/** * * Method Name: ParseByeReport * * * Inputs: unsigned char *puchReportBuffer - Buffer containing the Bye Report * * Outputs: None * * Returns: unsigned long * * Description: Extracts the contents of an Bye report using the buffer * passed in by the caller. * * Usage Notes: The header of the RTCP Report shall be parsed by delegating * to the base class. * * */ unsigned long CByeReport::ParseByeReport(unsigned char *puchReportBuffer) { unsigned char *puchPayloadBuffer = puchReportBuffer; // Check whether the RTCP Header has been correctly // formed (Version, etc...). if(!ParseRTCPHeader(puchReportBuffer)) return(GetReportLength()); // Good header. Let's bump the payload pointer and continue. puchPayloadBuffer += GetHeaderLength(); // Let's store the CSRCs from the Bye Report unsigned long ulCSRCCount = GetReportCount() ? GetReportCount() - 1 : 0; SetCSRC((ssrc_t *)puchPayloadBuffer, ulCSRCCount, TRUE); puchPayloadBuffer += (sizeof(ssrc_t) * ulCSRCCount); // Let's determine whether there is an optional Reason field associated // with this Bye Report. We can surmise this through comparing the // packet length to what we've already processed if(puchPayloadBuffer - puchReportBuffer < (long)GetReportLength()) { uint32_t ulReasonLength = (uint32_t)*puchPayloadBuffer++; SetReason(puchPayloadBuffer, ulReasonLength); puchPayloadBuffer += ulReasonLength; } // Let's process any padding that might be present to align the // payload on a 32 bit boundary. if(GetPadding()) puchPayloadBuffer += ExtractPadding(puchPayloadBuffer); return(puchPayloadBuffer - puchReportBuffer); }
/** * * Method Name: ParseSenderReport * * * Inputs: unsigned char *puchReportBuffer * - Buffer containing the Sender Report * * Outputs: None * * Returns: unsigned long * * Description: Extracts the contents of an Sender report using the buffer * passed in by the caller. The Sender Report object shall store * the content and length of data fields extracted from the Sender * Report. The timestamps identifying the time of SR report * reception shall obtained and sent with the SR Send timestamp to * the associated Receiver Report through the SetLastRcvdSRTime() * method of the ISetReceiverStatistics interface. * * Usage Notes: The header of the RTCP Report shall be parsed by delegating to * the base class. * * */ unsigned long CSenderReport::ParseSenderReport(unsigned char *puchReportBuffer) { unsigned char *puchPayloadBuffer = puchReportBuffer; // Check whether the RTCP Header has been correctly // formed (Version, etc...). if(!ParseRTCPHeader(puchReportBuffer)) return(GetReportLength()); // Good header. Let's bump the payload pointer and continue. puchPayloadBuffer += GetHeaderLength(); // Let's extract the NTP and RTP timestamps from the Sender Report puchPayloadBuffer += ExtractTimestamps((unsigned long *)puchPayloadBuffer); // Let's extract the Sender Statistics puchPayloadBuffer += ExtractSenderStats((unsigned long*)puchPayloadBuffer); return(puchPayloadBuffer - puchReportBuffer); }
/** * * Method Name: ProcessByeReport * * * Inputs: unsigned char *puchRTCPReport - A pointer to an RTCP Bye Report * * Outputs: None * * Returns: unsigned long * * Description: Takes the RTCP Bye Report and extracts the associated SSRC ID. * A notification shall be generated to all subscribing parties to * inform them of the receipt of the BYE along with the associated * SSRC ID. * * * Usage Notes: * * */ unsigned long CRTCPSource::ProcessByeReport(unsigned char *puchRTCPReport) { unsigned long ulSenderSSRC = GetSenderSSRC(TRUE, puchRTCPReport); unsigned long ulBytesProcessed = GetReportLength(puchRTCPReport); // Has a Bye Report object been instantiated for this participant? // Probably not, if this is the first Sender Report received in a session if(m_poByeReport != NULL); // Create The Bye Report Class else if((m_poByeReport = new CByeReport(ulSenderSSRC)) == NULL) { osPrintf("**** FAILURE **** CRTCPSource::ProcessByeReport()" " - Unable to Create Inbound Bye Report Object\n"); return(ulBytesProcessed); } // Initialize Bye Report Class else if(!m_poByeReport->Initialize()) { // Release the Bye Report reference. This should cause the object // to be destroyed osPrintf("**** FAILURE **** CRTCPSource::ProcessByeReport()" " - Unable to Initialize Inbound Bye Report Object\n"); ((IByeReport *)m_poByeReport)->Release(); return(ulBytesProcessed); } // A Bye object exists to processes this report. Let's delegate to its // parsing methods to complete this report's processing. m_poByeReport->ParseByeReport(puchRTCPReport); // Set the event mask to refelect receiving this report SendRTCPEvent(RTCP_BYE_RCVD, (void *)m_poByeReport); return(ulBytesProcessed); }
/** * * Method Name: ProcessAppReport * * * Inputs: unsigned char *puchRTCPReport * - A pointer to an RTCP Application Report * * Outputs: None * * Returns: unsigned long * * Description: No processing is performed on an Application Report but the * length is extracted from the header and returned so that other * composite reports might still be processed. * * * Usage Notes: * * */ unsigned long CRTCPSource::ProcessAppReport(unsigned char *puchRTCPReport) { // Disregard this packet return(GetReportLength(puchRTCPReport)); }
/** * * Method Name: ProcessSDESReport * * * Inputs: unsigned char *puchRTCPReport * - pointer to an RTCP Source Description Report * * Outputs: None * * Returns: unsigned long * * Description: Takes the RTCP SDES Report passed and calls the * CSourceDescription object's ISDESReport interface to parse the * Source Description packet and extract the identification * information contained therein. * * * Usage Notes: A call connection to a Mixer would cause all SDES Reports to * be forward as multiple SDES Reports. In this case, a new * CSourceDescription object shall be created and queued if not * already existing on the SrcDescription list. The SSRC ID will * be used to determine uniqueness among reports. * * Notifications shall be generated to all subscribing parties to * inform them of the new Source Descriptions or changes in * previously existing Source Descriptions. The notification * shall contain the event type and a pointer to the new or * modified Source Description interface (IGetSrcDescription). */ unsigned long CRTCPSource::ProcessSDESReport(unsigned char *puchRTCPReport) { bool bRTCPHeader = TRUE; unsigned long ulEventMask = 0; unsigned long ulSDESLength = 0; unsigned long ulReportCount = 0; unsigned long ulSenderSSRC = 0; unsigned long ulReportSize = GetReportLength(puchRTCPReport); CSourceDescription *poSDESReport = NULL; // Pull the Report Count from the header so we no how many reports we need // to process ulReportCount = GetReportCount(puchRTCPReport); // Let's prepare to iterate through each reception report until complete while(ulReportCount > 0) { // Extract the corresponding SSRC with the knowledge that this report // comes with a full formed RTCP header. ulSenderSSRC = GetSenderSSRC(bRTCPHeader, puchRTCPReport); // Has a SDES Report object been instantiated for this participant? // Probably not, if this is the first SDES Report received in a session if((poSDESReport = m_tSrcDescriptorList.GetEntry(SDESSsrcComparitor, (void *)ulSenderSSRC)) != NULL); // Create The SDES Report object else if((poSDESReport = new CSourceDescription(ulSenderSSRC)) == NULL) { osPrintf("**** FAILURE **** CRTCPSource::ProcessSDESReport()" " - Unable to Create Inbound SDES Report Object\n"); return(ulReportSize); } // Initialize SDES Report object else if(!poSDESReport->Initialize()) { // Release the SDES Report reference. This should cause the // object to be destroyed osPrintf("**** FAILURE **** CRTCPSource::ProcessSDESReport()" " - Unable to Initialize Inbound SDES Report Object\n"); ((ISDESReport *)poSDESReport)->Release(); return(ulReportSize); } // Place the new SDES Report object on the collection list else if(!m_tSrcDescriptorList.AddEntry(poSDESReport)) { // Release the SDES Report reference. // This should cause the object to be destroyed osPrintf("**** FAILURE **** CRTCPSource::ProcessSDESReport()" " - Unable to Add SDES Report Object to Collection\n"); ((ISDESReport *)poSDESReport)->Release(); return(ulReportSize); } else { // Set the event mask to indicate that a new SDES was received ulEventMask |= RTCP_NEW_SDES; } // A SDES object exists to processes this report. Let's delegate to // its parsing methods to complete this report's processing. if((ulSDESLength = poSDESReport->ParseSDESReport(bRTCPHeader, puchRTCPReport)) == 0) { osPrintf("**** FAILURE **** CRTCPSource::ProcessSDESReport()" " - Unable to Parse Inbound SDES Report\n"); return(ulReportSize); } // We've made it through our first SDES report successfully and we must // adjust the flags, counts, and report pointers for the next go-round. bRTCPHeader = FALSE; puchRTCPReport += ulSDESLength; ulReportCount--; // Check whether any information has changed in an existing SDES Report ulEventMask |= RTCP_SDES_UPDATE; SendRTCPEvent(ulEventMask, (void *)poSDESReport, poSDESReport->GetChanges()); ulEventMask = 0; } return(ulReportSize); }
/** * * Method Name: ProcessReceiverReport * * * Inputs: unsigned char *puchRTCPReport - pointer to an RTCP Receiver Report * unsigned long ulReportCount - Optional Count of receiver reports * * Outputs: None * * Returns: unsigned long * * Description: Takes the RTCP Receiver Report passed and calls the * CReceiverReport object's IReceiverReport interface to parse the * Receiver packet and extract the receiver statistics contained * therein. Although no more than one receiver report is expected * under the current Pingtel call model, it is possible that * multiple receiver reports (one per PingTel source) may be sent. * In this case, a new CReceiverReport object shall be created and * queued if not already existing on the Receiver Report list. * * * Usage Notes: Notifications shall be generated to all subscribing parties to * inform them of the receipt of a new Receiver Report. The * notification shall contain the event type and a pointer to the * Receiver Report's IGetReceiverStatistics interface. * * */ unsigned long CRTCPSource::ProcessReceiverReport(unsigned char *puchRTCPReport, unsigned long ulReportCount) { bool bRTCPHeader = FALSE; unsigned long ulReceiverSSRC = 0; CReceiverReport *poReceiverReport = NULL; unsigned long ulBytesProcessed = 0; unsigned long ulReportSize = 0; // Determine the Receiver Report count if it hasn't already been provided // to us. if(ulReportCount == 0) { // Set a flag to identify the existence of an RTCP Header bRTCPHeader = TRUE; // Pull the Report Count from the header so we know how many reports // we need to process ulReportCount = GetReportCount(puchRTCPReport); if (0 == ulReportCount) { // $$$ bRTCPHeader is the culprit that makes this necessary... // It is passed to a couple of routines that should not care // whether the header is still present. The header is // processed in the call to ParseReceiverReport when the // header flag is set. That processing should be done here, // the length set to 8, then all the remaining reports should // be processed without regard to the header. But // BETTER IS THE ENEMY OF GOOD! // hzm 16Aug01 ulReportSize = GetReportLength(puchRTCPReport); osPrintf("ProcessReceiverReport: RR/RC=0, len=%lu\n", ulReportSize); } } // Let's prepare to iterate through each reception report until complete while(ulReportCount > 0) { // Extract the corresponding SSRC with the knowledge that this report // comes with a full formed RTCP header. ulReceiverSSRC = GetReceiverSSRC(bRTCPHeader, puchRTCPReport); // Has a Receiver Report object been instantiated for this participant? // Probably not, if this is the first Receiver Report received in a // session if((poReceiverReport = m_tReceiverReportList.GetEntry(RRSsrcComparitor, (void *)ulReceiverSSRC)) != NULL); // $$$ IS THE ABOVE LINE, ENDING WITH A SEMICOLON, CORRECT??? - hzm // Create The Receiver Report object else if((poReceiverReport = new CReceiverReport(ulReceiverSSRC)) == NULL) { osPrintf("**** FAILURE **** CRTCPSource::ProcessReceiverReport()" " - Unable to create Inbound Receiver Report Object\n"); return(ulReportSize); } // Initialize Receiver Report object else if(!poReceiverReport->Initialize()) { // Release the Receiver Report reference. // This should cause the object to be destroyed osPrintf("**** FAILURE **** CRTCPSource::ProcessReceiverReport()" " - Unable to Initialize Inbound Receiver Report Object\n"); ((IReceiverReport *)poReceiverReport)->Release(); return(ulReportSize); } // Place the new Receiver Report object on the collection list else if(!m_tReceiverReportList.AddEntry(poReceiverReport)) { // Release the Receiver Report reference. // This should cause the object to be destroyed osPrintf("**** FAILURE **** CRTCPSource::ProcessReceiverReport()" " - Unable to Add Inbound Receiver Report Object to Collection\n"); ((IReceiverReport *)poReceiverReport)->Release(); return(ulReportSize); } // A Receiver object exists to process this report. // Let's delegate to its parsing methods to complete this report's // processing. if((ulBytesProcessed = poReceiverReport->ParseReceiverReport(bRTCPHeader, puchRTCPReport)) == 0) { osPrintf("**** FAILURE **** CRTCPSource::ProcessReceiverReport()" " - Unable to Parse Inbound Receiver Report\n"); return(ulReportSize); } // We've made it through our first receiver report successfully and we // must adjust the flags, counts, and report pointers for the next // go-round. bRTCPHeader = FALSE; ulReportSize += ulBytesProcessed; puchRTCPReport += ulBytesProcessed; ulReportCount--; // Send Event SendRTCPEvent(RTCP_RR_RCVD, (void *)poReceiverReport); } return(ulReportSize); }
/** * * Method Name: ProcessSenderReport * * * Inputs: unsigned char *puchRTCPReport - A pointer to an RTCP Sender Report * * Outputs: None * * Returns: unsigned long * * Description: Takes the RTCP Sender Report passed and calls the CSenderReport * object's ISenderReport interface to parse the Sender packet and * extract the sender statistics contained therein. This method * shall also check for the presence of receiver reports within * the packet and call the CReceiverReport object's * IReceiverReport interface to parse and extract its contents. * Although no more than one receiver report is expected under the * current Pingtel call model, it is possible that multiple * receiver reports (one per PingTel source) may be sent. In this * case, a new CReceiverReport object shall be created and queued * if not already existing on the Receiver Report list. * * * Usage Notes: Notifications shall be generated to all subscribing parties to * inform them of the receipt of a new Source Report. The * notification shall contain the event type and a pointer to the * Source Report's IGetSenderStatistics interface. * * */ unsigned long CRTCPSource::ProcessSenderReport(unsigned char *puchRTCPReport) { unsigned long ulSenderSSRC = GetSenderSSRC(TRUE, puchRTCPReport); unsigned long ulReportCount = 0; unsigned long ulBytesProcessed; // Has a Sender Report object been instantiated for this participant? // Probably not, if this is the first Sender Report received in a session if(m_poSenderReport != NULL); // Create The Sender Report Class else if((m_poSenderReport = new CSenderReport(ulSenderSSRC, m_piSetReceiverStatistics)) == NULL) { osPrintf("**** FAILURE **** CRTCPSource::ProcessSenderReport() -" " Unable to create Inbound Sender Report Object\n"); return(GetReportLength(puchRTCPReport)); } // Initialize Sender Report Class else if(!m_poSenderReport->Initialize()) { // Release the Sender Report reference. This should cause the object // to be destroyed osPrintf("**** FAILURE **** CRTCPSource::ProcessSenderReport() -" " Unable to Initialize Inbound Sender Report Object\n"); ((ISenderReport *)m_poSenderReport)->Release(); return(GetReportLength(puchRTCPReport)); } // A Sender object exists to processes this report. Let's delegate to its // parsing methods to complete this report's processing. if((ulBytesProcessed = m_poSenderReport->ParseSenderReport(puchRTCPReport)) == 0) { osPrintf("**** FAILURE **** CRTCPSource::ProcessSenderReport() -" " Unable to Parse Inbound Sender Report\n"); return(GetReportLength(puchRTCPReport)); } // Let's check whether there are Receiver reports associated with this // Sender Report. If so, delegate to the Receiver Report's processing // method. else if((ulReportCount = m_poSenderReport->GetReportCount()) > 0) { unsigned long ulRRBytesProcessed = 0; // Send Event SendRTCPEvent(RTCP_SR_RCVD, (void *)m_poSenderReport); // Adjust the buffer so that it points to the beginning of the // reception report section. puchRTCPReport += ulBytesProcessed; // Call Receiver Report processing method. if((ulRRBytesProcessed = ProcessReceiverReport(puchRTCPReport, ulReportCount)) == 0) return(GetReportLength(puchRTCPReport)); // Bump Total Byte Processed ulBytesProcessed += ulRRBytesProcessed; } return(ulBytesProcessed); }