/*---------------------------------------------------------------------------- * File: RTCPREPT.C * Product: RTP/RTCP implementation * Description: Provides report functions for the RRCM implementation. * * INTEL Corporation Proprietary Information * This listing is supplied under the terms of a license agreement with * Intel Corporation and may not be copied nor disclosed except in * accordance with the terms of that agreement. * Copyright (c) 1995 Intel Corporation. *--------------------------------------------------------------------------*/ #include "rrcm.h" /*--------------------------------------------------------------------------- / Global Variables /--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- / External Variables /--------------------------------------------------------------------------*/ extern PRTCP_CONTEXT pRTCPContext; extern RRCM_WS RRCMws; /*---------------------------------------------------------------------------- * Function : RTCPReportRequest * Description: The application request a report for a particular RTCP * session, identified by the socket descriptor. * * Input : RTCPsd: RTCP socket descriptor * offset: Offset to start from in the list * *status: -> to the report status information * *moreEntries: -> to a flag * numEntriesInBfr: Number of entries in buffer * pReportBfr: -> to report buffer * iFilterFlags Bit flags specifying filter to apply * pFilterPattern -> to value of filter pattern to use * dwFltrPtrnLen Filter pattern length * * Return: OK: RRCM_NoError * !0: Error code (see RRCM.H) ---------------------------------------------------------------------------*/ HRESULT WINAPI RTCPReportRequest (SOCKET RTCPsd, DWORD offset, DWORD *status, DWORD *moreEntries, DWORD numEntriesInBfr, PRTCP_REPORT pReportBfr, DWORD dwFilterFlags, LPVOID pFilterPattern, DWORD dwFltrPtrnLen) { PLINK_LIST pTmp; PSSRC_ENTRY pRRCM; DWORD dwStatus = RRCM_NoError; DWORD numEntryWritten = 0; DWORD index; DWORD dwLost; DWORD dwTmp; BOOL matched; IN_OUT_STR ("RTCP: Enter RTCPReportRequest()\n"); ASSERT (pReportBfr); ASSERT (numEntriesInBfr); // look for the RTCP session pTmp = pRTCPContext->RTCPSession.prev; if (pTmp == NULL) { RRCM_DBG_MSG ("RTCP: ERROR - Invalid RTCP session", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTCPInvalidSession)); } pRRCM = (PSSRC_ENTRY)((PRTCP_SESSION)pTmp)->XmtSSRCList.prev; if (pRRCM == NULL) { RRCM_DBG_MSG ("RCTP : ERROR - No RTCP Xmt list", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTCPNoXmtList)); } while (pTmp) { if (pRRCM->RTCPsd == RTCPsd) break; else { pTmp = pTmp->next; if (pTmp) { pRRCM = (PSSRC_ENTRY)((PRTCP_SESSION)pTmp)->XmtSSRCList.prev; } continue; } } if (pTmp == NULL) { RRCM_DBG_MSG ("RTCP: ERROR - Invalid RTCP session", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTCPInvalidSession)); } if (dwFilterFlags && (pFilterPattern == NULL)) { RRCM_DBG_MSG ("RTCP: ERROR - Invalid RTCP FilterPattern is NULL", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTCPInvalidRequest)); } // go through the list of transmitters for this RTCP session pRRCM = (PSSRC_ENTRY)((PRTCP_SESSION)pTmp)->XmtSSRCList.prev; index = 0; while (pRRCM && numEntriesInBfr) { // go to the desired offset if (offset) { offset--; pRRCM = (PSSRC_ENTRY)pRRCM->SSRCList.next; continue; } if (dwFilterFlags) { matched = FALSE; switch (dwFilterFlags) { case FLTR_SSRC: if(pRRCM->SSRC == *((DWORD *)pFilterPattern)) matched=TRUE; break; case FLTR_CNAME: if((memcmp ((char *)pFilterPattern, pRRCM->cnameInfo.sdesBfr, dwFltrPtrnLen)) == 0) matched = TRUE; break; default: RRCM_DBG_MSG ("RTCP: ERROR - Invalid FilterFlag", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTCPNotImpl)); } if (!matched) { pRRCM = (PSSRC_ENTRY)pRRCM->SSRCList.next; continue; } else numEntriesInBfr--; } else numEntriesInBfr--; // fill in the our active Sender report information pReportBfr[index].status = LOCAL_SSRC_RPT; pReportBfr[index].ssrc = pRRCM->SSRC; // lock-out bytes update EnterCriticalSection (&pRRCM->critSect); pReportBfr[index].dwSrcNumPcktRealTime = pRRCM->xmtInfo.dwNumPcktSent; pReportBfr[index].dwSrcNumByteRealTime = pRRCM->xmtInfo.dwNumBytesSent; // release lock LeaveCriticalSection (&pRRCM->critSect); // a source - It's supposed to know it's own payload type pReportBfr[index].PayLoadType = UNKNOWN_PAYLOAD_TYPE; // our own sampling frequency pReportBfr[index].dwStreamClock = pRRCM->dwStreamClock; if (pRRCM->cnameInfo.dwSdesLength) { memcpy (pReportBfr[index].cname, pRRCM->cnameInfo.sdesBfr, pRRCM->cnameInfo.dwSdesLength); pReportBfr[index].dwCnameLen = pRRCM->cnameInfo.dwSdesLength; } if (pRRCM->nameInfo.dwSdesLength) { memcpy (pReportBfr[index].name, pRRCM->nameInfo.sdesBfr, pRRCM->nameInfo.dwSdesLength); pReportBfr[index].dwNameLen = pRRCM->nameInfo.dwSdesLength; } if (pRRCM->fromLen) { memcpy (&pReportBfr[index].fromAddr, &pRRCM->from, pRRCM->fromLen); pReportBfr[index].dwFromLen = pRRCM->fromLen; } numEntryWritten++; index++; // go to next entry pRRCM = (PSSRC_ENTRY)pRRCM->SSRCList.next; } // go through the list of receivers for this RTCP session pRRCM = (PSSRC_ENTRY)((PRTCP_SESSION)pTmp)->RcvSSRCList.prev; while (pRRCM && numEntriesInBfr) { // go to the desired offset if (offset) { offset--; pRRCM = (PSSRC_ENTRY)pRRCM->SSRCList.next; continue; } if (dwFilterFlags) { matched = FALSE; switch (dwFilterFlags) { case FLTR_SSRC: if(pRRCM->SSRC == *((DWORD *)pFilterPattern)) matched=TRUE; break; case FLTR_CNAME: if((memcmp ((char *)pFilterPattern, pRRCM->cnameInfo.sdesBfr, dwFltrPtrnLen)) == 0) matched = TRUE; break; default: RRCM_DBG_MSG ("RTCP: ERROR - Invalid FilterFlag", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (MAKE_RRCM_ERROR(RRCMError_RTCPNotImpl)); } if (!matched) { pRRCM = (PSSRC_ENTRY)pRRCM->SSRCList.next; continue; } else numEntriesInBfr--; } else numEntriesInBfr--; // fill in the Receiver report information pReportBfr[index].ssrc = pRRCM->SSRC; pReportBfr[index].status = REMOTE_SSRC_RPT; // lock-out counters update EnterCriticalSection (&pRRCM->critSect); #ifdef ENABLE_FLOATING_POINT pReportBfr[index].SrcJitter = pRRCM->rcvInfo.interJitter; #else // Check RFC for details of the round off pReportBfr[index].SrcJitter = pRRCM->rcvInfo.interJitter >> 4; #endif pReportBfr[index].dwSrcXtndNum = pRRCM->rcvInfo.XtendedSeqNum.seq_union.dwXtndedHighSeqNumRcvd; // real time receive information pReportBfr[index].dwSrcNumPcktRealTime = pRRCM->rcvInfo.dwNumPcktRcvd; pReportBfr[index].dwSrcNumByteRealTime = pRRCM->rcvInfo.dwNumBytesRcvd; // get sender information from Sender's RTCP report pReportBfr[index].dwSrcNumPckt = pRRCM->xmtInfo.dwNumPcktSent; pReportBfr[index].dwSrcNumByte = pRRCM->xmtInfo.dwNumBytesSent; pReportBfr[index].dwSrcLsr = pRRCM->xmtInfo.dwLastSR; pReportBfr[index].dwSrcNtpMsw = pRRCM->xmtInfo.dwNTPmsw; pReportBfr[index].dwSrcNtpLsw = pRRCM->xmtInfo.dwNTPlsw; pReportBfr[index].dwSrcRtpTs = pRRCM->xmtInfo.dwRTPts; dwLost = getSSRCpcktLoss (pRRCM, FALSE); // release lock LeaveCriticalSection (&pRRCM->critSect); // the last payload seen on this RTP stream pReportBfr[index].PayLoadType = pRRCM->PayLoadType; // last report received time pReportBfr[index].dwLastReportRcvdTime = pRRCM->dwLastReportRcvdTime; // fraction lost is in network byte order pReportBfr[index].SrcFraction = (dwLost & 0xFF); // cumulative lost is a 24 bits value in network byte order RRCMws.ntohl (pRRCM->RTPsd, dwLost, &dwTmp); dwTmp &= 0x00FFFFFF; pReportBfr[index].SrcNumLost = dwTmp; // get feedback information if (pRRCM->rrFeedback.SSRC) { pReportBfr[index].status |= FEEDBACK_FOR_LOCAL_SSRC_PRESENT; memcpy (&pReportBfr[index].feedback, &pRRCM->rrFeedback, sizeof(RTCP_FEEDBACK)); } if (pRRCM->cnameInfo.dwSdesLength) { memcpy (pReportBfr[index].cname, pRRCM->cnameInfo.sdesBfr, pRRCM->cnameInfo.dwSdesLength); pReportBfr[index].dwCnameLen = pRRCM->cnameInfo.dwSdesLength; } if (pRRCM->nameInfo.dwSdesLength) { memcpy (pReportBfr[index].name, pRRCM->nameInfo.sdesBfr, pRRCM->nameInfo.dwSdesLength); pReportBfr[index].dwNameLen = pRRCM->nameInfo.dwSdesLength; } if (pRRCM->fromLen) { memcpy (&pReportBfr[index].fromAddr, &pRRCM->from, pRRCM->fromLen); pReportBfr[index].dwFromLen = pRRCM->fromLen; } numEntryWritten++; index++; // go to next entry pRRCM = (PSSRC_ENTRY)pRRCM->SSRCList.next; } // check to see if there are additional entries if (pRRCM != NULL) *moreEntries = TRUE; *status = numEntryWritten; IN_OUT_STR ("RTCP: Exit RTCPReportRequest()\n"); return (dwStatus); } /*---------------------------------------------------------------------------- * Function : getRtcpSessionList * Description: Get a list of current RTCP session. * * Input : pSockBfr: -> to a socket buffer * pNumEntries: -> to number of allocated entries in buffers. * pNumUpdated: -> number of entries updated * * Return: OK: RRCM_NoError * !0: Error code (see RRCM.H) ---------------------------------------------------------------------------*/ HRESULT WINAPI getRtcpSessionList (PDWORD_PTR pSockBfr, DWORD dwNumEntries, PDWORD pNumUpdated) { DWORD dwStatus = RRCM_NoError; PRTCP_SESSION pRTCP; PSSRC_ENTRY pSSRC; IN_OUT_STR ("RTCP: Enter getRtpSessionList()\n"); // lock out session's access EnterCriticalSection (&pRTCPContext->critSect); *pNumUpdated = 0; // look for the RTCP session pRTCP = (PRTCP_SESSION)pRTCPContext->RTCPSession.prev; if (pRTCP == NULL) { // Unlock out session's access LeaveCriticalSection (&pRTCPContext->critSect); IN_OUT_STR ("RTCP: Exit getRtpSessionList()\n"); return (MAKE_RRCM_ERROR (RRCMError_RTPNoSession)); } // loop through the session's list while (pRTCP) { pSSRC = (PSSRC_ENTRY)pRTCP->XmtSSRCList.prev; if (pSSRC == NULL) { // Unlock out session's access LeaveCriticalSection (&pRTCPContext->critSect); RRCM_DBG_MSG ("RCTP : ERROR - No RTCP Xmt list", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTCP: Exit getRtpSessionList()\n"); return (MAKE_RRCM_ERROR (RRCMError_RTCPNoXmtList)); } if (dwNumEntries) { pSockBfr[*pNumUpdated] = pSSRC->RTCPsd; *pNumUpdated += 1; dwNumEntries --; } if (dwNumEntries == 0) { break; } // next entry pRTCP = (PRTCP_SESSION)(pRTCP->RTCPList.next); } // Unlock out session's access LeaveCriticalSection (&pRTCPContext->critSect); IN_OUT_STR ("RTCP: Exit getRtpSessionList()\n"); return dwStatus; } // [EOF]