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.

4512 lines
122 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_APP_ROSTER);
  3. /*
  4. * arost.cpp
  5. *
  6. * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the implementation file for the Application Roster Class. This
  10. * class maintains the application roster, builds roster update and
  11. * refresh PDUs and manages the capabilities list which is part of the
  12. * application roster.
  13. *
  14. * This class makes use of a number of Rogue Wave lists to maintain the
  15. * roster entries and the capabilities list. The lists are organized in
  16. * such a way that the heirarchy of the conference can be maintained. This
  17. * is important to perform the necessary operations required by the T.124
  18. * specification. In general, there is a main "Roster_Record_List" that
  19. * maintains a list of "AppRosterRecords". The list is indexed by the
  20. * GCC user ID where each record in the list holds a list of application
  21. * records (or entities) at that node, a list of capabilities for each
  22. * "entity" and a list of sub-nodes (the GCC user IDs of all the nodes
  23. * below this one in the connection hierarchy). The Roster_Record_List
  24. * only holds entries for immediately connected nodes.
  25. *
  26. * SEE INTERFACE FILE FOR A MORE DETAILED ABSTRACT
  27. *
  28. * Private Instance Variables:
  29. * m_pAppRosterMgr
  30. * Pointer to the object that will receive all owner callbacks.
  31. * m_cbDataMemory
  32. * This is the number of bytes required to hold the data associated
  33. * with a roster update message. This is calculated on a lock.
  34. * m_fTopProvider
  35. * Flag indicating if the node where this roster lives is the top
  36. * provider.
  37. * m_fLocalRoster
  38. * Flag indicating if the roster data is associated with a local
  39. * roster (maintaining intermediate node data) or global roster (
  40. * (maintaining roster data for the whole conference).
  41. * m_pSessionKey
  42. * Pointer to a session key object that holds the session key
  43. * associated with this roster.
  44. * m_nInstance
  45. * The current instance of the roster. This number will change
  46. * whenever the roster is updated.
  47. * m_fRosterHasChanged
  48. * Flag indicating if the roster has changed since the last reset.
  49. * m_fPeerEntitiesAdded
  50. * Flag indicating if any APE records have been added to the
  51. * application roster since the last reset.
  52. * m_fPeerEntitiesRemoved
  53. * Flag indicating if any APE records have been deleted from the
  54. * application roster since the last reset.
  55. * m_fCapabilitiesHaveChanged
  56. * Flag indicating if the capabilities has changed since the last
  57. * reset.
  58. * m_NodeRecordList2
  59. * List which contains all the application roster's node records.
  60. * m_CollapsedCapListForAllNodes
  61. * List which contains all the application roster's collapsed
  62. * capabilities.
  63. * m_fMaintainPduBuffer
  64. * Flag indicating if it is necessary for this roster object to
  65. * maintain internal PDU data. Won't be necessary for global rosters
  66. * at subordinate nodes.
  67. * m_fPduIsFlushed
  68. * Flag indicating if the PDU that currently exists has been flushed.
  69. * m_SetOfAppInfo
  70. * Pointer to internal PDU data.
  71. * m_pSetOfAppRecordUpdates
  72. * This instance variable keeps up with the current record update so
  73. * that it will not be necessary to search the entire list updates
  74. * each a new update is added to the internal PDU.
  75. *
  76. * Caveats:
  77. * None.
  78. *
  79. * Author:
  80. * blp
  81. */
  82. #include "arost.h"
  83. #include "arostmgr.h"
  84. #include "clists.h"
  85. /*
  86. ** The maximum length the application data for a non-collapsed capablity
  87. ** can be.
  88. */
  89. #define MAXIMUM_APPLICATION_DATA_LENGTH 255
  90. /*
  91. * AppRosterRecord ()
  92. *
  93. * Public Function Description
  94. * Constructor definition to instantiate the hash list dictionaries that
  95. * are used in an AppRosterRecord. This constructor is needed to allow
  96. * the AppRosterRecord structure to be directly instantiated with hash
  97. * list.
  98. */
  99. APP_NODE_RECORD::APP_NODE_RECORD(void) :
  100. AppRecordList(DESIRED_MAX_APP_RECORDS),
  101. ListOfAppCapItemList2(DESIRED_MAX_CAP_LISTS),
  102. SubNodeList2(DESIRED_MAX_NODES)
  103. {}
  104. /*
  105. * CAppRoster ()
  106. *
  107. * Public Function Description
  108. * When pGccSessKey is not NULL
  109. * This constructor is used to create an empty application roster. Note
  110. * that the session key for the roster must be passed in to the
  111. * constructor.
  112. *
  113. * When pSessKey is not NULL
  114. * This constructor builds a roster based on an indication pdu.
  115. * Application Roster objects may exist at nodes which do not have
  116. * applications to perform the necessary operations required by T.124
  117. */
  118. CAppRoster::CAppRoster (
  119. PGCCSessionKey pGccSessKey,// create an empty app roster
  120. PSessionKey pPduSessKey,// build an app roster based on an indication pdu
  121. CAppRosterMgr *pAppRosterMgr,
  122. BOOL fTopProvider,
  123. BOOL fLocalRoster,
  124. BOOL fMaintainPduBuffer,
  125. PGCCError pRetCode)
  126. :
  127. CRefCount(MAKE_STAMP_ID('A','R','s','t')),
  128. m_nInstance(0),
  129. m_pAppRosterMgr(pAppRosterMgr),
  130. m_cbDataMemory(0),
  131. m_fTopProvider(fTopProvider),
  132. m_fLocalRoster(fLocalRoster),
  133. m_pSessionKey(NULL),
  134. m_fRosterHasChanged(FALSE),
  135. m_fPeerEntitiesAdded(FALSE),
  136. m_fPeerEntitiesRemoved(FALSE),
  137. m_fCapabilitiesHaveChanged(FALSE),
  138. m_NodeRecordList2(DESIRED_MAX_NODES),
  139. m_fMaintainPduBuffer(fMaintainPduBuffer),
  140. m_fPduIsFlushed(FALSE),
  141. m_pSetOfAppRecordUpdates(NULL)
  142. {
  143. DebugEntry(CAppRoster::CAppRoster);
  144. GCCError rc = GCC_NO_ERROR;
  145. ZeroMemory(&m_SetOfAppInfo, sizeof(m_SetOfAppInfo));
  146. /*
  147. ** Here we store the session key of the roster.
  148. */
  149. if (NULL != pGccSessKey)
  150. {
  151. ASSERT(NULL == pPduSessKey);
  152. DBG_SAVE_FILE_LINE
  153. m_pSessionKey = new CSessKeyContainer(pGccSessKey, &rc);
  154. }
  155. else
  156. if (NULL != pPduSessKey)
  157. {
  158. DBG_SAVE_FILE_LINE
  159. m_pSessionKey = new CSessKeyContainer(pPduSessKey, &rc);
  160. }
  161. else
  162. {
  163. ERROR_OUT(("CAppRoster::CAppRoster: invalid session key"));
  164. rc = GCC_BAD_SESSION_KEY;
  165. goto MyExit;
  166. }
  167. if (NULL == m_pSessionKey || GCC_NO_ERROR != rc)
  168. {
  169. ERROR_OUT(("CAppRoster::CAppRoster: can't create session key"));
  170. rc = GCC_ALLOCATION_FAILURE;
  171. // we do the cleanup in the destructor
  172. goto MyExit;
  173. }
  174. // Initialize the PDU structure to be no change.
  175. m_SetOfAppInfo.value.application_record_list.choice = APPLICATION_NO_CHANGE_CHOSEN;
  176. m_SetOfAppInfo.value.application_capabilities_list.choice = CAPABILITY_NO_CHANGE_CHOSEN;
  177. /*
  178. ** Here we go ahead and set up the session key portion of the
  179. ** PDU so we don't have to worry about it later.
  180. */
  181. if (m_fMaintainPduBuffer)
  182. {
  183. rc = m_pSessionKey->GetSessionKeyDataPDU(&m_SetOfAppInfo.value.session_key);
  184. }
  185. ASSERT(GCC_NO_ERROR == rc);
  186. MyExit:
  187. DebugExitINT(CAppRoster:;CAppRoster, rc);
  188. *pRetCode = rc;
  189. }
  190. /*
  191. * ~CAppRoster ()
  192. *
  193. * Public Function Description:
  194. * The destructor for the CAppRoster class is used to clean up
  195. * any memory allocated during the life of the object.
  196. */
  197. CAppRoster::~CAppRoster(void)
  198. {
  199. /*
  200. * Free up all memory associated with the roster record list.
  201. */
  202. ClearNodeRecordList();
  203. // Clear the Collapsed Capabilities List.
  204. m_CollapsedCapListForAllNodes.DeleteList();
  205. /*
  206. * Free up any outstanding PDU data.
  207. */
  208. if (m_fMaintainPduBuffer)
  209. {
  210. FreeRosterUpdateIndicationPDU();
  211. }
  212. /*
  213. * Free any memory associated with the session key..
  214. */
  215. if (NULL != m_pSessionKey)
  216. {
  217. m_pSessionKey->Release();
  218. }
  219. }
  220. /*
  221. * Utilities that operate on roster update PDU strucutures.
  222. */
  223. /*
  224. * GCCError FlushRosterUpdateIndicationPDU ()
  225. *
  226. * Public Function Description
  227. * This routine is used to access any PDU data that might currently be
  228. * queued inside the application roster. PDU data is queued whenever
  229. * a request is made to the application roster that affects its
  230. * internal information base.
  231. */
  232. void CAppRoster::FlushRosterUpdateIndicationPDU(PSetOfApplicationInformation *pSetOfAppInfo)
  233. {
  234. DebugEntry(CAppRoster::FlushRosterUpdateIndicationPDU);
  235. /*
  236. ** If this roster has already been flushed we will NOT allow the same
  237. ** PDU to be flushed again. Instead we delete the previously flushed
  238. ** PDU and set the flag back to unflushed. If another flush comes in
  239. ** before a PDU is built NULL will be returned in the application
  240. ** information pointer.
  241. */
  242. if (m_fPduIsFlushed)
  243. {
  244. FreeRosterUpdateIndicationPDU();
  245. m_fPduIsFlushed = FALSE;
  246. }
  247. if ((m_SetOfAppInfo.value.application_record_list.choice != APPLICATION_NO_CHANGE_CHOSEN) ||
  248. (m_SetOfAppInfo.value.application_capabilities_list.choice != CAPABILITY_NO_CHANGE_CHOSEN))
  249. {
  250. if (m_SetOfAppInfo.value.application_record_list.choice == APPLICATION_NO_CHANGE_CHOSEN)
  251. {
  252. TRACE_OUT(("CAppRoster::FlushRosterUpdateIndicationPDU:"
  253. "Sending APPLICATION_NO_CHANGE_CHOSEN PDU"));
  254. }
  255. /*
  256. ** This section of the code sets up all the variables that don't
  257. ** pertain to the record list or the caps list. Note that the
  258. ** session key PDU data was set up in the constructor. Also note that
  259. ** the record list data and capabilities list data should be set up
  260. ** before this routine is called if there is any PDU traffic to issue.
  261. */
  262. m_SetOfAppInfo.next = NULL;
  263. m_SetOfAppInfo.value.roster_instance_number = (USHORT) m_nInstance;
  264. m_SetOfAppInfo.value.peer_entities_are_added = (ASN1bool_t)m_fPeerEntitiesAdded;
  265. m_SetOfAppInfo.value.peer_entities_are_removed = (ASN1bool_t)m_fPeerEntitiesRemoved;
  266. /*
  267. ** Here we set up the pointer to the whole PDU structure associated
  268. ** with this application roster.
  269. */
  270. *pSetOfAppInfo = &m_SetOfAppInfo;
  271. /*
  272. ** Setting this to true will cause the PDU data to be freed up the
  273. ** next time the roster object is entered insuring that new PDU
  274. ** data will be created.
  275. */
  276. m_fPduIsFlushed = TRUE;
  277. }
  278. else
  279. {
  280. *pSetOfAppInfo = NULL;
  281. }
  282. }
  283. /*
  284. * GCCError BuildFullRefreshPDU ()
  285. *
  286. * Public Function Description
  287. * This routine is responsible for generating a full application roster
  288. * refresh PDU.
  289. */
  290. GCCError CAppRoster::BuildFullRefreshPDU(void)
  291. {
  292. GCCError rc;
  293. DebugEntry(CAppRoster::BuildFullRefreshPDU);
  294. /*
  295. ** Free up the old PDU data here if it is being maintained and the
  296. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  297. ** back to FALSE so that the new PDU will be maintained until it is
  298. ** flushed.
  299. */
  300. if (m_fPduIsFlushed)
  301. {
  302. FreeRosterUpdateIndicationPDU ();
  303. m_fPduIsFlushed = FALSE;
  304. }
  305. rc = BuildApplicationRecordListPDU (APP_FULL_REFRESH, 0, 0);
  306. if (rc == GCC_NO_ERROR)
  307. {
  308. BuildSetOfCapabilityRefreshesPDU ();
  309. }
  310. return rc;
  311. }
  312. /*
  313. * GCCError BuildApplicationRecordListPDU ()
  314. *
  315. * Private Function Description
  316. * This routine creates an application roster update indication
  317. * PDU based on the passed in parameters. Memory used after this
  318. * routine is called is still owned by this object and will be
  319. * freed the next time this objects internal information base is
  320. * modified.
  321. *
  322. * Formal Parameters:
  323. * update_type - What type of update are we building.
  324. * user_id - node id of record to update.
  325. * entity_id - entity id of record to update.
  326. *
  327. * Return Value
  328. * GCC_NO_ERROR - No error occured.
  329. * GCC_INVALID_PARAMETER - Parameter passed in is invalid.
  330. * GCC_ALLOCATION_FAILURE - A resource error occured.
  331. *
  332. * Side Effects
  333. * None.
  334. *
  335. * Caveats
  336. * None.
  337. */
  338. GCCError CAppRoster::BuildApplicationRecordListPDU (
  339. APP_ROSTER_UPDATE_TYPE update_type,
  340. UserID user_id,
  341. EntityID entity_id)
  342. {
  343. GCCError rc = GCC_NO_ERROR;
  344. DebugEntry(CAppRoster::BuildApplicationRecordListPDU);
  345. if (m_fMaintainPduBuffer)
  346. {
  347. /*
  348. ** Note here that the top provider node always sends a full refresh
  349. ** PDU so there is no need to pay any attention to update type in
  350. ** this case.
  351. */
  352. if ((update_type == APP_FULL_REFRESH) || m_fTopProvider)
  353. {
  354. /*
  355. ** First check to see if a refresh was already processed since the
  356. ** last PDU was flushed. If so we must free up the last refresh in
  357. ** preperation for the new one built here. Otherwise, if we have
  358. ** already started building an update this is not currently
  359. ** supported and is considered an error here.
  360. */
  361. if (m_SetOfAppInfo.value.application_record_list.choice == APPLICATION_RECORD_REFRESH_CHOSEN)
  362. {
  363. FreeSetOfRefreshesPDU();
  364. }
  365. else
  366. if (m_SetOfAppInfo.value.application_record_list.choice == APPLICATION_RECORD_UPDATE_CHOSEN)
  367. {
  368. ERROR_OUT(("CAppRoster::BuildApplicationRecordListPDU:"
  369. "ASSERTION: building refresh when update exists"));
  370. return GCC_INVALID_PARAMETER;
  371. }
  372. // This routine fills in the complete record list at this node.
  373. rc = BuildSetOfRefreshesPDU();
  374. if (rc == GCC_NO_ERROR)
  375. {
  376. m_SetOfAppInfo.value.application_record_list.choice = APPLICATION_RECORD_REFRESH_CHOSEN;
  377. }
  378. }
  379. else
  380. if (update_type != APP_NO_CHANGE)
  381. {
  382. /*
  383. ** Here if there has already been a refresh PDU built we flag this
  384. ** as an error since we do not support both types of application
  385. ** information at the same time.
  386. */
  387. if (m_SetOfAppInfo.value.application_record_list.choice == APPLICATION_RECORD_REFRESH_CHOSEN)
  388. {
  389. ERROR_OUT(("CAppRoster::BuildApplicationRecordListPDU:"
  390. "ASSERTION: building update when refresh exists"));
  391. return GCC_INVALID_PARAMETER;
  392. }
  393. // This routine fills in the specified update.
  394. rc = BuildSetOfUpdatesPDU(update_type, user_id, entity_id);
  395. if (rc == GCC_NO_ERROR)
  396. {
  397. /*
  398. ** If the first set of updates has not been used yet we
  399. ** initialize it here with the first update.
  400. */
  401. if (m_SetOfAppInfo.value.application_record_list.choice == APPLICATION_NO_CHANGE_CHOSEN)
  402. {
  403. ASSERT(NULL != m_pSetOfAppRecordUpdates);
  404. m_SetOfAppInfo.value.application_record_list.u.application_record_update =
  405. m_pSetOfAppRecordUpdates;
  406. m_SetOfAppInfo.value.application_record_list.choice = APPLICATION_RECORD_UPDATE_CHOSEN;
  407. }
  408. }
  409. }
  410. }
  411. return rc;
  412. }
  413. /*
  414. * GCCError BuildSetOfRefreshesPDU ()
  415. *
  416. * Private Function Description
  417. * This member function fills in the PDU with the entire set of roster
  418. * entries at this node. This is typically called when the Top Provider is
  419. * broadcasting a full refresh of the application roster.
  420. *
  421. * Formal Parameters
  422. * none
  423. *
  424. * Return Value
  425. * GCC_NO_ERROR - On Success
  426. * GCC_ALLOCATION_FAILURE - On resource failure
  427. *
  428. * Side Effects
  429. * none
  430. *
  431. * Caveats
  432. * none
  433. */
  434. GCCError CAppRoster::BuildSetOfRefreshesPDU(void)
  435. {
  436. GCCError rc = GCC_ALLOCATION_FAILURE;
  437. PSetOfApplicationRecordRefreshes pNewAppRecordRefreshes;
  438. PSetOfApplicationRecordRefreshes pOldAppRecordRefreshes = NULL;
  439. APP_NODE_RECORD *lpAppNodeRecord;
  440. APP_RECORD *lpAppRecData;
  441. CAppRecordList2 *lpAppRecDataList;
  442. UserID uid, uid2;
  443. EntityID eid;
  444. DebugEntry(CAppRoster::BuildSetOfRefreshesPDU);
  445. m_SetOfAppInfo.value.application_record_list.u.application_record_refresh = NULL;
  446. m_NodeRecordList2.Reset();
  447. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate(&uid)))
  448. {
  449. /*
  450. ** First we iterate through this nodes application record list. This
  451. ** encodes all the records local to this node. After this, all the
  452. ** sub nodes within this roster record will be encoded.
  453. */
  454. lpAppNodeRecord->AppRecordList.Reset();
  455. while (NULL != (lpAppRecData = lpAppNodeRecord->AppRecordList.Iterate(&eid)))
  456. {
  457. DBG_SAVE_FILE_LINE
  458. pNewAppRecordRefreshes = new SetOfApplicationRecordRefreshes;
  459. if (NULL == pNewAppRecordRefreshes)
  460. {
  461. goto MyExit;
  462. }
  463. if (m_SetOfAppInfo.value.application_record_list.u.application_record_refresh == NULL)
  464. {
  465. m_SetOfAppInfo.value.application_record_list.u.application_record_refresh = pNewAppRecordRefreshes;
  466. }
  467. else
  468. {
  469. pOldAppRecordRefreshes->next = pNewAppRecordRefreshes;
  470. }
  471. (pOldAppRecordRefreshes = pNewAppRecordRefreshes)->next = NULL;
  472. pNewAppRecordRefreshes->value.node_id = uid;
  473. pNewAppRecordRefreshes->value.entity_id = eid;
  474. // Fill in the application record.
  475. rc = BuildApplicationRecordPDU(lpAppRecData,
  476. &pNewAppRecordRefreshes->value.application_record);
  477. if (GCC_NO_ERROR != rc)
  478. {
  479. goto MyExit;
  480. }
  481. }
  482. // This section of the code copies the sub node records.
  483. lpAppNodeRecord->SubNodeList2.Reset();
  484. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate(&uid2)))
  485. {
  486. lpAppRecDataList->Reset();
  487. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate(&eid)))
  488. {
  489. DBG_SAVE_FILE_LINE
  490. pNewAppRecordRefreshes = new SetOfApplicationRecordRefreshes;
  491. if (NULL == pNewAppRecordRefreshes)
  492. {
  493. goto MyExit;
  494. }
  495. /*
  496. ** We must again check for null because it is possible
  497. ** to have an application roster with sub node records
  498. ** but no application records.
  499. */
  500. if (m_SetOfAppInfo.value.application_record_list.u.application_record_refresh == NULL)
  501. {
  502. m_SetOfAppInfo.value.application_record_list.u.application_record_refresh = pNewAppRecordRefreshes;
  503. }
  504. else
  505. {
  506. pOldAppRecordRefreshes->next = pNewAppRecordRefreshes;
  507. }
  508. (pOldAppRecordRefreshes = pNewAppRecordRefreshes)->next = NULL;
  509. pNewAppRecordRefreshes->value.node_id = uid2;
  510. pNewAppRecordRefreshes->value.entity_id = eid;
  511. // Fill in the application record.
  512. rc = BuildApplicationRecordPDU (lpAppRecData,
  513. &pNewAppRecordRefreshes->value.application_record);
  514. if (GCC_NO_ERROR != rc)
  515. {
  516. goto MyExit;
  517. }
  518. }
  519. }
  520. }
  521. rc = GCC_NO_ERROR;
  522. MyExit:
  523. return rc;
  524. }
  525. /*
  526. * GCCError BuildSetOfUpdatesPDU ()
  527. *
  528. * Private Function Description
  529. * This routine builds a single update based on the update type specified
  530. * in the passed in parameter.
  531. *
  532. * Formal Parameters
  533. * update_type - (i) Either APP_REPLACE_RECORD, APP_DELETE_RECORD, or
  534. * APP_ADD_RECORD.
  535. * node_id - (i) The node id of the update PDU record to build.
  536. * entity_id (i) The entity id of the update PDU record to build.
  537. *
  538. * Return Value
  539. * GCC_NO_ERROR - On Success
  540. * GCC_ALLOCATION_FAILURE - On resource failure
  541. * GCC_NO_SUCH_APPLICATION - If the specified record doesn't exist
  542. *
  543. * Side Effects
  544. * none
  545. *
  546. * Caveats
  547. * none
  548. */
  549. GCCError CAppRoster::BuildSetOfUpdatesPDU(
  550. APP_ROSTER_UPDATE_TYPE update_type,
  551. UserID node_id,
  552. EntityID entity_id)
  553. {
  554. GCCError rc = GCC_NO_ERROR;
  555. CAppRecordList2 *pAppRecordList;
  556. APP_RECORD *pAppRecord = NULL;
  557. APP_NODE_RECORD *node_record;
  558. DebugEntry(CAppRoster::BuildSetOfUpdatesPDU);
  559. /*
  560. ** We must first determine the pointer to the application record
  561. ** specified by the passed in user id and entity_id. We only do
  562. ** this search if the update type is not APP_DELETE_RECORD.
  563. */
  564. if (update_type != APP_DELETE_RECORD)
  565. {
  566. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  567. {
  568. // Get a pointer to the application record from the entity id.
  569. pAppRecord = node_record->AppRecordList.Find(entity_id);
  570. }
  571. else
  572. {
  573. // Here we iterate through the sub-node list looking for the record
  574. m_NodeRecordList2.Reset();
  575. while(NULL != (node_record = m_NodeRecordList2.Iterate()))
  576. {
  577. if (NULL != (pAppRecordList = node_record->SubNodeList2.Find(node_id)))
  578. {
  579. pAppRecord = pAppRecordList->Find(entity_id);
  580. break;
  581. }
  582. }
  583. }
  584. }
  585. /*
  586. ** Now if the application record was found or the update type is delete
  587. ** record we go ahead and encode the PDU here.
  588. */
  589. if ((pAppRecord != NULL) || (update_type == APP_DELETE_RECORD))
  590. {
  591. /*
  592. ** Here the record update will be NULL if it is the first record
  593. ** update being encoded. Otherwise we must bump the record to the
  594. ** next set of updates.
  595. */
  596. DBG_SAVE_FILE_LINE
  597. PSetOfApplicationRecordUpdates pUpdates = new SetOfApplicationRecordUpdates;
  598. if (NULL == pUpdates)
  599. {
  600. return GCC_ALLOCATION_FAILURE;
  601. }
  602. pUpdates->next = NULL;
  603. if (m_pSetOfAppRecordUpdates == NULL)
  604. {
  605. m_pSetOfAppRecordUpdates = pUpdates;
  606. }
  607. else
  608. {
  609. //
  610. // LONCHANC: right now, append the new one.
  611. // but, can we prepend the new one???
  612. //
  613. PSetOfApplicationRecordUpdates p;
  614. for (p = m_pSetOfAppRecordUpdates; NULL != p->next; p = p->next)
  615. ;
  616. p->next = pUpdates;
  617. }
  618. /*
  619. * This routine only returns one record.
  620. */
  621. pUpdates->value.node_id = node_id;
  622. pUpdates->value.entity_id = entity_id;
  623. switch (update_type)
  624. {
  625. case APP_ADD_RECORD:
  626. pUpdates->value.application_update.choice = APPLICATION_ADD_RECORD_CHOSEN;
  627. BuildApplicationRecordPDU(pAppRecord,
  628. &(pUpdates->value.application_update.u.application_add_record));
  629. break;
  630. case APP_REPLACE_RECORD:
  631. pUpdates->value.application_update.choice = APPLICATION_REPLACE_RECORD_CHOSEN;
  632. rc = BuildApplicationRecordPDU(pAppRecord,
  633. &(pUpdates->value.application_update.u.application_replace_record));
  634. break;
  635. default:
  636. /*
  637. * The record does not have to be filled in for this case.
  638. */
  639. pUpdates->value.application_update.choice = APPLICATION_REMOVE_RECORD_CHOSEN;
  640. break;
  641. }
  642. }
  643. else
  644. {
  645. WARNING_OUT(("CAppRoster::BuildSetOfUpdatesPDU: Assertion:"
  646. "No applicaton record found for PDU"));
  647. rc = GCC_NO_SUCH_APPLICATION;
  648. }
  649. return rc;
  650. }
  651. /*
  652. * GCCError BuildApplicationRecordPDU ()
  653. *
  654. * Private Function Description
  655. * This routine build a single application record for a PDU. A pointer to
  656. * the record is passed in to the routine.
  657. *
  658. * Formal Parameters
  659. * application_record - (i) Record to be encoded.
  660. * application_record_pdu - (i) PDU to fill in.
  661. *
  662. * Return Value
  663. * GCC_NO_ERROR - On Success
  664. * GCC_ALLOCATION_FAILURE - A resource error occured.
  665. *
  666. * Side Effects
  667. * none
  668. *
  669. * Caveats
  670. * none
  671. */
  672. GCCError CAppRoster::BuildApplicationRecordPDU(
  673. APP_RECORD *pAppRecord,
  674. PApplicationRecord pAppRecordPdu)
  675. {
  676. GCCError rc = GCC_NO_ERROR;
  677. DebugEntry(CAppRoster::BuildApplicationRecordPDU);
  678. pAppRecordPdu->bit_mask = 0;
  679. if (! pAppRecord->non_collapsed_caps_list.IsEmpty())
  680. {
  681. pAppRecordPdu->bit_mask |= NON_COLLAPSING_CAPABILITIES_PRESENT;
  682. rc = BuildSetOfNonCollapsingCapabilitiesPDU(
  683. &pAppRecordPdu->non_collapsing_capabilities,
  684. &pAppRecord->non_collapsed_caps_list);
  685. if (GCC_NO_ERROR != rc)
  686. {
  687. goto MyExit;
  688. }
  689. }
  690. // Fill in the startup channel type if it is specified
  691. if (pAppRecord->startup_channel_type != MCS_NO_CHANNEL_TYPE_SPECIFIED)
  692. {
  693. pAppRecordPdu->bit_mask |= RECORD_STARTUP_CHANNEL_PRESENT;
  694. pAppRecordPdu->record_startup_channel = (ChannelType) pAppRecord->startup_channel_type;
  695. }
  696. // Fill in the application user id if one is specified
  697. if (pAppRecord->application_user_id != 0)
  698. {
  699. pAppRecordPdu->bit_mask |= APPLICATION_USER_ID_PRESENT;
  700. pAppRecordPdu->application_user_id = pAppRecord->application_user_id;
  701. }
  702. // Fill in the required fields
  703. pAppRecordPdu->application_is_active = (ASN1bool_t)pAppRecord->is_enrolled_actively;
  704. pAppRecordPdu->is_conducting_capable = (ASN1bool_t)pAppRecord->is_conducting_capable;
  705. ASSERT(GCC_NO_ERROR == rc);
  706. MyExit:
  707. return rc;
  708. }
  709. /*
  710. * GCCError BuildSetOfCapabilityRefreshesPDU ()
  711. *
  712. * Private Function Description
  713. * This routine builds a PDU structure with the complete set of
  714. * capabilities maintained at this node.
  715. *
  716. * Formal Parameters
  717. * None
  718. *
  719. * Return Value
  720. * GCC_NO_ERROR - On Success
  721. * GCC_ALLOCATIONFAILURE - On resource failure
  722. *
  723. * Side Effects
  724. * None
  725. *
  726. * Caveats
  727. * The standard allows us to send a zero length set of capabilities when
  728. * an application leaves that previously had capabilites.
  729. */
  730. GCCError CAppRoster::BuildSetOfCapabilityRefreshesPDU(void)
  731. {
  732. GCCError rc = GCC_ALLOCATION_FAILURE;
  733. PSetOfApplicationCapabilityRefreshes pNew;
  734. PSetOfApplicationCapabilityRefreshes pOld = NULL;
  735. DebugEntry(CAppRoster::BuildSetOfCapabilityRefreshesPDU);
  736. if (m_fMaintainPduBuffer)
  737. {
  738. APP_CAP_ITEM *lpAppCapData;
  739. /*
  740. ** We must first free up any previously built PDU data associated
  741. ** with a capability refresh.
  742. */
  743. if (m_SetOfAppInfo.value.application_capabilities_list.choice == APPLICATION_CAPABILITY_REFRESH_CHOSEN)
  744. {
  745. FreeSetOfCapabilityRefreshesPDU ();
  746. }
  747. m_SetOfAppInfo.value.application_capabilities_list.choice = APPLICATION_CAPABILITY_REFRESH_CHOSEN;
  748. m_SetOfAppInfo.value.application_capabilities_list.u.application_capability_refresh = NULL;
  749. // Iterate through the complete list of capabilities.
  750. m_CollapsedCapListForAllNodes.Reset();
  751. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  752. {
  753. DBG_SAVE_FILE_LINE
  754. pNew = new SetOfApplicationCapabilityRefreshes;
  755. if (NULL == pNew)
  756. {
  757. goto MyExit;
  758. }
  759. /*
  760. ** If the set of capability refreshes pointer is equal to NULL
  761. ** we are at the first capability. Here we need to save the
  762. ** pointer to the first capability.
  763. */
  764. if (m_SetOfAppInfo.value.application_capabilities_list.u.
  765. application_capability_refresh == NULL)
  766. {
  767. m_SetOfAppInfo.value.application_capabilities_list.u.
  768. application_capability_refresh = pNew;
  769. }
  770. else
  771. {
  772. pOld->next = pNew;
  773. }
  774. /*
  775. ** This is used to set the next pointer if another record
  776. ** exists after this one.
  777. */
  778. /*
  779. * This will get filled in later if there is another record.
  780. */
  781. (pOld = pNew)->next = NULL;
  782. // Fill in the capability identifier
  783. rc = lpAppCapData->pCapID->GetCapabilityIdentifierDataPDU(
  784. &pNew->value.capability_id);
  785. if (GCC_NO_ERROR != rc)
  786. {
  787. goto MyExit;
  788. }
  789. // Fill in the capability choice from the GCC capability class.
  790. pNew->value.capability_class.choice = (USHORT) lpAppCapData->eCapType;
  791. // Note that nothing is filled in for a logical capability.
  792. if (lpAppCapData->eCapType == GCC_UNSIGNED_MINIMUM_CAPABILITY)
  793. {
  794. pNew->value.capability_class.u.unsigned_minimum =
  795. lpAppCapData->nUnsignedMinimum;
  796. }
  797. else if (lpAppCapData->eCapType == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  798. {
  799. pNew->value.capability_class.u.unsigned_maximum =
  800. lpAppCapData->nUnsignedMaximum;
  801. }
  802. // Fill in number of entities regardless of capability type.
  803. pNew->value.number_of_entities = lpAppCapData->cEntries;
  804. }
  805. }
  806. rc = GCC_NO_ERROR;
  807. MyExit:
  808. return rc;
  809. }
  810. /*
  811. * ApplicationRosterError BuildSetOfNonCollapsingCapabilitiesPDU ()
  812. *
  813. * Private Function Description
  814. * This routine builds a PDU structure for the non collapsing capabilities
  815. * list associated passed in.
  816. *
  817. * Formal Parameters
  818. * pSetOfCaps - (o) PDU structure to fill in
  819. * capabilities_list - (i) Source non-collapsing capabilities.
  820. *
  821. * Return Value
  822. * GCC_NO_ERROR - On Success
  823. * GCC_ALLOCATIONFAILURE - On resource failure
  824. *
  825. * Side Effects
  826. * None
  827. *
  828. * Caveats
  829. * None
  830. */
  831. GCCError CAppRoster::BuildSetOfNonCollapsingCapabilitiesPDU(
  832. PSetOfNonCollapsingCapabilities *pSetOfCaps,
  833. CAppCapItemList *pAppCapItemList)
  834. {
  835. GCCError rc = GCC_ALLOCATION_FAILURE;
  836. PSetOfNonCollapsingCapabilities new_set_of_capabilities;
  837. PSetOfNonCollapsingCapabilities old_set_of_capabilities;
  838. APP_CAP_ITEM *lpAppCapData;
  839. DebugEntry(CAppRoster::BuildSetOfNonCollapsingCapabilitiesPDU);
  840. *pSetOfCaps = NULL;
  841. old_set_of_capabilities = NULL; // Setting this to NULL removes warning
  842. /*
  843. * Iterate through the complete list of capabilities.
  844. */
  845. pAppCapItemList->Reset();
  846. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  847. {
  848. DBG_SAVE_FILE_LINE
  849. new_set_of_capabilities = new SetOfNonCollapsingCapabilities;
  850. if (NULL == new_set_of_capabilities)
  851. {
  852. goto MyExit;
  853. }
  854. /*
  855. ** If the passed in pointer is equal to NULL we are at the first
  856. ** capability. Here we need to save the pointer to the first
  857. ** capability in the passed in pointer.
  858. */
  859. if (*pSetOfCaps == NULL)
  860. {
  861. *pSetOfCaps = new_set_of_capabilities;
  862. }
  863. else
  864. {
  865. old_set_of_capabilities->next = new_set_of_capabilities;
  866. }
  867. /*
  868. ** This is used to set the next pointer if another record exists
  869. ** after this one.
  870. */
  871. old_set_of_capabilities = new_set_of_capabilities;
  872. /*
  873. * This will get filled in later if there is another record.
  874. */
  875. new_set_of_capabilities->next = NULL;
  876. new_set_of_capabilities->value.bit_mask = 0;
  877. // Fill in the capability identifier
  878. rc = lpAppCapData->pCapID->GetCapabilityIdentifierDataPDU(
  879. &new_set_of_capabilities->value.capability_id);
  880. if (GCC_NO_ERROR != rc)
  881. {
  882. goto MyExit;
  883. }
  884. if ((lpAppCapData->poszAppData != NULL) && (rc == GCC_NO_ERROR))
  885. {
  886. new_set_of_capabilities->value.bit_mask |= APPLICATION_DATA_PRESENT;
  887. new_set_of_capabilities->value.application_data.length =
  888. lpAppCapData->poszAppData->length;
  889. new_set_of_capabilities->value.application_data.value =
  890. lpAppCapData->poszAppData->value;
  891. }
  892. }
  893. rc = GCC_NO_ERROR;
  894. MyExit:
  895. return rc;
  896. }
  897. /*
  898. * These routines are used to free up a roster update indication PDU.
  899. */
  900. /*
  901. * void FreeRosterUpdateIndicationPDU ()
  902. *
  903. * Private Function Description
  904. * This routine frees up all the internal data allocated to hold the roster
  905. * update PDU.
  906. *
  907. * Formal Parameters
  908. * None
  909. *
  910. * Return Value
  911. * None
  912. *
  913. * Side Effects
  914. * None
  915. *
  916. * Caveats
  917. * Note that the session key PDU data is not freed. Since this data will
  918. * not change through out the life of this application roster object
  919. * we just use the same session id PDU data for every roster update
  920. * indication.
  921. */
  922. void CAppRoster::FreeRosterUpdateIndicationPDU(void)
  923. {
  924. DebugEntry(CAppRoster::FreeRosterUpdateIndicationPDU);
  925. switch (m_SetOfAppInfo.value.application_record_list.choice)
  926. {
  927. case APPLICATION_RECORD_REFRESH_CHOSEN:
  928. FreeSetOfRefreshesPDU ();
  929. break;
  930. case APPLICATION_RECORD_UPDATE_CHOSEN:
  931. FreeSetOfUpdatesPDU ();
  932. break;
  933. }
  934. // Free the PDU data associated with the capability list if one exists.
  935. if (m_SetOfAppInfo.value.application_capabilities_list.choice == APPLICATION_CAPABILITY_REFRESH_CHOSEN)
  936. {
  937. FreeSetOfCapabilityRefreshesPDU ();
  938. }
  939. m_SetOfAppInfo.value.application_record_list.choice = APPLICATION_NO_CHANGE_CHOSEN;
  940. m_SetOfAppInfo.value.application_capabilities_list.choice = CAPABILITY_NO_CHANGE_CHOSEN;
  941. m_pSetOfAppRecordUpdates = NULL;
  942. }
  943. /*
  944. * void FreeSetOfRefreshesPDU ()
  945. *
  946. * Private Function Description
  947. * This routine Frees all the memory associated with a set
  948. * of application record refreshes.
  949. *
  950. * Formal Parameters
  951. * none
  952. *
  953. * Return Value
  954. * none
  955. *
  956. * Side Effects
  957. * none
  958. *
  959. * Caveats
  960. * none
  961. */
  962. void CAppRoster::FreeSetOfRefreshesPDU(void)
  963. {
  964. PSetOfApplicationRecordRefreshes pCurr, pNext;
  965. DebugEntry(CAppRoster::FreeSetOfRefreshesPDU);
  966. for (pCurr = m_SetOfAppInfo.value.application_record_list.u.application_record_refresh;
  967. NULL != pCurr;
  968. pCurr = pNext)
  969. {
  970. pNext = pCurr->next;
  971. // Free up any non-collapsing capabilities data
  972. if (pCurr->value.application_record.bit_mask & NON_COLLAPSING_CAPABILITIES_PRESENT)
  973. {
  974. FreeSetOfNonCollapsingCapabilitiesPDU(pCurr->value.application_record.non_collapsing_capabilities);
  975. }
  976. // Delete the actual record refresh
  977. delete pCurr;
  978. }
  979. m_SetOfAppInfo.value.application_record_list.u.application_record_refresh = NULL;
  980. }
  981. /*
  982. * void FreeSetOfUpdatesPDU ()
  983. *
  984. * Private Function Description
  985. * This routine frees the memory associated with a complete set
  986. * application roster updates.
  987. *
  988. * Formal Parameters
  989. * none
  990. *
  991. * Return Value
  992. * none
  993. *
  994. * Side Effects
  995. * none
  996. *
  997. * Caveats
  998. * none
  999. */
  1000. void CAppRoster::FreeSetOfUpdatesPDU(void)
  1001. {
  1002. PSetOfApplicationRecordUpdates pCurr, pNext;
  1003. PApplicationRecord application_record;
  1004. DebugEntry(CAppRoster::FreeSetOfUpdatesPDU);
  1005. for (pCurr = m_SetOfAppInfo.value.application_record_list.u.application_record_update;
  1006. NULL != pCurr;
  1007. pCurr = pNext)
  1008. {
  1009. // remember the next one because we will free the current one
  1010. pNext = pCurr->next;
  1011. // Free up any non-collapsing capabilities data
  1012. switch(pCurr->value.application_update.choice)
  1013. {
  1014. case APPLICATION_ADD_RECORD_CHOSEN:
  1015. application_record = &pCurr->value.application_update.u.application_add_record;
  1016. break;
  1017. case APPLICATION_REPLACE_RECORD_CHOSEN:
  1018. application_record = &pCurr->value.application_update.u.application_replace_record;
  1019. break;
  1020. default:
  1021. application_record = NULL;
  1022. break;
  1023. }
  1024. if (application_record != NULL)
  1025. {
  1026. if (application_record->bit_mask & NON_COLLAPSING_CAPABILITIES_PRESENT)
  1027. {
  1028. FreeSetOfNonCollapsingCapabilitiesPDU(application_record->non_collapsing_capabilities);
  1029. }
  1030. }
  1031. // Delete the actual update structure
  1032. delete pCurr;
  1033. }
  1034. m_SetOfAppInfo.value.application_record_list.u.application_record_update = NULL;
  1035. }
  1036. /*
  1037. * void FreeSetOfCapabilityRefreshesPDU ()
  1038. *
  1039. * Private Function Description
  1040. * This routine frees all the memory associated with the capability PDU.
  1041. *
  1042. * Formal Parameters
  1043. * capability_refresh - (i) Capabilities to be freed.
  1044. *
  1045. * Return Value
  1046. * none
  1047. *
  1048. * Side Effects
  1049. * none
  1050. *
  1051. * Caveats
  1052. * Note that the capability id PDU data is not freed here. Since this
  1053. * data should not change through out the life of this object we don't
  1054. * bother freeing and regenerating it.
  1055. */
  1056. void CAppRoster::FreeSetOfCapabilityRefreshesPDU(void)
  1057. {
  1058. PSetOfApplicationCapabilityRefreshes pCurr, pNext;
  1059. for (pCurr = m_SetOfAppInfo.value.application_capabilities_list.u.application_capability_refresh;
  1060. NULL != pCurr;
  1061. pCurr = pNext)
  1062. {
  1063. pNext = pCurr->next;
  1064. delete pCurr;
  1065. }
  1066. }
  1067. /*
  1068. * void FreeSetOfNonCollapsingCapabilitiesPDU ()
  1069. *
  1070. * Private Function Description
  1071. * This routine frees all the memory associated with the
  1072. * non-collapsed capability PDU.
  1073. *
  1074. * Formal Parameters
  1075. * capability_refresh - (i) Non-Collapsed Capabilities to be freed.
  1076. *
  1077. * Return Value
  1078. * none
  1079. *
  1080. * Side Effects
  1081. * none
  1082. *
  1083. * Caveats
  1084. * Note that the capability id PDU data is not freed here. Since this
  1085. * data should not change through out the life of this object we don't
  1086. * bother freeing and regenerating it.
  1087. */
  1088. void CAppRoster::FreeSetOfNonCollapsingCapabilitiesPDU (
  1089. PSetOfNonCollapsingCapabilities capability_refresh)
  1090. {
  1091. PSetOfNonCollapsingCapabilities pCurr, pNext;
  1092. for (pCurr = capability_refresh; NULL != pCurr; pCurr = pNext)
  1093. {
  1094. pNext = pCurr->next;
  1095. delete pCurr;
  1096. }
  1097. }
  1098. /*
  1099. * These routines process roster update indication PDUs.
  1100. */
  1101. /*
  1102. * ApplicationRosterError ProcessRosterUpdateIndicationPDU ()
  1103. *
  1104. * Public Function Description
  1105. * This routine is responsible for processing the decoded PDU data.
  1106. * It essentially changes the application roster object's internal database
  1107. * based on the information in the structure.
  1108. */
  1109. GCCError CAppRoster::ProcessRosterUpdateIndicationPDU (
  1110. PSetOfApplicationInformation application_information,
  1111. UserID sender_id)
  1112. {
  1113. GCCError rc = GCC_NO_ERROR;
  1114. DebugEntry(CAppRoster::ProcessRosterUpdateIndicationPDU);
  1115. /*
  1116. ** Free up the old PDU data here if it is being maintained and the
  1117. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  1118. ** back to FALSE so that the new PDU will be maintained until it is
  1119. ** flushed.
  1120. */
  1121. if (m_fPduIsFlushed)
  1122. {
  1123. FreeRosterUpdateIndicationPDU ();
  1124. m_fPduIsFlushed = FALSE;
  1125. }
  1126. /*
  1127. ** Now check the application key to make sure we have a match. If
  1128. ** not, return with no change.
  1129. */
  1130. if (! m_pSessionKey->IsThisYourSessionKeyPDU(&application_information->value.session_key))
  1131. {
  1132. WARNING_OUT(("CAppRoster::ProcessRosterUpdateIndicationPDU:GCC_BAD_SESSION_KEY"));
  1133. rc = GCC_BAD_SESSION_KEY;
  1134. goto MyExit;
  1135. }
  1136. /*
  1137. ** If this is a roster update and refresh is chosen we must
  1138. ** clear out the entire list and rebuild it.
  1139. */
  1140. if (application_information->value.application_record_list.choice != APPLICATION_NO_CHANGE_CHOSEN)
  1141. {
  1142. // The roster is about to change
  1143. m_fRosterHasChanged = TRUE;
  1144. /*
  1145. ** If this node is the top provider or this roster is local and
  1146. ** only used to propogate PDUs up toward the top provider,
  1147. ** we increment the instance number. If it is not we get the
  1148. ** instance number out of the PDU.
  1149. */
  1150. if (m_fTopProvider || m_fLocalRoster)
  1151. {
  1152. m_nInstance++;
  1153. }
  1154. else
  1155. {
  1156. m_nInstance = application_information->value.roster_instance_number;
  1157. }
  1158. /*
  1159. ** Here if either of these booleans is already TRUE we do not
  1160. ** want to write over them with this PDU data. Therefore, we
  1161. ** check for FALSE before we do anything with them.
  1162. */
  1163. if (! m_fPeerEntitiesAdded)
  1164. {
  1165. m_fPeerEntitiesAdded = application_information->value.peer_entities_are_added;
  1166. }
  1167. if (! m_fPeerEntitiesRemoved)
  1168. {
  1169. m_fPeerEntitiesRemoved = application_information->value.peer_entities_are_removed;
  1170. }
  1171. if (application_information->value.application_record_list.choice == APPLICATION_RECORD_REFRESH_CHOSEN)
  1172. {
  1173. TRACE_OUT(("CAppRoster::ProcessRosterUpdateIndicationPDU:ProcessSetOfRefreshesPDU"));
  1174. rc = ProcessSetOfRefreshesPDU(
  1175. application_information->value.application_record_list.u.application_record_refresh,
  1176. sender_id);
  1177. }
  1178. else
  1179. {
  1180. TRACE_OUT(("CAppRoster::ProcessRosterUpdateIndicationPDU:ProcessSetOfUpdatesPDU"));
  1181. rc = ProcessSetOfUpdatesPDU(
  1182. application_information->value.application_record_list.u.application_record_update,
  1183. sender_id);
  1184. }
  1185. if (GCC_NO_ERROR != rc)
  1186. {
  1187. goto MyExit;
  1188. }
  1189. }
  1190. else
  1191. {
  1192. ERROR_OUT(("AppRoster::ProcessRosterUpdateIndicationPDU:ASSERTION: NO Change PDU received"));
  1193. }
  1194. // Process the capabilities list portion of the PDU.
  1195. if (application_information->value.application_capabilities_list.choice == APPLICATION_CAPABILITY_REFRESH_CHOSEN)
  1196. {
  1197. // Set flag to show that change has occured.
  1198. m_fCapabilitiesHaveChanged = TRUE;
  1199. /*
  1200. ** We will store the new capabilities in the roster record
  1201. ** associated with the sender id. Note that it is possible for
  1202. ** this roster record to contain an empty application record list
  1203. ** if the sending node has no enrolled applications.
  1204. */
  1205. rc = ProcessSetOfCapabilityRefreshesPDU(
  1206. application_information->value.application_capabilities_list.u.application_capability_refresh,
  1207. sender_id);
  1208. }
  1209. else
  1210. {
  1211. ASSERT(GCC_NO_ERROR == rc);
  1212. }
  1213. MyExit:
  1214. return rc;
  1215. }
  1216. /*
  1217. * GCCError ProcessSetOfRefreshesPDU ()
  1218. *
  1219. * Private Function Description
  1220. * This routine processes a set of record refreshes. It is responsible
  1221. * for managing the creation (or update) of all affected application
  1222. * records. The roster list built from a refresh PDU does not maintain the
  1223. * hierarchy of the conference since it is not important at this point.
  1224. * Refreshes are issued as broacast from the Top Provider down to the
  1225. * sub-ordinate nodes.
  1226. *
  1227. * Formal Parameters
  1228. * record_refresh - (i) Set of record refresh PDUs to be processed.
  1229. * sender_id - (i) Node id of node that sent the update.
  1230. *
  1231. * Return Value
  1232. * GCC_NO_ERROR - On Success
  1233. * GCC_ALLOCATION_FAILURE - On resource failure
  1234. *
  1235. * Side Effects
  1236. * none
  1237. *
  1238. * Caveate
  1239. * none
  1240. */
  1241. GCCError CAppRoster::ProcessSetOfRefreshesPDU(
  1242. PSetOfApplicationRecordRefreshes record_refresh,
  1243. UserID sender_id)
  1244. {
  1245. GCCError rc = GCC_ALLOCATION_FAILURE;
  1246. PSetOfApplicationRecordRefreshes pCurr;
  1247. APP_RECORD *app_record;
  1248. APP_NODE_RECORD *node_record;
  1249. CAppRecordList2 *record_list;
  1250. UserID node_id;
  1251. EntityID entity_id;
  1252. DebugEntry(CAppRoster::ProcessSetOfRefreshesPDU);
  1253. if (record_refresh != NULL)
  1254. {
  1255. // Clear out the node record for the sender id
  1256. ClearNodeRecordFromList (sender_id);
  1257. /*
  1258. ** Create the node record for the sender id passed into this routine.
  1259. ** Note that if the sender of this refresh is the Top Provider
  1260. ** all nodes below the top provider are contained in the sub node
  1261. ** list of the Top Provider's node record.
  1262. */
  1263. DBG_SAVE_FILE_LINE
  1264. node_record = new APP_NODE_RECORD;
  1265. if (NULL == node_record)
  1266. {
  1267. goto MyExit;
  1268. }
  1269. m_NodeRecordList2.Append(sender_id, node_record);
  1270. for (pCurr = record_refresh; NULL != pCurr; pCurr = pCurr->next)
  1271. {
  1272. node_id = pCurr->value.node_id;
  1273. entity_id = pCurr->value.entity_id;
  1274. if (sender_id != node_id)
  1275. {
  1276. // Get or create the sub node record list
  1277. if (NULL == (record_list = node_record->SubNodeList2.Find(node_id)))
  1278. {
  1279. DBG_SAVE_FILE_LINE
  1280. record_list = new CAppRecordList2(DESIRED_MAX_APP_RECORDS);
  1281. if (NULL == record_list)
  1282. {
  1283. goto MyExit;
  1284. }
  1285. node_record->SubNodeList2.Append(node_id, record_list);
  1286. }
  1287. }
  1288. else
  1289. {
  1290. /*
  1291. ** Here we set up the pointer to the record list. This
  1292. ** list is the node records application list which
  1293. ** means that this list contains the application records
  1294. ** associated with the sender's node.
  1295. */
  1296. record_list = &node_record->AppRecordList;
  1297. }
  1298. // Now create and fill in the new application record.
  1299. DBG_SAVE_FILE_LINE
  1300. app_record = new APP_RECORD;
  1301. if (NULL == app_record)
  1302. {
  1303. goto MyExit;
  1304. }
  1305. rc = ProcessApplicationRecordPDU(app_record, &pCurr->value.application_record);
  1306. if (GCC_NO_ERROR != rc)
  1307. {
  1308. goto MyExit;
  1309. }
  1310. record_list->Append(entity_id, app_record);
  1311. } // for
  1312. }
  1313. else
  1314. {
  1315. // This roster no longer contains any entries so clear the list!!!
  1316. ClearNodeRecordList ();
  1317. }
  1318. /*
  1319. ** Build a full refresh PDU here if no errors occured while processing
  1320. ** the refresh PDU.
  1321. */
  1322. rc = BuildApplicationRecordListPDU (APP_FULL_REFRESH, 0, 0);
  1323. MyExit:
  1324. return rc;
  1325. }
  1326. /*
  1327. * GCCError ProcessSetOfUpdatesPDU ()
  1328. *
  1329. * Private Function Description
  1330. * This routine processes a set of roster updates. It iterates through
  1331. * the complete list of updates making all necessary changes to the
  1332. * internal information base and building the appropriate PDU.
  1333. *
  1334. * Formal Parameters
  1335. * record_update - (i) set of updates PDU to be processed
  1336. * sender_id - (i) gcc user id of node that sent the update
  1337. *
  1338. * Return Value
  1339. * APP_ROSTER_NO_ERROR - On Success
  1340. * APP_ROSTER_RESOURCE_ERROR - On resource failure
  1341. *
  1342. * Side Effects
  1343. * none
  1344. *
  1345. * Caveate
  1346. * none
  1347. */
  1348. GCCError CAppRoster::ProcessSetOfUpdatesPDU(
  1349. PSetOfApplicationRecordUpdates record_update,
  1350. UserID sender_id)
  1351. {
  1352. GCCError rc = GCC_ALLOCATION_FAILURE;
  1353. PSetOfApplicationRecordUpdates pCurr;
  1354. UserID node_id;
  1355. EntityID entity_id;
  1356. PApplicationRecord pdu_record;
  1357. APP_RECORD *application_record = NULL;
  1358. APP_NODE_RECORD *node_record;
  1359. CAppRecordList2 *record_list;
  1360. APP_ROSTER_UPDATE_TYPE update_type;
  1361. DebugEntry(CAppRoster::ProcessSetOfUpdatesPDU);
  1362. if (record_update != NULL)
  1363. {
  1364. for (pCurr = record_update; NULL != pCurr; pCurr = pCurr->next)
  1365. {
  1366. node_id = pCurr->value.node_id;
  1367. entity_id = pCurr->value.entity_id;
  1368. switch(pCurr->value.application_update.choice)
  1369. {
  1370. case APPLICATION_ADD_RECORD_CHOSEN:
  1371. pdu_record = &(pCurr->value.application_update.u.application_add_record);
  1372. update_type = APP_ADD_RECORD;
  1373. break;
  1374. case APPLICATION_REPLACE_RECORD_CHOSEN:
  1375. DeleteRecord (node_id, entity_id, FALSE);
  1376. pdu_record = &(pCurr->value.application_update.u.application_replace_record);
  1377. update_type = APP_REPLACE_RECORD;
  1378. break;
  1379. default: // Remove record
  1380. /*
  1381. ** Inform the owner that a record was delete while processing
  1382. ** this PDU so that it can perform any necessary cleanup.
  1383. */
  1384. m_pAppRosterMgr->DeleteRosterRecord(node_id, entity_id);
  1385. DeleteRecord (node_id, entity_id, TRUE);
  1386. pdu_record = NULL;
  1387. update_type = APP_DELETE_RECORD;
  1388. break;
  1389. }
  1390. /*
  1391. ** First get the roster record and if one does not exist for this
  1392. ** app record create it. After that we will create the application
  1393. ** record and put it into the correct slot in the application
  1394. ** roster record.
  1395. */
  1396. if (pdu_record != NULL)
  1397. {
  1398. /*
  1399. ** First find the correct node record and if it does not
  1400. ** exist create it.
  1401. */
  1402. if (NULL == (node_record = m_NodeRecordList2.Find(sender_id)))
  1403. {
  1404. DBG_SAVE_FILE_LINE
  1405. node_record = new APP_NODE_RECORD;
  1406. if (NULL == node_record)
  1407. {
  1408. goto MyExit;
  1409. }
  1410. m_NodeRecordList2.Append(sender_id, node_record);
  1411. }
  1412. /*
  1413. ** If the user and sender id is the same then the record
  1414. ** will be contained in the app_record_list. Otherwise, it
  1415. ** will be maintained in the sub-node list.
  1416. */
  1417. /*
  1418. ** If the sender_id equals the node id being processed
  1419. ** use the application record list instead of the sub
  1420. ** node list.
  1421. */
  1422. if (sender_id != node_id)
  1423. {
  1424. /*
  1425. ** Find the correct node list and create it if it does
  1426. ** not exists. This list holds lists of all the
  1427. ** application peer entities at a node.
  1428. */
  1429. if (NULL == (record_list = node_record->SubNodeList2.Find(node_id)))
  1430. {
  1431. DBG_SAVE_FILE_LINE
  1432. record_list = new CAppRecordList2(DESIRED_MAX_APP_RECORDS);
  1433. if (NULL == record_list)
  1434. {
  1435. goto MyExit;
  1436. }
  1437. node_record->SubNodeList2.Append(node_id, record_list);
  1438. }
  1439. }
  1440. else
  1441. {
  1442. record_list = &node_record->AppRecordList;
  1443. }
  1444. // Now fill in the application record
  1445. DBG_SAVE_FILE_LINE
  1446. application_record = new APP_RECORD;
  1447. if (NULL == application_record)
  1448. {
  1449. goto MyExit;
  1450. }
  1451. record_list->Append(entity_id, application_record);
  1452. rc = ProcessApplicationRecordPDU(application_record, pdu_record);
  1453. if (GCC_NO_ERROR != rc)
  1454. {
  1455. goto MyExit;
  1456. }
  1457. } // if
  1458. /*
  1459. ** Here we add this update to our PDU and jump to the next update
  1460. ** in the PDU currently being processed.
  1461. */
  1462. rc = BuildApplicationRecordListPDU ( update_type,
  1463. node_id,
  1464. entity_id);
  1465. if (rc != GCC_NO_ERROR)
  1466. {
  1467. goto MyExit;
  1468. }
  1469. /*
  1470. ** If the capabilities changed during the above processing
  1471. ** we must create a new collapsed capabilities list and
  1472. ** build a new capability refresh PDU.
  1473. */
  1474. if (m_fCapabilitiesHaveChanged)
  1475. {
  1476. MakeCollapsedCapabilitiesList();
  1477. rc = BuildSetOfCapabilityRefreshesPDU ();
  1478. if (rc != GCC_NO_ERROR)
  1479. {
  1480. goto MyExit;
  1481. }
  1482. }
  1483. } // for
  1484. } // if
  1485. rc = GCC_NO_ERROR;
  1486. MyExit:
  1487. return rc;
  1488. }
  1489. /*
  1490. * GCCError ProcessApplicationRecordPDU ()
  1491. *
  1492. * Private Function Description
  1493. * This routine is responsible for decoding the Application Record
  1494. * portion of the roster update pdu.
  1495. *
  1496. * Formal Parameters
  1497. * application_record - This is the internal destination app record.
  1498. * pdu_record - Source PDU data
  1499. *
  1500. * Return Value
  1501. * GCC_NO_ERROR - On Success
  1502. * GCC_ALLOCATION_FAILURE - On resource failure
  1503. *
  1504. * Side Effects
  1505. * none
  1506. *
  1507. * Caveats
  1508. * none
  1509. */
  1510. GCCError CAppRoster::ProcessApplicationRecordPDU (
  1511. APP_RECORD *application_record,
  1512. PApplicationRecord pdu_record)
  1513. {
  1514. GCCError rc = GCC_NO_ERROR;
  1515. DebugEntry(CAppRoster::ProcessApplicationRecordPDU);
  1516. application_record->is_enrolled_actively = pdu_record->application_is_active;
  1517. application_record->is_conducting_capable = pdu_record->is_conducting_capable;
  1518. if (pdu_record->bit_mask & RECORD_STARTUP_CHANNEL_PRESENT)
  1519. {
  1520. application_record->startup_channel_type =
  1521. (MCSChannelType)pdu_record->record_startup_channel;
  1522. }
  1523. else
  1524. application_record->startup_channel_type= MCS_NO_CHANNEL_TYPE_SPECIFIED;
  1525. if (pdu_record->bit_mask & APPLICATION_USER_ID_PRESENT)
  1526. {
  1527. application_record->application_user_id =
  1528. pdu_record->application_user_id;
  1529. }
  1530. else
  1531. application_record->application_user_id = 0;
  1532. if (pdu_record->bit_mask & NON_COLLAPSING_CAPABILITIES_PRESENT)
  1533. {
  1534. rc = ProcessNonCollapsingCapabilitiesPDU (
  1535. &application_record->non_collapsed_caps_list,
  1536. pdu_record->non_collapsing_capabilities);
  1537. }
  1538. return rc;
  1539. }
  1540. /*
  1541. * GCCError ProcessSetOfCapabilityRefreshesPDU ()
  1542. *
  1543. * Private Function Description
  1544. * This routine is responsible for decoding the capabilities portion
  1545. * of an roster update PDU.
  1546. *
  1547. * Formal Parameters
  1548. * capability_refresh - (i) set of capabilities PDU to be processed
  1549. * sender_id - (i) gcc user id of node that sent the update
  1550. *
  1551. * Return Value
  1552. * GCC_NO_ERROR - On Success
  1553. * GCC_ALLOCATION_FAILURE - On resource failure
  1554. *
  1555. * Side Effects
  1556. * none
  1557. *
  1558. * Caveats
  1559. * This routine does handle NULL for the capability refresh which means
  1560. * that the capabilities delivered no longer exists.
  1561. */
  1562. GCCError CAppRoster::ProcessSetOfCapabilityRefreshesPDU(
  1563. PSetOfApplicationCapabilityRefreshes capability_refresh,
  1564. UserID sender_id)
  1565. {
  1566. GCCError rc = GCC_NO_ERROR;
  1567. PSetOfApplicationCapabilityRefreshes pCurr;
  1568. CAppCapItemList *pAppCapList;
  1569. APP_CAP_ITEM *pAppCapItem;
  1570. APP_NODE_RECORD *node_record;
  1571. DebugEntry(CAppRoster::ProcessSetOfCapabilityRefreshesPDU);
  1572. if (NULL == (node_record = m_NodeRecordList2.Find(sender_id)))
  1573. {
  1574. DBG_SAVE_FILE_LINE
  1575. node_record = new APP_NODE_RECORD;
  1576. if (NULL == node_record)
  1577. {
  1578. return GCC_ALLOCATION_FAILURE;
  1579. }
  1580. m_NodeRecordList2.Append(sender_id, node_record);
  1581. }
  1582. // get collapsed cap list ptr
  1583. pAppCapList = &node_record->CollapsedCapList;
  1584. // Clear out all the old capabilities from this list.
  1585. pAppCapList->DeleteList();
  1586. // Begin processing the PDU.
  1587. for (pCurr = capability_refresh; NULL != pCurr; pCurr = pCurr->next)
  1588. {
  1589. ASSERT(GCC_NO_ERROR == rc);
  1590. // Create and fill in the new capability.
  1591. DBG_SAVE_FILE_LINE
  1592. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType) pCurr->value.capability_class.choice);
  1593. if (NULL == pAppCapItem)
  1594. {
  1595. return GCC_ALLOCATION_FAILURE;
  1596. }
  1597. // Create the capability ID
  1598. DBG_SAVE_FILE_LINE
  1599. pAppCapItem->pCapID = new CCapIDContainer(&pCurr->value.capability_id, &rc);
  1600. if (NULL == pAppCapItem->pCapID)
  1601. {
  1602. rc = GCC_ALLOCATION_FAILURE;
  1603. }
  1604. if (GCC_NO_ERROR != rc)
  1605. {
  1606. delete pAppCapItem;
  1607. return rc;
  1608. }
  1609. // append this cap to the collapsed cap list
  1610. pAppCapList->Append(pAppCapItem);
  1611. /*
  1612. ** Note that a logical type's value is maintained as
  1613. ** number of entities.
  1614. */
  1615. if (pCurr->value.capability_class.choice == UNSIGNED_MINIMUM_CHOSEN)
  1616. {
  1617. pAppCapItem->nUnsignedMinimum = pCurr->value.capability_class.u.unsigned_minimum;
  1618. }
  1619. else
  1620. if (pCurr->value.capability_class.choice == UNSIGNED_MAXIMUM_CHOSEN)
  1621. {
  1622. pAppCapItem->nUnsignedMaximum = pCurr->value.capability_class.u.unsigned_maximum;
  1623. }
  1624. pAppCapItem->cEntries = pCurr->value.number_of_entities;
  1625. } // for
  1626. // This forces a new capabilities list to be calculated.
  1627. MakeCollapsedCapabilitiesList();
  1628. /*
  1629. ** Here we build the new PDU data associated with this refresh of the
  1630. ** capability list.
  1631. */
  1632. return BuildSetOfCapabilityRefreshesPDU();
  1633. }
  1634. /*
  1635. * GCCError ProcessNonCollapsingCapabilitiesPDU ()
  1636. *
  1637. * Private Function Description
  1638. * This routine is responsible for decoding the non-collapsing capabilities
  1639. * portion of a roster record PDU.
  1640. *
  1641. * Formal Parameters
  1642. * non_collapsed_caps_list - (o) Pointer to list to fill in with new
  1643. * non-collapsed caps.
  1644. * pSetOfCaps - (i) non-collapsed PDU data
  1645. *
  1646. * Return Value
  1647. * GCC_NO_ERROR - On Success
  1648. * GCC_ALLOCATION_FAILURE - On resource failure
  1649. *
  1650. * Side Effects
  1651. * none
  1652. *
  1653. * Caveats
  1654. * none
  1655. */
  1656. GCCError CAppRoster::ProcessNonCollapsingCapabilitiesPDU (
  1657. CAppCapItemList *non_collapsed_caps_list,
  1658. PSetOfNonCollapsingCapabilities pSetOfCaps)
  1659. {
  1660. GCCError rc = GCC_NO_ERROR;
  1661. PSetOfNonCollapsingCapabilities pCurr;
  1662. APP_CAP_ITEM *pAppCapItem;
  1663. DebugEntry(CAppRoster::ProcessNonCollapsingCapsPDU);
  1664. for (pCurr = pSetOfCaps; NULL != pCurr; pCurr = pCurr->next)
  1665. {
  1666. //
  1667. // LONCHANC: The following cap data does not have a type???
  1668. // for now, set it to zero.
  1669. //
  1670. DBG_SAVE_FILE_LINE
  1671. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType)0);
  1672. if (NULL == pAppCapItem)
  1673. {
  1674. rc = GCC_ALLOCATION_FAILURE;
  1675. goto MyExit;
  1676. }
  1677. DBG_SAVE_FILE_LINE
  1678. pAppCapItem->pCapID = new CCapIDContainer(&pCurr->value.capability_id, &rc);
  1679. if (NULL == pAppCapItem->pCapID)
  1680. {
  1681. rc = GCC_ALLOCATION_FAILURE;
  1682. }
  1683. if (rc != GCC_NO_ERROR)
  1684. {
  1685. goto MyExit;
  1686. }
  1687. if (pCurr->value.bit_mask & APPLICATION_DATA_PRESENT)
  1688. {
  1689. if (NULL == (pAppCapItem->poszAppData = ::My_strdupO2(
  1690. pCurr->value.application_data.value,
  1691. pCurr->value.application_data.length)))
  1692. {
  1693. rc = GCC_ALLOCATION_FAILURE;
  1694. goto MyExit;
  1695. }
  1696. }
  1697. non_collapsed_caps_list->Append(pAppCapItem);
  1698. } // for
  1699. ASSERT(GCC_NO_ERROR == rc);
  1700. MyExit:
  1701. if (GCC_NO_ERROR != rc)
  1702. {
  1703. delete pAppCapItem;
  1704. }
  1705. return rc;
  1706. }
  1707. /*
  1708. * Utilities that operate on conference records.
  1709. */
  1710. /*
  1711. * UINT LockApplicationRoster ()
  1712. *
  1713. * Public Function Description
  1714. * This routine is used to lock a GCCApplicationRoster and to determine the
  1715. * amount of memory necessary to hold the data referenced by the "API"
  1716. * application roster structure. The GCCApplicationRoster is used in
  1717. * indications to applications at the local node.
  1718. */
  1719. UINT CAppRoster::LockApplicationRoster(void)
  1720. {
  1721. UINT number_of_records = 0;
  1722. UINT number_of_capabilities = 0;
  1723. APP_NODE_RECORD *lpAppNodeRecord;
  1724. APP_RECORD *lpAppRecData;
  1725. APP_CAP_ITEM *lpAppCapData;
  1726. CAppRecordList2 *lpAppRecDataList;
  1727. DebugEntry(CAppRoster::LockApplicationRoster);
  1728. /*
  1729. * If this is the first time this routine is called, determine the size of
  1730. * the memory required to hold the data referenced by the application
  1731. * roster structure. Otherwise, just increment the lock count.
  1732. */
  1733. if (Lock() == 1)
  1734. {
  1735. /*
  1736. * Lock the data for the session key held within the roster. This lock
  1737. * call returns the size of the memory required to hold the session key
  1738. * data, rounded to an even multiple of four-bytes.
  1739. */
  1740. m_cbDataMemory = m_pSessionKey->LockSessionKeyData();
  1741. /*
  1742. * First calculate the total number of records. This count is used to
  1743. * determine the space necessary to hold the records. Note that we must
  1744. * count both the application record list and the sub-node list.
  1745. */
  1746. m_NodeRecordList2.Reset();
  1747. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate()))
  1748. {
  1749. /*
  1750. * Add the application records at this node to the count.
  1751. */
  1752. number_of_records += lpAppNodeRecord->AppRecordList.GetCount();
  1753. /*
  1754. * Next count the sub node records.
  1755. */
  1756. if (! lpAppNodeRecord->SubNodeList2.IsEmpty())
  1757. {
  1758. lpAppNodeRecord->SubNodeList2.Reset();
  1759. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate()))
  1760. {
  1761. number_of_records += lpAppRecDataList->GetCount();
  1762. }
  1763. }
  1764. }
  1765. /*
  1766. * Now determine the amount of memory necessary to hold all of the
  1767. * pointers to the application records as well as the actual
  1768. * GCCApplicationRecord structures.
  1769. */
  1770. m_cbDataMemory += number_of_records *
  1771. (sizeof(PGCCApplicationRecord) +
  1772. ROUNDTOBOUNDARY( sizeof(GCCApplicationRecord)) );
  1773. m_NodeRecordList2.Reset();
  1774. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate()))
  1775. {
  1776. /*
  1777. * Iterate through this node's record list, determining the amount
  1778. * of memory necessary to hold the pointers to the non-collapsing
  1779. * capabilities as well as the capability ID data and octet string
  1780. * data associated with each non-collapsing capability.
  1781. */
  1782. lpAppNodeRecord->AppRecordList.Reset();
  1783. while (NULL != (lpAppRecData = lpAppNodeRecord->AppRecordList.Iterate()))
  1784. {
  1785. /*
  1786. * Set up an iterator for the list of non-collapsing
  1787. * capabilities held within each application roster.
  1788. */
  1789. lpAppRecData->non_collapsed_caps_list.Reset();
  1790. number_of_capabilities += lpAppRecData->non_collapsed_caps_list.GetCount();
  1791. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  1792. {
  1793. /*
  1794. * Lock the data for each capability ID. The lock call
  1795. * returns the length of the data referenced by each
  1796. * capability ID rounded to occupy an even multiple of
  1797. * four-bytes.
  1798. */
  1799. m_cbDataMemory += lpAppCapData->pCapID->LockCapabilityIdentifierData();
  1800. /*
  1801. * Add up the space required to hold the application data
  1802. * octet strings if they are present. Make sure there is
  1803. * enough space for each octet string to occupy an even
  1804. * multiple of four bytes. Add room to hold the actual
  1805. * octet string structure also since the capability
  1806. * structure only contains a pointer to a OSTR.
  1807. */
  1808. if (lpAppCapData->poszAppData != NULL)
  1809. {
  1810. m_cbDataMemory += ROUNDTOBOUNDARY(sizeof(OSTR));
  1811. m_cbDataMemory += ROUNDTOBOUNDARY(lpAppCapData->poszAppData->length);
  1812. }
  1813. }
  1814. }
  1815. /*
  1816. * Iterate through this node's sub-node record list, determining the
  1817. * amount of memory necessary to hold the pointers to the
  1818. * non-collapsing capabilities as well as the capability ID data and
  1819. * octet string data associated with each non-collapsing capability.
  1820. */
  1821. lpAppNodeRecord->SubNodeList2.Reset();
  1822. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate()))
  1823. {
  1824. lpAppRecDataList->Reset();
  1825. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  1826. {
  1827. /*
  1828. * Set up an iterator for the list of non-collapsing
  1829. * capabilities held within each application roster.
  1830. */
  1831. number_of_capabilities += lpAppRecData->non_collapsed_caps_list.GetCount();
  1832. lpAppRecData->non_collapsed_caps_list.Reset();
  1833. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  1834. {
  1835. /*
  1836. * Lock the data for each capability ID. The lock call
  1837. * returns the length of the data referenced by each
  1838. * capability ID fixed up to occupy an even multiple of
  1839. * four-bytes.
  1840. */
  1841. m_cbDataMemory += lpAppCapData->pCapID->LockCapabilityIdentifierData();
  1842. /*
  1843. * Add up the space required to hold the application
  1844. * data octet strings if they are present. Make sure
  1845. * there is enough space for each octet string to occupy
  1846. * an even multiple of four bytes. Add room to hold the
  1847. * actual octet string structure also since the
  1848. * capability structure only contains a pointer to a OSTR
  1849. */
  1850. if (lpAppCapData->poszAppData != NULL)
  1851. {
  1852. m_cbDataMemory += ROUNDTOBOUNDARY(sizeof(OSTR));
  1853. m_cbDataMemory += ROUNDTOBOUNDARY(lpAppCapData->poszAppData->length);
  1854. }
  1855. }
  1856. }
  1857. }
  1858. }
  1859. /*
  1860. * Determine the amount of memory necessary to hold all of the pointers
  1861. * to the non-collapsing capabilities as well as the actual
  1862. * GCCNonCollapsingCapability structures.
  1863. */
  1864. m_cbDataMemory += number_of_capabilities *
  1865. (sizeof (PGCCNonCollapsingCapability) +
  1866. ROUNDTOBOUNDARY( sizeof(GCCNonCollapsingCapability)) );
  1867. /*
  1868. * Add the amount of memory necessary to hold the string data associated
  1869. * with each capability ID.
  1870. */
  1871. m_CollapsedCapListForAllNodes.Reset();
  1872. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  1873. {
  1874. m_cbDataMemory += lpAppCapData->pCapID->LockCapabilityIdentifierData();
  1875. }
  1876. /*
  1877. * Add the memory to hold the application capability pointers
  1878. * and structures.
  1879. */
  1880. number_of_capabilities = m_CollapsedCapListForAllNodes.GetCount();
  1881. m_cbDataMemory += number_of_capabilities *
  1882. (sizeof (PGCCApplicationCapability) +
  1883. ROUNDTOBOUNDARY( sizeof(GCCApplicationCapability)) );
  1884. }
  1885. return m_cbDataMemory;
  1886. }
  1887. /*
  1888. * UINT GetAppRoster()
  1889. *
  1890. * Public Function Description
  1891. * This routine is used to obtain a pointer to the GCCApplicatonRoster.
  1892. * This routine should not be called before LockApplicationRoster is
  1893. * called. LockApplicationRoster will create the GCCApplicationRoster in
  1894. * the memory provided. The GCCApplicationRoster is what is delivered to
  1895. * the end user Application SAP.
  1896. */
  1897. UINT CAppRoster::GetAppRoster(
  1898. PGCCApplicationRoster pGccAppRoster,
  1899. LPBYTE pData)
  1900. {
  1901. UINT rc;
  1902. DebugEntry(CAppRoster::GetAppRoster);
  1903. if (GetLockCount() > 0)
  1904. {
  1905. UINT data_length;
  1906. /*
  1907. * Fill in the output length parameter which indicates how much data
  1908. * referenced outside the structure will be written.
  1909. */
  1910. rc = m_cbDataMemory;
  1911. /*
  1912. * Get the data associated with the roster's session key and save
  1913. * the length of the data written into memory.
  1914. */
  1915. data_length = m_pSessionKey->GetGCCSessionKeyData(&pGccAppRoster->session_key, pData);
  1916. /*
  1917. * Move the memory pointer past the data associated with the
  1918. * session key.
  1919. */
  1920. pData += data_length;
  1921. /*
  1922. * Fill in other roster structure elements.
  1923. */
  1924. pGccAppRoster->application_roster_was_changed = m_fRosterHasChanged;
  1925. pGccAppRoster->instance_number = (USHORT) m_nInstance;
  1926. pGccAppRoster->nodes_were_added = m_fPeerEntitiesAdded;
  1927. pGccAppRoster->nodes_were_removed = m_fPeerEntitiesRemoved;
  1928. pGccAppRoster->capabilities_were_changed = m_fCapabilitiesHaveChanged;
  1929. /*
  1930. * Fill in the full set of application roster records.
  1931. */
  1932. data_length = GetApplicationRecords(pGccAppRoster, pData);
  1933. /*
  1934. * Move the memory pointer past the application records and their
  1935. * associated data. Get the full set of application capabilities.
  1936. */
  1937. pData += data_length;
  1938. data_length = GetCapabilitiesList(pGccAppRoster, pData);
  1939. }
  1940. else
  1941. {
  1942. ERROR_OUT(("CAppRoster::GetAppRoster: Error data not locked"));
  1943. rc = 0;
  1944. }
  1945. return rc;
  1946. }
  1947. /*
  1948. * void UnLockApplicationRoster ()
  1949. *
  1950. * Public Function Description
  1951. * This member function is responsible for unlocking the data locked for
  1952. * the "API" application roster after the lock count goes to zero.
  1953. */
  1954. void CAppRoster::UnLockApplicationRoster()
  1955. {
  1956. DebugEntry(CAppRoster::UnLockApplicationRoster);
  1957. if (Unlock(FALSE) == 0)
  1958. {
  1959. // reset the size
  1960. m_cbDataMemory = 0;
  1961. // free up all the memory locked for "API" data.
  1962. APP_NODE_RECORD *lpAppNodeRecord;
  1963. APP_RECORD *lpAppRecData;
  1964. APP_CAP_ITEM *lpAppCapData;
  1965. CAppRecordList2 *lpAppRecDataList;
  1966. // unlock session key data
  1967. m_pSessionKey->UnLockSessionKeyData();
  1968. // iterate through all the node records
  1969. m_NodeRecordList2.Reset();
  1970. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate()))
  1971. {
  1972. // iterate through this node's record list
  1973. lpAppNodeRecord->AppRecordList.Reset();
  1974. while (NULL != (lpAppRecData = lpAppNodeRecord->AppRecordList.Iterate()))
  1975. {
  1976. // set up an iterator for the list of non-collapsing
  1977. // capabilities held within each application roster.
  1978. lpAppRecData->non_collapsed_caps_list.Reset();
  1979. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  1980. {
  1981. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  1982. }
  1983. }
  1984. // iterate through this node's sub-node record list
  1985. lpAppNodeRecord->SubNodeList2.Reset();
  1986. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate()))
  1987. {
  1988. lpAppRecDataList->Reset();
  1989. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  1990. {
  1991. // set up an iterator for the list of non-collapsing
  1992. // capabilities held within each application roster.
  1993. lpAppRecData->non_collapsed_caps_list.Reset();
  1994. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  1995. {
  1996. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  1997. }
  1998. }
  1999. }
  2000. }
  2001. // iterate through collapsed caps
  2002. m_CollapsedCapListForAllNodes.Reset();
  2003. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  2004. {
  2005. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2006. }
  2007. }
  2008. // we have to call Release() because we used Unlock(FALSE)
  2009. Release();
  2010. }
  2011. /*
  2012. * UINT GetApplicationRecords ()
  2013. *
  2014. * Private Function Description
  2015. * This routine inserts the complete set of application roster records
  2016. * into the passed in application roster structure.
  2017. *
  2018. * Formal Parameters
  2019. * gcc_roster - (o) GCCApplicationRoster to be filled in.
  2020. * memory - (o) Location in memory to begin writing records.
  2021. *
  2022. * Return Value
  2023. * The total amount of data written into memory.
  2024. *
  2025. * Side Effects
  2026. * The memory pointer passed in will be advanced by the amount of memory
  2027. * necessary to hold the application records and their data.
  2028. *
  2029. * Caveats
  2030. * none
  2031. */
  2032. UINT CAppRoster::GetApplicationRecords(
  2033. PGCCApplicationRoster gcc_roster,
  2034. LPBYTE memory)
  2035. {
  2036. UINT data_length = 0;
  2037. UINT record_count = 0;
  2038. PGCCApplicationRecord gcc_record;
  2039. UINT capability_data_length;
  2040. APP_NODE_RECORD *lpAppNodeRec;
  2041. CAppRecordList2 *lpAppRecDataList;
  2042. APP_RECORD *lpAppRecData;
  2043. UserID uid, uid2;
  2044. EntityID eid;
  2045. DebugEntry(CAppRoster::GetApplicationRecords);
  2046. /*
  2047. * Initialize the number of records in the roster to zero.
  2048. */
  2049. gcc_roster->number_of_records = 0;
  2050. /*
  2051. * First calculate the total number of records. This count is used to
  2052. * allocate the space necessary to hold the record pointers. Note that we
  2053. * must count both the application record list and the sub-node list.
  2054. */
  2055. m_NodeRecordList2.Reset();
  2056. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  2057. {
  2058. /*
  2059. * Add the number of application records at this node to the count.
  2060. */
  2061. gcc_roster->number_of_records += (USHORT) (lpAppNodeRec->AppRecordList.GetCount());
  2062. /*
  2063. * Next add the number of sub node entries.
  2064. */
  2065. if (! lpAppNodeRec->SubNodeList2.IsEmpty())
  2066. {
  2067. lpAppNodeRec->SubNodeList2.Reset();
  2068. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  2069. {
  2070. gcc_roster->number_of_records += (USHORT) (lpAppRecDataList->GetCount());
  2071. }
  2072. }
  2073. }
  2074. if (gcc_roster->number_of_records != 0)
  2075. {
  2076. /*
  2077. * Fill in the roster's pointer to the list of application record
  2078. * pointers. The pointer list will begin at the memory location passed
  2079. * into this routine.
  2080. */
  2081. gcc_roster->application_record_list = (PGCCApplicationRecord *)memory;
  2082. /*
  2083. * Move the memory pointer past the list of record pointers. This is
  2084. * where the first application record will be written.
  2085. */
  2086. memory += gcc_roster->number_of_records * sizeof(PGCCApplicationRecord);
  2087. /*
  2088. * Add to the data length the amount of memory necessary to hold the
  2089. * application record pointers. Go ahead and add the amount of memory
  2090. * necessary to hold all of the GCCApplicationRecord structures.
  2091. */
  2092. data_length += gcc_roster->number_of_records *
  2093. (sizeof(PGCCApplicationRecord) +
  2094. ROUNDTOBOUNDARY(sizeof(GCCApplicationRecord)));
  2095. record_count = 0;
  2096. m_NodeRecordList2.Reset();
  2097. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate(&uid)))
  2098. {
  2099. /*
  2100. * Iterate through this node's record list, building an "API"
  2101. * application record for each record in the list.
  2102. */
  2103. lpAppNodeRec->AppRecordList.Reset();
  2104. while (NULL != (lpAppRecData = lpAppNodeRec->AppRecordList.Iterate(&eid)))
  2105. {
  2106. /*
  2107. * Set the application record pointer equal to the location in
  2108. * memory where it will be written.
  2109. */
  2110. gcc_record = (PGCCApplicationRecord)memory;
  2111. /*
  2112. * Save the pointer to the application record in the roster's
  2113. * list of record pointers.
  2114. */
  2115. gcc_roster->application_record_list[record_count] = gcc_record;
  2116. /*
  2117. * Get the GCC node ID from the node iterator.
  2118. */
  2119. gcc_record->node_id = uid;
  2120. /*
  2121. * Get the Entity ID from the record iterator.
  2122. */
  2123. gcc_record->entity_id = eid;
  2124. /*
  2125. * Fill in other application record elements.
  2126. */
  2127. gcc_record->is_enrolled_actively = lpAppRecData->is_enrolled_actively;
  2128. gcc_record->is_conducting_capable = lpAppRecData->is_conducting_capable;
  2129. gcc_record->startup_channel_type = lpAppRecData->startup_channel_type;
  2130. gcc_record->application_user_id = lpAppRecData->application_user_id;
  2131. /*
  2132. * Advance the memory pointer past the application record
  2133. * structure. This is where the list of non-collapsing
  2134. * capabilities pointers will begin. Round the memory location
  2135. * off to fall on an even four-byte boundary.
  2136. */
  2137. memory += ROUNDTOBOUNDARY(sizeof(GCCApplicationRecord));
  2138. /*
  2139. * Fill in the non-collapsing capabilities for this application
  2140. * record.
  2141. */
  2142. capability_data_length = GetNonCollapsedCapabilitiesList(
  2143. gcc_record,
  2144. &lpAppRecData->non_collapsed_caps_list,
  2145. memory);
  2146. /*
  2147. * Add the amount of memory necessary to hold the list of
  2148. * capabilities and associated data to the overall length and
  2149. * move the memory pointer past the capabilities data.
  2150. */
  2151. memory += capability_data_length;
  2152. data_length += capability_data_length;
  2153. /*
  2154. * Increment the record list array counter.
  2155. */
  2156. record_count++;
  2157. }
  2158. /*
  2159. * Iterate through this node's sub-node record list, building an
  2160. * "API" application record for each record in the list.
  2161. */
  2162. lpAppNodeRec->SubNodeList2.Reset();
  2163. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate(&uid2)))
  2164. {
  2165. /*
  2166. * Iterate through this node's record list.
  2167. */
  2168. lpAppRecDataList->Reset();
  2169. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate(&eid)))
  2170. {
  2171. /*
  2172. * Set the application record pointer equal to the location
  2173. * in memory where it will be written.
  2174. */
  2175. gcc_record = (PGCCApplicationRecord)memory;
  2176. /*
  2177. * Save the pointer to the application record in the
  2178. * roster's list of record pointers.
  2179. */
  2180. gcc_roster->application_record_list[record_count] = gcc_record;
  2181. /*
  2182. * Get the node ID from the sub_node_iterator.
  2183. */
  2184. gcc_record->node_id = uid2;
  2185. /*
  2186. * Get the entity ID from the record_iterator.
  2187. */
  2188. gcc_record->entity_id = eid;
  2189. /*
  2190. * Fill in other application record elements.
  2191. */
  2192. gcc_record->is_enrolled_actively = lpAppRecData->is_enrolled_actively;
  2193. gcc_record->is_conducting_capable = lpAppRecData->is_conducting_capable;
  2194. gcc_record->startup_channel_type = lpAppRecData->startup_channel_type;
  2195. gcc_record->application_user_id = lpAppRecData->application_user_id;
  2196. /*
  2197. * Advance the memory pointer past the application record
  2198. * structure. This is where the list of non-collapsing
  2199. * capabilities pointers will begin. Round the memory
  2200. * location off to fall on an even four-byte boundary.
  2201. */
  2202. memory += ROUNDTOBOUNDARY(sizeof(GCCApplicationRecord));
  2203. /*
  2204. * Fill in the non-collapsing capabilities for this
  2205. * application record. The memory pointer will be advanced
  2206. * past the capabilities list and data.
  2207. */
  2208. capability_data_length = GetNonCollapsedCapabilitiesList(
  2209. gcc_record,
  2210. &lpAppRecData->non_collapsed_caps_list,
  2211. memory);
  2212. /*
  2213. * Add the amount of memory necessary to hold the list of
  2214. * capabilities and associated data to the overall length.
  2215. */
  2216. memory += capability_data_length;
  2217. data_length += capability_data_length;
  2218. /*
  2219. * Increment the record list array counter.
  2220. */
  2221. record_count++;
  2222. }
  2223. }
  2224. }
  2225. }
  2226. else
  2227. {
  2228. /*
  2229. * There were no application records so set the pointer to the list
  2230. * of records to NULL and the data_length return value to zero.
  2231. */
  2232. gcc_roster->application_record_list = NULL;
  2233. data_length = 0;
  2234. }
  2235. return (data_length);
  2236. }
  2237. /*
  2238. * UINT GetCapabilitiesList ()
  2239. *
  2240. * Private Function Description
  2241. * This routine fills in the capabilities portion of the
  2242. * GCCAppicationRoster structure.
  2243. *
  2244. * Formal Parameters
  2245. * gcc_roster - (o) GCCApplicationRoster to be filled in
  2246. * memory - (o) Location in memory to begin writing records.
  2247. *
  2248. * Return Value
  2249. * The total amount of data written into memory.
  2250. *
  2251. * Side Effects
  2252. * none
  2253. *
  2254. * Caveats
  2255. * none
  2256. */
  2257. UINT CAppRoster::GetCapabilitiesList(
  2258. PGCCApplicationRoster gcc_roster,
  2259. LPBYTE memory)
  2260. {
  2261. UINT data_length = 0;
  2262. UINT capability_id_data_length = 0;
  2263. UINT capability_count;
  2264. PGCCApplicationCapability gcc_capability;
  2265. APP_CAP_ITEM *lpAppCapData;
  2266. DebugEntry(CAppRoster::GetCapabilitiesList);
  2267. /*
  2268. * Retrieve the number of capabilities for this roster and fill in any that
  2269. * are present.
  2270. */
  2271. gcc_roster->number_of_capabilities = (USHORT) m_CollapsedCapListForAllNodes.GetCount();
  2272. if (gcc_roster->number_of_capabilities != 0)
  2273. {
  2274. /*
  2275. * Fill in the roster's pointer to the list of application capability
  2276. * pointers. The pointer list will begin at the memory location passed
  2277. * into this routine.
  2278. */
  2279. gcc_roster->capabilities_list = (PGCCApplicationCapability *)memory;
  2280. /*
  2281. * Move the memory pointer past the list of capability pointers. This
  2282. * is where the first application capability structure will be written.
  2283. */
  2284. memory += (Int)(gcc_roster->number_of_capabilities *
  2285. sizeof(PGCCApplicationCapability));
  2286. /*
  2287. * Add to the data length the amount of memory necessary to hold the
  2288. * application capability pointers. Go ahead and add the amount of
  2289. * memory necessary to hold all of the GCCApplicationCapability
  2290. * structures.
  2291. */
  2292. data_length += gcc_roster->number_of_capabilities *
  2293. (sizeof(PGCCApplicationCapability) +
  2294. ROUNDTOBOUNDARY ( sizeof(GCCApplicationCapability)) );
  2295. capability_count = 0;
  2296. m_CollapsedCapListForAllNodes.Reset();
  2297. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  2298. {
  2299. /*
  2300. * Set the application capability pointer equal to the
  2301. * location in memory where it will be written.
  2302. */
  2303. gcc_capability = (PGCCApplicationCapability)memory;
  2304. /*
  2305. * Save the pointer to the application capability in the roster's
  2306. * list of application capability pointers.
  2307. */
  2308. gcc_roster->capabilities_list[capability_count] =
  2309. gcc_capability;
  2310. /*
  2311. * Advance the memory pointer past the application capability
  2312. * structure. This is where the string data for the capability ID
  2313. * will be written. Ensure that the memory pointer falls on an
  2314. * even four-byte boundary.
  2315. */
  2316. memory += (Int)(ROUNDTOBOUNDARY(sizeof(GCCApplicationCapability)));
  2317. /*
  2318. * Retrieve the capability ID information from the internal
  2319. * CapabilityIDData object. The length returned by this call will
  2320. * have already been rounded to an even multiple of four bytes.
  2321. */
  2322. capability_id_data_length = lpAppCapData->pCapID->GetGCCCapabilityIDData(
  2323. &gcc_capability->capability_id,
  2324. memory);
  2325. /*
  2326. * Advance the memory pointer past the string data written into
  2327. * memory by the capability ID object. Add the length of the string
  2328. * data to the overall capability length.
  2329. */
  2330. memory += (Int)capability_id_data_length;
  2331. data_length += capability_id_data_length;
  2332. /*
  2333. * Now fill in the rest of the capability.
  2334. */
  2335. gcc_capability->capability_class.eType =lpAppCapData->eCapType;
  2336. if (gcc_capability->capability_class.eType ==
  2337. GCC_UNSIGNED_MINIMUM_CAPABILITY)
  2338. {
  2339. gcc_capability->capability_class.nMinOrMax = lpAppCapData->nUnsignedMinimum;
  2340. }
  2341. else if (gcc_capability->capability_class.eType == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  2342. {
  2343. gcc_capability->capability_class.nMinOrMax = lpAppCapData->nUnsignedMaximum;
  2344. }
  2345. gcc_capability->number_of_entities = lpAppCapData->cEntries;
  2346. /*
  2347. * Increment the capability ID array counter.
  2348. */
  2349. capability_count++;
  2350. }
  2351. }
  2352. else
  2353. {
  2354. gcc_roster->capabilities_list = NULL;
  2355. }
  2356. return (data_length);
  2357. }
  2358. /*
  2359. * UINT GetNonCollapsedCapabilitiesList ()
  2360. *
  2361. * Private Function Description:
  2362. * This routine is used to fill in the "API" non-collapsing capabilities
  2363. * portion of a GCCApplicationRoster from the data which is stored
  2364. * internally by this class.
  2365. *
  2366. * Formal Parameters
  2367. * gcc_record - (o) The application record to be filled in.
  2368. * pAppCapItemList (i) The internal capabilities data.
  2369. * memory (i/o) The memory location to begin writing data.
  2370. *
  2371. * Return Value
  2372. * The total amount of data written into memory.
  2373. *
  2374. * Side Effects
  2375. * The memory pointer passed in will be advanced by the amount of memory
  2376. * necessary to hold the capabilities and their data.
  2377. *
  2378. * Caveats
  2379. * none
  2380. */
  2381. UINT CAppRoster::GetNonCollapsedCapabilitiesList(
  2382. PGCCApplicationRecord gcc_record,
  2383. CAppCapItemList *pAppCapItemList,
  2384. LPBYTE memory)
  2385. {
  2386. UINT capability_count;
  2387. PGCCNonCollapsingCapability gcc_capability;
  2388. APP_CAP_ITEM *lpAppCapData;
  2389. UINT capability_id_length = 0;
  2390. UINT capability_data_length = 0;
  2391. DebugEntry(CAppRoster::GetNonCollapsedCapabilitiesList);
  2392. /*
  2393. * Get the number of non-collapsed capabilities.
  2394. */
  2395. gcc_record->number_of_non_collapsed_caps = (USHORT) pAppCapItemList->GetCount();
  2396. if (gcc_record->number_of_non_collapsed_caps != 0)
  2397. {
  2398. /*
  2399. * Fill in the record's pointer to the list of non-collapsing
  2400. * capabilities pointers. The pointer list will begin at the memory
  2401. * location passed into this routine.
  2402. */
  2403. gcc_record->non_collapsed_caps_list = (PGCCNonCollapsingCapability *)memory;
  2404. /*
  2405. * Move the memory pointer past the list of capability pointers. This
  2406. * is where the first capability structure will be written.
  2407. */
  2408. memory += (Int)(gcc_record->number_of_non_collapsed_caps *
  2409. sizeof(PGCCNonCollapsingCapability));
  2410. /*
  2411. * Add to the data length the amount of memory necessary to hold the
  2412. * capability pointers. Go ahead and add the amount of memory necessary
  2413. * to hold all of the GCCNonCollapsingCapability structures.
  2414. */
  2415. capability_data_length = gcc_record->number_of_non_collapsed_caps *
  2416. (sizeof(PGCCNonCollapsingCapability) +
  2417. ROUNDTOBOUNDARY(sizeof (GCCNonCollapsingCapability)));
  2418. /*
  2419. * Iterate through this record's capabilities list, building an "API"
  2420. * non-collapsing capability for each capability in the list.
  2421. */
  2422. capability_count = 0;
  2423. pAppCapItemList->Reset();
  2424. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  2425. {
  2426. /*
  2427. * Set the capability pointer equal to the location in memory where
  2428. * it will be written.
  2429. */
  2430. gcc_capability = (PGCCNonCollapsingCapability)memory;
  2431. /*
  2432. * Save the pointer to the capability in the record's list of
  2433. * capability pointers.
  2434. */
  2435. gcc_record->non_collapsed_caps_list[capability_count] = gcc_capability;
  2436. /*
  2437. * Move the memory pointer past the capability ID structure. This
  2438. * is where the data associated with the structure will be written.
  2439. * Retrieve the capability ID data from the internal object, saving
  2440. * it in the "API" capability ID structure.
  2441. */
  2442. memory += (Int)ROUNDTOBOUNDARY(sizeof(GCCNonCollapsingCapability));
  2443. capability_id_length = lpAppCapData->pCapID->GetGCCCapabilityIDData(
  2444. &gcc_capability->capability_id, memory);
  2445. /*
  2446. * Add to the data length the amount of memory necessary to hold the
  2447. * capability ID data.
  2448. */
  2449. capability_data_length += capability_id_length;
  2450. /*
  2451. * Move the memory pointer past the data filled in for the
  2452. * capability ID. This is where the application data OSTR
  2453. * contained in the non-collapsing capability will be written, if
  2454. * one exists. Note that the capability contains a pointer to a
  2455. * OSTR and therefore the OSTR structure as well
  2456. * as the string data must be written into memory.
  2457. */
  2458. memory += capability_id_length;
  2459. if (lpAppCapData->poszAppData != NULL)
  2460. {
  2461. /*
  2462. * Set the application data structure pointer equal to the
  2463. * location in memory where it will be written.
  2464. */
  2465. gcc_capability->application_data = (LPOSTR) memory;
  2466. gcc_capability->application_data->length = lpAppCapData->poszAppData->length;
  2467. /*
  2468. * Move the memory pointer past the OSTR structure
  2469. * and round it off to an even four-byte boundary. This is
  2470. * where the actual string data will be written so set the
  2471. * structure string pointer equal to that location.
  2472. */
  2473. memory += ROUNDTOBOUNDARY(sizeof(OSTR));
  2474. gcc_capability->application_data->value =(LPBYTE)memory;
  2475. /*
  2476. * Copy the actual application string data into memory.
  2477. */
  2478. ::CopyMemory(gcc_capability->application_data->value,
  2479. lpAppCapData->poszAppData->value,
  2480. lpAppCapData->poszAppData->length);
  2481. /*
  2482. * Add to the data length the amount of memory necessary to
  2483. * hold the application data structure and string. The lengths
  2484. * will need to be aligned on a four-byte boundary before
  2485. * adding them to the total length.
  2486. */
  2487. capability_data_length += ROUNDTOBOUNDARY(sizeof(OSTR));
  2488. capability_data_length += ROUNDTOBOUNDARY(gcc_capability->application_data->length);
  2489. /*
  2490. * Move the memory pointer past the application string data.
  2491. * The memory pointer is then fixed up to ensure that it falls
  2492. * on an even four-byte boundary.
  2493. */
  2494. memory += ROUNDTOBOUNDARY(lpAppCapData->poszAppData->length);
  2495. }
  2496. else
  2497. {
  2498. gcc_capability->application_data = NULL;
  2499. }
  2500. /*
  2501. * Increment the capability array counter.
  2502. */
  2503. capability_count++;
  2504. }
  2505. }
  2506. else
  2507. {
  2508. gcc_record->non_collapsed_caps_list = NULL;
  2509. capability_data_length = 0;
  2510. }
  2511. return (capability_data_length);
  2512. }
  2513. /*
  2514. * void FreeApplicationRosterData ()
  2515. *
  2516. * Private Function Description:
  2517. * This routine is used to free up any data which was locked for an "API"
  2518. * application roster.
  2519. *
  2520. * Formal Parameters
  2521. * none
  2522. *
  2523. * Return Value
  2524. * none
  2525. *
  2526. * Side Effects
  2527. * none
  2528. *
  2529. * Caveats
  2530. * none
  2531. */
  2532. void CAppRoster::FreeApplicationRosterData(void)
  2533. {
  2534. APP_NODE_RECORD *lpAppNodeRec;
  2535. APP_RECORD *lpAppRecData;
  2536. APP_CAP_ITEM *lpAppCapData;
  2537. CAppRecordList2 *lpAppRecDataList;
  2538. DebugEntry(CAppRoster::FreeApplicationRosterData);
  2539. m_pSessionKey->UnLockSessionKeyData();
  2540. /*
  2541. * Unlock the data associated with each non-collapsed capability by
  2542. * iterating through the list of application records at each node as well as
  2543. * the list of sub-node records at each node, calling "UnLock" for each
  2544. * CapabilityIDData associated with each cabability.
  2545. */
  2546. m_NodeRecordList2.Reset();
  2547. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  2548. {
  2549. lpAppNodeRec->AppRecordList.Reset();
  2550. while (NULL != (lpAppRecData = lpAppNodeRec->AppRecordList.Iterate()))
  2551. {
  2552. lpAppRecData->non_collapsed_caps_list.Reset();
  2553. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  2554. {
  2555. lpAppCapData->pCapID->UnLockCapabilityIdentifierData ();
  2556. }
  2557. }
  2558. lpAppNodeRec->SubNodeList2.Reset();
  2559. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  2560. {
  2561. lpAppRecDataList->Reset();
  2562. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  2563. {
  2564. lpAppRecData->non_collapsed_caps_list.Reset();
  2565. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  2566. {
  2567. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2568. }
  2569. }
  2570. }
  2571. }
  2572. /*
  2573. * Iterate through the list of collapsed capabilities, unlocking the data
  2574. * for each CapabilityIDData object associated with each capability.
  2575. */
  2576. m_CollapsedCapListForAllNodes.Reset();
  2577. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  2578. {
  2579. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2580. }
  2581. }
  2582. /*
  2583. * GCCError AddRecord ()
  2584. *
  2585. * Public Function Description
  2586. * This member function is responsible for inserting a new application
  2587. * record into the Roster. This routine will return a failure if the
  2588. * application record already exist.
  2589. *
  2590. * Caveats
  2591. * Note that it is possible for a roster record (not application record)
  2592. * to already exist at this node if this is the second application
  2593. * entity to enroll at this node.
  2594. */
  2595. GCCError CAppRoster::
  2596. AddRecord(GCCEnrollRequest *pReq, GCCNodeID nid, GCCEntityID eid)
  2597. {
  2598. GCCError rc = GCC_NO_ERROR;
  2599. APP_NODE_RECORD *node_record;
  2600. APP_RECORD *pAppRecord;
  2601. CAppCapItemList *pAppCapItemList;
  2602. DebugEntry(CAppRoster::AddRecord);
  2603. if (m_fPduIsFlushed)
  2604. {
  2605. FreeRosterUpdateIndicationPDU ();
  2606. m_fPduIsFlushed = FALSE;
  2607. }
  2608. /*
  2609. * First create a roster entry for this user ID if one does not exists.
  2610. */
  2611. if (NULL == (node_record = m_NodeRecordList2.Find(nid)))
  2612. {
  2613. DBG_SAVE_FILE_LINE
  2614. node_record = new APP_NODE_RECORD;
  2615. if (node_record != NULL)
  2616. {
  2617. m_NodeRecordList2.Append(nid, node_record);
  2618. }
  2619. else
  2620. {
  2621. ERROR_OUT(("CAppRoster: AddRecord: Resource Error Occured"));
  2622. rc = GCC_ALLOCATION_FAILURE;
  2623. goto MyExit;
  2624. }
  2625. }
  2626. else
  2627. {
  2628. WARNING_OUT(("CAppRoster: AddRecord: Node Record is found"));
  2629. }
  2630. /*
  2631. * Check to make sure that the application record does not already exist..
  2632. */
  2633. if ((NULL != node_record->AppRecordList.Find(eid)) ||
  2634. (NULL != node_record->ListOfAppCapItemList2.Find(eid)))
  2635. {
  2636. WARNING_OUT(("AppRoster: AddRecord: Record already exists"));
  2637. rc = GCC_INVALID_PARAMETER;
  2638. goto MyExit;
  2639. }
  2640. // Next create a record entry in the roster's app_record_list.
  2641. DBG_SAVE_FILE_LINE
  2642. pAppRecord = new APP_RECORD;
  2643. if (NULL == pAppRecord)
  2644. {
  2645. ERROR_OUT(("CAppRoster: AddRecord: can't create APP_RECORD"));
  2646. rc = GCC_ALLOCATION_FAILURE;
  2647. goto MyExit;
  2648. }
  2649. /*
  2650. ** Here we must determine if an entry already exists at this
  2651. ** node. If so, only one entry can be conducting capable at a
  2652. ** node. Therefore, we set this variable based on this. We use
  2653. ** the "was_conducting_capable" variable to keep up with the
  2654. ** original state incase the conducting capable node leaves the
  2655. ** conference.
  2656. */
  2657. pAppRecord->is_conducting_capable = pReq->fConductingCapable;
  2658. APP_RECORD *p;
  2659. node_record->AppRecordList.Reset();
  2660. while (NULL != (p = node_record->AppRecordList.Iterate()))
  2661. {
  2662. if (p->is_conducting_capable)
  2663. {
  2664. pAppRecord->is_conducting_capable = FALSE;
  2665. break;
  2666. }
  2667. }
  2668. pAppRecord->was_conducting_capable = pReq->fConductingCapable;
  2669. pAppRecord->is_enrolled_actively = pReq->fEnrollActively;
  2670. pAppRecord->startup_channel_type = pReq->nStartupChannelType;
  2671. pAppRecord->application_user_id = pReq->nUserID;
  2672. if (pReq->cNonCollapsedCaps != 0)
  2673. {
  2674. rc = AddNonCollapsedCapabilities (
  2675. &pAppRecord->non_collapsed_caps_list,
  2676. pReq->cNonCollapsedCaps,
  2677. pReq->apNonCollapsedCaps);
  2678. if (GCC_NO_ERROR != rc)
  2679. {
  2680. ERROR_OUT(("CAppRoster::AddRecord: can't add non collapsed caps, rc=%u", (UINT) rc));
  2681. delete pAppRecord;
  2682. goto MyExit;
  2683. }
  2684. }
  2685. // Add the new record to the list of records at this node
  2686. node_record->AppRecordList.Append(eid, pAppRecord);
  2687. // from now on, we cannot free pAppRecord in case of error,
  2688. // because it is now in the app record list.
  2689. // Increment the instance number.
  2690. m_nInstance++;
  2691. m_fPeerEntitiesAdded = TRUE;
  2692. m_fRosterHasChanged = TRUE;
  2693. // Add an update to the PDU.
  2694. rc = BuildApplicationRecordListPDU(APP_ADD_RECORD, nid, eid);
  2695. if (GCC_NO_ERROR != rc)
  2696. {
  2697. ERROR_OUT(("CAppRoster::AddRecord: can't build app record list, rc=%u", (UINT) rc));
  2698. goto MyExit;
  2699. }
  2700. if (pReq->cCollapsedCaps != 0)
  2701. {
  2702. /*
  2703. ** Create a new capabilities list and insert it into the roster
  2704. ** record list of capabilities.
  2705. */
  2706. DBG_SAVE_FILE_LINE
  2707. pAppCapItemList = new CAppCapItemList;
  2708. if (NULL == pAppCapItemList)
  2709. {
  2710. ERROR_OUT(("CAppRoster::AddRecord: can't create CAppCapItemList"));
  2711. rc = GCC_ALLOCATION_FAILURE;
  2712. goto MyExit;
  2713. }
  2714. rc = AddCollapsableCapabilities(pAppCapItemList,
  2715. pReq->cCollapsedCaps,
  2716. pReq->apCollapsedCaps);
  2717. if (GCC_NO_ERROR != rc)
  2718. {
  2719. ERROR_OUT(("CAppRoster::AddRecord: can't add collapsable caps, rc=%u", (UINT) rc));
  2720. delete pAppCapItemList;
  2721. goto MyExit;
  2722. }
  2723. // Add list of capabilities to list at this node
  2724. node_record->ListOfAppCapItemList2.Append(eid, pAppCapItemList);
  2725. m_fCapabilitiesHaveChanged = TRUE;
  2726. // from now on, we cannot free pAppCapItemList in case of error,
  2727. // because it is now in the app cap item list
  2728. // Rebuild the collapsed capabilities list.
  2729. MakeCollapsedCapabilitiesList();
  2730. // Build the capabilities refresh portion of the PDU.
  2731. rc = BuildSetOfCapabilityRefreshesPDU();
  2732. if (GCC_NO_ERROR != rc)
  2733. {
  2734. ERROR_OUT(("CAppRoster::AddRecord: can't build set of cap refresh, rc=%u", (UINT) rc));
  2735. goto MyExit;
  2736. }
  2737. }
  2738. MyExit:
  2739. DebugExitINT(CAppRoster::AddRecord, rc);
  2740. return rc;
  2741. }
  2742. /*
  2743. * GCCError AddCollapsableCapabilities ()
  2744. *
  2745. * Private Function Description
  2746. * This routine takes API collapsed capabilities list data passed in
  2747. * through a local request and converts it to internal collapsed
  2748. * capabillities.
  2749. *
  2750. * Formal Parameters
  2751. * pAppCapItemList - (o) Pointer to internal capabilites list
  2752. * to fill in.
  2753. * number_of_capabilities - (i) Number of capabilities in the source
  2754. * list.
  2755. * capabilities_list - (i) Pointer to source capabilities list.
  2756. *
  2757. * Return Value
  2758. * GCC_NO_ERROR - No error occured.
  2759. * GCC_ALLOCATION_FAILURE - A resource error occured.
  2760. *
  2761. * Side Effects
  2762. * The collapsed capabilities will be recalculated at this node after
  2763. * all the new caps are added.
  2764. *
  2765. * Caveats
  2766. * none
  2767. */
  2768. GCCError CAppRoster::AddCollapsableCapabilities (
  2769. CAppCapItemList *pAppCapItemList,
  2770. UINT number_of_capabilities,
  2771. PGCCApplicationCapability *capabilities_list)
  2772. {
  2773. GCCError rc = GCC_NO_ERROR;
  2774. APP_CAP_ITEM *pAppCapItem;
  2775. UINT i;
  2776. BOOL capability_already_exists;
  2777. DebugEntry(CAppRoster::AddCollapsableCapabilities);
  2778. for (i = 0; i < number_of_capabilities; i++)
  2779. {
  2780. DBG_SAVE_FILE_LINE
  2781. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType)
  2782. capabilities_list[i]->capability_class.eType);
  2783. if (pAppCapItem != NULL)
  2784. {
  2785. DBG_SAVE_FILE_LINE
  2786. pAppCapItem->pCapID = new CCapIDContainer(&capabilities_list[i]->capability_id, &rc);
  2787. if ((pAppCapItem->pCapID != NULL) && (rc == GCC_NO_ERROR))
  2788. {
  2789. APP_CAP_ITEM *lpAppCapData;
  2790. /*
  2791. ** Here we check to make sure that this capability id does
  2792. ** not alreay exists in the list.
  2793. */
  2794. capability_already_exists = FALSE;
  2795. pAppCapItemList->Reset();
  2796. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  2797. {
  2798. if (*lpAppCapData->pCapID == *pAppCapItem->pCapID)
  2799. {
  2800. capability_already_exists = TRUE;
  2801. delete pAppCapItem;
  2802. break;
  2803. }
  2804. }
  2805. if (capability_already_exists == FALSE)
  2806. {
  2807. if (capabilities_list[i]->capability_class.eType ==
  2808. GCC_UNSIGNED_MINIMUM_CAPABILITY)
  2809. {
  2810. pAppCapItem->nUnsignedMinimum =
  2811. capabilities_list[i]->capability_class.nMinOrMax;
  2812. }
  2813. else if (capabilities_list[i]->capability_class.eType
  2814. == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  2815. {
  2816. pAppCapItem->nUnsignedMaximum = capabilities_list[i]->capability_class.nMinOrMax;
  2817. }
  2818. // Since we have yet to collapse the capabilities set to 1
  2819. pAppCapItem->cEntries = 1;
  2820. // Add this capability to the list
  2821. pAppCapItemList->Append(pAppCapItem);
  2822. }
  2823. }
  2824. else if (pAppCapItem->pCapID == NULL)
  2825. {
  2826. rc = GCC_ALLOCATION_FAILURE;
  2827. goto MyExit;
  2828. }
  2829. else
  2830. {
  2831. goto MyExit;
  2832. }
  2833. }
  2834. else
  2835. {
  2836. rc = GCC_ALLOCATION_FAILURE;
  2837. goto MyExit;
  2838. }
  2839. }
  2840. MyExit:
  2841. if (GCC_NO_ERROR != rc)
  2842. {
  2843. delete pAppCapItem;
  2844. }
  2845. return rc;
  2846. }
  2847. /*
  2848. * GCCError AddNonCollapsedCapabilities ()
  2849. *
  2850. * Private Function Description
  2851. * This routine takes API non-collapsed capabilities list data passed in
  2852. * through a local request and converts it to internal non-collapsed
  2853. * capabillities.
  2854. *
  2855. * Formal Parameters
  2856. * pAppCapItemList - (o) Pointer to internal non-collapsed
  2857. * capabilites list to fill in.
  2858. * number_of_capabilities - (i) Number of non-collapsed capabilities in
  2859. * the source list.
  2860. * capabilities_list - (i) Pointer to source non-collapsed
  2861. * capabilities list.
  2862. *
  2863. * Return Value
  2864. * GCC_NO_ERROR - No error occured.
  2865. * GCC_INVALID_NON_COLLAPSED_CAP - Invalid non-collapsed capability.
  2866. * GCC_ALLOCATION_FAILURE - A resource error occured.
  2867. *
  2868. * Side Effects
  2869. * none
  2870. *
  2871. * Caveats
  2872. * none
  2873. */
  2874. GCCError CAppRoster::AddNonCollapsedCapabilities (
  2875. CAppCapItemList *pAppCapItemList,
  2876. UINT number_of_capabilities,
  2877. PGCCNonCollapsingCapability *capabilities_list)
  2878. {
  2879. GCCError rc = GCC_NO_ERROR;
  2880. APP_CAP_ITEM *pAppCapItem;
  2881. UINT i;
  2882. DebugEntry(CAppRoster::AddNonCollapsedCapabilities);
  2883. for (i = 0; i < number_of_capabilities; i++)
  2884. {
  2885. //
  2886. // LONCHANC: Cap type is not set here.
  2887. // for now, it is zero.
  2888. //
  2889. DBG_SAVE_FILE_LINE
  2890. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType) 0);
  2891. if (pAppCapItem != NULL)
  2892. {
  2893. DBG_SAVE_FILE_LINE
  2894. pAppCapItem->pCapID = new CCapIDContainer(&capabilities_list[i]->capability_id, &rc);
  2895. if (pAppCapItem->pCapID != NULL)
  2896. {
  2897. if (capabilities_list[i]->application_data != NULL)
  2898. {
  2899. if (NULL == (pAppCapItem->poszAppData = ::My_strdupO2(
  2900. capabilities_list[i]->application_data->value,
  2901. capabilities_list[i]->application_data->length)))
  2902. {
  2903. rc = GCC_ALLOCATION_FAILURE;
  2904. goto MyExit;
  2905. }
  2906. else if (pAppCapItem->poszAppData->length > MAXIMUM_APPLICATION_DATA_LENGTH)
  2907. {
  2908. rc = GCC_INVALID_NON_COLLAPSED_CAP;
  2909. goto MyExit;
  2910. }
  2911. }
  2912. // Add this capability to the list if no errors
  2913. pAppCapItemList->Append(pAppCapItem);
  2914. }
  2915. else if (pAppCapItem->pCapID == NULL)
  2916. {
  2917. rc = GCC_ALLOCATION_FAILURE;
  2918. goto MyExit;
  2919. }
  2920. else
  2921. {
  2922. goto MyExit;
  2923. }
  2924. }
  2925. else
  2926. {
  2927. rc = GCC_ALLOCATION_FAILURE;
  2928. goto MyExit;
  2929. }
  2930. }
  2931. MyExit:
  2932. if (GCC_NO_ERROR != rc)
  2933. {
  2934. delete pAppCapItem;
  2935. }
  2936. return rc;
  2937. }
  2938. /*
  2939. * GCCError RemoveRecord ()
  2940. *
  2941. * Public Function Description
  2942. * This member function completely removes the specified record from the
  2943. * application roster. This includes any capabilities associated with
  2944. * this record. It also takes care of keeping the Instance number and
  2945. * added and removed flags up to date.
  2946. */
  2947. GCCError CAppRoster::RemoveRecord(GCCNodeID nid, GCCEntityID eid)
  2948. {
  2949. GCCError rc;
  2950. APP_RECORD *pAppRecord;
  2951. APP_NODE_RECORD *node_record;
  2952. DebugEntry(CAppRoster::RemoveRecord);
  2953. if (m_fPduIsFlushed)
  2954. {
  2955. FreeRosterUpdateIndicationPDU ();
  2956. m_fPduIsFlushed = FALSE;
  2957. }
  2958. // First see if the record is contained in the Roster_Record_List.
  2959. if (NULL == (node_record = m_NodeRecordList2.Find(nid)))
  2960. {
  2961. TRACE_OUT(("CAppRoster::RemoveRecord: can't find node record, nid=%u", (UINT) nid));
  2962. rc = GCC_INVALID_PARAMETER;
  2963. goto MyExit;
  2964. }
  2965. if (NULL == (pAppRecord = node_record->AppRecordList.Find(eid)))
  2966. {
  2967. TRACE_OUT(("CAppRoster::RemoveRecord: can't find app record, eid=%u", (UINT) eid));
  2968. rc = GCC_INVALID_PARAMETER;
  2969. goto MyExit;
  2970. }
  2971. /*
  2972. ** Here we must determine if any of the remaining APEs at this
  2973. ** node should become conducting capable based on their role
  2974. ** at the time they enrolled. We only do this if the record
  2975. ** that is being deleted was conducting capabile.
  2976. */
  2977. if (pAppRecord->is_conducting_capable)
  2978. {
  2979. APP_RECORD *p;
  2980. EntityID eid2;
  2981. node_record->AppRecordList.Reset();
  2982. while (NULL != (p = node_record->AppRecordList.Iterate(&eid2)))
  2983. {
  2984. /*
  2985. ** Here we only deal with record entries other than the
  2986. ** one being removed.
  2987. */
  2988. if (eid2 != eid)
  2989. {
  2990. if (p->was_conducting_capable)
  2991. {
  2992. p->is_conducting_capable = TRUE;
  2993. /*
  2994. ** Set up the update PDU for this conducting
  2995. ** capable change.
  2996. */
  2997. rc = BuildApplicationRecordListPDU(APP_REPLACE_RECORD, nid, eid2);
  2998. if (GCC_NO_ERROR != rc)
  2999. {
  3000. ERROR_OUT(("CAppRoster::RemoveRecord: can't build app record list, rc=%u", (UINT) rc));
  3001. goto MyExit;
  3002. }
  3003. break;
  3004. }
  3005. }
  3006. }
  3007. }
  3008. // Now delete the record
  3009. rc = DeleteRecord(nid, eid, TRUE);
  3010. if (GCC_NO_ERROR != rc)
  3011. {
  3012. WARNING_OUT(("CAppRoster::RemoveRecord: can't delete record, rc=%u", (UINT) rc));
  3013. goto MyExit;
  3014. }
  3015. // Increment the instance number.
  3016. m_nInstance++;
  3017. m_fPeerEntitiesRemoved = TRUE;
  3018. m_fRosterHasChanged = TRUE;
  3019. // Add an update to the PDU.
  3020. rc = BuildApplicationRecordListPDU(APP_DELETE_RECORD, nid, eid);
  3021. if (GCC_NO_ERROR != rc)
  3022. {
  3023. ERROR_OUT(("CAppRoster::RemoveRecord: can't build app record list, rc=%u", (UINT) rc));
  3024. goto MyExit;
  3025. }
  3026. /*
  3027. ** If the capabilities changed during the above processing
  3028. ** we must create a new collapsed capabilities list and
  3029. ** build a new capability refresh PDU.
  3030. */
  3031. if (m_fCapabilitiesHaveChanged)
  3032. {
  3033. MakeCollapsedCapabilitiesList();
  3034. rc = BuildSetOfCapabilityRefreshesPDU();
  3035. if (GCC_NO_ERROR != rc)
  3036. {
  3037. ERROR_OUT(("CAppRoster::RemoveRecord: can't build set of cap refreshes, rc=%u", (UINT) rc));
  3038. goto MyExit;
  3039. }
  3040. }
  3041. MyExit:
  3042. DebugExitINT(CAppRoster::RemoveRecord, rc);
  3043. return rc;
  3044. }
  3045. /*
  3046. * GCCError ReplaceRecord ()
  3047. *
  3048. * Public Function Description
  3049. * This routine completely replaces the specified record's parameters
  3050. * with the new parameters passed in. This includes the capabilities.
  3051. */
  3052. GCCError CAppRoster::
  3053. ReplaceRecord(GCCEnrollRequest *pReq, GCCNodeID nid, GCCEntityID eid)
  3054. {
  3055. GCCError rc = GCC_NO_ERROR;
  3056. BOOL capable_node_found;
  3057. APP_NODE_RECORD *node_record;
  3058. APP_RECORD *pAppRecord, *p;
  3059. APP_CAP_ITEM *lpAppCapData;
  3060. CAppCapItemList NonCollCapsList;
  3061. DebugEntry(CAppRoster::ReplaceRecord);
  3062. if (m_fPduIsFlushed)
  3063. {
  3064. FreeRosterUpdateIndicationPDU ();
  3065. m_fPduIsFlushed = FALSE;
  3066. }
  3067. /*
  3068. ** First determine if the node record does actually already exists. If not
  3069. ** we return an error here.
  3070. */
  3071. if (NULL == (node_record = m_NodeRecordList2.Find(nid)))
  3072. {
  3073. ERROR_OUT(("CAppRoster::ReplaceRecord: can't find the node record for nid=%u", (UINT) nid));
  3074. rc = GCC_INVALID_PARAMETER;
  3075. goto MyExit;
  3076. }
  3077. // make sure the app record exists. if not, return an error
  3078. if (NULL == (pAppRecord = node_record->AppRecordList.Find(eid)))
  3079. {
  3080. ERROR_OUT(("CAppRoster::ReplaceRecord: can't find the app record for eid=%u", (UINT) eid));
  3081. rc = GCC_INVALID_PARAMETER;
  3082. goto MyExit;
  3083. }
  3084. /*
  3085. ** First check to make sure that we can build the new record before
  3086. ** replacing the old record. The only entry we need to wory about
  3087. ** here are the non-collapsing capabilities.
  3088. */
  3089. if (pReq->cNonCollapsedCaps != 0)
  3090. {
  3091. rc = AddNonCollapsedCapabilities(&NonCollCapsList,
  3092. pReq->cNonCollapsedCaps,
  3093. pReq->apNonCollapsedCaps);
  3094. if (GCC_NO_ERROR != rc)
  3095. {
  3096. ERROR_OUT(("CAppRoster::ReplaceRecord: can't add non collapsed caps, rc=%u", (UINT) rc));
  3097. goto MyExit;
  3098. }
  3099. }
  3100. // Now replace the record entries.
  3101. pAppRecord->is_enrolled_actively = pReq->fEnrollActively;
  3102. pAppRecord->was_conducting_capable = pReq->fConductingCapable;
  3103. pAppRecord->startup_channel_type = pReq->nStartupChannelType;
  3104. pAppRecord->application_user_id = pReq->nUserID;
  3105. /*
  3106. ** If the is conducting capable flag that was passed in was set
  3107. ** to FALSE we can go ahead and set the internal is conducting
  3108. ** capable flag to FALSE regardless of what the previous
  3109. ** setting was. If it was passed in TRUE we leave the previous
  3110. ** setting alone.
  3111. */
  3112. if (pAppRecord->was_conducting_capable == FALSE)
  3113. {
  3114. pAppRecord->is_conducting_capable = FALSE;
  3115. }
  3116. /*
  3117. ** Here we delete the old non-collapsed capabilites and then
  3118. ** add the new ones.
  3119. */
  3120. if (! pAppRecord->non_collapsed_caps_list.IsEmpty())
  3121. {
  3122. pAppRecord->non_collapsed_caps_list.DeleteList();
  3123. pAppRecord->non_collapsed_caps_list.Clear();
  3124. }
  3125. // Copy the new non collapsed capabilities if any exists.
  3126. if (pReq->cNonCollapsedCaps != 0)
  3127. {
  3128. while (NULL != (lpAppCapData = NonCollCapsList.Get()))
  3129. {
  3130. pAppRecord->non_collapsed_caps_list.Append(lpAppCapData);
  3131. }
  3132. }
  3133. //
  3134. // handling collapsing cap list
  3135. //
  3136. m_nInstance++;
  3137. m_fRosterHasChanged = TRUE;
  3138. rc = BuildApplicationRecordListPDU(APP_REPLACE_RECORD, nid, eid);
  3139. if (rc != GCC_NO_ERROR)
  3140. {
  3141. ERROR_OUT(("CAppRoster::ReplaceRecord: can't build app record list, rc=%u", (UINT) rc));
  3142. goto MyExit;
  3143. }
  3144. /*
  3145. ** Here we must make sure that at least one of the APEs is
  3146. ** Conducting Capable. We do this by first scanning the
  3147. ** list to see if anyone is it. If one is not found, the
  3148. ** same list is scanned for an APE that "was" previously
  3149. ** capable. The first one found that was previously
  3150. ** capable is now it. If none are found then no one is
  3151. ** capable.
  3152. */
  3153. capable_node_found = FALSE;
  3154. node_record->AppRecordList.Reset();
  3155. while (NULL != (p = node_record->AppRecordList.Iterate()))
  3156. {
  3157. if (p->is_conducting_capable)
  3158. {
  3159. capable_node_found = TRUE;
  3160. break;
  3161. }
  3162. }
  3163. if (! capable_node_found)
  3164. {
  3165. GCCEntityID eid2;
  3166. node_record->AppRecordList.Reset();
  3167. while (NULL != (p = node_record->AppRecordList.Iterate(&eid2)))
  3168. {
  3169. if (p->was_conducting_capable)
  3170. {
  3171. p->is_conducting_capable = TRUE;
  3172. /*
  3173. ** Set up the update PDU for this conducting
  3174. ** capable change.
  3175. */
  3176. rc = BuildApplicationRecordListPDU(APP_REPLACE_RECORD, nid, eid2);
  3177. if (GCC_NO_ERROR != rc)
  3178. {
  3179. ERROR_OUT(("CAppRoster::ReplaceRecord: can't build app record list, rc=%u", (UINT) rc));
  3180. goto MyExit;
  3181. }
  3182. break;
  3183. }
  3184. }
  3185. }
  3186. /*
  3187. ** This section of code deals with the collapsable capabilities.
  3188. ** First we determine if the capabilities passed in are different
  3189. ** from the previously existing capabilities. If so, we must
  3190. ** delete the old set of caps and add back in the new ones.
  3191. */
  3192. TRACE_OUT(("ApplicatonRoster:ReplaceRecord: Check to see if caps match"));
  3193. if (! DoCapabilitiesListMatch(nid, eid, pReq->cCollapsedCaps, pReq->apCollapsedCaps))
  3194. {
  3195. CAppCapItemList *pCollCapsList, *q;
  3196. TRACE_OUT(("ApplicatonRoster:ReplaceRecord: Capabilities match"));
  3197. m_fCapabilitiesHaveChanged = TRUE;
  3198. /*
  3199. ** Delete the old capabilities list since it does not match the
  3200. ** new capabilities list.
  3201. */
  3202. if (NULL != (q = node_record->ListOfAppCapItemList2.Find(eid)))
  3203. {
  3204. q->DeleteList();
  3205. delete q;
  3206. node_record->ListOfAppCapItemList2.Remove(eid);
  3207. }
  3208. /*
  3209. ** Here we add back in the new capabilities. Create a new
  3210. ** capabilities list and insert it into the roster record list of
  3211. ** capabilities.
  3212. */
  3213. if (pReq->cCollapsedCaps != 0)
  3214. {
  3215. DBG_SAVE_FILE_LINE
  3216. pCollCapsList = new CAppCapItemList;
  3217. if (NULL == pCollCapsList)
  3218. {
  3219. ERROR_OUT(("CAppRoster::ReplaceRecord: can't create CAppCapItemList"));
  3220. rc = GCC_ALLOCATION_FAILURE;
  3221. goto MyExit;
  3222. }
  3223. rc = AddCollapsableCapabilities(pCollCapsList,
  3224. pReq->cCollapsedCaps,
  3225. pReq->apCollapsedCaps);
  3226. if (rc != GCC_NO_ERROR)
  3227. {
  3228. ERROR_OUT(("CAppRoster::ReplaceRecord: can't add collapsed caps, rc=%u", (UINT) rc));
  3229. delete pCollCapsList;
  3230. goto MyExit;
  3231. }
  3232. // Add list of capabilities to list at this node
  3233. node_record->ListOfAppCapItemList2.Append(eid, pCollCapsList);
  3234. }
  3235. // Rebuild the collapsed capabilities list.
  3236. MakeCollapsedCapabilitiesList();
  3237. // Build the capabilities refresh portion of the PDU.
  3238. rc = BuildSetOfCapabilityRefreshesPDU();
  3239. if (GCC_NO_ERROR != rc)
  3240. {
  3241. ERROR_OUT(("CAppRoster::ReplaceRecord: can't build set of cap refreshes, rc=%u", (UINT) rc));
  3242. goto MyExit;
  3243. }
  3244. }
  3245. else
  3246. {
  3247. TRACE_OUT(("CAppRoster:ReplaceRecord:Capabilities match with previous record"));
  3248. }
  3249. MyExit:
  3250. DebugExitINT(CAppRoster::ReplaceRecord, rc);
  3251. return rc;
  3252. }
  3253. /*
  3254. * GCCError DeleteRecord ()
  3255. *
  3256. * Private Function Description
  3257. * This member function completely removes the specified record from the
  3258. * application roster. This includes any capabilities associated with
  3259. * this record.
  3260. *
  3261. * Formal Parameters
  3262. * node_id - (i) Node ID of record to delete.
  3263. * entity_id - (i) Entity ID of record to delete.
  3264. * clear_empty_records - (i) This flag indicates whether or not to
  3265. * clear out the node record if it no-longer
  3266. * holds data. When replacing a record we
  3267. * do NOT want to do this so that we don't
  3268. * lose any "unchanged" capabilities.
  3269. *
  3270. * Return Value
  3271. * GCC_NO_ERROR - No error occured.
  3272. * GCC_INVALID_PARAMETER - Record specified to delete does not exists.
  3273. *
  3274. * Side Effects
  3275. * none
  3276. *
  3277. * Caveats
  3278. * none
  3279. */
  3280. GCCError CAppRoster::DeleteRecord(UserID node_id,
  3281. EntityID entity_id,
  3282. BOOL clear_empty_records)
  3283. {
  3284. GCCError rc = GCC_NO_ERROR;
  3285. APP_RECORD *application_record;
  3286. CAppCapItemList *pAppCapItemList;
  3287. CAppRecordList2 *pAppRecordList;
  3288. UserID node_to_check;
  3289. APP_NODE_RECORD *node_record;
  3290. //APP_CAP_ITEM *lpAppCapData;
  3291. APP_NODE_RECORD *lpAppNodeRec;
  3292. DebugEntry(CAppRoster::DeleteRecord);
  3293. // First see if the record is contained in the Roster_Record_List.
  3294. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  3295. {
  3296. // Set up node id to check at bottom for empty record
  3297. node_to_check = node_id;
  3298. // Delete the application record.
  3299. if (NULL != (application_record = node_record->AppRecordList.Find(entity_id)))
  3300. {
  3301. TRACE_OUT(("AppRoster: DeleteRecord: Delete AppRecord"));
  3302. // Delete the data associated with the application record
  3303. DeleteApplicationRecordData (application_record);
  3304. // Remove record from application record list
  3305. node_record->AppRecordList.Remove(entity_id);
  3306. /*
  3307. ** Delete the associated capabilities list. Note that this list
  3308. ** only exists for records of local nodes. The collapsed
  3309. ** capabilities list at the root node record take create of
  3310. ** subordniate nodes and is deleted some where else.
  3311. */
  3312. if (NULL != (pAppCapItemList = node_record->ListOfAppCapItemList2.Find(entity_id)))
  3313. {
  3314. m_fCapabilitiesHaveChanged = TRUE;
  3315. pAppCapItemList->DeleteList();
  3316. TRACE_OUT(("AppRoster: DeleteRecord: Delete Capabilities"));
  3317. delete pAppCapItemList;
  3318. node_record->ListOfAppCapItemList2.Remove(entity_id);
  3319. }
  3320. }
  3321. else
  3322. {
  3323. WARNING_OUT(("AppRoster: DeleteRecord: can't find this eid=%u", (UINT) entity_id));
  3324. rc = GCC_INVALID_PARAMETER;
  3325. }
  3326. }
  3327. else
  3328. {
  3329. UserID uid2;
  3330. /*
  3331. ** Here we search through all the sub node list trying to find the
  3332. ** record. Set return value to record does not exist here and
  3333. ** after the record is found set it back to no error.
  3334. */
  3335. rc = GCC_INVALID_PARAMETER;
  3336. m_NodeRecordList2.Reset();
  3337. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate(&uid2)))
  3338. {
  3339. // Delete the sub_node list if it exists
  3340. if (NULL != (pAppRecordList = lpAppNodeRec->SubNodeList2.Find(node_id)))
  3341. {
  3342. // Delete the app_record_list entry.
  3343. if (NULL != (application_record = pAppRecordList->Find(entity_id)))
  3344. {
  3345. // Delete the data associated with the application record
  3346. DeleteApplicationRecordData (application_record);
  3347. pAppRecordList->Remove(entity_id);
  3348. if (pAppRecordList->IsEmpty())
  3349. {
  3350. TRACE_OUT(("AppRoster: DeleteRecord: Deleting Sub-Node"));
  3351. delete pAppRecordList;
  3352. lpAppNodeRec->SubNodeList2.Remove(node_id);
  3353. }
  3354. // Set up node id to check at bottom for empty record
  3355. node_to_check = uid2;
  3356. rc = GCC_NO_ERROR;
  3357. }
  3358. break;
  3359. }
  3360. }
  3361. }
  3362. /*
  3363. ** If the record list is empty and the sub node list is empty
  3364. ** we can remove this entire record from the application roster.
  3365. ** If the record list is empty but the sub node list is not we
  3366. ** must keep the roster record around to maintain the sub node list.
  3367. */
  3368. if ((rc == GCC_NO_ERROR) && clear_empty_records)
  3369. {
  3370. if (NULL != (node_record = m_NodeRecordList2.Find(node_to_check)) &&
  3371. node_record->AppRecordList.IsEmpty() &&
  3372. node_record->SubNodeList2.IsEmpty())
  3373. {
  3374. if (! node_record->CollapsedCapList.IsEmpty())
  3375. {
  3376. m_fCapabilitiesHaveChanged = TRUE;
  3377. // Delete the collapsed capabilities list.
  3378. node_record->CollapsedCapList.DeleteList();
  3379. }
  3380. delete node_record;
  3381. m_NodeRecordList2.Remove(node_to_check);
  3382. }
  3383. }
  3384. return rc;
  3385. }
  3386. /*
  3387. * GCCError RemoveUserReference ()
  3388. *
  3389. * Public Function Description
  3390. * This routine will only remove the application record and its sub nodes
  3391. * if the node being removed is directly connected to this node.
  3392. * Otherwise, we wait to receive the update from either the sub node or
  3393. * the Top Provider.
  3394. */
  3395. GCCError CAppRoster::RemoveUserReference(UserID detached_node)
  3396. {
  3397. GCCError rc = GCC_NO_ERROR;
  3398. DebugEntry(CAppRoster::RemoveUserReference);
  3399. // Clear out any previously allocated PDUs
  3400. if (m_fPduIsFlushed)
  3401. {
  3402. FreeRosterUpdateIndicationPDU ();
  3403. m_fPduIsFlushed = FALSE;
  3404. }
  3405. /*
  3406. ** First Try to remove the node record if one exist. If it does not
  3407. ** exist we return immediately. If it does exists we will build the
  3408. ** appropriate PDU and update the instance variables.
  3409. */
  3410. rc = ClearNodeRecordFromList (detached_node);
  3411. if (rc == GCC_NO_ERROR)
  3412. {
  3413. // Increment the instance number.
  3414. m_nInstance++;
  3415. m_fPeerEntitiesRemoved = TRUE;
  3416. m_fRosterHasChanged = TRUE;
  3417. /*
  3418. ** Go ahead and do the full refresh here since we do not know the
  3419. ** specifics about who was deleted.
  3420. */
  3421. rc = BuildApplicationRecordListPDU(APP_FULL_REFRESH, 0, 0);
  3422. if (m_fCapabilitiesHaveChanged && (rc == GCC_NO_ERROR))
  3423. {
  3424. // Create a new collapsed capabilities list.
  3425. MakeCollapsedCapabilitiesList();
  3426. // Build the capabilities refresh portion of the PDU.
  3427. rc = BuildSetOfCapabilityRefreshesPDU ();
  3428. }
  3429. }
  3430. return rc;
  3431. }
  3432. /*
  3433. * void DeleteApplicationRecordData ()
  3434. *
  3435. * Private Function Description
  3436. * This routine internal application record data.
  3437. *
  3438. * Formal Parameters
  3439. * application_record - Pointer to the application record data to
  3440. * delete.
  3441. *
  3442. * Return Value
  3443. * none
  3444. *
  3445. * Side Effects
  3446. * none
  3447. *
  3448. * Caveats
  3449. * none
  3450. */
  3451. void CAppRoster::DeleteApplicationRecordData(APP_RECORD *pAppRec)
  3452. {
  3453. pAppRec->non_collapsed_caps_list.DeleteList();
  3454. delete pAppRec;
  3455. }
  3456. /*
  3457. * USHORT GetNumberOfApplicationRecords ()
  3458. *
  3459. * Public Function Description
  3460. * This routine returns the total number of application records that exist
  3461. * in this application roster.
  3462. *
  3463. * Formal Parameters
  3464. * none
  3465. *
  3466. * Return Value
  3467. * Number of application roster records
  3468. *
  3469. * Side Effects
  3470. * none
  3471. *
  3472. * Caveats
  3473. * none
  3474. */
  3475. UINT CAppRoster::GetNumberOfApplicationRecords(void)
  3476. {
  3477. UINT cRecords = 0;
  3478. APP_NODE_RECORD *lpAppNodeRec;
  3479. CAppRecordList2 *lpAppRecDataList;
  3480. DebugEntry(CAppRoster::GetNumberOfApplicationRecords);
  3481. /*
  3482. ** First calculate the total number of records. This count is used to
  3483. ** allocate the space necessary to hold the records. Note that we must
  3484. ** count both the application record list and the sub-node list.
  3485. */
  3486. m_NodeRecordList2.Reset();
  3487. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  3488. {
  3489. // Add the application records at this node to the count.
  3490. cRecords += lpAppNodeRec->AppRecordList.GetCount();
  3491. // Next count the sub node entries.
  3492. if (! lpAppNodeRec->SubNodeList2.IsEmpty())
  3493. {
  3494. lpAppNodeRec->SubNodeList2.Reset();
  3495. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  3496. {
  3497. cRecords += lpAppRecDataList->GetCount();
  3498. }
  3499. }
  3500. }
  3501. return cRecords;
  3502. }
  3503. /*
  3504. * PGCCSessionKey GetSessionKey ()
  3505. *
  3506. * Public Function Description
  3507. * This routine returns the session key associated with this
  3508. * application roster.
  3509. *
  3510. * Formal Parameters
  3511. * none
  3512. *
  3513. * Return Value
  3514. * PGCCSessionKey - the application key associated with this roster
  3515. *
  3516. * Side Effects
  3517. * none
  3518. *
  3519. * Caveats
  3520. * none
  3521. */
  3522. /*
  3523. * void ResetApplicationRoster ()
  3524. *
  3525. * Public Function Description
  3526. * This routine takes care of resetting all the internal flags that are
  3527. * used to convey the current state of the application roster. Should be
  3528. * called after the roster is flushed and any roster update messages have
  3529. * been delivered (after a change to the roster occurs).
  3530. */
  3531. void CAppRoster::ResetApplicationRoster(void)
  3532. {
  3533. m_fCapabilitiesHaveChanged = FALSE;
  3534. m_fRosterHasChanged = FALSE;
  3535. m_fPeerEntitiesRemoved = FALSE;
  3536. m_fPeerEntitiesAdded = FALSE;
  3537. }
  3538. /*
  3539. * BOOL DoesRecordExist ()
  3540. *
  3541. * Public Function Description
  3542. * This routine informs the caller if the specified application record
  3543. * exists or not.
  3544. */
  3545. BOOL CAppRoster::DoesRecordExist(UserID node_id, EntityID entity_id)
  3546. {
  3547. BOOL rc = FALSE;
  3548. APP_NODE_RECORD *node_record;
  3549. CAppRecordList2 *record_list;
  3550. DebugEntry(CAppRoster::DoesRecordExist);
  3551. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  3552. {
  3553. if (node_record->AppRecordList.Find(entity_id))
  3554. rc = TRUE;
  3555. }
  3556. else
  3557. {
  3558. m_NodeRecordList2.Reset();
  3559. while (NULL != (node_record = m_NodeRecordList2.Iterate()))
  3560. {
  3561. if (NULL != (record_list = node_record->SubNodeList2.Find(node_id)))
  3562. {
  3563. if (record_list->Find(entity_id))
  3564. rc = TRUE;
  3565. }
  3566. }
  3567. }
  3568. return rc;
  3569. }
  3570. /*
  3571. * BOOL HasRosterChanged ()
  3572. *
  3573. * Public Function Description
  3574. * This routine informs the caller if the roster has changed since the
  3575. * last time it was reset.
  3576. */
  3577. /*
  3578. * GCCError ClearNodeRecordFromList ()
  3579. *
  3580. * Private Function Description
  3581. * This routine clears out all the application records that exists at
  3582. * the specified node or below it in the connection hierarchy.
  3583. *
  3584. * Formal Parameters
  3585. * node_id - Node ID of node to clear from Node Record list
  3586. *
  3587. * Return Value
  3588. * GCC_NO_ERROR - No error occured
  3589. * GCC_INVALID_PARAMETER - The specified node ID is not associated
  3590. * with any records.
  3591. *
  3592. * Side Effects
  3593. * none
  3594. *
  3595. * Caveats
  3596. * none
  3597. */
  3598. GCCError CAppRoster::ClearNodeRecordFromList( UserID node_id)
  3599. {
  3600. GCCError rc = GCC_NO_ERROR;
  3601. APP_NODE_RECORD *node_record;
  3602. APP_RECORD *lpAppRecData;
  3603. //APP_CAP_ITEM *lpAppCapData;
  3604. CAppRecordList2 *lpAppRecDataList;
  3605. DebugEntry(CAppRoster::ClearNodeRecordFromList);
  3606. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  3607. {
  3608. // Delete all the app_record_list entries.
  3609. node_record->AppRecordList.Reset();
  3610. while (NULL != (lpAppRecData = node_record->AppRecordList.Iterate()))
  3611. {
  3612. DeleteApplicationRecordData (lpAppRecData);
  3613. }
  3614. /*
  3615. ** Delete the ListOfAppCapItemList2 entries. Note that this
  3616. ** list should not exists for detached nodes if the local applications
  3617. ** cleanly unenroll with GCC. This list should only exists for
  3618. ** locally enrolled APEs. We still check here just to make sure.
  3619. */
  3620. if (! node_record->ListOfAppCapItemList2.IsEmpty())
  3621. {
  3622. //CAppCapItemList *lpAppCapDataList;
  3623. m_fCapabilitiesHaveChanged = TRUE;
  3624. node_record->ListOfAppCapItemList2.DeleteList();
  3625. }
  3626. // Delete the sub_node list.
  3627. node_record->SubNodeList2.Reset();
  3628. while (NULL != (lpAppRecDataList = node_record->SubNodeList2.Iterate()))
  3629. {
  3630. // Delete all the app_record_list entries.
  3631. lpAppRecDataList->Reset();
  3632. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  3633. {
  3634. DeleteApplicationRecordData (lpAppRecData);
  3635. }
  3636. delete lpAppRecDataList;
  3637. }
  3638. // Delete the collapsed capabilities list.
  3639. if (! node_record->CollapsedCapList.IsEmpty())
  3640. {
  3641. m_fCapabilitiesHaveChanged = TRUE;
  3642. node_record->CollapsedCapList.DeleteList();
  3643. }
  3644. // Delete the rogoue wave reference to this roster record.
  3645. delete node_record;
  3646. m_NodeRecordList2.Remove(node_id);
  3647. }
  3648. else
  3649. rc = GCC_INVALID_PARAMETER;
  3650. return rc;
  3651. }
  3652. /*
  3653. * ApplicationRosterError ClearNodeRecordList ()
  3654. *
  3655. * Private Function Description
  3656. * This routine complete frees all memory associated with the roster
  3657. * record list and clears the list of all its entries.
  3658. *
  3659. * Formal Parameters
  3660. * none
  3661. *
  3662. * Return Value
  3663. * none
  3664. *
  3665. * Side Effects
  3666. * none
  3667. *
  3668. * Caveats
  3669. * Currently this routine does not handle standard identifiers.
  3670. */
  3671. void CAppRoster::ClearNodeRecordList(void)
  3672. {
  3673. APP_NODE_RECORD *lpAppNodeRec;
  3674. APP_RECORD *lpAppRecData;
  3675. CAppRecordList2 *lpAppRecDataList;
  3676. //APP_CAP_ITEM *lpAppCapData;
  3677. //CAppCapItemList *lpAppCapDataList;
  3678. DebugEntry(CAppRoster::ClearNodeRecordList);
  3679. // Delete all the records in the application roster.
  3680. m_NodeRecordList2.Reset();
  3681. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  3682. {
  3683. // First delete all the app records at this node.
  3684. lpAppNodeRec->AppRecordList.Reset();
  3685. while (NULL != (lpAppRecData = lpAppNodeRec->AppRecordList.Iterate()))
  3686. {
  3687. DeleteApplicationRecordData(lpAppRecData);
  3688. }
  3689. // Next delete all the sub node record list.
  3690. lpAppNodeRec->SubNodeList2.Reset();
  3691. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  3692. {
  3693. lpAppRecDataList->Reset();
  3694. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  3695. {
  3696. DeleteApplicationRecordData(lpAppRecData);
  3697. }
  3698. // Delete the rogue wave list holding the lists of sub nodes.
  3699. delete lpAppRecDataList;
  3700. }
  3701. // Delete the collapsed capabilities list.
  3702. lpAppNodeRec->CollapsedCapList.DeleteList();
  3703. // Delete the list of capabilities list.
  3704. lpAppNodeRec->ListOfAppCapItemList2.DeleteList();
  3705. // Now delete the node record
  3706. delete lpAppNodeRec;
  3707. }
  3708. m_NodeRecordList2.Clear();
  3709. }
  3710. /*
  3711. * GCCError MakeCollapsedCapabilitiesList ()
  3712. *
  3713. * Private Function Description
  3714. * This routine is responsible for applying the T.124 capabilities
  3715. * rules to create the collapsed capabilities list at this node.
  3716. * It iterates through all the capabilities at this node to create this
  3717. * collapsed list.
  3718. *
  3719. * Formal Parameters
  3720. * none
  3721. *
  3722. * Return Value
  3723. * GCC_NO_ERROR - On success
  3724. * GCC_ALLOCATION_FAILURE - On resource error
  3725. *
  3726. * Side Effects
  3727. * none
  3728. *
  3729. * Caveats
  3730. * Currently this routine does not handle standard identifiers.
  3731. */
  3732. GCCError CAppRoster::MakeCollapsedCapabilitiesList(void)
  3733. {
  3734. GCCError rc = GCC_NO_ERROR;
  3735. APP_CAP_ITEM *lpAppCapData;
  3736. APP_NODE_RECORD *lpAppNodeRec;
  3737. CAppCapItemList *lpAppCapDataList;
  3738. DebugEntry(CAppRoster::MakeCollapsedCapabilitiesList);
  3739. // First clear out the old capabilities list.
  3740. m_CollapsedCapListForAllNodes.DeleteList();
  3741. /*
  3742. ** We now iterate through the capabilities at each node to create the
  3743. ** new capabilities list. Note that we have to check for the collapsed
  3744. ** capabilities list at each node as well as the list of capabilities list
  3745. ** that represents all the different capabilities for each entity at a
  3746. ** node. Note that in this implementation it is not possible to have both
  3747. ** a list of capabilities list and a collapsed capabilities list in the
  3748. ** same roster record.
  3749. */
  3750. m_NodeRecordList2.Reset();
  3751. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  3752. {
  3753. /*
  3754. ** First check the collapsed capabilities list. If entries exists
  3755. ** then we don't have to worry about the list of list.
  3756. */
  3757. if (! lpAppNodeRec->CollapsedCapList.IsEmpty())
  3758. {
  3759. lpAppNodeRec->CollapsedCapList.Reset();
  3760. while (NULL != (lpAppCapData = lpAppNodeRec->CollapsedCapList.Iterate()))
  3761. {
  3762. rc = AddCapabilityToCollapsedList(lpAppCapData);
  3763. if (GCC_NO_ERROR != rc)
  3764. {
  3765. goto MyExit; // break;
  3766. }
  3767. }
  3768. }
  3769. else
  3770. if (! lpAppNodeRec->ListOfAppCapItemList2.IsEmpty())
  3771. {
  3772. // Here we check the list of capabilities list.
  3773. lpAppNodeRec->ListOfAppCapItemList2.Reset();
  3774. while (NULL != (lpAppCapDataList = lpAppNodeRec->ListOfAppCapItemList2.Iterate()))
  3775. {
  3776. lpAppCapDataList->Reset();
  3777. while (NULL != (lpAppCapData = lpAppCapDataList->Iterate()))
  3778. {
  3779. rc = AddCapabilityToCollapsedList(lpAppCapData);
  3780. if (GCC_NO_ERROR != rc)
  3781. {
  3782. goto MyExit;
  3783. }
  3784. }
  3785. }
  3786. }
  3787. }
  3788. ASSERT(GCC_NO_ERROR == rc);
  3789. MyExit:
  3790. return rc;
  3791. }
  3792. /*
  3793. * GCCError AddCapabilityToCollapsedList ()
  3794. *
  3795. * Private Function Description
  3796. * This is the routine that performs the rules that allow the capability
  3797. * to be collapsed into the collapsed list.
  3798. *
  3799. * Formal Parameters
  3800. * new_capability - (i) Add this capability to the collapsed list.
  3801. *
  3802. * Return Value
  3803. * GCC_NO_ERROR - On success
  3804. * GCC_ALLOCATION_FAILURE - On resource error
  3805. *
  3806. * Side Effects
  3807. * none
  3808. *
  3809. * Caveats
  3810. * none
  3811. */
  3812. GCCError CAppRoster::AddCapabilityToCollapsedList(APP_CAP_ITEM *new_capability)
  3813. {
  3814. GCCError rc = GCC_NO_ERROR;
  3815. APP_CAP_ITEM *pAppCapItem;
  3816. DebugEntry(CAppRoster::AddCapabilityToCollapsedList);
  3817. /*
  3818. ** First determine if the capability already exists in the list.
  3819. ** We must iterate through the complete list to determine if there
  3820. ** is a matching capability id.
  3821. */
  3822. m_CollapsedCapListForAllNodes.Reset();
  3823. while (NULL != (pAppCapItem = m_CollapsedCapListForAllNodes.Iterate()))
  3824. {
  3825. if (*pAppCapItem->pCapID == *new_capability->pCapID)
  3826. {
  3827. pAppCapItem->cEntries += new_capability->cEntries;
  3828. break;
  3829. }
  3830. }
  3831. if (pAppCapItem == NULL)
  3832. {
  3833. DBG_SAVE_FILE_LINE
  3834. pAppCapItem = new APP_CAP_ITEM(new_capability, &rc);
  3835. if (NULL == pAppCapItem)
  3836. {
  3837. return GCC_ALLOCATION_FAILURE;
  3838. }
  3839. if (GCC_NO_ERROR != rc)
  3840. {
  3841. delete pAppCapItem;
  3842. return rc;
  3843. }
  3844. m_CollapsedCapListForAllNodes.Append(pAppCapItem);
  3845. }
  3846. /*
  3847. ** If the unsigned minimum or unsigned maximum rule is used perform the
  3848. ** operation here.
  3849. */
  3850. ASSERT(GCC_NO_ERROR == rc);
  3851. if (new_capability->eCapType == GCC_UNSIGNED_MINIMUM_CAPABILITY)
  3852. {
  3853. if (new_capability->nUnsignedMinimum < pAppCapItem->nUnsignedMinimum)
  3854. {
  3855. pAppCapItem->nUnsignedMinimum = new_capability->nUnsignedMinimum;
  3856. }
  3857. }
  3858. else if (new_capability->eCapType == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  3859. {
  3860. if (new_capability->nUnsignedMaximum > pAppCapItem->nUnsignedMaximum)
  3861. {
  3862. pAppCapItem->nUnsignedMaximum = new_capability->nUnsignedMaximum;
  3863. }
  3864. }
  3865. return rc;
  3866. }
  3867. /*
  3868. * BOOL DoCapabilitiesListMatch ()
  3869. *
  3870. * Private Function Description
  3871. * This routine determines if the set of capabilities that were passed in
  3872. * match the set of internal capabilities associated with the record.
  3873. *
  3874. * Formal Parameters
  3875. * node_id - (i) Node ID of record that contains the
  3876. * capabilities to check.
  3877. * entity_id - (i) Entity ID of record that contains the
  3878. * capbilities to check.
  3879. * number_of_capabilities - (i) Number of capabilities in list to check.
  3880. * capabilities_list - (i) "API" capabillities list to check
  3881. *
  3882. * Return Value
  3883. * TRUE - If capabillities list match
  3884. * FALSE - If capabillities list do NOT match
  3885. *
  3886. * Side Effects
  3887. * none
  3888. *
  3889. * Caveats
  3890. * none
  3891. */
  3892. BOOL CAppRoster::DoCapabilitiesListMatch (
  3893. UserID node_id,
  3894. EntityID entity_id,
  3895. UINT number_of_capabilities,
  3896. PGCCApplicationCapability * capabilities_list)
  3897. {
  3898. BOOL rc = FALSE;
  3899. CAppCapItemList *pAppCapItemList;
  3900. GCCError error_value;
  3901. APP_NODE_RECORD *node_record;
  3902. UINT i;
  3903. CCapIDContainer *capability_id;
  3904. DebugEntry(CAppRoster::DoCapabilitiesListMatch);
  3905. if (NULL == (node_record = m_NodeRecordList2.Find(node_id)))
  3906. return (FALSE);
  3907. if (NULL == (pAppCapItemList = node_record->ListOfAppCapItemList2.Find(entity_id)))
  3908. {
  3909. /*
  3910. ** If the record shows no capabilities and the number of passed
  3911. ** in capabilities is zero than we got a match.
  3912. */
  3913. return ((number_of_capabilities == 0) ? TRUE : FALSE);
  3914. }
  3915. else if (pAppCapItemList->GetCount() != number_of_capabilities)
  3916. {
  3917. return (FALSE);
  3918. }
  3919. /*
  3920. ** If we have gotten this far we must iterate through the entire list to
  3921. ** see if all the capabilities match.
  3922. */
  3923. for (i = 0; i < number_of_capabilities; i++)
  3924. {
  3925. /*
  3926. ** First we create a temporary ID to compare to the other
  3927. ** capability IDs.
  3928. */
  3929. DBG_SAVE_FILE_LINE
  3930. capability_id = new CCapIDContainer(&capabilities_list[i]->capability_id, &error_value);
  3931. if ((capability_id != NULL) && (error_value == GCC_NO_ERROR))
  3932. {
  3933. APP_CAP_ITEM *lpAppCapData;
  3934. // Start with the return value equal to FALSE
  3935. rc = FALSE;
  3936. /*
  3937. ** Now iterate through the complate internal capability
  3938. ** list looking for a matching capability.
  3939. */
  3940. pAppCapItemList->Reset();
  3941. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  3942. {
  3943. if (*capability_id == *lpAppCapData->pCapID)
  3944. {
  3945. if (lpAppCapData->eCapType == capabilities_list[i]->capability_class.eType)
  3946. {
  3947. if (capabilities_list[i]->capability_class.eType ==
  3948. GCC_UNSIGNED_MINIMUM_CAPABILITY)
  3949. {
  3950. if (capabilities_list[i]->capability_class.nMinOrMax ==
  3951. lpAppCapData->nUnsignedMinimum)
  3952. {
  3953. rc = TRUE;
  3954. }
  3955. }
  3956. else if (capabilities_list[i]->capability_class.eType ==
  3957. GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  3958. {
  3959. if (capabilities_list[i]->capability_class.nMinOrMax ==
  3960. lpAppCapData->nUnsignedMaximum)
  3961. {
  3962. rc = TRUE;
  3963. }
  3964. }
  3965. else
  3966. rc = TRUE;
  3967. }
  3968. break;
  3969. }
  3970. }
  3971. // Delete the capability ID data
  3972. capability_id->Release();
  3973. if (rc == FALSE)
  3974. break;
  3975. }
  3976. else
  3977. {
  3978. if (NULL != capability_id)
  3979. {
  3980. capability_id->Release();
  3981. }
  3982. break;
  3983. }
  3984. }
  3985. return rc;
  3986. }
  3987. void CAppRosterList::DeleteList(void)
  3988. {
  3989. CAppRoster *pAppRoster;
  3990. while (NULL != (pAppRoster = Get()))
  3991. {
  3992. pAppRoster->Release();
  3993. }
  3994. }
  3995. void CListOfAppCapItemList2::DeleteList(void)
  3996. {
  3997. CAppCapItemList *pAppCapItemList;
  3998. while (NULL != (pAppCapItemList = Get()))
  3999. {
  4000. pAppCapItemList->DeleteList();
  4001. delete pAppCapItemList;
  4002. }
  4003. }
  4004.