832 lines
22 KiB
C++
832 lines
22 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1999 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
rascall.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
The RAS call functionality (ARQ/DRQ/ACF/DCF/IRR/ARJ/DRJ)
|
||
|
|
||
|
Author:
|
||
|
Nikhil Bobde (NikhilB)
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "globals.h"
|
||
|
#include "q931obj.h"
|
||
|
#include "line.h"
|
||
|
#include "q931pdu.h"
|
||
|
#include "ras.h"
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
BOOL
|
||
|
CH323Call::SendARQ(
|
||
|
IN long seqNumber
|
||
|
)
|
||
|
{
|
||
|
RasMessage rasMessage;
|
||
|
AdmissionRequest * ARQ;
|
||
|
EXPIRE_CONTEXT * pExpireContext;
|
||
|
PH323_ALIASNAMES pAliasList;
|
||
|
PAdmissionRequest_destinationInfo destInfo = NULL;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendARQ entered:%p.",this ));
|
||
|
|
||
|
//if not registered with the GK then return failure
|
||
|
if (!RasIsRegistered())
|
||
|
return FALSE;
|
||
|
|
||
|
pExpireContext = new EXPIRE_CONTEXT;
|
||
|
if( pExpireContext == NULL )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ZeroMemory( &rasMessage, sizeof RasMessage );
|
||
|
|
||
|
rasMessage.choice = admissionRequest_chosen;
|
||
|
ARQ = &rasMessage.u.admissionRequest;
|
||
|
|
||
|
// get sequence number
|
||
|
if( seqNumber != NOT_RESEND_SEQ_NUM )
|
||
|
{
|
||
|
ARQ -> requestSeqNum = (WORD)seqNumber;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_wARQSeqNum = RasAllocSequenceNumber();
|
||
|
ARQ -> requestSeqNum = m_wARQSeqNum;
|
||
|
}
|
||
|
|
||
|
ARQ -> callType.choice = pointToPoint_chosen;
|
||
|
|
||
|
// endpointIdentifier
|
||
|
RasGetEndpointID (&ARQ -> endpointIdentifier);
|
||
|
|
||
|
// srcInfo: pass on the registered aliases
|
||
|
pAliasList = RASGetRegisteredAliasList();
|
||
|
|
||
|
ARQ -> srcInfo = (PAdmissionRequest_srcInfo)
|
||
|
SetMsgAddressAlias( pAliasList );
|
||
|
|
||
|
if( ARQ -> srcInfo == NULL )
|
||
|
{
|
||
|
delete pExpireContext;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// destInfo
|
||
|
if( (m_dwOrigin==LINECALLORIGIN_OUTBOUND) && m_pCalleeAliasNames &&
|
||
|
(m_pCalleeAliasNames -> wCount) )
|
||
|
{
|
||
|
ARQ -> destinationInfo = (PAdmissionRequest_destinationInfo)
|
||
|
SetMsgAddressAlias( m_pCalleeAliasNames );
|
||
|
|
||
|
if( ARQ -> destinationInfo != NULL )
|
||
|
{
|
||
|
ARQ -> bit_mask |= AdmissionRequest_destinationInfo_present;
|
||
|
}
|
||
|
}
|
||
|
else if( (m_dwOrigin==LINECALLORIGIN_INBOUND) && m_pCallerAliasNames
|
||
|
&& (m_pCallerAliasNames -> wCount) )
|
||
|
{
|
||
|
ARQ -> destinationInfo = (PAdmissionRequest_destinationInfo)
|
||
|
SetMsgAddressAlias( m_pCallerAliasNames );
|
||
|
|
||
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
||
|
|
||
|
if( ARQ -> destinationInfo )
|
||
|
{
|
||
|
ARQ -> bit_mask |= AdmissionRequest_destinationInfo_present;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for( destInfo = ARQ -> destinationInfo; destInfo; destInfo=destInfo->next )
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "the alias:%s.", destInfo->value.u.e164 ));
|
||
|
}
|
||
|
|
||
|
ARQ -> bandWidth = 0;
|
||
|
ARQ -> callReferenceValue = m_wCallReference;
|
||
|
|
||
|
// no destExtraCallInfo
|
||
|
// no srcCallSignalAddress
|
||
|
// no nonStandardData
|
||
|
// no callServices
|
||
|
|
||
|
CopyConferenceID (&ARQ -> conferenceID, &m_ConferenceID);
|
||
|
|
||
|
ARQ -> activeMC = FALSE;
|
||
|
ARQ -> answerCall = ( m_dwOrigin == LINECALLORIGIN_INBOUND );
|
||
|
ARQ -> canMapAlias = TRUE;
|
||
|
|
||
|
CopyMemory( (PVOID)&ARQ -> callIdentifier.guid.value,
|
||
|
(PVOID)&m_callIdentifier, sizeof(GUID) );
|
||
|
|
||
|
ARQ -> callIdentifier.guid.length = sizeof (GUID);
|
||
|
ARQ -> bit_mask |= AdmissionRequest_callIdentifier_present;
|
||
|
|
||
|
// no srcAlternatives
|
||
|
// no destAlternatives
|
||
|
// no gatekeeperIdentifier
|
||
|
// no tokens
|
||
|
// no cryptoTokens
|
||
|
// no integrityCheckValue
|
||
|
// no transportQOS
|
||
|
|
||
|
ARQ -> willSupplyUUIEs = FALSE;
|
||
|
|
||
|
if( m_hARQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hARQTimer, NULL );
|
||
|
m_hARQTimer = NULL;
|
||
|
}
|
||
|
|
||
|
pExpireContext -> DriverCallHandle = m_hdCall;
|
||
|
pExpireContext -> seqNumber = ARQ -> requestSeqNum;
|
||
|
|
||
|
if( !CreateTimerQueueTimer(
|
||
|
&m_hARQTimer,
|
||
|
H323TimerQueue,
|
||
|
CH323Call::ARQExpiredCallback,
|
||
|
(PVOID)pExpireContext,
|
||
|
ARQ_EXPIRE_TIME, 0,
|
||
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE ))
|
||
|
{
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
|
||
|
if( RasEncodeSendMessage (&rasMessage) != S_OK )
|
||
|
{
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
if( ARQ -> bit_mask & AdmissionRequest_destinationInfo_present )
|
||
|
{
|
||
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
||
|
ARQ -> destinationInfo );
|
||
|
}
|
||
|
|
||
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)ARQ -> srcInfo );
|
||
|
m_dwRASCallState = RASCALL_STATE_ARQSENT;
|
||
|
m_dwARQRetryCount++;
|
||
|
|
||
|
_ASSERTE( m_pARQExpireContext == NULL );
|
||
|
m_pARQExpireContext = pExpireContext;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendARQ exited:%p.",this ));
|
||
|
return TRUE;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
if( m_hARQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue,
|
||
|
m_hARQTimer, NULL );
|
||
|
m_hARQTimer = NULL;
|
||
|
m_dwARQRetryCount = 0;
|
||
|
}
|
||
|
if( ARQ -> bit_mask & AdmissionRequest_destinationInfo_present )
|
||
|
{
|
||
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
||
|
ARQ -> destinationInfo );
|
||
|
}
|
||
|
|
||
|
if( pExpireContext != NULL )
|
||
|
{
|
||
|
delete pExpireContext;
|
||
|
}
|
||
|
|
||
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)ARQ -> srcInfo );
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
BOOL
|
||
|
CH323Call::SendDRQ(
|
||
|
IN USHORT usDisengageReason,
|
||
|
IN long seqNumber,
|
||
|
IN BOOL fResendOnExpire
|
||
|
)
|
||
|
{
|
||
|
RasMessage rasMessage;
|
||
|
DisengageRequest * DRQ;
|
||
|
EXPIRE_CONTEXT * pExpireContext;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendDRQ entered:%p.",this ));
|
||
|
|
||
|
ZeroMemory( &rasMessage, sizeof(rasMessage) );
|
||
|
rasMessage.choice = disengageRequest_chosen;
|
||
|
DRQ = &rasMessage.u.disengageRequest;
|
||
|
|
||
|
//if not registered with the GK then return failure
|
||
|
if (!RasIsRegistered())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if( fResendOnExpire == TRUE )
|
||
|
{
|
||
|
pExpireContext = new EXPIRE_CONTEXT;
|
||
|
if( pExpireContext == NULL )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// get sequence number
|
||
|
if( seqNumber != NOT_RESEND_SEQ_NUM )
|
||
|
{
|
||
|
DRQ -> requestSeqNum = (WORD)seqNumber;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_wDRQSeqNum = RasAllocSequenceNumber();
|
||
|
DRQ -> requestSeqNum = m_wDRQSeqNum;
|
||
|
}
|
||
|
|
||
|
DRQ -> callReferenceValue = m_wCallReference;
|
||
|
DRQ -> disengageReason.choice = usDisengageReason;
|
||
|
|
||
|
// endpoint identifier
|
||
|
RasGetEndpointID (&DRQ -> endpointIdentifier);
|
||
|
|
||
|
// conferenceID
|
||
|
CopyConferenceID (&DRQ -> conferenceID, &m_ConferenceID);
|
||
|
|
||
|
// callIdentifier
|
||
|
CopyConferenceID (&DRQ -> callIdentifier.guid, &m_callIdentifier);
|
||
|
DRQ -> bit_mask |= DisengageRequest_callIdentifier_present;
|
||
|
|
||
|
if( RasEncodeSendMessage( &rasMessage ) != S_OK )
|
||
|
{
|
||
|
delete pExpireContext;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if( m_hDRQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hDRQTimer, NULL );
|
||
|
m_hDRQTimer = NULL;
|
||
|
}
|
||
|
|
||
|
if( fResendOnExpire == TRUE )
|
||
|
{
|
||
|
pExpireContext -> DriverCallHandle = m_hdCall;
|
||
|
pExpireContext -> seqNumber = DRQ -> requestSeqNum;
|
||
|
|
||
|
if( !CreateTimerQueueTimer(
|
||
|
&m_hDRQTimer,
|
||
|
H323TimerQueue,
|
||
|
CH323Call::DRQExpiredCallback,
|
||
|
(PVOID)pExpireContext,
|
||
|
ARQ_EXPIRE_TIME, 0,
|
||
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE ))
|
||
|
{
|
||
|
delete pExpireContext;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
_ASSERTE( m_pDRQExpireContext == NULL );
|
||
|
m_pDRQExpireContext = pExpireContext;
|
||
|
}
|
||
|
|
||
|
m_dwRASCallState = RASCALL_STATE_DRQSENT;
|
||
|
m_dwDRQRetryCount++;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendDRQ exited:%p.",this ));
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void
|
||
|
CH323Call::OnDisengageRequest(
|
||
|
IN DisengageRequest * DRQ
|
||
|
)
|
||
|
{
|
||
|
GUID RequestConferenceID;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnDisengageRequest entered:%p.",this ));
|
||
|
|
||
|
if( (m_dwRASCallState == RASCALL_STATE_UNREGISTERED) ||
|
||
|
(m_dwRASCallState == RASCALL_STATE_ARJRECVD) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CopyConferenceID (&RequestConferenceID, &DRQ -> conferenceID);
|
||
|
|
||
|
if (!IsEqualGUID (m_ConferenceID, RequestConferenceID))
|
||
|
{
|
||
|
H323DBG ((DEBUG_LEVEL_ERROR, "DisengageRequest conference ID does not match this call, ignoring..."));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (SendDCF (DRQ -> requestSeqNum))
|
||
|
{
|
||
|
m_dwRASCallState = RASCALL_STATE_UNREGISTERED;
|
||
|
CloseCall( 0 );
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnDisengageRequest exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called in a lock
|
||
|
BOOL
|
||
|
CH323Call::SendDCF(
|
||
|
IN WORD seqNumber
|
||
|
)
|
||
|
{
|
||
|
RasMessage rasMessage;
|
||
|
DisengageConfirm * DCF;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendDCF entered:%p.",this ));
|
||
|
|
||
|
ZeroMemory( &rasMessage, sizeof(rasMessage) );
|
||
|
rasMessage.choice = disengageConfirm_chosen;
|
||
|
DCF = &rasMessage.u.disengageConfirm;
|
||
|
|
||
|
//if not registered with the GK then return failure
|
||
|
if (!RasIsRegistered())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DCF -> requestSeqNum = seqNumber;
|
||
|
if (RasEncodeSendMessage (&rasMessage) != S_OK)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendDCF exited:%p.",this ));
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void
|
||
|
CH323Call::OnDisengageReject(
|
||
|
IN DisengageReject* DRJ
|
||
|
)
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnDisengageReject entered:%p.",this ));
|
||
|
|
||
|
if( DRJ -> requestSeqNum != m_wDRQSeqNum )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if( m_dwRASCallState != RASCALL_STATE_DRQSENT )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( DRJ->rejectReason.choice == requestToDropOther_chosen )
|
||
|
{
|
||
|
//
|
||
|
H323DBG(( DEBUG_LEVEL_ERROR, "!!something is wrong in the way DRQ is encoded.",this ));
|
||
|
}
|
||
|
else //if( DRJ->rejectReason.choice == DisengageRejectReason_notRegistered_chosen )
|
||
|
{
|
||
|
//the call has been unregistered but is still around, so dsrop it
|
||
|
m_dwRASCallState = RASCALL_STATE_UNREGISTERED;
|
||
|
//CloseCall( 0 );
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnDisengageReject exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
CH323Call::OnRequestInProgress(
|
||
|
IN RequestInProgress* RIP
|
||
|
)
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnRequestInProgress entered:%p.",this ));
|
||
|
EXPIRE_CONTEXT * pExpireContext;
|
||
|
|
||
|
if( RIP -> requestSeqNum != m_wARQSeqNum )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( m_dwRASCallState != RASCALL_STATE_ARQSENT )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//if delay is more than 30 seconds ignore it
|
||
|
if( (RIP->delay > 0) && (RIP->delay > 30000) )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pExpireContext = new EXPIRE_CONTEXT;
|
||
|
if( pExpireContext == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//restart the timer
|
||
|
if( m_hARQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hARQTimer, NULL );
|
||
|
m_hARQTimer = NULL;
|
||
|
}
|
||
|
|
||
|
pExpireContext -> DriverCallHandle = m_hdCall;
|
||
|
pExpireContext -> seqNumber = m_wARQSeqNum;
|
||
|
|
||
|
if( !CreateTimerQueueTimer(
|
||
|
&m_hARQTimer,
|
||
|
H323TimerQueue,
|
||
|
CH323Call::ARQExpiredCallback,
|
||
|
(PVOID)pExpireContext,
|
||
|
(DWORD)RIP->delay, 0,
|
||
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE ))
|
||
|
{
|
||
|
//close the call
|
||
|
CloseCall( 0 );
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnRequestInProgress exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void
|
||
|
CH323Call::OnDisengageConfirm(
|
||
|
IN DisengageConfirm* DCF
|
||
|
)
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnDisengageConfirm entered:%p.",this ));
|
||
|
|
||
|
if( DCF -> requestSeqNum != m_wDRQSeqNum )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( m_dwRASCallState == RASCALL_STATE_DRQSENT )
|
||
|
{
|
||
|
if( m_hDRQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hDRQTimer,
|
||
|
NULL );
|
||
|
m_hDRQTimer = NULL;
|
||
|
}
|
||
|
|
||
|
//nikhil:if this is a replacement call/diverted call then this may lead
|
||
|
//to inconsistent behaviour
|
||
|
m_dwRASCallState = RASCALL_STATE_UNREGISTERED;
|
||
|
//CloseCall( 0 );
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnDisengageConfirm exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void
|
||
|
CH323Call::OnAdmissionConfirm(
|
||
|
IN AdmissionConfirm * ACF
|
||
|
)
|
||
|
{
|
||
|
PH323_CALL pCall = NULL;
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnAdmissionConfirm entered:%p.",this ));
|
||
|
|
||
|
_ASSERTE( m_dwRASCallState != RASCALL_STATE_IDLE );
|
||
|
|
||
|
if( ACF -> requestSeqNum != m_wARQSeqNum )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( m_hARQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hARQTimer,
|
||
|
NULL );
|
||
|
m_hARQTimer = NULL;
|
||
|
m_dwARQRetryCount = 0;
|
||
|
}
|
||
|
|
||
|
if( m_dwRASCallState == RASCALL_STATE_ARQSENT )
|
||
|
{
|
||
|
m_dwRASCallState = RASCALL_STATE_REGISTERED;
|
||
|
|
||
|
if( m_dwOrigin == LINECALLORIGIN_OUTBOUND )
|
||
|
{
|
||
|
if( (ACF ->destCallSignalAddress.choice != ipAddress_chosen) ||
|
||
|
(ACF->destCallSignalAddress.u.ipAddress.ip.length != 4) )
|
||
|
{
|
||
|
DropCall( LINEDISCONNECTMODE_BADADDRESS );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// save converted address
|
||
|
m_CalleeAddr.nAddrType = H323_IP_BINARY;
|
||
|
m_CalleeAddr.Addr.IP_Binary.dwAddr =
|
||
|
ntohl(*(DWORD*)(ACF->destCallSignalAddress.u.ipAddress.ip.value) );
|
||
|
m_CalleeAddr.Addr.IP_Binary.wPort =
|
||
|
ACF->destCallSignalAddress.u.ipAddress.port;
|
||
|
m_CalleeAddr.bMulticast =
|
||
|
IN_MULTICAST(m_CalleeAddr.Addr.IP_Binary.dwAddr);
|
||
|
|
||
|
//Replaces the first alias in the callee list (the dialableAddress
|
||
|
//passed in TSPI_lineMakecall ). The GK looks at the first alias
|
||
|
//only. Its assumed that only the first alias is mapped by the GK.
|
||
|
if( (ACF -> bit_mask & AdmissionConfirm_destinationInfo_present) &&
|
||
|
ACF->destinationInfo )
|
||
|
{
|
||
|
MapAliasItem( m_pCalleeAliasNames,
|
||
|
&(ACF->destinationInfo->value) );
|
||
|
}
|
||
|
|
||
|
if( !PlaceCall() )
|
||
|
{
|
||
|
DropCall( LINEDISCONNECTMODE_UNREACHABLE );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( (m_dwCallType & CALLTYPE_TRANSFEREDDEST) && m_hdRelatedCall )
|
||
|
{
|
||
|
MSPMessageData* pMSPMessageData = new MSPMessageData;
|
||
|
if( pMSPMessageData == NULL )
|
||
|
{
|
||
|
CloseCall( 0 );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
pMSPMessageData->hdCall = m_hdRelatedCall;
|
||
|
pMSPMessageData->messageType = SP_MSG_PrepareToAnswer;
|
||
|
pMSPMessageData->pbEncodedBuf = m_prepareToAnswerMsgData.pbBuffer;
|
||
|
pMSPMessageData->wLength = (WORD)m_prepareToAnswerMsgData.dwLength;
|
||
|
pMSPMessageData->hReplacementCall = m_hdCall;
|
||
|
m_prepareToAnswerMsgData.pbBuffer = NULL;
|
||
|
|
||
|
QueueUserWorkItem( SendMSPMessageOnRelatedCall,
|
||
|
pMSPMessageData, WT_EXECUTEDEFAULT );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
// signal incoming call
|
||
|
_ASSERTE(!m_htCall);
|
||
|
|
||
|
PostLineEvent (
|
||
|
LINE_NEWCALL,
|
||
|
(DWORD_PTR)m_hdCall,
|
||
|
(DWORD_PTR)&m_htCall, 0);
|
||
|
|
||
|
_ASSERTE( m_htCall );
|
||
|
if( m_htCall == NULL )
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_ERROR, "tapi call handle NULL!!" ));
|
||
|
CloseCall( 0 );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( IsListEmpty(&m_IncomingU2U) == FALSE )
|
||
|
{
|
||
|
// signal incoming
|
||
|
PostLineEvent (
|
||
|
LINE_CALLINFO,
|
||
|
(DWORD_PTR)LINECALLINFOSTATE_USERUSERINFO,
|
||
|
0, 0);
|
||
|
}
|
||
|
|
||
|
ChangeCallState( LINECALLSTATE_OFFERING, 0 );
|
||
|
|
||
|
// send the new call message to the unspecified MSP
|
||
|
SendMSPMessage( SP_MSG_PrepareToAnswer,
|
||
|
m_prepareToAnswerMsgData.pbBuffer,
|
||
|
m_prepareToAnswerMsgData.dwLength, NULL );
|
||
|
}
|
||
|
|
||
|
if( m_prepareToAnswerMsgData.pbBuffer )
|
||
|
delete m_prepareToAnswerMsgData.pbBuffer;
|
||
|
ZeroMemory( (PVOID)&m_prepareToAnswerMsgData, sizeof(BUFFERDESCR) );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
else if( m_dwRASCallState == RASCALL_STATE_ARQEXPIRED )
|
||
|
{
|
||
|
SendDRQ( forcedDrop_chosen, NOT_RESEND_SEQ_NUM, TRUE );
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnAdmissionConfirm exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void
|
||
|
CH323Call::OnAdmissionReject(
|
||
|
IN AdmissionReject * ARJ
|
||
|
)
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnAdmissionReject entered:%p.",this ));
|
||
|
|
||
|
if( ARJ -> requestSeqNum != m_wARQSeqNum )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_dwRASCallState = RASCALL_STATE_ARJRECVD;
|
||
|
|
||
|
//If a forward consult call then enable the forwarding anyway.
|
||
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
||
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
||
|
{
|
||
|
//Success of forwarding
|
||
|
EnableCallForwarding();
|
||
|
}
|
||
|
|
||
|
//drop the call. shutdown the call and rlease the call.
|
||
|
CloseCall( LINEDISCONNECTMODE_BADADDRESS );
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnAdmissionReject exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT
|
||
|
CH323Call::GetCallInfo (
|
||
|
OUT GUID * ReturnCallID,
|
||
|
OUT GUID * ReturnConferenceID )
|
||
|
{
|
||
|
|
||
|
//verify call state
|
||
|
if( m_dwCallState == LINECALLSTATE_DISCONNECTED )
|
||
|
{
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
|
||
|
*ReturnCallID = m_callIdentifier;
|
||
|
*ReturnConferenceID = m_ConferenceID;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
NTAPI CH323Call::DRQExpiredCallback(
|
||
|
IN PVOID ContextParameter, // pExpireContext
|
||
|
IN BOOLEAN TimerFired // not used
|
||
|
)
|
||
|
{
|
||
|
EXPIRE_CONTEXT * pExpireContext;
|
||
|
HDRVCALL DriverCall;
|
||
|
PH323_CALL pCall;
|
||
|
|
||
|
_ASSERTE(ContextParameter);
|
||
|
pExpireContext = (EXPIRE_CONTEXT *) ContextParameter;
|
||
|
_ASSERTE( pExpireContext == m_pDRQExpireContext );
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
DriverCall = (HDRVCALL) pExpireContext -> DriverCallHandle;
|
||
|
|
||
|
pCall = g_pH323Line -> FindH323CallAndLock (DriverCall);
|
||
|
if (pCall)
|
||
|
{
|
||
|
pCall -> DRQExpired (pExpireContext -> seqNumber);
|
||
|
|
||
|
delete pExpireContext;
|
||
|
pCall -> Unlock();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
H323DBG ((DEBUG_LEVEL_ERROR, "warning: DRQExpiredCallback failed to locate call object"));
|
||
|
}
|
||
|
}
|
||
|
__except( 1 )
|
||
|
{
|
||
|
// The call has already been deleted and hence the pExpireContext
|
||
|
// buffer is also deleted.
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
NTAPI CH323Call::ARQExpiredCallback(
|
||
|
IN PVOID ContextParameter, // pExpireContext
|
||
|
IN BOOLEAN TimerFired) // not used
|
||
|
{
|
||
|
EXPIRE_CONTEXT * pExpireContext;
|
||
|
HDRVCALL DriverCall;
|
||
|
PH323_CALL pCall;
|
||
|
|
||
|
_ASSERTE(ContextParameter);
|
||
|
pExpireContext = (EXPIRE_CONTEXT *) ContextParameter;
|
||
|
_ASSERTE( pExpireContext == m_pARQExpireContext );
|
||
|
|
||
|
|
||
|
__try
|
||
|
{
|
||
|
DriverCall = (HDRVCALL) pExpireContext -> DriverCallHandle;
|
||
|
|
||
|
pCall = g_pH323Line -> FindH323CallAndLock (DriverCall);
|
||
|
if (pCall)
|
||
|
{
|
||
|
pCall -> ARQExpired (pExpireContext -> seqNumber);
|
||
|
|
||
|
delete pExpireContext;
|
||
|
pCall -> Unlock();
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
H323DBG ((DEBUG_LEVEL_ERROR, "warning: ARQExpiredCallback failed to locate call object"));
|
||
|
}
|
||
|
}
|
||
|
__except( 1 )
|
||
|
{
|
||
|
// The call has already been deleted and hence the pExpireContext
|
||
|
// buffer is also deleted.
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void CH323Call::ARQExpired (
|
||
|
IN WORD seqNumber)
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "ARQExpired entered:%p.",this ));
|
||
|
|
||
|
m_pARQExpireContext = NULL;
|
||
|
|
||
|
if( m_hARQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hARQTimer, NULL );
|
||
|
m_hARQTimer = NULL;
|
||
|
}
|
||
|
|
||
|
if( m_dwRASCallState == RASCALL_STATE_ARQSENT )
|
||
|
{
|
||
|
if( m_dwARQRetryCount < ARQ_RETRY_MAX )
|
||
|
{
|
||
|
if( !SendARQ( (long)seqNumber ) )
|
||
|
{
|
||
|
// drop call using disconnect mode
|
||
|
DropCall(0);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_dwRASCallState = RASCALL_STATE_ARQEXPIRED;
|
||
|
//Not able to register, shutdown the RAS client object
|
||
|
CloseCall( 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "ARQExpired exited:%p.",this ));
|
||
|
}
|
||
|
|
||
|
|
||
|
//!!always called from a lock
|
||
|
void
|
||
|
CH323Call::DRQExpired(
|
||
|
IN WORD seqNumber
|
||
|
)
|
||
|
{
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "DRQExpired entered:%p.", this ));
|
||
|
m_pDRQExpireContext = NULL;
|
||
|
|
||
|
if( m_hDRQTimer != NULL )
|
||
|
{
|
||
|
DeleteTimerQueueTimer( H323TimerQueue, m_hDRQTimer, NULL );
|
||
|
m_hDRQTimer = NULL;
|
||
|
}
|
||
|
|
||
|
if( m_dwRASCallState == RASCALL_STATE_DRQSENT )
|
||
|
{
|
||
|
if( m_dwDRQRetryCount < DRQ_RETRY_MAX )
|
||
|
{
|
||
|
if( !SendDRQ( forcedDrop_chosen, (long)seqNumber, TRUE ) )
|
||
|
{
|
||
|
// drop call using disconnect mode
|
||
|
DropCall(0);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_dwRASCallState = RASCALL_STATE_DRQEXPIRED;
|
||
|
//Not able to register, shutdown the RAS client object
|
||
|
CloseCall( 0 );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
H323DBG(( DEBUG_LEVEL_TRACE, "DRQExpired exited:%p.",this ));
|
||
|
}
|