You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
389 lines
8.8 KiB
389 lines
8.8 KiB
/****************************************************************************
|
|
*
|
|
* $Archive: S:/STURGEON/SRC/CALLCONT/VCS/Listman.c_v $
|
|
*
|
|
* INTEL Corporation Prorietary 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) 1993-1994 Intel Corporation.
|
|
*
|
|
* $Revision: 1.22 $
|
|
* $Date: 22 Jan 1997 14:55:52 $
|
|
* $Author: MANDREWS $
|
|
*
|
|
* Deliverable:
|
|
*
|
|
* Abstract:
|
|
*
|
|
*
|
|
* Notes:
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "apierror.h"
|
|
#include "incommon.h"
|
|
#include "callcont.h"
|
|
#include "q931.h"
|
|
#include "ccmain.h"
|
|
#include "ccutils.h"
|
|
#include "listman.h"
|
|
|
|
|
|
static BOOL bListenInited = FALSE;
|
|
|
|
static struct {
|
|
PLISTEN pHead;
|
|
LOCK Lock;
|
|
} ListenTable;
|
|
|
|
static struct {
|
|
CC_HLISTEN hListen;
|
|
LOCK Lock;
|
|
} ListenHandle;
|
|
|
|
|
|
HRESULT InitListenManager()
|
|
{
|
|
ASSERT(bListenInited == FALSE);
|
|
|
|
ListenTable.pHead = NULL;
|
|
InitializeLock(&ListenTable.Lock);
|
|
|
|
ListenHandle.hListen = CC_INVALID_HANDLE + 1;
|
|
InitializeLock(&ListenHandle.Lock);
|
|
|
|
bListenInited = TRUE;
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT DeInitListenManager()
|
|
{
|
|
PLISTEN pListen;
|
|
PLISTEN pNextListen;
|
|
|
|
if (bListenInited == FALSE)
|
|
return CC_OK;
|
|
|
|
pListen = ListenTable.pHead;
|
|
while (pListen != NULL) {
|
|
AcquireLock(&pListen->Lock);
|
|
pNextListen = pListen->pNextInTable;
|
|
FreeListen(pListen);
|
|
pListen = pNextListen;
|
|
}
|
|
|
|
DeleteLock(&ListenHandle.Lock);
|
|
DeleteLock(&ListenTable.Lock);
|
|
bListenInited = FALSE;
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT _AddListenToTable( PLISTEN pListen)
|
|
{
|
|
ASSERT(pListen != NULL);
|
|
ASSERT(pListen->hListen != CC_INVALID_HANDLE);
|
|
ASSERT(pListen->bInTable == FALSE);
|
|
|
|
AcquireLock(&ListenTable.Lock);
|
|
|
|
pListen->pNextInTable = ListenTable.pHead;
|
|
pListen->pPrevInTable = NULL;
|
|
if (ListenTable.pHead != NULL)
|
|
ListenTable.pHead->pPrevInTable = pListen;
|
|
ListenTable.pHead = pListen;
|
|
|
|
pListen->bInTable = TRUE;
|
|
|
|
RelinquishLock(&ListenTable.Lock);
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT _RemoveListenFromTable( PLISTEN pListen)
|
|
{
|
|
CC_HLISTEN hListen;
|
|
BOOL bTimedOut;
|
|
|
|
ASSERT(pListen != NULL);
|
|
ASSERT(pListen->bInTable == TRUE);
|
|
|
|
// Caller must have a lock on the listen object;
|
|
// in order to avoid deadlock, we must:
|
|
// 1. unlock the listen object,
|
|
// 2. lock the ListenTable,
|
|
// 3. locate the listen object in the ListenTable (note that
|
|
// after step 2, the listen object may be deleted from the
|
|
// ListenTable by another thread),
|
|
// 4. lock the listen object (someone else may have the lock)
|
|
// 5. remove the listen object from the ListenTable,
|
|
// 6. unlock the ListenTable
|
|
//
|
|
// The caller can now safely unlock and destroy the listen object,
|
|
// since no other thread will be able to find the object (its been
|
|
// removed from the ListenTable), and therefore no other thread will
|
|
// be able to lock it.
|
|
|
|
// Save the listen handle; its the only way to look up
|
|
// the listen object in the ListenTable. Note that we
|
|
// can't use pListen to find the listen object, since
|
|
// pListen may be free'd up, and another listen object
|
|
// allocated at the same address
|
|
hListen = pListen->hListen;
|
|
|
|
// step 1
|
|
RelinquishLock(&pListen->Lock);
|
|
|
|
step2:
|
|
// step 2
|
|
AcquireLock(&ListenTable.Lock);
|
|
|
|
// step 3
|
|
pListen = ListenTable.pHead;
|
|
while ((pListen != NULL) && (pListen->hListen != hListen))
|
|
pListen = pListen->pNextInTable;
|
|
|
|
if (pListen != NULL) {
|
|
// step 4
|
|
AcquireTimedLock(&pListen->Lock,10,&bTimedOut);
|
|
if (bTimedOut) {
|
|
RelinquishLock(&ListenTable.Lock);
|
|
Sleep(0);
|
|
goto step2;
|
|
}
|
|
// step 5
|
|
if (pListen->pPrevInTable == NULL)
|
|
ListenTable.pHead = pListen->pNextInTable;
|
|
else
|
|
pListen->pPrevInTable->pNextInTable = pListen->pNextInTable;
|
|
|
|
if (pListen->pNextInTable != NULL)
|
|
pListen->pNextInTable->pPrevInTable = pListen->pPrevInTable;
|
|
|
|
pListen->pNextInTable = NULL;
|
|
pListen->pPrevInTable = NULL;
|
|
pListen->bInTable = FALSE;
|
|
}
|
|
|
|
// step 6
|
|
RelinquishLock(&ListenTable.Lock);
|
|
|
|
if (pListen == NULL)
|
|
return CC_BAD_PARAM;
|
|
else
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT _MakeListenHandle( PCC_HLISTEN phListen)
|
|
{
|
|
AcquireLock(&ListenHandle.Lock);
|
|
*phListen = ListenHandle.hListen++;
|
|
RelinquishLock(&ListenHandle.Lock);
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT AllocAndLockListen( PCC_HLISTEN phListen,
|
|
PCC_ADDR pListenAddr,
|
|
HQ931LISTEN hQ931Listen,
|
|
PCC_ALIASNAMES pLocalAliasNames,
|
|
DWORD_PTR dwListenToken,
|
|
CC_LISTEN_CALLBACK ListenCallback,
|
|
PPLISTEN ppListen)
|
|
{
|
|
HRESULT status;
|
|
|
|
ASSERT(bListenInited == TRUE);
|
|
|
|
// all parameters should have been validated by the caller
|
|
ASSERT(phListen != NULL);
|
|
ASSERT(pListenAddr != NULL);
|
|
ASSERT(ListenCallback != NULL);
|
|
ASSERT(ppListen != NULL);
|
|
|
|
// set phListen now, in case we encounter an error
|
|
*phListen = CC_INVALID_HANDLE;
|
|
|
|
*ppListen = (PLISTEN)MemAlloc(sizeof(LISTEN));
|
|
if (*ppListen == NULL)
|
|
return CC_NO_MEMORY;
|
|
|
|
(*ppListen)->bInTable = FALSE;
|
|
status = _MakeListenHandle(&(*ppListen)->hListen);
|
|
if (status != CC_OK) {
|
|
MemFree(*ppListen);
|
|
return status;
|
|
}
|
|
|
|
// make a local copy of the ListenAddr
|
|
(*ppListen)->ListenAddr = *pListenAddr;
|
|
(*ppListen)->hQ931Listen = hQ931Listen;
|
|
(*ppListen)->dwListenToken = dwListenToken;
|
|
(*ppListen)->pLocalAliasNames = NULL;
|
|
(*ppListen)->ListenCallback = ListenCallback;
|
|
(*ppListen)->pNextInTable = NULL;
|
|
(*ppListen)->pPrevInTable = NULL;
|
|
(*ppListen)->pLocalAliasNames = NULL;
|
|
|
|
InitializeLock(&(*ppListen)->Lock);
|
|
AcquireLock(&(*ppListen)->Lock);
|
|
|
|
*phListen = (*ppListen)->hListen;
|
|
|
|
// make a local copy of the local alias names
|
|
status = Q931CopyAliasNames(&(*ppListen)->pLocalAliasNames, pLocalAliasNames);
|
|
if (status != CS_OK) {
|
|
FreeListen(*ppListen);
|
|
*phListen = CC_INVALID_HANDLE;
|
|
return status;
|
|
}
|
|
|
|
// add the Listen to the Listen table
|
|
status = _AddListenToTable(*ppListen);
|
|
if (status != CC_OK)
|
|
FreeListen(*ppListen);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
|
|
// Caller must have a lock on the Listen object
|
|
HRESULT FreeListen( PLISTEN pListen)
|
|
{
|
|
CC_HLISTEN hListen;
|
|
|
|
ASSERT(pListen != NULL);
|
|
|
|
// caller must have a lock on the Listen object,
|
|
// so there's no need to re-lock it
|
|
|
|
hListen = pListen->hListen;
|
|
|
|
if (pListen->bInTable == TRUE)
|
|
if (_RemoveListenFromTable(pListen) == CC_BAD_PARAM)
|
|
// the Listen object was deleted by another thread,
|
|
// so just return CC_OK
|
|
return CC_OK;
|
|
|
|
if (pListen->pLocalAliasNames != NULL)
|
|
Q931FreeAliasNames(pListen->pLocalAliasNames);
|
|
|
|
// Since the listen object has been removed from the ListenTable,
|
|
// no other thread will be able to find the listen object and obtain
|
|
// a lock, so its safe to unlock the listen object and delete it here
|
|
RelinquishLock(&pListen->Lock);
|
|
DeleteLock(&pListen->Lock);
|
|
MemFree(pListen);
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT LockListen( CC_HLISTEN hListen,
|
|
PPLISTEN ppListen)
|
|
{
|
|
BOOL bTimedOut;
|
|
|
|
ASSERT(hListen != CC_INVALID_HANDLE);
|
|
ASSERT(ppListen != NULL);
|
|
|
|
step1:
|
|
AcquireLock(&ListenTable.Lock);
|
|
|
|
*ppListen = ListenTable.pHead;
|
|
while ((*ppListen != NULL) && ((*ppListen)->hListen != hListen))
|
|
*ppListen = (*ppListen)->pNextInTable;
|
|
|
|
if (*ppListen != NULL) {
|
|
AcquireTimedLock(&(*ppListen)->Lock,10,&bTimedOut);
|
|
if (bTimedOut) {
|
|
RelinquishLock(&ListenTable.Lock);
|
|
Sleep(0);
|
|
goto step1;
|
|
}
|
|
}
|
|
|
|
RelinquishLock(&ListenTable.Lock);
|
|
|
|
if (*ppListen == NULL)
|
|
return CC_BAD_PARAM;
|
|
else
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT ValidateListen( CC_HLISTEN hListen)
|
|
{
|
|
PLISTEN pListen;
|
|
|
|
ASSERT(hListen != CC_INVALID_HANDLE);
|
|
|
|
AcquireLock(&ListenTable.Lock);
|
|
|
|
pListen = ListenTable.pHead;
|
|
while ((pListen != NULL) && (pListen->hListen != hListen))
|
|
pListen = pListen->pNextInTable;
|
|
|
|
RelinquishLock(&ListenTable.Lock);
|
|
|
|
if (pListen == NULL)
|
|
return CC_BAD_PARAM;
|
|
else
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT UnlockListen( PLISTEN pListen)
|
|
{
|
|
ASSERT(pListen != NULL);
|
|
|
|
RelinquishLock(&pListen->Lock);
|
|
return CC_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT GetLastListenAddress( PCC_ADDR pListenAddr)
|
|
{
|
|
HRESULT status;
|
|
PLISTEN pListen;
|
|
PLISTEN pLastListen;
|
|
|
|
ASSERT(pListenAddr != NULL);
|
|
|
|
AcquireLock(&ListenTable.Lock);
|
|
|
|
pListen = ListenTable.pHead;
|
|
pLastListen = pListen;
|
|
while (pListen != NULL) {
|
|
if (pLastListen->hListen < pListen->hListen)
|
|
pLastListen = pListen;
|
|
pListen = pListen->pNextInTable;
|
|
}
|
|
|
|
if (pLastListen == NULL)
|
|
status = CC_BAD_PARAM;
|
|
else {
|
|
status = CC_OK;
|
|
*pListenAddr = pLastListen->ListenAddr;
|
|
}
|
|
|
|
RelinquishLock(&ListenTable.Lock);
|
|
return status;
|
|
}
|
|
|