Windows2003-3790/enduser/netmeeting/av/rrcm/rtp/rtpio.cpp

384 lines
11 KiB
C++
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*----------------------------------------------------------------------------
* 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%p) 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]