|
|
// File: icall.cpp
#include "precomp.h"
#include "icall.h"
#include "rostinfo.h"
#include "imanager.h"
#include "mperror.h"
#include "nmremote.h"
#include "util.h"
typedef struct { BOOL fMCU; PWSTR * pwszConfNames; BSTR * pbstrConfToJoin; } REMOTE_CONFERENCE;
typedef struct { BSTR bstrConference; BSTR *pbstrPassword; PBYTE pbRemoteCred; DWORD cbRemoteCred; BOOL fIsService; } REMOTE_PASSWORD;
HRESULT OnNotifyCallError(IUnknown *pCallNotify, PVOID pv, REFIID riid);
static HRESULT OnNotifyRemoteConference(IUnknown *pCallNotify, PVOID pv, REFIID riid); static HRESULT OnNotifyRemotePassword(IUnknown *pCallNotify, PVOID pv, REFIID riid);
static const IID * g_apiidCP[] = { {&IID_INmCallNotify}, {&IID_INmCallNotify2} };
// String Functions
inline VOID FreeBstr(BSTR *pbstr) { if (NULL != pbstr) { SysFreeString(*pbstr); *pbstr = NULL; } }
/* P S Z A L L O C */ /*-------------------------------------------------------------------------
%%Function: PszAlloc
-------------------------------------------------------------------------*/ LPTSTR PszAlloc(LPCTSTR pszSrc) { if (NULL == pszSrc) return NULL;
LPTSTR pszDest = new TCHAR[lstrlen(pszSrc) + 1]; if (NULL != pszDest) { lstrcpy(pszDest, pszSrc); } return pszDest; }
COutgoingCall::COutgoingCall(CConfObject* pco, DWORD dwFlags, NM_ADDR_TYPE addrType, BSTR bstrName, BSTR bstrDest, BSTR bstrAlias, BSTR bstrConference, BSTR bstrPassword, BSTR bstrUserString) : CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)), m_pConfObject (pco), m_addrType (addrType), m_dwFlags (dwFlags), m_bstrName (SysAllocString(bstrName)), m_bstrAlias (SysAllocString(bstrAlias)), m_bstrConfToJoin (SysAllocString(bstrConference)), m_bstrPassword (SysAllocString(bstrPassword)), m_bstrUserString (SysAllocString(bstrUserString)), m_hRequest (NULL), m_pH323Connection (NULL), m_fCanceled (FALSE), m_cnResult (CN_RC_NOERROR), m_cnState (CNS_IDLE), m_fService (FALSE) { m_pszAddr = PszAlloc(CUSTRING(bstrDest)); DbgMsg(iZONE_OBJECTS, "Obj: %08X created COutgoingCall", this); }
COutgoingCall::~COutgoingCall() { delete m_pszAddr;
FreeBstr(&m_bstrName); FreeBstr(&m_bstrAlias); FreeBstr(&m_bstrConfToJoin); FreeBstr(&m_bstrPassword); FreeBstr(&m_bstrUserString);
ASSERT(NULL == m_pH323Connection);
DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed COutgoingCall", this); }
BOOL COutgoingCall::MatchActiveCallee(LPCTSTR pszAddr, BSTR bstrAlias, BSTR bstrConference) { return ((0 == lstrcmp(pszAddr, m_pszAddr)) && (0 == UnicodeCompare(bstrAlias, m_bstrAlias)));
}
/* P L A C E C A L L */ /*-------------------------------------------------------------------------
%%Function: PlaceCall
-------------------------------------------------------------------------*/ VOID COutgoingCall::PlaceCall(void) { DebugEntry(COutgoingCall::PlaceCall);
COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance(); ASSERT(NULL != pOprahNCUI);
SetCallState(CNS_SEARCHING);
if ((CRPCF_H323CC & m_dwFlags) && (NULL != g_pH323UI)) { SetCallState(CNS_CONNECTING_H323);
// Start placing the H.323 call:
CNSTATUS cnResult = ConnectH323(); if (CN_RC_NOERROR != cnResult) { m_cnResult = cnResult; SetCallState(CNS_COMPLETE); } } else if ((CRPCF_DATA & m_dwFlags) && (NULL != g_pNodeController)) { // Start placing the T.120 call
CNSTATUS cnResult = StartT120Call(); if (CN_RC_NOERROR != cnResult) { m_cnResult = cnResult; SetCallState(CNS_COMPLETE); } } else { m_cnResult = CN_RC_TRANSPORT_FAILURE; SetCallState(CNS_COMPLETE); }
DebugExitVOID(COutgoingCall::PlaceCall); }
CNSTATUS COutgoingCall::ConnectH323() { DBGENTRY(COutgoingCall::ConnectH323); H323ALIASLIST AliasList; H323ALIASNAME AliasName; P_H323ALIASLIST pAliasList = &AliasList; SOCKADDR_IN sin; LPCWSTR pcwszPhone = NULL; CNSTATUS cnResult = CN_RC_NOERROR;
if (NULL == g_pH323UI) return cnResult; AliasName.aType = AT_H323_ID; AliasName.lpwData = m_bstrAlias; AliasName.wDataLength = (WORD)SysStringLen(m_bstrAlias);// # of unicode chars, w/o NULL terminator
AliasList.wCount = 1; AliasList.pItems = &AliasName;
sin.sin_family = AF_INET; sin.sin_addr.s_addr = inet_addr(m_pszAddr);
switch (m_addrType) { case NM_ADDR_PSTN: case NM_ADDR_H323_GATEWAY: case NM_ADDR_ALIAS_E164: // overide alias type and phone number
AliasName.aType = AT_H323_E164; pcwszPhone = m_bstrAlias; break;
case NM_ADDR_IP: case NM_ADDR_MACHINENAME: // overide alias list
pAliasList = NULL; break;
case NM_ADDR_ALIAS_ID: case NM_ADDR_ULS: default: break; }
if (INADDR_NONE != sin.sin_addr.s_addr) { HRESULT hr; ASSERT(g_pH323UI);
DWORD dwUserData = 0; APP_CALL_SETUP_DATA acsd; P_APP_CALL_SETUP_DATA pacsd = NULL; BYTE *pbUserData = NULL; COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance(); ASSERT(NULL !=pOprahNCUI); if (CRPCF_DATA & m_dwFlags) { if (CRPCF_SECURE & m_dwFlags) { dwUserData |= H323UDF_SECURE; }
if (m_pConfObject->IsConferenceActive()) { dwUserData |= H323UDF_INVITE; } else if (m_bstrConfToJoin != NULL) { dwUserData |= H323UDF_JOIN; } else { dwUserData |= H323UDF_INVITE | H323UDF_JOIN; } }
if (CRPCF_AUDIO & m_dwFlags) { dwUserData |= H323UDF_AUDIO; } if (CRPCF_VIDEO & m_dwFlags) { dwUserData |= H323UDF_VIDEO; }
CRosterInfo ri; PVOID pvRosterData; UINT cbRosterData = 0;
if (pOprahNCUI->GetULSName(&ri)) { if (FAILED(ri.Save(&pvRosterData, &cbRosterData))) { cbRosterData = 0; } }
UINT cbUserString = 0; if (m_bstrUserString) { cbUserString = SysStringByteLen(m_bstrUserString); } DWORD dwTotalSize = sizeof(DWORD); if (cbRosterData) { dwTotalSize += sizeof(GUID) + sizeof(DWORD) + cbRosterData; } if (cbUserString) { dwTotalSize += sizeof(GUID) + sizeof(DWORD) + cbUserString; } dwTotalSize += sizeof(GUID) + sizeof(DWORD) + sizeof(GUID);
pbUserData = new BYTE [dwTotalSize]; if (NULL != pbUserData) { BYTE *pb = pbUserData;
// H323UDF_ first
*((DWORD*)pb) = dwUserData; pb += sizeof(DWORD);
if(cbRosterData) { // RosterInfo GUID next
*((GUID*)pb) = g_csguidRostInfo, pb += sizeof(GUID);
// then RosterInfo size (a DWORD)
*((DWORD*)pb) = cbRosterData; pb += sizeof(DWORD);
// then RosterInfo data
CopyMemory(pb, pvRosterData, cbRosterData); pb += cbRosterData; }
if(cbUserString) { // string GUID next
*((GUID*)pb) = g_csguidUserString, pb += sizeof(GUID);
// then string size (a DWORD)
*((DWORD*)pb) = cbUserString; pb += sizeof(DWORD);
// then string data
CopyMemory(pb, m_bstrUserString, cbUserString); pb += cbUserString; }
{ // string GUID next
*((GUID*)pb) = g_csguidNodeIdTag, pb += sizeof(GUID);
// then string size (a DWORD)
*((DWORD*)pb) = sizeof(GUID); pb += sizeof(DWORD);
// then GUID data
*(GUID*)pb = g_guidLocalNodeId; pb += sizeof(GUID); }
acsd.dwDataSize = dwTotalSize; acsd.lpData = pbUserData; pacsd = &acsd; }
sin.sin_port = htons(H323_PORT); hr = Connect(&sin, pAliasList, pcwszPhone, pacsd, PID_H323, &m_pH323Connection); delete [] pbUserData;
if (SUCCEEDED(hr)) { TRACE_OUT(("COutgoingCall - Connect() succeeded!")); cnResult = CN_RC_NOERROR; } else { WARNING_OUT(("COutgoingCall - Connect() failed!")); if (CONN_E_GK_NOT_REGISTERED == hr) { cnResult = CN_RC_GK_NOT_REGISTERED; } else { cnResult = CN_RC_AUDIO_CONNECT_FAILED; } } } else { WARNING_OUT(("COutgoingCall - inet_addr failed!")); cnResult = CN_RC_NAME_RESOLUTION_FAILED; } return cnResult; }
HRESULT COutgoingCall::Connect( PSOCKADDR_IN psin, P_H323ALIASLIST pAliasList, LPCWSTR pcwszPSTNAddress, P_APP_CALL_SETUP_DATA lpvMNMData, GUID PIDofProtocolType, IH323Endpoint * *ppConnection) { DebugEntry(CH323UI::Connect);
HRESULT hr = E_ACCESSDENIED;
*ppConnection = NULL;
COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance(); ASSERT(NULL != pOprahNCUI);
IH323CallControl * pH323CallControl = g_pH323UI->GetH323CallControl(); // create the connection
IH323Endpoint* pConn = NULL; ASSERT(pH323CallControl); hr = pH323CallControl->CreateConnection(&pConn, PIDofProtocolType); if (FAILED(hr) || (NULL == pConn)) { ERROR_OUT(("Could not create a connection, hr=0x%lx", hr)); } else { // if the following operations fail, we still can delete this conn obj
*ppConnection = pConn;
if (!pOprahNCUI->AcquireAV(pConn)) { // we did not get AV, clear out the flags
m_dwFlags &= ~(CRPCF_AUDIO | CRPCF_VIDEO); } hr = pConn->SetAdviseInterface (pOprahNCUI); ASSERT(SUCCEEDED(hr));
// if we are using an alias, tell the Gatekeeper to resolve it
BOOL fUseGKResolution = (NULL != pAliasList);
// start the connection
hr = pConn->PlaceCall (fUseGKResolution, psin, pAliasList, NULL, pcwszPSTNAddress, lpvMNMData); if (FAILED(hr)) { // ERROR_OUT(("COutgoingCall::Connect: couldn't StartConnection, hr=0x%lx", hr));
if(hr == CONN_E_GK_NOT_REGISTERED) { WARNING_OUT(("COutgoingCall::Connect: not registered. Do you want to re-register..., hr=0x%lx", hr)); } *ppConnection = NULL;
pConn->Release();
pOprahNCUI->ReleaseAV(pConn); } }
DebugExitULONG(CH323UI::Connect, hr);
return hr; }
BOOL COutgoingCall::OnConferenceEnded() { DebugEntry(COutgoingCall::OnConferenceEnded);
BOOL bRet = FALSE;
switch (m_cnState) { case CNS_INVITING_REMOTE: { TRACE_OUT(("COutgoingCall (calling) rec. UNEXPECTED ConfEnded event"));
SetCallState(CNS_COMPLETE);
bRet = TRUE; break; }
case CNS_JOINING_REMOTE: { // JoinConference failed!
TRACE_OUT(("COutgoingCall (joining) received ConferenceEnded event"));
m_cnResult = CN_RC_CONFERENCE_JOIN_DENIED; SetCallState(CNS_COMPLETE);
bRet = TRUE; break; }
case CNS_TERMINATING_AFTER_INVITE: { TRACE_OUT(("COutgoingCall (terminating after invite) received ConferenceEnded event"));
SetCallState(CNS_QUERYING_REMOTE_AFTER_INVITE);
ASSERT(g_pNodeController);
HRESULT hr = g_pNodeController->QueryRemote(this, m_pszAddr, m_pConfObject->IsConfObjSecure(), m_pConfObject->IsConferenceActive()); if (S_OK != hr) { m_cnResult = CN_RC_QUERY_FAILED; SetCallState(CNS_COMPLETE); }
bRet = TRUE; break; }
default: { WARNING_OUT(("COutgoingCall received unexpected ConfEnded event")); } }
DebugExitBOOL(COutgoingCall::OnConferenceEnded, bRet); return bRet; }
BOOL COutgoingCall::OnInviteResult(HRESULT ncsResult, UINT uNodeID) { DebugEntry(COutgoingCall::OnInviteResult);
BOOL bRet = TRUE;
ASSERT(CNS_INVITING_REMOTE == m_cnState);
TRACE_OUT(("COutgoingCall (calling) received InviteResult event"));
// Clear the current request handle
m_hRequest = NULL; if (0 == ncsResult) { SetCallState(CNS_COMPLETE); if (m_pH323Connection) { m_pConfObject->OnT120Connected(m_pH323Connection, uNodeID); } } else { if (UI_RC_USER_REJECTED == ncsResult) { SetCallState(CNS_TERMINATING_AFTER_INVITE);
// Issue "soft" leave attempt (to allow auto-terminate)
ASSERT(m_pConfObject); if (S_OK != m_pConfObject->LeaveConference(FALSE)) { m_cnResult = CN_RC_CONFERENCE_INVITE_DENIED; SetCallState(CNS_COMPLETE); } } else { // make sure that we are not recieving this notification due to
// the conference going away
ASSERT(m_pConfObject); if (CS_GOING_DOWN != m_pConfObject->GetT120State()) { TRACE_OUT(("COutgoingCall - invite failed / couldn't connect -> leaving")); m_cnResult = CN_RC_INVITE_FAILED; SetCallState(CNS_COMPLETE);
// Issue "soft" leave attempt (to allow auto-terminate)
ASSERT(m_pConfObject); m_pConfObject->LeaveConference(FALSE); } } }
DebugExitBOOL(COutgoingCall::OnInviteResult, bRet); return bRet; }
BOOL COutgoingCall::OnQueryRemoteResult(HRESULT ncsResult, BOOL fMCU, PWSTR pwszConfNames[], PT120PRODUCTVERSION pVersion, PWSTR pwszConfDescriptors[]) { DebugEntry(COutgoingCall::OnQueryRemoteResult);
ASSERT ((CNS_QUERYING_REMOTE == m_cnState) || (CNS_QUERYING_REMOTE_AFTER_INVITE == m_cnState)); ASSERT (NULL == m_bstrConfToJoin);
if (SUCCEEDED(ncsResult)) { BOOL fRemoteInConf = FALSE; if ((NULL != pwszConfNames) && (NULL != pwszConfNames[0])) { fRemoteInConf = TRUE; }
m_fService = FALSE; if (fRemoteInConf && (NULL != pwszConfDescriptors) && (NULL != pwszConfDescriptors[0])) { if (0 == UnicodeCompare(pwszConfDescriptors[0],RDS_CONFERENCE_DESCRIPTOR)) { m_fService = TRUE; } }
if (m_pConfObject->IsConferenceActive()) { if (fMCU) { TRACE_OUT(("COutgoingCall - QR ok, but is MCU -> complete")); m_cnResult = CN_RC_CANT_INVITE_MCU; } else if (fRemoteInConf) { TRACE_OUT(("COutgoingCall - QR ok, but callee is in a conference")); m_cnResult = CN_RC_INVITE_DENIED_REMOTE_IN_CONF; } else { if (CNS_QUERYING_REMOTE_AFTER_INVITE == m_cnState) { m_cnResult = CN_RC_CONFERENCE_INVITE_DENIED; SetCallState(CNS_COMPLETE); } else { SetCallState(CNS_INVITING_REMOTE);
HRESULT hr = m_pConfObject->InviteConference(m_pszAddr, m_bstrUserString, &m_hRequest); if (S_OK != hr) { // Failure while inviting:
m_cnResult = CN_RC_INVITE_FAILED; } } }
if (CN_RC_NOERROR != m_cnResult) { SetCallState(CNS_COMPLETE); } } else if (fRemoteInConf || fMCU) { TRACE_OUT(("COutgoingCall - QR succeeded (>0 conf) -> joining")); TRACE_OUT(("\tfMCU is %d", fMCU)); // There are remote conferences
HRESULT hr = E_FAIL; // Assume a failure
SetCallState(CNS_JOINING_REMOTE);
if (!fMCU && (NULL == pwszConfNames[1])) { // we're not calling an MCU and we have just one conference, so join it
m_bstrConfToJoin = SysAllocString(pwszConfNames[0]); hr = m_pConfObject->JoinConference( m_bstrConfToJoin, m_bstrPassword, m_pszAddr, m_bstrUserString); } else { ASSERT(NULL == m_bstrConfToJoin); REMOTE_CONFERENCE remoteConf; remoteConf.fMCU = fMCU; remoteConf.pwszConfNames = pwszConfNames; remoteConf.pbstrConfToJoin = &m_bstrConfToJoin;
// Ask the app which conference to join
NotifySink(&remoteConf, OnNotifyRemoteConference);
if (NULL != m_bstrConfToJoin) { hr = m_pConfObject->JoinConference( m_bstrConfToJoin, m_bstrPassword, m_pszAddr, m_bstrUserString); } }
if (S_OK != hr) { // JoinConference failed!
m_cnResult = CN_RC_JOIN_FAILED; SetCallState(CNS_COMPLETE); } } else { if (CNS_QUERYING_REMOTE_AFTER_INVITE == m_cnState) { m_cnResult = CN_RC_CONFERENCE_INVITE_DENIED; SetCallState(CNS_COMPLETE); } else { // No conferences on remote machine, so create local:
TRACE_OUT(("COutgoingCall - QR succeeded (no conf)-> creating local"));
// Create local conf
ASSERT(m_pConfObject); SetCallState(CNS_CREATING_LOCAL); HRESULT hr = m_pConfObject->CreateConference();
if (S_OK != hr) { // CreateConference failed!
m_cnResult = CN_RC_CONFERENCE_CREATE_FAILED; SetCallState(CNS_COMPLETE); } } } } else { // The QueryRemote failed
switch( ncsResult ) { case UI_RC_USER_REJECTED: // The initial QueryRemote failed because GCC symmetry determined
// that the other node is calling someone, and it might be us
// See Bug 1886
TRACE_OUT(("COutgoingCall - QueryRemote rejected -> complete")); m_cnResult = CN_RC_REMOTE_PLACING_CALL; break; case UI_RC_T120_REMOTE_REQUIRE_SECURITY: m_cnResult = CN_RC_CONNECT_REMOTE_REQUIRE_SECURITY; break; case UI_RC_T120_SECURITY_FAILED: m_cnResult = CN_RC_SECURITY_FAILED; break; case UI_RC_T120_REMOTE_NO_SECURITY: m_cnResult = CN_RC_CONNECT_REMOTE_NO_SECURITY; break; case UI_RC_T120_REMOTE_DOWNLEVEL_SECURITY: m_cnResult = CN_RC_CONNECT_REMOTE_DOWNLEVEL_SECURITY; break; case UI_RC_T120_AUTHENTICATION_FAILED: m_cnResult = CN_RC_CONNECT_AUTHENTICATION_FAILED; break; default: m_cnResult = CN_RC_CONNECT_FAILED; break; } SetCallState(CNS_COMPLETE); }
DebugExitBOOL(COutgoingCall::OnQueryRemoteResult, TRUE); return TRUE; }
BOOL COutgoingCall::OnConferenceStarted(CONF_HANDLE hNewConf, HRESULT ncsResult) { DebugEntry(COutgoingCall::OnConferenceStarted);
switch (m_cnState) { case CNS_CREATING_LOCAL: { TRACE_OUT(("COutgoingCall (inviting) received ConferenceStarted event")); if (0 == ncsResult) { ASSERT(m_pConfObject); ASSERT(NULL == m_hRequest);
SetCallState(CNS_INVITING_REMOTE);
HRESULT hr = m_pConfObject->InviteConference(m_pszAddr, m_bstrUserString, &m_hRequest); if (S_OK != hr) { m_hRequest = NULL; m_cnResult = CN_RC_INVITE_FAILED; SetCallState(CNS_COMPLETE); // Issue "soft" leave attempt (to allow auto-terminate)
ASSERT(m_pConfObject); hr = m_pConfObject->LeaveConference(FALSE); if (FAILED(hr)) { WARNING_OUT(("Couldn't leave after failed invite")); } } } else { WARNING_OUT(("CreateConference (local) failed - need UI here!")); m_cnResult = CN_RC_CONFERENCE_CREATE_FAILED; SetCallState(CNS_COMPLETE); } break; }
case CNS_JOINING_REMOTE: { TRACE_OUT(("COutgoingCall (joining) received ConferenceStarted event"));
if (0 == ncsResult) { SetCallState(CNS_COMPLETE); if (m_pH323Connection) { UINT uNodeID = hNewConf->GetParentNodeID();
m_pConfObject->OnT120Connected(m_pH323Connection, uNodeID); } } else if (UI_RC_INVALID_PASSWORD == ncsResult) { TRACE_OUT(("COutgoingCall - invalid password, prompt for password"));
BSTR bstrPassword = NULL; REMOTE_PASSWORD remotePw; remotePw.bstrConference = m_bstrConfToJoin; remotePw.pbstrPassword = &bstrPassword; if (NO_ERROR != hNewConf->GetCred(&remotePw.pbRemoteCred, &remotePw.cbRemoteCred)) { remotePw.pbRemoteCred = NULL; remotePw.cbRemoteCred = 0; } remotePw.fIsService = m_fService; NotifySink(&remotePw, OnNotifyRemotePassword);
if (NULL != bstrPassword) { SysFreeString(m_bstrPassword); m_bstrPassword = bstrPassword;
// reissue join with new password
ASSERT(m_pConfObject); HRESULT ncs = m_pConfObject->JoinConference( m_bstrConfToJoin, m_bstrPassword, m_pszAddr, m_bstrUserString, TRUE); // retry
if (0 != ncs) { // JoinConference failed!
m_cnResult = CN_RC_JOIN_FAILED; SetCallState(CNS_COMPLETE); } } else { // cancel from pw dlg
m_cnResult = CN_RC_INVALID_PASSWORD; SetCallState(CNS_COMPLETE); ASSERT(m_pConfObject); HRESULT hr = m_pConfObject->LeaveConference(TRUE); if (FAILED(hr)) { ERROR_OUT(("Couldn't leave after cancelling pw join!")); } } } else if (UI_RC_UNKNOWN_CONFERENCE == ncsResult) { TRACE_OUT(("Join failed (conf does not exist) " "- notifying user")); // error while joining
m_cnResult = CN_RC_CONFERENCE_DOES_NOT_EXIST; SetCallState(CNS_COMPLETE); } else { TRACE_OUT(("Join failed - notifying user")); // error while joining
m_cnResult = CN_RC_CONFERENCE_JOIN_DENIED; SetCallState(CNS_COMPLETE); }
break; }
default: { if (m_pConfObject->GetConfHandle() == hNewConf) { WARNING_OUT(("COutgoingCall received unexpected ConferenceStarted event")); } else { TRACE_OUT(("COutgoingCall ignoring ConferenceStarted event - not our conf")); } } }
DebugExitBOOL(COutgoingCall::OnConferenceStarted, TRUE); return TRUE; }
BOOL COutgoingCall::OnH323Connected(IH323Endpoint * pConnection) { DebugEntry(COutgoingCall::OnH323Connected);
BOOL bRet = TRUE;
ASSERT(m_pH323Connection == pConnection);
if (m_dwFlags & CRPCF_DATA) { PCC_VENDORINFO pLocalVendorInfo; PCC_VENDORINFO pRemoteVendorInfo;
pConnection->GetVersionInfo(&pLocalVendorInfo, &pRemoteVendorInfo); H323VERSION version = GetH323Version(pRemoteVendorInfo);
if (H323_NetMeeting20 == version) { if ((m_addrType != NM_ADDR_H323_GATEWAY) && (m_addrType != NM_ADDR_PSTN) && (m_addrType != NM_ADDR_ALIAS_ID) && (m_addrType != NM_ADDR_ALIAS_E164)) { CNSTATUS cnResult = StartT120Call(); if (CN_RC_NOERROR != cnResult) { m_cnResult = cnResult; SetCallState(CNS_COMPLETE); } } else { SetCallState(CNS_COMPLETE); } } else { // wait for results of T.120 open logical channel
TRACE_OUT(("COutgoingCall - H323Connected received -> waiting for T120 channel open")); SetCallState(CNS_WAITING_T120_OPEN); } } else { // no T120 for this call
TRACE_OUT(("COutgoingCall - our H323 call started -> complete")); SetCallState(CNS_COMPLETE); } CConfObject *pco = ::GetConfObject(); if (NULL != pco) { // add member if we are calling with A/V
BOOL fAddMember = m_dwFlags & (CRPCF_AUDIO | CRPCF_VIDEO);
pco->OnH323Connected(pConnection, m_dwFlags, fAddMember, GUID_NULL); }
DebugExitBOOL(COutgoingCall::OnH323Connected, bRet); return bRet; }
BOOL COutgoingCall::OnH323Disconnected(IH323Endpoint * pConnection) { DebugEntry(COutgoingCall::OnH323Disconnected);
BOOL bRet = TRUE; ASSERT(m_pH323Connection == pConnection);
HRESULT hSummary = m_pH323Connection->GetSummaryCode(); // Check summary code for gatekeeper-caused disconnect
// Note: this applies only to MY gatekeeper, not the callee's gatekeeper
if(CUSTOM_FACILITY(hSummary) == FACILITY_GKIADMISSION) { DWORD dwRejectReason; dwRejectReason = CUSTOM_FACILITY_CODE(hSummary); // should the T.120 call be placed anyway?
switch (dwRejectReason) { case ARJ_CALLEE_NOT_REGISTERED: m_cnResult = CN_RC_GK_CALLEE_NOT_REGISTERED; break; case ARJ_TIMEOUT: m_cnResult = CN_RC_GK_TIMEOUT; break; case ARJ_INVALID_PERMISSION: case ARJ_REQUEST_DENIED: case ARJ_UNDEFINED: case ARJ_CALLER_NOT_REGISTERED: case ARJ_ROUTE_TO_GK: case ARJ_INVALID_ENDPOINT_ID: case ARJ_RESOURCE_UNAVAILABLE: case ARJ_SECURTY_DENIAL: case ARJ_QOS_CONTROL_NOT_SUPPORTED: case ARJ_INCOMPLETE_ADDRESS: default: m_cnResult = CN_RC_GK_REJECTED; break; }
SetCallState(CNS_COMPLETE); } else if (CNS_CONNECTING_H323 == m_cnState) { // attempted an H.323 call without success.
TRACE_OUT(("COutgoingCall - our leading H323 call ended -> complete"));
// check for cases of remote refusing the call
switch (hSummary) { case CCR_REMOTE_DISCONNECT: case CCR_REMOTE_REJECTED: m_cnResult = CN_RC_CONFERENCE_INVITE_DENIED; SetCallState(CNS_COMPLETE); break; case CCR_LOCAL_DISCONNECT: // cancelled by user, do not report error
m_cnResult = CN_RC_LOCAL_CANCELED; m_fCanceled = TRUE; SetCallState(CNS_COMPLETE); break; case CCR_GK_NO_RESOURCES: // callee's gatekeeper would not let callee answer
// do the same as CCR_REMOTE_REJECTED
// as a temporary measure !!!!
m_cnResult = CN_RC_CONFERENCE_INVITE_DENIED; SetCallState(CNS_COMPLETE); break; case CCR_REMOTE_SECURITY_DENIED: if (m_pConfObject->IsConfObjSecure()) { m_cnResult = CN_RC_CONNECT_REMOTE_NO_SECURITY; } else { m_cnResult = CN_RC_CONNECT_REMOTE_REQUIRE_SECURITY; } SetCallState(CNS_COMPLETE); break; case CCR_REMOTE_BUSY: if (m_pConfObject->IsConferenceActive()) { m_cnResult = CN_RC_INVITE_DENIED_REMOTE_IN_CONF; SetCallState(CNS_COMPLETE); break; } // else fall through
default: if ((m_dwFlags & CRPCF_DATA) && (m_addrType != NM_ADDR_H323_GATEWAY) && (m_addrType != NM_ADDR_PSTN) && (m_addrType != NM_ADDR_ALIAS_ID) && (m_addrType != NM_ADDR_ALIAS_E164)) { // The endpoint is not there, not listening for H.323 calls, or is busy,
// and the address is a resolvable type (not an H.323 alias or E.164 number)
// go back into the T.120 call state path
CNSTATUS cnResult = StartT120Call(); if (CN_RC_NOERROR != cnResult) { m_cnResult = cnResult; SetCallState(CNS_COMPLETE); bRet = FALSE; } } else { switch (hSummary) { case CCR_REMOTE_BUSY: m_cnResult = CN_RC_INVITE_DENIED_REMOTE_IN_CONF; break; case CCR_REMOTE_MEDIA_ERROR: m_cnResult = CN_RC_AUDIO_IN_USE_REMOTE; break; case CCR_LOCAL_MEDIA_ERROR: m_cnResult = CN_RC_AUDIO_IN_USE_LOCAL; break; case CCR_GK_NO_RESOURCES: m_cnResult = CN_RC_GK_REJECTED; break; default: m_cnResult = CN_RC_AUDIO_CONNECT_FAILED; break; } SetCallState(CNS_COMPLETE); } break; } } else if (CNS_WAITING_T120_OPEN == m_cnState) { TRACE_OUT(("COutgoingCall - OnH323Disconnected received -> call is canceled")); m_cnResult = CN_RC_CONFERENCE_INVITE_DENIED; SetCallState(CNS_COMPLETE); } else { TRACE_OUT(("COutgoingCall - OnH323Disconnected received -> canceling call")); ASSERT(m_pConfObject);
if (NULL != m_hRequest) { REQUEST_HANDLE hRequest = m_hRequest; m_hRequest = NULL; m_pConfObject->CancelInvite(hRequest); }
if (m_pConfObject->IsConferenceActive()) { // Issue "soft" leave attempt (to allow auto-terminate)
m_pConfObject->LeaveConference(FALSE); } }
// the connection may have been released due to the LeaveConference above
// bug 3996
if (m_pH323Connection) { m_pH323Connection->Release(); m_pH323Connection = NULL; }
DebugExitBOOL(COutgoingCall::OnH323Disconnected, bRet); return bRet; }
BOOL COutgoingCall::OnT120ChannelOpen(ICommChannel *pIChannel, DWORD dwStatus) { DebugEntry(COutgoingCall::OnT120ChannelOpen);
BOOL bRet = TRUE;
// sometimes we get an extra T120 channel open
// this is most likely due the master/slave anomolies that
// venkatg discovered.
if (CNS_WAITING_T120_OPEN == m_cnState) { switch(dwStatus) { case CHANNEL_OPEN: { // start the T.120 part of the call
// get the negotiated address
SOCKADDR_IN sin_T120; HRESULT hr = pIChannel->GetRemoteAddress(&sin_T120); delete m_pszAddr; // we won't be needing this anymore
TCHAR szAddress[256]; // allow plenty of room for conversion from numberic to string
wsprintf(szAddress, "%s:%d", inet_ntoa(sin_T120.sin_addr), ntohs(sin_T120.sin_port)); m_pszAddr = PszAlloc(szAddress);
CNSTATUS cnResult = StartT120Call(); if (CN_RC_NOERROR != cnResult) { m_cnResult = cnResult; SetCallState(CNS_COMPLETE); } } break; case CHANNEL_CLOSED: // if the T.120 channel is being closed
// the H.323 call is going down, so don't continue waiting for
// T.120 to connect!
m_cnResult = CN_RC_CONNECT_FAILED; SetCallState(CNS_COMPLETE);
if (NULL != m_hRequest) { REQUEST_HANDLE hRequest = m_hRequest; m_hRequest = NULL; ASSERT(m_pConfObject); m_pConfObject->CancelInvite(hRequest); } break; case CHANNEL_NO_CAPABILITY: case CHANNEL_REJECTED: case CHANNEL_OPEN_ERROR: default: m_cnResult = CN_RC_CONNECT_FAILED; SetCallState(CNS_COMPLETE); break; } }
DebugExitBOOL(COutgoingCall::OnT120ChannelOpen, bRet); return bRet; }
void COutgoingCall::CallComplete() { DebugEntry(COutgoingCall::CallComplete);
// If this fails, we are being destructed unexpectedly
ASSERT( (m_cnState == CNS_IDLE) || (m_cnState == CNS_COMPLETE));
// The request handle should have been reset
ASSERT(NULL == m_hRequest);
// make sure that the H323 connection is released
if (m_pH323Connection) { if (!IsDataOnly() && ((CN_RC_TRANSPORT_FAILURE == m_cnResult) || (CN_RC_QUERY_FAILED == m_cnResult) || (CN_RC_CONNECT_FAILED == m_cnResult))) { m_cnResult = CN_RC_NOERROR; }
if (CN_RC_NOERROR != m_cnResult) { m_pH323Connection->Disconnect(); } m_pH323Connection->Release(); m_pH323Connection = NULL; }
if (!FCanceled() && (CN_RC_NOERROR != m_cnResult)) { ReportError(m_cnResult); }
NM_CALL_STATE state; GetState(&state); NotifySink((PVOID) state, OnNotifyCallStateChanged);
TRACE_OUT(("ConfNode destroying addr %s", m_pszAddr)); DebugExitVOID(COutgoingCall::CallComplete); }
BOOL COutgoingCall::ReportError(CNSTATUS cns) { DebugEntry(COutgoingCall::ReportError); TRACE_OUT(("CNSTATUS 0x%08x", cns)); NotifySink((PVOID)cns, OnNotifyCallError);
DebugExitBOOL(COutgoingCall::ReportError, TRUE); return TRUE; }
CNSTATUS COutgoingCall::StartT120Call() { DebugEntry(COutgoingCall::StartT120Call); CNSTATUS cnResult = CN_RC_NOERROR;
if (NULL == m_bstrConfToJoin) { // conference name not specified
// need to start out with a QueryRemote
SetCallState(CNS_QUERYING_REMOTE);
ASSERT(g_pNodeController);
HRESULT hr = g_pNodeController->QueryRemote(this, m_pszAddr, m_pConfObject->IsConfObjSecure(), m_pConfObject->IsConferenceActive()); if (S_OK != hr) { cnResult = CN_RC_QUERY_FAILED; } } else { ASSERT(m_pConfObject); // conference name has been specified
// time to do a JoinConference
SetCallState(CNS_JOINING_REMOTE);
HRESULT hr = m_pConfObject->JoinConference( m_bstrConfToJoin, m_bstrPassword, m_pszAddr, m_bstrUserString); if (S_OK != hr) { cnResult = CN_RC_JOIN_FAILED; } } DebugExitINT(COutgoingCall::StartT120Call, cnResult); return cnResult; }
VOID COutgoingCall::SetCallState(CNODESTATE cnState) { NM_CALL_STATE stateOld; NM_CALL_STATE stateNew; GetState(&stateOld);
m_cnState = cnState;
// completion state will be fired off later
if (CNS_COMPLETE != cnState) { GetState(&stateNew); if (stateOld != stateNew) { NotifySink((PVOID) stateNew, OnNotifyCallStateChanged); } } }
HRESULT COutgoingCall::_Cancel(BOOL fLeaving) { DebugEntry(COutgoingCall::Cancel);
BOOL fAbortT120 = (m_cnState != CNS_COMPLETE);
if (fAbortT120) { m_fCanceled = TRUE;
// Abort T.120 Call:
// Attempt to make this transition regardless of our
// current state:
SetCallState(CNS_COMPLETE);
ASSERT(m_pConfObject);
if (NULL != m_hRequest) { REQUEST_HANDLE hRequest = m_hRequest; m_hRequest = NULL; m_pConfObject->CancelInvite(hRequest); }
if (!fLeaving && m_pConfObject->IsConferenceActive()) { HRESULT hr = m_pConfObject->LeaveConference(FALSE); if (FAILED(hr)) { WARNING_OUT(("Couldn't leave after disconnecting")); } } }
if (NULL != m_pH323Connection) { m_fCanceled = TRUE;
// Abort H.323 Call:
m_pH323Connection->Disconnect(); }
DebugExitULONG(COutgoingCall::Abort, m_cnResult);
return CN_RC_NOERROR ? S_OK : E_FAIL; }
STDMETHODIMP_(ULONG) COutgoingCall::AddRef(void) { return RefCount::AddRef(); } STDMETHODIMP_(ULONG) COutgoingCall::Release(void) { return RefCount::Release(); }
HRESULT STDMETHODCALLTYPE COutgoingCall::QueryInterface(REFIID riid, PVOID *ppv) { HRESULT hr = S_OK;
if ((riid == IID_INmCall) || (riid == IID_IUnknown)) { *ppv = (INmCall *)this; ApiDebugMsg(("COutgoingCall::QueryInterface()")); } else if (riid == IID_IConnectionPointContainer) { *ppv = (IConnectionPointContainer *) this; ApiDebugMsg(("CNmCall::QueryInterface(): Returning IConnectionPointContainer.")); } else { hr = E_NOINTERFACE; *ppv = NULL; ApiDebugMsg(("COutgoingCall::QueryInterface(): Called on unknown interface.")); }
if (S_OK == hr) { AddRef(); }
return hr; }
HRESULT COutgoingCall::IsIncoming(void) { return S_FALSE; }
HRESULT COutgoingCall::GetState(NM_CALL_STATE *pState) { HRESULT hr = E_POINTER;
if (NULL != pState) { if (FCanceled()) { *pState = NM_CALL_CANCELED; } else { switch (m_cnState) { case CNS_IDLE: *pState = NM_CALL_INIT; break;
case CNS_SEARCHING: *pState = NM_CALL_SEARCH; break;
case CNS_CONNECTING_H323: case CNS_WAITING_T120_OPEN: case CNS_QUERYING_REMOTE: case CNS_CREATING_LOCAL: case CNS_INVITING_REMOTE: case CNS_JOINING_REMOTE: *pState = NM_CALL_WAIT; break;
case CNS_COMPLETE: switch (m_cnResult) { case CN_RC_NOERROR: *pState = NM_CALL_ACCEPTED; break; case CN_RC_CONFERENCE_JOIN_DENIED: case CN_RC_CONFERENCE_INVITE_DENIED: case CN_RC_CONFERENCE_DOES_NOT_EXIST: case CN_RC_AUDIO_CONNECT_FAILED: case CN_RC_GK_CALLEE_NOT_REGISTERED: case CN_RC_GK_TIMEOUT: case CN_RC_GK_REJECTED: case CN_RC_GK_NOT_REGISTERED: case CN_RC_CONNECT_REMOTE_NO_SECURITY: case CN_RC_CONNECT_REMOTE_DOWNLEVEL_SECURITY: case CN_RC_CONNECT_REMOTE_REQUIRE_SECURITY: case CN_RC_TRANSPORT_FAILURE: case CN_RC_QUERY_FAILED: case CN_RC_CONNECT_FAILED: *pState = NM_CALL_REJECTED; break;
case CN_RC_ALREADY_IN_CONFERENCE: case CN_RC_CANT_INVITE_MCU: case CN_RC_CANT_JOIN_ALREADY_IN_CALL: case CN_RC_INVITE_DENIED_REMOTE_IN_CONF: case CN_RC_REMOTE_PLACING_CALL: case CN_RC_ALREADY_IN_CONFERENCE_MCU: case CN_RC_INVALID_PASSWORD: default: *pState = NM_CALL_CANCELED; break; } break;
default: *pState = NM_CALL_INVALID; break; } }
hr = S_OK; } return hr; }
HRESULT COutgoingCall::GetName(BSTR * pbstrName) { if (NULL == pbstrName) return E_POINTER;
*pbstrName = SysAllocString(m_bstrName); return (*pbstrName ? S_OK : E_FAIL); }
HRESULT COutgoingCall::GetAddr(BSTR *pbstrAddr, NM_ADDR_TYPE *puType) { if ((NULL == pbstrAddr) || (NULL == puType)) return E_POINTER;
*pbstrAddr = SysAllocString(CUSTRING(m_pszAddr)); *puType = m_addrType;
return *pbstrAddr ? S_OK : E_FAIL; }
HRESULT COutgoingCall::GetUserData(REFGUID rguid, BYTE **ppb, ULONG *pcb) { return E_NOTIMPL; }
HRESULT COutgoingCall::GetConference(INmConference **ppConference) { HRESULT hr = E_POINTER;
if (NULL != ppConference) { *ppConference = m_pConfObject; return S_OK; }
return hr; }
HRESULT COutgoingCall::Accept(void) { return E_UNEXPECTED; }
HRESULT COutgoingCall::Reject(void) { return E_UNEXPECTED; }
HRESULT COutgoingCall::Cancel(void) { DebugEntry(COutgoingCall::Cancel);
AddRef(); // protect against Release() while processing
// disconnect related indications & callbacks
HRESULT hr = _Cancel(FALSE); if (FIsComplete()) { COprahNCUI *pOprahNCUI = COprahNCUI::GetInstance(); ASSERT(NULL !=pOprahNCUI); pOprahNCUI->OnOutgoingCallCanceled(this); }
DebugExitULONG(COutgoingCall::Abort, m_cnResult);
Release();
return hr; }
/* O N N O T I F Y C A L L E R R O R */ /*-------------------------------------------------------------------------
%%Function: OnNotifyCallError -------------------------------------------------------------------------*/ HRESULT OnNotifyCallError(IUnknown *pCallNotify, PVOID pv, REFIID riid) { ASSERT(NULL != pCallNotify); CNSTATUS cnStatus = (CNSTATUS)((DWORD_PTR)pv); switch (cnStatus) { case CN_RC_ALREADY_IN_CONFERENCE: case CN_RC_CANT_INVITE_MCU: case CN_RC_CANT_JOIN_ALREADY_IN_CALL: case CN_RC_INVITE_DENIED_REMOTE_IN_CONF: case CN_RC_REMOTE_PLACING_CALL: case CN_RC_ALREADY_IN_CONFERENCE_MCU: ((INmCallNotify*)pCallNotify)->NmUI(CONFN_CALL_IN_CONFERENCE); break; case CN_RC_CONFERENCE_JOIN_DENIED: case CN_RC_CONFERENCE_INVITE_DENIED: case CN_RC_CONFERENCE_DOES_NOT_EXIST: case CN_RC_GK_CALLEE_NOT_REGISTERED: case CN_RC_GK_TIMEOUT: case CN_RC_GK_REJECTED: case CN_RC_GK_NOT_REGISTERED: case CN_RC_CONNECT_REMOTE_NO_SECURITY: case CN_RC_CONNECT_REMOTE_DOWNLEVEL_SECURITY: case CN_RC_CONNECT_REMOTE_REQUIRE_SECURITY: ((INmCallNotify*)pCallNotify)->NmUI(CONFN_CALL_IGNORED); break; case CN_RC_CONNECT_FAILED: case CN_RC_AUDIO_CONNECT_FAILED: ((INmCallNotify*)pCallNotify)->NmUI(CONFN_CALL_FAILED); break; default: break; }
if (IID_INmCallNotify2 == riid) { ((INmCallNotify2*)pCallNotify)->CallError(cnStatus); } return S_OK; }
/* O N N O T I F Y R E M O T E C O N F E R E N C E */ /*-------------------------------------------------------------------------
%%Function: OnNotifyRemoteConference -------------------------------------------------------------------------*/ HRESULT OnNotifyRemoteConference(IUnknown *pCallNotify, PVOID pv, REFIID riid) { REMOTE_CONFERENCE *prc = (REMOTE_CONFERENCE *)pv;
// WARNING: pwszConfName is an PWSTR array, not a BSTR
ASSERT(NULL != pCallNotify); ((INmCallNotify2*)pCallNotify)->RemoteConference(prc->fMCU, (BSTR *) prc->pwszConfNames, prc->pbstrConfToJoin); return S_OK; }
/* O N N O T I F Y R E M O T E P A S S W O R D */ /*-------------------------------------------------------------------------
%%Function: OnNotifyRemotePassword -------------------------------------------------------------------------*/ HRESULT OnNotifyRemotePassword(IUnknown *pCallNotify, PVOID pv, REFIID riid) { REMOTE_PASSWORD *prp = (REMOTE_PASSWORD *)pv;
ASSERT(NULL != pCallNotify); ((INmCallNotify2*)pCallNotify)->RemotePassword(prp->bstrConference, prp->pbstrPassword, prp->pbRemoteCred, prp->cbRemoteCred, prp->fIsService); return S_OK; }
COutgoingCallManager::COutgoingCallManager() { }
COutgoingCallManager::~COutgoingCallManager() { // Empty the call list:
while (!m_CallList.IsEmpty()) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.RemoveHead(); // Shouldn't have any NULL entries:
ASSERT(pCall); pCall->Release(); } }
UINT COutgoingCallManager::GetCallCount() { UINT nNodes = 0; POSITION pos = m_CallList.GetHeadPosition(); while (pos) { nNodes++; m_CallList.GetNext(pos); } return nNodes; }
COutgoingCall* COutgoingCallManager::FindCall(IH323Endpoint * lpConnection) { POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
if ((NULL != pCall) && (pCall->GetH323Connection() == lpConnection)) { return pCall; } } return NULL; }
BOOL COutgoingCallManager::MatchActiveCallee(LPCTSTR pszDest, BSTR bstrAlias, BSTR bstrConference) { // Try to find a matching callee
POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
if (NULL != pCall) { if (pCall->MatchActiveCallee(pszDest, bstrAlias, bstrConference)) { return TRUE; } } } return FALSE; }
HRESULT COutgoingCallManager::Call( INmCall **ppCall, COprahNCUI* pManager, DWORD dwFlags, NM_ADDR_TYPE addrType, BSTR bstrName, BSTR bstrSetup, BSTR bstrDest, BSTR bstrAlias, BSTR bstrURL, BSTR bstrConference, BSTR bstrPassword, BSTR bstrUserString) { DebugEntry(COutgoingCallManager::CallConference); HRESULT hr = E_FAIL; COutgoingCall* pCall = NULL; CConfObject* pConfObject = pManager->GetConfObject(); if (NULL != ppCall) { *ppCall = NULL; }
if (MatchActiveCallee(CUSTRING(bstrDest), bstrAlias, bstrConference)) { hr = NM_CALLERR_ALREADY_CALLING; } else if (pConfObject->IsConferenceActive() && (NULL != bstrConference)) { hr= NM_CALLERR_IN_CONFERENCE; } else { if (!pConfObject->IsConferenceActive()) { pConfObject->SetConfSecurity(0 != (CRPCF_SECURE & dwFlags)); }
//
// Check outgoing call settings
//
if (pConfObject->GetNumMembers() >= pConfObject->GetConfMaxParticipants()) { ASSERT(pConfObject->GetNumMembers() == pConfObject->GetConfMaxParticipants()); WARNING_OUT(("Outgoing call denied, reached limit of participants")); goto END_CALL; }
if ((pConfObject->IsHosting() != S_OK) && !(pConfObject->GetConfAttendeePermissions() & NM_PERMIT_OUTGOINGCALLS)) { WARNING_OUT(("Outgoing call denied, not permitted by meeting settings")); goto END_CALL; }
pCall = new COutgoingCall( pConfObject, dwFlags, addrType, bstrName, bstrDest, bstrAlias, bstrConference, bstrPassword, bstrUserString); if (NULL != pCall) { m_CallList.AddTail(pCall);
if (NULL != ppCall) { pCall->AddRef();
// This MUST be set before OnNotifyCallCreated
*ppCall = pCall; }
pCall->AddRef();
pManager->OnOutgoingCallCreated(pCall);
pCall->PlaceCall();
if (pCall->FIsComplete()) { RemoveFromList(pCall); }
pCall->Release();
// let the caller know that we successfully created the call
// any error will be reported asynchronously
hr = S_OK; } }
END_CALL: DebugExitHRESULT(COutgoingCallManager::CallConference, hr); return hr; }
BOOL COutgoingCallManager::RemoveFromList(COutgoingCall* pCall) { DebugEntry(COutgoingCallManager::RemoveFromList); ASSERT(pCall); BOOL bRet = FALSE;
POSITION pos = m_CallList.GetPosition(pCall); if (NULL != pos) { m_CallList.RemoveAt(pos);
pCall->CallComplete(); pCall->Release();
bRet = TRUE; } else { WARNING_OUT(("COutgoingCallManager::RemoveFromList() could not match call")); }
DebugExitBOOL(COutgoingCallManager::RemoveFromList, bRet); return bRet; }
BOOL COutgoingCallManager::OnH323Connected(IH323Endpoint* lpConnection) { DebugEntry(COutgoingCallManager::OnH323Connected);
BOOL fFound = FALSE;
COutgoingCall* pCall = FindCall(lpConnection); if (pCall) { fFound = TRUE;
pCall->AddRef(); pCall->OnH323Connected(lpConnection); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); } DebugExitBOOL(COutgoingCallManager::OnH323Connected, fFound);
return fFound; }
BOOL COutgoingCallManager::OnH323Disconnected(IH323Endpoint * lpConnection) { DebugEntry(COutgoingCallManager::OnH323Disconnected);
BOOL fFound = FALSE;
COutgoingCall* pCall = FindCall(lpConnection); if (pCall) { fFound = TRUE;
pCall->AddRef(); pCall->OnH323Disconnected(lpConnection); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); }
DebugExitBOOL(COutgoingCallManager::OnH323Disconnected, fFound);
return fFound; }
VOID COutgoingCallManager::OnT120ChannelOpen(ICommChannel *pIChannel, IH323Endpoint * lpConnection, DWORD dwStatus) { DebugEntry(COutgoingCallManager::OnT120ChannelOpen);
COutgoingCall* pCall = FindCall(lpConnection); if (pCall) { pCall->AddRef(); pCall->OnT120ChannelOpen(pIChannel, dwStatus); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); }
DebugExitVOID(COutgoingCallManager::OnT120ChannelOpen); }
VOID COutgoingCallManager::OnConferenceStarted(CONF_HANDLE hConference, HRESULT hResult) { DebugEntry(COutgoingCallManager::OnConferenceStarted);
// Tell all ConfNode's that a conference has started
POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
if (NULL != pCall) { pCall->AddRef(); pCall->OnConferenceStarted(hConference, hResult); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); } }
DebugExitVOID(COutgoingCallManager::OnConferenceStarted); }
VOID COutgoingCallManager::OnQueryRemoteResult(PVOID pvCallerContext, HRESULT hResult, BOOL fMCU, PWSTR* ppwszConferenceNames, PT120PRODUCTVERSION pVersion, PWSTR* ppwszConfDescriptors) { DebugEntry(COutgoingCallManager::OnQueryRemoteResult);
POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
// Notify the node that issued the query:
if ((COutgoingCall*) pvCallerContext == pCall) { pCall->AddRef(); pCall->OnQueryRemoteResult( hResult, fMCU, ppwszConferenceNames, pVersion, ppwszConfDescriptors); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); break; } } DebugExitVOID(COutgoingCallManager::OnQueryRemoteResult); }
VOID COutgoingCallManager::OnInviteResult( CONF_HANDLE hConference, REQUEST_HANDLE hRequest, UINT uNodeID, HRESULT hResult, PT120PRODUCTVERSION pVersion) { DebugEntry(COutgoingCallManager::OnInviteResult);
POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
if ((NULL != pCall) && (pCall->GetCurrentRequestHandle() == hRequest)) { pCall->AddRef(); pCall->OnInviteResult(hResult, uNodeID); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); break; } }
DebugExitVOID(COutgoingCallManager::OnInviteResult); }
VOID COutgoingCallManager::OnConferenceEnded(CONF_HANDLE hConference) { DebugEntry(COutgoingCallManager::OnConferenceEnded);
// Tell all ConfNode's that a conference has started
POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
if (NULL != pCall) { pCall->AddRef(); pCall->OnConferenceEnded(); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); } }
DebugExitVOID(COutgoingCallManager::OnConferenceEnded); }
VOID COutgoingCallManager::CancelCalls() { DebugEntry(COutgoingCallManager::CancelCalls);
// Tell all ConfNode's that a conference has started
POSITION pos = m_CallList.GetHeadPosition(); while (pos) { COutgoingCall* pCall = (COutgoingCall*) m_CallList.GetNext(pos);
if (NULL != pCall) { pCall->AddRef(); pCall->_Cancel(TRUE); if (pCall->FIsComplete()) { RemoveFromList(pCall); } pCall->Release(); } }
DebugExitVOID(COutgoingCallManager::CancelCalls); }
|