mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			1259 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1259 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| 
 | |
|  This file is a part of JRTPLIB
 | |
|  Copyright (c) 1999-2017 Jori Liesenborgs
 | |
| 
 | |
|  Contact: jori.liesenborgs@gmail.com
 | |
| 
 | |
|  This library was developed at the Expertise Centre for Digital Media
 | |
|  (http://www.edm.uhasselt.be), a research center of the Hasselt University
 | |
|  (http://www.uhasselt.be). The library is based upon work done for
 | |
|  my thesis at the School for Knowledge Technology (Belgium/The Netherlands).
 | |
| 
 | |
|  Permission is hereby granted, free of charge, to any person obtaining a
 | |
|  copy of this software and associated documentation files (the "Software"),
 | |
|  to deal in the Software without restriction, including without limitation
 | |
|  the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|  and/or sell copies of the Software, and to permit persons to whom the
 | |
|  Software is furnished to do so, subject to the following conditions:
 | |
| 
 | |
|  The above copyright notice and this permission notice shall be included
 | |
|  in all copies or substantial portions of the Software.
 | |
| 
 | |
|  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | |
|  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 | |
|  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | |
|  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 | |
|  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 | |
|  IN THE SOFTWARE.
 | |
| 
 | |
|  */
 | |
| 
 | |
| #include "rtpsources.h"
 | |
| #include "rtperrors.h"
 | |
| #include "rtprawpacket.h"
 | |
| #include "rtpinternalsourcedata.h"
 | |
| #include "rtptimeutilities.h"
 | |
| #include "rtpdefines.h"
 | |
| #include "rtcpcompoundpacket.h"
 | |
| #include "rtcppacket.h"
 | |
| #include "rtcpapppacket.h"
 | |
| #include "rtcpbyepacket.h"
 | |
| #include "rtcpsdespacket.h"
 | |
| #include "rtcpsrpacket.h"
 | |
| #include "rtcprrpacket.h"
 | |
| #include "rtptransmitter.h"
 | |
| 
 | |
| namespace qrtplib
 | |
| {
 | |
| 
 | |
| RTPSources::RTPSources()
 | |
| {
 | |
|     totalcount = 0;
 | |
|     sendercount = 0;
 | |
|     activecount = 0;
 | |
|     owndata = 0;
 | |
| }
 | |
| 
 | |
| RTPSources::~RTPSources()
 | |
| {
 | |
|     Clear();
 | |
| }
 | |
| 
 | |
| void RTPSources::Clear()
 | |
| {
 | |
|     ClearSourceList();
 | |
| }
 | |
| 
 | |
| void RTPSources::ClearSourceList()
 | |
| {
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *sourcedata;
 | |
| 
 | |
|         sourcedata = sourcelist.GetCurrentElement();
 | |
|         delete sourcedata;
 | |
|         sourcelist.GotoNextElement();
 | |
|     }
 | |
|     sourcelist.Clear();
 | |
|     owndata = 0;
 | |
|     totalcount = 0;
 | |
|     sendercount = 0;
 | |
|     activecount = 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::CreateOwnSSRC(uint32_t ssrc)
 | |
| {
 | |
|     if (owndata != 0)
 | |
|         return ERR_RTP_SOURCES_ALREADYHAVEOWNSSRC;
 | |
|     if (GotEntry(ssrc))
 | |
|         return ERR_RTP_SOURCES_SSRCEXISTS;
 | |
| 
 | |
|     int status;
 | |
|     bool created;
 | |
| 
 | |
|     status = ObtainSourceDataInstance(ssrc, &owndata, &created);
 | |
|     if (status < 0)
 | |
|     {
 | |
|         owndata = 0; // just to make sure
 | |
|         return status;
 | |
|     }
 | |
|     owndata->SetOwnSSRC();
 | |
|     owndata->SetRTPDataAddress(0);
 | |
|     owndata->SetRTCPDataAddress(0);
 | |
| 
 | |
|     // we've created a validated ssrc, so we should increase activecount
 | |
|     activecount++;
 | |
| 
 | |
|     OnNewSource(owndata);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::DeleteOwnSSRC()
 | |
| {
 | |
|     if (owndata == 0)
 | |
|         return ERR_RTP_SOURCES_DONTHAVEOWNSSRC;
 | |
| 
 | |
|     uint32_t ssrc = owndata->GetSSRC();
 | |
| 
 | |
|     sourcelist.GotoElement(ssrc);
 | |
|     sourcelist.DeleteCurrentElement();
 | |
| 
 | |
|     totalcount--;
 | |
|     if (owndata->IsSender())
 | |
|         sendercount--;
 | |
|     if (owndata->IsActive())
 | |
|         activecount--;
 | |
| 
 | |
|     OnRemoveSource(owndata);
 | |
| 
 | |
|     delete owndata;
 | |
|     owndata = 0;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void RTPSources::SentRTPPacket()
 | |
| {
 | |
|     if (owndata == 0)
 | |
|         return;
 | |
| 
 | |
|     bool prevsender = owndata->IsSender();
 | |
| 
 | |
|     owndata->SentRTPPacket();
 | |
|     if (!prevsender && owndata->IsSender())
 | |
|         sendercount++;
 | |
| }
 | |
| 
 | |
| int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans, bool acceptownpackets)
 | |
| {
 | |
|     RTPTransmitter *transmitters[1];
 | |
|     int num;
 | |
| 
 | |
|     transmitters[0] = rtptrans;
 | |
|     if (rtptrans == 0)
 | |
|         num = 0;
 | |
|     else
 | |
|         num = 1;
 | |
|     return ProcessRawPacket(rawpack, transmitters, num, acceptownpackets);
 | |
| }
 | |
| 
 | |
| int RTPSources::ProcessRawPacket(RTPRawPacket *rawpack, RTPTransmitter *rtptrans[], int numtrans, bool acceptownpackets)
 | |
| {
 | |
|     int status;
 | |
| 
 | |
|     if (rawpack->IsRTP()) // RTP packet
 | |
|     {
 | |
|         RTPPacket *rtppack;
 | |
| 
 | |
|         // First, we'll see if the packet can be parsed
 | |
|         rtppack = new RTPPacket(*rawpack);
 | |
|         if (rtppack == 0)
 | |
|             return ERR_RTP_OUTOFMEM;
 | |
|         if ((status = rtppack->GetCreationError()) < 0)
 | |
|         {
 | |
|             if (status == ERR_RTP_PACKET_INVALIDPACKET)
 | |
|             {
 | |
|                 delete rtppack;
 | |
|                 rtppack = 0;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 delete rtppack;
 | |
|                 return status;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Check if the packet was valid
 | |
|         if (rtppack != 0)
 | |
|         {
 | |
|             bool stored = false;
 | |
|             bool ownpacket = false;
 | |
|             int i;
 | |
|             const RTPAddress& senderaddress = rawpack->GetSenderAddress();
 | |
| 
 | |
|             for (i = 0; !ownpacket && i < numtrans; i++)
 | |
|             {
 | |
|                 if (rtptrans[i]->ComesFromThisTransmitter(senderaddress))
 | |
|                     ownpacket = true;
 | |
|             }
 | |
| 
 | |
|             // Check if the packet is our own.
 | |
|             if (ownpacket)
 | |
|             {
 | |
|                 // Now it depends on the user's preference
 | |
|                 // what to do with this packet:
 | |
|                 if (acceptownpackets)
 | |
|                 {
 | |
|                     // sender addres for own packets has to be NULL!
 | |
|                     if ((status = ProcessRTPPacket(rtppack, rawpack->GetReceiveTime(), 0, &stored)) < 0)
 | |
|                     {
 | |
|                         if (!stored)
 | |
|                             delete rtppack;
 | |
|                         return status;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if ((status = ProcessRTPPacket(rtppack, rawpack->GetReceiveTime(), &senderaddress, &stored)) < 0)
 | |
|                 {
 | |
|                     if (!stored)
 | |
|                         delete rtppack;
 | |
|                     return status;
 | |
|                 }
 | |
|             }
 | |
|             if (!stored)
 | |
|                 delete rtppack;
 | |
|         }
 | |
|     }
 | |
|     else // RTCP packet
 | |
|     {
 | |
|         RTCPCompoundPacket rtcpcomppack(*rawpack);
 | |
|         bool valid = false;
 | |
| 
 | |
|         if ((status = rtcpcomppack.GetCreationError()) < 0)
 | |
|         {
 | |
|             if (status != ERR_RTP_RTCPCOMPOUND_INVALIDPACKET)
 | |
|                 return status;
 | |
|         }
 | |
|         else
 | |
|             valid = true;
 | |
| 
 | |
|         if (valid)
 | |
|         {
 | |
|             bool ownpacket = false;
 | |
|             int i;
 | |
|             const RTPAddress& senderaddress = rawpack->GetSenderAddress();
 | |
| 
 | |
|             for (i = 0; !ownpacket && i < numtrans; i++)
 | |
|             {
 | |
|                 if (rtptrans[i]->ComesFromThisTransmitter(senderaddress))
 | |
|                     ownpacket = true;
 | |
|             }
 | |
| 
 | |
|             // First check if it's a packet of this session.
 | |
|             if (ownpacket)
 | |
|             {
 | |
|                 if (acceptownpackets)
 | |
|                 {
 | |
|                     // sender address for own packets has to be NULL
 | |
|                     status = ProcessRTCPCompoundPacket(&rtcpcomppack, rawpack->GetReceiveTime(), 0);
 | |
|                     if (status < 0)
 | |
|                         return status;
 | |
|                 }
 | |
|             }
 | |
|             else // not our own packet
 | |
|             {
 | |
|                 status = ProcessRTCPCompoundPacket(&rtcpcomppack, rawpack->GetReceiveTime(), &rawpack->GetSenderAddress());
 | |
|                 if (status < 0)
 | |
|                     return status;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::ProcessRTPPacket(RTPPacket *rtppack, const RTPTime &receivetime, const RTPAddress *senderaddress, bool *stored)
 | |
| {
 | |
|     uint32_t ssrc;
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     int status;
 | |
|     bool created;
 | |
| 
 | |
|     OnRTPPacket(rtppack, receivetime, senderaddress);
 | |
| 
 | |
|     *stored = false;
 | |
| 
 | |
|     ssrc = rtppack->GetSSRC();
 | |
|     if ((status = ObtainSourceDataInstance(ssrc, &srcdat, &created)) < 0)
 | |
|         return status;
 | |
| 
 | |
|     if (created)
 | |
|     {
 | |
|         if ((status = srcdat->SetRTPDataAddress(senderaddress)) < 0)
 | |
|             return status;
 | |
|     }
 | |
|     else // got a previously existing source
 | |
|     {
 | |
|         if (CheckCollision(srcdat, senderaddress, true))
 | |
|             return 0; // ignore packet on collision
 | |
|     }
 | |
| 
 | |
|     bool prevsender = srcdat->IsSender();
 | |
|     bool prevactive = srcdat->IsActive();
 | |
| 
 | |
|     uint32_t CSRCs[RTP_MAXCSRCS];
 | |
|     int numCSRCs = rtppack->GetCSRCCount();
 | |
|     if (numCSRCs > RTP_MAXCSRCS) // shouldn't happen, but better to check than go out of bounds
 | |
|         numCSRCs = RTP_MAXCSRCS;
 | |
| 
 | |
|     for (int i = 0; i < numCSRCs; i++)
 | |
|         CSRCs[i] = rtppack->GetCSRC(i);
 | |
| 
 | |
|     // The packet comes from a valid source, we can process it further now
 | |
|     // The following function should delete rtppack itself if something goes
 | |
|     // wrong
 | |
|     if ((status = srcdat->ProcessRTPPacket(rtppack, receivetime, stored, this)) < 0)
 | |
|         return status;
 | |
| 
 | |
|     // NOTE: we cannot use 'rtppack' anymore since it may have been deleted in
 | |
|     //       OnValidatedRTPPacket
 | |
| 
 | |
|     if (!prevsender && srcdat->IsSender())
 | |
|         sendercount++;
 | |
|     if (!prevactive && srcdat->IsActive())
 | |
|         activecount++;
 | |
| 
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
| 
 | |
|     if (srcdat->IsValidated()) // process the CSRCs
 | |
|     {
 | |
|         RTPInternalSourceData *csrcdat;
 | |
|         bool createdcsrc;
 | |
| 
 | |
|         int num = numCSRCs;
 | |
|         int i;
 | |
| 
 | |
|         for (i = 0; i < num; i++)
 | |
|         {
 | |
|             if ((status = ObtainSourceDataInstance(CSRCs[i], &csrcdat, &createdcsrc)) < 0)
 | |
|                 return status;
 | |
|             if (createdcsrc)
 | |
|             {
 | |
|                 csrcdat->SetCSRC();
 | |
|                 if (csrcdat->IsActive())
 | |
|                     activecount++;
 | |
|                 OnNewSource(csrcdat);
 | |
|             }
 | |
|             else // already found an entry, possibly because of RTCP data
 | |
|             {
 | |
|                 if (!CheckCollision(csrcdat, senderaddress, true))
 | |
|                     csrcdat->SetCSRC();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::ProcessRTCPCompoundPacket(RTCPCompoundPacket *rtcpcomppack, const RTPTime &receivetime, const RTPAddress *senderaddress)
 | |
| {
 | |
|     RTCPPacket *rtcppack;
 | |
|     int status;
 | |
|     bool gotownssrc = ((owndata == 0) ? false : true);
 | |
|     uint32_t ownssrc = ((owndata != 0) ? owndata->GetSSRC() : 0);
 | |
| 
 | |
|     OnRTCPCompoundPacket(rtcpcomppack, receivetime, senderaddress);
 | |
| 
 | |
|     rtcpcomppack->GotoFirstPacket();
 | |
|     while ((rtcppack = rtcpcomppack->GetNextPacket()) != 0)
 | |
|     {
 | |
|         if (rtcppack->IsKnownFormat())
 | |
|         {
 | |
|             switch (rtcppack->GetPacketType())
 | |
|             {
 | |
|             case RTCPPacket::SR:
 | |
|             {
 | |
|                 RTCPSRPacket *p = (RTCPSRPacket *) rtcppack;
 | |
|                 uint32_t senderssrc = p->GetSenderSSRC();
 | |
| 
 | |
|                 status = ProcessRTCPSenderInfo(senderssrc, p->GetNTPTimestamp(), p->GetRTPTimestamp(), p->GetSenderPacketCount(), p->GetSenderOctetCount(), receivetime,
 | |
|                         senderaddress);
 | |
|                 if (status < 0)
 | |
|                     return status;
 | |
| 
 | |
|                 bool gotinfo = false;
 | |
|                 if (gotownssrc)
 | |
|                 {
 | |
|                     int i;
 | |
|                     int num = p->GetReceptionReportCount();
 | |
|                     for (i = 0; i < num; i++)
 | |
|                     {
 | |
|                         if (p->GetSSRC(i) == ownssrc) // data is meant for us
 | |
|                         {
 | |
|                             gotinfo = true;
 | |
|                             status = ProcessRTCPReportBlock(senderssrc, p->GetFractionLost(i), p->GetLostPacketCount(i), p->GetExtendedHighestSequenceNumber(i), p->GetJitter(i),
 | |
|                                     p->GetLSR(i), p->GetDLSR(i), receivetime, senderaddress);
 | |
|                             if (status < 0)
 | |
|                                 return status;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 if (!gotinfo)
 | |
|                 {
 | |
|                     status = UpdateReceiveTime(senderssrc, receivetime, senderaddress);
 | |
|                     if (status < 0)
 | |
|                         return status;
 | |
|                 }
 | |
|             }
 | |
|                 break;
 | |
|             case RTCPPacket::RR:
 | |
|             {
 | |
|                 RTCPRRPacket *p = (RTCPRRPacket *) rtcppack;
 | |
|                 uint32_t senderssrc = p->GetSenderSSRC();
 | |
| 
 | |
|                 bool gotinfo = false;
 | |
| 
 | |
|                 if (gotownssrc)
 | |
|                 {
 | |
|                     int i;
 | |
|                     int num = p->GetReceptionReportCount();
 | |
|                     for (i = 0; i < num; i++)
 | |
|                     {
 | |
|                         if (p->GetSSRC(i) == ownssrc)
 | |
|                         {
 | |
|                             gotinfo = true;
 | |
|                             status = ProcessRTCPReportBlock(senderssrc, p->GetFractionLost(i), p->GetLostPacketCount(i), p->GetExtendedHighestSequenceNumber(i), p->GetJitter(i),
 | |
|                                     p->GetLSR(i), p->GetDLSR(i), receivetime, senderaddress);
 | |
|                             if (status < 0)
 | |
|                                 return status;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 if (!gotinfo)
 | |
|                 {
 | |
|                     status = UpdateReceiveTime(senderssrc, receivetime, senderaddress);
 | |
|                     if (status < 0)
 | |
|                         return status;
 | |
|                 }
 | |
|             }
 | |
|                 break;
 | |
|             case RTCPPacket::SDES:
 | |
|             {
 | |
|                 RTCPSDESPacket *p = (RTCPSDESPacket *) rtcppack;
 | |
| 
 | |
|                 if (p->GotoFirstChunk())
 | |
|                 {
 | |
|                     do
 | |
|                     {
 | |
|                         uint32_t sdesssrc = p->GetChunkSSRC();
 | |
|                         bool updated = false;
 | |
|                         if (p->GotoFirstItem())
 | |
|                         {
 | |
|                             do
 | |
|                             {
 | |
|                                 RTCPSDESPacket::ItemType t;
 | |
| 
 | |
|                                 if ((t = p->GetItemType()) != RTCPSDESPacket::PRIV)
 | |
|                                 {
 | |
|                                     updated = true;
 | |
|                                     status = ProcessSDESNormalItem(sdesssrc, t, p->GetItemLength(), p->GetItemData(), receivetime, senderaddress);
 | |
|                                     if (status < 0)
 | |
|                                         return status;
 | |
|                                 }
 | |
| #ifdef RTP_SUPPORT_SDESPRIV
 | |
|                                 else
 | |
|                                 {
 | |
|                                     updated = true;
 | |
|                                     status = ProcessSDESPrivateItem(sdesssrc, p->GetPRIVPrefixLength(), p->GetPRIVPrefixData(), p->GetPRIVValueLength(), p->GetPRIVValueData(),
 | |
|                                             receivetime, senderaddress);
 | |
|                                     if (status < 0)
 | |
|                                         return status;
 | |
|                                 }
 | |
| #endif // RTP_SUPPORT_SDESPRIV
 | |
|                             } while (p->GotoNextItem());
 | |
|                         }
 | |
|                         if (!updated)
 | |
|                         {
 | |
|                             status = UpdateReceiveTime(sdesssrc, receivetime, senderaddress);
 | |
|                             if (status < 0)
 | |
|                                 return status;
 | |
|                         }
 | |
|                     } while (p->GotoNextChunk());
 | |
|                 }
 | |
|             }
 | |
|                 break;
 | |
|             case RTCPPacket::BYE:
 | |
|             {
 | |
|                 RTCPBYEPacket *p = (RTCPBYEPacket *) rtcppack;
 | |
|                 int i;
 | |
|                 int num = p->GetSSRCCount();
 | |
| 
 | |
|                 for (i = 0; i < num; i++)
 | |
|                 {
 | |
|                     uint32_t byessrc = p->GetSSRC(i);
 | |
|                     status = ProcessBYE(byessrc, p->GetReasonLength(), p->GetReasonData(), receivetime, senderaddress);
 | |
|                     if (status < 0)
 | |
|                         return status;
 | |
|                 }
 | |
|             }
 | |
|                 break;
 | |
|             case RTCPPacket::APP:
 | |
|             {
 | |
|                 RTCPAPPPacket *p = (RTCPAPPPacket *) rtcppack;
 | |
| 
 | |
|                 OnAPPPacket(p, receivetime, senderaddress);
 | |
|             }
 | |
|                 break;
 | |
|             case RTCPPacket::Unknown:
 | |
|             default:
 | |
|             {
 | |
|                 OnUnknownPacketType(rtcppack, receivetime, senderaddress);
 | |
|             }
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             OnUnknownPacketFormat(rtcppack, receivetime, senderaddress);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotoFirstSource()
 | |
| {
 | |
|     sourcelist.GotoFirstElement();
 | |
|     if (sourcelist.HasCurrentElement())
 | |
|         return true;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotoNextSource()
 | |
| {
 | |
|     sourcelist.GotoNextElement();
 | |
|     if (sourcelist.HasCurrentElement())
 | |
|         return true;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotoPreviousSource()
 | |
| {
 | |
|     sourcelist.GotoPreviousElement();
 | |
|     if (sourcelist.HasCurrentElement())
 | |
|         return true;
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotoFirstSourceWithData()
 | |
| {
 | |
|     bool found = false;
 | |
| 
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (!found && sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat;
 | |
| 
 | |
|         srcdat = sourcelist.GetCurrentElement();
 | |
|         if (srcdat->HasData())
 | |
|             found = true;
 | |
|         else
 | |
|             sourcelist.GotoNextElement();
 | |
|     }
 | |
| 
 | |
|     return found;
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotoNextSourceWithData()
 | |
| {
 | |
|     bool found = false;
 | |
| 
 | |
|     sourcelist.GotoNextElement();
 | |
|     while (!found && sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat;
 | |
| 
 | |
|         srcdat = sourcelist.GetCurrentElement();
 | |
|         if (srcdat->HasData())
 | |
|             found = true;
 | |
|         else
 | |
|             sourcelist.GotoNextElement();
 | |
|     }
 | |
| 
 | |
|     return found;
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotoPreviousSourceWithData()
 | |
| {
 | |
|     bool found = false;
 | |
| 
 | |
|     sourcelist.GotoPreviousElement();
 | |
|     while (!found && sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat;
 | |
| 
 | |
|         srcdat = sourcelist.GetCurrentElement();
 | |
|         if (srcdat->HasData())
 | |
|             found = true;
 | |
|         else
 | |
|             sourcelist.GotoPreviousElement();
 | |
|     }
 | |
| 
 | |
|     return found;
 | |
| }
 | |
| 
 | |
| RTPSourceData *RTPSources::GetCurrentSourceInfo()
 | |
| {
 | |
|     if (!sourcelist.HasCurrentElement())
 | |
|         return 0;
 | |
|     return sourcelist.GetCurrentElement();
 | |
| }
 | |
| 
 | |
| RTPSourceData *RTPSources::GetSourceInfo(uint32_t ssrc)
 | |
| {
 | |
|     if (sourcelist.GotoElement(ssrc) < 0)
 | |
|         return 0;
 | |
|     if (!sourcelist.HasCurrentElement())
 | |
|         return 0;
 | |
|     return sourcelist.GetCurrentElement();
 | |
| }
 | |
| 
 | |
| bool RTPSources::GotEntry(uint32_t ssrc)
 | |
| {
 | |
|     return sourcelist.HasElement(ssrc);
 | |
| }
 | |
| 
 | |
| RTPPacket *RTPSources::GetNextPacket()
 | |
| {
 | |
|     if (!sourcelist.HasCurrentElement())
 | |
|         return 0;
 | |
| 
 | |
|     RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
 | |
|     RTPPacket *pack = srcdat->GetNextPacket();
 | |
|     return pack;
 | |
| }
 | |
| 
 | |
| int RTPSources::ProcessRTCPSenderInfo(uint32_t ssrc, const RTPNTPTime &ntptime, uint32_t rtptime, uint32_t packetcount, uint32_t octetcount, const RTPTime &receivetime,
 | |
|         const RTPAddress *senderaddress)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     bool created;
 | |
|     int status;
 | |
| 
 | |
|     status = GetRTCPSourceData(ssrc, senderaddress, &srcdat, &created);
 | |
|     if (status < 0)
 | |
|         return status;
 | |
|     if (srcdat == 0)
 | |
|         return 0;
 | |
| 
 | |
|     srcdat->ProcessSenderInfo(ntptime, rtptime, packetcount, octetcount, receivetime);
 | |
| 
 | |
|     // Call the callback
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
| 
 | |
|     OnRTCPSenderReport(srcdat);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::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)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     bool created;
 | |
|     int status;
 | |
| 
 | |
|     status = GetRTCPSourceData(ssrc, senderaddress, &srcdat, &created);
 | |
|     if (status < 0)
 | |
|         return status;
 | |
|     if (srcdat == 0)
 | |
|         return 0;
 | |
| 
 | |
|     srcdat->ProcessReportBlock(fractionlost, lostpackets, exthighseqnr, jitter, lsr, dlsr, receivetime);
 | |
| 
 | |
|     // Call the callback
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
| 
 | |
|     OnRTCPReceiverReport(srcdat);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::ProcessSDESNormalItem(uint32_t ssrc, RTCPSDESPacket::ItemType t, std::size_t itemlength, const void *itemdata, const RTPTime &receivetime,
 | |
|         const RTPAddress *senderaddress)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     bool created, cnamecollis;
 | |
|     int status;
 | |
|     uint8_t sdesid;
 | |
|     bool prevactive;
 | |
| 
 | |
|     switch (t)
 | |
|     {
 | |
|     case RTCPSDESPacket::CNAME:
 | |
|         sdesid = RTCP_SDES_ID_CNAME;
 | |
|         break;
 | |
|     case RTCPSDESPacket::NAME:
 | |
|         sdesid = RTCP_SDES_ID_NAME;
 | |
|         break;
 | |
|     case RTCPSDESPacket::EMAIL:
 | |
|         sdesid = RTCP_SDES_ID_EMAIL;
 | |
|         break;
 | |
|     case RTCPSDESPacket::PHONE:
 | |
|         sdesid = RTCP_SDES_ID_PHONE;
 | |
|         break;
 | |
|     case RTCPSDESPacket::LOC:
 | |
|         sdesid = RTCP_SDES_ID_LOCATION;
 | |
|         break;
 | |
|     case RTCPSDESPacket::TOOL:
 | |
|         sdesid = RTCP_SDES_ID_TOOL;
 | |
|         break;
 | |
|     case RTCPSDESPacket::NOTE:
 | |
|         sdesid = RTCP_SDES_ID_NOTE;
 | |
|         break;
 | |
|     default:
 | |
|         return ERR_RTP_SOURCES_ILLEGALSDESTYPE;
 | |
|     }
 | |
| 
 | |
|     status = GetRTCPSourceData(ssrc, senderaddress, &srcdat, &created);
 | |
|     if (status < 0)
 | |
|         return status;
 | |
|     if (srcdat == 0)
 | |
|         return 0;
 | |
| 
 | |
|     prevactive = srcdat->IsActive();
 | |
|     status = srcdat->ProcessSDESItem(sdesid, (const uint8_t *) itemdata, itemlength, receivetime, &cnamecollis);
 | |
|     if (!prevactive && srcdat->IsActive())
 | |
|         activecount++;
 | |
| 
 | |
|     // Call the callback
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
|     if (cnamecollis)
 | |
|         OnCNAMECollision(srcdat, senderaddress, (const uint8_t *) itemdata, itemlength);
 | |
| 
 | |
|     if (status >= 0)
 | |
|         OnRTCPSDESItem(srcdat, t, itemdata, itemlength);
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| 
 | |
| #ifdef RTP_SUPPORT_SDESPRIV
 | |
| int RTPSources::ProcessSDESPrivateItem(uint32_t ssrc, std::size_t prefixlen, const void *prefixdata, std::size_t valuelen, const void *valuedata, const RTPTime &receivetime,
 | |
|         const RTPAddress *senderaddress)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     bool created;
 | |
|     int status;
 | |
| 
 | |
|     status = GetRTCPSourceData(ssrc, senderaddress, &srcdat, &created);
 | |
|     if (status < 0)
 | |
|         return status;
 | |
|     if (srcdat == 0)
 | |
|         return 0;
 | |
| 
 | |
|     status = srcdat->ProcessPrivateSDESItem((const uint8_t *) prefixdata, prefixlen, (const uint8_t *) valuedata, valuelen, receivetime);
 | |
|     // Call the callback
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
| 
 | |
|     if (status >= 0)
 | |
|         OnRTCPSDESPrivateItem(srcdat, prefixdata, prefixlen, valuedata, valuelen);
 | |
| 
 | |
|     return status;
 | |
| }
 | |
| #endif //RTP_SUPPORT_SDESPRIV
 | |
| 
 | |
| int RTPSources::ProcessBYE(uint32_t ssrc, std::size_t reasonlength, const void *reasondata, const RTPTime &receivetime, const RTPAddress *senderaddress)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     bool created;
 | |
|     int status;
 | |
|     bool prevactive;
 | |
| 
 | |
|     status = GetRTCPSourceData(ssrc, senderaddress, &srcdat, &created);
 | |
|     if (status < 0)
 | |
|         return status;
 | |
|     if (srcdat == 0)
 | |
|         return 0;
 | |
| 
 | |
|     // we'll ignore BYE packets for our own ssrc
 | |
|     if (srcdat == owndata)
 | |
|         return 0;
 | |
| 
 | |
|     prevactive = srcdat->IsActive();
 | |
|     srcdat->ProcessBYEPacket((const uint8_t *) reasondata, reasonlength, receivetime);
 | |
|     if (prevactive && !srcdat->IsActive())
 | |
|         activecount--;
 | |
| 
 | |
|     // Call the callback
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
|     OnBYEPacket(srcdat);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::ObtainSourceDataInstance(uint32_t ssrc, RTPInternalSourceData **srcdat, bool *created)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat2;
 | |
|     int status;
 | |
| 
 | |
|     if (sourcelist.GotoElement(ssrc) < 0) // No entry for this source
 | |
|     {
 | |
|         srcdat2 = new RTPInternalSourceData(ssrc);
 | |
|         if (srcdat2 == 0)
 | |
|             return ERR_RTP_OUTOFMEM;
 | |
|         if ((status = sourcelist.AddElement(ssrc, srcdat2)) < 0)
 | |
|         {
 | |
|             delete srcdat2;
 | |
|             return status;
 | |
|         }
 | |
|         *srcdat = srcdat2;
 | |
|         *created = true;
 | |
|         totalcount++;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         *srcdat = sourcelist.GetCurrentElement();
 | |
|         *created = false;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::GetRTCPSourceData(uint32_t ssrc, const RTPAddress *senderaddress, RTPInternalSourceData **srcdat2, bool *newsource)
 | |
| {
 | |
|     int status;
 | |
|     bool created;
 | |
|     RTPInternalSourceData *srcdat;
 | |
| 
 | |
|     *srcdat2 = 0;
 | |
| 
 | |
|     if ((status = ObtainSourceDataInstance(ssrc, &srcdat, &created)) < 0)
 | |
|         return status;
 | |
| 
 | |
|     if (created)
 | |
|     {
 | |
|         if ((status = srcdat->SetRTCPDataAddress(senderaddress)) < 0)
 | |
|             return status;
 | |
|     }
 | |
|     else // got a previously existing source
 | |
|     {
 | |
|         if (CheckCollision(srcdat, senderaddress, false))
 | |
|             return 0; // ignore packet on collision
 | |
|     }
 | |
| 
 | |
|     *srcdat2 = srcdat;
 | |
|     *newsource = created;
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| int RTPSources::UpdateReceiveTime(uint32_t ssrc, const RTPTime &receivetime, const RTPAddress *senderaddress)
 | |
| {
 | |
|     RTPInternalSourceData *srcdat;
 | |
|     bool created;
 | |
|     int status;
 | |
| 
 | |
|     status = GetRTCPSourceData(ssrc, senderaddress, &srcdat, &created);
 | |
|     if (status < 0)
 | |
|         return status;
 | |
|     if (srcdat == 0)
 | |
|         return 0;
 | |
| 
 | |
|     // We got valid SSRC info
 | |
|     srcdat->UpdateMessageTime(receivetime);
 | |
| 
 | |
|     // Call the callback
 | |
|     if (created)
 | |
|         OnNewSource(srcdat);
 | |
| 
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void RTPSources::Timeout(const RTPTime &curtime, const RTPTime &timeoutdelay)
 | |
| {
 | |
|     int newtotalcount = 0;
 | |
|     int newsendercount = 0;
 | |
|     int newactivecount = 0;
 | |
|     RTPTime checktime = curtime;
 | |
|     checktime -= timeoutdelay;
 | |
| 
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
 | |
|         RTPTime lastmsgtime = srcdat->INF_GetLastMessageTime();
 | |
| 
 | |
|         // we don't want to time out ourselves
 | |
|         if ((srcdat != owndata) && (lastmsgtime < checktime)) // timeout
 | |
|         {
 | |
| 
 | |
|             totalcount--;
 | |
|             if (srcdat->IsSender())
 | |
|                 sendercount--;
 | |
|             if (srcdat->IsActive())
 | |
|                 activecount--;
 | |
| 
 | |
|             sourcelist.DeleteCurrentElement();
 | |
| 
 | |
|             OnTimeout(srcdat);
 | |
|             OnRemoveSource(srcdat);
 | |
|             delete srcdat;
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             newtotalcount++;
 | |
|             if (srcdat->IsSender())
 | |
|                 newsendercount++;
 | |
|             if (srcdat->IsActive())
 | |
|                 newactivecount++;
 | |
|             sourcelist.GotoNextElement();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     totalcount = newtotalcount; // just to play it safe
 | |
|     sendercount = newsendercount;
 | |
|     activecount = newactivecount;
 | |
| }
 | |
| 
 | |
| void RTPSources::SenderTimeout(const RTPTime &curtime, const RTPTime &timeoutdelay)
 | |
| {
 | |
|     int newtotalcount = 0;
 | |
|     int newsendercount = 0;
 | |
|     int newactivecount = 0;
 | |
|     RTPTime checktime = curtime;
 | |
|     checktime -= timeoutdelay;
 | |
| 
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
 | |
| 
 | |
|         newtotalcount++;
 | |
|         if (srcdat->IsActive())
 | |
|             newactivecount++;
 | |
| 
 | |
|         if (srcdat->IsSender())
 | |
|         {
 | |
|             RTPTime lastrtppacktime = srcdat->INF_GetLastRTPPacketTime();
 | |
| 
 | |
|             if (lastrtppacktime < checktime) // timeout
 | |
|             {
 | |
|                 srcdat->ClearSenderFlag();
 | |
|                 sendercount--;
 | |
|             }
 | |
|             else
 | |
|                 newsendercount++;
 | |
|         }
 | |
|         sourcelist.GotoNextElement();
 | |
|     }
 | |
| 
 | |
|     totalcount = newtotalcount; // just to play it safe
 | |
|     sendercount = newsendercount;
 | |
|     activecount = newactivecount;
 | |
| }
 | |
| 
 | |
| void RTPSources::BYETimeout(const RTPTime &curtime, const RTPTime &timeoutdelay)
 | |
| {
 | |
|     int newtotalcount = 0;
 | |
|     int newsendercount = 0;
 | |
|     int newactivecount = 0;
 | |
|     RTPTime checktime = curtime;
 | |
|     checktime -= timeoutdelay;
 | |
| 
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
 | |
| 
 | |
|         if (srcdat->ReceivedBYE())
 | |
|         {
 | |
|             RTPTime byetime = srcdat->GetBYETime();
 | |
| 
 | |
|             if ((srcdat != owndata) && (checktime > byetime))
 | |
|             {
 | |
|                 totalcount--;
 | |
|                 if (srcdat->IsSender())
 | |
|                     sendercount--;
 | |
|                 if (srcdat->IsActive())
 | |
|                     activecount--;
 | |
|                 sourcelist.DeleteCurrentElement();
 | |
|                 OnBYETimeout(srcdat);
 | |
|                 OnRemoveSource(srcdat);
 | |
|                 delete srcdat;
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 newtotalcount++;
 | |
|                 if (srcdat->IsSender())
 | |
|                     newsendercount++;
 | |
|                 if (srcdat->IsActive())
 | |
|                     newactivecount++;
 | |
|                 sourcelist.GotoNextElement();
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             newtotalcount++;
 | |
|             if (srcdat->IsSender())
 | |
|                 newsendercount++;
 | |
|             if (srcdat->IsActive())
 | |
|                 newactivecount++;
 | |
|             sourcelist.GotoNextElement();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     totalcount = newtotalcount; // just to play it safe
 | |
|     sendercount = newsendercount;
 | |
|     activecount = newactivecount;
 | |
| }
 | |
| 
 | |
| void RTPSources::NoteTimeout(const RTPTime &curtime, const RTPTime &timeoutdelay)
 | |
| {
 | |
|     int newtotalcount = 0;
 | |
|     int newsendercount = 0;
 | |
|     int newactivecount = 0;
 | |
|     RTPTime checktime = curtime;
 | |
|     checktime -= timeoutdelay;
 | |
| 
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
 | |
|         std::size_t notelen;
 | |
| 
 | |
|         srcdat->SDES_GetNote(¬elen);
 | |
|         if (notelen != 0) // Note has been set
 | |
|         {
 | |
|             RTPTime notetime = srcdat->INF_GetLastSDESNoteTime();
 | |
| 
 | |
|             if (checktime > notetime)
 | |
|             {
 | |
|                 srcdat->ClearNote();
 | |
|                 OnNoteTimeout(srcdat);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         newtotalcount++;
 | |
|         if (srcdat->IsSender())
 | |
|             newsendercount++;
 | |
|         if (srcdat->IsActive())
 | |
|             newactivecount++;
 | |
|         sourcelist.GotoNextElement();
 | |
|     }
 | |
| 
 | |
|     totalcount = newtotalcount; // just to play it safe
 | |
|     sendercount = newsendercount;
 | |
|     activecount = newactivecount;
 | |
| 
 | |
| }
 | |
| 
 | |
| void RTPSources::MultipleTimeouts(const RTPTime &curtime, const RTPTime &sendertimeout, const RTPTime &byetimeout, const RTPTime &generaltimeout, const RTPTime ¬etimeout)
 | |
| {
 | |
|     int newtotalcount = 0;
 | |
|     int newsendercount = 0;
 | |
|     int newactivecount = 0;
 | |
|     RTPTime senderchecktime = curtime;
 | |
|     RTPTime byechecktime = curtime;
 | |
|     RTPTime generaltchecktime = curtime;
 | |
|     RTPTime notechecktime = curtime;
 | |
|     senderchecktime -= sendertimeout;
 | |
|     byechecktime -= byetimeout;
 | |
|     generaltchecktime -= generaltimeout;
 | |
|     notechecktime -= notetimeout;
 | |
| 
 | |
|     sourcelist.GotoFirstElement();
 | |
|     while (sourcelist.HasCurrentElement())
 | |
|     {
 | |
|         RTPInternalSourceData *srcdat = sourcelist.GetCurrentElement();
 | |
|         bool deleted, issender, isactive;
 | |
|         bool byetimeout, normaltimeout, notetimeout;
 | |
| 
 | |
|         std::size_t notelen;
 | |
| 
 | |
|         issender = srcdat->IsSender();
 | |
|         isactive = srcdat->IsActive();
 | |
|         deleted = false;
 | |
|         byetimeout = false;
 | |
|         normaltimeout = false;
 | |
|         notetimeout = false;
 | |
| 
 | |
|         srcdat->SDES_GetNote(¬elen);
 | |
|         if (notelen != 0) // Note has been set
 | |
|         {
 | |
|             RTPTime notetime = srcdat->INF_GetLastSDESNoteTime();
 | |
| 
 | |
|             if (notechecktime > notetime)
 | |
|             {
 | |
|                 notetimeout = true;
 | |
|                 srcdat->ClearNote();
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (srcdat->ReceivedBYE())
 | |
|         {
 | |
|             RTPTime byetime = srcdat->GetBYETime();
 | |
| 
 | |
|             if ((srcdat != owndata) && (byechecktime > byetime))
 | |
|             {
 | |
|                 sourcelist.DeleteCurrentElement();
 | |
|                 deleted = true;
 | |
|                 byetimeout = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (!deleted)
 | |
|         {
 | |
|             RTPTime lastmsgtime = srcdat->INF_GetLastMessageTime();
 | |
| 
 | |
|             if ((srcdat != owndata) && (lastmsgtime < generaltchecktime))
 | |
|             {
 | |
|                 sourcelist.DeleteCurrentElement();
 | |
|                 deleted = true;
 | |
|                 normaltimeout = true;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (!deleted)
 | |
|         {
 | |
|             newtotalcount++;
 | |
| 
 | |
|             if (issender)
 | |
|             {
 | |
|                 RTPTime lastrtppacktime = srcdat->INF_GetLastRTPPacketTime();
 | |
| 
 | |
|                 if (lastrtppacktime < senderchecktime)
 | |
|                 {
 | |
|                     srcdat->ClearSenderFlag();
 | |
|                     sendercount--;
 | |
|                 }
 | |
|                 else
 | |
|                     newsendercount++;
 | |
|             }
 | |
| 
 | |
|             if (isactive)
 | |
|                 newactivecount++;
 | |
| 
 | |
|             if (notetimeout)
 | |
|                 OnNoteTimeout(srcdat);
 | |
| 
 | |
|             sourcelist.GotoNextElement();
 | |
|         }
 | |
|         else // deleted entry
 | |
|         {
 | |
|             if (issender)
 | |
|                 sendercount--;
 | |
|             if (isactive)
 | |
|                 activecount--;
 | |
|             totalcount--;
 | |
| 
 | |
|             if (byetimeout)
 | |
|                 OnBYETimeout(srcdat);
 | |
|             if (normaltimeout)
 | |
|                 OnTimeout(srcdat);
 | |
|             OnRemoveSource(srcdat);
 | |
|             delete srcdat;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     totalcount = newtotalcount; // just to play it safe
 | |
|     sendercount = newsendercount;
 | |
|     activecount = newactivecount;
 | |
| }
 | |
| 
 | |
| bool RTPSources::CheckCollision(RTPInternalSourceData *srcdat, const RTPAddress *senderaddress, bool isrtp)
 | |
| {
 | |
|     bool isset, otherisset;
 | |
|     const RTPAddress *addr, *otheraddr;
 | |
| 
 | |
|     if (isrtp)
 | |
|     {
 | |
|         isset = srcdat->IsRTPAddressSet();
 | |
|         addr = srcdat->GetRTPDataAddress();
 | |
|         otherisset = srcdat->IsRTCPAddressSet();
 | |
|         otheraddr = srcdat->GetRTCPDataAddress();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         isset = srcdat->IsRTCPAddressSet();
 | |
|         addr = srcdat->GetRTCPDataAddress();
 | |
|         otherisset = srcdat->IsRTPAddressSet();
 | |
|         otheraddr = srcdat->GetRTPDataAddress();
 | |
|     }
 | |
| 
 | |
|     if (!isset)
 | |
|     {
 | |
|         if (otherisset) // got other address, can check if it comes from same host
 | |
|         {
 | |
|             if (otheraddr == 0) // other came from our own session
 | |
|             {
 | |
|                 if (senderaddress != 0)
 | |
|                 {
 | |
|                     OnSSRCCollision(srcdat, senderaddress, isrtp);
 | |
|                     return true;
 | |
|                 }
 | |
| 
 | |
|                 // Ok, store it
 | |
| 
 | |
|                 if (isrtp)
 | |
|                     srcdat->SetRTPDataAddress(senderaddress);
 | |
|                 else
 | |
|                     srcdat->SetRTCPDataAddress(senderaddress);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (!otheraddr->IsFromSameHost(senderaddress))
 | |
|                 {
 | |
|                     OnSSRCCollision(srcdat, senderaddress, isrtp);
 | |
|                     return true;
 | |
|                 }
 | |
| 
 | |
|                 // Ok, comes from same host, store the address
 | |
| 
 | |
|                 if (isrtp)
 | |
|                     srcdat->SetRTPDataAddress(senderaddress);
 | |
|                 else
 | |
|                     srcdat->SetRTCPDataAddress(senderaddress);
 | |
|             }
 | |
|         }
 | |
|         else // no other address, store this one
 | |
|         {
 | |
|             if (isrtp)
 | |
|                 srcdat->SetRTPDataAddress(senderaddress);
 | |
|             else
 | |
|                 srcdat->SetRTCPDataAddress(senderaddress);
 | |
|         }
 | |
|     }
 | |
|     else // already got an address
 | |
|     {
 | |
|         if (addr == 0)
 | |
|         {
 | |
|             if (senderaddress != 0)
 | |
|             {
 | |
|                 OnSSRCCollision(srcdat, senderaddress, isrtp);
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             if (!addr->IsSameAddress(senderaddress))
 | |
|             {
 | |
|                 OnSSRCCollision(srcdat, senderaddress, isrtp);
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| } // end namespace
 | |
| 
 |