1 /*
2 
3   This file is a part of JRTPLIB
4   Copyright (c) 1999-2017 Jori Liesenborgs
5 
6   Contact: jori.liesenborgs@gmail.com
7 
8   This library was developed at the Expertise Centre for Digital Media
9   (http://www.edm.uhasselt.be), a research center of the Hasselt University
10   (http://www.uhasselt.be). The library is based upon work done for
11   my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
12 
13   Permission is hereby granted, free of charge, to any person obtaining a
14   copy of this software and associated documentation files (the "Software"),
15   to deal in the Software without restriction, including without limitation
16   the rights to use, copy, modify, merge, publish, distribute, sublicense,
17   and/or sell copies of the Software, and to permit persons to whom the
18   Software is furnished to do so, subject to the following conditions:
19 
20   The above copyright notice and this permission notice shall be included
21   in all copies or substantial portions of the Software.
22 
23   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
29   IN THE SOFTWARE.
30 
31 */
32 
33 /**
34  * \file rtpsources.h
35  */
36 
37 #ifndef RTPSOURCES_H
38 
39 #define RTPSOURCES_H
40 
41 #include "rtpconfig.h"
42 #include "rtpkeyhashtable.h"
43 #include "rtcpsdespacket.h"
44 #include "rtptypes.h"
45 #include "rtpmemoryobject.h"
46 
47 #define RTPSOURCES_HASHSIZE							8317
48 
49 namespace jrtplib
50 {
51 
52 class JRTPLIB_IMPORTEXPORT RTPSources_GetHashIndex
53 {
54 public:
GetIndex(const uint32_t & ssrc)55 	static int GetIndex(const uint32_t &ssrc)				{ return ssrc%RTPSOURCES_HASHSIZE; }
56 };
57 
58 class RTPNTPTime;
59 class RTPTransmitter;
60 class RTCPAPPPacket;
61 class RTPInternalSourceData;
62 class RTPRawPacket;
63 class RTPPacket;
64 class RTPTime;
65 class RTPAddress;
66 class RTPSourceData;
67 
68 /** Represents a table in which information about the participating sources is kept.
69  *  Represents a table in which information about the participating sources is kept. The class has member
70  *  functions to process RTP and RTCP data and to iterate over the participants. Note that a NULL address
71  *  is used to identify packets from our own session. The class also provides some overridable functions
72  *  which can be used to catch certain events (new SSRC, SSRC collision, ...).
73  */
74 class JRTPLIB_IMPORTEXPORT RTPSources : public RTPMemoryObject
75 {
76 	JRTPLIB_NO_COPY(RTPSources)
77 public:
78 	/** Type of probation to use for new sources. */
79 	enum ProbationType
80 	{
81 			NoProbation, 		/**< Don't use the probation algorithm; accept RTP packets immediately. */
82 			ProbationDiscard, 	/**< Discard incoming RTP packets originating from a source that's on probation. */
83 			ProbationStore 		/**< Store incoming RTP packet from a source that's on probation for later retrieval. */
84 	};
85 
86 	/** In the constructor you can select the probation type you'd like to use and also a memory manager. */
87 	RTPSources(ProbationType = ProbationStore,RTPMemoryManager *mgr = 0);
88 	virtual ~RTPSources();
89 
90 	/** Clears the source table. */
91 	void Clear();
92 #ifdef RTP_SUPPORT_PROBATION
93 	/** Changes the current probation type. */
SetProbationType(ProbationType probtype)94 	void SetProbationType(ProbationType probtype)							{ probationtype = probtype; }
95 #endif // RTP_SUPPORT_PROBATION
96 
97 	/** Creates an entry for our own SSRC identifier. */
98 	int CreateOwnSSRC(uint32_t ssrc);
99 
100 	/** Deletes the entry for our own SSRC identifier. */
101 	int DeleteOwnSSRC();
102 
103 	/** This function should be called if our own session has sent an RTP packet.
104 	 *  This function should be called if our own session has sent an RTP packet.
105 	 *  For our own SSRC entry, the sender flag is updated based upon outgoing packets instead of incoming packets.
106 	 */
107 	void SentRTPPacket();
108 
109 	/** Processes a raw packet \c rawpack.
110 	 *  Processes a raw packet \c rawpack. The instance \c trans will be used to check if this
111 	 *  packet is one of our own packets. The flag \c acceptownpackets indicates whether own packets should be
112 	 *  accepted or ignored.
113 	 */
114 	int ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *trans,bool acceptownpackets);
115 
116 	/** Processes a raw packet \c rawpack.
117 	 *  Processes a raw packet \c rawpack. Every transmitter in the array \c trans of length \c numtrans
118 	 *  is used to check if the packet is from our own session. The flag \c acceptownpackets indicates
119 	 *  whether own packets should be accepted or ignored.
120 	 */
121 	int ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *trans[],int numtrans,bool acceptownpackets);
122 
123 	/** Processes an RTPPacket instance \c rtppack which was received at time \c receivetime and
124 	 *  which originated from \c senderaddres.
125 	 *  Processes an RTPPacket instance \c rtppack which was received at time \c receivetime and
126 	 *  which originated from \c senderaddres. The \c senderaddress parameter must be NULL if
127 	 *  the packet was sent by the local participant. The flag \c stored indicates whether the packet
128 	 *  was stored in the table or not.  If so, the \c rtppack instance may not be deleted.
129 	 */
130 	int ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,const RTPAddress *senderaddress,bool *stored);
131 
132 	/** Processes the RTCP compound packet \c rtcpcomppack which was received at time \c receivetime from \c senderaddress.
133 	 *  Processes the RTCP compound packet \c rtcpcomppack which was received at time \c receivetime from \c senderaddress.
134 	 *  The \c senderaddress parameter must be NULL if the packet was sent by the local participant.
135 	 */
136 	int ProcessRTCPCompoundPacket(RTCPCompoundPacket *rtcpcomppack,const RTPTime &receivetime,
137 	                              const RTPAddress *senderaddress);
138 
139 	/** Process the sender information of SSRC \c ssrc into the source table.
140 	 *  Process the sender information of SSRC \c ssrc into the source table. The information was received
141 	 *  at time \c receivetime from address \c senderaddress. The \c senderaddress} parameter must be NULL
142 	 *  if the packet was sent by the local participant.
143 	 */
144 	int ProcessRTCPSenderInfo(uint32_t ssrc,const RTPNTPTime &ntptime,uint32_t rtptime,
145 	                          uint32_t packetcount,uint32_t octetcount,const RTPTime &receivetime,
146 				  const RTPAddress *senderaddress);
147 
148     /** Processes the report block information which was sent by participant \c ssrc into the source table.
149 	 *  Processes the report block information which was sent by participant \c ssrc into the source table.
150 	 *  The information was received at time \c receivetime from address \c senderaddress The \c senderaddress
151 	 *  parameter must be NULL if the packet was sent by the local participant.
152 	 */
153 	int ProcessRTCPReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t lostpackets,
154 	                           uint32_t exthighseqnr,uint32_t jitter,uint32_t lsr,
155 	                           uint32_t dlsr,const RTPTime &receivetime,const RTPAddress *senderaddress);
156 
157 	/** Processes the non-private SDES item from source \c ssrc into the source table.
158 	 *  Processes the non-private SDES item from source \c ssrc into the source table. The information was
159 	 *  received at time \c receivetime from address \c senderaddress. The \c senderaddress parameter must
160 	 *  be NULL if the packet was sent by the local participant.
161 	 */
162 	int ProcessSDESNormalItem(uint32_t ssrc,RTCPSDESPacket::ItemType t,size_t itemlength,
163 	                          const void *itemdata,const RTPTime &receivetime,const RTPAddress *senderaddress);
164 #ifdef RTP_SUPPORT_SDESPRIV
165 	/** Processes the SDES private item from source \c ssrc into the source table.
166 	 *  Processes the SDES private item from source \c ssrc into the source table. The information was
167 	 *  received at time \c receivetime from address \c senderaddress. The \c senderaddress
168 	 *  parameter must be NULL if the packet was sent by the local participant.
169 	 */
170 	int ProcessSDESPrivateItem(uint32_t ssrc,size_t prefixlen,const void *prefixdata,
171 	                           size_t valuelen,const void *valuedata,const RTPTime &receivetime,
172 	                           const RTPAddress *senderaddress);
173 #endif //RTP_SUPPORT_SDESPRIV
174 	/** Processes the BYE message for SSRC \c ssrc.
175 	 *  Processes the BYE message for SSRC \c ssrc. The information was received at time \c receivetime from
176 	 *  address \c senderaddress. The \c senderaddress parameter must be NULL if the packet was sent by the
177 	 *  local participant.
178 	 */
179 	int ProcessBYE(uint32_t ssrc,size_t reasonlength,const void *reasondata,const RTPTime &receivetime,
180 	               const RTPAddress *senderaddress);
181 
182 	/** If we heard from source \c ssrc, but no actual data was added to the source table (for example, if
183 	 *  no report block was meant for us), this function can e used to indicate that something was received from
184 	 *  this source.
185 	 *  If we heard from source \c ssrc, but no actual data was added to the source table (for example, if
186 	 *  no report block was meant for us), this function can e used to indicate that something was received from
187 	 *  this source. This will prevent a premature timeout for this participant. The message was received at time
188 	 *  \c receivetime from address \c senderaddress. The \c senderaddress parameter must be NULL if the
189 	 *  packet was sent by the local participant.
190 	 */
191 	int UpdateReceiveTime(uint32_t ssrc,const RTPTime &receivetime,const RTPAddress *senderaddress);
192 
193 	/** Starts the iteration over the participants by going to the first member in the table.
194 	 *  Starts the iteration over the participants by going to the first member in the table.
195 	 *  If a member was found, the function returns \c true, otherwise it returns \c false.
196 	 */
197 	bool GotoFirstSource();
198 
199 	/** Sets the current source to be the next source in the table.
200 	 *  Sets the current source to be the next source in the table. If we're already at the last source,
201 	 *  the function returns \c false, otherwise it returns \c true.
202 	 */
203 	bool GotoNextSource();
204 
205 	/** Sets the current source to be the previous source in the table.
206 	 *  Sets the current source to be the previous source in the table. If we're at the first source,
207 	 *  the function returns \c false, otherwise it returns \c true.
208 	 */
209 	bool GotoPreviousSource();
210 
211 	/** Sets the current source to be the first source in the table which has RTPPacket instances
212 	 *  that we haven't extracted yet.
213 	 *  Sets the current source to be the first source in the table which has RTPPacket instances
214 	 *  that we haven't extracted yet. If no such member was found, the function returns \c false,
215 	 *  otherwise it returns \c true.
216 	 */
217 	bool GotoFirstSourceWithData();
218 
219 	/** Sets the current source to be the next source in the table which has RTPPacket instances that
220 	 *  we haven't extracted yet.
221 	 *  Sets the current source to be the next source in the table which has RTPPacket instances that
222 	 *  we haven't extracted yet. If no such member was found, the function returns \c false,
223 	 *  otherwise it returns \c true.
224 	 */
225 	bool GotoNextSourceWithData();
226 
227 	/** Sets the current source to be the previous source in the table which has RTPPacket instances
228 	 *  that we haven't extracted yet.
229 	 *  Sets the current source to be the previous source in the table which has RTPPacket instances
230 	 *  that we haven't extracted yet. If no such member was found, the function returns \c false,
231 	 *  otherwise it returns \c true.
232 	 */
233 	bool GotoPreviousSourceWithData();
234 
235 	/** Returns the RTPSourceData instance for the currently selected participant. */
236 	RTPSourceData *GetCurrentSourceInfo();
237 
238 	/** Returns the RTPSourceData instance for the participant identified by \c ssrc, or
239 	 *  NULL if no such entry exists.
240 	 */
241 	RTPSourceData *GetSourceInfo(uint32_t ssrc);
242 
243 	/** Extracts the next packet from the received packets queue of the current participant. */
244 	RTPPacket *GetNextPacket();
245 
246 	/** Returns \c true if an entry for participant \c ssrc exists and \c false otherwise. */
247 	bool GotEntry(uint32_t ssrc);
248 
249 	/** If present, it returns the RTPSourceData instance of the entry which was created by CreateOwnSSRC. */
GetOwnSourceInfo()250 	RTPSourceData *GetOwnSourceInfo()								{ return (RTPSourceData *)owndata; }
251 
252 	/** Assuming that the current time is \c curtime, time out the members from whom we haven't heard
253 	 *  during the previous time  interval \c timeoutdelay.
254 	 */
255 	void Timeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
256 
257 	/** Assuming that the current time is \c curtime, remove the sender flag for senders from whom we haven't
258 	 *  received any RTP packets during the previous time interval \c timeoutdelay.
259 	 */
260 	void SenderTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
261 
262 	/** Assuming that the current time is \c curtime, remove the members who sent a BYE packet more than
263 	 *  the time interval \c timeoutdelay ago.
264 	 */
265 	void BYETimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
266 
267 	/** Assuming that the current time is \c curtime, clear the SDES NOTE items which haven't been updated
268 	 *  during the previous time interval \c timeoutdelay.
269 	 */
270 	void NoteTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay);
271 
272 	/** Combines the functions SenderTimeout, BYETimeout, Timeout and NoteTimeout.
273 	 *  Combines the functions SenderTimeout, BYETimeout, Timeout and NoteTimeout. This is more efficient
274 	 *  than calling all four functions since only one iteration is needed in this function.
275 	 */
276 	void MultipleTimeouts(const RTPTime &curtime,const RTPTime &sendertimeout,
277 			      const RTPTime &byetimeout,const RTPTime &generaltimeout,
278 			      const RTPTime &notetimeout);
279 
280 	/** Returns the number of participants which are marked as a sender. */
GetSenderCount()281 	int GetSenderCount() const										{ return sendercount; }
282 
283 	/** Returns the total number of entries in the source table. */
GetTotalCount()284 	int GetTotalCount() const										{ return totalcount; }
285 
286 	/** Returns the number of members which have been validated and which haven't sent a BYE packet yet. */
GetActiveMemberCount()287 	int GetActiveMemberCount() const								{ return activecount; }
288 #ifdef RTPDEBUG
289 	void Dump();
290 	void SafeCountTotal();
291 	void SafeCountSenders();
292 	void SafeCountActive();
293 #endif // RTPDEBUG
294 protected:
295 	/** Is called when an RTP packet is about to be processed. */
296 	virtual void OnRTPPacket(RTPPacket *pack,const RTPTime &receivetime, const RTPAddress *senderaddress);
297 
298 	/** Is called when an RTCP compound packet is about to be processed. */
299 	virtual void OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,
300 	                                  const RTPAddress *senderaddress);
301 
302 	/** Is called when an SSRC collision was detected.
303 	 *  Is called when an SSRC collision was detected. The instance \c srcdat is the one present in
304 	 *  the table, the address \c senderaddress is the one that collided with one of the addresses
305 	 *  and \c isrtp indicates against which address of \c srcdat the check failed.
306 	 */
307 	virtual void OnSSRCCollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
308 
309 	/** Is called when another CNAME was received than the one already present for source \c srcdat. */
310 	virtual void OnCNAMECollision(RTPSourceData *srcdat,const RTPAddress *senderaddress,
311 	                              const uint8_t *cname,size_t cnamelength);
312 
313 	/** Is called when a new entry \c srcdat is added to the source table. */
314 	virtual void OnNewSource(RTPSourceData *srcdat);
315 
316 	/** Is called when the entry \c srcdat is about to be deleted from the source table. */
317 	virtual void OnRemoveSource(RTPSourceData *srcdat);
318 
319 	/** Is called when participant \c srcdat is timed out. */
320 	virtual void OnTimeout(RTPSourceData *srcdat);
321 
322 	/** Is called when participant \c srcdat is timed after having sent a BYE packet. */
323 	virtual void OnBYETimeout(RTPSourceData *srcdat);
324 
325 	/** Is called when a BYE packet has been processed for source \c srcdat. */
326 	virtual void OnBYEPacket(RTPSourceData *srcdat);
327 
328 	/** Is called when an RTCP sender report has been processed for this source. */
329 	virtual void OnRTCPSenderReport(RTPSourceData *srcdat);
330 
331 	/** Is called when an RTCP receiver report has been processed for this source. */
332 	virtual void OnRTCPReceiverReport(RTPSourceData *srcdat);
333 
334 	/** Is called when a specific SDES item was received for this source. */
335 	virtual void OnRTCPSDESItem(RTPSourceData *srcdat, RTCPSDESPacket::ItemType t,
336 	                            const void *itemdata, size_t itemlength);
337 #ifdef RTP_SUPPORT_SDESPRIV
338 	/** Is called when a specific SDES item of 'private' type was received for this source. */
339 	virtual void OnRTCPSDESPrivateItem(RTPSourceData *srcdat, const void *prefixdata, size_t prefixlen,
340 	                                   const void *valuedata, size_t valuelen);
341 #endif // RTP_SUPPORT_SDESPRIV
342 
343 
344 	/** Is called when an RTCP APP packet \c apppacket has been received at time \c receivetime
345 	 *  from address \c senderaddress.
346 	 */
347 	virtual void OnAPPPacket(RTCPAPPPacket *apppacket,const RTPTime &receivetime,
348 	                         const RTPAddress *senderaddress);
349 
350 	/** Is called when an unknown RTCP packet type was detected. */
351 	virtual void OnUnknownPacketType(RTCPPacket *rtcppack,const RTPTime &receivetime,
352 	                                 const RTPAddress *senderaddress);
353 
354 	/** Is called when an unknown packet format for a known packet type was detected. */
355 	virtual void OnUnknownPacketFormat(RTCPPacket *rtcppack,const RTPTime &receivetime,
356 	                                   const RTPAddress *senderaddress);
357 
358 	/** Is called when the SDES NOTE item for source \c srcdat has been timed out. */
359 	virtual void OnNoteTimeout(RTPSourceData *srcdat);
360 
361 	/** Allows you to use an RTP packet from the specified source directly.
362 	 *  Allows you to use an RTP packet from the specified source directly. If
363 	 *  `ispackethandled` is set to `true`, the packet will no longer be stored in this
364 	 *  source's packet list. */
365 	virtual void OnValidatedRTPPacket(RTPSourceData *srcdat, RTPPacket *rtppack, bool isonprobation, bool *ispackethandled);
366 private:
367 	void ClearSourceList();
368 	int ObtainSourceDataInstance(uint32_t ssrc,RTPInternalSourceData **srcdat,bool *created);
369 	int GetRTCPSourceData(uint32_t ssrc,const RTPAddress *senderaddress,RTPInternalSourceData **srcdat,bool *newsource);
370 	bool CheckCollision(RTPInternalSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp);
371 
372 	RTPKeyHashTable<const uint32_t,RTPInternalSourceData*,RTPSources_GetHashIndex,RTPSOURCES_HASHSIZE> sourcelist;
373 
374 	int sendercount;
375 	int totalcount;
376 	int activecount;
377 
378 #ifdef RTP_SUPPORT_PROBATION
379 	ProbationType probationtype;
380 #endif // RTP_SUPPORT_PROBATION
381 
382 	RTPInternalSourceData *owndata;
383 
384 	friend class RTPInternalSourceData;
385 };
386 
387 // Inlining the default implementations to avoid unused-parameter errors.
OnRTPPacket(RTPPacket *,const RTPTime &,const RTPAddress *)388 inline void RTPSources::OnRTPPacket(RTPPacket *, const RTPTime &, const RTPAddress *)                               { }
OnRTCPCompoundPacket(RTCPCompoundPacket *,const RTPTime &,const RTPAddress *)389 inline void RTPSources::OnRTCPCompoundPacket(RTCPCompoundPacket *, const RTPTime &, const RTPAddress *)             { }
OnSSRCCollision(RTPSourceData *,const RTPAddress *,bool)390 inline void RTPSources::OnSSRCCollision(RTPSourceData *, const RTPAddress *, bool)                                  { }
OnCNAMECollision(RTPSourceData *,const RTPAddress *,const uint8_t *,size_t)391 inline void RTPSources::OnCNAMECollision(RTPSourceData *, const RTPAddress *, const uint8_t *, size_t)              { }
OnNewSource(RTPSourceData *)392 inline void RTPSources::OnNewSource(RTPSourceData *)                                                                { }
OnRemoveSource(RTPSourceData *)393 inline void RTPSources::OnRemoveSource(RTPSourceData *)                                                             { }
OnTimeout(RTPSourceData *)394 inline void RTPSources::OnTimeout(RTPSourceData *)                                                                  { }
OnBYETimeout(RTPSourceData *)395 inline void RTPSources::OnBYETimeout(RTPSourceData *)                                                               { }
OnBYEPacket(RTPSourceData *)396 inline void RTPSources::OnBYEPacket(RTPSourceData *)                                                                { }
OnRTCPSenderReport(RTPSourceData *)397 inline void RTPSources::OnRTCPSenderReport(RTPSourceData *)                                                         { }
OnRTCPReceiverReport(RTPSourceData *)398 inline void RTPSources::OnRTCPReceiverReport(RTPSourceData *)                                                       { }
OnRTCPSDESItem(RTPSourceData *,RTCPSDESPacket::ItemType,const void *,size_t)399 inline void RTPSources::OnRTCPSDESItem(RTPSourceData *, RTCPSDESPacket::ItemType, const void *, size_t)             { }
400 #ifdef RTP_SUPPORT_SDESPRIV
OnRTCPSDESPrivateItem(RTPSourceData *,const void *,size_t,const void *,size_t)401 inline void RTPSources::OnRTCPSDESPrivateItem(RTPSourceData *, const void *, size_t, const void *, size_t)          { }
402 #endif // RTP_SUPPORT_SDESPRIV
OnAPPPacket(RTCPAPPPacket *,const RTPTime &,const RTPAddress *)403 inline void RTPSources::OnAPPPacket(RTCPAPPPacket *, const RTPTime &, const RTPAddress *)                           { }
OnUnknownPacketType(RTCPPacket *,const RTPTime &,const RTPAddress *)404 inline void RTPSources::OnUnknownPacketType(RTCPPacket *, const RTPTime &, const RTPAddress *)                      { }
OnUnknownPacketFormat(RTCPPacket *,const RTPTime &,const RTPAddress *)405 inline void RTPSources::OnUnknownPacketFormat(RTCPPacket *, const RTPTime &, const RTPAddress *)                    { }
OnNoteTimeout(RTPSourceData *)406 inline void RTPSources::OnNoteTimeout(RTPSourceData *)                                                              { }
OnValidatedRTPPacket(RTPSourceData *,RTPPacket *,bool,bool *)407 inline void RTPSources::OnValidatedRTPPacket(RTPSourceData *, RTPPacket *, bool, bool *)                            { }
408 
409 } // end namespace
410 
411 #endif // RTPSOURCES_H
412 
413