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 ¬etimeout);
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