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 #include "rtpsources.h"
34 #include "rtperrors.h"
35 #include "rtprawpacket.h"
36 #include "rtpinternalsourcedata.h"
37 #include "rtptimeutilities.h"
38 #include "rtpdefines.h"
39 #include "rtcpcompoundpacket.h"
40 #include "rtcppacket.h"
41 #include "rtcpapppacket.h"
42 #include "rtcpbyepacket.h"
43 #include "rtcpsdespacket.h"
44 #include "rtcpsrpacket.h"
45 #include "rtcprrpacket.h"
46 #include "rtptransmitter.h"
47 
48 #ifdef RTPDEBUG
49 	#include <iostream>
50 #endif // RTPDEBUG
51 
52 #include "rtpdebug.h"
53 
54 namespace jrtplib
55 {
56 
RTPSources(ProbationType probtype,RTPMemoryManager * mgr)57 RTPSources::RTPSources(ProbationType probtype,RTPMemoryManager *mgr) : RTPMemoryObject(mgr),sourcelist(mgr,RTPMEM_TYPE_CLASS_SOURCETABLEHASHELEMENT)
58 {
59 	JRTPLIB_UNUSED(probtype); // possibly unused
60 
61 	totalcount = 0;
62 	sendercount = 0;
63 	activecount = 0;
64 	owndata = 0;
65 #ifdef RTP_SUPPORT_PROBATION
66 	probationtype = probtype;
67 #endif // RTP_SUPPORT_PROBATION
68 }
69 
~RTPSources()70 RTPSources::~RTPSources()
71 {
72 	Clear();
73 }
74 
Clear()75 void RTPSources::Clear()
76 {
77 	ClearSourceList();
78 }
79 
ClearSourceList()80 void RTPSources::ClearSourceList()
81 {
82 	sourcelist.GotoFirstElement();
83 	while (sourcelist.HasCurrentElement())
84 	{
85 		RTPInternalSourceData *sourcedata;
86 
87 		sourcedata = sourcelist.GetCurrentElement();
88 		RTPDelete(sourcedata,GetMemoryManager());
89 		sourcelist.GotoNextElement();
90 	}
91 	sourcelist.Clear();
92 	owndata = 0;
93 	totalcount = 0;
94 	sendercount = 0;
95 	activecount = 0;
96 }
97 
CreateOwnSSRC(uint32_t ssrc)98 int RTPSources::CreateOwnSSRC(uint32_t ssrc)
99 {
100 	if (owndata != 0)
101 		return ERR_RTP_SOURCES_ALREADYHAVEOWNSSRC;
102 	if (GotEntry(ssrc))
103 		return ERR_RTP_SOURCES_SSRCEXISTS;
104 
105 	int status;
106 	bool created;
107 
108 	status = ObtainSourceDataInstance(ssrc,&owndata,&created);
109 	if (status < 0)
110 	{
111 		owndata = 0; // just to make sure
112 		return status;
113 	}
114 	owndata->SetOwnSSRC();
115 	owndata->SetRTPDataAddress(0);
116 	owndata->SetRTCPDataAddress(0);
117 
118 	// we've created a validated ssrc, so we should increase activecount
119 	activecount++;
120 
121 	OnNewSource(owndata);
122 	return 0;
123 }
124 
DeleteOwnSSRC()125 int RTPSources::DeleteOwnSSRC()
126 {
127 	if (owndata == 0)
128 		return ERR_RTP_SOURCES_DONTHAVEOWNSSRC;
129 
130 	uint32_t ssrc = owndata->GetSSRC();
131 
132 	sourcelist.GotoElement(ssrc);
133 	sourcelist.DeleteCurrentElement();
134 
135 	totalcount--;
136 	if (owndata->IsSender())
137 		sendercount--;
138 	if (owndata->IsActive())
139 		activecount--;
140 
141 	OnRemoveSource(owndata);
142 
143 	RTPDelete(owndata,GetMemoryManager());
144 	owndata = 0;
145 	return 0;
146 }
147 
SentRTPPacket()148 void RTPSources::SentRTPPacket()
149 {
150 	if (owndata == 0)
151 		return;
152 
153 	bool prevsender = owndata->IsSender();
154 
155 	owndata->SentRTPPacket();
156 	if (!prevsender && owndata->IsSender())
157 		sendercount++;
158 }
159 
ProcessRawPacket(RTPRawPacket * rawpack,RTPTransmitter * rtptrans,bool acceptownpackets)160 int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *rtptrans,bool acceptownpackets)
161 {
162 	RTPTransmitter *transmitters[1];
163 	int num;
164 
165 	transmitters[0] = rtptrans;
166 	if (rtptrans == 0)
167 		num = 0;
168 	else
169 		num = 1;
170 	return ProcessRawPacket(rawpack,transmitters,num,acceptownpackets);
171 }
172 
ProcessRawPacket(RTPRawPacket * rawpack,RTPTransmitter * rtptrans[],int numtrans,bool acceptownpackets)173 int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack,RTPTransmitter *rtptrans[],int numtrans,bool acceptownpackets)
174 {
175 	int status;
176 
177 	if (rawpack->IsRTP()) // RTP packet
178 	{
179 		RTPPacket *rtppack;
180 
181 		// First, we'll see if the packet can be parsed
182 		rtppack = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPPACKET) RTPPacket(*rawpack,GetMemoryManager());
183 		if (rtppack == 0)
184 			return ERR_RTP_OUTOFMEM;
185 		if ((status = rtppack->GetCreationError()) < 0)
186 		{
187 			if (status == ERR_RTP_PACKET_INVALIDPACKET)
188 			{
189 				RTPDelete(rtppack,GetMemoryManager());
190 				rtppack = 0;
191 			}
192 			else
193 			{
194 				RTPDelete(rtppack,GetMemoryManager());
195 				return status;
196 			}
197 		}
198 
199 		// Check if the packet was valid
200 		if (rtppack != 0)
201 		{
202 			bool stored = false;
203 			bool ownpacket = false;
204 			int i;
205 			const RTPAddress *senderaddress = rawpack->GetSenderAddress();
206 
207 			for (i = 0 ; !ownpacket && i < numtrans ; i++)
208 			{
209 				if (rtptrans[i]->ComesFromThisTransmitter(senderaddress))
210 					ownpacket = true;
211 			}
212 
213 			// Check if the packet is our own.
214 			if (ownpacket)
215 			{
216 				// Now it depends on the user's preference
217 				// what to do with this packet:
218 				if (acceptownpackets)
219 				{
220 					// sender addres for own packets has to be NULL!
221 					if ((status = ProcessRTPPacket(rtppack,rawpack->GetReceiveTime(),0,&stored)) < 0)
222 					{
223 						if (!stored)
224 							RTPDelete(rtppack,GetMemoryManager());
225 						return status;
226 					}
227 				}
228 			}
229 			else
230 			{
231 				if ((status = ProcessRTPPacket(rtppack,rawpack->GetReceiveTime(),senderaddress,&stored)) < 0)
232 				{
233 					if (!stored)
234 						RTPDelete(rtppack,GetMemoryManager());
235 					return status;
236 				}
237 			}
238 			if (!stored)
239 				RTPDelete(rtppack,GetMemoryManager());
240 		}
241 	}
242 	else // RTCP packet
243 	{
244 		RTCPCompoundPacket rtcpcomppack(*rawpack,GetMemoryManager());
245 		bool valid = false;
246 
247 		if ((status = rtcpcomppack.GetCreationError()) < 0)
248 		{
249 			if (status != ERR_RTP_RTCPCOMPOUND_INVALIDPACKET)
250 				return status;
251 		}
252 		else
253 			valid = true;
254 
255 
256 		if (valid)
257 		{
258 			bool ownpacket = false;
259 			int i;
260 			const RTPAddress *senderaddress = rawpack->GetSenderAddress();
261 
262 			for (i = 0 ; !ownpacket && i < numtrans ; i++)
263 			{
264 				if (rtptrans[i]->ComesFromThisTransmitter(senderaddress))
265 					ownpacket = true;
266 			}
267 
268 			// First check if it's a packet of this session.
269 			if (ownpacket)
270 			{
271 				if (acceptownpackets)
272 				{
273 					// sender address for own packets has to be NULL
274 					status = ProcessRTCPCompoundPacket(&rtcpcomppack,rawpack->GetReceiveTime(),0);
275 					if (status < 0)
276 						return status;
277 				}
278 			}
279 			else // not our own packet
280 			{
281 				status = ProcessRTCPCompoundPacket(&rtcpcomppack,rawpack->GetReceiveTime(),rawpack->GetSenderAddress());
282 				if (status < 0)
283 					return status;
284 			}
285 		}
286 	}
287 
288 	return 0;
289 }
290 
ProcessRTPPacket(RTPPacket * rtppack,const RTPTime & receivetime,const RTPAddress * senderaddress,bool * stored)291 int RTPSources::ProcessRTPPacket(RTPPacket *rtppack,const RTPTime &receivetime,const RTPAddress *senderaddress,bool *stored)
292 {
293 	uint32_t ssrc;
294 	RTPInternalSourceData *srcdat;
295 	int status;
296 	bool created;
297 
298 	OnRTPPacket(rtppack,receivetime,senderaddress);
299 
300 	*stored = false;
301 
302 	ssrc = rtppack->GetSSRC();
303 	if ((status = ObtainSourceDataInstance(ssrc,&srcdat,&created)) < 0)
304 		return status;
305 
306 	if (created)
307 	{
308 		if ((status = srcdat->SetRTPDataAddress(senderaddress)) < 0)
309 			return status;
310 	}
311 	else // got a previously existing source
312 	{
313 		if (CheckCollision(srcdat,senderaddress,true))
314 			return 0; // ignore packet on collision
315 	}
316 
317 	bool prevsender = srcdat->IsSender();
318 	bool prevactive = srcdat->IsActive();
319 
320 	uint32_t CSRCs[RTP_MAXCSRCS];
321 	int numCSRCs = rtppack->GetCSRCCount();
322 	if (numCSRCs > RTP_MAXCSRCS) // shouldn't happen, but better to check than go out of bounds
323 		numCSRCs = RTP_MAXCSRCS;
324 
325 	for (int i = 0 ; i < numCSRCs ; i++)
326 		CSRCs[i] = rtppack->GetCSRC(i);
327 
328 	// The packet comes from a valid source, we can process it further now
329 	// The following function should delete rtppack itself if something goes
330 	// wrong
331 	if ((status = srcdat->ProcessRTPPacket(rtppack,receivetime,stored,this)) < 0)
332 		return status;
333 
334 	// NOTE: we cannot use 'rtppack' anymore since it may have been deleted in
335 	//       OnValidatedRTPPacket
336 
337 	if (!prevsender && srcdat->IsSender())
338 		sendercount++;
339 	if (!prevactive && srcdat->IsActive())
340 		activecount++;
341 
342 	if (created)
343 		OnNewSource(srcdat);
344 
345 	if (srcdat->IsValidated()) // process the CSRCs
346 	{
347 		RTPInternalSourceData *csrcdat;
348 		bool createdcsrc;
349 
350 		int num = numCSRCs;
351 		int i;
352 
353 		for (i = 0 ; i < num ; i++)
354 		{
355 			if ((status = ObtainSourceDataInstance(CSRCs[i],&csrcdat,&createdcsrc)) < 0)
356 				return status;
357 			if (createdcsrc)
358 			{
359 				csrcdat->SetCSRC();
360 				if (csrcdat->IsActive())
361 					activecount++;
362 				OnNewSource(csrcdat);
363 			}
364 			else // already found an entry, possibly because of RTCP data
365 			{
366 				if (!CheckCollision(csrcdat,senderaddress,true))
367 					csrcdat->SetCSRC();
368 			}
369 		}
370 	}
371 
372 	return 0;
373 }
374 
ProcessRTCPCompoundPacket(RTCPCompoundPacket * rtcpcomppack,const RTPTime & receivetime,const RTPAddress * senderaddress)375 int RTPSources::ProcessRTCPCompoundPacket(RTCPCompoundPacket *rtcpcomppack,const RTPTime &receivetime,const RTPAddress *senderaddress)
376 {
377 	RTCPPacket *rtcppack;
378 	int status;
379 	bool gotownssrc = ((owndata == 0)?false:true);
380 	uint32_t ownssrc = ((owndata != 0)?owndata->GetSSRC():0);
381 
382 	OnRTCPCompoundPacket(rtcpcomppack,receivetime,senderaddress);
383 
384 	rtcpcomppack->GotoFirstPacket();
385 	while ((rtcppack = rtcpcomppack->GetNextPacket()) != 0)
386 	{
387 		if (rtcppack->IsKnownFormat())
388 		{
389 			switch (rtcppack->GetPacketType())
390 			{
391 			case RTCPPacket::SR:
392 				{
393 					RTCPSRPacket *p = (RTCPSRPacket *)rtcppack;
394 					uint32_t senderssrc = p->GetSenderSSRC();
395 
396 					status = ProcessRTCPSenderInfo(senderssrc,p->GetNTPTimestamp(),p->GetRTPTimestamp(),
397 						                       p->GetSenderPacketCount(),p->GetSenderOctetCount(),
398 								       receivetime,senderaddress);
399 					if (status < 0)
400 						return status;
401 
402 					bool gotinfo = false;
403 					if (gotownssrc)
404 					{
405 						int i;
406 						int num = p->GetReceptionReportCount();
407 						for (i = 0 ; i < num ; i++)
408 						{
409 							if (p->GetSSRC(i) == ownssrc) // data is meant for us
410 							{
411 								gotinfo = true;
412 								status = ProcessRTCPReportBlock(senderssrc,p->GetFractionLost(i),p->GetLostPacketCount(i),
413 										                        p->GetExtendedHighestSequenceNumber(i),p->GetJitter(i),p->GetLSR(i),
414 													p->GetDLSR(i),receivetime,senderaddress);
415 								if (status < 0)
416 									return status;
417 							}
418 						}
419 					}
420 					if (!gotinfo)
421 					{
422 						status = UpdateReceiveTime(senderssrc,receivetime,senderaddress);
423 						if (status < 0)
424 							return status;
425 					}
426 				}
427 				break;
428 			case RTCPPacket::RR:
429 				{
430 					RTCPRRPacket *p = (RTCPRRPacket *)rtcppack;
431 					uint32_t senderssrc = p->GetSenderSSRC();
432 
433 					bool gotinfo = false;
434 
435 					if (gotownssrc)
436 					{
437 						int i;
438 						int num = p->GetReceptionReportCount();
439 						for (i = 0 ; i < num ; i++)
440 						{
441 							if (p->GetSSRC(i) == ownssrc)
442 							{
443 								gotinfo = true;
444 								status = ProcessRTCPReportBlock(senderssrc,p->GetFractionLost(i),p->GetLostPacketCount(i),
445 										                        p->GetExtendedHighestSequenceNumber(i),p->GetJitter(i),p->GetLSR(i),
446 													p->GetDLSR(i),receivetime,senderaddress);
447 								if (status < 0)
448 									return status;
449 							}
450 						}
451 					}
452 					if (!gotinfo)
453 					{
454 						status = UpdateReceiveTime(senderssrc,receivetime,senderaddress);
455 						if (status < 0)
456 							return status;
457 					}
458 				}
459 				break;
460 			case RTCPPacket::SDES:
461 				{
462 					RTCPSDESPacket *p = (RTCPSDESPacket *)rtcppack;
463 
464 					if (p->GotoFirstChunk())
465 					{
466 						do
467 						{
468 							uint32_t sdesssrc = p->GetChunkSSRC();
469 							bool updated = false;
470 							if (p->GotoFirstItem())
471 							{
472 								do
473 								{
474 									RTCPSDESPacket::ItemType t;
475 
476 									if ((t = p->GetItemType()) != RTCPSDESPacket::PRIV)
477 									{
478 										updated = true;
479 										status = ProcessSDESNormalItem(sdesssrc,t,p->GetItemLength(),p->GetItemData(),receivetime,senderaddress);
480 										if (status < 0)
481 											return status;
482 									}
483 #ifdef RTP_SUPPORT_SDESPRIV
484 									else
485 									{
486 										updated = true;
487 										status = ProcessSDESPrivateItem(sdesssrc,p->GetPRIVPrefixLength(),p->GetPRIVPrefixData(),p->GetPRIVValueLength(),
488 												                        p->GetPRIVValueData(),receivetime,senderaddress);
489 										if (status < 0)
490 											return status;
491 									}
492 #endif // RTP_SUPPORT_SDESPRIV
493 								} while (p->GotoNextItem());
494 							}
495 							if (!updated)
496 							{
497 								status = UpdateReceiveTime(sdesssrc,receivetime,senderaddress);
498 								if (status < 0)
499 									return status;
500 							}
501 						} while (p->GotoNextChunk());
502 					}
503 				}
504 				break;
505 			case RTCPPacket::BYE:
506 				{
507 					RTCPBYEPacket *p = (RTCPBYEPacket *)rtcppack;
508 					int i;
509 					int num = p->GetSSRCCount();
510 
511 					for (i = 0 ; i < num ; i++)
512 					{
513 						uint32_t byessrc = p->GetSSRC(i);
514 						status = ProcessBYE(byessrc,p->GetReasonLength(),p->GetReasonData(),receivetime,senderaddress);
515 						if (status < 0)
516 							return status;
517 					}
518 				}
519 				break;
520 			case RTCPPacket::APP:
521 				{
522 					RTCPAPPPacket *p = (RTCPAPPPacket *)rtcppack;
523 
524 					OnAPPPacket(p,receivetime,senderaddress);
525 				}
526 				break;
527 			case RTCPPacket::Unknown:
528 			default:
529 				{
530 					OnUnknownPacketType(rtcppack,receivetime,senderaddress);
531 				}
532 				break;
533 			}
534 		}
535 		else
536 		{
537 			OnUnknownPacketFormat(rtcppack,receivetime,senderaddress);
538 		}
539 	}
540 
541 	return 0;
542 }
543 
GotoFirstSource()544 bool RTPSources::GotoFirstSource()
545 {
546 	sourcelist.GotoFirstElement();
547 	if (sourcelist.HasCurrentElement())
548 		return true;
549 	return false;
550 }
551 
GotoNextSource()552 bool RTPSources::GotoNextSource()
553 {
554 	sourcelist.GotoNextElement();
555 	if (sourcelist.HasCurrentElement())
556 		return true;
557 	return false;
558 }
559 
GotoPreviousSource()560 bool RTPSources::GotoPreviousSource()
561 {
562 	sourcelist.GotoPreviousElement();
563 	if (sourcelist.HasCurrentElement())
564 		return true;
565 	return false;
566 }
567 
GotoFirstSourceWithData()568 bool RTPSources::GotoFirstSourceWithData()
569 {
570 	bool found = false;
571 
572 	sourcelist.GotoFirstElement();
573 	while (!found && sourcelist.HasCurrentElement())
574 	{
575 		RTPInternalSourceData *srcdat;
576 
577 		srcdat = sourcelist.GetCurrentElement();
578 		if (srcdat->HasData())
579 			found = true;
580 		else
581 			sourcelist.GotoNextElement();
582 	}
583 
584 	return found;
585 }
586 
GotoNextSourceWithData()587 bool RTPSources::GotoNextSourceWithData()
588 {
589 	bool found = false;
590 
591 	sourcelist.GotoNextElement();
592 	while (!found && sourcelist.HasCurrentElement())
593 	{
594 		RTPInternalSourceData *srcdat;
595 
596 		srcdat = sourcelist.GetCurrentElement();
597 		if (srcdat->HasData())
598 			found = true;
599 		else
600 			sourcelist.GotoNextElement();
601 	}
602 
603 	return found;
604 }
605 
GotoPreviousSourceWithData()606 bool RTPSources::GotoPreviousSourceWithData()
607 {
608 	bool found = false;
609 
610 	sourcelist.GotoPreviousElement();
611 	while (!found && sourcelist.HasCurrentElement())
612 	{
613 		RTPInternalSourceData *srcdat;
614 
615 		srcdat = sourcelist.GetCurrentElement();
616 		if (srcdat->HasData())
617 			found = true;
618 		else
619 			sourcelist.GotoPreviousElement();
620 	}
621 
622 	return found;
623 }
624 
GetCurrentSourceInfo()625 RTPSourceData *RTPSources::GetCurrentSourceInfo()
626 {
627 	if (!sourcelist.HasCurrentElement())
628 		return 0;
629 	return sourcelist.GetCurrentElement();
630 }
631 
GetSourceInfo(uint32_t ssrc)632 RTPSourceData *RTPSources::GetSourceInfo(uint32_t ssrc)
633 {
634 	if (sourcelist.GotoElement(ssrc) < 0)
635 		return 0;
636 	if (!sourcelist.HasCurrentElement())
637 		return 0;
638 	return sourcelist.GetCurrentElement();
639 }
640 
GotEntry(uint32_t ssrc)641 bool RTPSources::GotEntry(uint32_t ssrc)
642 {
643 	return sourcelist.HasElement(ssrc);
644 }
645 
GetNextPacket()646 RTPPacket *RTPSources::GetNextPacket()
647 {
648 	if (!sourcelist.HasCurrentElement())
649 		return 0;
650 
651 	RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
652 	RTPPacket *pack = srcdat->GetNextPacket();
653 	return pack;
654 }
655 
ProcessRTCPSenderInfo(uint32_t ssrc,const RTPNTPTime & ntptime,uint32_t rtptime,uint32_t packetcount,uint32_t octetcount,const RTPTime & receivetime,const RTPAddress * senderaddress)656 int RTPSources::ProcessRTCPSenderInfo(uint32_t ssrc,const RTPNTPTime &ntptime,uint32_t rtptime,
657                           uint32_t packetcount,uint32_t octetcount,const RTPTime &receivetime,
658 			  const RTPAddress *senderaddress)
659 {
660 	RTPInternalSourceData *srcdat;
661 	bool created;
662 	int status;
663 
664 	status = GetRTCPSourceData(ssrc,senderaddress,&srcdat,&created);
665 	if (status < 0)
666 		return status;
667 	if (srcdat == 0)
668 		return 0;
669 
670 	srcdat->ProcessSenderInfo(ntptime,rtptime,packetcount,octetcount,receivetime);
671 
672 	// Call the callback
673 	if (created)
674 		OnNewSource(srcdat);
675 
676 	OnRTCPSenderReport(srcdat);
677 
678 	return 0;
679 }
680 
ProcessRTCPReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t lostpackets,uint32_t exthighseqnr,uint32_t jitter,uint32_t lsr,uint32_t dlsr,const RTPTime & receivetime,const RTPAddress * senderaddress)681 int RTPSources::ProcessRTCPReportBlock(uint32_t ssrc,uint8_t fractionlost,int32_t lostpackets,
682                            uint32_t exthighseqnr,uint32_t jitter,uint32_t lsr,
683 			   uint32_t dlsr,const RTPTime &receivetime,const RTPAddress *senderaddress)
684 {
685 	RTPInternalSourceData *srcdat;
686 	bool created;
687 	int status;
688 
689 	status = GetRTCPSourceData(ssrc,senderaddress,&srcdat,&created);
690 	if (status < 0)
691 		return status;
692 	if (srcdat == 0)
693 		return 0;
694 
695 	srcdat->ProcessReportBlock(fractionlost,lostpackets,exthighseqnr,jitter,lsr,dlsr,receivetime);
696 
697 	// Call the callback
698 	if (created)
699 		OnNewSource(srcdat);
700 
701 	OnRTCPReceiverReport(srcdat);
702 
703 	return 0;
704 }
705 
ProcessSDESNormalItem(uint32_t ssrc,RTCPSDESPacket::ItemType t,size_t itemlength,const void * itemdata,const RTPTime & receivetime,const RTPAddress * senderaddress)706 int RTPSources::ProcessSDESNormalItem(uint32_t ssrc,RTCPSDESPacket::ItemType t,size_t itemlength,
707                           const void *itemdata,const RTPTime &receivetime,const RTPAddress *senderaddress)
708 {
709 	RTPInternalSourceData *srcdat;
710 	bool created,cnamecollis;
711 	int status;
712 	uint8_t sdesid;
713 	bool prevactive;
714 
715 	switch(t)
716 	{
717 	case RTCPSDESPacket::CNAME:
718 		sdesid = RTCP_SDES_ID_CNAME;
719 		break;
720 	case RTCPSDESPacket::NAME:
721 		sdesid = RTCP_SDES_ID_NAME;
722 		break;
723 	case RTCPSDESPacket::EMAIL:
724 		sdesid = RTCP_SDES_ID_EMAIL;
725 		break;
726 	case RTCPSDESPacket::PHONE:
727 		sdesid = RTCP_SDES_ID_PHONE;
728 		break;
729 	case RTCPSDESPacket::LOC:
730 		sdesid = RTCP_SDES_ID_LOCATION;
731 		break;
732 	case RTCPSDESPacket::TOOL:
733 		sdesid = RTCP_SDES_ID_TOOL;
734 		break;
735 	case RTCPSDESPacket::NOTE:
736 		sdesid = RTCP_SDES_ID_NOTE;
737 		break;
738 	default:
739 		return ERR_RTP_SOURCES_ILLEGALSDESTYPE;
740 	}
741 
742 	status = GetRTCPSourceData(ssrc,senderaddress,&srcdat,&created);
743 	if (status < 0)
744 		return status;
745 	if (srcdat == 0)
746 		return 0;
747 
748 	prevactive = srcdat->IsActive();
749 	status = srcdat->ProcessSDESItem(sdesid,(const uint8_t *)itemdata,itemlength,receivetime,&cnamecollis);
750 	if (!prevactive && srcdat->IsActive())
751 		activecount++;
752 
753 	// Call the callback
754 	if (created)
755 		OnNewSource(srcdat);
756 	if (cnamecollis)
757 		OnCNAMECollision(srcdat,senderaddress,(const uint8_t *)itemdata,itemlength);
758 
759 	if (status >= 0)
760 		OnRTCPSDESItem(srcdat, t, itemdata, itemlength);
761 
762 	return status;
763 }
764 
765 #ifdef RTP_SUPPORT_SDESPRIV
ProcessSDESPrivateItem(uint32_t ssrc,size_t prefixlen,const void * prefixdata,size_t valuelen,const void * valuedata,const RTPTime & receivetime,const RTPAddress * senderaddress)766 int RTPSources::ProcessSDESPrivateItem(uint32_t ssrc,size_t prefixlen,const void *prefixdata,
767                            size_t valuelen,const void *valuedata,const RTPTime &receivetime,
768 			   const RTPAddress *senderaddress)
769 {
770 	RTPInternalSourceData *srcdat;
771 	bool created;
772 	int status;
773 
774 	status = GetRTCPSourceData(ssrc,senderaddress,&srcdat,&created);
775 	if (status < 0)
776 		return status;
777 	if (srcdat == 0)
778 		return 0;
779 
780 	status = srcdat->ProcessPrivateSDESItem((const uint8_t *)prefixdata,prefixlen,(const uint8_t *)valuedata,valuelen,receivetime);
781 	// Call the callback
782 	if (created)
783 		OnNewSource(srcdat);
784 
785 	if (status >= 0)
786 		OnRTCPSDESPrivateItem(srcdat, prefixdata, prefixlen, valuedata, valuelen);
787 
788 	return status;
789 }
790 #endif //RTP_SUPPORT_SDESPRIV
791 
ProcessBYE(uint32_t ssrc,size_t reasonlength,const void * reasondata,const RTPTime & receivetime,const RTPAddress * senderaddress)792 int RTPSources::ProcessBYE(uint32_t ssrc,size_t reasonlength,const void *reasondata,
793 		           const RTPTime &receivetime,const RTPAddress *senderaddress)
794 {
795 	RTPInternalSourceData *srcdat;
796 	bool created;
797 	int status;
798 	bool prevactive;
799 
800 	status = GetRTCPSourceData(ssrc,senderaddress,&srcdat,&created);
801 	if (status < 0)
802 		return status;
803 	if (srcdat == 0)
804 		return 0;
805 
806 	// we'll ignore BYE packets for our own ssrc
807 	if (srcdat == owndata)
808 		return 0;
809 
810 	prevactive = srcdat->IsActive();
811 	srcdat->ProcessBYEPacket((const uint8_t *)reasondata,reasonlength,receivetime);
812 	if (prevactive && !srcdat->IsActive())
813 		activecount--;
814 
815 	// Call the callback
816 	if (created)
817 		OnNewSource(srcdat);
818 	OnBYEPacket(srcdat);
819 	return 0;
820 }
821 
ObtainSourceDataInstance(uint32_t ssrc,RTPInternalSourceData ** srcdat,bool * created)822 int RTPSources::ObtainSourceDataInstance(uint32_t ssrc,RTPInternalSourceData **srcdat,bool *created)
823 {
824 	RTPInternalSourceData *srcdat2;
825 	int status;
826 
827 	if (sourcelist.GotoElement(ssrc) < 0) // No entry for this source
828 	{
829 #ifdef RTP_SUPPORT_PROBATION
830 		srcdat2 = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPINTERNALSOURCEDATA) RTPInternalSourceData(ssrc,probationtype,GetMemoryManager());
831 #else
832 		srcdat2 = RTPNew(GetMemoryManager(),RTPMEM_TYPE_CLASS_RTPINTERNALSOURCEDATA) RTPInternalSourceData(ssrc,RTPSources::NoProbation,GetMemoryManager());
833 #endif // RTP_SUPPORT_PROBATION
834 		if (srcdat2 == 0)
835 			return ERR_RTP_OUTOFMEM;
836 		if ((status = sourcelist.AddElement(ssrc,srcdat2)) < 0)
837 		{
838 			RTPDelete(srcdat2,GetMemoryManager());
839 			return status;
840 		}
841 		*srcdat = srcdat2;
842 		*created = true;
843 		totalcount++;
844 	}
845 	else
846 	{
847 		*srcdat = sourcelist.GetCurrentElement();
848 		*created = false;
849 	}
850 	return 0;
851 }
852 
853 
GetRTCPSourceData(uint32_t ssrc,const RTPAddress * senderaddress,RTPInternalSourceData ** srcdat2,bool * newsource)854 int RTPSources::GetRTCPSourceData(uint32_t ssrc,const RTPAddress *senderaddress,
855 		                  RTPInternalSourceData **srcdat2,bool *newsource)
856 {
857 	int status;
858 	bool created;
859 	RTPInternalSourceData *srcdat;
860 
861 	*srcdat2 = 0;
862 
863 	if ((status = ObtainSourceDataInstance(ssrc,&srcdat,&created)) < 0)
864 		return status;
865 
866 	if (created)
867 	{
868 		if ((status = srcdat->SetRTCPDataAddress(senderaddress)) < 0)
869 			return status;
870 	}
871 	else // got a previously existing source
872 	{
873 		if (CheckCollision(srcdat,senderaddress,false))
874 			return 0; // ignore packet on collision
875 	}
876 
877 	*srcdat2 = srcdat;
878 	*newsource = created;
879 
880 	return 0;
881 }
882 
UpdateReceiveTime(uint32_t ssrc,const RTPTime & receivetime,const RTPAddress * senderaddress)883 int RTPSources::UpdateReceiveTime(uint32_t ssrc,const RTPTime &receivetime,const RTPAddress *senderaddress)
884 {
885 	RTPInternalSourceData *srcdat;
886 	bool created;
887 	int status;
888 
889 	status = GetRTCPSourceData(ssrc,senderaddress,&srcdat,&created);
890 	if (status < 0)
891 		return status;
892 	if (srcdat == 0)
893 		return 0;
894 
895 	// We got valid SSRC info
896 	srcdat->UpdateMessageTime(receivetime);
897 
898 	// Call the callback
899 	if (created)
900 		OnNewSource(srcdat);
901 
902 	return 0;
903 }
904 
Timeout(const RTPTime & curtime,const RTPTime & timeoutdelay)905 void RTPSources::Timeout(const RTPTime &curtime,const RTPTime &timeoutdelay)
906 {
907 	int newtotalcount = 0;
908 	int newsendercount = 0;
909 	int newactivecount = 0;
910 	RTPTime checktime = curtime;
911 	checktime -= timeoutdelay;
912 
913 	sourcelist.GotoFirstElement();
914 	while (sourcelist.HasCurrentElement())
915 	{
916 		RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
917 		RTPTime lastmsgtime = srcdat->INF_GetLastMessageTime();
918 
919 		// we don't want to time out ourselves
920 		if ((srcdat != owndata) && (lastmsgtime < checktime)) // timeout
921 		{
922 
923 			totalcount--;
924 			if (srcdat->IsSender())
925 				sendercount--;
926 			if (srcdat->IsActive())
927 				activecount--;
928 
929 			sourcelist.DeleteCurrentElement();
930 
931 			OnTimeout(srcdat);
932 			OnRemoveSource(srcdat);
933 			RTPDelete(srcdat,GetMemoryManager());
934 		}
935 		else
936 		{
937 			newtotalcount++;
938 			if (srcdat->IsSender())
939 				newsendercount++;
940 			if (srcdat->IsActive())
941 				newactivecount++;
942 			sourcelist.GotoNextElement();
943 		}
944 	}
945 
946 #ifdef RTPDEBUG
947 	if (newtotalcount != totalcount)
948 	{
949 		std::cout << "New total count " << newtotalcount << " doesnt match old total count " << totalcount << std::endl;
950 		SafeCountTotal();
951 	}
952 	if (newsendercount != sendercount)
953 	{
954 		std::cout << "New sender count " << newsendercount << " doesnt match old sender count " << sendercount << std::endl;
955 		SafeCountSenders();
956 	}
957 	if (newactivecount != activecount)
958 	{
959 		std::cout << "New active count " << newactivecount << " doesnt match old active count " << activecount << std::endl;
960 		SafeCountActive();
961 	}
962 #endif // RTPDEBUG
963 
964 	totalcount = newtotalcount; // just to play it safe
965 	sendercount = newsendercount;
966 	activecount = newactivecount;
967 }
968 
SenderTimeout(const RTPTime & curtime,const RTPTime & timeoutdelay)969 void RTPSources::SenderTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay)
970 {
971 	int newtotalcount = 0;
972 	int newsendercount = 0;
973 	int newactivecount = 0;
974 	RTPTime checktime = curtime;
975 	checktime -= timeoutdelay;
976 
977 	sourcelist.GotoFirstElement();
978 	while (sourcelist.HasCurrentElement())
979 	{
980 		RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
981 
982 		newtotalcount++;
983 		if (srcdat->IsActive())
984 			newactivecount++;
985 
986 		if (srcdat->IsSender())
987 		{
988 			RTPTime lastrtppacktime = srcdat->INF_GetLastRTPPacketTime();
989 
990 			if (lastrtppacktime < checktime) // timeout
991 			{
992 				srcdat->ClearSenderFlag();
993 				sendercount--;
994 			}
995 			else
996 				newsendercount++;
997 		}
998 		sourcelist.GotoNextElement();
999 	}
1000 
1001 #ifdef RTPDEBUG
1002 	if (newtotalcount != totalcount)
1003 	{
1004 		std::cout << "New total count " << newtotalcount << " doesnt match old total count " << totalcount << std::endl;
1005 		SafeCountTotal();
1006 	}
1007 	if (newsendercount != sendercount)
1008 	{
1009 		std::cout << "New sender count " << newsendercount << " doesnt match old sender count " << sendercount << std::endl;
1010 		SafeCountSenders();
1011 	}
1012 	if (newactivecount != activecount)
1013 	{
1014 		std::cout << "New active count " << newactivecount << " doesnt match old active count " << activecount << std::endl;
1015 		SafeCountActive();
1016 	}
1017 #endif // RTPDEBUG
1018 
1019 	totalcount = newtotalcount; // just to play it safe
1020 	sendercount = newsendercount;
1021 	activecount = newactivecount;
1022 }
1023 
BYETimeout(const RTPTime & curtime,const RTPTime & timeoutdelay)1024 void RTPSources::BYETimeout(const RTPTime &curtime,const RTPTime &timeoutdelay)
1025 {
1026 	int newtotalcount = 0;
1027 	int newsendercount = 0;
1028 	int newactivecount = 0;
1029 	RTPTime checktime = curtime;
1030 	checktime -= timeoutdelay;
1031 
1032 	sourcelist.GotoFirstElement();
1033 	while (sourcelist.HasCurrentElement())
1034 	{
1035 		RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
1036 
1037 		if (srcdat->ReceivedBYE())
1038 		{
1039 			RTPTime byetime = srcdat->GetBYETime();
1040 
1041 			if ((srcdat != owndata) && (checktime > byetime))
1042 			{
1043 				totalcount--;
1044 				if (srcdat->IsSender())
1045 					sendercount--;
1046 				if (srcdat->IsActive())
1047 					activecount--;
1048 				sourcelist.DeleteCurrentElement();
1049 				OnBYETimeout(srcdat);
1050 				OnRemoveSource(srcdat);
1051 				RTPDelete(srcdat,GetMemoryManager());
1052 			}
1053 			else
1054 			{
1055 				newtotalcount++;
1056 				if (srcdat->IsSender())
1057 					newsendercount++;
1058 				if (srcdat->IsActive())
1059 					newactivecount++;
1060 				sourcelist.GotoNextElement();
1061 			}
1062 		}
1063 		else
1064 		{
1065 			newtotalcount++;
1066 			if (srcdat->IsSender())
1067 				newsendercount++;
1068 			if (srcdat->IsActive())
1069 				newactivecount++;
1070 			sourcelist.GotoNextElement();
1071 		}
1072 	}
1073 
1074 #ifdef RTPDEBUG
1075 	if (newtotalcount != totalcount)
1076 	{
1077 		std::cout << "New total count " << newtotalcount << " doesnt match old total count " << totalcount << std::endl;
1078 		SafeCountTotal();
1079 	}
1080 	if (newsendercount != sendercount)
1081 	{
1082 		std::cout << "New sender count " << newsendercount << " doesnt match old sender count " << sendercount << std::endl;
1083 		SafeCountSenders();
1084 	}
1085 	if (newactivecount != activecount)
1086 	{
1087 		std::cout << "New active count " << newactivecount << " doesnt match old active count " << activecount << std::endl;
1088 		SafeCountActive();
1089 	}
1090 #endif // RTPDEBUG
1091 
1092 	totalcount = newtotalcount; // just to play it safe
1093 	sendercount = newsendercount;
1094 	activecount = newactivecount;
1095 }
1096 
NoteTimeout(const RTPTime & curtime,const RTPTime & timeoutdelay)1097 void RTPSources::NoteTimeout(const RTPTime &curtime,const RTPTime &timeoutdelay)
1098 {
1099 	int newtotalcount = 0;
1100 	int newsendercount = 0;
1101 	int newactivecount = 0;
1102 	RTPTime checktime = curtime;
1103 	checktime -= timeoutdelay;
1104 
1105 	sourcelist.GotoFirstElement();
1106 	while (sourcelist.HasCurrentElement())
1107 	{
1108 		RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
1109 		size_t notelen;
1110 
1111         	srcdat->SDES_GetNote(&notelen);
1112 		if (notelen != 0) // Note has been set
1113 		{
1114 			RTPTime notetime = srcdat->INF_GetLastSDESNoteTime();
1115 
1116 			if (checktime > notetime)
1117 			{
1118 				srcdat->ClearNote();
1119 				OnNoteTimeout(srcdat);
1120 			}
1121 		}
1122 
1123 		newtotalcount++;
1124 		if (srcdat->IsSender())
1125 			newsendercount++;
1126 		if (srcdat->IsActive())
1127 			newactivecount++;
1128 		sourcelist.GotoNextElement();
1129 	}
1130 
1131 #ifdef RTPDEBUG
1132 	if (newtotalcount != totalcount)
1133 	{
1134 		std::cout << "New total count " << newtotalcount << " doesnt match old total count " << totalcount << std::endl;
1135 		SafeCountTotal();
1136 	}
1137 	if (newsendercount != sendercount)
1138 	{
1139 		std::cout << "New sender count " << newsendercount << " doesnt match old sender count " << sendercount << std::endl;
1140 		SafeCountSenders();
1141 	}
1142 	if (newactivecount != activecount)
1143 	{
1144 		std::cout << "New active count " << newactivecount << " doesnt match old active count " << activecount << std::endl;
1145 		SafeCountActive();
1146 	}
1147 #endif // RTPDEBUG
1148 
1149 	totalcount = newtotalcount; // just to play it safe
1150 	sendercount = newsendercount;
1151 	activecount = newactivecount;
1152 
1153 }
1154 
MultipleTimeouts(const RTPTime & curtime,const RTPTime & sendertimeout,const RTPTime & byetimeout,const RTPTime & generaltimeout,const RTPTime & notetimeout)1155 void RTPSources::MultipleTimeouts(const RTPTime &curtime,const RTPTime &sendertimeout,const RTPTime &byetimeout,const RTPTime &generaltimeout,const RTPTime &notetimeout)
1156 {
1157 	int newtotalcount = 0;
1158 	int newsendercount = 0;
1159 	int newactivecount = 0;
1160 	RTPTime senderchecktime = curtime;
1161 	RTPTime byechecktime = curtime;
1162 	RTPTime generaltchecktime = curtime;
1163 	RTPTime notechecktime = curtime;
1164 	senderchecktime -= sendertimeout;
1165 	byechecktime -= byetimeout;
1166 	generaltchecktime -= generaltimeout;
1167 	notechecktime -= notetimeout;
1168 
1169 	sourcelist.GotoFirstElement();
1170 	while (sourcelist.HasCurrentElement())
1171 	{
1172 		RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
1173 		bool deleted,issender,isactive;
1174 		bool byetimeout,normaltimeout,notetimeout;
1175 
1176 		size_t notelen;
1177 
1178 		issender = srcdat->IsSender();
1179 		isactive = srcdat->IsActive();
1180 		deleted = false;
1181 		byetimeout = false;
1182 		normaltimeout = false;
1183 		notetimeout = false;
1184 
1185         	srcdat->SDES_GetNote(&notelen);
1186 		if (notelen != 0) // Note has been set
1187 		{
1188 			RTPTime notetime = srcdat->INF_GetLastSDESNoteTime();
1189 
1190 			if (notechecktime > notetime)
1191 			{
1192 				notetimeout = true;
1193 				srcdat->ClearNote();
1194 			}
1195 		}
1196 
1197 		if (srcdat->ReceivedBYE())
1198 		{
1199 			RTPTime byetime = srcdat->GetBYETime();
1200 
1201 			if ((srcdat != owndata) && (byechecktime > byetime))
1202 			{
1203 				sourcelist.DeleteCurrentElement();
1204 				deleted = true;
1205 				byetimeout = true;
1206 			}
1207 		}
1208 
1209 		if (!deleted)
1210 		{
1211 			RTPTime lastmsgtime = srcdat->INF_GetLastMessageTime();
1212 
1213 			if ((srcdat != owndata) && (lastmsgtime < generaltchecktime))
1214 			{
1215 				sourcelist.DeleteCurrentElement();
1216 				deleted = true;
1217 				normaltimeout = true;
1218 			}
1219 		}
1220 
1221 		if (!deleted)
1222 		{
1223 			newtotalcount++;
1224 
1225 			if (issender)
1226 			{
1227 				RTPTime lastrtppacktime = srcdat->INF_GetLastRTPPacketTime();
1228 
1229 				if (lastrtppacktime < senderchecktime)
1230 				{
1231 					srcdat->ClearSenderFlag();
1232 					sendercount--;
1233 				}
1234 				else
1235 					newsendercount++;
1236 			}
1237 
1238 			if (isactive)
1239 				newactivecount++;
1240 
1241 			if (notetimeout)
1242 				OnNoteTimeout(srcdat);
1243 
1244 			sourcelist.GotoNextElement();
1245 		}
1246 		else // deleted entry
1247 		{
1248 			if (issender)
1249 				sendercount--;
1250 			if (isactive)
1251 				activecount--;
1252 			totalcount--;
1253 
1254 			if (byetimeout)
1255 				OnBYETimeout(srcdat);
1256 			if (normaltimeout)
1257 				OnTimeout(srcdat);
1258 			OnRemoveSource(srcdat);
1259 			RTPDelete(srcdat,GetMemoryManager());
1260 		}
1261 	}
1262 
1263 #ifdef RTPDEBUG
1264 	if (newtotalcount != totalcount)
1265 	{
1266 		SafeCountTotal();
1267 		std::cout << "New total count " << newtotalcount << " doesnt match old total count " << totalcount << std::endl;
1268 	}
1269 	if (newsendercount != sendercount)
1270 	{
1271 		SafeCountSenders();
1272 		std::cout << "New sender count " << newsendercount << " doesnt match old sender count " << sendercount << std::endl;
1273 	}
1274 	if (newactivecount != activecount)
1275 	{
1276 		std::cout << "New active count " << newactivecount << " doesnt match old active count " << activecount << std::endl;
1277 		SafeCountActive();
1278 	}
1279 #endif // RTPDEBUG
1280 
1281 	totalcount = newtotalcount; // just to play it safe
1282 	sendercount = newsendercount;
1283 	activecount = newactivecount;
1284 }
1285 
1286 #ifdef RTPDEBUG
Dump()1287 void RTPSources::Dump()
1288 {
1289 	std::cout << "Total count:  " << totalcount << std::endl;
1290 	std::cout << "Sender count: " << sendercount << std::endl;
1291 	std::cout << "Active count: " << activecount << std::endl;
1292 	if (GotoFirstSource())
1293 	{
1294 		do
1295 		{
1296 			RTPSourceData *s;
1297 			s = GetCurrentSourceInfo();
1298 			s->Dump();
1299 			std::cout << std::endl;
1300 		} while (GotoNextSource());
1301 	}
1302 }
1303 
SafeCountTotal()1304 void RTPSources::SafeCountTotal()
1305 {
1306 	int count = 0;
1307 
1308 	if (GotoFirstSource())
1309 	{
1310 		do
1311 		{
1312 			count++;
1313 		} while (GotoNextSource());
1314 	}
1315 	std::cout << "Actual total count: " << count << std::endl;
1316 }
1317 
SafeCountSenders()1318 void RTPSources::SafeCountSenders()
1319 {
1320 	int count = 0;
1321 
1322 	if (GotoFirstSource())
1323 	{
1324 		do
1325 		{
1326 			RTPSourceData *s;
1327 			s = GetCurrentSourceInfo();
1328 			if (s->IsSender())
1329 				count++;
1330 		} while (GotoNextSource());
1331 	}
1332 	std::cout << "Actual sender count: " << count << std::endl;
1333 }
1334 
SafeCountActive()1335 void RTPSources::SafeCountActive()
1336 {
1337 	int count = 0;
1338 
1339 	if (GotoFirstSource())
1340 	{
1341 		do
1342 		{
1343 			RTPSourceData *s;
1344 			s = GetCurrentSourceInfo();
1345 			if (s->IsActive())
1346 				count++;
1347 		} while (GotoNextSource());
1348 	}
1349 	std::cout << "Actual active count: " << count << std::endl;
1350 }
1351 
1352 #endif // RTPDEBUG
1353 
CheckCollision(RTPInternalSourceData * srcdat,const RTPAddress * senderaddress,bool isrtp)1354 bool RTPSources::CheckCollision(RTPInternalSourceData *srcdat,const RTPAddress *senderaddress,bool isrtp)
1355 {
1356 	bool isset,otherisset;
1357 	const RTPAddress *addr,*otheraddr;
1358 
1359 	if (isrtp)
1360 	{
1361 		isset = srcdat->IsRTPAddressSet();
1362 		addr = srcdat->GetRTPDataAddress();
1363 		otherisset = srcdat->IsRTCPAddressSet();
1364 		otheraddr = srcdat->GetRTCPDataAddress();
1365 	}
1366 	else
1367 	{
1368 		isset = srcdat->IsRTCPAddressSet();
1369 		addr = srcdat->GetRTCPDataAddress();
1370 		otherisset = srcdat->IsRTPAddressSet();
1371 		otheraddr = srcdat->GetRTPDataAddress();
1372 	}
1373 
1374 	if (!isset)
1375 	{
1376 		if (otherisset) // got other address, can check if it comes from same host
1377 		{
1378 			if (otheraddr == 0) // other came from our own session
1379 			{
1380 				if (senderaddress != 0)
1381 				{
1382 					OnSSRCCollision(srcdat,senderaddress,isrtp);
1383 					return true;
1384 				}
1385 
1386 				// Ok, store it
1387 
1388 				if (isrtp)
1389 					srcdat->SetRTPDataAddress(senderaddress);
1390 				else
1391 					srcdat->SetRTCPDataAddress(senderaddress);
1392 			}
1393 			else
1394 			{
1395 				if (!otheraddr->IsFromSameHost(senderaddress))
1396 				{
1397 					OnSSRCCollision(srcdat,senderaddress,isrtp);
1398 					return true;
1399 				}
1400 
1401 				// Ok, comes from same host, store the address
1402 
1403 				if (isrtp)
1404 					srcdat->SetRTPDataAddress(senderaddress);
1405 				else
1406 					srcdat->SetRTCPDataAddress(senderaddress);
1407 			}
1408 		}
1409 		else // no other address, store this one
1410 		{
1411 			if (isrtp)
1412 				srcdat->SetRTPDataAddress(senderaddress);
1413 			else
1414 				srcdat->SetRTCPDataAddress(senderaddress);
1415 		}
1416 	}
1417 	else // already got an address
1418 	{
1419 		if (addr == 0)
1420 		{
1421 			if (senderaddress != 0)
1422 			{
1423 				OnSSRCCollision(srcdat,senderaddress,isrtp);
1424 				return true;
1425 			}
1426 		}
1427 		else
1428 		{
1429 			if (!addr->IsSameAddress(senderaddress))
1430 			{
1431 				OnSSRCCollision(srcdat,senderaddress,isrtp);
1432 				return true;
1433 			}
1434 		}
1435 	}
1436 
1437 	return false;
1438 }
1439 
1440 } // end namespace
1441 
1442