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

606 lines
18 KiB
C++
Raw Permalink Normal View History

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