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