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; }