11829 lines
311 KiB
C++
11829 lines
311 KiB
C++
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
call.cpp
|
|
|
|
Abstract:
|
|
|
|
TAPI Service Provider functions related to manipulating calls.
|
|
|
|
TSPI_lineAnswer
|
|
TSPI_lineCloseCall
|
|
TSPI_lineDrop
|
|
TSPI_lineGetCallAddressID
|
|
TSPI_lineGetCallInfo
|
|
TSPI_lineGetCallStatus
|
|
TSPI_lineMakeCall
|
|
TSPI_lineMonitorDigits
|
|
TSPI_lineSendUserUserInfo
|
|
TSPI_lineReleaseUserUserInfo
|
|
|
|
|
|
Author:
|
|
Nikhil Bobde (NikhilB)
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
//
|
|
// Include files
|
|
//
|
|
|
|
#include "globals.h"
|
|
#include "line.h"
|
|
#include "q931pdu.h"
|
|
#include "q931obj.h"
|
|
#include "ras.h"
|
|
#include "config.h"
|
|
|
|
#define SETUP_SENT_TIMEOUT 8000
|
|
#define H450_ENCODED_ARG_LEN 0x4000
|
|
#define MAX_DIVERSION_COUNTER 14
|
|
|
|
static LONG g_H323CallID;
|
|
static LONG g_lNumberOfcalls;
|
|
LONG g_lCallReference;
|
|
|
|
//
|
|
// Public functions
|
|
//
|
|
|
|
|
|
//
|
|
//The function that handles a network event(CONNECT|CLOSE) on any of the
|
|
//Q931 calls. This function needs to find out the exact event
|
|
// that took place and the socket on which it took place
|
|
//
|
|
|
|
void NTAPI Q931TransportEventHandler (
|
|
IN PVOID Parameter,
|
|
IN BOOLEAN TimerFired)
|
|
{
|
|
PH323_CALL pCall;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "Q931 transport event recvd." ));
|
|
|
|
pCall = g_pH323Line -> FindH323CallAndLock ((HDRVCALL) Parameter);
|
|
|
|
if( pCall != NULL )
|
|
{
|
|
pCall -> HandleTransportEvent();
|
|
pCall -> Unlock();
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// returns S_OK if socket was consumed
|
|
// returns E_FAIL if socket should be destroyed by caller
|
|
//
|
|
|
|
static HRESULT CallCreateIncomingCall (
|
|
IN SOCKET Socket,
|
|
IN SOCKADDR_IN * LocalAddress,
|
|
IN SOCKADDR_IN * RemoteAddress)
|
|
{
|
|
PH323_CALL pCall;
|
|
HANDLE SelectEvent;
|
|
HANDLE SelectWaitHandle;
|
|
BOOL fSuccess = TRUE;
|
|
BOOL DeleteCall = FALSE;
|
|
TCHAR ptstrEventName[100];
|
|
BOOL retVal;
|
|
|
|
pCall = new CH323Call;
|
|
if( pCall == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"failed to allocate memory for CH323Call." ));
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
_stprintf( ptstrEventName, _T("%s-%p"),
|
|
_T( "H323TSP_Incoming_TransportHandlerEvent" ), pCall );
|
|
|
|
// create the wait event
|
|
SelectEvent = H323CreateEvent (NULL, FALSE,
|
|
FALSE, ptstrEventName );
|
|
|
|
if( SelectEvent == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "CALL: failed to create select event." ));
|
|
delete pCall;
|
|
return GetLastResult();
|
|
}
|
|
|
|
retVal = pCall -> Initialize( NULL,
|
|
LINECALLORIGIN_INBOUND,
|
|
CALLTYPE_NORMAL );
|
|
|
|
if( retVal == FALSE )
|
|
{
|
|
H323DBG ((DEBUG_LEVEL_ERROR, "failed to initialize CH323Call."));
|
|
CloseHandle (SelectEvent);
|
|
delete pCall;
|
|
return E_FAIL;
|
|
}
|
|
|
|
//add it to the call context array
|
|
if (!pCall -> InitializeQ931 (Socket))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"Failed to initialize incoming call Q.931 state." ));
|
|
|
|
DeleteCall = FALSE;
|
|
pCall -> Shutdown (&DeleteCall);
|
|
delete pCall;
|
|
|
|
if (SelectEvent)
|
|
{
|
|
CloseHandle (SelectEvent);
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
pCall -> SetQ931CallState (Q931_CALL_CONNECTED);
|
|
|
|
pCall -> Lock();
|
|
|
|
if (!RegisterWaitForSingleObject(
|
|
&SelectWaitHandle, // pointer to the returned handle.
|
|
SelectEvent, // the event handle to wait for.
|
|
Q931TransportEventHandler, // the callback function.
|
|
(PVOID)pCall -> GetCallHandle(),// the context for the callback.
|
|
INFINITE, // wait forever.
|
|
WT_EXECUTEDEFAULT)) // use the wait thread to call the callback.
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
_ASSERTE( SelectWaitHandle );
|
|
if( SelectWaitHandle == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//store this in the call context
|
|
pCall -> SetNewCallInfo (SelectWaitHandle, SelectEvent,
|
|
Q931_CALL_CONNECTED);
|
|
SelectEvent = NULL;
|
|
|
|
pCall -> InitializeRecvBuf();
|
|
|
|
//post a buffer to winsock to accept messages from the peer
|
|
if(!pCall -> PostReadBuffer())
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "failed to post read buffer on call." ));
|
|
goto cleanup;
|
|
}
|
|
|
|
pCall -> Unlock();
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "successfully created incoming Q.931 call." ));
|
|
|
|
//success
|
|
return S_OK;
|
|
|
|
cleanup:
|
|
|
|
if (pCall)
|
|
{
|
|
pCall -> Unlock();
|
|
pCall -> Shutdown (&DeleteCall);
|
|
delete pCall;
|
|
}
|
|
|
|
if (SelectEvent)
|
|
{
|
|
CloseHandle (SelectEvent);
|
|
}
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
|
|
void CallProcessIncomingCall (
|
|
IN SOCKET Socket,
|
|
IN SOCKADDR_IN * LocalAddress,
|
|
IN SOCKADDR_IN * RemoteAddress)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = CallCreateIncomingCall (Socket, LocalAddress, RemoteAddress);
|
|
|
|
if (hr != S_OK)
|
|
{
|
|
closesocket (Socket);
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
|
|
DWORD
|
|
ProcessTAPICallRequest(
|
|
IN PVOID ContextParameter
|
|
)
|
|
{
|
|
__try
|
|
{
|
|
return ProcessTAPICallRequestFre( ContextParameter );
|
|
}
|
|
__except( 1 )
|
|
{
|
|
TAPI_CALLREQUEST_DATA* pRequestData =
|
|
(TAPI_CALLREQUEST_DATA*)ContextParameter;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "TSPI %s event threw exception: %p, %p.",
|
|
EventIDToString(pRequestData -> EventID),
|
|
pRequestData -> pCall,
|
|
pRequestData -> pCallforwardParams ));
|
|
|
|
_ASSERTE( FALSE );
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
DWORD
|
|
ProcessTAPICallRequestFre(
|
|
IN PVOID ContextParameter)
|
|
{
|
|
_ASSERTE( ContextParameter );
|
|
|
|
TAPI_CALLREQUEST_DATA* pCallRequestData = (TAPI_CALLREQUEST_DATA*)ContextParameter;
|
|
PH323_CALL pCall = pCallRequestData->pCall;
|
|
BOOL fDelete = FALSE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "TSPI %s event recvd.",
|
|
EventIDToString(pCallRequestData -> EventID) ));
|
|
|
|
pCall -> Lock();
|
|
|
|
if( pCallRequestData -> EventID == TSPI_DELETE_CALL )
|
|
{
|
|
pCall -> Unlock();
|
|
|
|
delete pCallRequestData;
|
|
delete pCall;
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
if( pCall -> IsCallShutdown() == FALSE )
|
|
{
|
|
switch( pCallRequestData -> EventID )
|
|
{
|
|
case TSPI_MAKE_CALL:
|
|
|
|
pCall -> MakeCall();
|
|
break;
|
|
|
|
case TSPI_ANSWER_CALL:
|
|
|
|
pCall -> AcceptCall();
|
|
break;
|
|
|
|
case TSPI_DROP_CALL:
|
|
|
|
pCall -> DropUserInitiated( 0 );
|
|
//pCall -> DropCall(0);
|
|
break;
|
|
|
|
case TSPI_RELEASE_U2U:
|
|
|
|
pCall -> ReleaseU2U();
|
|
break;
|
|
|
|
case TSPI_CALL_HOLD:
|
|
|
|
pCall -> Hold();
|
|
break;
|
|
|
|
case TSPI_CALL_UNHOLD:
|
|
|
|
pCall -> UnHold();
|
|
break;
|
|
|
|
case TSPI_CALL_DIVERT:
|
|
|
|
pCall -> CallDivertOnNoAnswer();
|
|
break;
|
|
|
|
case TSPI_LINEFORWARD_NOSPECIFIC:
|
|
case TSPI_LINEFORWARD_SPECIFIC:
|
|
|
|
pCall -> Forward( pCallRequestData -> EventID,
|
|
pCallRequestData -> pCallforwardParams );
|
|
|
|
break;
|
|
|
|
case TSPI_SEND_U2U:
|
|
|
|
pCall -> SendU2U( pCallRequestData -> pBuf->pbBuffer,
|
|
pCallRequestData->pBuf->dwLength );
|
|
|
|
delete pCallRequestData -> pBuf;
|
|
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE(0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
pCall -> DecrementIoRefCount( &fDelete );
|
|
pCall -> Unlock();
|
|
delete pCallRequestData;
|
|
|
|
if( fDelete == TRUE )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", pCall ));
|
|
delete pCall;
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// CH323Call Methods
|
|
//
|
|
|
|
|
|
CH323Call::CH323Call(void)
|
|
{
|
|
ZeroMemory( (PVOID)this, sizeof(CH323Call) );
|
|
|
|
/*m_dwFlags = 0;
|
|
m_pwszDisplay = NULL;
|
|
m_fMonitoringDigits = FALSE;
|
|
m_hdCall = NULL;
|
|
m_htCall = NULL;
|
|
m_dwCallState = NULL;
|
|
m_dwOrigin = NULL;
|
|
m_dwAddressType = NULL;
|
|
m_dwIncomingModes = NULL;
|
|
m_dwOutgoingModes = NULL;
|
|
m_dwRequestedModes = NULL; // requested media modes
|
|
m_hdMSPLine = NULL;
|
|
m_htMSPLine = NULL;
|
|
//m_fGateKeeperPresent = FALSE;
|
|
m_fReadyToAnswer = FALSE;
|
|
m_fCallAccepted = FALSE;
|
|
|
|
// reset addresses
|
|
memset((PVOID)&m_CalleeAddr,0,sizeof(H323_ADDR));
|
|
memset((PVOID)&m_CallerAddr,0,sizeof(H323_ADDR));
|
|
|
|
// reset addresses
|
|
m_pCalleeAliasNames = NULL;
|
|
m_pCallerAliasNames = NULL;
|
|
|
|
//reset non standard data
|
|
memset( (PVOID)&m_NonStandardData, 0, sizeof(H323NonStandardData ) );
|
|
|
|
//reset the conference ID
|
|
ZeroMemory (&m_ConferenceID, sizeof m_ConferenceID);
|
|
|
|
pFastStart = NULL;
|
|
|
|
//redet the peer information
|
|
memset( (PVOID)&m_peerH245Addr, 0, sizeof(H323_ADDR) );
|
|
memset( (PVOID)&m_selfH245Addr, 0, sizeof(H323_ADDR) );
|
|
memset( (PVOID)&m_peerNonStandardData, 0, sizeof(H323NonStandardData ) );
|
|
memset( (PVOID)&m_peerVendorInfo, 0, sizeof(H323_VENDORINFO) );
|
|
memset( (PVOID)&m_peerEndPointType, 0, sizeof(H323_ENDPOINTTYPE) );
|
|
m_pPeerFastStart = NULL;
|
|
m_pPeerExtraAliasNames = NULL;
|
|
m_pPeerDisplay = NULL;
|
|
|
|
m_hCallEstablishmentTimer = NULL;
|
|
m_hCallDivertOnNATimer = NULL;
|
|
|
|
//Q931call data
|
|
m_hTransport = NULL;
|
|
|
|
m_hTransportWait = NULL;
|
|
|
|
pRecvBuf = NULL;
|
|
m_hSetupSentTimer = NULL;
|
|
m_dwStateMachine = 0;
|
|
m_dwQ931Flags = 0;
|
|
//
|
|
|
|
fActiveMC = FALSE;
|
|
memset( (PVOID)&m_ASNCoderInfo, 0, sizeof(m_ASNCoderInfo));
|
|
m_wCallReference = NULL;
|
|
m_wQ931CallRef = NULL;
|
|
m_IoRefCount = 0;
|
|
|
|
//RAS call data
|
|
wARQSeqNum = 0;
|
|
m_wDRQSeqNum = 0;
|
|
|
|
m_pARQExpireContext = NULL;
|
|
m_pDRQExpireContext= NULL;
|
|
m_hARQTimer = NULL;
|
|
m_hDRQTimer = NULL;
|
|
m_dwDRQRetryCount = 0;
|
|
m_dwARQRetryCount = 0;
|
|
m_fCallInTrnasition = FALSE
|
|
m_dwAppSpecific = 0;*/
|
|
|
|
|
|
m_dwFastStart = FAST_START_UNDECIDED;
|
|
m_callSocket = INVALID_SOCKET;
|
|
m_bStartOfPDU = TRUE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"Initialize:m_IoRefCount:%d:%p.", m_IoRefCount, this ));
|
|
m_dwRASCallState = RASCALL_STATE_IDLE;
|
|
|
|
if( InterlockedIncrement( &g_lNumberOfcalls ) == 1 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"pCall no goes from 0 to 1:g_hCanUnloadDll set.", this ));
|
|
|
|
ResetEvent( g_hCanUnloadDll );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "New pCall object created:%p.", this ));
|
|
|
|
}
|
|
|
|
|
|
CH323Call::~CH323Call()
|
|
{
|
|
CALL_SEND_CONTEXT* pSendBuf;
|
|
PLIST_ENTRY pLE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "pCall object deleted:%p.", this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_INITIALIZED )
|
|
{
|
|
while( IsListEmpty( &m_sendBufList ) == FALSE )
|
|
{
|
|
pLE = RemoveHeadList( &m_sendBufList );
|
|
pSendBuf = CONTAINING_RECORD( pLE, CALL_SEND_CONTEXT, ListEntry);
|
|
delete pSendBuf->WSABuf.buf;
|
|
delete pSendBuf;
|
|
}
|
|
|
|
if( m_hTransportWait != NULL )
|
|
{
|
|
if( UnregisterWaitEx( m_hTransportWait, NULL ) == FALSE )
|
|
{
|
|
GetLastError();
|
|
}
|
|
|
|
m_hTransportWait = NULL;
|
|
}
|
|
|
|
if( m_hTransport != NULL )
|
|
{
|
|
if(!CloseHandle(m_hTransport))
|
|
{
|
|
WSAGetLastError();
|
|
}
|
|
|
|
m_hTransport = NULL;
|
|
}
|
|
|
|
if( m_callSocket != INVALID_SOCKET )
|
|
{
|
|
closesocket( m_callSocket );
|
|
m_callSocket = INVALID_SOCKET;
|
|
}
|
|
|
|
TermASNCoder();
|
|
|
|
DeleteCriticalSection( &m_CriticalSection );
|
|
}
|
|
|
|
if( InterlockedDecrement( &g_lNumberOfcalls ) == 0 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "Unload dll event set.%p.", this ));
|
|
SetEvent( g_hCanUnloadDll );
|
|
}
|
|
}
|
|
|
|
|
|
//!!no need to lock
|
|
BOOL
|
|
CH323Call::Initialize(
|
|
IN HTAPICALL htCall,
|
|
IN DWORD dwOrigin,
|
|
IN DWORD dwCallType
|
|
)
|
|
{
|
|
int index;
|
|
int rc;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "call init entered:%p.",this ));
|
|
|
|
m_pCallerAliasNames = new H323_ALIASNAMES;
|
|
|
|
if( m_pCallerAliasNames == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate caller name." ));
|
|
return FALSE;
|
|
}
|
|
memset( (PVOID)m_pCallerAliasNames, 0, sizeof(H323_ALIASNAMES) );
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
m_pCalleeAliasNames = new H323_ALIASNAMES;
|
|
|
|
if( m_pCalleeAliasNames == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate callee name." ));
|
|
goto error1;
|
|
}
|
|
memset( (PVOID)m_pCalleeAliasNames, 0, sizeof(H323_ALIASNAMES) );
|
|
|
|
|
|
__try
|
|
{
|
|
if( !InitializeCriticalSectionAndSpinCount( &m_CriticalSection,
|
|
0x80000000 ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "couldn't alloc critsec for call." ));
|
|
goto error2;
|
|
}
|
|
}
|
|
__except( 1 )
|
|
{
|
|
goto error2;
|
|
}
|
|
|
|
if( dwOrigin == LINECALLORIGIN_OUTBOUND )
|
|
{
|
|
int iresult = UuidCreate( &m_callIdentifier );
|
|
|
|
if( (iresult != RPC_S_OK) && (iresult !=RPC_S_UUID_LOCAL_ONLY) )
|
|
{
|
|
goto error3;
|
|
}
|
|
}
|
|
|
|
rc = InitASNCoder();
|
|
|
|
if( rc != ASN1_SUCCESS )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "Q931_InitCoder() returned: %d ", rc));
|
|
goto error3;
|
|
}
|
|
|
|
rc = InitH450ASNCoder();
|
|
|
|
if( rc != ASN1_SUCCESS )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "Q931_InitCoder() returned: %d ", rc));
|
|
goto error4;
|
|
}
|
|
|
|
//Create the CRV for this call.
|
|
do
|
|
{
|
|
m_wCallReference = ((WORD)InterlockedIncrement( &g_lCallReference ))
|
|
& 0x7fff;
|
|
|
|
} while( (m_wCallReference == 0) ||
|
|
g_pH323Line->CallReferenceDuped( m_wCallReference ) );
|
|
|
|
//add the call to the call table
|
|
index = g_pH323Line -> AddCallToTable((PH323_CALL)this);
|
|
if( index == -1 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not add call to call table." ));
|
|
goto error5;
|
|
}
|
|
|
|
//By incrementing the g_H323CallID and taking lower 16 bits we get 65536
|
|
//unique values and then same values are repeated. Thus we can have only
|
|
//65535 simultaneous calls. By using the call table index we make sure that
|
|
//no two existing calls have same call handle.
|
|
do
|
|
{
|
|
m_hdCall = (HDRVCALL)( ((BYTE*)NULL) +
|
|
MAKELONG( LOWORD((DWORD)index),
|
|
(WORD)InterlockedIncrement(&g_H323CallID) ));
|
|
|
|
} while ( m_hdCall == NULL );
|
|
|
|
ZeroMemory( (PVOID)&m_prepareToAnswerMsgData, sizeof(BUFFERDESCR) );
|
|
|
|
m_dwFlags |= CALLOBJECT_INITIALIZED;
|
|
m_htCall = htCall;
|
|
m_dwCallState = LINECALLSTATE_IDLE;
|
|
m_dwOrigin = dwOrigin;
|
|
m_hdConf = NULL;
|
|
|
|
m_wQ931CallRef = m_wCallReference;
|
|
m_dwCallType = dwCallType;
|
|
|
|
// initialize user user information
|
|
InitializeListHead( &m_IncomingU2U );
|
|
InitializeListHead( &m_OutgoingU2U );
|
|
InitializeListHead( &m_sendBufList );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"m_hdCall:%lx m_htCall:%lx m_wCallReference:%lx : %p .",
|
|
m_hdCall, m_htCall, m_wCallReference, this ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "call init exited:%p.",this ));
|
|
return TRUE;
|
|
|
|
error5:
|
|
TermH450ASNCoder();
|
|
error4:
|
|
TermASNCoder();
|
|
error3:
|
|
DeleteCriticalSection( &m_CriticalSection );
|
|
error2:
|
|
delete m_pCalleeAliasNames;
|
|
m_pCalleeAliasNames = NULL;
|
|
error1:
|
|
delete m_pCallerAliasNames;
|
|
m_pCallerAliasNames = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
//!!must be always called in a lock
|
|
//Queues a request made by TAPI to the thread pool
|
|
//
|
|
|
|
BOOL
|
|
CH323Call::QueueTAPICallRequest(
|
|
IN DWORD EventID,
|
|
IN PVOID pBuf
|
|
)
|
|
{
|
|
TAPI_CALLREQUEST_DATA * pCallRequestData = new TAPI_CALLREQUEST_DATA;
|
|
BOOL fResult = TRUE;
|
|
|
|
if( pCallRequestData != NULL )
|
|
{
|
|
pCallRequestData -> EventID = EventID;
|
|
pCallRequestData -> pCall = this;
|
|
pCallRequestData -> pBuf = (PBUFFERDESCR)pBuf;
|
|
|
|
if( !QueueUserWorkItem( ProcessTAPICallRequest, pCallRequestData,
|
|
WT_EXECUTEDEFAULT ) )
|
|
{
|
|
delete pCallRequestData;
|
|
fResult = FALSE;
|
|
}
|
|
|
|
m_IoRefCount++;
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "TAPICallRequest:m_IoRefCount:%d:%p.",
|
|
m_IoRefCount, this ));
|
|
}
|
|
else
|
|
{
|
|
fResult = FALSE;
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
void
|
|
CH323Call::CopyCallStatus(
|
|
IN LPLINECALLSTATUS pCallStatus
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "CopyCallStatus entered:%p.",this ));
|
|
|
|
// transer call state information
|
|
pCallStatus->dwCallState = m_dwCallState;
|
|
pCallStatus->dwCallStateMode = m_dwCallStateMode;
|
|
|
|
// determine call feature based on state
|
|
pCallStatus->dwCallFeatures = ( m_dwCallState != LINECALLSTATE_IDLE)?
|
|
(H323_CALL_FEATURES) : 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "CopyCallStatus exited:%p.",this ));
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
LONG
|
|
CH323Call::CopyCallInfo(
|
|
IN LPLINECALLINFO pCallInfo
|
|
)
|
|
{
|
|
DWORD dwCalleeNameSize = 0;
|
|
DWORD dwCallerNameSize = 0;
|
|
DWORD dwCallerAddressSize = 0;
|
|
WCHAR wszIPAddress[20];
|
|
DWORD dwNextOffset = sizeof(LINECALLINFO);
|
|
DWORD dwU2USize = 0;
|
|
PBYTE pU2U = NULL;
|
|
LONG retVal = NOERROR;
|
|
DWORD dwDivertingNameSize = 0;
|
|
DWORD dwDiversionNameSize = 0;
|
|
DWORD dwDivertedToNameSize = 0;
|
|
DWORD dwCallDataSize = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "CopyCallInfo entered:%p.",this ));
|
|
|
|
// see if user user info available
|
|
if( IsListEmpty( &m_IncomingU2U) == FALSE )
|
|
{
|
|
PLIST_ENTRY pLE;
|
|
PUserToUserLE pU2ULE;
|
|
|
|
// get first list entry
|
|
pLE = m_IncomingU2U.Flink;
|
|
|
|
// convert to user user structure
|
|
pU2ULE = CONTAINING_RECORD(pLE, UserToUserLE, Link);
|
|
|
|
// transfer info
|
|
dwU2USize = pU2ULE->dwU2USize;
|
|
pU2U = pU2ULE->pU2U;
|
|
}
|
|
|
|
// initialize caller and callee id flags now
|
|
pCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
pCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
pCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
pCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
|
|
|
|
// calculate memory necessary for strings
|
|
if( m_pCalleeAliasNames && m_pCalleeAliasNames -> wCount !=0 )
|
|
{
|
|
dwCalleeNameSize =
|
|
H323SizeOfWSZ( m_pCalleeAliasNames -> pItems[0].pData );
|
|
}
|
|
|
|
if( m_pCallerAliasNames && (m_pCallerAliasNames->wCount) )
|
|
{
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
dwCallerNameSize =
|
|
sizeof(WCHAR) * (m_pCallerAliasNames->pItems[0].wDataLength + 1);
|
|
}
|
|
|
|
if( m_CallerAddr.Addr.IP_Binary.dwAddr != 0 )
|
|
{
|
|
wsprintfW(wszIPAddress, L"%d.%d.%d.%d",
|
|
(m_CallerAddr.Addr.IP_Binary.dwAddr >> 24) & 0xff,
|
|
(m_CallerAddr.Addr.IP_Binary.dwAddr >> 16) & 0xff,
|
|
(m_CallerAddr.Addr.IP_Binary.dwAddr >> 8) & 0xff,
|
|
(m_CallerAddr.Addr.IP_Binary.dwAddr) & 0xff
|
|
);
|
|
|
|
dwCallerAddressSize = (wcslen(wszIPAddress) + 1) * sizeof(WCHAR);
|
|
|
|
}
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTEDDEST )
|
|
{
|
|
if( m_pCallReroutingInfo->divertingNrAlias &&
|
|
(m_pCallReroutingInfo->divertingNrAlias->wCount !=0) )
|
|
{
|
|
dwDivertingNameSize = H323SizeOfWSZ(
|
|
m_pCallReroutingInfo->divertingNrAlias-> pItems[0].pData );
|
|
}
|
|
|
|
if( m_pCallReroutingInfo->divertedToNrAlias &&
|
|
(m_pCallReroutingInfo->divertedToNrAlias->wCount != 0) )
|
|
{
|
|
dwDivertedToNameSize = sizeof(WCHAR) *
|
|
m_pCallReroutingInfo->divertedToNrAlias->pItems[0].wDataLength;
|
|
}
|
|
}
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTEDSRC_NOROUTING )
|
|
{
|
|
if( m_pCallReroutingInfo->divertedToNrAlias &&
|
|
(m_pCallReroutingInfo->divertedToNrAlias->wCount != 0) )
|
|
{
|
|
dwDivertedToNameSize = sizeof(WCHAR) *
|
|
m_pCallReroutingInfo->divertedToNrAlias->pItems[0].wDataLength;
|
|
}
|
|
}
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTEDSRC)
|
|
{
|
|
if( m_pCallReroutingInfo->divertedToNrAlias &&
|
|
(m_pCallReroutingInfo->divertedToNrAlias->wCount != 0) )
|
|
{
|
|
dwDivertedToNameSize = sizeof(WCHAR) *
|
|
m_pCallReroutingInfo->divertedToNrAlias->pItems[0].wDataLength;
|
|
}
|
|
|
|
if( m_pCallReroutingInfo->divertingNrAlias &&
|
|
(m_pCallReroutingInfo->divertingNrAlias->wCount !=0) )
|
|
{
|
|
dwDivertingNameSize = H323SizeOfWSZ(
|
|
m_pCallReroutingInfo->divertingNrAlias-> pItems[0].pData );
|
|
}
|
|
|
|
}
|
|
|
|
if( m_CallData.wOctetStringLength != 0 )
|
|
{
|
|
dwCallDataSize = m_CallData.wOctetStringLength;
|
|
}
|
|
|
|
// determine number of bytes needed
|
|
pCallInfo->dwNeededSize = sizeof(LINECALLINFO) +
|
|
dwCalleeNameSize +
|
|
dwCallerNameSize +
|
|
dwCallerAddressSize +
|
|
dwDivertingNameSize +
|
|
dwDiversionNameSize +
|
|
dwDivertedToNameSize +
|
|
dwU2USize +
|
|
dwCallDataSize
|
|
;
|
|
|
|
// see if structure size is large enough
|
|
if (pCallInfo->dwTotalSize >= pCallInfo->dwNeededSize)
|
|
{
|
|
// record number of bytes used
|
|
pCallInfo->dwUsedSize = pCallInfo->dwNeededSize;
|
|
|
|
// validate string size
|
|
if (dwCalleeNameSize > 0)
|
|
{
|
|
if( m_pCalleeAliasNames -> pItems[0].wType == e164_chosen )
|
|
{
|
|
// callee number was specified
|
|
pCallInfo->dwCalledIDFlags = LINECALLPARTYID_ADDRESS;
|
|
|
|
// determine size and offset for callee number
|
|
pCallInfo->dwCalledIDSize = dwCalleeNameSize;
|
|
pCallInfo->dwCalledIDOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwCalledIDOffset),
|
|
(LPBYTE)m_pCalleeAliasNames -> pItems[0].pData,
|
|
pCallInfo->dwCalledIDSize );
|
|
}
|
|
else
|
|
{
|
|
// callee name was specified
|
|
pCallInfo->dwCalledIDFlags = LINECALLPARTYID_NAME;
|
|
|
|
// determine size and offset for callee name
|
|
pCallInfo->dwCalledIDNameSize = dwCalleeNameSize;
|
|
pCallInfo->dwCalledIDNameOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwCalledIDNameOffset),
|
|
(LPBYTE)m_pCalleeAliasNames -> pItems[0].pData,
|
|
pCallInfo->dwCalledIDNameSize );
|
|
}
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += dwCalleeNameSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"callee name: %S.", m_pCalleeAliasNames -> pItems[0].pData ));
|
|
}
|
|
|
|
// validate string size
|
|
if (dwCallerNameSize > 0)
|
|
{
|
|
// caller name was specified
|
|
pCallInfo->dwCallerIDFlags = LINECALLPARTYID_NAME;
|
|
|
|
// determine size and offset for caller name
|
|
pCallInfo->dwCallerIDNameSize = dwCallerNameSize;
|
|
pCallInfo->dwCallerIDNameOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwCallerIDNameOffset),
|
|
(LPBYTE)m_pCallerAliasNames -> pItems[0].pData,
|
|
pCallInfo->dwCallerIDNameSize );
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += dwCallerNameSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"caller name: %S.", m_pCallerAliasNames -> pItems[0].pData ));
|
|
}
|
|
|
|
if( dwCallerAddressSize > 0 )
|
|
{
|
|
// caller number was specified
|
|
pCallInfo->dwCallerIDFlags |= LINECALLPARTYID_ADDRESS;
|
|
|
|
// determine size and offset for caller number
|
|
pCallInfo->dwCallerIDSize = dwCallerAddressSize;
|
|
pCallInfo->dwCallerIDOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwCallerIDOffset),
|
|
(LPBYTE)wszIPAddress,
|
|
pCallInfo->dwCallerIDSize );
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += dwCallerAddressSize;
|
|
}
|
|
|
|
// validate buffer
|
|
if (dwU2USize > 0)
|
|
{
|
|
// determine size and offset of info
|
|
pCallInfo->dwUserUserInfoSize = dwU2USize;
|
|
pCallInfo->dwUserUserInfoOffset = dwNextOffset;
|
|
|
|
// copy user user info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwUserUserInfoOffset),
|
|
(LPBYTE)pU2U,
|
|
pCallInfo->dwUserUserInfoSize );
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += pCallInfo->dwUserUserInfoSize;
|
|
}
|
|
|
|
if( dwDivertingNameSize > 0 )
|
|
{
|
|
// caller name was specified
|
|
pCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_NAME;
|
|
|
|
// determine size and offset for caller name
|
|
pCallInfo->dwRedirectingIDNameSize = dwDivertingNameSize;
|
|
pCallInfo->dwRedirectingIDNameOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwRedirectingIDNameOffset),
|
|
(LPBYTE)(m_pCallReroutingInfo->divertingNrAlias->pItems[0].pData),
|
|
pCallInfo->dwRedirectingIDNameSize );
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += dwDivertingNameSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "diverting name: %S.",
|
|
m_pCallReroutingInfo->divertingNrAlias->pItems[0].pData ));
|
|
}
|
|
|
|
if( dwDiversionNameSize > 0 )
|
|
{
|
|
// caller name was specified
|
|
pCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_NAME;
|
|
|
|
// determine size and offset for caller name
|
|
pCallInfo->dwRedirectionIDNameSize = dwDiversionNameSize;
|
|
pCallInfo->dwRedirectionIDNameOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwRedirectionIDNameOffset),
|
|
(LPBYTE)(m_pCallReroutingInfo->diversionNrAlias->pItems[0].pData),
|
|
pCallInfo->dwRedirectionIDNameSize );
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += dwDiversionNameSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "redirection name: %S.",
|
|
m_pCallReroutingInfo->diversionNrAlias->pItems[0].pData ));
|
|
}
|
|
|
|
if( dwDivertedToNameSize > 0 )
|
|
{
|
|
pCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_NAME;
|
|
|
|
// determine size and offset for caller name
|
|
pCallInfo->dwRedirectionIDNameSize = dwDivertedToNameSize;
|
|
pCallInfo->dwRedirectionIDNameOffset = dwNextOffset;
|
|
|
|
// copy call info after fixed portion
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo->dwRedirectionIDNameOffset),
|
|
(LPBYTE)(m_pCallReroutingInfo->divertedToNrAlias->pItems[0].pData),
|
|
pCallInfo->dwRedirectionIDNameSize );
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += pCallInfo->dwRedirectionIDNameSize;
|
|
|
|
// adjust offset to include string
|
|
dwNextOffset += dwDivertedToNameSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "redirection name: %S.",
|
|
m_pCallReroutingInfo->divertedToNrAlias->pItems[0].pData ));
|
|
|
|
}
|
|
|
|
//pass on the call data
|
|
if( dwCallDataSize > 0 )
|
|
{
|
|
pCallInfo -> dwCallDataSize = dwCallDataSize;
|
|
pCallInfo -> dwCallDataOffset = dwNextOffset;
|
|
|
|
CopyMemory(
|
|
(PVOID)((LPBYTE)pCallInfo + pCallInfo -> dwCallDataOffset),
|
|
(LPBYTE)m_CallData.pOctetString,
|
|
pCallInfo -> dwCallDataSize );
|
|
|
|
dwNextOffset += dwCallDataSize;
|
|
}
|
|
|
|
}
|
|
else if (pCallInfo->dwTotalSize >= sizeof(LINECALLINFO))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"linecallinfo structure too small for strings." ));
|
|
|
|
// structure only contains fixed portion
|
|
pCallInfo->dwUsedSize = sizeof(LINECALLINFO);
|
|
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "linecallinfo structure too small." ));
|
|
|
|
// structure is too small
|
|
return LINEERR_STRUCTURETOOSMALL;
|
|
}
|
|
|
|
// initialize call line device and address info
|
|
pCallInfo->dwLineDeviceID = g_pH323Line->GetDeviceID();
|
|
pCallInfo->dwAddressID = 0;
|
|
|
|
// initialize variable call parameters
|
|
pCallInfo->dwOrigin = m_dwOrigin;
|
|
pCallInfo->dwMediaMode = m_dwIncomingModes | m_dwOutgoingModes;
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTEDDEST )
|
|
{
|
|
if(m_pCallReroutingInfo->diversionReason==DiversionReason_cfu)
|
|
{
|
|
pCallInfo->dwReason = LINECALLREASON_FWDUNCOND;
|
|
}
|
|
else if(m_pCallReroutingInfo->diversionReason==DiversionReason_cfnr)
|
|
{
|
|
pCallInfo->dwReason = LINECALLREASON_FWDNOANSWER;
|
|
}
|
|
else
|
|
{
|
|
pCallInfo->dwReason = LINECALLREASON_FWDBUSY;
|
|
}
|
|
}
|
|
if( m_dwCallType & CALLTYPE_TRANSFEREDDEST )
|
|
{
|
|
pCallInfo->dwReason = LINECALLREASON_TRANSFER;
|
|
}
|
|
else
|
|
{
|
|
pCallInfo->dwReason = LINECALLREASON_DIRECT;
|
|
}
|
|
|
|
pCallInfo->dwCallStates = (m_dwOrigin==LINECALLORIGIN_INBOUND)
|
|
? H323_CALL_INBOUNDSTATES
|
|
: H323_CALL_OUTBOUNDSTATES
|
|
;
|
|
|
|
// initialize constant call parameters
|
|
pCallInfo->dwBearerMode = H323_LINE_BEARERMODES;
|
|
pCallInfo->dwRate = H323_LINE_MAXRATE;
|
|
|
|
// initialize unsupported call capabilities
|
|
pCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
|
|
|
|
//pass on the dwAppSpecific info
|
|
pCallInfo -> dwAppSpecific = m_dwAppSpecific;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "CopyCallInfo exited:%p.",this ));
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//!!always called in lock
|
|
BOOL
|
|
CH323Call::HandleReadyToInitiate(
|
|
IN PTspMspMessage pMessage
|
|
)
|
|
{
|
|
Q931_SETUP_ASN setupASN;
|
|
WORD wCount;
|
|
DWORD dwAPDUType = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "HandleReadyToInitiate entered:%p.", this ));
|
|
|
|
//set the additional callee addresses and callee aliases
|
|
//see if there is a fast-connect proposal
|
|
if( pMessage->dwEncodedASNSize != 0 )
|
|
{
|
|
if( !ParseSetupASN( pMessage ->pEncodedASNBuf,
|
|
pMessage->dwEncodedASNSize,
|
|
&setupASN,
|
|
&dwAPDUType ))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if( setupASN.fFastStartPresent )
|
|
{
|
|
_ASSERTE( !m_pFastStart );
|
|
m_pFastStart = setupASN.pFastStart;
|
|
setupASN.pFastStart = NULL;
|
|
m_dwFastStart = FAST_START_SELF_AVAIL;
|
|
}
|
|
else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}
|
|
|
|
if( setupASN.pCallerAliasList && !RasIsRegistered() )
|
|
{
|
|
//_ASSERTE(0);
|
|
|
|
if( m_pCallerAliasNames == NULL )
|
|
{
|
|
m_pCallerAliasNames = setupASN.pCallerAliasList;
|
|
|
|
//dont release this alias list
|
|
setupASN.pCallerAliasList = NULL;
|
|
}
|
|
else
|
|
{
|
|
wCount = m_pCallerAliasNames->wCount +
|
|
setupASN.pCallerAliasList->wCount;
|
|
|
|
PH323_ALIASITEM tempPtr = setupASN.pCallerAliasList->pItems;
|
|
|
|
setupASN.pCallerAliasList->pItems = (PH323_ALIASITEM)realloc(
|
|
(PVOID)setupASN.pCallerAliasList->pItems,
|
|
wCount * sizeof(H323_ALIASITEM) );
|
|
|
|
if( setupASN.pCallerAliasList->pItems == NULL )
|
|
{
|
|
//restore the old pointer in case enough memory was not
|
|
//available to expand the memory block
|
|
setupASN.pCallerAliasList->pItems = tempPtr;
|
|
}
|
|
else
|
|
{
|
|
CopyMemory(
|
|
(PVOID)&(setupASN.pCallerAliasList->pItems[setupASN.pCallerAliasList->wCount]),
|
|
(PVOID)m_pCallerAliasNames->pItems,
|
|
m_pCallerAliasNames->wCount * sizeof(H323_ALIASITEM) );
|
|
|
|
setupASN.pCallerAliasList->wCount = wCount;
|
|
|
|
delete m_pCallerAliasNames->pItems;
|
|
delete m_pCallerAliasNames;
|
|
m_pCallerAliasNames = setupASN.pCallerAliasList;
|
|
setupASN.pCallerAliasList = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//add the callee aliases sent by the MSP
|
|
if( setupASN.pCalleeAliasList != NULL )
|
|
{
|
|
//_ASSERTE(0);
|
|
|
|
if( m_pCalleeAliasNames == NULL )
|
|
{
|
|
m_pCalleeAliasNames = setupASN.pCalleeAliasList;
|
|
|
|
//dont release this alias list
|
|
setupASN.pCalleeAliasList = NULL;
|
|
}
|
|
else
|
|
{
|
|
wCount = m_pCalleeAliasNames->wCount +
|
|
setupASN.pCalleeAliasList->wCount;
|
|
|
|
PH323_ALIASITEM tempPtr = m_pCalleeAliasNames->pItems;
|
|
|
|
m_pCalleeAliasNames->pItems = (PH323_ALIASITEM)realloc(
|
|
(PVOID)m_pCalleeAliasNames->pItems,
|
|
wCount * sizeof(H323_ALIASITEM) );
|
|
|
|
if( m_pCalleeAliasNames->pItems == NULL )
|
|
{
|
|
//restore the old pointer in case enough memory was not
|
|
//available to expand the memory block
|
|
m_pCalleeAliasNames->pItems = tempPtr;
|
|
goto cleanup;
|
|
}
|
|
|
|
CopyMemory(
|
|
(PVOID)&(m_pCalleeAliasNames->pItems[m_pCalleeAliasNames->wCount]),
|
|
(PVOID)setupASN.pCalleeAliasList->pItems,
|
|
setupASN.pCalleeAliasList->wCount * sizeof(H323_ALIASITEM) );
|
|
|
|
m_pCalleeAliasNames->wCount = wCount;
|
|
|
|
delete setupASN.pCalleeAliasList->pItems;
|
|
delete setupASN.pCalleeAliasList;
|
|
setupASN.pCalleeAliasList = NULL;
|
|
}
|
|
}
|
|
|
|
FreeSetupASN( &setupASN );
|
|
}
|
|
else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}
|
|
|
|
//send the setup message
|
|
if( !SendSetupMessage() )
|
|
{
|
|
DropCall( 0 );
|
|
}
|
|
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "HandleReadyToInitiate exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
CloseCall( 0 );
|
|
FreeSetupASN( &setupASN );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in lock
|
|
BOOL
|
|
CH323Call::HandleProceedWithAnswer(
|
|
IN PTspMspMessage pMessage
|
|
)
|
|
{
|
|
Q931_CALL_PROCEEDING_ASN proceedingASN;
|
|
DWORD dwAPDUType = 0;
|
|
PH323_ALIASITEM pwszDivertedToAlias = NULL;
|
|
WCHAR *pwszAliasName = NULL;
|
|
WORD wAliasLength = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleProceedWithAnswer entered:%p.", this ));
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTED_SERVED )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"Call already diverted. ignore the message:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
//see if there is a fast-connect proposal
|
|
if( pMessage->dwEncodedASNSize != 0 )
|
|
{
|
|
if( !ParseProceedingASN(pMessage ->pEncodedASNBuf,
|
|
pMessage->dwEncodedASNSize,
|
|
&proceedingASN,
|
|
&dwAPDUType ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if( proceedingASN.fH245AddrPresent )
|
|
{
|
|
m_selfH245Addr = proceedingASN.h245Addr;
|
|
}
|
|
|
|
if( proceedingASN.fFastStartPresent &&
|
|
(m_dwFastStart!=FAST_START_NOTAVAIL) )
|
|
{
|
|
_ASSERTE( m_pFastStart == NULL );
|
|
|
|
m_pFastStart = proceedingASN.pFastStart;
|
|
m_dwFastStart = FAST_START_AVAIL;
|
|
|
|
//we keep a reference to the fast start list so don't release it
|
|
proceedingASN.pFastStart = NULL;
|
|
proceedingASN.fFastStartPresent = FALSE;
|
|
}
|
|
/*else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}*/
|
|
|
|
FreeProceedingASN( &proceedingASN );
|
|
}
|
|
/*else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}*/
|
|
|
|
//send proceeding message to the peer
|
|
if(!SendProceeding() )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//send alerting message to the peer
|
|
if( !SendQ931Message(NO_INVOKEID, 0, 0, ALERTINGMESSAGETYPE, NO_H450_APDU) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
m_dwStateMachine = Q931_ALERT_SENT;
|
|
|
|
//for TRANSFEREDDEST call directly accept the call wihtout the user
|
|
//answering the call
|
|
if( (m_dwCallType & CALLTYPE_TRANSFEREDDEST) && m_hdRelatedCall )
|
|
{
|
|
AcceptCall();
|
|
}
|
|
|
|
if( m_pCallerAliasNames && (m_pCallerAliasNames -> wCount > 0) )
|
|
{
|
|
pwszAliasName = m_pCallerAliasNames->pItems[0].pData;
|
|
wAliasLength = (m_pCallerAliasNames->pItems[0].wDataLength+1)
|
|
* sizeof(WCHAR);
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
|
|
pwszDivertedToAlias = g_pH323Line->CallToBeDiverted(
|
|
pwszAliasName,
|
|
wAliasLength,
|
|
LINEFORWARDMODE_NOANSW | LINEFORWARDMODE_NOANSWSPECIFIC |
|
|
LINEFORWARDMODE_BUSYNA | LINEFORWARDMODE_BUSYNASPECIFIC );
|
|
|
|
//if call is to be diverted for no answer, start the timer
|
|
if( pwszDivertedToAlias != NULL )
|
|
{
|
|
if( !StartTimerForCallDiversionOnNA( pwszDivertedToAlias ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleProceedWithAnswer exited:%p.",this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in lock
|
|
BOOL
|
|
CH323Call::HandleReadyToAnswer(
|
|
IN PTspMspMessage pMessage
|
|
)
|
|
{
|
|
Q931_CALL_PROCEEDING_ASN proceedingASN;
|
|
DWORD dwAPDUType = 0;
|
|
PH323_CALL pConsultCall = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "HandleReadyToAnswer entered:%p.",this ));
|
|
|
|
m_fReadyToAnswer = TRUE;
|
|
|
|
//see if there is a fast-connect proposal
|
|
if( pMessage->dwEncodedASNSize != 0 )
|
|
{
|
|
if( !ParseProceedingASN(pMessage ->pEncodedASNBuf,
|
|
pMessage->dwEncodedASNSize,
|
|
&proceedingASN,
|
|
&dwAPDUType) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if( proceedingASN.fH245AddrPresent )
|
|
{
|
|
m_selfH245Addr = proceedingASN.h245Addr;
|
|
}
|
|
|
|
if( proceedingASN.fFastStartPresent &&
|
|
(m_dwFastStart!=FAST_START_NOTAVAIL) )
|
|
{
|
|
_ASSERTE( m_pFastStart == NULL );
|
|
|
|
m_pFastStart = proceedingASN.pFastStart;
|
|
m_dwFastStart = FAST_START_AVAIL;
|
|
|
|
//we keep a reference to the fast start list so don't release it
|
|
proceedingASN.pFastStart = NULL;
|
|
proceedingASN.fFastStartPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}
|
|
|
|
FreeProceedingASN( &proceedingASN );
|
|
}
|
|
else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}
|
|
|
|
if( m_fCallAccepted )
|
|
{
|
|
// validate status
|
|
if( !AcceptH323Call() )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error answering call 0x%08lx.", this ));
|
|
|
|
// failure
|
|
goto cleanup;
|
|
}
|
|
|
|
//lock the primary call after replacement call to avoid deadlock
|
|
if( (m_dwCallType & CALLTYPE_TRANSFEREDDEST) && m_hdRelatedCall )
|
|
{
|
|
QueueSuppServiceWorkItem( SWAP_REPLACEMENT_CALL,
|
|
m_hdCall, (ULONG_PTR)m_hdRelatedCall );
|
|
}
|
|
else
|
|
{
|
|
//send MSP start H245
|
|
SendMSPStartH245( NULL, NULL );
|
|
|
|
//tell MSP about connect state
|
|
SendMSPMessage( SP_MSG_ConnectComplete, 0, 0, NULL );
|
|
}
|
|
|
|
//change call state to accepted from offering
|
|
ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "HandleReadyToAnswer exited:%p.",this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
//!!This function must be always called in a lock. The calling function should
|
|
//not unlock the call object as this function itself unlocks the call object
|
|
BOOL
|
|
CH323Call::HandleMSPMessage(
|
|
IN PTspMspMessage pMessage,
|
|
IN HDRVMSPLINE hdMSPLine,
|
|
IN HTAPIMSPLINE htMSPLine
|
|
)
|
|
{
|
|
BOOL fResult = TRUE;
|
|
PH323_CALL pCall = NULL;
|
|
ASN1octetstring_t pH245PDU;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleMSPMessage entered:%p.",this ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "MSP message:%s recvd.",
|
|
H323TSPMessageToString(pMessage->MessageType) ));
|
|
|
|
switch( pMessage -> MessageType )
|
|
{
|
|
case SP_MSG_ReadyToInitiate:
|
|
|
|
// The Q.931 connection should be in the connected state by now
|
|
if( pMessage -> MsgBody.ReadyToInitiateMessage.hMSPReplacementCall != NULL )
|
|
{
|
|
//unlock the primary call before locking the related call
|
|
Unlock();
|
|
|
|
pCall=g_pH323Line -> FindH323CallAndLock(m_hdRelatedCall);
|
|
if( pCall == NULL )
|
|
{
|
|
//transfered call is not around so close the primary call
|
|
CloseCall( 0 );
|
|
return TRUE;
|
|
}
|
|
|
|
fResult = pCall -> HandleReadyToInitiate( pMessage );
|
|
pCall -> Unlock();
|
|
}
|
|
else
|
|
{
|
|
m_hdMSPLine = hdMSPLine;
|
|
m_htMSPLine = htMSPLine;
|
|
fResult = HandleReadyToInitiate( pMessage );
|
|
Unlock();
|
|
}
|
|
|
|
break;
|
|
|
|
case SP_MSG_ProceedWithAnswer:
|
|
|
|
if( pMessage -> MsgBody.ProceedWithAnswerMessage.hMSPReplacementCall != NULL )
|
|
{
|
|
//unlock the primary call before locking the related call
|
|
Unlock();
|
|
|
|
pCall=g_pH323Line -> FindH323CallAndLock(m_hdRelatedCall);
|
|
if( pCall == NULL )
|
|
{
|
|
//transfered call is not around so close the primary call
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
fResult = pCall -> HandleProceedWithAnswer( pMessage );
|
|
pCall -> Unlock();
|
|
}
|
|
else
|
|
{
|
|
m_hdMSPLine = hdMSPLine;
|
|
m_htMSPLine = htMSPLine;
|
|
fResult = HandleProceedWithAnswer( pMessage );
|
|
Unlock();
|
|
}
|
|
|
|
break;
|
|
|
|
case SP_MSG_ReadyToAnswer:
|
|
|
|
if( pMessage -> MsgBody.ReadyToAnswerMessage.hMSPReplacementCall != NULL )
|
|
{
|
|
//unlock the primary call before locking the related call
|
|
Unlock();
|
|
|
|
pCall=g_pH323Line -> FindH323CallAndLock(m_hdRelatedCall);
|
|
if( pCall== NULL )
|
|
{
|
|
//transfered call is not around so close the primary call
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
fResult = pCall -> HandleReadyToAnswer( pMessage );
|
|
pCall -> Unlock();
|
|
}
|
|
else
|
|
{
|
|
//decode call_proceding message and extract local fast
|
|
//start inforamtion and local H245 address
|
|
fResult = HandleReadyToAnswer( pMessage );
|
|
Unlock();
|
|
}
|
|
|
|
break;
|
|
|
|
case SP_MSG_ReleaseCall:
|
|
|
|
//shutdown the H323 call
|
|
CloseCall( LINEDISCONNECTMODE_CANCELLED );
|
|
|
|
Unlock();
|
|
break;
|
|
|
|
case SP_MSG_H245Terminated:
|
|
|
|
//shutdown the H323 call
|
|
CloseCall( LINEDISCONNECTMODE_NORMAL );
|
|
|
|
Unlock();
|
|
break;
|
|
|
|
case SP_MSG_SendDTMFDigits:
|
|
|
|
if( m_fMonitoringDigits == TRUE )
|
|
{
|
|
WCHAR * pwch = pMessage->pWideChars;
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "dtmf digits recvd:%S.", pwch));
|
|
|
|
// process each digit
|
|
WORD indexI=0;
|
|
while( indexI < pMessage->MsgBody.SendDTMFDigitsMessage.wNumDigits )
|
|
{
|
|
// signal incoming
|
|
PostLineEvent(
|
|
LINE_MONITORDIGITS,
|
|
(DWORD_PTR)*pwch,
|
|
LINEDIGITMODE_DTMF,
|
|
GetTickCount()
|
|
);
|
|
|
|
++pwch;
|
|
indexI++;
|
|
}
|
|
}
|
|
Unlock();
|
|
break;
|
|
|
|
case SP_MSG_LegacyDefaultAlias:
|
|
|
|
if( pMessage -> MsgBody.LegacyDefaultAliasMessage.wNumChars > 0 )
|
|
{
|
|
if( !RasIsRegistered() )
|
|
{
|
|
_ASSERTE( m_pwszDisplay == NULL );
|
|
|
|
m_pwszDisplay = new WCHAR[
|
|
pMessage -> MsgBody.LegacyDefaultAliasMessage.wNumChars ];
|
|
|
|
if( m_pwszDisplay != NULL )
|
|
{
|
|
CopyMemory(
|
|
(PVOID)m_pwszDisplay,
|
|
pMessage->pWideChars,
|
|
sizeof(WCHAR) * pMessage -> MsgBody.LegacyDefaultAliasMessage.wNumChars
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
break;
|
|
|
|
case SP_MSG_H245PDU:
|
|
|
|
if( (pMessage ->pEncodedASNBuf) && (pMessage->dwEncodedASNSize != 0) )
|
|
{
|
|
pH245PDU.value = pMessage ->pEncodedASNBuf;
|
|
pH245PDU.length = pMessage->dwEncodedASNSize;
|
|
fResult = SendQ931Message( NO_INVOKEID, 0, (ULONG_PTR)&pH245PDU,
|
|
FACILITYMESSAGETYPE, NO_H450_APDU );
|
|
}
|
|
Unlock();
|
|
break;
|
|
|
|
case SP_MSG_RASRegistrationEvent:
|
|
default:
|
|
|
|
_ASSERTE(0);
|
|
Unlock();
|
|
break;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "HandleMSPMessage exited:%p.",this ));
|
|
return fResult;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::SendMSPMessage(
|
|
IN TspMspMessageType messageType,
|
|
IN BYTE* pbEncodedBuf,
|
|
IN DWORD dwLength,
|
|
IN HDRVCALL hReplacementCall
|
|
)
|
|
{
|
|
TspMspMessageEx messageEx;
|
|
HTAPIMSPLINE hMSP = MSP_HANDLE_UNKNOWN;
|
|
int iError = 0;
|
|
int iLen = sizeof(SOCKADDR_IN);
|
|
SOCKADDR_IN* psaLocalQ931Addr = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "SendMSPMessage:%s entered:%p.",
|
|
H323TSPMessageToString(messageType), this ));
|
|
|
|
messageEx.message.MessageType = messageType;
|
|
|
|
switch( messageType )
|
|
{
|
|
case SP_MSG_InitiateCall:
|
|
|
|
messageEx.message.MsgBody.InitiateCallMessage.hTSPReplacementCall =
|
|
(HANDLE)hReplacementCall;
|
|
messageEx.message.MsgBody.InitiateCallMessage.hTSPConferenceCall =
|
|
m_hdConf;
|
|
|
|
psaLocalQ931Addr =
|
|
&messageEx.message.MsgBody.InitiateCallMessage.saLocalQ931Addr;
|
|
ZeroMemory( (PVOID)psaLocalQ931Addr, sizeof(SOCKADDR_IN) );
|
|
|
|
*psaLocalQ931Addr = m_LocalAddr;
|
|
psaLocalQ931Addr->sin_family = AF_INET;
|
|
|
|
break;
|
|
|
|
case SP_MSG_PrepareToAnswer:
|
|
|
|
if( (dwLength<=0) || (dwLength > sizeof(messageEx.pEncodedASN)) ||
|
|
(!pbEncodedBuf) )
|
|
{
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
messageEx.message.MsgBody.PrepareToAnswerMessage.hReplacementCall =
|
|
(HANDLE)hReplacementCall;
|
|
|
|
psaLocalQ931Addr =
|
|
&messageEx.message.MsgBody.PrepareToAnswerMessage.saLocalQ931Addr;
|
|
ZeroMemory( (PVOID)psaLocalQ931Addr, sizeof(SOCKADDR_IN) );
|
|
|
|
*psaLocalQ931Addr = m_LocalAddr;
|
|
psaLocalQ931Addr->sin_family = AF_INET;
|
|
|
|
//send the received Setup message. This should have the information
|
|
//about m_pPeerFastStart param as wel
|
|
CopyMemory( (PVOID)messageEx.message.pEncodedASNBuf,
|
|
(PVOID)pbEncodedBuf, dwLength );
|
|
break;
|
|
|
|
case SP_MSG_SendDTMFDigits:
|
|
|
|
if( (dwLength<=0) || (dwLength > sizeof(messageEx.pEncodedASN)) ||
|
|
(!pbEncodedBuf) )
|
|
{
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
hMSP = m_htMSPLine;
|
|
messageEx.message.MsgBody.SendDTMFDigitsMessage.wNumDigits =
|
|
(WORD)dwLength;
|
|
|
|
dwLength = (dwLength+1) * sizeof(WCHAR);
|
|
CopyMemory( (PVOID)messageEx.message.pEncodedASNBuf,
|
|
(PVOID)pbEncodedBuf, dwLength );
|
|
|
|
break;
|
|
|
|
case SP_MSG_ConnectComplete:
|
|
case SP_MSG_CallShutdown:
|
|
|
|
//dont set anything
|
|
hMSP = m_htMSPLine;
|
|
break;
|
|
|
|
case SP_MSG_H245PDU:
|
|
case SP_MSG_AnswerCall:
|
|
|
|
hMSP = m_htMSPLine;
|
|
break;
|
|
|
|
case SP_MSG_Hold:
|
|
|
|
hMSP = m_htMSPLine;
|
|
messageEx.message.MsgBody.HoldMessage.fHold = (BOOL)dwLength;
|
|
dwLength = 0;
|
|
break;
|
|
}
|
|
|
|
messageEx.message.dwMessageSize = sizeof(TspMspMessage) + dwLength
|
|
- ((dwLength)?sizeof(WORD):0);
|
|
|
|
if( messageType == SP_MSG_SendDTMFDigits )
|
|
{
|
|
messageEx.message.dwEncodedASNSize = 0;
|
|
}
|
|
else
|
|
{
|
|
messageEx.message.dwEncodedASNSize = dwLength;
|
|
}
|
|
|
|
//send msp message
|
|
PostLineEvent (
|
|
LINE_SENDMSPDATA,
|
|
(DWORD_PTR)hMSP, //This handle should be NULL when htCall param is a valid value
|
|
(DWORD_PTR)&(messageEx.message),
|
|
messageEx.message.dwMessageSize);
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "SendMSPMessage exited:%p.",this ));
|
|
return;
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
void
|
|
CH323Call::SendMSPStartH245(
|
|
PH323_ADDR pPeerH245Addr,
|
|
PH323_FASTSTART pPeerFastStart
|
|
)
|
|
{
|
|
TspMspMessageEx messageEx;
|
|
WORD wEncodedLength;
|
|
BYTE* pEncodedASNBuffer;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "SendMSPStartH245 entered:%p.", this ));
|
|
|
|
wEncodedLength = 0;
|
|
|
|
messageEx.message.MessageType = SP_MSG_StartH245;
|
|
messageEx.message.MsgBody.StartH245Message.hMSPReplaceCall = NULL;
|
|
messageEx.message.MsgBody.StartH245Message.hTSPReplacementCall =
|
|
(HANDLE)pPeerH245Addr;
|
|
ZeroMemory( messageEx.message.MsgBody.StartH245Message.ConferenceID,
|
|
sizeof(GUID) );
|
|
|
|
messageEx.message.MsgBody.StartH245Message.fH245TunnelCapability = FALSE;
|
|
messageEx.message.MsgBody.StartH245Message.fH245AddressPresent = FALSE;
|
|
|
|
memset( (PVOID)&messageEx.message.MsgBody.StartH245Message.saH245Addr,
|
|
0, sizeof(SOCKADDR_IN) );
|
|
|
|
//for outgoing call send the fast start proposal.
|
|
if( (m_dwOrigin==LINECALLORIGIN_OUTBOUND) || pPeerH245Addr )
|
|
{
|
|
if( pPeerH245Addr == NULL )
|
|
{
|
|
pPeerFastStart = m_pPeerFastStart;
|
|
}
|
|
|
|
if( pPeerFastStart != NULL )
|
|
{
|
|
if( !EncodeFastStartProposal( pPeerFastStart, &pEncodedASNBuffer,
|
|
&wEncodedLength ) )
|
|
{
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
CopyMemory( (PVOID)messageEx.message.pEncodedASNBuf,
|
|
(PVOID)pEncodedASNBuffer, wEncodedLength );
|
|
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedASNBuffer );
|
|
}
|
|
}
|
|
|
|
//If outgoing call send peer's H245 address
|
|
if( (m_dwOrigin == LINECALLORIGIN_OUTBOUND) || pPeerH245Addr )
|
|
{
|
|
if( pPeerH245Addr == NULL )
|
|
{
|
|
pPeerH245Addr = &m_peerH245Addr;
|
|
}
|
|
|
|
messageEx.message.MsgBody.StartH245Message.fH245AddressPresent = FALSE;
|
|
if( pPeerH245Addr->Addr.IP_Binary.dwAddr != 0 )
|
|
{
|
|
messageEx.message.MsgBody.StartH245Message.saH245Addr.sin_family = AF_INET;
|
|
messageEx.message.MsgBody.StartH245Message.saH245Addr.sin_port =
|
|
htons(pPeerH245Addr->Addr.IP_Binary.wPort);
|
|
messageEx.message.MsgBody.StartH245Message.saH245Addr.sin_addr.s_addr =
|
|
htonl(pPeerH245Addr->Addr.IP_Binary.dwAddr);
|
|
|
|
messageEx.message.MsgBody.StartH245Message.fH245AddressPresent = TRUE;
|
|
}
|
|
}
|
|
|
|
//set the Q931 address
|
|
ZeroMemory( (PVOID)&messageEx.message.MsgBody.StartH245Message.saQ931Addr,
|
|
sizeof(SOCKADDR_IN) );
|
|
|
|
messageEx.message.MsgBody.StartH245Message.saQ931Addr.sin_family = AF_INET;
|
|
messageEx.message.MsgBody.StartH245Message.saQ931Addr.sin_port =
|
|
htons( m_CalleeAddr.Addr.IP_Binary.wPort );
|
|
messageEx.message.MsgBody.StartH245Message.saQ931Addr.sin_addr.s_addr =
|
|
htonl( m_CalleeAddr.Addr.IP_Binary.dwAddr );
|
|
|
|
messageEx.message.MsgBody.StartH245Message.fH245TunnelCapability =
|
|
(m_fh245Tunneling & REMOTE_H245_TUNNELING) &&
|
|
(m_fh245Tunneling & LOCAL_H245_TUNNELING);
|
|
|
|
messageEx.message.dwMessageSize = sizeof(messageEx.message) +
|
|
wEncodedLength - ((wEncodedLength)?1:0);
|
|
|
|
messageEx.message.dwEncodedASNSize = wEncodedLength;
|
|
|
|
// send msp message
|
|
PostLineEvent (
|
|
LINE_SENDMSPDATA,
|
|
//this handle should be NULL when htCall is a valid handle.
|
|
(DWORD_PTR)NULL,
|
|
(DWORD_PTR)&(messageEx.message),
|
|
messageEx.message.dwMessageSize);
|
|
|
|
m_dwFlags |= H245_START_MSG_SENT;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "SendMSPStartH245 exited:%p.",this ));
|
|
return;
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
BOOL
|
|
CH323Call::AddU2U(
|
|
IN DWORD dwDirection,
|
|
IN DWORD dwDataSize,
|
|
IN PBYTE pData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create user user structure and adds to list.
|
|
|
|
Arguments:
|
|
|
|
pLftHead - Pointer to list in which to add user user info.
|
|
|
|
dwDataSize - Size of buffer pointed to by pData.
|
|
|
|
pData - Pointer to user user info.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY pListHead = NULL;
|
|
PUserToUserLE pU2ULE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "AddU2U entered:%p.",this ));
|
|
|
|
if( dwDirection == U2U_OUTBOUND )
|
|
{
|
|
pListHead = &m_OutgoingU2U;
|
|
}
|
|
else
|
|
{
|
|
pListHead = &m_IncomingU2U;
|
|
}
|
|
|
|
// validate data buffer pointer and size
|
|
if( (pData != NULL) && (dwDataSize > 0) )
|
|
{
|
|
// allocate memory for user user info
|
|
pU2ULE = (PUserToUserLE)new char[ dwDataSize + sizeof(UserToUserLE) ];
|
|
|
|
// validate pointer
|
|
if (pU2ULE == NULL)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate user user info." ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// aim pointer at the end of the buffer by default
|
|
pU2ULE->pU2U = (LPBYTE)pU2ULE + sizeof(UserToUserLE);
|
|
pU2ULE->dwU2USize = dwDataSize;
|
|
|
|
// transfer user user info into list entry
|
|
CopyMemory( (PVOID)pU2ULE->pU2U, (PVOID)pData, pU2ULE->dwU2USize);
|
|
|
|
// add list entry to back of list
|
|
InsertTailList(pListHead, &pU2ULE->Link);
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"added user user info 0x%08lx (%d bytes).",
|
|
pU2ULE->pU2U,
|
|
pU2ULE->dwU2USize
|
|
));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "AddU2U exited:%p.",this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create user user structure and adds to list.
|
|
!!always called in lock.
|
|
|
|
Arguments:
|
|
|
|
pLftHead - Pointer to list in which to add user user info.
|
|
|
|
dwDataSize - Size of buffer pointed to by pData.
|
|
|
|
pData - Pointer to user user info.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
CH323Call::AddU2UNoAlloc(
|
|
IN DWORD dwDirection,
|
|
IN DWORD dwDataSize,
|
|
IN PBYTE pData
|
|
)
|
|
{
|
|
PLIST_ENTRY pListHead = NULL;
|
|
PUserToUserLE pU2ULE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "AddU2U entered:%p.",this ));
|
|
|
|
if( dwDirection == U2U_OUTBOUND )
|
|
{
|
|
pListHead = &m_OutgoingU2U;
|
|
}
|
|
else
|
|
{
|
|
pListHead = &m_IncomingU2U;
|
|
}
|
|
|
|
// validate data buffer pointer and size
|
|
if( (pData != NULL) && (dwDataSize > 0) )
|
|
{
|
|
// allocate memory for user user info
|
|
pU2ULE = new UserToUserLE;
|
|
|
|
// validate pointer
|
|
if (pU2ULE == NULL)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate user user info." ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// aim pointer at the end of the buffer by default
|
|
pU2ULE->pU2U = pData;
|
|
pU2ULE->dwU2USize = dwDataSize;
|
|
|
|
|
|
// add list entry to back of list
|
|
InsertTailList(pListHead, &pU2ULE->Link);
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"added user user info 0x%08lx (%d bytes).",
|
|
pU2ULE->pU2U,
|
|
pU2ULE->dwU2USize
|
|
));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "AddU2U exited:%p.",this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!must be always called in a lock.
|
|
BOOL
|
|
CH323Call::RemoveU2U(
|
|
IN DWORD dwDirection,
|
|
IN PUserToUserLE * ppU2ULE
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Removes user user info structure from list.
|
|
|
|
Arguments:
|
|
|
|
pListHead - Pointer to list in which to remove user user info.
|
|
|
|
ppU2ULE - Pointer to pointer to list entry.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY pListHead = NULL;
|
|
PLIST_ENTRY pLE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "RemoveU2U entered:%p.",this ));
|
|
|
|
if( dwDirection == U2U_OUTBOUND )
|
|
{
|
|
pListHead = &m_OutgoingU2U;
|
|
}
|
|
else
|
|
{
|
|
pListHead = &m_IncomingU2U;
|
|
}
|
|
|
|
// process list until empty
|
|
if( IsListEmpty(pListHead) == FALSE )
|
|
{
|
|
// retrieve first entry
|
|
pLE = RemoveHeadList(pListHead);
|
|
|
|
// convert list entry to structure pointer
|
|
*ppU2ULE = CONTAINING_RECORD(pLE, UserToUserLE, Link);
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"removed user user info 0x%08lx (%d bytes).",
|
|
(*ppU2ULE)->pU2U, (*ppU2ULE)->dwU2USize ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "RemoveU2U exited:%p.",this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::FreeU2U(
|
|
IN DWORD dwDirection
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Releases memory for user user list.
|
|
!!must be always called in a lock.
|
|
|
|
Arguments
|
|
|
|
pListHead - Pointer to list in which to free user user info.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY pLE;
|
|
PUserToUserLE pU2ULE;
|
|
PLIST_ENTRY pListHead = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "FreeU2U entered:%p.",this ));
|
|
|
|
if( dwDirection == U2U_OUTBOUND )
|
|
{
|
|
pListHead = &m_OutgoingU2U;
|
|
}
|
|
else
|
|
{
|
|
pListHead = &m_IncomingU2U;
|
|
}
|
|
|
|
// process list until empty
|
|
while( IsListEmpty(pListHead) == FALSE )
|
|
{
|
|
// retrieve first entry
|
|
pLE = RemoveHeadList(pListHead);
|
|
|
|
// convert list entry to structure pointer
|
|
pU2ULE = CONTAINING_RECORD(pLE, UserToUserLE, Link);
|
|
|
|
// release memory
|
|
if( pU2ULE )
|
|
{
|
|
delete pU2ULE;
|
|
pU2ULE = NULL;
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "FreeU2U exited:%p.",this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resets call object to original state for re-use.
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
void
|
|
CH323Call::Shutdown(
|
|
OUT BOOL * fDelete
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "Shutdown entered:%p.",this ));
|
|
|
|
if( !(m_dwFlags & CALLOBJECT_INITIALIZED) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//acquire the lock on call table before acquiring the lock on call object
|
|
g_pH323Line -> LockCallTable();
|
|
Lock();
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
Unlock();
|
|
g_pH323Line -> UnlockCallTable();
|
|
|
|
return;
|
|
}
|
|
|
|
// reset tapi info
|
|
m_dwCallState = LINECALLSTATE_UNKNOWN;
|
|
m_dwCallStateMode = 0;
|
|
m_dwOrigin = LINECALLORIGIN_UNKNOWN;
|
|
m_dwAddressType = 0;
|
|
m_dwIncomingModes = 0;
|
|
m_dwOutgoingModes = 0;
|
|
m_dwRequestedModes = 0;
|
|
m_fMonitoringDigits = FALSE;
|
|
|
|
// reset tapi handles
|
|
m_htCall = (HTAPICALL)NULL;
|
|
|
|
// reset addresses
|
|
memset( (PVOID)&m_CalleeAddr,0,sizeof(H323_ADDR));
|
|
memset( (PVOID)&m_CallerAddr,0,sizeof(H323_ADDR));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting calleealias:%p.",this ));
|
|
FreeAliasNames( m_pCalleeAliasNames );
|
|
m_pCalleeAliasNames = NULL;
|
|
|
|
if( m_pCallerAliasNames != NULL )
|
|
{
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
FreeAliasNames( m_pCallerAliasNames );
|
|
m_pCallerAliasNames = NULL;
|
|
}
|
|
|
|
//reset non standard data
|
|
memset( (PVOID)&m_NonStandardData, 0, sizeof(H323NonStandardData) );
|
|
|
|
// release user user information
|
|
FreeU2U( U2U_OUTBOUND );
|
|
FreeU2U( U2U_INBOUND );
|
|
|
|
//shutdown the Q931 call if not shutdown yet
|
|
if( m_hSetupSentTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hSetupSentTimer, NULL );
|
|
m_hSetupSentTimer = NULL;
|
|
}
|
|
|
|
if( m_hCallEstablishmentTimer )
|
|
{
|
|
DeleteTimerQueueTimer(H323TimerQueue, m_hCallEstablishmentTimer, NULL);
|
|
m_hCallEstablishmentTimer = NULL;
|
|
}
|
|
|
|
if( m_hCallDivertOnNATimer )
|
|
{
|
|
DeleteTimerQueueTimer(H323TimerQueue, m_hCallDivertOnNATimer, NULL);
|
|
m_hCallDivertOnNATimer = NULL;
|
|
}
|
|
|
|
*fDelete = FALSE;
|
|
if( m_IoRefCount == 0 )
|
|
{
|
|
*fDelete = TRUE;
|
|
}
|
|
|
|
m_dwStateMachine = Q931_CALL_STATE_NONE;
|
|
if( m_callSocket != INVALID_SOCKET )
|
|
{
|
|
if(shutdown( m_callSocket, SD_BOTH ) == SOCKET_ERROR)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "couldn't shutdown the socket:%d, %p.",
|
|
WSAGetLastError(), this ));
|
|
}
|
|
|
|
closesocket( m_callSocket );
|
|
m_callSocket = INVALID_SOCKET;
|
|
}
|
|
|
|
m_pwszDisplay = NULL;
|
|
|
|
FreeVendorInfo( &m_peerVendorInfo );
|
|
|
|
if( m_peerNonStandardData.sData.pOctetString )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting nonstd:%p.",this ));
|
|
delete m_peerNonStandardData.sData.pOctetString;
|
|
m_peerNonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting xtraalias:%p.",this ));
|
|
FreeAliasNames( m_pPeerExtraAliasNames );
|
|
m_pPeerExtraAliasNames = NULL;
|
|
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting display:%p.",this ));
|
|
if( m_pPeerDisplay )
|
|
{
|
|
delete m_pPeerDisplay;
|
|
m_pPeerDisplay = NULL;
|
|
}
|
|
|
|
if( m_CallData.pOctetString != NULL )
|
|
{
|
|
delete m_CallData.pOctetString;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting hdconf:%p.",this ));
|
|
// delete conference
|
|
if( m_hdConf != NULL )
|
|
{
|
|
g_pH323Line -> GetH323ConfTable() -> Remove( m_hdConf );
|
|
delete m_hdConf;
|
|
m_hdConf = NULL;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting preparetoans:%p.",this ));
|
|
if( m_prepareToAnswerMsgData.pbBuffer )
|
|
{
|
|
delete m_prepareToAnswerMsgData.pbBuffer;
|
|
}
|
|
|
|
ZeroMemory( (PVOID)&m_prepareToAnswerMsgData, sizeof(BUFFERDESCR) );
|
|
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting drq timer:%p.",this ));
|
|
//ras related data structures
|
|
if( m_hDRQTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hDRQTimer, NULL );
|
|
m_hDRQTimer = NULL;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "deleting arq timer:%p.",this ));
|
|
if( m_hARQTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hARQTimer, NULL );
|
|
m_hARQTimer = NULL;
|
|
}
|
|
|
|
if( m_pPeerFastStart != NULL )
|
|
{
|
|
FreeFastStart( m_pPeerFastStart );
|
|
m_pPeerFastStart = NULL;
|
|
}
|
|
|
|
if( m_pFastStart != NULL )
|
|
{
|
|
FreeFastStart( m_pFastStart );
|
|
m_pFastStart = NULL;
|
|
}
|
|
|
|
if( m_pARQExpireContext != NULL )
|
|
{
|
|
delete m_pARQExpireContext;
|
|
m_pARQExpireContext = NULL;
|
|
}
|
|
|
|
if( m_pDRQExpireContext != NULL )
|
|
{
|
|
delete m_pDRQExpireContext;
|
|
m_pDRQExpireContext = NULL;
|
|
}
|
|
|
|
FreeCallForwardData();
|
|
|
|
g_pH323Line -> RemoveCallFromTable (m_hdCall);
|
|
|
|
m_dwFlags |= CALLOBJECT_SHUTDOWN;
|
|
|
|
Unlock();
|
|
g_pH323Line -> UnlockCallTable();
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "Shutdown exited:%p.",this ));
|
|
return;
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::FreeCallForwardData()
|
|
{
|
|
if( m_pCallReroutingInfo )
|
|
{
|
|
FreeCallReroutingInfo();
|
|
}
|
|
|
|
if( m_hCheckRestrictionTimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCheckRestrictionTimer,
|
|
NULL );
|
|
m_hCheckRestrictionTimer = NULL;
|
|
}
|
|
|
|
if( m_hCallReroutingTimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCallReroutingTimer, NULL );
|
|
m_hCallReroutingTimer = NULL;
|
|
}
|
|
|
|
if( m_hCTIdentifyTimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCTIdentifyTimer, NULL );
|
|
m_hCTIdentifyTimer = NULL;
|
|
}
|
|
|
|
if( m_hCTIdentifyRRTimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCTIdentifyRRTimer, NULL );
|
|
m_hCTIdentifyRRTimer = NULL;
|
|
}
|
|
|
|
if( m_hCTInitiateTimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCTInitiateTimer, NULL );
|
|
m_hCTInitiateTimer = NULL;
|
|
}
|
|
|
|
if( m_pTransferedToAlias )
|
|
{
|
|
FreeAliasNames( m_pTransferedToAlias );
|
|
m_pTransferedToAlias = NULL;
|
|
}
|
|
|
|
if( m_dwCallType & CALLTYPE_TRANSFERED2_CONSULT )
|
|
{
|
|
g_pH323Line -> RemoveFromCTCallIdentityTable( m_hdCall );
|
|
}
|
|
|
|
if( m_H450ASNCoderInfo.pEncInfo )
|
|
{
|
|
TermH450ASNCoder();
|
|
}
|
|
|
|
if( m_pCallForwardParams )
|
|
{
|
|
FreeCallForwardParams( m_pCallForwardParams );
|
|
m_pCallForwardParams = NULL;
|
|
}
|
|
|
|
if( m_pForwardAddress )
|
|
{
|
|
FreeForwardAddress( m_pForwardAddress );
|
|
m_pForwardAddress = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::ResolveCallerAddress(void)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resolves caller address from callee address.
|
|
!!must be always called in a lock.
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT nStatus;
|
|
SOCKET hCtrlSocket = INVALID_SOCKET;
|
|
SOCKADDR CalleeSockAddr;
|
|
SOCKADDR CallerSockAddr;
|
|
DWORD dwNumBytesReturned = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveCallerAddress entered:%p.",this ));
|
|
|
|
// allocate control socket
|
|
hCtrlSocket = WSASocket(
|
|
AF_INET, // af
|
|
SOCK_DGRAM, // type
|
|
IPPROTO_IP, // protocol
|
|
NULL, // lpProtocolInfo
|
|
0, // g
|
|
WSA_FLAG_OVERLAPPED // dwFlags
|
|
);
|
|
|
|
// validate control socket
|
|
if (hCtrlSocket == INVALID_SOCKET)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error %d creating control socket.", WSAGetLastError() ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// initialize ioctl parameters
|
|
memset( (PVOID)&CalleeSockAddr,0,sizeof(SOCKADDR));
|
|
memset( (PVOID)&CallerSockAddr,0,sizeof(SOCKADDR));
|
|
|
|
// initialize address family
|
|
CalleeSockAddr.sa_family = AF_INET;
|
|
|
|
// transfer callee information
|
|
((SOCKADDR_IN*)&CalleeSockAddr)->sin_addr.s_addr =
|
|
htonl(m_CalleeAddr.Addr.IP_Binary.dwAddr);
|
|
|
|
// query stack
|
|
nStatus = WSAIoctl(
|
|
hCtrlSocket,
|
|
SIO_ROUTING_INTERFACE_QUERY,
|
|
&CalleeSockAddr,
|
|
sizeof(SOCKADDR),
|
|
&CallerSockAddr,
|
|
sizeof(SOCKADDR),
|
|
&dwNumBytesReturned,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
// release handle
|
|
closesocket(hCtrlSocket);
|
|
|
|
// validate return code
|
|
if (nStatus == SOCKET_ERROR)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error 0x%08lx calling SIO_ROUTING_INTERFACE_QUERY.",
|
|
WSAGetLastError() ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// save interface address of best route
|
|
m_CallerAddr.nAddrType = H323_IP_BINARY;
|
|
m_CallerAddr.Addr.IP_Binary.dwAddr =
|
|
ntohl(((SOCKADDR_IN*)&CallerSockAddr)->sin_addr.s_addr);
|
|
m_CallerAddr.Addr.IP_Binary.wPort =
|
|
LOWORD(g_RegistrySettings.dwQ931ListenPort);
|
|
m_CallerAddr.bMulticast =
|
|
IN_MULTICAST(m_CallerAddr.Addr.IP_Binary.dwAddr);
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"caller address resolved to %s.",
|
|
H323AddrToString(((SOCKADDR_IN*)&CallerSockAddr)->sin_addr.s_addr) ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveCallerAddress exited:%p.",this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::ResolveE164Address(
|
|
IN LPCWSTR pwszDialableAddr
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resolves E.164 address ("4259367111").
|
|
!!must be always called in a lock.
|
|
|
|
Arguments:
|
|
|
|
pwszDialableAddr - Specifies a pointer to the dialable address specified
|
|
by the TAPI application.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR wszAddr[H323_MAXDESTNAMELEN+1];
|
|
DWORD dwE164AddrSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveE164Address entered:%p.",this ));
|
|
|
|
// make sure pstn gateway has been specified
|
|
if ((g_RegistrySettings.fIsGatewayEnabled == FALSE) ||
|
|
(g_RegistrySettings.gatewayAddr.nAddrType == 0))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"pstn gateway not specified."
|
|
));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// save gateway address as callee address
|
|
m_CalleeAddr = g_RegistrySettings.gatewayAddr;
|
|
|
|
dwE164AddrSize = ValidateE164Address( pwszDialableAddr, wszAddr );
|
|
if( dwE164AddrSize == 0 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"invlid e164 callee alias ."));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"callee alias resolved to E.164 number." ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveE164Address exited:%p.",this ));
|
|
|
|
//determine caller address
|
|
return ResolveCallerAddress();
|
|
}
|
|
|
|
|
|
DWORD
|
|
ValidateE164Address(
|
|
LPCWSTR pwszDialableAddr,
|
|
WCHAR* wszAddr
|
|
)
|
|
{
|
|
DWORD dwE164AddrSize = 0;
|
|
WCHAR * pwszValidE164Chars;
|
|
WCHAR wszValidE164Chars[] = { H323_ALIAS_H323_PHONE_CHARS L"\0" };
|
|
|
|
// process until termination char
|
|
while (*pwszDialableAddr != L'\0')
|
|
{
|
|
// reset pointer to valid characters
|
|
pwszValidE164Chars = wszValidE164Chars;
|
|
|
|
// process until termination char
|
|
while (*pwszValidE164Chars != L'\0')
|
|
{
|
|
// see if valid E.164 character specified
|
|
if (*pwszDialableAddr == *pwszValidE164Chars)
|
|
{
|
|
// save valid character in temp buffer
|
|
wszAddr[dwE164AddrSize++] = *pwszDialableAddr;
|
|
|
|
break;
|
|
}
|
|
|
|
// next valid char
|
|
++pwszValidE164Chars;
|
|
}
|
|
|
|
// next input char
|
|
++pwszDialableAddr;
|
|
}
|
|
|
|
// terminate string
|
|
wszAddr[dwE164AddrSize++] = L'\0';
|
|
|
|
// validate string
|
|
if (dwE164AddrSize == 0)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"no valid E.164 characters in string." ));
|
|
}
|
|
|
|
return dwE164AddrSize;
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resolves IP address ("172.31.255.231") or DNS entry ("NIKHILB1").
|
|
!!must be always called in a lock.
|
|
|
|
Arguments:
|
|
|
|
pszDialableAddr - Specifies a pointer to the dialable address specified
|
|
by the TAPI application.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
CH323Call::ResolveIPAddress(
|
|
IN LPSTR pszDialableAddr
|
|
)
|
|
{
|
|
DWORD dwIPAddr;
|
|
struct hostent* pHost;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveIPAddress entered:%p.",this ));
|
|
|
|
// attempt to convert ip address
|
|
dwIPAddr = inet_addr(pszDialableAddr);
|
|
|
|
// see if address converted
|
|
if( dwIPAddr == INADDR_NONE )
|
|
{
|
|
// attempt to lookup hostname
|
|
pHost = gethostbyname(pszDialableAddr);
|
|
|
|
// validate pointer
|
|
if( pHost != NULL )
|
|
{
|
|
// retrieve host address from structure
|
|
dwIPAddr = *(unsigned long *)pHost->h_addr;
|
|
}
|
|
}
|
|
|
|
// see if address converted
|
|
if( dwIPAddr == INADDR_NONE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error 0x%08lx resolving IP address.",
|
|
WSAGetLastError() ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// save converted address
|
|
m_CalleeAddr.nAddrType = H323_IP_BINARY;
|
|
m_CalleeAddr.Addr.IP_Binary.dwAddr = ntohl(dwIPAddr);
|
|
m_CalleeAddr.Addr.IP_Binary.wPort =
|
|
LOWORD(g_RegistrySettings.dwQ931ListenPort);
|
|
m_CalleeAddr.bMulticast =
|
|
IN_MULTICAST(m_CalleeAddr.Addr.IP_Binary.dwAddr);
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"callee address resolved to %s:%d.",
|
|
H323AddrToString(dwIPAddr),
|
|
m_CalleeAddr.Addr.IP_Binary.wPort ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveIPAddress exited:%p.",this ));
|
|
|
|
// determine caller address
|
|
return ResolveCallerAddress();
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::ResolveEmailAddress(
|
|
IN LPCWSTR pwszDialableAddr,
|
|
IN LPSTR pszUser,
|
|
IN LPSTR pszDomain
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resolves e-mail address ("nikhilb@microsoft.com").
|
|
!!must be always called in a lock.
|
|
|
|
Arguments:
|
|
|
|
pwszDialableAddr - Specifies a pointer to the dialable address specified
|
|
by the TAPI application.
|
|
|
|
pszUser - Specifies a pointer to the user component of e-mail name.
|
|
|
|
pszDomain - Specified a pointer to the domain component of e-mail name.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwAddrSize;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveEmailAddress entered:%p.",this ));
|
|
|
|
// size destination address string
|
|
dwAddrSize = wcslen(pwszDialableAddr) + 1;
|
|
|
|
// attempt to resolve domain locally
|
|
if( ResolveIPAddress( pszDomain) )
|
|
{
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
// make sure proxy has been specified
|
|
if( (g_RegistrySettings.fIsProxyEnabled == FALSE) ||
|
|
(g_RegistrySettings.proxyAddr.nAddrType == 0) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "proxy not specified." ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// save proxy address as callee address
|
|
m_CalleeAddr = g_RegistrySettings.proxyAddr;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"callee alias resolved to H.323 alias."));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveEmailAddress exited:%p.",this ));
|
|
|
|
// determine caller address
|
|
return ResolveCallerAddress();
|
|
}
|
|
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Resolves remote address and determines the correct local address
|
|
to use in order to reach remote address.
|
|
!!must be always called in a lock.
|
|
|
|
Arguments:
|
|
|
|
pwszDialableAddr - Specifies a pointer to the dialable address specified
|
|
by the TAPI application.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
CH323Call::ResolveAddress(
|
|
IN LPCWSTR pwszDialableAddr
|
|
)
|
|
{
|
|
CHAR szDelimiters[] = "@ \t\n";
|
|
CHAR szAddr[H323_MAXDESTNAMELEN+1];
|
|
LPSTR pszUser = NULL;
|
|
LPSTR pszDomain = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveAddress entered:%p.",this ));
|
|
|
|
// validate pointerr
|
|
if (pwszDialableAddr == NULL)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "null destination address." ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"resolving %s %S.",
|
|
H323AddressTypeToString( m_dwAddressType),
|
|
pwszDialableAddr ));
|
|
|
|
// check whether phone number has been specified
|
|
if( m_dwAddressType == LINEADDRESSTYPE_PHONENUMBER )
|
|
{
|
|
// need to direct call to pstn gateway
|
|
return ResolveE164Address( pwszDialableAddr);
|
|
}
|
|
|
|
// convert address from unicode
|
|
if (WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
pwszDialableAddr,
|
|
-1,
|
|
szAddr,
|
|
sizeof(szAddr),
|
|
NULL,
|
|
NULL
|
|
) == 0)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not convert address from unicode." ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// parse user name
|
|
pszUser = strtok(szAddr, szDelimiters);
|
|
|
|
// parse domain name
|
|
pszDomain = strtok(NULL, szDelimiters);
|
|
|
|
// validate pointer
|
|
if (pszUser == NULL)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not parse destination address." ));
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// validate pointer
|
|
if (pszDomain == NULL)
|
|
{
|
|
// switch pointers
|
|
pszDomain = pszUser;
|
|
|
|
// re-initialize
|
|
pszUser = NULL;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"resolving user %s domain %s.",
|
|
pszUser,
|
|
pszDomain
|
|
));
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ResolveAddress exited:%p.",this ));
|
|
|
|
// process e-mail and domain names
|
|
return ResolveEmailAddress(
|
|
pwszDialableAddr,
|
|
pszUser,
|
|
pszDomain
|
|
);
|
|
}
|
|
|
|
|
|
BOOL
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate optional call parameters specified by user.
|
|
|
|
!!no need to call in a lock because not added to the call table yet
|
|
|
|
Arguments:
|
|
|
|
pCallParams - Pointer to specified call parameters to be
|
|
validated.
|
|
|
|
pwszDialableAddr - Pointer to the dialable address specified
|
|
by the TAPI application.
|
|
|
|
pdwStatus - Pointer to DWORD containing error code if this
|
|
routine fails for any reason.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
CH323Call::ValidateCallParams(
|
|
IN LPLINECALLPARAMS pCallParams,
|
|
IN LPCWSTR pwszDialableAddr,
|
|
IN PDWORD pdwStatus
|
|
)
|
|
{
|
|
DWORD dwMediaModes = H323_LINE_DEFMEDIAMODES;
|
|
DWORD dwAddrSize;
|
|
WCHAR wszAddr[H323_MAXDESTNAMELEN+1];
|
|
|
|
PH323_ALIASNAMES pAliasList;
|
|
WCHAR* wszMachineName;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "ValidateCallParams entered:%p.", this ));
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "clearing unknown media mode." ));
|
|
|
|
// validate pointer
|
|
if( (pCallParams == NULL) || (pwszDialableAddr == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// retrieve media modes specified
|
|
dwMediaModes = pCallParams->dwMediaMode;
|
|
|
|
// retrieve address type specified
|
|
m_dwAddressType = pCallParams->dwAddressType;
|
|
|
|
// see if we support call parameters
|
|
if( pCallParams->dwCallParamFlags != 0 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"do not support call parameters 0x%08lx.",
|
|
pCallParams->dwCallParamFlags ));
|
|
|
|
// do not support param flags
|
|
*pdwStatus = LINEERR_INVALCALLPARAMS;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// see if unknown bit is specified
|
|
if( dwMediaModes & LINEMEDIAMODE_UNKNOWN )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"clearing unknown media mode." ));
|
|
|
|
// clear unknown bit from modes
|
|
dwMediaModes &= ~LINEMEDIAMODE_UNKNOWN;
|
|
}
|
|
|
|
// see if both audio bits are specified
|
|
if( (dwMediaModes & LINEMEDIAMODE_AUTOMATEDVOICE) &&
|
|
(dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"clearing automated voice media mode." ));
|
|
|
|
// clear extra audio bit from modes
|
|
dwMediaModes &= ~LINEMEDIAMODE_INTERACTIVEVOICE;
|
|
}
|
|
|
|
// see if we support media modes specified
|
|
if( dwMediaModes & ~H323_LINE_MEDIAMODES )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"do not support media modes 0x%08lx.",
|
|
pCallParams->dwMediaMode ));
|
|
|
|
// do not support media mode
|
|
*pdwStatus = LINEERR_INVALMEDIAMODE;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// see if we support bearer modes
|
|
if( pCallParams->dwBearerMode & ~H323_LINE_BEARERMODES )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"do not support bearer mode 0x%08lx.",
|
|
pCallParams->dwBearerMode ));
|
|
|
|
// do not support bearer mode
|
|
*pdwStatus = LINEERR_INVALBEARERMODE;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// see if we support address modes
|
|
if( pCallParams->dwAddressMode & ~H323_LINE_ADDRESSMODES )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"do not support address mode 0x%08lx.",
|
|
pCallParams->dwAddressMode ));
|
|
|
|
// do not support address mode
|
|
*pdwStatus = LINEERR_INVALADDRESSMODE;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// validate address id specified
|
|
if (pCallParams->dwAddressID != 0 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "address id 0x%08lx invalid.",
|
|
pCallParams->dwAddressID ));
|
|
|
|
// invalid address id
|
|
*pdwStatus = LINEERR_INVALADDRESSID;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// validate destination address type specified
|
|
if( m_dwAddressType & ~H323_LINE_ADDRESSTYPES )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "address type 0x%08lx invalid.",
|
|
pCallParams->dwAddressType ));
|
|
|
|
// invalid address type
|
|
*pdwStatus = LINEERR_INVALADDRESSTYPE;
|
|
|
|
//failure
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_dwAddressType == LINEADDRESSTYPE_PHONENUMBER )
|
|
{
|
|
dwAddrSize = ValidateE164Address( pwszDialableAddr, wszAddr );
|
|
|
|
//add the callee alias
|
|
if( dwAddrSize==0 )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"invlid e164 callee alias ."));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( (dwAddrSize > MAX_E164_ADDR_LEN) || (dwAddrSize == 0) )
|
|
return FALSE;
|
|
|
|
if(!AddAliasItem( m_pCalleeAliasNames,
|
|
(BYTE*)wszAddr,
|
|
dwAddrSize * sizeof(WCHAR),
|
|
e164_chosen ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate for callee alias ."));
|
|
// invalid destination addr
|
|
*pdwStatus = LINEERR_INVALADDRESS;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "callee alias added:%S.", wszAddr ));
|
|
}
|
|
else
|
|
{
|
|
dwAddrSize = (wcslen(pwszDialableAddr)+1);
|
|
|
|
if( (dwAddrSize > MAX_H323_ADDR_LEN) || (dwAddrSize == 0) )
|
|
return FALSE;
|
|
|
|
if(!AddAliasItem( m_pCalleeAliasNames,
|
|
(BYTE*)pwszDialableAddr,
|
|
dwAddrSize * sizeof(WCHAR),
|
|
h323_ID_chosen ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate for callee alias ."));
|
|
// invalid destination addr
|
|
*pdwStatus = LINEERR_INVALADDRESS;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "callee alias added:%S.", pwszDialableAddr ));
|
|
}
|
|
|
|
// see if callee alias specified
|
|
if( pCallParams->dwCalledPartySize > 0 )
|
|
{
|
|
//avoid duplicate aliases
|
|
dwAddrSize *= sizeof(WCHAR);
|
|
|
|
if( ( (m_dwAddressType != LINEADDRESSTYPE_PHONENUMBER) ||
|
|
(memcmp(
|
|
(PVOID)((BYTE*)pCallParams + pCallParams->dwCalledPartyOffset),
|
|
wszAddr,
|
|
pCallParams->dwCalledPartySize ) != 0 )
|
|
) &&
|
|
( memcmp(
|
|
(PVOID)((BYTE*)pCallParams + pCallParams->dwCalledPartyOffset),
|
|
pwszDialableAddr,
|
|
pCallParams->dwCalledPartySize ) != 0
|
|
)
|
|
)
|
|
{
|
|
// allocate memory for callee string
|
|
if( !AddAliasItem( m_pCalleeAliasNames,
|
|
(BYTE*)pCallParams + pCallParams->dwCalledPartyOffset,
|
|
pCallParams->dwCalledPartySize,
|
|
(m_dwAddressType != LINEADDRESSTYPE_PHONENUMBER)?
|
|
h323_ID_chosen : e164_chosen) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate caller name." ));
|
|
|
|
// invalid address id
|
|
*pdwStatus = LINEERR_NOMEM;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "callee alias added:%S.",
|
|
((BYTE*)pCallParams + pCallParams->dwCalledPartyOffset) ));
|
|
}
|
|
}
|
|
|
|
// see if caller name specified
|
|
if( pCallParams->dwCallingPartyIDSize > 0 )
|
|
{
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
// allocate memory for callee string
|
|
if(!AddAliasItem( m_pCallerAliasNames,
|
|
(BYTE*)pCallParams + pCallParams->dwCallingPartyIDOffset,
|
|
pCallParams->dwCallingPartyIDSize,
|
|
h323_ID_chosen ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate caller name." ));
|
|
|
|
// invalid address id
|
|
*pdwStatus = LINEERR_NOMEM;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
else if( RasIsRegistered() )
|
|
{
|
|
//ARQ message must have a caller alias
|
|
pAliasList = RASGetRegisteredAliasList();
|
|
wszMachineName = pAliasList -> pItems[0].pData;
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
//set the value for m_pCallerAliasNames
|
|
if( !AddAliasItem( m_pCallerAliasNames,
|
|
(BYTE*)(wszMachineName),
|
|
sizeof(WCHAR) * (wcslen(wszMachineName) + 1 ),
|
|
pAliasList -> pItems[0].wType ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not allocate caller name." ));
|
|
|
|
// invalid address id
|
|
*pdwStatus = LINEERR_NOMEM;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
|
|
// check for user user information
|
|
if( pCallParams->dwUserUserInfoSize > 0 )
|
|
{
|
|
// save user user info
|
|
if (AddU2U( U2U_OUTBOUND, pCallParams->dwUserUserInfoSize,
|
|
(LPBYTE)pCallParams + pCallParams->dwUserUserInfoOffset ) == FALSE )
|
|
{
|
|
//no need to free above aloocated memory for m_CalleeAlias and
|
|
//m_CallerAlias
|
|
|
|
// invalid address id
|
|
*pdwStatus = LINEERR_NOMEM;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// save call data buffer.
|
|
if( SetCallData( (LPBYTE)pCallParams + pCallParams->dwCallDataOffset,
|
|
pCallParams->dwCallDataSize ) == FALSE )
|
|
{
|
|
//no need to free above aloocated memory for m_CalleeAlias and
|
|
//m_CallerAlias
|
|
|
|
// invalid address id
|
|
*pdwStatus = LINEERR_NOMEM;
|
|
|
|
// failure
|
|
return FALSE;
|
|
}
|
|
|
|
// clear incoming modes
|
|
m_dwIncomingModes = 0;
|
|
|
|
// outgoing modes will be finalized after H.245 stage
|
|
m_dwOutgoingModes = dwMediaModes | LINEMEDIAMODE_UNKNOWN;
|
|
|
|
// save media modes specified
|
|
m_dwRequestedModes = dwMediaModes;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "ValidateCallParams exited:%p.", this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Associates call object with the specified conference id.
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
PH323_CONFERENCE
|
|
CH323Call::CreateConference (
|
|
IN GUID* pConferenceId OPTIONAL)
|
|
|
|
{
|
|
int iresult;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CreateConference entered:%p.", this ));
|
|
|
|
Lock();
|
|
|
|
_ASSERTE( m_hdConf == NULL );
|
|
|
|
// create conference
|
|
m_hdConf = new H323_CONFERENCE( this );
|
|
|
|
// validate
|
|
if ( m_hdConf == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could no allocate the conference object."));
|
|
|
|
Unlock();
|
|
return NULL;
|
|
}
|
|
|
|
if (pConferenceId)
|
|
{
|
|
m_ConferenceID = *pConferenceId;
|
|
}
|
|
else
|
|
{
|
|
iresult = UuidCreate (&m_ConferenceID);
|
|
|
|
if ((iresult == RPC_S_OK) || (iresult ==RPC_S_UUID_LOCAL_ONLY))
|
|
{
|
|
H323DBG ((DEBUG_LEVEL_INFO, "generated new conference id (GUID)."));
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"failed to generate GUID for conference id: %d.", iresult ));
|
|
ZeroMemory (&m_ConferenceID, sizeof m_ConferenceID);
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CreateConference exited:%p.", this ));
|
|
return m_hdConf;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initiates outbound call to specified destination.
|
|
!!always called in a lock
|
|
|
|
Arguments:
|
|
|
|
none
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
BOOL
|
|
CH323Call::PlaceCall(void)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "PlaceCall entered:%p.", this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// see if user user information specified
|
|
CopyU2UAsNonStandard( U2U_OUTBOUND );
|
|
|
|
if( m_pwszDisplay == NULL )
|
|
{
|
|
// see if caller alias specified
|
|
if( m_pCallerAliasNames && m_pCallerAliasNames -> wCount )
|
|
{
|
|
if((m_pCallerAliasNames ->pItems[0].wType == h323_ID_chosen) ||
|
|
(m_pCallerAliasNames ->pItems[0].wType == e164_chosen) )
|
|
{
|
|
// send caller name as display
|
|
m_pwszDisplay = m_pCallerAliasNames -> pItems[0].pData;
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
}
|
|
|
|
// validate
|
|
if( !SetupCall() )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "Q931 call: failed." ));
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "PlaceCall exited:%p.", this ));
|
|
|
|
// return status
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::DropUserInitiated(
|
|
IN DWORD dwDisconnectMode
|
|
)
|
|
{
|
|
//since this is a user initiated drop, the transfered call should also
|
|
//be dropped for a primary call and vice versa
|
|
if( IsTransferredCall( m_dwCallType ) && m_hdRelatedCall )
|
|
{
|
|
QueueTAPILineRequest(
|
|
TSPI_CLOSE_CALL,
|
|
m_hdRelatedCall,
|
|
NULL,
|
|
dwDisconnectMode,
|
|
m_wCallReference );
|
|
}
|
|
|
|
DropCall(dwDisconnectMode);
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
BOOL
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Hangs up call (if necessary) and changes state to idle.
|
|
|
|
Arguments:
|
|
|
|
dwDisconnectMode - Status code for disconnect.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
CH323Call::DropCall(
|
|
IN DWORD dwDisconnectMode
|
|
)
|
|
{
|
|
PUserToUserLE pU2ULE = NULL;
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "DropCall entered:%p.", this ));
|
|
|
|
if( (m_dwRASCallState == RASCALL_STATE_REGISTERED ) ||
|
|
(m_dwRASCallState == RASCALL_STATE_ARQSENT ) )
|
|
{
|
|
//disengage from the GK
|
|
SendDRQ( forcedDrop_chosen, NOT_RESEND_SEQ_NUM, TRUE );
|
|
}
|
|
|
|
// determine call state
|
|
switch (m_dwCallState)
|
|
{
|
|
case LINECALLSTATE_CONNECTED:
|
|
|
|
// hangup call (this will invoke async indication)
|
|
// validate
|
|
//encode ASN.1 and send Q931release message to the peer
|
|
if(!SendQ931Message( NO_INVOKEID,
|
|
0,
|
|
0,
|
|
RELEASECOMPLMESSAGETYPE,
|
|
NO_H450_APDU ))
|
|
{
|
|
//post a message to the callback thread to shutdown the H323 call
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error hanging up call 0x%08lx.", this ));
|
|
}
|
|
else
|
|
{
|
|
m_dwStateMachine = Q931_RELEASE_SENT;
|
|
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx hung up.", this ));
|
|
}
|
|
|
|
// change call state to disconnected
|
|
ChangeCallState(LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
|
|
|
|
break;
|
|
|
|
case LINECALLSTATE_OFFERING:
|
|
|
|
// see if user user information specified
|
|
CopyU2UAsNonStandard( U2U_OUTBOUND );
|
|
|
|
// reject call
|
|
//encode ASN.1 and send Q931Setup message to the peer
|
|
if( SendQ931Message( NO_INVOKEID,
|
|
0,
|
|
0,
|
|
RELEASECOMPLMESSAGETYPE,
|
|
NO_H450_APDU ))
|
|
{
|
|
m_dwStateMachine = Q931_RELEASE_SENT;
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx rejected.", this ));
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "error reject call 0x%08lx.",this));
|
|
}
|
|
|
|
// change call state to disconnected
|
|
ChangeCallState(LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
|
|
|
|
break;
|
|
|
|
case LINECALLSTATE_RINGBACK:
|
|
case LINECALLSTATE_ACCEPTED:
|
|
|
|
// cancel outbound call
|
|
if( SendQ931Message( NO_INVOKEID,
|
|
0,
|
|
0,
|
|
RELEASECOMPLMESSAGETYPE,
|
|
NO_H450_APDU ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error cancelling call 0x%08lx.", this ));
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error reject call 0x%08lx.", this ));
|
|
}
|
|
|
|
// change call state to disconnected
|
|
ChangeCallState(LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
|
|
|
|
break;
|
|
|
|
case LINECALLSTATE_DIALING:
|
|
|
|
// change call state to disconnected
|
|
ChangeCallState(LINECALLSTATE_DISCONNECTED, dwDisconnectMode);
|
|
|
|
break;
|
|
|
|
case LINECALLSTATE_DISCONNECTED:
|
|
|
|
//
|
|
// disconnected but still need to clean up
|
|
//
|
|
break;
|
|
|
|
case LINECALLSTATE_IDLE:
|
|
|
|
//
|
|
// call object already idle
|
|
//
|
|
|
|
if( (m_dwCallType == CALLTYPE_NORMAL) &&
|
|
(m_dwStateMachine == Q931_SETUP_RECVD) )
|
|
{
|
|
if( SendQ931Message( NO_INVOKEID,
|
|
0,
|
|
0,
|
|
RELEASECOMPLMESSAGETYPE,
|
|
NO_H450_APDU ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error cancelling call 0x%08lx.", this ));
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error reject call 0x%08lx.", this ));
|
|
}
|
|
}
|
|
|
|
DropSupplementaryServicesCalls();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if( ( (m_dwCallType & CALLTYPE_TRANSFEREDDEST) && m_hdRelatedCall ) ||
|
|
( (m_dwCallType & CALLTYPE_TRANSFEREDSRC ) && m_hdRelatedCall ) )
|
|
{
|
|
m_dwCallState = LINECALLSTATE_IDLE;
|
|
}
|
|
else
|
|
{
|
|
// Tell the MSP to stop streaming.
|
|
SendMSPMessage( SP_MSG_CallShutdown, 0, 0, NULL );
|
|
|
|
// change call state to idle
|
|
ChangeCallState( LINECALLSTATE_IDLE, 0 );
|
|
}
|
|
|
|
if( (m_dwCallType & CALLTYPE_TRANSFEREDSRC ) && m_hdRelatedCall )
|
|
{
|
|
//drop the primary call
|
|
if( !QueueTAPILineRequest(
|
|
TSPI_CLOSE_CALL,
|
|
m_hdRelatedCall,
|
|
NULL,
|
|
LINEDISCONNECTMODE_NORMAL,
|
|
NULL ) )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "could not post H323 close event"));
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "DropCall exited:%p.", this ));
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::DropSupplementaryServicesCalls()
|
|
{
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT) ||
|
|
(m_dwCallType & CALLTYPE_DIVERTED_SERVED) ||
|
|
(m_dwCallType & CALLTYPE_DIVERTEDSRC) ||
|
|
(m_dwCallType & CALLTYPE_DIVERTEDSRC_NOROUTING) )
|
|
{
|
|
if( m_dwQ931Flags & Q931_CALL_CONNECTED )
|
|
{
|
|
if( SendQ931Message( NO_INVOKEID,
|
|
0,
|
|
0,
|
|
RELEASECOMPLMESSAGETYPE,
|
|
NO_H450_APDU ))
|
|
{
|
|
m_dwStateMachine = Q931_RELEASE_SENT;
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx rejected.", this ));
|
|
}
|
|
}
|
|
|
|
g_pH323Line->m_fForwardConsultInProgress = FALSE;
|
|
}
|
|
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT) &&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//inform the user about failure of line forward operation
|
|
if( m_dwCallDiversionState != H4503_CHECKRESTRICTION_SUCC )
|
|
{
|
|
(*g_pfnLineEventProc)(
|
|
g_pH323Line->m_htLine,
|
|
(HTAPICALL)NULL,
|
|
(DWORD)LINE_ADDRESSSTATE,
|
|
(DWORD)LINEADDRESSSTATE_FORWARD,
|
|
(DWORD)LINEADDRESSSTATE_FORWARD,
|
|
(DWORD)0
|
|
);
|
|
}
|
|
}
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTEDSRC )
|
|
{
|
|
ChangeCallState( LINECALLSTATE_IDLE, 0 );
|
|
}
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::HandleConnectMessage(
|
|
IN Q931_CONNECT_ASN *pConnectASN
|
|
)
|
|
{
|
|
PH323_CALL pPrimaryCall = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleConnectMessage entered:%p.", this ));
|
|
|
|
if( pConnectASN->fNonStandardDataPresent )
|
|
{
|
|
//add user user info
|
|
if( AddU2UNoAlloc( U2U_INBOUND,
|
|
pConnectASN->nonStandardData.sData.wOctetStringLength,
|
|
pConnectASN->nonStandardData.sData.pOctetString ) == TRUE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"user user info available in CONNECT PDU." ));
|
|
|
|
if( !(m_dwCallType & CALLTYPE_TRANSFEREDSRC) )
|
|
{
|
|
// signal incoming
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_USERUSERINFO, 0, 0 );
|
|
}
|
|
|
|
//don't release the data buffer
|
|
pConnectASN->fNonStandardDataPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"could not save incoming user user info." ));
|
|
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
//get the vendor info
|
|
if( pConnectASN->EndpointType.pVendorInfo )
|
|
{
|
|
FreeVendorInfo( &m_peerVendorInfo );
|
|
|
|
m_peerVendorInfo = pConnectASN->VendorInfo;
|
|
pConnectASN->EndpointType.pVendorInfo = NULL;
|
|
}
|
|
|
|
if( pConnectASN->h245AddrPresent )
|
|
{
|
|
m_peerH245Addr = pConnectASN->h245Addr;
|
|
}
|
|
|
|
//copy the fast start proposal
|
|
if( pConnectASN->fFastStartPresent &&
|
|
(m_dwFastStart!=FAST_START_NOTAVAIL) )
|
|
{
|
|
if( m_pPeerFastStart )
|
|
{
|
|
//we had received fast start params in previous proceeding
|
|
//or alerting message
|
|
FreeFastStart( m_pPeerFastStart );
|
|
}
|
|
|
|
m_pPeerFastStart = pConnectASN->pFastStart;
|
|
m_dwFastStart = FAST_START_AVAIL;
|
|
|
|
//we are keeping a reference to the fast start list so don't release it
|
|
pConnectASN->pFastStart = NULL;
|
|
}
|
|
else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}
|
|
|
|
if( ( (m_dwCallType & CALLTYPE_TRANSFEREDSRC)||
|
|
(m_dwCallType & CALLTYPE_DIVERTEDTRANSFERED) ) && m_hdRelatedCall )
|
|
{
|
|
QueueSuppServiceWorkItem( SWAP_REPLACEMENT_CALL,
|
|
m_hdCall, (ULONG_PTR)m_hdRelatedCall );
|
|
}
|
|
else
|
|
{
|
|
//start H245
|
|
SendMSPStartH245( NULL, NULL );
|
|
|
|
SendMSPMessage( SP_MSG_ConnectComplete, 0, 0, NULL );
|
|
}
|
|
|
|
//If we join MCU we get the conference ID of the conference we
|
|
//joined and not the one that we sent in Setup message.
|
|
if( IsEqualConferenceID( &pConnectASN->ConferenceID ) == FALSE )
|
|
{
|
|
H323DBG ((DEBUG_LEVEL_ERROR,
|
|
"OnReceiveConnect: We received different conference id." ));
|
|
|
|
m_ConferenceID = pConnectASN->ConferenceID;
|
|
}
|
|
|
|
//tell TAPI about state change
|
|
ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
|
|
|
|
FreeConnectASN( pConnectASN );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleConnectMessage exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
FreeConnectASN( pConnectASN );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::HandleAlertingMessage(
|
|
IN Q931_ALERTING_ASN * pAlertingASN
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleAlertingMessage entered:%p.", this ));
|
|
|
|
if( pAlertingASN->fNonStandardDataPresent )
|
|
{
|
|
// add user user info
|
|
if( AddU2UNoAlloc( U2U_INBOUND,
|
|
pAlertingASN->nonStandardData.sData.wOctetStringLength,
|
|
pAlertingASN->nonStandardData.sData.pOctetString ) == TRUE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"user user info available in ALERT PDU." ));
|
|
// signal incoming
|
|
|
|
if( !(m_dwCallType & CALLTYPE_TRANSFEREDSRC) )
|
|
{
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_USERUSERINFO, 0, 0 );
|
|
}
|
|
|
|
//don't release the data buffer
|
|
pAlertingASN->fNonStandardDataPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"could not save incoming user user info." ));
|
|
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( pAlertingASN->fH245AddrPresent )
|
|
{
|
|
m_peerH245Addr = pAlertingASN->h245Addr;
|
|
}
|
|
|
|
if( pAlertingASN->fFastStartPresent &&
|
|
(m_dwFastStart!=FAST_START_NOTAVAIL) )
|
|
{
|
|
if( m_pPeerFastStart )
|
|
{
|
|
//we had received fast start params in previous proceeding
|
|
//or alerting message
|
|
FreeFastStart( m_pPeerFastStart );
|
|
}
|
|
|
|
m_pPeerFastStart = pAlertingASN->pFastStart;
|
|
m_dwFastStart = FAST_START_AVAIL;
|
|
|
|
//we are keeping a reference to the fast start list so don't release it
|
|
pAlertingASN->pFastStart = NULL;
|
|
pAlertingASN->fFastStartPresent = FALSE;
|
|
}
|
|
|
|
//for DIVERTEDSRC, call its ok to tell TAPI about this state
|
|
ChangeCallState( LINECALLSTATE_RINGBACK, 0 );
|
|
|
|
/*if( pAlertingASN->fH245AddrPresent && !(m_dwFlags & H245_START_MSG_SENT) )
|
|
{
|
|
//start early H245
|
|
SendMSPStartH245( NULL, NULL);
|
|
}*/
|
|
|
|
FreeAlertingASN( pAlertingASN );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleAlertingMessage exited:%p.", this ));
|
|
return;
|
|
}
|
|
|
|
|
|
//!!must be always called in a lock
|
|
BOOL
|
|
CH323Call::HandleSetupMessage(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
PH323_ALIASITEM pwszDivertedToAlias = NULL;
|
|
WCHAR * pwszAliasName = NULL;
|
|
WORD wAliasLength = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleSetupMessage entered:%p.", this ));
|
|
|
|
if( m_pCallerAliasNames && (m_pCallerAliasNames -> wCount > 0) )
|
|
{
|
|
pwszAliasName = m_pCallerAliasNames->pItems[0].pData;
|
|
wAliasLength = (m_pCallerAliasNames->pItems[0].wDataLength+1)
|
|
* sizeof(WCHAR);
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
|
|
pwszDivertedToAlias = g_pH323Line->CallToBeDiverted(
|
|
pwszAliasName,
|
|
wAliasLength,
|
|
LINEFORWARDMODE_UNCOND | LINEFORWARDMODE_UNCONDSPECIFIC );
|
|
|
|
if( pwszDivertedToAlias )
|
|
{
|
|
if( !InitiateCallDiversion( pwszDivertedToAlias, DiversionReason_cfu ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//send the proceeding message to the peer if not already sent by the GK
|
|
//SendProceeding();
|
|
|
|
if(RasIsRegistered())
|
|
{
|
|
if( !SendARQ( NOT_RESEND_SEQ_NUM ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//copy the data to be sent in preparetoanswer message
|
|
if( m_prepareToAnswerMsgData.pbBuffer )
|
|
delete m_prepareToAnswerMsgData.pbBuffer;
|
|
ZeroMemory( (PVOID)&m_prepareToAnswerMsgData, sizeof(BUFFERDESCR) );
|
|
|
|
|
|
m_prepareToAnswerMsgData.pbBuffer =
|
|
(BYTE*)new char[pMessage->UserToUser.wUserInfoLen];
|
|
if( m_prepareToAnswerMsgData.pbBuffer == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory( (PVOID)m_prepareToAnswerMsgData.pbBuffer,
|
|
(PVOID)pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen );
|
|
|
|
m_prepareToAnswerMsgData.dwLength = pMessage->UserToUser.wUserInfoLen;
|
|
}
|
|
else
|
|
{
|
|
if( (m_dwCallType & CALLTYPE_TRANSFEREDDEST) && m_hdRelatedCall )
|
|
{
|
|
MSPMessageData* pMSPMessageData = new MSPMessageData;
|
|
if( pMSPMessageData == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pMSPMessageData->hdCall = m_hdRelatedCall;
|
|
pMSPMessageData->messageType = SP_MSG_PrepareToAnswer;
|
|
|
|
pMSPMessageData->pbEncodedBuf =
|
|
new BYTE[pMessage->UserToUser.wUserInfoLen];
|
|
if( pMSPMessageData->pbEncodedBuf == NULL )
|
|
{
|
|
delete pMSPMessageData;
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory( pMSPMessageData->pbEncodedBuf,
|
|
(PVOID)pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen );
|
|
|
|
pMSPMessageData->wLength = pMessage->UserToUser.wUserInfoLen;
|
|
pMSPMessageData->hReplacementCall = m_hdCall;
|
|
|
|
if( !QueueUserWorkItem( SendMSPMessageOnRelatedCall,
|
|
pMSPMessageData, WT_EXECUTEDEFAULT ) )
|
|
{
|
|
delete pMSPMessageData->pbEncodedBuf;
|
|
delete pMSPMessageData;
|
|
return FALSE;
|
|
}
|
|
}
|
|
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 )
|
|
return FALSE;
|
|
|
|
if( IsListEmpty(&m_IncomingU2U) == FALSE )
|
|
{
|
|
// signal incoming
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_USERUSERINFO, 0, 0);
|
|
}
|
|
|
|
ChangeCallState( LINECALLSTATE_OFFERING, 0 );
|
|
|
|
//Send the new call message to the unspecified MSP
|
|
SendMSPMessage( SP_MSG_PrepareToAnswer,
|
|
pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen, NULL );
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleSetupMessage exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCallDiversionFacility(
|
|
PH323_ADDR pAlternateAddress )
|
|
{
|
|
PSTR pszAlias;
|
|
WCHAR pwszAliasName[H323_MAXDESTNAMELEN];
|
|
in_addr addr;
|
|
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
m_pCallReroutingInfo = new CALLREROUTINGINFO;
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
|
|
}
|
|
|
|
m_pCallReroutingInfo->diversionCounter = 1;
|
|
m_pCallReroutingInfo->diversionReason = DiversionReason_cfu;
|
|
|
|
//free any previous divertedTo alias
|
|
if( m_pCallReroutingInfo->divertedToNrAlias )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertedToNrAlias );
|
|
m_pCallReroutingInfo->divertedToNrAlias = NULL;
|
|
}
|
|
|
|
addr.S_un.S_addr = htonl( pAlternateAddress->Addr.IP_Binary.dwAddr );
|
|
pszAlias = inet_ntoa( addr );
|
|
if( pszAlias == NULL )
|
|
return FALSE;
|
|
|
|
m_pCallReroutingInfo->divertedToNrAlias = new H323_ALIASNAMES;
|
|
if( m_pCallReroutingInfo->divertedToNrAlias == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
ZeroMemory( m_pCallReroutingInfo->divertedToNrAlias,
|
|
sizeof(H323_ALIASNAMES) );
|
|
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
pszAlias,
|
|
strlen(pszAlias)+1,
|
|
pwszAliasName,
|
|
H323_MAXDESTNAMELEN
|
|
);
|
|
|
|
if( !AddAliasItem( m_pCallReroutingInfo->divertedToNrAlias,
|
|
pwszAliasName, h323_ID_chosen ) )
|
|
{
|
|
delete m_pCallReroutingInfo->divertedToNrAlias;
|
|
m_pCallReroutingInfo->divertedToNrAlias = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
m_CalleeAddr = *pAlternateAddress;
|
|
|
|
if( m_pCalleeAliasNames && m_pCalleeAliasNames->wCount )
|
|
{
|
|
m_pCallReroutingInfo->divertingNrAlias = new H323_ALIASNAMES;
|
|
|
|
if( m_pCallReroutingInfo->divertingNrAlias != NULL )
|
|
{
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo->divertingNrAlias,
|
|
sizeof(H323_ALIASNAMES) );
|
|
|
|
if( !AddAliasItem( m_pCallReroutingInfo->divertingNrAlias,
|
|
m_pCalleeAliasNames->pItems[0].pData,
|
|
m_pCalleeAliasNames->pItems[0].wType ) )
|
|
{
|
|
delete m_pCallReroutingInfo->divertingNrAlias;
|
|
m_pCallReroutingInfo->divertingNrAlias = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_DIVERTEDSRC;
|
|
m_dwCallDiversionState = H4503_CALLREROUTING_RECVD;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCallDiversionFacility exited:%p.",
|
|
this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCallDiversionFacility(
|
|
PH323_ALIASNAMES pAliasList )
|
|
{
|
|
if( !m_pCallReroutingInfo )
|
|
{
|
|
m_pCallReroutingInfo = new CALLREROUTINGINFO;
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
|
|
}
|
|
|
|
m_pCallReroutingInfo->diversionCounter = 1;
|
|
m_pCallReroutingInfo->diversionReason = DiversionReason_cfu;
|
|
|
|
if( m_pCallReroutingInfo->divertedToNrAlias )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertedToNrAlias );
|
|
m_pCallReroutingInfo->divertedToNrAlias = NULL;
|
|
}
|
|
|
|
m_pCallReroutingInfo->divertedToNrAlias = pAliasList;
|
|
|
|
if( m_pCalleeAliasNames && m_pCalleeAliasNames->wCount )
|
|
{
|
|
m_pCallReroutingInfo->divertingNrAlias = new H323_ALIASNAMES;
|
|
|
|
if( m_pCallReroutingInfo->divertingNrAlias != NULL )
|
|
{
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo->divertingNrAlias,
|
|
sizeof(H323_ALIASNAMES) );
|
|
|
|
if( !AddAliasItem( m_pCallReroutingInfo->divertingNrAlias,
|
|
m_pCalleeAliasNames->pItems[0].pData,
|
|
m_pCalleeAliasNames->pItems[0].wType ) )
|
|
{
|
|
delete m_pCallReroutingInfo->divertingNrAlias;
|
|
m_pCallReroutingInfo->divertingNrAlias = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_DIVERTEDSRC;
|
|
m_dwCallDiversionState = H4503_CALLREROUTING_RECVD;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCallDiversionFacility exited:%p.",
|
|
this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleTransferFacility(
|
|
PH323_ALIASNAMES pAliasList )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleTransferFacility entered:%p.", this ));
|
|
|
|
//argument.callIdentity
|
|
ZeroMemory( (PVOID)m_pCTCallIdentity, sizeof(m_pCTCallIdentity) );
|
|
|
|
//argument.reroutingNumber
|
|
FreeAliasNames( m_pTransferedToAlias );
|
|
m_pTransferedToAlias = pAliasList;
|
|
|
|
m_dwCallType |= CALLTYPE_TRANSFERED_PRIMARY;
|
|
m_dwCallDiversionState = H4502_CTINITIATE_RECV;
|
|
|
|
//queue an event for creating a new call
|
|
if( !QueueSuppServiceWorkItem( TSPI_DIAL_TRNASFEREDCALL, m_hdCall,
|
|
(ULONG_PTR)m_pTransferedToAlias ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "could not post dial transfer event." ));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleTransferFacility entered:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleTransferFacility(
|
|
PH323_ADDR pAlternateAddress )
|
|
{
|
|
PSTR pszAlias;
|
|
WCHAR pwszAliasName[H323_MAXDESTNAMELEN];
|
|
in_addr addr;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleTransferFacility entered:%p.", this ));
|
|
|
|
//argument.callIdentity
|
|
ZeroMemory( (PVOID)m_pCTCallIdentity, sizeof(m_pCTCallIdentity) );
|
|
|
|
//argument.reroutingNumber
|
|
//free any previous divertedTo alias
|
|
FreeAliasNames( m_pTransferedToAlias );
|
|
|
|
addr.S_un.S_addr = htonl( pAlternateAddress->Addr.IP_Binary.dwAddr );
|
|
pszAlias = inet_ntoa( addr );
|
|
|
|
if( pszAlias == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
m_pTransferedToAlias = new H323_ALIASNAMES;
|
|
if( m_pTransferedToAlias == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
ZeroMemory( m_pTransferedToAlias, sizeof(H323_ALIASNAMES) );
|
|
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
pszAlias,
|
|
strlen(pszAlias)+1,
|
|
pwszAliasName,
|
|
H323_MAXDESTNAMELEN
|
|
);
|
|
|
|
if( !AddAliasItem( m_pTransferedToAlias, pwszAliasName, h323_ID_chosen ) )
|
|
{
|
|
delete m_pTransferedToAlias;
|
|
m_pTransferedToAlias = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
m_CalleeAddr = *pAlternateAddress;
|
|
|
|
m_dwCallType |= CALLTYPE_TRANSFERED_PRIMARY;
|
|
m_dwCallDiversionState = H4502_CTINITIATE_RECV;
|
|
|
|
//queue an event for creating a new call
|
|
if( !QueueSuppServiceWorkItem( TSPI_DIAL_TRNASFEREDCALL, m_hdCall,
|
|
(ULONG_PTR)m_pTransferedToAlias ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "could not post dial transfer event." ));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleTransferFacility entered:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::HandleFacilityMessage(
|
|
IN DWORD dwInvokeID,
|
|
IN Q931_FACILITY_ASN * pFacilityASN
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleFacilityMessage entered:%p.", this ));
|
|
|
|
if( pFacilityASN->fNonStandardDataPresent )
|
|
{
|
|
// add user user info
|
|
if( AddU2UNoAlloc( U2U_INBOUND,
|
|
pFacilityASN->nonStandardData.sData.wOctetStringLength,
|
|
pFacilityASN->nonStandardData.sData.pOctetString ) == TRUE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"user user info available in ALERT PDU." ));
|
|
// signal incoming
|
|
|
|
if( !(m_dwCallType & CALLTYPE_TRANSFEREDSRC) )
|
|
{
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_USERUSERINFO, 0, 0);
|
|
}
|
|
|
|
//don't release the data buffer
|
|
pFacilityASN->fNonStandardDataPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"could not save incoming user user info." ));
|
|
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( (pFacilityASN->bReason == callForwarded_chosen) ||
|
|
(pFacilityASN->bReason == FacilityReason_routeCallToGatekeeper_chosen) ||
|
|
(pFacilityASN->bReason == routeCallToMC_chosen) )
|
|
{
|
|
if( pFacilityASN->pAlternativeAliasList != NULL )
|
|
{
|
|
if( m_dwCallState == LINECALLSTATE_CONNECTED )
|
|
{
|
|
HandleTransferFacility( pFacilityASN->pAlternativeAliasList );
|
|
|
|
//don't free the alias list
|
|
pFacilityASN->pAlternativeAliasList = NULL;
|
|
}
|
|
else if( m_dwCallState != LINECALLSTATE_DISCONNECTED )
|
|
{
|
|
//redirect the call if not yet connected
|
|
if( HandleCallDiversionFacility(
|
|
pFacilityASN->pAlternativeAliasList ) )
|
|
{
|
|
OnCallReroutingReceive( NO_INVOKEID );
|
|
|
|
//don't free the alias list
|
|
pFacilityASN->pAlternativeAliasList = NULL;
|
|
}
|
|
}
|
|
}
|
|
else if( pFacilityASN->fAlternativeAddressPresent )
|
|
{
|
|
if( m_dwCallState == LINECALLSTATE_CONNECTED )
|
|
{
|
|
HandleTransferFacility( &pFacilityASN->AlternativeAddr );
|
|
}
|
|
else if( m_dwCallState != LINECALLSTATE_DISCONNECTED )
|
|
{
|
|
//redirect the call if not yet connected
|
|
if( HandleCallDiversionFacility( &pFacilityASN->AlternativeAddr ) )
|
|
{
|
|
OnCallReroutingReceive( NO_INVOKEID );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Handle H.450 APDU
|
|
if( pFacilityASN->dwH450APDUType == DIVERTINGLEGINFO1_OPCODE )
|
|
{
|
|
if( m_dwOrigin != LINECALLORIGIN_OUTBOUND )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( m_pCallReroutingInfo->fPresentAllow )
|
|
{
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_REDIRECTINGID, 0, 0);
|
|
}
|
|
}
|
|
else if( pFacilityASN->dwH450APDUType == CALLREROUTING_OPCODE )
|
|
{
|
|
OnCallReroutingReceive( dwInvokeID );
|
|
}
|
|
else if( pFacilityASN->dwH450APDUType == REMOTEHOLD_OPCODE )
|
|
{
|
|
if( m_fRemoteHoldInitiated )
|
|
{
|
|
//Hold();
|
|
m_fRemoteHoldInitiated = FALSE;
|
|
}
|
|
}
|
|
else if( pFacilityASN->dwH450APDUType == REMOTERETRIEVE_OPCODE )
|
|
{
|
|
if( m_fRemoteRetrieveInitiated )
|
|
{
|
|
//UnHold();
|
|
m_fRemoteRetrieveInitiated = FALSE;
|
|
}
|
|
}
|
|
else if( pFacilityASN->fH245AddrPresent )
|
|
{
|
|
m_peerH245Addr = pFacilityASN->h245Addr;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "H245 address received in facility." ));
|
|
|
|
//If Q931 call already connected then send another StartH245.
|
|
if( m_dwCallState == LINECALLSTATE_CONNECTED )
|
|
{
|
|
SendMSPStartH245( NULL, NULL );
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleFacilityMessage exited:%p.", this ));
|
|
return;
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::SetNewCallInfo(
|
|
HANDLE hConnWait,
|
|
HANDLE hWSAEvent,
|
|
DWORD dwState
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "SetNewCallInfo entered." ));
|
|
|
|
Lock();
|
|
|
|
m_hTransportWait = hConnWait;
|
|
m_hTransport = hWSAEvent;
|
|
SetQ931CallState( dwState );
|
|
|
|
Unlock();
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "SetNewCallInfo exited." ));
|
|
}
|
|
|
|
|
|
//!!no need to call in a lock
|
|
void
|
|
CH323Call::SetQ931CallState( DWORD dwState )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "SetQ931CallState entered." ));
|
|
|
|
//turn off the current state
|
|
m_dwQ931Flags &= ~(Q931_CALL_CONNECTING |
|
|
Q931_CALL_CONNECTED |
|
|
Q931_CALL_DISCONNECTED );
|
|
|
|
//set the new state
|
|
m_dwQ931Flags |= dwState;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "SetQ931CallState exited." ));
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::DialCall()
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "DialCall entered:%p.", this ));
|
|
Lock();
|
|
|
|
ChangeCallState( LINECALLSTATE_DIALING, 0);
|
|
|
|
if( RasIsRegistered() )
|
|
{
|
|
if( !SendARQ( NOT_RESEND_SEQ_NUM ) )
|
|
{
|
|
//If a forward consult call then enable theforwarding anyway.
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//Success of forwarding
|
|
EnableCallForwarding();
|
|
}
|
|
|
|
CloseCall( 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !PlaceCall() )
|
|
{
|
|
//If a forward consult call then enable theforwarding anyway.
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//Success of forwarding
|
|
EnableCallForwarding();
|
|
}
|
|
|
|
CloseCall( LINEDISCONNECTMODE_UNREACHABLE );
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "DialCall exited:%p.", this ));
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::MakeCall()
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "MakeCall entered:%p.", this ));
|
|
|
|
ChangeCallState( LINECALLSTATE_DIALING, 0 );
|
|
|
|
// resolve dialable into local and remote address
|
|
if( !RasIsRegistered() &&
|
|
!ResolveAddress( GetDialableAddress() ) )
|
|
{
|
|
CloseCall( LINEDISCONNECTMODE_BADADDRESS );
|
|
}
|
|
else
|
|
{
|
|
if( RasIsRegistered() )
|
|
{
|
|
if( !SendARQ( NOT_RESEND_SEQ_NUM ) )
|
|
{
|
|
//If a forward consult call then enable theforwarding anyway.
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//Success of forwarding
|
|
EnableCallForwarding();
|
|
}
|
|
|
|
CloseCall( 0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( !PlaceCall() )
|
|
{
|
|
//If a forward consult call then enable theforwarding anyway.
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//Success of forwarding
|
|
EnableCallForwarding();
|
|
}
|
|
|
|
CloseCall( LINEDISCONNECTMODE_UNREACHABLE );
|
|
}
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "MakeCall exited:%p.", this ));
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::HandleProceedingMessage(
|
|
IN Q931_ALERTING_ASN * pProceedingASN
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleProceedingMessage entered:%p.", this ));
|
|
|
|
if( pProceedingASN->fNonStandardDataPresent )
|
|
{
|
|
// add user user info
|
|
if( AddU2UNoAlloc( U2U_INBOUND,
|
|
pProceedingASN->nonStandardData.sData.wOctetStringLength,
|
|
pProceedingASN->nonStandardData.sData.pOctetString ) == TRUE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"user user info available in ALERT PDU." ));
|
|
// signal incoming
|
|
if( !(m_dwCallType & CALLTYPE_TRANSFEREDSRC) )
|
|
{
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_USERUSERINFO, 0, 0);
|
|
}
|
|
|
|
//don't release the data buffer
|
|
pProceedingASN->fNonStandardDataPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"could not save incoming user user info." ));
|
|
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( pProceedingASN->fH245AddrPresent )
|
|
{
|
|
m_peerH245Addr = pProceedingASN->h245Addr;
|
|
}
|
|
|
|
if( pProceedingASN->fFastStartPresent &&
|
|
(m_dwFastStart!=FAST_START_NOTAVAIL) )
|
|
{
|
|
if( m_pPeerFastStart )
|
|
{
|
|
//we had received fast start params in previous proceeding
|
|
//or alerting message
|
|
FreeFastStart( m_pPeerFastStart );
|
|
}
|
|
|
|
m_pPeerFastStart = pProceedingASN->pFastStart;
|
|
m_dwFastStart = FAST_START_AVAIL;
|
|
|
|
//we are keeping a reference to the fast start list so don't release it
|
|
pProceedingASN->pFastStart = NULL;
|
|
pProceedingASN->fFastStartPresent = FALSE;
|
|
}
|
|
|
|
/*
|
|
if( pProceedingASN->fH245AddrPresent && !(m_dwFlags & H245_START_MSG_SENT) )
|
|
{
|
|
//start early H245
|
|
SendMSPStartH245( NULL, NULL );
|
|
}*/
|
|
FreeProceedingASN( pProceedingASN );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleProceedingMessage exited:%p.", this ));
|
|
return;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::HandleReleaseMessage(
|
|
IN Q931_RELEASE_COMPLETE_ASN *pReleaseASN
|
|
)
|
|
{
|
|
DWORD dwDisconnectMode = LINEDISCONNECTMODE_NORMAL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReleaseMessage entered:%p.", this ));
|
|
|
|
if( (m_dwCallType & CALLTYPE_TRANSFERED_PRIMARY) &&
|
|
(m_hdRelatedCall != NULL) )
|
|
{
|
|
return QueueSuppServiceWorkItem( DROP_PRIMARY_CALL,
|
|
m_hdRelatedCall, (ULONG_PTR)m_hdCall );
|
|
}
|
|
|
|
//change the state to disconnected before callong drop call.
|
|
//This will ensure that release message is not sent to the peer
|
|
ChangeCallState( LINECALLSTATE_DISCONNECTED, 0 );
|
|
|
|
//release non standard data
|
|
if( pReleaseASN->fNonStandardDataPresent )
|
|
{
|
|
delete pReleaseASN->nonStandardData.sData.pOctetString;
|
|
pReleaseASN->nonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
|
|
//Should we drop the primary call if the transfered call in rejected?
|
|
if( (m_dwCallType == CALLTYPE_TRANSFEREDSRC) && m_hdRelatedCall )
|
|
{
|
|
if( !QueueTAPILineRequest(
|
|
TSPI_CLOSE_CALL,
|
|
m_hdRelatedCall,
|
|
NULL,
|
|
LINEDISCONNECTMODE_NORMAL,
|
|
NULL ) )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "could not post H323 close event"));
|
|
}
|
|
}
|
|
|
|
//close call
|
|
if( m_dwCallState != LINECALLSTATE_CONNECTED )
|
|
{
|
|
dwDisconnectMode = LINEDISCONNECTMODE_REJECT;
|
|
}
|
|
|
|
CloseCall( dwDisconnectMode );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReleaseMessage exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//never call in lock
|
|
BOOL
|
|
CH323Call::InitializeIncomingCall(
|
|
IN Q931_SETUP_ASN* pSetupASN,
|
|
IN DWORD dwCallType,
|
|
IN WORD wCallRef
|
|
)
|
|
{
|
|
PH323_CONFERENCE pConf;
|
|
WCHAR* wszMachineName;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "InitializeIncomingCall entered:%p.",this));
|
|
|
|
//bind outgoing call
|
|
pConf = CreateConference( &(pSetupASN->ConferenceID) );
|
|
if( pConf == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not create conference." ));
|
|
|
|
goto cleanup;
|
|
}
|
|
|
|
if( !g_pH323Line -> GetH323ConfTable() -> Add( pConf ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not add conf to conf table." ));
|
|
|
|
// failure
|
|
goto cleanup;
|
|
}
|
|
|
|
// save caller transport address
|
|
if( !GetPeerAddress(&m_CallerAddr) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if( !GetHostAddress(&m_CalleeAddr) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//get endpoint info
|
|
m_peerEndPointType = pSetupASN->EndpointType;
|
|
|
|
//get the vendor info
|
|
if( pSetupASN->EndpointType.pVendorInfo )
|
|
{
|
|
m_peerVendorInfo = pSetupASN->VendorInfo;
|
|
|
|
//we have copied the vendor info pointers. So dont release
|
|
//the pointers in the ASN's vendor info struct
|
|
pSetupASN->EndpointType.pVendorInfo = NULL;
|
|
}
|
|
|
|
if( pSetupASN -> fCallIdentifierPresent )
|
|
{
|
|
m_callIdentifier = pSetupASN->callIdentifier;
|
|
}
|
|
else
|
|
{
|
|
int iresult = UuidCreate( &m_callIdentifier );
|
|
if( (iresult != RPC_S_OK) && (iresult !=RPC_S_UUID_LOCAL_ONLY) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
_ASSERTE( !m_pPeerFastStart );
|
|
if( pSetupASN->fFastStartPresent &&
|
|
(m_dwFastStart!=FAST_START_NOTAVAIL) )
|
|
{
|
|
m_pPeerFastStart = pSetupASN->pFastStart;
|
|
|
|
m_dwFastStart = FAST_START_PEER_AVAIL;
|
|
|
|
//we are keeping a reference to the fast start list so don't release it
|
|
pSetupASN->pFastStart = NULL;
|
|
pSetupASN->fFastStartPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
m_dwFastStart = FAST_START_NOTAVAIL;
|
|
}
|
|
|
|
//get the alias names
|
|
if( pSetupASN->pCalleeAliasList )
|
|
{
|
|
_ASSERTE( m_pCalleeAliasNames );
|
|
delete m_pCalleeAliasNames;
|
|
|
|
m_pCalleeAliasNames = pSetupASN->pCalleeAliasList;
|
|
pSetupASN->pCalleeAliasList = NULL;
|
|
}
|
|
else
|
|
{
|
|
if( RasIsRegistered() )
|
|
{
|
|
PH323_ALIASNAMES pAliasList = RASGetRegisteredAliasList();
|
|
|
|
AddAliasItem( m_pCalleeAliasNames,
|
|
pAliasList->pItems[0].pData,
|
|
pAliasList->pItems[0].wType );
|
|
}
|
|
else
|
|
{
|
|
wszMachineName = g_pH323Line->GetMachineName();
|
|
|
|
//set the value for m_pCalleeAliasNames
|
|
AddAliasItem( m_pCalleeAliasNames,
|
|
(BYTE*)(wszMachineName),
|
|
sizeof(WCHAR) * (wcslen(wszMachineName) + 1 ),
|
|
h323_ID_chosen );
|
|
}
|
|
}
|
|
|
|
_ASSERTE( m_pCallerAliasNames );
|
|
delete m_pCallerAliasNames;
|
|
m_pCallerAliasNames = NULL;
|
|
|
|
if( pSetupASN->pCallerAliasList )
|
|
{
|
|
m_pCallerAliasNames = pSetupASN->pCallerAliasList;
|
|
pSetupASN->pCallerAliasList = NULL;
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
|
|
if( pSetupASN->pExtraAliasList )
|
|
{
|
|
m_pPeerExtraAliasNames = pSetupASN->pExtraAliasList;
|
|
pSetupASN->pExtraAliasList = NULL;
|
|
}
|
|
|
|
//non -standard info
|
|
if( pSetupASN->fNonStandardDataPresent )
|
|
{
|
|
// add user user info
|
|
if( AddU2UNoAlloc( U2U_INBOUND,
|
|
pSetupASN->nonStandardData.sData.wOctetStringLength,
|
|
pSetupASN->nonStandardData.sData.pOctetString ) == TRUE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"user user info available in Setup PDU." ));
|
|
|
|
//don't release the data buffer
|
|
pSetupASN->fNonStandardDataPresent = FALSE;
|
|
}
|
|
else
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"could not save incoming user user info." ));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if( pSetupASN->fSourceAddrPresent )
|
|
{
|
|
m_CallerAddr = pSetupASN->sourceAddr;
|
|
}
|
|
|
|
m_dwCallType = dwCallType;
|
|
if( wCallRef )
|
|
{
|
|
m_wQ931CallRef = (wCallRef | 0x8000);
|
|
}
|
|
|
|
//clear incoming modes
|
|
m_dwIncomingModes = 0;
|
|
|
|
//outgoing modes will be finalized during H.245 phase
|
|
m_dwOutgoingModes = g_pH323Line->GetMediaModes() | LINEMEDIAMODE_UNKNOWN;
|
|
|
|
//save media modes specified
|
|
m_dwRequestedModes = g_pH323Line->GetMediaModes();
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "InitializeIncomingCall exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::ChangeCallState(
|
|
IN DWORD dwCallState,
|
|
IN DWORD dwCallStateMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Reports call state of specified call object.
|
|
|
|
Arguments:
|
|
|
|
dwCallState - Specifies new state of call object.
|
|
|
|
dwCallStateMode - Specifies new state mode of call object.
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE, "call 0x%08lx %s. state mode: 0x%08lx.",
|
|
this, H323CallStateToString(dwCallState), dwCallStateMode ));
|
|
|
|
// save new call state
|
|
m_dwCallState = dwCallState;
|
|
m_dwCallStateMode = dwCallStateMode;
|
|
|
|
if(
|
|
((m_dwCallType & CALLTYPE_TRANSFEREDDEST) && m_hdRelatedCall ) ||
|
|
((m_dwCallType & CALLTYPE_TRANSFEREDSRC ) && m_hdRelatedCall ) ||
|
|
(m_dwCallType & CALLTYPE_FORWARDCONSULT )
|
|
)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
// report call status
|
|
PostLineEvent (
|
|
LINE_CALLSTATE,
|
|
m_dwCallState,
|
|
m_dwCallStateMode,
|
|
m_dwIncomingModes | m_dwOutgoingModes);
|
|
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//always called in a lock
|
|
void
|
|
CH323Call::CopyU2UAsNonStandard(
|
|
IN DWORD dwDirection
|
|
)
|
|
{
|
|
PUserToUserLE pU2ULE = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CopyU2UAsNonStandard entered:%p.", this ));
|
|
|
|
if( RemoveU2U( dwDirection, &pU2ULE ) )
|
|
{
|
|
// transfer header information
|
|
m_NonStandardData.bCountryCode = H221_COUNTRY_CODE_USA;
|
|
m_NonStandardData.bExtension = H221_COUNTRY_EXT_USA;
|
|
m_NonStandardData.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
|
|
|
|
// initialize octet string containing data
|
|
m_NonStandardData.sData.wOctetStringLength = LOWORD(pU2ULE->dwU2USize);
|
|
|
|
if( m_NonStandardData.sData.pOctetString )
|
|
{
|
|
delete m_NonStandardData.sData.pOctetString;
|
|
m_NonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
|
|
m_NonStandardData.sData.pOctetString = pU2ULE->pU2U;
|
|
}
|
|
else
|
|
{
|
|
//reset non standard data
|
|
memset( (PVOID)&m_NonStandardData,0,sizeof(H323NonStandardData ));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CopyU2UAsNonStandard exited:%p.", this ));
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::AcceptCall(void)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Accepts incoming call.
|
|
!!always called in lock
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
Returns true if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
PH323_CALL pCall = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "AcceptCall entered:%p.", this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// see if user user information specified
|
|
CopyU2UAsNonStandard( U2U_OUTBOUND );
|
|
|
|
if( m_pwszDisplay == NULL )
|
|
{
|
|
// see if callee alias specified
|
|
if( m_pCalleeAliasNames && m_pCalleeAliasNames -> wCount )
|
|
{
|
|
if((m_pCalleeAliasNames->pItems[0].wType == h323_ID_chosen) ||
|
|
(m_pCalleeAliasNames ->pItems[0].wType == e164_chosen) )
|
|
{
|
|
// send callee name as display
|
|
m_pwszDisplay = m_pCalleeAliasNames -> pItems[0].pData;
|
|
}
|
|
}
|
|
}
|
|
|
|
//send answer call message to the MSP instance
|
|
|
|
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_AnswerCall;
|
|
pMSPMessageData->pbEncodedBuf = NULL;
|
|
pMSPMessageData->wLength = 0;
|
|
pMSPMessageData->hReplacementCall = m_hdCall;
|
|
|
|
if( !QueueUserWorkItem( SendMSPMessageOnRelatedCall, pMSPMessageData,
|
|
WT_EXECUTEDEFAULT ) )
|
|
{
|
|
delete pMSPMessageData;
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SendMSPMessage( SP_MSG_AnswerCall, 0, 0, NULL );
|
|
}
|
|
|
|
m_fCallAccepted = TRUE;
|
|
|
|
if( m_fReadyToAnswer )
|
|
{
|
|
// validate status
|
|
if( !AcceptH323Call() )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "error answering call 0x%08lx.",
|
|
this ));
|
|
|
|
// drop call using disconnect mode
|
|
DropCall( LINEDISCONNECTMODE_TEMPFAILURE );
|
|
|
|
// failure
|
|
return;
|
|
}
|
|
|
|
if( !(m_dwFlags & H245_START_MSG_SENT) )
|
|
{
|
|
//start H245
|
|
SendMSPStartH245( NULL, NULL );
|
|
}
|
|
|
|
//tell MSP about connect state
|
|
SendMSPMessage( SP_MSG_ConnectComplete, 0, 0, NULL );
|
|
|
|
//change call state to accepted from offering
|
|
ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "AcceptCall exited:%p.", this ));
|
|
// success
|
|
return;
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
void
|
|
CH323Call::ReleaseU2U(void)
|
|
{
|
|
PUserToUserLE pU2ULE = NULL;
|
|
PLIST_ENTRY pLE;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "ReleaseU2U entered:%p.", this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// see if list is empty
|
|
if( IsListEmpty( &m_IncomingU2U ) == FALSE )
|
|
{
|
|
// remove first entry from list
|
|
pLE = RemoveHeadList( &m_IncomingU2U );
|
|
|
|
// convert to user user structure
|
|
pU2ULE = CONTAINING_RECORD(pLE, UserToUserLE, Link);
|
|
|
|
// release memory
|
|
if(pU2ULE)
|
|
{
|
|
delete pU2ULE;
|
|
pU2ULE = NULL;
|
|
}
|
|
}
|
|
|
|
// see if list contains pending data
|
|
if( IsListEmpty( &m_IncomingU2U ) == FALSE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_VERBOSE,
|
|
"more user user info available." ));
|
|
|
|
// signal incoming
|
|
PostLineEvent (
|
|
LINE_CALLINFO,
|
|
LINECALLINFOSTATE_USERUSERINFO, 0, 0);
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "ReleaseU2U exited:%p.", this ));
|
|
}
|
|
|
|
|
|
//always called in lock
|
|
void
|
|
CH323Call::SendU2U(
|
|
IN BYTE* pUserUserInfo,
|
|
IN DWORD dwSize
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendU2U entered:%p.", this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// check for user user info
|
|
if( pUserUserInfo != NULL )
|
|
{
|
|
// transfer header information
|
|
m_NonStandardData.bCountryCode = H221_COUNTRY_CODE_USA;
|
|
m_NonStandardData.bExtension = H221_COUNTRY_EXT_USA;
|
|
m_NonStandardData.wManufacturerCode = H221_MFG_CODE_MICROSOFT;
|
|
|
|
// initialize octet string containing data
|
|
m_NonStandardData.sData.wOctetStringLength = (WORD)dwSize;
|
|
|
|
if( m_NonStandardData.sData.pOctetString != NULL )
|
|
{
|
|
delete m_NonStandardData.sData.pOctetString;
|
|
m_NonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
|
|
m_NonStandardData.sData.pOctetString = pUserUserInfo;
|
|
}
|
|
|
|
// send user user data
|
|
if( !SendQ931Message( 0, 0, 0, FACILITYMESSAGETYPE, NO_H450_APDU ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error sending non-standard message."));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "SendU2U exited:%p.", this ));
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::InitializeQ931(
|
|
IN SOCKET callSocket
|
|
)
|
|
{
|
|
BOOL fSuccess;
|
|
|
|
H323DBG((DEBUG_LEVEL_ERROR, "q931 call initialize entered:%p.", this ));
|
|
|
|
if( !BindIoCompletionCallback(
|
|
(HANDLE)callSocket,
|
|
CH323Call::IoCompletionCallback,
|
|
0) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"couldn't bind i/o completion callabck:%d:%p.",
|
|
GetLastError(), this ));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//initilize the member variables
|
|
m_callSocket = callSocket;
|
|
|
|
H323DBG((DEBUG_LEVEL_ERROR, "q931 call initialize exited:%lx, %p.",
|
|
m_callSocket, this ));
|
|
return TRUE;
|
|
}
|
|
|
|
//no need to lock
|
|
BOOL
|
|
CH323Call::GetPeerAddress(
|
|
IN H323_ADDR *pAddr
|
|
)
|
|
{
|
|
SOCKADDR_IN sockaddr;
|
|
int len = sizeof(sockaddr);
|
|
|
|
H323DBG((DEBUG_LEVEL_ERROR, "GetPeerAddress entered:%p.", this ));
|
|
|
|
if( getpeername( m_callSocket, (SOCKADDR*)&sockaddr, &len)
|
|
== SOCKET_ERROR )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error 0x%08lx calling getpeername.", WSAGetLastError() ));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
pAddr->nAddrType = H323_IP_BINARY;
|
|
pAddr->bMulticast = FALSE;
|
|
pAddr->Addr.IP_Binary.wPort = ntohs(sockaddr.sin_port);
|
|
pAddr->Addr.IP_Binary.dwAddr = ntohl(sockaddr.sin_addr.S_un.S_addr);
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "GetPeerAddress exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//no need to lock
|
|
BOOL CH323Call::GetHostAddress(
|
|
IN H323_ADDR *pAddr
|
|
)
|
|
{
|
|
int len = sizeof(m_LocalAddr);
|
|
|
|
H323DBG((DEBUG_LEVEL_ERROR, "GetHostAddress entered:%p.", this ));
|
|
|
|
if( getsockname( m_callSocket, (SOCKADDR *)&m_LocalAddr, &len) ==
|
|
SOCKET_ERROR)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error 0x%08lx calling getockname.", WSAGetLastError() ));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
pAddr->nAddrType = H323_IP_BINARY;
|
|
pAddr->bMulticast = FALSE;
|
|
pAddr->Addr.IP_Binary.wPort = ntohs(m_LocalAddr.sin_port);
|
|
pAddr->Addr.IP_Binary.dwAddr = ntohl(m_LocalAddr.sin_addr.S_un.S_addr);
|
|
|
|
H323DBG((DEBUG_LEVEL_ERROR, "GetHostAddress exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::OnReceiveFacility(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
Q931_FACILITY_ASN facilityASN;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveFacility entered: %p.", this ));
|
|
|
|
//decode the U2U information
|
|
if( !pMessage ->UserToUser.fPresent ||
|
|
pMessage ->UserToUser.wUserInfoLen == 0 )
|
|
{
|
|
//Ignore this message. Don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( !ParseFacilityASN( pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen, &facilityASN ))
|
|
{
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( (facilityASN.pH245PDU.length != 0) && facilityASN.pH245PDU.value )
|
|
{
|
|
SendMSPMessage( SP_MSG_H245PDU, facilityASN.pH245PDU.value,
|
|
facilityASN.pH245PDU.length, NULL );
|
|
delete facilityASN.pH245PDU.value;
|
|
}
|
|
|
|
HandleFacilityMessage( facilityASN.dwInvokeID, &facilityASN );
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveFacility exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::OnReceiveProceeding(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
Q931_CALL_PROCEEDING_ASN proceedingASN;
|
|
DWORD dwAPDUType = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveProceeding entered: %p.", this ));
|
|
|
|
//decode the U2U information
|
|
if( (pMessage ->UserToUser.fPresent == FALSE) ||
|
|
(pMessage ->UserToUser.wUserInfoLen == 0) )
|
|
{
|
|
//ignore this message. don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( (m_dwOrigin!=LINECALLORIGIN_OUTBOUND) ||
|
|
( (m_dwStateMachine != Q931_SETUP_SENT) &&
|
|
(m_dwStateMachine != Q931_PROCEED_RECVD) )
|
|
)
|
|
{
|
|
//ignore this message. don't shutdown the Q931 call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( !ParseProceedingASN(
|
|
pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen,
|
|
&proceedingASN,
|
|
&dwAPDUType ))
|
|
{
|
|
//Ignore the wrong proceeding message.
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "wrong proceeding PDU:%p.", this ));
|
|
H323DUMPBUFFER( pMessage->UserToUser.pbUserInfo,
|
|
(DWORD)pMessage->UserToUser.wUserInfoLen );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//success of forwarding
|
|
EnableCallForwarding();
|
|
|
|
CloseCall( 0 );
|
|
return TRUE;
|
|
}
|
|
|
|
HandleProceedingMessage( &proceedingASN );
|
|
|
|
//reset the timeout for setup sent
|
|
if( m_hSetupSentTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hSetupSentTimer, NULL );
|
|
m_hSetupSentTimer = NULL;
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveProceeding exited: %p.", this ));
|
|
m_dwStateMachine = Q931_PROCEED_RECVD;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::OnReceiveAlerting(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
Q931_ALERTING_ASN alertingASN;
|
|
DWORD dwAPDUType = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveAlerting entered: %p.", this ));
|
|
|
|
//decode the U2U information
|
|
if( (pMessage ->UserToUser.fPresent == FALSE) ||
|
|
(pMessage ->UserToUser.wUserInfoLen == 0) )
|
|
{
|
|
//ignore this message. don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( (m_dwOrigin!=LINECALLORIGIN_OUTBOUND) ||
|
|
!( (m_dwStateMachine==Q931_SETUP_SENT) ||
|
|
(m_dwStateMachine==Q931_PROCEED_RECVD)
|
|
)
|
|
)
|
|
{
|
|
//ignore this message. don't shutdown the Q931 call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( !ParseAlertingASN( pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen,
|
|
&alertingASN,
|
|
&dwAPDUType ))
|
|
{
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//success of forwarding
|
|
EnableCallForwarding();
|
|
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
//reset the timeout for setup sent
|
|
if( m_hSetupSentTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hSetupSentTimer, NULL );
|
|
m_hSetupSentTimer = NULL;
|
|
}
|
|
|
|
if( !CreateTimerQueueTimer(
|
|
&m_hCallEstablishmentTimer,
|
|
H323TimerQueue,
|
|
CH323Call::CallEstablishmentExpiredCallback,
|
|
(PVOID)m_hdCall,
|
|
g_RegistrySettings.dwQ931AlertingTimeout, 0,
|
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE ))
|
|
{
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
HandleAlertingMessage( &alertingASN );
|
|
m_dwStateMachine = Q931_ALERT_RECVD;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveAlerting exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in lock
|
|
void
|
|
CH323Call::SetupSentTimerExpired(void)
|
|
{
|
|
DWORD dwState;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SetupSentTimerExpired entered."));
|
|
|
|
dwState = m_dwStateMachine;
|
|
|
|
if( m_hSetupSentTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hSetupSentTimer, NULL );
|
|
m_hSetupSentTimer = NULL;
|
|
}
|
|
|
|
if( (dwState!= Q931_CONNECT_RECVD) &&
|
|
(dwState != Q931_ALERT_RECVD) &&
|
|
(dwState != Q931_PROCEED_RECVD) &&
|
|
(dwState != Q931_RELEASE_RECVD)
|
|
)
|
|
{
|
|
//time out has occured
|
|
CloseCall( 0 );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SetupSentTimerExpired exited." ));
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::OnReceiveRelease(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
DWORD dwAPDUType = 0;
|
|
Q931_RELEASE_COMPLETE_ASN releaseASN;
|
|
|
|
//decode the U2U information
|
|
if( (pMessage ->UserToUser.fPresent == FALSE) ||
|
|
(pMessage ->UserToUser.wUserInfoLen == 0) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "ReleaseComplete PDU did not contain "
|
|
"user-to-user information, ignoring message." ));
|
|
|
|
//ignore this message. don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( !ParseReleaseCompleteASN(
|
|
pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen,
|
|
&releaseASN,
|
|
&dwAPDUType ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"ReleaseComplete PDU could not be parsed, terminating call." ));
|
|
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG ((DEBUG_LEVEL_INFO, "Received ReleaseComplete PDU."));
|
|
|
|
HandleReleaseMessage( &releaseASN );
|
|
m_dwStateMachine = Q931_RELEASE_RECVD;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::OnReceiveConnect(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
Q931_CONNECT_ASN connectASN;
|
|
DWORD dwH450APDUType = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveConnect entered: %p.", this ));
|
|
|
|
//decode the U2U information
|
|
if( (pMessage ->UserToUser.fPresent == FALSE) ||
|
|
(pMessage ->UserToUser.wUserInfoLen == 0) )
|
|
{
|
|
//ignore this message. don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_dwOrigin!=LINECALLORIGIN_OUTBOUND )
|
|
{
|
|
//ignore this message. don't shutdown the Q931 call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( (m_dwStateMachine != Q931_SETUP_SENT) &&
|
|
(m_dwStateMachine != Q931_ALERT_RECVD) &&
|
|
(m_dwStateMachine != Q931_PROCEED_RECVD)
|
|
)
|
|
{
|
|
//ignore this message. don't shutdown the Q931 call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( ParseConnectASN( pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen,
|
|
&connectASN,
|
|
&dwH450APDUType) == FALSE )
|
|
{
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_dwCallType & CALLTYPE_FORWARDCONSULT )
|
|
{
|
|
FreeConnectASN( &connectASN );
|
|
|
|
if( dwH450APDUType == H4503_DUMMYTYPERETURNRESULT_APDU)
|
|
{
|
|
//assuming this return result is for check restriction operation
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
//success of forwarding
|
|
EnableCallForwarding();
|
|
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if( !HandleConnectMessage( &connectASN ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//reset the timeout for setup sent
|
|
if( m_hSetupSentTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hSetupSentTimer, NULL );
|
|
m_hSetupSentTimer = NULL;
|
|
}
|
|
|
|
if( m_hCallEstablishmentTimer )
|
|
{
|
|
DeleteTimerQueueTimer(H323TimerQueue, m_hCallEstablishmentTimer, NULL);
|
|
m_hCallEstablishmentTimer = NULL;
|
|
}
|
|
|
|
m_dwStateMachine = Q931_CONNECT_RECVD;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnReceiveConnect exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::OnReceiveSetup(
|
|
IN Q931MESSAGE* pMessage
|
|
)
|
|
{
|
|
Q931_SETUP_ASN setupASN;
|
|
DWORD dwH450APDUType = 0;
|
|
PH323_CALL pCall = NULL;
|
|
WCHAR pwszCallingPartyNr[H323_MAXPATHNAMELEN];
|
|
WCHAR pwszCalledPartyNr[H323_MAXPATHNAMELEN];
|
|
BYTE* pstrTemp;
|
|
|
|
//decode the U2U information
|
|
if( (pMessage ->UserToUser.fPresent == FALSE) ||
|
|
(pMessage ->UserToUser.wUserInfoLen == 0) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"Setup message did not contain H.323 UUIE, ignoring."));
|
|
|
|
//ignore this message. don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_dwOrigin != LINECALLORIGIN_INBOUND )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"Received Setup message on outbound call, ignoring."));
|
|
|
|
//ignore this message. don't shutdown the call.
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_dwStateMachine != Q931_CALL_STATE_NONE )
|
|
{
|
|
H323DBG( (DEBUG_LEVEL_ERROR,
|
|
"Received Setup message on a call that is already in progress." ));
|
|
|
|
//This Q931 call has already received a setup!!!!
|
|
CloseCall( 0 );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( !ParseSetupASN( pMessage->UserToUser.pbUserInfo,
|
|
pMessage->UserToUser.wUserInfoLen,
|
|
&setupASN,
|
|
&dwH450APDUType ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"Failed to parse Setup UUIE, closing call." ));
|
|
|
|
//shutdown the Q931 call
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
if( dwH450APDUType )
|
|
{
|
|
if( m_dwCallType & CALLTYPE_FORWARDCONSULT )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if( (pMessage->CallingPartyNumber.fPresent == TRUE) &&
|
|
(pMessage->CallingPartyNumber.dwLength > 1) &&
|
|
(setupASN.pCallerAliasList == NULL ) )
|
|
{
|
|
// Always skip 1st byte in the contents.
|
|
// Skip the 2nd byte if its not an e.164 char (could be the screening indicator byte)
|
|
|
|
pstrTemp = pMessage->CallingPartyNumber.pbContents +
|
|
((pMessage->CallingPartyNumber.pbContents[1] & 0x80)? 2 : 1);
|
|
|
|
MultiByteToWideChar( CP_ACP,
|
|
0,
|
|
(const char *)(pstrTemp),
|
|
-1,
|
|
pwszCallingPartyNr,
|
|
sizeof(pwszCallingPartyNr)/sizeof(WCHAR));
|
|
|
|
setupASN.pCallerAliasList = new H323_ALIASNAMES;
|
|
|
|
if( setupASN.pCallerAliasList != NULL )
|
|
{
|
|
ZeroMemory( setupASN.pCallerAliasList, sizeof(H323_ALIASNAMES) );
|
|
|
|
AddAliasItem( setupASN.pCallerAliasList,
|
|
pwszCallingPartyNr,
|
|
e164_chosen );
|
|
}
|
|
}
|
|
|
|
if( (pMessage->CalledPartyNumber.fPresent == TRUE) &&
|
|
(pMessage->CalledPartyNumber.PartyNumberLength > 0) &&
|
|
(setupASN.pCalleeAliasList == NULL ) )
|
|
{
|
|
// Always skip 1st byte in the contents.
|
|
// Skip the 2nd byte if its not an e.164 char (could be the screening indicator byte)
|
|
|
|
MultiByteToWideChar(CP_ACP,
|
|
0,
|
|
(const char *)(pMessage->CalledPartyNumber.PartyNumbers),
|
|
-1,
|
|
pwszCalledPartyNr,
|
|
sizeof(pwszCalledPartyNr) / sizeof(WCHAR) );
|
|
|
|
setupASN.pCalleeAliasList = new H323_ALIASNAMES;
|
|
|
|
if( setupASN.pCalleeAliasList != NULL )
|
|
{
|
|
ZeroMemory( setupASN.pCalleeAliasList, sizeof(H323_ALIASNAMES) );
|
|
|
|
AddAliasItem( setupASN.pCalleeAliasList,
|
|
pwszCalledPartyNr,
|
|
e164_chosen );
|
|
}
|
|
}
|
|
|
|
//don't change the call type here
|
|
if( !InitializeIncomingCall( &setupASN, m_dwCallType, pMessage->wCallRef ) )
|
|
{
|
|
H323DBG ((DEBUG_LEVEL_ERROR,
|
|
"Failed to initialize incoming call, closing call."));
|
|
|
|
//shutdown the Q931 call
|
|
FreeSetupASN( &setupASN );
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
FreeSetupASN( &setupASN );
|
|
m_dwStateMachine = Q931_SETUP_RECVD;
|
|
|
|
if( !HandleSetupMessage( pMessage ) )
|
|
{
|
|
H323DBG ((DEBUG_LEVEL_ERROR,
|
|
"Failed to process Setup message, closing call."));
|
|
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::CloseCall(
|
|
IN DWORD dwDisconnectMode )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_INFO, "[%08XH] Terminating call.", this ));
|
|
|
|
if (!QueueTAPILineRequest(
|
|
TSPI_CLOSE_CALL,
|
|
m_hdCall,
|
|
NULL,
|
|
dwDisconnectMode,
|
|
m_wCallReference ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not post H323 close event." ));
|
|
}
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::ReadEvent(
|
|
IN DWORD cbTransfer
|
|
)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ReadEvent entered: %p.", this ));
|
|
H323DBG((DEBUG_LEVEL_TRACE, "bytes received: %d.", cbTransfer));
|
|
|
|
m_RecvBuf.dwBytesCopied += cbTransfer;
|
|
|
|
//update the recv buffer
|
|
if( m_bStartOfPDU )
|
|
{
|
|
if( m_RecvBuf.dwBytesCopied < sizeof(TPKT_HEADER_SIZE) )
|
|
{
|
|
//set the buffer to get the remainig TPKT_HEADER
|
|
m_RecvBuf.WSABuf.buf =
|
|
m_RecvBuf.arBuf + m_RecvBuf.dwBytesCopied;
|
|
|
|
m_RecvBuf.WSABuf.len =
|
|
TPKT_HEADER_SIZE - m_RecvBuf.dwBytesCopied;
|
|
}
|
|
else
|
|
{
|
|
m_RecvBuf.dwPDULen = GetTpktLength( m_RecvBuf.arBuf );
|
|
|
|
if( (m_RecvBuf.dwPDULen < TPKT_HEADER_SIZE) ||
|
|
(m_RecvBuf.dwPDULen > Q931_RECV_BUFFER_LENGTH) )
|
|
{
|
|
//messed up peer. close the call.
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "error:PDULen:%d.",
|
|
m_RecvBuf.dwPDULen ));
|
|
|
|
//close the call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
else if( m_RecvBuf.dwPDULen == TPKT_HEADER_SIZE )
|
|
{
|
|
InitializeRecvBuf();
|
|
}
|
|
else
|
|
{
|
|
//set the buffer to get the remaining PDU
|
|
m_bStartOfPDU = FALSE;
|
|
m_RecvBuf.WSABuf.buf = m_RecvBuf.arBuf +
|
|
m_RecvBuf.dwBytesCopied;
|
|
m_RecvBuf.WSABuf.len = m_RecvBuf.dwPDULen -
|
|
m_RecvBuf.dwBytesCopied;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_ASSERTE( m_RecvBuf.dwBytesCopied <= m_RecvBuf.dwPDULen );
|
|
|
|
if( m_RecvBuf.dwBytesCopied == m_RecvBuf.dwPDULen )
|
|
{
|
|
//we got the whole PDU
|
|
if( !ProcessQ931PDU( &m_RecvBuf ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error in processing PDU:%p.", this ));
|
|
|
|
H323DUMPBUFFER( (BYTE*)m_RecvBuf.arBuf, m_RecvBuf.dwPDULen );
|
|
}
|
|
|
|
//if the call has been already shutdown due to
|
|
//a fatal error while processing the PDU or because of receiveing
|
|
//release complete message then dont post any more read buffers
|
|
if( (m_dwFlags & CALLOBJECT_SHUTDOWN) ||
|
|
(m_dwQ931Flags & Q931_CALL_DISCONNECTED) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
InitializeRecvBuf();
|
|
}
|
|
else
|
|
{
|
|
//set the buffer to get the remainig PDU
|
|
m_RecvBuf.WSABuf. buf =
|
|
m_RecvBuf.arBuf + m_RecvBuf.dwBytesCopied;
|
|
m_RecvBuf.WSABuf. len =
|
|
m_RecvBuf.dwPDULen - m_RecvBuf.dwBytesCopied;
|
|
}
|
|
}
|
|
|
|
//post a read for the remaining PDU
|
|
if(!PostReadBuffer())
|
|
{
|
|
//post a message to the callback thread to shutdown the H323 call
|
|
CloseCall( 0 );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ReadEvent exited: %p.", this ));
|
|
}
|
|
|
|
|
|
/*
|
|
Parse a generic Q931 message and place the fields of the buffer
|
|
into the appropriate structure fields.
|
|
|
|
Parameters:
|
|
pBuf Pointer to buffer descriptor of an
|
|
input packet containing the 931 message.
|
|
pMessage Pointer to space for parsed output information.
|
|
*/
|
|
|
|
//!!always called in a lock
|
|
HRESULT
|
|
CH323Call::Q931ParseMessage(
|
|
IN BYTE * pbCodedBuffer,
|
|
IN DWORD dwCodedBufferLength,
|
|
OUT PQ931MESSAGE pMessage
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
BUFFERDESCR pBuf;
|
|
|
|
pBuf.dwLength = dwCodedBufferLength;
|
|
pBuf.pbBuffer = pbCodedBuffer;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "Q931ParseMessage entered: %p.", this ));
|
|
|
|
memset( (PVOID)pMessage, 0, sizeof(Q931MESSAGE));
|
|
|
|
hr = ParseProtocolDiscriminator(&pBuf, &pMessage->ProtocolDiscriminator);
|
|
|
|
if( hr != S_OK )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = ParseCallReference( &pBuf, &pMessage->wCallRef);
|
|
if( hr != S_OK )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
hr = ParseMessageType( &pBuf, &pMessage->MessageType );
|
|
if( hr != S_OK )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
while (pBuf.dwLength)
|
|
{
|
|
hr = ParseQ931Field(&pBuf, pMessage);
|
|
if (hr != S_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "Q931ParseMessage exited: %p.", this ));
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//decode the PDU and release the buffer
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::ProcessQ931PDU(
|
|
IN CALL_RECV_CONTEXT* pRecvBuf
|
|
)
|
|
{
|
|
PQ931MESSAGE pMessage;
|
|
BOOL retVal;
|
|
HRESULT hr;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ProcessQ931PDU entered: %p.", this ));
|
|
|
|
pMessage = new Q931MESSAGE;
|
|
if( pMessage == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
hr = Q931ParseMessage( (BYTE*)(pRecvBuf->arBuf + sizeof(TPKT_HEADER_SIZE)),
|
|
pRecvBuf->dwPDULen - 4,
|
|
pMessage );
|
|
|
|
if( !SUCCEEDED( hr) )
|
|
{
|
|
delete pMessage;
|
|
return FALSE;
|
|
}
|
|
|
|
if( (m_dwCallType & CALLTYPE_TRANSFERED_PRIMARY ) &&
|
|
(m_dwCallDiversionState == H4502_CTINITIATE_RECV) &&
|
|
(pMessage->MessageType != RELEASECOMPLMESSAGETYPE) )
|
|
{
|
|
// If this endpoint has already been transferred then
|
|
// ignore any further messages on the primary call.
|
|
delete pMessage;
|
|
return FALSE;
|
|
}
|
|
|
|
switch( pMessage->MessageType )
|
|
{
|
|
case ALERTINGMESSAGETYPE:
|
|
|
|
retVal = OnReceiveAlerting( pMessage );
|
|
break;
|
|
|
|
case PROCEEDINGMESSAGETYPE:
|
|
|
|
retVal = OnReceiveProceeding( pMessage );
|
|
break;
|
|
|
|
case CONNECTMESSAGETYPE:
|
|
|
|
retVal = OnReceiveConnect( pMessage );
|
|
break;
|
|
|
|
case RELEASECOMPLMESSAGETYPE:
|
|
|
|
retVal = OnReceiveRelease( pMessage );
|
|
break;
|
|
|
|
case SETUPMESSAGETYPE:
|
|
|
|
retVal = OnReceiveSetup( pMessage );
|
|
break;
|
|
|
|
case FACILITYMESSAGETYPE:
|
|
|
|
retVal = OnReceiveFacility( pMessage );
|
|
break;
|
|
|
|
default:
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "unrecognised PDU recvd:%d,%p.",
|
|
pMessage->MessageType, this ));
|
|
retVal = FALSE;
|
|
}
|
|
|
|
delete pMessage;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ProcessQ931PDU exited: %p.", this ));
|
|
return retVal;
|
|
}
|
|
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::OnConnectComplete(void)
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
PH323_CALL pCall = NULL;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnConnectComplete entered: %p.", this ));
|
|
|
|
_ASSERTE( m_dwOrigin==LINECALLORIGIN_OUTBOUND );
|
|
|
|
if( !GetHostAddress( &m_CallerAddr) )
|
|
{
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
InitializeRecvBuf();
|
|
|
|
//post a buffer to winsock to accept messages from the peer
|
|
if( !PostReadBuffer() )
|
|
{
|
|
//memory failure : shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
//set the state to connected
|
|
SetQ931CallState( Q931_CALL_CONNECTED );
|
|
|
|
if( (m_dwCallType == CALLTYPE_NORMAL) ||
|
|
(m_dwCallType & CALLTYPE_TRANSFERING_CONSULT) )
|
|
{
|
|
SendMSPMessage( SP_MSG_InitiateCall, 0, 0, NULL );
|
|
}
|
|
else if( m_dwCallType & CALLTYPE_TRANSFEREDSRC )
|
|
{
|
|
_ASSERTE( m_hdRelatedCall );
|
|
MSPMessageData* pMSPMessageData = new MSPMessageData;
|
|
if( pMSPMessageData == NULL )
|
|
{
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
pMSPMessageData->hdCall = m_hdRelatedCall;
|
|
pMSPMessageData->messageType = SP_MSG_InitiateCall;
|
|
pMSPMessageData->pbEncodedBuf = NULL;
|
|
pMSPMessageData->wLength = 0;
|
|
pMSPMessageData->hReplacementCall = m_hdCall;
|
|
|
|
if( !QueueUserWorkItem( SendMSPMessageOnRelatedCall, pMSPMessageData,
|
|
WT_EXECUTEDEFAULT ) )
|
|
{
|
|
delete pMSPMessageData;
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//send the setup message
|
|
if( !SendSetupMessage() )
|
|
{
|
|
DropCall( 0 );
|
|
}
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "OnConnectComplete exited: %p.", this ));
|
|
}
|
|
|
|
|
|
//!!aleways called in a lock
|
|
BOOL
|
|
CH323Call::SendSetupMessage(void)
|
|
{
|
|
BOOL retVal = TRUE;
|
|
DWORD dwAPDUType = NO_H450_APDU;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendSetupMessage entered: %p.", this ));
|
|
|
|
//encode ASN.1 and send Q931Setup message to the peer
|
|
if( m_dwCallType & CALLTYPE_FORWARDCONSULT )
|
|
{
|
|
//send the callRerouitng.invoke APDU if this is a forwardconsult call
|
|
retVal = SendQ931Message( NO_INVOKEID,
|
|
(DWORD)create_chosen,
|
|
(DWORD)pointToPoint_chosen,
|
|
SETUPMESSAGETYPE,
|
|
CHECKRESTRICTION_OPCODE| H450_INVOKE );
|
|
|
|
if( retVal )
|
|
{
|
|
m_dwStateMachine = Q931_SETUP_SENT;
|
|
m_dwCallDiversionState = H4503_CHECKRESTRICTION_SENT;
|
|
|
|
retVal = CreateTimerQueueTimer(
|
|
&m_hCheckRestrictionTimer,
|
|
H323TimerQueue,
|
|
CH323Call::CheckRestrictionTimerCallback,
|
|
(PVOID)m_hdCall,
|
|
CHECKRESTRICTION_EXPIRE_TIME, 0,
|
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( ( m_dwCallType & CALLTYPE_DIVERTEDSRC ) ||
|
|
( m_dwCallType & CALLTYPE_DIVERTEDSRC_NOROUTING ) )
|
|
{
|
|
dwAPDUType = DIVERTINGLEGINFO2_OPCODE | H450_INVOKE;
|
|
}
|
|
else if( m_dwCallType & CALLTYPE_TRANSFEREDSRC )
|
|
{
|
|
dwAPDUType = CTSETUP_OPCODE | H450_INVOKE;
|
|
}
|
|
|
|
retVal = SendQ931Message( NO_INVOKEID,
|
|
(DWORD)create_chosen,
|
|
(DWORD)pointToPoint_chosen,
|
|
SETUPMESSAGETYPE,
|
|
dwAPDUType );
|
|
|
|
if( retVal )
|
|
{
|
|
m_dwStateMachine = Q931_SETUP_SENT;
|
|
|
|
retVal = CreateTimerQueueTimer(
|
|
&m_hSetupSentTimer,
|
|
H323TimerQueue,
|
|
CH323Call::SetupSentTimerCallback,
|
|
(PVOID)m_hdCall,
|
|
SETUP_SENT_TIMEOUT, 0,
|
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE );
|
|
}
|
|
}
|
|
|
|
if( retVal == FALSE )
|
|
{
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendSetupMessage exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::SendProceeding(void)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendProceeding entered: %p.", this ));
|
|
|
|
_ASSERTE( m_dwOrigin == LINECALLORIGIN_INBOUND );
|
|
|
|
//encode ASN.1 and send Q931Setup message to the peer
|
|
if(!SendQ931Message( NO_INVOKEID, 0, 0, PROCEEDINGMESSAGETYPE, NO_H450_APDU ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
m_dwStateMachine = Q931_PROCEED_SENT;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendProceeding exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::PostReadBuffer(void)
|
|
{
|
|
int iError;
|
|
DWORD dwByteReceived = 0;
|
|
BOOL fDelete = FALSE;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "PostReadBuffer entered: %p.", this ));
|
|
|
|
m_RecvBuf.Type = OVERLAPPED_TYPE_RECV;
|
|
m_RecvBuf.pCall = this;
|
|
m_RecvBuf.dwFlags = 0;
|
|
m_RecvBuf.BytesTransferred = 0;
|
|
ZeroMemory( (PVOID)&m_RecvBuf.Overlapped, sizeof(OVERLAPPED) );
|
|
|
|
//register with winsock for overlappped I/O
|
|
if( WSARecv( m_callSocket,
|
|
&(m_RecvBuf.WSABuf),
|
|
1,
|
|
&(m_RecvBuf.BytesTransferred),
|
|
&(m_RecvBuf.dwFlags),
|
|
&(m_RecvBuf.Overlapped),
|
|
NULL ) == SOCKET_ERROR )
|
|
{
|
|
iError = WSAGetLastError();
|
|
|
|
if( iError != WSA_IO_PENDING )
|
|
{
|
|
//take care of error conditions here
|
|
H323DBG((DEBUG_LEVEL_ERROR, "error while recving buf: %d.",
|
|
iError ));
|
|
return FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//There is some data to read!!!!!
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "bytes received immediately: %d.",
|
|
m_RecvBuf.BytesTransferred ));
|
|
}
|
|
|
|
m_IoRefCount++;
|
|
H323DBG((DEBUG_LEVEL_TRACE,
|
|
"PostReadBuffer:m_IoRefCount: %d:%p.", m_IoRefCount, this ));
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "PostReadBuffer exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::SendBuffer(
|
|
IN BYTE* pbBuffer,
|
|
IN DWORD dwLength
|
|
)
|
|
{
|
|
int iError;
|
|
CALL_SEND_CONTEXT* pSendBuf = NULL;
|
|
DWORD cbTransfer;
|
|
BOOL fDelete = FALSE;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendBuffer entered: %p.", this ));
|
|
|
|
if( !(m_dwQ931Flags & Q931_CALL_CONNECTED) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pSendBuf = new CALL_SEND_CONTEXT;
|
|
if( pSendBuf == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
ZeroMemory( (PVOID)pSendBuf, sizeof(CALL_SEND_CONTEXT) );
|
|
pSendBuf->WSABuf.buf = (char*)pbBuffer;
|
|
pSendBuf->WSABuf.len = dwLength;
|
|
pSendBuf->BytesTransferred = 0;
|
|
pSendBuf->pCall = this;
|
|
pSendBuf->Type = OVERLAPPED_TYPE_SEND;
|
|
|
|
InsertTailList( &m_sendBufList, &(pSendBuf ->ListEntry) );
|
|
|
|
if( WSASend(m_callSocket,
|
|
&(pSendBuf->WSABuf),
|
|
1,
|
|
&(pSendBuf->BytesTransferred),
|
|
0,
|
|
&(pSendBuf->Overlapped),
|
|
NULL) == SOCKET_ERROR )
|
|
{
|
|
iError = WSAGetLastError();
|
|
|
|
if( iError != WSA_IO_PENDING )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "error sending the buf: %lx.", iError));
|
|
|
|
RemoveEntryList( &pSendBuf->ListEntry );
|
|
goto cleanup;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//data was sent immediately!!!
|
|
H323DBG((DEBUG_LEVEL_TRACE, "data sent immediately!!." ));
|
|
}
|
|
|
|
m_IoRefCount++;
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendBuffer:m_IoRefCount11: %d:%p.",
|
|
m_IoRefCount, this ));
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendBuffer exited: %p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
if(pSendBuf)
|
|
{
|
|
delete pSendBuf;
|
|
}
|
|
|
|
delete pbBuffer;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!aleways called in a lock
|
|
BOOL
|
|
CH323Call::SetupCall(void)
|
|
{
|
|
SOCKET Q931CallSocket = INVALID_SOCKET;
|
|
SOCKADDR_IN sin;
|
|
HANDLE hWSAEvent;
|
|
HANDLE hConnWait;
|
|
BOOL fSuccess = TRUE;
|
|
int iError;
|
|
BOOL fDelete;
|
|
DWORD dwEnable = 1;
|
|
TCHAR ptstrEventName[100];
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SetupCall entered."));
|
|
|
|
//create a socket
|
|
Q931CallSocket = WSASocket(
|
|
AF_INET,
|
|
SOCK_STREAM,
|
|
IPPROTO_IP,
|
|
NULL,
|
|
NULL,
|
|
WSA_FLAG_OVERLAPPED );
|
|
|
|
if( Q931CallSocket == INVALID_SOCKET )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "error while creating socket: %lx.",
|
|
WSAGetLastError() ));
|
|
goto error1;
|
|
}
|
|
|
|
//create a new Q931 call object
|
|
if( InitializeQ931(Q931CallSocket) == NULL )
|
|
{
|
|
goto error2;
|
|
}
|
|
|
|
_stprintf( ptstrEventName, _T("%s-%p") ,
|
|
_T( "H323TSP_OutgoingCall_TransportHandlerEvent" ), this );
|
|
|
|
//create the wait event
|
|
hWSAEvent = H323CreateEvent( NULL, FALSE,
|
|
FALSE, ptstrEventName );
|
|
|
|
if( hWSAEvent == NULL )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "couldn't create wsaevent" ));
|
|
goto error3;
|
|
}
|
|
|
|
//register with thread pool the event handle and handler proc
|
|
fSuccess = RegisterWaitForSingleObject(
|
|
&hConnWait, // pointer to the returned handle
|
|
hWSAEvent, // the event handle to wait for.
|
|
Q931TransportEventHandler, // the callback function.
|
|
(PVOID)m_hdCall, // the context for the callback.
|
|
INFINITE, // wait forever.
|
|
// probably don't need this flag set
|
|
WT_EXECUTEDEFAULT // use the wait thread to call the callback.
|
|
);
|
|
|
|
if ( ( !fSuccess ) || (hConnWait== NULL) )
|
|
{
|
|
GetLastError();
|
|
if( !CloseHandle( hWSAEvent ) )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR, "couldn't close wsaevent" ));
|
|
}
|
|
|
|
goto error3;
|
|
}
|
|
|
|
//store this in the call context
|
|
SetNewCallInfo( hConnWait, hWSAEvent, Q931_CALL_CONNECTING );
|
|
|
|
//register with Winsock the event handle and the events
|
|
if( WSAEventSelect( Q931CallSocket,
|
|
hWSAEvent,
|
|
FD_CONNECT | FD_CLOSE
|
|
) == SOCKET_ERROR )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_ERROR,
|
|
"error selecting event outgoing call: %lx.", WSAGetLastError()));
|
|
goto error3;
|
|
}
|
|
|
|
if( setsockopt( Q931CallSocket,
|
|
IPPROTO_TCP,
|
|
TCP_NODELAY,
|
|
(char*)&dwEnable,
|
|
sizeof(DWORD)
|
|
) == SOCKET_ERROR )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_WARNING,
|
|
"Couldn't set NODELAY option on outgoing call socket:%d, %p",
|
|
WSAGetLastError(), this ));
|
|
}
|
|
|
|
//set the address structure
|
|
memset( (PVOID)&sin, 0, sizeof(SOCKADDR_IN) );
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_addr.s_addr = htonl( m_CalleeAddr.Addr.IP_Binary.dwAddr );
|
|
sin.sin_port = htons( m_CalleeAddr.Addr.IP_Binary.wPort );
|
|
|
|
//make the winsock connection
|
|
if( WSAConnect( Q931CallSocket,
|
|
(sockaddr*)&sin,
|
|
sizeof(SOCKADDR_IN),
|
|
NULL, NULL, NULL, NULL
|
|
)
|
|
== SOCKET_ERROR )
|
|
{
|
|
iError = WSAGetLastError();
|
|
|
|
if(iError != WSAEWOULDBLOCK )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"error while connecting socket: %lx.", iError ));
|
|
|
|
goto error3;
|
|
}
|
|
}
|
|
else
|
|
{ //connection went through immediately!!!
|
|
OnConnectComplete();
|
|
}
|
|
|
|
//success
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SetupCall exited."));
|
|
return TRUE;
|
|
|
|
error3:
|
|
Unlock();
|
|
Shutdown( &fDelete );
|
|
Lock();
|
|
error2:
|
|
closesocket( Q931CallSocket );
|
|
error1:
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!aleways called in a lock
|
|
BOOL
|
|
CH323Call::AcceptH323Call(void)
|
|
{
|
|
DWORD dwAPDUType = NO_H450_APDU;
|
|
DWORD dwInvokeID = NO_INVOKEID;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "AcceptH323Call entered: %p.", this ));
|
|
|
|
if( m_dwCallType & CALLTYPE_DIVERTEDDEST )
|
|
{
|
|
dwAPDUType = (DIVERTINGLEGINFO3_OPCODE | H450_INVOKE);
|
|
}
|
|
else if( m_dwCallType & CALLTYPE_TRANSFEREDDEST )
|
|
{
|
|
dwAPDUType = (CTSETUP_OPCODE | H450_RETURNRESULT);
|
|
dwInvokeID = m_dwInvokeID;
|
|
}
|
|
|
|
ChangeCallState( LINECALLSTATE_ACCEPTED, 0 );
|
|
|
|
//if pCall Divert On No Answer is enabled, then stop the timer
|
|
if( m_hCallDivertOnNATimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCallDivertOnNATimer, NULL );
|
|
m_hCallDivertOnNATimer = NULL;
|
|
}
|
|
|
|
//encode and send Q931Connect message to the peer
|
|
if( !SendQ931Message( dwInvokeID, 0, 0, CONNECTMESSAGETYPE, dwAPDUType ) )
|
|
{
|
|
//post a message to the callback thread to shutdown the H323 call
|
|
CloseCall( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
m_dwStateMachine = Q931_CONNECT_SENT;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "AcceptH323Call exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::SendQ931Message(
|
|
IN DWORD dwInvokeID,
|
|
IN ULONG_PTR dwParam1,
|
|
IN ULONG_PTR dwParam2,
|
|
IN DWORD dwMessageType,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
BINARY_STRING userUserData;
|
|
DWORD dwCodedLengthPDU;
|
|
BYTE *pbCodedPDU;
|
|
BOOL retVal = FALSE;
|
|
WCHAR * pwszCalledPartyNumber = NULL;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendQ931Message entered: %p.", this ));
|
|
|
|
//check if socket is connected
|
|
if( !(m_dwQ931Flags & Q931_CALL_CONNECTED) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
switch ( dwMessageType )
|
|
{
|
|
//encode the UU message
|
|
case SETUPMESSAGETYPE:
|
|
retVal = EncodeSetupMessage( dwInvokeID, (WORD)dwParam1, //dwGoal
|
|
(WORD)dwParam2, //dwCalType
|
|
&userUserData.pbBuffer,
|
|
&userUserData.length,
|
|
dwAPDUType );
|
|
break;
|
|
|
|
case ALERTINGMESSAGETYPE:
|
|
retVal = EncodeAlertMessage( dwInvokeID,
|
|
&userUserData.pbBuffer,
|
|
&userUserData.length,
|
|
dwAPDUType );
|
|
break;
|
|
|
|
case PROCEEDINGMESSAGETYPE:
|
|
retVal = EncodeProceedingMessage( dwInvokeID,
|
|
&userUserData.pbBuffer,
|
|
&userUserData.length,
|
|
dwAPDUType );
|
|
break;
|
|
|
|
case RELEASECOMPLMESSAGETYPE:
|
|
retVal = EncodeReleaseCompleteMessage( dwInvokeID,
|
|
(BYTE*)dwParam1, //pbReason
|
|
&userUserData.pbBuffer,
|
|
&userUserData.length,
|
|
dwAPDUType );
|
|
break;
|
|
|
|
case CONNECTMESSAGETYPE:
|
|
retVal = EncodeConnectMessage( dwInvokeID,
|
|
&userUserData.pbBuffer,
|
|
&userUserData.length,
|
|
dwAPDUType );
|
|
break;
|
|
|
|
case FACILITYMESSAGETYPE:
|
|
retVal = EncodeFacilityMessage( dwInvokeID,
|
|
(BYTE)dwParam1,
|
|
(ASN1octetstring_t*)dwParam2,
|
|
&userUserData.pbBuffer,
|
|
&userUserData.length,
|
|
dwAPDUType );
|
|
break;
|
|
}
|
|
|
|
if( retVal == FALSE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not encode message:%d.", dwMessageType));
|
|
|
|
if( userUserData.pbBuffer )
|
|
{
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, userUserData.pbBuffer );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if (m_dwAddressType == LINEADDRESSTYPE_PHONENUMBER)
|
|
{
|
|
_ASSERTE( m_pCalleeAliasNames->pItems[0].wType == e164_chosen );
|
|
pwszCalledPartyNumber = m_pCalleeAliasNames ->pItems[0].pData;
|
|
}
|
|
|
|
//encode the PDU
|
|
retVal = EncodePDU( &userUserData,
|
|
&pbCodedPDU,
|
|
&dwCodedLengthPDU,
|
|
dwMessageType,
|
|
pwszCalledPartyNumber );
|
|
|
|
if( retVal == FALSE )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR,
|
|
"could not encode PDU: %d.", dwMessageType ));
|
|
}
|
|
else if(!SendBuffer( pbCodedPDU, dwCodedLengthPDU ))
|
|
{
|
|
retVal = FALSE;
|
|
}
|
|
|
|
if( userUserData.pbBuffer )
|
|
{
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, userUserData.pbBuffer );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "SendQ931Message exited: %p.", this ));
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeFastStartProposal(
|
|
PH323_FASTSTART pFastStart,
|
|
BYTE** ppEncodedBuf,
|
|
WORD* pwEncodedLength
|
|
)
|
|
{
|
|
int rc;
|
|
H323_UserInformation UserInfo;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeFastStartProposal entered: %p.", this ));
|
|
|
|
CallProceeding_UUIE & proceedingMessage =
|
|
UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pwEncodedLength = 0;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
UserInfo.bit_mask = 0;
|
|
|
|
|
|
//copy the call identifier
|
|
proceedingMessage.bit_mask |= CallProceeding_UUIE_callIdentifier_present;
|
|
CopyMemory( (PVOID)&proceedingMessage.callIdentifier.guid.value,
|
|
(PVOID)&m_callIdentifier,
|
|
sizeof(GUID) );
|
|
proceedingMessage.callIdentifier.guid.length = sizeof(GUID);
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = callProceeding_chosen;
|
|
proceedingMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
|
|
proceedingMessage.bit_mask |= CallProceeding_UUIE_fastStart_present;
|
|
proceedingMessage.fastStart = (PCallProceeding_UUIE_fastStart)pFastStart;
|
|
|
|
rc = EncodeASN( (void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pwEncodedLength);
|
|
|
|
if (ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pwEncodedLength == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeFastStartProposal exited: %p.", this ));
|
|
//success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeFacilityMessage(
|
|
IN DWORD dwInvokeID,
|
|
IN BYTE bReason,
|
|
IN ASN1octetstring_t* pH245PDU,
|
|
OUT BYTE **ppEncodedBuf,
|
|
OUT WORD *pdwEncodedLength,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
H323_UU_PDU_h4501SupplementaryService h4501APDU;
|
|
int rc;
|
|
H323_UserInformation UserInfo;
|
|
DWORD dwAPDULen = 0;
|
|
BYTE* pEncodedAPDU = NULL;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeFacilityMessage entered: %p.", this ));
|
|
|
|
Facility_UUIE & facilityMessage =
|
|
UserInfo.h323_uu_pdu.h323_message_body.u.facility;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pdwEncodedLength = 0;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
UserInfo.bit_mask = 0;
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
//send the appropriate ADPDUS
|
|
if( dwAPDUType != NO_H450_APDU )
|
|
{
|
|
if( !EncodeH450APDU(dwInvokeID, dwAPDUType,
|
|
&pEncodedAPDU, &dwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService = &h4501APDU;
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> next = NULL;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.value = pEncodedAPDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.length = dwAPDULen;
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask |= h4501SupplementaryService_present;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h245Tunneling = FALSE;//(m_fh245Tunneling & LOCAL_H245_TUNNELING);
|
|
UserInfo.h323_uu_pdu.bit_mask |= h245Tunneling_present;
|
|
|
|
SetNonStandardData( UserInfo );
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = facility_chosen;
|
|
|
|
facilityMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
facilityMessage.bit_mask = 0;
|
|
|
|
TransportAddress& transportAddress = facilityMessage.alternativeAddress;
|
|
|
|
if( IsGuidSet( &m_ConferenceID ) )
|
|
{
|
|
CopyConferenceID(&facilityMessage.conferenceID, &m_ConferenceID);
|
|
facilityMessage.bit_mask |= Facility_UUIE_conferenceID_present;
|
|
}
|
|
|
|
switch (bReason)
|
|
{
|
|
case H323_REJECT_ROUTE_TO_GATEKEEPER:
|
|
facilityMessage.reason.choice =
|
|
FacilityReason_routeCallToGatekeeper_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_CALL_FORWARDED:
|
|
facilityMessage.reason.choice = callForwarded_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_ROUTE_TO_MC:
|
|
facilityMessage.reason.choice = routeCallToMC_chosen;
|
|
break;
|
|
|
|
default:
|
|
facilityMessage.reason.choice = FacilityReason_undefinedReason_chosen;
|
|
}
|
|
|
|
facilityMessage.bit_mask |= Facility_UUIE_callIdentifier_present;
|
|
CopyMemory( (PVOID)&facilityMessage.callIdentifier.guid.value,
|
|
(PVOID)"abcdabcdabcdabcdabcd",
|
|
sizeof(GUID) );
|
|
facilityMessage.callIdentifier.guid.length = sizeof(GUID);
|
|
|
|
if( pH245PDU && (pH245PDU->value != NULL) )
|
|
{
|
|
//h245 PDU to be sent
|
|
UserInfo.h323_uu_pdu.h245Control->next = NULL;
|
|
UserInfo.h323_uu_pdu.h245Control->value.length = pH245PDU->length;
|
|
UserInfo.h323_uu_pdu.h245Control->value.value = pH245PDU->value;
|
|
}
|
|
|
|
rc = EncodeASN((void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pdwEncodedLength);
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pdwEncodedLength == 0) )
|
|
{
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeFacilityMessage exited: %p.", this ));
|
|
//success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeAlertMessage(
|
|
IN DWORD dwInvokeID,
|
|
OUT BYTE **ppEncodedBuf,
|
|
OUT WORD *pdwEncodedLength,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
H323_UU_PDU_h4501SupplementaryService h4501APDU;
|
|
int rc;
|
|
H323_UserInformation UserInfo;
|
|
DWORD dwAPDULen = 0;
|
|
BYTE* pEncodedAPDU = NULL;
|
|
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeAlertMessage entered: %p.", this ));
|
|
|
|
Alerting_UUIE & alertingMessage =
|
|
UserInfo.h323_uu_pdu.h323_message_body.u.alerting;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pdwEncodedLength = 0;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
UserInfo.bit_mask = 0;
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
if( dwAPDUType != NO_H450_APDU )
|
|
{
|
|
if( !EncodeH450APDU( dwInvokeID, dwAPDUType, &pEncodedAPDU, &dwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService = &h4501APDU;
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> next = NULL;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.value = pEncodedAPDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.length = dwAPDULen;
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask |= h4501SupplementaryService_present;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h245Tunneling = FALSE;//(m_fh245Tunneling & LOCAL_H245_TUNNELING);
|
|
UserInfo.h323_uu_pdu.bit_mask |= h245Tunneling_present;
|
|
|
|
SetNonStandardData( UserInfo );
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = alerting_chosen;
|
|
|
|
alertingMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
alertingMessage.destinationInfo.bit_mask = 0;
|
|
|
|
//copy the vendor info
|
|
alertingMessage.destinationInfo.bit_mask |= vendor_present;
|
|
CopyVendorInfo( &alertingMessage.destinationInfo.vendor );
|
|
|
|
//its a terminal
|
|
alertingMessage.destinationInfo.bit_mask = terminal_present;
|
|
alertingMessage.destinationInfo.terminal.bit_mask = 0;
|
|
|
|
//not na MC
|
|
alertingMessage.destinationInfo.mc = 0;
|
|
alertingMessage.destinationInfo.undefinedNode = 0;
|
|
|
|
TransportAddress& transportAddress = alertingMessage.h245Address;
|
|
|
|
//send H245 address only if the caller hasn't proposed FasrStart
|
|
//or the fast start proposal has been accepeted
|
|
if( (m_pPeerFastStart == NULL) || m_pFastStart )
|
|
{
|
|
if( m_selfH245Addr.Addr.IP_Binary.dwAddr != 0 )
|
|
{
|
|
CopyTransportAddress( transportAddress, &m_selfH245Addr );
|
|
alertingMessage.bit_mask |= (Alerting_UUIE_h245Address_present);
|
|
}
|
|
else
|
|
{
|
|
alertingMessage.bit_mask &= (~Alerting_UUIE_h245Address_present);
|
|
}
|
|
}
|
|
|
|
if( m_pFastStart != NULL )
|
|
{
|
|
_ASSERTE( m_pPeerFastStart );
|
|
alertingMessage.bit_mask |= Alerting_UUIE_fastStart_present;
|
|
alertingMessage.fastStart = (PAlerting_UUIE_fastStart)m_pFastStart;
|
|
}
|
|
else
|
|
{
|
|
alertingMessage.bit_mask &= ~Alerting_UUIE_fastStart_present;
|
|
}
|
|
|
|
//copy the call identifier
|
|
alertingMessage.bit_mask |= Alerting_UUIE_callIdentifier_present;
|
|
CopyMemory( (PVOID)&alertingMessage.callIdentifier.guid.value,
|
|
(PVOID)&m_callIdentifier,
|
|
sizeof(GUID) );
|
|
alertingMessage.callIdentifier.guid.length = sizeof(GUID);
|
|
|
|
|
|
rc = EncodeASN( (void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pdwEncodedLength);
|
|
|
|
if (ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pdwEncodedLength == 0) )
|
|
{
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeAlertMessage exited: %p.", this ));
|
|
//success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeProceedingMessage(
|
|
IN DWORD dwInvokeID,
|
|
OUT BYTE **ppEncodedBuf,
|
|
OUT WORD *pdwEncodedLength,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
H323_UU_PDU_h4501SupplementaryService h4501APDU;
|
|
int rc;
|
|
H323_UserInformation UserInfo;
|
|
DWORD dwAPDULen = 0;
|
|
BYTE* pEncodedAPDU = NULL;
|
|
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeProceedingMessage entered: %p.", this ));
|
|
|
|
CallProceeding_UUIE & proceedingMessage =
|
|
UserInfo.h323_uu_pdu.h323_message_body.u.callProceeding;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pdwEncodedLength = 0;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
UserInfo.bit_mask = 0;
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
if( dwAPDUType != NO_H450_APDU )
|
|
{
|
|
if( !EncodeH450APDU( dwInvokeID, dwAPDUType, &pEncodedAPDU, &dwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService = &h4501APDU;
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> next = NULL;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.value = pEncodedAPDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.length = dwAPDULen;
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask |= h4501SupplementaryService_present;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h245Tunneling = FALSE;//(m_fh245Tunneling & LOCAL_H245_TUNNELING);
|
|
UserInfo.h323_uu_pdu.bit_mask |= h245Tunneling_present;
|
|
|
|
SetNonStandardData( UserInfo );
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = callProceeding_chosen;
|
|
proceedingMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
|
|
TransportAddress& transportAddress = proceedingMessage.h245Address;
|
|
|
|
//send H245 address only if the caller hasn't proposed FasrStart
|
|
//or the fast start proposal has been accepeted
|
|
if( (m_pPeerFastStart == NULL) || m_pFastStart )
|
|
{
|
|
if( m_selfH245Addr.Addr.IP_Binary.dwAddr != 0 )
|
|
{
|
|
CopyTransportAddress( transportAddress, &m_selfH245Addr );
|
|
proceedingMessage.bit_mask |= CallProceeding_UUIE_h245Address_present;
|
|
}
|
|
else
|
|
{
|
|
proceedingMessage.bit_mask &= ~CallProceeding_UUIE_h245Address_present;
|
|
}
|
|
}
|
|
|
|
proceedingMessage.destinationInfo.bit_mask = 0;
|
|
|
|
//copy the vendor info
|
|
proceedingMessage.destinationInfo.bit_mask |= vendor_present;
|
|
CopyVendorInfo( &proceedingMessage.destinationInfo.vendor );
|
|
|
|
proceedingMessage.destinationInfo.mc = 0;
|
|
proceedingMessage.destinationInfo.undefinedNode = 0;
|
|
|
|
if( m_pFastStart != NULL )
|
|
{
|
|
_ASSERTE( m_pPeerFastStart );
|
|
proceedingMessage.bit_mask |= Alerting_UUIE_fastStart_present;
|
|
proceedingMessage.fastStart =
|
|
(PCallProceeding_UUIE_fastStart)m_pFastStart;
|
|
}
|
|
else
|
|
{
|
|
proceedingMessage.bit_mask &= ~Alerting_UUIE_fastStart_present;
|
|
}
|
|
|
|
//copy the call identifier
|
|
proceedingMessage.bit_mask |= CallProceeding_UUIE_callIdentifier_present;
|
|
CopyMemory( (PVOID)&proceedingMessage.callIdentifier.guid.value,
|
|
(PVOID)&m_callIdentifier,
|
|
sizeof(GUID) );
|
|
proceedingMessage.callIdentifier.guid.length = sizeof(GUID);
|
|
|
|
rc = EncodeASN( (void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pdwEncodedLength);
|
|
|
|
if (ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pdwEncodedLength == 0) )
|
|
{
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeProceedingMessage exited: %p.", this ));
|
|
//success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeReleaseCompleteMessage(
|
|
IN DWORD dwInvokeID,
|
|
IN BYTE *pbReason,
|
|
OUT BYTE **ppEncodedBuf,
|
|
OUT WORD *pdwEncodedLength,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
H323_UU_PDU_h4501SupplementaryService h4501APDU;
|
|
int rc;
|
|
H323_UserInformation UserInfo;
|
|
DWORD dwAPDULen = 0;
|
|
BYTE* pEncodedAPDU = NULL;
|
|
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeReleaseCompleteMessage entered: %p.", this ));
|
|
|
|
ReleaseComplete_UUIE & releaseMessage =
|
|
UserInfo.h323_uu_pdu.h323_message_body.u.releaseComplete;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pdwEncodedLength = 0;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
UserInfo.bit_mask = 0;
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
if( dwAPDUType != NO_H450_APDU )
|
|
{
|
|
if( !EncodeH450APDU( dwInvokeID, dwAPDUType, &pEncodedAPDU, &dwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService = &h4501APDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> next = NULL;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.value = pEncodedAPDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.length = dwAPDULen;
|
|
UserInfo.h323_uu_pdu.bit_mask |= h4501SupplementaryService_present;
|
|
}
|
|
|
|
SetNonStandardData( UserInfo );
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = releaseComplete_chosen;
|
|
|
|
releaseMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
|
|
if( pbReason )
|
|
{
|
|
releaseMessage.reason.choice = 0;
|
|
releaseMessage.bit_mask |= (ReleaseComplete_UUIE_reason_present);
|
|
|
|
switch (*pbReason)
|
|
{
|
|
case H323_REJECT_NO_BANDWIDTH:
|
|
releaseMessage.reason.choice = noBandwidth_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_GATEKEEPER_RESOURCES:
|
|
releaseMessage.reason.choice = gatekeeperResources_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_UNREACHABLE_DESTINATION:
|
|
releaseMessage.reason.choice = unreachableDestination_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_DESTINATION_REJECTION:
|
|
releaseMessage.reason.choice = destinationRejection_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_INVALID_REVISION:
|
|
releaseMessage.reason.choice
|
|
= ReleaseCompleteReason_invalidRevision_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_NO_PERMISSION:
|
|
releaseMessage.reason.choice = noPermission_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_UNREACHABLE_GATEKEEPER:
|
|
releaseMessage.reason.choice = unreachableGatekeeper_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_GATEWAY_RESOURCES:
|
|
releaseMessage.reason.choice = gatewayResources_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_BAD_FORMAT_ADDRESS:
|
|
releaseMessage.reason.choice = badFormatAddress_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_ADAPTIVE_BUSY:
|
|
releaseMessage.reason.choice = adaptiveBusy_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_IN_CONF:
|
|
releaseMessage.reason.choice = inConf_chosen;
|
|
break;
|
|
|
|
case H323_REJECT_CALL_DEFLECTION:
|
|
releaseMessage.reason.choice =
|
|
ReleaseCompleteReason_undefinedReason_chosen ;
|
|
break;
|
|
|
|
case H323_REJECT_UNDEFINED_REASON:
|
|
releaseMessage.reason.choice = ReleaseCompleteReason_undefinedReason_chosen ;
|
|
break;
|
|
|
|
case H323_REJECT_USER_BUSY:
|
|
releaseMessage.reason.choice = inConf_chosen;
|
|
break;
|
|
|
|
default:
|
|
//log
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
rc = EncodeASN( (void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pdwEncodedLength);
|
|
|
|
if (ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pdwEncodedLength == 0) )
|
|
{
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeReleaseCompleteMessage exited: %p.", this ));
|
|
//success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeConnectMessage(
|
|
IN DWORD dwInvokeID,
|
|
OUT BYTE **ppEncodedBuf,
|
|
OUT WORD *pdwEncodedLength,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
H323_UU_PDU_h4501SupplementaryService h4501APDU;
|
|
int rc;
|
|
H323_UserInformation UserInfo;
|
|
DWORD dwAPDULen = 0;
|
|
BYTE* pEncodedAPDU = NULL;
|
|
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeConnectMessage entered: %p.", this ));
|
|
|
|
Connect_UUIE & connectMessage =
|
|
UserInfo.h323_uu_pdu.h323_message_body.u.connect;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pdwEncodedLength = 0;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
UserInfo.bit_mask = 0;
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
//send the appropriate ADPDUS
|
|
if( dwAPDUType != NO_H450_APDU )
|
|
{
|
|
if( !EncodeH450APDU( dwInvokeID, dwAPDUType,
|
|
&pEncodedAPDU, &dwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService = &h4501APDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> next = NULL;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.value = pEncodedAPDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.length = dwAPDULen;
|
|
UserInfo.h323_uu_pdu.bit_mask |= h4501SupplementaryService_present;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h245Tunneling = FALSE;//(m_fh245Tunneling & LOCAL_H245_TUNNELING);
|
|
UserInfo.h323_uu_pdu.bit_mask |= h245Tunneling_present;
|
|
|
|
SetNonStandardData( UserInfo );
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = connect_chosen;
|
|
|
|
connectMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
|
|
TransportAddress& transportAddress = connectMessage.h245Address;
|
|
CopyTransportAddress( transportAddress, &m_selfH245Addr );
|
|
connectMessage.bit_mask |= (Connect_UUIE_h245Address_present);
|
|
|
|
connectMessage.destinationInfo.bit_mask = 0;
|
|
|
|
//copy the vendor info
|
|
connectMessage.destinationInfo.bit_mask |= vendor_present;
|
|
CopyVendorInfo( &connectMessage.destinationInfo.vendor );
|
|
|
|
//terminal is present
|
|
connectMessage.destinationInfo.bit_mask |= terminal_present;
|
|
connectMessage.destinationInfo.terminal.bit_mask = 0;
|
|
|
|
connectMessage.destinationInfo.mc = 0;
|
|
connectMessage.destinationInfo.undefinedNode = 0;
|
|
|
|
//copy the 16 byte conference ID
|
|
CopyConferenceID (&connectMessage.conferenceID, &m_ConferenceID);
|
|
|
|
if( m_pFastStart != NULL )
|
|
{
|
|
_ASSERTE( m_pPeerFastStart );
|
|
connectMessage.bit_mask |= Connect_UUIE_fastStart_present;
|
|
connectMessage.fastStart = (PConnect_UUIE_fastStart)m_pFastStart;
|
|
}
|
|
else
|
|
{
|
|
connectMessage.bit_mask &= ~Alerting_UUIE_fastStart_present;
|
|
}
|
|
|
|
//copy the call identifier
|
|
connectMessage.bit_mask |= Connect_UUIE_callIdentifier_present;
|
|
CopyMemory( (PVOID)&connectMessage.callIdentifier.guid.value,
|
|
(PVOID)&m_callIdentifier,
|
|
sizeof(GUID) );
|
|
connectMessage.callIdentifier.guid.length = sizeof(GUID);
|
|
|
|
rc = EncodeASN( (void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pdwEncodedLength);
|
|
|
|
if (ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pdwEncodedLength == 0) )
|
|
{
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeConnectMessage exited: %p.", this ));
|
|
//success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void CH323Call::SetNonStandardData(
|
|
OUT H323_UserInformation & UserInfo
|
|
)
|
|
{
|
|
if( m_NonStandardData.sData.pOctetString )
|
|
{
|
|
H221NonStandard & nonStd =
|
|
UserInfo.h323_uu_pdu.nonStandardData.nonStandardIdentifier.u.h221NonStandard;
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask |= H323_UU_PDU_nonStandardData_present;
|
|
|
|
UserInfo.h323_uu_pdu.nonStandardData.nonStandardIdentifier.choice
|
|
= H225NonStandardIdentifier_h221NonStandard_chosen;
|
|
|
|
nonStd.t35CountryCode = m_NonStandardData.bCountryCode;
|
|
nonStd.t35Extension = m_NonStandardData.bExtension;
|
|
nonStd.manufacturerCode = m_NonStandardData.wManufacturerCode;
|
|
|
|
UserInfo.h323_uu_pdu.nonStandardData.data.length =
|
|
m_NonStandardData.sData.wOctetStringLength;
|
|
|
|
UserInfo.h323_uu_pdu.nonStandardData.data.value =
|
|
m_NonStandardData.sData.pOctetString;
|
|
|
|
// Maintain only one reference to the buffer.
|
|
m_NonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
else
|
|
{
|
|
UserInfo.h323_uu_pdu.bit_mask &= (~H323_UU_PDU_nonStandardData_present);
|
|
}
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeSetupMessage(
|
|
IN DWORD dwInvokeID,
|
|
IN WORD wGoal,
|
|
IN WORD wCallType,
|
|
OUT BYTE **ppEncodedBuf,
|
|
OUT WORD *pdwEncodedLength,
|
|
IN DWORD dwAPDUType
|
|
)
|
|
{
|
|
H323_UU_PDU_h4501SupplementaryService h4501APDU;
|
|
H323_UserInformation UserInfo;
|
|
int rc = 0;
|
|
BOOL retVal = TRUE;
|
|
DWORD dwAPDULen = 0;
|
|
BYTE* pEncodedAPDU = NULL;
|
|
|
|
*ppEncodedBuf = NULL;
|
|
*pdwEncodedLength = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeSetupMessage entered: %p.", this ));
|
|
|
|
Setup_UUIE & setupMessage = UserInfo.h323_uu_pdu.h323_message_body.u.setup;
|
|
TransportAddress& calleeAddr = setupMessage.destCallSignalAddress;
|
|
TransportAddress& callerAddr = setupMessage.sourceCallSignalAddress;
|
|
|
|
memset( (PVOID)&UserInfo, 0, sizeof(H323_UserInformation));
|
|
|
|
UserInfo.bit_mask = 0;
|
|
|
|
// make sure the user_data_present flag is turned off.
|
|
UserInfo.bit_mask &= (~user_data_present);
|
|
|
|
UserInfo.h323_uu_pdu.bit_mask = 0;
|
|
|
|
//send the appropriate ADPDUS
|
|
if( dwAPDUType != NO_H450_APDU )
|
|
{
|
|
if( !EncodeH450APDU( dwInvokeID, dwAPDUType, &pEncodedAPDU, &dwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService = &h4501APDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> next = NULL;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.value = pEncodedAPDU;
|
|
UserInfo.h323_uu_pdu.h4501SupplementaryService -> value.length = dwAPDULen;
|
|
UserInfo.h323_uu_pdu.bit_mask |= h4501SupplementaryService_present;
|
|
}
|
|
|
|
UserInfo.h323_uu_pdu.h245Tunneling = FALSE;//(m_fh245Tunneling & LOCAL_H245_TUNNELING);
|
|
UserInfo.h323_uu_pdu.bit_mask |= h245Tunneling_present;
|
|
|
|
SetNonStandardData( UserInfo );
|
|
|
|
UserInfo.h323_uu_pdu.h323_message_body.choice = setup_chosen;
|
|
setupMessage.bit_mask = 0;
|
|
|
|
setupMessage.protocolIdentifier = OID_H225ProtocolIdentifierV2;
|
|
|
|
if( m_pCallerAliasNames && m_pCallerAliasNames -> wCount )
|
|
{
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
setupMessage.sourceAddress = SetMsgAddressAlias(m_pCallerAliasNames);
|
|
|
|
if( setupMessage.sourceAddress != NULL )
|
|
{
|
|
setupMessage.bit_mask |= (sourceAddress_present);
|
|
}
|
|
else
|
|
{
|
|
setupMessage.bit_mask &= (~sourceAddress_present);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
setupMessage.bit_mask &= (~sourceAddress_present);
|
|
}
|
|
|
|
setupMessage.sourceInfo.bit_mask = 0;
|
|
|
|
//pass the vendor info
|
|
setupMessage.sourceInfo.bit_mask |= vendor_present;
|
|
CopyVendorInfo( &setupMessage.sourceInfo.vendor );
|
|
|
|
//terminal is present
|
|
setupMessage.sourceInfo.bit_mask |= terminal_present;
|
|
setupMessage.sourceInfo.terminal.bit_mask = 0;
|
|
|
|
//not an MC
|
|
setupMessage.sourceInfo.mc = FALSE;
|
|
setupMessage.sourceInfo.undefinedNode = 0;
|
|
|
|
if( m_pCalleeAliasNames && m_pCalleeAliasNames -> wCount )
|
|
{
|
|
setupMessage.destinationAddress = (PSetup_UUIE_destinationAddress)
|
|
SetMsgAddressAlias( m_pCalleeAliasNames );
|
|
|
|
if( setupMessage.destinationAddress != NULL )
|
|
{
|
|
setupMessage.bit_mask |= (destinationAddress_present);
|
|
}
|
|
else
|
|
{
|
|
setupMessage.bit_mask &= (~destinationAddress_present);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
setupMessage.bit_mask &= (~destinationAddress_present);
|
|
}
|
|
|
|
//extra alias not present
|
|
setupMessage.bit_mask &= (~Setup_UUIE_destExtraCallInfo_present );
|
|
|
|
//If talking to gateway then don't pass on destn call signal address
|
|
if( m_dwAddressType != LINEADDRESSTYPE_PHONENUMBER )
|
|
{
|
|
CopyTransportAddress( calleeAddr, &m_CalleeAddr );
|
|
setupMessage.bit_mask |= Setup_UUIE_destCallSignalAddress_present;
|
|
}
|
|
|
|
//not an MC
|
|
setupMessage.activeMC = m_fActiveMC;
|
|
|
|
//copy the 16 byte conference ID
|
|
CopyConferenceID (&setupMessage.conferenceID, &m_ConferenceID);
|
|
|
|
//copy the call identifier
|
|
setupMessage.bit_mask |= Setup_UUIE_callIdentifier_present;
|
|
CopyConferenceID (&setupMessage.callIdentifier.guid, &m_callIdentifier);
|
|
|
|
//fast start params
|
|
if( m_pFastStart != NULL )
|
|
{
|
|
setupMessage.bit_mask |= Setup_UUIE_fastStart_present;
|
|
setupMessage.fastStart = (PSetup_UUIE_fastStart)m_pFastStart;
|
|
}
|
|
else
|
|
{
|
|
setupMessage.bit_mask &= ~Setup_UUIE_fastStart_present;
|
|
}
|
|
|
|
//copy media wait for connect
|
|
setupMessage.mediaWaitForConnect = FALSE;
|
|
|
|
setupMessage.conferenceGoal.choice = (BYTE)wGoal;
|
|
setupMessage.callType.choice = (BYTE)wCallType;
|
|
|
|
CopyTransportAddress( callerAddr, &m_CallerAddr );
|
|
setupMessage.bit_mask |= sourceCallSignalAddress_present;
|
|
|
|
//no extension alias
|
|
setupMessage.bit_mask &= (~Setup_UUIE_remoteExtensionAddress_present);
|
|
|
|
rc = EncodeASN( (void *) &UserInfo,
|
|
H323_UserInformation_PDU,
|
|
ppEncodedBuf,
|
|
pdwEncodedLength);
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedBuf == NULL) || (pdwEncodedLength == 0) )
|
|
{
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
retVal = FALSE;
|
|
}
|
|
|
|
// Free the alias name structures from the UserInfo area.
|
|
if( setupMessage.bit_mask & sourceAddress_present )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
setupMessage.sourceAddress );
|
|
}
|
|
|
|
if( setupMessage.bit_mask & destinationAddress_present )
|
|
{
|
|
FreeAddressAliases( setupMessage.destinationAddress );
|
|
}
|
|
|
|
if( pEncodedAPDU != NULL )
|
|
{
|
|
ASN1_FreeEncoded(m_H450ASNCoderInfo.pEncInfo, pEncodedAPDU );
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeSetupMessage exited: %p.", this ));
|
|
//success/failure
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeH450APDU(
|
|
IN DWORD dwInvokeID,
|
|
IN DWORD dwAPDUType,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
H4501SupplementaryService SupplementaryServiceAPDU;
|
|
ServiceApdus_rosApdus rosAPDU;
|
|
DWORD dwErrorCode = 0;
|
|
DWORD dwOperationType = (dwAPDUType & 0x0000FF00);
|
|
dwAPDUType &= 0x000000FF;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeH450APDU entered: %p.", this ));
|
|
|
|
ZeroMemory( (PVOID)&SupplementaryServiceAPDU,
|
|
sizeof(H4501SupplementaryService) );
|
|
|
|
//interpretationAPDU
|
|
SupplementaryServiceAPDU.interpretationApdu.choice =
|
|
rejectAnyUnrecognizedInvokePdu_chosen;
|
|
SupplementaryServiceAPDU.bit_mask |= interpretationApdu_present;
|
|
|
|
//NFE
|
|
SupplementaryServiceAPDU.networkFacilityExtension.bit_mask = 0;
|
|
SupplementaryServiceAPDU.networkFacilityExtension.destinationEntity.choice
|
|
= endpoint_chosen;
|
|
SupplementaryServiceAPDU.networkFacilityExtension.sourceEntity.choice
|
|
= endpoint_chosen;
|
|
SupplementaryServiceAPDU.bit_mask |= networkFacilityExtension_present;
|
|
|
|
//serviceAPDUS
|
|
SupplementaryServiceAPDU.serviceApdu.choice = rosApdus_chosen;
|
|
SupplementaryServiceAPDU.serviceApdu.u.rosApdus = &rosAPDU;
|
|
SupplementaryServiceAPDU.serviceApdu.u.rosApdus->next = NULL;
|
|
|
|
if( dwOperationType == H450_REJECT )
|
|
{
|
|
if( !EncodeRejectAPDU( &SupplementaryServiceAPDU, dwInvokeID,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else if( dwOperationType == H450_RETURNERROR )
|
|
{
|
|
EncodeReturnErrorAPDU( dwInvokeID, dwErrorCode,
|
|
&SupplementaryServiceAPDU, ppEncodedAPDU, pdwAPDULen );
|
|
}
|
|
else if( dwOperationType == H450_RETURNRESULT )
|
|
{
|
|
if( !EncodeDummyReturnResultAPDU( dwInvokeID,
|
|
dwAPDUType, &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
else //H450_INVOKE
|
|
{
|
|
switch( dwAPDUType )
|
|
{
|
|
case CHECKRESTRICTION_OPCODE:
|
|
|
|
if( !EncodeCheckRestrictionAPDU( &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case CALLREROUTING_OPCODE:
|
|
|
|
if( !EncodeCallReroutingAPDU( &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case DIVERTINGLEGINFO2_OPCODE:
|
|
|
|
if( !EncodeDivertingLeg2APDU( &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case DIVERTINGLEGINFO3_OPCODE:
|
|
|
|
if( !EncodeDivertingLeg3APDU( &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case HOLDNOTIFIC_OPCODE:
|
|
case REMOTEHOLD_OPCODE:
|
|
case RETRIEVENOTIFIC_OPCODE:
|
|
case REMOTERETRIEVE_OPCODE:
|
|
case CTIDENTIFY_OPCODE:
|
|
|
|
if( !EncodeH450APDUNoArgument( dwAPDUType, &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
case CTSETUP_OPCODE:
|
|
|
|
if( !EncodeCTSetupAPDU( &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case CTINITIATE_OPCODE:
|
|
|
|
if( !EncodeCTInitiateAPDU( &SupplementaryServiceAPDU,
|
|
ppEncodedAPDU, pdwAPDULen ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE( 0 );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeH450APDU exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodePDU(
|
|
IN BINARY_STRING *pUserUserData,
|
|
OUT BYTE ** ppbCodedBuffer,
|
|
OUT DWORD * pdwCodedBufferLength,
|
|
IN DWORD dwMessageType,
|
|
WCHAR * pwszCalledPartyNumber
|
|
)
|
|
{
|
|
PQ931MESSAGE pMessage;
|
|
BYTE bBandwidth;
|
|
char pszDisplay[131] = "";
|
|
DWORD dwMessageLength = 0;
|
|
BYTE indexI;
|
|
BOOL retVal;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodePDU entered: %p.", this ));
|
|
|
|
pMessage = new Q931MESSAGE;
|
|
if( pMessage == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// fill in the required fields for the Q931 message.
|
|
memset( (PVOID)pMessage, 0, sizeof(Q931MESSAGE));
|
|
pMessage->ProtocolDiscriminator = Q931PDVALUE;
|
|
pMessage->wCallRef = m_wQ931CallRef;
|
|
pMessage->MessageType = (BYTE)dwMessageType;
|
|
|
|
dwMessageLength +=
|
|
( 1 + sizeof(PDTYPE) + sizeof(CRTYPE) + sizeof(MESSAGEIDTYPE) );
|
|
|
|
if( (dwMessageType == SETUPMESSAGETYPE) ||
|
|
(dwMessageType == CONNECTMESSAGETYPE) )
|
|
{
|
|
if( m_pwszDisplay &&
|
|
WideCharToMultiByte(CP_ACP,
|
|
0,
|
|
m_pwszDisplay,
|
|
-1,
|
|
pszDisplay,
|
|
sizeof(pszDisplay),
|
|
NULL,
|
|
NULL) == 0)
|
|
{
|
|
delete pMessage;
|
|
return FALSE;
|
|
}
|
|
|
|
if( *pszDisplay )
|
|
{
|
|
pMessage->Display.fPresent = TRUE;
|
|
pMessage->Display.dwLength = (BYTE)(strlen(pszDisplay) + 1);
|
|
strcpy((char *)pMessage->Display.pbContents, pszDisplay);
|
|
dwMessageLength += (2 + pMessage->Display.dwLength);
|
|
}
|
|
|
|
pMessage->BearerCapability.fPresent = TRUE;
|
|
pMessage->BearerCapability.dwLength = 3;
|
|
pMessage->BearerCapability.pbContents[0] =
|
|
(BYTE)(BEAR_EXT_BIT | BEAR_CCITT | BEAR_UNRESTRICTED_DIGITAL);
|
|
pMessage->BearerCapability.pbContents[1] =
|
|
(BYTE)(BEAR_EXT_BIT | 0x17); //64kbps
|
|
pMessage->BearerCapability.pbContents[2] = (BYTE)
|
|
(BEAR_EXT_BIT | BEAR_LAYER1_INDICATOR | BEAR_LAYER1_H221_H242);
|
|
|
|
dwMessageLength += (2+pMessage->BearerCapability.dwLength);
|
|
}
|
|
|
|
//if talking to gateway encode the called party number
|
|
if( m_dwAddressType == LINEADDRESSTYPE_PHONENUMBER )
|
|
{
|
|
BYTE bLen = (BYTE)(wcslen(pwszCalledPartyNumber)+1);
|
|
pMessage->CalledPartyNumber.fPresent = TRUE;
|
|
|
|
pMessage->CalledPartyNumber.NumberType =
|
|
(BYTE)(CALLED_PARTY_EXT_BIT | CALLED_PARTY_TYPE_UNKNOWN);
|
|
pMessage->CalledPartyNumber.NumberingPlan =
|
|
(BYTE)(CALLED_PARTY_PLAN_E164);
|
|
pMessage->CalledPartyNumber.PartyNumberLength = bLen;
|
|
|
|
for( indexI =0; indexI < bLen; indexI++ )
|
|
{
|
|
pMessage->CalledPartyNumber.PartyNumbers[indexI] =
|
|
(BYTE)pwszCalledPartyNumber[indexI];
|
|
}
|
|
|
|
dwMessageLength += (2 + pMessage->CalledPartyNumber.PartyNumberLength);
|
|
}
|
|
|
|
if( dwMessageType == FACILITYMESSAGETYPE )
|
|
{
|
|
// The facility ie is encoded as present, but empty...
|
|
pMessage->Facility.fPresent = TRUE;
|
|
pMessage->Facility.dwLength = 0;
|
|
pMessage->Facility.pbContents[0] = 0;
|
|
|
|
dwMessageLength += (2 + pMessage->Facility.dwLength);
|
|
}
|
|
|
|
if (pUserUserData && pUserUserData->pbBuffer)
|
|
{
|
|
if (pUserUserData->length > sizeof(pMessage->UserToUser.pbUserInfo))
|
|
{
|
|
delete pMessage;
|
|
return FALSE;
|
|
}
|
|
pMessage->UserToUser.fPresent = TRUE;
|
|
pMessage->UserToUser.wUserInfoLen = pUserUserData->length;
|
|
|
|
//This CopyMemory should be avoided
|
|
//may be we should do:pMessage->UserToUser.pbUserInfo = pUserUserData->pbBuffer;
|
|
//change the definition of pMessage->UserToUser.pbUserInfo to BYTE* from BYTE[0x1000]
|
|
CopyMemory( (PVOID)pMessage->UserToUser.pbUserInfo,
|
|
(PVOID)pUserUserData->pbBuffer, pUserUserData->length );
|
|
|
|
dwMessageLength += (4+pMessage->UserToUser.wUserInfoLen);
|
|
}
|
|
|
|
_ASSERTE( dwMessageLength );
|
|
|
|
retVal = EncodeMessage( pMessage, ppbCodedBuffer,
|
|
pdwCodedBufferLength, dwMessageLength );
|
|
|
|
delete pMessage;
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::EncodeMessage(
|
|
IN PQ931MESSAGE pMessage,
|
|
OUT BYTE **ppbCodedMessage,
|
|
OUT DWORD *pdwCodedMessageLength,
|
|
IN DWORD dwMessageLength
|
|
)
|
|
{
|
|
BUFFERDESCR pBuf;
|
|
DWORD dwPDULen = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeMessage entered: %p.", this ));
|
|
|
|
*ppbCodedMessage = (BYTE *)new char[ dwMessageLength + 100 ];
|
|
|
|
if( *ppbCodedMessage == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pBuf.dwLength = dwMessageLength + 100;
|
|
|
|
pBuf.pbBuffer = *ppbCodedMessage + TPKT_HEADER_SIZE;
|
|
|
|
WriteQ931Fields(&pBuf, pMessage, &dwPDULen );
|
|
|
|
_ASSERTE( dwPDULen == dwMessageLength );
|
|
|
|
SetupTPKTHeader( *ppbCodedMessage , dwPDULen );
|
|
|
|
*pdwCodedMessageLength = dwPDULen + 4;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeMessage exited: %p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
void
|
|
CH323Call::WriteQ931Fields(
|
|
IN PBUFFERDESCR pBuf,
|
|
IN PQ931MESSAGE pMessage,
|
|
OUT DWORD * pdwPDULen
|
|
)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "WriteQ931Fields entered: %p.", this ));
|
|
|
|
// write the required information elements...
|
|
WriteProtocolDiscriminator( pBuf, pdwPDULen );
|
|
|
|
WriteCallReference( pBuf, &pMessage->wCallRef,
|
|
pdwPDULen );
|
|
|
|
WriteMessageType(pBuf, &pMessage->MessageType,
|
|
pdwPDULen);
|
|
|
|
// try to write all other information elements...
|
|
// don't write this message.
|
|
if (pMessage->Facility.fPresent)
|
|
{
|
|
WriteVariableOctet(pBuf, IDENT_FACILITY,
|
|
pMessage->Facility.dwLength,
|
|
pMessage->Facility.pbContents,
|
|
pdwPDULen);
|
|
}
|
|
|
|
if( pMessage->BearerCapability.fPresent
|
|
&& pMessage->BearerCapability.dwLength )
|
|
{
|
|
WriteVariableOctet(pBuf, IDENT_BEARERCAP,
|
|
pMessage->BearerCapability.dwLength,
|
|
pMessage->BearerCapability.pbContents,
|
|
pdwPDULen);
|
|
}
|
|
|
|
if (pMessage->Display.fPresent && pMessage->Display.dwLength)
|
|
{
|
|
WriteVariableOctet(pBuf, IDENT_DISPLAY,
|
|
pMessage->Display.dwLength,
|
|
pMessage->Display.pbContents,
|
|
pdwPDULen);
|
|
}
|
|
|
|
if( pMessage->CalledPartyNumber.fPresent )
|
|
{
|
|
WritePartyNumber(pBuf,
|
|
IDENT_CALLEDNUMBER,
|
|
pMessage->CalledPartyNumber.NumberType,
|
|
pMessage->CalledPartyNumber.NumberingPlan,
|
|
pMessage->CalledPartyNumber.PartyNumberLength,
|
|
pMessage->CalledPartyNumber.PartyNumbers,
|
|
pdwPDULen);
|
|
}
|
|
|
|
if( pMessage->UserToUser.fPresent &&
|
|
pMessage->UserToUser.wUserInfoLen )
|
|
{
|
|
WriteUserInformation(pBuf,
|
|
IDENT_USERUSER,
|
|
pMessage->UserToUser.wUserInfoLen,
|
|
pMessage->UserToUser.pbUserInfo,
|
|
pdwPDULen);
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "WriteQ931Fields exited: %p.", this ));
|
|
}
|
|
|
|
|
|
//!!always calld in a lock
|
|
void
|
|
CH323Call::HandleTransportEvent(void)
|
|
{
|
|
WSANETWORKEVENTS networkEvents;
|
|
int iError;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleTransportEvent entered: %p.", this ));
|
|
|
|
if( (m_callSocket == INVALID_SOCKET) &&
|
|
(m_dwCallType == CALLTYPE_DIVERTEDSRC) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "The diverted call is not initialized yet."
|
|
"This is probably an event for the primary call. Ignore it %p.",
|
|
this ));
|
|
|
|
return;
|
|
}
|
|
|
|
//find out the event that took place
|
|
if(WSAEnumNetworkEvents(m_callSocket,
|
|
m_hTransport,
|
|
&networkEvents ) == SOCKET_ERROR )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "WSAEnumNetworkEvents error:%d, %lx, %p.",
|
|
WSAGetLastError(), m_callSocket, this ));
|
|
return;
|
|
}
|
|
|
|
if( networkEvents.lNetworkEvents & FD_CLOSE )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "socket close event: %p.", this ));
|
|
|
|
|
|
//if the call is in transition then don't close the call when the
|
|
//old socket gets closed
|
|
if( m_fCallInTrnasition == TRUE )
|
|
{
|
|
//the call is noot in transition mode anymore
|
|
m_fCallInTrnasition = FALSE;
|
|
return;
|
|
}
|
|
//convey the Q931 close status to the TAPI call object
|
|
//and the tapisrv
|
|
iError = networkEvents.iErrorCode[FD_CLOSE_BIT];
|
|
|
|
SetQ931CallState( Q931_CALL_DISCONNECTED );
|
|
|
|
//clean up the Q931 call
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
|
|
//This can occur only for outbound calls
|
|
if( (networkEvents.lNetworkEvents) & FD_CONNECT )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "socket connect event: %p.", this ));
|
|
|
|
//FD_CONNECT event received
|
|
//This func is called by the callback thread when m_hEventQ931Conn is
|
|
//signalled. This function takes care of the outgoing Q931 calls only
|
|
//call the member function
|
|
iError = networkEvents.iErrorCode[FD_CONNECT_BIT];
|
|
if(iError != ERROR_SUCCESS)
|
|
{
|
|
if( (m_dwCallType & CALLTYPE_FORWARDCONSULT )&&
|
|
(m_dwOrigin == LINECALLORIGIN_OUTBOUND ) )
|
|
{
|
|
//Success of forwarding
|
|
EnableCallForwarding();
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_ERROR, "FD_CONNECT returned error: %d.",
|
|
iError ));
|
|
|
|
CloseCall( 0 );
|
|
return;
|
|
}
|
|
OnConnectComplete();
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "HandleTransportEvent exited: %p.", this ));
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::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
|
|
CH323Call::TermASNCoder(void)
|
|
{
|
|
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));
|
|
|
|
return ASN1_SUCCESS;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::EncodeASN(
|
|
IN void * pStruct,
|
|
IN int nPDU,
|
|
OUT BYTE ** ppEncoded,
|
|
OUT WORD * pcbEncodedSize
|
|
)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeASN entered: %p.", this ));
|
|
|
|
ASN1encoding_t pEncInfo = m_ASNCoderInfo.pEncInfo;
|
|
int rc = ASN1_Encode(
|
|
pEncInfo, // ptr to encoder info
|
|
pStruct, // pdu data structure
|
|
nPDU, // pdu id
|
|
ASN1ENCODE_ALLOCATEBUFFER, // flags
|
|
NULL, // do not provide buffer
|
|
0); // buffer size if provided
|
|
if (ASN1_SUCCEEDED(rc))
|
|
{
|
|
if( rc != ASN1_SUCCESS )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "warning while encoding ASN:%d.", rc ));
|
|
}
|
|
*pcbEncodedSize = (WORD)pEncInfo->len; // len of encoded data in buffer
|
|
*ppEncoded = pEncInfo->buf; // buffer to encode into
|
|
}
|
|
else
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "error while encoding ASN:%d.", rc ));
|
|
*pcbEncodedSize = 0;
|
|
*ppEncoded = NULL;
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeASN exited: %p.", this ));
|
|
return rc;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::DecodeASN(
|
|
OUT void ** ppStruct,
|
|
IN int nPDU,
|
|
IN BYTE * pEncoded,
|
|
IN DWORD cbEncodedSize
|
|
)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "h323call DecodeASN entered: %p.", this ));
|
|
ASN1decoding_t pDecInfo = m_ASNCoderInfo.pDecInfo;
|
|
int rc = ASN1_Decode(
|
|
pDecInfo, // ptr to encoder info
|
|
ppStruct, // pdu data structure
|
|
nPDU, // pdu id
|
|
ASN1DECODE_SETBUFFER, // flags
|
|
pEncoded, // do not provide buffer
|
|
cbEncodedSize); // buffer size if provided
|
|
|
|
if (ASN1_SUCCEEDED(rc))
|
|
{
|
|
if( rc != ASN1_SUCCESS )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "warning while deciding ASN:%d.", rc ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "error while deciding ASN:%d.", rc ));
|
|
H323DUMPBUFFER( (BYTE*)pEncoded, cbEncodedSize);
|
|
*ppStruct = NULL;
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "h323call DecodeASN exited: %p.", this ));
|
|
return rc;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::InitH450ASNCoder(void)
|
|
{
|
|
int rc;
|
|
H323DBG((DEBUG_LEVEL_TRACE, "InitH450ASNCoder entered: %p.", this ));
|
|
|
|
memset((PVOID)&m_H450ASNCoderInfo, 0, sizeof(m_H450ASNCoderInfo));
|
|
|
|
if( H4503PP_Module == NULL)
|
|
{
|
|
return ASN1_ERR_BADARGS;
|
|
}
|
|
|
|
rc = ASN1_CreateEncoder(
|
|
H4503PP_Module, // ptr to mdule
|
|
&(m_H450ASNCoderInfo.pEncInfo), // ptr to encoder info
|
|
NULL, // buffer ptr
|
|
0, // buffer size
|
|
NULL); // parent ptr
|
|
if (rc == ASN1_SUCCESS)
|
|
{
|
|
_ASSERTE(m_H450ASNCoderInfo.pEncInfo );
|
|
|
|
rc = ASN1_CreateDecoder(
|
|
H4503PP_Module, // ptr to mdule
|
|
&(m_H450ASNCoderInfo.pDecInfo), // ptr to decoder info
|
|
NULL, // buffer ptr
|
|
0, // buffer size
|
|
NULL ); // parent ptr
|
|
_ASSERTE( m_H450ASNCoderInfo.pDecInfo );
|
|
}
|
|
|
|
if (rc != ASN1_SUCCESS)
|
|
{
|
|
TermH450ASNCoder();
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "InitH450ASNCoder exited: %p.", this ));
|
|
return rc;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::TermH450ASNCoder(void)
|
|
{
|
|
if( H4503PP_Module == NULL )
|
|
{
|
|
return ASN1_ERR_BADARGS;
|
|
}
|
|
|
|
ASN1_CloseEncoder(m_H450ASNCoderInfo.pEncInfo);
|
|
ASN1_CloseDecoder(m_H450ASNCoderInfo.pDecInfo);
|
|
|
|
memset( (PVOID)&m_H450ASNCoderInfo, 0, sizeof(m_ASNCoderInfo));
|
|
|
|
return ASN1_SUCCESS;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::EncodeH450ASN(
|
|
IN void * pStruct,
|
|
IN int nPDU,
|
|
OUT BYTE ** ppEncoded,
|
|
OUT WORD * pcbEncodedSize
|
|
)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeH450ASN entered: %p.", this ));
|
|
|
|
ASN1encoding_t pEncInfo = m_H450ASNCoderInfo.pEncInfo;
|
|
int rc = ASN1_Encode(
|
|
pEncInfo, // ptr to encoder info
|
|
pStruct, // pdu data structure
|
|
nPDU, // pdu id
|
|
ASN1ENCODE_ALLOCATEBUFFER, // flags
|
|
NULL, // do not provide buffer
|
|
0); // buffer size if provided
|
|
if (ASN1_SUCCEEDED(rc))
|
|
{
|
|
if( rc != ASN1_SUCCESS )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "warning while encoding ASN:%d.", rc ));
|
|
}
|
|
*pcbEncodedSize = (WORD)pEncInfo->len; // len of encoded data in buffer
|
|
*ppEncoded = pEncInfo->buf; // buffer to encode into
|
|
}
|
|
else
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "error while encoding ASN:%d.", rc ));
|
|
*pcbEncodedSize = 0;
|
|
*ppEncoded = NULL;
|
|
}
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "EncodeH450ASN exited: %p.", this ));
|
|
return rc;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
int
|
|
CH323Call::DecodeH450ASN(
|
|
OUT void ** ppStruct,
|
|
IN int nPDU,
|
|
IN BYTE * pEncoded,
|
|
IN DWORD cbEncodedSize
|
|
)
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "h323call DecodeH450ASN entered: %p.", this ));
|
|
ASN1decoding_t pDecInfo = m_H450ASNCoderInfo.pDecInfo;
|
|
int rc = ASN1_Decode(
|
|
pDecInfo, // ptr to encoder info
|
|
ppStruct, // pdu data structure
|
|
nPDU, // pdu id
|
|
ASN1DECODE_SETBUFFER, // flags
|
|
pEncoded, // do not provide buffer
|
|
cbEncodedSize); // buffer size if provided
|
|
|
|
if( ASN1_SUCCEEDED(rc) )
|
|
{
|
|
if( rc != ASN1_SUCCESS )
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "warning while deciding ASN:%d.", rc ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
H323DBG((DEBUG_LEVEL_TRACE, "error while deciding ASN:%d.", rc ));
|
|
H323DUMPBUFFER( (BYTE*)pEncoded, cbEncodedSize);
|
|
*ppStruct = NULL;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "h323call DecodeH450ASN exited: %p.", this ));
|
|
return rc;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::ParseReleaseCompleteASN(
|
|
IN BYTE *pEncodedBuf,
|
|
IN DWORD dwEncodedLength,
|
|
OUT Q931_RELEASE_COMPLETE_ASN *pReleaseASN,
|
|
OUT DWORD* pdwH450APDUType
|
|
)
|
|
{
|
|
H323_UserInformation *pUserInfo;
|
|
int iResult;
|
|
DWORD dwInvokeID = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseReleaseCompleteASN entered: %p.", this ));
|
|
|
|
memset( (PVOID)pReleaseASN, 0, sizeof(Q931_RELEASE_COMPLETE_ASN));
|
|
|
|
iResult = DecodeASN((void **) &pUserInfo,
|
|
H323_UserInformation_PDU,
|
|
pEncodedBuf,
|
|
dwEncodedLength);
|
|
|
|
if (ASN1_FAILED(iResult) || (pUserInfo == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
*pdwH450APDUType = 0;
|
|
if( (pUserInfo->h323_uu_pdu.bit_mask & h4501SupplementaryService_present) &&
|
|
pUserInfo->h323_uu_pdu.h4501SupplementaryService )
|
|
{
|
|
if( !HandleH450APDU( pUserInfo->h323_uu_pdu.h4501SupplementaryService,
|
|
pdwH450APDUType, &dwInvokeID, NULL ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// validate that the PDU user-data uses ASN encoding.
|
|
if( (pUserInfo->bit_mask & user_data_present) &&
|
|
(pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// validate that the PDU is H323 Release Complete information.
|
|
if( pUserInfo->h323_uu_pdu.h323_message_body.choice != releaseComplete_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// parse the message contained in pUserInfo.
|
|
|
|
pReleaseASN->fNonStandardDataPresent = FALSE;
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nonStandardData_present )
|
|
{
|
|
if( !ParseNonStandardData( &pReleaseASN -> nonStandardData,
|
|
&pUserInfo->h323_uu_pdu.nonStandardData ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pReleaseASN->fNonStandardDataPresent = TRUE;
|
|
}
|
|
|
|
if (pUserInfo->h323_uu_pdu.h323_message_body.u.releaseComplete.bit_mask &
|
|
ReleaseComplete_UUIE_reason_present)
|
|
{
|
|
switch( pUserInfo->h323_uu_pdu.h323_message_body.u.releaseComplete.reason.choice )
|
|
{
|
|
case noBandwidth_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_NO_BANDWIDTH;
|
|
break;
|
|
|
|
case gatekeeperResources_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_GATEKEEPER_RESOURCES;
|
|
break;
|
|
|
|
case unreachableDestination_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_UNREACHABLE_DESTINATION;
|
|
break;
|
|
|
|
case destinationRejection_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_DESTINATION_REJECTION;
|
|
break;
|
|
|
|
case ReleaseCompleteReason_invalidRevision_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_INVALID_REVISION;
|
|
break;
|
|
|
|
case noPermission_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_NO_PERMISSION;
|
|
break;
|
|
|
|
case unreachableGatekeeper_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_UNREACHABLE_GATEKEEPER;
|
|
break;
|
|
|
|
case gatewayResources_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_GATEWAY_RESOURCES;
|
|
break;
|
|
|
|
case badFormatAddress_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_BAD_FORMAT_ADDRESS;
|
|
break;
|
|
|
|
case adaptiveBusy_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_ADAPTIVE_BUSY;
|
|
break;
|
|
|
|
case inConf_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_IN_CONF;
|
|
break;
|
|
|
|
case facilityCallDeflection_chosen:
|
|
pReleaseASN->bReason = H323_REJECT_CALL_DEFLECTION;
|
|
break;
|
|
|
|
default:
|
|
pReleaseASN->bReason = H323_REJECT_UNDEFINED_REASON;
|
|
} // switch
|
|
}
|
|
else
|
|
{
|
|
pReleaseASN->bReason = H323_REJECT_UNDEFINED_REASON;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE,
|
|
"ParseReleaseCompleteASN error:%d, q931 error:%d, exit:%p.",
|
|
pReleaseASN->bReason,
|
|
pUserInfo->h323_uu_pdu.h323_message_body.u.releaseComplete.reason.choice,
|
|
this ));
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
if( pReleaseASN->fNonStandardDataPresent )
|
|
{
|
|
delete pReleaseASN -> nonStandardData.sData.pOctetString;
|
|
pReleaseASN -> nonStandardData.sData.pOctetString = NULL;
|
|
pReleaseASN->fNonStandardDataPresent = FALSE;
|
|
}
|
|
|
|
ASN1_FreeDecoded( m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::ParseConnectASN(
|
|
IN BYTE *pEncodedBuf,
|
|
IN DWORD dwEncodedLength,
|
|
OUT Q931_CONNECT_ASN *pConnectASN,
|
|
OUT DWORD* pdwH450APDUType
|
|
)
|
|
{
|
|
H323_UserInformation *pUserInfo;
|
|
int iResult;
|
|
DWORD dwInvokeID = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseConnectASN entered: %p.", this ));
|
|
|
|
memset( (PVOID) pConnectASN, 0, sizeof(Q931_CONNECT_ASN) );
|
|
|
|
iResult = DecodeASN((void **) &pUserInfo ,
|
|
H323_UserInformation_PDU,
|
|
pEncodedBuf,
|
|
dwEncodedLength);
|
|
|
|
if (ASN1_FAILED(iResult) || (pUserInfo == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Connect_UUIE & connectMessage =
|
|
pUserInfo->h323_uu_pdu.h323_message_body.u.connect;
|
|
|
|
*pdwH450APDUType = 0;
|
|
if( (pUserInfo->h323_uu_pdu.bit_mask & h4501SupplementaryService_present) &&
|
|
pUserInfo->h323_uu_pdu.h4501SupplementaryService )
|
|
{
|
|
if( !HandleH450APDU( pUserInfo->h323_uu_pdu.h4501SupplementaryService,
|
|
pdwH450APDUType, &dwInvokeID, NULL ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// validate that the PDU user-data uses ASN encoding.
|
|
if( (pUserInfo->bit_mask & user_data_present) &&
|
|
(pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// validate that the PDU is H323 Connect information.
|
|
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != connect_chosen)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// make sure that the conference id is formed correctly.
|
|
if (connectMessage.conferenceID.length >
|
|
sizeof(connectMessage.conferenceID.value))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// parse the message contained in pUserInfo.
|
|
|
|
pConnectASN->h245Addr.bMulticast = FALSE;
|
|
|
|
pConnectASN->fNonStandardDataPresent = FALSE;
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nonStandardData_present )
|
|
{
|
|
if( !ParseNonStandardData( &pConnectASN -> nonStandardData,
|
|
&pUserInfo->h323_uu_pdu.nonStandardData ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pConnectASN->fNonStandardDataPresent = TRUE;
|
|
}
|
|
|
|
pConnectASN->h245AddrPresent = FALSE;
|
|
if( connectMessage.bit_mask & Connect_UUIE_h245Address_present )
|
|
{
|
|
if( connectMessage.h245Address.choice != ipAddress_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pConnectASN->h245Addr.nAddrType = H323_IP_BINARY;
|
|
pConnectASN->h245Addr.Addr.IP_Binary.wPort =
|
|
connectMessage.h245Address.u.ipAddress.port;
|
|
|
|
pConnectASN->h245Addr.Addr.IP_Binary.dwAddr =
|
|
ntohl( *((DWORD*)connectMessage.h245Address.u.ipAddress.ip.value) );
|
|
|
|
pConnectASN->h245AddrPresent = TRUE;
|
|
}
|
|
|
|
// no validation of destinationInfo needed.
|
|
pConnectASN->EndpointType.pVendorInfo = NULL;
|
|
if( connectMessage.destinationInfo.bit_mask & (vendor_present))
|
|
{
|
|
if( !ParseVendorInfo( &pConnectASN->VendorInfo,
|
|
&connectMessage.destinationInfo.vendor) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pConnectASN->EndpointType.pVendorInfo = &(pConnectASN->VendorInfo);
|
|
}
|
|
|
|
pConnectASN->EndpointType.bIsTerminal = FALSE;
|
|
if (connectMessage.destinationInfo.bit_mask & (terminal_present))
|
|
{
|
|
pConnectASN->EndpointType.bIsTerminal = TRUE;
|
|
}
|
|
|
|
pConnectASN->EndpointType.bIsGateway = FALSE;
|
|
if (connectMessage.destinationInfo.bit_mask & (gateway_present))
|
|
{
|
|
pConnectASN->EndpointType.bIsGateway = TRUE;
|
|
}
|
|
|
|
pConnectASN -> fFastStartPresent = FALSE;
|
|
if( (connectMessage.bit_mask & Connect_UUIE_fastStart_present) &&
|
|
connectMessage.fastStart )
|
|
{
|
|
pConnectASN->pFastStart = CopyFastStart(
|
|
(PSetup_UUIE_fastStart)connectMessage.fastStart );
|
|
|
|
if( pConnectASN->pFastStart != NULL )
|
|
{
|
|
pConnectASN -> fFastStartPresent = TRUE;
|
|
}
|
|
}
|
|
|
|
CopyConferenceID( &pConnectASN -> ConferenceID,
|
|
&connectMessage.conferenceID );
|
|
|
|
if( pUserInfo->h323_uu_pdu.h245Tunneling )
|
|
{
|
|
//the remote endpoint has sent a tunneling proposal
|
|
m_fh245Tunneling |= REMOTE_H245_TUNNELING;
|
|
}
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU);
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseConnectASN exited: %p.", this ));
|
|
return TRUE;
|
|
cleanup:
|
|
|
|
FreeConnectASN( pConnectASN );
|
|
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::ParseAlertingASN(
|
|
IN BYTE *pEncodedBuf,
|
|
IN DWORD dwEncodedLength,
|
|
OUT Q931_ALERTING_ASN *pAlertingASN,
|
|
OUT DWORD* pdwH450APDUType
|
|
)
|
|
{
|
|
H323_UserInformation *pUserInfo;
|
|
int iResult;
|
|
DWORD dwInvokeID = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseAlertingASN entered: %p.", this ));
|
|
|
|
memset( (PVOID) pAlertingASN, 0, sizeof(Q931_ALERTING_ASN) );
|
|
|
|
iResult = DecodeASN((void **) &pUserInfo,
|
|
H323_UserInformation_PDU,
|
|
pEncodedBuf,
|
|
dwEncodedLength);
|
|
|
|
if (ASN1_FAILED(iResult) || (pUserInfo == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Alerting_UUIE & alertingMessage =
|
|
pUserInfo->h323_uu_pdu.h323_message_body.u.alerting;
|
|
|
|
*pdwH450APDUType = 0;
|
|
if( (pUserInfo->h323_uu_pdu.bit_mask & h4501SupplementaryService_present) &&
|
|
pUserInfo->h323_uu_pdu.h4501SupplementaryService )
|
|
{
|
|
if( !HandleH450APDU( pUserInfo->h323_uu_pdu.h4501SupplementaryService,
|
|
pdwH450APDUType, &dwInvokeID, NULL ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// validate that the PDU user-data uses ASN encoding.
|
|
if( (pUserInfo->bit_mask & user_data_present ) &&
|
|
(pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// validate that the PDU is H323 Alerting information.
|
|
if (pUserInfo->h323_uu_pdu.h323_message_body.choice != alerting_chosen)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// parse the message contained in pUserInfo.
|
|
pAlertingASN->h245Addr.bMulticast = FALSE;
|
|
|
|
pAlertingASN->fNonStandardDataPresent = FALSE;
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nonStandardData_present )
|
|
{
|
|
if( !ParseNonStandardData( &pAlertingASN -> nonStandardData,
|
|
&pUserInfo->h323_uu_pdu.nonStandardData ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pAlertingASN->fNonStandardDataPresent = TRUE;
|
|
}
|
|
|
|
if( alertingMessage.bit_mask & Alerting_UUIE_h245Address_present )
|
|
{
|
|
if( alertingMessage.h245Address.choice != ipAddress_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pAlertingASN->h245Addr.nAddrType = H323_IP_BINARY;
|
|
pAlertingASN->h245Addr.Addr.IP_Binary.wPort =
|
|
alertingMessage.h245Address.u.ipAddress.port;
|
|
|
|
AddressReverseAndCopy(
|
|
&(pAlertingASN->h245Addr.Addr.IP_Binary.dwAddr),
|
|
alertingMessage.h245Address.u.ipAddress.ip.value );
|
|
}
|
|
|
|
pAlertingASN -> fFastStartPresent = FALSE;
|
|
if( (alertingMessage.bit_mask & Alerting_UUIE_fastStart_present) &&
|
|
alertingMessage.fastStart )
|
|
{
|
|
pAlertingASN->pFastStart = CopyFastStart(
|
|
(PSetup_UUIE_fastStart)alertingMessage.fastStart);
|
|
|
|
if( pAlertingASN->pFastStart != NULL )
|
|
pAlertingASN-> fFastStartPresent = TRUE;
|
|
}
|
|
|
|
if( pUserInfo->h323_uu_pdu.h245Tunneling )
|
|
{
|
|
m_fh245Tunneling |= REMOTE_H245_TUNNELING;
|
|
}
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU);
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseAlertingASN exited: %p.", this ));
|
|
return TRUE;
|
|
cleanup:
|
|
|
|
FreeAlertingASN( pAlertingASN );
|
|
|
|
ASN1_FreeDecoded( m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!aleways called in a lock
|
|
BOOL
|
|
CH323Call::ParseProceedingASN(
|
|
IN BYTE *pEncodedBuf,
|
|
IN DWORD dwEncodedLength,
|
|
OUT Q931_CALL_PROCEEDING_ASN *pProceedingASN,
|
|
OUT DWORD* pdwH450APDUType
|
|
)
|
|
{
|
|
H323_UserInformation * pUserInfo;
|
|
int iResult;
|
|
DWORD dwInvokeID = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseProceedingASN entered: %p.", this ));
|
|
|
|
memset( (PVOID) pProceedingASN, 0, sizeof(Q931_CALL_PROCEEDING_ASN) );
|
|
|
|
iResult = DecodeASN((void **) &pUserInfo,
|
|
H323_UserInformation_PDU,
|
|
pEncodedBuf,
|
|
dwEncodedLength);
|
|
|
|
if (ASN1_FAILED(iResult) || (pUserInfo == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CallProceeding_UUIE & proceedingMessage =
|
|
pUserInfo->h323_uu_pdu.h323_message_body.u.callProceeding;
|
|
|
|
*pdwH450APDUType = 0;
|
|
if( (pUserInfo->h323_uu_pdu.bit_mask & h4501SupplementaryService_present) &&
|
|
pUserInfo->h323_uu_pdu.h4501SupplementaryService )
|
|
{
|
|
if( !HandleH450APDU( pUserInfo->h323_uu_pdu.h4501SupplementaryService,
|
|
pdwH450APDUType, &dwInvokeID, NULL ) )
|
|
goto cleanup;
|
|
}
|
|
|
|
// validate that the PDU user-data uses ASN encoding.
|
|
if( (pUserInfo->bit_mask & user_data_present) &&
|
|
(pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// validate that the PDU is H323 Proceeding information.
|
|
// validate that the PDU is H323 pCall Proceeding information.
|
|
if( pUserInfo->h323_uu_pdu.h323_message_body.choice != callProceeding_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// parse the message contained in pUserInfo.
|
|
|
|
pProceedingASN->fNonStandardDataPresent = FALSE;
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nonStandardData_present )
|
|
{
|
|
if( !ParseNonStandardData( &pProceedingASN -> nonStandardData,
|
|
&pUserInfo->h323_uu_pdu.nonStandardData ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pProceedingASN->fNonStandardDataPresent = TRUE;
|
|
}
|
|
|
|
//copy the H245 address information
|
|
pProceedingASN->fH245AddrPresent = FALSE;
|
|
if( proceedingMessage.bit_mask & CallProceeding_UUIE_h245Address_present )
|
|
{
|
|
if( proceedingMessage.h245Address.choice != ipAddress_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pProceedingASN->h245Addr.nAddrType = H323_IP_BINARY;
|
|
pProceedingASN->h245Addr.Addr.IP_Binary.wPort =
|
|
proceedingMessage.h245Address.u.ipAddress.port;
|
|
|
|
AddressReverseAndCopy(
|
|
&(pProceedingASN->h245Addr.Addr.IP_Binary.dwAddr),
|
|
proceedingMessage.h245Address.u.ipAddress.ip.value );
|
|
|
|
pProceedingASN->h245Addr.bMulticast = FALSE;
|
|
pProceedingASN->fH245AddrPresent = TRUE;
|
|
}
|
|
|
|
|
|
pProceedingASN -> fFastStartPresent = FALSE;
|
|
if( (proceedingMessage.bit_mask & CallProceeding_UUIE_fastStart_present) &&
|
|
proceedingMessage.fastStart )
|
|
{
|
|
pProceedingASN->pFastStart = CopyFastStart(
|
|
(PSetup_UUIE_fastStart)proceedingMessage.fastStart);
|
|
|
|
if( pProceedingASN->pFastStart != NULL )
|
|
pProceedingASN-> fFastStartPresent = TRUE;
|
|
}
|
|
|
|
//ignore the destinationInfo field.
|
|
|
|
if( pUserInfo->h323_uu_pdu.h245Tunneling )
|
|
{
|
|
if( m_dwOrigin == LINECALLORIGIN_INBOUND )
|
|
{
|
|
//the msp has enabled tunneling in ProceedWithAnswer messsage
|
|
m_fh245Tunneling |= LOCAL_H245_TUNNELING;
|
|
}
|
|
else
|
|
//the remote endpoint has sent a tunneling proposal
|
|
m_fh245Tunneling |= REMOTE_H245_TUNNELING;
|
|
}
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseProceedingASN exited: %p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
FreeProceedingASN( pProceedingASN );
|
|
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::ParseFacilityASN(
|
|
IN BYTE * pEncodedBuf,
|
|
IN DWORD dwEncodedLength,
|
|
OUT Q931_FACILITY_ASN * pFacilityASN
|
|
)
|
|
{
|
|
H323_UserInformation *pUserInfo;
|
|
int iResult;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseFacilityASN entered: %p.", this ));
|
|
|
|
ZeroMemory( (PVOID) pFacilityASN, sizeof(Q931_FACILITY_ASN) );
|
|
|
|
iResult = DecodeASN((void **) &pUserInfo,
|
|
H323_UserInformation_PDU,
|
|
pEncodedBuf,
|
|
dwEncodedLength);
|
|
|
|
if( ASN1_FAILED(iResult) || (pUserInfo == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// validate that the PDU is H323 facility information.
|
|
if( pUserInfo->h323_uu_pdu.h323_message_body.choice == facility_chosen )
|
|
{
|
|
Facility_UUIE & facilityMessage =
|
|
pUserInfo->h323_uu_pdu.h323_message_body.u.facility;
|
|
|
|
// validate that the PDU user-data uses ASN encoding.
|
|
if( (pUserInfo->bit_mask & user_data_present) &&
|
|
(pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// make sure that the conference id is formed correctly.
|
|
if( facilityMessage.conferenceID.length >
|
|
sizeof(facilityMessage.conferenceID.value) )
|
|
{
|
|
//goto cleanup;
|
|
}
|
|
|
|
// parse the message contained in pUserInfo.
|
|
pFacilityASN->fNonStandardDataPresent = FALSE;
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nonStandardData_present )
|
|
{
|
|
if( !ParseNonStandardData( &pFacilityASN -> nonStandardData,
|
|
&pUserInfo->h323_uu_pdu.nonStandardData ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pFacilityASN->fNonStandardDataPresent = TRUE;
|
|
}
|
|
|
|
pFacilityASN->fAlternativeAddressPresent = FALSE;
|
|
if( facilityMessage.bit_mask & alternativeAddress_present )
|
|
{
|
|
if( facilityMessage.alternativeAddress.choice == ipAddress_chosen )
|
|
{
|
|
pFacilityASN->AlternativeAddr.nAddrType = H323_IP_BINARY;
|
|
pFacilityASN->AlternativeAddr.Addr.IP_Binary.wPort =
|
|
facilityMessage.alternativeAddress.u.ipAddress.port;
|
|
|
|
AddressReverseAndCopy(
|
|
&(pFacilityASN->AlternativeAddr.Addr.IP_Binary.dwAddr),
|
|
facilityMessage.alternativeAddress.u.ipAddress.ip.value );
|
|
|
|
pFacilityASN->fAlternativeAddressPresent = TRUE;
|
|
}
|
|
}
|
|
|
|
if( facilityMessage.bit_mask & alternativeAliasAddress_present )
|
|
{
|
|
if( !AliasAddrToAliasNames( &(pFacilityASN->pAlternativeAliasList),
|
|
(PSetup_UUIE_sourceAddress)
|
|
&(facilityMessage.alternativeAliasAddress) ) )
|
|
{
|
|
pFacilityASN -> pAlternativeAliasList = NULL;
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
if( facilityMessage.bit_mask & Facility_UUIE_conferenceID_present )
|
|
{
|
|
CopyConferenceID( &pFacilityASN -> ConferenceID,
|
|
&facilityMessage.conferenceID );
|
|
pFacilityASN -> ConferenceIDPresent = TRUE;
|
|
}
|
|
|
|
pFacilityASN->bReason = facilityMessage.reason.choice;
|
|
|
|
pFacilityASN->fH245AddrPresent = FALSE;
|
|
|
|
if( facilityMessage.bit_mask & Facility_UUIE_h245Address_present )
|
|
{
|
|
if( facilityMessage.h245Address.choice == ipAddress_chosen )
|
|
{
|
|
pFacilityASN->h245Addr.nAddrType = H323_IP_BINARY;
|
|
pFacilityASN->h245Addr.Addr.IP_Binary.wPort =
|
|
facilityMessage.h245Address.u.ipAddress.port;
|
|
|
|
pFacilityASN->h245Addr.Addr.IP_Binary.dwAddr =
|
|
ntohl( *((DWORD*)facilityMessage.h245Address.u.ipAddress.ip.value) );
|
|
|
|
pFacilityASN->fH245AddrPresent = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
pFacilityASN->dwH450APDUType = 0;
|
|
if( (pUserInfo->h323_uu_pdu.bit_mask & h4501SupplementaryService_present) &&
|
|
pUserInfo->h323_uu_pdu.h4501SupplementaryService )
|
|
{
|
|
pFacilityASN->dwInvokeID = 0;
|
|
|
|
if( !HandleH450APDU( pUserInfo->h323_uu_pdu.h4501SupplementaryService,
|
|
&pFacilityASN->dwH450APDUType, &pFacilityASN->dwInvokeID, NULL ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & h245Control_present )
|
|
{
|
|
if( pUserInfo->h323_uu_pdu.h245Control != NULL )
|
|
{
|
|
pFacilityASN->pH245PDU.value =
|
|
new BYTE[pUserInfo->h323_uu_pdu.h245Control->value.length];
|
|
|
|
if( pFacilityASN->pH245PDU.value != NULL )
|
|
{
|
|
CopyMemory( (PVOID)pFacilityASN->pH245PDU.value,
|
|
(PVOID)pUserInfo->h323_uu_pdu.h245Control->value.value,
|
|
pUserInfo->h323_uu_pdu.h245Control->value.length );
|
|
}
|
|
|
|
pFacilityASN->pH245PDU.length =
|
|
pUserInfo->h323_uu_pdu.h245Control->value.length;
|
|
}
|
|
}
|
|
|
|
ASN1_FreeDecoded( m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseFacilityASN exited: %p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
if( pFacilityASN -> pAlternativeAliasList != NULL )
|
|
{
|
|
FreeAliasNames( pFacilityASN -> pAlternativeAliasList );
|
|
pFacilityASN -> pAlternativeAliasList = NULL;
|
|
}
|
|
|
|
if( pFacilityASN->fNonStandardDataPresent != NULL )
|
|
{
|
|
delete pFacilityASN->nonStandardData.sData.pOctetString;
|
|
pFacilityASN->nonStandardData.sData.pOctetString = NULL;
|
|
pFacilityASN->fNonStandardDataPresent = NULL;
|
|
}
|
|
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!aleways called in a lock
|
|
BOOL
|
|
CH323Call::ParseSetupASN(
|
|
IN BYTE *pEncodedBuf,
|
|
IN DWORD dwEncodedLength,
|
|
OUT Q931_SETUP_ASN *pSetupASN,
|
|
OUT DWORD* pdwH450APDUType
|
|
)
|
|
{
|
|
H323_UserInformation *pUserInfo;
|
|
HRESULT hr;
|
|
int iResult;
|
|
DWORD dwInvokeID = 0;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "ParseSetupASN entered: %p.", this ));
|
|
|
|
memset( (PVOID)pSetupASN, 0, sizeof(Q931_SETUP_ASN));
|
|
|
|
iResult = DecodeASN((void **) &pUserInfo,
|
|
H323_UserInformation_PDU,
|
|
pEncodedBuf,
|
|
dwEncodedLength);
|
|
|
|
if (ASN1_FAILED(iResult) || (pUserInfo == NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
Setup_UUIE & setupMessage = pUserInfo->h323_uu_pdu.h323_message_body.u.setup;
|
|
|
|
// validate that the PDU user-data uses ASN encoding.
|
|
if( (pUserInfo->bit_mask & user_data_present) &&
|
|
(pUserInfo->user_data.protocol_discriminator != USE_ASN1_ENCODING) )
|
|
{
|
|
//log
|
|
goto cleanup;
|
|
}
|
|
|
|
// validate that the PDU is H323 Setup information.
|
|
if( pUserInfo->h323_uu_pdu.h323_message_body.choice != setup_chosen )
|
|
{
|
|
//log
|
|
goto cleanup;
|
|
}
|
|
|
|
// make sure that the conference id is formed correctly.
|
|
if (setupMessage.conferenceID.length >
|
|
sizeof(setupMessage.conferenceID.value))
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
// parse the message contained in pUserInfo.
|
|
pSetupASN->sourceAddr.bMulticast = FALSE;
|
|
pSetupASN->callerAddr.bMulticast = FALSE;
|
|
pSetupASN->calleeDestAddr.bMulticast = FALSE;
|
|
pSetupASN->calleeAddr.bMulticast = FALSE;
|
|
|
|
// no validation of sourceInfo needed.
|
|
|
|
//copy thevendor info
|
|
pSetupASN->EndpointType.pVendorInfo = NULL;
|
|
if( setupMessage.sourceInfo.bit_mask & vendor_present )
|
|
{
|
|
if( !ParseVendorInfo( &pSetupASN->VendorInfo,
|
|
&setupMessage.sourceInfo.vendor) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pSetupASN->EndpointType.pVendorInfo = &(pSetupASN->VendorInfo);
|
|
}
|
|
|
|
pSetupASN->EndpointType.bIsTerminal = FALSE;
|
|
if( setupMessage.sourceInfo.bit_mask & terminal_present )
|
|
{
|
|
pSetupASN->EndpointType.bIsTerminal = TRUE;
|
|
}
|
|
|
|
pSetupASN->EndpointType.bIsGateway = FALSE;
|
|
if( setupMessage.sourceInfo.bit_mask & gateway_present )
|
|
{
|
|
pSetupASN->EndpointType.bIsGateway = TRUE;
|
|
}
|
|
|
|
pSetupASN->fNonStandardDataPresent = FALSE;
|
|
if( pUserInfo->h323_uu_pdu.bit_mask & H323_UU_PDU_nonStandardData_present )
|
|
{
|
|
if( !ParseNonStandardData( &pSetupASN -> nonStandardData,
|
|
&pUserInfo->h323_uu_pdu.nonStandardData ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pSetupASN->fNonStandardDataPresent = TRUE;
|
|
}
|
|
|
|
// parse the sourceAddress aliases here...
|
|
if( setupMessage.bit_mask & sourceAddress_present )
|
|
{
|
|
if( !AliasAddrToAliasNames( &(pSetupASN->pCallerAliasList),
|
|
setupMessage.sourceAddress ) )
|
|
{
|
|
pSetupASN->pCallerAliasList = NULL;
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
// parse the destinationAddress aliases here...
|
|
if( (setupMessage.bit_mask & destinationAddress_present) &&
|
|
setupMessage.destinationAddress )
|
|
{
|
|
if( !AliasAddrToAliasNames( &(pSetupASN->pCalleeAliasList),
|
|
(PSetup_UUIE_sourceAddress)setupMessage.destinationAddress) )
|
|
{
|
|
pSetupASN->pCalleeAliasList = NULL;
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
// parse the destExtraCallInfo aliases here...
|
|
if( (setupMessage.bit_mask & Setup_UUIE_destExtraCallInfo_present) &&
|
|
setupMessage.destExtraCallInfo )
|
|
{
|
|
if( !AliasAddrToAliasNames(&(pSetupASN->pExtraAliasList),
|
|
(PSetup_UUIE_sourceAddress)setupMessage.destExtraCallInfo) )
|
|
{
|
|
pSetupASN->pExtraAliasList = NULL;
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
// parse the remoteExtensionAddress aliases here...
|
|
if( setupMessage.bit_mask & Setup_UUIE_remoteExtensionAddress_present )
|
|
{
|
|
pSetupASN->pExtensionAliasItem = new H323_ALIASITEM;
|
|
|
|
if( pSetupASN->pExtensionAliasItem == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
hr = AliasAddrToAliasItem(pSetupASN->pExtensionAliasItem,
|
|
&(setupMessage.remoteExtensionAddress));
|
|
|
|
if( hr == E_OUTOFMEMORY )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
pSetupASN -> fCalleeDestAddrPresent = FALSE;
|
|
if( setupMessage.bit_mask & Setup_UUIE_destCallSignalAddress_present )
|
|
{
|
|
if( setupMessage.destCallSignalAddress.choice != ipAddress_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pSetupASN->calleeDestAddr.nAddrType = H323_IP_BINARY;
|
|
pSetupASN->calleeDestAddr.Addr.IP_Binary.wPort =
|
|
setupMessage.destCallSignalAddress.u.ipAddress.port;
|
|
|
|
AddressReverseAndCopy(
|
|
&(pSetupASN->calleeDestAddr.Addr.IP_Binary.dwAddr),
|
|
setupMessage.destCallSignalAddress.u.ipAddress.ip.value );
|
|
|
|
pSetupASN -> fCalleeDestAddrPresent = TRUE;
|
|
}
|
|
|
|
pSetupASN->fSourceAddrPresent = FALSE;
|
|
if( setupMessage.bit_mask & sourceCallSignalAddress_present )
|
|
{
|
|
if( setupMessage.sourceCallSignalAddress.choice != ipAddress_chosen )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pSetupASN->sourceAddr.nAddrType = H323_IP_BINARY;
|
|
pSetupASN->sourceAddr.Addr.IP_Binary.wPort =
|
|
setupMessage.sourceCallSignalAddress.u.ipAddress.port;
|
|
|
|
pSetupASN->sourceAddr.Addr.IP_Binary.dwAddr = ntohl( *((DWORD*)
|
|
setupMessage.sourceCallSignalAddress.u.ipAddress.ip.value) );
|
|
|
|
pSetupASN->fSourceAddrPresent = TRUE;
|
|
}
|
|
|
|
pSetupASN->bCallerIsMC = setupMessage.activeMC;
|
|
|
|
pSetupASN -> fFastStartPresent = FALSE;
|
|
if( (setupMessage.bit_mask & Setup_UUIE_fastStart_present) &&
|
|
setupMessage.fastStart )
|
|
{
|
|
pSetupASN->pFastStart = CopyFastStart( setupMessage.fastStart );
|
|
|
|
if( pSetupASN->pFastStart != NULL )
|
|
{
|
|
pSetupASN -> fFastStartPresent = TRUE;
|
|
}
|
|
}
|
|
|
|
CopyConferenceID (&pSetupASN -> ConferenceID, &setupMessage.conferenceID);
|
|
|
|
//copy the call identifier
|
|
pSetupASN -> fCallIdentifierPresent = FALSE;
|
|
if( setupMessage.bit_mask & Setup_UUIE_callIdentifier_present )
|
|
{
|
|
pSetupASN -> fCallIdentifierPresent = TRUE;
|
|
CopyMemory( (PVOID)&(pSetupASN->callIdentifier),
|
|
setupMessage.callIdentifier.guid.value,
|
|
sizeof(GUID) );
|
|
}
|
|
|
|
if( pUserInfo->h323_uu_pdu.h245Tunneling )
|
|
{
|
|
if( m_dwOrigin == LINECALLORIGIN_INBOUND )
|
|
{
|
|
//the remote endpoint has sent a tunneling proposal
|
|
m_fh245Tunneling |= REMOTE_H245_TUNNELING;
|
|
}
|
|
else
|
|
{
|
|
//the msp has enabled tunneling in ReadyToInitiate messsage
|
|
m_fh245Tunneling |= LOCAL_H245_TUNNELING;
|
|
}
|
|
}
|
|
|
|
pSetupASN->wGoal = (WORD)setupMessage.conferenceGoal.choice;
|
|
pSetupASN->wCallType = setupMessage.callType.choice;
|
|
|
|
*pdwH450APDUType = 0;
|
|
if( (pUserInfo->h323_uu_pdu.bit_mask & h4501SupplementaryService_present) &&
|
|
pUserInfo->h323_uu_pdu.h4501SupplementaryService )
|
|
{
|
|
if( !HandleH450APDU( pUserInfo->h323_uu_pdu.h4501SupplementaryService,
|
|
pdwH450APDUType, &dwInvokeID, pSetupASN ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded( m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "ParseSetupASN exited: %p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
FreeSetupASN( pSetupASN );
|
|
|
|
ASN1_FreeDecoded(m_ASNCoderInfo.pDecInfo, pUserInfo,
|
|
H323_UserInformation_PDU);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//GLOBAL CALLBACK FUNCTIONS CALLED BY THREAD POOL
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// static
|
|
|
|
void
|
|
NTAPI CH323Call::IoCompletionCallback(
|
|
IN DWORD dwStatus,
|
|
IN DWORD dwBytesTransferred,
|
|
IN OVERLAPPED * pOverlapped
|
|
)
|
|
{
|
|
CALL_OVERLAPPED *pCallOverlapped;
|
|
CH323Call* pCall;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CH323Call-IoCompletionCallback entered." ));
|
|
|
|
_ASSERTE (pOverlapped);
|
|
pCallOverlapped = CONTAINING_RECORD( pOverlapped, CALL_OVERLAPPED,
|
|
Overlapped );
|
|
|
|
pCall = pCallOverlapped -> pCall;
|
|
|
|
switch (pCallOverlapped -> Type)
|
|
{
|
|
case OVERLAPPED_TYPE_SEND:
|
|
|
|
pCall -> OnWriteComplete( dwStatus,
|
|
static_cast<CALL_SEND_CONTEXT *>(pCallOverlapped) );
|
|
break;
|
|
|
|
case OVERLAPPED_TYPE_RECV:
|
|
|
|
pCallOverlapped -> BytesTransferred = dwBytesTransferred;
|
|
pCall -> OnReadComplete( dwStatus,
|
|
static_cast<CALL_RECV_CONTEXT *>(pCallOverlapped) );
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE(FALSE);
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CH323Call-IoCompletionCallback exited." ));
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::OnWriteComplete(
|
|
IN DWORD dwStatus,
|
|
IN CALL_SEND_CONTEXT * pSendContext
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnWriteComplete entered:%p.",this ));
|
|
|
|
Lock();
|
|
|
|
_ASSERTE( m_IoRefCount != 0 );
|
|
m_IoRefCount--;
|
|
H323DBG((DEBUG_LEVEL_TRACE, "WriteComplete:m_IoRefCount: %d:%p.",
|
|
m_IoRefCount, this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
if( m_IoRefCount == 0 )
|
|
{
|
|
QueueTAPICallRequest( TSPI_DELETE_CALL, NULL );
|
|
H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", this ));
|
|
}
|
|
}
|
|
else if( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
if( IsInList( &m_sendBufList, &pSendContext->ListEntry ) )
|
|
{
|
|
RemoveEntryList( &pSendContext->ListEntry );
|
|
delete pSendContext->WSABuf.buf;
|
|
delete pSendContext;
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnWriteComplete exited:%p.",this ));
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::OnReadComplete(
|
|
IN DWORD dwStatus,
|
|
IN CALL_RECV_CONTEXT * pRecvContext )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnReadComplete entered:%p.",this ));
|
|
|
|
Lock();
|
|
|
|
_ASSERTE( m_IoRefCount != 0 );
|
|
m_IoRefCount --;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "RecvBuffer:m_IoRefCount:%d:%p.",
|
|
m_IoRefCount, this ));
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
if( m_IoRefCount == 0 )
|
|
{
|
|
QueueTAPICallRequest( TSPI_DELETE_CALL, NULL );
|
|
H323DBG((DEBUG_LEVEL_TRACE, "call delete:%p.", this ));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( dwStatus == ERROR_SUCCESS )
|
|
{
|
|
_ASSERTE( m_pRecvBuffer == pRecvContext );
|
|
|
|
if( pRecvContext->BytesTransferred == 0 )
|
|
{
|
|
CloseCall( 0 );
|
|
H323DBG((DEBUG_LEVEL_TRACE, "0 bytes recvd:%p.", this ));
|
|
}
|
|
else
|
|
{
|
|
ReadEvent( pRecvContext->BytesTransferred );
|
|
}
|
|
}
|
|
}
|
|
|
|
Unlock();
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "OnReadComplete exited:%p.",this ));
|
|
}
|
|
|
|
|
|
// static
|
|
void
|
|
NTAPI CH323Call::SetupSentTimerCallback(
|
|
IN PVOID Parameter1,
|
|
IN BOOLEAN bTimer
|
|
)
|
|
{
|
|
PH323_CALL pCall = NULL;
|
|
|
|
//if the timer expired
|
|
_ASSERTE( bTimer );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "Q931 setup expired event recvd." ));
|
|
|
|
pCall=g_pH323Line -> FindH323CallAndLock((HDRVCALL) Parameter1);
|
|
if( pCall != NULL )
|
|
{
|
|
pCall -> SetupSentTimerExpired();
|
|
pCall -> Unlock();
|
|
}
|
|
}
|
|
|
|
|
|
// static
|
|
void
|
|
NTAPI CH323Call::CheckRestrictionTimerCallback(
|
|
IN PVOID Parameter1,
|
|
IN BOOLEAN bTimer
|
|
)
|
|
{
|
|
//if the timer expired
|
|
_ASSERTE( bTimer );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CheckRestrictionTimerCallback entered." ));
|
|
if(!QueueTAPILineRequest(
|
|
TSPI_CLOSE_CALL,
|
|
(HDRVCALL) Parameter1,
|
|
NULL,
|
|
LINEDISCONNECTMODE_NOANSWER,
|
|
NULL) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not post H323 close event." ));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CheckRestrictionTimerCallback exited." ));
|
|
}
|
|
|
|
// static
|
|
void
|
|
NTAPI CH323Call::CallReroutingTimerCallback(
|
|
IN PVOID Parameter1,
|
|
IN BOOLEAN bTimer
|
|
)
|
|
{
|
|
//If the timer expired
|
|
_ASSERTE( bTimer );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CallReroutingTimerCallback entered." ));
|
|
|
|
if(!QueueTAPILineRequest(
|
|
TSPI_CLOSE_CALL,
|
|
(HDRVCALL) Parameter1,
|
|
NULL,
|
|
LINEDISCONNECTMODE_NOANSWER,
|
|
NULL) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not post H323 close event." ));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CallReroutingTimerCallback exited." ));
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//CALL DIVERSION (H450.3) ENCODE/DECODE ROUTINES
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
CH323Call::HandleH450APDU(
|
|
IN PH323_UU_PDU_h4501SupplementaryService pH450APDU,
|
|
IN DWORD* pdwH450APDUType,
|
|
OUT DWORD* pdwInvokeID,
|
|
IN Q931_SETUP_ASN* pSetupASN
|
|
)
|
|
{
|
|
BOOL retVal = TRUE;
|
|
H4501SupplementaryService * pH450APDUStruct = NULL;
|
|
ServiceApdus_rosApdus * pROSApdu = NULL;
|
|
int iResult;
|
|
BYTE pEncodedArg[H450_ENCODED_ARG_LEN];
|
|
DWORD dwEncodedArgLen;
|
|
DWORD dwOpcode;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleH450APDU entered:%p.", this ));
|
|
|
|
//right now assuming that only one APDU is passed at a time
|
|
iResult = DecodeH450ASN( (void **) &pH450APDUStruct,
|
|
H4501SupplementaryService_PDU,
|
|
pH450APDU->value.value,
|
|
pH450APDU->value.length );
|
|
|
|
if( ASN1_FAILED(iResult) || (pH450APDUStruct == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( pH450APDUStruct->serviceApdu.choice != rosApdus_chosen )
|
|
{
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
pROSApdu = pH450APDUStruct->serviceApdu.u.rosApdus;
|
|
|
|
switch( pROSApdu->value.choice )
|
|
{
|
|
case H4503ROS_invoke_chosen:
|
|
|
|
if( (pROSApdu->value.u.invoke.opcode.choice != local_chosen) ||
|
|
(pROSApdu->value.u.invoke.argument.length > H450_ENCODED_ARG_LEN) )
|
|
{
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
return FALSE;
|
|
}
|
|
|
|
*pdwInvokeID = pROSApdu->value.u.invoke.invokeId;
|
|
dwEncodedArgLen = pROSApdu->value.u.invoke.argument.length;
|
|
|
|
CopyMemory( (PVOID)pEncodedArg,
|
|
(PVOID)pROSApdu->value.u.invoke.argument.value,
|
|
dwEncodedArgLen );
|
|
dwOpcode = pROSApdu->value.u.invoke.opcode.u.local;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
|
|
*pdwH450APDUType = dwOpcode;
|
|
switch( dwOpcode )
|
|
{
|
|
case CALLREROUTING_OPCODE:
|
|
|
|
retVal = HandleCallRerouting( pEncodedArg, dwEncodedArgLen );
|
|
break;
|
|
|
|
case DIVERTINGLEGINFO1_OPCODE:
|
|
|
|
retVal = HandleDiversionLegInfo1( pEncodedArg, dwEncodedArgLen );
|
|
break;
|
|
|
|
case DIVERTINGLEGINFO2_OPCODE:
|
|
|
|
retVal = HandleDiversionLegInfo2( pEncodedArg, dwEncodedArgLen );
|
|
break;
|
|
|
|
case DIVERTINGLEGINFO3_OPCODE:
|
|
|
|
//Don't bail out even if this function fails.
|
|
HandleDiversionLegInfo3( pEncodedArg, dwEncodedArgLen );
|
|
break;
|
|
|
|
case CHECKRESTRICTION_OPCODE:
|
|
|
|
if( pSetupASN == NULL )
|
|
{
|
|
retVal = FALSE;
|
|
}
|
|
else
|
|
{
|
|
retVal = HandleCheckRestriction( pEncodedArg, dwEncodedArgLen,
|
|
pSetupASN );
|
|
}
|
|
|
|
if( retVal )
|
|
{
|
|
retVal = SendQ931Message( *pdwInvokeID, 0, 0,
|
|
CONNECTMESSAGETYPE,
|
|
H450_RETURNRESULT|CHECKRESTRICTION_OPCODE );
|
|
}
|
|
break;
|
|
|
|
case CTIDENTIFY_OPCODE:
|
|
|
|
retVal = HandleCTIdentify( *pdwInvokeID );
|
|
m_dwInvokeID = *pdwInvokeID;
|
|
break;
|
|
|
|
case CTINITIATE_OPCODE:
|
|
|
|
retVal = HandleCTInitiate( pEncodedArg, dwEncodedArgLen );
|
|
m_dwInvokeID = *pdwInvokeID;
|
|
break;
|
|
|
|
case CTSETUP_OPCODE:
|
|
|
|
retVal = HandleCTSetup( pEncodedArg, dwEncodedArgLen );
|
|
m_dwInvokeID = *pdwInvokeID;
|
|
break;
|
|
|
|
case HOLDNOTIFIC_OPCODE:
|
|
|
|
//local hold request from the remote endpoint
|
|
if( m_dwCallState != LINECALLSTATE_ONHOLD )
|
|
{
|
|
SendMSPMessage( SP_MSG_Hold, 0, 1, NULL );
|
|
ChangeCallState( LINECALLSTATE_ONHOLD, 0 );
|
|
}
|
|
break;
|
|
|
|
case RETRIEVENOTIFIC_OPCODE:
|
|
|
|
//local retrieve request from the remote endpoint
|
|
if( (m_dwCallState == LINECALLSTATE_ONHOLD) &&
|
|
!(m_dwFlags & TSPI_CALL_LOCAL_HOLD) )
|
|
{
|
|
SendMSPMessage( SP_MSG_Hold, 0, 0, NULL );
|
|
ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
|
|
}
|
|
break;
|
|
|
|
case REMOTEHOLD_OPCODE:
|
|
|
|
//remote hold request from remote endpoint
|
|
if( m_dwCallState != LINECALLSTATE_ONHOLD )
|
|
{
|
|
SendMSPMessage( SP_MSG_Hold, 0, 1, NULL );
|
|
ChangeCallState( LINECALLSTATE_ONHOLD, 0 );
|
|
|
|
retVal = SendQ931Message( *pdwInvokeID, 0, 0,
|
|
FACILITYMESSAGETYPE,
|
|
REMOTEHOLD_OPCODE| H450_RETURNRESULT );
|
|
}
|
|
break;
|
|
|
|
case REMOTERETRIEVE_OPCODE:
|
|
|
|
//remote retrieve request from remote endpoint
|
|
if( m_dwCallState == LINECALLSTATE_ONHOLD )
|
|
{
|
|
SendMSPMessage( SP_MSG_Hold, 0, 0, NULL );
|
|
ChangeCallState( LINECALLSTATE_CONNECTED, 0 );
|
|
|
|
retVal = SendQ931Message( *pdwInvokeID, 0, 0,
|
|
FACILITYMESSAGETYPE,
|
|
REMOTERETRIEVE_OPCODE| H450_RETURNRESULT );
|
|
}
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE( 0 );
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case H4503ROS_returnResult_chosen:
|
|
|
|
*pdwH450APDUType = H4503_DUMMYTYPERETURNRESULT_APDU;
|
|
*pdwInvokeID =
|
|
pH450APDUStruct->serviceApdu.u.rosApdus->value.u.returnResult.invokeId;
|
|
retVal = HandleReturnResultDummyType( pH450APDUStruct );
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
|
|
break;
|
|
|
|
case H4503ROS_returnError_chosen:
|
|
|
|
*pdwH450APDUType = H4503_RETURNERROR_APDU;
|
|
*pdwInvokeID =
|
|
pH450APDUStruct->serviceApdu.u.rosApdus->value.u.returnError.invokeId;
|
|
retVal = HandleReturnError( pH450APDUStruct );
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
|
|
break;
|
|
|
|
case reject_chosen:
|
|
|
|
*pdwH450APDUType = H4503_REJECT_APDU;
|
|
*pdwInvokeID =
|
|
pH450APDUStruct->serviceApdu.u.rosApdus->value.u.reject.invokeId;
|
|
retVal = HandleReject( pH450APDUStruct );
|
|
|
|
// Free the PDU data.
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
break;
|
|
|
|
default:
|
|
_ASSERTE( 0 );
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pH450APDUStruct,
|
|
H4501SupplementaryService_PDU );
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
if( retVal == FALSE )
|
|
{
|
|
SendQ931Message( *pdwInvokeID,
|
|
0,
|
|
0,
|
|
RELEASECOMPLMESSAGETYPE,
|
|
H450_REJECT );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleH450APDU exited:%p.", this ));
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleReturnError(
|
|
IN H4501SupplementaryService * pH450APDUStruct
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReturnError entered:%p.", this ));
|
|
|
|
ReturnError * pReturnError =
|
|
&(pH450APDUStruct->serviceApdu.u.rosApdus->value.u.returnError);
|
|
|
|
if( IsValidInvokeID( pReturnError->invokeId ) == FALSE )
|
|
{
|
|
//ignore APDU
|
|
return TRUE;
|
|
}
|
|
|
|
CloseCall( 0 );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReturnError exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleReject(
|
|
IN H4501SupplementaryService * pH450APDUStruct
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReject entered:%p.", this ));
|
|
|
|
Reject * pReject =
|
|
&(pH450APDUStruct->serviceApdu.u.rosApdus->value.u.reject);
|
|
|
|
if( IsValidInvokeID( pReject->invokeId ) == FALSE )
|
|
{
|
|
//ignore the APDU
|
|
return TRUE;
|
|
}
|
|
|
|
CloseCall( 0 );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReject exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleReturnResultDummyType(
|
|
IN H4501SupplementaryService * pH450APDUStruct
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReturnResultDummyType entered:%p.",
|
|
this ));
|
|
|
|
ReturnResult* dummyResult =
|
|
&(pH450APDUStruct->serviceApdu.u.rosApdus->value.u.returnResult);
|
|
|
|
if( dummyResult->bit_mask & result_present )
|
|
{
|
|
if( dummyResult->result.opcode.choice != local_chosen )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
switch( dummyResult->result.opcode.u.local )
|
|
{
|
|
case CHECKRESTRICTION_OPCODE:
|
|
|
|
//forwarding has been enabled. inform the user
|
|
if( !EnableCallForwarding() )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//close the call
|
|
CloseCall( 0 );
|
|
|
|
break;
|
|
|
|
case CALLREROUTING_OPCODE:
|
|
|
|
//call has been rerouted. log the info or inform the user
|
|
m_dwCallDiversionState = H4503_CALLREROUTING_RRSUCC;
|
|
_ASSERTE( m_hCallReroutingTimer );
|
|
if( m_hCallReroutingTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue,
|
|
m_hCallReroutingTimer, NULL );
|
|
|
|
m_hCallReroutingTimer = NULL;
|
|
}
|
|
|
|
break;
|
|
|
|
case CTIDENTIFY_OPCODE:
|
|
|
|
//call tranfer has been accepted by transfered-to endpoint
|
|
m_dwCallDiversionState = H4502_CIIDENTIFY_RRSUCC;
|
|
|
|
_ASSERTE( m_hCTIdentifyTimer );
|
|
if( m_hCTIdentifyTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCTIdentifyTimer, NULL );
|
|
m_hCTIdentifyTimer = NULL;
|
|
}
|
|
|
|
return HandleCTIdentifyReturnResult( dummyResult->result.result.value,
|
|
dummyResult->result.result.length );
|
|
|
|
break;
|
|
|
|
case CTINITIATE_OPCODE:
|
|
|
|
_ASSERTE( m_hCTInitiateTimer );
|
|
if( m_hCTInitiateTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCTInitiateTimer, NULL );
|
|
m_hCTInitiateTimer = NULL;
|
|
}
|
|
break;
|
|
|
|
case CTSETUP_OPCODE:
|
|
case REMOTEHOLD_OPCODE:
|
|
case REMOTERETRIEVE_OPCODE:
|
|
//no processing required
|
|
break;
|
|
|
|
default:
|
|
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "wrong opcode.",
|
|
dummyResult->result.opcode.u.local ));
|
|
break;
|
|
}
|
|
}
|
|
else if( IsValidInvokeID( dummyResult->invokeId ) == FALSE )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleReturnResultDummyType exited:%p.",
|
|
this ));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EnableCallForwarding()
|
|
{
|
|
m_dwCallDiversionState = H4503_CHECKRESTRICTION_SUCC;
|
|
|
|
if( m_pCallForwardParams != NULL )
|
|
{
|
|
g_pH323Line->SetCallForwardParams( m_pCallForwardParams );
|
|
m_pCallForwardParams = NULL;
|
|
}
|
|
else if( m_pForwardAddress != NULL )
|
|
{
|
|
if( !g_pH323Line->SetCallForwardParams( m_pForwardAddress ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
m_pForwardAddress = NULL;
|
|
}
|
|
|
|
//_ASSERTE( m_hCheckRestrictionTimer );
|
|
|
|
//stop the timer
|
|
if( m_hCheckRestrictionTimer )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCheckRestrictionTimer,
|
|
NULL );
|
|
m_hCheckRestrictionTimer = NULL;
|
|
}
|
|
|
|
//inform the user about change in line forward state
|
|
(*g_pfnLineEventProc)(
|
|
g_pH323Line->m_htLine,
|
|
(HTAPICALL)NULL,
|
|
(DWORD)LINE_ADDRESSSTATE,
|
|
(DWORD)LINEADDRESSSTATE_FORWARD,
|
|
(DWORD)LINEADDRESSSTATE_FORWARD,
|
|
(DWORD)0
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCTIdentifyReturnResult(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
PH323_CALL pCall = NULL;
|
|
CTIdentifyRes * pCTIdentifyRes;
|
|
int iResult;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTIdentifyReturnResult entered:%p.", this ));
|
|
|
|
if( (pEncodeArg == NULL) || (dwEncodedArgLen==0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
iResult = DecodeH450ASN( (void **) &pCTIdentifyRes,
|
|
CTIdentifyRes_PDU, pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (pCTIdentifyRes == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//send a CTInitiate message on the primary call
|
|
if( !QueueSuppServiceWorkItem( SEND_CTINITIATE_MESSAGE, m_hdRelatedCall,
|
|
(ULONG_PTR)pCTIdentifyRes ))
|
|
{
|
|
//close the consultation call.
|
|
CloseCall( 0 );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTIdentifyReturnResult exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCTIdentify(
|
|
IN DWORD dwInvokeID
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTIdentify entered:%p.", this ));
|
|
|
|
BOOL retVal = TRUE;
|
|
|
|
//send the return result for CTIdentify
|
|
retVal = SendQ931Message( dwInvokeID, 0, 0, FACILITYMESSAGETYPE,
|
|
H450_RETURNRESULT|CTIDENTIFY_OPCODE );
|
|
|
|
m_dwCallType |= CALLTYPE_TRANSFERED2_CONSULT;
|
|
|
|
//start the timer for CTIdenity message
|
|
if( retVal )
|
|
{
|
|
retVal = CreateTimerQueueTimer(
|
|
&m_hCTIdentifyRRTimer,
|
|
H323TimerQueue,
|
|
CH323Call::CTIdentifyRRExpiredCallback,
|
|
(PVOID)m_hdCall,
|
|
CTIDENTIFYRR_SENT_TIMEOUT, 0,
|
|
WT_EXECUTEINIOTHREAD | WT_EXECUTEONLYONCE );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTIdentify exited:%p.", this ));
|
|
return retVal;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCTInitiate(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTInitiate entered:%p.", this ));
|
|
|
|
CTInitiateArg * pCTInitiateArg;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &pCTInitiateArg,
|
|
CTInitiateArg_PDU,
|
|
pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (pCTInitiateArg == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//argument.callIdentity
|
|
CopyMemory( (PVOID)m_pCTCallIdentity, pCTInitiateArg->callIdentity,
|
|
sizeof(m_pCTCallIdentity) );
|
|
|
|
//argument.reroutingNumber
|
|
if( !AliasAddrToAliasNames( &m_pTransferedToAlias,
|
|
(PSetup_UUIE_sourceAddress)
|
|
pCTInitiateArg->reroutingNumber.destinationAddress ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_TRANSFERED_PRIMARY;
|
|
m_dwCallDiversionState = H4502_CTINITIATE_RECV;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCTInitiateArg,
|
|
CTInitiateArg_PDU );
|
|
|
|
//queue an event for creating a new call
|
|
if( !QueueSuppServiceWorkItem( TSPI_DIAL_TRNASFEREDCALL, m_hdCall,
|
|
(ULONG_PTR)m_pTransferedToAlias ))
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "could not post dial transfer event." ));
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTInitiate exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCTInitiateArg,
|
|
CTInitiateArg_PDU );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//!!always called in a lock
|
|
BOOL
|
|
CH323Call::HandleCTSetup(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
PH323_CALL pCall = NULL;
|
|
WORD wRelatedCallRef = 0;
|
|
int iCTCallID;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTSetup entered:%p.", this ));
|
|
|
|
CTSetupArg * pCTSetupArg;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &pCTSetupArg,
|
|
CTSetupArg_PDU, pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (pCTSetupArg == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_TRANSFEREDDEST;
|
|
m_dwCallDiversionState = H4502_CTSETUP_RECV;
|
|
|
|
iCTCallID = atoi( pCTSetupArg->callIdentity );
|
|
|
|
if( iCTCallID != 0 )
|
|
{
|
|
m_hdRelatedCall = g_pH323Line -> GetCallFromCTCallIdentity( iCTCallID );
|
|
|
|
if( m_hdRelatedCall )
|
|
{
|
|
if( !QueueSuppServiceWorkItem( STOP_CTIDENTIFYRR_TIMER,
|
|
m_hdRelatedCall, (ULONG_PTR)m_hdCall ))
|
|
{
|
|
m_hdRelatedCall = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCTSetupArg,
|
|
CTSetupArg_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCTSEtup exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCheckRestriction(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen,
|
|
IN Q931_SETUP_ASN* pSetupASN
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCheckRestriction entered:%p.", this ));
|
|
|
|
CheckRestrictionArgument * pCheckRestriction;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &pCheckRestriction,
|
|
CheckRestrictionArgument_PDU,
|
|
pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (pCheckRestriction == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( pSetupASN->pCalleeAliasList != NULL )
|
|
{
|
|
FreeAliasNames( pSetupASN->pCalleeAliasList );
|
|
pSetupASN->pCalleeAliasList = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(pSetupASN->pCalleeAliasList),
|
|
(PSetup_UUIE_sourceAddress)pCheckRestriction->divertedToNr.destinationAddress ) )
|
|
{
|
|
pSetupASN->pCalleeAliasList = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
if( pSetupASN->pCallerAliasList != NULL )
|
|
{
|
|
FreeAliasNames( pSetupASN->pCallerAliasList );
|
|
pSetupASN->pCallerAliasList = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(pSetupASN->pCallerAliasList),
|
|
(PSetup_UUIE_sourceAddress)
|
|
pCheckRestriction->servedUserNr.destinationAddress ) )
|
|
{
|
|
pSetupASN->pCallerAliasList = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_FORWARDCONSULT;
|
|
|
|
if( !InitializeIncomingCall( pSetupASN, CALLTYPE_FORWARDCONSULT, 0 ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
FreeSetupASN( pSetupASN );
|
|
m_dwStateMachine = Q931_SETUP_RECVD;
|
|
m_dwCallDiversionState = H4503_CHECKRESTRICTION_RECV;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCheckRestriction,
|
|
CheckRestrictionArgument_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCheckRestriction exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCheckRestriction,
|
|
CheckRestrictionArgument_PDU );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleDiversionLegInfo1(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleDiversionLegInfo1 entered:%p.", this ));
|
|
|
|
DivertingLegInformation1Argument * plegInfo1Invoke;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &plegInfo1Invoke,
|
|
DivertingLegInformation1Argument_PDU,
|
|
pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (plegInfo1Invoke == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
m_pCallReroutingInfo = new CALLREROUTINGINFO;
|
|
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
|
|
}
|
|
|
|
m_pCallReroutingInfo->diversionReason = plegInfo1Invoke->diversionReason;
|
|
|
|
m_pCallReroutingInfo->fPresentAllow = plegInfo1Invoke->subscriptionOption;
|
|
|
|
//argument.divertedToNr
|
|
if( m_pCallReroutingInfo->divertedToNrAlias != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertedToNrAlias );
|
|
m_pCallReroutingInfo->divertedToNrAlias = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->divertedToNrAlias),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(plegInfo1Invoke->nominatedNr.destinationAddress) ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_DIVERTEDSRC_NOROUTING;
|
|
m_dwCallDiversionState = H4503_DIVERSIONLEG1_RECVD;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, plegInfo1Invoke,
|
|
DivertingLegInformation1Argument_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleDiversionLegInfo1 exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, plegInfo1Invoke,
|
|
DivertingLegInformation1Argument_PDU );
|
|
|
|
FreeCallReroutingInfo();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleDiversionLegInfo2(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleDiversionLegInfo2 entered:%p.", this ));
|
|
|
|
DivertingLegInformation2Argument * plegInfo2Invoke;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &plegInfo2Invoke,
|
|
DivertingLegInformation2Argument_PDU,
|
|
pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (plegInfo2Invoke == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_ASSERTE(!m_pCallReroutingInfo);
|
|
|
|
m_pCallReroutingInfo = new CALLREROUTINGINFO;
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "memory failure." ));
|
|
goto cleanup;
|
|
}
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
|
|
|
|
//argument.diversionCounter
|
|
m_pCallReroutingInfo->diversionCounter =
|
|
plegInfo2Invoke->diversionCounter;
|
|
|
|
//argument.diversionReason
|
|
m_pCallReroutingInfo->diversionReason = plegInfo2Invoke->diversionReason;
|
|
|
|
if( m_pCallReroutingInfo->divertingNrAlias != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertingNrAlias );
|
|
m_pCallReroutingInfo->divertingNrAlias = NULL;
|
|
}
|
|
|
|
if( (plegInfo2Invoke->bit_mask & divertingNr_present ) &&
|
|
plegInfo2Invoke->divertingNr.destinationAddress )
|
|
{
|
|
//argument.divertingNr
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->divertingNrAlias),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(plegInfo2Invoke->divertingNr.destinationAddress) ) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "no divertingnr alias." ));
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
//argument.originalCalledNr
|
|
if( (plegInfo2Invoke->bit_mask &
|
|
DivertingLegInformation2Argument_originalCalledNr_present ) &&
|
|
plegInfo2Invoke->originalCalledNr.destinationAddress )
|
|
{
|
|
if( m_pCallReroutingInfo->originalCalledNr != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->originalCalledNr );
|
|
m_pCallReroutingInfo->originalCalledNr = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->originalCalledNr),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(plegInfo2Invoke->originalCalledNr.destinationAddress)) )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "no originalcalled alias." ));
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_DIVERTEDDEST;
|
|
m_dwCallDiversionState = H4503_DIVERSIONLEG2_RECVD;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, plegInfo2Invoke,
|
|
DivertingLegInformation2Argument_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleDiversionLegInfo2 exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, plegInfo2Invoke,
|
|
DivertingLegInformation2Argument_PDU );
|
|
|
|
FreeCallReroutingInfo();
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::FreeCallReroutingInfo(void)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeCallReroutingInfo entered:%p.", this ));
|
|
|
|
if( m_pCallReroutingInfo != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertingNrAlias );
|
|
FreeAliasNames( m_pCallReroutingInfo->originalCalledNr );
|
|
FreeAliasNames( m_pCallReroutingInfo->divertedToNrAlias );
|
|
FreeAliasNames( m_pCallReroutingInfo->diversionNrAlias );
|
|
|
|
delete m_pCallReroutingInfo;
|
|
m_pCallReroutingInfo = NULL;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeCallReroutingInfo exited:%p.", this ));
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleDiversionLegInfo3(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleDiversionLegInfo3 entered:%p.", this ));
|
|
|
|
DivertingLegInformation3Argument * plegInfo3Invoke;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &plegInfo3Invoke,
|
|
DivertingLegInformation3Argument_PDU,
|
|
pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (plegInfo3Invoke == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
_ASSERTE(m_pCallReroutingInfo);
|
|
|
|
m_pCallReroutingInfo-> fPresentAllow =
|
|
plegInfo3Invoke->presentationAllowedIndicator;
|
|
|
|
if( m_pCallReroutingInfo->diversionNrAlias )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->diversionNrAlias );
|
|
m_pCallReroutingInfo->diversionNrAlias = NULL;
|
|
}
|
|
|
|
//argument.redirectionNr
|
|
if( (plegInfo3Invoke->bit_mask & redirectionNr_present ) &&
|
|
plegInfo3Invoke->redirectionNr.destinationAddress )
|
|
{
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->diversionNrAlias),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(plegInfo3Invoke->redirectionNr.destinationAddress) ) )
|
|
{
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
_ASSERTE( (m_dwCallType & CALLTYPE_DIVERTEDSRC ) ||
|
|
(m_dwCallType & CALLTYPE_DIVERTEDSRC_NOROUTING ) );
|
|
m_dwCallDiversionState = H4503_DIVERSIONLEG3_RECVD;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, plegInfo3Invoke,
|
|
DivertingLegInformation3Argument_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleDiversionLegInfo3 exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
/*cleanup:
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, plegInfo3Invoke,
|
|
DivertingLegInformation3Argument_PDU );
|
|
|
|
FreeCallReroutingInfo();
|
|
return FALSE;
|
|
*/
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::HandleCallRerouting(
|
|
IN BYTE * pEncodeArg,
|
|
IN DWORD dwEncodedArgLen
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCallRerouting entered:%p.", this ));
|
|
|
|
CallReroutingArgument* pCallReroutingInv;
|
|
|
|
int iResult = DecodeH450ASN( (void **) &pCallReroutingInv,
|
|
CallReroutingArgument_PDU,
|
|
pEncodeArg, dwEncodedArgLen );
|
|
|
|
if( ASN1_FAILED(iResult) || (pCallReroutingInv == NULL) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
m_pCallReroutingInfo = new CALLREROUTINGINFO;
|
|
if( m_pCallReroutingInfo == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
ZeroMemory( (PVOID)m_pCallReroutingInfo, sizeof(CALLREROUTINGINFO) );
|
|
}
|
|
|
|
if( pCallReroutingInv->diversionCounter > MAX_DIVERSION_COUNTER )
|
|
return FALSE;
|
|
|
|
m_pCallReroutingInfo->diversionCounter =
|
|
pCallReroutingInv->diversionCounter;
|
|
|
|
m_pCallReroutingInfo->diversionReason = pCallReroutingInv->reroutingReason;
|
|
|
|
if( pCallReroutingInv->bit_mask & originalReroutingReason_present )
|
|
{
|
|
m_pCallReroutingInfo->originalDiversionReason =
|
|
pCallReroutingInv->originalReroutingReason;
|
|
}
|
|
else
|
|
{
|
|
m_pCallReroutingInfo->originalDiversionReason =
|
|
pCallReroutingInv->reroutingReason;
|
|
}
|
|
|
|
if( ( pCallReroutingInv->bit_mask &
|
|
CallReroutingArgument_originalCalledNr_present ) &&
|
|
pCallReroutingInv->originalCalledNr.destinationAddress )
|
|
{
|
|
|
|
if( m_pCallReroutingInfo->originalCalledNr != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->originalCalledNr );
|
|
m_pCallReroutingInfo->originalCalledNr = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->originalCalledNr),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(pCallReroutingInv->originalCalledNr.destinationAddress) ) )
|
|
{
|
|
//goto cleanup;
|
|
}
|
|
}
|
|
|
|
if( m_pCallReroutingInfo->divertingNrAlias != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertingNrAlias );
|
|
m_pCallReroutingInfo->divertingNrAlias = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->divertingNrAlias),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(pCallReroutingInv->lastReroutingNr.destinationAddress) ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if( m_pCallReroutingInfo->divertedToNrAlias != NULL )
|
|
{
|
|
FreeAliasNames( m_pCallReroutingInfo->divertedToNrAlias );
|
|
m_pCallReroutingInfo->divertedToNrAlias = NULL;
|
|
}
|
|
|
|
if( !AliasAddrToAliasNames( &(m_pCallReroutingInfo->divertedToNrAlias),
|
|
(PSetup_UUIE_sourceAddress)
|
|
(pCallReroutingInv->calledAddress.destinationAddress) ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
m_dwCallType |= CALLTYPE_DIVERTEDSRC;
|
|
m_dwCallDiversionState = H4503_CALLREROUTING_RECVD;
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCallReroutingInv,
|
|
CallReroutingArgument_PDU );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "HandleCallRerouting exited:%p.", this ));
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
ASN1_FreeDecoded( m_H450ASNCoderInfo.pDecInfo, pCallReroutingInv,
|
|
CallReroutingArgument_PDU );
|
|
|
|
FreeCallReroutingInfo();
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeRejectAPDU(
|
|
IN H4501SupplementaryService * pSupplementaryServiceAPDU,
|
|
IN DWORD dwInvokeID,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
WORD wAPDULen;
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeRejectAPDU entered:%p.", this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
pROSAPDU->value.choice = reject_chosen;
|
|
pROSAPDU->value.u.reject.invokeId = (WORD)dwInvokeID;
|
|
pROSAPDU->value.u.reject.problem.choice = H4503ROS_invoke_chosen;
|
|
pROSAPDU->value.u.reject.problem.u.invoke = InvokeProblem_mistypedArgument;
|
|
|
|
//call ASN.1 encoding functions
|
|
int rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wAPDULen );
|
|
|
|
*pdwAPDULen = wAPDULen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeRejectAPDU exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeReturnErrorAPDU(
|
|
IN DWORD dwInvokeID,
|
|
IN DWORD dwErrorCode,
|
|
IN H4501SupplementaryService *pH450APDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
WORD wAPDULen;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeReturnErrorAPDU entered:%p.", this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU = pH450APDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
pROSAPDU ->value.choice = H4503ROS_returnError_chosen;
|
|
pROSAPDU ->value.u.returnError.invokeId = (WORD)dwInvokeID;
|
|
|
|
pROSAPDU ->value.u.returnError.errcode.choice = local_chosen;
|
|
pROSAPDU ->value.u.returnError.errcode.u.local = dwErrorCode;
|
|
|
|
//call ASN.1 encoding functions
|
|
int rc = EncodeH450ASN( (void *) pH450APDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wAPDULen );
|
|
|
|
*pdwAPDULen = wAPDULen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeReturnErrorAPDU exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeDummyReturnResultAPDU(
|
|
IN DWORD dwInvokeID,
|
|
IN DWORD dwOpCode,
|
|
IN H4501SupplementaryService *pH450APDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
WORD wEncodedLen = 0;
|
|
int rc;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDummyReturnResultAPDU entered:%p.",
|
|
this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU = pH450APDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
pROSAPDU ->value.choice = H4503ROS_returnResult_chosen;
|
|
|
|
pROSAPDU ->value.u.returnResult.invokeId = (WORD)dwInvokeID;
|
|
pROSAPDU ->value.u.returnResult.bit_mask = result_present;
|
|
|
|
pROSAPDU ->value.u.returnResult.result.opcode.choice = local_chosen;
|
|
pROSAPDU ->value.u.returnResult.result.opcode.u.local = dwOpCode;
|
|
|
|
//dummy result not present
|
|
pROSAPDU ->value.u.returnResult.result.result.length = 0;
|
|
pROSAPDU ->value.u.returnResult.result.result.value = NULL;
|
|
|
|
switch( dwOpCode )
|
|
{
|
|
case CTIDENTIFY_OPCODE:
|
|
|
|
pROSAPDU ->value.u.returnResult.result.result.value = pBufEncodedArg;
|
|
|
|
if( !EncodeCTIdentifyReturnResult( pROSAPDU ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
pROSAPDU ->value.u.returnResult.result.result.value = pBufEncodedArg;
|
|
|
|
if( !EncodeDummyResult( pROSAPDU ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
//call ASN.1 encoding functions
|
|
rc = EncodeH450ASN( (void *) pH450APDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDummyReturnResultAPDU exited:%p.",
|
|
this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeDummyResult(
|
|
OUT ServiceApdus_rosApdus *pROSAPDU
|
|
)
|
|
{
|
|
DummyRes dummyRes;
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
int rc;
|
|
UCHAR sData[3] = "MS";
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDummyResult entered:%p.", this ));
|
|
|
|
ZeroMemory( (PVOID)&dummyRes, sizeof(DummyRes) );
|
|
|
|
dummyRes.choice = DummyRes_nonStandardData_chosen;
|
|
dummyRes.u.nonStandardData.nonStandardIdentifier.choice
|
|
= H225NonStandardIdentifier_h221NonStandard_chosen;
|
|
dummyRes.u.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35CountryCode
|
|
= H221_COUNTRY_CODE_USA;
|
|
dummyRes.u.nonStandardData.nonStandardIdentifier.u.h221NonStandard.t35Extension
|
|
= H221_COUNTRY_EXT_USA;
|
|
dummyRes.u.nonStandardData.nonStandardIdentifier.u.h221NonStandard.manufacturerCode
|
|
= H221_MFG_CODE_MICROSOFT;
|
|
|
|
dummyRes.u.nonStandardData.data.length = 2;
|
|
dummyRes.u.nonStandardData.data.value = sData;
|
|
|
|
//encode the return result argument.
|
|
rc = EncodeH450ASN( (void*) &dummyRes,
|
|
DummyRes_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pROSAPDU ->value.u.returnResult.result.result.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU ->value.u.returnResult.result.result.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDummyResult exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeCTIdentifyReturnResult(
|
|
OUT ServiceApdus_rosApdus *pROSAPDU
|
|
)
|
|
{
|
|
CTIdentifyRes cTIdentifyRes;
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
int iCallID;
|
|
int rc;
|
|
|
|
ZeroMemory( (PVOID)&cTIdentifyRes, sizeof(CTIdentifyRes) );
|
|
|
|
iCallID = g_pH323Line -> GetCTCallIdentity(m_hdCall );
|
|
|
|
if( iCallID == 0 )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//argument.callIdentity
|
|
_itoa( iCallID, (char*)m_pCTCallIdentity, 10 );
|
|
|
|
CopyMemory( (PVOID)cTIdentifyRes.callIdentity, (PVOID)m_pCTCallIdentity,
|
|
sizeof(m_pCTCallIdentity) );
|
|
|
|
//argument.reroutingNumber
|
|
cTIdentifyRes.reroutingNumber.bit_mask = 0;
|
|
|
|
cTIdentifyRes.reroutingNumber.destinationAddress =
|
|
(PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCalleeAliasNames );
|
|
|
|
if( cTIdentifyRes.reroutingNumber.destinationAddress == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//encode the return result argument.
|
|
rc = EncodeH450ASN( (void *) &cTIdentifyRes,
|
|
CTIdentifyRes_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
cTIdentifyRes.reroutingNumber.destinationAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
pROSAPDU ->value.u.returnResult.result.result.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU ->value.u.returnResult.result.result.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
cTIdentifyRes.reroutingNumber.destinationAddress );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//supplemantary services functions
|
|
BOOL
|
|
CH323Call::EncodeCheckRestrictionAPDU(
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
BOOL retVal = FALSE;
|
|
int rc = 0;
|
|
TCHAR szMsg[20];
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCheckRestrictionAPDU entered:%p.",
|
|
this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = argument_present;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
m_dwInvokeID = pROSAPDU->value.u.invoke.invokeId;
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = CHECKRESTRICTION_OPCODE;
|
|
|
|
//argument
|
|
CheckRestrictionArgument checkRestrictionArgument;
|
|
ZeroMemory( (PVOID)&checkRestrictionArgument,
|
|
sizeof(CheckRestrictionArgument) );
|
|
|
|
//argument.divertedToNR
|
|
checkRestrictionArgument.divertedToNr.bit_mask = 0;
|
|
checkRestrictionArgument.divertedToNr.destinationAddress =
|
|
(PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCalleeAliasNames );
|
|
if( checkRestrictionArgument.divertedToNr.destinationAddress == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
if( m_pCallerAliasNames == NULL )
|
|
{
|
|
m_pCallerAliasNames = new H323_ALIASNAMES;
|
|
|
|
if( m_pCallerAliasNames == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate caller name." ));
|
|
goto cleanup;
|
|
}
|
|
memset( (PVOID)m_pCallerAliasNames, 0, sizeof(H323_ALIASNAMES) );
|
|
|
|
LoadString( g_hInstance,
|
|
IDS_UNKNOWN,
|
|
szMsg,
|
|
20
|
|
);
|
|
|
|
if( !AddAliasItem( m_pCallerAliasNames,
|
|
szMsg,
|
|
h323_ID_chosen ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
}
|
|
|
|
//argument.servedUserNR
|
|
checkRestrictionArgument.servedUserNr.bit_mask = 0;
|
|
|
|
checkRestrictionArgument.servedUserNr.destinationAddress =
|
|
(PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCallerAliasNames );
|
|
|
|
//H323DBG(( DEBUG_LEVEL_ERROR, "Caller alias count:%d : %p", m_pCallerAliasNames->wCount, this ));
|
|
|
|
if( checkRestrictionArgument.servedUserNr.destinationAddress == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//argument.basicservice
|
|
checkRestrictionArgument.basicService = allServices;
|
|
|
|
//encode the checkrestriction argument.
|
|
rc = EncodeH450ASN( (void *) &checkRestrictionArgument,
|
|
CheckRestrictionArgument_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pROSAPDU->value.u.invoke.argument.value = pBufEncodedArg;
|
|
pROSAPDU->value.u.invoke.argument.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU->value.u.invoke.argument.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
//call ASN.1 encoding functions
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCheckRestrictionAPDU exited:%p.",
|
|
this ));
|
|
retVal = TRUE;
|
|
|
|
cleanup:
|
|
|
|
if( checkRestrictionArgument.servedUserNr.destinationAddress )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
checkRestrictionArgument.servedUserNr.destinationAddress );
|
|
}
|
|
|
|
if( checkRestrictionArgument.divertedToNr.destinationAddress )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
checkRestrictionArgument.divertedToNr.destinationAddress );
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeDivertingLeg2APDU(
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
BOOL retVal = FALSE;
|
|
int rc = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDivertingLeg2APDU entered:%p.", this ));
|
|
|
|
pSupplementaryServiceAPDU->interpretationApdu.choice =
|
|
discardAnyUnrecognizedInvokePdu_chosen;
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = argument_present;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = DIVERTINGLEGINFO2_OPCODE;
|
|
|
|
//argument
|
|
DivertingLegInformation2Argument divertLegInfo2Arg;
|
|
|
|
ZeroMemory( (PVOID)&divertLegInfo2Arg,
|
|
sizeof(DivertingLegInformation2Argument) );
|
|
|
|
//argument.diversionCounter
|
|
divertLegInfo2Arg.diversionCounter
|
|
= (WORD)m_pCallReroutingInfo->diversionCounter;
|
|
|
|
//argument.diversionreason
|
|
divertLegInfo2Arg.diversionReason = m_pCallReroutingInfo->diversionReason;
|
|
|
|
//argument.originalDiversionReason
|
|
if( m_pCallReroutingInfo->originalDiversionReason != 0 )
|
|
{
|
|
divertLegInfo2Arg.originalDiversionReason =
|
|
m_pCallReroutingInfo->originalDiversionReason;
|
|
|
|
divertLegInfo2Arg.bit_mask |= originalDiversionReason_present;
|
|
}
|
|
|
|
//argument.divertingNr
|
|
if( m_pCallReroutingInfo->divertingNrAlias != NULL )
|
|
{
|
|
divertLegInfo2Arg.bit_mask |= divertingNr_present;
|
|
|
|
divertLegInfo2Arg.divertingNr.bit_mask = 0;
|
|
divertLegInfo2Arg.divertingNr.destinationAddress
|
|
= (PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCallReroutingInfo->divertingNrAlias );
|
|
|
|
if( divertLegInfo2Arg.divertingNr.destinationAddress == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//argument.originalCalledNr
|
|
if( m_pCallReroutingInfo->originalCalledNr != NULL )
|
|
{
|
|
divertLegInfo2Arg.bit_mask |=
|
|
DivertingLegInformation2Argument_originalCalledNr_present;
|
|
|
|
divertLegInfo2Arg.originalCalledNr.bit_mask = 0;
|
|
divertLegInfo2Arg.originalCalledNr.destinationAddress
|
|
= (PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCallReroutingInfo->originalCalledNr );
|
|
|
|
if( divertLegInfo2Arg.originalCalledNr.destinationAddress == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
//encode the divertingleg2 argument.
|
|
rc = EncodeH450ASN( (void *) &divertLegInfo2Arg,
|
|
DivertingLegInformation2Argument_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pROSAPDU->value.u.invoke.argument.value = pBufEncodedArg;
|
|
pROSAPDU->value.u.invoke.argument.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU->value.u.invoke.argument.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before encoding new one
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
//call ASN.1 encoding function for APDU
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDivertingLeg2APDU exited:%p.", this ));
|
|
retVal= TRUE;
|
|
|
|
cleanup:
|
|
|
|
if( divertLegInfo2Arg.divertingNr.destinationAddress )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
divertLegInfo2Arg.divertingNr.destinationAddress );
|
|
}
|
|
|
|
if( divertLegInfo2Arg.originalCalledNr.destinationAddress )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
divertLegInfo2Arg.originalCalledNr.destinationAddress );
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeDivertingLeg3APDU(
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDivertingLeg3APDU entered:%p.", this ));
|
|
|
|
pSupplementaryServiceAPDU->interpretationApdu.choice =
|
|
discardAnyUnrecognizedInvokePdu_chosen;
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = argument_present;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = DIVERTINGLEGINFO3_OPCODE;
|
|
|
|
//argument
|
|
DivertingLegInformation3Argument divertLegInfo3Arg;
|
|
ZeroMemory( (PVOID)&divertLegInfo3Arg,
|
|
sizeof(DivertingLegInformation3Argument) );
|
|
|
|
//argument.presentationallowed
|
|
divertLegInfo3Arg.presentationAllowedIndicator = TRUE;
|
|
|
|
//argument.redirectionNr
|
|
divertLegInfo3Arg.redirectionNr.bit_mask = 0;
|
|
|
|
divertLegInfo3Arg.redirectionNr.destinationAddress =
|
|
(PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCalleeAliasNames );
|
|
|
|
if( divertLegInfo3Arg.redirectionNr.destinationAddress )
|
|
{
|
|
divertLegInfo3Arg.bit_mask |= redirectionNr_present;
|
|
}
|
|
|
|
//encode the divertingleg3 argument.
|
|
int rc = EncodeH450ASN( (void *) &divertLegInfo3Arg,
|
|
DivertingLegInformation3Argument_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
if( divertLegInfo3Arg.redirectionNr.destinationAddress )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
divertLegInfo3Arg.redirectionNr.destinationAddress );
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
pROSAPDU->value.u.invoke.argument.value = pBufEncodedArg;
|
|
pROSAPDU->value.u.invoke.argument.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU->value.u.invoke.argument.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before encoding new one
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
if( divertLegInfo3Arg.redirectionNr.destinationAddress )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
divertLegInfo3Arg.redirectionNr.destinationAddress );
|
|
}
|
|
|
|
//call ASN.1 encoding function for APDU
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeDivertingLeg3APDU exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeCallReroutingAPDU(
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
BOOL retVal = FALSE;
|
|
int rc = 0;
|
|
UCHAR bearerCap[5];
|
|
TCHAR szMsg[20];
|
|
|
|
PH323_ALIASNAMES pCallerAliasNames = m_pCallerAliasNames;
|
|
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCallReroutingAPDU entered:%p.", this ));
|
|
|
|
_ASSERTE( m_pCallReroutingInfo );
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = argument_present;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
m_dwInvokeID = pROSAPDU->value.u.invoke.invokeId;
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = CALLREROUTING_OPCODE;
|
|
|
|
//argument
|
|
CallReroutingArgument callReroutingArg;
|
|
ZeroMemory( (PVOID)&callReroutingArg, sizeof(CallReroutingArgument) );
|
|
|
|
//argument.reroutingReason
|
|
callReroutingArg.reroutingReason = m_pCallReroutingInfo->diversionReason;
|
|
|
|
//argument.originalReroutingReason
|
|
if( m_pCallReroutingInfo->originalDiversionReason != 0 )
|
|
{
|
|
callReroutingArg.originalReroutingReason
|
|
= m_pCallReroutingInfo->originalDiversionReason;
|
|
}
|
|
else
|
|
{
|
|
callReroutingArg.originalReroutingReason
|
|
= m_pCallReroutingInfo->diversionReason;
|
|
}
|
|
|
|
//argument.diversionCounter
|
|
callReroutingArg.diversionCounter =
|
|
++(m_pCallReroutingInfo->diversionCounter);
|
|
|
|
//argument.calledAddress
|
|
callReroutingArg.calledAddress.bit_mask = 0;
|
|
callReroutingArg.calledAddress.destinationAddress
|
|
= (PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias(m_pCallReroutingInfo->divertedToNrAlias);
|
|
|
|
if( callReroutingArg.calledAddress.destinationAddress == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//argument.lastReroutingNr
|
|
callReroutingArg.lastReroutingNr.bit_mask = 0;
|
|
callReroutingArg.lastReroutingNr.destinationAddress
|
|
= (PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias(m_pCalleeAliasNames);
|
|
|
|
if( callReroutingArg.lastReroutingNr.destinationAddress == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//argument.subscriptionoption
|
|
callReroutingArg.subscriptionOption = notificationWithDivertedToNr;
|
|
|
|
//argument.callingNumber
|
|
callReroutingArg.callingNumber.bit_mask = 0;
|
|
|
|
if( pCallerAliasNames == NULL )
|
|
{
|
|
pCallerAliasNames = new H323_ALIASNAMES;
|
|
|
|
if( pCallerAliasNames == NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate caller name." ));
|
|
goto cleanup;
|
|
}
|
|
memset( (PVOID)pCallerAliasNames, 0, sizeof(H323_ALIASNAMES) );
|
|
|
|
LoadString( g_hInstance,
|
|
IDS_UNKNOWN,
|
|
szMsg,
|
|
20
|
|
);
|
|
|
|
if( !AddAliasItem( pCallerAliasNames,
|
|
szMsg,
|
|
h323_ID_chosen ) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
callReroutingArg.callingNumber.destinationAddress
|
|
= (PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias(pCallerAliasNames);
|
|
|
|
if( callReroutingArg.callingNumber.destinationAddress == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
//argumnt.h225infoelement
|
|
callReroutingArg.h225InfoElement.length = 5;
|
|
callReroutingArg.h225InfoElement.value = bearerCap;
|
|
|
|
bearerCap[0]= IDENT_BEARERCAP;
|
|
bearerCap[1]= 0x03; //length of the bearer capability
|
|
bearerCap[2]= (BYTE)(BEAR_EXT_BIT | BEAR_CCITT | BEAR_UNRESTRICTED_DIGITAL);
|
|
|
|
bearerCap[3]= BEAR_EXT_BIT | 0x17;
|
|
bearerCap[4]= (BYTE)(BEAR_EXT_BIT | BEAR_LAYER1_INDICATOR |
|
|
BEAR_LAYER1_H221_H242);
|
|
|
|
|
|
//argument.callingNumber
|
|
if( m_pCallReroutingInfo->originalCalledNr != NULL )
|
|
{
|
|
callReroutingArg.originalCalledNr.bit_mask = 0;
|
|
|
|
callReroutingArg.originalCalledNr.destinationAddress
|
|
= (PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pCallReroutingInfo->originalCalledNr );
|
|
|
|
if( callReroutingArg.originalCalledNr.destinationAddress != NULL )
|
|
{
|
|
callReroutingArg.bit_mask |=
|
|
CallReroutingArgument_originalCalledNr_present;
|
|
}
|
|
}
|
|
|
|
//encode the callrerouting argument.
|
|
rc = EncodeH450ASN( (void *) &callReroutingArg,
|
|
CallReroutingArgument_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pROSAPDU->value.u.invoke.argument.value = pBufEncodedArg;
|
|
pROSAPDU->value.u.invoke.argument.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU->value.u.invoke.argument.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before encoding new one
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
//call ASN.1 encoding function for APDU
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCallReroutingAPDU exited:%p.", this ));
|
|
retVal = TRUE;
|
|
|
|
cleanup:
|
|
if( pCallerAliasNames != m_pCallerAliasNames )
|
|
{
|
|
FreeAliasNames( pCallerAliasNames );
|
|
}
|
|
|
|
FreeCallReroutingArg( &callReroutingArg );
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//No need to call in a lock!!
|
|
void
|
|
CH323Call::FreeCallReroutingArg(
|
|
CallReroutingArgument* pCallReroutingArg
|
|
)
|
|
{
|
|
//free all the aliases
|
|
if( pCallReroutingArg->calledAddress.destinationAddress != NULL )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
pCallReroutingArg->calledAddress.destinationAddress );
|
|
}
|
|
|
|
if( pCallReroutingArg->lastReroutingNr.destinationAddress != NULL )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
pCallReroutingArg->lastReroutingNr.destinationAddress );
|
|
}
|
|
|
|
if( pCallReroutingArg->callingNumber.destinationAddress != NULL )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
pCallReroutingArg->callingNumber.destinationAddress );
|
|
}
|
|
|
|
if( pCallReroutingArg->originalCalledNr.destinationAddress != NULL )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
pCallReroutingArg->originalCalledNr.destinationAddress );
|
|
}
|
|
}
|
|
|
|
|
|
// static
|
|
void
|
|
NTAPI CH323Call::CallEstablishmentExpiredCallback(
|
|
IN PVOID DriverCallHandle, // HDRVCALL
|
|
IN BOOLEAN bTimer)
|
|
{
|
|
PH323_CALL pCall = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CallEstablishmentExpiredCallback entered." ));
|
|
|
|
//if the timer expired
|
|
_ASSERTE( bTimer );
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "Q931 setup expired event recvd." ));
|
|
pCall=g_pH323Line -> FindH323CallAndLock((HDRVCALL) DriverCallHandle);
|
|
|
|
if( pCall != NULL )
|
|
{
|
|
if( pCall -> GetStateMachine() != Q931_CONNECT_RECVD )
|
|
{
|
|
//time out has occured
|
|
pCall -> CloseCall( LINEDISCONNECTMODE_NOANSWER );
|
|
}
|
|
|
|
pCall -> Unlock();
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CallEstablishmentExpiredCallback exited." ));
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//CALL TRANSFER (H450.2) ENCODE/DECODE ROUTINES
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeH450APDUNoArgument(
|
|
IN DWORD dwOpcode,
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
int rc;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeH450APDUNoArgument entered:%p.",
|
|
this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = 0;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
m_dwInvokeID = pROSAPDU->value.u.invoke.invokeId;
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = dwOpcode;
|
|
|
|
//no argument passed
|
|
|
|
//call ASN.1 encoding function for APDU
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeH450APDUNoArgument exited:%p.",
|
|
this ));
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
CH323Call::EncodeCTInitiateAPDU(
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
int rc = 0;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCTInitiateAPDU entered:%p.", this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = argument_present;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
m_dwInvokeID = pROSAPDU->value.u.invoke.invokeId;
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = CTINITIATE_OPCODE;
|
|
|
|
//argument
|
|
CTInitiateArg cTInitiateArg;
|
|
ZeroMemory( (PVOID)&cTInitiateArg, sizeof(CTInitiateArg) );
|
|
|
|
//argument.callIdentity
|
|
CopyMemory( (PVOID)cTInitiateArg.callIdentity,
|
|
(PVOID)m_pCTCallIdentity, sizeof(m_pCTCallIdentity) );
|
|
|
|
//argument.reroutingNumber
|
|
cTInitiateArg.reroutingNumber.bit_mask = 0;
|
|
cTInitiateArg.reroutingNumber.destinationAddress =
|
|
(PEndpointAddress_destinationAddress)
|
|
SetMsgAddressAlias( m_pTransferedToAlias );
|
|
|
|
if( cTInitiateArg.reroutingNumber.destinationAddress == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//encode the CTSetup argument.
|
|
rc = EncodeH450ASN( (void *) &cTInitiateArg,
|
|
CTInitiateArg_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
cTInitiateArg.reroutingNumber.destinationAddress );
|
|
return FALSE;
|
|
}
|
|
|
|
pROSAPDU->value.u.invoke.argument.value = pBufEncodedArg;
|
|
pROSAPDU->value.u.invoke.argument.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU->value.u.invoke.argument.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before encoding new one
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)
|
|
cTInitiateArg.reroutingNumber.destinationAddress );
|
|
|
|
//call ASN.1 encoding function for APDU
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCTInitiateAPDU exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::EncodeCTSetupAPDU(
|
|
OUT H4501SupplementaryService *pSupplementaryServiceAPDU,
|
|
OUT BYTE** ppEncodedAPDU,
|
|
OUT DWORD* pdwAPDULen
|
|
)
|
|
{
|
|
BYTE *pEncodedArg = NULL;
|
|
WORD wEncodedLen = 0;
|
|
BYTE pBufEncodedArg[H450_ENCODED_ARG_LEN];
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCTSetupAPDU entered:%p.", this ));
|
|
|
|
ServiceApdus_rosApdus *pROSAPDU =
|
|
pSupplementaryServiceAPDU->serviceApdu.u.rosApdus;
|
|
|
|
pROSAPDU->next = NULL;
|
|
|
|
pROSAPDU->value.choice = H4503ROS_invoke_chosen;
|
|
|
|
pROSAPDU->value.u.invoke.bit_mask = argument_present;
|
|
|
|
//invoke ID
|
|
pROSAPDU->value.u.invoke.invokeId = g_pH323Line->GetNextInvokeID();
|
|
m_dwInvokeID = pROSAPDU->value.u.invoke.invokeId;
|
|
|
|
//opcode
|
|
pROSAPDU->value.u.invoke.opcode.choice = local_chosen;
|
|
pROSAPDU->value.u.invoke.opcode.u.local = CTSETUP_OPCODE;
|
|
|
|
//argument
|
|
CTSetupArg cTSetupArg;
|
|
ZeroMemory( (PVOID)&cTSetupArg, sizeof(CTSetupArg) );
|
|
|
|
//argument.callIdentity
|
|
CopyMemory( (PVOID)cTSetupArg.callIdentity,
|
|
(PVOID)m_pCTCallIdentity, sizeof(m_pCTCallIdentity) );
|
|
|
|
//no argument.transferingNumber
|
|
|
|
//encode the CTSetup argument.
|
|
int rc = EncodeH450ASN( (void *) &cTSetupArg,
|
|
CTSetupArg_PDU,
|
|
&pEncodedArg,
|
|
&wEncodedLen );
|
|
|
|
if( ASN1_FAILED(rc) || (pEncodedArg == NULL) || (wEncodedLen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pROSAPDU->value.u.invoke.argument.value = pBufEncodedArg;
|
|
pROSAPDU->value.u.invoke.argument.length = wEncodedLen;
|
|
|
|
CopyMemory( (PVOID)pROSAPDU->value.u.invoke.argument.value,
|
|
pEncodedArg, wEncodedLen );
|
|
|
|
//free the previous asn buffer before encoding new one
|
|
ASN1_FreeEncoded(m_ASNCoderInfo.pEncInfo, pEncodedArg );
|
|
|
|
//call ASN.1 encoding function for APDU
|
|
rc = EncodeH450ASN( (void *) pSupplementaryServiceAPDU,
|
|
H4501SupplementaryService_PDU,
|
|
ppEncodedAPDU,
|
|
&wEncodedLen );
|
|
|
|
*pdwAPDULen = wEncodedLen;
|
|
|
|
if( ASN1_FAILED(rc) || (*ppEncodedAPDU == NULL) || (pdwAPDULen == 0) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "EncodeCTSetupAPDU exited:%p.", this ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void CH323Call::PostLineEvent (
|
|
IN DWORD MessageID,
|
|
IN DWORD_PTR Parameter1,
|
|
IN DWORD_PTR Parameter2,
|
|
IN DWORD_PTR Parameter3)
|
|
{
|
|
(*g_pfnLineEventProc) (
|
|
g_pH323Line -> m_htLine,
|
|
m_htCall,
|
|
MessageID,
|
|
Parameter1,
|
|
Parameter2,
|
|
Parameter3);
|
|
}
|
|
|
|
|
|
//!!must be always called in a lock
|
|
void
|
|
CH323Call::DecrementIoRefCount(
|
|
OUT BOOL * pfDelete
|
|
)
|
|
{
|
|
_ASSERTE( m_IoRefCount != 0 );
|
|
m_IoRefCount--;
|
|
|
|
H323DBG((DEBUG_LEVEL_TRACE, "DecrementIoRefCount:m_IoRefCount:%d:%p.",
|
|
m_IoRefCount, this ));
|
|
|
|
*pfDelete = FALSE;
|
|
|
|
if( m_dwFlags & CALLOBJECT_SHUTDOWN )
|
|
{
|
|
*pfDelete = (m_IoRefCount==0) ? TRUE : FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
//!!must be always called in a lock
|
|
void
|
|
CH323Call::StopCTIdentifyRRTimer(
|
|
HDRVCALL hdRelatedCall
|
|
)
|
|
{
|
|
if( m_hCTIdentifyRRTimer != NULL )
|
|
{
|
|
DeleteTimerQueueTimer( H323TimerQueue, m_hCTIdentifyRRTimer, NULL );
|
|
m_hCTIdentifyRRTimer = NULL;
|
|
}
|
|
|
|
m_hdRelatedCall = hdRelatedCall;
|
|
}
|
|
|
|
|
|
void
|
|
CH323Call::InitializeRecvBuf()
|
|
{
|
|
m_RecvBuf.WSABuf.len = sizeof(TPKT_HEADER_SIZE);
|
|
m_RecvBuf.WSABuf.buf = m_RecvBuf.arBuf;
|
|
m_RecvBuf.dwPDULen = m_RecvBuf.dwBytesCopied = 0;
|
|
m_bStartOfPDU = TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
CH323Call::SetCallData(
|
|
LPVOID lpCallData,
|
|
DWORD dwSize )
|
|
{
|
|
if( m_CallData.pOctetString != NULL )
|
|
{
|
|
delete m_CallData.pOctetString;
|
|
}
|
|
|
|
m_CallData.pOctetString = new BYTE[dwSize];
|
|
|
|
if( m_CallData.pOctetString == NULL )
|
|
{
|
|
m_CallData.wOctetStringLength = 0;
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory( (PVOID)m_CallData.pOctetString, lpCallData, dwSize );
|
|
|
|
m_CallData.wOctetStringLength = (WORD)dwSize;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// Global Functions
|
|
|
|
BOOL
|
|
IsPhoneNumber(
|
|
char * szAddr
|
|
)
|
|
{
|
|
while( *szAddr )
|
|
{
|
|
if( !isdigit(*szAddr) &&
|
|
('#' != *szAddr) &&
|
|
('*' != *szAddr) &&
|
|
('+' != *szAddr)
|
|
)
|
|
return FALSE;
|
|
szAddr++;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
IsValidE164String(
|
|
IN WCHAR* wszDigits
|
|
)
|
|
{
|
|
for( ; (*wszDigits) != L'\0'; wszDigits++ )
|
|
{
|
|
if(!(
|
|
((*wszDigits >= L'0') && (*wszDigits <= L'9')) ||
|
|
(*wszDigits == L'*') ||
|
|
(*wszDigits == L'#') ||
|
|
(*wszDigits == L'!') ||
|
|
(*wszDigits == L',')
|
|
))
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
} |