855 lines
24 KiB
C++
855 lines
24 KiB
C++
/*----------------------------------------------------------------------------
|
|
* File: RTCPSSRC.C
|
|
* Product: RTP/RTCP implementation
|
|
* Description: Provides SSRC related function.
|
|
*
|
|
* 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"
|
|
#include "md5.h"
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
/ Global Variables
|
|
/--------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
/ External Variables
|
|
/--------------------------------------------------------------------------*/
|
|
extern PRTCP_CONTEXT pRTCPContext;
|
|
|
|
#ifdef ENABLE_ISDM2
|
|
extern KEY_HANDLE hRRCMRootKey;
|
|
extern ISDM2 Isdm2;
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
extern char debug_string[];
|
|
#endif
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : getOneSSRCentry
|
|
* Description: Get an SSRC entry from the free list of entries.
|
|
*
|
|
* Input : pList : -> to the list to get the entry from
|
|
* hHeap : Handle to the heap where the data resides
|
|
* *pNum : -> to the number of initial free entry in the list
|
|
* *pCritSect : -> to the critical section
|
|
*
|
|
* Return: OK: -> to SSRC entry
|
|
* Error: NULL
|
|
---------------------------------------------------------------------------*/
|
|
PSSRC_ENTRY getOneSSRCentry (PLINK_LIST pList,
|
|
HANDLE hHeap,
|
|
DWORD *pNum,
|
|
CRITICAL_SECTION *pCritSect)
|
|
{
|
|
PSSRC_ENTRY pSSRC = NULL;
|
|
|
|
IN_OUT_STR ("RTCP: Enter getOneSSRCentry()\n");
|
|
|
|
// get an entry from the free list
|
|
pSSRC = (PSSRC_ENTRY)removePcktFromHead (pList, pCritSect);
|
|
if (pSSRC == NULL)
|
|
{
|
|
// try to reallocate some free cells
|
|
if (allocateLinkedList (pList, hHeap, pNum,
|
|
sizeof(SSRC_ENTRY),
|
|
pCritSect) == RRCM_NoError)
|
|
{
|
|
// get a free cell if some have been reallocated
|
|
pSSRC = (PSSRC_ENTRY)removePcktFromHead (pList, pCritSect);
|
|
}
|
|
}
|
|
|
|
if (pSSRC)
|
|
{
|
|
clearSSRCEntry (pSSRC);
|
|
|
|
// initialize the critical section
|
|
InitializeCriticalSection(&pSSRC->critSect);
|
|
}
|
|
|
|
IN_OUT_STR ("RTCP: Exit getOneSSRCentry()\n");
|
|
|
|
return (pSSRC);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : getSSRC
|
|
* Description: Get a unique 32 bits SSRC
|
|
*
|
|
* Input : RcvSSRCList: Session's receive SSRC list address
|
|
* XmtSSRCList: Session's transmit SSRC list address
|
|
*
|
|
* Return: Unique 32 bits SSRC
|
|
---------------------------------------------------------------------------*/
|
|
DWORD getSSRC (LINK_LIST RcvSSRCList,
|
|
LINK_LIST XmtSSRCList)
|
|
{
|
|
DWORD SSRCnum = 0;
|
|
DWORD dwStatus;
|
|
PSSRC_ENTRY pSSRC;
|
|
MD5_CTX context;
|
|
DWORD i;
|
|
union {
|
|
unsigned char c[16];
|
|
DWORD x[4];
|
|
}digest;
|
|
|
|
struct {
|
|
DWORD pid;
|
|
DWORD time;
|
|
FILETIME createTime;
|
|
FILETIME exitTime;
|
|
FILETIME kernelTime;
|
|
FILETIME userTime;
|
|
} md5Input;
|
|
|
|
IN_OUT_STR ("RTCP: Enter getSSRC()\n");
|
|
|
|
// go through all SSRCs of this RTP/RTCP session
|
|
while (SSRCnum == 0)
|
|
{
|
|
// get MD5 inputs
|
|
md5Input.pid = GetCurrentThreadId();
|
|
md5Input.time = timeGetTime();
|
|
|
|
dwStatus = GetProcessTimes (GetCurrentProcess(),
|
|
&md5Input.createTime,
|
|
&md5Input.exitTime,
|
|
&md5Input.kernelTime,
|
|
&md5Input.userTime);
|
|
if (dwStatus == FALSE)
|
|
{
|
|
RRCM_DBG_MSG ("RTCP: GetProcessTimes() failed", GetLastError(),
|
|
__FILE__, __LINE__, DBG_NOTIFY);
|
|
}
|
|
|
|
// Implementation suggested by draft 08, Appendix 6
|
|
MD5Init (&context);
|
|
MD5Update (&context, (unsigned char *)&md5Input, sizeof (md5Input));
|
|
MD5Final ((unsigned char *)&digest, &context);
|
|
SSRCnum = 0;
|
|
for (i=0; i < 3; i++)
|
|
SSRCnum ^= digest.x[i];
|
|
|
|
// look through all transmitter for this session
|
|
pSSRC = (PSSRC_ENTRY)XmtSSRCList.prev;
|
|
if (isSSRCunique (pSSRC, &SSRCnum) == TRUE)
|
|
{
|
|
// look through all received SSRC for this session
|
|
pSSRC = (PSSRC_ENTRY)RcvSSRCList.prev;
|
|
isSSRCunique (pSSRC, &SSRCnum);
|
|
}
|
|
}
|
|
|
|
IN_OUT_STR ("RTCP: Exit getSSRC()\n");
|
|
|
|
return (SSRCnum);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : getAnSSRC
|
|
* Description: Build an SSRC according to the RFC, but does not check for
|
|
* collision. Mainly used by H.323 to get a 32 bits number.
|
|
*
|
|
* Input : None
|
|
*
|
|
* Return: 32 bits SSRC
|
|
---------------------------------------------------------------------------*/
|
|
DWORD WINAPI getAnSSRC (void)
|
|
{
|
|
DWORD SSRCnum = 0;
|
|
DWORD dwStatus;
|
|
MD5_CTX context;
|
|
DWORD i;
|
|
union {
|
|
unsigned char c[16];
|
|
DWORD x[4];
|
|
}digest;
|
|
|
|
struct {
|
|
DWORD pid;
|
|
DWORD time;
|
|
FILETIME createTime;
|
|
FILETIME exitTime;
|
|
FILETIME kernelTime;
|
|
FILETIME userTime;
|
|
} md5Input;
|
|
|
|
IN_OUT_STR ("RTCP: Enter getAnSSRC()\n");
|
|
|
|
// get MD5 inputs
|
|
md5Input.pid = GetCurrentThreadId();
|
|
md5Input.time = timeGetTime();
|
|
|
|
dwStatus = GetProcessTimes (GetCurrentProcess(),
|
|
&md5Input.createTime,
|
|
&md5Input.exitTime,
|
|
&md5Input.kernelTime,
|
|
&md5Input.userTime);
|
|
if (dwStatus == FALSE)
|
|
{
|
|
RRCM_DBG_MSG ("RTCP: GetProcessTimes() failed", GetLastError(),
|
|
__FILE__, __LINE__, DBG_NOTIFY);
|
|
}
|
|
|
|
// Implementation suggested by draft 08, Appendix 6
|
|
MD5Init (&context);
|
|
MD5Update (&context, (unsigned char *)&md5Input, sizeof (md5Input));
|
|
MD5Final ((unsigned char *)&digest, &context);
|
|
SSRCnum = 0;
|
|
for (i=0; i < 3; i++)
|
|
SSRCnum ^= digest.x[i];
|
|
|
|
IN_OUT_STR ("RTCP: Exit getAnSSRC()\n");
|
|
|
|
return (SSRCnum);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : isSSRCunique
|
|
* Description: Check to see the SSRC already exist
|
|
*
|
|
* Input : pSSRC : -> to an SSRC list
|
|
* *SSRCnum : -> to the SSRC to check
|
|
*
|
|
* Return: 0: SSRC already exist
|
|
* 1: SSRC is unique
|
|
---------------------------------------------------------------------------*/
|
|
DWORD isSSRCunique (PSSRC_ENTRY pSSRC,
|
|
DWORD *SSRCnum)
|
|
{
|
|
IN_OUT_STR ("RTCP: Enter isSSRCunique()\n");
|
|
|
|
// make sure SSRC is unique for this session
|
|
while (pSSRC)
|
|
{
|
|
if (pSSRC->SSRC == *SSRCnum)
|
|
{
|
|
// SSRC already in use, get a new one
|
|
*SSRCnum = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
// get next RTCP session
|
|
pSSRC = (PSSRC_ENTRY)pSSRC->SSRCList.next;
|
|
}
|
|
|
|
IN_OUT_STR ("RTCP: Exit isSSRCunique()\n");
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : createSSRCEntry
|
|
* Description: Create an SSRC entry, for a particular RTP/RTCP session
|
|
*
|
|
* Input : SSRCnum : SSRC number
|
|
* pRTCP : -> to the RTCP session
|
|
* fromAddr : From address
|
|
* fromLen : From length
|
|
* headOfList : Put the new entry at the head of the list
|
|
*
|
|
* Return: Address of the SSRC entry data structure.
|
|
---------------------------------------------------------------------------*/
|
|
PSSRC_ENTRY createSSRCEntry (DWORD SSRCnum,
|
|
PRTCP_SESSION pRTCP,
|
|
PSOCKADDR fromAddr,
|
|
DWORD fromLen,
|
|
DWORD headOfList)
|
|
{
|
|
PSSRC_ENTRY pSSRCentry;
|
|
PSSRC_ENTRY pSSRCtmp;
|
|
PLINK_LIST pTmp;
|
|
BOOL entryAdded = FALSE;
|
|
|
|
IN_OUT_STR ("RTCP: Enter createSSRCEntry()\n");
|
|
|
|
// get an SSRC cell from the free list
|
|
pSSRCentry = getOneSSRCentry (&pRTCPContext->RRCMFreeStat,
|
|
pRTCPContext->hHeapRRCMStat,
|
|
&pRTCPContext->dwInitNumFreeRRCMStat,
|
|
&pRTCPContext->critSect);
|
|
if (pSSRCentry == NULL)
|
|
return NULL;
|
|
|
|
// save the remote source address
|
|
if (saveNetworkAddress(pSSRCentry,
|
|
fromAddr,
|
|
fromLen) != RRCM_NoError)
|
|
{
|
|
addToHeadOfList (&pRTCPContext->RRCMFreeStat,
|
|
(PLINK_LIST)pSSRCentry,
|
|
&pRTCPContext->critSect);
|
|
return (NULL);
|
|
}
|
|
|
|
pSSRCentry->SSRC = SSRCnum;
|
|
pSSRCentry->rcvInfo.dwProbation = MIN_SEQUENTIAL;
|
|
|
|
// set this SSRC entry's RTCP session
|
|
pSSRCentry->pRTCPses = pRTCP;
|
|
|
|
// initialize the socket descriptor
|
|
pSSRCentry->RTPsd = ((PSSRC_ENTRY)pRTCP->XmtSSRCList.prev)->RTPsd;
|
|
pSSRCentry->RTCPsd = ((PSSRC_ENTRY)pRTCP->XmtSSRCList.prev)->RTCPsd;
|
|
|
|
// initialize 'dwLastReportRcvdTime' to now
|
|
pSSRCentry->dwLastReportRcvdTime = timeGetTime();
|
|
|
|
#ifdef _DEBUG
|
|
wsprintf (debug_string,
|
|
"RTCP: Create SSRC entry (Addr:x%lX, SSRC=x%lX) for session: (Addr:x%lX)",
|
|
pSSRCentry, pSSRCentry->SSRC, pRTCP);
|
|
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
|
#endif
|
|
|
|
#ifdef ENABLE_ISDM2
|
|
// register to ISDM
|
|
if (Isdm2.hISDMdll && (pRTCP->dwSessionStatus & RTCP_DEST_LEARNED))
|
|
registerSessionToISDM (pSSRCentry, pRTCP, &Isdm2);
|
|
#endif
|
|
|
|
// check to see if it's our entry that needs to be put at the head of
|
|
// the SSRC list. If it's not our entry, will find a place for it in the
|
|
// ordered list
|
|
if (headOfList)
|
|
{
|
|
// Attach the SSRC to the RTCP session list entry head
|
|
addToHeadOfList (&pRTCP->XmtSSRCList,
|
|
(PLINK_LIST)pSSRCentry,
|
|
&pRTCP->critSect);
|
|
|
|
// number of SSRC entry for the RTCP session
|
|
InterlockedIncrement ((long *)&pRTCP->dwCurNumSSRCperSes);
|
|
|
|
#ifdef MONITOR_STATS
|
|
// high number of SSRC entry for the RTCP session
|
|
InterlockedIncrement ((long *)&pRTCP->dwHiNumSSRCperSes)
|
|
#endif
|
|
|
|
return (pSSRCentry);
|
|
}
|
|
|
|
// put it on the receive list of SSRCs
|
|
pTmp = (PLINK_LIST)pRTCP->RcvSSRCList.prev;
|
|
|
|
// check if it's the first one
|
|
if (pTmp == NULL)
|
|
{
|
|
// Attach the SSRC to the RTCP session list entry head
|
|
addToHeadOfList (&pRTCP->RcvSSRCList,
|
|
(PLINK_LIST)pSSRCentry,
|
|
&pRTCP->critSect);
|
|
|
|
// number of SSRC entry for the RTCP session
|
|
InterlockedIncrement ((long *)&pRTCP->dwCurNumSSRCperSes);
|
|
|
|
#ifdef MONITOR_STATS
|
|
// high number of SSRC entry for the RTCP session
|
|
InterlockedIncrement ((long *)&pRTCP->dwHiNumSSRCperSes)
|
|
#endif
|
|
|
|
return (pSSRCentry);
|
|
}
|
|
|
|
while (!entryAdded)
|
|
{
|
|
if (pTmp != NULL)
|
|
{
|
|
pSSRCtmp = (PSSRC_ENTRY)pTmp;
|
|
if (pSSRCtmp->SSRC < SSRCnum)
|
|
pTmp = pTmp->next;
|
|
else
|
|
{
|
|
// lock at the RTCP session level, for head/tail ptrs access
|
|
EnterCriticalSection (&pRTCP->critSect);
|
|
|
|
if ((pTmp->next == NULL) && (pSSRCtmp->SSRC < SSRCnum))
|
|
{
|
|
// attach the SSRC to the RTCP session list entry head
|
|
// This SSRC is bigger than all other ones
|
|
addToHeadOfList (&pRTCP->RcvSSRCList,
|
|
(PLINK_LIST)pSSRCentry,
|
|
&pRTCP->critSect);
|
|
}
|
|
else if (pTmp->prev == NULL)
|
|
{
|
|
// attach the SSRC to the RTCP session list entry tail
|
|
// This SSRC is smaller than all other ones
|
|
addToTailOfList (&pRTCP->RcvSSRCList,
|
|
(PLINK_LIST)pSSRCentry,
|
|
&pRTCP->critSect);
|
|
}
|
|
else
|
|
{
|
|
// this SSRC is in between other SSRCs
|
|
EnterCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
|
|
(pTmp->prev)->next = (PLINK_LIST)pSSRCentry;
|
|
LeaveCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
|
|
|
|
// don't need to lock out pSSRCentry pointers
|
|
pSSRCentry->SSRCList.next = pTmp;
|
|
pSSRCentry->SSRCList.prev = pTmp->prev;
|
|
|
|
pTmp->prev = (PLINK_LIST)pSSRCentry;
|
|
}
|
|
|
|
// unlock RTCP session access
|
|
LeaveCriticalSection (&pRTCP->critSect);
|
|
|
|
// set loop flag
|
|
entryAdded = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// attach the SSRC to the RTCP session list entry head
|
|
addToHeadOfList (&pRTCP->RcvSSRCList,
|
|
(PLINK_LIST)pSSRCentry,
|
|
&pRTCP->critSect);
|
|
|
|
// set loop flag
|
|
entryAdded = TRUE;
|
|
}
|
|
}
|
|
|
|
// number of SSRC entry for the RTCP session
|
|
InterlockedIncrement ((long *)&pRTCP->dwCurNumSSRCperSes);
|
|
|
|
#ifdef MONITOR_STATS
|
|
// high number of SSRC entry for the RTCP session
|
|
InterlockedIncrement ((long *)&pRTCP->dwHiNumSSRCperSes)
|
|
#endif
|
|
|
|
IN_OUT_STR ("RTCP: Exit createSSRCEntry()\n");
|
|
|
|
return (pSSRCentry);
|
|
}
|
|
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : deleteSSRCEntry
|
|
* Description: Delete an SSRC entry (for a particular RTP/RTCP session).
|
|
*
|
|
* Input : SSRCnum : SSRC number to delete from the list
|
|
* pRTCP : -> to the RTCP session
|
|
*
|
|
* Return: TRUE: Deleted
|
|
* FALSE: Entry not found
|
|
---------------------------------------------------------------------------*/
|
|
DWORD deleteSSRCEntry (DWORD SSRCnum,
|
|
PRTCP_SESSION pRTCP)
|
|
{
|
|
PSSRC_ENTRY pSSRCtmp = NULL;
|
|
PLINK_LIST pTmp;
|
|
DWORD dwStatus = FALSE;
|
|
|
|
IN_OUT_STR ("RTCP: Enter deleteSSRCEntry()\n");
|
|
|
|
// walk through the list from the tail
|
|
pTmp = (PLINK_LIST)pRTCP->RcvSSRCList.prev;
|
|
|
|
while (pTmp)
|
|
{
|
|
// lock access to this entry
|
|
EnterCriticalSection (&((PSSRC_ENTRY)pTmp)->critSect);
|
|
|
|
if (((PSSRC_ENTRY)pTmp)->SSRC == SSRCnum)
|
|
{
|
|
#ifdef _DEBUG
|
|
wsprintf (debug_string,
|
|
"RTCP: Delete SSRC=x%lX from session: (Addr:x%lX)",
|
|
SSRCnum, pRTCP);
|
|
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
|
#endif
|
|
|
|
#ifdef ENABLE_ISDM2
|
|
// unregister ISDM session
|
|
if (Isdm2.hISDMdll && ((PSSRC_ENTRY)pTmp)->hISDM)
|
|
Isdm2.ISDMEntry.ISD_DeleteValue(hRRCMRootKey,
|
|
((PSSRC_ENTRY)pTmp)->hISDM, NULL);
|
|
#endif
|
|
|
|
// remove the entry from the list
|
|
if (pTmp->next == NULL)
|
|
{
|
|
removePcktFromHead (&pRTCP->RcvSSRCList,
|
|
&pRTCP->critSect);
|
|
}
|
|
else if (pTmp->prev == NULL)
|
|
{
|
|
removePcktFromTail (&pRTCP->RcvSSRCList,
|
|
&pRTCP->critSect);
|
|
}
|
|
else
|
|
{
|
|
// in between, relink around
|
|
EnterCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
|
|
(pTmp->prev)->next = pTmp->next;
|
|
LeaveCriticalSection (&((PSSRC_ENTRY)pTmp->prev)->critSect);
|
|
|
|
EnterCriticalSection (&((PSSRC_ENTRY)pTmp->next)->critSect);
|
|
(pTmp->next)->prev = pTmp->prev;
|
|
LeaveCriticalSection (&((PSSRC_ENTRY)pTmp->next)->critSect);
|
|
}
|
|
|
|
// number of SSRC entry for the RTCP session
|
|
InterlockedDecrement ((long *)&pRTCP->dwCurNumSSRCperSes);
|
|
|
|
// return entry to the free list
|
|
addToHeadOfList (&pRTCPContext->RRCMFreeStat,
|
|
pTmp,
|
|
&pRTCPContext->critSect);
|
|
|
|
// unlock access to this entry
|
|
LeaveCriticalSection (&((PSSRC_ENTRY)pTmp)->critSect);
|
|
|
|
dwStatus = TRUE;
|
|
break;
|
|
}
|
|
|
|
// unlock access to this entry
|
|
LeaveCriticalSection (&((PSSRC_ENTRY)pTmp)->critSect);
|
|
|
|
pTmp = pTmp->next;
|
|
}
|
|
|
|
IN_OUT_STR ("RTCP: Exit deleteSSRCEntry()\n");
|
|
|
|
return (dwStatus);
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : deleteSSRClist
|
|
* Description: Delete the SSRC list of an RTP/RTCP session.
|
|
*
|
|
* Input : pRTCP : -> to RTCP session
|
|
* pFreeList : -> to the free list of SSRCs
|
|
* pOwner : -> to the free list owner
|
|
*
|
|
* Return: None
|
|
---------------------------------------------------------------------------*/
|
|
void deleteSSRClist (PRTCP_SESSION pRTCP,
|
|
PLINK_LIST pFreeList,
|
|
PRTCP_CONTEXT pOwner)
|
|
{
|
|
PLINK_LIST pSSRC;
|
|
|
|
IN_OUT_STR ("RTCP: Enter deleteSSRClist()\n");
|
|
|
|
ASSERT (pFreeList);
|
|
ASSERT (pRTCP);
|
|
|
|
// lock access to the full RTCP session
|
|
EnterCriticalSection (&pRTCP->critSect);
|
|
|
|
// go through the list of transmit SSRCs for this RTCP session
|
|
while (pRTCP->XmtSSRCList.next != NULL)
|
|
{
|
|
// get packet from the list tail
|
|
pSSRC = removePcktFromTail ((PLINK_LIST)&pRTCP->XmtSSRCList,
|
|
&pRTCP->critSect);
|
|
if (pSSRC != NULL)
|
|
{
|
|
#ifdef _DEBUG
|
|
wsprintf(debug_string,
|
|
"RTCP: Delete SSRC entry (x%lX) from session (x%lX)",
|
|
((PSSRC_ENTRY)pSSRC)->SSRC, pRTCP);
|
|
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
|
#endif
|
|
|
|
#ifdef ENABLE_ISDM2
|
|
// unregister ISDM session
|
|
if (Isdm2.hISDMdll && ((PSSRC_ENTRY)pSSRC)->hISDM)
|
|
Isdm2.ISDMEntry.ISD_DeleteValue (hRRCMRootKey,
|
|
((PSSRC_ENTRY)pSSRC)->hISDM, NULL);
|
|
#endif
|
|
|
|
// put it back to the free list
|
|
addToHeadOfList (pFreeList, pSSRC, &pOwner->critSect);
|
|
|
|
// release the critical section
|
|
DeleteCriticalSection (&((PSSRC_ENTRY)pSSRC)->critSect);
|
|
}
|
|
}
|
|
|
|
// go through the list of SSRCs for this RTP/RTCP session
|
|
while (pRTCP->RcvSSRCList.next != NULL)
|
|
{
|
|
// get packet from the list tail
|
|
pSSRC = removePcktFromTail ((PLINK_LIST)&pRTCP->RcvSSRCList,
|
|
&pRTCP->critSect);
|
|
if (pSSRC != NULL)
|
|
{
|
|
#ifdef _DEBUG
|
|
wsprintf(debug_string,
|
|
"RTCP: Delete SSRC entry (x%lX) from session (x%lX)",
|
|
((PSSRC_ENTRY)pSSRC)->SSRC, pRTCP);
|
|
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
|
#endif
|
|
|
|
#ifdef ENABLE_ISDM2
|
|
// unregister ISDM session
|
|
if (Isdm2.hISDMdll && ((PSSRC_ENTRY)pSSRC)->hISDM)
|
|
Isdm2.ISDMEntry.ISD_DeleteValue (hRRCMRootKey,
|
|
((PSSRC_ENTRY)pSSRC)->hISDM, NULL);
|
|
#endif
|
|
|
|
// put it back to the free list
|
|
addToHeadOfList (pFreeList, pSSRC, &pOwner->critSect);
|
|
|
|
// release the critical section
|
|
DeleteCriticalSection (&((PSSRC_ENTRY)pSSRC)->critSect);
|
|
}
|
|
}
|
|
|
|
// unlock access to the full RTCP session
|
|
LeaveCriticalSection (&pRTCP->critSect);
|
|
|
|
IN_OUT_STR ("RTCP: Exit deleteSSRClist()\n");
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : SSRCTimeoutCheck
|
|
* Description: Check if an rcv SSRC needs to be timed out
|
|
* Since there may be multiple RCV SSRCs, repeat calling
|
|
* this function until it returns NULL
|
|
*
|
|
* Input : pRTCC : -> to the RTCP session
|
|
* curTime : Current time
|
|
*
|
|
* Return: NULL : No action needed
|
|
* PSSRC : -> to the SSRC entry that should be deleted
|
|
---------------------------------------------------------------------------*/
|
|
PSSRC_ENTRY SSRCTimeoutCheck (PRTCP_SESSION pRTCP, DWORD curTime)
|
|
{
|
|
PSSRC_ENTRY pSSRC;
|
|
DWORD tmpTime;
|
|
|
|
// check the colliding entries table and clear it if needed
|
|
RRCMTimeOutCollisionTable (pRTCP);
|
|
|
|
// get the right session to close
|
|
pSSRC = (PSSRC_ENTRY)pRTCP->RcvSSRCList.prev;
|
|
while (pSSRC)
|
|
{
|
|
// check if this SSRC timed-out
|
|
tmpTime = curTime - pSSRC->dwLastReportRcvdTime;
|
|
|
|
// get the time in minutes
|
|
tmpTime /= (1000*60);
|
|
if (tmpTime > RTCP_TIME_OUT_MINUTES)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pSSRC = (PSSRC_ENTRY)pSSRC->SSRCList.next;
|
|
}
|
|
return pSSRC;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function : RRCMChkCollisionTable
|
|
* Description: Check the collision table to try to find a match
|
|
*
|
|
* Input : pFrom : -> recv from address
|
|
* fromlen : -> recv from address length
|
|
* pSSRC : -> to the SSRC entry
|
|
*
|
|
* Return: TRUE: Match found
|
|
* FALSE: No match found
|
|
--------------------------------------------------------------------------*/
|
|
DWORD RRCMChkCollisionTable (PSOCKADDR pFrom,
|
|
UINT fromlen,
|
|
PSSRC_ENTRY pSSRC)
|
|
{
|
|
DWORD idx;
|
|
DWORD dwStatus = FALSE;
|
|
PRTCP_SESSION pRTCP = pSSRC->pRTCPses;
|
|
|
|
IN_OUT_STR ("RRCM: Enter RRCMChkCollisionTable()\n");
|
|
|
|
// entry w/ time == 0 are empty
|
|
for (idx = 0; idx < NUM_COLLISION_ENTRIES; idx++)
|
|
{
|
|
if (pRTCP->collInfo[idx].dwCollideTime != 0)
|
|
{
|
|
if (memcmp (&pRTCP->collInfo[idx].collideAddr,
|
|
pFrom,
|
|
fromlen) == 0)
|
|
{
|
|
// update the time of last collision received
|
|
pRTCP->collInfo[idx].dwCollideTime = timeGetTime();
|
|
|
|
dwStatus = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
IN_OUT_STR ("RRCM: Exit RRCMChkCollisionTable()\n");
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function : RRCMAddEntryToCollisionTable
|
|
* Description: Add an entry into the collision table.
|
|
*
|
|
* Input : pFrom : -> recv from address
|
|
* fromlen : -> recv from address length
|
|
* pSSRC : -> to the SSRC entry
|
|
*
|
|
* Return: TRUE: Entry added
|
|
* FALSE: Table full
|
|
--------------------------------------------------------------------------*/
|
|
DWORD RRCMAddEntryToCollisionTable (PSOCKADDR pFrom,
|
|
UINT fromlen,
|
|
PSSRC_ENTRY pSSRC)
|
|
{
|
|
DWORD idx;
|
|
DWORD dwStatus = FALSE;
|
|
PRTCP_SESSION pRTCP = pSSRC->pRTCPses;
|
|
|
|
IN_OUT_STR ("RRCM: Enter RRCMAddEntryToCollisionTable()\n");
|
|
|
|
// entry w/ time == 0 are empty
|
|
for (idx = 0; idx < NUM_COLLISION_ENTRIES; idx++)
|
|
{
|
|
if (pRTCP->collInfo[idx].dwCollideTime == 0)
|
|
{
|
|
memcpy (&pRTCP->collInfo[idx].collideAddr,
|
|
pFrom,
|
|
fromlen);
|
|
|
|
pRTCP->collInfo[idx].addrLen = fromlen;
|
|
pRTCP->collInfo[idx].dwCollideTime = timeGetTime();
|
|
pRTCP->collInfo[idx].dwCurRecvRTCPrptNumber = pSSRC->dwNumRptRcvd;
|
|
|
|
pRTCP->collInfo[idx].SSRC = pSSRC->SSRC;
|
|
|
|
dwStatus = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
IN_OUT_STR ("RRCM: Exit RRCMAddEntryToCollisionTable()\n");
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* Function : RRCMTimeOutInCollisionTable
|
|
* Description: Check if an entry in the collision table must be timed-out
|
|
*
|
|
* Input : pRTCP : -> to the RTCP session
|
|
*
|
|
* Return: None
|
|
--------------------------------------------------------------------------*/
|
|
void RRCMTimeOutCollisionTable (PRTCP_SESSION pRTCP)
|
|
{
|
|
DWORD idx;
|
|
DWORD currTime = timeGetTime();
|
|
DWORD diffTime;
|
|
|
|
IN_OUT_STR ("RTCP: Enter RRCMTimeOutCollisionTable()\n");
|
|
|
|
// entry w/ time == 0 are empty
|
|
for (idx = 0; idx < NUM_COLLISION_ENTRIES; idx++)
|
|
{
|
|
// valid entries have the time set
|
|
if (pRTCP->collInfo[idx].dwCollideTime)
|
|
{
|
|
// remove the entry from this table if 10 RTCP report intervals
|
|
// have occured without a collision
|
|
|
|
// clear the entry if over 5'
|
|
// !!! TODO !!!
|
|
// !!! using the right interval !!!
|
|
diffTime = currTime - pRTCP->collInfo[idx].dwCollideTime;
|
|
diffTime /= 1000;
|
|
if (diffTime > 300)
|
|
{
|
|
pRTCP->collInfo[idx].dwCollideTime = 0;
|
|
|
|
// the SSRC entry in the receive list will be deleted by
|
|
// the timeout thread
|
|
}
|
|
}
|
|
}
|
|
|
|
IN_OUT_STR ("RTCP: Exit RRCMTimeOutCollisionTable()\n");
|
|
}
|
|
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* Function : clearSSRCEntry
|
|
* Description: Clears what needs to be cleared in an SSRC entry
|
|
*
|
|
* Input : pSSRC : -> to the SSRC entry
|
|
*
|
|
* Return: None
|
|
---------------------------------------------------------------------------*/
|
|
void clearSSRCEntry (PSSRC_ENTRY pSSRC)
|
|
{
|
|
IN_OUT_STR ("RTCP: Enter clearSSRCEntry()\n");
|
|
|
|
memset (&pSSRC->xmtInfo, 0x00, sizeof(XMIT_INFO));
|
|
memset (&pSSRC->rcvInfo, 0x00, sizeof(RECV_INFO));
|
|
memset (&pSSRC->rrFeedback, 0x00, sizeof (RTCP_FEEDBACK));
|
|
memset (&pSSRC->cnameInfo, 0x00, sizeof(SDES_DATA));
|
|
memset (&pSSRC->nameInfo, 0x00, sizeof(SDES_DATA));
|
|
memset (&pSSRC->from, 0x00, sizeof(SOCKADDR));
|
|
|
|
pSSRC->SSRC = 0;
|
|
pSSRC->dwSSRCStatus = 0;
|
|
pSSRC->dwStreamClock = 0;
|
|
pSSRC->fromLen = 0;
|
|
pSSRC->dwLastReportRcvdTime = 0;
|
|
pSSRC->dwUserXmtTimeoutCtrl = 0;
|
|
pSSRC->RTPsd = 0;
|
|
pSSRC->RTCPsd = 0;
|
|
pSSRC->pRTCPses = NULL;
|
|
pSSRC->dwNumRptSent = 0;
|
|
pSSRC->dwNumRptRcvd = 0;
|
|
|
|
#ifdef ENABLE_ISDM2
|
|
pSSRC->hISDM = 0;
|
|
#endif
|
|
|
|
#ifdef _DEBUG
|
|
pSSRC->dwPrvTime = 0;
|
|
#endif
|
|
|
|
IN_OUT_STR ("RTCP: Exit clearSSRCEntry()\n");
|
|
}
|
|
|
|
|
|
// [EOF]
|
|
|