blob: 971c151648097828b94a712afe3d2a9aeb763c98 [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
nissee4bcd6d2017-05-16 04:47:04 -070091 RtpDemuxer();
92 ~RtpDemuxer();
93
Steve Anton53c7ba62017-08-18 10:05:47 -070094 RtpDemuxer(const RtpDemuxer&) = delete;
95 void operator=(const RtpDemuxer&) = delete;
96
97 // Registers a sink that will be notified when RTP packets match its given
98 // criteria according to the algorithm described in the class description.
99 // Returns true if the sink was successfully added.
100 // Returns false in the following situations:
101 // - Only MID is specified and the MID is already registered.
102 // - Only RSID is specified and the RSID is already registered.
103 // - Both MID and RSID is specified and the (MID, RSID) pair is already
104 // registered.
105 // - Any of the criteria SSRCs are already registered.
106 // If false is returned, no changes are made to the demuxer state.
107 bool AddSink(const RtpDemuxerCriteria& criteria,
108 RtpPacketSinkInterface* sink);
109
eladalon5daecca2017-08-04 06:34:54 -0700110 // Registers a sink. Multiple SSRCs may be mapped to the same sink, but
111 // each SSRC may only be mapped to one sink. The return value reports
112 // whether the association has been recorded or rejected. Rejection may occur
113 // if the SSRC has already been associated with a sink. The previously added
114 // sink is *not* forgotten.
115 bool AddSink(uint32_t ssrc, RtpPacketSinkInterface* sink);
eladalond0244c22017-06-08 04:19:13 -0700116
eladalon5daecca2017-08-04 06:34:54 -0700117 // Registers a sink's association to an RSID. Only one sink may be associated
118 // with a given RSID. Null pointer is not allowed.
eladalond0244c22017-06-08 04:19:13 -0700119 void AddSink(const std::string& rsid, RtpPacketSinkInterface* sink);
120
121 // Removes a sink. Return value reports if anything was actually removed.
122 // Null pointer is not allowed.
123 bool RemoveSink(const RtpPacketSinkInterface* sink);
nissee4bcd6d2017-05-16 04:47:04 -0700124
Steve Anton53c7ba62017-08-18 10:05:47 -0700125 // Demuxes the given packet and forwards it to the chosen sink. Returns true
126 // if the packet was forwarded and false if the packet was dropped.
nissee4bcd6d2017-05-16 04:47:04 -0700127 bool OnRtpPacket(const RtpPacketReceived& packet);
128
Steve Anton53c7ba62017-08-18 10:05:47 -0700129 // The Observer will be notified when an attribute (e.g., RSID, MID, etc.) is
130 // bound to an SSRC.
Steve Antonb3329172017-08-17 15:23:51 -0700131 void RegisterSsrcBindingObserver(SsrcBindingObserver* observer);
132 // Deprecated: Use the above method.
133 void RegisterRsidResolutionObserver(SsrcBindingObserver* observer);
eladalona52722f2017-06-26 11:23:54 -0700134
Steve Antonb3329172017-08-17 15:23:51 -0700135 // Undo a previous RegisterSsrcBindingObserver().
136 void DeregisterSsrcBindingObserver(const SsrcBindingObserver* observer);
137 // Deprecated: Use the above method.
138 void DeregisterRsidResolutionObserver(const SsrcBindingObserver* observer);
eladalona52722f2017-06-26 11:23:54 -0700139
nissee4bcd6d2017-05-16 04:47:04 -0700140 private:
Steve Anton53c7ba62017-08-18 10:05:47 -0700141 // Returns true if adding a sink with the given criteria would cause conflicts
142 // with the existing criteria and should be rejected.
143 bool CriteriaWouldConflict(const RtpDemuxerCriteria& criteria) const;
eladalona52722f2017-06-26 11:23:54 -0700144
Steve Anton53c7ba62017-08-18 10:05:47 -0700145 // Runs the demux algorithm on the given packet and returns the sink that
146 // should receive the packet.
147 // Will record any SSRC<->ID associations along the way.
148 // If the packet should be dropped, this method returns null.
149 RtpPacketSinkInterface* ResolveSink(const RtpPacketReceived& packet);
eladalond0244c22017-06-08 04:19:13 -0700150
Steve Anton53c7ba62017-08-18 10:05:47 -0700151 // Used by the ResolveSink algorithm.
152 RtpPacketSinkInterface* ResolveSinkByMid(const std::string& mid,
153 uint32_t ssrc);
154 RtpPacketSinkInterface* ResolveSinkByMidRsid(const std::string& mid,
155 const std::string& rsid,
156 uint32_t ssrc);
157 RtpPacketSinkInterface* ResolveSinkByRsid(const std::string& rsid,
158 uint32_t ssrc);
159 RtpPacketSinkInterface* ResolveSinkByPayloadType(uint8_t payload_type,
160 uint32_t ssrc);
eladalond0244c22017-06-08 04:19:13 -0700161
Steve Anton53c7ba62017-08-18 10:05:47 -0700162 // Regenerate the known_mids_ set from information in the sink_by_mid_ and
163 // sink_by_mid_and_rsid_ maps.
164 void RefreshKnownMids();
165
166 // Map each sink by its component attributes to facilitate quick lookups.
167 // Payload Type mapping is a multimap because if two sinks register for the
168 // same payload type, both AddSinks succeed but we must know not to demux on
169 // that attribute since it is ambiguous.
170 // Note: Mappings are only modified by AddSink/RemoveSink (except for
171 // SSRC mapping which receives all MID, payload type, or RSID to SSRC bindings
172 // discovered when demuxing packets).
173 std::map<std::string, RtpPacketSinkInterface*> sink_by_mid_;
174 std::map<uint32_t, RtpPacketSinkInterface*> sink_by_ssrc_;
175 std::multimap<uint8_t, RtpPacketSinkInterface*> sinks_by_pt_;
176 std::map<std::pair<std::string, std::string>, RtpPacketSinkInterface*>
177 sink_by_mid_and_rsid_;
178 std::map<std::string, RtpPacketSinkInterface*> sink_by_rsid_;
179
180 // Tracks all the MIDs that have been identified in added criteria. Used to
181 // determine if a packet should be dropped right away because the MID is
182 // unknown.
183 std::set<std::string> known_mids_;
184
185 // Records learned mappings of MID --> SSRC and RSID --> SSRC as packets are
186 // received.
187 // This is stored separately from the sink mappings because if a sink is
188 // removed we want to still remember these associations.
189 std::map<uint32_t, std::string> mid_by_ssrc_;
190 std::map<uint32_t, std::string> rsid_by_ssrc_;
191
192 // Adds a binding from the SSRC to the given sink. Returns true if there was
193 // not already a sink bound to the SSRC or if the sink replaced a different
194 // sink. Returns false if the binding was unchanged.
195 bool AddSsrcSinkBinding(uint32_t ssrc, RtpPacketSinkInterface* sink);
eladalond0244c22017-06-08 04:19:13 -0700196
eladalona52722f2017-06-26 11:23:54 -0700197 // Observers which will be notified when an RSID association to an SSRC is
198 // resolved by this object.
Steve Antonb3329172017-08-17 15:23:51 -0700199 std::vector<SsrcBindingObserver*> ssrc_binding_observers_;
nissee4bcd6d2017-05-16 04:47:04 -0700200};
201
202} // namespace webrtc
203
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200204#endif // CALL_RTP_DEMUXER_H_