Ejemplo n.º 1
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;
}
int RTPPacketProcessor::ProcessRTCPBlock(unsigned char *data,int len,unsigned long ip,int port,bool *collis,double localtsunit)
{
	RTCPHeader *rtcphdr;
	unsigned char *data2;
	int type,restlen,calclen;
	int status,count;
	bool firstblock;

	*collis = false;
	if (!initialized)
	{
		delete [] data;
		return ERR_RTP_PACKETPROCESSORNOTINITIALIZED;
	}

	if (ip == conn->GetLocalIP() && port == conn->GetSendPort())
	{
		CheckRTCPHandler(data,len,ip,port); // let user process packet
		
		/* processing own control information is not useful, so we won't
		   do it ... */
		delete [] data;
		return 0;
	}

	curip = ip;
	curport = port;

	data2 = data;
	restlen = len;
	firstblock = true;
	while (restlen >= (int)sizeof(RTCPHeader))
	{
		rtcphdr = (RTCPHeader *)data2;
		data2 += sizeof(RTCPHeader);
		restlen -= sizeof(RTCPHeader);

		if (rtcphdr->version == RTP_VERSION)
		{
			type = rtcphdr->packettype;
			calclen = ntohs(rtcphdr->length);
			calclen *= sizeof(RTPuint32);
			count = rtcphdr->blockcount;
			if (calclen <= restlen) // otherwise not all the info is included
			{
				/* Check if the compound packet starts with a SR or RR */

				if (firstblock)
				{
					firstblock = false;
					if (type != TYPE_RTCP_SR && type != TYPE_RTCP_RR) // not a rtcp compound packet
					{
						CheckRTCPHandler(data,len,ip,port); // let user process packet
						delete [] data;
						return 0;
					}
				}

				/* Just handle the types */

				status = 0;
				switch(type)
				{
				case TYPE_RTCP_SR:
					status = ProcessSenderReport(data2,calclen,count,collis,localtsunit);
					break;
				case TYPE_RTCP_RR:
					status = ProcessReceiverReport(data2,calclen,count,collis,localtsunit);
					break;
				case TYPE_RTCP_SDES:
					if (count > 0)
						status = ProcessSDES(data2,calclen,count,collis,localtsunit);
					break;
				case TYPE_RTCP_BYE:
					if (count > 0)
						status = ProcessBYE(data2,calclen,count);
					break;
				case TYPE_RTCP_APP:
					if (handlers->handlers[RTP_EXCEPTION_RECEIVERTCPAPPDATA].handler != NULL)
						CallAppDataHandler(data2,calclen,count);
					break;
				}
				if (status < 0)
				{
					CheckRTCPHandler(data,len,ip,port); // let user process packet
					delete [] data;
					return status;
				}
			}
		}
		else // Not a rtcp compound packet
		{
			CheckRTCPHandler(data,len,ip,port); // let user process packet
			delete [] data;
			return 0;
		}

		restlen -= calclen;
		data2 += calclen;
	}
	
	if (*collis) // call handler
	{
		if (handlers->handlers[RTP_EXCEPTION_LOCALSSRCCOLLISION].handler != NULL)
			CallLocalSSRCCollHandler(ntohl(contribsrcs->GetLocalSSRC()),ip,false,port);
	}
	CheckRTCPHandler(data,len,ip,port); // let user process packet
	delete [] data;
	return 0;
}