|
|
/****************************************************************************/ /* */ /* 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 <service.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; GCCNodeType nodeType; GCCNodeProperties nodeProperties; BSTR nodeName; UINT nRecords; GCCUserData ** ppUserData;
DebugEntry(DCRNCConference::AnnouncePresence);
if (0 != m_nConfID) { // bugbug: handle errors that cause failure to announce presence.
/************************************************************************/ /* 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); }
SysFreeString(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 ) {
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)); }
InviteComplete(pInviteConf->connection_handle, ::GetGCCResultDetails(pInviteConf->result));
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;
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));
// 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 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. */ /************************************************************************/ BSTR szLocalName;
if (NULL != (szLocalName = ::GetNodeName())) { GCCrc = g_pIT120ControlSap->ConfInviteRequest( m_nConfID, szLocalName, // caller_identifier
NULL, // calling_address
&szAddress[0], // called_address
fSecure, // secure connection?
0, NULL, 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]));
SysFreeString(szLocalName); } 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) { BSTR szLocalName;
if (NULL != (szLocalName = ::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; }
GCCrc = g_pIT120ControlSap->ConfJoinRequest(&m_ConfName, NULL, // called_node_modifier
NULL, // calling_node_modifier
NULL, // convener_password
pPassword_Challenge, // password_challenge
szLocalName, // 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 ); SysFreeString(szLocalName); 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, BSTR *ppwszNodeName, LPWSTR *ppwszSiteInformation ) { DebugEntry(LoadAnnouncePresenceParameters);
// Get the type of node controller.
if (nodeType) { *nodeType = GCC_MULTIPORT_TERMINAL; }
// Load the node properties.
if (nodeProperties) { *nodeProperties = GCC_NEITHER_PERIPHERAL_NOR_MANAGEMENT; }
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); }
|