384 lines
10 KiB
C++
384 lines
10 KiB
C++
/*----------------------------------------------------------------------------
|
||
* File: RTPIO.C
|
||
* Product: RTP/RTCP implementation
|
||
* Description: Provides Session Creation/Deletion Functionality.
|
||
*
|
||
*
|
||
* This listing is supplied under the terms
|
||
* of a license agreement with Intel Corporation and
|
||
* many 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 PRTP_CONTEXT pRTPContext;
|
||
|
||
#ifdef _DEBUG
|
||
extern char debug_string[];
|
||
#endif
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
* Function : CreateRTPSession
|
||
* Description: Creates an RTP (and RTCP) session for a new stream.
|
||
*
|
||
* Input : RTPsocket : RTP socket descriptor
|
||
* RTCPsd : RTCP socket descriptor
|
||
* pRTCPTo : RTCP destination address
|
||
* toRTCPLen : RTCP destination address length
|
||
* pSdesInfo : -> to SDES information
|
||
* dwStreamClock : Stream clocking frequency
|
||
* ssrc : If set, user selected SSRC
|
||
* pRRCMcallback : RRCM notification
|
||
* dwCallbackInfo : User callback info
|
||
* miscInfo : Miscelleanous information:
|
||
* H.323Conf: 0x00000002
|
||
* Encrypt SR/RR: 0x00000004
|
||
* RTCPon: 0x00000008
|
||
* dwRtpSessionBw : RTP session bandwidth used for RTCP BW
|
||
* *pStatus : -> to status information
|
||
*
|
||
* Return: handle to created session if successful
|
||
* Otherwise(0) *pStatus = Initialization Error (see RRCM.H)
|
||
---------------------------------------------------------------------------*/
|
||
HANDLE WINAPI CreateRTPSession (SOCKET RTPsocket,
|
||
SOCKET RTCPsocket,
|
||
LPVOID pRTCPTo,
|
||
DWORD toRTCPLen,
|
||
PSDES_DATA pSdesInfo,
|
||
DWORD dwStreamClock,
|
||
PENCRYPT_INFO pEncryptInfo,
|
||
DWORD ssrc,
|
||
PRRCM_EVENT_CALLBACK pRRCMcallback,
|
||
DWORD_PTR dwCallbackInfo,
|
||
DWORD miscInfo,
|
||
DWORD dwRtpSessionBw,
|
||
DWORD *pStatus)
|
||
{
|
||
DWORD numCells = NUM_FREE_CONTEXT_CELLS;
|
||
DWORD dwStatus;
|
||
DWORD dwRTCPstatus;
|
||
PRTP_SESSION pSession = NULL;
|
||
PSSRC_ENTRY pSSRC;
|
||
|
||
IN_OUT_STR ("RTP : Enter CreateRTPSession()\n");
|
||
|
||
// set status code
|
||
*pStatus = dwStatus = RRCM_NoError;
|
||
|
||
// If RTP context doesn't exist, report error and return.
|
||
if (pRTPContext == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - No RTP Instance",
|
||
0, __FILE__, __LINE__, DBG_CRITICAL);
|
||
IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
|
||
|
||
*pStatus = MAKE_RRCM_ERROR(RRCMError_RTPNoContext);
|
||
|
||
return 0;
|
||
}
|
||
|
||
#if 0
|
||
// look for an existing session - Sender/Receiver for the same session
|
||
// will be on two different graph under ActiveMovie
|
||
if (pSession = findSessionID (RTPsocket))
|
||
{
|
||
RRCM_DBG_MSG ("RTP : Session already created", 0,
|
||
__FILE__, __LINE__, DBG_TRACE);
|
||
|
||
IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
|
||
|
||
// return the unique RTP session ID
|
||
return ((HANDLE)pSession);
|
||
}
|
||
#endif
|
||
|
||
// Allocate a new session pointer.
|
||
pSession = (PRTP_SESSION)GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT,
|
||
sizeof(RTP_SESSION));
|
||
|
||
// Report error if could not allocate context
|
||
if (pSession == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - Resource allocation failed", 0,
|
||
__FILE__, __LINE__, DBG_CRITICAL);
|
||
IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
|
||
|
||
*pStatus = MAKE_RRCM_ERROR(RRCMError_RTPSessResources);
|
||
|
||
return 0;
|
||
}
|
||
|
||
// Initialize the RTP session's critical section
|
||
InitializeCriticalSection(&pSession->critSect);
|
||
|
||
|
||
// All seems OK, initialize RTCP for this session
|
||
pSession->pRTCPSession = CreateRTCPSession(RTPsocket,
|
||
RTCPsocket,
|
||
pRTCPTo,
|
||
toRTCPLen,
|
||
pSdesInfo,
|
||
dwStreamClock,
|
||
pEncryptInfo,
|
||
ssrc,
|
||
pRRCMcallback,
|
||
dwCallbackInfo,
|
||
miscInfo,
|
||
dwRtpSessionBw,
|
||
&dwRTCPstatus);
|
||
|
||
if (pSession->pRTCPSession == NULL)
|
||
{
|
||
dwStatus = dwRTCPstatus;
|
||
|
||
|
||
// Can't proceed, return session pointer
|
||
if (pSession)
|
||
{
|
||
GlobalFree (pSession);
|
||
pSession = NULL;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
#if 0
|
||
// Associate the socket with the Session address
|
||
dwStatus = createHashEntry (pSession, RTPsocket);
|
||
#endif
|
||
|
||
if (dwStatus == RRCM_NoError)
|
||
{
|
||
pSSRC =
|
||
(PSSRC_ENTRY)pSession->pRTCPSession->XmtSSRCList.prev;
|
||
|
||
if (pSSRC == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - No RTCP Xmt list", 0,
|
||
__FILE__, __LINE__, DBG_CRITICAL);
|
||
|
||
dwStatus = RRCMError_RTCPNoXmtList;
|
||
}
|
||
else
|
||
{
|
||
// Let's add this to our context
|
||
addToHeadOfList(&(pRTPContext->pRTPSession),
|
||
(PLINK_LIST)pSession,
|
||
&pRTPContext->critSect);
|
||
#ifdef _DEBUG
|
||
wsprintf(debug_string, "RTP : Adding RTP Session. (Addr:0x%p)",
|
||
pSession);
|
||
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
||
#endif
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
// set status code
|
||
if (dwStatus != RRCM_NoError)
|
||
*pStatus = MAKE_RRCM_ERROR(dwStatus);
|
||
|
||
IN_OUT_STR ("RTP : Exit CreateRTPSession()\n");
|
||
|
||
// return the unique RTP session ID
|
||
return ((HANDLE)pSession);
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
* Function : CloseRTPSession
|
||
* Description: Terminates a local stream session.
|
||
*
|
||
* Input : RTPSession = RTP session ID
|
||
* byeReason = -> to BYE reason
|
||
* closeRTCPSocket = TRUE/FALSE. RTCP will close or not the socket
|
||
*
|
||
* Return: RRCM_NoError = OK.
|
||
* Otherwise(!=0) = Error (see RRCM.H)
|
||
---------------------------------------------------------------------------*/
|
||
HRESULT WINAPI CloseRTPSession (HANDLE RTPSession,
|
||
PCHAR byeReason,
|
||
DWORD closeRTCPSocket)
|
||
{
|
||
PRTP_SESSION pSession;
|
||
PSSRC_ENTRY pSSRCList;
|
||
PSSRC_ENTRY pSSRC;
|
||
DWORD dwStatus;
|
||
|
||
IN_OUT_STR ("RTP : Enter CloseRTPSession()\n");
|
||
|
||
// If RTP context doesn't exist, report error and return.
|
||
if (pRTPContext == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - No RTP Instance", 0,
|
||
__FILE__, __LINE__, DBG_ERROR);
|
||
IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
|
||
|
||
return (MAKE_RRCM_ERROR(RRCMError_RTPNoContext));
|
||
}
|
||
|
||
// Cast Session ID to obtain the session pointer.
|
||
pSession = (PRTP_SESSION)RTPSession;
|
||
if (pSession == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - Invalid RTP session", 0,
|
||
__FILE__, __LINE__, DBG_ERROR);
|
||
IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
|
||
|
||
return (MAKE_RRCM_ERROR(RRCMError_RTPInvalidSession));
|
||
}
|
||
|
||
// Remove the session from the linked list of sessions
|
||
dwStatus = deleteRTPSession (pRTPContext, pSession);
|
||
if (dwStatus != RRCM_NoError)
|
||
{
|
||
#ifdef _DEBUG
|
||
wsprintf(debug_string,
|
||
"RTP : ERROR - RTP session (Addr:0x%lX) not found",
|
||
RTPSession);
|
||
|
||
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_ERROR);
|
||
#endif
|
||
return (MAKE_RRCM_ERROR(dwStatus));
|
||
}
|
||
|
||
// lock out the session - it's on a free list now
|
||
EnterCriticalSection (&pSession->critSect);
|
||
|
||
#if 0
|
||
// clean up the Hash table for any stream still left in the Session
|
||
for (pSSRCList = (PSSRC_ENTRY)pSession->pRTCPSession->XmtSSRCList.prev;
|
||
pSSRCList != NULL;
|
||
pSSRCList = (PSSRC_ENTRY)pSSRCList->SSRCList.next)
|
||
{
|
||
deleteHashEntry (pSSRCList->RTPsd);
|
||
}
|
||
#endif
|
||
|
||
// All seems OK, close RTCP for each stream still open
|
||
pSSRC = (PSSRC_ENTRY)pSession->pRTCPSession->XmtSSRCList.prev;
|
||
if (pSSRC == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - No SSRC entry on the Xmt list", 0,
|
||
__FILE__, __LINE__, DBG_ERROR);
|
||
IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
|
||
|
||
return (MAKE_RRCM_ERROR(RRCMError_RTCPInvalidSSRCentry));
|
||
}
|
||
|
||
// reset the close socket flag
|
||
if (closeRTCPSocket)
|
||
pSSRC->dwSSRCStatus |= CLOSE_RTCP_SOCKET;
|
||
|
||
dwStatus = deleteRTCPSession (pSSRC->RTCPsd, byeReason);
|
||
#ifdef _DEBUG
|
||
if (dwStatus != RRCM_NoError)
|
||
{
|
||
wsprintf(debug_string,
|
||
"RTP : ERROR - RTCP delete Session (Addr: x%p) error:%d",
|
||
pSession, dwStatus);
|
||
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
||
}
|
||
#endif
|
||
|
||
|
||
#ifdef _DEBUG
|
||
wsprintf(debug_string, "RTP : Deleting Session x%p", pSession);
|
||
RRCM_DBG_MSG (debug_string, 0, NULL, 0, DBG_TRACE);
|
||
#endif
|
||
|
||
// lock out the session - it's on a free list now
|
||
LeaveCriticalSection (&pSession->critSect);
|
||
DeleteCriticalSection (&pSession->critSect);
|
||
|
||
GlobalFree (pSession);
|
||
pSession = NULL;
|
||
|
||
IN_OUT_STR ("RTP : Exit CloseRTPSession()\n");
|
||
|
||
if (dwStatus != RRCM_NoError)
|
||
dwStatus = MAKE_RRCM_ERROR(dwStatus);
|
||
|
||
return (dwStatus);
|
||
}
|
||
|
||
|
||
/*--------------------------------------------------------------------------
|
||
** Function : deleteRTPSession
|
||
** Description: Remove from RTP session queue and restore links for other
|
||
** sessions.
|
||
**
|
||
** Input : pRTPContext: -> to the RTP context
|
||
** pSession: -> to the RTP session
|
||
**
|
||
** Return: OK: RRCM_NoError
|
||
** !0: Error code (see RRCM.H)
|
||
--------------------------------------------------------------------------*/
|
||
DWORD deleteRTPSession(PRTP_CONTEXT pRTPContext,
|
||
PRTP_SESSION pSession)
|
||
{
|
||
PLINK_LIST pTmp;
|
||
|
||
IN_OUT_STR ("RTP : Enter deleteRTPSession()\n");
|
||
|
||
// make sure the session exist
|
||
pTmp = pRTPContext->pRTPSession.prev;
|
||
while (pTmp)
|
||
{
|
||
if (pTmp == (PLINK_LIST)pSession)
|
||
break;
|
||
|
||
pTmp = pTmp->next;
|
||
}
|
||
|
||
if (pTmp == NULL)
|
||
{
|
||
RRCM_DBG_MSG ("RTP : ERROR - Invalid RTP session", 0,
|
||
__FILE__, __LINE__, DBG_ERROR);
|
||
|
||
IN_OUT_STR ("RTP : Exit deleteRTPSession()\n");
|
||
|
||
return (MAKE_RRCM_ERROR(RRCMError_RTPInvalidSession));
|
||
}
|
||
|
||
// lock out queue access
|
||
EnterCriticalSection (&pRTPContext->critSect);
|
||
EnterCriticalSection (&pSession->critSect);
|
||
|
||
if (pSession->RTPList.prev == NULL)
|
||
// this was the first entry in the queue
|
||
pRTPContext->pRTPSession.prev = pSession->RTPList.next;
|
||
else
|
||
(pSession->RTPList.prev)->next = pSession->RTPList.next;
|
||
|
||
if (pSession->RTPList.next == NULL)
|
||
// this was the last entry in the queue
|
||
pRTPContext->pRTPSession.next = pSession->RTPList.prev;
|
||
else
|
||
(pSession->RTPList.next)->prev = pSession->RTPList.prev;
|
||
|
||
// unlock out queue access
|
||
LeaveCriticalSection (&pSession->critSect);
|
||
LeaveCriticalSection (&pRTPContext->critSect);
|
||
|
||
IN_OUT_STR ("RTP : Exit deleteRTPSession()\n");
|
||
|
||
return (RRCM_NoError);
|
||
}
|
||
|
||
|
||
// [EOF]
|
||
|
||
|