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; }
void CRTCPSource::ProcessPacket(unsigned char *puchDataBuffer, unsigned long ulBufferLength, int verbose) { unsigned char *SAVEpuchDataBuffer = puchDataBuffer; unsigned long SAVEulBufferLength = ulBufferLength; #ifdef DEBUG_RTCP_PACKETS /* [ */ if (0 < numPacketsToDump--) { verbose = 1; } if (verbose) { unsigned char *tp = puchDataBuffer; unsigned long tl = ulBufferLength; int i = 0; osPrintf("CRTCPSource::ProcessPacket(%8p, %lu)\n", puchDataBuffer, ulBufferLength); while(tl > 0) { osPrintf(" %02X", *tp++); if (0xf == (0xf & i++)) osPrintf("\n"); tl--; } if (0 != (0xf & i)) osPrintf("\n"); } #endif /* DEBUG_RTCP_PACKETS ] */ // This could be either a simple or composite report. Let's process the // buffer until there is nothing more to process. while(ulBufferLength > 0) { unsigned long ulBytesProcessed = 0; // Let's peek into the RTCP header to determine the payload type of an // RTCP report and route it to the appropriate handler. switch(GetPayloadType(puchDataBuffer)) { // Process Sender Report case etSenderReport: ulBytesProcessed = ProcessSenderReport(puchDataBuffer); #ifdef DEBUG_RTCP_PACKETS /* [ */ if (verbose) { osPrintf(" Sender Report (%lu bytes)\n", ulBytesProcessed); } #endif /* DEBUG_RTCP_PACKETS ] */ break; // Process Receiver Report case etReceiverReport: ulBytesProcessed = ProcessReceiverReport(puchDataBuffer); #ifdef DEBUG_RTCP_PACKETS /* [ */ if (verbose) { osPrintf(" Recvr Report (%lu bytes)\n", ulBytesProcessed); } #endif /* DEBUG_RTCP_PACKETS ] */ break; // Process Source Description Report case etSDESReport: ulBytesProcessed = ProcessSDESReport(puchDataBuffer); #ifdef DEBUG_RTCP_PACKETS /* [ */ if (verbose) { osPrintf(" SDES Report (%lu bytes)\n", ulBytesProcessed); } #endif /* DEBUG_RTCP_PACKETS ] */ break; // Process Bye Report case etByeReport: ulBytesProcessed = ProcessByeReport(puchDataBuffer); #ifdef DEBUG_RTCP_PACKETS /* [ */ if (verbose) { osPrintf(" Bye Report (%lu bytes)\n", ulBytesProcessed); } #endif /* DEBUG_RTCP_PACKETS ] */ break; // Process Application Report case etAppReport: ulBytesProcessed = ProcessAppReport(puchDataBuffer); #ifdef DEBUG_RTCP_PACKETS /* [ */ if (verbose) { osPrintf(" App Report (%lu bytes)\n", ulBytesProcessed); } #endif /* DEBUG_RTCP_PACKETS ] */ break; // Unrecognized Report default: { int count, i; osPrintf("** TROUBLE ** CRTCPSource::ProcessPacket()" " - Unrecognized RTCP Report Type of %d\n", GetPayloadType(puchDataBuffer)); osPrintf(" - Remaining buffer length of %lu", ulBufferLength); count = ulBufferLength > 0 ? ulBufferLength : 0; count = count < 100 ? count : 100; if (count > 0) osPrintf(" containing\n==>"); for (i=0; i<count; i++) { if (15 == (15 & i)) osPrintf(" %02X\n ", *puchDataBuffer); else osPrintf(" %02X", *puchDataBuffer); puchDataBuffer++; } osPrintf("\n"); } if (!verbose) { ProcessPacket(SAVEpuchDataBuffer, SAVEulBufferLength, 1); } return; } #ifdef DEBUG_RTCP_PACKETS /* [ */ if (verbose) { unsigned char *tp = puchDataBuffer; unsigned long tl = ulBytesProcessed; int i = 0; while(tl > 0) { osPrintf(" %02X", *tp++); if (0xf == (0xf & i++)) osPrintf("\n"); tl--; } if (0 != (0xf & i)) osPrintf("\n"); } #endif /* DEBUG_RTCP_PACKETS ] */ // Adjust length remaining and the buffer pointer so that we are // prepared to recognize and process other reports. puchDataBuffer += ulBytesProcessed; ulBufferLength -= ulBytesProcessed; } }