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

2804 lines
79 KiB
C
Raw Blame History

This file contains invisible Unicode characters

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

/****************************************************************************
*
* $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;
}