windows-nt/Source/XPSP1/NT/net/tapi/skywalker/cc/callcont/gkiman.c
2020-09-26 16:20:57 +08:00

2861 lines
76 KiB
C

/****************************************************************************
*
* $Archive: S:\sturgeon\src\callcont\vcs\gkiman.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) 1996 Intel Corporation.
*
* $Revision: 1.77.1.6 $
* $Date: 21 Aug 1997 16:56:32 $
* $Author: Helgebal $
*
* Deliverable:
*
* Abstract:
*
* Notes:
*
* Much effort has gone into working around the following constraints of
* the GKI interface:
* 1) Only one admission request can be pending at a time. This is because
* the hCall is unknown until it completes.
* 2) Only one bandwidth request per call can be pending at a time.
* 3) Any pending bandwidth request must complete before issuing a
* disengage request.
* 4) Any calls must be disengaged before issuing a deregistration request.
*
***************************************************************************/
#ifdef GATEKEEPER
#pragma warning ( disable : 4115 4201 4214 4514)
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include "incommon.h"
#include "ccerror.h"
#include "isrg.h"
#include "gkiexp.h"
#include "callman2.h"
#ifdef FORCE_SERIALIZE_CALL_CONTROL
#include "cclock.h"
#endif // FORCE_SERIALIZE_CALL_CONTROL
#pragma warning ( default : 4115 4201 4214)
#if defined(DBG)
void GKDbgPrint(DWORD dwLevel,
#ifdef UNICODE_TRACE
LPTSTR pszFormat,
#else
LPSTR pszFormat,
#endif
...);
#define GKDBG(_x_) GKDbgPrint _x_
#else
#define GKDBG(_x_)
#endif
extern HINSTANCE ghCallControlInstance;
#define Malloc(size) GlobalAlloc(GMEM_FIXED, size)
#define ReAlloc(p, size) GlobalReAlloc(p, GMEM_FIXED, size)
#define Free(p) GlobalFree(p)
#ifdef FORCE_SERIALIZE_CALL_CONTROL
#define EnterCallControlTop() {CCLOCK_AcquireLock();}
#define LeaveCallControlTop(f) {HRESULT stat; \
stat = f; \
CCLOCK_RelinquishLock(); \
return stat;}
#else
#define EnterCallControlTop()
#define LeaveCallControlTop(f) {HRESULT stat; \
stat = f; \
return stat;}
#endif
#define DEFAULT_LISTEN_HANDLE 0xFFFFFFFF
#define GKIMAN_BASE WM_USER
#define MIN_BANDWIDTH 1
#define MAX_BANDWIDTH (0xFFFFFFFF / 100)
#define GKI_ADMITTING_HANDLE ((HANDLE)-1)
#define GKI_BYPASS_HANDLE ((HANDLE)-2)
// GKI Manager state
#define STATE_START 0
#define STATE_CLASS_REGISTERED 1
#define STATE_WINDOW_CREATED 2
#define STATE_REGISTERING 3
#define STATE_REGISTERING_REREG 4
#define STATE_REGISTERING_UNREG 5
#define STATE_REGISTERED 6
#define STATE_ADMITTING 7
#define STATE_ADMITTING_REREG 8
#define STATE_ADMITTING_UNREG 9
#define STATE_DISENGAGING 10
#define STATE_DISENGAGING_REREG 11
#define STATE_UNREGISTERING 12
#define STATE_UNREGISTERING_REREG 13
#define STATE_REG_BYPASS 14
typedef HRESULT (*PGKI_RegistrationRequest)(long lVersion,
SeqTransportAddr *pCallSignalAddr,
EndpointType *pTerminalType,
SeqAliasAddr *pAliasAddr,
HWND hWnd,
WORD wBaseMessage,
unsigned short usRegistrationTransport /* = ipAddress_chosen */);
typedef HRESULT (*PGKI_UnregistrationRequest)(void);
typedef HRESULT (*PGKI_LocationRequest)(SeqAliasAddr *pLocationInfo);
typedef HRESULT (*PGKI_AdmissionRequest)(unsigned short usCallTypeChoice,
SeqAliasAddr *pDestinationInfo,
TransportAddress *pDestCallSignalAddress,
SeqAliasAddr *pDextExtraCallInfo,
BandWidth bandWidth,
ConferenceIdentifier *pConferenceID,
BOOL activeMC,
BOOL answerCall,
unsigned short usCallTransport /* = ipAddress_chosen */);
typedef HRESULT (*PGKI_BandwidthRequest)(HANDLE hModCall,
unsigned short usCallTypeChoice,
BandWidth bandWidth);
typedef HRESULT (*PGKI_DisengageRequest)(HANDLE hCall);
typedef HRESULT (*PGKI_CleanupRequest)(void);
HRESULT Q931CopyAliasNames(PCC_ALIASNAMES *ppTarget, PCC_ALIASNAMES pSource);
HRESULT Q931FreeAliasNames(PCC_ALIASNAMES pSource);
#define CopyAliasNames Q931CopyAliasNames
#define FreeAliasNames Q931FreeAliasNames
typedef struct _LISTEN
{
struct _LISTEN * pNext;
PCC_ALIASNAMES pAliasNames;
DWORD hListen;
DWORD dwAddr;
WORD wPort;
} LISTEN, *PLISTEN;
//
// GKI Manager Global Data
//
CRITICAL_SECTION GkiLock;
const char szClassName[] = "GkiManWndClass";
HWND hwndGki = 0;
ATOM atomGki = 0;
unsigned int uGkiState = STATE_START;
PLISTEN pListenList = NULL;
unsigned int uGkiCalls = 0;
unsigned int uPendingDisengages = 0;
HINSTANCE hGkiDll = 0;
PGKI_RegistrationRequest pGKI_RegistrationRequest = NULL;
PGKI_UnregistrationRequest pGKI_UnregistrationRequest = NULL;
PGKI_LocationRequest pGKI_LocationRequest = NULL;
PGKI_AdmissionRequest pGKI_AdmissionRequest = NULL;
PGKI_BandwidthRequest pGKI_BandwidthRequest = NULL;
PGKI_DisengageRequest pGKI_DisengageRequest = NULL;
PGKI_CleanupRequest pGKI_CleanupRequest = NULL;
HRESULT ValidateCall(DWORD hCall);
HRESULT LastGkiError = CC_GKI_STATE;
//
// Forward declarations
//
LONG APIENTRY GkiWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam);
//
// Helper subroutines
//
#ifdef DBG
typedef struct _GKIMAP
{
HRESULT hResult;
char * pString;
} GKIMAP;
GKIMAP GkiErrorNames[] =
{
GKI_OK, "GKI_OK",
GKI_EXIT_THREAD, "GKI_EXIT_THREAD",
GKI_REDISCOVER, "GKI_REDISCOVER",
GKI_DELETE_CALL, "GKI_DELETE_CALL",
GKI_GCF_RCV, "GKI_GCF_RCV",
GKI_NO_MEMORY, "GKI_NO_MEMORY",
GKI_NO_THREAD, "GKI_NO_THREAD",
GKI_HANDLE_ERROR, "GKI_HANDLE_ERROR",
GKI_ALREADY_REG, "GKI_ALREADY_REG",
GKI_VERSION_ERROR, "GKI_VERSION_ERROR",
GKI_ENCODER_ERROR, "GKI_ENCODER_ERROR",
GKI_NOT_REG, "GKI_NOT_REG",
GKI_BUSY, "GKI_BUSY",
GKI_NO_TA_ERROR, "GKI_NO_TA_ERROR",
GKI_NO_RESPONSE, "GKI_NO_RESPONSE",
GKI_DECODER_ERROR, "GKI_DECODER_ERROR",
};
char *StateNames[] =
{
"STATE_START",
"STATE_CLASS_REGISTERED",
"STATE_WINDOW_CREATED",
"STATE_REGISTERING",
"STATE_REGISTERING_REREG",
"STATE_REGISTERING_UNREG",
"STATE_REGISTERED",
"STATE_ADMITTING",
"STATE_ADMITTING_REREG",
"STATE_ADMITTING_UNREG",
"STATE_DISENGAGING",
"STATE_DISENGAGING_REREG",
"STATE_UNREGISTERING",
"STATE_UNREGISTERING_REREG",
"STATE_REG_BYPASS",
};
char *CallStateNames[] =
{
"GCS_START",
"GCS_WAITING",
"GCS_ADMITTING",
"GCS_ADMITTING_CLOSE_PENDING",
"GCS_ADMITTED",
"GCS_CHANGING",
"GCS_CHANGING_CLOSE_PENDING",
"GCS_DISENGAGING",
};
char szBuffer[128];
char * GkiErrorName(char *szFormat, HRESULT hResult)
{
register int nIndex = sizeof(GkiErrorNames) / sizeof(GkiErrorNames[0]);
char szTemp[32];
while (nIndex > 0)
{
if (GkiErrorNames[--nIndex].hResult == hResult)
{
wsprintf(szBuffer, szFormat, GkiErrorNames[nIndex].pString);
return szBuffer;
}
}
wsprintf(szTemp, "Unknown(0x%x)", hResult);
wsprintf(szBuffer, szFormat, szTemp);
return szBuffer;
} // GkiErrorName()
char * StateName(char *szFormat, unsigned uState)
{
char szTemp[32];
if (uState < (sizeof(StateNames)/sizeof(StateNames[0])))
{
wsprintf(szBuffer, szFormat, StateNames[uState]);
}
else
{
wsprintf(szTemp, "Unknown(%d)", uState);
wsprintf(szBuffer, szFormat, szTemp);
}
return szBuffer;
} // StateName()
char * CallStateName(char *szFormat, unsigned uCallState)
{
char szTemp[32];
if (uCallState <= (sizeof(CallStateNames)/sizeof(CallStateNames[0])))
{
wsprintf(szBuffer, szFormat, CallStateNames[uCallState]);
}
else
{
wsprintf(szTemp, "Unknown(%d)", uCallState);
wsprintf(szBuffer, szFormat, szTemp);
}
return szBuffer;
} // CallStateName()
#else
#define GkiErrorName(x,y) ""
#define StateName(x,y) ""
#define CallStateName(x,y) ""
#endif // DBG
HRESULT MapRegistrationRejectReason(register UINT uReason)
{
register HRESULT lReason;
// TBD - Map reason code into CC_xxx HRESULT
switch (uReason)
{
case discoveryRequired_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case RgstrtnRjctRsn_invldRvsn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case invalidCallSignalAddress_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case invalidRASAddress_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case duplicateAlias_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case invalidTerminalType_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case RgstrtnRjctRsn_undfndRsn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case transportNotSupported_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
default:
lReason = CC_GATEKEEPER_REFUSED;
} // switch
return lReason;
} // MapRegistrationRejectReason()
HRESULT MapAdmissionRejectReason(register UINT uReason)
{
register HRESULT lReason;
// TBD - Map reason code into CC_xxx HRESULT
switch (uReason)
{
case calledPartyNotRegistered_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case ARRn_invldPrmssn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case AdmssnRjctRsn_rqstDnd_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case AdmssnRjctRsn_undfndRsn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case callerNotRegistered_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case routeCallToGatekeeper_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case invldEndpntIdntfr_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case AdmssnRjctRsn_rsrcUnvlbl_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
default:
lReason = CC_GATEKEEPER_REFUSED;
} // switch
return lReason;
} // MapAdmissionRejectReason()
HRESULT MapBandwidthRejectReason(register UINT uReason)
{
register HRESULT lReason;
// TBD - Map reason code into CC_xxx HRESULT
switch (uReason)
{
case notBound_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case invalidConferenceID_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case BndRjctRsn_invldPrmssn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case insufficientResources_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case BndRjctRsn_invldRvsn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
case BndRjctRsn_undfndRsn_chosen:
lReason = CC_GATEKEEPER_REFUSED;
break;
default:
lReason = CC_GATEKEEPER_REFUSED;
} // switch
return lReason;
} // MapBandwidthRejectReason()
/*
* NOTES
* GkiLock must be locked before calling this routine!
*/
static PLISTEN ListenEnqueue(register PLISTEN pListen)
{
if (pListenList && pListenList->hListen == DEFAULT_LISTEN_HANDLE)
{
PLISTEN pDefaultListen = pListenList;
pListenList = pListenList->pNext;
Free(pDefaultListen);
}
pListen->pNext = pListenList;
return pListenList = pListen;
} // ListenEnqueue()
/*
* NOTES
* GkiLock must be locked before calling this routine!
*/
static PLISTEN ListenDequeue(register DWORD hListen)
{
register PLISTEN pListen = pListenList;
register PLISTEN pListenPrev;
if (pListen)
{
if (pListen->hListen == hListen)
{
pListenList = pListen->pNext;
}
else
{
do
{
pListenPrev = pListen;
pListen = pListen->pNext;
} while (pListen && pListen->hListen != hListen);
if (pListen)
{
pListenPrev->pNext = pListen->pNext;
}
}
}
return pListen;
} // ListenDequeue()
/*
* NOTES
* Since the pGkiCall is locked, we don't need a critical section
* around the queue manipulation code.
*/
static PBWREQ BwReqEnqueue(register PGKICALL pGkiCall, register PBWREQ pBwReq)
{
pBwReq->pNext = NULL;
if (pGkiCall->pBwReqHead)
{
pGkiCall->pBwReqTail->pNext = pBwReq;
}
else
{
pGkiCall->pBwReqHead = pBwReq;
}
return pGkiCall->pBwReqTail = pBwReq;
} // BwReqEnqueue()
/*
* NOTES
* Since the pGkiCall is locked, we don't need a critical section
* around the queue manipulation code.
*/
static PBWREQ BwReqDequeue(register PGKICALL pGkiCall)
{
register PBWREQ pBwReq = pGkiCall->pBwReqHead;
if (pBwReq)
{
pGkiCall->pBwReqHead = pBwReq->pNext;
}
return pBwReq;
} // BwReqDequeue()
DWORD GetIpAddress(void)
{
DWORD dwAddr;
char szHostName[128];
if (gethostname(szHostName, sizeof(szHostName)) == 0)
{
struct hostent *pHostent;
pHostent = gethostbyname(szHostName);
if (pHostent != NULL)
{
ASSERT(pHostent->h_addrtype == AF_INET);
dwAddr = *((DWORD *)pHostent->h_addr_list[0]);
return ntohl(dwAddr);
}
}
return INADDR_ANY;
} // GetIpAddress()
// Caveat: *pAlias should be initialized to all 0 before calling!
static HRESULT CopyAliasItem(SeqAliasAddr *pAlias, PCC_ALIASITEM pAliasItem)
{
unsigned int uDigit;
unsigned int uPrefixLength;
unsigned int uDataLength;
if (pAliasItem->pData == NULL || pAliasItem->wDataLength == 0)
return CC_BAD_PARAM;
if (pAliasItem->pPrefix)
{
// Strip off terminating NULs if included in prefix length
uPrefixLength = pAliasItem->wPrefixLength;
while (uPrefixLength && pAliasItem->pPrefix[uPrefixLength - 1] == 0)
--uPrefixLength;
}
else
{
uPrefixLength = 0;
}
uDataLength = pAliasItem->wDataLength;
switch (pAliasItem->wType)
{
case CC_ALIAS_H323_ID:
pAlias->value.choice = h323_ID_chosen;
pAlias->value.u.h323_ID.value = Malloc((uPrefixLength + uDataLength) * sizeof(pAliasItem->pData[0]));
if (pAlias->value.u.h323_ID.value == NULL)
{
GKDBG((1, "CopyAliasItem: Could not allocate %d bytes memory",
(uPrefixLength + uDataLength) * sizeof(pAliasItem->pData[0])));
return CC_NO_MEMORY;
}
if (uPrefixLength)
{
memcpy(&pAlias->value.u.h323_ID.value[0],
pAliasItem->pPrefix,
uPrefixLength * sizeof(pAliasItem->pPrefix[0]));
memcpy(&pAlias->value.u.h323_ID.value[uPrefixLength],
pAliasItem->pData,
uDataLength * sizeof(pAliasItem->pData[0]));
}
else
{
memcpy(&pAlias->value.u.h323_ID.value[0],
pAliasItem->pData,
uDataLength * sizeof(pAliasItem->pData[0]));
}
pAlias->value.u.h323_ID.length = (unsigned short)(uPrefixLength + uDataLength);
break;
case CC_ALIAS_H323_PHONE:
pAlias->value.choice = e164_chosen;
if (uPrefixLength)
{
for (uDigit = 0; uDigit < uPrefixLength; ++uDigit)
{
pAlias->value.u.e164[uDigit] = (char)pAliasItem->pPrefix[uDigit];
}
for (uDigit = 0; uDigit < uDataLength; ++uDigit)
{
pAlias->value.u.e164[uDigit + uPrefixLength] = (char)pAliasItem->pData[uDigit];
}
}
else
{
for (uDigit = 0; uDigit < uDataLength; ++uDigit)
{
pAlias->value.u.e164[uDigit] = (char)pAliasItem->pData[uDigit];
}
}
break;
default:
GKDBG((1, "CopyAliasItem: Bad alias name type %d", pAliasItem->wType));
return CC_BAD_PARAM;
} // switch
return NOERROR;
} // CopyAliasItem()
/*
* NOTES
* Must have Call locked before calling!
*/
static void GkiAllocCall(PGKICALL pGkiCall, HANDLE hGkiCall)
{
ASSERT(pGkiCall != NULL);
ASSERT(hGkiCall != 0);
ASSERT(hGkiCall != GKI_ADMITTING_HANDLE);
pGkiCall->hGkiCall = hGkiCall;
pGkiCall->uGkiCallState = GCS_ADMITTED;
++uGkiCalls;
GKDBG((1, "GkiAllocCall: uGkiCalls = %d", uGkiCalls));
} // GkiAllocCall()
/*
* NOTES
* Must have Call locked before calling!
*/
static HRESULT GkiCancelCall(PGKICALL pGkiCall, void *pConference)
{
DWORD hCall;
ASSERT(pGkiCall != NULL);
pConference = pConference; // Disable compiler warning
hCall = pGkiCall->hCall;
GKDBG((1, CallStateName("GkiCancelCall <- Call State = %s", pGkiCall->uGkiCallState), 0));
switch (pGkiCall->uGkiCallState)
{
case GCS_START:
break;
case GCS_WAITING:
ASSERT(pGkiCall->hGkiCall == 0);
if (pGkiCall->bAnswerCall)
AcceptCallReject(pGkiCall->pCall, pConference, CC_GATEKEEPER_REFUSED);
else
PlaceCallReject (pGkiCall->pCall, pConference, CC_GATEKEEPER_REFUSED);
break;
case GCS_ADMITTING:
case GCS_ADMITTING_CLOSE_PENDING:
ASSERT(pGkiCall->hGkiCall == GKI_ADMITTING_HANDLE);
if (pGkiCall->bAnswerCall)
AcceptCallReject(pGkiCall->pCall, pConference, CC_GATEKEEPER_REFUSED);
else
PlaceCallReject (pGkiCall->pCall, pConference, CC_GATEKEEPER_REFUSED);
break;
case GCS_ADMITTED:
case GCS_CHANGING:
case GCS_CHANGING_CLOSE_PENDING:
case GCS_DISENGAGING:
ASSERT(pGkiCall->hGkiCall != 0);
ASSERT(pGkiCall->hGkiCall != GKI_ADMITTING_HANDLE);
Disengage(pGkiCall->pCall);
return NOERROR;
default:
GKDBG((1, "GkiCancelCall: Invalid call state %d", pGkiCall->uGkiCallState));
} // switch
if (ValidateCall(hCall) == NOERROR && pGkiCall->uGkiCallState != GCS_START)
{
GkiFreeCall(pGkiCall);
}
GKDBG((1, CallStateName("GkiCancelCall -> Call State = %s", pGkiCall->uGkiCallState), 0));
return NOERROR;
} // GkiCancelCall()
/*
* NOTES
* Must have Call locked before calling!
*/
static HRESULT GkiCancelAdmitting(PGKICALL pGkiCall, void *pConference)
{
ASSERT(pGkiCall != NULL);
pConference = pConference; // Disable compiler warning
GKDBG((1, CallStateName("GkiCancelAdmitting <- Call State = %s", pGkiCall->uGkiCallState), 0));
switch (pGkiCall->uGkiCallState)
{
case GCS_ADMITTING:
ASSERT(pGkiCall->hGkiCall == GKI_ADMITTING_HANDLE);
pGkiCall->hGkiCall = 0;
pGkiCall->uGkiCallState = GCS_WAITING;
break;
case GCS_ADMITTING_CLOSE_PENDING:
ASSERT(pGkiCall->hGkiCall == GKI_ADMITTING_HANDLE);
GkiFreeCall(pGkiCall);
break;
} // switch
GKDBG((1, CallStateName("GkiCancelAdmitting -> Call State = %s", pGkiCall->uGkiCallState), 0));
return NOERROR;
} // GkiCancelAdmitting()
/*
* NOTES
* Must have Call locked before calling!
*/
static HRESULT CheckPendingBandwidth(PGKICALL pGkiCall);
static HRESULT GatekeeperNotFound(PGKICALL pGkiCall, void *pConference)
{
ASSERT(pGkiCall != NULL);
ASSERT(pConference != NULL);
GKDBG((1, CallStateName("GatekeeperNotFound <- Call State = %s", pGkiCall->uGkiCallState), 0));
switch (pGkiCall->uGkiCallState)
{
case GCS_START:
case GCS_ADMITTED:
break;
case GCS_WAITING:
case GCS_ADMITTING:
GkiOpenCall(pGkiCall, pConference);
break;
case GCS_ADMITTING_CLOSE_PENDING:
case GCS_CHANGING_CLOSE_PENDING:
case GCS_DISENGAGING:
GkiCloseCall(pGkiCall);
break;
case GCS_CHANGING:
pGkiCall->uGkiCallState = GCS_ADMITTED;
pGkiCall->uBandwidthAllocated = MAX_BANDWIDTH;
CheckPendingBandwidth(pGkiCall);
break;
default:
GKDBG((1, "GatekeeperNotFound: Invalid call state %d", pGkiCall->uGkiCallState));
} // switch
GKDBG((1, CallStateName("GatekeeperNotFound -> Call State = %s", pGkiCall->uGkiCallState), 0));
return NOERROR;
} // GatekeeperNotFound()
/*
* NOTES
* GkiLock must be locked before calling this routine!
*/
static HRESULT GkiRegister(void)
{
register HRESULT status = NOERROR;
ASSERT(pListenList != NULL);
switch (uGkiState)
{
case STATE_START:
// Register window class
{
WNDCLASS wndclass = { 0, GkiWndProc, 0, 0, 0, 0, 0, 0, NULL, szClassName };
atomGki = RegisterClass(&wndclass);
if (atomGki == 0)
{
status = HRESULT_FROM_WIN32(GetLastError());
GKDBG((1, "GkiRegister: Error 0x%x registering class", status));
break;
}
}
uGkiState = STATE_CLASS_REGISTERED;
// Fall-through to next case
case STATE_CLASS_REGISTERED:
// Create window to receive GKI messages
hwndGki = CreateWindow(szClassName, "", WS_OVERLAPPED, 0, 0, 0, 0, 0, 0, 0, NULL);
if (hwndGki == 0)
{
status = HRESULT_FROM_WIN32(GetLastError());
GKDBG((1, "GkiRegister: Error 0x%x creating window", status));
break;
}
uGkiState = STATE_WINDOW_CREATED;
// Fall-through to next case
case STATE_WINDOW_CREATED:
{
PLISTEN pListen;
unsigned uListens = 0;
unsigned uAliasNames = 0;
SeqTransportAddr *pTransportAddrs;
SeqAliasAddr *pAliasAddrs;
PCC_ALIASITEM pAliasItem;
unsigned uIndex;
unsigned uDigit;
EndpointType TerminalType = {0};
// Count Transport Addresses and Alias Names
pListen = pListenList;
while (pListen)
{
// Count the Transport Address
++uListens;
if (pListen->pAliasNames)
{
// Count the Alias Names
uAliasNames += pListen->pAliasNames->wCount;
}
pListen = pListen->pNext;
}
pTransportAddrs = Malloc(uListens * sizeof(*pTransportAddrs));
if (pTransportAddrs == NULL)
{
GKDBG((1, "GkiRegister: Could not allocate %d Transport Addresses", uListens));
return CC_NO_MEMORY;
}
if (uAliasNames)
{
pAliasAddrs = Malloc(uAliasNames * sizeof(*pAliasAddrs));
if (pAliasAddrs == NULL)
{
Free(pTransportAddrs);
GKDBG((1, "GkiRegister: Could not allocate %d Alias Addresses", uAliasNames));
return CC_NO_MEMORY;
}
}
else
{
pAliasAddrs = NULL;
}
pListen = pListenList;
uListens = 0;
uAliasNames = 0;
while (pListen)
{
// Initialize a transport address
// TBD - throw out duplicates
pTransportAddrs[uListens].next = &pTransportAddrs[uListens + 1];
pTransportAddrs[uListens].value.choice = ipAddress_chosen;
pTransportAddrs[uListens].value.u.ipAddress.ip.length = 4;
*((DWORD *)pTransportAddrs[uListens].value.u.ipAddress.ip.value) = pListen->dwAddr;
pTransportAddrs[uListens].value.u.ipAddress.port = pListen->wPort;
// Add any alias names to list
// TBD - throw out duplicates
if (pListen->pAliasNames)
{
pAliasItem = pListen->pAliasNames->pItems;
for (uIndex = 0; uIndex < pListen->pAliasNames->wCount; ++uIndex, ++pAliasItem)
{
pAliasAddrs[uAliasNames].next = &pAliasAddrs[uAliasNames + 1];
switch (pAliasItem->wType)
{
case CC_ALIAS_H323_ID:
pAliasAddrs[uAliasNames].value.choice = h323_ID_chosen;
pAliasAddrs[uAliasNames].value.u.h323_ID.length = pAliasItem->wDataLength;
pAliasAddrs[uAliasNames].value.u.h323_ID.value = pAliasItem->pData;
break;
case CC_ALIAS_H323_PHONE:
pAliasAddrs[uAliasNames].value.choice = e164_chosen;
memset(pAliasAddrs[uAliasNames].value.u.e164, 0, sizeof(pAliasAddrs[uAliasNames].value.u.e164));
for (uDigit = 0; uDigit < pAliasItem->wDataLength; ++uDigit)
{
pAliasAddrs[uAliasNames].value.u.e164[uDigit] = (char)pAliasItem->pData[uDigit];
}
break;
default:
Free(pAliasAddrs);
Free(pTransportAddrs);
GKDBG((1, "GkiRegister: Bad alias name type %d",
pAliasItem->wType));
return CC_BAD_PARAM;
} // switch
++uAliasNames;
} // for
} // if
++uListens;
pListen = pListen->pNext;
} // while
pTransportAddrs[uListens - 1].next = NULL;
if (pAliasAddrs)
{
pAliasAddrs[uAliasNames - 1].next = NULL;
}
// Initialize TerminalType
TerminalType.bit_mask = terminal_present;
TerminalType.mc = TRUE;
uGkiState = STATE_REGISTERING;
GKDBG((1, "GKI_RegistrationRequest called...", 0));
status =
pGKI_RegistrationRequest(GKI_VERSION, // lVersion
pTransportAddrs, // pCallSignalAddr
&TerminalType, // pTerminalType
pAliasAddrs, // pRgstrtnRgst_trmnlAls
hwndGki, // hWnd
GKIMAN_BASE, // wBaseMessage
ipAddress_chosen); // usRegistrationTransport
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_RegistrationRequest returned %s", status), 0));
}
else
{
GKDBG((1, GkiErrorName("GKI_RegistrationRequest returned %s", status), 0));
uGkiState = STATE_WINDOW_CREATED;
}
if (pAliasAddrs)
Free(pAliasAddrs);
if (pTransportAddrs)
Free(pTransportAddrs);
}
break;
case STATE_REGISTERING:
case STATE_REGISTERING_REREG:
case STATE_REGISTERING_UNREG:
uGkiState = STATE_REGISTERING_REREG;
break;
case STATE_REGISTERED:
uGkiState = STATE_UNREGISTERING_REREG;
GKDBG((1, "GKI_UnregistrationRequest called...", 0));
status = pGKI_UnregistrationRequest();
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_UnregistrationRequest returned %s", status), 0));
}
else
{
GKDBG((1, GkiErrorName("GKI_UnregistrationRequest returned %s", status), 0));
uGkiState = STATE_REG_BYPASS;
ApplyToAllCalls(GatekeeperNotFound);
}
break;
case STATE_ADMITTING:
case STATE_ADMITTING_REREG:
case STATE_ADMITTING_UNREG:
uGkiState = STATE_ADMITTING_REREG;
break;
case STATE_DISENGAGING:
uGkiState = STATE_DISENGAGING_REREG;
break;
case STATE_DISENGAGING_REREG:
break;
case STATE_UNREGISTERING:
uGkiState = STATE_UNREGISTERING_REREG;
break;
case STATE_UNREGISTERING_REREG:
break;
case STATE_REG_BYPASS:
break;
default:
GKDBG((1, "GkiRegister: Invalid state %d", uGkiState));
status = LastGkiError;
} // switch
return status;
} // GkiRegister()
/*
* NOTES
* GkiLock must be locked before calling this routine!
*/
HRESULT GkiCloseCallNoError(PGKICALL pGkiCall, void *pConference)
{
ASSERT(pGkiCall != NULL);
pConference = pConference; // Disable compiler warning
if (pGkiCall->uGkiCallState != GCS_START)
GkiCloseCall(pGkiCall);
return NOERROR;
} // GkiCloseCallNoError()
HRESULT GkiUnregister(void)
{
register HRESULT status = NOERROR;
switch (uGkiState)
{
case STATE_REG_BYPASS:
ApplyToAllCalls(GkiCancelCall);
uGkiState = STATE_WINDOW_CREATED;
break;
case STATE_UNREGISTERING_REREG:
uGkiState = STATE_UNREGISTERING;
break;
case STATE_UNREGISTERING:
break;
case STATE_DISENGAGING_REREG:
if (uGkiCalls != 0 || uPendingDisengages != 0)
{
uGkiState = STATE_DISENGAGING;
}
else
{
uGkiState = STATE_REGISTERED;
return GkiUnregister();
}
break;
case STATE_DISENGAGING:
if (uGkiCalls == 0 && uPendingDisengages == 0)
{
uGkiState = STATE_REGISTERED;
return GkiUnregister();
}
break;
case STATE_ADMITTING_UNREG:
case STATE_ADMITTING_REREG:
case STATE_ADMITTING:
uGkiState = STATE_ADMITTING_UNREG;
break;
case STATE_REGISTERING_UNREG:
case STATE_REGISTERING_REREG:
case STATE_REGISTERING:
uGkiState = STATE_REGISTERING_UNREG;
break;
case STATE_REGISTERED:
if (uGkiCalls)
{
// Issue Disengage Request for every call
uGkiState = STATE_DISENGAGING;
ApplyToAllCalls(GkiCloseCallNoError);
break;
}
else
{
// Issue Unregistration Request
uGkiState = STATE_UNREGISTERING;
GKDBG((1, "GKI_UnregistrationRequest called...", 0));
status = pGKI_UnregistrationRequest();
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_UnregistrationRequest returned %s", status), 0));
}
else
{
GKDBG((1, GkiErrorName("GKI_UnregistrationRequest returned %s", status), 0));
uGkiState = STATE_WINDOW_CREATED;
}
}
break;
case STATE_WINDOW_CREATED:
case STATE_CLASS_REGISTERED:
case STATE_START:
GKDBG((1, StateName("GkiUnregister: Already in uninitialized state %s", uGkiState), 0));
status = LastGkiError;
break;
default:
GKDBG((1, "GkiUnregister: Invalid state %d", uGkiState));
status = LastGkiError;
} // switch
return status;
} // GkiUnregister()
void DeInitGkiManager(void)
{
register PLISTEN pListen;
EnterCriticalSection(&GkiLock);
#if 0
// TBD - When called from DllMain PROCESS_DETACH, this does not work because
// apparently the socket to the Gatekeeper has already been closed.
if (uGkiState != STATE_START)
{
GkiUnregister();
uGkiState = STATE_START;
}
#else
uGkiState = STATE_START;
#endif
while (pListenList)
{
pListen = pListenList;
pListenList = pListenList->pNext;
if (pListen->pAliasNames)
{
FreeAliasNames(pListen->pAliasNames);
}
Free(pListen);
}
pGKI_RegistrationRequest = NULL;
pGKI_UnregistrationRequest = NULL;
pGKI_LocationRequest = NULL;
pGKI_AdmissionRequest = NULL;
pGKI_BandwidthRequest = NULL;
pGKI_DisengageRequest = NULL;
if (hGkiDll)
{
if (pGKI_CleanupRequest)
pGKI_CleanupRequest();
#if defined(REMOVE_FROM_TSP)
FreeLibrary(hGkiDll);
#endif // REMOVE_FROM_TSP
}
pGKI_CleanupRequest = NULL;
LeaveCriticalSection(&GkiLock);
DeleteCriticalSection(&GkiLock);
DestroyWindow(hwndGki);
UnregisterClass(szClassName, 0);
} // DeInitGkiManager()
HRESULT InitGkiManager(void)
{
InitializeCriticalSection(&GkiLock);
#if defined(REMOVE_FROM_TSP)
hGkiDll = LoadLibrary("GKI.DLL");
if (hGkiDll == NULL)
{
DeInitGkiManager();
return CC_GKI_LOAD;
}
pGKI_RegistrationRequest = (PGKI_RegistrationRequest) GetProcAddress(hGkiDll, "GKI_RegistrationRequest");
pGKI_UnregistrationRequest = (PGKI_UnregistrationRequest)GetProcAddress(hGkiDll, "GKI_UnregistrationRequest");
pGKI_LocationRequest = (PGKI_LocationRequest) GetProcAddress(hGkiDll, "GKI_LocationRequest");
pGKI_AdmissionRequest = (PGKI_AdmissionRequest) GetProcAddress(hGkiDll, "GKI_AdmissionRequest");
pGKI_BandwidthRequest = (PGKI_BandwidthRequest) GetProcAddress(hGkiDll, "GKI_BandwidthRequest");
pGKI_DisengageRequest = (PGKI_DisengageRequest) GetProcAddress(hGkiDll, "GKI_DisengageRequest");
pGKI_CleanupRequest = (PGKI_CleanupRequest) GetProcAddress(hGkiDll, "GKI_CleanupRequest");
if (pGKI_RegistrationRequest == NULL ||
pGKI_UnregistrationRequest == NULL ||
pGKI_LocationRequest == NULL ||
pGKI_AdmissionRequest == NULL ||
pGKI_BandwidthRequest == NULL ||
pGKI_DisengageRequest == NULL ||
pGKI_CleanupRequest == NULL)
{
DeInitGkiManager();
return CC_GKI_LOAD;
}
#else // REMOVE_FROM_TSP
pGKI_RegistrationRequest = GKI_RegistrationRequest;
pGKI_UnregistrationRequest = GKI_UnregistrationRequest;
pGKI_LocationRequest = GKI_LocationRequest;
pGKI_AdmissionRequest = GKI_AdmissionRequest;
pGKI_BandwidthRequest = GKI_BandwidthRequest;
pGKI_DisengageRequest = GKI_DisengageRequest;
pGKI_CleanupRequest = GKI_CleanupRequest;
#endif // REMOVE_FROM_TSP
return NOERROR;
} // InitGkiManager()
//
// Entry Points
//
HRESULT GkiFreeCall(PGKICALL pGkiCall)
{
HRESULT status = NOERROR;
ASSERT(pGkiCall != NULL);
ASSERT(pGkiCall->uGkiCallState != GCS_START);
pGkiCall->hGkiCall = 0;
while (pGkiCall->pBwReqHead)
{
Free(BwReqDequeue(pGkiCall));
}
if (pGkiCall->pCalleeAliasNames)
{
Q931FreeAliasNames(pGkiCall->pCalleeAliasNames);
pGkiCall->pCalleeAliasNames = NULL;
}
if (pGkiCall->pCalleeExtraAliasNames != NULL)
{
Q931FreeAliasNames(pGkiCall->pCalleeExtraAliasNames);
pGkiCall->pCalleeExtraAliasNames = NULL;
}
switch (pGkiCall->uGkiCallState)
{
case GCS_START:
case GCS_WAITING:
break;
case GCS_ADMITTING:
ASSERT(uGkiState == STATE_ADMITTING);
switch (uGkiState)
{
case STATE_ADMITTING:
uGkiState = STATE_REGISTERED;
break;
} // switch
break;
case GCS_ADMITTING_CLOSE_PENDING:
ASSERT(uGkiState == STATE_ADMITTING || uGkiState == STATE_ADMITTING_UNREG || uGkiState == STATE_ADMITTING_REREG);
switch (uGkiState)
{
case STATE_ADMITTING:
uGkiState = STATE_REGISTERED;
break;
case STATE_ADMITTING_UNREG:
uGkiState = STATE_REGISTERED;
status = GkiUnregister();
break;
case STATE_ADMITTING_REREG:
uGkiState = STATE_REGISTERED;
status = GkiRegister();
break;
} // switch
break;
case GCS_ADMITTED:
case GCS_CHANGING:
case GCS_CHANGING_CLOSE_PENDING:
case GCS_DISENGAGING:
--uGkiCalls;
GKDBG((1, "GkiFreeCall: uGkiCalls = %d", uGkiCalls));
break;
default:
GKDBG((1, "GkiFreeCall: Invalid call state %d", pGkiCall->uGkiCallState));
} // switch
pGkiCall->uGkiCallState = GCS_START;
if (uGkiCalls == 0 && uPendingDisengages == 0)
{
switch (uGkiState)
{
case STATE_DISENGAGING:
uGkiState = STATE_REGISTERED;
status = GkiUnregister();
break;
case STATE_DISENGAGING_REREG:
uGkiState = STATE_REGISTERED;
status = GkiRegister();
break;
} // switch
if (pListenList && pListenList->hListen == DEFAULT_LISTEN_HANDLE)
{
GkiCloseListen(DEFAULT_LISTEN_HANDLE);
}
}
return status;
} // GkiFreeCall()
HRESULT GkiCloseListen (DWORD hListen)
{
register PLISTEN pListen;
register HRESULT status;
GKDBG((1, StateName("GkiCloseListen <- State = %s", uGkiState), 0));
EnterCriticalSection(&GkiLock);
pListen = ListenDequeue(hListen);
if (pListen == NULL)
{
status = CC_GKI_LISTEN_NOT_FOUND;
}
else
{
if (pListen->pAliasNames)
{
FreeAliasNames(pListen->pAliasNames);
}
Free(pListen);
if (pListenList)
{
status = GkiRegister();
}
else
{
status = GkiUnregister();
}
}
LeaveCriticalSection(&GkiLock);
GKDBG((1, StateName("GkiCloseListen -> State = %s", uGkiState), 0));
return status;
} // GkiCloseListen()
HRESULT GkiOpenListen (DWORD hListen, PCC_ALIASNAMES pAliasNames, DWORD dwAddr, WORD wPort)
{
register PLISTEN pListen;
register HRESULT status = NOERROR;
GKDBG((1, StateName("GkiOpenListen <- State = %s", uGkiState), 0));
EnterCriticalSection(&GkiLock);
// Check for invalid IP address
if (dwAddr == INADDR_ANY || dwAddr == INADDR_NONE)
{
dwAddr = GetIpAddress();
if (dwAddr == INADDR_ANY)
return CC_GKI_IP_ADDRESS;
}
// Check for invalid alias list
if (pAliasNames)
{
PCC_ALIASITEM pAliasItem;
unsigned int uIndex;
if (pAliasNames->wCount == 0)
{
GKDBG((1, "GkiOpenListen: Alias name wCount == 0", 0));
return CC_BAD_PARAM;
}
pAliasItem = pAliasNames->pItems;
for (uIndex = 0; uIndex < pAliasNames->wCount; ++uIndex, ++pAliasItem)
{
if (pAliasItem->wDataLength == 0 || pAliasItem->pData == NULL)
{
// Bad alias item
GKDBG((1, "GkiOpenListen: Bad alias item (wDataLength = %d)",
pAliasItem->wDataLength));
return CC_BAD_PARAM;
}
}
}
pListen = (PLISTEN)Malloc(sizeof(*pListen));
if (pListen)
{
if (pAliasNames)
{
status = CopyAliasNames(&pListen->pAliasNames, pAliasNames);
if (status != NOERROR)
{
GKDBG((1, "GkiOpenListen: CopyAliasNames returned 0x%x", status));
LeaveCriticalSection(&GkiLock);
return status;
}
}
else
{
pListen->pAliasNames = NULL;
}
pListen->hListen = hListen;
pListen->dwAddr = ntohl(dwAddr);
pListen->wPort = wPort;
ListenEnqueue(pListen);
status = GkiRegister();
} // if
else
{
GKDBG((1, "GkiOpenListen: Could not allocate listen structure", 0));
status = CC_NO_MEMORY;
} // else
LeaveCriticalSection(&GkiLock);
GKDBG((1, StateName("GkiOpenListen -> State = %s", uGkiState), 0));
return status;
} // GkiOpenListen()
/*
* NOTES
* Must have Call locked before calling!
*/
HRESULT GkiCloseCall(PGKICALL pGkiCall)
{
HRESULT status = NOERROR;
ASSERT(pGkiCall != NULL);
GKDBG((1, CallStateName("GkiCloseCall <- Call State = %s", pGkiCall->uGkiCallState), 0));
while (pGkiCall->pBwReqHead)
{
Free(BwReqDequeue(pGkiCall));
}
if (pGkiCall->uGkiCallState == GCS_START)
{
GKDBG((1, CallStateName("GkiCloseCall: Call already in state %s", pGkiCall->uGkiCallState), 0));
status = CC_GKI_CALL_STATE;
}
else
{
switch (uGkiState)
{
case STATE_START:
break;
case STATE_REG_BYPASS:
status = GkiFreeCall(pGkiCall);
break;
default:
switch (pGkiCall->uGkiCallState)
{
case GCS_WAITING:
status = GkiFreeCall(pGkiCall);
break;
case GCS_ADMITTING:
pGkiCall->uGkiCallState = GCS_ADMITTING_CLOSE_PENDING;
break;
case GCS_ADMITTING_CLOSE_PENDING:
case GCS_CHANGING_CLOSE_PENDING:
case GCS_DISENGAGING:
GKDBG((1, CallStateName("GkiCloseCall: Call already in closing state %s", pGkiCall->uGkiCallState), 0));
status = CC_GKI_CALL_STATE;
break;
case GCS_ADMITTED:
pGkiCall->uGkiCallState = GCS_DISENGAGING;
GKDBG((1, "GKI_DisengageRequest called...", 0));
++uPendingDisengages;
status = pGKI_DisengageRequest(pGkiCall->hGkiCall);
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_DisengageRequest returned %s", status), 0));
}
else
{
--uPendingDisengages;
GKDBG((1, GkiErrorName("GKI_DisengageRequest returned %s", status), 0));
GkiFreeCall(pGkiCall);
}
break;
case GCS_CHANGING:
pGkiCall->uGkiCallState = GCS_CHANGING_CLOSE_PENDING;
break;
default:
GKDBG((1, CallStateName("GkiCloseCall: Call in invalid state %s", pGkiCall->uGkiCallState), 0));
status = CC_GKI_CALL_STATE;
} // switch
} // switch
} // else
GKDBG((1, StateName("GkiCloseCall -> State = %s", uGkiState), 0));
return status;
} // GkiCloseCall()
/*
* NOTES
* Must have Call locked before calling!
*/
static HRESULT BandwidthRejected(PGKICALL pGkiCall, UINT Reason)
{
HRESULT status = NOERROR;
PBWREQ pBwReq;
DWORD hCall;
ASSERT(pGkiCall != NULL);
pBwReq = BwReqDequeue(pGkiCall);
hCall = pGkiCall->hCall;
if (pBwReq)
{
if ((pGkiCall->uBandwidthUsed + pBwReq->uChannelBandwidth) <= pGkiCall->uBandwidthAllocated)
{
if (pBwReq->Type == TX)
{
OpenChannelConfirm (pBwReq->hChannel);
}
else
{
AcceptChannelConfirm(pBwReq->hChannel);
}
}
else
{
if (pBwReq->Type == TX)
{
OpenChannelReject (pBwReq->hChannel, MapBandwidthRejectReason(Reason));
}
else
{
AcceptChannelReject (pBwReq->hChannel, MapBandwidthRejectReason(Reason));
}
}
Free(pBwReq);
if (ValidateCall(hCall) == NOERROR)
{
CheckPendingBandwidth(pGkiCall);
}
}
return status;
} // BandwidthRejected()
/*
* NOTES
* Must have Call locked before calling!
*/
static HRESULT CheckPendingBandwidth(PGKICALL pGkiCall)
{
HRESULT status = NOERROR;
PBWREQ pBwReq;
DWORD hCall;
ASSERT(pGkiCall != NULL);
ASSERT(pGkiCall->uGkiCallState == GCS_ADMITTED);
hCall = pGkiCall->hCall;
while (pGkiCall->pBwReqHead != NULL &&
(pGkiCall->uBandwidthUsed + pGkiCall->pBwReqHead->uChannelBandwidth) <= pGkiCall->uBandwidthAllocated)
{
pBwReq = BwReqDequeue(pGkiCall);
ASSERT(pBwReq != NULL);
pGkiCall->uBandwidthUsed += pBwReq->uChannelBandwidth;
if (pBwReq->Type == TX)
{
OpenChannelConfirm(pBwReq->hChannel);
}
else
{
AcceptChannelConfirm(pBwReq->hChannel);
}
Free(pBwReq);
if (ValidateCall(hCall) != NOERROR)
{
return status;
}
}
if (pGkiCall->pBwReqHead != NULL)
{
pGkiCall->uGkiCallState = GCS_CHANGING;
GKDBG((1, "GKI_BandwidthRequest called...", 0);
status = pGKI_BandwidthRequest(pGkiCall->hGkiCall,
pGkiCall->usCallTypeChoice,
pGkiCall->uBandwidthUsed + pGkiCall->pBwReqHead->uChannelBandwidth));
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_BandwidthRequest returned %s", status), 0));
}
else
{
GKDBG((1, GkiErrorName("GKI_BandwidthRequest returned %s", status), 0));
BandwidthRejected(pGkiCall, BndRjctRsn_undfndRsn_chosen);
}
}
return status;
} // CheckPendingBandwidth()
static void FreeAliasList(SeqAliasAddr *pAliasAddrs)
{
register SeqAliasAddr *pAlias = pAliasAddrs;
while (pAlias)
{
if (pAlias->value.choice == h323_ID_chosen && pAlias->value.u.h323_ID.value)
Free(pAlias->value.u.h323_ID.value);
pAlias = pAlias->next;
}
Free(pAlias);
} // FreeAliasList()
/*
* NOTES
* Must have Call locked before calling!
*
* The following fields in the GKICALL structure must be properly filled
* in before calling this function:
* pCall Pointer back to containing CALL structure.
* CallType Type of call.
* uBandwidthRequested Initial bandwidth for call.
* pConferenceId Pointer to conference ID buffer.
* bActiveMC TRUE if calling party has an active MC.
* bAnswerCall ???
*/
HRESULT GkiOpenCall (PGKICALL pGkiCall, void *pConference)
{
HRESULT status = NOERROR;
DWORD hCall;
TransportAddress SrcCallSignalAddress;
TransportAddress * pSrcCallSignalAddress;
TransportAddress DestCallSignalAddress;
TransportAddress * pDestCallSignalAddress;
SeqAliasAddr * pAliasAddrs;
SeqAliasAddr * pExtraAliasAddrs;
SeqAliasAddr * pAlias;
PCC_ALIASITEM pAliasItem;
unsigned uCount;
unsigned uIndex;
ConferenceIdentifier ConferenceId;
ASSERT(pGkiCall != NULL);
ASSERT(pConference != NULL);
GKDBG((1, StateName("GkiOpenCall <- State = %s", uGkiState), 0));
EnterCriticalSection(&GkiLock);
switch (uGkiState)
{
case STATE_REG_BYPASS:
ASSERT(pGkiCall->uGkiCallState == GCS_START || pGkiCall->uGkiCallState == GCS_WAITING || pGkiCall->uGkiCallState == GCS_ADMITTING);
hCall = pGkiCall->hCall;
GkiAllocCall(pGkiCall, GKI_BYPASS_HANDLE);
pGkiCall->uBandwidthAllocated = MAX_BANDWIDTH;
if (pGkiCall->bAnswerCall)
{
status = AcceptCallConfirm(pGkiCall->pCall, pConference);
if (status == NOERROR && ValidateCall(hCall) == NOERROR)
{
CheckPendingBandwidth(pGkiCall);
}
}
else if (pGkiCall->dwIpAddress == 0)
{
status = PlaceCallReject (pGkiCall->pCall, pConference, CC_INVALID_WITHOUT_GATEKEEPER);
}
else
{
status = PlaceCallConfirm (pGkiCall->pCall, pConference);
if (status == NOERROR && ValidateCall(hCall) == NOERROR)
{
CheckPendingBandwidth(pGkiCall);
}
}
break;
case STATE_REGISTERING:
case STATE_REGISTERING_REREG:
case STATE_ADMITTING:
pGkiCall->uGkiCallState = GCS_WAITING;
break;
case STATE_REGISTERED:
switch (pGkiCall->CallType)
{
case POINT_TO_POINT:
pGkiCall->usCallTypeChoice = pointToPoint_chosen;
break;
case ONE_TO_MANY:
pGkiCall->usCallTypeChoice = oneToN_chosen;
break;
case MANY_TO_ONE:
pGkiCall->usCallTypeChoice = nToOne_chosen;
break;
case MANY_TO_MANY:
pGkiCall->usCallTypeChoice = nToN_chosen;
break;
default:
LeaveCriticalSection(&GkiLock);
GKDBG((1, "GkiOpenCall -> Invalid CallType %d", pGkiCall->CallType));
return CC_BAD_PARAM;
} // switch
pSrcCallSignalAddress = NULL;
pDestCallSignalAddress = NULL;
pAliasAddrs = NULL;
pExtraAliasAddrs = NULL;
if (pGkiCall->dwSrcCallSignalIpAddress != 0 && pGkiCall->wSrcCallSignalPort != 0)
{
SrcCallSignalAddress.choice = ipAddress_chosen;
SrcCallSignalAddress.u.ipAddress.ip.length = 4;
*((DWORD *)SrcCallSignalAddress.u.ipAddress.ip.value) = pGkiCall->dwSrcCallSignalIpAddress;
SrcCallSignalAddress.u.ipAddress.port = pGkiCall->wSrcCallSignalPort;
pSrcCallSignalAddress = &SrcCallSignalAddress;
}
if (pGkiCall->dwIpAddress != 0 && pGkiCall->wPort != 0)
{
DestCallSignalAddress.choice = ipAddress_chosen;
DestCallSignalAddress.u.ipAddress.ip.length = 4;
*((DWORD *)DestCallSignalAddress.u.ipAddress.ip.value) = pGkiCall->dwIpAddress;
DestCallSignalAddress.u.ipAddress.port = pGkiCall->wPort;
pDestCallSignalAddress = &DestCallSignalAddress;
}
if (pGkiCall->pCalleeAliasNames)
{
// pDestCallSignalAddress = NULL;
uCount = pGkiCall->pCalleeAliasNames->wCount;
pAliasAddrs = Malloc(uCount * sizeof(*pAliasAddrs));
if (pAliasAddrs == NULL)
{
LeaveCriticalSection(&GkiLock);
GKDBG((1, "GkiOpenCall: Could not allocate %d Alias Addresses", uCount));
return CC_NO_MEMORY;
}
memset(pAliasAddrs, 0, uCount * sizeof(*pAliasAddrs));
pAlias = pAliasAddrs;
pAliasItem = pGkiCall->pCalleeAliasNames->pItems;
for (uIndex = 0; uIndex < uCount; ++uIndex)
{
status = CopyAliasItem(pAlias, pAliasItem);
if (status != NOERROR)
{
LeaveCriticalSection(&GkiLock);
GKDBG((1, "GkiOpenCall: CopyAliasItem returned %d", status));
FreeAliasList(pAliasAddrs);
return status;
}
pAlias->next = pAlias + 1;
++pAlias;
++pAliasItem;
} // for
--pAlias;
pAlias->next = NULL;
}
if (pGkiCall->pCalleeExtraAliasNames)
{
uCount = pGkiCall->pCalleeExtraAliasNames->wCount;
pExtraAliasAddrs = Malloc(uCount * sizeof(*pExtraAliasAddrs));
if (pExtraAliasAddrs == NULL)
{
LeaveCriticalSection(&GkiLock);
GKDBG((1, "GkiOpenCall: Could not allocate %d Alias Addresses", uCount));
if (pAliasAddrs)
FreeAliasList(pAliasAddrs);
return CC_NO_MEMORY;
}
memset(pExtraAliasAddrs, 0, uCount * sizeof(*pExtraAliasAddrs));
pAlias = pExtraAliasAddrs;
pAliasItem = pGkiCall->pCalleeExtraAliasNames->pItems;
for (uIndex = 0; uIndex < uCount; ++uIndex)
{
status = CopyAliasItem(pAlias, pAliasItem);
if (status != NOERROR)
{
LeaveCriticalSection(&GkiLock);
GKDBG((1, "GkiOpenCall: CopyAliasItem returned %d", status));
if (pAliasAddrs)
FreeAliasList(pAliasAddrs);
FreeAliasList(pExtraAliasAddrs);
return status;
}
pAlias->next = pAlias + 1;
++pAlias;
++pAliasItem;
} // for
--pAlias;
pAlias->next = NULL;
}
if (pGkiCall->uBandwidthRequested < MIN_BANDWIDTH)
{
pGkiCall->uBandwidthRequested = MIN_BANDWIDTH;
}
ASSERT(pGkiCall->uBandwidthAllocated == 0);
ASSERT(pGkiCall->uBandwidthUsed == 0);
memcpy(ConferenceId.value, pGkiCall->pConferenceId, 16);
if (((DWORD *)pGkiCall->pConferenceId)[0] != 0 ||
((DWORD *)pGkiCall->pConferenceId)[1] != 0 ||
((DWORD *)pGkiCall->pConferenceId)[2] != 0 ||
((DWORD *)pGkiCall->pConferenceId)[3] != 0)
{
ConferenceId.length = 16;
}
else
{
ConferenceId.length = 0;
}
pGkiCall->hGkiCall = GKI_ADMITTING_HANDLE;
if (pDestCallSignalAddress != NULL || pAliasAddrs != NULL)
{
uGkiState = STATE_ADMITTING;
pGkiCall->uGkiCallState = GCS_ADMITTING;
GKDBG((1, "GKI_AdmissionRequest called...", 0);
status = pGKI_AdmissionRequest(pGkiCall->usCallTypeChoice, // usCallTypeChoice.
pAliasAddrs, // pDestinationInfo
pGkiCall->bAnswerCall ? pSrcCallSignalAddress : pDestCallSignalAddress,
pExtraAliasAddrs, // pDestExtraCallInfo,
pGkiCall->uBandwidthRequested, // bandWidth,
&ConferenceId, // pConferenceID,
pGkiCall->bActiveMC, // activeMC,
pGkiCall->bAnswerCall, // answerCall,
ipAddress_chosen)); // usCallTransport
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_AdmissionRequest returned %s", status), 0));
}
else
{
GKDBG((1, GkiErrorName("GKI_AdmissionRequest returned %s", status), 0));
}
}
else
{
pGkiCall->hGkiCall = 0;
status = CC_BAD_PARAM;
}
if (status != NOERROR)
{
uGkiState = STATE_REGISTERED;
GkiCancelCall(pGkiCall, pConference);
}
if (pAliasAddrs)
FreeAliasList(pAliasAddrs);
if (pExtraAliasAddrs)
FreeAliasList(pExtraAliasAddrs);
break;
case STATE_START:
case STATE_CLASS_REGISTERED:
case STATE_WINDOW_CREATED:
pGkiCall->uGkiCallState = GCS_WAITING;
status = GkiOpenListen(DEFAULT_LISTEN_HANDLE, NULL, 0, 1720);
break;
default:
GKDBG((1, StateName("GkiOpenCall: Invalid state %s", uGkiState), 0));
status = LastGkiError;
} // switch
LeaveCriticalSection(&GkiLock);
GKDBG((1, CallStateName("GkiOpenCall -> Call State = %s", pGkiCall->uGkiCallState), 0));
return status;
} // GkiOpenCall()
/*
* NOTES
* Must have Call locked before calling!
*/
HRESULT GkiOpenChannel(PGKICALL pGkiCall, unsigned uChannelBandwidth, DWORD hChannel, CHANNELTYPE Type)
{
HRESULT status = NOERROR;
PBWREQ pBwReq;
ASSERT(pGkiCall != NULL);
GKDBG((1, CallStateName("GkiOpenChannel <- Call State = %s", pGkiCall->uGkiCallState), 0));
pBwReq = (PBWREQ)Malloc(sizeof(*pBwReq));
if (pBwReq == NULL)
{
GKDBG((1, "GkiOpenChannel: Memory allocation failed", 0));
return CC_NO_MEMORY;
}
pBwReq->uChannelBandwidth = uChannelBandwidth / 100;
pBwReq->hChannel = hChannel;
pBwReq->Type = Type;
BwReqEnqueue(pGkiCall, pBwReq);
switch (pGkiCall->uGkiCallState)
{
case GCS_WAITING:
case GCS_ADMITTING:
case GCS_CHANGING:
// Must wait for current operation to complete
break;
case GCS_ADMITTED:
status = CheckPendingBandwidth(pGkiCall);
break;
default:
GKDBG((1, "GkiOpenChannel: Invalid call state %d", pGkiCall->uGkiCallState));
status = CC_GKI_CALL_STATE;
} // switch
GKDBG((1, CallStateName("GkiOpenChannel -> Call State = %s", pGkiCall->uGkiCallState), 0));
return status;
} // GkiOpenChannel()
/*
* NOTES
* Must have Call locked before calling!
*/
HRESULT GkiCloseChannel(PGKICALL pGkiCall, unsigned uChannelBandwidth, DWORD hChannel)
{
PBWREQ pBwReq;
PBWREQ pBwReq1;
ASSERT(pGkiCall != NULL);
GKDBG((1, CallStateName("GkiCloseChannel <- Call State = %s", pGkiCall->uGkiCallState), 0));
// If Bandwidth request is still in queue, bandwidth has not been allocated
pBwReq = pGkiCall->pBwReqHead;
if (pBwReq)
{
if (pBwReq->hChannel == hChannel)
{
Free(BwReqDequeue(pGkiCall));
GKDBG((1, CallStateName("GkiCloseChannel -> Call State = %s", pGkiCall->uGkiCallState), 0));
return NOERROR;
}
while ((pBwReq1 = pBwReq->pNext) != NULL)
{
if (pBwReq1->hChannel == hChannel)
{
if (pGkiCall->pBwReqTail == pBwReq1)
{
pGkiCall->pBwReqTail = pBwReq;
}
pBwReq->pNext = pBwReq1->pNext;
Free(pBwReq1);
GKDBG((1, CallStateName("GkiCloseChannel -> Call State = %s", pGkiCall->uGkiCallState), 0));
return NOERROR;
}
}
}
pGkiCall->uBandwidthUsed -= (uChannelBandwidth / 100);
GKDBG((1, CallStateName("GkiCloseChannel -> Call State = %s", pGkiCall->uGkiCallState), 0));
return NOERROR;
} // GkiCloseChannel()
unsigned GkiGetBandwidth(PGKICALL pGkiCall)
{
ASSERT(pGkiCall != NULL);
return pGkiCall->uBandwidthAllocated * 100;
} // GkiGetBandwidth()
//
// GkiWndProc subroutines
//
/*
* NOTES
* Must have Call locked before calling!
*/
static HRESULT CheckPendingOpen(PGKICALL pGkiCall, void *pConference)
{
HRESULT status = NOERROR;
ASSERT(pGkiCall != NULL);
ASSERT(pConference != NULL);
switch (uGkiState)
{
case STATE_REGISTERED:
case STATE_REG_BYPASS:
// TBD - Can only open 1!!!
ASSERT(pGkiCall->uGkiCallState != GCS_ADMITTING);
if (pGkiCall->uGkiCallState == GCS_WAITING)
{
status = GkiOpenCall(pGkiCall, pConference);
}
break;
default:
status = LastGkiError;
} // switch
return status;
} // CheckPendingOpen()
static void GkiNoResponse(HWND hWnd)
{
HRESULT status;
switch (uGkiState)
{
case STATE_START:
case STATE_CLASS_REGISTERED:
case STATE_WINDOW_CREATED:
case STATE_REG_BYPASS:
break;
case STATE_REGISTERING:
case STATE_REGISTERING_REREG:
case STATE_REGISTERING_UNREG:
GKDBG((1, "GkiWndProc: dummy GKI_REG_REJECT", 0));
PostMessage(hWnd, GKIMAN_BASE + GKI_REG_REJECT, 0, 0);
break;
case STATE_ADMITTING:
case STATE_ADMITTING_REREG:
ApplyToAllCalls(GkiCancelAdmitting);
uGkiState = STATE_REGISTERED;
// Fall-through to next case
case STATE_REGISTERED:
if (uGkiCalls == 0)
{
GkiRegister();
}
else
{
uGkiState = STATE_REG_BYPASS;
ApplyToAllCalls(GatekeeperNotFound);
GKDBG((1, "GKI_UnregistrationRequest called...", 0));
status = pGKI_UnregistrationRequest();
if (status == NOERROR)
{
GKDBG((1, GkiErrorName("GKI_UnregistrationRequest returned %s", status), 0));
}
else
{
GKDBG((1, GkiErrorName("GKI_UnregistrationRequest returned %s", status), 0));
}
}
break;
case STATE_ADMITTING_UNREG:
ApplyToAllCalls(GkiCancelAdmitting);
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
case STATE_DISENGAGING:
ApplyToAllCalls(GatekeeperNotFound);
ASSERT(uGkiCalls == 0);
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
case STATE_DISENGAGING_REREG:
ApplyToAllCalls(GatekeeperNotFound);
ASSERT(uGkiCalls == 0);
uGkiState = STATE_REGISTERED;
GkiRegister();
break;
case STATE_UNREGISTERING:
case STATE_UNREGISTERING_REREG:
GKDBG((1, "GkiWndProc: dummy GKI_UNREG_CONFIRM", 0));
PostMessage(hWnd, GKIMAN_BASE + GKI_UNREG_CONFIRM, 0, 0);
break;
default:
GKDBG((1, "GkiWndProc: Bad uGkiState %d", uGkiState));
} // switch
} // GkiNoResponse()
LONG APIENTRY GkiWndProc(
HWND hWnd, /* window handle */
UINT message, /* type of message */
UINT wParam, /* additional information */
LONG lParam) /* additional information */
{
CallReturnInfo * pCallReturnInfo;
PGKICALL pGkiCall;
void * pConference;
DWORD hCall;
DWORD hConference;
HRESULT status;
if (message < GKIMAN_BASE)
{
return DefWindowProc(hWnd, message, wParam, lParam);
}
EnterCallControlTop();
GKDBG((1, StateName("GkiWndProc <- State = %s", uGkiState), 0));
switch (message)
{
case GKIMAN_BASE + GKI_REG_CONFIRM:
GKDBG((1, "GkiWndProc: GKI_REG_CONFIRM", 0));
switch (uGkiState)
{
case STATE_REGISTERING:
uGkiState = STATE_REGISTERED;
ApplyToAllCalls(CheckPendingOpen);
break;
case STATE_REGISTERING_REREG:
uGkiState = STATE_REGISTERED;
GkiRegister();
break;
case STATE_REGISTERING_UNREG:
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_REG_CONFIRM in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_REG_DISCOVERY:
GKDBG((1, "GkiWndProc: GKI_REG_DISCOVERY", 0));
ASSERT(uGkiState == STATE_REGISTERING || uGkiState == STATE_REGISTERING_REREG || uGkiState == STATE_REGISTERING_UNREG);
break;
case GKIMAN_BASE + GKI_REG_REJECT:
GKDBG((1, "GkiWndProc: GKI_REG_REJECT Reason = %d", wParam));
switch (uGkiState)
{
case STATE_REGISTERING:
ApplyToAllCalls(GkiCancelCall);
EnterCriticalSection(&GkiLock);
while (pListenList)
{
register PLISTEN pListen = pListenList;
pListenList = pListen->pNext;
LeaveCriticalSection(&GkiLock);
ListenReject(pListen->hListen, MapRegistrationRejectReason(wParam));
if (pListen->pAliasNames)
{
FreeAliasNames(pListen->pAliasNames);
}
Free(pListen);
EnterCriticalSection(&GkiLock);
}
LeaveCriticalSection(&GkiLock);
uGkiState = STATE_WINDOW_CREATED;
break;
case STATE_REGISTERING_REREG:
uGkiState = STATE_WINDOW_CREATED;
GkiRegister();
break;
case STATE_REGISTERING_UNREG:
uGkiState = STATE_WINDOW_CREATED;
GkiUnregister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_REG_REJECT in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_REG_BYPASS:
GKDBG((1, "GkiWndProc: GKI_REG_BYPASS", 0));
switch (uGkiState)
{
case STATE_REGISTERING:
case STATE_REGISTERING_REREG:
uGkiState = STATE_REG_BYPASS;
ApplyToAllCalls(CheckPendingOpen);
break;
case STATE_REGISTERING_UNREG:
uGkiState = STATE_WINDOW_CREATED;
GkiUnregister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_REG_BYPASS in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_UNREG_CONFIRM:
GKDBG((1, "GkiWndProc: GKI_UNREG_CONFIRM", 0));
switch (uGkiState)
{
case STATE_REGISTERING:
case STATE_REGISTERING_REREG:
case STATE_REGISTERED:
case STATE_ADMITTING:
case STATE_ADMITTING_REREG:
case STATE_DISENGAGING_REREG:
case STATE_UNREGISTERING_REREG:
uGkiState = STATE_WINDOW_CREATED;
GkiRegister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_UNREG_CONFIRM in state %s", uGkiState), 0));
// Fall through to next case
case STATE_ADMITTING_UNREG:
case STATE_DISENGAGING:
ApplyToAllCalls(GkiCancelCall);
// Fall-through to next case
case STATE_REGISTERING_UNREG:
case STATE_UNREGISTERING:
uGkiState = STATE_WINDOW_CREATED;
// Fall-through to next case
case STATE_CLASS_REGISTERED:
case STATE_WINDOW_CREATED:
// Fall-through to next case
case STATE_START:
case STATE_REG_BYPASS:
break;
} // switch
break;
case GKIMAN_BASE + GKI_UNREG_REJECT:
GKDBG((1, "GkiWndProc: GKI_UNREG_REJECT Reason = %d", wParam));
switch (uGkiState)
{
case STATE_UNREGISTERING:
uGkiState = STATE_WINDOW_CREATED;
GkiUnregister();
break;
case STATE_UNREGISTERING_REREG:
uGkiState = STATE_WINDOW_CREATED;
GkiRegister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_UNREG_REJECT in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_ADM_CONFIRM:
GKDBG((1, "GkiWndProc: GKI_ADM_CONFIRM", 0));
switch (uGkiState)
{
case STATE_ADMITTING:
uGkiState = STATE_REGISTERED;
pCallReturnInfo = (CallReturnInfo *) lParam;
if (LockGkiCallAndConference(GKI_ADMITTING_HANDLE, &pGkiCall, &pConference, &hCall, &hConference) == NOERROR)
{
GKDBG((1, CallStateName("GkiWndProc: Call State = %s", pGkiCall->uGkiCallState), 0));
pGkiCall->usCallModelChoice = pCallReturnInfo->callModel.choice;
pGkiCall->uBandwidthAllocated = pCallReturnInfo->bandWidth;
pGkiCall->usCRV = pCallReturnInfo->callReferenceValue;
memcpy(pGkiCall->pConferenceId, pCallReturnInfo->conferenceID.value, 16);
switch (pGkiCall->uGkiCallState)
{
case GCS_ADMITTING:
GkiAllocCall(pGkiCall, pCallReturnInfo->hCall);
if (pGkiCall->bAnswerCall)
{
status = AcceptCallConfirm(pGkiCall->pCall, pConference);
}
else
{
ASSERT(pCallReturnInfo->destCallSignalAddress.choice == ipAddress_chosen);
pGkiCall->dwIpAddress = *((DWORD *)pCallReturnInfo->destCallSignalAddress.u.ipAddress.ip.value);
pGkiCall->dwIpAddress = pGkiCall->dwIpAddress;
pGkiCall->wPort = pCallReturnInfo->destCallSignalAddress.u.ipAddress.port;
status = PlaceCallConfirm(pGkiCall->pCall, pConference);
}
if (status == NOERROR && ValidateCall(hCall) == NOERROR)
CheckPendingBandwidth(pGkiCall);
break;
case GCS_ADMITTING_CLOSE_PENDING:
GkiAllocCall(pGkiCall, pCallReturnInfo->hCall);
GkiCloseCall(pGkiCall);
break;
default:
GKDBG((1, CallStateName("GkiWndProc: GKI_ADM_CONFIRM in call state %s", pGkiCall->uGkiCallState), 0));
} // switch
UnlockGkiCallAndConference(pGkiCall, pConference, hCall, hConference);
} // if
else
{
GKDBG((1, "GkiWndProc: GKI_ADM_CONFIRM handle not found", 0));
}
ApplyToAllCalls(CheckPendingOpen);
break;
case STATE_ADMITTING_UNREG:
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_ADM_CONFIRM in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_ADM_REJECT:
GKDBG((1, "GkiWndProc: GKI_ADM_REJECT Reason = %d", wParam));
switch (uGkiState)
{
case STATE_ADMITTING:
pCallReturnInfo = (CallReturnInfo *) lParam;
if (LockGkiCallAndConference(GKI_ADMITTING_HANDLE, &pGkiCall, &pConference, &hCall, &hConference) == NOERROR)
{
ASSERT(pGkiCall->uGkiCallState == GCS_ADMITTING);
switch (wParam)
{
case calledPartyNotRegistered_chosen:
if (pGkiCall->bAnswerCall)
{
// The gateway has gone away and come back without our notice!
GkiCancelAdmitting(pGkiCall, pConference);
uGkiState = STATE_REGISTERED;
GkiRegister();
GKDBG((1, StateName("GkiWndProc -> State = %s", uGkiState), 0));
LeaveCallControlTop(0);
}
break;
case callerNotRegistered_chosen:
if (pGkiCall->bAnswerCall == FALSE)
{
// The gateway has gone away and come back without our notice!
GkiCancelAdmitting(pGkiCall, pConference);
uGkiState = STATE_REGISTERED;
GkiRegister();
GKDBG((1, StateName("GkiWndProc -> State = %s", uGkiState), 0));
LeaveCallControlTop(0);
}
} // switch
GkiFreeCall(pGkiCall);
if (pGkiCall->bAnswerCall)
AcceptCallReject(pGkiCall->pCall, pConference, MapAdmissionRejectReason(wParam));
else
PlaceCallReject (pGkiCall->pCall, pConference, MapAdmissionRejectReason(wParam));
UnlockGkiCallAndConference(pGkiCall, pConference, hCall, hConference);
} // if
else
{
GKDBG((1, "GkiWndProc: GKI_ADM_REJECT handle not found", 0));
}
uGkiState = STATE_REGISTERED;
ApplyToAllCalls(CheckPendingOpen);
break;
case STATE_ADMITTING_REREG:
pCallReturnInfo = (CallReturnInfo *) lParam;
if (LockGkiCallAndConference(GKI_ADMITTING_HANDLE, &pGkiCall, &pConference, &hCall, &hConference) == NOERROR)
{
ASSERT(pGkiCall->uGkiCallState == GCS_ADMITTING_CLOSE_PENDING);
GkiFreeCall(pGkiCall);
if (pGkiCall->bAnswerCall)
{
AcceptCallReject(pGkiCall->pCall, pConference, MapAdmissionRejectReason(wParam));
}
else
{
PlaceCallReject (pGkiCall->pCall, pConference, MapAdmissionRejectReason(wParam));
}
UnlockGkiCallAndConference(pGkiCall, pConference, hCall, hConference);
} // if
else
{
GKDBG((1, "GkiWndProc: GKI_ADM_REJECT handle not found", 0));
}
uGkiState = STATE_REGISTERED;
GkiRegister();
break;
case STATE_ADMITTING_UNREG:
pCallReturnInfo = (CallReturnInfo *) lParam;
if (LockGkiCallAndConference(GKI_ADMITTING_HANDLE, &pGkiCall, &pConference, &hCall, &hConference) == NOERROR)
{
ASSERT(pGkiCall->uGkiCallState == GCS_ADMITTING_CLOSE_PENDING);
GkiFreeCall(pGkiCall);
if (pGkiCall->bAnswerCall)
{
AcceptCallReject(pGkiCall->pCall, pConference, MapAdmissionRejectReason(wParam));
}
else
{
PlaceCallReject (pGkiCall->pCall, pConference, MapAdmissionRejectReason(wParam));
}
UnlockGkiCallAndConference(pGkiCall, pConference, hCall, hConference);
} // if
else
{
GKDBG((1, "GkiWndProc: GKI_ADM_REJECT handle not found", 0));
}
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_ADM_REJECT in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_BW_CONFIRM:
GKDBG((1, "GkiWndProc: GKI_BW_CONFIRM", 0));
switch (uGkiState)
{
case STATE_REGISTERED:
pCallReturnInfo = (CallReturnInfo *) lParam;
if (LockGkiCallAndConference(pCallReturnInfo->hCall, &pGkiCall, &pConference, &hCall, &hConference) == NOERROR)
{
GKDBG((1, CallStateName("GkiWndProc: Call State = %s", pGkiCall->uGkiCallState), 0));
pGkiCall->uBandwidthAllocated = pCallReturnInfo->bandWidth;
switch (pGkiCall->uGkiCallState)
{
case GCS_ADMITTED:
if (pGkiCall->uBandwidthUsed < pGkiCall->uBandwidthAllocated)
{
BandwidthShrunk(pGkiCall->pCall,
pConference,
pGkiCall->uBandwidthAllocated,
((long)pGkiCall->uBandwidthAllocated) - ((long)pGkiCall->uBandwidthUsed));
}
break;
case GCS_CHANGING:
pGkiCall->uGkiCallState = GCS_ADMITTED;
CheckPendingBandwidth(pGkiCall);
break;
case GCS_CHANGING_CLOSE_PENDING:
pGkiCall->uGkiCallState = GCS_ADMITTED;
GkiCloseCall(pGkiCall);
break;
default:
GKDBG((1, CallStateName("GkiWndProc: GKI_BW_CONFIRM in call state %s", pGkiCall->uGkiCallState), 0));
} // switch
UnlockGkiCallAndConference(pGkiCall, pConference, hCall, hConference);
} // if
else
{
GKDBG((1, "GkiWndProc: GKI_BW_CONFIRM handle not found", 0));
} // else
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_BW_CONFIRM in GKI state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_BW_REJECT:
GKDBG((1, "GkiWndProc: GKI_BW_REJECT Reason = %d", wParam));
switch (uGkiState)
{
case STATE_REGISTERED:
pCallReturnInfo = (CallReturnInfo *) lParam;
if (LockGkiCallAndConference(pCallReturnInfo->hCall, &pGkiCall, &pConference, &hCall, &hConference) == NOERROR)
{
GKDBG((1, CallStateName("GkiWndProc: Call State = %s", pGkiCall->uGkiCallState), 0));
pGkiCall->uBandwidthAllocated = pCallReturnInfo->bandWidth;
switch (pGkiCall->uGkiCallState)
{
case GCS_CHANGING:
pGkiCall->uGkiCallState = GCS_ADMITTED;
BandwidthRejected(pGkiCall, wParam);
if (ValidateCall(hCall) == NOERROR)
{
CheckPendingBandwidth(pGkiCall);
}
break;
case GCS_CHANGING_CLOSE_PENDING:
pGkiCall->uGkiCallState = GCS_ADMITTED;
GkiCloseCall(pGkiCall);
break;
default:
GKDBG((1, CallStateName("GkiWndProc: GKI_BW_REJECT in state %s", pGkiCall->uGkiCallState), 0));
} // switch
UnlockGkiCallAndConference(pGkiCall, pConference, hCall, hConference);
} // if
else
{
GKDBG((1, "GkiWndProc: GKI_BW_REJECT handle not found", 0));
}
break;
default:
GKDBG((1, StateName("GkiWndProc: GKI_BW_REJECT in state %s", uGkiState), 0));
} // switch
break;
case GKIMAN_BASE + GKI_DISENG_CONFIRM:
GKDBG((1, "GkiWndProc: GKI_DISENG_CONFIRM", 0));
if (LockGkiCall((HANDLE)lParam, &pGkiCall) == NOERROR)
{
GKDBG((1, CallStateName("GkiWndProc: Call State = %s", pGkiCall->uGkiCallState), 0));
switch (pGkiCall->uGkiCallState)
{
case GCS_DISENGAGING:
--uPendingDisengages;
break;
default:
GKDBG((1, CallStateName("GkiWndProc: GKI_DISENG_CONFIRM in call state %s", pGkiCall->uGkiCallState), 0));
} // switch
GkiFreeCall(pGkiCall);
Disengage(pGkiCall->pCall);
} // if
else if (uPendingDisengages != 0)
{
--uPendingDisengages;
if (uPendingDisengages == 0)
{
switch (uGkiState)
{
case STATE_DISENGAGING:
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
case STATE_DISENGAGING_REREG:
uGkiState = STATE_REGISTERED;
GkiRegister();
break;
} // switch
if (pListenList && pListenList->hListen == DEFAULT_LISTEN_HANDLE)
{
GkiCloseListen(DEFAULT_LISTEN_HANDLE);
}
} // if
} // else if
else
{
GKDBG((1, "GkiWndProc: GKI_DISENG_CONFIRM handle not found", 0));
}
break;
case GKIMAN_BASE + GKI_DISENG_REJECT:
GKDBG((1, "GkiWndProc: GKI_DISENG_REJECT Reason = %d", wParam));
if (LockGkiCall((HANDLE)lParam, &pGkiCall) == NOERROR)
{
GKDBG((1, CallStateName("GkiWndProc: Call State = %s", pGkiCall->uGkiCallState), 0));
switch (pGkiCall->uGkiCallState)
{
case GCS_DISENGAGING:
// Pretend we received a Disengage Confirm
--uPendingDisengages;
break;
default:
GKDBG((1, CallStateName("GkiWndProc: GKI_DISENG_REJECT in call state %s", pGkiCall->uGkiCallState), 0));
} // switch
GkiFreeCall(pGkiCall);
Disengage(pGkiCall->pCall);
} // if
else if (uPendingDisengages != 0)
{
// Pretend we received a Disengage Confirm
--uPendingDisengages;
if (uPendingDisengages == 0)
{
switch (uGkiState)
{
case STATE_DISENGAGING:
uGkiState = STATE_REGISTERED;
GkiUnregister();
break;
case STATE_DISENGAGING_REREG:
uGkiState = STATE_REGISTERED;
GkiRegister();
break;
} // switch
if (pListenList && pListenList->hListen == DEFAULT_LISTEN_HANDLE)
{
GkiCloseListen(DEFAULT_LISTEN_HANDLE);
}
} // if
} // else if
else
{
GKDBG((1, "GkiWndProc: GKI_DISENG_REJECT handle not found", 0));
}
break;
case GKIMAN_BASE + GKI_LOCATION_CONFIRM:
GKDBG((1, "GkiWndProc: GKI_LOCATION_CONFIRM", 0));
break;
case GKIMAN_BASE + GKI_LOCATION_REJECT:
GKDBG((1, "GkiWndProc: GKI_LOCATION_REJECT Reason = %d", wParam));
break;
case GKIMAN_BASE + GKI_ERROR:
GKDBG((1, GkiErrorName("GkiWndProc: GKI_ERROR %s %%d", lParam), wParam));
switch (lParam)
{
case GKI_NO_RESPONSE:
LastGkiError = lParam;
GkiNoResponse(hWnd);
break;
#if 1
// TEMPORARY KLUDGE FOR WINSOCK 2 BETA 1.6 OPERATION
case MAKE_CUSTOM_HRESULT(SEVERITY_ERROR,1,FACILITY_WINSOCK,0xffff):
uGkiState = STATE_REG_BYPASS;
ApplyToAllCalls(CheckPendingOpen);
break;
#endif
default:
LastGkiError = lParam;
GkiUnregister();
} // switch
break;
default:
GKDBG((1, "Unknown message %d", message));
} // switch
GKDBG((1, StateName("GkiWndProc -> State = %s", uGkiState), 0));
LeaveCallControlTop(0);
} // GkiWndProc()
#if defined(DBG)
DWORD g_dwH225DbgLevel = 0;
BOOL g_fInitialized = FALSE;
void GKDbgInit() {
#define H323_REGKEY_ROOT \
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\H323TSP")
#define H323_REGVAL_DEBUGLEVEL \
TEXT("DebugLevel")
#define H323_REGVAL_H225DEBUGLEVEL \
TEXT("H225DebugLevel")
HKEY hKey;
LONG lStatus;
DWORD dwValue;
DWORD dwValueSize;
DWORD dwValueType;
LPSTR pszValue;
LPSTR pszKey = H323_REGKEY_ROOT;
// only call this once
g_fInitialized = TRUE;
// open registry subkey
lStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pszKey,
0,
KEY_READ,
&hKey
);
// validate return code
if (lStatus != ERROR_SUCCESS) {
return; // bail...
}
// initialize values
dwValueType = REG_DWORD;
dwValueSize = sizeof(DWORD);
// retrieve ras debug level
pszValue = H323_REGVAL_H225DEBUGLEVEL;
// query for registry value
lStatus = RegQueryValueEx(
hKey,
pszValue,
NULL,
&dwValueType,
(LPBYTE)&dwValue,
&dwValueSize
);
// validate return code
if (lStatus != ERROR_SUCCESS) {
// initialize values
dwValueType = REG_DWORD;
dwValueSize = sizeof(DWORD);
// retrieve tsp debug level
pszValue = H323_REGVAL_DEBUGLEVEL;
// query for registry value
lStatus = RegQueryValueEx(
hKey,
pszValue,
NULL,
&dwValueType,
(LPBYTE)&dwValue,
&dwValueSize
);
}
// validate return code
if (lStatus == ERROR_SUCCESS) {
// update debug level
g_dwH225DbgLevel = dwValue;
}
// close key
RegCloseKey(hKey);
}
void GKDbgPrint(DWORD dwLevel,
#ifdef UNICODE_TRACE
LPTSTR pszFormat,
#else
LPSTR pszFormat,
#endif
...)
{
#define DEBUG_FORMAT_HEADER "H225 "
#define DEBUG_FORMAT_TIMESTAMP "[%02u:%02u:%02u.%03u"
#define DEBUG_FORMAT_THREADID ",tid=%x] "
#define MAXDBG_STRLEN 512
va_list Args;
SYSTEMTIME SystemTime;
char szDebugMessage[MAXDBG_STRLEN+1];
int nLengthRemaining;
int nLength = 0;
// make sure initialized
if (g_fInitialized == FALSE) {
GKDbgInit();
}
// validate debug log level
if (dwLevel > g_dwH225DbgLevel) {
return; // bail...
}
// retrieve local time
GetLocalTime(&SystemTime);
// add component header to the debug message
nLength += sprintf(&szDebugMessage[nLength],
DEBUG_FORMAT_HEADER
);
// add timestamp to the debug message
nLength += sprintf(&szDebugMessage[nLength],
DEBUG_FORMAT_TIMESTAMP,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds
);
// add thread id to the debug message
nLength += sprintf(&szDebugMessage[nLength],
DEBUG_FORMAT_THREADID,
GetCurrentThreadId()
);
// point at first argument
va_start(Args, pszFormat);
// determine number of bytes left in buffer
nLengthRemaining = sizeof(szDebugMessage) - nLength;
// add user specified debug message
_vsnprintf(&szDebugMessage[nLength],
nLengthRemaining,
pszFormat,
Args
);
// release pointer
va_end(Args);
// output message to specified sink
OutputDebugString(szDebugMessage);
OutputDebugString("\n");
}
#endif
#else // GATEKEEPER
static char ch; // Kludge around warning C4206: nonstandard extension used : translation unit is empty
#endif // GATEKEEPER