windows-nt/Source/XPSP1/NT/net/tapi/skywalker/h323/tsp/ras.cpp
2020-09-26 16:20:57 +08:00

2551 lines
70 KiB
C++

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
ras.cpp
Abstract:
The RAS client functionality (Transport/session mangement)
Author:
Nikhil Bobde (NikhilB)
Revision History:
--*/
#include "globals.h"
#include "q931obj.h"
#include "line.h"
#include "q931pdu.h"
#include "ras.h"
#define OID_ELEMENT_LAST(Value) { NULL, Value }
#define OID_ELEMENT(Index,Value) { (ASN1objectidentifier_s *) &_OID_H225ProtocolIdentifierV1 [Index], Value },
// this stores an unrolled constant linked list
const ASN1objectidentifier_s _OID_H225ProtocolIdentifierV1 [] = {
OID_ELEMENT (1, 0) // 0 = ITU-T
OID_ELEMENT (2, 0) // 0 = Recommendation
OID_ELEMENT (3, 8) // 8 = H Series
OID_ELEMENT (4, 2250) // 2250 = H.225.0
OID_ELEMENT (5, 0) // 0 = Version
OID_ELEMENT_LAST (1) // 1 = V1
};
#undef OID_ELEMENT
#define OID_ELEMENT(Index,Value) { (ASN1objectidentifier_s *) &_OID_H225ProtocolIdentifierV2 [Index], Value },
// this stores an unrolled constant linked list
const ASN1objectidentifier_s _OID_H225ProtocolIdentifierV2 [] = {
OID_ELEMENT (1, 0) // 0 = ITU-T
OID_ELEMENT (2, 0) // 0 = Recommendation
OID_ELEMENT (3, 8) // 8 = H Series
OID_ELEMENT (4, 2250) // 2250 = H.225.0
OID_ELEMENT (5, 0) // 0 = Version
OID_ELEMENT_LAST (2) // 2 = V2
};
RAS_CLIENT g_RasClient;
static LONG RasSequenceNumber;
PH323_ALIASNAMES
RASGetRegisteredAliasList()
{
return g_RasClient.GetRegisteredAliasList();
}
HRESULT RasStart (void)
{
H323DBG(( DEBUG_LEVEL_TRACE, "RasStart - entered." ));
if( (g_RegistrySettings.saGKAddr.sin_addr.s_addr == NULL) ||
(g_RegistrySettings.saGKAddr.sin_addr.s_addr == INADDR_NONE )
)
{
return E_FAIL;
}
if (g_RegistrySettings.fIsGKEnabled)
{
if( !g_RasClient.Initialize (&g_RegistrySettings.saGKAddr) )
return E_OUTOFMEMORY;
//send the rrq message
if( !g_RasClient.SendRRQ( NOT_RESEND_SEQ_NUM, NULL ) )
{
H323DBG(( DEBUG_LEVEL_TRACE, "couldn't send rrq." ));
//m_RegisterState = RAS_REGISTER_STATE_IDLE;
return E_FAIL;
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "RasStart - exited." ));
return S_OK;
}
void RasStop (void)
{
H323DBG(( DEBUG_LEVEL_TRACE, "RasStop - entered." ));
DWORD dwState = g_RasClient.GetRegState();
if( (dwState==RAS_REGISTER_STATE_REGISTERED) ||
(dwState==RAS_REGISTER_STATE_RRQSENT) )
{
//send urq
g_RasClient.SendURQ( NOT_RESEND_SEQ_NUM, NULL );
}
g_RasClient.Shutdown();
H323DBG(( DEBUG_LEVEL_TRACE, "RasStop - exited." ));
}
BOOL RasIsRegistered (void)
{
return g_RasClient.GetRegState() == RAS_REGISTER_STATE_REGISTERED;
}
HRESULT RasGetLocalAddress (
OUT SOCKADDR_IN * ReturnLocalAddress)
{
return g_RasClient.GetLocalAddress (ReturnLocalAddress);
}
USHORT RasAllocSequenceNumber (void)
{
USHORT SequenceNumber;
H323DBG(( DEBUG_LEVEL_TRACE, "RasAllocSequenceNumber - entered." ));
do
{
SequenceNumber = (USHORT) InterlockedIncrement (&RasSequenceNumber);
} while( SequenceNumber == 0 );
H323DBG(( DEBUG_LEVEL_TRACE, "RasAllocSequenceNumber - exited." ));
return SequenceNumber;
}
HRESULT RasEncodeSendMessage (
IN RasMessage * pRasMessage)
{
return g_RasClient.IssueSend( pRasMessage ) ? S_OK : E_FAIL;
}
HRESULT RasGetEndpointID (
OUT EndpointIdentifier * ReturnEndpointID)
{
return g_RasClient.GetEndpointID (ReturnEndpointID);
}
void RasHandleRegistryChange()
{
g_RasClient.HandleRegistryChange();
}
RAS_CLIENT::RAS_CLIENT()
{
//create the timer queue
m_hRegTimer = NULL;
m_hRegTTLTimer = NULL;
m_hUnRegTimer = NULL;
m_RegisterState = RAS_REGISTER_STATE_IDLE;
m_IoRefCount = 0;
m_dwState = RAS_CLIENT_STATE_NONE;
m_pAliasList = NULL;
m_Socket = INVALID_SOCKET;
InitializeListHead( &m_sendPendingList );
InitializeListHead( &m_sendFreeList );
InitializeListHead( &m_aliasChangeRequestList );
m_dwSendFreeLen = 0;
m_lastRegisterSeqNum = 0;
m_wTTLSeqNumber = 0;
m_UnRegisterSeqNum = 0;
m_wRASSeqNum = 0;
m_dwRegRetryCount = 0;
m_dwUnRegRetryCount = 0;
m_dwCallsInProgress = 0;
m_dwRegTimeToLive = 0;
m_pRRQExpireContext = NULL;
m_pURQExpireContext = NULL;
ZeroMemory( (PVOID)&m_GKAddress, sizeof(SOCKADDR_IN) );
ZeroMemory( (PVOID)&m_ASNCoderInfo, sizeof(ASN1_CODER_INFO) );
ZeroMemory( (PVOID)&m_PendingURQ, sizeof(PENDINGURQ) );
ZeroMemory( (PVOID)&m_RASEndpointID, sizeof(ENDPOINT_ID) );
// No need to check the result of this one since this object is
// not allocated on heap, right when the DLL is loaded.
InitializeCriticalSectionAndSpinCount( &m_CriticalSection, 0x80000000 );
}
RAS_CLIENT::~RAS_CLIENT (void)
{
//free the various lists
FreeSendList( &m_sendFreeList );
FreeSendList( &m_sendPendingList );
FreeSendList( &m_aliasChangeRequestList );
DeleteCriticalSection( &m_CriticalSection );
}
HRESULT
RAS_CLIENT::GetEndpointID(
OUT EndpointIdentifier * ReturnEndpointID )
{
HRESULT hr;
H323DBG(( DEBUG_LEVEL_TRACE, "GetEndpointID - entered." ));
Lock();
if (m_RegisterState == RAS_REGISTER_STATE_REGISTERED)
{
ReturnEndpointID->length = m_RASEndpointID.length;
//m_RASEndpointID.value is an array and not a pointer.
//so explicit assignment of each field is required
ReturnEndpointID->value = m_RASEndpointID.value;
hr = S_OK;
}
else
{
hr = S_OK;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "GetEndpointID - exited." ));
return hr;
}
//the addr and port are in network byte order
BOOL
RAS_CLIENT::Initialize(
IN SOCKADDR_IN* psaGKAddr
)
{
DWORD dwSize;
int rc;
H323DBG(( DEBUG_LEVEL_TRACE, "RAS Initialize entered:%p.",this ));
//set the m_GKAddress here
dwSize = sizeof m_RASEndpointID.value;
GetComputerNameW( m_RASEndpointID.value, &dwSize );
m_RASEndpointID.length = (WORD)wcslen(m_RASEndpointID.value);
m_pAliasList = new H323_ALIASNAMES;
if( m_pAliasList == NULL )
{
goto error2;
}
ZeroMemory( (PVOID)m_pAliasList, sizeof(H323_ALIASNAMES) );
if( g_RegistrySettings.fIsGKLogOnPhoneEnabled )
{
if(!AddAliasItem( m_pAliasList,
g_RegistrySettings.wszGKLogOnPhone,
e164_chosen ))
{
goto error3;
}
}
if( g_RegistrySettings.fIsGKLogOnAccountEnabled )
{
if(!AddAliasItem( m_pAliasList,
g_RegistrySettings.wszGKLogOnAccount,
h323_ID_chosen ))
{
goto error3;
}
}
if( m_pAliasList->wCount == 0 )
{
//add the machine name as he default alias
if(!AddAliasItem( m_pAliasList,
m_RASEndpointID.value,
h323_ID_chosen ))
{
goto error3;
}
}
rc = InitASNCoder();
if( rc != ASN1_SUCCESS )
{
H323DBG((DEBUG_LEVEL_TRACE, "RAS_InitCoder() returned: %d ", rc));
goto error3;
}
m_GKAddress = *psaGKAddr;
if(!InitializeIo() )
{
goto error4;
}
H323DBG((DEBUG_LEVEL_TRACE, "GK addr:%lx.", m_GKAddress.sin_addr.s_addr ));
m_dwState = RAS_CLIENT_STATE_INITIALIZED;
m_RegisterState = RAS_REGISTER_STATE_IDLE;
H323DBG(( DEBUG_LEVEL_TRACE, "RAS Initialize exited:%p.",this ));
return TRUE;
error4:
TermASNCoder();
error3:
FreeAliasNames( m_pAliasList );
m_pAliasList = NULL;
error2:
return FALSE;
}
void
RAS_CLIENT::Shutdown(void)
{
H323DBG(( DEBUG_LEVEL_TRACE, "RAS Shutdown entered:%p.",this ));
Lock();
switch (m_dwState)
{
case RAS_CLIENT_STATE_NONE:
// nothing to do
break;
case RAS_CLIENT_STATE_INITIALIZED:
if( m_Socket != INVALID_SOCKET )
{
closesocket(m_Socket);
m_Socket = INVALID_SOCKET;
}
//free alias list
FreeAliasNames( m_pAliasList );
m_pAliasList = NULL;
TermASNCoder();
m_dwState = RAS_CLIENT_STATE_NONE;
//delete if any timers
if( m_hRegTTLTimer )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTTLTimer, NULL );
m_hRegTTLTimer = NULL;
}
if( m_hUnRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hUnRegTimer, NULL );
m_hUnRegTimer = NULL;
m_dwUnRegRetryCount = 0;
}
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL );
m_hRegTimer = NULL;
}
if( m_pRRQExpireContext != NULL )
{
delete m_pRRQExpireContext;
m_pRRQExpireContext = NULL;
}
if( m_pURQExpireContext != NULL )
{
delete m_pURQExpireContext;
m_pURQExpireContext = NULL;
}
m_RegisterState = RAS_REGISTER_STATE_IDLE;
m_dwSendFreeLen = 0;
m_dwRegRetryCount = 0;
m_dwUnRegRetryCount = 0;
m_dwCallsInProgress = 0;
m_lastRegisterSeqNum = 0;
m_wTTLSeqNumber = 0;
m_UnRegisterSeqNum = 0;
m_wRASSeqNum = 0;
m_dwRegTimeToLive = 0;
ZeroMemory( (PVOID)&m_GKAddress, sizeof(SOCKADDR_IN) );
ZeroMemory( (PVOID)&m_ASNCoderInfo, sizeof(ASN1_CODER_INFO) );
ZeroMemory( (PVOID)&m_PendingURQ, sizeof(PENDINGURQ) );
ZeroMemory( (PVOID)&m_RASEndpointID, sizeof(ENDPOINT_ID) );
break;
default:
_ASSERTE(FALSE);
break;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "RAS Shutdown exited:%p.",this ));
}
BOOL
RAS_CLIENT::FreeSendList(
PLIST_ENTRY pListHead
)
{
PLIST_ENTRY pLE;
RAS_SEND_CONTEXT * pSendContext;
H323DBG(( DEBUG_LEVEL_ERROR, "FreeSendList entered." ));
// process list until empty
while( IsListEmpty(pListHead) == FALSE )
{
// retrieve first entry
pLE = RemoveHeadList(pListHead);
// convert list entry to structure pointer
pSendContext = CONTAINING_RECORD( pLE, RAS_SEND_CONTEXT, ListEntry );
// release memory
if( pSendContext != NULL )
{
delete pSendContext;
pSendContext = NULL;
}
}
H323DBG(( DEBUG_LEVEL_ERROR, "FreeSendList exited:%p.", this ));
// success
return TRUE;
}
//!!always called from a lock
RAS_SEND_CONTEXT *
RAS_CLIENT::AllocSendBuffer(void)
{
RAS_SEND_CONTEXT *pSendBuf;
H323DBG(( DEBUG_LEVEL_TRACE, "AllocSendBuffer entered:%p.",this ));
if( m_dwSendFreeLen )
{
m_dwSendFreeLen--;
_ASSERTE( IsListEmpty(&m_sendFreeList) == FALSE );
LIST_ENTRY *pLE = RemoveHeadList( &m_sendFreeList );
pSendBuf = CONTAINING_RECORD( pLE, RAS_SEND_CONTEXT, ListEntry );
}
else
{
pSendBuf = (RAS_SEND_CONTEXT*)new RAS_SEND_CONTEXT;
}
H323DBG(( DEBUG_LEVEL_TRACE, "AllocSendBuffer exited:%p.",this ));
return pSendBuf;
}
//!!always called from a lock
void
RAS_CLIENT::FreeSendBuffer(
IN RAS_SEND_CONTEXT * pBuffer
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "FreeSendBuffer entered:%p.",this ));
if(m_dwSendFreeLen < RASIO_SEND_BUFFER_LIST_MAX )
{
m_dwSendFreeLen++;
InsertHeadList( &m_sendFreeList, &pBuffer->ListEntry );
}
else
{
delete pBuffer;
}
H323DBG(( DEBUG_LEVEL_TRACE, "FreeSendBuffer exited:%p.",this ));
}
//RAS client functions
void
NTAPI RAS_CLIENT::RegExpiredCallback (
IN PVOID ContextParameter, // ExpContext
IN BOOLEAN TimerFired) // not used
{
EXPIRE_CONTEXT * pExpireContext;
RAS_CLIENT * This;
H323DBG(( DEBUG_LEVEL_TRACE, "RegExpiredCallback - entered." ));
_ASSERTE( ContextParameter );
pExpireContext = (EXPIRE_CONTEXT *)ContextParameter;
_ASSERTE( m_pRRQExpireContext == pExpireContext );
_ASSERTE(pExpireContext -> RasClient);
This = (RAS_CLIENT *) pExpireContext -> RasClient;
This -> RegExpired (pExpireContext -> seqNumber);
H323DBG(( DEBUG_LEVEL_TRACE, "RegExpiredCallback - exited." ));
delete pExpireContext;
}
void
NTAPI RAS_CLIENT::UnregExpiredCallback(
IN PVOID ContextParameter, // ExpContext
IN BOOLEAN TimerFired) // not used
{
EXPIRE_CONTEXT * pExpireContext;
RAS_CLIENT * This;
H323DBG(( DEBUG_LEVEL_TRACE, "UnregExpiredCallback - entered." ));
_ASSERTE(ContextParameter);
pExpireContext = (EXPIRE_CONTEXT *) ContextParameter;
_ASSERTE( m_pURQExpireContext == pExpireContext );
_ASSERTE( pExpireContext -> RasClient );
This = (RAS_CLIENT *) pExpireContext -> RasClient;
This -> UnregExpired( pExpireContext -> seqNumber );
H323DBG(( DEBUG_LEVEL_TRACE, "UnregExpiredCallback - exited." ));
delete pExpireContext;
}
void
NTAPI RAS_CLIENT::TTLExpiredCallback(
IN PVOID ContextParameter, // ExpContext
IN BOOLEAN TimerFired) // not used
{
RAS_CLIENT * This;
_ASSERTE(ContextParameter);
This = (RAS_CLIENT*)ContextParameter;
_ASSERTE(This == &g_RasClient);
This -> TTLExpired();
}
//If we have already sent RRQ to this GK then this RRQ is supposed to rplace
//the original alias list with the new list
BOOL
RAS_CLIENT::SendRRQ(
IN long seqNumber,
IN PALIASCHANGE_REQUEST pAliasChangeRequest
)
{
RasMessage rasMessage;
RegistrationRequest * RRQ;
SOCKADDR_IN sockAddr;
EXPIRE_CONTEXT * pExpireContext = NULL;
RegistrationRequest_callSignalAddress CallSignalAddressSequence;
RegistrationRequest_rasAddress RasAddressSequence;
H323DBG(( DEBUG_LEVEL_TRACE, "SendRRQ entered:%p.",this ));
pExpireContext = new EXPIRE_CONTEXT;
if( pExpireContext == NULL )
{
return FALSE;
}
Lock();
// initialize the structure
ZeroMemory (&rasMessage, sizeof rasMessage);
rasMessage.choice = registrationRequest_chosen;
RRQ = &rasMessage.u.registrationRequest;
RRQ -> bit_mask = 0;
RRQ -> protocolIdentifier = OID_H225ProtocolIdentifierV2;
// get sequence number
if( seqNumber != NOT_RESEND_SEQ_NUM )
{
RRQ -> requestSeqNum = (WORD)seqNumber;
}
else
{
RRQ -> requestSeqNum = GetNextSeqNum();
if( pAliasChangeRequest == NULL )
{
m_lastRegisterSeqNum = RRQ -> requestSeqNum;
}
else
{
pAliasChangeRequest->wRequestSeqNum = RRQ -> requestSeqNum;
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "RRQ seqNum:%d.", RRQ -> requestSeqNum ));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port =
htons(LOWORD(g_RegistrySettings.dwQ931ListenPort));
//we are listening for Q931 conns on all local interfaces
//so specify just one of the local IP addresses
sockAddr.sin_addr.s_addr = m_sockAddr.sin_addr.s_addr;
SetTransportAddress( &sockAddr, &CallSignalAddressSequence.value);
CallSignalAddressSequence.next = NULL;
RRQ -> callSignalAddress = &CallSignalAddressSequence;
// ras address. The UDP socket for this GK
RasAddressSequence.next = NULL;
RasAddressSequence.value = m_transportAddress;
RRQ -> rasAddress = &RasAddressSequence;
// fill in endpoint type
RRQ -> terminalType.bit_mask |= terminal_present;
RRQ -> terminalType.terminal.bit_mask = 0;
//fill in terminal alias list
if( pAliasChangeRequest && pAliasChangeRequest->pAliasList )
{
RRQ -> terminalAlias = (RegistrationRequest_terminalAlias *)
SetMsgAddressAlias( pAliasChangeRequest->pAliasList );
if (NULL == RRQ -> terminalAlias)
{
goto cleanup;
}
RRQ -> bit_mask |= RegistrationRequest_terminalAlias_present;
RRQ -> bit_mask |= RegistrationRequest_endpointIdentifier_present;
RRQ->endpointIdentifier.length = pAliasChangeRequest->rasEndpointID.length;
RRQ->endpointIdentifier.value = pAliasChangeRequest->rasEndpointID.value;
}
else if( m_pAliasList && m_pAliasList->wCount )
{
RRQ -> terminalAlias = (RegistrationRequest_terminalAlias *)
SetMsgAddressAlias( m_pAliasList );
if (NULL == RRQ -> terminalAlias)
{
goto cleanup;
}
RRQ -> bit_mask |= RegistrationRequest_terminalAlias_present;
}
else
{
_ASSERTE(0);
}
//endpointVendor
CopyVendorInfo( &(RRQ -> endpointVendor) );
//a few random booleans
RRQ -> discoveryComplete = FALSE;
RRQ -> keepAlive = FALSE;
RRQ -> willSupplyUUIEs = FALSE;
// encode and send
if( !IssueSend(&rasMessage) )
{
goto cleanup;
}
//delete if any previous TTL timer
if( m_hRegTTLTimer )
{
DeleteTimerQueueTimer(H323TimerQueue, m_hRegTTLTimer, NULL );
m_hRegTTLTimer = NULL;
}
//delete if any previous RRQ sent timer
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL );
m_hRegTimer = NULL;
}
pExpireContext -> RasClient = this;
pExpireContext -> seqNumber = RRQ -> requestSeqNum;
if( !CreateTimerQueueTimer(
&m_hRegTimer,
H323TimerQueue,
RAS_CLIENT::RegExpiredCallback,
pExpireContext,
REG_EXPIRE_TIME, 0,
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE ) )
{
goto cleanup;
}
if( RRQ -> bit_mask & RegistrationRequest_terminalAlias_present )
{
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
RRQ -> terminalAlias);
}
m_dwRegRetryCount++;
if( pAliasChangeRequest == NULL )
{
m_RegisterState = RAS_REGISTER_STATE_RRQSENT;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "SendRRQ exited:%p.", this ));
return TRUE;
cleanup:
if( RRQ -> bit_mask & RegistrationRequest_terminalAlias_present )
{
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
RRQ -> terminalAlias);
}
if( pExpireContext != NULL )
{
delete pExpireContext;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "SendRRQ error:%p.",this ));
return FALSE;
}
BOOL
RAS_CLIENT::SendURQ(
IN long seqNumber,
IN EndpointIdentifier * pEndpointID
)
{
RasMessage rasMessage;
UnregistrationRequest * URQ;
SOCKADDR_IN sockAddr;
EXPIRE_CONTEXT * pExpireContext = NULL;
UnregistrationRequest_callSignalAddress CallSignalAddressSequence;
H323DBG(( DEBUG_LEVEL_TRACE, "SendURQ entered:%p.",this ));
Lock();
if( m_RegisterState == RAS_REGISTER_STATE_RRQSENT )
{
//store the seqNumber of this RRQ and send URQ if we recv RCF
m_PendingURQ.RRQSeqNumber = m_lastRegisterSeqNum;
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "rrq sent:so pending urq." ));
return TRUE;
}
else if( m_RegisterState != RAS_REGISTER_STATE_REGISTERED )
{
//if already unregistered or URQ sent then return success
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "current state:%d.", m_RegisterState ));
return TRUE;
}
pExpireContext = new EXPIRE_CONTEXT;
if( pExpireContext == NULL )
{
goto cleanup;
}
ZeroMemory (&rasMessage, sizeof RasMessage);
rasMessage.choice = unregistrationRequest_chosen;
URQ = &rasMessage.u.unregistrationRequest;
// get sequence number
if( seqNumber != NOT_RESEND_SEQ_NUM )
{
URQ -> requestSeqNum = (WORD)seqNumber;
}
else
{
m_UnRegisterSeqNum = GetNextSeqNum();
URQ -> requestSeqNum = (WORD)m_UnRegisterSeqNum;
}
H323DBG(( DEBUG_LEVEL_TRACE, "RRQ seqNum:%d.", URQ -> requestSeqNum ));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port =
htons(LOWORD(g_RegistrySettings.dwQ931ListenPort));
//we are listening for Q931 conns on all local interfaces
//so specify just one of the local IP addresses
sockAddr.sin_addr.s_addr = m_sockAddr.sin_addr.s_addr;
SetTransportAddress( &sockAddr, &CallSignalAddressSequence.value);
CallSignalAddressSequence.next = NULL;
URQ -> callSignalAddress = &CallSignalAddressSequence;
//get endpointidentifier by using GetComputerNameW
URQ -> bit_mask |= UnregistrationRequest_endpointIdentifier_present;
if( pEndpointID != NULL )
{
URQ->endpointIdentifier.length = pEndpointID ->length;
URQ->endpointIdentifier.value = pEndpointID -> value;
}
else
{
URQ->endpointIdentifier.length = m_RASEndpointID.length;
URQ->endpointIdentifier.value = m_RASEndpointID.value;
}
// encode and send
if( !IssueSend( &rasMessage ) )
{
goto cleanup;
}
pExpireContext -> RasClient = this;
pExpireContext -> seqNumber = URQ -> requestSeqNum;
//delete if any previous RRQ sent timer
if( m_hUnRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hUnRegTimer, NULL );
m_hUnRegTimer = NULL;
m_dwUnRegRetryCount = 0;
}
if( !CreateTimerQueueTimer(
&m_hUnRegTimer,
H323TimerQueue,
RAS_CLIENT::UnregExpiredCallback,
pExpireContext,
REG_EXPIRE_TIME, 0,
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE) )
{
goto cleanup;
}
//delete if any TTL timer
if( m_hRegTTLTimer )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTTLTimer, NULL );
m_hRegTTLTimer = NULL;
}
m_dwUnRegRetryCount++;
m_RegisterState = RAS_REGISTER_STATE_URQSENT;
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "SendURQ exited:%p.",this ));
return TRUE;
cleanup:
if( pExpireContext != NULL )
{
delete pExpireContext;
}
Unlock();
return FALSE;
}
//!!always called from a lock
BOOL
RAS_CLIENT::SendUCF(
IN WORD seqNumber
)
{
RasMessage rasMessage;
UnregistrationConfirm * UCF;
H323DBG(( DEBUG_LEVEL_TRACE, "SendUCF entered:%p.",this ));
// initialize the structure
ZeroMemory (&rasMessage, sizeof rasMessage);
rasMessage.choice = unregistrationConfirm_chosen;
UCF = &rasMessage.u.unregistrationConfirm;
UCF -> bit_mask = 0;
UCF -> requestSeqNum = seqNumber;
if( !IssueSend( &rasMessage ) )
{
return FALSE;
}
H323DBG(( DEBUG_LEVEL_TRACE, "SendUCF exited:%p.",this ));
return TRUE;
}
//!!always called from a lock
BOOL
RAS_CLIENT::SendURJ(
IN WORD seqNumber,
IN DWORD dwReason
)
{
RasMessage rasMessage;
UnregistrationReject * URJ;
H323DBG(( DEBUG_LEVEL_TRACE, "SendURJ entered:%p.",this ));
// initialize the structure
ZeroMemory (&rasMessage, sizeof rasMessage);
rasMessage.choice = unregistrationReject_chosen;
URJ = &rasMessage.u.unregistrationReject;
URJ -> bit_mask = 0;
URJ -> requestSeqNum = seqNumber;
URJ -> rejectReason.choice = (WORD)dwReason;
if( !IssueSend( &rasMessage ) )
{
return FALSE;
}
H323DBG(( DEBUG_LEVEL_TRACE, "SendURJ exited:%p.",this ));
return TRUE;
}
//!!always called from a lock
void
RAS_CLIENT::ProcessRasMessage(
IN RasMessage *pRasMessage
)
{
PH323_CALL pCall = NULL;
ASN1decoding_s ASN1decInfo;
H323DBG(( DEBUG_LEVEL_TRACE, "RAS: processing RasMessage" ));
//Verify that the RCF came from the expected gatekeeper
switch( pRasMessage -> choice )
{
case registrationReject_chosen:
OnRegistrationReject( &pRasMessage -> u.registrationReject );
break;
case registrationConfirm_chosen:
OnRegistrationConfirm( &pRasMessage -> u.registrationConfirm );
break;
case unregistrationRequest_chosen:
OnUnregistrationRequest( &pRasMessage -> u.unregistrationRequest );
break;
case unregistrationReject_chosen:
OnUnregistrationReject( &pRasMessage -> u.unregistrationReject );
break;
case unregistrationConfirm_chosen:
OnUnregistrationConfirm( &pRasMessage -> u.unregistrationConfirm );
break;
case infoRequest_chosen:
CopyMemory( (PVOID)&ASN1decInfo, (PVOID)m_ASNCoderInfo.pDecInfo,
sizeof(ASN1decoding_s) );
//This function should be always called in
//a lock and it unlocks the the ras client
OnInfoRequest( &pRasMessage -> u.infoRequest );
ASN1_FreeDecoded( &ASN1decInfo, pRasMessage, RasMessage_PDU );
//return here since we have already unlocked and freed the buffer
return;
default:
CopyMemory( (PVOID)&ASN1decInfo, (PVOID)m_ASNCoderInfo.pDecInfo,
sizeof(ASN1decoding_s) );
//Don't loclk the RAS client while locking the call object.
Unlock();
HandleRASCallMessage( pRasMessage );
ASN1_FreeDecoded( &ASN1decInfo, pRasMessage, RasMessage_PDU );
//return here since we have already unlocked and freed the buffer
return;
}
ASN1_FreeDecoded( m_ASNCoderInfo.pDecInfo, pRasMessage, RasMessage_PDU );
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "ProcessRasMessage exited:%p.",this ));
}
//!!always called from a lock
void
HandleRASCallMessage(
IN RasMessage *pRasMessage
)
{
PH323_CALL pCall = NULL;
H323DBG(( DEBUG_LEVEL_TRACE, "RAS: processing RASCallMessage" ));
switch( pRasMessage -> choice )
{
case admissionConfirm_chosen:
pCall = g_pH323Line -> FindCallByARQSeqNumAndLock(
pRasMessage -> u.admissionConfirm.requestSeqNum);
if( pCall != NULL )
{
pCall -> OnAdmissionConfirm( &pRasMessage->u.admissionConfirm );
pCall -> Unlock();
}
else
H323DBG(( DEBUG_LEVEL_ERROR, "acf:call not found:%d.",
pRasMessage -> u.admissionConfirm.requestSeqNum ));
break;
case admissionReject_chosen:
pCall = g_pH323Line -> FindCallByARQSeqNumAndLock(
pRasMessage -> u.admissionReject.requestSeqNum );
if( pCall != NULL )
{
pCall -> OnAdmissionReject( &pRasMessage->u.admissionReject );
pCall -> Unlock();
}
else
H323DBG(( DEBUG_LEVEL_ERROR, "arj:call not found:%d.",
pRasMessage -> u.admissionReject.requestSeqNum ));
break;
case disengageRequest_chosen:
pCall = g_pH323Line -> FindCallByCallRefAndLock(
pRasMessage -> u.disengageRequest.callReferenceValue );
if( pCall != NULL )
{
pCall -> OnDisengageRequest( &pRasMessage -> u.disengageRequest );
pCall -> Unlock();
}
else
H323DBG(( DEBUG_LEVEL_ERROR, "drq:call not found:%d.",
pRasMessage -> u.disengageRequest.callReferenceValue ));
break;
case disengageConfirm_chosen:
pCall = g_pH323Line -> FindCallByDRQSeqNumAndLock(
pRasMessage -> u.disengageConfirm.requestSeqNum );
if( pCall != NULL )
{
pCall -> OnDisengageConfirm( &pRasMessage -> u.disengageConfirm );
pCall -> Unlock();
}
else
H323DBG(( DEBUG_LEVEL_ERROR, "dcf:call not found:%d.",
pRasMessage -> u.disengageConfirm.requestSeqNum ));
break;
case disengageReject_chosen:
pCall = g_pH323Line -> FindCallByDRQSeqNumAndLock(
pRasMessage -> u.disengageReject.requestSeqNum );
if( pCall != NULL )
{
pCall -> OnDisengageReject( &pRasMessage -> u.disengageReject );
pCall -> Unlock();
}
else
H323DBG(( DEBUG_LEVEL_ERROR, "drj:call not found:%d.",
pRasMessage -> u.disengageReject.requestSeqNum));
break;
case requestInProgress_chosen:
pCall = g_pH323Line -> FindCallByARQSeqNumAndLock(
pRasMessage->u.requestInProgress.requestSeqNum );
if( pCall != NULL )
{
pCall -> OnRequestInProgress( &pRasMessage->u.requestInProgress );
pCall -> Unlock();
}
else
H323DBG(( DEBUG_LEVEL_ERROR, "rip:call not found:%d.",
pRasMessage->u.requestInProgress.requestSeqNum ));
break;
default:
_ASSERTE(0);
H323DBG(( DEBUG_LEVEL_ERROR, "ProcessRASMessage: wrong message:%d",
pRasMessage -> choice));
break;
}
H323DBG(( DEBUG_LEVEL_TRACE, "HandleRASCallMessage exited" ));
}
void
RAS_CLIENT::RegExpired(
IN WORD seqNumber
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "RegExpired entered:%p.", this ));
Lock();
m_pRRQExpireContext = NULL;
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL );
m_hRegTimer = NULL;
}
/*
1. Registered:ignore this timeout
2. RRQ sent: (the endpoint has initiated the process of registering but
hasn't heard from the GK yet) Resend the RRQ
3. Unregistered: ignore this imeout
4. URQ sent: (the endpoint has initiated the process of unregistering but
hasn't heard from the GK yet) ignore this timeout
5. Idle: The GK client object has just been initialized and hasn't done
anything. This should not happen.
*/
switch( m_RegisterState )
{
case RAS_REGISTER_STATE_RRQSENT:
if( m_dwRegRetryCount < REG_RETRY_MAX )
{
if( !SendRRQ( (long)seqNumber, NULL ) )
{
m_RegisterState = RAS_REGISTER_STATE_RRQEXPIRED;
}
}
else
{
m_RegisterState = RAS_REGISTER_STATE_RRQEXPIRED;
}
break;
case RAS_REGISTER_STATE_REGISTERED:
case RAS_REGISTER_STATE_URQSENT:
case RAS_REGISTER_STATE_UNREGISTERED:
break;
case RAS_REGISTER_STATE_IDLE:
_ASSERTE(0);
break;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "RegExpired exited:%p.",this ));
}
void
RAS_CLIENT::TTLExpired()
{
RasMessage rasMessage;
RegistrationRequest * RRQ;
H323DBG(( DEBUG_LEVEL_TRACE, "TTLExpired entered:%p.",this ));
Lock();
if( m_RegisterState == RAS_REGISTER_STATE_REGISTERED )
{
//send light weight RRQ
// initialize the structure
ZeroMemory (&rasMessage, sizeof rasMessage);
rasMessage.choice = registrationRequest_chosen;
RRQ = &rasMessage.u.registrationRequest;
RRQ -> bit_mask = 0;
RRQ -> protocolIdentifier = OID_H225ProtocolIdentifierV2;
RRQ -> bit_mask |= keepAlive_present;
RRQ -> keepAlive = TRUE;
//copy TTL
RRQ -> bit_mask |= RegistrationRequest_timeToLive_present;
RRQ -> timeToLive = m_dwRegTimeToLive;
//endpoint identifier
RRQ -> bit_mask |= RegistrationRequest_endpointIdentifier_present;
RRQ->endpointIdentifier.length = m_RASEndpointID.length;
RRQ->endpointIdentifier.value = m_RASEndpointID.value;
//seqNumber
m_wTTLSeqNumber = GetNextSeqNum();
RRQ -> requestSeqNum = (WORD)m_wTTLSeqNumber;
//what about gatekeeperIdentifier, tokens?
// encode and send
if( !IssueSend(&rasMessage) )
{
H323DBG(( DEBUG_LEVEL_TRACE, "SendLwtRRQ error:%p.",this ));
Unlock();
return;
}
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "TTLExpired exited:%p.",this ));
}
void
RAS_CLIENT::UnregExpired(
IN WORD seqNumber
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "UnregExpired entered:%p.",this ));
Lock();
m_pURQExpireContext = NULL;
if( m_hUnRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hUnRegTimer, NULL);
m_hUnRegTimer = NULL;
m_dwUnRegRetryCount = 0;
}
switch( m_RegisterState )
{
case RAS_REGISTER_STATE_URQSENT:
if( m_dwUnRegRetryCount < URQ_RETRY_MAX )
{
SendURQ( (long)seqNumber, NULL );
}
else
{
m_RegisterState = RAS_REGISTER_STATE_URQEXPIRED;
}
break;
case RAS_REGISTER_STATE_REGISTERED:
case RAS_REGISTER_STATE_RRQSENT:
case RAS_REGISTER_STATE_UNREGISTERED:
break;
case RAS_REGISTER_STATE_IDLE:
_ASSERTE(0);
break;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "UnregExpired exited:%p.",this ));
}
void
RAS_CLIENT::OnUnregistrationRequest(
IN UnregistrationRequest *URQ
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "OnUnregistrationRequest entered:%p.", this ));
_ASSERTE( m_RegisterState != RAS_REGISTER_STATE_IDLE );
if( (m_RegisterState == RAS_REGISTER_STATE_UNREGISTERED) ||
(m_RegisterState == RAS_REGISTER_STATE_RRJ) )
{
SendURJ( URQ -> requestSeqNum, notCurrentlyRegistered_chosen );
}
else if( m_dwCallsInProgress )
{
SendURJ( URQ -> requestSeqNum, callInProgress_chosen );
}
else
{
m_RegisterState = RAS_REGISTER_STATE_UNREGISTERED;
SendUCF( URQ -> requestSeqNum );
//try to register again
if( !SendRRQ( NOT_RESEND_SEQ_NUM, NULL ) )
{
H323DBG(( DEBUG_LEVEL_ERROR,
"couldn't send rrq on urq request." ));
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "OnUnregistrationRequest exited:%p.",this ));
}
//!!always called from a lock
void
RAS_CLIENT::OnUnregistrationConfirm(
IN UnregistrationConfirm *UCF
)
{
H323DBG((DEBUG_LEVEL_TRACE, "OnUnregistrationConfirm entered:%p.",this));
if( UCF -> requestSeqNum != m_UnRegisterSeqNum )
return;
_ASSERTE( m_hUnRegTimer );
if( m_hUnRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hUnRegTimer, NULL);
m_hUnRegTimer = NULL;
m_dwUnRegRetryCount = 0;
}
if( (m_RegisterState == RAS_REGISTER_STATE_URQSENT) ||
(m_RegisterState == RAS_REGISTER_STATE_URQEXPIRED) )
{
//delete if any TTL timer
if( m_hRegTTLTimer )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTTLTimer, NULL );
m_hRegTTLTimer = NULL;
}
m_RegisterState = RAS_REGISTER_STATE_UNREGISTERED;
}
H323DBG(( DEBUG_LEVEL_TRACE, "OnUnregistrationConfirm exited:%p.",this));
}
//!!always called from a lock
void
RAS_CLIENT::OnUnregistrationReject(
IN UnregistrationReject *URJ
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "OnUnregistrationReject entered:%p.",this ));
if( URJ -> requestSeqNum != m_UnRegisterSeqNum )
{
return;
}
if( m_hUnRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hUnRegTimer, NULL);
m_hUnRegTimer = NULL;
m_dwUnRegRetryCount = 0;
}
if( (m_RegisterState == RAS_REGISTER_STATE_URQSENT) ||
(m_RegisterState == RAS_REGISTER_STATE_URQEXPIRED) )
{
m_RegisterState = RAS_REGISTER_STATE_UNREGISTERED;
}
H323DBG(( DEBUG_LEVEL_TRACE, "OnUnregistrationReject exited:%p.",this ));
}
//!!always called from a lock
void
RAS_CLIENT::OnRegistrationReject(
IN RegistrationReject * RRJ
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "OnRegistrationReject entered:%p.",this ));
if( RRJ -> requestSeqNum == m_wTTLSeqNumber )
{
//Keep alive failed. So start registration process again.
//This will change the RAS registration state to RRQSENT from REGISTERED.
if( !SendRRQ( NOT_RESEND_SEQ_NUM, NULL ) )
{
H323DBG(( DEBUG_LEVEL_ERROR,
"couldn't send rrq on Keep alive failure." ));
m_RegisterState = RAS_REGISTER_STATE_UNREGISTERED;
}
}
else if( RRJ -> requestSeqNum == m_lastRegisterSeqNum )
{
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL);
m_hRegTimer = NULL;
m_dwRegRetryCount = 0;
}
if( (m_RegisterState == RAS_REGISTER_STATE_RRQSENT) ||
(m_RegisterState == RAS_REGISTER_STATE_RRQEXPIRED) )
{
m_RegisterState = RAS_REGISTER_STATE_RRJ;
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "OnRegistrationReject exitd:%p.",this ));
}
//!!always called in lock
void
RAS_CLIENT::OnRegistrationConfirm(
IN RegistrationConfirm * RCF )
{
LIST_ENTRY *pListEntry = NULL;
PALIASCHANGE_REQUEST pAliasChangeRequest = NULL;
H323DBG(( DEBUG_LEVEL_TRACE, "OnRegistrationConfirm entered:%p.", this ));
if( RCF -> requestSeqNum == m_PendingURQ.RRQSeqNumber )
{
//The timer could have been startd with the last RRQ,
//irrespective of the current state of registration.
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL);
m_hRegTimer = NULL;
m_dwRegRetryCount = 0;
}
//send URQ with the endpointIdentifier
SendURQ( NOT_RESEND_SEQ_NUM, &RCF->endpointIdentifier );
H323DBG(( DEBUG_LEVEL_TRACE, "sending pending URQ for RRQ:%d",
RCF->requestSeqNum ));
return;
}
else if( RCF -> requestSeqNum == m_lastRegisterSeqNum )
{
//The timer could have been startd with the last RRQ,
//irrespective of the current state of registration.
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL);
m_hRegTimer = NULL;
m_dwRegRetryCount = 0;
}
switch (m_RegisterState)
{
case RAS_REGISTER_STATE_REGISTERED:
if (RCF->requestSeqNum == m_wTTLSeqNumber)
{
H323DBG(( DEBUG_LEVEL_TRACE, "RCF for TTL-RRQ." ));
}
else
{
H323DBG(( DEBUG_LEVEL_WARNING,
"warning: received RCF, but was already registered-ignoring"));
}
break;
case RAS_REGISTER_STATE_RRQEXPIRED:
H323DBG(( DEBUG_LEVEL_TRACE,
"received RCF, but registration already expired, send URQ" ));
SendURQ (NOT_RESEND_SEQ_NUM, &RCF->endpointIdentifier);
break;
case RAS_REGISTER_STATE_RRQSENT:
//expecting RRQ. gatekeeper has responded.
m_RegisterState = RAS_REGISTER_STATE_REGISTERED;
CopyMemory( (PVOID)m_RASEndpointID.value,
(PVOID)RCF -> endpointIdentifier.value,
RCF -> endpointIdentifier.length * sizeof(WCHAR) );
m_RASEndpointID.value[RCF -> endpointIdentifier.length] = L'\0';
m_RASEndpointID.length = (WORD)RCF -> endpointIdentifier.length;
InitializeTTLTimer( RCF );
break;
default:
H323DBG(( DEBUG_LEVEL_TRACE,
"RAS: received RRQ, but was in unexpected state"));
break;
}
}
else if( RCF -> requestSeqNum == m_wTTLSeqNumber )
{
//The timer could have been startd with the last RRQ,
//irrespective of the current state of registration.
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL);
m_hRegTimer = NULL;
m_dwRegRetryCount = 0;
}
//look for the change in keepalive interval.
InitializeTTLTimer( RCF );
}
else
{
//Try to find if this is a alias change request.
for( pListEntry = m_aliasChangeRequestList.Flink;
pListEntry != &m_aliasChangeRequestList;
pListEntry = pListEntry -> Flink )
{
pAliasChangeRequest = CONTAINING_RECORD( pListEntry,
ALIASCHANGE_REQUEST, listEntry );
if( pAliasChangeRequest -> wRequestSeqNum == RCF -> requestSeqNum )
{
break;
}
}
if( pListEntry != &m_aliasChangeRequestList )
{
//The timer could have been startd with the last RRQ,
//irrespective of the current state of registration.
if( m_hRegTimer != NULL )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTimer, NULL);
m_hRegTimer = NULL;
m_dwRegRetryCount = 0;
}
//if registration has changed since this request was made then
//ignore the message.
if( memcmp( (PVOID)pAliasChangeRequest -> rasEndpointID.value,
m_RASEndpointID.value, m_RASEndpointID.length * sizeof(WCHAR) )
== 0 )
{
//update the alias list.
FreeAliasNames( m_pAliasList );
m_pAliasList = pAliasChangeRequest->pAliasList;
RemoveEntryList( &pAliasChangeRequest->listEntry );
delete pAliasChangeRequest;
}
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "OnRegistrationConfirm exited:%p.", this ));
}
//!!always called in a lock.
BOOL
RAS_CLIENT::InitializeTTLTimer(
IN RegistrationConfirm * RCF )
{
H323DBG(( DEBUG_LEVEL_TRACE, "InitializeTTLTimer - entered." ));
if( (RCF->bit_mask & RegistrationConfirm_timeToLive_present) &&
( (m_dwRegTimeToLive != RCF->timeToLive) || (m_hRegTTLTimer == NULL) )
)
{
m_dwRegTimeToLive = RCF->timeToLive;
H323DBG(( DEBUG_LEVEL_TRACE, "timetolive value:%d.",
m_dwRegTimeToLive ));
//delete if any previous TTL timer
if( m_hRegTTLTimer )
{
DeleteTimerQueueTimer( H323TimerQueue, m_hRegTTLTimer, NULL );
m_hRegTTLTimer = NULL;
}
//start a timer to send lightweight RRQ afetr given time
if( !CreateTimerQueueTimer(
&m_hRegTTLTimer,
H323TimerQueue,
RAS_CLIENT::TTLExpiredCallback,
this,
(m_dwRegTimeToLive - REG_TTL_MARGIN)*1000,
(m_dwRegTimeToLive - REG_TTL_MARGIN)*1000,
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE ) )
{
H323DBG ((DEBUG_LEVEL_ERROR, "failed to create timer queue timer"));
m_hRegTTLTimer = NULL;
return FALSE;
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "InitializeTTLTimer - exited." ));
return TRUE;
}
void
RAS_CLIENT::OnInfoRequest (
IN InfoRequest * IRQ)
{
PH323_CALL pCall;
SOCKADDR_IN ReplyAddress;
InfoRequestResponse_perCallInfo CallInfoList;
InfoRequestResponse_perCallInfo * pCallInfoList = NULL;
InfoRequestResponse_perCallInfo_Seq * CallInfo;
HRESULT hr;
int iIndex, jIndex;
int iNumCalls = 0;
int iCallTableSize;
H323DBG(( DEBUG_LEVEL_TRACE, "OnInfoRequest - entered." ));
if (m_RegisterState != RAS_REGISTER_STATE_REGISTERED)
{
H323DBG ((DEBUG_LEVEL_ERROR, "RAS: received InfoRequest, but was not registered"));
Unlock();
return;
}
if (IRQ->bit_mask & replyAddress_present)
{
if (!GetTransportAddress (&IRQ -> replyAddress, &ReplyAddress))
{
H323DBG ((DEBUG_LEVEL_ERROR, "RAS: received InfoRequest, but replyAddress was malformed"));
Unlock();
return;
}
}
else
{
ReplyAddress = m_GKAddress;
}
//Don't loclk the RAS client while locking the call object.
Unlock();
if( IRQ -> callReferenceValue )
{
//query is for a specific call. So find the call and then send IRR
pCall = g_pH323Line ->
FindCallByCallRefAndLock( IRQ -> callReferenceValue );
if( pCall )
{
CallInfo = &CallInfoList.value;
CallInfoList.next = NULL;
ZeroMemory (CallInfo, sizeof (InfoRequestResponse_perCallInfo_Seq));
CallInfo -> callIdentifier.guid.length = sizeof (GUID);
CallInfo -> conferenceID.length = sizeof (GUID);
hr = pCall -> GetCallInfo (
(GUID *) &CallInfo -> callIdentifier.guid.value,
(GUID *) &CallInfo -> conferenceID.value);
if( hr != S_OK )
{
H323DBG ((DEBUG_LEVEL_ERROR,
"RAS: call is disconnected for crv (%04XH).",
IRQ -> callReferenceValue));
return;
}
pCall -> Unlock();
CallInfo -> callReferenceValue = IRQ -> callReferenceValue;
CallInfo -> callType.choice = pointToPoint_chosen;
CallInfo -> callModel.choice = direct_chosen;
}
else
{
H323DBG(( DEBUG_LEVEL_ERROR,
"RAS: received InfoRequest for nonexistent crv (%04XH).",
IRQ -> callReferenceValue));
return;
}
SendInfoRequestResponse (&ReplyAddress, IRQ -> requestSeqNum, &CallInfoList);
}
else
{
//send the info about all the active calls.
iNumCalls = g_pH323Line->GetNoOfCalls();
if( iNumCalls != 0 )
{
pCallInfoList = new InfoRequestResponse_perCallInfo[iNumCalls];
}
if( pCallInfoList != NULL )
{
//lock the call table
g_pH323Line -> LockCallTable();
iCallTableSize = g_pH323Line->GetCallTableSize();
//lock the call so that nobody else would be able to delete the call
for( jIndex=0, iIndex=0;
(iIndex < iCallTableSize) && (jIndex < iNumCalls);
iIndex++ )
{
pCall = g_pH323Line->GetCallAtIndex(iIndex);
if( pCall != NULL )
{
pCall -> Lock();
CallInfo = &(pCallInfoList[jIndex++].value);
ZeroMemory( CallInfo, sizeof (InfoRequestResponse_perCallInfo_Seq) );
CallInfo -> callIdentifier.guid.length = sizeof( GUID );
CallInfo -> conferenceID.length = sizeof( GUID );
pCall -> GetCallInfo(
(GUID *) &CallInfo -> callIdentifier.guid.value,
(GUID *) &CallInfo -> conferenceID.value);
CallInfo -> callReferenceValue = pCall->GetCallRef();
pCall -> Unlock();
CallInfo -> callType.choice = pointToPoint_chosen;
CallInfo -> callModel.choice = direct_chosen;
}
}
for( iIndex=0; iIndex < jIndex-1; iIndex++ )
{
pCallInfoList[iIndex].next = &(pCallInfoList[iIndex+1]);
}
pCallInfoList[iIndex].next = NULL;
//unlock the call table
g_pH323Line -> UnlockCallTable();
}
SendInfoRequestResponse( &ReplyAddress, IRQ -> requestSeqNum,
pCallInfoList );
if( pCallInfoList != NULL )
{
delete pCallInfoList;
}
}
H323DBG(( DEBUG_LEVEL_TRACE, "OnInfoRequest - exited." ));
}
HRESULT RAS_CLIENT::SendInfoRequestResponse (
IN SOCKADDR_IN * RasAddress,
IN USHORT SequenceNumber,
IN InfoRequestResponse_perCallInfo * CallInfoList)
{
RasMessage RasMessage;
InfoRequestResponse * IRR;
SOCKADDR_IN SocketAddress;
HRESULT hr;
H323DBG(( DEBUG_LEVEL_TRACE, "SendInfoRequestResponse - entered." ));
Lock();
if( m_RegisterState == RAS_REGISTER_STATE_REGISTERED )
{
InfoRequestResponse_callSignalAddress CallSignalAddressSequence;
H323DBG(( DEBUG_LEVEL_TRACE, "SendIRR entered:%p.",this ));
ZeroMemory (&RasMessage, sizeof RasMessage);
RasMessage.choice = infoRequestResponse_chosen;
IRR = &RasMessage.u.infoRequestResponse;
IRR -> requestSeqNum = SequenceNumber;
// we are listening for Q931 conns on all local interfaces
// so specify just one of the local IP addresses
// -XXX- fix for multihomed support later
SocketAddress.sin_family = AF_INET;
SocketAddress.sin_port = htons (LOWORD(g_RegistrySettings.dwQ931ListenPort));
SocketAddress.sin_addr.s_addr = m_sockAddr.sin_addr.s_addr;
// callSignalAddress
SetTransportAddress (&SocketAddress, &CallSignalAddressSequence.value);
CallSignalAddressSequence.next = NULL;
IRR -> callSignalAddress = &CallSignalAddressSequence;
// rasAddress
IRR -> rasAddress = m_transportAddress;
// endpointIdentifier
IRR -> endpointIdentifier.length = m_RASEndpointID.length;
IRR -> endpointIdentifier.value = m_RASEndpointID.value;
// fill in endpoint type
IRR -> endpointType.bit_mask |= terminal_present;
IRR -> endpointType.terminal.bit_mask = 0;
if( CallInfoList )
{
IRR -> bit_mask |= perCallInfo_present;
IRR -> perCallInfo = CallInfoList;
}
// send the pdu
hr = EncodeSendMessage (&RasMessage);
}
else
{
hr = E_FAIL;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "SendInfoRequestResponse - exited." ));
return TRUE;
}
//!!always called from a lock
BOOL
RAS_CLIENT::InitializeIo (void)
{
DWORD dwFlags = 0;
int AddressLength;
H323DBG(( DEBUG_LEVEL_TRACE, "InitializeIo entered:%p.",this ));
m_Socket = WSASocket (AF_INET,
SOCK_DGRAM,
IPPROTO_UDP,
NULL, 0,
WSA_FLAG_OVERLAPPED);
if( m_Socket == INVALID_SOCKET )
{
WSAGetLastError();
return FALSE;
}
if( !H323BindIoCompletionCallback ( (HANDLE)m_Socket,
RAS_CLIENT::IoCompletionCallback, 0))
{
GetLastError();
goto cleanup;
}
m_sockAddr.sin_family = AF_INET;
m_sockAddr.sin_port = htons (0);
m_sockAddr.sin_addr.s_addr =
GetLocalIPAddress( m_GKAddress.sin_addr.S_un.S_addr );
H323DBG(( DEBUG_LEVEL_TRACE,
"gk sock addr:%lx.", m_sockAddr.sin_addr.s_addr ));
if( bind( m_Socket, (SOCKADDR *)&m_sockAddr, sizeof(m_sockAddr) )
== SOCKET_ERROR )
{
H323DBG(( DEBUG_LEVEL_ERROR,
"Couldn't bind the RAS socket:%d, %p", WSAGetLastError(), this ));
goto cleanup;
}
// now that we've bound to a dynamic UDP port,
// query that port from the stack and store it.
AddressLength = sizeof m_sockAddr;
if( getsockname(m_Socket, (SOCKADDR *)&m_sockAddr, &AddressLength)
== SOCKET_ERROR )
{
H323DBG(( DEBUG_LEVEL_ERROR,
"getsockname failed :%d, %p", WSAGetLastError(), this ));
goto cleanup;
}
_ASSERTE( ntohs(m_sockAddr.sin_port) );
// fill in the IoTransportAddress structure.
// this structure is the ASN.1-friendly transport
// address of this client's endpoint.
SetTransportAddress( &m_sockAddr, &m_transportAddress );
// initiate i/o
ZeroMemory( (PVOID)&m_recvOverlapped, sizeof(RAS_RECV_CONTEXT) );
if( !IssueRecv() )
{
goto cleanup;
}
H323DBG(( DEBUG_LEVEL_TRACE, "InitializeIo exited:%p.",this ));
return TRUE;
cleanup:
closesocket(m_Socket);
m_Socket = INVALID_SOCKET;
return FALSE;
}
DWORD GetLocalIPAddress(
IN DWORD dwRemoteAddr
)
{
DWORD dwLocalAddr = INADDR_ANY;
SOCKADDR_IN sRemoteAddr;
SOCKADDR_IN sLocalAddr;
DWORD dwNumBytesReturned = 0;
SOCKET querySocket;
H323DBG(( DEBUG_LEVEL_TRACE, "GetLocalIPAddress - entered." ));
ZeroMemory( (PVOID)&sRemoteAddr, sizeof(SOCKADDR_IN) );
ZeroMemory( (PVOID)&sLocalAddr, sizeof(SOCKADDR_IN) );
sRemoteAddr.sin_family = AF_INET;
sRemoteAddr.sin_addr = *(struct in_addr *) &dwRemoteAddr;
querySocket = WSASocket(
AF_INET, // int af
SOCK_DGRAM, // int type
IPPROTO_UDP, // int protocol
NULL, // LPWSAPROTOCOL_INFO lpProtocolInfo
0, // GROUP g
WSA_FLAG_OVERLAPPED // DWORD dwFlags
);
if( querySocket == INVALID_SOCKET )
{
H323DBG(( DEBUG_LEVEL_ERROR, "getlocalIP wsasocket:%d.",
WSAGetLastError() ));
return dwLocalAddr;
}
if( WSAIoctl(
querySocket, // SOCKET s
SIO_ROUTING_INTERFACE_QUERY, // DWORD dwIoControlCode
&sRemoteAddr, // LPVOID lpvInBuffer
sizeof(SOCKADDR_IN), // DWORD cbInBuffer
&sLocalAddr, // LPVOID lpvOUTBuffer
sizeof(SOCKADDR_IN), // DWORD cbOUTBuffer
&dwNumBytesReturned, // LPDWORD lpcbBytesReturned
NULL, // LPWSAOVERLAPPED lpOverlapped
NULL // LPWSAOVERLAPPED_COMPLETION_ROUTINE lpComplROUTINE
) == SOCKET_ERROR)
{
H323DBG(( DEBUG_LEVEL_ERROR, "getlocalIP error wsaioctl:%d.",
WSAGetLastError() ));
}
else
{
dwLocalAddr = *(DWORD *)&sLocalAddr.sin_addr;
//if the remote address is on the same machine then...
H323DBG(( DEBUG_LEVEL_ERROR, "dwLocalAddr:%x.", dwLocalAddr ));
if( dwLocalAddr == NET_LOCAL_IP_ADDR_INTERFACE )
{
dwLocalAddr = dwRemoteAddr;
}
_ASSERTE( dwLocalAddr );
}
closesocket( querySocket );
H323DBG(( DEBUG_LEVEL_TRACE, "GetLocalIPAddress - exited." ));
return dwLocalAddr;
}
//!!always called from a lock
BOOL
RAS_CLIENT::IssueRecv(void)
{
int iError;
WSABUF BufferArray [1];
H323DBG(( DEBUG_LEVEL_TRACE, "IssueRecv entered:%p.",this ));
_ASSERTE(!m_recvOverlapped.IsPending);
if(m_Socket == INVALID_SOCKET)
{
return FALSE;
}
BufferArray [0].buf = (char *)(m_recvOverlapped.arBuf);
BufferArray [0].len = IO_BUFFER_SIZE;
ZeroMemory (&m_recvOverlapped.Overlapped, sizeof(OVERLAPPED));
m_recvOverlapped.Type = OVERLAPPED_TYPE_RECV;
m_recvOverlapped.RasClient = this;
m_recvOverlapped.AddressLength = sizeof (SOCKADDR_IN);
m_recvOverlapped.Flags = 0;
if( WSARecvFrom(m_Socket,
BufferArray, 1,
&m_recvOverlapped.BytesTransferred,
&m_recvOverlapped.Flags,
(SOCKADDR*)&m_recvOverlapped.Address,
&m_recvOverlapped.AddressLength,
&m_recvOverlapped.Overlapped,
NULL) == SOCKET_ERROR )
{
iError = WSAGetLastError();
if( iError == WSA_IO_PENDING )
{
m_recvOverlapped.IsPending = TRUE;
m_IoRefCount++;
}
else if( iError == WSAEMSGSIZE )
{
//We don't handle this condition right now as it should not happen
//In future with changes in the protocol this might be invoked and
//should be fixed
_ASSERTE( FALSE );
}
else if( iError == WSAECONNRESET )
{
//On a UPD-datagram socket this error would indicate that a
//previous send operation resulted in an ICMP "Port Unreachable"
//message. This will happen if GK is not listening on the specified
//port. This case would need special handling.
_ASSERTE( FALSE );
return FALSE;
}
else
{
//fatal error on the socket. shutdown the RAS client
return FALSE;
}
}
else
{
//data recvd immediately. IsPending is set beacause anyway a
//SendComplete event will be sent which will reset this BOOL
m_recvOverlapped.IsPending = TRUE;
m_IoRefCount++;
}
H323DBG(( DEBUG_LEVEL_TRACE, "IssueRecv exited:%p.",this ));
return TRUE;
}
HRESULT
RAS_CLIENT::EncodeSendMessage(
IN RasMessage * RasMessage)
{
RAS_SEND_CONTEXT * SendContext;
ASN1error_e AsnError;
WSABUF BufferArray [1];
DWORD dwStatus;
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeSendMessage entered:%p.",this ));
Lock();
if (m_Socket == INVALID_SOCKET)
{
Unlock();
return E_FAIL;
}
SendContext = AllocSendBuffer();
if( SendContext == NULL )
{
Unlock();
return E_OUTOFMEMORY;
}
ZeroMemory( &SendContext -> Overlapped, sizeof (OVERLAPPED) );
AsnError = ASN1_Encode (
m_ASNCoderInfo.pEncInfo,
RasMessage,
RasMessage_PDU,
ASN1ENCODE_SETBUFFER,
SendContext -> arBuf,
IO_BUFFER_SIZE);
if (ASN1_FAILED (AsnError))
{
H323DBG ((DEBUG_LEVEL_ERROR, "RAS: failed to encode RAS PDU (%d).", AsnError));
FreeSendBuffer (SendContext);
Unlock();
return E_FAIL;
}
BufferArray [0].buf = (char *) SendContext -> arBuf;
BufferArray [0].len = m_ASNCoderInfo.pEncInfo -> len;
SendContext -> Type = OVERLAPPED_TYPE_SEND;
SendContext -> RasClient = this;
SendContext -> Address = m_GKAddress;
if( WSASendTo (m_Socket,
BufferArray,
1,
&SendContext -> BytesTransferred,
0,
(SOCKADDR *)&SendContext -> Address,
sizeof (SOCKADDR_IN),
&SendContext->Overlapped,
NULL) == SOCKET_ERROR
&& WSAGetLastError() != WSA_IO_PENDING)
{
dwStatus = WSAGetLastError();
H323DBG(( DEBUG_LEVEL_ERROR, "failed to issue async send on RAS socket" ));
DumpError (dwStatus);
//fatal error: shut down the client
FreeSendBuffer (SendContext);
Unlock();
return HRESULT_FROM_WIN32 (dwStatus);
}
InsertHeadList( &m_sendPendingList, &SendContext -> ListEntry );
m_IoRefCount++;
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeSendMessage exited:%p.",this ));
return S_OK;
}
// static
void
NTAPI RAS_CLIENT::IoCompletionCallback(
IN DWORD dwStatus,
IN DWORD BytesTransferred,
IN OVERLAPPED * Overlapped
)
{
RAS_OVERLAPPED * RasOverlapped;
RAS_CLIENT * pRASClient;
H323DBG(( DEBUG_LEVEL_TRACE, "ras-IoCompletionCallback entered." ));
_ASSERTE( Overlapped );
RasOverlapped = CONTAINING_RECORD( Overlapped, RAS_OVERLAPPED, Overlapped );
pRASClient = RasOverlapped -> RasClient;
switch (RasOverlapped -> Type)
{
case OVERLAPPED_TYPE_SEND:
pRASClient -> OnSendComplete( dwStatus,
static_cast<RAS_SEND_CONTEXT *> (RasOverlapped));
break;
case OVERLAPPED_TYPE_RECV:
RasOverlapped -> BytesTransferred = BytesTransferred;
pRASClient -> OnRecvComplete( dwStatus,
static_cast<RAS_RECV_CONTEXT *> (RasOverlapped));
break;
default:
_ASSERTE(FALSE);
}
H323DBG(( DEBUG_LEVEL_TRACE, "ras-IoCompletionCallback exited." ));
}
void
RAS_CLIENT::OnSendComplete(
IN DWORD dwStatus,
IN RAS_SEND_CONTEXT * pSendContext
)
{
H323DBG(( DEBUG_LEVEL_TRACE, "OnSendComplete entered:%p.",this ));
if( dwStatus != ERROR_SUCCESS )
{
return;
}
Lock();
m_IoRefCount--;
//if the RAS client is already shutdown, then reduce the I/O refcount and return.
if( m_dwState == RAS_CLIENT_STATE_NONE )
{
Unlock();
return;
}
//this buffer may have already been freed
if( IsInList( &m_sendPendingList, &pSendContext->ListEntry ) )
{
RemoveEntryList( &pSendContext->ListEntry );
FreeSendBuffer( pSendContext );
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "OnSendComplete exited:%p.",this ));
}
void
RAS_CLIENT::OnRecvComplete(
IN DWORD dwStatus,
IN RAS_RECV_CONTEXT * RecvContext )
{
RasMessage * RasMessage = NULL;
ASN1error_e AsnError;
H323DBG(( DEBUG_LEVEL_TRACE, "OnRecvComplete enterd:%p.",this ));
Lock();
m_IoRefCount--;
//if the RAS client is already shutdown, then reduce the I/O refcount and return.
if( m_dwState == RAS_CLIENT_STATE_NONE )
{
Unlock();
return;
}
_ASSERTE(m_recvOverlapped.IsPending);
m_recvOverlapped.IsPending = FALSE;
switch( dwStatus )
{
case ERROR_SUCCESS:
//asn decode and process the message
if( m_recvOverlapped.BytesTransferred != 0 )
{
AsnError = ASN1_Decode (
m_ASNCoderInfo.pDecInfo, // ptr to encoder info
(PVOID *) &RasMessage, // pdu data structure
RasMessage_PDU, // pdu id
ASN1DECODE_SETBUFFER, // flags
m_recvOverlapped.arBuf, // buffer to decode
m_recvOverlapped.BytesTransferred); // size of buffer to decode
//issue another read
IssueRecv();
if( ASN1_SUCCEEDED(AsnError) )
{
_ASSERTE(RasMessage);
//This function should be always called in
//a lock and it unlocks the the ras client
ProcessRasMessage( RasMessage );
return;
}
else
{
H323DBG(( DEBUG_LEVEL_ERROR, "RAS ASNDecode returned error:%d.",
AsnError ));
H323DUMPBUFFER( (BYTE*)m_recvOverlapped.arBuf,
(DWORD)m_recvOverlapped.BytesTransferred);
}
}
break;
case STATUS_PORT_UNREACHABLE:
case STATUS_CANCELLED:
IssueRecv();
break;
default:
H323DBG ((DEBUG_LEVEL_ERROR, "failed to recv data on socket"));
DumpError (dwStatus);
break;
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "OnRecvComplete exited:%p.",this ));
}
int
RAS_CLIENT::InitASNCoder(void)
{
int rc;
H323DBG((DEBUG_LEVEL_TRACE, "InitASNCoder entered: %p.", this ));
memset((PVOID)&m_ASNCoderInfo, 0, sizeof(m_ASNCoderInfo));
if( H225ASN_Module == NULL)
{
return ASN1_ERR_BADARGS;
}
rc = ASN1_CreateEncoder(
H225ASN_Module, // ptr to mdule
&(m_ASNCoderInfo.pEncInfo), // ptr to encoder info
NULL, // buffer ptr
0, // buffer size
NULL); // parent ptr
if (rc == ASN1_SUCCESS)
{
_ASSERTE(m_ASNCoderInfo.pEncInfo );
rc = ASN1_CreateDecoder(
H225ASN_Module, // ptr to mdule
&(m_ASNCoderInfo.pDecInfo), // ptr to decoder info
NULL, // buffer ptr
0, // buffer size
NULL); // parent ptr
_ASSERTE(m_ASNCoderInfo.pDecInfo );
}
if (rc != ASN1_SUCCESS)
{
TermASNCoder();
}
H323DBG((DEBUG_LEVEL_TRACE, "InitASNCoder exited: %p.", this ));
return rc;
}
//!!always called in a lock
int
RAS_CLIENT::TermASNCoder(void)
{
H323DBG(( DEBUG_LEVEL_TRACE, "RAS TermASNCoder entered:%p.",this ));
if (H225ASN_Module == NULL)
{
return ASN1_ERR_BADARGS;
}
ASN1_CloseEncoder(m_ASNCoderInfo.pEncInfo);
ASN1_CloseDecoder(m_ASNCoderInfo.pDecInfo);
memset( (PVOID)&m_ASNCoderInfo, 0, sizeof(m_ASNCoderInfo));
H323DBG(( DEBUG_LEVEL_TRACE, "RAS TermASNCoder exited:%p.",this ));
return ASN1_SUCCESS;
}
void
RAS_CLIENT::HandleRegistryChange()
{
PH323_ALIASNAMES pAliasList = NULL;
PH323_ALIASITEM pAliasItem = NULL;
PALIASCHANGE_REQUEST pAliasChangeRequest = NULL;
int iIndex;
H323DBG(( DEBUG_LEVEL_TRACE, "RAS HandleRegistryChange entered:%p.",this ));
//If line is not in listening mode then, return
if( g_pH323Line -> GetState() != H323_LINESTATE_LISTENING )
return;
Lock();
__try
{
//If registered with a GK, and GK disabled then send URQ.
if( g_RegistrySettings.fIsGKEnabled == FALSE )
{
RasStop();
}
else
{
switch( m_RegisterState )
{
//If not registered then send RRQ to the GK.
case RAS_REGISTER_STATE_IDLE:
//No need to send URQ.
//Shutdown the object.
g_RasClient.Shutdown();
RasStart();
break;
case RAS_REGISTER_STATE_REGISTERED:
case RAS_REGISTER_STATE_RRQSENT:
if( g_RegistrySettings.saGKAddr.sin_addr.s_addr !=
m_GKAddress.sin_addr.s_addr )
{
//change of GK address
//send URQ to the old GK and shutdown the RASClinet object.
RasStop();
//Initialize the GK object with new settings and send RRQ to the new GK.
RasStart();
}
else
{
//check for change in alias list.
for( iIndex=0; iIndex < m_pAliasList->wCount; iIndex++ )
{
pAliasItem = &(m_pAliasList->pItems[iIndex]);
if( pAliasItem->wType == e164_chosen )
{
if( g_RegistrySettings.fIsGKLogOnPhoneEnabled == FALSE )
{
break;
}
else if( memcmp(
(PVOID)g_RegistrySettings.wszGKLogOnPhone,
pAliasItem->pData,
(pAliasItem->wDataLength+1) * sizeof(WCHAR) ) != 0 )
{
break;
}
}
else if( pAliasItem->wType == h323_ID_chosen )
{
if( g_RegistrySettings.fIsGKLogOnAccountEnabled==FALSE )
{
break;
}
else if( memcmp(
(PVOID)g_RegistrySettings.wszGKLogOnAccount,
pAliasItem->pData,
(pAliasItem->wDataLength+1) * sizeof(WCHAR) ) != 0 )
{
break;
}
}
}
if( (iIndex < m_pAliasList->wCount ) ||
( m_pAliasList->wCount !=
(g_RegistrySettings.fIsGKLogOnPhoneEnabled +
g_RegistrySettings.fIsGKLogOnAccountEnabled
)
)
)
{
//create the new alias list.
pAliasList = new H323_ALIASNAMES;
if( pAliasList != NULL )
{
ZeroMemory( (PVOID)pAliasList, sizeof(H323_ALIASNAMES) );
if( g_RegistrySettings.fIsGKLogOnPhoneEnabled )
{
if( !AddAliasItem( pAliasList,
g_RegistrySettings.wszGKLogOnPhone,
e164_chosen ) )
{
goto cleanup;
}
}
if( g_RegistrySettings.fIsGKLogOnAccountEnabled )
{
if( !AddAliasItem( pAliasList,
g_RegistrySettings.wszGKLogOnAccount,
h323_ID_chosen ) )
{
goto cleanup;
}
}
//queue the alias change request in the list
pAliasChangeRequest = new ALIASCHANGE_REQUEST;
if( pAliasChangeRequest == NULL )
{
goto cleanup;
}
pAliasChangeRequest->rasEndpointID.length = m_RASEndpointID.length;
CopyMemory( (PVOID)pAliasChangeRequest->rasEndpointID.value,
m_RASEndpointID.value,
(pAliasChangeRequest->rasEndpointID.length+1)*sizeof(WCHAR) );
pAliasChangeRequest->wRequestSeqNum = 0;
pAliasChangeRequest->pAliasList = pAliasList;
//Send RRQ with the new alias list.
if( !SendRRQ(NOT_RESEND_SEQ_NUM, pAliasChangeRequest) )
{
goto cleanup;
}
InsertHeadList( &m_aliasChangeRequestList,
&pAliasChangeRequest->listEntry );
}
}
}
break;
default:
//Shutdown the RASClinet object. Send RRQ to new GK.
RasStop();
RasStart();
break;
}
}
}
__except(1)
{
H323DBG(( DEBUG_LEVEL_TRACE, "except in HandleRegistryChange :%p.", this ));
_ASSERTE(0);
}
Unlock();
H323DBG(( DEBUG_LEVEL_TRACE, "RAS HandleRegistryChange exited:%p.", this ));
return;
cleanup:
if( pAliasList != NULL )
{
FreeAliasNames( pAliasList );
}
if( pAliasChangeRequest != NULL )
{
delete pAliasChangeRequest;
}
Unlock();
}