457 lines
12 KiB
C++
457 lines
12 KiB
C++
|
/*----------------------------------------------------------------------------
|
|||
|
* 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]
|
|||
|
|
|||
|
|