|
|
#include "precomp.h"
#include "events.hpp"
#include "ernccm.hpp"
#include "erncconf.hpp"
#include "erncvrsn.hpp"
#include "nccglbl.hpp"
extern PController g_pMCSController;
CWorkItem::~CWorkItem(void) { } // pure virtual
BOOL GetSecurityInfo(ConnectionHandle connection_handle, PBYTE pInfo, PDWORD pcbInfo);
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CInviteIndWork
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CInviteIndWork:: CInviteIndWork ( PCONFERENCE _pConference, LPCWSTR _wszCallerID, CLogicalConnection * _pConEntry ) : CWorkItem(_pConference), m_pConf(_pConference), m_fSecure(_pConEntry->IsConnectionSecure()) { DebugEntry(CInviteIndWork::CInviteIndWork);
// Take copy of caller ID.
// Note memory allocation failure proceeds with NULL ID.
m_pwszCallerID = ::My_strdupW(_wszCallerID);
DebugExitVOID(CInviteIndWork::CInviteIndWork); }
CInviteIndWork:: ~CInviteIndWork(void) { DebugEntry(CInviteIndWork::~CInviteIndWork);
//
// If we substituted transport security data for roster data,
// free that buffer now
//
delete m_pwszCallerID;
DebugExitVOID(CInviteIndWork::~CInviteIndWork); }
void CInviteIndWork:: DoWork(void) { DebugEntry(CInviteIndWork::DoWork);
// Now we are actually processing the invite, validate that there
// are no other conferences of the same name, and, if not, block
// a conference of the same name by setting the conference to be active,
// and give invite request up to the UI.
PCONFERENCE pOtherConf = g_pNCConfMgr->GetConferenceFromName(m_pConf->GetName()); if (NULL == pOtherConf) { m_pConf->SetNotifyToDo(TRUE); g_pCallbackInterface->OnIncomingInviteRequest((CONF_HANDLE) m_pConf, GetCallerID(), m_fSecure); } else { m_pConf->InviteResponse(UI_RC_CONFERENCE_ALREADY_EXISTS); }
DebugExitVOID(CInviteIndWork::DoWork); }
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CJoinIndWork
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CJoinIndWork:: CJoinIndWork ( GCCResponseTag Tag, PCONFERENCE _pConference, LPCWSTR _wszCallerID, CLogicalConnection *_pConEntry, HRESULT *pRetCode ) : CWorkItem(_pConference), m_nResponseTag(Tag), m_pConf(_pConference), m_pConEntry(_pConEntry) { DebugEntry(CJoinIndWork::CJoinIndWork);
*pRetCode = NO_ERROR;
#ifdef DEBUG
SOCKET socket_number; g_pMCSController->FindSocketNumber(m_pConEntry->GetConnectionHandle(),&socket_number); #endif
// Take copy of caller ID because T120
// implementation is not keeping its copy valid
// until the join response.
// Note that memory allocation failure proceeds with
// NULL caller ID.
m_pwszCallerID = ::My_strdupW(_wszCallerID);
DebugExitVOID(CJoinIndWork::CJoinIndWork); }
CJoinIndWork:: ~CJoinIndWork(void) { DebugEntry(CJoinIndWork::~CJoinIndWork);
delete m_pwszCallerID;
DebugExitVOID(CJoinIndWork::~CJoinIndWork); }
void CJoinIndWork:: DoWork(void) { DebugEntry(CJoinIndWork::DoWork);
// Notify the core.
g_pCallbackInterface->OnIncomingJoinRequest((CONF_HANDLE) m_pConf, m_pwszCallerID); DebugExitVOID(CJoinIndWork::DoWork); }
HRESULT CJoinIndWork:: Respond ( GCCResult _Result ) { DebugEntry(CJoinIndWork::Respond);
// It is a response from the core.
HRESULT hr = ::GCCJoinResponseWrapper(m_nResponseTag, NULL, _Result, m_pConf->GetID(), 0, NULL);
DebugExitHRESULT(CJoinIndWork::Respond, hr); return hr; }
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CSequentialWorkList
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void CSequentialWorkList:: AddWorkItem ( CWorkItem *pWorkItem ) { DebugEntry(CSequentialWorkList::AddWorkItem);
Append(pWorkItem);
// If first entry in list, then kick off handler.
if (1 == GetCount()) { pWorkItem->DoWork(); }
DebugExitVOID(CSequentialWorkList::AddWorkItem); }
void CSequentialWorkList:: RemoveWorkItem ( CWorkItem *pWorkItem ) { DebugEntry(CSequentialWorkList::RemoveWorkItem);
if (pWorkItem) { // Make a note as to whether we are going to remove the head
// work item in the list.
BOOL bHeadItemRemoved = (pWorkItem == PeekHead());
// Remove work item from list and destroy it.
if (Remove(pWorkItem)) { delete pWorkItem;
// If there are more entries in the list, and we removed the
// first one, then start the work of the next one in line.
// Note that before doing this, the pointer to the workitem
// was NULLed out (above) to prevent reentracy problems.
if (bHeadItemRemoved && !IsEmpty()) { PeekHead()->DoWork(); } } else { ASSERT(! bHeadItemRemoved); } }
DebugExitVOID(CSequentialWorkList::RemoveWorkItem); }
void CSequentialWorkList:: PurgeListEntriesByOwner ( DCRNCConference *pOwner ) { CWorkItem *pWorkItem;
DebugEntry(CSequentialWorkList::PurgeListEntriesByOwner);
if (NULL != pOwner) { // Note that head entry is removed last to stop work being started
// on other entries in the list that are owned by pOwner.
// Check to ensure there is a head item in the list.
if (NULL != (pWorkItem = PeekHead())) { // Remember we are going to remove the head.
BOOL fHeadToRemove = pWorkItem->IsOwnedBy(pOwner);
// Walk remaining entries in the list removing them.
BOOL fMoreToRemove; do { fMoreToRemove = FALSE; Reset(); while (NULL != (pWorkItem = Iterate())) { if (pWorkItem->IsOwnedBy(pOwner)) { Remove(pWorkItem); delete pWorkItem; fMoreToRemove = TRUE; break; } } } while (fMoreToRemove);
// Now done removing all entries, including the head if needed...
if (fHeadToRemove && ! IsEmpty()) { PeekHead()->DoWork(); } } }
DebugExitVOID(CSequentialWorkList::PurgeListEntriesByOwner); }
void CSequentialWorkList:: DeleteList(void) { CWorkItem *pWorkItem; while (NULL != (pWorkItem = Get())) { delete pWorkItem; } }
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Implementation of Methods for CQueryRemoteWork
//
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
CQueryRemoteWork:: CQueryRemoteWork ( LPVOID pCallerContext, GCCAsymmetryType eAsymType, LPCSTR pcszNodeAddress, BOOL fSecure, HRESULT *pRetCode ) : CWorkItem(pCallerContext), m_hGCCConnHandle(NULL), m_apConfNames(NULL), m_fRemoteIsMCU(FALSE), m_eAsymType(eAsymType), m_fSecure(fSecure), m_apConfDescriptors(NULL) { DebugEntry(CQueryRemoteWork::CQueryRemoteWork);
char szAddress[RNC_MAX_NODE_STRING_LEN]; ::BuildAddressFromNodeDetails((LPSTR) pcszNodeAddress, &szAddress[0]); m_pszAddress = ::My_strdupA(&szAddress[0]); m_hr = (NULL != m_pszAddress) ? NO_ERROR : UI_RC_OUT_OF_MEMORY; *pRetCode = m_hr; DebugExitVOID(CQueryRemoteWork::CQueryRemoteWork); }
CQueryRemoteWork:: ~CQueryRemoteWork(void) { LPWSTR *ppTempTargetName; LPWSTR *ppTempTargetDescriptor;
DebugEntry(CQueryRemoteWork::~CQueryRemoteWork);
// Clean up memory allocated.
if (m_apConfNames) { ppTempTargetName = m_apConfNames; while (*ppTempTargetName) { delete *(ppTempTargetName++); } delete [] m_apConfNames; }
if (m_apConfDescriptors) { ppTempTargetDescriptor = m_apConfDescriptors; while (*ppTempTargetDescriptor) { delete *(ppTempTargetDescriptor++); } delete [] m_apConfDescriptors; } delete m_pszAddress;
DebugExitVOID(CQueryRemoteWork::~CQueryRemoteWork); }
void CQueryRemoteWork:: DoWork(void) { GCCError GCCrc; GCCNodeType nodeType; GCCAsymmetryIndicator asymmetry_indicator;
DebugEntry(CQueryRemoteWork::DoWork);
::LoadAnnouncePresenceParameters(&nodeType, NULL, NULL, NULL);
asymmetry_indicator.asymmetry_type = m_eAsymType; asymmetry_indicator.random_number = 0; if (asymmetry_indicator.asymmetry_type == GCC_ASYMMETRY_UNKNOWN) { m_nRandSeed = (int) ::GetTickCount(); m_LocalAsymIndicator.random_number = ((GenerateRand() << 16) + GenerateRand()); asymmetry_indicator.random_number = m_LocalAsymIndicator.random_number; m_LocalAsymIndicator.asymmetry_type = GCC_ASYMMETRY_UNKNOWN; m_fInUnknownQueryRequest = TRUE; }
GCCrc = g_pIT120ControlSap->ConfQueryRequest( nodeType, &asymmetry_indicator, NULL, (TransportAddress) m_pszAddress, m_fSecure, 0, NULL, &m_hGCCConnHandle); TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfQueryRequest, rc=%d", GCCrc));
if (NO_ERROR != (m_hr = ::GetGCCRCDetails(GCCrc))) { AsyncQueryRemoteResult(); }
DebugExitHRESULT(CQueryRemoteWork::DoWork, m_hr); }
void CQueryRemoteWork:: HandleQueryConfirmation ( QueryConfirmMessage * pQueryMessage ) { UINT NumberOfConferences; GCCConferenceDescriptor ** ppConferenceDescriptor; PWSTR * ppTempTargetName; PWSTR ConferenceTextName; GCCConferenceName * pGCCConferenceName; PWSTR * ppTempTargetDescriptor; PWSTR pwszConfDescriptor=NULL; HRESULT hrTmp;
DebugEntry(CQueryRemoteWork::HandleQueryConfirmation);
// If no error, then package up information.
m_hr = ::GetGCCResultDetails(pQueryMessage->result); if (NO_ERROR == m_hr) { m_fRemoteIsMCU = (pQueryMessage->node_type == GCC_MCU); NumberOfConferences = pQueryMessage->number_of_descriptors; DBG_SAVE_FILE_LINE m_apConfNames = new PWSTR[NumberOfConferences + 1]; m_apConfDescriptors = new PWSTR[NumberOfConferences + 1]; if (!m_apConfNames || !m_apConfDescriptors) { m_hr = UI_RC_OUT_OF_MEMORY; } else { ppConferenceDescriptor = pQueryMessage->conference_descriptor_list; ppTempTargetName = m_apConfNames; ppTempTargetDescriptor = m_apConfDescriptors; while (NumberOfConferences--) { pwszConfDescriptor = (*(ppConferenceDescriptor))->conference_descriptor; pGCCConferenceName = &(*(ppConferenceDescriptor++))->conference_name;
if (pwszConfDescriptor != NULL) { pwszConfDescriptor = ::My_strdupW(pwszConfDescriptor); } ConferenceTextName = pGCCConferenceName->text_string; if (ConferenceTextName != NULL) { ConferenceTextName = ::My_strdupW(ConferenceTextName); if (!ConferenceTextName) { // Out of memory, give back what we have.
m_hr = UI_RC_OUT_OF_MEMORY; break; } } else if (pGCCConferenceName->numeric_string != NULL) { ConferenceTextName = ::AnsiToUnicode((PCSTR)pGCCConferenceName->numeric_string); if (!ConferenceTextName) { // Out of memory, give back what we have.
m_hr = UI_RC_OUT_OF_MEMORY; break; } } if (ConferenceTextName) { *(ppTempTargetName++) = ConferenceTextName; *(ppTempTargetDescriptor++) = pwszConfDescriptor; } } *ppTempTargetName = NULL; *ppTempTargetDescriptor = NULL; } }
m_fInUnknownQueryRequest = FALSE;
hrTmp = m_hr;
// Propagate the result directly without posting a message.
SyncQueryRemoteResult();
DebugExitHRESULT(CQueryRemoteWork::HandleQueryConfirmation, hrTmp); }
void CQueryRemoteWork:: SyncQueryRemoteResult(void) { DebugEntry(CQueryRemoteWork::SyncQueryRemoteResult);
// Let the user know the result of his request.
// The user is expected to call Release() after getting the result,
// if he wants to drop the line - and should for errors.
// Also, if the user is being called back before the inline code
// has filled in the handle, then fill it in here - see comments in
// DCRNCConferenceManager::QueryRemote for additional background.
g_pCallbackInterface->OnQueryRemoteResult( m_pOwner, m_hr, m_fRemoteIsMCU, m_apConfNames, m_apConfDescriptors);
// If we are not inline, and this request made it into
// the sequential work item list,
// then remove from list (which will cause item to be deleted),
// otherwise, just delete item.
g_pQueryRemoteList->RemoveWorkItem(this);
DebugExitVOID(CQueryRemoteWork::SyncQueryRemoteResult); }
void CQueryRemoteWork:: AsyncQueryRemoteResult(void) { g_pNCConfMgr->PostWndMsg(NCMSG_QUERY_REMOTE_FAILURE, (LPARAM) this); }
int CQueryRemoteWork:: GenerateRand(void) { // code from CRT
return (((m_nRandSeed = m_nRandSeed * 214013L + 2531011L) >> 16) & 0x7fff); }
HRESULT CQueryRemoteWorkList:: Cancel ( LPVOID pCallerContext ) { HRESULT hr = S_FALSE; // if not found
CQueryRemoteWork *p; Reset(); while (NULL != (p = Iterate())) { if (p->IsOwnedBy(pCallerContext)) { // clean up the underlying plumbing.
g_pIT120ControlSap->CancelConfQueryRequest(p->GetConnectionHandle());
// clean up node controller data.
RemoveWorkItem(p); hr = S_OK; break; } }
return hr; }
|