|
|
/*----------------------------------------------------------------------------
* File: RTPINIT.C * Product: RTP/RTCP implementation * Description: Provides initialization functions. * * 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"
/*---------------------------------------------------------------------------
/ External Variables /--------------------------------------------------------------------------*/
extern SOCKET PASCAL WS2EmulSocket( int af, int type,int protocol, LPWSAPROTOCOL_INFO ,GROUP,DWORD); extern int PASCAL WS2EmulCloseSocket(SOCKET s); extern int PASCAL WS2EmulSetSockOpt(SOCKET s, int level,int optname,const char FAR * optval,int optlen); extern int PASCAL WS2EmulBind( SOCKET s, const struct sockaddr FAR * name, int namelen); extern int PASCAL WS2EmulRecvFrom( SOCKET s,LPWSABUF , DWORD, LPDWORD, LPDWORD,struct sockaddr FAR *, LPINT, LPWSAOVERLAPPED,LPWSAOVERLAPPED_COMPLETION_ROUTINE ); extern int PASCAL WS2EmulSendTo( SOCKET s,LPWSABUF, DWORD ,LPDWORD , DWORD , const struct sockaddr FAR *, int, LPWSAOVERLAPPED , LPWSAOVERLAPPED_COMPLETION_ROUTINE ); extern int PASCAL WS2EmulGetSockName( SOCKET s, struct sockaddr * name, int * namelen ); extern int PASCAL WS2EmulHtonl( SOCKET s,u_long hostlong,u_long FAR * lpnetlong); extern int PASCAL WS2EmulNtohl( SOCKET s,u_long ,u_long FAR * ); extern int PASCAL WS2EmulHtons( SOCKET s,u_short ,u_short FAR *); extern int PASCAL WS2EmulNtohs( SOCKET s,u_short ,u_short FAR *); extern int PASCAL WS2EmulGetHostName(char *name, int namelen); extern struct hostent FAR * PASCAL WS2EmulGetHostByName(const char * name); extern SOCKET PASCAL WS2EmulJoinLeaf(SOCKET s, const struct sockaddr FAR * name,int , LPWSABUF , LPWSABUF , LPQOS, LPQOS, DWORD dwFlags); extern int PASCAL WS2EmulIoctl(SOCKET s, DWORD, LPVOID,DWORD cbInBuffer, LPVOID , DWORD, LPDWORD lpcbBytesReturned,LPWSAOVERLAPPED, LPWSAOVERLAPPED_COMPLETION_ROUTINE);
extern void WS2EmulInit();
extern void WS2EmulTerminate();
/*---------------------------------------------------------------------------
/ Global Variables /--------------------------------------------------------------------------*/ PRTP_CONTEXT pRTPContext = NULL; RRCM_WS RRCMws = { NULL, // hWSdll
WS2EmulSendTo, WS2EmulRecvFrom, WS2EmulNtohl, WS2EmulNtohs, WS2EmulHtonl, WS2EmulHtons, WS2EmulGetSockName, WS2EmulGetHostName, WS2EmulGetHostByName, WS2EmulCloseSocket, WS2EmulSocket, WS2EmulBind, NULL, //WSAEnumProtocols
WS2EmulJoinLeaf, //WSAJoinLeaf
WS2EmulIoctl, //WSAIoctl
WS2EmulSetSockOpt };
DWORD g_fDisableWinsock2 = 0;
#ifdef ENABLE_ISDM2
KEY_HANDLE hRRCMRootKey; ISDM2 Isdm2; #endif
#ifdef _DEBUG
char debug_string[DBG_STRING_LEN]; #endif
#ifdef UNICODE
static const char szWSASocket[] = "WSASocketW"; static const char szWSAEnumProtocols[] = "WSAEnumProtocolsW"; #else
static const char szWSASocket[] = "WSASocketA"; static const char szWSAEnumProtocols[] = "WSAEnumProtocolsA"; #endif
/*----------------------------------------------------------------------------
* Function : initRTP * Description: Initializes the RTP task. * * Input : hInst: Handle to the DLL instance * * Return: RRCM_NoError = OK. * Otherwise(!=0) = Initialization Error (see RRCM.H). ---------------------------------------------------------------------------*/ DWORD initRTP (HINSTANCE hInst) { DWORD dwStatus; DWORD hashTableEntries = NUM_RTP_HASH_SESS;
IN_OUT_STR ("RTP : Enter initRTP()\n");
// If RTP has already been initialized, stop, report the error and return
if (pRTPContext != NULL) { RRCM_DBG_MSG ("RTP : ERROR - Multiple RTP Instances", 0, __FILE__, __LINE__, DBG_CRITICAL); IN_OUT_STR ("RTP : Exit initRTP()\n");
return (MAKE_RRCM_ERROR(RRCMError_RTPReInit)); }
// Obtain our context
pRTPContext = (PRTP_CONTEXT)GlobalAlloc (GMEM_FIXED | GMEM_ZEROINIT, sizeof(RTP_CONTEXT));
// if no resources, exit with appropriate error
if (pRTPContext == NULL) { RRCM_DBG_MSG ("RTP : ERROR - Resource allocation failed", 0, __FILE__, __LINE__, DBG_CRITICAL); IN_OUT_STR ("RTP : Exit initRTP()\n");
return (MAKE_RRCM_ERROR(RRCMError_RTPResources)); }
// Get information from the registry if any present
RRCMreadRegistry (pRTPContext);
// Perform dynamic linking of what we need
if ((dwStatus = RRCMgetDynamicLink ()) != RRCM_NoError) { GlobalFree(pRTPContext); pRTPContext = NULL;
RRCM_DBG_MSG ("RTP : ERROR - Winsock library not found", 0, __FILE__, __LINE__, DBG_CRITICAL); IN_OUT_STR ("RTP : Exit initRTP()\n");
return MAKE_RRCM_ERROR(dwStatus); }
// Initialize RTP context critical section
InitializeCriticalSection(&pRTPContext->critSect);
//Initialize WS2Emulation critical section
WS2EmulInit();
// Create RTCP and look at return value. If error, don't proceed
// any further. Pass this error to the calling function
if ((dwStatus = initRTCP()) == RRCM_NoError) { // RTCP is up. We need to initialize our context
pRTPContext->hInst = hInst; pRTPContext->pRTPSession.next = NULL; pRTPContext->pRTPSession.prev = NULL;
} // if any part of initialation did not succeed, declare it all a failure
// and return all resourses allocated
if (dwStatus != RRCM_NoError) { if (pRTPContext) { GlobalFree(pRTPContext); pRTPContext = NULL; } }
IN_OUT_STR ("RTP : Exit initRTP()\n");
if (dwStatus != RRCM_NoError) dwStatus = MAKE_RRCM_ERROR(dwStatus);
return (dwStatus); }
/*----------------------------------------------------------------------------
* Function : deleteRTP * Description: Deletes RTP. Closes all RTP and RTCP sessions and releases all * resources. * * Input : hInst: Handle to the DLL instance. * * Return: RRCM_NoError = OK. * Otherwise(!=0) = Initialization Error (see RRCM.H). ---------------------------------------------------------------------------*/ DWORD deleteRTP (HINSTANCE hInst) { DWORD dwStatus; PRTP_SESSION pDeleteSession;
#ifdef ENABLE_ISDM2
HRESULT hError; #endif
IN_OUT_STR ("RTP : Enter deleteRTP()\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 deleteRTP()\n");
return (MAKE_RRCM_ERROR(RRCMError_RTPInvalidDelete)); }
if (pRTPContext->hInst != hInst) { RRCM_DBG_MSG ("RTP : ERROR - Invalid DLL instance handle", 0, __FILE__, __LINE__, DBG_ERROR); IN_OUT_STR ("RTP : Exit deleteRTP()\n");
return (MAKE_RRCM_ERROR(RRCMError_RTPNoContext)); }
// If we still have sessions open, clean them up
while ((pDeleteSession = (PRTP_SESSION)pRTPContext->pRTPSession.prev) != NULL) { RRCM_DBG_MSG ("RTP : ERROR - Session x still open at DLL exit", 0, __FILE__, __LINE__, DBG_ERROR); ASSERT(0); //Close all open sessions
CloseRTPSession (pDeleteSession, NULL, FALSE); }
// Call RTCP to terminate and cleanup
dwStatus = deleteRTCP(); #ifdef ENABLE_ISDM2
// Query ISDM key
if (Isdm2.hISDMdll) { DWORD dwKeys = 0; DWORD dwValues = 0;
if (SUCCEEDED (Isdm2.ISDMEntry.ISD_QueryInfoKey (hRRCMRootKey, NULL, NULL, &dwKeys, &dwValues))) { if (!dwKeys && !dwValues) { hError = Isdm2.ISDMEntry.ISD_DeleteKey(hRRCMRootKey); if(FAILED(hError)) RRCM_DBG_MSG ("RTP: ISD_DeleteKey failed", 0, NULL, 0, DBG_NOTIFY); } }
DeleteCriticalSection (&Isdm2.critSect);
if (FreeLibrary (Isdm2.hISDMdll) == FALSE) { RRCM_DBG_MSG ("RTP : ERROR - Freeing WS Lib", GetLastError(), __FILE__, __LINE__, DBG_ERROR); } } #endif
// unload the WS library
if (RRCMws.hWSdll) { if (FreeLibrary (RRCMws.hWSdll) == FALSE) { RRCM_DBG_MSG ("RTP : ERROR - Freeing WS Lib", GetLastError(), __FILE__, __LINE__, DBG_ERROR); } }
// delete RTP context critical section
DeleteCriticalSection(&pRTPContext->critSect);
// delete WS2 Emulation
WS2EmulTerminate(); // delete RTP context
GlobalFree(pRTPContext); pRTPContext = NULL;
IN_OUT_STR ("RTP : Exit deleteRTP()\n");
if (dwStatus != RRCM_NoError) dwStatus = MAKE_RRCM_ERROR(dwStatus);
return (dwStatus); }
/*----------------------------------------------------------------------------
* Function : RRCMreadRegistry * Description: Access the registry * * Input : pCtxt: -> to the RTP context * * Return: None ---------------------------------------------------------------------------*/ void RRCMreadRegistry (PRTP_CONTEXT pCtxt) { HKEY hKey; long lRes; char keyBfr[50];
// open the key
strcpy (keyBfr, szRegRRCMKey);
// INTEL key vs MICROSOFT KEY
#ifndef INTEL
strcat (keyBfr, szRegRRCMSubKey); #else
strcat (keyBfr, szRegRRCMSubKeyIntel); #endif
lRes = RegOpenKeyEx (HKEY_LOCAL_MACHINE, keyBfr, 0, KEY_READ, &hKey); if (lRes || !hKey) { // key not found, setup default values
pCtxt->registry.NumSessions = NUM_RRCM_SESS; pCtxt->registry.NumFreeSSRC = NUM_FREE_SSRC; pCtxt->registry.NumRTCPPostedBfr = NUM_RCV_BFR_POSTED; pCtxt->registry.RTCPrcvBfrSize = RRCM_RCV_BFR_SIZE; return; }
// get the number of RRCM sessions
RRCMgetRegistryValue (hKey, szRegRRCMNumSessions, &pCtxt->registry.NumSessions, REG_DWORD, sizeof(DWORD)); // check range
if (pCtxt->registry.NumSessions < MIN_NUM_RRCM_SESS) pCtxt->registry.NumSessions = MIN_NUM_RRCM_SESS; else if (pCtxt->registry.NumSessions > MAX_NUM_RRCM_SESS) pCtxt->registry.NumSessions = MAX_NUM_RRCM_SESS;
// get the number of initial free SSRC
RRCMgetRegistryValue (hKey, szRegRRCMNumFreeSSRC, &pCtxt->registry.NumFreeSSRC, REG_DWORD, sizeof(DWORD));
// check range
if (pCtxt->registry.NumFreeSSRC < MIN_NUM_FREE_SSRC) pCtxt->registry.NumFreeSSRC = MIN_NUM_FREE_SSRC; else if (pCtxt->registry.NumFreeSSRC > MAX_NUM_FREE_SSRC) pCtxt->registry.NumFreeSSRC = MAX_NUM_FREE_SSRC;
// get the number of RTCP rcv buffers to be posted
RRCMgetRegistryValue (hKey, szRegRRCMNumRTCPPostedBfr, &pCtxt->registry.NumRTCPPostedBfr, REG_DWORD, sizeof(DWORD));
// check range
if (pCtxt->registry.NumRTCPPostedBfr < MIN_NUM_RCV_BFR_POSTED) pCtxt->registry.NumRTCPPostedBfr = MIN_NUM_RCV_BFR_POSTED; else if (pCtxt->registry.NumRTCPPostedBfr > MAX_NUM_RCV_BFR_POSTED) pCtxt->registry.NumRTCPPostedBfr = MAX_NUM_RCV_BFR_POSTED;
// get the RTCP rcv buffer size
RRCMgetRegistryValue (hKey, szRegRRCMRTCPrcvBfrSize, &pCtxt->registry.RTCPrcvBfrSize, REG_DWORD, sizeof(DWORD));
// check range
if (pCtxt->registry.RTCPrcvBfrSize < MIN_RRCM_RCV_BFR_SIZE) pCtxt->registry.RTCPrcvBfrSize = MIN_RRCM_RCV_BFR_SIZE; else if (pCtxt->registry.RTCPrcvBfrSize > MAX_RRCM_RCV_BFR_SIZE) pCtxt->registry.RTCPrcvBfrSize = MAX_RRCM_RCV_BFR_SIZE;
RRCMgetRegistryValue(hKey, "DisableWinsock2", &g_fDisableWinsock2, REG_DWORD, sizeof(DWORD));
// close the key
RegCloseKey (hKey); }
/*----------------------------------------------------------------------------
* Function : RRCMgetRegistryValue * Description: Read a value from the registry * * Input : hKey : Key handle * pValStr : -> to string value * pKeyVal : -> to value * type : Type to read * len : Receiving buffer length * * Return: None ---------------------------------------------------------------------------*/ void RRCMgetRegistryValue (HKEY hKey, LPTSTR pValStr, PDWORD pKeyVal, DWORD type, DWORD len) { DWORD dwType = type; DWORD retSize = len;
// query the value
RegQueryValueEx (hKey, pValStr, NULL, &dwType, (BYTE *)pKeyVal, &retSize); }
/*----------------------------------------------------------------------------
* Function : RRCMgetDynamicLink * Description: Get all dynamic linked DLL entries * * Input : None * * Return: None ---------------------------------------------------------------------------*/ DWORD RRCMgetDynamicLink (void) { HINSTANCE hWSdll;
#ifdef ENABLE_ISDM2
HRESULT hError;
Isdm2.hISDMdll = LoadLibrary(szISDMdll);
// make sure the LoadLibrary call did not fail
if (Isdm2.hISDMdll) { RRCM_DBG_MSG ("RTP: ISDM2 LoadLibrary worked", 0, NULL, 0, DBG_NOTIFY); // get the ISDM entry points used by RRCM
Isdm2.ISDMEntry.ISD_CreateKey = (ISD_CREATEKEY) GetProcAddress (Isdm2.hISDMdll, "ISD_CreateKey");
Isdm2.ISDMEntry.ISD_CreateValue = (ISD_CREATEVALUE) GetProcAddress (Isdm2.hISDMdll, "ISD_CreateValue");
Isdm2.ISDMEntry.ISD_SetValue = (ISD_SETVALUE) GetProcAddress (Isdm2.hISDMdll, "ISD_SetValue");
Isdm2.ISDMEntry.ISD_DeleteValue = (ISD_DELETEVALUE) GetProcAddress (Isdm2.hISDMdll, "ISD_DeleteValue");
Isdm2.ISDMEntry.ISD_DeleteKey = (ISD_DELETEKEY) GetProcAddress (Isdm2.hISDMdll, "ISD_DeleteKey");
Isdm2.ISDMEntry.ISD_QueryInfoKey = (ISD_QUERYINFOKEY) GetProcAddress (Isdm2.hISDMdll, "ISD_QueryInfoKey");
// initialize critical section
InitializeCriticalSection (&Isdm2.critSect);
// make sure we have all of them
if (Isdm2.ISDMEntry.ISD_CreateKey == NULL || Isdm2.ISDMEntry.ISD_CreateValue == NULL || Isdm2.ISDMEntry.ISD_SetValue == NULL || Isdm2.ISDMEntry.ISD_DeleteValue == NULL || Isdm2.ISDMEntry.ISD_DeleteKey == NULL || Isdm2.ISDMEntry.ISD_QueryInfoKey == NULL ) { Isdm2.hISDMdll = 0; RRCM_DBG_MSG ("RTP: Failed to load all ISDM2 functions", 0, NULL, 0, DBG_NOTIFY); // delete critical section
DeleteCriticalSection (&Isdm2.critSect); } else { hError = Isdm2.ISDMEntry.ISD_CreateKey(MAIN_ROOT_KEY, szRRCMISDM, &hRRCMRootKey); if(FAILED(hError)) { RRCM_DBG_MSG ("RTP: ISD_CreateKey Failed",0, NULL, 0, DBG_NOTIFY); hRRCMRootKey = 0; } } } #endif
if (!g_fDisableWinsock2) { // load Winsock2 if present
hWSdll = LoadLibrary(szRRCMdefaultLib);
if (hWSdll) { RRCMws.hWSdll = hWSdll;
RRCMws.sendTo = (LPFN_WSASENDTO)GetProcAddress (hWSdll, "WSASendTo"); RRCMws.recvFrom = (LPFN_WSARECVFROM)GetProcAddress (hWSdll, "WSARecvFrom"); RRCMws.getsockname = (LPFN_GETSOCKNAME)GetProcAddress (hWSdll, "getsockname"); RRCMws.gethostname = (LPFN_GETHOSTNAME)GetProcAddress (hWSdll, "gethostname"); RRCMws.gethostbyname = (LPFN_GETHOSTBYNAME)GetProcAddress (hWSdll, "gethostbyname"); RRCMws.WSASocket = (LPFN_WSASOCKET)GetProcAddress (hWSdll, szWSASocket); RRCMws.closesocket = (LPFN_CLOSESOCKET)GetProcAddress (hWSdll, "closesocket"); RRCMws.bind = (LPFN_BIND)GetProcAddress (hWSdll, "bind"); RRCMws.WSAEnumProtocols = (LPFN_WSAENUMPROTOCOLS) ::GetProcAddress(hWSdll, szWSAEnumProtocols); RRCMws.WSAIoctl = (LPFN_WSAIOCTL) ::GetProcAddress(hWSdll, "WSAIoctl"); RRCMws.WSAJoinLeaf = (LPFN_WSAJOINLEAF) ::GetProcAddress(hWSdll, "WSAJoinLeaf"); RRCMws.setsockopt = (LPFN_SETSOCKOPT) ::GetProcAddress(hWSdll, "setsockopt"); RRCMws.ntohl = (LPFN_WSANTOHL)GetProcAddress (hWSdll, "WSANtohl"); RRCMws.ntohs = (LPFN_WSANTOHS)GetProcAddress (hWSdll, "WSANtohs"); RRCMws.htonl = (LPFN_WSAHTONL)GetProcAddress (hWSdll, "WSAHtonl"); RRCMws.htons = (LPFN_WSAHTONS)GetProcAddress (hWSdll, "WSAHtons"); if (RRCMws.WSAEnumProtocols) { int nProt = 0, i; int iProt[2]; // array of protocols we're interested in
DWORD dwBufLength = sizeof(WSAPROTOCOL_INFO); LPWSAPROTOCOL_INFO pProtInfo = (LPWSAPROTOCOL_INFO) LocalAlloc(0,dwBufLength);
iProt[0] = IPPROTO_UDP; iProt[1] = 0; // figure out the buffer size needed for WSAPROTOCOLINFO structs
nProt = RRCMws.WSAEnumProtocols(iProt,pProtInfo,&dwBufLength); if (nProt < 0 && GetLastError() == WSAENOBUFS) { LocalFree(pProtInfo); pProtInfo = (LPWSAPROTOCOL_INFO) LocalAlloc(0,dwBufLength); if (pProtInfo) nProt = RRCMws.WSAEnumProtocols(iProt,pProtInfo,&dwBufLength); }
if (nProt > 0) { for (i=0;i < nProt; i++) { if (pProtInfo[i].iProtocol == IPPROTO_UDP && pProtInfo[i].iSocketType == SOCK_DGRAM && ((pProtInfo[i].dwServiceFlags1 & XP1_QOS_SUPPORTED) || RRCMws.RTPProtInfo.iProtocol == 0) ) { // make a copy of the matching WSAPROTOCOL_INFO
RRCMws.RTPProtInfo = pProtInfo[i]; if (pProtInfo[i].dwServiceFlags1 & XP1_QOS_SUPPORTED) { RRCM_DBG_MSG ("QOS UDP provider found.\n", 0, __FILE__, __LINE__, DBG_WARNING); break; } // else keep looking for a provider that supports QOS
} } } if (pProtInfo) LocalFree(pProtInfo);
if (RRCMws.RTPProtInfo.iProtocol == IPPROTO_UDP) { // we found the protocol(s) we wanted
//RETAILMSG(("NAC: Using Winsock 2"));
} else { FreeLibrary(RRCMws.hWSdll); RRCMws.hWSdll = NULL; } } } } // make sure we have the Xmt/Recv functionality
if (RRCMws.sendTo == NULL || RRCMws.recvFrom == NULL || RRCMws.getsockname == NULL || RRCMws.ntohl == NULL || RRCMws.ntohs == NULL || RRCMws.htonl == NULL || RRCMws.htons == NULL || RRCMws.gethostname == NULL || RRCMws.gethostbyname == NULL || RRCMws.WSASocket == NULL || RRCMws.closesocket == NULL || RRCMws.WSAIoctl == NULL || RRCMws.WSAJoinLeaf == NULL ) { RRCM_DBG_MSG ("RTP : ERROR - Invalid Winsock DLL", 0, __FILE__, __LINE__, DBG_CRITICAL);
return RRCMError_WinsockLibNotFound; } else return RRCM_NoError; }
// [EOF]
|