|
|
/****************************************************************************
* * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/callman.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.69.1.1 $ * $Date: 23 Jun 1997 15:58:00 $ * $Author: MANDREWS $ * * Deliverable: * * Abstract: * * * Notes: * ***************************************************************************/
#pragma warning ( disable: 4115 4201 4214)
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#pragma warning ( default: 4115 4201 4214)
#include "incommon.h"
#include "callcont.h"
#include "q931.h"
#include "ccmain.h"
#include "h245man.h"
#include "confman.h"
#include "callman.h"
#include "ccutils.h"
#include "callman2.h"
static BOOL bCallInited = FALSE;
#define HASH_TABLE_SIZE 11
static struct { PCALL pHead[HASH_TABLE_SIZE]; LOCK Lock; } CallTable;
static struct { CC_HCALL hCall; LOCK Lock; } CallHandle;
HRESULT _LockCallAndConferenceMarkedForDeletion( CC_HCALL hCall, PPCALL ppCall, PPCONFERENCE ppConference);
HRESULT InitCallManager() { int i;
ASSERT(bCallInited == FALSE);
for (i = 0; i < HASH_TABLE_SIZE; i++) CallTable.pHead[i] = NULL; InitializeLock(&CallTable.Lock);
CallHandle.hCall = CC_INVALID_HANDLE + 1; InitializeLock(&CallHandle.Lock);
bCallInited = TRUE; return CC_OK; }
HRESULT DeInitCallManager() { HRESULT status; HRESULT SaveStatus; int i; PCALL pCall; PCALL pNextCall; H245_INST_T H245Instance;
if (bCallInited == FALSE) return CC_OK;
SaveStatus = CC_OK; for (i = 0; i < HASH_TABLE_SIZE; i++) { pCall = CallTable.pHead[i]; while (pCall != NULL) { AcquireLock(&pCall->Lock); pNextCall = pCall->pNextInTable; H245Instance = pCall->H245Instance; FreeCall(pCall); if (H245Instance != H245_INVALID_ID) { status = H245ShutDown(H245Instance); if (status != H245_ERROR_OK) SaveStatus = status; } pCall = pNextCall; } }
DeleteLock(&CallHandle.Lock); DeleteLock(&CallTable.Lock); bCallInited = FALSE; return SaveStatus; }
#define _Hash(hCall) ((hCall) % HASH_TABLE_SIZE)
HRESULT _AddCallToTable( PCALL pCall) { int index;
ASSERT(pCall != NULL); ASSERT(pCall->hCall != CC_INVALID_HANDLE); ASSERT(pCall->bInTable == FALSE);
AcquireLock(&CallTable.Lock);
index = _Hash(pCall->hCall); pCall->pNextInTable = CallTable.pHead[index]; pCall->pPrevInTable = NULL; if (CallTable.pHead[index] != NULL) CallTable.pHead[index]->pPrevInTable = pCall; CallTable.pHead[index] = pCall;
pCall->bInTable = TRUE;
RelinquishLock(&CallTable.Lock); return CC_OK; }
HRESULT _RemoveCallFromTable( PCALL pCall) { CC_HCALL hCall; int index; BOOL bTimedOut;
ASSERT(pCall != NULL); ASSERT(pCall->bInTable == TRUE);
// Caller must have a lock on the call object;
// in order to avoid deadlock, we must:
// 1. unlock the Call object,
// 2. lock the CallTable,
// 3. locate the call object in the CallTable (note that
// after step 2, the call object may be deleted from the
// CallTable by another thread),
// 4. lock the Call object (someone else may have the lock)
// 5. remove the call object from the CallTable,
// 6. unlock the CallTable
//
// The caller can now safely unlock and destroy the call object,
// since no other thread will be able to find the object (its been
// removed from the CallTable), and therefore no other thread will
// be able to lock it.
// Save the call handle; its the only way to look up
// the call object in the CallTable. Note that we
// can't use pCall to find the call object, since
// pCall may be free'd up, and another call object
// allocated at the same address
hCall = pCall->hCall;
// step 1
RelinquishLock(&pCall->Lock);
step2: // step 2
AcquireLock(&CallTable.Lock);
index = _Hash(hCall);
// step 3
pCall = CallTable.pHead[index]; while ((pCall != NULL) && (pCall->hCall != hCall)) pCall = pCall->pNextInTable;
if (pCall != NULL) { // step 4
AcquireTimedLock(&pCall->Lock,10,&bTimedOut); if (bTimedOut) { RelinquishLock(&CallTable.Lock); Sleep(0); goto step2; }
// step 5
if (pCall->pPrevInTable == NULL) CallTable.pHead[index] = pCall->pNextInTable; else pCall->pPrevInTable->pNextInTable = pCall->pNextInTable;
if (pCall->pNextInTable != NULL) pCall->pNextInTable->pPrevInTable = pCall->pPrevInTable;
pCall->pNextInTable = NULL; pCall->pPrevInTable = NULL; pCall->bInTable = FALSE; }
// step 6
RelinquishLock(&CallTable.Lock);
if (pCall == NULL) return CC_BAD_PARAM; else return CC_OK; }
HRESULT _MakeCallHandle( PCC_HCALL phCall) { AcquireLock(&CallHandle.Lock); *phCall = CallHandle.hCall++; RelinquishLock(&CallHandle.Lock); return CC_OK; }
HRESULT AllocAndLockCall( PCC_HCALL phCall, CC_HCONFERENCE hConference, HQ931CALL hQ931Call, HQ931CALL hQ931CallInvitor, PCC_ALIASNAMES pLocalAliasNames, PCC_ALIASNAMES pPeerAliasNames, PCC_ALIASNAMES pPeerExtraAliasNames, PCC_ALIASITEM pPeerExtension, PCC_NONSTANDARDDATA pLocalNonStandardData, PCC_NONSTANDARDDATA pPeerNonStandardData, PWSTR pszLocalDisplay, PWSTR pszPeerDisplay, PCC_VENDORINFO pPeerVendorInfo, PCC_ADDR pQ931LocalConnectAddr, PCC_ADDR pQ931PeerConnectAddr, PCC_ADDR pQ931DestinationAddr, PCC_ADDR pSourceCallSignalAddr, CALLTYPE CallType, BOOL bCallerIsMC, DWORD dwUserToken, CALLSTATE InitialCallState, DWORD dwBandwidth, PCC_CONFERENCEID pConferenceID, PPCALL ppCall) { HRESULT status; ASSERT(bCallInited == TRUE);
// all parameters should have been validated by the caller
ASSERT(phCall != NULL); ASSERT(ppCall != NULL); ASSERT(pConferenceID != NULL);
// set phCall now, in case we encounter an error
*phCall = CC_INVALID_HANDLE;
*ppCall = (PCALL)Malloc(sizeof(CALL)); if (*ppCall == NULL) return CC_NO_MEMORY;
memset(*ppCall, 0, sizeof(CALL)); (*ppCall)->bInTable = FALSE; (*ppCall)->hConference = hConference; (*ppCall)->hQ931Call = hQ931Call; (*ppCall)->hQ931CallInvitor = hQ931CallInvitor; (*ppCall)->pPeerParticipantInfo = NULL; (*ppCall)->bMarkedForDeletion = FALSE; (*ppCall)->H245Instance = H245_INVALID_ID; (*ppCall)->dwH245PhysicalID = 0; (*ppCall)->dwUserToken = dwUserToken; (*ppCall)->pLocalNonStandardData = NULL; (*ppCall)->pPeerNonStandardData = NULL; (*ppCall)->pQ931LocalConnectAddr = NULL; (*ppCall)->pQ931PeerConnectAddr = NULL; (*ppCall)->pQ931DestinationAddr = NULL; (*ppCall)->pszLocalDisplay = NULL; (*ppCall)->pszPeerDisplay = NULL; (*ppCall)->pPeerVendorInfo = NULL; (*ppCall)->pLocalAliasNames = NULL; (*ppCall)->pPeerAliasNames = NULL; (*ppCall)->pPeerExtraAliasNames = NULL; (*ppCall)->pPeerExtension = NULL; (*ppCall)->OutgoingTermCapState = NEED_TO_SEND_TERMCAP; (*ppCall)->IncomingTermCapState = AWAITING_TERMCAP; (*ppCall)->MasterSlaveState = MASTER_SLAVE_NOT_STARTED; (*ppCall)->pPeerH245TermCapList = NULL; (*ppCall)->pPeerH245H2250MuxCapability = NULL; (*ppCall)->pPeerH245TermCapDescriptors = NULL; (*ppCall)->CallState = InitialCallState; (*ppCall)->dwBandwidth = dwBandwidth; (*ppCall)->ConferenceID = *pConferenceID; (*ppCall)->CallType = CallType; (*ppCall)->bCallerIsMC = bCallerIsMC; (*ppCall)->bLinkEstablished = FALSE; (*ppCall)->pNext = NULL; (*ppCall)->pPrev = NULL; (*ppCall)->pNextInTable = NULL; (*ppCall)->pPrevInTable = NULL;
InitializeLock(&(*ppCall)->Lock); AcquireLock(&(*ppCall)->Lock);
status = _MakeCallHandle(&(*ppCall)->hCall); if (status != CC_OK) { FreeCall(*ppCall); return status; } // make a local copy of the local non-standard data, if supplied
status = CopyNonStandardData(&(*ppCall)->pLocalNonStandardData, pLocalNonStandardData); if (status != CC_OK) { FreeCall(*ppCall); return status; } // make a local copy of the peer's non-standard data, if supplied
status = CopyNonStandardData(&(*ppCall)->pPeerNonStandardData, pPeerNonStandardData); if (status != CC_OK) { FreeCall(*ppCall); return status; } // make a copy of the local connect address, if supplied
if (pQ931LocalConnectAddr != NULL) { (*ppCall)->pQ931LocalConnectAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR)); if ((*ppCall)->pQ931LocalConnectAddr == NULL) { FreeCall(*ppCall); return CC_NO_MEMORY; } *(*ppCall)->pQ931LocalConnectAddr = *pQ931LocalConnectAddr; }
// make a copy of the peer's connect address, if supplied
if (pQ931PeerConnectAddr != NULL) { (*ppCall)->pQ931PeerConnectAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR)); if ((*ppCall)->pQ931PeerConnectAddr == NULL) { FreeCall(*ppCall); return CC_NO_MEMORY; } *(*ppCall)->pQ931PeerConnectAddr = *pQ931PeerConnectAddr; }
// make a copy of the destination address, if supplied
if (pQ931DestinationAddr != NULL) { (*ppCall)->pQ931DestinationAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR)); if ((*ppCall)->pQ931DestinationAddr == NULL) { FreeCall(*ppCall); return CC_NO_MEMORY; } *(*ppCall)->pQ931DestinationAddr = *pQ931DestinationAddr; }
// make a copy of the source call signal address, if supplied
if (pSourceCallSignalAddr != NULL) { (*ppCall)->pSourceCallSignalAddr = (PCC_ADDR)Malloc(sizeof(CC_ADDR)); if ((*ppCall)->pSourceCallSignalAddr == NULL) { FreeCall(*ppCall); return CC_NO_MEMORY; } *(*ppCall)->pSourceCallSignalAddr = *pSourceCallSignalAddr; }
// make a local copy of the local alias names
status = Q931CopyAliasNames(&((*ppCall)->pLocalAliasNames), pLocalAliasNames); if (status != CS_OK) { FreeCall(*ppCall); return status; }
// make a local copy of the peer alias names
status = Q931CopyAliasNames(&((*ppCall)->pPeerAliasNames), pPeerAliasNames); if (status != CS_OK) { FreeCall(*ppCall); return status; }
// make a local copy of the peer extra alias names
status = Q931CopyAliasNames(&((*ppCall)->pPeerExtraAliasNames), pPeerExtraAliasNames); if (status != CS_OK) { FreeCall(*ppCall); return status; }
// make a local copy of the peer extension
status = Q931CopyAliasItem(&((*ppCall)->pPeerExtension), pPeerExtension); if (status != CS_OK) { FreeCall(*ppCall); return status; }
status = CopyDisplay(&(*ppCall)->pszLocalDisplay, pszLocalDisplay); if (status != CC_OK) { FreeCall(*ppCall); return status; }
status = CopyDisplay(&(*ppCall)->pszPeerDisplay, pszPeerDisplay); if (status != CC_OK) { FreeCall(*ppCall); return status; }
status = CopyVendorInfo(&(*ppCall)->pPeerVendorInfo, pPeerVendorInfo); if (status != CC_OK) { FreeCall(*ppCall); return status; }
*phCall = (*ppCall)->hCall;
// add the Call to the Call table
status = _AddCallToTable(*ppCall); if (status != CC_OK) FreeCall(*ppCall); return status; }
// Caller must have a lock on the Call object
HRESULT FreeCall( PCALL pCall) { HRESULT status; CC_HCALL hCall; PCONFERENCE pConference;
ASSERT(pCall != NULL);
#ifdef GATEKEEPER
if (pCall->GkiCall.uGkiCallState != 0) GkiCloseCall(&pCall->GkiCall); #endif // GATEKEEPER
// caller must have a lock on the Call object,
// so there's no need to re-lock it
hCall = pCall->hCall; if (pCall->hConference != CC_INVALID_HANDLE) { UnlockCall(pCall); status = _LockCallAndConferenceMarkedForDeletion(hCall, &pCall, &pConference); if (status != CC_OK) return status; }
if (pCall->bInTable == TRUE) if (_RemoveCallFromTable(pCall) == CC_BAD_PARAM) // the Call object was deleted by another thread,
// so just return CC_OK
return CC_OK;
if (pCall->pPeerParticipantInfo != NULL) { if (pCall->CallType == VIRTUAL_CALL) FreePeerParticipantInfo(NULL, pCall->pPeerParticipantInfo); else FreePeerParticipantInfo(pConference, pCall->pPeerParticipantInfo); }
// If the call object is associated with a conference object, deassociate it.
if (pCall->hConference != CC_INVALID_HANDLE) { RemoveCallFromConference(pCall, pConference); UnlockConference(pConference); }
if (pCall->pLocalNonStandardData != NULL) FreeNonStandardData(pCall->pLocalNonStandardData);
if (pCall->pPeerNonStandardData != NULL) FreeNonStandardData(pCall->pPeerNonStandardData);
if (pCall->pQ931LocalConnectAddr != NULL) Free(pCall->pQ931LocalConnectAddr);
if (pCall->pQ931PeerConnectAddr != NULL) Free(pCall->pQ931PeerConnectAddr);
if (pCall->pQ931DestinationAddr != NULL) Free(pCall->pQ931DestinationAddr);
if (pCall->pSourceCallSignalAddr != NULL) Free(pCall->pSourceCallSignalAddr);
if (pCall->pPeerH245TermCapList != NULL) DestroyH245TermCapList(&(pCall->pPeerH245TermCapList));
if (pCall->pPeerH245H2250MuxCapability != NULL) DestroyH245TermCap(&(pCall->pPeerH245H2250MuxCapability));
if (pCall->pPeerH245TermCapDescriptors != NULL) DestroyH245TermCapDescriptors(&(pCall->pPeerH245TermCapDescriptors));
if (pCall->pLocalAliasNames != NULL) Q931FreeAliasNames(pCall->pLocalAliasNames);
if (pCall->pPeerAliasNames != NULL) Q931FreeAliasNames(pCall->pPeerAliasNames);
if (pCall->pPeerExtraAliasNames != NULL) Q931FreeAliasNames(pCall->pPeerExtraAliasNames); if (pCall->pPeerExtension != NULL) Q931FreeAliasItem(pCall->pPeerExtension);
if (pCall->pszLocalDisplay != NULL) FreeDisplay(pCall->pszLocalDisplay);
if (pCall->pszPeerDisplay != NULL) FreeDisplay(pCall->pszPeerDisplay);
if (pCall->pPeerVendorInfo != NULL) FreeVendorInfo(pCall->pPeerVendorInfo);
#ifdef GATEKEEPER
if (pCall->GkiCall.uGkiCallState != 0) GkiFreeCall(&pCall->GkiCall); #endif // GATEKEEPER
// Since the call object has been removed from the CallTable,
// no other thread will be able to find the call object and obtain
// a lock, so its safe to unlock the call object and delete it here
RelinquishLock(&pCall->Lock); DeleteLock(&pCall->Lock); Free(pCall); return CC_OK; }
HRESULT _LockQ931CallMarkedForDeletion( CC_HCALL hCall, HQ931CALL hQ931Call, PPCALL ppCall) { int index; BOOL bTimedOut;
// If hCall != CC_INVALID_HANDLE, the search is based on hCall;
// otherwise, the search is based on hQ931Call
ASSERT(ppCall != NULL);
step1: AcquireLock(&CallTable.Lock);
if (hCall != CC_INVALID_HANDLE) { index = _Hash(hCall);
*ppCall = CallTable.pHead[index]; while ((*ppCall != NULL) && ((*ppCall)->hCall != hCall)) *ppCall = (*ppCall)->pNextInTable; } else { // Perform an exhaustive search based on hQ931Call
for (index = 0; index < HASH_TABLE_SIZE; index++) { *ppCall = CallTable.pHead[index]; while ((*ppCall != NULL) && ((*ppCall)->hQ931Call != hQ931Call)) *ppCall = (*ppCall)->pNextInTable; if (*ppCall != NULL) break; } }
if (*ppCall != NULL) { AcquireTimedLock(&(*ppCall)->Lock,10,&bTimedOut); if (bTimedOut) { RelinquishLock(&CallTable.Lock); Sleep(0); goto step1; } }
RelinquishLock(&CallTable.Lock);
if (*ppCall == NULL) return CC_BAD_PARAM; else return CC_OK; }
HRESULT LockQ931Call( CC_HCALL hCall, HQ931CALL hQ931Call, PPCALL ppCall) { HRESULT status;
status = _LockQ931CallMarkedForDeletion(hCall, hQ931Call, ppCall); if (status != CC_OK) return status; if ((*ppCall)->bMarkedForDeletion) { UnlockCall(*ppCall); return CC_BAD_PARAM; } return CC_OK; }
HRESULT LockCall( CC_HCALL hCall, PPCALL ppCall) { ASSERT(hCall != CC_INVALID_HANDLE); ASSERT(ppCall != NULL);
return LockQ931Call(hCall, // Call Control call handle (used in this call)
0, // Q931 call handle (ignored in this call)
ppCall); }
HRESULT _LockCallMarkedForDeletion( CC_HCALL hCall, PPCALL ppCall) { ASSERT(hCall != CC_INVALID_HANDLE); ASSERT(ppCall != NULL);
return _LockQ931CallMarkedForDeletion(hCall, // Call Control call handle (used in this call)
0, // Q931 call handle (ignored in this call)
ppCall); }
HRESULT LockCallAndConference( CC_HCALL hCall, PPCALL ppCall, PPCONFERENCE ppConference) { HRESULT status; CC_HCONFERENCE hConference;
ASSERT(hCall != CC_INVALID_HANDLE); ASSERT(ppCall != NULL); ASSERT(ppConference != NULL);
status = LockCall(hCall, ppCall); if (status != CC_OK) return status; if ((*ppCall)->hConference == CC_INVALID_HANDLE) { UnlockCall(*ppCall); return CC_BAD_PARAM; }
hConference = (*ppCall)->hConference; UnlockCall(*ppCall);
status = LockConference(hConference, ppConference); if (status != CC_OK) return status;
status = LockCall(hCall, ppCall); if (status != CC_OK) { UnlockConference(*ppConference); return status; } return CC_OK; }
HRESULT _LockCallAndConferenceMarkedForDeletion( CC_HCALL hCall, PPCALL ppCall, PPCONFERENCE ppConference) { HRESULT status; CC_HCONFERENCE hConference;
ASSERT(hCall != CC_INVALID_HANDLE); ASSERT(ppCall != NULL); ASSERT(ppConference != NULL);
status = _LockCallMarkedForDeletion(hCall, ppCall); if (status != CC_OK) return status; if ((*ppCall)->hConference == CC_INVALID_HANDLE) { UnlockCall(*ppCall); return CC_BAD_PARAM; }
hConference = (*ppCall)->hConference; UnlockCall(*ppCall);
status = LockConference(hConference, ppConference); if (status != CC_OK) return status;
status = _LockCallMarkedForDeletion(hCall, ppCall); if (status != CC_OK) { UnlockConference(*ppConference); return status; } return CC_OK; }
HRESULT MarkCallForDeletion( PCALL pCall) { ASSERT(pCall != NULL); ASSERT(pCall->bMarkedForDeletion == FALSE);
pCall->bMarkedForDeletion = TRUE; return CC_OK; }
HRESULT ValidateCall( CC_HCALL hCall) { PCALL pCall; int index;
ASSERT(hCall != CC_INVALID_HANDLE);
AcquireLock(&CallTable.Lock);
index = _Hash(hCall);
pCall = CallTable.pHead[index]; while ((pCall != NULL) && (pCall->hCall != hCall)) pCall = pCall->pNextInTable;
if (pCall != NULL) if (pCall->bMarkedForDeletion == TRUE) pCall = NULL;
RelinquishLock(&CallTable.Lock);
if (pCall == NULL) return CC_BAD_PARAM; else return CC_OK; }
HRESULT ValidateCallMarkedForDeletion( CC_HCALL hCall) { PCALL pCall; int index;
ASSERT(hCall != CC_INVALID_HANDLE);
AcquireLock(&CallTable.Lock);
index = _Hash(hCall);
pCall = CallTable.pHead[index]; while ((pCall != NULL) && (pCall->hCall != hCall)) pCall = pCall->pNextInTable;
RelinquishLock(&CallTable.Lock);
if (pCall == NULL) return CC_BAD_PARAM; else return CC_OK; }
HRESULT UnlockCall( PCALL pCall) { ASSERT(pCall != NULL);
RelinquishLock(&pCall->Lock); return CC_OK; }
HRESULT AddLocalNonStandardDataToCall( PCALL pCall, PCC_NONSTANDARDDATA pLocalNonStandardData) { HRESULT status;
ASSERT(pCall != NULL);
if (pCall->pLocalNonStandardData != NULL) FreeNonStandardData(pCall->pLocalNonStandardData); status = CopyNonStandardData(&pCall->pLocalNonStandardData, pLocalNonStandardData); return status; }
HRESULT AddLocalDisplayToCall( PCALL pCall, PWSTR pszLocalDisplay) { HRESULT status;
ASSERT(pCall != NULL);
if (pCall->pszLocalDisplay != NULL) FreeDisplay(pCall->pszLocalDisplay); status = CopyDisplay(&pCall->pszLocalDisplay, pszLocalDisplay); return status; }
HRESULT AllocatePeerParticipantInfo(PCONFERENCE pConference, PPARTICIPANTINFO *ppPeerParticipantInfo) { HRESULT status; H245_TERMINAL_LABEL_T H245TerminalLabel;
ASSERT(ppPeerParticipantInfo != NULL);
if (pConference == NULL) { H245TerminalLabel.mcuNumber = 0; H245TerminalLabel.terminalNumber = 0; } else { status = AllocateTerminalNumber(pConference, &H245TerminalLabel); if (status != CC_OK) { *ppPeerParticipantInfo = NULL; return status; } }
*ppPeerParticipantInfo = (PPARTICIPANTINFO)Malloc(sizeof(PARTICIPANTINFO)); if (*ppPeerParticipantInfo == NULL) return CC_NO_MEMORY;
(*ppPeerParticipantInfo)->TerminalIDState = TERMINAL_ID_INVALID; (*ppPeerParticipantInfo)->ParticipantInfo.TerminalLabel.bMCUNumber = (BYTE)H245TerminalLabel.mcuNumber; (*ppPeerParticipantInfo)->ParticipantInfo.TerminalLabel.bTerminalNumber = (BYTE)H245TerminalLabel.terminalNumber; (*ppPeerParticipantInfo)->ParticipantInfo.TerminalID.pOctetString = NULL; (*ppPeerParticipantInfo)->ParticipantInfo.TerminalID.wOctetStringLength = 0; (*ppPeerParticipantInfo)->pEnqueuedRequestsForTerminalID = NULL;
return CC_OK; }
HRESULT FreePeerParticipantInfo( PCONFERENCE pConference, PPARTICIPANTINFO pPeerParticipantInfo) { HRESULT status = CC_OK;
ASSERT(pPeerParticipantInfo != NULL);
if (pConference != NULL) status = FreeTerminalNumber(pConference, pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber);
while (DequeueRequest(&pPeerParticipantInfo->pEnqueuedRequestsForTerminalID, NULL) == CC_OK);
if (pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString != NULL) Free(pPeerParticipantInfo->ParticipantInfo.TerminalID.pOctetString); Free(pPeerParticipantInfo); return status; }
#ifdef GATEKEEPER
HRESULT LockGkiCallAndConference( HANDLE hGkiCall, PGKICALL * ppGkiCall, void * * ppConference, DWORD * phCall, DWORD * phConference) { unsigned int uIndex; PCALL pCall; PCONFERENCE pConference; CC_HCONFERENCE hConference; BOOL bTimedOut; ASSERT(hGkiCall != 0); ASSERT(ppGkiCall != NULL); ASSERT(ppConference != NULL); ASSERT(phCall != NULL); ASSERT(phConference != NULL);
step1: AcquireLock(&CallTable.Lock);
// Perform an exhaustive search based on hGkiCall
for (uIndex = 0; uIndex < HASH_TABLE_SIZE; ++uIndex) { pCall = CallTable.pHead[uIndex]; while (pCall) { if (pCall->GkiCall.hGkiCall == hGkiCall) { AcquireTimedLock(&pCall->Lock,10,&bTimedOut); if (bTimedOut) { RelinquishLock(&CallTable.Lock); Sleep(0); goto step1; } hConference = pCall->hConference; if (pCall->bMarkedForDeletion || hConference == CC_INVALID_HANDLE) { RelinquishLock(&pCall->Lock); RelinquishLock(&CallTable.Lock); return CC_BAD_PARAM; } RelinquishLock(&pCall->Lock); if (LockConference(hConference, &pConference) != CC_OK) { RelinquishLock(&CallTable.Lock); return CC_BAD_PARAM; } AcquireLock(&pCall->Lock); *ppGkiCall = &pCall->GkiCall; *ppConference = (void *)pConference; *phCall = pCall->hCall; *phConference = pCall->hConference; RelinquishLock(&CallTable.Lock); return NOERROR; } pCall = pCall->pNextInTable; } // while
}
RelinquishLock(&CallTable.Lock); return CC_BAD_PARAM; } // LockGkiCallAndConference()
HRESULT UnlockGkiCallAndConference( PGKICALL pGkiCall, void * pConference, DWORD hCall, DWORD hConference) { if (ValidateConference(hConference) == CC_OK) UnlockConference((PCONFERENCE)pConference); if (ValidateCall(hCall) == CC_OK) UnlockCall(pGkiCall->pCall); return NOERROR; } // UnlockGkiCallAndConference()
HRESULT LockGkiCall(HANDLE hGkiCall, PPGKICALL ppGkiCall) { unsigned int uIndex; PCALL pCall; BOOL bTimedOut;
ASSERT(hGkiCall != 0); ASSERT(ppGkiCall != NULL);
step1: AcquireLock(&CallTable.Lock);
// Perform an exhaustive search based on hGkiCall
for (uIndex = 0; uIndex < HASH_TABLE_SIZE; ++uIndex) { pCall = CallTable.pHead[uIndex]; while (pCall) { if (pCall->GkiCall.hGkiCall == hGkiCall) { AcquireTimedLock(&pCall->Lock,10,&bTimedOut); if (bTimedOut) { RelinquishLock(&CallTable.Lock); Sleep(0); goto step1; } if (pCall->bMarkedForDeletion) { RelinquishLock(&pCall->Lock); *ppGkiCall = NULL; RelinquishLock(&CallTable.Lock); return CC_BAD_PARAM; } *ppGkiCall = &pCall->GkiCall; RelinquishLock(&CallTable.Lock); return NOERROR; } pCall = pCall->pNextInTable; } // while
}
*ppGkiCall = NULL; RelinquishLock(&CallTable.Lock); return CC_BAD_PARAM; } // LockGkiCall()
HRESULT UnlockGkiCall(PGKICALL pGkiCall) { return UnlockCall(pGkiCall->pCall); } // UnlockGkiCall()
HRESULT ApplyToAllCalls(PGKICALLFUN pGkiCallFun) { unsigned uIndex; PCALL pCall; DWORD hCall; PCONFERENCE pConference; DWORD hConference; HRESULT status; BOOL bTimedOut;
step1: AcquireLock(&CallTable.Lock);
// Apply pGkiCallFun to all calls in table
for (uIndex = 0; uIndex < HASH_TABLE_SIZE; ++uIndex) { pCall = CallTable.pHead[uIndex]; while (pCall) { AcquireTimedLock(&pCall->Lock,10,&bTimedOut); if (bTimedOut) { RelinquishLock(&CallTable.Lock); Sleep(0); goto step1; } hConference = pCall->hConference; if (pCall->bMarkedForDeletion || hConference == CC_INVALID_HANDLE) { RelinquishLock(&pCall->Lock); } else { RelinquishLock(&pCall->Lock); if (LockConference(hConference, &pConference) == CC_OK) { AcquireLock(&pCall->Lock); hCall = pCall->hCall; status = pGkiCallFun(&pCall->GkiCall, pConference); if (ValidateConference(hConference) == NOERROR) UnlockConference(pConference); if (ValidateCall(hCall) != NOERROR) { // Call was deleted
RelinquishLock(&CallTable.Lock); if (status != NOERROR) return status; // Start all over again
goto step1; } RelinquishLock(&pCall->Lock); if (status != NOERROR) { RelinquishLock(&CallTable.Lock); return status; } } } pCall = pCall->pNextInTable; } // while
}
RelinquishLock(&CallTable.Lock); return NOERROR; } // ApplyToAllCalls()
#endif // GATEKEEPER
|