|
|
/****************************************************************************
* * $Archive: S:/STURGEON/SRC/CALLCONT/VCS/ccutils.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.107 $ * $Date: 04 Mar 1997 17:34:44 $ * $Author: MANDREWS $ * * Deliverable: * * Abstract: * * * Notes: * ***************************************************************************/
#include "precomp.h"
#include "incommon.h"
#include "callcont.h"
#include "q931.h"
#include "apierror.h"
#include "ccmain.h"
#include "chanman.h"
#include "confman.h"
#include "callman.h"
#include "q931man.h"
#include "userman.h"
#include "ccutils.h"
#include "linkapi.h"
#include "h245man.h"
extern CC_CONFERENCEID InvalidConferenceID;
HANDLE ghCCLock = NULL; HRESULT InitializeCCLock(VOID) { ASSERT(ghCCLock == NULL); ghCCLock = CreateMutex(NULL, FALSE, NULL); if(ghCCLock == NULL) { return CC_INTERNAL_ERROR; } else { return CC_OK; } } VOID UnInitializeCCLock() { ASSERT(ghCCLock); if(ghCCLock) { CloseHandle(ghCCLock); } }
VOID CCLOCK_AcquireLock() { DWORD dwStatus; ASSERT(ghCCLock); dwStatus = WaitForSingleObject(ghCCLock, INFINITE);
if ((dwStatus != WAIT_OBJECT_0) && (dwStatus != WAIT_TIMEOUT)) { ASSERT(0); } }
VOID CCLOCK_RelinquishLock() { ASSERT(ghCCLock); ReleaseMutex(ghCCLock); }
HRESULT InitializeLock( PLOCK pLock) { ASSERT(pLock != NULL);
#ifdef _DEBUG
InitializeCriticalSection(&pLock->LockInfoLock); pLock->wLockCount = 0; pLock->wNumQueuedThreads = 0; pLock->hOwningThread = 0; #endif
pLock->Lock = CreateMutex(NULL, // security attributes
FALSE, // initial owner
NULL); // name
if (pLock->Lock == NULL) { #ifdef _DEBUG
DeleteCriticalSection(&pLock->LockInfoLock); #endif
return CC_INTERNAL_ERROR; } else return CC_OK; }
HRESULT DeleteLock( PLOCK pLock) { ASSERT(pLock != NULL);
#ifdef _DEBUG
DeleteCriticalSection(&pLock->LockInfoLock); #endif
if (CloseHandle(pLock->Lock) == TRUE) return CC_OK; else return CC_INTERNAL_ERROR; }
HRESULT AcquireLock( PLOCK pLock) { HRESULT status;
ASSERT(pLock != NULL); status = AcquireTimedLock(pLock, INFINITE, NULL); return status; }
HRESULT AcquireTimedLock( PLOCK pLock, DWORD dwTimeout, BOOL *pbTimedOut) { DWORD dwStatus;
ASSERT(pLock != NULL);
#ifdef _DEBUG
EnterCriticalSection(&pLock->LockInfoLock); (pLock->wNumQueuedThreads)++; LeaveCriticalSection(&pLock->LockInfoLock); #endif
dwStatus = WaitForSingleObject(pLock->Lock, dwTimeout);
#ifdef _DEBUG
EnterCriticalSection(&pLock->LockInfoLock); (pLock->wNumQueuedThreads)--; (pLock->wLockCount)++; pLock->hOwningThread = GetCurrentThread(); LeaveCriticalSection(&pLock->LockInfoLock); #endif
if ((dwStatus != WAIT_OBJECT_0) && (dwStatus != WAIT_TIMEOUT)) return CC_INTERNAL_ERROR;
if (dwStatus == WAIT_TIMEOUT) { if (pbTimedOut != NULL) { *pbTimedOut = TRUE; } } else { if (pbTimedOut != NULL) { *pbTimedOut = FALSE; } } return CC_OK; }
HRESULT RelinquishLock( PLOCK pLock) { ASSERT(pLock != NULL);
#ifdef _DEBUG
EnterCriticalSection(&pLock->LockInfoLock); (pLock->wLockCount)--; if (pLock->wLockCount == 0) pLock->hOwningThread = 0; LeaveCriticalSection(&pLock->LockInfoLock); #endif
if (ReleaseMutex(pLock->Lock) == TRUE) return CC_OK; else return CC_INTERNAL_ERROR; }
HRESULT ValidateOctetString( PCC_OCTETSTRING pOctetString) { if (pOctetString == NULL) return CC_OK; if ((pOctetString->wOctetStringLength > 0) && (pOctetString->pOctetString == NULL)) return CC_BAD_PARAM; return CC_OK; }
HRESULT CopyOctetString( PCC_OCTETSTRING *ppDest, PCC_OCTETSTRING pSource) { ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; } *ppDest = (PCC_OCTETSTRING)MemAlloc(sizeof(CC_OCTETSTRING)); if (*ppDest == NULL) return CC_NO_MEMORY; (*ppDest)->wOctetStringLength = pSource->wOctetStringLength; if ((pSource->wOctetStringLength == 0) || (pSource->pOctetString == NULL)) { pSource->wOctetStringLength = 0; (*ppDest)->pOctetString = NULL; } else { (*ppDest)->pOctetString = (BYTE *)MemAlloc(pSource->wOctetStringLength); if ((*ppDest)->pOctetString == NULL) { MemFree(*ppDest); *ppDest = NULL; return CC_NO_MEMORY; } memcpy((*ppDest)->pOctetString, pSource->pOctetString, pSource->wOctetStringLength); } return CC_OK; }
HRESULT FreeOctetString( PCC_OCTETSTRING pOctetString) { if (pOctetString == NULL) return CC_OK; if ((pOctetString->wOctetStringLength > 0) && (pOctetString->pOctetString != NULL)) MemFree(pOctetString->pOctetString); MemFree(pOctetString); return CC_OK; }
HRESULT CopySeparateStack( H245_ACCESS_T **ppDest, H245_ACCESS_T *pSource) { ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; }
// We currently can't handle IP source route addresses,
// since this address format contains embedded pointers
// that cannot simply be copied
if ((pSource->networkAddress.choice == localAreaAddress_chosen) && (pSource->networkAddress.u.localAreaAddress.choice == unicastAddress_chosen) && (pSource->networkAddress.u.localAreaAddress.u.unicastAddress.choice == iPSourceRouteAddress_chosen)) return CC_NOT_IMPLEMENTED;
*ppDest = (H245_ACCESS_T *)MemAlloc(sizeof(H245_ACCESS_T)); if (*ppDest == NULL) return CC_NO_MEMORY;
**ppDest = *pSource; return CC_OK; }
HRESULT FreeSeparateStack( H245_ACCESS_T *pSeparateStack) { if (pSeparateStack == NULL) return CC_OK; MemFree(pSeparateStack); return CC_OK; }
HRESULT ValidateNonStandardData( PCC_NONSTANDARDDATA pNonStandardData) { if (pNonStandardData == NULL) return CC_OK; return ValidateOctetString(&pNonStandardData->sData); }
HRESULT CopyNonStandardData( PCC_NONSTANDARDDATA *ppDest, PCC_NONSTANDARDDATA pSource) { ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; } *ppDest = (PCC_NONSTANDARDDATA)MemAlloc(sizeof(CC_NONSTANDARDDATA)); if (*ppDest == NULL) return CC_NO_MEMORY; **ppDest = *pSource; if ((pSource->sData.wOctetStringLength == 0) || (pSource->sData.pOctetString == NULL)) { (*ppDest)->sData.wOctetStringLength = 0; (*ppDest)->sData.pOctetString = NULL; } else { (*ppDest)->sData.pOctetString = (BYTE *)MemAlloc(pSource->sData.wOctetStringLength); if ((*ppDest)->sData.pOctetString == NULL) { MemFree(*ppDest); return CC_NO_MEMORY; } memcpy((*ppDest)->sData.pOctetString, pSource->sData.pOctetString, pSource->sData.wOctetStringLength); } return CC_OK; }
HRESULT FreeNonStandardData( PCC_NONSTANDARDDATA pNonStandardData) { if (pNonStandardData == NULL) return CC_OK; if ((pNonStandardData->sData.wOctetStringLength > 0) && (pNonStandardData->sData.pOctetString != NULL)) MemFree(pNonStandardData->sData.pOctetString); MemFree(pNonStandardData); return CC_OK; }
HRESULT ValidateVendorInfo( PCC_VENDORINFO pVendorInfo) { HRESULT status;
if (pVendorInfo == NULL) return CC_OK; status = ValidateOctetString(pVendorInfo->pProductNumber); if (status != CC_OK) return status; status = ValidateOctetString(pVendorInfo->pVersionNumber); return status; }
HRESULT CopyVendorInfo( PCC_VENDORINFO *ppDest, PCC_VENDORINFO pSource) { HRESULT status;
ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; } *ppDest = (PCC_VENDORINFO)MemAlloc(sizeof(CC_VENDORINFO)); if (*ppDest == NULL) return CC_NO_MEMORY; **ppDest = *pSource; status = CopyOctetString(&(*ppDest)->pProductNumber, pSource->pProductNumber); if (status != CC_OK) { MemFree(*ppDest); return status; } status = CopyOctetString(&(*ppDest)->pVersionNumber, pSource->pVersionNumber); if (status != CC_OK) { FreeOctetString((*ppDest)->pProductNumber); MemFree(*ppDest); return status; } return CC_OK; }
HRESULT FreeVendorInfo( PCC_VENDORINFO pVendorInfo) { if (pVendorInfo == NULL) return CC_OK; FreeOctetString(pVendorInfo->pProductNumber); FreeOctetString(pVendorInfo->pVersionNumber); MemFree(pVendorInfo); return CC_OK; }
BOOL EqualConferenceIDs( PCC_CONFERENCEID pConferenceID1, PCC_CONFERENCEID pConferenceID2) { ASSERT(pConferenceID1 != NULL); ASSERT(pConferenceID2 != NULL);
if (memcmp(pConferenceID1->buffer, pConferenceID2->buffer, sizeof(pConferenceID1->buffer)) == 0) return TRUE; else return FALSE; }
BOOL EqualAddrs( PCC_ADDR pAddr1, PCC_ADDR pAddr2) { ASSERT(pAddr1 != NULL); ASSERT(pAddr2 != NULL);
if (pAddr1->nAddrType != pAddr2->nAddrType) return FALSE;
if (pAddr1->bMulticast != pAddr2->bMulticast) return FALSE;
switch (pAddr1->nAddrType) { case CC_IP_DOMAIN_NAME: if ((pAddr1->Addr.IP_DomainName.wPort == pAddr2->Addr.IP_DomainName.wPort) && (wcscmp(pAddr1->Addr.IP_DomainName.cAddr, pAddr2->Addr.IP_DomainName.cAddr) == 0)) return TRUE; else return FALSE; case CC_IP_DOT: if ((pAddr1->Addr.IP_Dot.wPort == pAddr2->Addr.IP_Dot.wPort) && (wcscmp(pAddr1->Addr.IP_Dot.cAddr, pAddr2->Addr.IP_Dot.cAddr) == 0)) return TRUE; else return FALSE; case CC_IP_BINARY: if ((pAddr1->Addr.IP_Binary.wPort == pAddr2->Addr.IP_Binary.wPort) && (pAddr1->Addr.IP_Binary.dwAddr == pAddr2->Addr.IP_Binary.dwAddr)) return TRUE; else return FALSE; default: ASSERT(0); return FALSE; } }
HRESULT ValidateTermCapList( PCC_TERMCAPLIST pTermCapList) { unsigned i, j;
if (pTermCapList == NULL) return CC_OK;
for (i = 0; i < pTermCapList->wLength; i++) if (pTermCapList->pTermCapArray[i] == NULL) return CC_BAD_PARAM;
// make sure that all capability IDs are unique
for (i = 0; i < pTermCapList->wLength; i++) { for (j = i + 1; j < pTermCapList->wLength; j++) { if (pTermCapList->pTermCapArray[i]->CapId == pTermCapList->pTermCapArray[j]->CapId) return CC_BAD_PARAM; } if ((pTermCapList->pTermCapArray[i]->CapId == H245_INVALID_CAPID) || (pTermCapList->pTermCapArray[i]->CapId == 0)) return CC_BAD_PARAM; } return CC_OK; }
HRESULT ValidateTermCapDescriptors( PCC_TERMCAPDESCRIPTORS pTermCapDescriptors, PCC_TERMCAPLIST pTermCapList) { WORD i, j, k, l; H245_TOTCAPDESC_T *pTermCapDescriptor; H245_SIMCAP_T *pSimCaps;
if (pTermCapDescriptors == NULL) return CC_OK;
for (i = 0; i < pTermCapDescriptors->wLength; i++) { pTermCapDescriptor = pTermCapDescriptors->pTermCapDescriptorArray[i]; if ((pTermCapDescriptor->CapDescId > 255) || (pTermCapDescriptor->CapDesc.Length == 0) || (pTermCapDescriptor->CapDesc.Length > H245_MAX_SIMCAPS)) return CC_BAD_PARAM; for (j = i + 1; j < pTermCapDescriptors->wLength; j++) { if (pTermCapDescriptor->CapDescId == pTermCapDescriptors->pTermCapDescriptorArray[j]->CapDescId) { return CC_BAD_PARAM; } } for (j = 0; j < pTermCapDescriptor->CapDesc.Length; j++) { pSimCaps = &(pTermCapDescriptor->CapDesc.SimCapArray[j]); if ((pSimCaps->Length == 0) || (pSimCaps->Length > H245_MAX_ALTCAPS)) return CC_BAD_PARAM; for (k = 0; k < pSimCaps->Length; k++) { for (l = 0; l < pTermCapList->wLength; l++) { if (pSimCaps->AltCaps[k] == pTermCapList->pTermCapArray[l]->CapId) break; } if (l == pTermCapList->wLength) // the capability descriptor contains a capability ID
// which is not present in the capability table
return CC_BAD_PARAM; } } } return CC_OK; }
HRESULT ValidateAddr( PCC_ADDR pAddr) { if (pAddr == NULL) return CC_OK; if ((pAddr->nAddrType != CC_IP_DOMAIN_NAME) && (pAddr->nAddrType != CC_IP_DOT) && (pAddr->nAddrType != CC_IP_BINARY)) return CC_BAD_PARAM; return CC_OK; }
HRESULT CopyAddr( PCC_ADDR *ppDest, PCC_ADDR pSource) { ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; } *ppDest = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR)); if (*ppDest == NULL) return CC_NO_MEMORY; **ppDest = *pSource; return CC_OK; }
HRESULT FreeAddr( PCC_ADDR pAddr) { if (pAddr == NULL) return CC_OK; MemFree(pAddr); return CC_OK; }
HRESULT SetQ931Port( PCC_ADDR pAddr) { if (pAddr == NULL) return CC_OK; switch (pAddr->nAddrType) { case CC_IP_DOMAIN_NAME: if (pAddr->Addr.IP_DomainName.wPort == 0) pAddr->Addr.IP_DomainName.wPort = CC_H323_HOST_CALL; return CC_OK; case CC_IP_DOT: if (pAddr->Addr.IP_Dot.wPort == 0) pAddr->Addr.IP_Dot.wPort = CC_H323_HOST_CALL; return CC_OK; case CC_IP_BINARY: if (pAddr->Addr.IP_Binary.wPort == 0) pAddr->Addr.IP_Binary.wPort = CC_H323_HOST_CALL; return CC_OK; }
ASSERT(0); return CC_INTERNAL_ERROR; }
HRESULT ValidateDisplay( PWSTR pszDisplay) { return CC_OK; }
HRESULT CopyDisplay( PWSTR *ppDest, PWSTR pSource) { ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; } *ppDest = (WCHAR *)MemAlloc((wcslen(pSource)+1)*sizeof(WCHAR)); if (*ppDest == NULL) return CC_NO_MEMORY; wcscpy(*ppDest, pSource); return CC_OK; }
HRESULT FreeDisplay( PWSTR pszDisplay) { MemFree(pszDisplay); return CC_OK; }
HRESULT ValidateTerminalID( PCC_OCTETSTRING pTerminalID) { return ValidateOctetString(pTerminalID); }
HRESULT CopyTerminalID( PCC_OCTETSTRING *ppDest, PCC_OCTETSTRING pSource) { ASSERT(ppDest != NULL);
return CopyOctetString(ppDest, pSource); }
HRESULT FreeTerminalID( PCC_OCTETSTRING pTerminalID) { return FreeOctetString(pTerminalID); }
HRESULT SetTerminalType( TRISTATE tsMultipointController, BYTE *pbTerminalType) { switch (tsMultipointController) { case TS_TRUE: *pbTerminalType = 240; break; case TS_UNKNOWN: *pbTerminalType = 70; break; case TS_FALSE: *pbTerminalType = 50; break; default: ASSERT(0); *pbTerminalType = 0; break; } return CC_OK; }
HRESULT CopyH245TermCapList( PCC_TERMCAPLIST *ppDest, PCC_TERMCAPLIST pSource) { WORD i; HRESULT status;
ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; }
*ppDest = (PCC_TERMCAPLIST)MemAlloc(sizeof(CC_TERMCAPLIST)); if (*ppDest == NULL) return CC_NO_MEMORY;
(*ppDest)->wLength = pSource->wLength; (*ppDest)->pTermCapArray = (PPCC_TERMCAP)MemAlloc(sizeof(PCC_TERMCAP) * pSource->wLength); if ((*ppDest)->pTermCapArray == NULL) { (*ppDest)->wLength = 0; DestroyH245TermCapList(ppDest); return CC_NO_MEMORY; } for (i = 0; i < pSource->wLength; i++) { status = H245CopyCap(&((*ppDest)->pTermCapArray[i]), pSource->pTermCapArray[i]); if (status != H245_ERROR_OK) { (*ppDest)->wLength = i; DestroyH245TermCapList(ppDest); return status; } } return CC_OK; }
HRESULT CopyH245TermCapDescriptors( PCC_TERMCAPDESCRIPTORS *ppDest, PCC_TERMCAPDESCRIPTORS pSource) { WORD i; HRESULT status;
ASSERT(ppDest != NULL);
if (pSource == NULL) { *ppDest = NULL; return CC_OK; }
(*ppDest) = (PCC_TERMCAPDESCRIPTORS)MemAlloc(sizeof(CC_TERMCAPDESCRIPTORS)); if (*ppDest == NULL) return CC_NO_MEMORY;
(*ppDest)->wLength = pSource->wLength; (*ppDest)->pTermCapDescriptorArray = (H245_TOTCAPDESC_T **)MemAlloc(sizeof(H245_TOTCAPDESC_T *) * pSource->wLength); if ((*ppDest)->pTermCapDescriptorArray == NULL) { (*ppDest)->wLength = 0; DestroyH245TermCapDescriptors(ppDest); return CC_NO_MEMORY; }
for (i = 0; i < pSource->wLength; i++) { status = H245CopyCapDescriptor(&((*ppDest)->pTermCapDescriptorArray[i]), pSource->pTermCapDescriptorArray[i]); if (status != H245_ERROR_OK) { (*ppDest)->wLength = i; DestroyH245TermCapDescriptors(ppDest); return status; } } return CC_OK; }
HRESULT CreateH245DefaultTermCapDescriptors( PCC_TERMCAPDESCRIPTORS *ppDest, PCC_TERMCAPLIST pTermCapList) { H245_TOTCAPDESC_T TermCapDescriptor; WORD i; HRESULT status;
ASSERT(ppDest != NULL);
if (pTermCapList == NULL) { *ppDest = NULL; return CC_OK; }
*ppDest = (PCC_TERMCAPDESCRIPTORS)MemAlloc(sizeof(CC_TERMCAPDESCRIPTORS)); if (*ppDest == NULL) return CC_NO_MEMORY;
if (pTermCapList->wLength == 0) { (*ppDest)->wLength = 0; (*ppDest)->pTermCapDescriptorArray = NULL; return CC_OK; }
(*ppDest)->wLength = 1; (*ppDest)->pTermCapDescriptorArray = (H245_TOTCAPDESC_T **)MemAlloc(sizeof(H245_TOTCAPDESC_T *)); if ((*ppDest)->pTermCapDescriptorArray == NULL) { (*ppDest)->wLength = 0; DestroyH245TermCapDescriptors(ppDest); return CC_NO_MEMORY; }
TermCapDescriptor.CapDesc.Length = pTermCapList->wLength; TermCapDescriptor.CapDescId = 0;
for (i = 0; i < pTermCapList->wLength; i++) { TermCapDescriptor.CapDesc.SimCapArray[i].Length = 1; TermCapDescriptor.CapDesc.SimCapArray[i].AltCaps[0] = pTermCapList->pTermCapArray[i]->CapId; }
status = H245CopyCapDescriptor(&((*ppDest)->pTermCapDescriptorArray[0]), &TermCapDescriptor); if (status != H245_ERROR_OK) { (*ppDest)->wLength = 0; DestroyH245TermCapDescriptors(ppDest); return status; } return CC_OK; }
HRESULT DestroyH245TermCap( PPCC_TERMCAP ppTermCap) { ASSERT(ppTermCap != NULL);
if (*ppTermCap == NULL) return CC_OK;
H245FreeCap(*ppTermCap); *ppTermCap = NULL; return CC_OK; }
HRESULT UnregisterTermCapListFromH245( PCONFERENCE pConference, PCC_TERMCAPLIST pTermCapList) { WORD i, j; PCALL pCall; PCC_HCALL CallList; WORD wNumCalls; HRESULT status; HRESULT SaveStatus;
ASSERT(pConference != NULL);
if (pTermCapList == NULL) return CC_OK;
EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
SaveStatus = CC_OK; for (i = 0; i < pTermCapList->wLength; i++) { ASSERT(pTermCapList->pTermCapArray[i] != NULL); for (j = 0; j < wNumCalls; j++) { if (LockCall(CallList[j], &pCall) == CC_OK) { status = H245DelLocalCap(pCall->H245Instance, pTermCapList->pTermCapArray[i]->CapId); if (status != CC_OK) SaveStatus = status; UnlockCall(pCall); } } } if (CallList != NULL) MemFree(CallList); return SaveStatus; }
HRESULT DestroyH245TermCapList( PCC_TERMCAPLIST *ppTermCapList) { WORD i;
ASSERT(ppTermCapList != NULL);
if (*ppTermCapList == NULL) return CC_OK;
for (i = 0; i < (*ppTermCapList)->wLength; i++) { ASSERT((*ppTermCapList)->pTermCapArray[i] != NULL); H245FreeCap((*ppTermCapList)->pTermCapArray[i]); } if ((*ppTermCapList)->pTermCapArray != NULL) MemFree((*ppTermCapList)->pTermCapArray); MemFree(*ppTermCapList); *ppTermCapList = NULL; return CC_OK; }
HRESULT UnregisterTermCapDescriptorsFromH245( PCONFERENCE pConference, PCC_TERMCAPDESCRIPTORS pTermCapDescriptors) { WORD i, j; PCALL pCall; PCC_HCALL CallList; WORD wNumCalls; HRESULT status; HRESULT SaveStatus;
ASSERT(pConference != NULL);
if (pTermCapDescriptors == NULL) return CC_OK;
EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
SaveStatus = CC_OK; for (i = 0; i < pTermCapDescriptors->wLength; i++) { ASSERT(pTermCapDescriptors->pTermCapDescriptorArray[i] != NULL); for (j = 0; j < wNumCalls; j++) { if (LockCall(CallList[j], &pCall) == CC_OK) { status = H245DelCapDescriptor(pCall->H245Instance, pTermCapDescriptors->pTermCapDescriptorArray[i]->CapDescId); if (status != CC_OK) SaveStatus = status; UnlockCall(pCall); } } } if (CallList != NULL) MemFree(CallList); return SaveStatus; }
HRESULT DestroyH245TermCapDescriptors( PCC_TERMCAPDESCRIPTORS *ppTermCapDescriptors) { WORD i;
ASSERT(ppTermCapDescriptors != NULL);
if (*ppTermCapDescriptors == NULL) return CC_OK;
for (i = 0; i < (*ppTermCapDescriptors)->wLength; i++) { ASSERT((*ppTermCapDescriptors)->pTermCapDescriptorArray[i] != NULL); H245FreeCapDescriptor((*ppTermCapDescriptors)->pTermCapDescriptorArray[i]); } if ((*ppTermCapDescriptors)->pTermCapDescriptorArray != NULL) MemFree((*ppTermCapDescriptors)->pTermCapDescriptorArray); MemFree(*ppTermCapDescriptors); *ppTermCapDescriptors = NULL; return CC_OK; }
HRESULT HostToH245IPNetwork( BYTE *NetworkArray, DWORD dwAddr) { if (NetworkArray == NULL) { ASSERT(0); return CC_BAD_PARAM; }
NetworkArray[0] = HIBYTE(HIWORD(dwAddr)); NetworkArray[1] = LOBYTE(HIWORD(dwAddr)); NetworkArray[2] = HIBYTE(LOWORD(dwAddr)); NetworkArray[3] = LOBYTE(LOWORD(dwAddr));
return CC_OK; }
HRESULT H245IPNetworkToHost( DWORD *pdwAddr, BYTE *NetworkArray) { if ((pdwAddr == NULL) || (NetworkArray == NULL)) { ASSERT(0); return CC_BAD_PARAM; }
*pdwAddr = NetworkArray[0] * 0x01000000 + NetworkArray[1] * 0x00010000 + NetworkArray[2] * 0x00000100 + NetworkArray[3] * 0x00000001;
return CC_OK; }
HRESULT ProcessRemoteHangup( CC_HCALL hCall, HQ931CALL hQ931Initiator, BYTE bHangupReason) { PCALL pCall; CC_HCONFERENCE hConference; PCONFERENCE pConference; HRESULT status; HQ931CALL hQ931Call; H245_INST_T H245Instance; PCHANNEL pChannel; WORD wNumChannels; PCC_HCHANNEL ChannelList; WORD i; WORD wNumCalls; PCC_HCALL CallList; PCALL pOldCall; CC_CONNECT_CALLBACK_PARAMS ConnectCallbackParams; CC_PEER_DROP_CALLBACK_PARAMS PeerDropCallbackParams; CC_PEER_CHANGE_CAP_CALLBACK_PARAMS PeerChangeCapCallbackParams; BOOL bConferenceTermCapsChanged; HRESULT CallbackStatus;
if (hCall == CC_INVALID_HANDLE) return CC_BAD_PARAM;
status = LockCallAndConference(hCall, &pCall, &pConference); if (status != CC_OK) return CC_BAD_PARAM;
hConference = pCall->hConference; hQ931Call = pCall->hQ931Call; H245Instance = pCall->H245Instance; PeerDropCallbackParams.hCall = pCall->hCall; if (pCall->pPeerParticipantInfo == NULL) { PeerDropCallbackParams.TerminalLabel.bMCUNumber = 255; PeerDropCallbackParams.TerminalLabel.bTerminalNumber = 255; PeerDropCallbackParams.pPeerTerminalID = NULL; } else { PeerDropCallbackParams.TerminalLabel = pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel; if (pCall->pPeerParticipantInfo->TerminalIDState == TERMINAL_ID_VALID) PeerDropCallbackParams.pPeerTerminalID = &pCall->pPeerParticipantInfo->ParticipantInfo.TerminalID; else PeerDropCallbackParams.pPeerTerminalID = NULL; }
if ((pConference->ConferenceMode == MULTIPOINT_MODE) && (pConference->tsMultipointController == TS_TRUE)) CreateConferenceTermCaps(pConference, &bConferenceTermCapsChanged); else bConferenceTermCapsChanged = FALSE;
// Remove all TX, RX and PROXY channels associated with this call
EnumerateChannelsInConference(&wNumChannels, &ChannelList, pConference, TX_CHANNEL | RX_CHANNEL | PROXY_CHANNEL); for (i = 0; i < wNumChannels; i++) { if (LockChannel(ChannelList[i], &pChannel) == CC_OK) { if (pChannel->hCall == hCall) FreeChannel(pChannel); else UnlockChannel(pChannel); } } if (ChannelList != NULL) MemFree(ChannelList);
switch (bHangupReason) { case CC_REJECT_NORMAL_CALL_CLEARING: CallbackStatus = CC_OK; break; case CC_REJECT_GATEKEEPER_TERMINATED: CallbackStatus = CC_GATEKEEPER_REFUSED; bHangupReason = CC_REJECT_NORMAL_CALL_CLEARING; break; default: CallbackStatus = CC_PEER_REJECT; } // switch
if (pCall->CallType == THIRD_PARTY_INVITOR) { MarkCallForDeletion(pCall);
ConnectCallbackParams.pNonStandardData = pCall->pPeerNonStandardData; ConnectCallbackParams.pszPeerDisplay = pCall->pszPeerDisplay; ConnectCallbackParams.bRejectReason = bHangupReason; ConnectCallbackParams.pTermCapList = pCall->pPeerH245TermCapList; ConnectCallbackParams.pH2250MuxCapability = pCall->pPeerH245H2250MuxCapability; ConnectCallbackParams.pTermCapDescriptors = pCall->pPeerH245TermCapDescriptors; ConnectCallbackParams.pLocalAddr = pCall->pQ931LocalConnectAddr; if (pCall->pQ931DestinationAddr == NULL) ConnectCallbackParams.pPeerAddr = pCall->pQ931PeerConnectAddr; else ConnectCallbackParams.pPeerAddr = pCall->pQ931DestinationAddr; ConnectCallbackParams.pVendorInfo = pCall->pPeerVendorInfo; ConnectCallbackParams.bMultipointConference = TRUE; ConnectCallbackParams.pConferenceID = &pConference->ConferenceID; ConnectCallbackParams.pMCAddress = pConference->pMultipointControllerAddr; ConnectCallbackParams.pAlternateAddress = NULL; ConnectCallbackParams.dwUserToken = pCall->dwUserToken; InvokeUserConferenceCallback(pConference, CC_CONNECT_INDICATION, CallbackStatus, &ConnectCallbackParams); // Need to validate the conference and call handles; the associated
// objects may have been deleted during user callback on this thread
if (ValidateConference(hConference) == CC_OK) UnlockConference(pConference); if (ValidateCallMarkedForDeletion(hCall) == CC_OK) FreeCall(pCall); Q931Hangup(hQ931Call, bHangupReason); return CC_OK; }
if (pCall->CallType == THIRD_PARTY_INTERMEDIARY) { if ((hQ931Initiator == pCall->hQ931CallInvitor) && (hQ931Initiator != CC_INVALID_HANDLE)) { pCall->hQ931CallInvitor = CC_INVALID_HANDLE; UnlockCall(pCall); UnlockConference(pConference); return CC_OK; } else { if (pCall->CallState != CALL_COMPLETE) { if (pCall->hQ931CallInvitor != CC_INVALID_HANDLE) Q931Hangup(pCall->hQ931CallInvitor, CC_REJECT_UNDEFINED_REASON); if (ValidateCall(hCall) == CC_OK) Q931Hangup(pCall->hQ931Call, bHangupReason); } } }
if ((pConference->ConferenceMode == MULTIPOINT_MODE) && (pConference->tsMultipointController == TS_TRUE)) { if (pCall->pPeerParticipantInfo != NULL) { EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL); for (i = 0; i < wNumCalls; i++) { if (CallList[i] != hCall) { if (LockCall(CallList[i], &pOldCall) == CC_OK) { if (pCall->pPeerParticipantInfo != NULL) H245ConferenceIndication( pOldCall->H245Instance, H245_IND_TERMINAL_LEFT, // Indication Type
0, // SBE number; ignored here
pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bMCUNumber, // MCU number
pCall->pPeerParticipantInfo->ParticipantInfo.TerminalLabel.bTerminalNumber); if (bConferenceTermCapsChanged) // Send new term caps
SendTermCaps(pOldCall, pConference); UnlockCall(pOldCall); } } } if (CallList != NULL) MemFree(CallList); }
InvokeUserConferenceCallback(pConference, CC_PEER_DROP_INDICATION, CC_OK, &PeerDropCallbackParams); if (ValidateCall(hCall) == CC_OK) FreeCall(pCall);
if (ValidateConference(hConference) == CC_OK) { if (bConferenceTermCapsChanged) { // Generate CC_PEER_CHANGE_CAP callback
PeerChangeCapCallbackParams.pTermCapList = pConference->pConferenceTermCapList; PeerChangeCapCallbackParams.pH2250MuxCapability = pConference->pConferenceH245H2250MuxCapability; PeerChangeCapCallbackParams.pTermCapDescriptors = pConference->pConferenceTermCapDescriptors; InvokeUserConferenceCallback(pConference, CC_PEER_CHANGE_CAP_INDICATION, CC_OK, &PeerChangeCapCallbackParams); } }
if (ValidateConference(hConference) == CC_OK) { if (pConference->bDeferredDelete) { ASSERT(pConference->LocalEndpointAttached == DETACHED); EnumerateCallsInConference(&wNumCalls, NULL, pConference, ALL_CALLS); if (wNumCalls == 0) { FreeConference(pConference); return CC_OK; } } UnlockConference(pConference); } return CC_OK; } else { status = EnumerateChannelsInConference(&wNumChannels, &ChannelList, pConference, ALL_CHANNELS); if (status == CC_OK) { // free all the channels
for (i = 0; i < wNumChannels; i++) { if (LockChannel(ChannelList[i], &pChannel) == CC_OK) // Notice that since we're going to hangup, we don't need to
// close any channels
FreeChannel(pChannel); } if (ChannelList != NULL) MemFree(ChannelList); }
if (H245Instance != H245_INVALID_ID) status = H245ShutDown(H245Instance); else status = H245_ERROR_OK; if (status == H245_ERROR_OK) { status = Q931Hangup(hQ931Call, CC_REJECT_NORMAL_CALL_CLEARING); // Q931Hangup may legitimately return CS_BAD_PARAM, because the Q.931 call object
// may have been deleted at this point
if (status == CS_BAD_PARAM) status = CC_OK; } else Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON);
if (pConference->bDeferredDelete) { ASSERT(pConference->LocalEndpointAttached == DETACHED); FreeConference(pConference); } else { ReInitializeConference(pConference);
InvokeUserConferenceCallback(pConference, CC_CONFERENCE_TERMINATION_INDICATION, CallbackStatus, NULL);
if (ValidateConference(hConference) == CC_OK) UnlockConference(pConference); } return CC_OK; } // We should never reach this point
ASSERT(0); }
HRESULT DefaultSessionTableConstructor( CC_HCONFERENCE hConference, DWORD_PTR dwConferenceToken, BOOL bCreate, BOOL *pbSessionTableChanged, WORD wListCount, PCC_TERMCAPLIST pTermCapList[], PCC_TERMCAPDESCRIPTORS pTermCapDescriptors[], PCC_SESSIONTABLE *ppSessionTable) { WORD i; HRESULT status; PCONFERENCE pConference; WORD wNumChannels; PCC_HCHANNEL ChannelList; PCHANNEL pChannel; WORD wNumCalls; PCC_HCALL CallList; PCALL pCall; BYTE bSessionID; WORD wPort; DWORD dwAddr; WCHAR szSessionDescription[100]; WCHAR ss[10];
ASSERT(hConference != CC_INVALID_HANDLE); ASSERT(ppSessionTable != NULL); if (*ppSessionTable != NULL) { for (i = 0; i < (*ppSessionTable)->wLength; i++) { if ((*ppSessionTable)->SessionInfoArray[i].pTermCap != NULL) H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap); FreeAddr((*ppSessionTable)->SessionInfoArray[i].pRTPAddr); FreeAddr((*ppSessionTable)->SessionInfoArray[i].pRTCPAddr); } if ((*ppSessionTable)->SessionInfoArray != NULL) MemFree((*ppSessionTable)->SessionInfoArray); MemFree(*ppSessionTable); *ppSessionTable = NULL; }
if (bCreate == FALSE) return CC_OK;
*ppSessionTable = NULL; if (pbSessionTableChanged != NULL) *pbSessionTableChanged = FALSE;
status = LockConference(hConference, &pConference); if (status != CC_OK) return status;
if ((pConference->ConferenceMode == UNCONNECTED_MODE) || (pConference->ConferenceMode == POINT_TO_POINT_MODE)) { UnlockConference(pConference); return CC_BAD_PARAM; }
// pConference->ConferenceMode == MULTIPOINT_MODE
// Create one session entry for each open channel on this conference
bSessionID = 1; wPort = 2050;
// Set dwAddr
EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL); if (wNumCalls == 0) { UnlockConference(pConference); return CC_INTERNAL_ERROR; }
status = LockCall(CallList[0], &pCall); if (status != CC_OK) { MemFree(CallList); UnlockConference(pConference); return status; }
if (pCall->pQ931LocalConnectAddr == NULL) { MemFree(CallList); UnlockCall(pCall); UnlockConference(pConference); return CC_INTERNAL_ERROR; }
if (pCall->pQ931LocalConnectAddr->nAddrType != CC_IP_BINARY) { MemFree(CallList); UnlockCall(pCall); UnlockConference(pConference); return CC_INTERNAL_ERROR; }
// Construct dwAddr from one of the unicast Q.931 addresses by setting the high
// nibble of the Q.931 address to 0xE
dwAddr = (pCall->pQ931LocalConnectAddr->Addr.IP_Binary.dwAddr & 0xEFFFFFFF) | 0xE0000000;
UnlockCall(pCall); MemFree(CallList); EnumerateChannelsInConference(&wNumChannels, &ChannelList, pConference, TX_CHANNEL); *ppSessionTable = (PCC_SESSIONTABLE)MemAlloc(sizeof(CC_SESSIONTABLE)); if (*ppSessionTable == NULL) { MemFree(ChannelList); UnlockConference(pConference); return CC_NO_MEMORY; } (*ppSessionTable)->wLength = wNumChannels; if (wNumChannels == 0) (*ppSessionTable)->SessionInfoArray = NULL; else { (*ppSessionTable)->SessionInfoArray = (PCC_SESSIONINFO)MemAlloc(sizeof(CC_SESSIONINFO) * wNumChannels); if ((*ppSessionTable)->SessionInfoArray == NULL) { MemFree(ChannelList); UnlockConference(pConference); (*ppSessionTable)->wLength = 0; DefaultSessionTableConstructor( hConference, dwConferenceToken, FALSE, // bCreate,
NULL, // pbSessionTableChanged,
0, // wListCount,
NULL, // pTermCapList[],
NULL, // pTermCapDescriptors[],
ppSessionTable); return CC_NO_MEMORY; } for (i = 0; i < wNumChannels; i++) { (*ppSessionTable)->SessionInfoArray[i].bSessionID = bSessionID++;
(*ppSessionTable)->SessionInfoArray[i].bAssociatedSessionID = 0;
wcscpy(szSessionDescription, L"Session "); _itow((int)(*ppSessionTable)->SessionInfoArray[i].bSessionID, ss, 10); wcscat(szSessionDescription, ss); (*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength = (WORD)((wcslen(szSessionDescription)+1)*sizeof(WCHAR)); (*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString = (BYTE *)MemAlloc((*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength); if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString == NULL) { MemFree(ChannelList); UnlockConference(pConference); (*ppSessionTable)->wLength = i; DefaultSessionTableConstructor( hConference, dwConferenceToken, FALSE, // bCreate,
NULL, // pbSessionTableChanged,
0, // wListCount,
NULL, // pTermCapList[],
NULL, // pTermCapDescriptors[],
ppSessionTable); return CC_NO_MEMORY; } memcpy((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString, szSessionDescription, (*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength); status = LockChannel(ChannelList[i], &pChannel); if (status != CC_OK) { MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); MemFree(ChannelList); UnlockConference(pConference); (*ppSessionTable)->wLength = i; DefaultSessionTableConstructor( hConference, dwConferenceToken, FALSE, // bCreate,
NULL, // pbSessionTableChanged,
0, // wListCount,
NULL, // pTermCapList[],
NULL, // pTermCapDescriptors[],
ppSessionTable); return CC_NO_MEMORY; } status = H245CopyCap(&(*ppSessionTable)->SessionInfoArray[i].pTermCap, pChannel->pTxH245TermCap); UnlockChannel(pChannel); if (status != H245_ERROR_OK) { MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); MemFree(ChannelList); UnlockConference(pConference); (*ppSessionTable)->wLength = i; DefaultSessionTableConstructor( hConference, dwConferenceToken, FALSE, // bCreate,
NULL, // pbSessionTableChanged,
0, // wListCount,
NULL, // pTermCapList[],
NULL, // pTermCapDescriptors[],
ppSessionTable); return status; } (*ppSessionTable)->SessionInfoArray[i].pRTPAddr = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR)); if ((*ppSessionTable)->SessionInfoArray[i].pRTPAddr == NULL) { H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap); MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); MemFree(ChannelList); UnlockConference(pConference); (*ppSessionTable)->wLength = i; DefaultSessionTableConstructor( hConference, dwConferenceToken, FALSE, // bCreate,
NULL, // pbSessionTableChanged,
0, // wListCount,
NULL, // pTermCapList[],
NULL, // pTermCapDescriptors[],
ppSessionTable); return CC_NO_MEMORY; } (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->nAddrType = CC_IP_BINARY; (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->bMulticast = TRUE; (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.wPort = wPort++; (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.dwAddr = dwAddr; (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR)); if ((*ppSessionTable)->SessionInfoArray[i].pRTCPAddr == NULL) { H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap); FreeAddr((*ppSessionTable)->SessionInfoArray[i].pRTPAddr); MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); MemFree(ChannelList); UnlockConference(pConference); (*ppSessionTable)->wLength = i; DefaultSessionTableConstructor( hConference, dwConferenceToken, FALSE, // bCreate,
NULL, // pbSessionTableChanged,
0, // wListCount,
NULL, // pTermCapList[],
NULL, // pTermCapDescriptors[],
ppSessionTable); return CC_NO_MEMORY; } (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->nAddrType = CC_IP_BINARY; (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->bMulticast = TRUE; (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.wPort = wPort++; (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.dwAddr = dwAddr; } }
MemFree(ChannelList); UnlockConference(pConference); if (pbSessionTableChanged != NULL) *pbSessionTableChanged = TRUE;
return CC_OK; }
HRESULT DefaultTermCapConstructor( CC_HCONFERENCE hConference, DWORD_PTR dwConferenceToken, BOOL bCreate, BOOL *pbTermCapsChanged, WORD wListCount, PCC_TERMCAPLIST pInTermCapList[], PCC_TERMCAPDESCRIPTORS pInTermCapDescriptors[], PCC_TERMCAPLIST *ppOutTermCapList, PCC_TERMCAPDESCRIPTORS *ppOutTermCapDescriptors) { HRESULT status; PCONFERENCE pConference; WORD wNumChannels; PCC_HCHANNEL ChannelList; WORD i; PCHANNEL pChannel;
ASSERT(hConference != CC_INVALID_HANDLE); ASSERT(ppOutTermCapList != NULL); ASSERT(ppOutTermCapDescriptors != NULL); if (*ppOutTermCapList != NULL) { DestroyH245TermCapList(ppOutTermCapList); *ppOutTermCapList = NULL; }
if (*ppOutTermCapDescriptors != NULL) { DestroyH245TermCapDescriptors(ppOutTermCapDescriptors); *ppOutTermCapDescriptors = NULL; } if (bCreate == FALSE) return CC_OK;
*ppOutTermCapList = NULL; *ppOutTermCapDescriptors = NULL; if (pbTermCapsChanged != NULL) *pbTermCapsChanged = FALSE;
status = LockConference(hConference, &pConference); if (status != CC_OK) return status;
if (pConference->LocalEndpointAttached == NEVER_ATTACHED) { // Copy the local term caps to the conference term caps
status = CopyH245TermCapList(ppOutTermCapList, pConference->pLocalH245TermCapList); if (status != CC_OK) { UnlockConference(pConference); return CC_NO_MEMORY; }
// Copy the local term cap descriptors to the conference term cap descriptors
status = CopyH245TermCapDescriptors(ppOutTermCapDescriptors, pConference->pLocalH245TermCapDescriptors); if (status != CC_OK) { UnlockConference(pConference); return CC_NO_MEMORY; } } else { // pConference->LocalEndpointAttached != NEVER_ATTACHED
// Create one term cap entry for each open channel on this conference
EnumerateChannelsInConference(&wNumChannels, &ChannelList, pConference, TX_CHANNEL);
*ppOutTermCapList = (PCC_TERMCAPLIST)MemAlloc(sizeof(CC_TERMCAPLIST)); if (*ppOutTermCapList == NULL) { MemFree(ChannelList); UnlockConference(pConference); return CC_NO_MEMORY; } (*ppOutTermCapList)->wLength = wNumChannels; if (wNumChannels == 0) (*ppOutTermCapList)->pTermCapArray = NULL; else { (*ppOutTermCapList)->pTermCapArray = (PPCC_TERMCAP)MemAlloc(sizeof(PCC_TERMCAP) * wNumChannels); if ((*ppOutTermCapList)->pTermCapArray == NULL) { MemFree(ChannelList); UnlockConference(pConference); (*ppOutTermCapList)->wLength = 0; DefaultTermCapConstructor( hConference, dwConferenceToken, FALSE, // bCreate
NULL, // pbTermCapsChanged
0, // wListCount
NULL, // pInTermCapList[]
NULL, // pInTermCapDescriptors[]
ppOutTermCapList, ppOutTermCapDescriptors); return CC_NO_MEMORY; } for (i = 0; i < wNumChannels; i++) { status = LockChannel(ChannelList[i], &pChannel); if (status != CC_OK) { MemFree(ChannelList); UnlockConference(pConference); (*ppOutTermCapList)->wLength = i; DefaultTermCapConstructor( hConference, dwConferenceToken, FALSE, // bCreate
NULL, // pbTermCapsChanged
0, // wListCount
NULL, // pInTermCapList[]
NULL, // pInTermCapDescriptors[]
ppOutTermCapList, ppOutTermCapDescriptors); return CC_NO_MEMORY; } status = H245CopyCap(&((*ppOutTermCapList)->pTermCapArray[i]), pChannel->pTxH245TermCap); UnlockChannel(pChannel); if (status != H245_ERROR_OK) { MemFree(ChannelList); UnlockConference(pConference); (*ppOutTermCapList)->wLength = i; DefaultTermCapConstructor( hConference, dwConferenceToken, FALSE, // bCreate
NULL, // pbTermCapsChanged
0, // wListCount
NULL, // pInTermCapList[]
NULL, // pInTermCapDescriptors[]
ppOutTermCapList, ppOutTermCapDescriptors); return status; }
(*ppOutTermCapList)->pTermCapArray[i]->Dir = H245_CAPDIR_LCLRXTX; (*ppOutTermCapList)->pTermCapArray[i]->CapId = (WORD)(i+1); } }
MemFree(ChannelList); UnlockConference(pConference);
// create a new descriptor list
status = CreateH245DefaultTermCapDescriptors(ppOutTermCapDescriptors, *ppOutTermCapList); if (status != CC_OK) { DefaultTermCapConstructor( hConference, dwConferenceToken, FALSE, // bCreate
NULL, // pbTermCapsChanged
0, // wListCount
NULL, // pInTermCapList[]
NULL, // pInTermCapDescriptors[]
ppOutTermCapList, ppOutTermCapDescriptors); return CC_NO_MEMORY; } } // pConference->LocalEndpointAttached != NEVER_ATTACHED
if (pbTermCapsChanged != NULL) *pbTermCapsChanged = TRUE;
return CC_OK; }
HRESULT AcceptCall( PCALL pCall, PCONFERENCE pConference) { HRESULT status; CC_HCALL hCall; CC_HCONFERENCE hConference; HQ931CALL hQ931Call; CC_CONFERENCEID ConferenceID; BYTE bTerminalType; CC_ADDR H245Addr; H245_INST_T H245Instance; PCC_VENDORINFO pVendorInfo; PCC_NONSTANDARDDATA pNonStandardData; PWSTR pszDisplay; CC_ENDPOINTTYPE DestinationEndpointType; TRISTATE tsMultipointController; DWORD dwLinkLayerPhysicalId;
ASSERT(pCall != NULL); ASSERT(pConference != NULL);
hCall = pCall->hCall; hConference = pConference->hConference; hQ931Call = pCall->hQ931Call; ConferenceID = pCall->ConferenceID; pCall->hConference = pConference->hConference;
status = CopyNonStandardData(&pNonStandardData, pCall->pLocalNonStandardData); if (status != CC_OK) { UnlockConference(pConference); FreeCall(pCall); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
return status; }
status = CopyVendorInfo(&pVendorInfo, pConference->pVendorInfo); if (status != CC_OK) { UnlockConference(pConference); FreeCall(pCall); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
FreeNonStandardData(pNonStandardData); return status; }
status = CopyDisplay(&pszDisplay, pCall->pszLocalDisplay); if (status != CC_OK) { UnlockConference(pConference); FreeCall(pCall); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
FreeNonStandardData(pNonStandardData); FreeVendorInfo(pVendorInfo); return status; }
status = MakeH245PhysicalID(&pCall->dwH245PhysicalID); if (status != CC_OK) { UnlockConference(pConference); FreeCall(pCall); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
FreeNonStandardData(pNonStandardData); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); return status; }
if (pCall->bCallerIsMC) { ASSERT(pConference->tsMultipointController != TS_TRUE); ASSERT(pConference->bMultipointCapable == TRUE); tsMultipointController = TS_FALSE; } else tsMultipointController = pConference->tsMultipointController;
//MULTITHREAD
//Use a tmp ID so we don't clobber the chosen H245Id.
// H245Id=>
// <= linkLayerId
dwLinkLayerPhysicalId = INVALID_PHYS_ID;
SetTerminalType(tsMultipointController, &bTerminalType); pCall->H245Instance = H245Init(H245_CONF_H323, // configuration
pCall->dwH245PhysicalID, // H245 physical ID
&dwLinkLayerPhysicalId, // the link layer ID is returned
hCall, // dwPreserved
(H245_CONF_IND_CALLBACK_T)H245Callback, // callback
bTerminalType); if (pCall->H245Instance == H245_INVALID_ID) { // H245 initialization failure
UnlockConference(pConference); FreeCall(pCall); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
FreeNonStandardData(pNonStandardData); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); return CC_INTERNAL_ERROR; }
H245Instance = pCall->H245Instance;
// Set the H.245 TCP/IP address to the same IP address on which
// the Q.931 connection was made; this ensures that if the host
// is multi-homed, the H.245 will be made on the same IP address
// as the Q.931 connection. Set the initial H.245 port to zero,
// so that it will be dynamically determined.
ASSERT(pCall->pQ931LocalConnectAddr != NULL); H245Addr = *pCall->pQ931LocalConnectAddr;
switch (pCall->pQ931LocalConnectAddr->nAddrType) { case CC_IP_DOMAIN_NAME: H245Addr.Addr.IP_DomainName.wPort = 0; break; case CC_IP_DOT: H245Addr.Addr.IP_Dot.wPort = 0; break; case CC_IP_BINARY: H245Addr.Addr.IP_Binary.wPort = 0; break; default: ASSERT(0); UnlockConference(pConference); FreeCall(pCall); H245ShutDown(H245Instance); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
FreeNonStandardData(pNonStandardData); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); return CC_INTERNAL_ERROR; }
status = linkLayerListen(&dwLinkLayerPhysicalId, H245Instance, &H245Addr, NULL); if (status != NOERROR) { UnlockConference(pConference); FreeCall(pCall); H245ShutDown(H245Instance); Q931RejectCall(hQ931Call, // Q931 call handle
CC_REJECT_UNDEFINED_REASON, // reject reason
&ConferenceID, NULL, // alternate address
pNonStandardData); // non-standard data
FreeNonStandardData(pNonStandardData); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); return status; }
UnlockConference(pConference); UnlockCall(pCall);
DestinationEndpointType.pVendorInfo = pVendorInfo; DestinationEndpointType.bIsTerminal = TRUE; DestinationEndpointType.bIsGateway = FALSE;
status = Q931AcceptCall(hQ931Call, pszDisplay, pNonStandardData, // non-standard data
&DestinationEndpointType, &H245Addr, // H245 address
hCall); // user token
FreeNonStandardData(pNonStandardData); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); if (status != CS_OK) { if (LockCall(hCall, &pCall) == CC_OK) FreeCall(pCall); H245ShutDown(H245Instance); return status; } status = LockCallAndConference(hCall, &pCall, &pConference); if (status != CC_OK) { if (LockCall(hCall, &pCall) == CC_OK) FreeCall(pCall); H245ShutDown(H245Instance); Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON); return status; }
pCall->CallState = TERMCAP; pConference->ConferenceID = pCall->ConferenceID;
status = AddPlacedCallToConference(pCall, pConference); if (status != CC_OK) { UnlockConference(pConference); FreeCall(pCall); H245ShutDown(H245Instance); Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON); return status; }
status = SendTermCaps(pCall, pConference); if (status != CC_OK) { UnlockConference(pConference); FreeCall(pCall); H245ShutDown(H245Instance); Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON); return status; } pCall->OutgoingTermCapState = AWAITING_ACK;
if (pCall->MasterSlaveState == MASTER_SLAVE_NOT_STARTED) { status = H245InitMasterSlave(H245Instance, H245Instance); // returned as dwTransId in the callback
if (status != H245_ERROR_OK) { UnlockConference(pConference); FreeCall(pCall); H245ShutDown(H245Instance); Q931Hangup(hQ931Call, CC_REJECT_UNDEFINED_REASON); return status; } pCall->MasterSlaveState = MASTER_SLAVE_IN_PROGRESS; }
if (pCall->bCallerIsMC) { pConference->tsMultipointController = TS_FALSE; pConference->ConferenceMode = MULTIPOINT_MODE; }
UnlockConference(pConference); UnlockCall(pCall); return CC_OK; }
HRESULT PlaceCall( PCALL pCall, PCONFERENCE pConference) { CC_HCALL hCall; HRESULT status; WORD wGoal; HQ931CALL hQ931Call; PCC_ALIASNAMES pCallerAliasNames; PCC_ALIASNAMES pCalleeAliasNames; PCC_ALIASNAMES pCalleeExtraAliasNames; PCC_ALIASITEM pCalleeExtension; PCC_VENDORINFO pVendorInfo; PWSTR pszDisplay; PCC_NONSTANDARDDATA pNonStandardData; WORD wNumCalls; PCC_ADDR pConnectAddr; PCC_ADDR pDestinationAddr; CC_ADDR SourceAddr; CC_ENDPOINTTYPE SourceEndpointType; BOOL bCallerIsMC; WORD wCallType;
ASSERT(pCall != NULL);
hCall = pCall->hCall;
if (pCall->CallState == ENQUEUED) { // Enqueue the call on the conference object and HResultLeaveCallControl.
// There will be exactly one placed call for this conference,
// which is in the process of being placed. If this call placement
// completes successfully, all enqueued calls will then be placed.
// If this call placement fails or is terminated, one enqueued call
// will be placed
status = AddEnqueuedCallToConference(pCall, pConference); return status; } // CallState == PLACED
EnumerateCallsInConference(&wNumCalls, NULL, pConference, PLACED_CALL | ESTABLISHED_CALL); if (EqualConferenceIDs(&pConference->ConferenceID, &InvalidConferenceID)) wGoal = CSG_CREATE; else if ((wNumCalls == 0) && (pConference->tsMultipointController != TS_TRUE)) wGoal = CSG_JOIN; else wGoal = CSG_INVITE;
status = AddPlacedCallToConference(pCall, pConference); if (status != CC_OK) return status;
status = CopyAddr(&pConnectAddr, pCall->pQ931PeerConnectAddr); if (status != CC_OK) return status; status = CopyAddr(&pDestinationAddr, pCall->pQ931DestinationAddr); if (status != CC_OK) { FreeAddr(pConnectAddr); return status; }
status = Q931CopyAliasNames(&pCallerAliasNames, pCall->pLocalAliasNames); if (status != CS_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); return status; }
status = CopyVendorInfo(&pVendorInfo, pConference->pVendorInfo); if (status != CC_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); return status; } status = CopyDisplay(&pszDisplay, pCall->pszLocalDisplay); if (status != CC_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); FreeVendorInfo(pVendorInfo); return status; } status = Q931CopyAliasNames(&pCalleeAliasNames, pCall->pPeerAliasNames); if (status != CS_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); return status; } status = Q931CopyAliasNames(&pCalleeExtraAliasNames, pCall->pPeerExtraAliasNames); if (status != CS_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); Q931FreeAliasNames(pCalleeAliasNames); return status; }
status = Q931CopyAliasItem(&pCalleeExtension, pCall->pPeerExtension); if (status != CS_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); Q931FreeAliasNames(pCalleeAliasNames); Q931FreeAliasNames(pCalleeExtraAliasNames); return status; }
status = CopyNonStandardData(&pNonStandardData, pCall->pLocalNonStandardData); if (status != CC_OK) { FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); Q931FreeAliasNames(pCalleeAliasNames); Q931FreeAliasNames(pCalleeExtraAliasNames); Q931FreeAliasItem(pCalleeExtension); return status; }
bCallerIsMC = (pConference->tsMultipointController == TS_TRUE ? TRUE : FALSE); // Note that if pConference->ConferenceMode == POINT_TO_POINT_MODE, this call attempt
// will result in a multipoint call if successful, so set the wCallType accordingly
wCallType = (WORD)((pConference->ConferenceMode == UNCONNECTED_MODE) ? CC_CALLTYPE_PT_PT : CC_CALLTYPE_N_N);
SourceEndpointType.pVendorInfo = pVendorInfo; SourceEndpointType.bIsTerminal = TRUE; SourceEndpointType.bIsGateway = FALSE;
// Cause our local Q.931 connect address to be placed in the
// Q.931 setup-UUIE sourceAddress field
SourceAddr.nAddrType = CC_IP_BINARY; SourceAddr.bMulticast = FALSE; SourceAddr.Addr.IP_Binary.dwAddr = 0; SourceAddr.Addr.IP_Binary.wPort = 0;
status = Q931PlaceCall(&hQ931Call, // Q931 call handle
pszDisplay, pCallerAliasNames, pCalleeAliasNames, pCalleeExtraAliasNames, // pCalleeExtraAliasNames
pCalleeExtension, // pCalleeExtension
pNonStandardData, // non-standard data
&SourceEndpointType, NULL, // pszCalledPartyNumber
pConnectAddr, pDestinationAddr, &SourceAddr, // source address
bCallerIsMC, &pCall->ConferenceID, // conference ID
wGoal, wCallType, hCall, // user token
(Q931_CALLBACK)Q931Callback, // callback
#ifdef GATEKEEPER
pCall->GkiCall.usCRV, // CRV
&pCall->CallIdentifier); // H.225 CallIdentifier
#else
0, // CRV
&pCall->CallIdentifier); // H.225 CallIdentifier
#endif GATEKEEPER
FreeAddr(pConnectAddr); FreeAddr(pDestinationAddr); Q931FreeAliasNames(pCallerAliasNames); FreeVendorInfo(pVendorInfo); FreeDisplay(pszDisplay); Q931FreeAliasNames(pCalleeAliasNames); Q931FreeAliasNames(pCalleeExtraAliasNames); Q931FreeAliasItem(pCalleeExtension); FreeNonStandardData(pNonStandardData); if (status != CS_OK) return status; pCall->hQ931Call = hQ931Call; return CC_OK; }
HRESULT SendTermCaps( PCALL pCall, PCONFERENCE pConference) { HRESULT status; WORD i; H245_TOTCAPDESC_T *pTermCapDescriptor; PCC_TERMCAP pH2250MuxCapability; PCC_TERMCAPLIST pTermCapList; PCC_TERMCAPDESCRIPTORS pTermCapDescriptors;
ASSERT(pCall != NULL); ASSERT(pConference != NULL);
if ((pConference->ConferenceMode == MULTIPOINT_MODE) && (pConference->tsMultipointController == TS_TRUE)) { pH2250MuxCapability = pConference->pConferenceH245H2250MuxCapability; pTermCapList = pConference->pConferenceTermCapList; pTermCapDescriptors = pConference->pConferenceTermCapDescriptors; } else { pH2250MuxCapability = pConference->pLocalH245H2250MuxCapability; pTermCapList = pConference->pLocalH245TermCapList; pTermCapDescriptors = pConference->pLocalH245TermCapDescriptors; }
ASSERT(pH2250MuxCapability != NULL); ASSERT(pTermCapList != NULL); ASSERT(pTermCapDescriptors != NULL);
// First send out the H.225.0 capability
status = H245SetLocalCap(pCall->H245Instance, pH2250MuxCapability, &pH2250MuxCapability->CapId); ASSERT(pH2250MuxCapability->CapId == 0); if (status != H245_ERROR_OK) return status;
// Now send out the terminal capabilities
for (i = 0; i < pTermCapList->wLength; i++) { status = H245SetLocalCap(pCall->H245Instance, pTermCapList->pTermCapArray[i], &pTermCapList->pTermCapArray[i]->CapId); if (status != H245_ERROR_OK) return status; }
// Finally send out the capability descriptors
for (i = 0; i < pTermCapDescriptors->wLength; i++) { pTermCapDescriptor = pTermCapDescriptors->pTermCapDescriptorArray[i]; status = H245SetCapDescriptor(pCall->H245Instance, &pTermCapDescriptor->CapDesc, &pTermCapDescriptor->CapDescId); if (status != H245_ERROR_OK) return status; }
status = H245SendTermCaps(pCall->H245Instance, pCall->H245Instance); // returned as dwTransId in the callback
return status; }
HRESULT SessionTableToH245CommunicationTable( PCC_SESSIONTABLE pSessionTable, H245_COMM_MODE_ENTRY_T *pH245CommunicationTable[], BYTE *pbCommunicationTableCount) { WORD i, j; WORD wStringLength;
ASSERT(pH245CommunicationTable != NULL); ASSERT(pbCommunicationTableCount != NULL);
if ((pSessionTable == NULL) || (pSessionTable->wLength == 0)) { *pH245CommunicationTable = NULL; *pbCommunicationTableCount = 0; return CC_OK; }
if (pSessionTable->SessionInfoArray == NULL) { *pH245CommunicationTable = NULL; *pbCommunicationTableCount = 0; return CC_BAD_PARAM; }
*pH245CommunicationTable = (H245_COMM_MODE_ENTRY_T *)MemAlloc(sizeof(H245_COMM_MODE_ENTRY_T) * pSessionTable->wLength); if (*pH245CommunicationTable == NULL) { *pbCommunicationTableCount = 0; return CC_NO_MEMORY; }
*pbCommunicationTableCount = (BYTE)pSessionTable->wLength;
for (i = 0; i < pSessionTable->wLength; i++) { (*pH245CommunicationTable)[i].pNonStandard = NULL; (*pH245CommunicationTable)[i].sessionID = pSessionTable->SessionInfoArray[i].bSessionID; if (pSessionTable->SessionInfoArray[i].bAssociatedSessionID == 0) (*pH245CommunicationTable)[i].associatedSessionIDPresent = FALSE; else { (*pH245CommunicationTable)[i].associatedSessionIDPresent = TRUE; (*pH245CommunicationTable)[i].associatedSessionID = pSessionTable->SessionInfoArray[i].bAssociatedSessionID; } (*pH245CommunicationTable)[i].terminalLabelPresent = FALSE; wStringLength = pSessionTable->SessionInfoArray[i].SessionDescription.wOctetStringLength; if (wStringLength > 0) { (*pH245CommunicationTable)[i].pSessionDescription = (unsigned short *)MemAlloc(sizeof(unsigned short) * wStringLength); if ((*pH245CommunicationTable)[i].pSessionDescription == NULL) { for (j = 0; j < i; j++) MemFree((*pH245CommunicationTable)[j].pSessionDescription); MemFree(*pH245CommunicationTable); *pbCommunicationTableCount = 0; return CC_NO_MEMORY; } memcpy((*pH245CommunicationTable)[i].pSessionDescription, pSessionTable->SessionInfoArray[i].SessionDescription.pOctetString, wStringLength); } else (*pH245CommunicationTable)[i].pSessionDescription = NULL; (*pH245CommunicationTable)[i].wSessionDescriptionLength = wStringLength; (*pH245CommunicationTable)[i].dataType = *pSessionTable->SessionInfoArray[i].pTermCap; if (pSessionTable->SessionInfoArray[i].pRTPAddr == NULL) (*pH245CommunicationTable)[i].mediaChannelPresent = FALSE; else { if (pSessionTable->SessionInfoArray[i].pRTPAddr->nAddrType != CC_IP_BINARY) { for (j = 0; j <= i; j++) if ((*pH245CommunicationTable)[j].pSessionDescription != NULL) MemFree((*pH245CommunicationTable)[j].pSessionDescription); MemFree(*pH245CommunicationTable); *pbCommunicationTableCount = 0; return CC_BAD_PARAM; } if (pSessionTable->SessionInfoArray[i].pRTPAddr->bMulticast) (*pH245CommunicationTable)[i].mediaChannel.type = H245_IP_MULTICAST; else (*pH245CommunicationTable)[i].mediaChannel.type = H245_IP_UNICAST; (*pH245CommunicationTable)[i].mediaChannel.u.ip.tsapIdentifier = pSessionTable->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.wPort; HostToH245IPNetwork((*pH245CommunicationTable)[i].mediaChannel.u.ip.network, pSessionTable->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.dwAddr); (*pH245CommunicationTable)[i].mediaChannelPresent = TRUE; } if (pSessionTable->SessionInfoArray[i].pRTCPAddr == NULL) (*pH245CommunicationTable)[i].mediaControlChannelPresent = FALSE; else { if (pSessionTable->SessionInfoArray[i].pRTCPAddr->nAddrType != CC_IP_BINARY) { for (j = 0; j <= i; j++) if ((*pH245CommunicationTable)[j].pSessionDescription != NULL) MemFree((*pH245CommunicationTable)[j].pSessionDescription); MemFree(*pH245CommunicationTable); *pbCommunicationTableCount = 0; return CC_BAD_PARAM; } if (pSessionTable->SessionInfoArray[i].pRTCPAddr->bMulticast) (*pH245CommunicationTable)[i].mediaControlChannel.type = H245_IP_MULTICAST; else (*pH245CommunicationTable)[i].mediaControlChannel.type = H245_IP_UNICAST; (*pH245CommunicationTable)[i].mediaControlChannel.u.ip.tsapIdentifier = pSessionTable->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.wPort; HostToH245IPNetwork((*pH245CommunicationTable)[i].mediaControlChannel.u.ip.network, pSessionTable->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.dwAddr); (*pH245CommunicationTable)[i].mediaControlChannelPresent = TRUE; } (*pH245CommunicationTable)[i].mediaGuaranteed = FALSE; (*pH245CommunicationTable)[i].mediaGuaranteedPresent = TRUE; (*pH245CommunicationTable)[i].mediaControlGuaranteed = FALSE; (*pH245CommunicationTable)[i].mediaControlGuaranteedPresent = TRUE; }
return CC_OK; }
HRESULT H245CommunicationTableToSessionTable( H245_COMM_MODE_ENTRY_T H245CommunicationTable[], BYTE bCommunicationTableCount, PCC_SESSIONTABLE *ppSessionTable) { WORD i, j; HRESULT status;
ASSERT(ppSessionTable != NULL);
if (H245CommunicationTable == NULL) if (bCommunicationTableCount == 0) { *ppSessionTable = NULL; return CC_OK; } else return CC_BAD_PARAM; else if (bCommunicationTableCount == 0) return CC_BAD_PARAM;
*ppSessionTable = (PCC_SESSIONTABLE)MemAlloc(sizeof(CC_SESSIONTABLE)); if (*ppSessionTable == NULL) return CC_NO_MEMORY;
(*ppSessionTable)->wLength = bCommunicationTableCount;
(*ppSessionTable)->SessionInfoArray = (PCC_SESSIONINFO)MemAlloc(sizeof(CC_SESSIONINFO) * bCommunicationTableCount); if ((*ppSessionTable)->SessionInfoArray == NULL) { MemFree(*ppSessionTable); *ppSessionTable = NULL; return CC_NO_MEMORY; }
for (i = 0; i < bCommunicationTableCount; i++) { (*ppSessionTable)->SessionInfoArray[i].bSessionID = H245CommunicationTable[i].sessionID; if (H245CommunicationTable[i].associatedSessionIDPresent) (*ppSessionTable)->SessionInfoArray[i].bAssociatedSessionID = H245CommunicationTable[i].associatedSessionID; else (*ppSessionTable)->SessionInfoArray[i].bAssociatedSessionID = 0; (*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength = H245CommunicationTable[i].wSessionDescriptionLength; if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.wOctetStringLength == 0) (*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString = NULL; else { (*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString = (BYTE *)MemAlloc(H245CommunicationTable[i].wSessionDescriptionLength); if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString == NULL) { for (j = 0; j < i; j++) { H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap); if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTPAddr); if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr); } MemFree((*ppSessionTable)->SessionInfoArray); MemFree(*ppSessionTable); return CC_NO_MEMORY; } memcpy((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString, H245CommunicationTable[i].pSessionDescription, H245CommunicationTable[i].wSessionDescriptionLength); } status = H245CopyCap(&(*ppSessionTable)->SessionInfoArray[i].pTermCap, &H245CommunicationTable[i].dataType); if (status != H245_ERROR_OK) { if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString != NULL) MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); for (j = 0; j < i; j++) { H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap); if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTPAddr); if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr); } MemFree((*ppSessionTable)->SessionInfoArray); MemFree(*ppSessionTable); return status; } if ((H245CommunicationTable[i].mediaChannelPresent) && ((H245CommunicationTable[i].mediaChannel.type == H245_IP_MULTICAST) || (H245CommunicationTable[i].mediaChannel.type == H245_IP_UNICAST))) { (*ppSessionTable)->SessionInfoArray[i].pRTPAddr = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR)); if ((*ppSessionTable)->SessionInfoArray[i].pRTPAddr == NULL) { if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString != NULL) MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap); for (j = 0; j < i; j++) { H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap); if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTPAddr); if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr); } MemFree((*ppSessionTable)->SessionInfoArray); MemFree(*ppSessionTable); return CC_NO_MEMORY; } (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->nAddrType = CC_IP_BINARY; if (H245CommunicationTable[i].mediaChannel.type == H245_IP_MULTICAST) (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->bMulticast = TRUE; else (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->bMulticast = FALSE; (*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.wPort = H245CommunicationTable[i].mediaChannel.u.ip.tsapIdentifier; H245IPNetworkToHost(&(*ppSessionTable)->SessionInfoArray[i].pRTPAddr->Addr.IP_Binary.dwAddr, H245CommunicationTable[i].mediaChannel.u.ip.network); } else (*ppSessionTable)->SessionInfoArray[i].pRTPAddr = NULL; if ((H245CommunicationTable[i].mediaControlChannelPresent) && ((H245CommunicationTable[i].mediaControlChannel.type == H245_IP_MULTICAST) || (H245CommunicationTable[i].mediaControlChannel.type == H245_IP_UNICAST))) { (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr = (PCC_ADDR)MemAlloc(sizeof(CC_ADDR)); if ((*ppSessionTable)->SessionInfoArray[i].pRTCPAddr == NULL) { if ((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString != NULL) MemFree((*ppSessionTable)->SessionInfoArray[i].SessionDescription.pOctetString); H245FreeCap((*ppSessionTable)->SessionInfoArray[i].pTermCap); if ((*ppSessionTable)->SessionInfoArray[i].pRTPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[i].pRTPAddr); for (j = 0; j < i; j++) { H245FreeCap((*ppSessionTable)->SessionInfoArray[j].pTermCap); if ((*ppSessionTable)->SessionInfoArray[j].pRTPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTPAddr); if ((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr != NULL) MemFree((*ppSessionTable)->SessionInfoArray[j].pRTCPAddr); } MemFree((*ppSessionTable)->SessionInfoArray); MemFree(*ppSessionTable); return CC_NO_MEMORY; } (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->nAddrType = CC_IP_BINARY; if (H245CommunicationTable[i].mediaChannel.type == H245_IP_MULTICAST) (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->bMulticast = TRUE; else (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->bMulticast = FALSE; (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.wPort = H245CommunicationTable[i].mediaControlChannel.u.ip.tsapIdentifier; H245IPNetworkToHost(&(*ppSessionTable)->SessionInfoArray[i].pRTCPAddr->Addr.IP_Binary.dwAddr, H245CommunicationTable[i].mediaControlChannel.u.ip.network); } else (*ppSessionTable)->SessionInfoArray[i].pRTCPAddr = NULL; } return CC_OK; }
HRESULT FreeH245CommunicationTable( H245_COMM_MODE_ENTRY_T H245CommunicationTable[], BYTE bCommunicationTableCount) { WORD i;
if (H245CommunicationTable == NULL) if (bCommunicationTableCount == 0) return CC_OK; else return CC_BAD_PARAM; else if (bCommunicationTableCount == 0) return CC_BAD_PARAM;
for (i = 0; i < bCommunicationTableCount; i++) if (H245CommunicationTable[i].pSessionDescription != NULL) MemFree(H245CommunicationTable[i].pSessionDescription); MemFree(H245CommunicationTable); return CC_OK; }
HRESULT _PrepareTermCapLists( PCONFERENCE pConference, WORD *pwListCount, PCC_TERMCAPLIST **ppTermCapList, PCC_TERMCAPDESCRIPTORS **ppTermCapDescriptorList, PCALL *pCallList[]) { WORD i; WORD wNumCalls; WORD wOffset; PCC_HCALL CallList; PCALL pCall;
ASSERT(pConference != NULL); ASSERT(pwListCount != NULL); ASSERT(ppTermCapList != NULL); ASSERT(ppTermCapDescriptorList != NULL); ASSERT(pCallList != NULL);
EnumerateCallsInConference(&wNumCalls, &CallList, pConference, ESTABLISHED_CALL);
if ((pConference->LocalEndpointAttached == DETACHED) && (wNumCalls > 0)) wOffset = 0; else // LocalEndpointAttached is either UNATTACHED or ATTACHED, or there are no calls
// in the conference; in the latter case, we need to have some term caps in
// order to form the conference term cap set (which cannot be empty)
wOffset = 1;
*pwListCount = (WORD)(wNumCalls + wOffset);
*ppTermCapList = (PCC_TERMCAPLIST *)MemAlloc(sizeof(PCC_TERMCAPLIST) * (*pwListCount)); if (*ppTermCapList == NULL) { MemFree(CallList); return CC_NO_MEMORY; }
*ppTermCapDescriptorList = (PCC_TERMCAPDESCRIPTORS *)MemAlloc(sizeof(PCC_TERMCAPDESCRIPTORS) * (*pwListCount)); if (*ppTermCapDescriptorList == NULL) { MemFree(CallList); MemFree(*ppTermCapList); return CC_NO_MEMORY; }
*pCallList = (PCALL *)MemAlloc(sizeof(PCALL) * (*pwListCount)); if (*pCallList == NULL) { MemFree(CallList); MemFree(*ppTermCapList); MemFree(*ppTermCapDescriptorList); return CC_NO_MEMORY; }
// Fill in pTermCapList and pTermCapDescriptorList
if (wOffset == 1) { // The local endpoint is attached to the conference, so fill in the first
// slot in both lists with the local term cap and descriptor lists
(*ppTermCapList)[0] = pConference->pLocalH245TermCapList; (*ppTermCapDescriptorList)[0] = pConference->pLocalH245TermCapDescriptors; } for (i = 0; i < wNumCalls; i++) { if (LockCall(CallList[i], &pCall) == CC_OK) { (*ppTermCapList)[i+wOffset] = pCall->pPeerH245TermCapList; (*ppTermCapDescriptorList)[i+wOffset] = pCall->pPeerH245TermCapDescriptors; (*pCallList)[i] = pCall; } else { (*ppTermCapList)[i+wOffset] = NULL; (*ppTermCapDescriptorList)[i+wOffset] = NULL; (*pCallList)[i] = NULL; } } for (i = 0; i < wOffset; i++) (*pCallList)[wNumCalls+i] = NULL; MemFree(CallList); return CC_OK; }
HRESULT _FreeTermCapLists( WORD wListCount, PCC_TERMCAPLIST *pTermCapList, PCC_TERMCAPDESCRIPTORS *pTermCapDescriptorList, PCALL pCallList[]) { WORD i;
for (i = 0; i < wListCount; i++) if (pCallList[i] != NULL) UnlockCall(pCallList[i]); if (pTermCapList != NULL) MemFree(pTermCapList); if (pTermCapDescriptorList != NULL) MemFree(pTermCapDescriptorList); MemFree(pCallList); return CC_OK; }
HRESULT CreateConferenceSessionTable( PCONFERENCE pConference, BOOL *pbSessionTableChanged) { HRESULT status; PCALL *pCallList; PCC_TERMCAPLIST *pTermCapList; PCC_TERMCAPDESCRIPTORS *pTermCapDescriptorList; WORD wListCount;
ASSERT(pConference != NULL);
if (pConference->bSessionTableInternallyConstructed == TRUE) { status = FreeConferenceSessionTable(pConference); if (status != CC_OK) return status; pConference->bSessionTableInternallyConstructed = FALSE; }
status = _PrepareTermCapLists(pConference, &wListCount, &pTermCapList, &pTermCapDescriptorList, &pCallList); if (status != CC_OK) return status;
status = pConference->SessionTableConstructor( pConference->hConference, pConference->dwConferenceToken, TRUE, // bCreate
pbSessionTableChanged, wListCount, pTermCapList, pTermCapDescriptorList, &pConference->pSessionTable);
_FreeTermCapLists(wListCount, pTermCapList, pTermCapDescriptorList, pCallList); return status; }
HRESULT FreeConferenceSessionTable( PCONFERENCE pConference) { HRESULT status;
ASSERT(pConference != NULL);
if (pConference->bSessionTableInternallyConstructed) status = DefaultSessionTableConstructor( pConference->hConference, pConference->dwConferenceToken, FALSE, // bCreate
NULL, // pbSessionTableChanged
0, // wListCount
NULL, // pTermCapList[]
NULL, // pTermCapDescriptors[]
&pConference->pSessionTable); else status = pConference->SessionTableConstructor( pConference->hConference, pConference->dwConferenceToken, FALSE, // bCreate
NULL, // pbSessionTableChanged
0, // wListCount
NULL, // pTermCapList[]
NULL, // pTermCapDescriptors[]
&pConference->pSessionTable); pConference->pSessionTable = NULL; return status; }
HRESULT CreateConferenceTermCaps( PCONFERENCE pConference, BOOL *pbTermCapsChanged) { HRESULT status; WORD wListCount; PCALL *pCallList; PCC_TERMCAPLIST *pInTermCapList; PCC_TERMCAPDESCRIPTORS *pInTermCapDescriptors;
ASSERT(pConference != NULL);
if (pConference->pConferenceH245H2250MuxCapability != NULL) H245FreeCap(pConference->pConferenceH245H2250MuxCapability);
ASSERT(pConference->pLocalH245H2250MuxCapability != NULL); status = H245CopyCap(&pConference->pConferenceH245H2250MuxCapability, pConference->pLocalH245H2250MuxCapability); if (status != H245_ERROR_OK) return status;
status = _PrepareTermCapLists(pConference, &wListCount, &pInTermCapList, &pInTermCapDescriptors, &pCallList); if (status != CC_OK) return status;
status = UnregisterTermCapListFromH245(pConference, pConference->pConferenceTermCapList); if (status != CC_OK) return status;
status = UnregisterTermCapDescriptorsFromH245(pConference, pConference->pConferenceTermCapDescriptors); if (status != CC_OK) return status;
status = pConference->TermCapConstructor( pConference->hConference, pConference->dwConferenceToken, TRUE, // bCreate
pbTermCapsChanged, wListCount, pInTermCapList, pInTermCapDescriptors, &pConference->pConferenceTermCapList, &pConference->pConferenceTermCapDescriptors);
_FreeTermCapLists(wListCount, pInTermCapList, pInTermCapDescriptors, pCallList); return status; }
HRESULT FreeConferenceTermCaps( PCONFERENCE pConference) { HRESULT status;
ASSERT(pConference != NULL);
status = pConference->TermCapConstructor( pConference->hConference, pConference->dwConferenceToken, FALSE, // bCreate
NULL, // pbTermCapsChanged
0, // wListCount
NULL, // pInTermCapList[]
NULL, // pInTermCapDescriptors[]
&pConference->pConferenceTermCapList, &pConference->pConferenceTermCapDescriptors); pConference->pConferenceTermCapList = NULL; pConference->pConferenceTermCapDescriptors = NULL; return status; }
HRESULT FindEnqueuedRequest( PCALL_QUEUE pQueueHead, CC_HCALL hEnqueuedCall) { PCALL_QUEUE pQueueItem;
ASSERT(hEnqueuedCall != CC_INVALID_HANDLE);
pQueueItem = pQueueHead;
while (pQueueItem != NULL) { if (pQueueItem->hCall == hEnqueuedCall) break; pQueueItem = pQueueItem->pNext; } if (pQueueItem == NULL) return CC_BAD_PARAM; else return CC_OK; }
HRESULT EnqueueRequest( PCALL_QUEUE *ppQueueHead, CC_HCALL hEnqueuedCall) { PCALL_QUEUE pQueueItem;
ASSERT(ppQueueHead != NULL); ASSERT(hEnqueuedCall != CC_INVALID_HANDLE);
// Make sure we're not enqueuing a duplicate request
pQueueItem = *ppQueueHead; while (pQueueItem != NULL) { if (pQueueItem->hCall == hEnqueuedCall) return CC_OK; pQueueItem = pQueueItem->pNext; }
pQueueItem = (PCALL_QUEUE)MemAlloc(sizeof(CALL_QUEUE)); if (pQueueItem == NULL) return CC_NO_MEMORY; pQueueItem->hCall = hEnqueuedCall; pQueueItem->pPrev = NULL; pQueueItem->pNext = *ppQueueHead; if (*ppQueueHead != NULL) (*ppQueueHead)->pPrev = pQueueItem; *ppQueueHead = pQueueItem; return CC_OK; }
HRESULT DequeueRequest( PCALL_QUEUE *ppQueueHead, PCC_HCALL phEnqueuedCall)
{ PCALL_QUEUE pQueueItem;
ASSERT(ppQueueHead != NULL);
if (phEnqueuedCall != NULL) *phEnqueuedCall = CC_INVALID_HANDLE;
if (*ppQueueHead == NULL) return CC_BAD_PARAM;
pQueueItem = *ppQueueHead; *ppQueueHead = (*ppQueueHead)->pNext; if (*ppQueueHead != NULL) (*ppQueueHead)->pPrev = NULL;
if (phEnqueuedCall != NULL) *phEnqueuedCall = pQueueItem->hCall; MemFree(pQueueItem); return CC_OK; }
HRESULT DequeueSpecificRequest( PCALL_QUEUE *ppQueueHead, CC_HCALL hEnqueuedCall) { PCALL_QUEUE pQueueItem;
ASSERT(ppQueueHead != NULL); ASSERT(hEnqueuedCall != CC_INVALID_HANDLE);
pQueueItem = *ppQueueHead; while (pQueueItem != NULL) if (pQueueItem->hCall == hEnqueuedCall) break; else pQueueItem = pQueueItem->pNext;
if (pQueueItem == NULL) return CC_BAD_PARAM;
if (pQueueItem->pNext != NULL) pQueueItem->pNext->pPrev = pQueueItem->pPrev; if (pQueueItem->pPrev == NULL) *ppQueueHead = pQueueItem->pNext; else pQueueItem->pPrev->pNext = pQueueItem->pNext;
MemFree(pQueueItem); return CC_OK; }
|