550 lines
15 KiB
C++
550 lines
15 KiB
C++
|
#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;
|
||
|
}
|
||
|
|
||
|
|