Source code of Windows XP (NT5)
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.

3142 lines
83 KiB

  1. #include "precomp.h"
  2. #include "fsdiag.h"
  3. DEBUG_FILEZONE(ZONE_T120_CONF_ROSTER);
  4. /*
  5. * crost.cpp
  6. *
  7. * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
  8. *
  9. * Abstract:
  10. * This is the implementation file for the Conference Roster Class.
  11. * Instances of this class represent a single Conference Roster's
  12. * information base. It encapsulates all the functionality required to
  13. * maintain the information base which includes the ability to add new
  14. * roster records, delete records and update records. It has the ability
  15. * to convert its internal information base into a list of conference
  16. * records that can be used in a GCC_ROSTER_UPDATE_INDICATION callback.
  17. * It is also responsible for converting its internal information base
  18. * into Conference Roster Update PDUs. Basically, this class is
  19. * responsible for all operations that require direct access to the
  20. * records contained in a Conference Roster.
  21. *
  22. * The Conference Roster class incorporates Rogue Wave list to hold the
  23. * roster record information. Using iterators throughout the class makes
  24. * it easy to quickly convert the information contained in the list into
  25. * either a PDU or into a list of record pointers (for roster update
  26. * indications back to the node controller).
  27. *
  28. * A Conference Roster object has the ability to serialize its roster data
  29. * into a single contiguous memory block when it is required to send a
  30. * message to the application interface. This serialization process is
  31. * managed externally by the CConfRosterMsg class through calls
  32. * to LockConferenceRoster(), UnLockConferenceRoster() and
  33. * GetConfRoster(). When a conference roster is to be serialized, a
  34. * call is made to LockConferenceRoster() which causes the CConfRoster
  35. * object to increment an internal lock count and returns the number of
  36. * bytes required to hold the complete roster update. The Conference
  37. * Roster is then serialized into memory through a call to
  38. * GetConfRoster(). The CConfRoster is then unlocked to allow
  39. * it to be deleted when the free flag gets set through the
  40. * FreeConferenceRoster() function. In the current implementation of GCC,
  41. * FreeConferenceRoster() is not used since the CConfRosterMsg
  42. * maintains the data used to deliver the message.
  43. *
  44. * Private Instance Variables:
  45. * m_RecordList2
  46. * This is the rogue wave list used to hold the pointers to all of the
  47. * rogue wave records.
  48. * m_nInstanceNumber
  49. * This instance variable maintains an up to date instance #
  50. * corresponding to the current conference roster.
  51. * m_fNodesAdded
  52. * Flag indicating if any node records have been added to the
  53. * conference roster since the last reset.
  54. * m_fNodesRemoved
  55. * Flag indicating if any node records have been removed from the
  56. * conference roster since the last reset.
  57. * m_fRosterChanged
  58. * Flag indicating if the roster has changed since the last reset.
  59. * m_uidTopProvider
  60. * The node id of the top provider in the conference.
  61. * m_uidSuperiorNode
  62. * This is the node id of this nodes superior node. For the top
  63. * provider this is zero.
  64. * m_cbDataMemorySize
  65. * This is the number of bytes required to hold the data associated
  66. * with a roster update message. This is calculated on a lock.
  67. * m_NodeInformation
  68. * Structure used to hold the roster update indication node information
  69. * data in "PDU" form.
  70. * m_fTopProvider
  71. * Flag indicating if the node where this roster lives is the top
  72. * provider.
  73. * m_fLocalRoster
  74. * Flag indicating if the roster data is associated with a local
  75. * roster (maintaining intermediate node data) or global roster (
  76. * (maintaining roster data for the whole conference).
  77. * m_fMaintainPduBuffer
  78. * Flag indicating if it is necessary for this roster object to
  79. * maintain internal PDU data. Won't be necessary for global rosters
  80. * at subordinate nodes.
  81. * m_fPduFlushed
  82. * Flag indicating if the PDU that currently exists has been flushed.
  83. * m_pNodeRecordUpdateSet
  84. * Pointer to internal PDU data.
  85. *
  86. * Caveats:
  87. * None.
  88. *
  89. * Author:
  90. * blp/jbo
  91. */
  92. #include "ms_util.h"
  93. #include "crost.h"
  94. #define MAXIMUM_NODE_NAME_LENGTH 255
  95. #define MAXIMUM_PARTICIPANT_NAME_LENGTH 255
  96. #define MAXIMUM_SITE_INFORMATION_LENGTH 255
  97. #define ALTERNATIVE_NODE_ID_LENGTH 2
  98. /*
  99. * CConfRoster ()
  100. *
  101. * Public Function Description:
  102. * This is a constructor for the CConfRoster class. It initializes
  103. * instance variables.
  104. *
  105. */
  106. CConfRoster::CConfRoster(UserID uidTopProvider, UserID uidSuperiorNode, UserID uidMyself,
  107. BOOL is_top_provider, BOOL is_local_roster, BOOL maintain_pdu_buffer)
  108. :
  109. CRefCount(MAKE_STAMP_ID('C','R','s','t')),
  110. m_fNodesAdded(FALSE),
  111. m_fNodesRemoved(FALSE),
  112. m_fRosterChanged(FALSE),
  113. m_fTopProvider(is_top_provider),
  114. m_fLocalRoster(is_local_roster),
  115. m_fMaintainPduBuffer(maintain_pdu_buffer),
  116. m_fPduFlushed(FALSE),
  117. m_uidTopProvider(uidTopProvider),
  118. m_uidSuperiorNode(uidSuperiorNode),
  119. m_uidMyNodeID(uidMyself),
  120. m_nInstanceNumber(0),
  121. m_cbDataMemorySize(0),
  122. m_RecordList2(DESIRED_MAX_NODE_RECORDS),
  123. m_pNodeRecordUpdateSet(NULL)
  124. {
  125. m_NodeInformation.node_record_list.choice = NODE_NO_CHANGE_CHOSEN;
  126. }
  127. /*
  128. * ~CConfRoster ()
  129. *
  130. * Public Function Description:
  131. * This is the destructor for the CConfRoster. It performs any
  132. * necessary cleanup.
  133. */
  134. CConfRoster::~CConfRoster(void)
  135. {
  136. // Free up any left over PDU data.
  137. if (m_fMaintainPduBuffer)
  138. FreeRosterUpdateIndicationPDU ();
  139. // Cleanup the Rogue Wave list of node records.
  140. ClearRecordList();
  141. }
  142. /*
  143. * Utilities that operate on roster update PDU structures.
  144. */
  145. /*
  146. * void FlushRosterUpdateIndicationPDU ()
  147. *
  148. * Public Function Description:
  149. * This routine is used to retrieve a "RosterUpdateIndication" in the "PDU"
  150. * form which is suitable for passing to the ASN.1 encoder. The "PDU"
  151. * structure is built from a previous request to the conference roster.
  152. */
  153. void CConfRoster::FlushRosterUpdateIndicationPDU(
  154. PNodeInformation node_information)
  155. {
  156. /*
  157. ** If this roster has already been flushed we will NOT allow the same
  158. ** PDU to be flushed again. Instead we delete the previously flushed
  159. ** PDU and set the flag back to unflushed. If another flush comes in
  160. ** before a PDU is built no change will be passed back in the node
  161. ** information.
  162. */
  163. if (m_fPduFlushed)
  164. {
  165. FreeRosterUpdateIndicationPDU ();
  166. m_fPduFlushed = FALSE;
  167. }
  168. // First we copy all of the node record list information.
  169. *node_information = m_NodeInformation;
  170. /*
  171. ** Next we copy the relevent instance variables. Note that we must do
  172. ** this after we copy the node information so that these variables
  173. ** will not be copied over with garbage.
  174. */
  175. node_information->roster_instance_number = (ASN1uint16_t)m_nInstanceNumber;
  176. node_information->nodes_are_added = (ASN1bool_t)m_fNodesAdded;
  177. node_information->nodes_are_removed = (ASN1bool_t)m_fNodesRemoved;
  178. /*
  179. ** Setting this to true will cause the PDU data to be freed up the
  180. ** next time the roster object is entered insuring that new PDU
  181. ** data will be created.
  182. */
  183. if (m_NodeInformation.node_record_list.choice != NODE_NO_CHANGE_CHOSEN)
  184. m_fPduFlushed = TRUE;
  185. }
  186. /*
  187. * GCCError BuildFullRefreshPDU ()
  188. *
  189. * Public Function Description
  190. *
  191. */
  192. GCCError CConfRoster::BuildFullRefreshPDU(void)
  193. {
  194. GCCError rc;
  195. /*
  196. ** Free up the old PDU data here if it is being maintained and the
  197. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  198. ** back to FALSE so that the new PDU will be maintained until it is
  199. ** flushed.
  200. */
  201. if (m_fPduFlushed)
  202. {
  203. FreeRosterUpdateIndicationPDU ();
  204. m_fPduFlushed = FALSE;
  205. }
  206. rc = BuildRosterUpdateIndicationPDU (FULL_REFRESH, 0);
  207. return (rc);
  208. }
  209. /*
  210. * GCCError BuildRosterUpdateIndicationPDU ()
  211. *
  212. * Public Function Description:
  213. * This routine is used to build a "RosterUpdateIndication" in the "PDU"
  214. * form which is suitable for passing to the ASN.1 encoder. The "PDU"
  215. * structure is built from the data maintained internally.
  216. */
  217. GCCError CConfRoster::BuildRosterUpdateIndicationPDU(
  218. CONF_ROSTER_UPDATE_TYPE update_type,
  219. UserID node_id)
  220. {
  221. GCCError rc = GCC_NO_ERROR;
  222. if (m_fMaintainPduBuffer)
  223. {
  224. /*
  225. ** If "PDU" data has already been allocated then we free it up and
  226. ** rebuild the PDU structure. This ensures that the most up-to-date
  227. ** PDU is returned.
  228. */
  229. if ((update_type == FULL_REFRESH) || m_fTopProvider)
  230. {
  231. if (m_NodeInformation.node_record_list.choice ==
  232. NODE_RECORD_REFRESH_CHOSEN)
  233. {
  234. // Here we free the old set of refreshes.
  235. FreeSetOfRefreshesPDU();
  236. }
  237. else if (m_NodeInformation.node_record_list.choice ==
  238. NODE_RECORD_UPDATE_CHOSEN)
  239. {
  240. ERROR_OUT(("CConfRoster::BuildRosterUpdateIndicationPDU:"
  241. "ASSERTION: building refresh when update exists"));
  242. rc = GCC_INVALID_PARAMETER;
  243. }
  244. if (rc == GCC_NO_ERROR)
  245. {
  246. rc = BuildSetOfRefreshesPDU();
  247. if (rc == GCC_NO_ERROR)
  248. {
  249. m_NodeInformation.node_record_list.choice =
  250. NODE_RECORD_REFRESH_CHOSEN;
  251. }
  252. }
  253. }
  254. else
  255. {
  256. if (m_NodeInformation.node_record_list.choice ==
  257. NODE_RECORD_REFRESH_CHOSEN)
  258. {
  259. ERROR_OUT(("CConfRoster::BuildRosterUpdateIndicationPDU:"
  260. "ASSERTION: building update when refresh exists"));
  261. rc = GCC_INVALID_PARAMETER;
  262. }
  263. if (rc == GCC_NO_ERROR)
  264. {
  265. rc = BuildSetOfUpdatesPDU(node_id, update_type);
  266. if (rc == GCC_NO_ERROR)
  267. {
  268. //
  269. // LONCHANC: Commented out the following check because
  270. // we can overrun the update, namely, two updates coming
  271. // in side by side. It happens when shutting down a
  272. // conference, we got two ConferenceAnnouncePresenceRequest.
  273. // It is quite stupid in the node controller to call it
  274. // twice unncessarily. The node controller should not call
  275. // it at all when we know we are about to ending a conference.
  276. //
  277. // When two updates come in side by side, m_pNodeRecordUpdateSet
  278. // will keep all the update information intact. New information
  279. // can then be appended to the list.
  280. //
  281. // if (m_NodeInformation.node_record_list.choice ==
  282. // NODE_NO_CHANGE_CHOSEN)
  283. {
  284. m_NodeInformation.node_record_list.u.node_record_update =
  285. m_pNodeRecordUpdateSet;
  286. m_NodeInformation.node_record_list.choice =
  287. NODE_RECORD_UPDATE_CHOSEN;
  288. }
  289. }
  290. }
  291. }
  292. }
  293. return (rc);
  294. }
  295. /*
  296. * GCCError BuildSetOfRefreshesPDU ()
  297. *
  298. * Private Function Description:
  299. * This routine is used to retrieve the "SetOfRefreshes" portion of a
  300. * "RosterUpdateIndication" in the "PDU" form. The internally maintained
  301. * data is converted into the "PDU" form.
  302. *
  303. * Formal Parameters:
  304. * None.
  305. *
  306. * Return Value
  307. * GCC_NO_ERROR - No error occured.
  308. * GCC_ALLOCATION_FAILURE - A resource error occured.
  309. *
  310. * Side Effects
  311. * None.
  312. *
  313. * Caveats
  314. * None.
  315. */
  316. GCCError CConfRoster::BuildSetOfRefreshesPDU(void)
  317. {
  318. GCCError rc = GCC_NO_ERROR;
  319. PSetOfNodeRecordRefreshes new_record_refresh;
  320. PSetOfNodeRecordRefreshes old_record_refresh;
  321. PNodeRecord node_record;
  322. CONF_RECORD *lpRec;
  323. UserID uid;
  324. m_NodeInformation.node_record_list.u.node_record_refresh = NULL;
  325. old_record_refresh = NULL; // This eliminates a compiler warning
  326. m_RecordList2.Reset();
  327. while (NULL != (lpRec = m_RecordList2.Iterate(&uid)))
  328. {
  329. DBG_SAVE_FILE_LINE
  330. new_record_refresh = new SetOfNodeRecordRefreshes;
  331. if (new_record_refresh == NULL)
  332. {
  333. ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: can't create set ofnode record refreshes"));
  334. rc = GCC_ALLOCATION_FAILURE;
  335. goto MyExit;
  336. }
  337. //
  338. // Ensure everything here is clean.
  339. // We may fail in the middle of building this node record.
  340. //
  341. ::ZeroMemory(new_record_refresh, sizeof(SetOfNodeRecordRefreshes));
  342. //
  343. // Hook to the linked list.
  344. //
  345. if (m_NodeInformation.node_record_list.u.node_record_refresh == NULL)
  346. {
  347. m_NodeInformation.node_record_list.u.node_record_refresh = new_record_refresh;
  348. }
  349. else
  350. {
  351. old_record_refresh->next = new_record_refresh;
  352. }
  353. old_record_refresh = new_record_refresh;
  354. /*
  355. * Initialize the refresh "next" pointer to NULL and set the
  356. * refresh value node ID equal to the internal node ID.
  357. */
  358. new_record_refresh->next = NULL;
  359. new_record_refresh->value.node_id = uid;
  360. /*
  361. * Fill in the "PDU" node record structure from the internal
  362. * record structure.
  363. */
  364. node_record = &(new_record_refresh->value.node_record);
  365. node_record->bit_mask = 0;
  366. /*
  367. * Check to see if the superior node ID is present. If the value
  368. * is zero, then the record is for the top provider node and the
  369. * superior node ID does not need to be filled in.
  370. */
  371. if (lpRec->superior_node != 0)
  372. {
  373. node_record->bit_mask |= SUPERIOR_NODE_PRESENT;
  374. node_record->superior_node = lpRec->superior_node;
  375. }
  376. /*
  377. * Fill in the node type and node properties which are always
  378. * present.
  379. */
  380. node_record->node_type = lpRec->node_type;
  381. node_record->node_properties = lpRec->node_properties;
  382. /*
  383. ** This roster object must not go out of scope while this
  384. ** update record is still in use!
  385. */
  386. /*
  387. * Fill in the node name if it is present.
  388. */
  389. if (lpRec->pwszNodeName != NULL)
  390. {
  391. node_record->bit_mask |= NODE_NAME_PRESENT;
  392. node_record->node_name.value = lpRec->pwszNodeName;
  393. node_record->node_name.length = ::lstrlenW(lpRec->pwszNodeName);
  394. }
  395. /*
  396. * Fill in the participants list if it is present.
  397. */
  398. if (lpRec->participant_name_list != NULL)
  399. {
  400. node_record->bit_mask |= PARTICIPANTS_LIST_PRESENT;
  401. rc = BuildParticipantsListPDU(uid, &(node_record->participants_list));
  402. if (GCC_NO_ERROR != rc)
  403. {
  404. ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: can't build participant list, rc=%d", rc));
  405. goto MyExit;
  406. }
  407. }
  408. /*
  409. * Fill in the site information if it is present.
  410. */
  411. if (lpRec->pwszSiteInfo != NULL)
  412. {
  413. node_record->bit_mask |= SITE_INFORMATION_PRESENT;
  414. node_record->site_information.value = lpRec->pwszSiteInfo;
  415. node_record->site_information.length = ::lstrlenW(lpRec->pwszSiteInfo);
  416. }
  417. /*
  418. * Fill in the network address if it is present.
  419. */
  420. if ((lpRec->network_address_list != NULL) && (rc == GCC_NO_ERROR))
  421. {
  422. node_record->bit_mask |= RECORD_NET_ADDRESS_PRESENT;
  423. rc = lpRec->network_address_list->GetNetworkAddressListPDU (
  424. &(node_record->record_net_address));
  425. if (GCC_NO_ERROR != rc)
  426. {
  427. ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: can't get network address list, rc=%d", rc));
  428. goto MyExit;
  429. }
  430. }
  431. /*
  432. * Fill in the alternative node ID if it is present.
  433. */
  434. if (lpRec->poszAltNodeID != NULL)
  435. {
  436. node_record->bit_mask |= ALTERNATIVE_NODE_ID_PRESENT;
  437. node_record->alternative_node_id.choice = H243_NODE_ID_CHOSEN;
  438. node_record->alternative_node_id.u.h243_node_id.length = lpRec->poszAltNodeID->length;
  439. ::CopyMemory(node_record->alternative_node_id.u.h243_node_id.value,
  440. lpRec->poszAltNodeID->value,
  441. node_record->alternative_node_id.u.h243_node_id.length);
  442. }
  443. /*
  444. * Fill in the user data list if it is present.
  445. */
  446. if ((lpRec->user_data_list != NULL) && (rc == GCC_NO_ERROR))
  447. {
  448. node_record->bit_mask |= RECORD_USER_DATA_PRESENT;
  449. rc = lpRec->user_data_list->GetUserDataPDU (&(node_record->record_user_data));
  450. }
  451. }
  452. MyExit:
  453. if (rc != GCC_NO_ERROR)
  454. {
  455. ERROR_OUT(("CConfRoster::BuildSetOfRefreshesPDU: ASSERTION: Error occured: rc=%d", rc));
  456. }
  457. return (rc);
  458. }
  459. /*
  460. * GCCError BuildSetOfUpdatesPDU ()
  461. *
  462. * Private Function Description
  463. * This routine is used to retrieve the "SetOfUpdates" portion of a
  464. * "RosterUpdateIndication" in the "PDU" form. The internally maintained
  465. * data is converted into the "PDU" form.
  466. *
  467. * Formal Parameters:
  468. * node_id - (i) Node ID of node record to be included in
  469. * the update.
  470. * update_type - (i) The type of update PDU to build (Add,
  471. * Delete, Replace).
  472. *
  473. * Return Value
  474. * GCC_NO_ERROR - No error occured.
  475. * GCC_ALLOCATION_FAILURE - A resource error occured.
  476. *
  477. * Side Effects
  478. * None.
  479. *
  480. * Caveats
  481. * None.
  482. */
  483. GCCError CConfRoster::BuildSetOfUpdatesPDU(
  484. UserID node_id,
  485. CONF_ROSTER_UPDATE_TYPE update_type)
  486. {
  487. GCCError rc = GCC_NO_ERROR;
  488. PNodeRecord node_record = NULL;
  489. CONF_RECORD *lpRec;
  490. PSetOfNodeRecordUpdates pRecordUpdate, p;
  491. BOOL fReplaceExistingOne = FALSE;
  492. if (NULL != (lpRec = m_RecordList2.Find(node_id)))
  493. {
  494. //
  495. // LONCHANC: Check to see if a update record already exists
  496. // for this particular node ID. If so, we should replace
  497. // the record.
  498. //
  499. for (p = m_pNodeRecordUpdateSet; NULL != p; p = p->next)
  500. {
  501. if (node_id == p->value.node_id)
  502. {
  503. pRecordUpdate = p;
  504. fReplaceExistingOne = TRUE;
  505. CleanUpdateRecordPDU(pRecordUpdate); // do not free the record itself
  506. //
  507. // Remember who is the next to restore because
  508. // we will zero out the entire structure later.
  509. //
  510. p = pRecordUpdate->next;
  511. break;
  512. }
  513. }
  514. if (! fReplaceExistingOne)
  515. {
  516. DBG_SAVE_FILE_LINE
  517. pRecordUpdate = new SetOfNodeRecordUpdates;
  518. if (NULL == pRecordUpdate)
  519. {
  520. ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: can't create set of node record updates, rc=%d", rc));
  521. rc = GCC_ALLOCATION_FAILURE;
  522. goto MyExit;
  523. }
  524. }
  525. //
  526. // Ensure everything here is clean.
  527. // We may fail in the middle of building this node record.
  528. //
  529. ::ZeroMemory(pRecordUpdate, sizeof(SetOfNodeRecordUpdates));
  530. if (! fReplaceExistingOne)
  531. {
  532. //
  533. // Hook to the linked list.
  534. //
  535. if (m_pNodeRecordUpdateSet == NULL)
  536. {
  537. m_pNodeRecordUpdateSet = pRecordUpdate;
  538. }
  539. else
  540. {
  541. // append to the list
  542. for (p = m_pNodeRecordUpdateSet; NULL != p->next; p = p->next)
  543. ;
  544. p->next = pRecordUpdate;
  545. }
  546. }
  547. else
  548. {
  549. ASSERT(NULL == pRecordUpdate->next); // just zero out
  550. // p could not NULL if the one being replaced is
  551. // the last one in the list.
  552. pRecordUpdate->next = p; // restore
  553. }
  554. /*
  555. * Initialize the update "next" pointer to NULL and set the
  556. * update value node ID equal to the node ID passed in.
  557. */
  558. // pRecordUpdate->next = NULL; // struct already zeroed out
  559. pRecordUpdate->value.node_id = node_id;
  560. if (update_type == ADD_RECORD)
  561. {
  562. pRecordUpdate->value.node_update.choice = NODE_ADD_RECORD_CHOSEN;
  563. node_record = &pRecordUpdate->value.node_update.u.node_add_record;
  564. }
  565. else if (update_type == REPLACE_RECORD)
  566. {
  567. pRecordUpdate->value.node_update.choice = NODE_REPLACE_RECORD_CHOSEN;
  568. node_record = &pRecordUpdate->value.node_update.u.node_replace_record;
  569. }
  570. else
  571. {
  572. pRecordUpdate->value.node_update.choice = NODE_REMOVE_RECORD_CHOSEN;
  573. }
  574. if (node_record != NULL)
  575. {
  576. // node_record->bit_mask = 0; // struct already zeroed out
  577. /*
  578. * Check to see if the superior node ID is present. If the
  579. * value is zero, then the record is for the top provider node
  580. * and the superior node ID does not need to be filled in.
  581. */
  582. if (lpRec->superior_node != 0)
  583. {
  584. node_record->bit_mask |= SUPERIOR_NODE_PRESENT;
  585. node_record->superior_node = lpRec->superior_node;
  586. }
  587. /*
  588. * Fill in the node type and node properties which are always
  589. * present.
  590. */
  591. node_record->node_type = lpRec->node_type;
  592. node_record->node_properties = lpRec->node_properties;
  593. /*
  594. ** This roster object must not go out of scope while this
  595. ** update record is still in use!
  596. */
  597. /*
  598. * Fill in the node name if it is present.
  599. */
  600. if (lpRec->pwszNodeName != NULL)
  601. {
  602. node_record->bit_mask |= NODE_NAME_PRESENT;
  603. node_record->node_name.value = lpRec->pwszNodeName;
  604. node_record->node_name.length = ::lstrlenW(lpRec->pwszNodeName);
  605. }
  606. /*
  607. * Fill in the participants list if it is present.
  608. */
  609. if (lpRec->participant_name_list != NULL)
  610. {
  611. node_record->bit_mask |= PARTICIPANTS_LIST_PRESENT;
  612. rc = BuildParticipantsListPDU (node_id,
  613. &(node_record->participants_list));
  614. if (GCC_NO_ERROR != rc)
  615. {
  616. ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: can't build participant list, rc=%d", rc));
  617. goto MyExit;
  618. }
  619. }
  620. /*
  621. * Fill in the site information if it is present.
  622. */
  623. if (lpRec->pwszSiteInfo != NULL)
  624. {
  625. node_record->bit_mask |= SITE_INFORMATION_PRESENT;
  626. node_record->site_information.value = lpRec->pwszSiteInfo;
  627. node_record->site_information.length = ::lstrlenW(lpRec->pwszSiteInfo);
  628. }
  629. /*
  630. * Fill in the network address if it is present.
  631. */
  632. if ((lpRec->network_address_list != NULL) && (rc == GCC_NO_ERROR))
  633. {
  634. node_record->bit_mask |= RECORD_NET_ADDRESS_PRESENT;
  635. rc = lpRec->network_address_list->GetNetworkAddressListPDU (
  636. &(node_record->record_net_address));
  637. if (GCC_NO_ERROR != rc)
  638. {
  639. ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: can't get network address list, rc=%d", rc));
  640. goto MyExit;
  641. }
  642. }
  643. /*
  644. * Fill in the alternative node ID if it is present.
  645. */
  646. if (lpRec->poszAltNodeID != NULL)
  647. {
  648. node_record->bit_mask |= ALTERNATIVE_NODE_ID_PRESENT;
  649. node_record->alternative_node_id.choice = H243_NODE_ID_CHOSEN;
  650. node_record->alternative_node_id.u.h243_node_id.length = lpRec->poszAltNodeID->length;
  651. ::CopyMemory(node_record->alternative_node_id.u.h243_node_id.value,
  652. lpRec->poszAltNodeID->value,
  653. node_record->alternative_node_id.u.h243_node_id.length);
  654. }
  655. /*
  656. * Fill in the user data list if it is present.
  657. */
  658. if (lpRec->user_data_list != NULL)
  659. {
  660. node_record->bit_mask |= RECORD_USER_DATA_PRESENT;
  661. rc = lpRec->user_data_list->GetUserDataPDU (&(node_record->record_user_data));
  662. }
  663. }
  664. }
  665. else
  666. {
  667. ERROR_OUT(("CConfRoster::BuildSetOfUpdatesPDU: invalid param"));
  668. rc = GCC_INVALID_PARAMETER;
  669. }
  670. MyExit:
  671. return (rc);
  672. }
  673. /*
  674. * GCCError BuildParticipantsListPDU ()
  675. *
  676. * Public Function Description
  677. * This routine is used to retrieve the "ParticipantList" portion of a
  678. * "RosterUpdateIndication" in the "PDU" form. The internally maintained
  679. * data is converted into the "PDU" form.
  680. *
  681. * Formal Parameters:
  682. * node_id - (i) Node ID of node record to get the
  683. * participant list from.
  684. * participants_list - (o) This is a pointer to the set of participant
  685. * list PDU structures to be filled in by this
  686. * routine.
  687. *
  688. * Return Value
  689. * GCC_NO_ERROR - No error occured.
  690. * GCC_ALLOCATION_FAILURE - A resource error occured.
  691. *
  692. * Side Effects
  693. * None.
  694. *
  695. * Caveats
  696. * None.
  697. */
  698. GCCError CConfRoster::BuildParticipantsListPDU(
  699. UserID node_id,
  700. PParticipantsList * participants_list)
  701. {
  702. GCCError rc = GCC_NO_ERROR;
  703. PParticipantsList new_participants_list;
  704. PParticipantsList old_participants_list;
  705. CONF_RECORD *lpRec;
  706. if (NULL != (lpRec = m_RecordList2.Find(node_id)))
  707. {
  708. LPWSTR PUstring;
  709. *participants_list = NULL;
  710. old_participants_list = NULL;
  711. lpRec->participant_name_list->Reset();
  712. while (NULL != (PUstring = lpRec->participant_name_list->Iterate()))
  713. {
  714. DBG_SAVE_FILE_LINE
  715. new_participants_list = new ParticipantsList;
  716. if (new_participants_list == NULL)
  717. {
  718. rc = GCC_ALLOCATION_FAILURE;
  719. FreeParticipantsListPDU (*participants_list);
  720. break;
  721. }
  722. if (*participants_list == NULL)
  723. *participants_list = new_participants_list;
  724. else
  725. old_participants_list->next = new_participants_list;
  726. /*
  727. * Save this pointer so that it's "next" pointer can be filled in
  728. * by the line above on the next pass through.
  729. */
  730. old_participants_list = new_participants_list;
  731. /*
  732. * Initialize the current "next" pointer to NULL in case this is
  733. * the last time through the loop.
  734. */
  735. new_participants_list->next = NULL;
  736. /*
  737. * Finally, put the participant list info. in the structure.
  738. */
  739. new_participants_list->value.value = PUstring;
  740. new_participants_list->value.length = ::lstrlenW(PUstring);
  741. }
  742. }
  743. else
  744. rc = GCC_INVALID_PARAMETER;
  745. return (rc);
  746. }
  747. /*
  748. * These routines are used to free up a roster update indication PDU.
  749. */
  750. /*
  751. * void FreeRosterUpdateIndicationPDU ()
  752. *
  753. * Private Function Description
  754. * This routine is responsible for freeing up all the data associated
  755. * with the PDU. This routine should be called each time a PDU is
  756. * obtained through the GetRosterUpdateIndicationPDU () routine.
  757. *
  758. * Formal Parameters:
  759. * None.
  760. *
  761. * Return Value
  762. * None.
  763. *
  764. * Side Effects
  765. * None.
  766. *
  767. * Caveats
  768. * None.
  769. */
  770. void CConfRoster::FreeRosterUpdateIndicationPDU(void)
  771. {
  772. if (m_NodeInformation.node_record_list.choice == NODE_RECORD_REFRESH_CHOSEN)
  773. {
  774. FreeSetOfRefreshesPDU ();
  775. }
  776. else if (m_NodeInformation.node_record_list.choice == NODE_RECORD_UPDATE_CHOSEN)
  777. {
  778. FreeSetOfUpdatesPDU ();
  779. }
  780. m_NodeInformation.node_record_list.choice = NODE_NO_CHANGE_CHOSEN;
  781. m_pNodeRecordUpdateSet = NULL;
  782. }
  783. /*
  784. * void FreeSetOfRefreshesPDU ()
  785. *
  786. * Private Function Description:
  787. * This routine is used to free up any data allocated to construct the
  788. * "PDU" form of the "SetOfRefreshes" portion of the RosterUpdateIndication
  789. * "PDU" structure.
  790. *
  791. * Formal Parameters:
  792. * None.
  793. *
  794. * Return Value
  795. * None.
  796. *
  797. * Side Effects
  798. * None.
  799. *
  800. * Caveats
  801. * None.
  802. */
  803. void CConfRoster::FreeSetOfRefreshesPDU(void)
  804. {
  805. PSetOfNodeRecordRefreshes pCurr, pNext;
  806. for (pCurr = m_NodeInformation.node_record_list.u.node_record_refresh;
  807. NULL != pCurr;
  808. pCurr = pNext)
  809. {
  810. pNext = pCurr->next;
  811. if (pCurr->value.node_record.bit_mask & PARTICIPANTS_LIST_PRESENT)
  812. {
  813. FreeParticipantsListPDU(pCurr->value.node_record.participants_list);
  814. }
  815. delete pCurr;
  816. }
  817. m_NodeInformation.node_record_list.u.node_record_refresh = NULL;
  818. m_RecordList2.CleanList();
  819. }
  820. /*
  821. * void FreeSetOfUpdatesPDU ()
  822. *
  823. * Private Function Description:
  824. * This routine is used to free up any data allocated to construct the
  825. * "PDU" form of the "SetOfUpdates" portion of the RosterUpdateIndication
  826. * "PDU" structure.
  827. *
  828. * Formal Parameters:
  829. * None.
  830. *
  831. * Return Value
  832. * None.
  833. *
  834. * Side Effects
  835. * None.
  836. *
  837. * Caveats
  838. * None.
  839. */
  840. void CConfRoster::
  841. CleanUpdateRecordPDU ( PSetOfNodeRecordUpdates pCurr)
  842. {
  843. /*
  844. * Check to see if the update is an "Add" or a "Replace".
  845. */
  846. if (pCurr->value.node_update.choice == NODE_ADD_RECORD_CHOSEN)
  847. {
  848. /*
  849. * Free the participants list memory if any exists.
  850. */
  851. if (pCurr->value.node_update.u.node_add_record.bit_mask & PARTICIPANTS_LIST_PRESENT)
  852. {
  853. FreeParticipantsListPDU(pCurr->value.node_update.u.node_add_record.participants_list);
  854. }
  855. }
  856. else if (pCurr->value.node_update.choice == NODE_REPLACE_RECORD_CHOSEN)
  857. {
  858. /*
  859. * Free the participants list memory if any exists.
  860. */
  861. if (pCurr->value.node_update.u.node_replace_record.bit_mask & PARTICIPANTS_LIST_PRESENT)
  862. {
  863. FreeParticipantsListPDU(pCurr->value.node_update.u.node_replace_record.participants_list);
  864. }
  865. }
  866. }
  867. void CConfRoster::FreeSetOfUpdatesPDU(void)
  868. {
  869. PSetOfNodeRecordUpdates pCurr, pNext;
  870. //PSetOfNodeRecordUpdates current_record_update;
  871. for (pCurr = m_NodeInformation.node_record_list.u.node_record_update;
  872. NULL != pCurr;
  873. pCurr = pNext)
  874. {
  875. pNext = pCurr->next;
  876. CleanUpdateRecordPDU(pCurr);
  877. delete pCurr;
  878. }
  879. m_NodeInformation.node_record_list.u.node_record_update = NULL;
  880. m_RecordList2.CleanList();
  881. }
  882. void CConfRecordList2::CleanList(void)
  883. {
  884. CONF_RECORD *lpRec;
  885. /*
  886. * Iterate through the internal list of Record structures telling each
  887. * CUserDataListContainer object in the Record to free up it's PDU data.
  888. */
  889. Reset();
  890. while (NULL != (lpRec = Iterate()))
  891. {
  892. if (lpRec->user_data_list != NULL)
  893. {
  894. lpRec->user_data_list->FreeUserDataListPDU();
  895. }
  896. if (lpRec->network_address_list != NULL)
  897. {
  898. lpRec->network_address_list->FreeNetworkAddressListPDU();
  899. }
  900. }
  901. }
  902. /*
  903. * void FreeParticipantsListPDU ()
  904. *
  905. * Private Function Description
  906. * This routine is used to free up any data allocated to construct the
  907. * "PDU" form of the "ParticipantList" portion of the
  908. * RosterUpdateIndication "PDU" structure.
  909. *
  910. * Formal Parameters:
  911. * participants_list - (i/o) This is the participant list PDU
  912. * to free up.
  913. *
  914. * Return Value
  915. * None.
  916. *
  917. * Side Effects
  918. * None.
  919. *
  920. * Caveats
  921. * None.
  922. */
  923. void CConfRoster::FreeParticipantsListPDU(
  924. PParticipantsList participants_list)
  925. {
  926. PParticipantsList pCurr, pNext;
  927. for (pCurr = participants_list; NULL != pCurr; pCurr = pNext)
  928. {
  929. pNext = pCurr->next;
  930. delete pCurr;
  931. }
  932. }
  933. /*
  934. * These routines process roster update indication PDUs.
  935. */
  936. /*
  937. * GCCError ProcessRosterUpdateIndicationPDU ()
  938. *
  939. * Public Function Description:
  940. * This routine is used process a RosterUpdateIndication PDU by saving the
  941. * data in the internal format.
  942. */
  943. GCCError CConfRoster::ProcessRosterUpdateIndicationPDU(
  944. PNodeInformation node_information,
  945. UserID sender_id)
  946. {
  947. GCCError rc = GCC_NO_ERROR;
  948. CUidList node_delete_list;
  949. /*
  950. ** Free up the old PDU data here if it is being maintained and the
  951. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  952. ** back to FALSE so that the new PDU will be maintained until it is
  953. ** flushed.
  954. */
  955. if (m_fPduFlushed)
  956. {
  957. FreeRosterUpdateIndicationPDU ();
  958. m_fPduFlushed = FALSE;
  959. }
  960. /*
  961. ** If this is a conference roster update and refresh is chosen we must
  962. ** clear out the entire list and rebuild it.
  963. */
  964. if (node_information->node_record_list.choice == NODE_RECORD_REFRESH_CHOSEN)
  965. {
  966. m_fRosterChanged = TRUE;
  967. /*
  968. ** If this refresh came from the top provider we must clear out the
  969. ** entire roster to prepare for the new roster list. If it was NOT
  970. ** sent by the Top Provider, we must determine which sub tree is
  971. ** affected and clear out this particular sub tree.
  972. */
  973. if (sender_id == m_uidTopProvider)
  974. {
  975. ClearRecordList();
  976. }
  977. else
  978. {
  979. rc = GetNodeSubTree(sender_id, &node_delete_list);
  980. if (rc == GCC_NO_ERROR)
  981. {
  982. UserID uid;
  983. // Clear out the affected nodes
  984. node_delete_list.Reset();
  985. while (GCC_INVALID_UID != (uid = node_delete_list.Iterate()))
  986. {
  987. DeleteRecord(uid);
  988. }
  989. }
  990. }
  991. /*
  992. ** Increment the instance number if this node is the top provider or
  993. ** a local roster otherwise get the instance number from the PDU.
  994. */
  995. if (rc == GCC_NO_ERROR)
  996. {
  997. if ((m_fTopProvider) || (m_fLocalRoster))
  998. {
  999. m_nInstanceNumber++;
  1000. }
  1001. else
  1002. {
  1003. m_nInstanceNumber = node_information->roster_instance_number;
  1004. }
  1005. if (m_fNodesAdded == FALSE)
  1006. {
  1007. m_fNodesAdded = node_information->nodes_are_added;
  1008. }
  1009. if (m_fNodesRemoved == FALSE)
  1010. {
  1011. m_fNodesRemoved = node_information->nodes_are_removed;
  1012. }
  1013. rc = ProcessSetOfRefreshesPDU(node_information->node_record_list.u.node_record_refresh);
  1014. }
  1015. }
  1016. else if (node_information->node_record_list.choice == NODE_RECORD_UPDATE_CHOSEN)
  1017. {
  1018. m_fRosterChanged = TRUE;
  1019. /*
  1020. ** Increment the instance number if this node is the top provider or
  1021. ** a local roster otherwise get the instance number from the PDU.
  1022. */
  1023. if ((m_fTopProvider) || (m_fLocalRoster))
  1024. {
  1025. m_nInstanceNumber++;
  1026. }
  1027. else
  1028. {
  1029. m_nInstanceNumber = node_information->roster_instance_number;
  1030. }
  1031. if (m_fNodesAdded == FALSE)
  1032. {
  1033. m_fNodesAdded = node_information->nodes_are_added;
  1034. }
  1035. if (m_fNodesRemoved == FALSE)
  1036. {
  1037. m_fNodesRemoved = node_information->nodes_are_removed;
  1038. }
  1039. rc = ProcessSetOfUpdatesPDU(node_information->node_record_list.u.node_record_update);
  1040. }
  1041. return (rc);
  1042. }
  1043. /*
  1044. * GCCError ProcessSetOfRefreshesPDU ()
  1045. *
  1046. * Private Function Description:
  1047. * This routine is used process the SetOfRefreshes portion of a
  1048. * RosterUpdateIndication PDU by saving the data in the internal format.
  1049. *
  1050. * Formal Parameters:
  1051. * record_refresh - (i) Refresh PDU data to process.
  1052. *
  1053. * Return Value
  1054. * GCC_NO_ERROR - No error occured.
  1055. * GCC_ALLOCATION_FAILURE - A resource error occured.
  1056. *
  1057. * Side Effects
  1058. * None.
  1059. *
  1060. * Caveats
  1061. * None.
  1062. */
  1063. GCCError CConfRoster::ProcessSetOfRefreshesPDU(
  1064. PSetOfNodeRecordRefreshes record_refresh)
  1065. {
  1066. GCCError rc = GCC_NO_ERROR;
  1067. PSetOfNodeRecordRefreshes current_record_refresh;
  1068. UserID node_id;
  1069. CONF_RECORD *internal_record = NULL;
  1070. if (record_refresh != NULL)
  1071. {
  1072. current_record_refresh = record_refresh;
  1073. while ((current_record_refresh != NULL) &&
  1074. (rc == GCC_NO_ERROR))
  1075. {
  1076. node_id = (UserID)current_record_refresh->value.node_id;
  1077. /*
  1078. * Create and fill in the new internal conference record.
  1079. */
  1080. DBG_SAVE_FILE_LINE
  1081. internal_record = new CONF_RECORD;
  1082. if (internal_record == NULL)
  1083. {
  1084. ERROR_OUT(("CConfRoster::ProcessSetOfRefreshesPDU: Error "
  1085. "creating new Record"));
  1086. rc = GCC_ALLOCATION_FAILURE;
  1087. break;
  1088. }
  1089. /*
  1090. * Fill in the superior node ID if it is present.
  1091. */
  1092. if (current_record_refresh->value.node_record.bit_mask &
  1093. SUPERIOR_NODE_PRESENT)
  1094. {
  1095. internal_record->superior_node = current_record_refresh->
  1096. value.node_record.superior_node;
  1097. }
  1098. else
  1099. {
  1100. ASSERT(0 == internal_record->superior_node);
  1101. }
  1102. /*
  1103. * Fill in the node type and node properties which are always
  1104. * present.
  1105. */
  1106. internal_record->node_type = current_record_refresh->
  1107. value.node_record.node_type;
  1108. internal_record->node_properties = current_record_refresh->
  1109. value.node_record.node_properties;
  1110. /*
  1111. * Fill in the node name if it is present.
  1112. */
  1113. if (current_record_refresh->value.node_record.bit_mask & NODE_NAME_PRESENT)
  1114. {
  1115. if (NULL == (internal_record->pwszNodeName = ::My_strdupW2(
  1116. current_record_refresh->value.node_record.node_name.length,
  1117. current_record_refresh->value.node_record.node_name.value)))
  1118. {
  1119. rc = GCC_ALLOCATION_FAILURE;
  1120. }
  1121. }
  1122. else
  1123. {
  1124. ASSERT(NULL == internal_record->pwszNodeName);
  1125. }
  1126. /*
  1127. * Fill in the participants name list if it is present.
  1128. */
  1129. if ((rc == GCC_NO_ERROR) &&
  1130. (current_record_refresh->value.node_record.bit_mask &
  1131. PARTICIPANTS_LIST_PRESENT))
  1132. {
  1133. rc = ProcessParticipantsListPDU (
  1134. current_record_refresh->
  1135. value.node_record.participants_list,
  1136. internal_record);
  1137. }
  1138. else
  1139. {
  1140. ASSERT(NULL == internal_record->participant_name_list);
  1141. }
  1142. /*
  1143. * Fill in the site information if it is present.
  1144. */
  1145. if ((rc == GCC_NO_ERROR) &&
  1146. (current_record_refresh->value.node_record.bit_mask & SITE_INFORMATION_PRESENT))
  1147. {
  1148. if (NULL == (internal_record->pwszSiteInfo = ::My_strdupW2(
  1149. current_record_refresh->value.node_record.site_information.length,
  1150. current_record_refresh->value.node_record.site_information.value)))
  1151. {
  1152. rc = GCC_ALLOCATION_FAILURE;
  1153. }
  1154. }
  1155. else
  1156. {
  1157. ASSERT(NULL == internal_record->pwszSiteInfo);
  1158. }
  1159. /*
  1160. * Fill in the network address if it is present. The network
  1161. * address is maintained internally as a CNetAddrListContainer object
  1162. * which is constructed here from the PDU "SetOfNetworkAddresses"
  1163. * structure. If an error occurs in constructing the object, set
  1164. * the Record's network address list pointer to NULL.
  1165. */
  1166. if ((rc == GCC_NO_ERROR) &&
  1167. (current_record_refresh->value.node_record.bit_mask &
  1168. RECORD_NET_ADDRESS_PRESENT))
  1169. {
  1170. DBG_SAVE_FILE_LINE
  1171. internal_record->network_address_list = new CNetAddrListContainer(
  1172. current_record_refresh->value.node_record.record_net_address,
  1173. &rc);
  1174. if ((internal_record->network_address_list == NULL) ||
  1175. (rc != GCC_NO_ERROR))
  1176. {
  1177. rc = GCC_ALLOCATION_FAILURE;
  1178. }
  1179. }
  1180. else
  1181. {
  1182. ASSERT(NULL == internal_record->network_address_list);
  1183. }
  1184. /*
  1185. * Fill in the alternative node ID if it is present.
  1186. */
  1187. if ((rc == GCC_NO_ERROR) &&
  1188. (current_record_refresh->value.node_record.bit_mask &
  1189. ALTERNATIVE_NODE_ID_PRESENT))
  1190. {
  1191. if (NULL == (internal_record->poszAltNodeID = ::My_strdupO2(
  1192. current_record_refresh->value.node_record.
  1193. alternative_node_id.u.h243_node_id.value,
  1194. current_record_refresh->value.node_record.
  1195. alternative_node_id.u.h243_node_id.length)))
  1196. {
  1197. rc = GCC_ALLOCATION_FAILURE;
  1198. }
  1199. }
  1200. else
  1201. {
  1202. ASSERT(NULL == internal_record->poszAltNodeID);
  1203. }
  1204. /*
  1205. * Fill in the user data if it is present. The user data is
  1206. * maintained internally as a CUserDataListContainer object which is
  1207. * constructed here from the PDU "SetOfUserData" structure. If an
  1208. * error occurs in constructing the object, set the Record's user
  1209. * data pointer to NULL.
  1210. */
  1211. if ((rc == GCC_NO_ERROR) &&
  1212. (current_record_refresh->value.node_record.bit_mask &
  1213. RECORD_USER_DATA_PRESENT))
  1214. {
  1215. DBG_SAVE_FILE_LINE
  1216. internal_record->user_data_list = new CUserDataListContainer(
  1217. current_record_refresh->value.node_record.record_user_data,
  1218. &rc);
  1219. if ((internal_record->user_data_list == NULL) ||
  1220. (rc != GCC_NO_ERROR))
  1221. {
  1222. rc = GCC_ALLOCATION_FAILURE;
  1223. }
  1224. }
  1225. else
  1226. {
  1227. ASSERT(NULL == internal_record->user_data_list);
  1228. }
  1229. /*
  1230. * If the Record was successfully filled in, add it to the internal
  1231. * Rogue Wave list.
  1232. */
  1233. if (rc == GCC_NO_ERROR)
  1234. {
  1235. m_RecordList2.Append(node_id, internal_record);
  1236. current_record_refresh = current_record_refresh->next;
  1237. }
  1238. }
  1239. }
  1240. /*
  1241. ** Build a full refresh PDU here if no errors occured while processing
  1242. ** the refresh PDU.
  1243. */
  1244. if (rc == GCC_NO_ERROR)
  1245. {
  1246. rc = BuildRosterUpdateIndicationPDU(FULL_REFRESH, 0);
  1247. }
  1248. else
  1249. {
  1250. delete internal_record;
  1251. }
  1252. return (rc);
  1253. }
  1254. /*
  1255. * GCCError ProcessSetOfUpdatesPDU ()
  1256. *
  1257. * Private Function Description:
  1258. * This routine is used process the SetOfUpdates portion of a
  1259. * RosterUpdateIndication PDU by saving the data in the internal format.
  1260. *
  1261. * Formal Parameters:
  1262. * record_update - (i) Update PDU data to process.
  1263. *
  1264. * Return Value
  1265. * GCC_NO_ERROR - No error occured.
  1266. * GCC_ALLOCATION_FAILURE - A resource error occured.
  1267. *
  1268. * Side Effects
  1269. * None.
  1270. *
  1271. * Caveats
  1272. * None.
  1273. */
  1274. GCCError CConfRoster::ProcessSetOfUpdatesPDU(
  1275. PSetOfNodeRecordUpdates record_update)
  1276. {
  1277. GCCError rc = GCC_NO_ERROR;
  1278. PSetOfNodeRecordUpdates current_record_update;
  1279. UserID node_id;
  1280. PNodeRecord node_record;
  1281. CONF_RECORD *internal_record;
  1282. CONF_ROSTER_UPDATE_TYPE update_type;
  1283. if (record_update != NULL)
  1284. {
  1285. current_record_update = record_update;
  1286. while ((current_record_update != NULL) &&
  1287. (rc == GCC_NO_ERROR))
  1288. {
  1289. internal_record = NULL;
  1290. node_id = (UserID)current_record_update->value.node_id;
  1291. // Create and fill in the new conference record.
  1292. if (current_record_update->value.node_update.choice ==
  1293. NODE_ADD_RECORD_CHOSEN)
  1294. {
  1295. // Add the record.
  1296. if (! m_RecordList2.Find(node_id))
  1297. {
  1298. node_record = &current_record_update->value.node_update.u.node_add_record;
  1299. update_type = ADD_RECORD;
  1300. }
  1301. else
  1302. {
  1303. node_record = NULL;
  1304. ERROR_OUT(("CConfRoster: ProcessSetOfUpdatesPDU: can't add record"));
  1305. }
  1306. }
  1307. else if (current_record_update->value.node_update.choice ==
  1308. NODE_REPLACE_RECORD_CHOSEN)
  1309. {
  1310. // Replace the record.
  1311. if (m_RecordList2.Find(node_id))
  1312. {
  1313. DeleteRecord (node_id);
  1314. node_record = &current_record_update->
  1315. value.node_update.u.node_replace_record;
  1316. update_type = REPLACE_RECORD;
  1317. }
  1318. else
  1319. {
  1320. node_record = NULL;
  1321. WARNING_OUT(("CConfRoster: ProcessSetOfUpdatesPDU: "
  1322. "ASSERTION: Replace record failed"));
  1323. }
  1324. }
  1325. else
  1326. {
  1327. // Remove the record.
  1328. if (m_RecordList2.Find(node_id))
  1329. {
  1330. DeleteRecord (node_id);
  1331. update_type = DELETE_RECORD;
  1332. }
  1333. else
  1334. {
  1335. ERROR_OUT(("CConfRoster: ProcessSetOfUpdatesPDU: can't delete record"));
  1336. }
  1337. node_record = NULL;
  1338. }
  1339. /*
  1340. ** Process the conference record if one exists. Create a new
  1341. ** node record to be filled in and added to the internal record
  1342. ** list.
  1343. */
  1344. if (node_record != NULL)
  1345. {
  1346. DBG_SAVE_FILE_LINE
  1347. internal_record = new CONF_RECORD;
  1348. if (internal_record == NULL)
  1349. {
  1350. ERROR_OUT(("CConfRoster::ProcessSetOfUpdatesPDU: can't create new record"));
  1351. rc = GCC_ALLOCATION_FAILURE;
  1352. break;
  1353. }
  1354. // Fill in the superior node ID if it is present.
  1355. if (node_record->bit_mask & SUPERIOR_NODE_PRESENT)
  1356. {
  1357. internal_record->superior_node = node_record->superior_node;
  1358. }
  1359. else
  1360. {
  1361. ASSERT(0 == internal_record->superior_node);
  1362. }
  1363. /*
  1364. ** Fill in the node type and node properties which are always
  1365. ** present.
  1366. */
  1367. internal_record->node_type = node_record->node_type;
  1368. internal_record->node_properties = node_record->node_properties;
  1369. // Fill in the node name if it is present.
  1370. if (node_record->bit_mask & NODE_NAME_PRESENT)
  1371. {
  1372. if (NULL == (internal_record->pwszNodeName = ::My_strdupW2(
  1373. node_record->node_name.length,
  1374. node_record->node_name.value)))
  1375. {
  1376. rc = GCC_ALLOCATION_FAILURE;
  1377. }
  1378. }
  1379. else
  1380. {
  1381. ASSERT(NULL == internal_record->pwszNodeName);
  1382. }
  1383. // Fill in the participants list if it is present.
  1384. if ((rc == GCC_NO_ERROR) &&
  1385. (node_record->bit_mask & PARTICIPANTS_LIST_PRESENT))
  1386. {
  1387. rc = ProcessParticipantsListPDU(node_record->participants_list,
  1388. internal_record);
  1389. }
  1390. else
  1391. {
  1392. ASSERT(NULL == internal_record->participant_name_list);
  1393. }
  1394. // Fill in the site information if it is present.
  1395. if ((rc == GCC_NO_ERROR) &&
  1396. (node_record->bit_mask & SITE_INFORMATION_PRESENT))
  1397. {
  1398. if (NULL == (internal_record->pwszSiteInfo = ::My_strdupW2(
  1399. node_record->site_information.length,
  1400. node_record->site_information.value)))
  1401. {
  1402. rc = GCC_ALLOCATION_FAILURE;
  1403. }
  1404. }
  1405. else
  1406. {
  1407. ASSERT(NULL == internal_record->pwszSiteInfo);
  1408. }
  1409. /*
  1410. ** Fill in the network address if it is present. The network
  1411. ** address is maintained internally as a CNetAddrListContainer
  1412. ** object which is constructed here from the PDU
  1413. ** "SetOfNetworkAddresses" structure. If an error occurs
  1414. ** in constructing the object, set the Record's network address
  1415. ** list pointer to NULL.
  1416. */
  1417. if ((rc == GCC_NO_ERROR) &&
  1418. (node_record->bit_mask & RECORD_NET_ADDRESS_PRESENT))
  1419. {
  1420. DBG_SAVE_FILE_LINE
  1421. internal_record->network_address_list =
  1422. new CNetAddrListContainer(node_record->record_net_address, &rc);
  1423. if ((internal_record->network_address_list == NULL) ||
  1424. (rc != GCC_NO_ERROR))
  1425. {
  1426. rc = GCC_ALLOCATION_FAILURE;
  1427. }
  1428. }
  1429. else
  1430. {
  1431. ASSERT(NULL == internal_record->network_address_list);
  1432. }
  1433. /*
  1434. * Fill in the alternative node ID if it is present.
  1435. */
  1436. if ((rc == GCC_NO_ERROR) &&
  1437. (node_record->bit_mask & ALTERNATIVE_NODE_ID_PRESENT))
  1438. {
  1439. if (NULL == (internal_record->poszAltNodeID = ::My_strdupO2(
  1440. node_record->alternative_node_id.u.h243_node_id.value,
  1441. node_record->alternative_node_id.u.h243_node_id.length)))
  1442. {
  1443. rc = GCC_ALLOCATION_FAILURE;
  1444. }
  1445. }
  1446. else
  1447. {
  1448. ASSERT(NULL == internal_record->poszAltNodeID);
  1449. }
  1450. /*
  1451. * Fill in the user data if it is present. The user data is
  1452. * maintained internally as a CUserDataListContainer object which is
  1453. * constructed here from the PDU "SetOfUserData" structure. If
  1454. * an error occurs in constructing the object, set the Record's
  1455. * user data pointer to NULL.
  1456. */
  1457. if ((rc == GCC_NO_ERROR) &&
  1458. (node_record->bit_mask & RECORD_USER_DATA_PRESENT))
  1459. {
  1460. DBG_SAVE_FILE_LINE
  1461. internal_record->user_data_list = new CUserDataListContainer(
  1462. node_record->record_user_data,
  1463. &rc);
  1464. if ((internal_record->user_data_list == NULL) ||
  1465. (rc != GCC_NO_ERROR))
  1466. {
  1467. rc = GCC_ALLOCATION_FAILURE;
  1468. }
  1469. }
  1470. else
  1471. {
  1472. ASSERT(NULL == internal_record->user_data_list);
  1473. }
  1474. }
  1475. /*
  1476. ** Here we add this update to our PDU and jump to the next update
  1477. ** in the PDU currently being processed.
  1478. */
  1479. if (rc == GCC_NO_ERROR)
  1480. {
  1481. /*
  1482. ** If the Record was successfully filled in, add it to the
  1483. ** internal Rogue Wave list.
  1484. */
  1485. if (internal_record != NULL)
  1486. {
  1487. m_RecordList2.Append(node_id, internal_record);
  1488. }
  1489. // Build the PDU from the above update.
  1490. rc = BuildRosterUpdateIndicationPDU(update_type, node_id);
  1491. if (rc == GCC_NO_ERROR)
  1492. {
  1493. current_record_update = current_record_update->next;
  1494. }
  1495. }
  1496. else
  1497. {
  1498. delete internal_record;
  1499. }
  1500. }
  1501. }
  1502. return (rc);
  1503. }
  1504. /*
  1505. * GCCError ProcessParticipantsListPDU ()
  1506. *
  1507. * Private Function Description:
  1508. * This routine is used process the ParticipantsList portion of an
  1509. * incoming RosterUpdateIndication PDU by saving the data in the internal
  1510. * format.
  1511. *
  1512. * Formal Parameters:
  1513. * participants_list - (i) Participant List PDU data to process.
  1514. *
  1515. * Return Value
  1516. * GCC_NO_ERROR - No error occured.
  1517. * GCC_ALLOCATION_FAILURE - A resource error occured.
  1518. *
  1519. * Side Effects
  1520. * None.
  1521. *
  1522. * Caveats
  1523. * None.
  1524. */
  1525. GCCError CConfRoster::ProcessParticipantsListPDU (
  1526. PParticipantsList participants_list,
  1527. CONF_RECORD *node_record)
  1528. {
  1529. GCCError rc = GCC_NO_ERROR;
  1530. PParticipantsList pCurr;
  1531. LPWSTR pwszParticipantName;
  1532. /*
  1533. * Clear the current list.
  1534. */
  1535. DBG_SAVE_FILE_LINE
  1536. node_record->participant_name_list = new CParticipantNameList;
  1537. if (node_record->participant_name_list == NULL)
  1538. return (GCC_ALLOCATION_FAILURE);
  1539. for (pCurr = participants_list; NULL != pCurr; pCurr = pCurr->next)
  1540. {
  1541. if (NULL != (pwszParticipantName = ::My_strdupW2(pCurr->value.length, pCurr->value.value)))
  1542. {
  1543. (node_record->participant_name_list)->Append(pwszParticipantName);
  1544. }
  1545. else
  1546. {
  1547. rc = GCC_ALLOCATION_FAILURE;
  1548. break;
  1549. }
  1550. }
  1551. return (rc);
  1552. }
  1553. /*
  1554. * Utilities that operate on conference records.
  1555. */
  1556. /*
  1557. * UINT LockConferenceRoster ()
  1558. *
  1559. * Public Function Description:
  1560. * This routine is used "lock" the CConfRoster data in the "API"
  1561. * form. The "API" version of the CConfRoster is built from the
  1562. * internally maintained data.
  1563. */
  1564. UINT CConfRoster::LockConferenceRoster(void)
  1565. {
  1566. CONF_RECORD *internal_node_record;
  1567. if (Lock() == 1)
  1568. {
  1569. //CONF_RECORD *lpRec;
  1570. /*
  1571. * Set aside memory to hold the conference roster, the pointers to the
  1572. * GCCNodeRecord structures and the GCCNodeRecord structures themselves.
  1573. * The "sizeof" the structure must be rounded to an even four-byte
  1574. * boundary.
  1575. */
  1576. m_cbDataMemorySize = ROUNDTOBOUNDARY (sizeof (GCCConferenceRoster));
  1577. m_cbDataMemorySize += m_RecordList2.GetCount() *
  1578. (sizeof(PGCCNodeRecord) + ROUNDTOBOUNDARY (sizeof(GCCNodeRecord)) );
  1579. m_RecordList2.Reset();
  1580. while (NULL != (internal_node_record = m_RecordList2.Iterate()))
  1581. {
  1582. /*
  1583. * Add the size of the node name Unicode String, if it exists.
  1584. * Space must be allowed for the NULL terminator of the string.
  1585. */
  1586. if (internal_node_record->pwszNodeName != NULL)
  1587. {
  1588. m_cbDataMemorySize += ROUNDTOBOUNDARY(
  1589. (::lstrlenW(internal_node_record->pwszNodeName) + 1) * sizeof(WCHAR));
  1590. }
  1591. /*
  1592. * Add the amount of memory needed to hold the pointers to the
  1593. * list of participants, if it exists. Also add the total amount
  1594. * of memory needed to hold the participant list data.
  1595. */
  1596. if (internal_node_record->participant_name_list != NULL)
  1597. {
  1598. LPWSTR lpUstring;
  1599. m_cbDataMemorySize += internal_node_record->participant_name_list->GetCount() * sizeof(LPWSTR);
  1600. /*
  1601. * Set up an iterator for the participant name list in order to
  1602. * add the amount of memory necessary to hold each Unicode
  1603. * String. Space must be allowed for the strings' NULL
  1604. * terminators.
  1605. */
  1606. internal_node_record->participant_name_list->Reset();
  1607. while (NULL != (lpUstring = internal_node_record->participant_name_list->Iterate()))
  1608. {
  1609. m_cbDataMemorySize += ROUNDTOBOUNDARY(
  1610. (::lstrlenW(lpUstring) + 1) * sizeof(WCHAR));
  1611. }
  1612. }
  1613. /*
  1614. * Add the size of the site information Unicode String, if it
  1615. * exists. Space must be allowed for the NULL terminator of
  1616. * the string.
  1617. */
  1618. if (internal_node_record->pwszSiteInfo != NULL)
  1619. {
  1620. m_cbDataMemorySize += ROUNDTOBOUNDARY(
  1621. (::lstrlenW(internal_node_record->pwszSiteInfo) + 1) * sizeof(WCHAR));
  1622. }
  1623. /*
  1624. * If a network address list is present, lock the internal network
  1625. * address list object in order to find the amount of memory
  1626. * required by the list.
  1627. */
  1628. if (internal_node_record->network_address_list != NULL)
  1629. {
  1630. m_cbDataMemorySize += internal_node_record->
  1631. network_address_list->LockNetworkAddressList ();
  1632. }
  1633. /*
  1634. * Add the space necessary to hold the alternative node ID octet
  1635. * string structure as well as the string data, if it exists.
  1636. */
  1637. if (internal_node_record->poszAltNodeID != NULL)
  1638. {
  1639. m_cbDataMemorySize += ROUNDTOBOUNDARY(sizeof(OSTR));
  1640. m_cbDataMemorySize += ROUNDTOBOUNDARY(internal_node_record->poszAltNodeID->length);
  1641. }
  1642. /*
  1643. * If a user data list is present, lock the internal user data
  1644. * list object in order to find the amount of memory required by
  1645. * the list.
  1646. */
  1647. if (internal_node_record->user_data_list != NULL)
  1648. {
  1649. m_cbDataMemorySize += internal_node_record->user_data_list->LockUserDataList ();
  1650. }
  1651. }
  1652. }
  1653. return m_cbDataMemorySize;
  1654. }
  1655. /*
  1656. * void UnLockConferenceRoster ()
  1657. *
  1658. * Public Function Description:
  1659. * This routine is used to "unlock" the CConfRoster "API" data. The
  1660. * lock count is decremented each time the routine is called and the "API"
  1661. * data will actually be freed when the lock count reaches zero.
  1662. */
  1663. void CConfRoster::UnLockConferenceRoster(void)
  1664. {
  1665. if (Unlock(FALSE) == 0)
  1666. {
  1667. CONF_RECORD *lpRec;
  1668. /*
  1669. ** Set up an iterator in order to unlock any internal data
  1670. ** containers
  1671. ** which have been locked.
  1672. */
  1673. m_RecordList2.Reset();
  1674. while (NULL != (lpRec = m_RecordList2.Iterate()))
  1675. {
  1676. /*
  1677. * Unlock the network address list if it exists.
  1678. */
  1679. if (lpRec->network_address_list != NULL)
  1680. {
  1681. lpRec->network_address_list->UnLockNetworkAddressList ();
  1682. }
  1683. /*
  1684. * Unlock the user data list if it exists.
  1685. */
  1686. if (lpRec->user_data_list != NULL)
  1687. {
  1688. lpRec->user_data_list->UnLockUserDataList ();
  1689. }
  1690. }
  1691. }
  1692. // we have to call Release() because we used Unlock(FALSE)
  1693. Release();
  1694. }
  1695. /*
  1696. * UINT GetConfRoster ()
  1697. *
  1698. * Public Function Description:
  1699. * This routine is called in order to retrieve the CConfRoster data
  1700. * in "API" form. The CConfRoster data must first be "locked" before
  1701. * this routine may be called.
  1702. */
  1703. UINT CConfRoster::GetConfRoster(
  1704. PGCCConferenceRoster * conference_roster,
  1705. LPBYTE memory)
  1706. {
  1707. UINT rc;
  1708. /*
  1709. * If the user data has been locked, fill in the output parameters and
  1710. * the data referenced by the pointers. Otherwise, report that the object
  1711. * has yet to be locked into the "API" form.
  1712. */
  1713. if (GetLockCount() > 0)
  1714. {
  1715. UINT total_data_length = 0;
  1716. UINT data_length = 0;
  1717. UINT node_record_counter = 0;
  1718. PGCCNodeRecord node_record;
  1719. PGCCConferenceRoster roster;
  1720. CONF_RECORD *internal_record;
  1721. UserID node_id;
  1722. USHORT i;
  1723. /*
  1724. * Fill in the output length parameter which indicates how much data
  1725. * referenced outside the structure will be written.
  1726. */
  1727. rc = m_cbDataMemorySize;
  1728. /*
  1729. * Set the conference roster pointer equal to the memory pointer passed
  1730. * in. This is where the conference roster structure will be built.
  1731. * Save the conference roster pointer for convienence.
  1732. */
  1733. *conference_roster = (PGCCConferenceRoster)memory;
  1734. roster = *conference_roster;
  1735. /*
  1736. * Fill in all of the elements of the conference roster except for
  1737. * the node record list.
  1738. */
  1739. roster->instance_number = (USHORT)m_nInstanceNumber;
  1740. roster->nodes_were_added = m_fNodesAdded;
  1741. roster->nodes_were_removed = m_fNodesRemoved;
  1742. roster->number_of_records = (USHORT) m_RecordList2.GetCount();
  1743. /*
  1744. * The "total_data_length" will hold the total amount of data written
  1745. * into memory. Save the amount of memory needed to hold the
  1746. * conference roster. Add the amount of memory necessary to hold the
  1747. * node record pointers and structures.
  1748. */
  1749. data_length = ROUNDTOBOUNDARY(sizeof(GCCConferenceRoster));
  1750. total_data_length = data_length + m_RecordList2.GetCount() *
  1751. (ROUNDTOBOUNDARY(sizeof(GCCNodeRecord)) + sizeof(PGCCNodeRecord));
  1752. /*
  1753. * Move the memory pointer past the conference roster structure. This
  1754. * is where the node record pointer list will be written.
  1755. */
  1756. memory += data_length;
  1757. /*
  1758. * Set the roster's node record list pointer.
  1759. */
  1760. roster->node_record_list = (PGCCNodeRecord *)memory;
  1761. /*
  1762. * Move the memory pointer past the list of node record pointers.
  1763. */
  1764. memory += (m_RecordList2.GetCount() * sizeof(PGCCNodeRecord));
  1765. /*
  1766. * Iterate through the internal list of record structures, building
  1767. * "API" GCCNodeRecord structures in memory.
  1768. */
  1769. m_RecordList2.Reset();
  1770. while (NULL != (internal_record = m_RecordList2.Iterate(&node_id)))
  1771. {
  1772. /*
  1773. * Save the pointer to the node record structure in the list
  1774. * of pointers. Get the internal node record from the list.
  1775. */
  1776. node_record = (PGCCNodeRecord)memory;
  1777. roster->node_record_list[node_record_counter++] = node_record;
  1778. /*
  1779. * Fill in the node ID and the superior node ID.
  1780. */
  1781. node_record->node_id = node_id;
  1782. node_record->superior_node_id = internal_record->superior_node;
  1783. /*
  1784. * Fill in the node type and the node properties.
  1785. */
  1786. GetNodeTypeAndProperties (
  1787. internal_record->node_type,
  1788. internal_record->node_properties,
  1789. &node_record->node_type,
  1790. &node_record->node_properties);
  1791. /*
  1792. * Move the memory pointer past the node record structure. This is
  1793. * where the node name unicode string will be written, if it exists.
  1794. */
  1795. memory += ROUNDTOBOUNDARY(sizeof(GCCNodeRecord));
  1796. if (internal_record->pwszNodeName != NULL)
  1797. {
  1798. /*
  1799. * Set the record's node name pointer and copy the node name
  1800. * data into memory from the internal unicode string. Be sure
  1801. * to copy the strings NULL terminating character. Move the
  1802. * memory pointer past the node name string data.
  1803. */
  1804. node_record->node_name = (LPWSTR) memory;
  1805. UINT cbStrSize = (::lstrlenW(internal_record->pwszNodeName) + 1) * sizeof(WCHAR);
  1806. ::CopyMemory(memory, internal_record->pwszNodeName, cbStrSize);
  1807. total_data_length += ROUNDTOBOUNDARY(cbStrSize);
  1808. memory += (Int) ROUNDTOBOUNDARY(cbStrSize);
  1809. }
  1810. else
  1811. {
  1812. /*
  1813. * The node name string does not exist, so set the node record
  1814. * pointer to NULL.
  1815. */
  1816. node_record->node_name = NULL;
  1817. }
  1818. if (internal_record->participant_name_list != NULL)
  1819. {
  1820. LPWSTR lpUstring;
  1821. /*
  1822. * Fill in the node record's participant name list. Use an
  1823. * iterator to access each participant name for this node
  1824. * record, copying each string into the appropriate location
  1825. * in memory.
  1826. */
  1827. node_record->participant_name_list = (LPWSTR *)memory;
  1828. node_record->number_of_participants = (USHORT)
  1829. internal_record->participant_name_list->GetCount();
  1830. /*
  1831. * Move the memory pointer past the list of participant name
  1832. * pointers. This is where the first participant name string
  1833. * will be written. There is no need to round this value off
  1834. * to an even multiple of four bytes since a LPWSTR
  1835. * is actually a pointer.
  1836. */
  1837. memory += internal_record->participant_name_list->GetCount() * sizeof(LPWSTR);
  1838. total_data_length += internal_record->participant_name_list->GetCount() * sizeof(LPWSTR);
  1839. /*
  1840. * Initialize the loop counter to zero and fill in the
  1841. * participants name list.
  1842. */
  1843. i = 0;
  1844. internal_record->participant_name_list->Reset();
  1845. while (NULL != (lpUstring = internal_record->participant_name_list->Iterate()))
  1846. {
  1847. node_record->participant_name_list[i++] = (LPWSTR)memory;
  1848. UINT cbStrSize = (::lstrlenW(lpUstring) + 1) * sizeof(WCHAR);
  1849. ::CopyMemory(memory, lpUstring, cbStrSize);
  1850. memory += ROUNDTOBOUNDARY(cbStrSize);
  1851. total_data_length += ROUNDTOBOUNDARY(cbStrSize);
  1852. }
  1853. }
  1854. else
  1855. {
  1856. /*
  1857. * The participant name list does not exist, so set the node
  1858. * record pointer to NULL and the number of participants to
  1859. * zero.
  1860. */
  1861. node_record->participant_name_list = NULL;
  1862. node_record->number_of_participants = 0;
  1863. }
  1864. if (internal_record->pwszSiteInfo != NULL)
  1865. {
  1866. /*
  1867. * Set the record's site information pointer and copy the site
  1868. * information data into memory from the internal unicode
  1869. * string. Be sure to copy the strings NULL terminating
  1870. * character. Move the memory pointer past the site information
  1871. * string data.
  1872. */
  1873. node_record->site_information = (LPWSTR)memory;
  1874. UINT cbStrSize = (::lstrlenW(internal_record->pwszSiteInfo) + 1) * sizeof(WCHAR);
  1875. ::CopyMemory(memory, internal_record->pwszSiteInfo, cbStrSize);
  1876. total_data_length += ROUNDTOBOUNDARY(cbStrSize);
  1877. memory += ROUNDTOBOUNDARY(cbStrSize);
  1878. }
  1879. else
  1880. {
  1881. /*
  1882. * The site information string does not exist, so set the
  1883. * node record pointer to NULL.
  1884. */
  1885. node_record->site_information = NULL;
  1886. }
  1887. if (internal_record->network_address_list != NULL)
  1888. {
  1889. /*
  1890. * Fill in the network address list by using the internal
  1891. * CNetAddrListContainer object. The "Get" call will fill in the
  1892. * node record's network address list pointer and number of
  1893. * addresses, write the network address data into memory, and
  1894. * return the amount of data written into memory.
  1895. */
  1896. data_length = internal_record->network_address_list->GetNetworkAddressListAPI (
  1897. &node_record->number_of_network_addresses,
  1898. &node_record->network_address_list,
  1899. memory);
  1900. /*
  1901. * Move the memory pointer past the network address list data.
  1902. * This is where the user data list data will be written.
  1903. */
  1904. memory += data_length;
  1905. total_data_length += data_length;
  1906. }
  1907. else
  1908. {
  1909. /*
  1910. * The network address list does not exist, so set the node
  1911. * record pointer to NULL and the number of addresses to zero.
  1912. */
  1913. node_record->network_address_list = NULL;
  1914. node_record->number_of_network_addresses = 0;
  1915. }
  1916. if (internal_record->poszAltNodeID != NULL)
  1917. {
  1918. /*
  1919. * Set the node record's alternative node ID pointer to the
  1920. * location in memory where the OSTR will be built.
  1921. * Note that the node record contains a pointer to a
  1922. * OSTR structure in memory, not just a pointer to
  1923. * string data.
  1924. */
  1925. node_record->alternative_node_id = (LPOSTR) memory;
  1926. /*
  1927. * Move the memory pointer past the octet string structure.
  1928. * This is where the actual string data will be written.
  1929. */
  1930. memory += ROUNDTOBOUNDARY(sizeof(OSTR));
  1931. total_data_length += ROUNDTOBOUNDARY(sizeof(OSTR));
  1932. node_record->alternative_node_id->length =
  1933. internal_record->poszAltNodeID->length;
  1934. /*
  1935. * Set the pointer for the alternative node ID octet string
  1936. * equal to the location in memory where it will be copied.
  1937. */
  1938. node_record->alternative_node_id->value =(LPBYTE)memory;
  1939. /*
  1940. * Now copy the octet string data from the internal Rogue Wave
  1941. * string into the object key structure held in memory.
  1942. */
  1943. ::CopyMemory(memory, internal_record->poszAltNodeID->value,
  1944. node_record->alternative_node_id->length);
  1945. /*
  1946. * Move the memory pointer past the alternative node ID string
  1947. * data written into memory.
  1948. */
  1949. memory += ROUNDTOBOUNDARY(node_record->alternative_node_id->length);
  1950. total_data_length += ROUNDTOBOUNDARY(node_record->alternative_node_id->length);
  1951. }
  1952. else
  1953. {
  1954. /*
  1955. * The alternative node ID string does not exist, so set the
  1956. * node record pointer to NULL.
  1957. */
  1958. node_record->alternative_node_id = NULL;
  1959. }
  1960. if (internal_record->user_data_list != NULL)
  1961. {
  1962. /*
  1963. * Fill in the user data list by using the internal CUserDataListContainer
  1964. * object. The "Get" call will fill in the node record's user
  1965. * data list pointer and number of user data members, write the
  1966. * user data into memory, and return the amount of data written
  1967. * into memory.
  1968. */
  1969. data_length = internal_record->user_data_list->GetUserDataList (
  1970. &node_record->number_of_user_data_members,
  1971. &node_record->user_data_list,
  1972. memory);
  1973. /*
  1974. * Move the memory pointer past the user data list data.
  1975. */
  1976. memory += data_length;
  1977. total_data_length += data_length;
  1978. }
  1979. else
  1980. {
  1981. /*
  1982. * The user data list does not exist, so set the node record
  1983. * pointer to NULL and the number of data members to zero.
  1984. */
  1985. node_record->user_data_list = NULL;
  1986. node_record->number_of_user_data_members = 0;
  1987. }
  1988. }
  1989. }
  1990. else
  1991. {
  1992. ERROR_OUT(("CConfRoster::GetConfRoster: Error Data Not Locked"));
  1993. *conference_roster = NULL;
  1994. rc = 0;
  1995. }
  1996. return rc;
  1997. }
  1998. /*
  1999. * GCCError AddRecord ()
  2000. *
  2001. * Public Function Description:
  2002. * This routine is used to add a new Node Record to this conference
  2003. * roster object.
  2004. */
  2005. GCCError CConfRoster::AddRecord( PGCCNodeRecord node_record,
  2006. UserID node_id)
  2007. {
  2008. GCCError rc = GCC_NO_ERROR;
  2009. USHORT i;
  2010. LPWSTR pwszParticipantName;
  2011. CONF_RECORD *internal_record;
  2012. /*
  2013. ** Free up the old PDU data here if it is being maintained and the
  2014. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  2015. ** back to FALSE so that the new PDU will be maintained until it is
  2016. ** flushed.
  2017. */
  2018. if (m_fPduFlushed)
  2019. {
  2020. FreeRosterUpdateIndicationPDU ();
  2021. m_fPduFlushed = FALSE;
  2022. }
  2023. if (! m_RecordList2.Find(node_id))
  2024. {
  2025. DBG_SAVE_FILE_LINE
  2026. internal_record = new CONF_RECORD;
  2027. if (internal_record != NULL)
  2028. {
  2029. /*
  2030. ** Convert the passed in conference record to the form that it
  2031. ** is going to be stored in the internal roster database.
  2032. */
  2033. /*
  2034. ** Save the node type and properties internally. These will
  2035. ** always exist.
  2036. */
  2037. GetPDUNodeTypeAndProperties (
  2038. node_record->node_type,
  2039. node_record->node_properties,
  2040. &internal_record->node_type,
  2041. &internal_record->node_properties);
  2042. internal_record->superior_node = m_uidSuperiorNode;
  2043. // Save the node name internally if it exists.
  2044. if (node_record->node_name != NULL)
  2045. {
  2046. if (::lstrlenW(node_record->node_name) > MAXIMUM_NODE_NAME_LENGTH)
  2047. {
  2048. rc = GCC_INVALID_NODE_NAME;
  2049. }
  2050. else
  2051. if (NULL == (internal_record->pwszNodeName = ::My_strdupW(node_record->node_name)))
  2052. {
  2053. rc = GCC_ALLOCATION_FAILURE;
  2054. }
  2055. }
  2056. else
  2057. {
  2058. ASSERT(NULL == internal_record->pwszNodeName);
  2059. }
  2060. // Save the list of participants internally if it exists.
  2061. if ((node_record->number_of_participants != 0) &&
  2062. (rc == GCC_NO_ERROR))
  2063. {
  2064. if (node_record->participant_name_list != NULL)
  2065. {
  2066. DBG_SAVE_FILE_LINE
  2067. internal_record->participant_name_list = new CParticipantNameList;
  2068. if (internal_record->participant_name_list == NULL)
  2069. rc = GCC_ALLOCATION_FAILURE;
  2070. }
  2071. else
  2072. {
  2073. ASSERT(NULL == internal_record->participant_name_list);
  2074. rc = GCC_INVALID_PARAMETER;
  2075. }
  2076. if (rc == GCC_NO_ERROR)
  2077. {
  2078. /*
  2079. ** Convert each participant name that is LPWSTR
  2080. ** to a UnicodeString when storing it into a record.
  2081. */
  2082. for (i = 0; i < node_record->number_of_participants; i++)
  2083. {
  2084. if (node_record->participant_name_list[i] != NULL)
  2085. {
  2086. if (::lstrlenW(node_record->participant_name_list[i]) >
  2087. MAXIMUM_PARTICIPANT_NAME_LENGTH)
  2088. {
  2089. rc = GCC_INVALID_PARTICIPANT_NAME;
  2090. //
  2091. // LONCHANC: Why no "break"?
  2092. //
  2093. }
  2094. else
  2095. if (NULL == (pwszParticipantName = ::My_strdupW(
  2096. node_record->participant_name_list[i])))
  2097. {
  2098. rc = GCC_ALLOCATION_FAILURE;
  2099. break;
  2100. }
  2101. else
  2102. {
  2103. // Add the participant to the list
  2104. internal_record->participant_name_list->Append(pwszParticipantName);
  2105. }
  2106. }
  2107. else
  2108. {
  2109. rc = GCC_INVALID_PARAMETER;
  2110. break;
  2111. }
  2112. }
  2113. }
  2114. }
  2115. else
  2116. {
  2117. ASSERT(NULL == internal_record->participant_name_list);
  2118. }
  2119. // Save site information internally if it exists.
  2120. if (node_record->site_information != NULL)
  2121. {
  2122. if (::lstrlenW(node_record->site_information) > MAXIMUM_SITE_INFORMATION_LENGTH)
  2123. {
  2124. rc = GCC_INVALID_SITE_INFORMATION;
  2125. }
  2126. else
  2127. if (NULL == (internal_record->pwszSiteInfo =
  2128. ::My_strdupW(node_record->site_information)))
  2129. {
  2130. rc = GCC_ALLOCATION_FAILURE;
  2131. }
  2132. }
  2133. else
  2134. {
  2135. ASSERT(NULL == internal_record->pwszSiteInfo);
  2136. }
  2137. /*
  2138. ** Fill in the network address list if it exists. The network
  2139. ** address list is maintained internally in a CNetAddrListContainer
  2140. ** object which is constructed here using the GCCNetworkAddress
  2141. ** portion of the "API" node record passed in.
  2142. */
  2143. if ((node_record->number_of_network_addresses != 0) &&
  2144. (node_record->network_address_list != NULL) &&
  2145. (rc == GCC_NO_ERROR))
  2146. {
  2147. DBG_SAVE_FILE_LINE
  2148. internal_record->network_address_list = new CNetAddrListContainer(
  2149. node_record->number_of_network_addresses,
  2150. node_record->network_address_list,
  2151. &rc);
  2152. if ((internal_record->network_address_list == NULL) ||
  2153. (rc != GCC_NO_ERROR))
  2154. {
  2155. rc = GCC_ALLOCATION_FAILURE;
  2156. }
  2157. }
  2158. else
  2159. {
  2160. ASSERT(NULL == internal_record->network_address_list);
  2161. }
  2162. // Save the alternative node ID internally if it exists.
  2163. if ((node_record->alternative_node_id != NULL) &&
  2164. (rc == GCC_NO_ERROR))
  2165. {
  2166. if (NULL == (internal_record->poszAltNodeID = ::My_strdupO2(
  2167. node_record->alternative_node_id->value,
  2168. node_record->alternative_node_id->length)))
  2169. {
  2170. rc = GCC_ALLOCATION_FAILURE;
  2171. }
  2172. else if (internal_record->poszAltNodeID->length != ALTERNATIVE_NODE_ID_LENGTH)
  2173. {
  2174. ERROR_OUT(("not equal to alt node id length"));
  2175. rc = GCC_INVALID_ALTERNATIVE_NODE_ID;
  2176. }
  2177. }
  2178. else
  2179. {
  2180. ASSERT(NULL == internal_record->poszAltNodeID);
  2181. }
  2182. /*
  2183. ** Fill in the user data if it exists. The user data is
  2184. ** maintained internally in a CUserDataListContainer object which is
  2185. ** constructed here using the GCCUserData portion of the "API"
  2186. ** node record passed in.
  2187. */
  2188. if ((node_record->number_of_user_data_members != 0) &&
  2189. (node_record->user_data_list != NULL) &&
  2190. (rc == GCC_NO_ERROR))
  2191. {
  2192. DBG_SAVE_FILE_LINE
  2193. internal_record->user_data_list = new CUserDataListContainer(
  2194. node_record->number_of_user_data_members,
  2195. node_record->user_data_list,
  2196. &rc);
  2197. if ((internal_record->user_data_list == NULL) ||
  2198. (rc != GCC_NO_ERROR))
  2199. {
  2200. rc = GCC_ALLOCATION_FAILURE;
  2201. }
  2202. }
  2203. else
  2204. {
  2205. ASSERT(NULL == internal_record->user_data_list);
  2206. }
  2207. /*
  2208. ** If the new Record was successfully filled in, add it to the
  2209. ** internal Rogue Wave list of Records.
  2210. */
  2211. if (rc == GCC_NO_ERROR)
  2212. {
  2213. // Increment the instance number.
  2214. m_nInstanceNumber++;
  2215. m_fNodesAdded = TRUE;
  2216. m_fRosterChanged = TRUE;
  2217. // Add the new record to the list of internal records.
  2218. m_RecordList2.Append(node_id, internal_record);
  2219. // Add an update to the PDU.
  2220. rc = BuildRosterUpdateIndicationPDU(ADD_RECORD, node_id);
  2221. }
  2222. else
  2223. {
  2224. delete internal_record;
  2225. }
  2226. }
  2227. else
  2228. {
  2229. rc = GCC_ALLOCATION_FAILURE;
  2230. }
  2231. }
  2232. else
  2233. {
  2234. rc = GCC_INVALID_PARAMETER;
  2235. }
  2236. return (rc);
  2237. }
  2238. /*
  2239. * GCCError RemoveUserReference ()
  2240. *
  2241. * Public Function Description:
  2242. * This routine is used to remove a node record from the list of node
  2243. * records.
  2244. */
  2245. GCCError CConfRoster::RemoveUserReference(UserID detached_node_id)
  2246. {
  2247. GCCError rc = GCC_NO_ERROR;
  2248. CONF_RECORD *node_record;
  2249. CUidList node_delete_list;
  2250. /*
  2251. ** Free up the old PDU data here if it is being maintained and the
  2252. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  2253. ** back to FALSE so that the new PDU will be maintained until it is
  2254. ** flushed.
  2255. */
  2256. if (m_fPduFlushed)
  2257. {
  2258. FreeRosterUpdateIndicationPDU ();
  2259. m_fPduFlushed = FALSE;
  2260. }
  2261. /*
  2262. ** Here we must determine if the node that is detaching is directly
  2263. ** connected to this node. If so, we will delete the node and any other
  2264. ** nodes found in the roster list that are subordinate to this. We
  2265. ** determine all of this by using the superior node id stored in each
  2266. ** conference record.
  2267. */
  2268. if (NULL != (node_record = m_RecordList2.Find(detached_node_id)))
  2269. {
  2270. // Is this node directly connected to me?
  2271. if (node_record->superior_node == m_uidMyNodeID)
  2272. {
  2273. /*
  2274. ** Use NULL for the pointer since were not concerned about
  2275. ** the pointer here.
  2276. */
  2277. rc = GetNodeSubTree(detached_node_id, &node_delete_list);
  2278. if (rc == GCC_NO_ERROR)
  2279. {
  2280. UserID uid;
  2281. node_delete_list.Reset();
  2282. while ((GCC_INVALID_UID != (uid = node_delete_list.Iterate())) &&
  2283. (rc == GCC_NO_ERROR))
  2284. {
  2285. rc = DeleteRecord(uid);
  2286. }
  2287. if (rc == GCC_NO_ERROR)
  2288. {
  2289. // Increment the instance number.
  2290. m_nInstanceNumber++;
  2291. m_fNodesRemoved = TRUE;
  2292. m_fRosterChanged = TRUE;
  2293. // Add an update to the PDU.
  2294. rc = BuildRosterUpdateIndicationPDU (FULL_REFRESH, 0 );
  2295. }
  2296. }
  2297. }
  2298. else
  2299. {
  2300. rc = GCC_INVALID_PARAMETER;
  2301. }
  2302. }
  2303. else
  2304. {
  2305. rc = GCC_INVALID_PARAMETER;
  2306. }
  2307. return (rc);
  2308. }
  2309. /*
  2310. * GCCError ReplaceRecord ()
  2311. *
  2312. * Public Function Description:
  2313. * This routine is used to replace one of the records in the list of
  2314. * node records.
  2315. */
  2316. GCCError CConfRoster::ReplaceRecord(
  2317. PGCCNodeRecord node_record,
  2318. UserID node_id)
  2319. {
  2320. GCCError rc = GCC_NO_ERROR;
  2321. USHORT i;
  2322. LPWSTR pwszParticipantName;
  2323. CONF_RECORD *pCRD = NULL;
  2324. /*
  2325. ** Free up the old PDU data here if it is being maintained and the
  2326. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  2327. ** back to FALSE so that the new PDU will be maintained until it is
  2328. ** flushed.
  2329. */
  2330. if (m_fPduFlushed)
  2331. {
  2332. FreeRosterUpdateIndicationPDU ();
  2333. m_fPduFlushed = FALSE;
  2334. }
  2335. //
  2336. // LONCHANC: Do we really need to check this? Why can't we simply
  2337. // add the new one if the old one does not exist?
  2338. //
  2339. if (NULL == m_RecordList2.Find(node_id))
  2340. {
  2341. rc = GCC_INVALID_PARAMETER;
  2342. goto MyExit;
  2343. }
  2344. DBG_SAVE_FILE_LINE
  2345. if (NULL == (pCRD = new CONF_RECORD))
  2346. {
  2347. rc = GCC_ALLOCATION_FAILURE;
  2348. goto MyExit;
  2349. }
  2350. /*
  2351. ** First we build all the internal data and check for validity
  2352. ** before we replace the old record. We want to make sure that
  2353. ** everything will build before we do the replace. This prevents
  2354. ** us from corrupting the current record if there is a problem
  2355. ** with the new record data.
  2356. */
  2357. // Save the node name internally if it exists.
  2358. if (node_record->node_name != NULL)
  2359. {
  2360. if (::lstrlenW(node_record->node_name) > MAXIMUM_NODE_NAME_LENGTH)
  2361. {
  2362. rc = GCC_INVALID_NODE_NAME;
  2363. }
  2364. else
  2365. if (NULL == (pCRD->pwszNodeName = ::My_strdupW(node_record->node_name)))
  2366. {
  2367. rc = GCC_ALLOCATION_FAILURE;
  2368. }
  2369. }
  2370. // Save the list of participants internally if it exists.
  2371. if ((node_record->number_of_participants != 0) &&
  2372. (rc == GCC_NO_ERROR))
  2373. {
  2374. if (node_record->participant_name_list != NULL)
  2375. {
  2376. DBG_SAVE_FILE_LINE
  2377. if (NULL == (pCRD->participant_name_list = new CParticipantNameList))
  2378. {
  2379. rc = GCC_ALLOCATION_FAILURE;
  2380. }
  2381. }
  2382. else
  2383. rc = GCC_INVALID_PARAMETER;
  2384. if (rc == GCC_NO_ERROR)
  2385. {
  2386. /*
  2387. ** Convert each participant name that is LPWSTR
  2388. ** to a UnicodeString when storing it into a record.
  2389. */
  2390. for (i = 0; i < node_record->number_of_participants; i++)
  2391. {
  2392. if (node_record->participant_name_list[i] != NULL)
  2393. {
  2394. if (::lstrlenW(node_record->participant_name_list[i]) >
  2395. MAXIMUM_PARTICIPANT_NAME_LENGTH)
  2396. {
  2397. rc = GCC_INVALID_PARTICIPANT_NAME;
  2398. //
  2399. // LONCHANC: Why no "break"?
  2400. //
  2401. }
  2402. else
  2403. if (NULL == (pwszParticipantName = ::My_strdupW(
  2404. node_record->participant_name_list[i])))
  2405. {
  2406. rc = GCC_ALLOCATION_FAILURE;
  2407. break;
  2408. }
  2409. else
  2410. {
  2411. // Add the participant to the list
  2412. pCRD->participant_name_list->Append(pwszParticipantName);
  2413. }
  2414. }
  2415. else
  2416. {
  2417. rc = GCC_INVALID_PARAMETER;
  2418. break;
  2419. }
  2420. }
  2421. }
  2422. }
  2423. // Save site information internally if it exists.
  2424. if (node_record->site_information != NULL)
  2425. {
  2426. if (::lstrlenW(node_record->site_information) > MAXIMUM_SITE_INFORMATION_LENGTH)
  2427. {
  2428. rc = GCC_INVALID_SITE_INFORMATION;
  2429. }
  2430. else
  2431. if (NULL == (pCRD->pwszSiteInfo = ::My_strdupW(node_record->site_information)))
  2432. {
  2433. rc = GCC_ALLOCATION_FAILURE;
  2434. }
  2435. }
  2436. /*
  2437. ** Fill in the network address list if it exists. The network
  2438. ** address list is maintained internally in a CNetAddrListContainer
  2439. ** object which is constructed here using the GCCNetworkAddress
  2440. ** portion of the "API" node record passed in.
  2441. */
  2442. if ((node_record->number_of_network_addresses != 0) &&
  2443. (node_record->network_address_list != NULL) &&
  2444. (rc == GCC_NO_ERROR))
  2445. {
  2446. DBG_SAVE_FILE_LINE
  2447. pCRD->network_address_list = new CNetAddrListContainer(
  2448. node_record->number_of_network_addresses,
  2449. node_record->network_address_list,
  2450. &rc);
  2451. if ((pCRD->network_address_list == NULL) ||
  2452. (rc != GCC_NO_ERROR))
  2453. {
  2454. rc = GCC_ALLOCATION_FAILURE;
  2455. }
  2456. }
  2457. // Save the alternative node ID internally if it exists.
  2458. if ((node_record->alternative_node_id != NULL) &&
  2459. (rc == GCC_NO_ERROR))
  2460. {
  2461. if (NULL == (pCRD->poszAltNodeID = ::My_strdupO2(
  2462. node_record->alternative_node_id->value,
  2463. node_record->alternative_node_id->length)))
  2464. {
  2465. rc = GCC_ALLOCATION_FAILURE;
  2466. }
  2467. else if (pCRD->poszAltNodeID->length !=ALTERNATIVE_NODE_ID_LENGTH)
  2468. {
  2469. ERROR_OUT(("not equal to alt node id length"));
  2470. rc = GCC_INVALID_ALTERNATIVE_NODE_ID;
  2471. }
  2472. }
  2473. /*
  2474. ** Fill in the user data if it exists. The user data is
  2475. ** maintained internally in a CUserDataListContainer object which is
  2476. ** constructed here using the GCCUserData portion of the "API"
  2477. ** node record passed in.
  2478. */
  2479. if ((node_record->number_of_user_data_members != 0) &&
  2480. (node_record->user_data_list != NULL) &&
  2481. (rc == GCC_NO_ERROR))
  2482. {
  2483. DBG_SAVE_FILE_LINE
  2484. pCRD->user_data_list = new CUserDataListContainer(
  2485. node_record->number_of_user_data_members,
  2486. node_record->user_data_list,
  2487. &rc);
  2488. if ((pCRD->user_data_list == NULL) || (rc != GCC_NO_ERROR))
  2489. {
  2490. rc = GCC_ALLOCATION_FAILURE;
  2491. }
  2492. }
  2493. /*
  2494. ** Now if no errors occured we replace the old record with the new
  2495. ** record information created above.
  2496. */
  2497. if (rc == GCC_NO_ERROR)
  2498. {
  2499. /*
  2500. ** Save the node type and properties internally. These will
  2501. ** always exist.
  2502. */
  2503. GetPDUNodeTypeAndProperties (
  2504. node_record->node_type,
  2505. node_record->node_properties,
  2506. &pCRD->node_type,
  2507. &pCRD->node_properties);
  2508. pCRD->superior_node = m_uidSuperiorNode;
  2509. // replace the old record with the new one
  2510. DeleteRecord(node_id);
  2511. m_RecordList2.Append(node_id, pCRD);
  2512. // Increment the instance number.
  2513. m_nInstanceNumber++;
  2514. m_fRosterChanged = TRUE;
  2515. }
  2516. MyExit:
  2517. if (GCC_NO_ERROR == rc)
  2518. {
  2519. // Add an update to the PDU.
  2520. rc = BuildRosterUpdateIndicationPDU(REPLACE_RECORD, node_id);
  2521. }
  2522. else
  2523. {
  2524. delete pCRD;
  2525. }
  2526. return (rc);
  2527. }
  2528. /*
  2529. * GCCError DeleteRecord ()
  2530. *
  2531. * Private Function Description:
  2532. * This routine is used to delete one of the records from the list of
  2533. * node records. It only operates on the conference roster list. It
  2534. * does not deal with any of the flags associated with a roster PDU or
  2535. * message such as: m_fNodesAdded and m_fNodesRemoved.
  2536. *
  2537. * Formal Parameters:
  2538. * node_id - (i) Node ID of node record to delete.
  2539. *
  2540. * Return Value
  2541. * GCC_NO_ERROR - No error occured.
  2542. * GCC_INVALID_PARAMETER - Bad node id passed in.
  2543. *
  2544. * Side Effects
  2545. * None.
  2546. *
  2547. * Caveats
  2548. * None.
  2549. */
  2550. CONF_RECORD::CONF_RECORD(void)
  2551. :
  2552. pwszNodeName(NULL),
  2553. participant_name_list(NULL),
  2554. pwszSiteInfo(NULL),
  2555. network_address_list(NULL),
  2556. poszAltNodeID(NULL),
  2557. user_data_list(NULL),
  2558. superior_node(0)
  2559. {
  2560. }
  2561. CONF_RECORD::~CONF_RECORD(void)
  2562. {
  2563. /*
  2564. * If a node name exists, delete it from the Record.
  2565. */
  2566. delete pwszNodeName;
  2567. /*
  2568. * If a participants list exists, clear the list and then delete it
  2569. * from the Record.
  2570. */
  2571. if (participant_name_list != NULL)
  2572. {
  2573. participant_name_list->DeleteList();
  2574. delete participant_name_list;
  2575. }
  2576. /*
  2577. * If site information exists, delete it from the Record.
  2578. */
  2579. delete pwszSiteInfo;
  2580. /*
  2581. * If a network address list exists, delete it from the Record.
  2582. */
  2583. if (NULL != network_address_list)
  2584. {
  2585. network_address_list->Release();
  2586. }
  2587. /*
  2588. * If a user data list exists, delete it from the Record.
  2589. */
  2590. if (NULL != user_data_list)
  2591. {
  2592. user_data_list->Release();
  2593. }
  2594. }
  2595. GCCError CConfRoster::DeleteRecord(UserID node_id)
  2596. {
  2597. GCCError rc;
  2598. CONF_RECORD *lpRec;
  2599. if (NULL != (lpRec = m_RecordList2.Remove(node_id)))
  2600. {
  2601. delete lpRec;
  2602. rc = GCC_NO_ERROR;
  2603. }
  2604. else
  2605. {
  2606. rc = GCC_INVALID_PARAMETER;
  2607. }
  2608. return (rc);
  2609. }
  2610. /*
  2611. * void ClearRecordList ()
  2612. *
  2613. * Private Function Description:
  2614. * This routine is used to clear out the internal list of records which
  2615. * hold the conference roster information. This routine is called upon
  2616. * destruction of this object or when a refresh occurs causing the entire
  2617. * record list to be rebuilt.
  2618. *
  2619. * Formal Parameters:
  2620. * None.
  2621. *
  2622. * Return Value
  2623. * None.
  2624. *
  2625. * Side Effects
  2626. * None.
  2627. *
  2628. * Caveats
  2629. * None.
  2630. */
  2631. void CConfRoster::ClearRecordList(void)
  2632. {
  2633. CONF_RECORD *pRec;
  2634. while (NULL != (pRec = m_RecordList2.Get()))
  2635. {
  2636. delete pRec;
  2637. }
  2638. }
  2639. /*
  2640. * NodeType GetNodeTypeAndProperties ()
  2641. *
  2642. * Private Function Description:
  2643. * This routine is used to translate the node type and node properties
  2644. * from the "PDU" form into the "API" form.
  2645. *
  2646. * Formal Parameters:
  2647. * pdu_node_type - (i) This is the node type defined for the PDU.
  2648. * pdu_node_properties - (i) This is the node properties defined for
  2649. * the PDU.
  2650. * node_type - (o) This is a pointer to the GCCNodeType to
  2651. * be filled in by this routine.
  2652. * node_properties - (o) This is a pointer to the GCCNodeProperties
  2653. * to be filled in by this routine.
  2654. *
  2655. * Return Value
  2656. * None.
  2657. *
  2658. * Side Effects
  2659. * None.
  2660. *
  2661. * Caveats
  2662. * None.
  2663. */
  2664. void CConfRoster::GetNodeTypeAndProperties (
  2665. NodeType pdu_node_type,
  2666. NodeProperties pdu_node_properties,
  2667. PGCCNodeType node_type,
  2668. PGCCNodeProperties node_properties)
  2669. {
  2670. /*
  2671. * First translate the node type.
  2672. */
  2673. if (pdu_node_type == TERMINAL)
  2674. *node_type = GCC_TERMINAL;
  2675. else if (pdu_node_type == MCU)
  2676. *node_type = GCC_MCU;
  2677. else
  2678. *node_type = GCC_MULTIPORT_TERMINAL;
  2679. /*
  2680. * Next translate the node properties.
  2681. */
  2682. if ((pdu_node_properties.device_is_peripheral) &&
  2683. (pdu_node_properties.device_is_manager == FALSE))
  2684. {
  2685. *node_properties = GCC_PERIPHERAL_DEVICE;
  2686. }
  2687. else if ((pdu_node_properties.device_is_peripheral == FALSE) &&
  2688. (pdu_node_properties.device_is_manager))
  2689. {
  2690. *node_properties = GCC_MANAGEMENT_DEVICE;
  2691. }
  2692. else if ((pdu_node_properties.device_is_peripheral) &&
  2693. (pdu_node_properties.device_is_manager))
  2694. {
  2695. *node_properties = GCC_PERIPHERAL_AND_MANAGEMENT_DEVICE;
  2696. }
  2697. else
  2698. *node_properties = GCC_NEITHER_PERIPHERAL_NOR_MANAGEMENT;
  2699. }
  2700. /*
  2701. * void GetPDUNodeTypeAndProperties ()
  2702. *
  2703. * Private Function Description:
  2704. * This routine is used to translate the node type and node properties
  2705. * from the "API" form into the "PDU" form.
  2706. *
  2707. * Formal Parameters:
  2708. * node_type - (i) This is the GCC (or API) node type.
  2709. * node_properties - (i) This is the GCC (or API) node properties
  2710. * pdu_node_type - (o) This is a pointer to the PDU node type to
  2711. * be filled in by this routine.
  2712. * pdu_node_properties - (o) This is a pointer to the PDU node properties
  2713. * to be filled in by this routine.
  2714. *
  2715. * Return Value
  2716. * None.
  2717. *
  2718. * Side Effects
  2719. * None.
  2720. *
  2721. * Caveats
  2722. * None.
  2723. */
  2724. void CConfRoster::GetPDUNodeTypeAndProperties (
  2725. GCCNodeType node_type,
  2726. GCCNodeProperties node_properties,
  2727. PNodeType pdu_node_type,
  2728. PNodeProperties pdu_node_properties)
  2729. {
  2730. /*
  2731. * First translate node types.
  2732. */
  2733. if (node_type == GCC_TERMINAL)
  2734. *pdu_node_type = TERMINAL;
  2735. else if (node_type == GCC_MCU)
  2736. *pdu_node_type = MCU;
  2737. else
  2738. *pdu_node_type = MULTIPORT_TERMINAL;
  2739. /*
  2740. * Next translate node properties.
  2741. */
  2742. if (node_properties == GCC_PERIPHERAL_DEVICE)
  2743. {
  2744. pdu_node_properties->device_is_manager = FALSE;
  2745. pdu_node_properties->device_is_peripheral = TRUE;
  2746. }
  2747. else if (node_properties == GCC_MANAGEMENT_DEVICE)
  2748. {
  2749. pdu_node_properties->device_is_manager = TRUE;
  2750. pdu_node_properties->device_is_peripheral = FALSE;
  2751. }
  2752. else if (node_properties == GCC_PERIPHERAL_AND_MANAGEMENT_DEVICE)
  2753. {
  2754. pdu_node_properties->device_is_manager = TRUE;
  2755. pdu_node_properties->device_is_peripheral = TRUE;
  2756. }
  2757. else
  2758. {
  2759. pdu_node_properties->device_is_manager = FALSE;
  2760. pdu_node_properties->device_is_peripheral = FALSE;
  2761. }
  2762. }
  2763. /*
  2764. * BOOL Contains ()
  2765. *
  2766. * Public Function Description:
  2767. * This routine is used to determine whether or not a record exists within
  2768. * the internal list corresponding to the given user ID.
  2769. */
  2770. /*
  2771. * UINT GetNumberOfApplicationRecords ()
  2772. *
  2773. * Public Function Description:
  2774. * This routine is used to get the number of node records currently being
  2775. * maintained within this object's internal list.
  2776. */
  2777. /*
  2778. * void ResetConferenceRoster ()
  2779. *
  2780. * Public Function Description:
  2781. */
  2782. void CConfRoster::ResetConferenceRoster(void)
  2783. {
  2784. m_fRosterChanged = FALSE;
  2785. m_fNodesAdded = FALSE;
  2786. m_fNodesRemoved = FALSE;
  2787. }
  2788. /*
  2789. * BOOL HasRosterChanged ()
  2790. *
  2791. * Public Function Description:
  2792. */
  2793. /*
  2794. * GCCError GetNodeSubTree ()
  2795. *
  2796. * Public Function Description:
  2797. * This routine traverses the entire tree level-by-level starting at the
  2798. * root node and then progressively going down the tree.
  2799. */
  2800. GCCError CConfRoster::GetNodeSubTree (
  2801. UserID uidRootNode,
  2802. CUidList *node_list)
  2803. {
  2804. GCCError rc = GCC_NO_ERROR;
  2805. CUidList high_level_list;
  2806. UserID uidSuperiorNode;
  2807. CONF_RECORD *lpRec;
  2808. UserID uid;
  2809. if (m_RecordList2.Find(uidRootNode))
  2810. {
  2811. /*
  2812. ** First add the root node to the high level list to get every thing
  2813. ** going.
  2814. */
  2815. high_level_list.Append(uidRootNode);
  2816. while (! high_level_list.IsEmpty())
  2817. {
  2818. uidSuperiorNode = high_level_list.Get();
  2819. // Append the high level node id to the node list passed in.
  2820. node_list->Append(uidSuperiorNode);
  2821. /*
  2822. ** Iterate through the entire roster looking for the next
  2823. ** level of dependent nodes.
  2824. */
  2825. m_RecordList2.Reset();
  2826. while (NULL != (lpRec = m_RecordList2.Iterate(&uid)))
  2827. {
  2828. if (lpRec->superior_node == uidSuperiorNode)
  2829. {
  2830. high_level_list.Append(uid);
  2831. }
  2832. }
  2833. }
  2834. }
  2835. else
  2836. {
  2837. rc = GCC_INVALID_PARAMETER;
  2838. }
  2839. return (rc);
  2840. }
  2841. void CParticipantNameList::DeleteList(void)
  2842. {
  2843. LPWSTR pwszParticipantName;
  2844. while (NULL != (pwszParticipantName = Get()))
  2845. {
  2846. delete pwszParticipantName;
  2847. }
  2848. }
  2849.