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]
|
||
|
||
|