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