mirror of https://github.com/tongzx/nt5src
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.
3143 lines
83 KiB
3143 lines
83 KiB
#include "precomp.h"
|
|
#include "fsdiag.h"
|
|
DEBUG_FILEZONE(ZONE_T120_CONF_ROSTER);
|
|
/*
|
|
* crost.cpp
|
|
*
|
|
* Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
|
|
*
|
|
* Abstract:
|
|
* This is the implementation file for the Conference Roster Class.
|
|
* Instances of this class represent a single Conference Roster's
|
|
* information base. It encapsulates all the functionality required to
|
|
* maintain the information base which includes the ability to add new
|
|
* roster records, delete records and update records. It has the ability
|
|
* to convert its internal information base into a list of conference
|
|
* records that can be used in a GCC_ROSTER_UPDATE_INDICATION callback.
|
|
* It is also responsible for converting its internal information base
|
|
* into Conference Roster Update PDUs. Basically, this class is
|
|
* responsible for all operations that require direct access to the
|
|
* records contained in a Conference Roster.
|
|
*
|
|
* The Conference Roster class incorporates Rogue Wave list to hold the
|
|
* roster record information. Using iterators throughout the class makes
|
|
* it easy to quickly convert the information contained in the list into
|
|
* either a PDU or into a list of record pointers (for roster update
|
|
* indications back to the node controller).
|
|
*
|
|
* A Conference Roster object has the ability to serialize its roster data
|
|
* into a single contiguous memory block when it is required to send a
|
|
* message to the application interface. This serialization process is
|
|
* managed externally by the CConfRosterMsg class through calls
|
|
* to LockConferenceRoster(), UnLockConferenceRoster() and
|
|
* GetConfRoster(). When a conference roster is to be serialized, a
|
|
* call is made to LockConferenceRoster() which causes the CConfRoster
|
|
* object to increment an internal lock count and returns the number of
|
|
* bytes required to hold the complete roster update. The Conference
|
|
* Roster is then serialized into memory through a call to
|
|
* GetConfRoster(). The CConfRoster is then unlocked to allow
|
|
* it to be deleted when the free flag gets set through the
|
|
* FreeConferenceRoster() function. In the current implementation of GCC,
|
|
* FreeConferenceRoster() is not used since the CConfRosterMsg
|
|
* maintains the data used to deliver the message.
|
|
*
|
|
* Private Instance Variables:
|
|
* m_RecordList2
|
|
* This is the rogue wave list used to hold the pointers to all of the
|
|
* rogue wave records.
|
|
* m_nInstanceNumber
|
|
* This instance variable maintains an up to date instance #
|
|
* corresponding to the current conference roster.
|
|
* m_fNodesAdded
|
|
* Flag indicating if any node records have been added to the
|
|
* conference roster since the last reset.
|
|
* m_fNodesRemoved
|
|
* Flag indicating if any node records have been removed from the
|
|
* conference roster since the last reset.
|
|
* m_fRosterChanged
|
|
* Flag indicating if the roster has changed since the last reset.
|
|
* m_uidTopProvider
|
|
* The node id of the top provider in the conference.
|
|
* m_uidSuperiorNode
|
|
* This is the node id of this nodes superior node. For the top
|
|
* provider this is zero.
|
|
* m_cbDataMemorySize
|
|
* This is the number of bytes required to hold the data associated
|
|
* with a roster update message. This is calculated on a lock.
|
|
* m_NodeInformation
|
|
* Structure used to hold the roster update indication node information
|
|
* data in "PDU" form.
|
|
* m_fTopProvider
|
|
* Flag indicating if the node where this roster lives is the top
|
|
* provider.
|
|
* m_fLocalRoster
|
|
* Flag indicating if the roster data is associated with a local
|
|
* roster (maintaining intermediate node data) or global roster (
|
|
* (maintaining roster data for the whole conference).
|
|
* m_fMaintainPduBuffer
|
|
* Flag indicating if it is necessary for this roster object to
|
|
* maintain internal PDU data. Won't be necessary for global rosters
|
|
* at subordinate nodes.
|
|
* m_fPduFlushed
|
|
* Flag indicating if the PDU that currently exists has been flushed.
|
|
* m_pNodeRecordUpdateSet
|
|
* Pointer to internal PDU data.
|
|
*
|
|
* Caveats:
|
|
* None.
|
|
*
|
|
* Author:
|
|
* blp/jbo
|
|
*/
|
|
|
|
#include "ms_util.h"
|
|
#include "crost.h"
|
|
|
|
#define MAXIMUM_NODE_NAME_LENGTH 255
|
|
#define MAXIMUM_PARTICIPANT_NAME_LENGTH 255
|
|
#define MAXIMUM_SITE_INFORMATION_LENGTH 255
|
|
#define ALTERNATIVE_NODE_ID_LENGTH 2
|
|
|
|
/*
|
|
* CConfRoster ()
|
|
*
|
|
* Public Function Description:
|
|
* This is a constructor for the CConfRoster class. It initializes
|
|
* instance variables.
|
|
*
|
|
*/
|
|
CConfRoster::CConfRoster(UserID uidTopProvider, UserID uidSuperiorNode, UserID uidMyself,
|
|
BOOL is_top_provider, BOOL is_local_roster, BOOL maintain_pdu_buffer)
|
|
:
|
|
CRefCount(MAKE_STAMP_ID('C','R','s','t')),
|
|
m_fNodesAdded(FALSE),
|
|
m_fNodesRemoved(FALSE),
|
|
m_fRosterChanged(FALSE),
|
|
m_fTopProvider(is_top_provider),
|
|
m_fLocalRoster(is_local_roster),
|
|
m_fMaintainPduBuffer(maintain_pdu_buffer),
|
|
m_fPduFlushed(FALSE),
|
|
m_uidTopProvider(uidTopProvider),
|
|
m_uidSuperiorNode(uidSuperiorNode),
|
|
m_uidMyNodeID(uidMyself),
|
|
m_nInstanceNumber(0),
|
|
m_cbDataMemorySize(0),
|
|
m_RecordList2(DESIRED_MAX_NODE_RECORDS),
|
|
m_pNodeRecordUpdateSet(NULL)
|
|
{
|
|
m_NodeInformation.node_record_list.choice = NODE_NO_CHANGE_CHOSEN;
|
|
}
|
|
|
|
/*
|
|
* ~CConfRoster ()
|
|
*
|
|
* Public Function Description:
|
|
* This is the destructor for the CConfRoster. It performs any
|
|
* necessary cleanup.
|
|
*/
|
|
CConfRoster::~CConfRoster(void)
|
|
{
|
|
// Free up any left over PDU data.
|
|
if (m_fMaintainPduBuffer)
|
|
FreeRosterUpdateIndicationPDU ();
|
|
|
|
// Cleanup the Rogue Wave list of node records.
|
|
ClearRecordList();
|
|
}
|
|
|
|
|
|
/*
|
|
* Utilities that operate on roster update PDU structures.
|
|
*/
|
|
|
|
/*
|
|
* void FlushRosterUpdateIndicationPDU ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to retrieve a "RosterUpdateIndication" in the "PDU"
|
|
* form which is suitable for passing to the ASN.1 encoder. The "PDU"
|
|
* structure is built from a previous request to the conference roster.
|
|
*/
|
|
void CConfRoster::FlushRosterUpdateIndicationPDU(
|
|
PNodeInformation node_information)
|
|
{
|
|
/*
|
|
** If this roster has already been flushed we will NOT allow the same
|
|
** PDU to be flushed again. Instead we delete the previously flushed
|
|
** PDU and set the flag back to unflushed. If another flush comes in
|
|
** before a PDU is built no change will be passed back in the node
|
|
** information.
|
|
*/
|
|
if (m_fPduFlushed)
|
|
{
|
|
FreeRosterUpdateIndicationPDU ();
|
|
m_fPduFlushed = FALSE;
|
|
}
|
|
|
|
// First we copy all of the node record list information.
|
|
*node_information = m_NodeInformation;
|
|
|
|
/*
|
|
** Next we copy the relevent instance variables. Note that we must do
|
|
** this after we copy the node information so that these variables
|
|
** will not be copied over with garbage.
|
|
*/
|
|
node_information->roster_instance_number = (ASN1uint16_t)m_nInstanceNumber;
|
|
node_information->nodes_are_added = (ASN1bool_t)m_fNodesAdded;
|
|
node_information->nodes_are_removed = (ASN1bool_t)m_fNodesRemoved;
|
|
|
|
/*
|
|
** Setting this to true will cause the PDU data to be freed up the
|
|
** next time the roster object is entered insuring that new PDU
|
|
** data will be created.
|
|
*/
|
|
if (m_NodeInformation.node_record_list.choice != NODE_NO_CHANGE_CHOSEN)
|
|
m_fPduFlushed = TRUE;
|
|
}
|
|
|
|
/*
|
|
* GCCError BuildFullRefreshPDU ()
|
|
*
|
|
* Public Function Description
|
|
*
|
|
*/
|
|
GCCError CConfRoster::BuildFullRefreshPDU(void)
|
|
{
|
|
GCCError rc;
|
|
|
|
/*
|
|
** Free up the old PDU data here if it is being maintained and the
|
|
** PDU has been flushed. Note that we also set the PDU is flushed boolean
|
|
** back to FALSE so that the new PDU will be maintained until it is
|
|
** flushed.
|
|
*/
|
|
if (m_fPduFlushed)
|
|
{
|
|
FreeRosterUpdateIndicationPDU ();
|
|
m_fPduFlushed = FALSE;
|
|
}
|
|
|
|
rc = BuildRosterUpdateIndicationPDU (FULL_REFRESH, 0);
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError BuildRosterUpdateIndicationPDU ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to build a "RosterUpdateIndication" in the "PDU"
|
|
* form which is suitable for passing to the ASN.1 encoder. The "PDU"
|
|
* structure is built from the data maintained internally.
|
|
*/
|
|
GCCError CConfRoster::BuildRosterUpdateIndicationPDU(
|
|
CONF_ROSTER_UPDATE_TYPE update_type,
|
|
UserID node_id)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
|
|
if (m_fMaintainPduBuffer)
|
|
{
|
|
/*
|
|
** If "PDU" data has already been allocated then we free it up and
|
|
** rebuild the PDU structure. This ensures that the most up-to-date
|
|
** PDU is returned.
|
|
*/
|
|
if ((update_type == FULL_REFRESH) || m_fTopProvider)
|
|
{
|
|
if (m_NodeInformation.node_record_list.choice ==
|
|
NODE_RECORD_REFRESH_CHOSEN)
|
|
{
|
|
// Here we free the old set of refreshes.
|
|
FreeSetOfRefreshesPDU();
|
|
}
|
|
else if (m_NodeInformation.node_record_list.choice ==
|
|
NODE_RECORD_UPDATE_CHOSEN)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildRosterUpdateIndicationPDU:"
|
|
"ASSERTION: building refresh when update exists"));
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
rc = BuildSetOfRefreshesPDU();
|
|
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
m_NodeInformation.node_record_list.choice =
|
|
NODE_RECORD_REFRESH_CHOSEN;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_NodeInformation.node_record_list.choice ==
|
|
NODE_RECORD_REFRESH_CHOSEN)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildRosterUpdateIndicationPDU:"
|
|
"ASSERTION: building update when refresh exists"));
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
rc = BuildSetOfUpdatesPDU(node_id, update_type);
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
//
|
|
// LONCHANC: Commented out the following check because
|
|
// we can overrun the update, namely, two updates coming
|
|
// in side by side. It happens when shutting down a
|
|
// conference, we got two ConferenceAnnouncePresenceRequest.
|
|
// It is quite stupid in the node controller to call it
|
|
// twice unncessarily. The node controller should not call
|
|
// it at all when we know we are about to ending a conference.
|
|
//
|
|
// When two updates come in side by side, m_pNodeRecordUpdateSet
|
|
// will keep all the update information intact. New information
|
|
// can then be appended to the list.
|
|
//
|
|
|
|
// if (m_NodeInformation.node_record_list.choice ==
|
|
// NODE_NO_CHANGE_CHOSEN)
|
|
{
|
|
m_NodeInformation.node_record_list.u.node_record_update =
|
|
m_pNodeRecordUpdateSet;
|
|
m_NodeInformation.node_record_list.choice =
|
|
NODE_RECORD_UPDATE_CHOSEN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError BuildSetOfRefreshesPDU ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to retrieve the "SetOfRefreshes" portion of a
|
|
* "RosterUpdateIndication" in the "PDU" form. The internally maintained
|
|
* data is converted into the "PDU" form.
|
|
*
|
|
* Formal Parameters:
|
|
* None.
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_ALLOCATION_FAILURE - A resource error occured.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
GCCError CConfRoster::BuildSetOfRefreshesPDU(void)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
PSetOfNodeRecordRefreshes new_record_refresh;
|
|
PSetOfNodeRecordRefreshes old_record_refresh;
|
|
PNodeRecord node_record;
|
|
CONF_RECORD *lpRec;
|
|
UserID uid;
|
|
|
|
m_NodeInformation.node_record_list.u.node_record_refresh = NULL;
|
|
old_record_refresh = NULL; // This eliminates a compiler warning
|
|
|
|
m_RecordList2.Reset();
|
|
while (NULL != (lpRec = m_RecordList2.Iterate(&uid)))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
new_record_refresh = new SetOfNodeRecordRefreshes;
|
|
if (new_record_refresh == NULL)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: can't create set ofnode record refreshes"));
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
goto MyExit;
|
|
}
|
|
|
|
//
|
|
// Ensure everything here is clean.
|
|
// We may fail in the middle of building this node record.
|
|
//
|
|
::ZeroMemory(new_record_refresh, sizeof(SetOfNodeRecordRefreshes));
|
|
|
|
//
|
|
// Hook to the linked list.
|
|
//
|
|
if (m_NodeInformation.node_record_list.u.node_record_refresh == NULL)
|
|
{
|
|
m_NodeInformation.node_record_list.u.node_record_refresh = new_record_refresh;
|
|
}
|
|
else
|
|
{
|
|
old_record_refresh->next = new_record_refresh;
|
|
}
|
|
|
|
old_record_refresh = new_record_refresh;
|
|
|
|
/*
|
|
* Initialize the refresh "next" pointer to NULL and set the
|
|
* refresh value node ID equal to the internal node ID.
|
|
*/
|
|
new_record_refresh->next = NULL;
|
|
new_record_refresh->value.node_id = uid;
|
|
|
|
/*
|
|
* Fill in the "PDU" node record structure from the internal
|
|
* record structure.
|
|
*/
|
|
node_record = &(new_record_refresh->value.node_record);
|
|
node_record->bit_mask = 0;
|
|
|
|
/*
|
|
* Check to see if the superior node ID is present. If the value
|
|
* is zero, then the record is for the top provider node and the
|
|
* superior node ID does not need to be filled in.
|
|
*/
|
|
if (lpRec->superior_node != 0)
|
|
{
|
|
node_record->bit_mask |= SUPERIOR_NODE_PRESENT;
|
|
node_record->superior_node = lpRec->superior_node;
|
|
}
|
|
|
|
/*
|
|
* Fill in the node type and node properties which are always
|
|
* present.
|
|
*/
|
|
node_record->node_type = lpRec->node_type;
|
|
node_record->node_properties = lpRec->node_properties;
|
|
|
|
/*
|
|
** This roster object must not go out of scope while this
|
|
** update record is still in use!
|
|
*/
|
|
|
|
/*
|
|
* Fill in the node name if it is present.
|
|
*/
|
|
if (lpRec->pwszNodeName != NULL)
|
|
{
|
|
node_record->bit_mask |= NODE_NAME_PRESENT;
|
|
node_record->node_name.value = lpRec->pwszNodeName;
|
|
node_record->node_name.length = ::lstrlenW(lpRec->pwszNodeName);
|
|
}
|
|
|
|
/*
|
|
* Fill in the participants list if it is present.
|
|
*/
|
|
if (lpRec->participant_name_list != NULL)
|
|
{
|
|
node_record->bit_mask |= PARTICIPANTS_LIST_PRESENT;
|
|
|
|
rc = BuildParticipantsListPDU(uid, &(node_record->participants_list));
|
|
if (GCC_NO_ERROR != rc)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: can't build participant list, rc=%d", rc));
|
|
goto MyExit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fill in the site information if it is present.
|
|
*/
|
|
if (lpRec->pwszSiteInfo != NULL)
|
|
{
|
|
node_record->bit_mask |= SITE_INFORMATION_PRESENT;
|
|
node_record->site_information.value = lpRec->pwszSiteInfo;
|
|
node_record->site_information.length = ::lstrlenW(lpRec->pwszSiteInfo);
|
|
}
|
|
|
|
/*
|
|
* Fill in the network address if it is present.
|
|
*/
|
|
if ((lpRec->network_address_list != NULL) && (rc == GCC_NO_ERROR))
|
|
{
|
|
node_record->bit_mask |= RECORD_NET_ADDRESS_PRESENT;
|
|
|
|
rc = lpRec->network_address_list->GetNetworkAddressListPDU (
|
|
&(node_record->record_net_address));
|
|
if (GCC_NO_ERROR != rc)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: can't get network address list, rc=%d", rc));
|
|
goto MyExit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fill in the alternative node ID if it is present.
|
|
*/
|
|
if (lpRec->poszAltNodeID != NULL)
|
|
{
|
|
node_record->bit_mask |= ALTERNATIVE_NODE_ID_PRESENT;
|
|
|
|
node_record->alternative_node_id.choice = H243_NODE_ID_CHOSEN;
|
|
node_record->alternative_node_id.u.h243_node_id.length = lpRec->poszAltNodeID->length;
|
|
|
|
::CopyMemory(node_record->alternative_node_id.u.h243_node_id.value,
|
|
lpRec->poszAltNodeID->value,
|
|
node_record->alternative_node_id.u.h243_node_id.length);
|
|
}
|
|
|
|
/*
|
|
* Fill in the user data list if it is present.
|
|
*/
|
|
if ((lpRec->user_data_list != NULL) && (rc == GCC_NO_ERROR))
|
|
{
|
|
node_record->bit_mask |= RECORD_USER_DATA_PRESENT;
|
|
rc = lpRec->user_data_list->GetUserDataPDU (&(node_record->record_user_data));
|
|
}
|
|
}
|
|
|
|
MyExit:
|
|
|
|
if (rc != GCC_NO_ERROR)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: ASSERTION: Error occured: rc=%d", rc));
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError BuildSetOfUpdatesPDU ()
|
|
*
|
|
* Private Function Description
|
|
* This routine is used to retrieve the "SetOfUpdates" portion of a
|
|
* "RosterUpdateIndication" in the "PDU" form. The internally maintained
|
|
* data is converted into the "PDU" form.
|
|
*
|
|
* Formal Parameters:
|
|
* node_id - (i) Node ID of node record to be included in
|
|
* the update.
|
|
* update_type - (i) The type of update PDU to build (Add,
|
|
* Delete, Replace).
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_ALLOCATION_FAILURE - A resource error occured.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
GCCError CConfRoster::BuildSetOfUpdatesPDU(
|
|
UserID node_id,
|
|
CONF_ROSTER_UPDATE_TYPE update_type)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
PNodeRecord node_record = NULL;
|
|
CONF_RECORD *lpRec;
|
|
PSetOfNodeRecordUpdates pRecordUpdate, p;
|
|
BOOL fReplaceExistingOne = FALSE;
|
|
|
|
if (NULL != (lpRec = m_RecordList2.Find(node_id)))
|
|
{
|
|
//
|
|
// LONCHANC: Check to see if a update record already exists
|
|
// for this particular node ID. If so, we should replace
|
|
// the record.
|
|
//
|
|
for (p = m_pNodeRecordUpdateSet; NULL != p; p = p->next)
|
|
{
|
|
if (node_id == p->value.node_id)
|
|
{
|
|
pRecordUpdate = p;
|
|
fReplaceExistingOne = TRUE;
|
|
CleanUpdateRecordPDU(pRecordUpdate); // do not free the record itself
|
|
|
|
//
|
|
// Remember who is the next to restore because
|
|
// we will zero out the entire structure later.
|
|
//
|
|
p = pRecordUpdate->next;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (! fReplaceExistingOne)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
pRecordUpdate = new SetOfNodeRecordUpdates;
|
|
if (NULL == pRecordUpdate)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: can't create set of node record updates, rc=%d", rc));
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
goto MyExit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Ensure everything here is clean.
|
|
// We may fail in the middle of building this node record.
|
|
//
|
|
::ZeroMemory(pRecordUpdate, sizeof(SetOfNodeRecordUpdates));
|
|
|
|
if (! fReplaceExistingOne)
|
|
{
|
|
//
|
|
// Hook to the linked list.
|
|
//
|
|
if (m_pNodeRecordUpdateSet == NULL)
|
|
{
|
|
m_pNodeRecordUpdateSet = pRecordUpdate;
|
|
}
|
|
else
|
|
{
|
|
// append to the list
|
|
for (p = m_pNodeRecordUpdateSet; NULL != p->next; p = p->next)
|
|
;
|
|
p->next = pRecordUpdate;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == pRecordUpdate->next); // just zero out
|
|
// p could not NULL if the one being replaced is
|
|
// the last one in the list.
|
|
pRecordUpdate->next = p; // restore
|
|
}
|
|
|
|
/*
|
|
* Initialize the update "next" pointer to NULL and set the
|
|
* update value node ID equal to the node ID passed in.
|
|
*/
|
|
// pRecordUpdate->next = NULL; // struct already zeroed out
|
|
pRecordUpdate->value.node_id = node_id;
|
|
|
|
if (update_type == ADD_RECORD)
|
|
{
|
|
pRecordUpdate->value.node_update.choice = NODE_ADD_RECORD_CHOSEN;
|
|
node_record = &pRecordUpdate->value.node_update.u.node_add_record;
|
|
}
|
|
else if (update_type == REPLACE_RECORD)
|
|
{
|
|
pRecordUpdate->value.node_update.choice = NODE_REPLACE_RECORD_CHOSEN;
|
|
node_record = &pRecordUpdate->value.node_update.u.node_replace_record;
|
|
}
|
|
else
|
|
{
|
|
pRecordUpdate->value.node_update.choice = NODE_REMOVE_RECORD_CHOSEN;
|
|
}
|
|
|
|
if (node_record != NULL)
|
|
{
|
|
// node_record->bit_mask = 0; // struct already zeroed out
|
|
|
|
/*
|
|
* Check to see if the superior node ID is present. If the
|
|
* value is zero, then the record is for the top provider node
|
|
* and the superior node ID does not need to be filled in.
|
|
*/
|
|
if (lpRec->superior_node != 0)
|
|
{
|
|
node_record->bit_mask |= SUPERIOR_NODE_PRESENT;
|
|
node_record->superior_node = lpRec->superior_node;
|
|
}
|
|
|
|
/*
|
|
* Fill in the node type and node properties which are always
|
|
* present.
|
|
*/
|
|
node_record->node_type = lpRec->node_type;
|
|
node_record->node_properties = lpRec->node_properties;
|
|
|
|
/*
|
|
** This roster object must not go out of scope while this
|
|
** update record is still in use!
|
|
*/
|
|
|
|
/*
|
|
* Fill in the node name if it is present.
|
|
*/
|
|
if (lpRec->pwszNodeName != NULL)
|
|
{
|
|
node_record->bit_mask |= NODE_NAME_PRESENT;
|
|
node_record->node_name.value = lpRec->pwszNodeName;
|
|
node_record->node_name.length = ::lstrlenW(lpRec->pwszNodeName);
|
|
}
|
|
|
|
/*
|
|
* Fill in the participants list if it is present.
|
|
*/
|
|
if (lpRec->participant_name_list != NULL)
|
|
{
|
|
node_record->bit_mask |= PARTICIPANTS_LIST_PRESENT;
|
|
|
|
rc = BuildParticipantsListPDU (node_id,
|
|
&(node_record->participants_list));
|
|
if (GCC_NO_ERROR != rc)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: can't build participant list, rc=%d", rc));
|
|
goto MyExit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fill in the site information if it is present.
|
|
*/
|
|
if (lpRec->pwszSiteInfo != NULL)
|
|
{
|
|
node_record->bit_mask |= SITE_INFORMATION_PRESENT;
|
|
node_record->site_information.value = lpRec->pwszSiteInfo;
|
|
node_record->site_information.length = ::lstrlenW(lpRec->pwszSiteInfo);
|
|
}
|
|
|
|
/*
|
|
* Fill in the network address if it is present.
|
|
*/
|
|
if ((lpRec->network_address_list != NULL) && (rc == GCC_NO_ERROR))
|
|
{
|
|
node_record->bit_mask |= RECORD_NET_ADDRESS_PRESENT;
|
|
|
|
rc = lpRec->network_address_list->GetNetworkAddressListPDU (
|
|
&(node_record->record_net_address));
|
|
if (GCC_NO_ERROR != rc)
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: can't get network address list, rc=%d", rc));
|
|
goto MyExit;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Fill in the alternative node ID if it is present.
|
|
*/
|
|
if (lpRec->poszAltNodeID != NULL)
|
|
{
|
|
node_record->bit_mask |= ALTERNATIVE_NODE_ID_PRESENT;
|
|
|
|
node_record->alternative_node_id.choice = H243_NODE_ID_CHOSEN;
|
|
node_record->alternative_node_id.u.h243_node_id.length = lpRec->poszAltNodeID->length;
|
|
|
|
::CopyMemory(node_record->alternative_node_id.u.h243_node_id.value,
|
|
lpRec->poszAltNodeID->value,
|
|
node_record->alternative_node_id.u.h243_node_id.length);
|
|
}
|
|
|
|
/*
|
|
* Fill in the user data list if it is present.
|
|
*/
|
|
if (lpRec->user_data_list != NULL)
|
|
{
|
|
node_record->bit_mask |= RECORD_USER_DATA_PRESENT;
|
|
|
|
rc = lpRec->user_data_list->GetUserDataPDU (&(node_record->record_user_data));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: invalid param"));
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
MyExit:
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError BuildParticipantsListPDU ()
|
|
*
|
|
* Public Function Description
|
|
* This routine is used to retrieve the "ParticipantList" portion of a
|
|
* "RosterUpdateIndication" in the "PDU" form. The internally maintained
|
|
* data is converted into the "PDU" form.
|
|
*
|
|
* Formal Parameters:
|
|
* node_id - (i) Node ID of node record to get the
|
|
* participant list from.
|
|
* participants_list - (o) This is a pointer to the set of participant
|
|
* list PDU structures to be filled in by this
|
|
* routine.
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_ALLOCATION_FAILURE - A resource error occured.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
GCCError CConfRoster::BuildParticipantsListPDU(
|
|
UserID node_id,
|
|
PParticipantsList * participants_list)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
PParticipantsList new_participants_list;
|
|
PParticipantsList old_participants_list;
|
|
CONF_RECORD *lpRec;
|
|
|
|
if (NULL != (lpRec = m_RecordList2.Find(node_id)))
|
|
{
|
|
LPWSTR PUstring;
|
|
|
|
*participants_list = NULL;
|
|
old_participants_list = NULL;
|
|
|
|
lpRec->participant_name_list->Reset();
|
|
while (NULL != (PUstring = lpRec->participant_name_list->Iterate()))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
new_participants_list = new ParticipantsList;
|
|
if (new_participants_list == NULL)
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
FreeParticipantsListPDU (*participants_list);
|
|
break;
|
|
}
|
|
|
|
if (*participants_list == NULL)
|
|
*participants_list = new_participants_list;
|
|
else
|
|
old_participants_list->next = new_participants_list;
|
|
|
|
/*
|
|
* Save this pointer so that it's "next" pointer can be filled in
|
|
* by the line above on the next pass through.
|
|
*/
|
|
old_participants_list = new_participants_list;
|
|
|
|
/*
|
|
* Initialize the current "next" pointer to NULL in case this is
|
|
* the last time through the loop.
|
|
*/
|
|
new_participants_list->next = NULL;
|
|
|
|
/*
|
|
* Finally, put the participant list info. in the structure.
|
|
*/
|
|
new_participants_list->value.value = PUstring;
|
|
new_participants_list->value.length = ::lstrlenW(PUstring);
|
|
}
|
|
}
|
|
else
|
|
rc = GCC_INVALID_PARAMETER;
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* These routines are used to free up a roster update indication PDU.
|
|
*/
|
|
|
|
|
|
/*
|
|
* void FreeRosterUpdateIndicationPDU ()
|
|
*
|
|
* Private Function Description
|
|
* This routine is responsible for freeing up all the data associated
|
|
* with the PDU. This routine should be called each time a PDU is
|
|
* obtained through the GetRosterUpdateIndicationPDU () routine.
|
|
*
|
|
* Formal Parameters:
|
|
* None.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::FreeRosterUpdateIndicationPDU(void)
|
|
{
|
|
if (m_NodeInformation.node_record_list.choice == NODE_RECORD_REFRESH_CHOSEN)
|
|
{
|
|
FreeSetOfRefreshesPDU ();
|
|
}
|
|
else if (m_NodeInformation.node_record_list.choice == NODE_RECORD_UPDATE_CHOSEN)
|
|
{
|
|
FreeSetOfUpdatesPDU ();
|
|
}
|
|
|
|
m_NodeInformation.node_record_list.choice = NODE_NO_CHANGE_CHOSEN;
|
|
m_pNodeRecordUpdateSet = NULL;
|
|
}
|
|
|
|
|
|
/*
|
|
* void FreeSetOfRefreshesPDU ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to free up any data allocated to construct the
|
|
* "PDU" form of the "SetOfRefreshes" portion of the RosterUpdateIndication
|
|
* "PDU" structure.
|
|
*
|
|
* Formal Parameters:
|
|
* None.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::FreeSetOfRefreshesPDU(void)
|
|
{
|
|
PSetOfNodeRecordRefreshes pCurr, pNext;
|
|
|
|
for (pCurr = m_NodeInformation.node_record_list.u.node_record_refresh;
|
|
NULL != pCurr;
|
|
pCurr = pNext)
|
|
{
|
|
pNext = pCurr->next;
|
|
if (pCurr->value.node_record.bit_mask & PARTICIPANTS_LIST_PRESENT)
|
|
{
|
|
FreeParticipantsListPDU(pCurr->value.node_record.participants_list);
|
|
}
|
|
delete pCurr;
|
|
}
|
|
m_NodeInformation.node_record_list.u.node_record_refresh = NULL;
|
|
|
|
m_RecordList2.CleanList();
|
|
}
|
|
|
|
|
|
/*
|
|
* void FreeSetOfUpdatesPDU ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to free up any data allocated to construct the
|
|
* "PDU" form of the "SetOfUpdates" portion of the RosterUpdateIndication
|
|
* "PDU" structure.
|
|
*
|
|
* Formal Parameters:
|
|
* None.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::
|
|
CleanUpdateRecordPDU ( PSetOfNodeRecordUpdates pCurr)
|
|
{
|
|
/*
|
|
* Check to see if the update is an "Add" or a "Replace".
|
|
*/
|
|
if (pCurr->value.node_update.choice == NODE_ADD_RECORD_CHOSEN)
|
|
{
|
|
/*
|
|
* Free the participants list memory if any exists.
|
|
*/
|
|
if (pCurr->value.node_update.u.node_add_record.bit_mask & PARTICIPANTS_LIST_PRESENT)
|
|
{
|
|
FreeParticipantsListPDU(pCurr->value.node_update.u.node_add_record.participants_list);
|
|
}
|
|
}
|
|
else if (pCurr->value.node_update.choice == NODE_REPLACE_RECORD_CHOSEN)
|
|
{
|
|
/*
|
|
* Free the participants list memory if any exists.
|
|
*/
|
|
if (pCurr->value.node_update.u.node_replace_record.bit_mask & PARTICIPANTS_LIST_PRESENT)
|
|
{
|
|
FreeParticipantsListPDU(pCurr->value.node_update.u.node_replace_record.participants_list);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CConfRoster::FreeSetOfUpdatesPDU(void)
|
|
{
|
|
PSetOfNodeRecordUpdates pCurr, pNext;
|
|
//PSetOfNodeRecordUpdates current_record_update;
|
|
|
|
for (pCurr = m_NodeInformation.node_record_list.u.node_record_update;
|
|
NULL != pCurr;
|
|
pCurr = pNext)
|
|
{
|
|
pNext = pCurr->next;
|
|
CleanUpdateRecordPDU(pCurr);
|
|
delete pCurr;
|
|
}
|
|
m_NodeInformation.node_record_list.u.node_record_update = NULL;
|
|
|
|
m_RecordList2.CleanList();
|
|
}
|
|
|
|
|
|
void CConfRecordList2::CleanList(void)
|
|
{
|
|
CONF_RECORD *lpRec;
|
|
/*
|
|
* Iterate through the internal list of Record structures telling each
|
|
* CUserDataListContainer object in the Record to free up it's PDU data.
|
|
*/
|
|
Reset();
|
|
while (NULL != (lpRec = Iterate()))
|
|
{
|
|
if (lpRec->user_data_list != NULL)
|
|
{
|
|
lpRec->user_data_list->FreeUserDataListPDU();
|
|
}
|
|
|
|
if (lpRec->network_address_list != NULL)
|
|
{
|
|
lpRec->network_address_list->FreeNetworkAddressListPDU();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* void FreeParticipantsListPDU ()
|
|
*
|
|
* Private Function Description
|
|
* This routine is used to free up any data allocated to construct the
|
|
* "PDU" form of the "ParticipantList" portion of the
|
|
* RosterUpdateIndication "PDU" structure.
|
|
*
|
|
* Formal Parameters:
|
|
* participants_list - (i/o) This is the participant list PDU
|
|
* to free up.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::FreeParticipantsListPDU(
|
|
PParticipantsList participants_list)
|
|
{
|
|
PParticipantsList pCurr, pNext;
|
|
|
|
for (pCurr = participants_list; NULL != pCurr; pCurr = pNext)
|
|
{
|
|
pNext = pCurr->next;
|
|
delete pCurr;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* These routines process roster update indication PDUs.
|
|
*/
|
|
|
|
|
|
/*
|
|
* GCCError ProcessRosterUpdateIndicationPDU ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used process a RosterUpdateIndication PDU by saving the
|
|
* data in the internal format.
|
|
*/
|
|
GCCError CConfRoster::ProcessRosterUpdateIndicationPDU(
|
|
PNodeInformation node_information,
|
|
UserID sender_id)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
CUidList node_delete_list;
|
|
|
|
/*
|
|
** Free up the old PDU data here if it is being maintained and the
|
|
** PDU has been flushed. Note that we also set the PDU is flushed boolean
|
|
** back to FALSE so that the new PDU will be maintained until it is
|
|
** flushed.
|
|
*/
|
|
if (m_fPduFlushed)
|
|
{
|
|
FreeRosterUpdateIndicationPDU ();
|
|
m_fPduFlushed = FALSE;
|
|
}
|
|
|
|
/*
|
|
** If this is a conference roster update and refresh is chosen we must
|
|
** clear out the entire list and rebuild it.
|
|
*/
|
|
if (node_information->node_record_list.choice == NODE_RECORD_REFRESH_CHOSEN)
|
|
{
|
|
m_fRosterChanged = TRUE;
|
|
|
|
/*
|
|
** If this refresh came from the top provider we must clear out the
|
|
** entire roster to prepare for the new roster list. If it was NOT
|
|
** sent by the Top Provider, we must determine which sub tree is
|
|
** affected and clear out this particular sub tree.
|
|
*/
|
|
if (sender_id == m_uidTopProvider)
|
|
{
|
|
ClearRecordList();
|
|
}
|
|
else
|
|
{
|
|
rc = GetNodeSubTree(sender_id, &node_delete_list);
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
UserID uid;
|
|
|
|
// Clear out the affected nodes
|
|
node_delete_list.Reset();
|
|
while (GCC_INVALID_UID != (uid = node_delete_list.Iterate()))
|
|
{
|
|
DeleteRecord(uid);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Increment the instance number if this node is the top provider or
|
|
** a local roster otherwise get the instance number from the PDU.
|
|
*/
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
if ((m_fTopProvider) || (m_fLocalRoster))
|
|
{
|
|
m_nInstanceNumber++;
|
|
}
|
|
else
|
|
{
|
|
m_nInstanceNumber = node_information->roster_instance_number;
|
|
}
|
|
|
|
if (m_fNodesAdded == FALSE)
|
|
{
|
|
m_fNodesAdded = node_information->nodes_are_added;
|
|
}
|
|
|
|
if (m_fNodesRemoved == FALSE)
|
|
{
|
|
m_fNodesRemoved = node_information->nodes_are_removed;
|
|
}
|
|
|
|
rc = ProcessSetOfRefreshesPDU(node_information->node_record_list.u.node_record_refresh);
|
|
}
|
|
}
|
|
else if (node_information->node_record_list.choice == NODE_RECORD_UPDATE_CHOSEN)
|
|
{
|
|
m_fRosterChanged = TRUE;
|
|
|
|
/*
|
|
** Increment the instance number if this node is the top provider or
|
|
** a local roster otherwise get the instance number from the PDU.
|
|
*/
|
|
if ((m_fTopProvider) || (m_fLocalRoster))
|
|
{
|
|
m_nInstanceNumber++;
|
|
}
|
|
else
|
|
{
|
|
m_nInstanceNumber = node_information->roster_instance_number;
|
|
}
|
|
|
|
if (m_fNodesAdded == FALSE)
|
|
{
|
|
m_fNodesAdded = node_information->nodes_are_added;
|
|
}
|
|
|
|
if (m_fNodesRemoved == FALSE)
|
|
{
|
|
m_fNodesRemoved = node_information->nodes_are_removed;
|
|
}
|
|
|
|
rc = ProcessSetOfUpdatesPDU(node_information->node_record_list.u.node_record_update);
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError ProcessSetOfRefreshesPDU ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used process the SetOfRefreshes portion of a
|
|
* RosterUpdateIndication PDU by saving the data in the internal format.
|
|
*
|
|
* Formal Parameters:
|
|
* record_refresh - (i) Refresh PDU data to process.
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_ALLOCATION_FAILURE - A resource error occured.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
GCCError CConfRoster::ProcessSetOfRefreshesPDU(
|
|
PSetOfNodeRecordRefreshes record_refresh)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
PSetOfNodeRecordRefreshes current_record_refresh;
|
|
UserID node_id;
|
|
CONF_RECORD *internal_record = NULL;
|
|
|
|
if (record_refresh != NULL)
|
|
{
|
|
current_record_refresh = record_refresh;
|
|
while ((current_record_refresh != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
node_id = (UserID)current_record_refresh->value.node_id;
|
|
|
|
/*
|
|
* Create and fill in the new internal conference record.
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record = new CONF_RECORD;
|
|
if (internal_record == NULL)
|
|
{
|
|
ERROR_OUT(("CConfRoster::ProcessSetOfRefreshesPDU: Error "
|
|
"creating new Record"));
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Fill in the superior node ID if it is present.
|
|
*/
|
|
if (current_record_refresh->value.node_record.bit_mask &
|
|
SUPERIOR_NODE_PRESENT)
|
|
{
|
|
internal_record->superior_node = current_record_refresh->
|
|
value.node_record.superior_node;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0 == internal_record->superior_node);
|
|
}
|
|
|
|
/*
|
|
* Fill in the node type and node properties which are always
|
|
* present.
|
|
*/
|
|
internal_record->node_type = current_record_refresh->
|
|
value.node_record.node_type;
|
|
|
|
internal_record->node_properties = current_record_refresh->
|
|
value.node_record.node_properties;
|
|
|
|
/*
|
|
* Fill in the node name if it is present.
|
|
*/
|
|
if (current_record_refresh->value.node_record.bit_mask & NODE_NAME_PRESENT)
|
|
{
|
|
if (NULL == (internal_record->pwszNodeName = ::My_strdupW2(
|
|
current_record_refresh->value.node_record.node_name.length,
|
|
current_record_refresh->value.node_record.node_name.value)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->pwszNodeName);
|
|
}
|
|
|
|
/*
|
|
* Fill in the participants name list if it is present.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(current_record_refresh->value.node_record.bit_mask &
|
|
PARTICIPANTS_LIST_PRESENT))
|
|
{
|
|
rc = ProcessParticipantsListPDU (
|
|
current_record_refresh->
|
|
value.node_record.participants_list,
|
|
internal_record);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->participant_name_list);
|
|
}
|
|
|
|
/*
|
|
* Fill in the site information if it is present.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(current_record_refresh->value.node_record.bit_mask & SITE_INFORMATION_PRESENT))
|
|
{
|
|
if (NULL == (internal_record->pwszSiteInfo = ::My_strdupW2(
|
|
current_record_refresh->value.node_record.site_information.length,
|
|
current_record_refresh->value.node_record.site_information.value)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->pwszSiteInfo);
|
|
}
|
|
|
|
/*
|
|
* Fill in the network address if it is present. The network
|
|
* address is maintained internally as a CNetAddrListContainer object
|
|
* which is constructed here from the PDU "SetOfNetworkAddresses"
|
|
* structure. If an error occurs in constructing the object, set
|
|
* the Record's network address list pointer to NULL.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(current_record_refresh->value.node_record.bit_mask &
|
|
RECORD_NET_ADDRESS_PRESENT))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->network_address_list = new CNetAddrListContainer(
|
|
current_record_refresh->value.node_record.record_net_address,
|
|
&rc);
|
|
if ((internal_record->network_address_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->network_address_list);
|
|
}
|
|
|
|
/*
|
|
* Fill in the alternative node ID if it is present.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(current_record_refresh->value.node_record.bit_mask &
|
|
ALTERNATIVE_NODE_ID_PRESENT))
|
|
{
|
|
if (NULL == (internal_record->poszAltNodeID = ::My_strdupO2(
|
|
current_record_refresh->value.node_record.
|
|
alternative_node_id.u.h243_node_id.value,
|
|
current_record_refresh->value.node_record.
|
|
alternative_node_id.u.h243_node_id.length)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->poszAltNodeID);
|
|
}
|
|
|
|
/*
|
|
* Fill in the user data if it is present. The user data is
|
|
* maintained internally as a CUserDataListContainer object which is
|
|
* constructed here from the PDU "SetOfUserData" structure. If an
|
|
* error occurs in constructing the object, set the Record's user
|
|
* data pointer to NULL.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(current_record_refresh->value.node_record.bit_mask &
|
|
RECORD_USER_DATA_PRESENT))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->user_data_list = new CUserDataListContainer(
|
|
current_record_refresh->value.node_record.record_user_data,
|
|
&rc);
|
|
if ((internal_record->user_data_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->user_data_list);
|
|
}
|
|
|
|
/*
|
|
* If the Record was successfully filled in, add it to the internal
|
|
* Rogue Wave list.
|
|
*/
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
m_RecordList2.Append(node_id, internal_record);
|
|
current_record_refresh = current_record_refresh->next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Build a full refresh PDU here if no errors occured while processing
|
|
** the refresh PDU.
|
|
*/
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
rc = BuildRosterUpdateIndicationPDU(FULL_REFRESH, 0);
|
|
}
|
|
else
|
|
{
|
|
delete internal_record;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError ProcessSetOfUpdatesPDU ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used process the SetOfUpdates portion of a
|
|
* RosterUpdateIndication PDU by saving the data in the internal format.
|
|
*
|
|
* Formal Parameters:
|
|
* record_update - (i) Update PDU data to process.
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_ALLOCATION_FAILURE - A resource error occured.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
GCCError CConfRoster::ProcessSetOfUpdatesPDU(
|
|
PSetOfNodeRecordUpdates record_update)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
PSetOfNodeRecordUpdates current_record_update;
|
|
UserID node_id;
|
|
PNodeRecord node_record;
|
|
CONF_RECORD *internal_record;
|
|
CONF_ROSTER_UPDATE_TYPE update_type;
|
|
|
|
if (record_update != NULL)
|
|
{
|
|
current_record_update = record_update;
|
|
|
|
while ((current_record_update != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
internal_record = NULL;
|
|
node_id = (UserID)current_record_update->value.node_id;
|
|
|
|
// Create and fill in the new conference record.
|
|
if (current_record_update->value.node_update.choice ==
|
|
NODE_ADD_RECORD_CHOSEN)
|
|
{
|
|
// Add the record.
|
|
if (! m_RecordList2.Find(node_id))
|
|
{
|
|
node_record = ¤t_record_update->value.node_update.u.node_add_record;
|
|
update_type = ADD_RECORD;
|
|
}
|
|
else
|
|
{
|
|
node_record = NULL;
|
|
ERROR_OUT(("CConfRoster: ProcessSetOfUpdatesPDU: can't add record"));
|
|
}
|
|
}
|
|
else if (current_record_update->value.node_update.choice ==
|
|
NODE_REPLACE_RECORD_CHOSEN)
|
|
{
|
|
// Replace the record.
|
|
if (m_RecordList2.Find(node_id))
|
|
{
|
|
DeleteRecord (node_id);
|
|
node_record = ¤t_record_update->
|
|
value.node_update.u.node_replace_record;
|
|
update_type = REPLACE_RECORD;
|
|
}
|
|
else
|
|
{
|
|
node_record = NULL;
|
|
WARNING_OUT(("CConfRoster: ProcessSetOfUpdatesPDU: "
|
|
"ASSERTION: Replace record failed"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Remove the record.
|
|
if (m_RecordList2.Find(node_id))
|
|
{
|
|
DeleteRecord (node_id);
|
|
update_type = DELETE_RECORD;
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CConfRoster: ProcessSetOfUpdatesPDU: can't delete record"));
|
|
}
|
|
|
|
node_record = NULL;
|
|
}
|
|
|
|
/*
|
|
** Process the conference record if one exists. Create a new
|
|
** node record to be filled in and added to the internal record
|
|
** list.
|
|
*/
|
|
if (node_record != NULL)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record = new CONF_RECORD;
|
|
if (internal_record == NULL)
|
|
{
|
|
ERROR_OUT(("CConfRoster::ProcessSetOfUpdatesPDU: can't create new record"));
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
break;
|
|
}
|
|
|
|
// Fill in the superior node ID if it is present.
|
|
if (node_record->bit_mask & SUPERIOR_NODE_PRESENT)
|
|
{
|
|
internal_record->superior_node = node_record->superior_node;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(0 == internal_record->superior_node);
|
|
}
|
|
|
|
/*
|
|
** Fill in the node type and node properties which are always
|
|
** present.
|
|
*/
|
|
internal_record->node_type = node_record->node_type;
|
|
internal_record->node_properties = node_record->node_properties;
|
|
|
|
// Fill in the node name if it is present.
|
|
if (node_record->bit_mask & NODE_NAME_PRESENT)
|
|
{
|
|
if (NULL == (internal_record->pwszNodeName = ::My_strdupW2(
|
|
node_record->node_name.length,
|
|
node_record->node_name.value)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->pwszNodeName);
|
|
}
|
|
|
|
// Fill in the participants list if it is present.
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(node_record->bit_mask & PARTICIPANTS_LIST_PRESENT))
|
|
{
|
|
rc = ProcessParticipantsListPDU(node_record->participants_list,
|
|
internal_record);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->participant_name_list);
|
|
}
|
|
|
|
// Fill in the site information if it is present.
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(node_record->bit_mask & SITE_INFORMATION_PRESENT))
|
|
{
|
|
if (NULL == (internal_record->pwszSiteInfo = ::My_strdupW2(
|
|
node_record->site_information.length,
|
|
node_record->site_information.value)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->pwszSiteInfo);
|
|
}
|
|
|
|
/*
|
|
** Fill in the network address if it is present. The network
|
|
** address is maintained internally as a CNetAddrListContainer
|
|
** object which is constructed here from the PDU
|
|
** "SetOfNetworkAddresses" structure. If an error occurs
|
|
** in constructing the object, set the Record's network address
|
|
** list pointer to NULL.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(node_record->bit_mask & RECORD_NET_ADDRESS_PRESENT))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->network_address_list =
|
|
new CNetAddrListContainer(node_record->record_net_address, &rc);
|
|
if ((internal_record->network_address_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->network_address_list);
|
|
}
|
|
|
|
/*
|
|
* Fill in the alternative node ID if it is present.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(node_record->bit_mask & ALTERNATIVE_NODE_ID_PRESENT))
|
|
{
|
|
if (NULL == (internal_record->poszAltNodeID = ::My_strdupO2(
|
|
node_record->alternative_node_id.u.h243_node_id.value,
|
|
node_record->alternative_node_id.u.h243_node_id.length)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->poszAltNodeID);
|
|
}
|
|
|
|
/*
|
|
* Fill in the user data if it is present. The user data is
|
|
* maintained internally as a CUserDataListContainer object which is
|
|
* constructed here from the PDU "SetOfUserData" structure. If
|
|
* an error occurs in constructing the object, set the Record's
|
|
* user data pointer to NULL.
|
|
*/
|
|
if ((rc == GCC_NO_ERROR) &&
|
|
(node_record->bit_mask & RECORD_USER_DATA_PRESENT))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->user_data_list = new CUserDataListContainer(
|
|
node_record->record_user_data,
|
|
&rc);
|
|
if ((internal_record->user_data_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->user_data_list);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Here we add this update to our PDU and jump to the next update
|
|
** in the PDU currently being processed.
|
|
*/
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
/*
|
|
** If the Record was successfully filled in, add it to the
|
|
** internal Rogue Wave list.
|
|
*/
|
|
if (internal_record != NULL)
|
|
{
|
|
m_RecordList2.Append(node_id, internal_record);
|
|
}
|
|
|
|
// Build the PDU from the above update.
|
|
rc = BuildRosterUpdateIndicationPDU(update_type, node_id);
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
current_record_update = current_record_update->next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete internal_record;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError ProcessParticipantsListPDU ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used process the ParticipantsList portion of an
|
|
* incoming RosterUpdateIndication PDU by saving the data in the internal
|
|
* format.
|
|
*
|
|
* Formal Parameters:
|
|
* participants_list - (i) Participant List PDU data to process.
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_ALLOCATION_FAILURE - A resource error occured.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
GCCError CConfRoster::ProcessParticipantsListPDU (
|
|
PParticipantsList participants_list,
|
|
CONF_RECORD *node_record)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
PParticipantsList pCurr;
|
|
LPWSTR pwszParticipantName;
|
|
|
|
/*
|
|
* Clear the current list.
|
|
*/
|
|
DBG_SAVE_FILE_LINE
|
|
node_record->participant_name_list = new CParticipantNameList;
|
|
|
|
if (node_record->participant_name_list == NULL)
|
|
return (GCC_ALLOCATION_FAILURE);
|
|
|
|
for (pCurr = participants_list; NULL != pCurr; pCurr = pCurr->next)
|
|
{
|
|
if (NULL != (pwszParticipantName = ::My_strdupW2(pCurr->value.length, pCurr->value.value)))
|
|
{
|
|
(node_record->participant_name_list)->Append(pwszParticipantName);
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* Utilities that operate on conference records.
|
|
*/
|
|
|
|
/*
|
|
* UINT LockConferenceRoster ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used "lock" the CConfRoster data in the "API"
|
|
* form. The "API" version of the CConfRoster is built from the
|
|
* internally maintained data.
|
|
*/
|
|
UINT CConfRoster::LockConferenceRoster(void)
|
|
{
|
|
CONF_RECORD *internal_node_record;
|
|
|
|
if (Lock() == 1)
|
|
{
|
|
//CONF_RECORD *lpRec;
|
|
/*
|
|
* Set aside memory to hold the conference roster, the pointers to the
|
|
* GCCNodeRecord structures and the GCCNodeRecord structures themselves.
|
|
* The "sizeof" the structure must be rounded to an even four-byte
|
|
* boundary.
|
|
*/
|
|
m_cbDataMemorySize = ROUNDTOBOUNDARY (sizeof (GCCConferenceRoster));
|
|
|
|
m_cbDataMemorySize += m_RecordList2.GetCount() *
|
|
(sizeof(PGCCNodeRecord) + ROUNDTOBOUNDARY (sizeof(GCCNodeRecord)) );
|
|
|
|
m_RecordList2.Reset();
|
|
while (NULL != (internal_node_record = m_RecordList2.Iterate()))
|
|
{
|
|
/*
|
|
* Add the size of the node name Unicode String, if it exists.
|
|
* Space must be allowed for the NULL terminator of the string.
|
|
*/
|
|
if (internal_node_record->pwszNodeName != NULL)
|
|
{
|
|
m_cbDataMemorySize += ROUNDTOBOUNDARY(
|
|
(::lstrlenW(internal_node_record->pwszNodeName) + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
/*
|
|
* Add the amount of memory needed to hold the pointers to the
|
|
* list of participants, if it exists. Also add the total amount
|
|
* of memory needed to hold the participant list data.
|
|
*/
|
|
if (internal_node_record->participant_name_list != NULL)
|
|
{
|
|
LPWSTR lpUstring;
|
|
|
|
m_cbDataMemorySize += internal_node_record->participant_name_list->GetCount() * sizeof(LPWSTR);
|
|
|
|
/*
|
|
* Set up an iterator for the participant name list in order to
|
|
* add the amount of memory necessary to hold each Unicode
|
|
* String. Space must be allowed for the strings' NULL
|
|
* terminators.
|
|
*/
|
|
internal_node_record->participant_name_list->Reset();
|
|
while (NULL != (lpUstring = internal_node_record->participant_name_list->Iterate()))
|
|
{
|
|
m_cbDataMemorySize += ROUNDTOBOUNDARY(
|
|
(::lstrlenW(lpUstring) + 1) * sizeof(WCHAR));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Add the size of the site information Unicode String, if it
|
|
* exists. Space must be allowed for the NULL terminator of
|
|
* the string.
|
|
*/
|
|
if (internal_node_record->pwszSiteInfo != NULL)
|
|
{
|
|
m_cbDataMemorySize += ROUNDTOBOUNDARY(
|
|
(::lstrlenW(internal_node_record->pwszSiteInfo) + 1) * sizeof(WCHAR));
|
|
}
|
|
|
|
/*
|
|
* If a network address list is present, lock the internal network
|
|
* address list object in order to find the amount of memory
|
|
* required by the list.
|
|
*/
|
|
if (internal_node_record->network_address_list != NULL)
|
|
{
|
|
m_cbDataMemorySize += internal_node_record->
|
|
network_address_list->LockNetworkAddressList ();
|
|
}
|
|
|
|
/*
|
|
* Add the space necessary to hold the alternative node ID octet
|
|
* string structure as well as the string data, if it exists.
|
|
*/
|
|
if (internal_node_record->poszAltNodeID != NULL)
|
|
{
|
|
m_cbDataMemorySize += ROUNDTOBOUNDARY(sizeof(OSTR));
|
|
m_cbDataMemorySize += ROUNDTOBOUNDARY(internal_node_record->poszAltNodeID->length);
|
|
}
|
|
|
|
/*
|
|
* If a user data list is present, lock the internal user data
|
|
* list object in order to find the amount of memory required by
|
|
* the list.
|
|
*/
|
|
if (internal_node_record->user_data_list != NULL)
|
|
{
|
|
m_cbDataMemorySize += internal_node_record->user_data_list->LockUserDataList ();
|
|
}
|
|
}
|
|
}
|
|
|
|
return m_cbDataMemorySize;
|
|
}
|
|
|
|
/*
|
|
* void UnLockConferenceRoster ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to "unlock" the CConfRoster "API" data. The
|
|
* lock count is decremented each time the routine is called and the "API"
|
|
* data will actually be freed when the lock count reaches zero.
|
|
*/
|
|
void CConfRoster::UnLockConferenceRoster(void)
|
|
{
|
|
if (Unlock(FALSE) == 0)
|
|
{
|
|
CONF_RECORD *lpRec;
|
|
|
|
/*
|
|
** Set up an iterator in order to unlock any internal data
|
|
** containers
|
|
** which have been locked.
|
|
*/
|
|
m_RecordList2.Reset();
|
|
while (NULL != (lpRec = m_RecordList2.Iterate()))
|
|
{
|
|
/*
|
|
* Unlock the network address list if it exists.
|
|
*/
|
|
if (lpRec->network_address_list != NULL)
|
|
{
|
|
lpRec->network_address_list->UnLockNetworkAddressList ();
|
|
}
|
|
|
|
/*
|
|
* Unlock the user data list if it exists.
|
|
*/
|
|
if (lpRec->user_data_list != NULL)
|
|
{
|
|
lpRec->user_data_list->UnLockUserDataList ();
|
|
}
|
|
}
|
|
}
|
|
|
|
// we have to call Release() because we used Unlock(FALSE)
|
|
Release();
|
|
}
|
|
|
|
|
|
/*
|
|
* UINT GetConfRoster ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is called in order to retrieve the CConfRoster data
|
|
* in "API" form. The CConfRoster data must first be "locked" before
|
|
* this routine may be called.
|
|
*/
|
|
UINT CConfRoster::GetConfRoster(
|
|
PGCCConferenceRoster * conference_roster,
|
|
LPBYTE memory)
|
|
{
|
|
UINT rc;
|
|
|
|
/*
|
|
* If the user data has been locked, fill in the output parameters and
|
|
* the data referenced by the pointers. Otherwise, report that the object
|
|
* has yet to be locked into the "API" form.
|
|
*/
|
|
if (GetLockCount() > 0)
|
|
{
|
|
UINT total_data_length = 0;
|
|
UINT data_length = 0;
|
|
UINT node_record_counter = 0;
|
|
PGCCNodeRecord node_record;
|
|
PGCCConferenceRoster roster;
|
|
CONF_RECORD *internal_record;
|
|
UserID node_id;
|
|
USHORT i;
|
|
|
|
/*
|
|
* Fill in the output length parameter which indicates how much data
|
|
* referenced outside the structure will be written.
|
|
*/
|
|
rc = m_cbDataMemorySize;
|
|
|
|
/*
|
|
* Set the conference roster pointer equal to the memory pointer passed
|
|
* in. This is where the conference roster structure will be built.
|
|
* Save the conference roster pointer for convienence.
|
|
*/
|
|
*conference_roster = (PGCCConferenceRoster)memory;
|
|
roster = *conference_roster;
|
|
|
|
/*
|
|
* Fill in all of the elements of the conference roster except for
|
|
* the node record list.
|
|
*/
|
|
roster->instance_number = (USHORT)m_nInstanceNumber;
|
|
roster->nodes_were_added = m_fNodesAdded;
|
|
roster->nodes_were_removed = m_fNodesRemoved;
|
|
roster->number_of_records = (USHORT) m_RecordList2.GetCount();
|
|
|
|
/*
|
|
* The "total_data_length" will hold the total amount of data written
|
|
* into memory. Save the amount of memory needed to hold the
|
|
* conference roster. Add the amount of memory necessary to hold the
|
|
* node record pointers and structures.
|
|
*/
|
|
data_length = ROUNDTOBOUNDARY(sizeof(GCCConferenceRoster));
|
|
|
|
total_data_length = data_length + m_RecordList2.GetCount() *
|
|
(ROUNDTOBOUNDARY(sizeof(GCCNodeRecord)) + sizeof(PGCCNodeRecord));
|
|
|
|
/*
|
|
* Move the memory pointer past the conference roster structure. This
|
|
* is where the node record pointer list will be written.
|
|
*/
|
|
memory += data_length;
|
|
|
|
/*
|
|
* Set the roster's node record list pointer.
|
|
*/
|
|
roster->node_record_list = (PGCCNodeRecord *)memory;
|
|
|
|
/*
|
|
* Move the memory pointer past the list of node record pointers.
|
|
*/
|
|
memory += (m_RecordList2.GetCount() * sizeof(PGCCNodeRecord));
|
|
|
|
/*
|
|
* Iterate through the internal list of record structures, building
|
|
* "API" GCCNodeRecord structures in memory.
|
|
*/
|
|
m_RecordList2.Reset();
|
|
while (NULL != (internal_record = m_RecordList2.Iterate(&node_id)))
|
|
{
|
|
/*
|
|
* Save the pointer to the node record structure in the list
|
|
* of pointers. Get the internal node record from the list.
|
|
*/
|
|
node_record = (PGCCNodeRecord)memory;
|
|
roster->node_record_list[node_record_counter++] = node_record;
|
|
|
|
/*
|
|
* Fill in the node ID and the superior node ID.
|
|
*/
|
|
node_record->node_id = node_id;
|
|
node_record->superior_node_id = internal_record->superior_node;
|
|
|
|
/*
|
|
* Fill in the node type and the node properties.
|
|
*/
|
|
GetNodeTypeAndProperties (
|
|
internal_record->node_type,
|
|
internal_record->node_properties,
|
|
&node_record->node_type,
|
|
&node_record->node_properties);
|
|
|
|
/*
|
|
* Move the memory pointer past the node record structure. This is
|
|
* where the node name unicode string will be written, if it exists.
|
|
*/
|
|
memory += ROUNDTOBOUNDARY(sizeof(GCCNodeRecord));
|
|
|
|
if (internal_record->pwszNodeName != NULL)
|
|
{
|
|
/*
|
|
* Set the record's node name pointer and copy the node name
|
|
* data into memory from the internal unicode string. Be sure
|
|
* to copy the strings NULL terminating character. Move the
|
|
* memory pointer past the node name string data.
|
|
*/
|
|
node_record->node_name = (LPWSTR) memory;
|
|
UINT cbStrSize = (::lstrlenW(internal_record->pwszNodeName) + 1) * sizeof(WCHAR);
|
|
::CopyMemory(memory, internal_record->pwszNodeName, cbStrSize);
|
|
total_data_length += ROUNDTOBOUNDARY(cbStrSize);
|
|
memory += (Int) ROUNDTOBOUNDARY(cbStrSize);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The node name string does not exist, so set the node record
|
|
* pointer to NULL.
|
|
*/
|
|
node_record->node_name = NULL;
|
|
}
|
|
|
|
if (internal_record->participant_name_list != NULL)
|
|
{
|
|
LPWSTR lpUstring;
|
|
/*
|
|
* Fill in the node record's participant name list. Use an
|
|
* iterator to access each participant name for this node
|
|
* record, copying each string into the appropriate location
|
|
* in memory.
|
|
*/
|
|
node_record->participant_name_list = (LPWSTR *)memory;
|
|
node_record->number_of_participants = (USHORT)
|
|
internal_record->participant_name_list->GetCount();
|
|
|
|
/*
|
|
* Move the memory pointer past the list of participant name
|
|
* pointers. This is where the first participant name string
|
|
* will be written. There is no need to round this value off
|
|
* to an even multiple of four bytes since a LPWSTR
|
|
* is actually a pointer.
|
|
*/
|
|
memory += internal_record->participant_name_list->GetCount() * sizeof(LPWSTR);
|
|
total_data_length += internal_record->participant_name_list->GetCount() * sizeof(LPWSTR);
|
|
|
|
/*
|
|
* Initialize the loop counter to zero and fill in the
|
|
* participants name list.
|
|
*/
|
|
i = 0;
|
|
internal_record->participant_name_list->Reset();
|
|
while (NULL != (lpUstring = internal_record->participant_name_list->Iterate()))
|
|
{
|
|
node_record->participant_name_list[i++] = (LPWSTR)memory;
|
|
UINT cbStrSize = (::lstrlenW(lpUstring) + 1) * sizeof(WCHAR);
|
|
::CopyMemory(memory, lpUstring, cbStrSize);
|
|
memory += ROUNDTOBOUNDARY(cbStrSize);
|
|
total_data_length += ROUNDTOBOUNDARY(cbStrSize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The participant name list does not exist, so set the node
|
|
* record pointer to NULL and the number of participants to
|
|
* zero.
|
|
*/
|
|
node_record->participant_name_list = NULL;
|
|
node_record->number_of_participants = 0;
|
|
}
|
|
|
|
if (internal_record->pwszSiteInfo != NULL)
|
|
{
|
|
/*
|
|
* Set the record's site information pointer and copy the site
|
|
* information data into memory from the internal unicode
|
|
* string. Be sure to copy the strings NULL terminating
|
|
* character. Move the memory pointer past the site information
|
|
* string data.
|
|
*/
|
|
node_record->site_information = (LPWSTR)memory;
|
|
UINT cbStrSize = (::lstrlenW(internal_record->pwszSiteInfo) + 1) * sizeof(WCHAR);
|
|
::CopyMemory(memory, internal_record->pwszSiteInfo, cbStrSize);
|
|
total_data_length += ROUNDTOBOUNDARY(cbStrSize);
|
|
memory += ROUNDTOBOUNDARY(cbStrSize);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The site information string does not exist, so set the
|
|
* node record pointer to NULL.
|
|
*/
|
|
node_record->site_information = NULL;
|
|
}
|
|
|
|
if (internal_record->network_address_list != NULL)
|
|
{
|
|
/*
|
|
* Fill in the network address list by using the internal
|
|
* CNetAddrListContainer object. The "Get" call will fill in the
|
|
* node record's network address list pointer and number of
|
|
* addresses, write the network address data into memory, and
|
|
* return the amount of data written into memory.
|
|
*/
|
|
data_length = internal_record->network_address_list->GetNetworkAddressListAPI (
|
|
&node_record->number_of_network_addresses,
|
|
&node_record->network_address_list,
|
|
memory);
|
|
|
|
/*
|
|
* Move the memory pointer past the network address list data.
|
|
* This is where the user data list data will be written.
|
|
*/
|
|
memory += data_length;
|
|
total_data_length += data_length;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The network address list does not exist, so set the node
|
|
* record pointer to NULL and the number of addresses to zero.
|
|
*/
|
|
node_record->network_address_list = NULL;
|
|
node_record->number_of_network_addresses = 0;
|
|
}
|
|
|
|
if (internal_record->poszAltNodeID != NULL)
|
|
{
|
|
/*
|
|
* Set the node record's alternative node ID pointer to the
|
|
* location in memory where the OSTR will be built.
|
|
* Note that the node record contains a pointer to a
|
|
* OSTR structure in memory, not just a pointer to
|
|
* string data.
|
|
*/
|
|
node_record->alternative_node_id = (LPOSTR) memory;
|
|
|
|
/*
|
|
* Move the memory pointer past the octet string structure.
|
|
* This is where the actual string data will be written.
|
|
*/
|
|
memory += ROUNDTOBOUNDARY(sizeof(OSTR));
|
|
total_data_length += ROUNDTOBOUNDARY(sizeof(OSTR));
|
|
|
|
node_record->alternative_node_id->length =
|
|
internal_record->poszAltNodeID->length;
|
|
|
|
/*
|
|
* Set the pointer for the alternative node ID octet string
|
|
* equal to the location in memory where it will be copied.
|
|
*/
|
|
node_record->alternative_node_id->value =(LPBYTE)memory;
|
|
|
|
/*
|
|
* Now copy the octet string data from the internal Rogue Wave
|
|
* string into the object key structure held in memory.
|
|
*/
|
|
::CopyMemory(memory, internal_record->poszAltNodeID->value,
|
|
node_record->alternative_node_id->length);
|
|
|
|
/*
|
|
* Move the memory pointer past the alternative node ID string
|
|
* data written into memory.
|
|
*/
|
|
memory += ROUNDTOBOUNDARY(node_record->alternative_node_id->length);
|
|
|
|
total_data_length += ROUNDTOBOUNDARY(node_record->alternative_node_id->length);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The alternative node ID string does not exist, so set the
|
|
* node record pointer to NULL.
|
|
*/
|
|
node_record->alternative_node_id = NULL;
|
|
}
|
|
|
|
if (internal_record->user_data_list != NULL)
|
|
{
|
|
/*
|
|
* Fill in the user data list by using the internal CUserDataListContainer
|
|
* object. The "Get" call will fill in the node record's user
|
|
* data list pointer and number of user data members, write the
|
|
* user data into memory, and return the amount of data written
|
|
* into memory.
|
|
*/
|
|
data_length = internal_record->user_data_list->GetUserDataList (
|
|
&node_record->number_of_user_data_members,
|
|
&node_record->user_data_list,
|
|
memory);
|
|
|
|
/*
|
|
* Move the memory pointer past the user data list data.
|
|
*/
|
|
memory += data_length;
|
|
total_data_length += data_length;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The user data list does not exist, so set the node record
|
|
* pointer to NULL and the number of data members to zero.
|
|
*/
|
|
node_record->user_data_list = NULL;
|
|
node_record->number_of_user_data_members = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERROR_OUT(("CConfRoster::GetConfRoster: Error Data Not Locked"));
|
|
*conference_roster = NULL;
|
|
rc = 0;
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError AddRecord ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to add a new Node Record to this conference
|
|
* roster object.
|
|
*/
|
|
GCCError CConfRoster::AddRecord( PGCCNodeRecord node_record,
|
|
UserID node_id)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
USHORT i;
|
|
LPWSTR pwszParticipantName;
|
|
CONF_RECORD *internal_record;
|
|
|
|
/*
|
|
** Free up the old PDU data here if it is being maintained and the
|
|
** PDU has been flushed. Note that we also set the PDU is flushed boolean
|
|
** back to FALSE so that the new PDU will be maintained until it is
|
|
** flushed.
|
|
*/
|
|
if (m_fPduFlushed)
|
|
{
|
|
FreeRosterUpdateIndicationPDU ();
|
|
m_fPduFlushed = FALSE;
|
|
}
|
|
|
|
if (! m_RecordList2.Find(node_id))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record = new CONF_RECORD;
|
|
if (internal_record != NULL)
|
|
{
|
|
/*
|
|
** Convert the passed in conference record to the form that it
|
|
** is going to be stored in the internal roster database.
|
|
*/
|
|
|
|
/*
|
|
** Save the node type and properties internally. These will
|
|
** always exist.
|
|
*/
|
|
GetPDUNodeTypeAndProperties (
|
|
node_record->node_type,
|
|
node_record->node_properties,
|
|
&internal_record->node_type,
|
|
&internal_record->node_properties);
|
|
|
|
internal_record->superior_node = m_uidSuperiorNode;
|
|
|
|
// Save the node name internally if it exists.
|
|
if (node_record->node_name != NULL)
|
|
{
|
|
if (::lstrlenW(node_record->node_name) > MAXIMUM_NODE_NAME_LENGTH)
|
|
{
|
|
rc = GCC_INVALID_NODE_NAME;
|
|
}
|
|
else
|
|
if (NULL == (internal_record->pwszNodeName = ::My_strdupW(node_record->node_name)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->pwszNodeName);
|
|
}
|
|
|
|
// Save the list of participants internally if it exists.
|
|
if ((node_record->number_of_participants != 0) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
if (node_record->participant_name_list != NULL)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->participant_name_list = new CParticipantNameList;
|
|
if (internal_record->participant_name_list == NULL)
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->participant_name_list);
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
/*
|
|
** Convert each participant name that is LPWSTR
|
|
** to a UnicodeString when storing it into a record.
|
|
*/
|
|
for (i = 0; i < node_record->number_of_participants; i++)
|
|
{
|
|
if (node_record->participant_name_list[i] != NULL)
|
|
{
|
|
if (::lstrlenW(node_record->participant_name_list[i]) >
|
|
MAXIMUM_PARTICIPANT_NAME_LENGTH)
|
|
{
|
|
rc = GCC_INVALID_PARTICIPANT_NAME;
|
|
//
|
|
// LONCHANC: Why no "break"?
|
|
//
|
|
}
|
|
else
|
|
if (NULL == (pwszParticipantName = ::My_strdupW(
|
|
node_record->participant_name_list[i])))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Add the participant to the list
|
|
internal_record->participant_name_list->Append(pwszParticipantName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->participant_name_list);
|
|
}
|
|
|
|
// Save site information internally if it exists.
|
|
if (node_record->site_information != NULL)
|
|
{
|
|
if (::lstrlenW(node_record->site_information) > MAXIMUM_SITE_INFORMATION_LENGTH)
|
|
{
|
|
rc = GCC_INVALID_SITE_INFORMATION;
|
|
}
|
|
else
|
|
if (NULL == (internal_record->pwszSiteInfo =
|
|
::My_strdupW(node_record->site_information)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->pwszSiteInfo);
|
|
}
|
|
|
|
/*
|
|
** Fill in the network address list if it exists. The network
|
|
** address list is maintained internally in a CNetAddrListContainer
|
|
** object which is constructed here using the GCCNetworkAddress
|
|
** portion of the "API" node record passed in.
|
|
*/
|
|
if ((node_record->number_of_network_addresses != 0) &&
|
|
(node_record->network_address_list != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->network_address_list = new CNetAddrListContainer(
|
|
node_record->number_of_network_addresses,
|
|
node_record->network_address_list,
|
|
&rc);
|
|
if ((internal_record->network_address_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->network_address_list);
|
|
}
|
|
|
|
// Save the alternative node ID internally if it exists.
|
|
if ((node_record->alternative_node_id != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
if (NULL == (internal_record->poszAltNodeID = ::My_strdupO2(
|
|
node_record->alternative_node_id->value,
|
|
node_record->alternative_node_id->length)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
else if (internal_record->poszAltNodeID->length != ALTERNATIVE_NODE_ID_LENGTH)
|
|
{
|
|
ERROR_OUT(("not equal to alt node id length"));
|
|
rc = GCC_INVALID_ALTERNATIVE_NODE_ID;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->poszAltNodeID);
|
|
}
|
|
|
|
/*
|
|
** Fill in the user data if it exists. The user data is
|
|
** maintained internally in a CUserDataListContainer object which is
|
|
** constructed here using the GCCUserData portion of the "API"
|
|
** node record passed in.
|
|
*/
|
|
if ((node_record->number_of_user_data_members != 0) &&
|
|
(node_record->user_data_list != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
internal_record->user_data_list = new CUserDataListContainer(
|
|
node_record->number_of_user_data_members,
|
|
node_record->user_data_list,
|
|
&rc);
|
|
if ((internal_record->user_data_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERT(NULL == internal_record->user_data_list);
|
|
}
|
|
|
|
/*
|
|
** If the new Record was successfully filled in, add it to the
|
|
** internal Rogue Wave list of Records.
|
|
*/
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
// Increment the instance number.
|
|
m_nInstanceNumber++;
|
|
m_fNodesAdded = TRUE;
|
|
m_fRosterChanged = TRUE;
|
|
|
|
// Add the new record to the list of internal records.
|
|
m_RecordList2.Append(node_id, internal_record);
|
|
|
|
// Add an update to the PDU.
|
|
rc = BuildRosterUpdateIndicationPDU(ADD_RECORD, node_id);
|
|
}
|
|
else
|
|
{
|
|
delete internal_record;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError RemoveUserReference ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to remove a node record from the list of node
|
|
* records.
|
|
*/
|
|
GCCError CConfRoster::RemoveUserReference(UserID detached_node_id)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
CONF_RECORD *node_record;
|
|
CUidList node_delete_list;
|
|
|
|
/*
|
|
** Free up the old PDU data here if it is being maintained and the
|
|
** PDU has been flushed. Note that we also set the PDU is flushed boolean
|
|
** back to FALSE so that the new PDU will be maintained until it is
|
|
** flushed.
|
|
*/
|
|
if (m_fPduFlushed)
|
|
{
|
|
FreeRosterUpdateIndicationPDU ();
|
|
m_fPduFlushed = FALSE;
|
|
}
|
|
|
|
/*
|
|
** Here we must determine if the node that is detaching is directly
|
|
** connected to this node. If so, we will delete the node and any other
|
|
** nodes found in the roster list that are subordinate to this. We
|
|
** determine all of this by using the superior node id stored in each
|
|
** conference record.
|
|
*/
|
|
if (NULL != (node_record = m_RecordList2.Find(detached_node_id)))
|
|
{
|
|
// Is this node directly connected to me?
|
|
if (node_record->superior_node == m_uidMyNodeID)
|
|
{
|
|
/*
|
|
** Use NULL for the pointer since were not concerned about
|
|
** the pointer here.
|
|
*/
|
|
rc = GetNodeSubTree(detached_node_id, &node_delete_list);
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
UserID uid;
|
|
|
|
node_delete_list.Reset();
|
|
while ((GCC_INVALID_UID != (uid = node_delete_list.Iterate())) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
rc = DeleteRecord(uid);
|
|
}
|
|
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
// Increment the instance number.
|
|
m_nInstanceNumber++;
|
|
m_fNodesRemoved = TRUE;
|
|
m_fRosterChanged = TRUE;
|
|
|
|
// Add an update to the PDU.
|
|
rc = BuildRosterUpdateIndicationPDU (FULL_REFRESH, 0 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError ReplaceRecord ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to replace one of the records in the list of
|
|
* node records.
|
|
*/
|
|
GCCError CConfRoster::ReplaceRecord(
|
|
PGCCNodeRecord node_record,
|
|
UserID node_id)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
USHORT i;
|
|
LPWSTR pwszParticipantName;
|
|
CONF_RECORD *pCRD = NULL;
|
|
|
|
/*
|
|
** Free up the old PDU data here if it is being maintained and the
|
|
** PDU has been flushed. Note that we also set the PDU is flushed boolean
|
|
** back to FALSE so that the new PDU will be maintained until it is
|
|
** flushed.
|
|
*/
|
|
if (m_fPduFlushed)
|
|
{
|
|
FreeRosterUpdateIndicationPDU ();
|
|
m_fPduFlushed = FALSE;
|
|
}
|
|
|
|
//
|
|
// LONCHANC: Do we really need to check this? Why can't we simply
|
|
// add the new one if the old one does not exist?
|
|
//
|
|
if (NULL == m_RecordList2.Find(node_id))
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
goto MyExit;
|
|
}
|
|
|
|
DBG_SAVE_FILE_LINE
|
|
if (NULL == (pCRD = new CONF_RECORD))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
goto MyExit;
|
|
}
|
|
|
|
/*
|
|
** First we build all the internal data and check for validity
|
|
** before we replace the old record. We want to make sure that
|
|
** everything will build before we do the replace. This prevents
|
|
** us from corrupting the current record if there is a problem
|
|
** with the new record data.
|
|
*/
|
|
|
|
// Save the node name internally if it exists.
|
|
if (node_record->node_name != NULL)
|
|
{
|
|
if (::lstrlenW(node_record->node_name) > MAXIMUM_NODE_NAME_LENGTH)
|
|
{
|
|
rc = GCC_INVALID_NODE_NAME;
|
|
}
|
|
else
|
|
if (NULL == (pCRD->pwszNodeName = ::My_strdupW(node_record->node_name)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
|
|
// Save the list of participants internally if it exists.
|
|
if ((node_record->number_of_participants != 0) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
if (node_record->participant_name_list != NULL)
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
if (NULL == (pCRD->participant_name_list = new CParticipantNameList))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
else
|
|
rc = GCC_INVALID_PARAMETER;
|
|
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
/*
|
|
** Convert each participant name that is LPWSTR
|
|
** to a UnicodeString when storing it into a record.
|
|
*/
|
|
for (i = 0; i < node_record->number_of_participants; i++)
|
|
{
|
|
if (node_record->participant_name_list[i] != NULL)
|
|
{
|
|
if (::lstrlenW(node_record->participant_name_list[i]) >
|
|
MAXIMUM_PARTICIPANT_NAME_LENGTH)
|
|
{
|
|
rc = GCC_INVALID_PARTICIPANT_NAME;
|
|
//
|
|
// LONCHANC: Why no "break"?
|
|
//
|
|
}
|
|
else
|
|
if (NULL == (pwszParticipantName = ::My_strdupW(
|
|
node_record->participant_name_list[i])))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// Add the participant to the list
|
|
pCRD->participant_name_list->Append(pwszParticipantName);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save site information internally if it exists.
|
|
if (node_record->site_information != NULL)
|
|
{
|
|
if (::lstrlenW(node_record->site_information) > MAXIMUM_SITE_INFORMATION_LENGTH)
|
|
{
|
|
rc = GCC_INVALID_SITE_INFORMATION;
|
|
}
|
|
else
|
|
if (NULL == (pCRD->pwszSiteInfo = ::My_strdupW(node_record->site_information)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Fill in the network address list if it exists. The network
|
|
** address list is maintained internally in a CNetAddrListContainer
|
|
** object which is constructed here using the GCCNetworkAddress
|
|
** portion of the "API" node record passed in.
|
|
*/
|
|
if ((node_record->number_of_network_addresses != 0) &&
|
|
(node_record->network_address_list != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
pCRD->network_address_list = new CNetAddrListContainer(
|
|
node_record->number_of_network_addresses,
|
|
node_record->network_address_list,
|
|
&rc);
|
|
if ((pCRD->network_address_list == NULL) ||
|
|
(rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
|
|
// Save the alternative node ID internally if it exists.
|
|
if ((node_record->alternative_node_id != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
if (NULL == (pCRD->poszAltNodeID = ::My_strdupO2(
|
|
node_record->alternative_node_id->value,
|
|
node_record->alternative_node_id->length)))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
else if (pCRD->poszAltNodeID->length !=ALTERNATIVE_NODE_ID_LENGTH)
|
|
{
|
|
ERROR_OUT(("not equal to alt node id length"));
|
|
rc = GCC_INVALID_ALTERNATIVE_NODE_ID;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Fill in the user data if it exists. The user data is
|
|
** maintained internally in a CUserDataListContainer object which is
|
|
** constructed here using the GCCUserData portion of the "API"
|
|
** node record passed in.
|
|
*/
|
|
if ((node_record->number_of_user_data_members != 0) &&
|
|
(node_record->user_data_list != NULL) &&
|
|
(rc == GCC_NO_ERROR))
|
|
{
|
|
DBG_SAVE_FILE_LINE
|
|
pCRD->user_data_list = new CUserDataListContainer(
|
|
node_record->number_of_user_data_members,
|
|
node_record->user_data_list,
|
|
&rc);
|
|
if ((pCRD->user_data_list == NULL) || (rc != GCC_NO_ERROR))
|
|
{
|
|
rc = GCC_ALLOCATION_FAILURE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Now if no errors occured we replace the old record with the new
|
|
** record information created above.
|
|
*/
|
|
if (rc == GCC_NO_ERROR)
|
|
{
|
|
/*
|
|
** Save the node type and properties internally. These will
|
|
** always exist.
|
|
*/
|
|
GetPDUNodeTypeAndProperties (
|
|
node_record->node_type,
|
|
node_record->node_properties,
|
|
&pCRD->node_type,
|
|
&pCRD->node_properties);
|
|
|
|
pCRD->superior_node = m_uidSuperiorNode;
|
|
|
|
// replace the old record with the new one
|
|
DeleteRecord(node_id);
|
|
m_RecordList2.Append(node_id, pCRD);
|
|
|
|
// Increment the instance number.
|
|
m_nInstanceNumber++;
|
|
m_fRosterChanged = TRUE;
|
|
}
|
|
|
|
MyExit:
|
|
|
|
if (GCC_NO_ERROR == rc)
|
|
{
|
|
// Add an update to the PDU.
|
|
rc = BuildRosterUpdateIndicationPDU(REPLACE_RECORD, node_id);
|
|
}
|
|
else
|
|
{
|
|
delete pCRD;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* GCCError DeleteRecord ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to delete one of the records from the list of
|
|
* node records. It only operates on the conference roster list. It
|
|
* does not deal with any of the flags associated with a roster PDU or
|
|
* message such as: m_fNodesAdded and m_fNodesRemoved.
|
|
*
|
|
* Formal Parameters:
|
|
* node_id - (i) Node ID of node record to delete.
|
|
*
|
|
* Return Value
|
|
* GCC_NO_ERROR - No error occured.
|
|
* GCC_INVALID_PARAMETER - Bad node id passed in.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
CONF_RECORD::CONF_RECORD(void)
|
|
:
|
|
pwszNodeName(NULL),
|
|
participant_name_list(NULL),
|
|
pwszSiteInfo(NULL),
|
|
network_address_list(NULL),
|
|
poszAltNodeID(NULL),
|
|
user_data_list(NULL),
|
|
superior_node(0)
|
|
{
|
|
}
|
|
|
|
CONF_RECORD::~CONF_RECORD(void)
|
|
{
|
|
/*
|
|
* If a node name exists, delete it from the Record.
|
|
*/
|
|
delete pwszNodeName;
|
|
|
|
/*
|
|
* If a participants list exists, clear the list and then delete it
|
|
* from the Record.
|
|
*/
|
|
if (participant_name_list != NULL)
|
|
{
|
|
participant_name_list->DeleteList();
|
|
delete participant_name_list;
|
|
}
|
|
|
|
/*
|
|
* If site information exists, delete it from the Record.
|
|
*/
|
|
delete pwszSiteInfo;
|
|
|
|
/*
|
|
* If a network address list exists, delete it from the Record.
|
|
*/
|
|
if (NULL != network_address_list)
|
|
{
|
|
network_address_list->Release();
|
|
}
|
|
|
|
/*
|
|
* If a user data list exists, delete it from the Record.
|
|
*/
|
|
if (NULL != user_data_list)
|
|
{
|
|
user_data_list->Release();
|
|
}
|
|
}
|
|
|
|
GCCError CConfRoster::DeleteRecord(UserID node_id)
|
|
{
|
|
GCCError rc;
|
|
CONF_RECORD *lpRec;
|
|
|
|
if (NULL != (lpRec = m_RecordList2.Remove(node_id)))
|
|
{
|
|
delete lpRec;
|
|
rc = GCC_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
/*
|
|
* void ClearRecordList ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to clear out the internal list of records which
|
|
* hold the conference roster information. This routine is called upon
|
|
* destruction of this object or when a refresh occurs causing the entire
|
|
* record list to be rebuilt.
|
|
*
|
|
* Formal Parameters:
|
|
* None.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::ClearRecordList(void)
|
|
{
|
|
CONF_RECORD *pRec;
|
|
while (NULL != (pRec = m_RecordList2.Get()))
|
|
{
|
|
delete pRec;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* NodeType GetNodeTypeAndProperties ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to translate the node type and node properties
|
|
* from the "PDU" form into the "API" form.
|
|
*
|
|
* Formal Parameters:
|
|
* pdu_node_type - (i) This is the node type defined for the PDU.
|
|
* pdu_node_properties - (i) This is the node properties defined for
|
|
* the PDU.
|
|
* node_type - (o) This is a pointer to the GCCNodeType to
|
|
* be filled in by this routine.
|
|
* node_properties - (o) This is a pointer to the GCCNodeProperties
|
|
* to be filled in by this routine.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::GetNodeTypeAndProperties (
|
|
NodeType pdu_node_type,
|
|
NodeProperties pdu_node_properties,
|
|
PGCCNodeType node_type,
|
|
PGCCNodeProperties node_properties)
|
|
{
|
|
/*
|
|
* First translate the node type.
|
|
*/
|
|
if (pdu_node_type == TERMINAL)
|
|
*node_type = GCC_TERMINAL;
|
|
else if (pdu_node_type == MCU)
|
|
*node_type = GCC_MCU;
|
|
else
|
|
*node_type = GCC_MULTIPORT_TERMINAL;
|
|
|
|
/*
|
|
* Next translate the node properties.
|
|
*/
|
|
if ((pdu_node_properties.device_is_peripheral) &&
|
|
(pdu_node_properties.device_is_manager == FALSE))
|
|
{
|
|
*node_properties = GCC_PERIPHERAL_DEVICE;
|
|
}
|
|
else if ((pdu_node_properties.device_is_peripheral == FALSE) &&
|
|
(pdu_node_properties.device_is_manager))
|
|
{
|
|
*node_properties = GCC_MANAGEMENT_DEVICE;
|
|
}
|
|
else if ((pdu_node_properties.device_is_peripheral) &&
|
|
(pdu_node_properties.device_is_manager))
|
|
{
|
|
*node_properties = GCC_PERIPHERAL_AND_MANAGEMENT_DEVICE;
|
|
}
|
|
else
|
|
*node_properties = GCC_NEITHER_PERIPHERAL_NOR_MANAGEMENT;
|
|
}
|
|
|
|
|
|
/*
|
|
* void GetPDUNodeTypeAndProperties ()
|
|
*
|
|
* Private Function Description:
|
|
* This routine is used to translate the node type and node properties
|
|
* from the "API" form into the "PDU" form.
|
|
*
|
|
* Formal Parameters:
|
|
* node_type - (i) This is the GCC (or API) node type.
|
|
* node_properties - (i) This is the GCC (or API) node properties
|
|
* pdu_node_type - (o) This is a pointer to the PDU node type to
|
|
* be filled in by this routine.
|
|
* pdu_node_properties - (o) This is a pointer to the PDU node properties
|
|
* to be filled in by this routine.
|
|
*
|
|
* Return Value
|
|
* None.
|
|
*
|
|
* Side Effects
|
|
* None.
|
|
*
|
|
* Caveats
|
|
* None.
|
|
*/
|
|
void CConfRoster::GetPDUNodeTypeAndProperties (
|
|
GCCNodeType node_type,
|
|
GCCNodeProperties node_properties,
|
|
PNodeType pdu_node_type,
|
|
PNodeProperties pdu_node_properties)
|
|
{
|
|
/*
|
|
* First translate node types.
|
|
*/
|
|
if (node_type == GCC_TERMINAL)
|
|
*pdu_node_type = TERMINAL;
|
|
else if (node_type == GCC_MCU)
|
|
*pdu_node_type = MCU;
|
|
else
|
|
*pdu_node_type = MULTIPORT_TERMINAL;
|
|
|
|
/*
|
|
* Next translate node properties.
|
|
*/
|
|
if (node_properties == GCC_PERIPHERAL_DEVICE)
|
|
{
|
|
pdu_node_properties->device_is_manager = FALSE;
|
|
pdu_node_properties->device_is_peripheral = TRUE;
|
|
}
|
|
else if (node_properties == GCC_MANAGEMENT_DEVICE)
|
|
{
|
|
pdu_node_properties->device_is_manager = TRUE;
|
|
pdu_node_properties->device_is_peripheral = FALSE;
|
|
}
|
|
else if (node_properties == GCC_PERIPHERAL_AND_MANAGEMENT_DEVICE)
|
|
{
|
|
pdu_node_properties->device_is_manager = TRUE;
|
|
pdu_node_properties->device_is_peripheral = TRUE;
|
|
}
|
|
else
|
|
{
|
|
pdu_node_properties->device_is_manager = FALSE;
|
|
pdu_node_properties->device_is_peripheral = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* BOOL Contains ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to determine whether or not a record exists within
|
|
* the internal list corresponding to the given user ID.
|
|
*/
|
|
|
|
|
|
/*
|
|
* UINT GetNumberOfApplicationRecords ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine is used to get the number of node records currently being
|
|
* maintained within this object's internal list.
|
|
*/
|
|
|
|
|
|
/*
|
|
* void ResetConferenceRoster ()
|
|
*
|
|
* Public Function Description:
|
|
*/
|
|
void CConfRoster::ResetConferenceRoster(void)
|
|
{
|
|
m_fRosterChanged = FALSE;
|
|
m_fNodesAdded = FALSE;
|
|
m_fNodesRemoved = FALSE;
|
|
}
|
|
|
|
|
|
/*
|
|
* BOOL HasRosterChanged ()
|
|
*
|
|
* Public Function Description:
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
* GCCError GetNodeSubTree ()
|
|
*
|
|
* Public Function Description:
|
|
* This routine traverses the entire tree level-by-level starting at the
|
|
* root node and then progressively going down the tree.
|
|
*/
|
|
GCCError CConfRoster::GetNodeSubTree (
|
|
UserID uidRootNode,
|
|
CUidList *node_list)
|
|
{
|
|
GCCError rc = GCC_NO_ERROR;
|
|
CUidList high_level_list;
|
|
UserID uidSuperiorNode;
|
|
CONF_RECORD *lpRec;
|
|
UserID uid;
|
|
|
|
if (m_RecordList2.Find(uidRootNode))
|
|
{
|
|
/*
|
|
** First add the root node to the high level list to get every thing
|
|
** going.
|
|
*/
|
|
high_level_list.Append(uidRootNode);
|
|
|
|
while (! high_level_list.IsEmpty())
|
|
{
|
|
uidSuperiorNode = high_level_list.Get();
|
|
|
|
// Append the high level node id to the node list passed in.
|
|
node_list->Append(uidSuperiorNode);
|
|
|
|
/*
|
|
** Iterate through the entire roster looking for the next
|
|
** level of dependent nodes.
|
|
*/
|
|
m_RecordList2.Reset();
|
|
while (NULL != (lpRec = m_RecordList2.Iterate(&uid)))
|
|
{
|
|
if (lpRec->superior_node == uidSuperiorNode)
|
|
{
|
|
high_level_list.Append(uid);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rc = GCC_INVALID_PARAMETER;
|
|
}
|
|
|
|
return (rc);
|
|
}
|
|
|
|
|
|
void CParticipantNameList::DeleteList(void)
|
|
{
|
|
LPWSTR pwszParticipantName;
|
|
while (NULL != (pwszParticipantName = Get()))
|
|
{
|
|
delete pwszParticipantName;
|
|
}
|
|
}
|
|
|
|
|