mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-11-03 21:20:31 -05: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
 | 
						|
 |