|
|
/*++
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 = NULL;
tempPtr = (PH323_ALIASITEM)realloc( (PVOID)setupASN.pCallerAliasList->pItems, wCount * sizeof(H323_ALIASITEM) );
if( tempPtr == NULL ) { //restore the old pointer in case enough memory was not
//available to expand the memory block
} else { setupASN.pCallerAliasList->pItems = tempPtr;
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 = NULL; tempPtr = (PH323_ALIASITEM)realloc( (PVOID)m_pCalleeAliasNames->pItems, wCount * sizeof(H323_ALIASITEM) );
if( tempPtr == NULL ) { //restore the old pointer in case enough memory was not
//available to expand the memory block
goto cleanup; }
m_pCalleeAliasNames->pItems = tempPtr; 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 = 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 = new BYTE[ dwDataSize ];
// validate pointer
if (pU2ULE->pU2U == NULL) { H323DBG(( DEBUG_LEVEL_ERROR, "could not allocate user user info." ));
delete pU2ULE;
// failure
return FALSE; }
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 ("[email protected]"). !!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 && 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; }
//We are assigning here part of the structure and then may be the structure is deleted or not??
m_NonStandardData.sData.pOctetString = pU2ULE->pU2U; delete pU2ULE; } 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; }
|