windows-nt/Source/XPSP1/NT/enduser/netmeeting/av/callcont/h245sys.c
2020-09-26 16:20:57 +08:00

619 lines
17 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
*
* INTEL Corporation Proprietary Information
* Copyright (c) 1994, 1995, 1996 Intel Corporation.
*
* This listing is supplied under the terms of a license agreement
* with INTEL Corporation and may not be used, copied, nor disclosed
* except in accordance with the terms of that agreement.
*
*****************************************************************************/
/******************************************************************************
*
* $Workfile: h245sys.c $
* $Revision: 1.8 $
* $Modtime: Mar 04 1997 17:38:08 $
* $Log: S:/STURGEON/SRC/H245/SRC/VCS/h245sys.c_v $
*
* Rev 1.8 Mar 04 1997 17:51:56 tomitowx
* process detach fix
*
* Rev 1.7 24 Jan 1997 19:40:48 SBELL1
* upgraded to oss 4.2
*
* Rev 1.6 21 Jun 1996 18:53:22 unknown
* Changed InstUnlock() to fix shutdown re-entrancy bug.
*
* Rev 1.5 10 Jun 1996 16:59:34 EHOWARDX
* Moved init/shutdown of submodules to CreateInstance/InstanceUnlock.
*
* Rev 1.3 04 Jun 1996 13:57:02 EHOWARDX
* Fixed Release build warnings.
*
* Rev 1.2 28 May 1996 14:25:38 EHOWARDX
* Tel Aviv update.
*
* Rev 1.1 16 May 1996 13:51:26 EHOWARDX
* Fixed minor timer/lock count interaction bugs.
*
* Rev 1.0 09 May 1996 21:06:28 EHOWARDX
* Initial revision.
*
* Rev 1.25 09 May 1996 19:39:04 EHOWARDX
* Changed includes.
*
* Rev 1.24 29 Apr 1996 12:56:58 EHOWARDX
* Made timers more accurate & made them use fewer resources.
* Note: This is windows-specific.
*
* Rev 1.18.1.2 15 Apr 1996 15:12:34 EHOWARDX
* Kludge to not call H245DeInitTimer() when last timer is stopped.
* This will have to be revisited later.
*
* Rev 1.18.1.1 02 Apr 1996 22:06:22 EHOWARDX
* No change.
*
* Rev 1.18.1.0 27 Mar 1996 16:44:18 EHOWARDX
* Changed timer code; decided it would work better if H245InitTimer()
* actually got called.
*
* Rev 1.18 26 Mar 1996 09:46:08 cjutzi
*
* - ok.. Added Enter&Leave&Init&Delete Critical Sections for Ring 0
*
* Rev 1.17 25 Mar 1996 18:30:14 helgebax
* - removed H245ASSERT .
* .
*
*
* Rev 1.16 25 Mar 1996 18:10:48 cjutzi
*
* - well .. I broke the build.. had to put back what I did..
*
*
* Rev 1.15 25 Mar 1996 17:50:02 cjutzi
*
* - removed critical section.. back step
*
* Rev 1.14 25 Mar 1996 17:20:34 cjutzi
*
* - added Remesh's EnterCritical section definitions.. to use
* oil layer.
*
* Rev 1.13 18 Mar 1996 12:44:40 cjutzi
*
* - put NULL as callback at shutdown
*
* Rev 1.12 18 Mar 1996 12:41:32 cjutzi
* - added timer code for multiple timers queue..
*
* Rev 1.11 12 Mar 1996 15:48:46 cjutzi
*
* - added InstanceTbl Lock
*
* Rev 1.10 07 Mar 1996 22:47:34 dabrown1
*
* Modifications required for ring0/ring3 compatibilty
*
* Rev 1.9 02 Mar 1996 22:14:52 DABROWN1
*
* removed h245_bzero and h245_bcopy (use memset and memcpy instead)
*
* Rev 1.8 26 Feb 1996 17:10:56 cjutzi
*
* - removed h245sys.h
*
* Rev 1.7 26 Feb 1996 12:42:26 cjutzi
*
* - added bcopy
*
* Rev 1.6 21 Feb 1996 16:23:38 DABROWN1
*
* removed h245_ASN1free
* modified malloc and free to save buffer size internally
*
* Rev 1.5 13 Feb 1996 14:54:12 DABROWN1
*
* removed trace/debug files to new debug directory
*
* Rev 1.4 09 Feb 1996 15:45:08 cjutzi
* - added h245trace
* - added h245Assert
*
*****************************************************************************/
#ifndef STRICT
#define STRICT
#endif
#include "precomp.h"
#include "h245api.h"
#include "h245com.h"
#include "h245sys.x"
/**************************************************************************
*
* Instance Table/Instance Lock implementation
*
**************************************************************************/
CRITICAL_SECTION InstanceCreateLock = {0};
CRITICAL_SECTION InstanceLocks[MAXINST] = {0};
struct InstanceStruct * InstanceTable[MAXINST] = {0};
struct InstanceStruct *InstanceCreate(DWORD dwPhysId, H245_CONFIG_T Configuration)
{
register struct InstanceStruct *pInstance;
register unsigned int uIndex;
unsigned int uFirst = (dwPhysId - 1) % MAXINST;
HRESULT lError;
// Allocate new instance
pInstance = (struct InstanceStruct *)MemAlloc(sizeof(*pInstance));
if (pInstance == NULL)
{
H245TRACE(dwPhysId,1,"InstanceCreate -> Instance malloc failed");
return NULL;
}
// Make sure no one is trying to simultaneously add same physical Id
// (I know this is a stretch...)
EnterCriticalSection(&InstanceCreateLock);
// Check if instance corresponding to dwPhysId already exists
uIndex = uFirst; // Hash start index into table
do
{
// Avoid entering critical section for unused instances
if (InstanceTable[uIndex])
{
EnterCriticalSection(&InstanceLocks[uIndex]);
if (InstanceTable[uIndex] && InstanceTable[uIndex]->dwPhysId == dwPhysId)
{
LeaveCriticalSection(&InstanceLocks[uIndex]);
LeaveCriticalSection(&InstanceCreateLock);
MemFree(pInstance);
H245TRACE(dwPhysId,1,"InstanceCreate -> Physical Id already in use");
return NULL;
}
LeaveCriticalSection(&InstanceLocks[uIndex]);
}
uIndex = (uIndex + 1) % MAXINST;
} while (uIndex != uFirst);
// Find empty slot for new instance
uIndex = uFirst; // Hash start index into table
do
{
// Avoid entering critical section for used instances
if (InstanceTable[uIndex] == NULL)
{
EnterCriticalSection(&InstanceLocks[uIndex]);
if (InstanceTable[uIndex] == NULL)
{
// Initialize new instance
// Once the new instance is added to the instance table,
// we can relinquish the CreateInstanceLock
InstanceTable[uIndex] = pInstance;
LeaveCriticalSection(&InstanceCreateLock);
memset(pInstance, 0, sizeof(*pInstance));
pInstance->dwPhysId = dwPhysId;
pInstance->dwInst = uIndex + 1;
pInstance->LockCount = 1;
/* API Subsystem Initialization */
pInstance->Configuration = Configuration;
lError = api_init(pInstance);
if (lError != H245_ERROR_OK)
{
InstanceTable[uIndex] = NULL;
LeaveCriticalSection(&InstanceLocks[uIndex]);
MemFree(pInstance);
H245TRACE(dwPhysId,1,"InstanceCreate -> api_init failed");
return NULL;
}
/* Send Receive Subsystem Initialization */
lError = sendRcvInit(pInstance);
if (lError != H245_ERROR_OK)
{
api_deinit(pInstance);
InstanceTable[uIndex] = NULL;
LeaveCriticalSection(&InstanceLocks[uIndex]);
MemFree(pInstance);
H245TRACE(dwPhysId,1,"InstanceCreate -> sendRcvInit failed");
return NULL;
}
/* State Machine Subsystem Initialization */
lError = Fsm_init(pInstance);
if (lError != H245_ERROR_OK)
{
sendRcvShutdown(pInstance);
api_deinit(pInstance);
InstanceTable[uIndex] = NULL;
LeaveCriticalSection(&InstanceLocks[uIndex]);
MemFree(pInstance);
H245TRACE(dwPhysId,1,"InstanceCreate -> Fsm_init failed");
return NULL;
}
H245TRACE(pInstance->dwInst,9,"InstanceCreate: ++LockCount=%d", pInstance->LockCount);
return pInstance; // Return locked instance
}
LeaveCriticalSection(&InstanceLocks[uIndex]);
}
uIndex = (uIndex + 1) % MAXINST;
} while (uIndex != uFirst);
LeaveCriticalSection(&InstanceCreateLock);
MemFree(pInstance);
H245TRACE(dwPhysId,1,"InstanceCreate -> Too many instances");
return NULL;
} // InstanceCreate()
struct InstanceStruct *InstanceLock(register H245_INST_T dwInst)
{
if (--dwInst >= MAXINST)
{
H245TRACE(dwInst+1,1,"InstanceLock -> Invalid instance");
return NULL;
}
if (!InstanceTable[dwInst])
{
H245TRACE(dwInst+1,1,"InstanceLock -> Invalid instance");
return NULL;
}
// Lock instance, then see if it still exists
EnterCriticalSection(&InstanceLocks[dwInst]);
if (InstanceTable[dwInst])
{
InstanceTable[dwInst]->LockCount++;
H245TRACE(dwInst+1,9,"InstanceLock: ++LockCount=%d", InstanceTable[dwInst]->LockCount);
return InstanceTable[dwInst]; // Return locked instance
}
LeaveCriticalSection(&InstanceLocks[dwInst]);
H245TRACE(dwInst+1,1,"InstanceLock -> Invalid instance");
return NULL;
} // InstanceLock()
int InstanceUnlock(struct InstanceStruct *pInstance)
{
register H245_INST_T dwInst = pInstance->dwInst - 1;
if (dwInst >= MAXINST || InstanceTable[dwInst] != pInstance)
{
H245TRACE(pInstance->dwInst,1,"InstanceUnlock -> Invalid instance");
return -1;
}
if (pInstance->fDelete && pInstance->LockCount == 1)
{
H245TRACE(pInstance->dwInst,9,"InstanceUnlock: deleting instance");
pInstance->fDelete = FALSE; // InstanceUnlock will be re-entered from H245WS callback!
Fsm_shutdown(pInstance);
sendRcvShutdown(pInstance);
api_deinit(pInstance);
InstanceTable[dwInst] = NULL;
LeaveCriticalSection(&InstanceLocks[dwInst]);
while (pInstance->pTimerList)
{
register TimerList_T *pTimer = pInstance->pTimerList;
pInstance->pTimerList = pTimer->pNext;
H245TRACE(pInstance->dwInst,1,"InstanceUnlock: deleting timer");
MemFree(pTimer);
}
MemFree(pInstance);
}
else
{
pInstance->LockCount--;
H245TRACE(pInstance->dwInst,9,"InstanceUnlock: --LockCount=%d", pInstance->LockCount);
LeaveCriticalSection(&InstanceLocks[dwInst]);
}
return 0;
} // InstanceUnlock()
int InstanceDelete(struct InstanceStruct *pInstance)
{
H245TRACE(pInstance->dwInst,9,"InstanceDelete");
pInstance->fDelete = TRUE;
return InstanceUnlock(pInstance);
} // InstanceDelete()
int InstanceUnlock_ProcessDetach(struct InstanceStruct *pInstance, BOOL fProcessDetach)
{
register H245_INST_T dwInst = pInstance->dwInst - 1;
if (dwInst >= MAXINST || InstanceTable[dwInst] != pInstance)
{
H245TRACE(pInstance->dwInst,1,"InstanceUnlock -> Invalid instance");
return -1;
}
if (pInstance->fDelete && pInstance->LockCount == 1)
{
H245TRACE(pInstance->dwInst,9,"InstanceUnlock: deleting instance");
pInstance->fDelete = FALSE; // InstanceUnlock will be re-entered from H245WS callback!
Fsm_shutdown(pInstance);
//sendRcvShutdown(pInstance);
sendRcvShutdown_ProcessDetach(pInstance,fProcessDetach);
api_deinit(pInstance);
InstanceTable[dwInst] = NULL;
LeaveCriticalSection(&InstanceLocks[dwInst]);
while (pInstance->pTimerList)
{
register TimerList_T *pTimer = pInstance->pTimerList;
pInstance->pTimerList = pTimer->pNext;
H245TRACE(pInstance->dwInst,1,"InstanceUnlock: deleting timer");
MemFree(pTimer);
}
MemFree(pInstance);
}
else
{
pInstance->LockCount--;
H245TRACE(pInstance->dwInst,9,"InstanceUnlock: --LockCount=%d", pInstance->LockCount);
LeaveCriticalSection(&InstanceLocks[dwInst]);
}
return 0;
} // InstanceUnlock_ProcessDetach()
/*****************************************************************************
*
* TYPE: TIMER STUFF
*
*****************************************************************************/
CRITICAL_SECTION TimerLock = {0};
static int TimerInited = 0;
#ifndef _IA_SPOX_
static UINT_PTR H245TimerId;
#endif
/*****************************************************************************
*
* TYPE: Global System
*
* PROCEDURE: H245TimerTick - ticks every 1000ms
*
* DESCRIPTION:
*
* RETURN:
*
*****************************************************************************/
void H245TimerTick (void)
{
DWORD dwTickCount = GetTickCount();
unsigned int uIndex;
register struct InstanceStruct *pInstance;
register TimerList_T *pTimer;
H245TRACE(0,9,"H245TimerTick <-");
if (0 != TimerInited)
{
for (uIndex = 0; uIndex < MAXINST; ++uIndex)
{
// Avoid entering critical section for unused instances
if (InstanceTable[uIndex])
{
pInstance = InstanceLock(uIndex + 1);
if (pInstance)
{
while (pInstance->pTimerList && (pInstance->pTimerList->dwAlarm - dwTickCount) >= 0x80000000)
{
pTimer = pInstance->pTimerList;
pInstance->pTimerList = pTimer->pNext;
EnterCriticalSection(&TimerLock);
if (--TimerInited == 0)
{
#ifdef _IA_SPOX_
H223_RegisterTimerCallBack((H223TIMERCB)NULL);
#else
KillTimer (NULL, H245TimerId);
#endif
}
LeaveCriticalSection(&TimerLock);
if (pTimer->pfnCallBack)
{
// TBD - what if pContext is no longer valid?
(pTimer->pfnCallBack)(pInstance, (DWORD_PTR)pTimer, pTimer->pContext);
}
MemFree (pTimer);
} // while
InstanceUnlock(pInstance);
} // if
} // if
} // for
}
H245TRACE(0,9,"H245TimerTick ->");
} // TimerTick()
/*****************************************************************************
*
* TYPE: Global System
*
* PROCEDURE: H245TimerProc - FOR WINDOWS Ring 3 only
*
* DESCRIPTION:
*
* RETURN:
*
*****************************************************************************/
#ifndef _IA_SPOX_
void CALLBACK H245TimerProc(HWND hwHwnd,
UINT uiMessg,
UINT_PTR idTimer,
DWORD dwTime)
{
if (idTimer == H245TimerId)
H245TimerTick ();
}
#endif
/*****************************************************************************
*
* TYPE: Global System
*
* PROCEDURE: H245StartTimer
*
* DESCRIPTION:
*
* RETURN:
*
*****************************************************************************/
DWORD_PTR H245StartTimer (struct InstanceStruct * pInstance,
void * pContext,
H245TIMERCALLBACK pfnCallBack,
DWORD dwTicks)
{
TimerList_T *pNew;
TimerList_T *pLook;
TimerList_T *pList;
if (!pfnCallBack)
{
H245TRACE(pInstance->dwInst,1,"H245StartTimer: pfnCallBack == NULL");
return 0;
}
pNew = (TimerList_T *)MemAlloc(sizeof(TimerList_T));
if (pNew == NULL)
{
H245TRACE(pInstance->dwInst,1,"H245StartTimer: memory allocation failed");
return 0;
}
pNew->pNext = NULL;
pNew->pContext = pContext;
pNew->pfnCallBack = pfnCallBack;
pNew->dwAlarm = GetTickCount() + dwTicks;
EnterCriticalSection(&TimerLock);
if (++TimerInited == 1)
{
#ifdef _IA_SPOX_
H223_RegisterTimerCallBack((H223TIMERCB)H245TimerTick);
#else
H245TimerId = SetTimer ((HWND)NULL, (UINT)0, (UINT)1000, H245TimerProc);
#endif
}
LeaveCriticalSection(&TimerLock);
/* as you traverse the list.. subtract the delta off the new one */
/* and link it in.. this list is a list of delta's off the time */
/* out that is linked in front of it.. so subtract as you go */
for (pList = NULL, pLook = pInstance->pTimerList;
pLook && (pLook->dwAlarm - pNew->dwAlarm) >= 0x80000000;
pList = pLook, pLook = pLook->pNext);
/* link it in the list */
pNew->pNext = pLook;
if (pList)
{
// Insert new timer after pList and before pLook
pList->pNext = pNew;
}
else
{
// Insert new timer at front of list
pInstance->pTimerList = pNew;
}
return (DWORD_PTR)pNew;
}
/*****************************************************************************
*
* TYPE: Global System
*
* PROCEDURE: H245StopTimer
*
* DESCRIPTION:
*
* RETURN:
*
*****************************************************************************/
DWORD H245StopTimer(struct InstanceStruct *pInstance, DWORD_PTR dwTimerId)
{
TimerList_T *pTimer = (TimerList_T *)dwTimerId;
TimerList_T *pLook;
TimerList_T *pList;
ASSERT(TimerInited != 0);
EnterCriticalSection(&TimerLock);
if (--TimerInited == 0)
{
#ifdef _IA_SPOX_
H223_RegisterTimerCallBack((H223TIMERCB)NULL);
#else
KillTimer (NULL, H245TimerId);
#endif
}
LeaveCriticalSection(&TimerLock);
if (pInstance->pTimerList == NULL)
{
H245TRACE(pInstance->dwInst,1,"H245StopTimer: timer list NULL");
return TRUE;
}
if (pTimer == pInstance->pTimerList)
{
pInstance->pTimerList = pTimer->pNext;
MemFree (pTimer);
return FALSE;
}
pList = pInstance->pTimerList;
pLook = pList->pNext;
while (pLook && pLook != pTimer)
{
pList = pLook;
pLook = pLook->pNext;
}
/* if the timer exists.. */
if (pLook == NULL)
{
H245TRACE(pInstance->dwInst,1,"H245StopTimer: pTimer not in timer list");
return TRUE;
}
pList->pNext = pTimer->pNext;
MemFree (pTimer);
return FALSE;
}
#ifdef _IA_SPOX_
PUBLIC RESULT InitializeCriticalSection(CRITICAL_SECTION * phLock)
{
return OIL_CreateLock(phLock);
}
PUBLIC RESULT EnterCriticalSection(CRITICAL_SECTION * phLock)
{
return OIL_AcquireLock(*phLock);
}
PUBLIC RESULT LeaveCriticalSection(CRITICAL_SECTION * phLock)
{
return OIL_ReleaseLock(*phLock);
}
PUBLIC RESULT DeleteCriticalSection(CRITICAL_SECTION * phLock)
{
return OIL_DeleteLock(*phLock);
}
#endif