You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1419 lines
58 KiB
1419 lines
58 KiB
/****************************************************************************/
|
|
/* */
|
|
/* ERNCGCCC.CPP */
|
|
/* */
|
|
/* T120 Conference class for the Reference System Node Controller. */
|
|
/* */
|
|
/* Copyright Data Connection Ltd. 1995 */
|
|
/* */
|
|
/****************************************************************************/
|
|
/* Changes: */
|
|
/* */
|
|
/* 14Jul95 NFC Created. */
|
|
/* 13Sep95 NFC Added handler for GCC_EJECT_USER_INDICATION */
|
|
/* 26Sep95 NFC Reset conference state in HandleEjectUser(). */
|
|
/* 11Oct95 PM Relax conference termination checks to avoid */
|
|
/* "no win" situations. The user wants it down */
|
|
/* then bring it down, whatever the state! */
|
|
/* */
|
|
/****************************************************************************/
|
|
#include "precomp.h"
|
|
DEBUG_FILEZONE(ZONE_GCC_NC);
|
|
#include "ernccons.h"
|
|
#include "nccglbl.hpp"
|
|
#include "erncvrsn.hpp"
|
|
#include "cuserdta.hpp"
|
|
|
|
#include "ernccm.hpp"
|
|
#include "ernctrc.h"
|
|
#include "nmremote.h"
|
|
|
|
|
|
static UINT s_nNumericNameCounter = 0;
|
|
__inline UINT GetNewNumericNameCounter(void) { return ++s_nNumericNameCounter; }
|
|
|
|
|
|
|
|
HRESULT DCRNCConference::
|
|
NewT120Conference(void)
|
|
{
|
|
DebugEntry(DCRNCConference::NewT120Conference);
|
|
|
|
m_eT120State = T120C_ST_IDLE;
|
|
|
|
HRESULT hr;
|
|
PCONFERENCE pConf;
|
|
GCCNumericString pszNewNumericName;
|
|
|
|
m_ConfName.numeric_string = NULL; // No numeric name yet.
|
|
|
|
hr = ::GetGCCFromUnicode(m_pwszConfName, &pszNewNumericName, &m_ConfName.text_string);
|
|
if (NO_ERROR == hr)
|
|
{
|
|
if (! ::IsEmptyStringA((LPCSTR) pszNewNumericName))
|
|
{
|
|
// Conference has a preassigned numeric name.
|
|
// Validate that it does not conflict with another
|
|
// conferences numeric name.
|
|
pConf = g_pNCConfMgr->GetConferenceFromNumber(pszNewNumericName);
|
|
if (NULL == pConf)
|
|
{
|
|
hr = NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("DCRNCConference::NewT120Conference: conference already exists"));
|
|
hr = UI_RC_CONFERENCE_ALREADY_EXISTS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Conference does not have a numeric name.
|
|
// Go get it a unique one.
|
|
DBG_SAVE_FILE_LINE
|
|
pszNewNumericName = (GCCNumericString)new CHAR[10];
|
|
if (NULL != pszNewNumericName)
|
|
{
|
|
do
|
|
{
|
|
// Do not allocate a conference number that is the same as
|
|
// an existing conference.
|
|
// bugbug: T120 should really do this, but it doesn't.
|
|
::wsprintfA((LPSTR) pszNewNumericName, "%u", ::GetNewNumericNameCounter());
|
|
pConf = g_pNCConfMgr->GetConferenceFromNumber(pszNewNumericName);
|
|
if (NULL == pConf)
|
|
{
|
|
hr = NO_ERROR; // Name good.
|
|
break;
|
|
}
|
|
}
|
|
while (TRUE); // Assumes not a DWORDs worth of conferences active.
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("DCRNCConference::NewT120Conference: can't create numeric name"));
|
|
hr = UI_RC_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("DCRNCConference::NewT120Conference: GetGCCFromUnicode failed, hr=0x%x", (UINT) hr));
|
|
}
|
|
|
|
// Done looking for numeric name, so can now insert into list.
|
|
m_ConfName.numeric_string = pszNewNumericName;
|
|
|
|
// In case of failure, be sure to notify nmcom.
|
|
if (NO_ERROR != hr)
|
|
{
|
|
g_pNCConfMgr->NotifyConferenceComplete(this, m_fIncoming, hr);
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::NewT120Conference, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* AnnouncePresence() - announce this nodes participation in the */
|
|
/* conference. */
|
|
/****************************************************************************/
|
|
HRESULT DCRNCConference::
|
|
AnnouncePresence(void)
|
|
{
|
|
GCCError GCCrc = GCC_INVALID_CONFERENCE;
|
|
HRESULT hr = UI_RC_OUT_OF_MEMORY;
|
|
GCCNodeType nodeType;
|
|
GCCNodeProperties nodeProperties;
|
|
LPWSTR nodeName;
|
|
UINT nRecords;
|
|
GCCUserData ** ppUserData;
|
|
|
|
DebugEntry(DCRNCConference::AnnouncePresence);
|
|
|
|
if (0 != m_nConfID)
|
|
{
|
|
// bugbug: handle errors that cause failure to announce presence.
|
|
|
|
// Obtain the local addresses for the local user and
|
|
// publish them in the roster.
|
|
g_pCallbackInterface->OnUpdateUserData(this);
|
|
|
|
/************************************************************************/
|
|
/* Load the node type, node properties and node name from the RNC INI */
|
|
/* file. */
|
|
/************************************************************************/
|
|
nodeName = NULL;
|
|
::LoadAnnouncePresenceParameters(
|
|
&nodeType,
|
|
&nodeProperties,
|
|
&nodeName,
|
|
NULL); // &siteInfo)) : Not used right now.
|
|
|
|
/************************************************************************/
|
|
/* Announce our presence in the conference. */
|
|
/************************************************************************/
|
|
hr = m_LocalUserData.GetUserDataList(&nRecords, &ppUserData);
|
|
if (NO_ERROR == hr)
|
|
{
|
|
GCCrc = g_pIT120ControlSap->AnnouncePresenceRequest(
|
|
m_nConfID,
|
|
nodeType,
|
|
nodeProperties,
|
|
nodeName,
|
|
0, /* number_of_participants */
|
|
NULL, //partNameList, /* participant_name_list */
|
|
NULL, /* pwszSiteInfo */
|
|
0, /* number_of_network_addresses */
|
|
NULL, /* network_address_list */
|
|
NULL, //pAltID, /* alternative_node_id */
|
|
nRecords,/* number_of_user_data_members */
|
|
ppUserData /* user_data_list */
|
|
);
|
|
hr = ::GetGCCRCDetails(GCCrc);
|
|
}
|
|
|
|
delete nodeName;
|
|
}
|
|
|
|
if (GCC_NO_ERROR != GCCrc)
|
|
{
|
|
if (GCC_CONFERENCE_NOT_ESTABLISHED == GCCrc ||
|
|
GCC_INVALID_CONFERENCE == GCCrc)
|
|
{
|
|
TRACE_OUT(("DCRNCConference::AnnouncePresence: conf is gone."));
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("DCRNCConference::AnnouncePresence: failed, gcc_rc=%u", GCCrc));
|
|
}
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::AnnouncePresence, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleGCCCallback() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleGCCCallback ( GCCMessage *pGCCMessage )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleGCCCallback);
|
|
|
|
TRACE_OUT(("DCRNCConference::HandleGCCCallback: msg id=%u", pGCCMessage->message_type));
|
|
|
|
/************************************************************************/
|
|
/* Note that GCC_CREATE_IND and GCC_INVITE_IND callbacks are handled */
|
|
/* higher up the stack by the conference manager and are not passed */
|
|
/* onto us. */
|
|
/************************************************************************/
|
|
switch (pGCCMessage->message_type)
|
|
{
|
|
case GCC_CREATE_CONFIRM:
|
|
HandleCreateConfirm(&(pGCCMessage->u.create_confirm));
|
|
break;
|
|
|
|
case GCC_INVITE_CONFIRM:
|
|
HandleInviteConfirm(&(pGCCMessage->u.invite_confirm));
|
|
break;
|
|
|
|
case GCC_ADD_CONFIRM:
|
|
HandleAddConfirm(&(pGCCMessage->u.add_confirm));
|
|
break;
|
|
|
|
case GCC_DISCONNECT_INDICATION:
|
|
HandleDisconnectInd(&(pGCCMessage->u.disconnect_indication));
|
|
break;
|
|
|
|
case GCC_DISCONNECT_CONFIRM:
|
|
HandleDisconnectConfirm(
|
|
&(pGCCMessage->u.disconnect_confirm));
|
|
break;
|
|
|
|
case GCC_TERMINATE_INDICATION:
|
|
HandleTerminateInd(&(pGCCMessage->u.terminate_indication));
|
|
break;
|
|
|
|
case GCC_TERMINATE_CONFIRM:
|
|
HandleTerminateConfirm(&(pGCCMessage->u.terminate_confirm));
|
|
break;
|
|
|
|
case GCC_ANNOUNCE_PRESENCE_CONFIRM:
|
|
HandleAnnounceConfirm(&(pGCCMessage->u.announce_presence_confirm));
|
|
break;
|
|
|
|
case GCC_ROSTER_REPORT_INDICATION:
|
|
HandleRosterReport(pGCCMessage->u.conf_roster_report_indication.conference_roster);
|
|
break;
|
|
|
|
case GCC_ROSTER_INQUIRE_CONFIRM:
|
|
HandleRosterReport(pGCCMessage->u.conf_roster_inquire_confirm.conference_roster);
|
|
break;
|
|
|
|
case GCC_PERMIT_TO_ANNOUNCE_PRESENCE:
|
|
HandlePermitToAnnounce(&(pGCCMessage->u.permit_to_announce_presence));
|
|
break;
|
|
|
|
case GCC_EJECT_USER_INDICATION:
|
|
HandleEjectUser(&(pGCCMessage->u.eject_user_indication));
|
|
break;
|
|
|
|
case GCC_CONNECTION_BROKEN_INDICATION:
|
|
HandleConnectionBrokenIndication(&(pGCCMessage->u.connection_broken_indication));
|
|
break;
|
|
|
|
default :
|
|
WARNING_OUT(("Unrecognised event %d", pGCCMessage->message_type));
|
|
break;
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleGCCCallback);
|
|
}
|
|
|
|
|
|
void DCRNCConference::
|
|
HandleConnectionBrokenIndication ( ConnectionBrokenIndicationMessage * pConnDownMsg )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleConnectionBrokenIndication);
|
|
|
|
// A logical connection in a conference has gone away.
|
|
// Find the associated logical connection (if it is still around)
|
|
// and Delete() it.
|
|
// This function is what causes a modem line to drop when someone
|
|
// invited into a conference over a modem leaves the conference.
|
|
CLogicalConnection *pConEntry = GetConEntry(pConnDownMsg->connection_handle);
|
|
if (NULL != pConEntry)
|
|
{
|
|
pConEntry->Delete(UI_RC_USER_DISCONNECTED);
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleConnectionBrokenIndication);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleAddConfirm - handle a GCC_ADD_CONFIRM message */
|
|
/****************************************************************************/
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleAnnounceConfirm - handle a GCC_ANNOUNCE_PRESENCE_CONFIRM message */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleAnnounceConfirm ( AnnouncePresenceConfirmMessage * pAnnounceConf )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleAnnounceConfirm);
|
|
|
|
/************************************************************************/
|
|
/* Map the return code to a conference return code. */
|
|
/************************************************************************/
|
|
HRESULT hr = ::GetGCCResultDetails(pAnnounceConf->result);
|
|
|
|
TRACE_OUT(("GCC event: GCC_ANNOUNCE_PRESENCE_CONFIRM"));
|
|
TRACE_OUT(("Result=%u", pAnnounceConf->result));
|
|
|
|
/************************************************************************/
|
|
/* If this failed, tell the base conference that we failed to start. */
|
|
/************************************************************************/
|
|
if (NO_ERROR != hr)
|
|
{
|
|
ERROR_OUT(("Failed to announce presence in conference"));
|
|
NotifyConferenceComplete(hr);
|
|
// bugbug: ??? Should we leave the conference here???
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Now sit and wait for our entry to appear in the conference roster. */
|
|
/************************************************************************/
|
|
|
|
DebugExitHRESULT(DCRNCConference::HandleAnnounceConfirm, hr);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleCreateConfirm - handle a GCC_CREATE_CONFIRM message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleCreateConfirm ( CreateConfirmMessage * pCreateConfirm )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleCreateConfirm);
|
|
|
|
/************************************************************************/
|
|
/* Map the GCC result onto CONF_RC_ return code. */
|
|
/************************************************************************/
|
|
HRESULT hr = ::GetGCCResultDetails(pCreateConfirm->result);
|
|
|
|
TRACE_OUT(("GCC event: GCC_CREATE_CONFIRM"));
|
|
TRACE_OUT(("Result=%u", pCreateConfirm->result));
|
|
TRACE_OUT(("Conference ID %ld", pCreateConfirm->conference_id));
|
|
|
|
/************************************************************************/
|
|
/* Result of our attempt to start a new conference */
|
|
/************************************************************************/
|
|
if (NO_ERROR == hr)
|
|
{
|
|
/************************************************************************/
|
|
/* Store the conference ID. */
|
|
/************************************************************************/
|
|
m_nConfID = pCreateConfirm->conference_id;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("Error %d creating new conference", hr));
|
|
|
|
/************************************************************************/
|
|
/* Pass any failure result onto the base conference. */
|
|
/************************************************************************/
|
|
NotifyConferenceComplete(hr);
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleCreateConfirm);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleDisconnectConfirm - handle a GCC_DISCONNECT_CONFIRM message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleDisconnectConfirm ( DisconnectConfirmMessage * pDiscConf )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleDisconnectConfirm);
|
|
|
|
/************************************************************************/
|
|
/* Check the state. */
|
|
/************************************************************************/
|
|
if (m_eT120State != T120C_ST_PENDING_DISCONNECT)
|
|
{
|
|
WARNING_OUT(("Bad state %d, expecting %d",
|
|
T120C_ST_PENDING_DISCONNECT,
|
|
m_eT120State));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Map the GCC result onto CONF_RC_ return code. */
|
|
/************************************************************************/
|
|
TRACE_OUT(("GCC event: GCC_DISCONNECT_CONFIRM"));
|
|
TRACE_OUT(("Result=%u", pDiscConf->result));
|
|
TRACE_OUT(("Conference ID %ld", pDiscConf->conference_id));
|
|
|
|
/************************************************************************/
|
|
/* We have successsfully left the conference, so tell the base */
|
|
/* conference about it. */
|
|
/************************************************************************/
|
|
g_pNCConfMgr->RemoveConference(this);
|
|
|
|
DebugExitVOID(DCRNCConference::HandleDisconnectConfirm);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleDisconnectInd - handle a GCC_DISCONNECT_INDICATION message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleDisconnectInd ( DisconnectIndicationMessage * pDiscInd )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleDisconnectInd);
|
|
|
|
/************************************************************************/
|
|
/* Check the state. */
|
|
/************************************************************************/
|
|
TRACE_OUT(("GCC event: GCC_DISCONNECT_INDICATION"));
|
|
TRACE_OUT(("Conference ID %d", pDiscInd->conference_id));
|
|
TRACE_OUT(("Reason=%u", pDiscInd->reason));
|
|
TRACE_OUT(("Disconnected Node ID %d", pDiscInd->disconnected_node_id));
|
|
|
|
/************************************************************************/
|
|
/* If this is our node ID, we have left the conference, tell the CM we */
|
|
/* are dead. */
|
|
/************************************************************************/
|
|
if (pDiscInd->disconnected_node_id == m_nidMyself)
|
|
{
|
|
WARNING_OUT(("We have been disconnected from conference"));
|
|
// m_eT120State = T120C_ST_IDLE;
|
|
g_pNCConfMgr->RemoveConference(this);
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleDisconnectInd);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleEjectUser - handle a GCC_EJECT_USER_INDICATION message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleEjectUser ( EjectUserIndicationMessage * pEjectInd )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleEjectUser);
|
|
|
|
TRACE_OUT(("GCC_EJECT_USER_INDICATION"));
|
|
TRACE_OUT(("Conference ID %ld", pEjectInd->conference_id));
|
|
TRACE_OUT(("Ejected node ID %d", pEjectInd->ejected_node_id));
|
|
TRACE_OUT(("Reason=%u", pEjectInd->reason));
|
|
|
|
/************************************************************************/
|
|
/* If the ejected node ID is ours, we have been tossed out of the */
|
|
/* conference, so tell CM about it. */
|
|
/************************************************************************/
|
|
if (pEjectInd->ejected_node_id == m_nidMyself)
|
|
{
|
|
/********************************************************************/
|
|
/* Reset the conference state first. */
|
|
/********************************************************************/
|
|
m_eT120State = T120C_ST_IDLE;
|
|
|
|
WARNING_OUT(("We have been thrown out of the conference"));
|
|
g_pNCConfMgr->RemoveConference(this);
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleEjectUser);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleInviteConfirm - handle a GCC_INVITE_CONFIRM message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleInviteConfirm ( InviteConfirmMessage * pInviteConf )
|
|
{
|
|
PT120PRODUCTVERSION pVersion;
|
|
|
|
DebugEntry(DCRNCConference::HandleInviteConfirm);
|
|
|
|
/************************************************************************/
|
|
/* Map the GCC result onto CONF_RC_ return code. */
|
|
/************************************************************************/
|
|
TRACE_OUT(("GCC event: GCC_INVITE_CONFIRM"));
|
|
TRACE_OUT(("Result=%u", pInviteConf->result));
|
|
|
|
if (pInviteConf->result == GCC_RESULT_SUCCESSFUL)
|
|
{
|
|
TRACE_OUT(("New node successfully invited into conference"));
|
|
ASSERT((ConnectionHandle)pInviteConf->connection_handle);
|
|
}
|
|
else
|
|
{
|
|
TRACE_OUT(("Error %d inviting new node into conference", pInviteConf->result));
|
|
}
|
|
|
|
// Notify the base conference that the invite has completed.
|
|
pVersion = ::GetVersionData(pInviteConf->number_of_user_data_members,
|
|
pInviteConf->user_data_list);
|
|
InviteComplete(pInviteConf->connection_handle,
|
|
::GetGCCResultDetails(pInviteConf->result),
|
|
pVersion);
|
|
|
|
DebugExitVOID(DCRNCConference::HandleInviteConfirm);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleJoinConfirm - handle a GCC_JOIN_CONFIRM message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleJoinConfirm ( JoinConfirmMessage * pJoinConf )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleJoinConfirm);
|
|
|
|
m_nConfID = pJoinConf->conference_id;
|
|
|
|
HRESULT hr;
|
|
CLogicalConnection *pConEntry;
|
|
PT120PRODUCTVERSION pVersion;
|
|
|
|
hr = ::GetGCCResultDetails(pJoinConf->result);
|
|
|
|
TRACE_OUT(("GCC event: GCC_JOIN_CONFIRM"));
|
|
TRACE_OUT(("Result=%u", pJoinConf->result));
|
|
TRACE_OUT(("Conference ID %ld", pJoinConf->conference_id));
|
|
TRACE_OUT(("Locked %d", pJoinConf->conference_is_locked));
|
|
TRACE_OUT(("Listed %d", pJoinConf->conference_is_listed));
|
|
TRACE_OUT(("Conductible %d", pJoinConf->conference_is_conductible));
|
|
TRACE_OUT(("Connection Handle %d", pJoinConf->connection_handle));
|
|
TRACE_OUT(("Termination method %d", pJoinConf->termination_method));
|
|
|
|
pVersion = ::GetVersionData(pJoinConf->number_of_user_data_members,
|
|
pJoinConf->user_data_list);
|
|
|
|
// Check the state.
|
|
// If we are not expecting a join confirm at this point, then
|
|
// it is most likely that the connection went down whilst we
|
|
// were waiting for a join confirmation and we are in the middle of
|
|
// telling the user. In this case, just ignore the event.
|
|
if (m_eT120State != T120C_ST_PENDING_JOIN_CONFIRM)
|
|
{
|
|
WARNING_OUT(("Bad state %d, expecting %d",
|
|
T120C_ST_PENDING_JOIN_CONFIRM,
|
|
m_eT120State));
|
|
return;
|
|
}
|
|
if (NULL == m_ConnList.PeekHead())
|
|
{
|
|
WARNING_OUT(("Join confirm without a connection"));
|
|
return;
|
|
}
|
|
pConEntry = m_ConnList.PeekHead();
|
|
if ((pConEntry->GetState() != CONF_CON_PENDING_JOIN) &&
|
|
(pConEntry->GetState() != CONF_CON_PENDING_PASSWORD))
|
|
{
|
|
if (pConEntry->GetState() != CONF_CON_ERROR)
|
|
{
|
|
TRACE_OUT(("Join confirm indication ignored"));
|
|
}
|
|
return;
|
|
}
|
|
pConEntry->Grab(); // Grab the pending result to the user.
|
|
|
|
pConEntry->SetConnectionHandle(pJoinConf->connection_handle);
|
|
|
|
/************************************************************************/
|
|
/* Expected result of our attempt to join a conference. */
|
|
/* */
|
|
/* If it worked, save the conference ID, otherwise tell the base */
|
|
/* conference that our attempt to join has failed. */
|
|
/************************************************************************/
|
|
|
|
// There will always be a pConEntry when a JoinConfirm fires,
|
|
// even if a physical disconnect is racing the JoinConfirm
|
|
// because the physical disconnect handler will cause this code
|
|
// to be entered before the physical connection is destroyed,
|
|
// as this gives the most accurate return codes.
|
|
if (NO_ERROR == hr)
|
|
{
|
|
TRACE_OUT(("Join worked"));
|
|
pConEntry->SetState(CONF_CON_CONNECTED);
|
|
m_nConfID = pJoinConf->conference_id;
|
|
}
|
|
|
|
// If the result is an invalid password, then tell the UI
|
|
// so that it can put up an invalid password dialog.
|
|
// The UI is then supposed to either reissue the join request
|
|
// with a new password or end the conference.
|
|
// It is done this way to keep the connection up whilst the
|
|
// user is entering the password, and not re-connect.
|
|
if (UI_RC_INVALID_PASSWORD == hr)
|
|
{
|
|
// Put the conference in the correct state for allowing
|
|
// a second join attempt.
|
|
pConEntry->SetState(CONF_CON_PENDING_PASSWORD);
|
|
m_eT120State = T120C_ST_IDLE;
|
|
m_pbCred = pJoinConf->pb_remote_cred;
|
|
m_cbCred = pJoinConf->cb_remote_cred;
|
|
|
|
// Now tell the user about the result.
|
|
g_pCallbackInterface->OnConferenceStarted(this, hr);
|
|
}
|
|
else
|
|
// If the result is an error, then end the conference.
|
|
if (NO_ERROR != hr)
|
|
{
|
|
NotifyConferenceComplete(hr);
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleJoinConfirm);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandlePermitToAnnounce - handle a GCC_PERMIT_TO_ANNOUNCE_PRESENCE */
|
|
/* message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandlePermitToAnnounce ( PermitToAnnouncePresenceMessage * pAnnounce )
|
|
{
|
|
DebugEntry(DCRNCConference::HandlePermitToAnnounce);
|
|
|
|
TRACE_OUT(("GCC event: GCC_PERMIT_TO_ANNOUNCE_PRESENCE"));
|
|
TRACE_OUT(("Conference ID %ld", pAnnounce->conference_id));
|
|
TRACE_OUT(("Node ID %d", pAnnounce->node_id));
|
|
|
|
/************************************************************************/
|
|
/* Store the node ID. */
|
|
/************************************************************************/
|
|
m_nidMyself = pAnnounce->node_id;
|
|
|
|
// See if there is a new local connection that needs publishing in the roster.
|
|
|
|
if (! m_ConnList.IsEmpty())
|
|
{
|
|
m_ConnList.PeekHead()->NewLocalAddress();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Announce our presence in the conference. */
|
|
/************************************************************************/
|
|
HRESULT hr = AnnouncePresence();
|
|
if (NO_ERROR == hr)
|
|
{
|
|
m_eT120State = T120C_ST_PENDING_ROSTER_ENTRY;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("Failed to announce presence in conference, error %d", hr));
|
|
// bugbug: end conference?
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandlePermitToAnnounce);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleRosterReportInd - handle a GCC_ROSTER_REPORT_INDICATION message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleRosterReport ( GCCConferenceRoster * pConferenceRoster )
|
|
{
|
|
PNC_ROSTER pRoster;
|
|
UINT i;
|
|
UINT numRecords = pConferenceRoster->number_of_records;
|
|
|
|
DebugEntry(DCRNCConference::HandleRosterReport);
|
|
|
|
TRACE_OUT(("GCC event: GCC_ROSTER_REPORT_INDICATION"));
|
|
TRACE_OUT(("Nodes added ? %d", pConferenceRoster->nodes_were_added));
|
|
TRACE_OUT(("Nodes removed ? %d", pConferenceRoster->nodes_were_removed));
|
|
TRACE_OUT(("Number of records %d", numRecords));
|
|
|
|
/************************************************************************/
|
|
/* If we are still setting up the conference, see whether we have */
|
|
/* appeared in the conference roster. */
|
|
/************************************************************************/
|
|
if (m_eT120State == T120C_ST_PENDING_ROSTER_ENTRY)
|
|
{
|
|
for (i = 0; i < numRecords ; i++)
|
|
{
|
|
if (pConferenceRoster->node_record_list[i]->node_id == m_nidMyself)
|
|
{
|
|
TRACE_OUT(("Found our entry in the roster"));
|
|
|
|
// We are in the roster! The conference has been
|
|
// successfully started so set the state and post
|
|
// a message to continue processing.
|
|
// This is so that callbacks can be made without getting
|
|
// blocked in T120.
|
|
|
|
m_eT120State = T120C_ST_PENDING_ROSTER_MESSAGE;
|
|
g_pNCConfMgr->PostWndMsg(NCMSG_FIRST_ROSTER_RECVD, (LPARAM) this);
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* If we have successfully started, build an RNC roster from the */
|
|
/* conference roster and pass it up to the CM. */
|
|
/************************************************************************/
|
|
if (m_eT120State == T120C_ST_CONF_STARTED)
|
|
{
|
|
/********************************************************************/
|
|
/* Allocate memory for a roster large enough to hold all the */
|
|
/* entries. */
|
|
/********************************************************************/
|
|
DBG_SAVE_FILE_LINE
|
|
pRoster = (PNC_ROSTER) new BYTE[(sizeof(NC_ROSTER) +
|
|
((numRecords - 1) * sizeof(NC_ROSTER_NODE_ENTRY)))];
|
|
if (pRoster == NULL)
|
|
{
|
|
ERROR_OUT(("Failed to create new conference roster."));
|
|
}
|
|
else
|
|
{
|
|
pRoster->uNumNodes = numRecords;
|
|
pRoster->uLocalNodeID = m_nidMyself;
|
|
|
|
// Add the node details to the roster.
|
|
for (i = 0; i < numRecords ; i++)
|
|
{
|
|
pRoster->nodes[i].uNodeID = pConferenceRoster->node_record_list[i]->node_id;
|
|
pRoster->nodes[i].uSuperiorNodeID = pConferenceRoster->node_record_list[i]->superior_node_id;
|
|
pRoster->nodes[i].fMCU = (pConferenceRoster->node_record_list[i]->node_type == GCC_MCU);
|
|
pRoster->nodes[i].pwszNodeName = pConferenceRoster->node_record_list[i]->node_name;
|
|
pRoster->nodes[i].hUserData = pConferenceRoster->node_record_list[i];
|
|
// If we have been invited into the conference, then the CLogicalConnection
|
|
// list maintained by the conference will not have our superior node's UserID,
|
|
// so we need to fill that in here.
|
|
if (pRoster->nodes[i].uNodeID == pRoster->uLocalNodeID &&
|
|
pRoster->nodes[i].uSuperiorNodeID != 0)
|
|
{
|
|
// We do have a superior node, so find its CLogicalConnection and fill in the
|
|
// UserID. It turns out that the UserIDs of subordinate nodes are filled in
|
|
// by another mechanism, so the superior node should be the only entry with
|
|
// zero for a UserID.
|
|
#ifdef DEBUG
|
|
int nSuperiorNode = 0;
|
|
#endif
|
|
CLogicalConnection * pConEntry;
|
|
m_ConnList.Reset();
|
|
while (NULL != (pConEntry = m_ConnList.Iterate()))
|
|
{
|
|
if (pConEntry->GetConnectionNodeID() == 0)
|
|
{
|
|
pConEntry->SetConnectionNodeID((GCCNodeID)pRoster->nodes[i].uSuperiorNodeID);
|
|
#ifdef DEBUG
|
|
nSuperiorNode++;
|
|
#else
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
ASSERT (nSuperiorNode <= 1);
|
|
}
|
|
}
|
|
NotifyRosterChanged(pRoster);
|
|
delete [] pRoster;
|
|
}
|
|
}
|
|
|
|
DebugExitVOID(DCRNCConference::HandleRosterReport);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleTerminateConfirm - handle a GCC_TERMINATE_CONFIRM message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleTerminateConfirm ( TerminateConfirmMessage * pTermConf )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleTerminateConfirm);
|
|
|
|
/************************************************************************/
|
|
/* Check the state */
|
|
/************************************************************************/
|
|
if (m_eT120State != T120C_ST_PENDING_TERMINATE)
|
|
{
|
|
WARNING_OUT(("Bad state: unexpected terminate confirm")); // Go ahead anyway
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Map the GCC result onto CONF_RC_ return code. */
|
|
/************************************************************************/
|
|
TRACE_OUT(("GCC event: GCC_TERMINATE_CONFIRM"));
|
|
TRACE_OUT(("Result=%u", pTermConf->result));
|
|
TRACE_OUT(("Conference ID %d", pTermConf->conference_id));
|
|
|
|
/************************************************************************/
|
|
/* If the request failed, reset our state and tell the FE? */
|
|
/************************************************************************/
|
|
if (pTermConf->result != GCC_RESULT_SUCCESSFUL)
|
|
{
|
|
ERROR_OUT(("Error %d attempting to terminate conference", pTermConf->result));
|
|
m_eT120State = T120C_ST_CONF_STARTED;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Our request to end the conference has worked - wait for the */
|
|
/* termination indication before telling the FE that we have died. */
|
|
/************************************************************************/
|
|
|
|
DebugExitVOID(DCRNCConference::HandleTerminateConfirm);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* HandleTerminateInd - handle a GCC_TERMINATE_INDICATION message. */
|
|
/****************************************************************************/
|
|
void DCRNCConference::
|
|
HandleTerminateInd ( TerminateIndicationMessage * pTermInd )
|
|
{
|
|
DebugEntry(DCRNCConference::HandleTerminateInd);
|
|
|
|
TRACE_OUT(("GCC event: GCC_TERMINATE_INDICATION"));
|
|
TRACE_OUT(("Conference ID %d", pTermInd->conference_id));
|
|
TRACE_OUT(("Requesting node ID %d", pTermInd->requesting_node_id));
|
|
TRACE_OUT(("Reason=%u", pTermInd->reason));
|
|
|
|
/************************************************************************/
|
|
/* The conference has ended beneath us. Reset our internal state and */
|
|
/* tell the base conference about it. */
|
|
/************************************************************************/
|
|
m_eT120State = T120C_ST_IDLE;
|
|
g_pNCConfMgr->RemoveConference(this);
|
|
|
|
DebugExitVOID(DCRNCConference::HandleTerminateInd);
|
|
}
|
|
|
|
|
|
HRESULT DCRNCConference::
|
|
RefreshRoster(void)
|
|
{
|
|
DebugEntry(DCRNCConference::RefreshRoster);
|
|
|
|
// Check the state.
|
|
if (m_eT120State != T120C_ST_CONF_STARTED)
|
|
{
|
|
ERROR_OUT(("Bad state: refresh roster requested before conference up"));
|
|
return(UI_RC_CONFERENCE_NOT_READY);
|
|
}
|
|
|
|
// Issue the request
|
|
GCCError GCCrc = g_pIT120ControlSap->ConfRosterInqRequest(m_nConfID); // Conference ID
|
|
|
|
// Handle the result
|
|
HRESULT hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfRosterInqRequest, rc=%d", GCCrc));
|
|
|
|
DebugExitHRESULT(DCRNCConference::RefreshRoster, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Invite() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
HRESULT DCRNCConference::
|
|
T120Invite
|
|
(
|
|
LPSTR pszNodeAddress,
|
|
BOOL fSecure,
|
|
CNCUserDataList *pUserDataInfoList,
|
|
ConnectionHandle *phInviteReqConn
|
|
)
|
|
{
|
|
GCCError GCCrc = GCC_NO_ERROR;
|
|
HRESULT hr;
|
|
UINT nUserDataRecords = 0;
|
|
GCCUserData **ppInfoUserData = NULL;
|
|
UINT nData;
|
|
PVOID pData;
|
|
char szAddress[RNC_MAX_NODE_STRING_LEN];
|
|
|
|
DebugEntry(DCRNCConference::T120Invite);
|
|
|
|
ASSERT(phInviteReqConn != NULL);
|
|
|
|
/************************************************************************/
|
|
/* Check the state. */
|
|
/************************************************************************/
|
|
if (m_eT120State != T120C_ST_CONF_STARTED)
|
|
{
|
|
ERROR_OUT(("Bad state: refresh roster requested before conference up"));
|
|
return(UI_RC_CONFERENCE_NOT_READY);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Build the address from the node details. */
|
|
/************************************************************************/
|
|
::BuildAddressFromNodeDetails(pszNodeAddress, &szAddress[0]);
|
|
|
|
/************************************************************************/
|
|
/* Invite the specified node into the conference. */
|
|
/************************************************************************/
|
|
LPWSTR pwszNodeName;
|
|
|
|
// If there is any user data to be sent
|
|
if (pUserDataInfoList)
|
|
{
|
|
// Add versioning data
|
|
if (NO_ERROR == ::GetUserData(g_nVersionRecords, g_ppVersionUserData, &g_csguidVerInfo, &nData, &pData))
|
|
{
|
|
pUserDataInfoList->AddUserData(&g_csguidVerInfo, nData, pData);
|
|
}
|
|
|
|
pUserDataInfoList->GetUserDataList(&nUserDataRecords,&ppInfoUserData);
|
|
}
|
|
else
|
|
{
|
|
ppInfoUserData = g_ppVersionUserData;
|
|
nUserDataRecords = g_nVersionRecords;
|
|
}
|
|
|
|
if (NULL != (pwszNodeName = ::GetNodeName()))
|
|
{
|
|
GCCrc = g_pIT120ControlSap->ConfInviteRequest(
|
|
m_nConfID,
|
|
pwszNodeName, // caller_identifier
|
|
NULL, // calling_address
|
|
&szAddress[0], // called_address
|
|
fSecure, // secure connection?
|
|
nUserDataRecords, // number_of_user_data_members
|
|
ppInfoUserData, // user_data_list
|
|
phInviteReqConn // returned connection_handle
|
|
);
|
|
|
|
hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfInviteRequest, rc=%d", GCCrc));
|
|
TRACE_OUT(("Transport handle %d", (UINT) *phInviteReqConn));
|
|
TRACE_OUT(("Called address '%s'", &szAddress[0]));
|
|
delete pwszNodeName;
|
|
}
|
|
else
|
|
{
|
|
hr = UI_RC_OUT_OF_MEMORY;
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::T120Invite, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Terminate() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
#if 0 // LONCHANC
|
|
HRESULT DCRNCConference::
|
|
Terminate(void)
|
|
{
|
|
DebugEntry(DCRNCConference::Terminate);
|
|
|
|
/************************************************************************/
|
|
/* Request to terminate the conference. */
|
|
/************************************************************************/
|
|
GCCError GCCrc = ::GCCConferenceTerminateRequest(m_nConfID, GCC_REASON_USER_INITIATED);
|
|
HRESULT hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: GCCConferenceTerminateRequest, rc=%d", GCCrc));
|
|
if (NO_ERROR == hr)
|
|
{
|
|
// Set the state to show we are about to die.
|
|
m_eT120State = T120C_ST_PENDING_TERMINATE;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("Failed to terminate conference, GCC error %d", GCCrc));
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::Terminate, hr);
|
|
return hr;
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
/****************************************************************************/
|
|
/* SendText() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
#if 0 // LONCHANC: not used
|
|
HRESULT DCRNCConference::
|
|
SendText
|
|
(
|
|
LPWSTR pwszTextMsg,
|
|
GCCNodeID node_id
|
|
)
|
|
{
|
|
DebugEntry(DCRNCConference::SendText);
|
|
|
|
/************************************************************************/
|
|
/* Request to send text to node in the conference. */
|
|
/************************************************************************/
|
|
GCCError GCCrc = ::GCCTextMessageRequest(m_nConfID, pwszTextMsg, node_id);
|
|
HRESULT hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: GCCTextMessageRequest, rc=%d", GCCrc));
|
|
if (NO_ERROR != hr)
|
|
{
|
|
ERROR_OUT(("Failed to send text to user, GCC error %d", GCCrc));
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::SendText, hr);
|
|
return hr;
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
#if 0 // LONCHANC: not used
|
|
HRESULT DCRNCConference::
|
|
TimeRemaining
|
|
(
|
|
UINT nTimeRemaining,
|
|
GCCNodeID nidDestination
|
|
)
|
|
{
|
|
DebugEntry(DCRNCConference::TimeRemaining);
|
|
|
|
/************************************************************************/
|
|
/* Request remaining time of the conference */
|
|
/************************************************************************/
|
|
GCCError GCCrc = g_pIT120ControlSap->ConfTimeRemainingRequest(m_nConfID, nTimeRemaining, nidDestination);
|
|
HRESULT hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfTimeRemainingRequest, rc=%d", GCCrc));
|
|
if (NO_ERROR != hr)
|
|
{
|
|
ERROR_OUT(("Failed to send the time remaining to user, GCC error %d", GCCrc));
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::TimeRemaining, hr);
|
|
return hr;
|
|
}
|
|
#endif // 0
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Join() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
HRESULT DCRNCConference::
|
|
T120Join
|
|
(
|
|
LPSTR pszNodeAddress,
|
|
BOOL fSecure,
|
|
LPCWSTR conferenceName,
|
|
CNCUserDataList *pUserDataInfoList,
|
|
LPCWSTR wszPassword
|
|
// REQUEST_HANDLE *phRequest
|
|
)
|
|
{
|
|
GCCError GCCrc = GCC_NO_ERROR;
|
|
HRESULT hr = NO_ERROR;
|
|
ConnectionHandle connectionHandle = 0;
|
|
GCCChallengeRequestResponse Password_Challenge;
|
|
GCCChallengeRequestResponse *pPassword_Challenge = NULL;
|
|
Password_Challenge.u.password_in_the_clear.numeric_string = NULL;
|
|
|
|
UINT nUserDataRecords = 0;
|
|
GCCUserData **ppInfoUserData = NULL;
|
|
UINT nData;
|
|
LPVOID pData;
|
|
|
|
char szAddress[RNC_MAX_NODE_STRING_LEN];
|
|
|
|
DebugEntry(DCRNCConference::T120Join);
|
|
|
|
/************************************************************************/
|
|
/* Check the state */
|
|
/************************************************************************/
|
|
ASSERT(m_eT120State == T120C_ST_IDLE);
|
|
|
|
/************************************************************************/
|
|
/* Build the address from the node details. */
|
|
/************************************************************************/
|
|
::BuildAddressFromNodeDetails(pszNodeAddress, &szAddress[0]);
|
|
|
|
// Set up password rubbish
|
|
if (! ::IsEmptyStringW(wszPassword))
|
|
{
|
|
pPassword_Challenge = & Password_Challenge;
|
|
Password_Challenge.password_challenge_type = GCC_PASSWORD_IN_THE_CLEAR;
|
|
hr = ::GetGCCFromUnicode(wszPassword,
|
|
&Password_Challenge.u.password_in_the_clear.numeric_string,
|
|
&Password_Challenge.u.password_in_the_clear.text_string);
|
|
}
|
|
|
|
if (NO_ERROR == hr)
|
|
{
|
|
LPWSTR pwszNodeName;
|
|
if (NULL != (pwszNodeName = ::GetNodeName()))
|
|
{
|
|
// Do not specify a numeric and text name when trying
|
|
// to join a conference because if a numeric name was
|
|
// autogenerated, rather than specified by the user,
|
|
// then it will not be correct on the node being joined.
|
|
// Consequently, remove the numeric name from the request
|
|
// and rediscover it, if needed, from the GCC_JOIN_CONFIRM indication
|
|
// (this is not currently done).
|
|
if ((m_ConfName.numeric_string != NULL) && (m_ConfName.text_string != NULL))
|
|
{
|
|
delete m_ConfName.numeric_string;
|
|
m_ConfName.numeric_string = NULL;
|
|
}
|
|
|
|
// If there is any user data to be sent
|
|
if (pUserDataInfoList)
|
|
{
|
|
// Add versioning data
|
|
if (NO_ERROR == ::GetUserData(g_nVersionRecords, g_ppVersionUserData, &g_csguidVerInfo, &nData, &pData))
|
|
{
|
|
pUserDataInfoList->AddUserData(&g_csguidVerInfo, nData, pData);
|
|
}
|
|
|
|
pUserDataInfoList->GetUserDataList(&nUserDataRecords,&ppInfoUserData);
|
|
}
|
|
else
|
|
{
|
|
ppInfoUserData = g_ppVersionUserData;
|
|
nUserDataRecords = g_nVersionRecords;
|
|
}
|
|
|
|
GCCrc = g_pIT120ControlSap->ConfJoinRequest(&m_ConfName,
|
|
NULL, // called_node_modifier
|
|
NULL, // calling_node_modifier
|
|
NULL, // convener_password
|
|
pPassword_Challenge, // password_challenge
|
|
pwszNodeName, // caller_identifier
|
|
NULL, // calling_address
|
|
&szAddress[0], // called_address
|
|
fSecure,
|
|
NULL, // domain_parameters
|
|
0, // number_of_network_addresses
|
|
NULL, // local_network_address_list
|
|
nUserDataRecords, // number_of_user_data_members
|
|
ppInfoUserData, // user_data_list
|
|
&connectionHandle, // connection_handle
|
|
&m_nConfID
|
|
);
|
|
delete pwszNodeName;
|
|
hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfJoinRequest, rc=%d", GCCrc));
|
|
TRACE_OUT(("Called address '%s'", &szAddress[0]));
|
|
if (NO_ERROR == hr)
|
|
{
|
|
m_eT120State = T120C_ST_PENDING_JOIN_CONFIRM;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = UI_RC_OUT_OF_MEMORY;
|
|
}
|
|
}
|
|
delete Password_Challenge.u.password_in_the_clear.numeric_string;
|
|
|
|
DebugExitHRESULT(DCRNCConference::T120Join, hr);
|
|
return hr;
|
|
}
|
|
|
|
/****************************************************************************/
|
|
/* StartLocal() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
HRESULT DCRNCConference::
|
|
T120StartLocal(BOOL fSecure)
|
|
{
|
|
GCCError GCCrc;
|
|
HRESULT hr;
|
|
ConnectionHandle hConnection = 0;
|
|
GCCConferencePrivileges priv = {1,1,1,1,1};
|
|
WCHAR pwszRDS[] = RDS_CONFERENCE_DESCRIPTOR;
|
|
|
|
DebugEntry(DCRNCConference::T120StartLocal);
|
|
|
|
/************************************************************************/
|
|
/* Call GCC_Conference_Create_Request and wait for the confirmation */
|
|
/* event. */
|
|
/************************************************************************/
|
|
GCCConfCreateRequest ccr;
|
|
::ZeroMemory(&ccr, sizeof(ccr));
|
|
ccr.Core.conference_name = &m_ConfName;
|
|
// ccr.Core.conference_modifier = NULL;
|
|
// ccr.Core.use_password_in_the_clear = 0;
|
|
// ccr.Core.conference_is_locked = 0;
|
|
ccr.Core.conference_is_listed = 1;
|
|
// ccr.Core.conference_is_conductible = 0;
|
|
ccr.Core.termination_method = GCC_MANUAL_TERMINATION_METHOD;
|
|
ccr.Core.conduct_privilege_list = &priv; // Conductor priveleges
|
|
ccr.Core.conduct_mode_privilege_list = &priv; // Member priveleges in conducted conference
|
|
ccr.Core.non_conduct_privilege_list = &priv; // Member priveleges in non-conducted conference
|
|
|
|
// ccr.Core.pwszConfDescriptor = NULL;
|
|
OSVERSIONINFO osvi;
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
if (FALSE == ::GetVersionEx (&osvi))
|
|
{
|
|
ERROR_OUT(("GetVersionEx() failed!"));
|
|
}
|
|
|
|
if ( VER_PLATFORM_WIN32_NT == osvi.dwPlatformId && g_bRDS)
|
|
{
|
|
ccr.Core.pwszConfDescriptor = pwszRDS;
|
|
}
|
|
// ccr.Core.pwszCallerID = NULL;
|
|
// ccr.Core.calling_address = NULL;
|
|
// ccr.Core.called_address = NULL;
|
|
// ccr.Core.domain_parameters = NULL;
|
|
// ccr.Core.number_of_network_addresses = 0;
|
|
// ccr.Core.network_address_list = NULL;
|
|
ccr.Core.connection_handle = &hConnection;
|
|
// ccr.convener_password = NULL;
|
|
// ccr.password = NULL;
|
|
// ccr.number_of_user_data_members = 0;
|
|
// ccr.user_data_list = NULL;
|
|
ccr.fSecure = fSecure;
|
|
|
|
GCCrc = g_pIT120ControlSap->ConfCreateRequest(&ccr, &m_nConfID);
|
|
|
|
hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfCreateRequest"));
|
|
TRACE_OUT(("LOCAL CONFERENCE"));
|
|
TRACE_OUT(("Connection handle %d", (UINT) hConnection));
|
|
|
|
/************************************************************************/
|
|
/* Map the GCC return code to a conference return code. */
|
|
/************************************************************************/
|
|
if (NO_ERROR == hr)
|
|
{
|
|
// Set the state.
|
|
m_eT120State = T120C_ST_PENDING_START_CONFIRM;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("GCC Error %d starting local conference", GCCrc));
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::T120StartLocal, hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// LONCHANC: please do not remove this chunk of code.
|
|
#ifdef ENABLE_START_REMOTE
|
|
/****************************************************************************/
|
|
/* StartRemote() - see erncgccc.hpp */
|
|
/****************************************************************************/
|
|
HRESULT DCRNCConference::
|
|
T120StartRemote ( LPSTR pszNodeAddress )
|
|
{
|
|
// Do not allow attempts to create T120 conferences on remote nodes.
|
|
// The code that was written to do this is left here in case someone
|
|
// wants to resurrect this functionality in the future.
|
|
GCCError GCCrc;
|
|
HRESULT hr;
|
|
ConnectionHandle connectionHandle = 0;
|
|
GCCConferencePrivileges priv = {1,1,1,1,1};
|
|
char szAddress[RNC_MAX_NODE_STRING_LEN];
|
|
|
|
DebugEntry(DCRNCConference::T120StartRemote);
|
|
|
|
/************************************************************************/
|
|
/* Build the address from the node details. */
|
|
/************************************************************************/
|
|
::BuildAddressFromNodeDetails(pszNodeAddress, &szAddress[0]);
|
|
|
|
/************************************************************************/
|
|
/* Call GCC_Conference_Create_Request and wait for the confirmation */
|
|
/* event. */
|
|
/************************************************************************/
|
|
TRACE_OUT(("Starting New Remote Conference..."));
|
|
|
|
/************************************************************************/
|
|
/* Call GCC_Conference_Create_Request and wait for the confirmation */
|
|
/* event. */
|
|
/************************************************************************/
|
|
GCCConfCreateRequest ccr;
|
|
::ZeroMemory(&ccr, sizeof(ccr));
|
|
ccr.Core.conference_name = &m_ConfName;
|
|
ccr.Core.conference_modifier = NULL;
|
|
// ccr.Core.use_password_in_the_clear = 0;
|
|
// ccr.Core.conference_is_locked = 0;
|
|
ccr.Core.conference_is_listed = 1;
|
|
ccr.Core.conference_is_conductible = 1;
|
|
ccr.Core.termination_method = GCC_AUTOMATIC_TERMINATION_METHOD;
|
|
ccr.Core.conduct_privilege_list = &priv; // Conductor priveleges
|
|
ccr.Core.conduct_mode_privilege_list = &priv; // Member priveleges in conducted conference
|
|
ccr.Core.non_conduct_privilege_list = &priv; // Member priveleges in non-conducted conference
|
|
// ccr.Core.pwszConfDescriptor = NULL;
|
|
// ccr.Core.pwszCallerID = NULL;
|
|
// ccr.Core.calling_address = NULL;
|
|
ccr.Core.called_address = &szAddress[0];
|
|
// ccr.Core.domain_parameters = NULL;
|
|
// ccr.Core.number_of_network_addresses = 0;
|
|
// ccr.Core.network_address_list = NULL;
|
|
ccr.Core.connection_handle = &connectionHandle;
|
|
// ccr.convener_password = NULL;
|
|
// ccr.password = NULL;
|
|
// ccr.number_of_user_data_members = 0;
|
|
// ccr.user_data_list = NULL;
|
|
|
|
GCCrc = g_pIT120ControlSap->ConfCreateRequest(&ccr, &m_nConfID);
|
|
|
|
hr = ::GetGCCRCDetails(GCCrc);
|
|
TRACE_OUT(("GCC call: g_pIT120ControlSap->ConfCreateRequest"));
|
|
TRACE_OUT(("Called address '%s'", &szAddress[0]));
|
|
TRACE_OUT(("Connection handle %d", connectionHandle));
|
|
|
|
/************************************************************************/
|
|
/* Map the GCC return code to a conference return code. */
|
|
/************************************************************************/
|
|
if (NO_ERROR != hr)
|
|
{
|
|
ERROR_OUT(("GCC Error %d starting local conference", GCCrc));
|
|
}
|
|
else
|
|
{
|
|
// Set the state.
|
|
m_eT120State = T120C_ST_PENDING_START_CONFIRM;
|
|
}
|
|
|
|
DebugExitHRESULT(DCRNCConference::T120StartRemote, hr);
|
|
return hr;
|
|
}
|
|
#endif // ENABLE_START_REMOTE
|
|
|
|
|
|
void LoadAnnouncePresenceParameters
|
|
(
|
|
GCCNodeType *nodeType,
|
|
GCCNodeProperties *nodeProperties,
|
|
LPWSTR *ppwszNodeName,
|
|
LPWSTR *ppwszSiteInformation
|
|
)
|
|
{
|
|
DebugEntry(LoadAnnouncePresenceParameters);
|
|
|
|
/* The following key does not currently exist.
|
|
* If we ever decide to use it, we should un-comment this call
|
|
* and following calls in this function, designed to access the
|
|
* registry entries under this key.
|
|
* Some of the rest of the registry calls are under #if 0, #else, #endif
|
|
* clauses.
|
|
*/
|
|
#if 0
|
|
RegEntry ConferenceKey(DATA_CONFERENCING_KEY, HKEY_LOCAL_MACHINE);
|
|
#endif // 0
|
|
|
|
// Get the type of node controller.
|
|
|
|
if (nodeType)
|
|
{
|
|
#if 0
|
|
*nodeType = ConferenceKey.GetNumber(REGVAL_NODE_CONTROLLER_MODE, GCC_MULTIPORT_TERMINAL);
|
|
#else // 0
|
|
*nodeType = GCC_MULTIPORT_TERMINAL;
|
|
#endif // 0
|
|
TRACE_OUT(("Node type %d", *nodeType));
|
|
}
|
|
|
|
// Load the node properties.
|
|
|
|
if (nodeProperties)
|
|
{
|
|
#if 0
|
|
*nodeProperties = ConferenceKey.GetNumber(REGVAL_NODE_CONTROLLER_PROPERTY,
|
|
GCC_NEITHER_PERIPHERAL_NOR_MANAGEMENT);
|
|
#else // 0
|
|
*nodeProperties = GCC_NEITHER_PERIPHERAL_NOR_MANAGEMENT;
|
|
#endif // 0
|
|
TRACE_OUT(("Node properties %d", *nodeProperties));
|
|
}
|
|
|
|
// Get site information.
|
|
// Ignore if no site info.
|
|
#if 0
|
|
if (ppwszSiteInformation)
|
|
{
|
|
*ppwszSiteInformation = ::AnsiToUnicode(ConferenceKey.GetString(REGVAL_NODE_CONTROLLER_SITE_INFO));
|
|
}
|
|
#endif // 0
|
|
|
|
if (ppwszNodeName)
|
|
{
|
|
// Rely upon GetNodeName returning NULL pointer if error.
|
|
// Note that successful if got this, so no need to free on error.
|
|
*ppwszNodeName = ::GetNodeName();
|
|
}
|
|
|
|
DebugExitVOID(LoadAnnouncePresenceParameters);
|
|
}
|
|
|
|
|
|
/****************************************************************************/
|
|
/* Build the address from the node details. */
|
|
/****************************************************************************/
|
|
void BuildAddressFromNodeDetails
|
|
(
|
|
LPSTR pszNodeAddress,
|
|
LPSTR pszDstAddress
|
|
)
|
|
{
|
|
DebugEntry(BuildAddressFromNodeDetails);
|
|
|
|
/************************************************************************/
|
|
/* GCC address take the form <transport type>:address. */
|
|
/************************************************************************/
|
|
TRACE_OUT(("BuildAddressFromNodeDetails:: TCP address '%s'", pszNodeAddress));
|
|
|
|
/************************************************************************/
|
|
/* Add the prefix for this transport type. */
|
|
/************************************************************************/
|
|
/************************************************************************/
|
|
/* Add the separator followed by the actual address. */
|
|
/************************************************************************/
|
|
::lstrcpyA(pszDstAddress, RNC_GCC_TRANSPORT_AND_SEPARATOR);
|
|
::lstrcatA(pszDstAddress, pszNodeAddress);
|
|
|
|
DebugExitVOID(BuildAddressFromNodeDetails);
|
|
}
|
|
|