windows-nt/Source/XPSP1/NT/net/tapi/skywalker/cc/callcont/callman.c

1090 lines
26 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/****************************************************************************
*
* $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