Leaked source code of windows server 2003
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.

4544 lines
127 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. if(old_set_of_capabilities != NULL)
  866. {
  867. old_set_of_capabilities->next = new_set_of_capabilities;
  868. }
  869. }
  870. /*
  871. ** This is used to set the next pointer if another record exists
  872. ** after this one.
  873. */
  874. old_set_of_capabilities = new_set_of_capabilities;
  875. /*
  876. * This will get filled in later if there is another record.
  877. */
  878. new_set_of_capabilities->next = NULL;
  879. new_set_of_capabilities->value.bit_mask = 0;
  880. // Fill in the capability identifier
  881. rc = lpAppCapData->pCapID->GetCapabilityIdentifierDataPDU(
  882. &new_set_of_capabilities->value.capability_id);
  883. if (GCC_NO_ERROR != rc)
  884. {
  885. goto MyExit;
  886. }
  887. if ((lpAppCapData->poszAppData != NULL) && (rc == GCC_NO_ERROR))
  888. {
  889. new_set_of_capabilities->value.bit_mask |= APPLICATION_DATA_PRESENT;
  890. new_set_of_capabilities->value.application_data.length =
  891. lpAppCapData->poszAppData->length;
  892. new_set_of_capabilities->value.application_data.value =
  893. lpAppCapData->poszAppData->value;
  894. }
  895. }
  896. rc = GCC_NO_ERROR;
  897. MyExit:
  898. if(rc != GCC_NO_ERROR)
  899. {
  900. FreeSetOfNonCollapsingCapabilitiesPDU(*pSetOfCaps);
  901. *pSetOfCaps = NULL;
  902. }
  903. return rc;
  904. }
  905. /*
  906. * These routines are used to free up a roster update indication PDU.
  907. */
  908. /*
  909. * void FreeRosterUpdateIndicationPDU ()
  910. *
  911. * Private Function Description
  912. * This routine frees up all the internal data allocated to hold the roster
  913. * update PDU.
  914. *
  915. * Formal Parameters
  916. * None
  917. *
  918. * Return Value
  919. * None
  920. *
  921. * Side Effects
  922. * None
  923. *
  924. * Caveats
  925. * Note that the session key PDU data is not freed. Since this data will
  926. * not change through out the life of this application roster object
  927. * we just use the same session id PDU data for every roster update
  928. * indication.
  929. */
  930. void CAppRoster::FreeRosterUpdateIndicationPDU(void)
  931. {
  932. DebugEntry(CAppRoster::FreeRosterUpdateIndicationPDU);
  933. switch (m_SetOfAppInfo.value.application_record_list.choice)
  934. {
  935. case APPLICATION_RECORD_REFRESH_CHOSEN:
  936. FreeSetOfRefreshesPDU ();
  937. break;
  938. case APPLICATION_RECORD_UPDATE_CHOSEN:
  939. FreeSetOfUpdatesPDU ();
  940. break;
  941. }
  942. // Free the PDU data associated with the capability list if one exists.
  943. if (m_SetOfAppInfo.value.application_capabilities_list.choice == APPLICATION_CAPABILITY_REFRESH_CHOSEN)
  944. {
  945. FreeSetOfCapabilityRefreshesPDU ();
  946. }
  947. m_SetOfAppInfo.value.application_record_list.choice = APPLICATION_NO_CHANGE_CHOSEN;
  948. m_SetOfAppInfo.value.application_capabilities_list.choice = CAPABILITY_NO_CHANGE_CHOSEN;
  949. m_pSetOfAppRecordUpdates = NULL;
  950. }
  951. /*
  952. * void FreeSetOfRefreshesPDU ()
  953. *
  954. * Private Function Description
  955. * This routine Frees all the memory associated with a set
  956. * of application record refreshes.
  957. *
  958. * Formal Parameters
  959. * none
  960. *
  961. * Return Value
  962. * none
  963. *
  964. * Side Effects
  965. * none
  966. *
  967. * Caveats
  968. * none
  969. */
  970. void CAppRoster::FreeSetOfRefreshesPDU(void)
  971. {
  972. PSetOfApplicationRecordRefreshes pCurr, pNext;
  973. DebugEntry(CAppRoster::FreeSetOfRefreshesPDU);
  974. for (pCurr = m_SetOfAppInfo.value.application_record_list.u.application_record_refresh;
  975. NULL != pCurr;
  976. pCurr = pNext)
  977. {
  978. pNext = pCurr->next;
  979. // Free up any non-collapsing capabilities data
  980. if (pCurr->value.application_record.bit_mask & NON_COLLAPSING_CAPABILITIES_PRESENT)
  981. {
  982. FreeSetOfNonCollapsingCapabilitiesPDU(pCurr->value.application_record.non_collapsing_capabilities);
  983. }
  984. // Delete the actual record refresh
  985. delete pCurr;
  986. }
  987. m_SetOfAppInfo.value.application_record_list.u.application_record_refresh = NULL;
  988. }
  989. /*
  990. * void FreeSetOfUpdatesPDU ()
  991. *
  992. * Private Function Description
  993. * This routine frees the memory associated with a complete set
  994. * application roster updates.
  995. *
  996. * Formal Parameters
  997. * none
  998. *
  999. * Return Value
  1000. * none
  1001. *
  1002. * Side Effects
  1003. * none
  1004. *
  1005. * Caveats
  1006. * none
  1007. */
  1008. void CAppRoster::FreeSetOfUpdatesPDU(void)
  1009. {
  1010. PSetOfApplicationRecordUpdates pCurr, pNext;
  1011. PApplicationRecord application_record;
  1012. DebugEntry(CAppRoster::FreeSetOfUpdatesPDU);
  1013. for (pCurr = m_SetOfAppInfo.value.application_record_list.u.application_record_update;
  1014. NULL != pCurr;
  1015. pCurr = pNext)
  1016. {
  1017. // remember the next one because we will free the current one
  1018. pNext = pCurr->next;
  1019. // Free up any non-collapsing capabilities data
  1020. switch(pCurr->value.application_update.choice)
  1021. {
  1022. case APPLICATION_ADD_RECORD_CHOSEN:
  1023. application_record = &pCurr->value.application_update.u.application_add_record;
  1024. break;
  1025. case APPLICATION_REPLACE_RECORD_CHOSEN:
  1026. application_record = &pCurr->value.application_update.u.application_replace_record;
  1027. break;
  1028. default:
  1029. application_record = NULL;
  1030. break;
  1031. }
  1032. if (application_record != NULL)
  1033. {
  1034. if (application_record->bit_mask & NON_COLLAPSING_CAPABILITIES_PRESENT)
  1035. {
  1036. FreeSetOfNonCollapsingCapabilitiesPDU(application_record->non_collapsing_capabilities);
  1037. }
  1038. }
  1039. // Delete the actual update structure
  1040. delete pCurr;
  1041. }
  1042. m_SetOfAppInfo.value.application_record_list.u.application_record_update = NULL;
  1043. }
  1044. /*
  1045. * void FreeSetOfCapabilityRefreshesPDU ()
  1046. *
  1047. * Private Function Description
  1048. * This routine frees all the memory associated with the capability PDU.
  1049. *
  1050. * Formal Parameters
  1051. * capability_refresh - (i) Capabilities to be freed.
  1052. *
  1053. * Return Value
  1054. * none
  1055. *
  1056. * Side Effects
  1057. * none
  1058. *
  1059. * Caveats
  1060. * Note that the capability id PDU data is not freed here. Since this
  1061. * data should not change through out the life of this object we don't
  1062. * bother freeing and regenerating it.
  1063. */
  1064. void CAppRoster::FreeSetOfCapabilityRefreshesPDU(void)
  1065. {
  1066. PSetOfApplicationCapabilityRefreshes pCurr, pNext;
  1067. for (pCurr = m_SetOfAppInfo.value.application_capabilities_list.u.application_capability_refresh;
  1068. NULL != pCurr;
  1069. pCurr = pNext)
  1070. {
  1071. pNext = pCurr->next;
  1072. delete pCurr;
  1073. }
  1074. }
  1075. /*
  1076. * void FreeSetOfNonCollapsingCapabilitiesPDU ()
  1077. *
  1078. * Private Function Description
  1079. * This routine frees all the memory associated with the
  1080. * non-collapsed capability PDU.
  1081. *
  1082. * Formal Parameters
  1083. * capability_refresh - (i) Non-Collapsed Capabilities to be freed.
  1084. *
  1085. * Return Value
  1086. * none
  1087. *
  1088. * Side Effects
  1089. * none
  1090. *
  1091. * Caveats
  1092. * Note that the capability id PDU data is not freed here. Since this
  1093. * data should not change through out the life of this object we don't
  1094. * bother freeing and regenerating it.
  1095. */
  1096. void CAppRoster::FreeSetOfNonCollapsingCapabilitiesPDU (
  1097. PSetOfNonCollapsingCapabilities capability_refresh)
  1098. {
  1099. PSetOfNonCollapsingCapabilities pCurr, pNext;
  1100. for (pCurr = capability_refresh; NULL != pCurr; pCurr = pNext)
  1101. {
  1102. pNext = pCurr->next;
  1103. delete pCurr;
  1104. }
  1105. }
  1106. /*
  1107. * These routines process roster update indication PDUs.
  1108. */
  1109. /*
  1110. * ApplicationRosterError ProcessRosterUpdateIndicationPDU ()
  1111. *
  1112. * Public Function Description
  1113. * This routine is responsible for processing the decoded PDU data.
  1114. * It essentially changes the application roster object's internal database
  1115. * based on the information in the structure.
  1116. */
  1117. GCCError CAppRoster::ProcessRosterUpdateIndicationPDU (
  1118. PSetOfApplicationInformation application_information,
  1119. UserID sender_id)
  1120. {
  1121. GCCError rc = GCC_NO_ERROR;
  1122. DebugEntry(CAppRoster::ProcessRosterUpdateIndicationPDU);
  1123. /*
  1124. ** Free up the old PDU data here if it is being maintained and the
  1125. ** PDU has been flushed. Note that we also set the PDU is flushed boolean
  1126. ** back to FALSE so that the new PDU will be maintained until it is
  1127. ** flushed.
  1128. */
  1129. if (m_fPduIsFlushed)
  1130. {
  1131. FreeRosterUpdateIndicationPDU ();
  1132. m_fPduIsFlushed = FALSE;
  1133. }
  1134. /*
  1135. ** Now check the application key to make sure we have a match. If
  1136. ** not, return with no change.
  1137. */
  1138. if (! m_pSessionKey->IsThisYourSessionKeyPDU(&application_information->value.session_key))
  1139. {
  1140. WARNING_OUT(("CAppRoster::ProcessRosterUpdateIndicationPDU:GCC_BAD_SESSION_KEY"));
  1141. rc = GCC_BAD_SESSION_KEY;
  1142. goto MyExit;
  1143. }
  1144. /*
  1145. ** If this is a roster update and refresh is chosen we must
  1146. ** clear out the entire list and rebuild it.
  1147. */
  1148. if (application_information->value.application_record_list.choice != APPLICATION_NO_CHANGE_CHOSEN)
  1149. {
  1150. // The roster is about to change
  1151. m_fRosterHasChanged = TRUE;
  1152. /*
  1153. ** If this node is the top provider or this roster is local and
  1154. ** only used to propogate PDUs up toward the top provider,
  1155. ** we increment the instance number. If it is not we get the
  1156. ** instance number out of the PDU.
  1157. */
  1158. if (m_fTopProvider || m_fLocalRoster)
  1159. {
  1160. m_nInstance++;
  1161. }
  1162. else
  1163. {
  1164. m_nInstance = application_information->value.roster_instance_number;
  1165. }
  1166. /*
  1167. ** Here if either of these booleans is already TRUE we do not
  1168. ** want to write over them with this PDU data. Therefore, we
  1169. ** check for FALSE before we do anything with them.
  1170. */
  1171. if (! m_fPeerEntitiesAdded)
  1172. {
  1173. m_fPeerEntitiesAdded = application_information->value.peer_entities_are_added;
  1174. }
  1175. if (! m_fPeerEntitiesRemoved)
  1176. {
  1177. m_fPeerEntitiesRemoved = application_information->value.peer_entities_are_removed;
  1178. }
  1179. if (application_information->value.application_record_list.choice == APPLICATION_RECORD_REFRESH_CHOSEN)
  1180. {
  1181. TRACE_OUT(("CAppRoster::ProcessRosterUpdateIndicationPDU:ProcessSetOfRefreshesPDU"));
  1182. rc = ProcessSetOfRefreshesPDU(
  1183. application_information->value.application_record_list.u.application_record_refresh,
  1184. sender_id);
  1185. }
  1186. else
  1187. {
  1188. TRACE_OUT(("CAppRoster::ProcessRosterUpdateIndicationPDU:ProcessSetOfUpdatesPDU"));
  1189. rc = ProcessSetOfUpdatesPDU(
  1190. application_information->value.application_record_list.u.application_record_update,
  1191. sender_id);
  1192. }
  1193. if (GCC_NO_ERROR != rc)
  1194. {
  1195. goto MyExit;
  1196. }
  1197. }
  1198. else
  1199. {
  1200. ERROR_OUT(("AppRoster::ProcessRosterUpdateIndicationPDU:ASSERTION: NO Change PDU received"));
  1201. }
  1202. // Process the capabilities list portion of the PDU.
  1203. if (application_information->value.application_capabilities_list.choice == APPLICATION_CAPABILITY_REFRESH_CHOSEN)
  1204. {
  1205. // Set flag to show that change has occured.
  1206. m_fCapabilitiesHaveChanged = TRUE;
  1207. /*
  1208. ** We will store the new capabilities in the roster record
  1209. ** associated with the sender id. Note that it is possible for
  1210. ** this roster record to contain an empty application record list
  1211. ** if the sending node has no enrolled applications.
  1212. */
  1213. rc = ProcessSetOfCapabilityRefreshesPDU(
  1214. application_information->value.application_capabilities_list.u.application_capability_refresh,
  1215. sender_id);
  1216. }
  1217. else
  1218. {
  1219. ASSERT(GCC_NO_ERROR == rc);
  1220. }
  1221. MyExit:
  1222. return rc;
  1223. }
  1224. /*
  1225. * GCCError ProcessSetOfRefreshesPDU ()
  1226. *
  1227. * Private Function Description
  1228. * This routine processes a set of record refreshes. It is responsible
  1229. * for managing the creation (or update) of all affected application
  1230. * records. The roster list built from a refresh PDU does not maintain the
  1231. * hierarchy of the conference since it is not important at this point.
  1232. * Refreshes are issued as broacast from the Top Provider down to the
  1233. * sub-ordinate nodes.
  1234. *
  1235. * Formal Parameters
  1236. * record_refresh - (i) Set of record refresh PDUs to be processed.
  1237. * sender_id - (i) Node id of node that sent the update.
  1238. *
  1239. * Return Value
  1240. * GCC_NO_ERROR - On Success
  1241. * GCC_ALLOCATION_FAILURE - On resource failure
  1242. *
  1243. * Side Effects
  1244. * none
  1245. *
  1246. * Caveate
  1247. * none
  1248. */
  1249. GCCError CAppRoster::ProcessSetOfRefreshesPDU(
  1250. PSetOfApplicationRecordRefreshes record_refresh,
  1251. UserID sender_id)
  1252. {
  1253. GCCError rc = GCC_ALLOCATION_FAILURE;
  1254. PSetOfApplicationRecordRefreshes pCurr;
  1255. APP_RECORD *app_record;
  1256. APP_NODE_RECORD *node_record = NULL;
  1257. CAppRecordList2 *record_list=NULL;
  1258. UserID node_id;
  1259. EntityID entity_id;
  1260. DebugEntry(CAppRoster::ProcessSetOfRefreshesPDU);
  1261. if (record_refresh != NULL)
  1262. {
  1263. // Clear out the node record for the sender id
  1264. ClearNodeRecordFromList (sender_id);
  1265. /*
  1266. ** Create the node record for the sender id passed into this routine.
  1267. ** Note that if the sender of this refresh is the Top Provider
  1268. ** all nodes below the top provider are contained in the sub node
  1269. ** list of the Top Provider's node record.
  1270. */
  1271. DBG_SAVE_FILE_LINE
  1272. node_record = new APP_NODE_RECORD;
  1273. if (NULL == node_record)
  1274. {
  1275. goto MyExit;
  1276. }
  1277. if(!m_NodeRecordList2.Append(sender_id, node_record))
  1278. {
  1279. goto MyExit;
  1280. }
  1281. for (pCurr = record_refresh; NULL != pCurr; pCurr = pCurr->next)
  1282. {
  1283. node_id = pCurr->value.node_id;
  1284. entity_id = pCurr->value.entity_id;
  1285. if (sender_id != node_id)
  1286. {
  1287. // Get or create the sub node record list
  1288. if (NULL == (record_list = node_record->SubNodeList2.Find(node_id)))
  1289. {
  1290. DBG_SAVE_FILE_LINE
  1291. record_list = new CAppRecordList2(DESIRED_MAX_APP_RECORDS);
  1292. if (NULL == record_list)
  1293. {
  1294. goto MyExit;
  1295. }
  1296. node_record->SubNodeList2.Append(node_id, record_list);
  1297. }
  1298. }
  1299. else
  1300. {
  1301. /*
  1302. ** Here we set up the pointer to the record list. This
  1303. ** list is the node records application list which
  1304. ** means that this list contains the application records
  1305. ** associated with the sender's node.
  1306. */
  1307. record_list = &node_record->AppRecordList;
  1308. }
  1309. // Now create and fill in the new application record.
  1310. DBG_SAVE_FILE_LINE
  1311. app_record = new APP_RECORD;
  1312. if (NULL == app_record)
  1313. {
  1314. goto MyExit;
  1315. }
  1316. rc = ProcessApplicationRecordPDU(app_record, &pCurr->value.application_record);
  1317. if (GCC_NO_ERROR != rc)
  1318. {
  1319. goto MyExit;
  1320. }
  1321. record_list->Append(entity_id, app_record);
  1322. } // for
  1323. }
  1324. else
  1325. {
  1326. // This roster no longer contains any entries so clear the list!!!
  1327. ClearNodeRecordList ();
  1328. }
  1329. /*
  1330. ** Build a full refresh PDU here if no errors occured while processing
  1331. ** the refresh PDU.
  1332. */
  1333. rc = BuildApplicationRecordListPDU (APP_FULL_REFRESH, 0, 0);
  1334. MyExit:
  1335. if(rc ==GCC_ALLOCATION_FAILURE)
  1336. {
  1337. if(node_record)
  1338. {
  1339. delete node_record;
  1340. }
  1341. }
  1342. return rc;
  1343. }
  1344. /*
  1345. * GCCError ProcessSetOfUpdatesPDU ()
  1346. *
  1347. * Private Function Description
  1348. * This routine processes a set of roster updates. It iterates through
  1349. * the complete list of updates making all necessary changes to the
  1350. * internal information base and building the appropriate PDU.
  1351. *
  1352. * Formal Parameters
  1353. * record_update - (i) set of updates PDU to be processed
  1354. * sender_id - (i) gcc user id of node that sent the update
  1355. *
  1356. * Return Value
  1357. * APP_ROSTER_NO_ERROR - On Success
  1358. * APP_ROSTER_RESOURCE_ERROR - On resource failure
  1359. *
  1360. * Side Effects
  1361. * none
  1362. *
  1363. * Caveate
  1364. * none
  1365. */
  1366. GCCError CAppRoster::ProcessSetOfUpdatesPDU(
  1367. PSetOfApplicationRecordUpdates record_update,
  1368. UserID sender_id)
  1369. {
  1370. GCCError rc = GCC_ALLOCATION_FAILURE;
  1371. PSetOfApplicationRecordUpdates pCurr;
  1372. UserID node_id;
  1373. EntityID entity_id;
  1374. PApplicationRecord pdu_record;
  1375. APP_RECORD *application_record = NULL;
  1376. APP_NODE_RECORD *node_record;
  1377. CAppRecordList2 *record_list;
  1378. APP_ROSTER_UPDATE_TYPE update_type;
  1379. DebugEntry(CAppRoster::ProcessSetOfUpdatesPDU);
  1380. if (record_update != NULL)
  1381. {
  1382. for (pCurr = record_update; NULL != pCurr; pCurr = pCurr->next)
  1383. {
  1384. node_id = pCurr->value.node_id;
  1385. entity_id = pCurr->value.entity_id;
  1386. switch(pCurr->value.application_update.choice)
  1387. {
  1388. case APPLICATION_ADD_RECORD_CHOSEN:
  1389. pdu_record = &(pCurr->value.application_update.u.application_add_record);
  1390. update_type = APP_ADD_RECORD;
  1391. break;
  1392. case APPLICATION_REPLACE_RECORD_CHOSEN:
  1393. DeleteRecord (node_id, entity_id, FALSE);
  1394. pdu_record = &(pCurr->value.application_update.u.application_replace_record);
  1395. update_type = APP_REPLACE_RECORD;
  1396. break;
  1397. default: // Remove record
  1398. /*
  1399. ** Inform the owner that a record was delete while processing
  1400. ** this PDU so that it can perform any necessary cleanup.
  1401. */
  1402. m_pAppRosterMgr->DeleteRosterRecord(node_id, entity_id);
  1403. DeleteRecord (node_id, entity_id, TRUE);
  1404. pdu_record = NULL;
  1405. update_type = APP_DELETE_RECORD;
  1406. break;
  1407. }
  1408. /*
  1409. ** First get the roster record and if one does not exist for this
  1410. ** app record create it. After that we will create the application
  1411. ** record and put it into the correct slot in the application
  1412. ** roster record.
  1413. */
  1414. if (pdu_record != NULL)
  1415. {
  1416. /*
  1417. ** First find the correct node record and if it does not
  1418. ** exist create it.
  1419. */
  1420. if (NULL == (node_record = m_NodeRecordList2.Find(sender_id)))
  1421. {
  1422. DBG_SAVE_FILE_LINE
  1423. node_record = new APP_NODE_RECORD;
  1424. if (NULL == node_record)
  1425. {
  1426. goto MyExit;
  1427. }
  1428. m_NodeRecordList2.Append(sender_id, node_record);
  1429. }
  1430. /*
  1431. ** If the user and sender id is the same then the record
  1432. ** will be contained in the app_record_list. Otherwise, it
  1433. ** will be maintained in the sub-node list.
  1434. */
  1435. /*
  1436. ** If the sender_id equals the node id being processed
  1437. ** use the application record list instead of the sub
  1438. ** node list.
  1439. */
  1440. if (sender_id != node_id)
  1441. {
  1442. /*
  1443. ** Find the correct node list and create it if it does
  1444. ** not exists. This list holds lists of all the
  1445. ** application peer entities at a node.
  1446. */
  1447. if (NULL == (record_list = node_record->SubNodeList2.Find(node_id)))
  1448. {
  1449. DBG_SAVE_FILE_LINE
  1450. record_list = new CAppRecordList2(DESIRED_MAX_APP_RECORDS);
  1451. if (NULL == record_list)
  1452. {
  1453. goto MyExit;
  1454. }
  1455. node_record->SubNodeList2.Append(node_id, record_list);
  1456. }
  1457. }
  1458. else
  1459. {
  1460. record_list = &node_record->AppRecordList;
  1461. }
  1462. // Now fill in the application record
  1463. DBG_SAVE_FILE_LINE
  1464. application_record = new APP_RECORD;
  1465. if (NULL == application_record)
  1466. {
  1467. goto MyExit;
  1468. }
  1469. record_list->Append(entity_id, application_record);
  1470. rc = ProcessApplicationRecordPDU(application_record, pdu_record);
  1471. if (GCC_NO_ERROR != rc)
  1472. {
  1473. goto MyExit;
  1474. }
  1475. } // if
  1476. /*
  1477. ** Here we add this update to our PDU and jump to the next update
  1478. ** in the PDU currently being processed.
  1479. */
  1480. rc = BuildApplicationRecordListPDU ( update_type,
  1481. node_id,
  1482. entity_id);
  1483. if (rc != GCC_NO_ERROR)
  1484. {
  1485. goto MyExit;
  1486. }
  1487. /*
  1488. ** If the capabilities changed during the above processing
  1489. ** we must create a new collapsed capabilities list and
  1490. ** build a new capability refresh PDU.
  1491. */
  1492. if (m_fCapabilitiesHaveChanged)
  1493. {
  1494. MakeCollapsedCapabilitiesList();
  1495. rc = BuildSetOfCapabilityRefreshesPDU ();
  1496. if (rc != GCC_NO_ERROR)
  1497. {
  1498. goto MyExit;
  1499. }
  1500. }
  1501. } // for
  1502. } // if
  1503. rc = GCC_NO_ERROR;
  1504. MyExit:
  1505. return rc;
  1506. }
  1507. /*
  1508. * GCCError ProcessApplicationRecordPDU ()
  1509. *
  1510. * Private Function Description
  1511. * This routine is responsible for decoding the Application Record
  1512. * portion of the roster update pdu.
  1513. *
  1514. * Formal Parameters
  1515. * application_record - This is the internal destination app record.
  1516. * pdu_record - Source PDU data
  1517. *
  1518. * Return Value
  1519. * GCC_NO_ERROR - On Success
  1520. * GCC_ALLOCATION_FAILURE - On resource failure
  1521. *
  1522. * Side Effects
  1523. * none
  1524. *
  1525. * Caveats
  1526. * none
  1527. */
  1528. GCCError CAppRoster::ProcessApplicationRecordPDU (
  1529. APP_RECORD *application_record,
  1530. PApplicationRecord pdu_record)
  1531. {
  1532. GCCError rc = GCC_NO_ERROR;
  1533. DebugEntry(CAppRoster::ProcessApplicationRecordPDU);
  1534. application_record->is_enrolled_actively = pdu_record->application_is_active;
  1535. application_record->is_conducting_capable = pdu_record->is_conducting_capable;
  1536. if (pdu_record->bit_mask & RECORD_STARTUP_CHANNEL_PRESENT)
  1537. {
  1538. application_record->startup_channel_type =
  1539. (MCSChannelType)pdu_record->record_startup_channel;
  1540. }
  1541. else
  1542. application_record->startup_channel_type= MCS_NO_CHANNEL_TYPE_SPECIFIED;
  1543. if (pdu_record->bit_mask & APPLICATION_USER_ID_PRESENT)
  1544. {
  1545. application_record->application_user_id =
  1546. pdu_record->application_user_id;
  1547. }
  1548. else
  1549. application_record->application_user_id = 0;
  1550. if (pdu_record->bit_mask & NON_COLLAPSING_CAPABILITIES_PRESENT)
  1551. {
  1552. rc = ProcessNonCollapsingCapabilitiesPDU (
  1553. &application_record->non_collapsed_caps_list,
  1554. pdu_record->non_collapsing_capabilities);
  1555. }
  1556. return rc;
  1557. }
  1558. /*
  1559. * GCCError ProcessSetOfCapabilityRefreshesPDU ()
  1560. *
  1561. * Private Function Description
  1562. * This routine is responsible for decoding the capabilities portion
  1563. * of an roster update PDU.
  1564. *
  1565. * Formal Parameters
  1566. * capability_refresh - (i) set of capabilities PDU to be processed
  1567. * sender_id - (i) gcc user id of node that sent the update
  1568. *
  1569. * Return Value
  1570. * GCC_NO_ERROR - On Success
  1571. * GCC_ALLOCATION_FAILURE - On resource failure
  1572. *
  1573. * Side Effects
  1574. * none
  1575. *
  1576. * Caveats
  1577. * This routine does handle NULL for the capability refresh which means
  1578. * that the capabilities delivered no longer exists.
  1579. */
  1580. GCCError CAppRoster::ProcessSetOfCapabilityRefreshesPDU(
  1581. PSetOfApplicationCapabilityRefreshes capability_refresh,
  1582. UserID sender_id)
  1583. {
  1584. GCCError rc = GCC_NO_ERROR;
  1585. PSetOfApplicationCapabilityRefreshes pCurr;
  1586. CAppCapItemList *pAppCapList;
  1587. APP_CAP_ITEM *pAppCapItem;
  1588. APP_NODE_RECORD *node_record;
  1589. DebugEntry(CAppRoster::ProcessSetOfCapabilityRefreshesPDU);
  1590. if (NULL == (node_record = m_NodeRecordList2.Find(sender_id)))
  1591. {
  1592. DBG_SAVE_FILE_LINE
  1593. node_record = new APP_NODE_RECORD;
  1594. if (NULL == node_record)
  1595. {
  1596. return GCC_ALLOCATION_FAILURE;
  1597. }
  1598. if(!m_NodeRecordList2.Append(sender_id, node_record))
  1599. {
  1600. delete node_record;
  1601. return GCC_ALLOCATION_FAILURE;
  1602. }
  1603. }
  1604. // get collapsed cap list ptr
  1605. pAppCapList = &node_record->CollapsedCapList;
  1606. // Clear out all the old capabilities from this list.
  1607. pAppCapList->DeleteList();
  1608. // Begin processing the PDU.
  1609. for (pCurr = capability_refresh; NULL != pCurr; pCurr = pCurr->next)
  1610. {
  1611. ASSERT(GCC_NO_ERROR == rc);
  1612. // Create and fill in the new capability.
  1613. DBG_SAVE_FILE_LINE
  1614. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType) pCurr->value.capability_class.choice);
  1615. if (NULL == pAppCapItem)
  1616. {
  1617. return GCC_ALLOCATION_FAILURE;
  1618. }
  1619. // Create the capability ID
  1620. DBG_SAVE_FILE_LINE
  1621. pAppCapItem->pCapID = new CCapIDContainer(&pCurr->value.capability_id, &rc);
  1622. if (NULL == pAppCapItem->pCapID)
  1623. {
  1624. rc = GCC_ALLOCATION_FAILURE;
  1625. }
  1626. if (GCC_NO_ERROR != rc)
  1627. {
  1628. delete pAppCapItem;
  1629. return rc;
  1630. }
  1631. // append this cap to the collapsed cap list
  1632. pAppCapList->Append(pAppCapItem);
  1633. /*
  1634. ** Note that a logical type's value is maintained as
  1635. ** number of entities.
  1636. */
  1637. if (pCurr->value.capability_class.choice == UNSIGNED_MINIMUM_CHOSEN)
  1638. {
  1639. pAppCapItem->nUnsignedMinimum = pCurr->value.capability_class.u.unsigned_minimum;
  1640. }
  1641. else
  1642. if (pCurr->value.capability_class.choice == UNSIGNED_MAXIMUM_CHOSEN)
  1643. {
  1644. pAppCapItem->nUnsignedMaximum = pCurr->value.capability_class.u.unsigned_maximum;
  1645. }
  1646. pAppCapItem->cEntries = pCurr->value.number_of_entities;
  1647. } // for
  1648. // This forces a new capabilities list to be calculated.
  1649. MakeCollapsedCapabilitiesList();
  1650. /*
  1651. ** Here we build the new PDU data associated with this refresh of the
  1652. ** capability list.
  1653. */
  1654. return BuildSetOfCapabilityRefreshesPDU();
  1655. }
  1656. /*
  1657. * GCCError ProcessNonCollapsingCapabilitiesPDU ()
  1658. *
  1659. * Private Function Description
  1660. * This routine is responsible for decoding the non-collapsing capabilities
  1661. * portion of a roster record PDU.
  1662. *
  1663. * Formal Parameters
  1664. * non_collapsed_caps_list - (o) Pointer to list to fill in with new
  1665. * non-collapsed caps.
  1666. * pSetOfCaps - (i) non-collapsed PDU data
  1667. *
  1668. * Return Value
  1669. * GCC_NO_ERROR - On Success
  1670. * GCC_ALLOCATION_FAILURE - On resource failure
  1671. *
  1672. * Side Effects
  1673. * none
  1674. *
  1675. * Caveats
  1676. * none
  1677. */
  1678. GCCError CAppRoster::ProcessNonCollapsingCapabilitiesPDU (
  1679. CAppCapItemList *non_collapsed_caps_list,
  1680. PSetOfNonCollapsingCapabilities pSetOfCaps)
  1681. {
  1682. GCCError rc = GCC_NO_ERROR;
  1683. PSetOfNonCollapsingCapabilities pCurr;
  1684. APP_CAP_ITEM *pAppCapItem;
  1685. DebugEntry(CAppRoster::ProcessNonCollapsingCapsPDU);
  1686. for (pCurr = pSetOfCaps; NULL != pCurr; pCurr = pCurr->next)
  1687. {
  1688. //
  1689. // LONCHANC: The following cap data does not have a type???
  1690. // for now, set it to zero.
  1691. //
  1692. DBG_SAVE_FILE_LINE
  1693. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType)0);
  1694. if (NULL == pAppCapItem)
  1695. {
  1696. rc = GCC_ALLOCATION_FAILURE;
  1697. goto MyExit;
  1698. }
  1699. DBG_SAVE_FILE_LINE
  1700. pAppCapItem->pCapID = new CCapIDContainer(&pCurr->value.capability_id, &rc);
  1701. if (NULL == pAppCapItem->pCapID)
  1702. {
  1703. rc = GCC_ALLOCATION_FAILURE;
  1704. }
  1705. if (rc != GCC_NO_ERROR)
  1706. {
  1707. goto MyExit;
  1708. }
  1709. if (pCurr->value.bit_mask & APPLICATION_DATA_PRESENT)
  1710. {
  1711. if (NULL == (pAppCapItem->poszAppData = ::My_strdupO2(
  1712. pCurr->value.application_data.value,
  1713. pCurr->value.application_data.length)))
  1714. {
  1715. rc = GCC_ALLOCATION_FAILURE;
  1716. goto MyExit;
  1717. }
  1718. }
  1719. if( !non_collapsed_caps_list->Append(pAppCapItem) )
  1720. {
  1721. rc = GCC_ALLOCATION_FAILURE;
  1722. goto MyExit;
  1723. }
  1724. } // for
  1725. ASSERT(GCC_NO_ERROR == rc);
  1726. MyExit:
  1727. if (GCC_NO_ERROR != rc)
  1728. {
  1729. if( NULL != pAppCapItem )
  1730. delete pAppCapItem;
  1731. }
  1732. return rc;
  1733. }
  1734. /*
  1735. * Utilities that operate on conference records.
  1736. */
  1737. /*
  1738. * UINT LockApplicationRoster ()
  1739. *
  1740. * Public Function Description
  1741. * This routine is used to lock a GCCApplicationRoster and to determine the
  1742. * amount of memory necessary to hold the data referenced by the "API"
  1743. * application roster structure. The GCCApplicationRoster is used in
  1744. * indications to applications at the local node.
  1745. */
  1746. UINT CAppRoster::LockApplicationRoster(void)
  1747. {
  1748. UINT number_of_records = 0;
  1749. UINT number_of_capabilities = 0;
  1750. APP_NODE_RECORD *lpAppNodeRecord;
  1751. APP_RECORD *lpAppRecData;
  1752. APP_CAP_ITEM *lpAppCapData;
  1753. CAppRecordList2 *lpAppRecDataList;
  1754. DebugEntry(CAppRoster::LockApplicationRoster);
  1755. /*
  1756. * If this is the first time this routine is called, determine the size of
  1757. * the memory required to hold the data referenced by the application
  1758. * roster structure. Otherwise, just increment the lock count.
  1759. */
  1760. if (Lock() == 1)
  1761. {
  1762. /*
  1763. * Lock the data for the session key held within the roster. This lock
  1764. * call returns the size of the memory required to hold the session key
  1765. * data, rounded to an even multiple of four-bytes.
  1766. */
  1767. m_cbDataMemory = m_pSessionKey->LockSessionKeyData();
  1768. /*
  1769. * First calculate the total number of records. This count is used to
  1770. * determine the space necessary to hold the records. Note that we must
  1771. * count both the application record list and the sub-node list.
  1772. */
  1773. m_NodeRecordList2.Reset();
  1774. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate()))
  1775. {
  1776. /*
  1777. * Add the application records at this node to the count.
  1778. */
  1779. number_of_records += lpAppNodeRecord->AppRecordList.GetCount();
  1780. /*
  1781. * Next count the sub node records.
  1782. */
  1783. if (! lpAppNodeRecord->SubNodeList2.IsEmpty())
  1784. {
  1785. lpAppNodeRecord->SubNodeList2.Reset();
  1786. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate()))
  1787. {
  1788. number_of_records += lpAppRecDataList->GetCount();
  1789. }
  1790. }
  1791. }
  1792. /*
  1793. * Now determine the amount of memory necessary to hold all of the
  1794. * pointers to the application records as well as the actual
  1795. * GCCApplicationRecord structures.
  1796. */
  1797. m_cbDataMemory += number_of_records *
  1798. (sizeof(PGCCApplicationRecord) +
  1799. ROUNDTOBOUNDARY( sizeof(GCCApplicationRecord)) );
  1800. m_NodeRecordList2.Reset();
  1801. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate()))
  1802. {
  1803. /*
  1804. * Iterate through this node's record list, determining the amount
  1805. * of memory necessary to hold the pointers to the non-collapsing
  1806. * capabilities as well as the capability ID data and octet string
  1807. * data associated with each non-collapsing capability.
  1808. */
  1809. lpAppNodeRecord->AppRecordList.Reset();
  1810. while (NULL != (lpAppRecData = lpAppNodeRecord->AppRecordList.Iterate()))
  1811. {
  1812. /*
  1813. * Set up an iterator for the list of non-collapsing
  1814. * capabilities held within each application roster.
  1815. */
  1816. lpAppRecData->non_collapsed_caps_list.Reset();
  1817. number_of_capabilities += lpAppRecData->non_collapsed_caps_list.GetCount();
  1818. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  1819. {
  1820. /*
  1821. * Lock the data for each capability ID. The lock call
  1822. * returns the length of the data referenced by each
  1823. * capability ID rounded to occupy an even multiple of
  1824. * four-bytes.
  1825. */
  1826. m_cbDataMemory += lpAppCapData->pCapID->LockCapabilityIdentifierData();
  1827. /*
  1828. * Add up the space required to hold the application data
  1829. * octet strings if they are present. Make sure there is
  1830. * enough space for each octet string to occupy an even
  1831. * multiple of four bytes. Add room to hold the actual
  1832. * octet string structure also since the capability
  1833. * structure only contains a pointer to a OSTR.
  1834. */
  1835. if (lpAppCapData->poszAppData != NULL)
  1836. {
  1837. m_cbDataMemory += ROUNDTOBOUNDARY(sizeof(OSTR));
  1838. m_cbDataMemory += ROUNDTOBOUNDARY(lpAppCapData->poszAppData->length);
  1839. }
  1840. }
  1841. }
  1842. /*
  1843. * Iterate through this node's sub-node record list, determining the
  1844. * amount of memory necessary to hold the pointers to the
  1845. * non-collapsing capabilities as well as the capability ID data and
  1846. * octet string data associated with each non-collapsing capability.
  1847. */
  1848. lpAppNodeRecord->SubNodeList2.Reset();
  1849. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate()))
  1850. {
  1851. lpAppRecDataList->Reset();
  1852. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  1853. {
  1854. /*
  1855. * Set up an iterator for the list of non-collapsing
  1856. * capabilities held within each application roster.
  1857. */
  1858. number_of_capabilities += lpAppRecData->non_collapsed_caps_list.GetCount();
  1859. lpAppRecData->non_collapsed_caps_list.Reset();
  1860. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  1861. {
  1862. /*
  1863. * Lock the data for each capability ID. The lock call
  1864. * returns the length of the data referenced by each
  1865. * capability ID fixed up to occupy an even multiple of
  1866. * four-bytes.
  1867. */
  1868. m_cbDataMemory += lpAppCapData->pCapID->LockCapabilityIdentifierData();
  1869. /*
  1870. * Add up the space required to hold the application
  1871. * data octet strings if they are present. Make sure
  1872. * there is enough space for each octet string to occupy
  1873. * an even multiple of four bytes. Add room to hold the
  1874. * actual octet string structure also since the
  1875. * capability structure only contains a pointer to a OSTR
  1876. */
  1877. if (lpAppCapData->poszAppData != NULL)
  1878. {
  1879. m_cbDataMemory += ROUNDTOBOUNDARY(sizeof(OSTR));
  1880. m_cbDataMemory += ROUNDTOBOUNDARY(lpAppCapData->poszAppData->length);
  1881. }
  1882. }
  1883. }
  1884. }
  1885. }
  1886. /*
  1887. * Determine the amount of memory necessary to hold all of the pointers
  1888. * to the non-collapsing capabilities as well as the actual
  1889. * GCCNonCollapsingCapability structures.
  1890. */
  1891. m_cbDataMemory += number_of_capabilities *
  1892. (sizeof (PGCCNonCollapsingCapability) +
  1893. ROUNDTOBOUNDARY( sizeof(GCCNonCollapsingCapability)) );
  1894. /*
  1895. * Add the amount of memory necessary to hold the string data associated
  1896. * with each capability ID.
  1897. */
  1898. m_CollapsedCapListForAllNodes.Reset();
  1899. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  1900. {
  1901. m_cbDataMemory += lpAppCapData->pCapID->LockCapabilityIdentifierData();
  1902. }
  1903. /*
  1904. * Add the memory to hold the application capability pointers
  1905. * and structures.
  1906. */
  1907. number_of_capabilities = m_CollapsedCapListForAllNodes.GetCount();
  1908. m_cbDataMemory += number_of_capabilities *
  1909. (sizeof (PGCCApplicationCapability) +
  1910. ROUNDTOBOUNDARY( sizeof(GCCApplicationCapability)) );
  1911. }
  1912. return m_cbDataMemory;
  1913. }
  1914. /*
  1915. * UINT GetAppRoster()
  1916. *
  1917. * Public Function Description
  1918. * This routine is used to obtain a pointer to the GCCApplicatonRoster.
  1919. * This routine should not be called before LockApplicationRoster is
  1920. * called. LockApplicationRoster will create the GCCApplicationRoster in
  1921. * the memory provided. The GCCApplicationRoster is what is delivered to
  1922. * the end user Application SAP.
  1923. */
  1924. UINT CAppRoster::GetAppRoster(
  1925. PGCCApplicationRoster pGccAppRoster,
  1926. LPBYTE pData)
  1927. {
  1928. UINT rc;
  1929. DebugEntry(CAppRoster::GetAppRoster);
  1930. if (GetLockCount() > 0)
  1931. {
  1932. UINT data_length;
  1933. /*
  1934. * Fill in the output length parameter which indicates how much data
  1935. * referenced outside the structure will be written.
  1936. */
  1937. rc = m_cbDataMemory;
  1938. /*
  1939. * Get the data associated with the roster's session key and save
  1940. * the length of the data written into memory.
  1941. */
  1942. data_length = m_pSessionKey->GetGCCSessionKeyData(&pGccAppRoster->session_key, pData);
  1943. /*
  1944. * Move the memory pointer past the data associated with the
  1945. * session key.
  1946. */
  1947. pData += data_length;
  1948. /*
  1949. * Fill in other roster structure elements.
  1950. */
  1951. pGccAppRoster->application_roster_was_changed = m_fRosterHasChanged;
  1952. pGccAppRoster->instance_number = (USHORT) m_nInstance;
  1953. pGccAppRoster->nodes_were_added = m_fPeerEntitiesAdded;
  1954. pGccAppRoster->nodes_were_removed = m_fPeerEntitiesRemoved;
  1955. pGccAppRoster->capabilities_were_changed = m_fCapabilitiesHaveChanged;
  1956. /*
  1957. * Fill in the full set of application roster records.
  1958. */
  1959. data_length = GetApplicationRecords(pGccAppRoster, pData);
  1960. /*
  1961. * Move the memory pointer past the application records and their
  1962. * associated data. Get the full set of application capabilities.
  1963. */
  1964. pData += data_length;
  1965. data_length = GetCapabilitiesList(pGccAppRoster, pData);
  1966. }
  1967. else
  1968. {
  1969. ERROR_OUT(("CAppRoster::GetAppRoster: Error data not locked"));
  1970. rc = 0;
  1971. }
  1972. return rc;
  1973. }
  1974. /*
  1975. * void UnLockApplicationRoster ()
  1976. *
  1977. * Public Function Description
  1978. * This member function is responsible for unlocking the data locked for
  1979. * the "API" application roster after the lock count goes to zero.
  1980. */
  1981. void CAppRoster::UnLockApplicationRoster()
  1982. {
  1983. DebugEntry(CAppRoster::UnLockApplicationRoster);
  1984. if (Unlock(FALSE) == 0)
  1985. {
  1986. // reset the size
  1987. m_cbDataMemory = 0;
  1988. // free up all the memory locked for "API" data.
  1989. APP_NODE_RECORD *lpAppNodeRecord;
  1990. APP_RECORD *lpAppRecData;
  1991. APP_CAP_ITEM *lpAppCapData;
  1992. CAppRecordList2 *lpAppRecDataList;
  1993. // unlock session key data
  1994. m_pSessionKey->UnLockSessionKeyData();
  1995. // iterate through all the node records
  1996. m_NodeRecordList2.Reset();
  1997. while (NULL != (lpAppNodeRecord = m_NodeRecordList2.Iterate()))
  1998. {
  1999. // iterate through this node's record list
  2000. lpAppNodeRecord->AppRecordList.Reset();
  2001. while (NULL != (lpAppRecData = lpAppNodeRecord->AppRecordList.Iterate()))
  2002. {
  2003. // set up an iterator for the list of non-collapsing
  2004. // capabilities held within each application roster.
  2005. lpAppRecData->non_collapsed_caps_list.Reset();
  2006. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  2007. {
  2008. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2009. }
  2010. }
  2011. // iterate through this node's sub-node record list
  2012. lpAppNodeRecord->SubNodeList2.Reset();
  2013. while (NULL != (lpAppRecDataList = lpAppNodeRecord->SubNodeList2.Iterate()))
  2014. {
  2015. lpAppRecDataList->Reset();
  2016. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  2017. {
  2018. // set up an iterator for the list of non-collapsing
  2019. // capabilities held within each application roster.
  2020. lpAppRecData->non_collapsed_caps_list.Reset();
  2021. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  2022. {
  2023. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2024. }
  2025. }
  2026. }
  2027. }
  2028. // iterate through collapsed caps
  2029. m_CollapsedCapListForAllNodes.Reset();
  2030. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  2031. {
  2032. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2033. }
  2034. }
  2035. // we have to call Release() because we used Unlock(FALSE)
  2036. Release();
  2037. }
  2038. /*
  2039. * UINT GetApplicationRecords ()
  2040. *
  2041. * Private Function Description
  2042. * This routine inserts the complete set of application roster records
  2043. * into the passed in application roster structure.
  2044. *
  2045. * Formal Parameters
  2046. * gcc_roster - (o) GCCApplicationRoster to be filled in.
  2047. * memory - (o) Location in memory to begin writing records.
  2048. *
  2049. * Return Value
  2050. * The total amount of data written into memory.
  2051. *
  2052. * Side Effects
  2053. * The memory pointer passed in will be advanced by the amount of memory
  2054. * necessary to hold the application records and their data.
  2055. *
  2056. * Caveats
  2057. * none
  2058. */
  2059. UINT CAppRoster::GetApplicationRecords(
  2060. PGCCApplicationRoster gcc_roster,
  2061. LPBYTE memory)
  2062. {
  2063. UINT data_length = 0;
  2064. UINT record_count = 0;
  2065. PGCCApplicationRecord gcc_record;
  2066. UINT capability_data_length;
  2067. APP_NODE_RECORD *lpAppNodeRec;
  2068. CAppRecordList2 *lpAppRecDataList;
  2069. APP_RECORD *lpAppRecData;
  2070. UserID uid, uid2;
  2071. EntityID eid;
  2072. DebugEntry(CAppRoster::GetApplicationRecords);
  2073. /*
  2074. * Initialize the number of records in the roster to zero.
  2075. */
  2076. gcc_roster->number_of_records = 0;
  2077. /*
  2078. * First calculate the total number of records. This count is used to
  2079. * allocate the space necessary to hold the record pointers. Note that we
  2080. * must count both the application record list and the sub-node list.
  2081. */
  2082. m_NodeRecordList2.Reset();
  2083. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  2084. {
  2085. /*
  2086. * Add the number of application records at this node to the count.
  2087. */
  2088. gcc_roster->number_of_records += (USHORT) (lpAppNodeRec->AppRecordList.GetCount());
  2089. /*
  2090. * Next add the number of sub node entries.
  2091. */
  2092. if (! lpAppNodeRec->SubNodeList2.IsEmpty())
  2093. {
  2094. lpAppNodeRec->SubNodeList2.Reset();
  2095. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  2096. {
  2097. gcc_roster->number_of_records += (USHORT) (lpAppRecDataList->GetCount());
  2098. }
  2099. }
  2100. }
  2101. if (gcc_roster->number_of_records != 0)
  2102. {
  2103. /*
  2104. * Fill in the roster's pointer to the list of application record
  2105. * pointers. The pointer list will begin at the memory location passed
  2106. * into this routine.
  2107. */
  2108. gcc_roster->application_record_list = (PGCCApplicationRecord *)memory;
  2109. /*
  2110. * Move the memory pointer past the list of record pointers. This is
  2111. * where the first application record will be written.
  2112. */
  2113. memory += gcc_roster->number_of_records * sizeof(PGCCApplicationRecord);
  2114. /*
  2115. * Add to the data length the amount of memory necessary to hold the
  2116. * application record pointers. Go ahead and add the amount of memory
  2117. * necessary to hold all of the GCCApplicationRecord structures.
  2118. */
  2119. data_length += gcc_roster->number_of_records *
  2120. (sizeof(PGCCApplicationRecord) +
  2121. ROUNDTOBOUNDARY(sizeof(GCCApplicationRecord)));
  2122. record_count = 0;
  2123. m_NodeRecordList2.Reset();
  2124. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate(&uid)))
  2125. {
  2126. /*
  2127. * Iterate through this node's record list, building an "API"
  2128. * application record for each record in the list.
  2129. */
  2130. lpAppNodeRec->AppRecordList.Reset();
  2131. while (NULL != (lpAppRecData = lpAppNodeRec->AppRecordList.Iterate(&eid)))
  2132. {
  2133. /*
  2134. * Set the application record pointer equal to the location in
  2135. * memory where it will be written.
  2136. */
  2137. gcc_record = (PGCCApplicationRecord)memory;
  2138. /*
  2139. * Save the pointer to the application record in the roster's
  2140. * list of record pointers.
  2141. */
  2142. gcc_roster->application_record_list[record_count] = gcc_record;
  2143. /*
  2144. * Get the GCC node ID from the node iterator.
  2145. */
  2146. gcc_record->node_id = uid;
  2147. /*
  2148. * Get the Entity ID from the record iterator.
  2149. */
  2150. gcc_record->entity_id = eid;
  2151. /*
  2152. * Fill in other application record elements.
  2153. */
  2154. gcc_record->is_enrolled_actively = lpAppRecData->is_enrolled_actively;
  2155. gcc_record->is_conducting_capable = lpAppRecData->is_conducting_capable;
  2156. gcc_record->startup_channel_type = lpAppRecData->startup_channel_type;
  2157. gcc_record->application_user_id = lpAppRecData->application_user_id;
  2158. /*
  2159. * Advance the memory pointer past the application record
  2160. * structure. This is where the list of non-collapsing
  2161. * capabilities pointers will begin. Round the memory location
  2162. * off to fall on an even four-byte boundary.
  2163. */
  2164. memory += ROUNDTOBOUNDARY(sizeof(GCCApplicationRecord));
  2165. /*
  2166. * Fill in the non-collapsing capabilities for this application
  2167. * record.
  2168. */
  2169. capability_data_length = GetNonCollapsedCapabilitiesList(
  2170. gcc_record,
  2171. &lpAppRecData->non_collapsed_caps_list,
  2172. memory);
  2173. /*
  2174. * Add the amount of memory necessary to hold the list of
  2175. * capabilities and associated data to the overall length and
  2176. * move the memory pointer past the capabilities data.
  2177. */
  2178. memory += capability_data_length;
  2179. data_length += capability_data_length;
  2180. /*
  2181. * Increment the record list array counter.
  2182. */
  2183. record_count++;
  2184. }
  2185. /*
  2186. * Iterate through this node's sub-node record list, building an
  2187. * "API" application record for each record in the list.
  2188. */
  2189. lpAppNodeRec->SubNodeList2.Reset();
  2190. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate(&uid2)))
  2191. {
  2192. /*
  2193. * Iterate through this node's record list.
  2194. */
  2195. lpAppRecDataList->Reset();
  2196. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate(&eid)))
  2197. {
  2198. /*
  2199. * Set the application record pointer equal to the location
  2200. * in memory where it will be written.
  2201. */
  2202. gcc_record = (PGCCApplicationRecord)memory;
  2203. /*
  2204. * Save the pointer to the application record in the
  2205. * roster's list of record pointers.
  2206. */
  2207. gcc_roster->application_record_list[record_count] = gcc_record;
  2208. /*
  2209. * Get the node ID from the sub_node_iterator.
  2210. */
  2211. gcc_record->node_id = uid2;
  2212. /*
  2213. * Get the entity ID from the record_iterator.
  2214. */
  2215. gcc_record->entity_id = eid;
  2216. /*
  2217. * Fill in other application record elements.
  2218. */
  2219. gcc_record->is_enrolled_actively = lpAppRecData->is_enrolled_actively;
  2220. gcc_record->is_conducting_capable = lpAppRecData->is_conducting_capable;
  2221. gcc_record->startup_channel_type = lpAppRecData->startup_channel_type;
  2222. gcc_record->application_user_id = lpAppRecData->application_user_id;
  2223. /*
  2224. * Advance the memory pointer past the application record
  2225. * structure. This is where the list of non-collapsing
  2226. * capabilities pointers will begin. Round the memory
  2227. * location off to fall on an even four-byte boundary.
  2228. */
  2229. memory += ROUNDTOBOUNDARY(sizeof(GCCApplicationRecord));
  2230. /*
  2231. * Fill in the non-collapsing capabilities for this
  2232. * application record. The memory pointer will be advanced
  2233. * past the capabilities list and data.
  2234. */
  2235. capability_data_length = GetNonCollapsedCapabilitiesList(
  2236. gcc_record,
  2237. &lpAppRecData->non_collapsed_caps_list,
  2238. memory);
  2239. /*
  2240. * Add the amount of memory necessary to hold the list of
  2241. * capabilities and associated data to the overall length.
  2242. */
  2243. memory += capability_data_length;
  2244. data_length += capability_data_length;
  2245. /*
  2246. * Increment the record list array counter.
  2247. */
  2248. record_count++;
  2249. }
  2250. }
  2251. }
  2252. }
  2253. else
  2254. {
  2255. /*
  2256. * There were no application records so set the pointer to the list
  2257. * of records to NULL and the data_length return value to zero.
  2258. */
  2259. gcc_roster->application_record_list = NULL;
  2260. data_length = 0;
  2261. }
  2262. return (data_length);
  2263. }
  2264. /*
  2265. * UINT GetCapabilitiesList ()
  2266. *
  2267. * Private Function Description
  2268. * This routine fills in the capabilities portion of the
  2269. * GCCAppicationRoster structure.
  2270. *
  2271. * Formal Parameters
  2272. * gcc_roster - (o) GCCApplicationRoster to be filled in
  2273. * memory - (o) Location in memory to begin writing records.
  2274. *
  2275. * Return Value
  2276. * The total amount of data written into memory.
  2277. *
  2278. * Side Effects
  2279. * none
  2280. *
  2281. * Caveats
  2282. * none
  2283. */
  2284. UINT CAppRoster::GetCapabilitiesList(
  2285. PGCCApplicationRoster gcc_roster,
  2286. LPBYTE memory)
  2287. {
  2288. UINT data_length = 0;
  2289. UINT capability_id_data_length = 0;
  2290. UINT capability_count;
  2291. PGCCApplicationCapability gcc_capability;
  2292. APP_CAP_ITEM *lpAppCapData;
  2293. DebugEntry(CAppRoster::GetCapabilitiesList);
  2294. /*
  2295. * Retrieve the number of capabilities for this roster and fill in any that
  2296. * are present.
  2297. */
  2298. gcc_roster->number_of_capabilities = (USHORT) m_CollapsedCapListForAllNodes.GetCount();
  2299. if (gcc_roster->number_of_capabilities != 0)
  2300. {
  2301. /*
  2302. * Fill in the roster's pointer to the list of application capability
  2303. * pointers. The pointer list will begin at the memory location passed
  2304. * into this routine.
  2305. */
  2306. gcc_roster->capabilities_list = (PGCCApplicationCapability *)memory;
  2307. /*
  2308. * Move the memory pointer past the list of capability pointers. This
  2309. * is where the first application capability structure will be written.
  2310. */
  2311. memory += (Int)(gcc_roster->number_of_capabilities *
  2312. sizeof(PGCCApplicationCapability));
  2313. /*
  2314. * Add to the data length the amount of memory necessary to hold the
  2315. * application capability pointers. Go ahead and add the amount of
  2316. * memory necessary to hold all of the GCCApplicationCapability
  2317. * structures.
  2318. */
  2319. data_length += gcc_roster->number_of_capabilities *
  2320. (sizeof(PGCCApplicationCapability) +
  2321. ROUNDTOBOUNDARY ( sizeof(GCCApplicationCapability)) );
  2322. capability_count = 0;
  2323. m_CollapsedCapListForAllNodes.Reset();
  2324. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  2325. {
  2326. /*
  2327. * Set the application capability pointer equal to the
  2328. * location in memory where it will be written.
  2329. */
  2330. gcc_capability = (PGCCApplicationCapability)memory;
  2331. /*
  2332. * Save the pointer to the application capability in the roster's
  2333. * list of application capability pointers.
  2334. */
  2335. gcc_roster->capabilities_list[capability_count] =
  2336. gcc_capability;
  2337. /*
  2338. * Advance the memory pointer past the application capability
  2339. * structure. This is where the string data for the capability ID
  2340. * will be written. Ensure that the memory pointer falls on an
  2341. * even four-byte boundary.
  2342. */
  2343. memory += (Int)(ROUNDTOBOUNDARY(sizeof(GCCApplicationCapability)));
  2344. /*
  2345. * Retrieve the capability ID information from the internal
  2346. * CapabilityIDData object. The length returned by this call will
  2347. * have already been rounded to an even multiple of four bytes.
  2348. */
  2349. capability_id_data_length = lpAppCapData->pCapID->GetGCCCapabilityIDData(
  2350. &gcc_capability->capability_id,
  2351. memory);
  2352. /*
  2353. * Advance the memory pointer past the string data written into
  2354. * memory by the capability ID object. Add the length of the string
  2355. * data to the overall capability length.
  2356. */
  2357. memory += (Int)capability_id_data_length;
  2358. data_length += capability_id_data_length;
  2359. /*
  2360. * Now fill in the rest of the capability.
  2361. */
  2362. gcc_capability->capability_class.eType =lpAppCapData->eCapType;
  2363. if (gcc_capability->capability_class.eType ==
  2364. GCC_UNSIGNED_MINIMUM_CAPABILITY)
  2365. {
  2366. gcc_capability->capability_class.nMinOrMax = lpAppCapData->nUnsignedMinimum;
  2367. }
  2368. else if (gcc_capability->capability_class.eType == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  2369. {
  2370. gcc_capability->capability_class.nMinOrMax = lpAppCapData->nUnsignedMaximum;
  2371. }
  2372. gcc_capability->number_of_entities = lpAppCapData->cEntries;
  2373. /*
  2374. * Increment the capability ID array counter.
  2375. */
  2376. capability_count++;
  2377. }
  2378. }
  2379. else
  2380. {
  2381. gcc_roster->capabilities_list = NULL;
  2382. }
  2383. return (data_length);
  2384. }
  2385. /*
  2386. * UINT GetNonCollapsedCapabilitiesList ()
  2387. *
  2388. * Private Function Description:
  2389. * This routine is used to fill in the "API" non-collapsing capabilities
  2390. * portion of a GCCApplicationRoster from the data which is stored
  2391. * internally by this class.
  2392. *
  2393. * Formal Parameters
  2394. * gcc_record - (o) The application record to be filled in.
  2395. * pAppCapItemList (i) The internal capabilities data.
  2396. * memory (i/o) The memory location to begin writing data.
  2397. *
  2398. * Return Value
  2399. * The total amount of data written into memory.
  2400. *
  2401. * Side Effects
  2402. * The memory pointer passed in will be advanced by the amount of memory
  2403. * necessary to hold the capabilities and their data.
  2404. *
  2405. * Caveats
  2406. * none
  2407. */
  2408. UINT CAppRoster::GetNonCollapsedCapabilitiesList(
  2409. PGCCApplicationRecord gcc_record,
  2410. CAppCapItemList *pAppCapItemList,
  2411. LPBYTE memory)
  2412. {
  2413. UINT capability_count;
  2414. PGCCNonCollapsingCapability gcc_capability;
  2415. APP_CAP_ITEM *lpAppCapData;
  2416. UINT capability_id_length = 0;
  2417. UINT capability_data_length = 0;
  2418. DebugEntry(CAppRoster::GetNonCollapsedCapabilitiesList);
  2419. /*
  2420. * Get the number of non-collapsed capabilities.
  2421. */
  2422. gcc_record->number_of_non_collapsed_caps = (USHORT) pAppCapItemList->GetCount();
  2423. if (gcc_record->number_of_non_collapsed_caps != 0)
  2424. {
  2425. /*
  2426. * Fill in the record's pointer to the list of non-collapsing
  2427. * capabilities pointers. The pointer list will begin at the memory
  2428. * location passed into this routine.
  2429. */
  2430. gcc_record->non_collapsed_caps_list = (PGCCNonCollapsingCapability *)memory;
  2431. /*
  2432. * Move the memory pointer past the list of capability pointers. This
  2433. * is where the first capability structure will be written.
  2434. */
  2435. memory += (Int)(gcc_record->number_of_non_collapsed_caps *
  2436. sizeof(PGCCNonCollapsingCapability));
  2437. /*
  2438. * Add to the data length the amount of memory necessary to hold the
  2439. * capability pointers. Go ahead and add the amount of memory necessary
  2440. * to hold all of the GCCNonCollapsingCapability structures.
  2441. */
  2442. capability_data_length = gcc_record->number_of_non_collapsed_caps *
  2443. (sizeof(PGCCNonCollapsingCapability) +
  2444. ROUNDTOBOUNDARY(sizeof (GCCNonCollapsingCapability)));
  2445. /*
  2446. * Iterate through this record's capabilities list, building an "API"
  2447. * non-collapsing capability for each capability in the list.
  2448. */
  2449. capability_count = 0;
  2450. pAppCapItemList->Reset();
  2451. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  2452. {
  2453. /*
  2454. * Set the capability pointer equal to the location in memory where
  2455. * it will be written.
  2456. */
  2457. gcc_capability = (PGCCNonCollapsingCapability)memory;
  2458. /*
  2459. * Save the pointer to the capability in the record's list of
  2460. * capability pointers.
  2461. */
  2462. gcc_record->non_collapsed_caps_list[capability_count] = gcc_capability;
  2463. /*
  2464. * Move the memory pointer past the capability ID structure. This
  2465. * is where the data associated with the structure will be written.
  2466. * Retrieve the capability ID data from the internal object, saving
  2467. * it in the "API" capability ID structure.
  2468. */
  2469. memory += (Int)ROUNDTOBOUNDARY(sizeof(GCCNonCollapsingCapability));
  2470. capability_id_length = lpAppCapData->pCapID->GetGCCCapabilityIDData(
  2471. &gcc_capability->capability_id, memory);
  2472. /*
  2473. * Add to the data length the amount of memory necessary to hold the
  2474. * capability ID data.
  2475. */
  2476. capability_data_length += capability_id_length;
  2477. /*
  2478. * Move the memory pointer past the data filled in for the
  2479. * capability ID. This is where the application data OSTR
  2480. * contained in the non-collapsing capability will be written, if
  2481. * one exists. Note that the capability contains a pointer to a
  2482. * OSTR and therefore the OSTR structure as well
  2483. * as the string data must be written into memory.
  2484. */
  2485. memory += capability_id_length;
  2486. if (lpAppCapData->poszAppData != NULL)
  2487. {
  2488. /*
  2489. * Set the application data structure pointer equal to the
  2490. * location in memory where it will be written.
  2491. */
  2492. gcc_capability->application_data = (LPOSTR) memory;
  2493. gcc_capability->application_data->length = lpAppCapData->poszAppData->length;
  2494. /*
  2495. * Move the memory pointer past the OSTR structure
  2496. * and round it off to an even four-byte boundary. This is
  2497. * where the actual string data will be written so set the
  2498. * structure string pointer equal to that location.
  2499. */
  2500. memory += ROUNDTOBOUNDARY(sizeof(OSTR));
  2501. gcc_capability->application_data->value =(LPBYTE)memory;
  2502. /*
  2503. * Copy the actual application string data into memory.
  2504. */
  2505. ::CopyMemory(gcc_capability->application_data->value,
  2506. lpAppCapData->poszAppData->value,
  2507. lpAppCapData->poszAppData->length);
  2508. /*
  2509. * Add to the data length the amount of memory necessary to
  2510. * hold the application data structure and string. The lengths
  2511. * will need to be aligned on a four-byte boundary before
  2512. * adding them to the total length.
  2513. */
  2514. capability_data_length += ROUNDTOBOUNDARY(sizeof(OSTR));
  2515. capability_data_length += ROUNDTOBOUNDARY(gcc_capability->application_data->length);
  2516. /*
  2517. * Move the memory pointer past the application string data.
  2518. * The memory pointer is then fixed up to ensure that it falls
  2519. * on an even four-byte boundary.
  2520. */
  2521. memory += ROUNDTOBOUNDARY(lpAppCapData->poszAppData->length);
  2522. }
  2523. else
  2524. {
  2525. gcc_capability->application_data = NULL;
  2526. }
  2527. /*
  2528. * Increment the capability array counter.
  2529. */
  2530. capability_count++;
  2531. }
  2532. }
  2533. else
  2534. {
  2535. gcc_record->non_collapsed_caps_list = NULL;
  2536. capability_data_length = 0;
  2537. }
  2538. return (capability_data_length);
  2539. }
  2540. /*
  2541. * void FreeApplicationRosterData ()
  2542. *
  2543. * Private Function Description:
  2544. * This routine is used to free up any data which was locked for an "API"
  2545. * application roster.
  2546. *
  2547. * Formal Parameters
  2548. * none
  2549. *
  2550. * Return Value
  2551. * none
  2552. *
  2553. * Side Effects
  2554. * none
  2555. *
  2556. * Caveats
  2557. * none
  2558. */
  2559. void CAppRoster::FreeApplicationRosterData(void)
  2560. {
  2561. APP_NODE_RECORD *lpAppNodeRec;
  2562. APP_RECORD *lpAppRecData;
  2563. APP_CAP_ITEM *lpAppCapData;
  2564. CAppRecordList2 *lpAppRecDataList;
  2565. DebugEntry(CAppRoster::FreeApplicationRosterData);
  2566. m_pSessionKey->UnLockSessionKeyData();
  2567. /*
  2568. * Unlock the data associated with each non-collapsed capability by
  2569. * iterating through the list of application records at each node as well as
  2570. * the list of sub-node records at each node, calling "UnLock" for each
  2571. * CapabilityIDData associated with each cabability.
  2572. */
  2573. m_NodeRecordList2.Reset();
  2574. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  2575. {
  2576. lpAppNodeRec->AppRecordList.Reset();
  2577. while (NULL != (lpAppRecData = lpAppNodeRec->AppRecordList.Iterate()))
  2578. {
  2579. lpAppRecData->non_collapsed_caps_list.Reset();
  2580. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  2581. {
  2582. lpAppCapData->pCapID->UnLockCapabilityIdentifierData ();
  2583. }
  2584. }
  2585. lpAppNodeRec->SubNodeList2.Reset();
  2586. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  2587. {
  2588. lpAppRecDataList->Reset();
  2589. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  2590. {
  2591. lpAppRecData->non_collapsed_caps_list.Reset();
  2592. while (NULL != (lpAppCapData = lpAppRecData->non_collapsed_caps_list.Iterate()))
  2593. {
  2594. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2595. }
  2596. }
  2597. }
  2598. }
  2599. /*
  2600. * Iterate through the list of collapsed capabilities, unlocking the data
  2601. * for each CapabilityIDData object associated with each capability.
  2602. */
  2603. m_CollapsedCapListForAllNodes.Reset();
  2604. while (NULL != (lpAppCapData = m_CollapsedCapListForAllNodes.Iterate()))
  2605. {
  2606. lpAppCapData->pCapID->UnLockCapabilityIdentifierData();
  2607. }
  2608. }
  2609. /*
  2610. * GCCError AddRecord ()
  2611. *
  2612. * Public Function Description
  2613. * This member function is responsible for inserting a new application
  2614. * record into the Roster. This routine will return a failure if the
  2615. * application record already exist.
  2616. *
  2617. * Caveats
  2618. * Note that it is possible for a roster record (not application record)
  2619. * to already exist at this node if this is the second application
  2620. * entity to enroll at this node.
  2621. */
  2622. GCCError CAppRoster::
  2623. AddRecord(GCCEnrollRequest *pReq, GCCNodeID nid, GCCEntityID eid)
  2624. {
  2625. GCCError rc = GCC_NO_ERROR;
  2626. APP_NODE_RECORD *node_record;
  2627. APP_RECORD *pAppRecord;
  2628. CAppCapItemList *pAppCapItemList;
  2629. DebugEntry(CAppRoster::AddRecord);
  2630. if (m_fPduIsFlushed)
  2631. {
  2632. FreeRosterUpdateIndicationPDU ();
  2633. m_fPduIsFlushed = FALSE;
  2634. }
  2635. /*
  2636. * First create a roster entry for this user ID if one does not exists.
  2637. */
  2638. if (NULL == (node_record = m_NodeRecordList2.Find(nid)))
  2639. {
  2640. DBG_SAVE_FILE_LINE
  2641. node_record = new APP_NODE_RECORD;
  2642. if (node_record != NULL)
  2643. {
  2644. m_NodeRecordList2.Append(nid, node_record);
  2645. }
  2646. else
  2647. {
  2648. ERROR_OUT(("CAppRoster: AddRecord: Resource Error Occured"));
  2649. rc = GCC_ALLOCATION_FAILURE;
  2650. goto MyExit;
  2651. }
  2652. }
  2653. else
  2654. {
  2655. WARNING_OUT(("CAppRoster: AddRecord: Node Record is found"));
  2656. }
  2657. /*
  2658. * Check to make sure that the application record does not already exist..
  2659. */
  2660. if ((NULL != node_record->AppRecordList.Find(eid)) ||
  2661. (NULL != node_record->ListOfAppCapItemList2.Find(eid)))
  2662. {
  2663. WARNING_OUT(("AppRoster: AddRecord: Record already exists"));
  2664. rc = GCC_INVALID_PARAMETER;
  2665. goto MyExit;
  2666. }
  2667. // Next create a record entry in the roster's app_record_list.
  2668. DBG_SAVE_FILE_LINE
  2669. pAppRecord = new APP_RECORD;
  2670. if (NULL == pAppRecord)
  2671. {
  2672. ERROR_OUT(("CAppRoster: AddRecord: can't create APP_RECORD"));
  2673. rc = GCC_ALLOCATION_FAILURE;
  2674. goto MyExit;
  2675. }
  2676. /*
  2677. ** Here we must determine if an entry already exists at this
  2678. ** node. If so, only one entry can be conducting capable at a
  2679. ** node. Therefore, we set this variable based on this. We use
  2680. ** the "was_conducting_capable" variable to keep up with the
  2681. ** original state incase the conducting capable node leaves the
  2682. ** conference.
  2683. */
  2684. pAppRecord->is_conducting_capable = pReq->fConductingCapable;
  2685. APP_RECORD *p;
  2686. node_record->AppRecordList.Reset();
  2687. while (NULL != (p = node_record->AppRecordList.Iterate()))
  2688. {
  2689. if (p->is_conducting_capable)
  2690. {
  2691. pAppRecord->is_conducting_capable = FALSE;
  2692. break;
  2693. }
  2694. }
  2695. pAppRecord->was_conducting_capable = pReq->fConductingCapable;
  2696. pAppRecord->is_enrolled_actively = pReq->fEnrollActively;
  2697. pAppRecord->startup_channel_type = pReq->nStartupChannelType;
  2698. pAppRecord->application_user_id = pReq->nUserID;
  2699. if (pReq->cNonCollapsedCaps != 0)
  2700. {
  2701. rc = AddNonCollapsedCapabilities (
  2702. &pAppRecord->non_collapsed_caps_list,
  2703. pReq->cNonCollapsedCaps,
  2704. pReq->apNonCollapsedCaps);
  2705. if (GCC_NO_ERROR != rc)
  2706. {
  2707. ERROR_OUT(("CAppRoster::AddRecord: can't add non collapsed caps, rc=%u", (UINT) rc));
  2708. delete pAppRecord;
  2709. goto MyExit;
  2710. }
  2711. }
  2712. // Add the new record to the list of records at this node
  2713. node_record->AppRecordList.Append(eid, pAppRecord);
  2714. // from now on, we cannot free pAppRecord in case of error,
  2715. // because it is now in the app record list.
  2716. // Increment the instance number.
  2717. m_nInstance++;
  2718. m_fPeerEntitiesAdded = TRUE;
  2719. m_fRosterHasChanged = TRUE;
  2720. // Add an update to the PDU.
  2721. rc = BuildApplicationRecordListPDU(APP_ADD_RECORD, nid, eid);
  2722. if (GCC_NO_ERROR != rc)
  2723. {
  2724. ERROR_OUT(("CAppRoster::AddRecord: can't build app record list, rc=%u", (UINT) rc));
  2725. goto MyExit;
  2726. }
  2727. if (pReq->cCollapsedCaps != 0)
  2728. {
  2729. /*
  2730. ** Create a new capabilities list and insert it into the roster
  2731. ** record list of capabilities.
  2732. */
  2733. DBG_SAVE_FILE_LINE
  2734. pAppCapItemList = new CAppCapItemList;
  2735. if (NULL == pAppCapItemList)
  2736. {
  2737. ERROR_OUT(("CAppRoster::AddRecord: can't create CAppCapItemList"));
  2738. rc = GCC_ALLOCATION_FAILURE;
  2739. goto MyExit;
  2740. }
  2741. rc = AddCollapsableCapabilities(pAppCapItemList,
  2742. pReq->cCollapsedCaps,
  2743. pReq->apCollapsedCaps);
  2744. if (GCC_NO_ERROR != rc)
  2745. {
  2746. ERROR_OUT(("CAppRoster::AddRecord: can't add collapsable caps, rc=%u", (UINT) rc));
  2747. delete pAppCapItemList;
  2748. goto MyExit;
  2749. }
  2750. // Add list of capabilities to list at this node
  2751. node_record->ListOfAppCapItemList2.Append(eid, pAppCapItemList);
  2752. m_fCapabilitiesHaveChanged = TRUE;
  2753. // from now on, we cannot free pAppCapItemList in case of error,
  2754. // because it is now in the app cap item list
  2755. // Rebuild the collapsed capabilities list.
  2756. MakeCollapsedCapabilitiesList();
  2757. // Build the capabilities refresh portion of the PDU.
  2758. rc = BuildSetOfCapabilityRefreshesPDU();
  2759. if (GCC_NO_ERROR != rc)
  2760. {
  2761. ERROR_OUT(("CAppRoster::AddRecord: can't build set of cap refresh, rc=%u", (UINT) rc));
  2762. goto MyExit;
  2763. }
  2764. }
  2765. MyExit:
  2766. DebugExitINT(CAppRoster::AddRecord, rc);
  2767. return rc;
  2768. }
  2769. /*
  2770. * GCCError AddCollapsableCapabilities ()
  2771. *
  2772. * Private Function Description
  2773. * This routine takes API collapsed capabilities list data passed in
  2774. * through a local request and converts it to internal collapsed
  2775. * capabillities.
  2776. *
  2777. * Formal Parameters
  2778. * pAppCapItemList - (o) Pointer to internal capabilites list
  2779. * to fill in.
  2780. * number_of_capabilities - (i) Number of capabilities in the source
  2781. * list.
  2782. * capabilities_list - (i) Pointer to source capabilities list.
  2783. *
  2784. * Return Value
  2785. * GCC_NO_ERROR - No error occured.
  2786. * GCC_ALLOCATION_FAILURE - A resource error occured.
  2787. *
  2788. * Side Effects
  2789. * The collapsed capabilities will be recalculated at this node after
  2790. * all the new caps are added.
  2791. *
  2792. * Caveats
  2793. * none
  2794. */
  2795. GCCError CAppRoster::AddCollapsableCapabilities (
  2796. CAppCapItemList *pAppCapItemList,
  2797. UINT number_of_capabilities,
  2798. PGCCApplicationCapability *capabilities_list)
  2799. {
  2800. GCCError rc = GCC_NO_ERROR;
  2801. APP_CAP_ITEM *pAppCapItem;
  2802. UINT i;
  2803. BOOL capability_already_exists;
  2804. DebugEntry(CAppRoster::AddCollapsableCapabilities);
  2805. for (i = 0; i < number_of_capabilities; i++)
  2806. {
  2807. DBG_SAVE_FILE_LINE
  2808. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType)
  2809. capabilities_list[i]->capability_class.eType);
  2810. if (pAppCapItem != NULL)
  2811. {
  2812. DBG_SAVE_FILE_LINE
  2813. pAppCapItem->pCapID = new CCapIDContainer(&capabilities_list[i]->capability_id, &rc);
  2814. if ((pAppCapItem->pCapID != NULL) && (rc == GCC_NO_ERROR))
  2815. {
  2816. APP_CAP_ITEM *lpAppCapData;
  2817. /*
  2818. ** Here we check to make sure that this capability id does
  2819. ** not alreay exists in the list.
  2820. */
  2821. capability_already_exists = FALSE;
  2822. pAppCapItemList->Reset();
  2823. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  2824. {
  2825. if (*lpAppCapData->pCapID == *pAppCapItem->pCapID)
  2826. {
  2827. capability_already_exists = TRUE;
  2828. delete pAppCapItem;
  2829. break;
  2830. }
  2831. }
  2832. if (capability_already_exists == FALSE)
  2833. {
  2834. if (capabilities_list[i]->capability_class.eType ==
  2835. GCC_UNSIGNED_MINIMUM_CAPABILITY)
  2836. {
  2837. pAppCapItem->nUnsignedMinimum =
  2838. capabilities_list[i]->capability_class.nMinOrMax;
  2839. }
  2840. else if (capabilities_list[i]->capability_class.eType
  2841. == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  2842. {
  2843. pAppCapItem->nUnsignedMaximum = capabilities_list[i]->capability_class.nMinOrMax;
  2844. }
  2845. // Since we have yet to collapse the capabilities set to 1
  2846. pAppCapItem->cEntries = 1;
  2847. // Add this capability to the list
  2848. pAppCapItemList->Append(pAppCapItem);
  2849. }
  2850. }
  2851. else if (pAppCapItem->pCapID == NULL)
  2852. {
  2853. rc = GCC_ALLOCATION_FAILURE;
  2854. goto MyExit;
  2855. }
  2856. else
  2857. {
  2858. goto MyExit;
  2859. }
  2860. }
  2861. else
  2862. {
  2863. rc = GCC_ALLOCATION_FAILURE;
  2864. goto MyExit;
  2865. }
  2866. }
  2867. MyExit:
  2868. if (GCC_NO_ERROR != rc)
  2869. {
  2870. delete pAppCapItem;
  2871. }
  2872. return rc;
  2873. }
  2874. /*
  2875. * GCCError AddNonCollapsedCapabilities ()
  2876. *
  2877. * Private Function Description
  2878. * This routine takes API non-collapsed capabilities list data passed in
  2879. * through a local request and converts it to internal non-collapsed
  2880. * capabillities.
  2881. *
  2882. * Formal Parameters
  2883. * pAppCapItemList - (o) Pointer to internal non-collapsed
  2884. * capabilites list to fill in.
  2885. * number_of_capabilities - (i) Number of non-collapsed capabilities in
  2886. * the source list.
  2887. * capabilities_list - (i) Pointer to source non-collapsed
  2888. * capabilities list.
  2889. *
  2890. * Return Value
  2891. * GCC_NO_ERROR - No error occured.
  2892. * GCC_INVALID_NON_COLLAPSED_CAP - Invalid non-collapsed capability.
  2893. * GCC_ALLOCATION_FAILURE - A resource error occured.
  2894. *
  2895. * Side Effects
  2896. * none
  2897. *
  2898. * Caveats
  2899. * none
  2900. */
  2901. GCCError CAppRoster::AddNonCollapsedCapabilities (
  2902. CAppCapItemList *pAppCapItemList,
  2903. UINT number_of_capabilities,
  2904. PGCCNonCollapsingCapability *capabilities_list)
  2905. {
  2906. GCCError rc = GCC_NO_ERROR;
  2907. APP_CAP_ITEM *pAppCapItem = NULL;
  2908. UINT i;
  2909. DebugEntry(CAppRoster::AddNonCollapsedCapabilities);
  2910. for (i = 0; i < number_of_capabilities; i++)
  2911. {
  2912. //
  2913. // LONCHANC: Cap type is not set here.
  2914. // for now, it is zero.
  2915. //
  2916. DBG_SAVE_FILE_LINE
  2917. pAppCapItem = new APP_CAP_ITEM((GCCCapabilityType) 0);
  2918. if (pAppCapItem != NULL)
  2919. {
  2920. DBG_SAVE_FILE_LINE
  2921. pAppCapItem->pCapID = new CCapIDContainer(&capabilities_list[i]->capability_id, &rc);
  2922. if (pAppCapItem->pCapID != NULL)
  2923. {
  2924. if (capabilities_list[i]->application_data != NULL)
  2925. {
  2926. if (NULL == (pAppCapItem->poszAppData = ::My_strdupO2(
  2927. capabilities_list[i]->application_data->value,
  2928. capabilities_list[i]->application_data->length)))
  2929. {
  2930. rc = GCC_ALLOCATION_FAILURE;
  2931. goto MyExit;
  2932. }
  2933. else if (pAppCapItem->poszAppData->length > MAXIMUM_APPLICATION_DATA_LENGTH)
  2934. {
  2935. rc = GCC_INVALID_NON_COLLAPSED_CAP;
  2936. goto MyExit;
  2937. }
  2938. }
  2939. // Add this capability to the list if no errors
  2940. if( !pAppCapItemList->Append(pAppCapItem) )
  2941. {
  2942. rc = GCC_ALLOCATION_FAILURE;
  2943. goto MyExit;
  2944. }
  2945. }
  2946. else
  2947. {
  2948. rc = GCC_ALLOCATION_FAILURE;
  2949. goto MyExit;
  2950. }
  2951. }
  2952. else
  2953. {
  2954. rc = GCC_ALLOCATION_FAILURE;
  2955. goto MyExit;
  2956. }
  2957. }
  2958. MyExit:
  2959. if (GCC_NO_ERROR != rc)
  2960. {
  2961. if(pAppCapItem != NULL)
  2962. {
  2963. delete pAppCapItem;
  2964. }
  2965. }
  2966. return rc;
  2967. }
  2968. /*
  2969. * GCCError RemoveRecord ()
  2970. *
  2971. * Public Function Description
  2972. * This member function completely removes the specified record from the
  2973. * application roster. This includes any capabilities associated with
  2974. * this record. It also takes care of keeping the Instance number and
  2975. * added and removed flags up to date.
  2976. */
  2977. GCCError CAppRoster::RemoveRecord(GCCNodeID nid, GCCEntityID eid)
  2978. {
  2979. GCCError rc;
  2980. APP_RECORD *pAppRecord;
  2981. APP_NODE_RECORD *node_record;
  2982. DebugEntry(CAppRoster::RemoveRecord);
  2983. if (m_fPduIsFlushed)
  2984. {
  2985. FreeRosterUpdateIndicationPDU ();
  2986. m_fPduIsFlushed = FALSE;
  2987. }
  2988. // First see if the record is contained in the Roster_Record_List.
  2989. if (NULL == (node_record = m_NodeRecordList2.Find(nid)))
  2990. {
  2991. TRACE_OUT(("CAppRoster::RemoveRecord: can't find node record, nid=%u", (UINT) nid));
  2992. rc = GCC_INVALID_PARAMETER;
  2993. goto MyExit;
  2994. }
  2995. if (NULL == (pAppRecord = node_record->AppRecordList.Find(eid)))
  2996. {
  2997. TRACE_OUT(("CAppRoster::RemoveRecord: can't find app record, eid=%u", (UINT) eid));
  2998. rc = GCC_INVALID_PARAMETER;
  2999. goto MyExit;
  3000. }
  3001. /*
  3002. ** Here we must determine if any of the remaining APEs at this
  3003. ** node should become conducting capable based on their role
  3004. ** at the time they enrolled. We only do this if the record
  3005. ** that is being deleted was conducting capabile.
  3006. */
  3007. if (pAppRecord->is_conducting_capable)
  3008. {
  3009. APP_RECORD *p;
  3010. EntityID eid2;
  3011. node_record->AppRecordList.Reset();
  3012. while (NULL != (p = node_record->AppRecordList.Iterate(&eid2)))
  3013. {
  3014. /*
  3015. ** Here we only deal with record entries other than the
  3016. ** one being removed.
  3017. */
  3018. if (eid2 != eid)
  3019. {
  3020. if (p->was_conducting_capable)
  3021. {
  3022. p->is_conducting_capable = TRUE;
  3023. /*
  3024. ** Set up the update PDU for this conducting
  3025. ** capable change.
  3026. */
  3027. rc = BuildApplicationRecordListPDU(APP_REPLACE_RECORD, nid, eid2);
  3028. if (GCC_NO_ERROR != rc)
  3029. {
  3030. ERROR_OUT(("CAppRoster::RemoveRecord: can't build app record list, rc=%u", (UINT) rc));
  3031. goto MyExit;
  3032. }
  3033. break;
  3034. }
  3035. }
  3036. }
  3037. }
  3038. // Now delete the record
  3039. rc = DeleteRecord(nid, eid, TRUE);
  3040. if (GCC_NO_ERROR != rc)
  3041. {
  3042. WARNING_OUT(("CAppRoster::RemoveRecord: can't delete record, rc=%u", (UINT) rc));
  3043. goto MyExit;
  3044. }
  3045. // Increment the instance number.
  3046. m_nInstance++;
  3047. m_fPeerEntitiesRemoved = TRUE;
  3048. m_fRosterHasChanged = TRUE;
  3049. // Add an update to the PDU.
  3050. rc = BuildApplicationRecordListPDU(APP_DELETE_RECORD, nid, eid);
  3051. if (GCC_NO_ERROR != rc)
  3052. {
  3053. ERROR_OUT(("CAppRoster::RemoveRecord: can't build app record list, rc=%u", (UINT) rc));
  3054. goto MyExit;
  3055. }
  3056. /*
  3057. ** If the capabilities changed during the above processing
  3058. ** we must create a new collapsed capabilities list and
  3059. ** build a new capability refresh PDU.
  3060. */
  3061. if (m_fCapabilitiesHaveChanged)
  3062. {
  3063. MakeCollapsedCapabilitiesList();
  3064. rc = BuildSetOfCapabilityRefreshesPDU();
  3065. if (GCC_NO_ERROR != rc)
  3066. {
  3067. ERROR_OUT(("CAppRoster::RemoveRecord: can't build set of cap refreshes, rc=%u", (UINT) rc));
  3068. goto MyExit;
  3069. }
  3070. }
  3071. MyExit:
  3072. DebugExitINT(CAppRoster::RemoveRecord, rc);
  3073. return rc;
  3074. }
  3075. /*
  3076. * GCCError ReplaceRecord ()
  3077. *
  3078. * Public Function Description
  3079. * This routine completely replaces the specified record's parameters
  3080. * with the new parameters passed in. This includes the capabilities.
  3081. */
  3082. GCCError CAppRoster::
  3083. ReplaceRecord(GCCEnrollRequest *pReq, GCCNodeID nid, GCCEntityID eid)
  3084. {
  3085. GCCError rc = GCC_NO_ERROR;
  3086. BOOL capable_node_found;
  3087. APP_NODE_RECORD *node_record;
  3088. APP_RECORD *pAppRecord, *p;
  3089. APP_CAP_ITEM *lpAppCapData;
  3090. CAppCapItemList NonCollCapsList;
  3091. DebugEntry(CAppRoster::ReplaceRecord);
  3092. if (m_fPduIsFlushed)
  3093. {
  3094. FreeRosterUpdateIndicationPDU ();
  3095. m_fPduIsFlushed = FALSE;
  3096. }
  3097. /*
  3098. ** First determine if the node record does actually already exists. If not
  3099. ** we return an error here.
  3100. */
  3101. if (NULL == (node_record = m_NodeRecordList2.Find(nid)))
  3102. {
  3103. ERROR_OUT(("CAppRoster::ReplaceRecord: can't find the node record for nid=%u", (UINT) nid));
  3104. rc = GCC_INVALID_PARAMETER;
  3105. goto MyExit;
  3106. }
  3107. // make sure the app record exists. if not, return an error
  3108. if (NULL == (pAppRecord = node_record->AppRecordList.Find(eid)))
  3109. {
  3110. ERROR_OUT(("CAppRoster::ReplaceRecord: can't find the app record for eid=%u", (UINT) eid));
  3111. rc = GCC_INVALID_PARAMETER;
  3112. goto MyExit;
  3113. }
  3114. /*
  3115. ** First check to make sure that we can build the new record before
  3116. ** replacing the old record. The only entry we need to wory about
  3117. ** here are the non-collapsing capabilities.
  3118. */
  3119. if (pReq->cNonCollapsedCaps != 0)
  3120. {
  3121. rc = AddNonCollapsedCapabilities(&NonCollCapsList,
  3122. pReq->cNonCollapsedCaps,
  3123. pReq->apNonCollapsedCaps);
  3124. if (GCC_NO_ERROR != rc)
  3125. {
  3126. ERROR_OUT(("CAppRoster::ReplaceRecord: can't add non collapsed caps, rc=%u", (UINT) rc));
  3127. goto MyExit;
  3128. }
  3129. }
  3130. // Now replace the record entries.
  3131. pAppRecord->is_enrolled_actively = pReq->fEnrollActively;
  3132. pAppRecord->was_conducting_capable = pReq->fConductingCapable;
  3133. pAppRecord->startup_channel_type = pReq->nStartupChannelType;
  3134. pAppRecord->application_user_id = pReq->nUserID;
  3135. /*
  3136. ** If the is conducting capable flag that was passed in was set
  3137. ** to FALSE we can go ahead and set the internal is conducting
  3138. ** capable flag to FALSE regardless of what the previous
  3139. ** setting was. If it was passed in TRUE we leave the previous
  3140. ** setting alone.
  3141. */
  3142. if (pAppRecord->was_conducting_capable == FALSE)
  3143. {
  3144. pAppRecord->is_conducting_capable = FALSE;
  3145. }
  3146. /*
  3147. ** Here we delete the old non-collapsed capabilites and then
  3148. ** add the new ones.
  3149. */
  3150. if (! pAppRecord->non_collapsed_caps_list.IsEmpty())
  3151. {
  3152. pAppRecord->non_collapsed_caps_list.DeleteList();
  3153. pAppRecord->non_collapsed_caps_list.Clear();
  3154. }
  3155. // Copy the new non collapsed capabilities if any exists.
  3156. if (pReq->cNonCollapsedCaps != 0)
  3157. {
  3158. while (NULL != (lpAppCapData = NonCollCapsList.Get()))
  3159. {
  3160. pAppRecord->non_collapsed_caps_list.Append(lpAppCapData);
  3161. }
  3162. }
  3163. //
  3164. // handling collapsing cap list
  3165. //
  3166. m_nInstance++;
  3167. m_fRosterHasChanged = TRUE;
  3168. rc = BuildApplicationRecordListPDU(APP_REPLACE_RECORD, nid, eid);
  3169. if (rc != GCC_NO_ERROR)
  3170. {
  3171. ERROR_OUT(("CAppRoster::ReplaceRecord: can't build app record list, rc=%u", (UINT) rc));
  3172. goto MyExit;
  3173. }
  3174. /*
  3175. ** Here we must make sure that at least one of the APEs is
  3176. ** Conducting Capable. We do this by first scanning the
  3177. ** list to see if anyone is it. If one is not found, the
  3178. ** same list is scanned for an APE that "was" previously
  3179. ** capable. The first one found that was previously
  3180. ** capable is now it. If none are found then no one is
  3181. ** capable.
  3182. */
  3183. capable_node_found = FALSE;
  3184. node_record->AppRecordList.Reset();
  3185. while (NULL != (p = node_record->AppRecordList.Iterate()))
  3186. {
  3187. if (p->is_conducting_capable)
  3188. {
  3189. capable_node_found = TRUE;
  3190. break;
  3191. }
  3192. }
  3193. if (! capable_node_found)
  3194. {
  3195. GCCEntityID eid2;
  3196. node_record->AppRecordList.Reset();
  3197. while (NULL != (p = node_record->AppRecordList.Iterate(&eid2)))
  3198. {
  3199. if (p->was_conducting_capable)
  3200. {
  3201. p->is_conducting_capable = TRUE;
  3202. /*
  3203. ** Set up the update PDU for this conducting
  3204. ** capable change.
  3205. */
  3206. rc = BuildApplicationRecordListPDU(APP_REPLACE_RECORD, nid, eid2);
  3207. if (GCC_NO_ERROR != rc)
  3208. {
  3209. ERROR_OUT(("CAppRoster::ReplaceRecord: can't build app record list, rc=%u", (UINT) rc));
  3210. goto MyExit;
  3211. }
  3212. break;
  3213. }
  3214. }
  3215. }
  3216. /*
  3217. ** This section of code deals with the collapsable capabilities.
  3218. ** First we determine if the capabilities passed in are different
  3219. ** from the previously existing capabilities. If so, we must
  3220. ** delete the old set of caps and add back in the new ones.
  3221. */
  3222. TRACE_OUT(("ApplicatonRoster:ReplaceRecord: Check to see if caps match"));
  3223. if (! DoCapabilitiesListMatch(nid, eid, pReq->cCollapsedCaps, pReq->apCollapsedCaps))
  3224. {
  3225. CAppCapItemList *pCollCapsList, *q;
  3226. TRACE_OUT(("ApplicatonRoster:ReplaceRecord: Capabilities match"));
  3227. m_fCapabilitiesHaveChanged = TRUE;
  3228. /*
  3229. ** Delete the old capabilities list since it does not match the
  3230. ** new capabilities list.
  3231. */
  3232. if (NULL != (q = node_record->ListOfAppCapItemList2.Find(eid)))
  3233. {
  3234. q->DeleteList();
  3235. delete q;
  3236. node_record->ListOfAppCapItemList2.Remove(eid);
  3237. }
  3238. /*
  3239. ** Here we add back in the new capabilities. Create a new
  3240. ** capabilities list and insert it into the roster record list of
  3241. ** capabilities.
  3242. */
  3243. if (pReq->cCollapsedCaps != 0)
  3244. {
  3245. DBG_SAVE_FILE_LINE
  3246. pCollCapsList = new CAppCapItemList;
  3247. if (NULL == pCollCapsList)
  3248. {
  3249. ERROR_OUT(("CAppRoster::ReplaceRecord: can't create CAppCapItemList"));
  3250. rc = GCC_ALLOCATION_FAILURE;
  3251. goto MyExit;
  3252. }
  3253. rc = AddCollapsableCapabilities(pCollCapsList,
  3254. pReq->cCollapsedCaps,
  3255. pReq->apCollapsedCaps);
  3256. if (rc != GCC_NO_ERROR)
  3257. {
  3258. ERROR_OUT(("CAppRoster::ReplaceRecord: can't add collapsed caps, rc=%u", (UINT) rc));
  3259. delete pCollCapsList;
  3260. goto MyExit;
  3261. }
  3262. // Add list of capabilities to list at this node
  3263. node_record->ListOfAppCapItemList2.Append(eid, pCollCapsList);
  3264. }
  3265. // Rebuild the collapsed capabilities list.
  3266. MakeCollapsedCapabilitiesList();
  3267. // Build the capabilities refresh portion of the PDU.
  3268. rc = BuildSetOfCapabilityRefreshesPDU();
  3269. if (GCC_NO_ERROR != rc)
  3270. {
  3271. ERROR_OUT(("CAppRoster::ReplaceRecord: can't build set of cap refreshes, rc=%u", (UINT) rc));
  3272. goto MyExit;
  3273. }
  3274. }
  3275. else
  3276. {
  3277. TRACE_OUT(("CAppRoster:ReplaceRecord:Capabilities match with previous record"));
  3278. }
  3279. MyExit:
  3280. DebugExitINT(CAppRoster::ReplaceRecord, rc);
  3281. return rc;
  3282. }
  3283. /*
  3284. * GCCError DeleteRecord ()
  3285. *
  3286. * Private Function Description
  3287. * This member function completely removes the specified record from the
  3288. * application roster. This includes any capabilities associated with
  3289. * this record.
  3290. *
  3291. * Formal Parameters
  3292. * node_id - (i) Node ID of record to delete.
  3293. * entity_id - (i) Entity ID of record to delete.
  3294. * clear_empty_records - (i) This flag indicates whether or not to
  3295. * clear out the node record if it no-longer
  3296. * holds data. When replacing a record we
  3297. * do NOT want to do this so that we don't
  3298. * lose any "unchanged" capabilities.
  3299. *
  3300. * Return Value
  3301. * GCC_NO_ERROR - No error occured.
  3302. * GCC_INVALID_PARAMETER - Record specified to delete does not exists.
  3303. *
  3304. * Side Effects
  3305. * none
  3306. *
  3307. * Caveats
  3308. * none
  3309. */
  3310. GCCError CAppRoster::DeleteRecord(UserID node_id,
  3311. EntityID entity_id,
  3312. BOOL clear_empty_records)
  3313. {
  3314. GCCError rc = GCC_NO_ERROR;
  3315. APP_RECORD *application_record;
  3316. CAppCapItemList *pAppCapItemList;
  3317. CAppRecordList2 *pAppRecordList;
  3318. UserID node_to_check;
  3319. APP_NODE_RECORD *node_record;
  3320. //APP_CAP_ITEM *lpAppCapData;
  3321. APP_NODE_RECORD *lpAppNodeRec;
  3322. DebugEntry(CAppRoster::DeleteRecord);
  3323. // First see if the record is contained in the Roster_Record_List.
  3324. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  3325. {
  3326. // Set up node id to check at bottom for empty record
  3327. node_to_check = node_id;
  3328. // Delete the application record.
  3329. if (NULL != (application_record = node_record->AppRecordList.Find(entity_id)))
  3330. {
  3331. TRACE_OUT(("AppRoster: DeleteRecord: Delete AppRecord"));
  3332. // Delete the data associated with the application record
  3333. DeleteApplicationRecordData (application_record);
  3334. // Remove record from application record list
  3335. node_record->AppRecordList.Remove(entity_id);
  3336. /*
  3337. ** Delete the associated capabilities list. Note that this list
  3338. ** only exists for records of local nodes. The collapsed
  3339. ** capabilities list at the root node record take create of
  3340. ** subordniate nodes and is deleted some where else.
  3341. */
  3342. if (NULL != (pAppCapItemList = node_record->ListOfAppCapItemList2.Find(entity_id)))
  3343. {
  3344. m_fCapabilitiesHaveChanged = TRUE;
  3345. pAppCapItemList->DeleteList();
  3346. TRACE_OUT(("AppRoster: DeleteRecord: Delete Capabilities"));
  3347. delete pAppCapItemList;
  3348. node_record->ListOfAppCapItemList2.Remove(entity_id);
  3349. }
  3350. }
  3351. else
  3352. {
  3353. WARNING_OUT(("AppRoster: DeleteRecord: can't find this eid=%u", (UINT) entity_id));
  3354. rc = GCC_INVALID_PARAMETER;
  3355. }
  3356. }
  3357. else
  3358. {
  3359. UserID uid2;
  3360. /*
  3361. ** Here we search through all the sub node list trying to find the
  3362. ** record. Set return value to record does not exist here and
  3363. ** after the record is found set it back to no error.
  3364. */
  3365. rc = GCC_INVALID_PARAMETER;
  3366. m_NodeRecordList2.Reset();
  3367. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate(&uid2)))
  3368. {
  3369. // Delete the sub_node list if it exists
  3370. if (NULL != (pAppRecordList = lpAppNodeRec->SubNodeList2.Find(node_id)))
  3371. {
  3372. // Delete the app_record_list entry.
  3373. if (NULL != (application_record = pAppRecordList->Find(entity_id)))
  3374. {
  3375. // Delete the data associated with the application record
  3376. DeleteApplicationRecordData (application_record);
  3377. pAppRecordList->Remove(entity_id);
  3378. if (pAppRecordList->IsEmpty())
  3379. {
  3380. TRACE_OUT(("AppRoster: DeleteRecord: Deleting Sub-Node"));
  3381. delete pAppRecordList;
  3382. lpAppNodeRec->SubNodeList2.Remove(node_id);
  3383. }
  3384. // Set up node id to check at bottom for empty record
  3385. node_to_check = uid2;
  3386. rc = GCC_NO_ERROR;
  3387. }
  3388. break;
  3389. }
  3390. }
  3391. }
  3392. /*
  3393. ** If the record list is empty and the sub node list is empty
  3394. ** we can remove this entire record from the application roster.
  3395. ** If the record list is empty but the sub node list is not we
  3396. ** must keep the roster record around to maintain the sub node list.
  3397. */
  3398. if ((rc == GCC_NO_ERROR) && clear_empty_records)
  3399. {
  3400. if (NULL != (node_record = m_NodeRecordList2.Find(node_to_check)) &&
  3401. node_record->AppRecordList.IsEmpty() &&
  3402. node_record->SubNodeList2.IsEmpty())
  3403. {
  3404. if (! node_record->CollapsedCapList.IsEmpty())
  3405. {
  3406. m_fCapabilitiesHaveChanged = TRUE;
  3407. // Delete the collapsed capabilities list.
  3408. node_record->CollapsedCapList.DeleteList();
  3409. }
  3410. delete node_record;
  3411. m_NodeRecordList2.Remove(node_to_check);
  3412. }
  3413. }
  3414. return rc;
  3415. }
  3416. /*
  3417. * GCCError RemoveUserReference ()
  3418. *
  3419. * Public Function Description
  3420. * This routine will only remove the application record and its sub nodes
  3421. * if the node being removed is directly connected to this node.
  3422. * Otherwise, we wait to receive the update from either the sub node or
  3423. * the Top Provider.
  3424. */
  3425. GCCError CAppRoster::RemoveUserReference(UserID detached_node)
  3426. {
  3427. GCCError rc = GCC_NO_ERROR;
  3428. DebugEntry(CAppRoster::RemoveUserReference);
  3429. // Clear out any previously allocated PDUs
  3430. if (m_fPduIsFlushed)
  3431. {
  3432. FreeRosterUpdateIndicationPDU ();
  3433. m_fPduIsFlushed = FALSE;
  3434. }
  3435. /*
  3436. ** First Try to remove the node record if one exist. If it does not
  3437. ** exist we return immediately. If it does exists we will build the
  3438. ** appropriate PDU and update the instance variables.
  3439. */
  3440. rc = ClearNodeRecordFromList (detached_node);
  3441. if (rc == GCC_NO_ERROR)
  3442. {
  3443. // Increment the instance number.
  3444. m_nInstance++;
  3445. m_fPeerEntitiesRemoved = TRUE;
  3446. m_fRosterHasChanged = TRUE;
  3447. /*
  3448. ** Go ahead and do the full refresh here since we do not know the
  3449. ** specifics about who was deleted.
  3450. */
  3451. rc = BuildApplicationRecordListPDU(APP_FULL_REFRESH, 0, 0);
  3452. if (m_fCapabilitiesHaveChanged && (rc == GCC_NO_ERROR))
  3453. {
  3454. // Create a new collapsed capabilities list.
  3455. MakeCollapsedCapabilitiesList();
  3456. // Build the capabilities refresh portion of the PDU.
  3457. rc = BuildSetOfCapabilityRefreshesPDU ();
  3458. }
  3459. }
  3460. return rc;
  3461. }
  3462. /*
  3463. * void DeleteApplicationRecordData ()
  3464. *
  3465. * Private Function Description
  3466. * This routine internal application record data.
  3467. *
  3468. * Formal Parameters
  3469. * application_record - Pointer to the application record data to
  3470. * delete.
  3471. *
  3472. * Return Value
  3473. * none
  3474. *
  3475. * Side Effects
  3476. * none
  3477. *
  3478. * Caveats
  3479. * none
  3480. */
  3481. void CAppRoster::DeleteApplicationRecordData(APP_RECORD *pAppRec)
  3482. {
  3483. pAppRec->non_collapsed_caps_list.DeleteList();
  3484. delete pAppRec;
  3485. }
  3486. /*
  3487. * USHORT GetNumberOfApplicationRecords ()
  3488. *
  3489. * Public Function Description
  3490. * This routine returns the total number of application records that exist
  3491. * in this application roster.
  3492. *
  3493. * Formal Parameters
  3494. * none
  3495. *
  3496. * Return Value
  3497. * Number of application roster records
  3498. *
  3499. * Side Effects
  3500. * none
  3501. *
  3502. * Caveats
  3503. * none
  3504. */
  3505. UINT CAppRoster::GetNumberOfApplicationRecords(void)
  3506. {
  3507. UINT cRecords = 0;
  3508. APP_NODE_RECORD *lpAppNodeRec;
  3509. CAppRecordList2 *lpAppRecDataList;
  3510. DebugEntry(CAppRoster::GetNumberOfApplicationRecords);
  3511. /*
  3512. ** First calculate the total number of records. This count is used to
  3513. ** allocate the space necessary to hold the records. Note that we must
  3514. ** count both the application record list and the sub-node list.
  3515. */
  3516. m_NodeRecordList2.Reset();
  3517. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  3518. {
  3519. // Add the application records at this node to the count.
  3520. cRecords += lpAppNodeRec->AppRecordList.GetCount();
  3521. // Next count the sub node entries.
  3522. if (! lpAppNodeRec->SubNodeList2.IsEmpty())
  3523. {
  3524. lpAppNodeRec->SubNodeList2.Reset();
  3525. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  3526. {
  3527. cRecords += lpAppRecDataList->GetCount();
  3528. }
  3529. }
  3530. }
  3531. return cRecords;
  3532. }
  3533. /*
  3534. * PGCCSessionKey GetSessionKey ()
  3535. *
  3536. * Public Function Description
  3537. * This routine returns the session key associated with this
  3538. * application roster.
  3539. *
  3540. * Formal Parameters
  3541. * none
  3542. *
  3543. * Return Value
  3544. * PGCCSessionKey - the application key associated with this roster
  3545. *
  3546. * Side Effects
  3547. * none
  3548. *
  3549. * Caveats
  3550. * none
  3551. */
  3552. /*
  3553. * void ResetApplicationRoster ()
  3554. *
  3555. * Public Function Description
  3556. * This routine takes care of resetting all the internal flags that are
  3557. * used to convey the current state of the application roster. Should be
  3558. * called after the roster is flushed and any roster update messages have
  3559. * been delivered (after a change to the roster occurs).
  3560. */
  3561. void CAppRoster::ResetApplicationRoster(void)
  3562. {
  3563. m_fCapabilitiesHaveChanged = FALSE;
  3564. m_fRosterHasChanged = FALSE;
  3565. m_fPeerEntitiesRemoved = FALSE;
  3566. m_fPeerEntitiesAdded = FALSE;
  3567. }
  3568. /*
  3569. * BOOL DoesRecordExist ()
  3570. *
  3571. * Public Function Description
  3572. * This routine informs the caller if the specified application record
  3573. * exists or not.
  3574. */
  3575. BOOL CAppRoster::DoesRecordExist(UserID node_id, EntityID entity_id)
  3576. {
  3577. BOOL rc = FALSE;
  3578. APP_NODE_RECORD *node_record;
  3579. CAppRecordList2 *record_list;
  3580. DebugEntry(CAppRoster::DoesRecordExist);
  3581. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  3582. {
  3583. if (node_record->AppRecordList.Find(entity_id))
  3584. rc = TRUE;
  3585. }
  3586. else
  3587. {
  3588. m_NodeRecordList2.Reset();
  3589. while (NULL != (node_record = m_NodeRecordList2.Iterate()))
  3590. {
  3591. if (NULL != (record_list = node_record->SubNodeList2.Find(node_id)))
  3592. {
  3593. if (record_list->Find(entity_id))
  3594. rc = TRUE;
  3595. }
  3596. }
  3597. }
  3598. return rc;
  3599. }
  3600. /*
  3601. * BOOL HasRosterChanged ()
  3602. *
  3603. * Public Function Description
  3604. * This routine informs the caller if the roster has changed since the
  3605. * last time it was reset.
  3606. */
  3607. /*
  3608. * GCCError ClearNodeRecordFromList ()
  3609. *
  3610. * Private Function Description
  3611. * This routine clears out all the application records that exists at
  3612. * the specified node or below it in the connection hierarchy.
  3613. *
  3614. * Formal Parameters
  3615. * node_id - Node ID of node to clear from Node Record list
  3616. *
  3617. * Return Value
  3618. * GCC_NO_ERROR - No error occured
  3619. * GCC_INVALID_PARAMETER - The specified node ID is not associated
  3620. * with any records.
  3621. *
  3622. * Side Effects
  3623. * none
  3624. *
  3625. * Caveats
  3626. * none
  3627. */
  3628. GCCError CAppRoster::ClearNodeRecordFromList( UserID node_id)
  3629. {
  3630. GCCError rc = GCC_NO_ERROR;
  3631. APP_NODE_RECORD *node_record;
  3632. APP_RECORD *lpAppRecData;
  3633. //APP_CAP_ITEM *lpAppCapData;
  3634. CAppRecordList2 *lpAppRecDataList;
  3635. DebugEntry(CAppRoster::ClearNodeRecordFromList);
  3636. if (NULL != (node_record = m_NodeRecordList2.Find(node_id)))
  3637. {
  3638. // Delete all the app_record_list entries.
  3639. node_record->AppRecordList.Reset();
  3640. while (NULL != (lpAppRecData = node_record->AppRecordList.Iterate()))
  3641. {
  3642. DeleteApplicationRecordData (lpAppRecData);
  3643. }
  3644. /*
  3645. ** Delete the ListOfAppCapItemList2 entries. Note that this
  3646. ** list should not exists for detached nodes if the local applications
  3647. ** cleanly unenroll with GCC. This list should only exists for
  3648. ** locally enrolled APEs. We still check here just to make sure.
  3649. */
  3650. if (! node_record->ListOfAppCapItemList2.IsEmpty())
  3651. {
  3652. //CAppCapItemList *lpAppCapDataList;
  3653. m_fCapabilitiesHaveChanged = TRUE;
  3654. node_record->ListOfAppCapItemList2.DeleteList();
  3655. }
  3656. // Delete the sub_node list.
  3657. node_record->SubNodeList2.Reset();
  3658. while (NULL != (lpAppRecDataList = node_record->SubNodeList2.Iterate()))
  3659. {
  3660. // Delete all the app_record_list entries.
  3661. lpAppRecDataList->Reset();
  3662. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  3663. {
  3664. DeleteApplicationRecordData (lpAppRecData);
  3665. }
  3666. delete lpAppRecDataList;
  3667. }
  3668. // Delete the collapsed capabilities list.
  3669. if (! node_record->CollapsedCapList.IsEmpty())
  3670. {
  3671. m_fCapabilitiesHaveChanged = TRUE;
  3672. node_record->CollapsedCapList.DeleteList();
  3673. }
  3674. // Delete the rogoue wave reference to this roster record.
  3675. delete node_record;
  3676. m_NodeRecordList2.Remove(node_id);
  3677. }
  3678. else
  3679. rc = GCC_INVALID_PARAMETER;
  3680. return rc;
  3681. }
  3682. /*
  3683. * ApplicationRosterError ClearNodeRecordList ()
  3684. *
  3685. * Private Function Description
  3686. * This routine complete frees all memory associated with the roster
  3687. * record list and clears the list of all its entries.
  3688. *
  3689. * Formal Parameters
  3690. * none
  3691. *
  3692. * Return Value
  3693. * none
  3694. *
  3695. * Side Effects
  3696. * none
  3697. *
  3698. * Caveats
  3699. * Currently this routine does not handle standard identifiers.
  3700. */
  3701. void CAppRoster::ClearNodeRecordList(void)
  3702. {
  3703. APP_NODE_RECORD *lpAppNodeRec;
  3704. APP_RECORD *lpAppRecData;
  3705. CAppRecordList2 *lpAppRecDataList;
  3706. //APP_CAP_ITEM *lpAppCapData;
  3707. //CAppCapItemList *lpAppCapDataList;
  3708. DebugEntry(CAppRoster::ClearNodeRecordList);
  3709. // Delete all the records in the application roster.
  3710. m_NodeRecordList2.Reset();
  3711. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  3712. {
  3713. // First delete all the app records at this node.
  3714. lpAppNodeRec->AppRecordList.Reset();
  3715. while (NULL != (lpAppRecData = lpAppNodeRec->AppRecordList.Iterate()))
  3716. {
  3717. DeleteApplicationRecordData(lpAppRecData);
  3718. }
  3719. // Next delete all the sub node record list.
  3720. lpAppNodeRec->SubNodeList2.Reset();
  3721. while (NULL != (lpAppRecDataList = lpAppNodeRec->SubNodeList2.Iterate()))
  3722. {
  3723. lpAppRecDataList->Reset();
  3724. while (NULL != (lpAppRecData = lpAppRecDataList->Iterate()))
  3725. {
  3726. DeleteApplicationRecordData(lpAppRecData);
  3727. }
  3728. // Delete the rogue wave list holding the lists of sub nodes.
  3729. delete lpAppRecDataList;
  3730. }
  3731. // Delete the collapsed capabilities list.
  3732. lpAppNodeRec->CollapsedCapList.DeleteList();
  3733. // Delete the list of capabilities list.
  3734. lpAppNodeRec->ListOfAppCapItemList2.DeleteList();
  3735. // Now delete the node record
  3736. delete lpAppNodeRec;
  3737. }
  3738. m_NodeRecordList2.Clear();
  3739. }
  3740. /*
  3741. * GCCError MakeCollapsedCapabilitiesList ()
  3742. *
  3743. * Private Function Description
  3744. * This routine is responsible for applying the T.124 capabilities
  3745. * rules to create the collapsed capabilities list at this node.
  3746. * It iterates through all the capabilities at this node to create this
  3747. * collapsed list.
  3748. *
  3749. * Formal Parameters
  3750. * none
  3751. *
  3752. * Return Value
  3753. * GCC_NO_ERROR - On success
  3754. * GCC_ALLOCATION_FAILURE - On resource error
  3755. *
  3756. * Side Effects
  3757. * none
  3758. *
  3759. * Caveats
  3760. * Currently this routine does not handle standard identifiers.
  3761. */
  3762. GCCError CAppRoster::MakeCollapsedCapabilitiesList(void)
  3763. {
  3764. GCCError rc = GCC_NO_ERROR;
  3765. APP_CAP_ITEM *lpAppCapData;
  3766. APP_NODE_RECORD *lpAppNodeRec;
  3767. CAppCapItemList *lpAppCapDataList;
  3768. DebugEntry(CAppRoster::MakeCollapsedCapabilitiesList);
  3769. // First clear out the old capabilities list.
  3770. m_CollapsedCapListForAllNodes.DeleteList();
  3771. /*
  3772. ** We now iterate through the capabilities at each node to create the
  3773. ** new capabilities list. Note that we have to check for the collapsed
  3774. ** capabilities list at each node as well as the list of capabilities list
  3775. ** that represents all the different capabilities for each entity at a
  3776. ** node. Note that in this implementation it is not possible to have both
  3777. ** a list of capabilities list and a collapsed capabilities list in the
  3778. ** same roster record.
  3779. */
  3780. m_NodeRecordList2.Reset();
  3781. while (NULL != (lpAppNodeRec = m_NodeRecordList2.Iterate()))
  3782. {
  3783. /*
  3784. ** First check the collapsed capabilities list. If entries exists
  3785. ** then we don't have to worry about the list of list.
  3786. */
  3787. if (! lpAppNodeRec->CollapsedCapList.IsEmpty())
  3788. {
  3789. lpAppNodeRec->CollapsedCapList.Reset();
  3790. while (NULL != (lpAppCapData = lpAppNodeRec->CollapsedCapList.Iterate()))
  3791. {
  3792. rc = AddCapabilityToCollapsedList(lpAppCapData);
  3793. if (GCC_NO_ERROR != rc)
  3794. {
  3795. goto MyExit; // break;
  3796. }
  3797. }
  3798. }
  3799. else
  3800. if (! lpAppNodeRec->ListOfAppCapItemList2.IsEmpty())
  3801. {
  3802. // Here we check the list of capabilities list.
  3803. lpAppNodeRec->ListOfAppCapItemList2.Reset();
  3804. while (NULL != (lpAppCapDataList = lpAppNodeRec->ListOfAppCapItemList2.Iterate()))
  3805. {
  3806. lpAppCapDataList->Reset();
  3807. while (NULL != (lpAppCapData = lpAppCapDataList->Iterate()))
  3808. {
  3809. rc = AddCapabilityToCollapsedList(lpAppCapData);
  3810. if (GCC_NO_ERROR != rc)
  3811. {
  3812. goto MyExit;
  3813. }
  3814. }
  3815. }
  3816. }
  3817. }
  3818. ASSERT(GCC_NO_ERROR == rc);
  3819. MyExit:
  3820. return rc;
  3821. }
  3822. /*
  3823. * GCCError AddCapabilityToCollapsedList ()
  3824. *
  3825. * Private Function Description
  3826. * This is the routine that performs the rules that allow the capability
  3827. * to be collapsed into the collapsed list.
  3828. *
  3829. * Formal Parameters
  3830. * new_capability - (i) Add this capability to the collapsed list.
  3831. *
  3832. * Return Value
  3833. * GCC_NO_ERROR - On success
  3834. * GCC_ALLOCATION_FAILURE - On resource error
  3835. *
  3836. * Side Effects
  3837. * none
  3838. *
  3839. * Caveats
  3840. * none
  3841. */
  3842. GCCError CAppRoster::AddCapabilityToCollapsedList(APP_CAP_ITEM *new_capability)
  3843. {
  3844. GCCError rc = GCC_NO_ERROR;
  3845. APP_CAP_ITEM *pAppCapItem;
  3846. DebugEntry(CAppRoster::AddCapabilityToCollapsedList);
  3847. /*
  3848. ** First determine if the capability already exists in the list.
  3849. ** We must iterate through the complete list to determine if there
  3850. ** is a matching capability id.
  3851. */
  3852. m_CollapsedCapListForAllNodes.Reset();
  3853. while (NULL != (pAppCapItem = m_CollapsedCapListForAllNodes.Iterate()))
  3854. {
  3855. if (*pAppCapItem->pCapID == *new_capability->pCapID)
  3856. {
  3857. pAppCapItem->cEntries += new_capability->cEntries;
  3858. break;
  3859. }
  3860. }
  3861. if (pAppCapItem == NULL)
  3862. {
  3863. DBG_SAVE_FILE_LINE
  3864. pAppCapItem = new APP_CAP_ITEM(new_capability, &rc);
  3865. if (NULL == pAppCapItem)
  3866. {
  3867. return GCC_ALLOCATION_FAILURE;
  3868. }
  3869. if (GCC_NO_ERROR != rc)
  3870. {
  3871. delete pAppCapItem;
  3872. return rc;
  3873. }
  3874. m_CollapsedCapListForAllNodes.Append(pAppCapItem);
  3875. }
  3876. /*
  3877. ** If the unsigned minimum or unsigned maximum rule is used perform the
  3878. ** operation here.
  3879. */
  3880. ASSERT(GCC_NO_ERROR == rc);
  3881. if (new_capability->eCapType == GCC_UNSIGNED_MINIMUM_CAPABILITY)
  3882. {
  3883. if (new_capability->nUnsignedMinimum < pAppCapItem->nUnsignedMinimum)
  3884. {
  3885. pAppCapItem->nUnsignedMinimum = new_capability->nUnsignedMinimum;
  3886. }
  3887. }
  3888. else if (new_capability->eCapType == GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  3889. {
  3890. if (new_capability->nUnsignedMaximum > pAppCapItem->nUnsignedMaximum)
  3891. {
  3892. pAppCapItem->nUnsignedMaximum = new_capability->nUnsignedMaximum;
  3893. }
  3894. }
  3895. return rc;
  3896. }
  3897. /*
  3898. * BOOL DoCapabilitiesListMatch ()
  3899. *
  3900. * Private Function Description
  3901. * This routine determines if the set of capabilities that were passed in
  3902. * match the set of internal capabilities associated with the record.
  3903. *
  3904. * Formal Parameters
  3905. * node_id - (i) Node ID of record that contains the
  3906. * capabilities to check.
  3907. * entity_id - (i) Entity ID of record that contains the
  3908. * capbilities to check.
  3909. * number_of_capabilities - (i) Number of capabilities in list to check.
  3910. * capabilities_list - (i) "API" capabillities list to check
  3911. *
  3912. * Return Value
  3913. * TRUE - If capabillities list match
  3914. * FALSE - If capabillities list do NOT match
  3915. *
  3916. * Side Effects
  3917. * none
  3918. *
  3919. * Caveats
  3920. * none
  3921. */
  3922. BOOL CAppRoster::DoCapabilitiesListMatch (
  3923. UserID node_id,
  3924. EntityID entity_id,
  3925. UINT number_of_capabilities,
  3926. PGCCApplicationCapability * capabilities_list)
  3927. {
  3928. BOOL rc = FALSE;
  3929. CAppCapItemList *pAppCapItemList;
  3930. GCCError error_value;
  3931. APP_NODE_RECORD *node_record;
  3932. UINT i;
  3933. CCapIDContainer *capability_id;
  3934. DebugEntry(CAppRoster::DoCapabilitiesListMatch);
  3935. if (NULL == (node_record = m_NodeRecordList2.Find(node_id)))
  3936. return (FALSE);
  3937. if (NULL == (pAppCapItemList = node_record->ListOfAppCapItemList2.Find(entity_id)))
  3938. {
  3939. /*
  3940. ** If the record shows no capabilities and the number of passed
  3941. ** in capabilities is zero than we got a match.
  3942. */
  3943. return ((number_of_capabilities == 0) ? TRUE : FALSE);
  3944. }
  3945. else if (pAppCapItemList->GetCount() != number_of_capabilities)
  3946. {
  3947. return (FALSE);
  3948. }
  3949. /*
  3950. ** If we have gotten this far we must iterate through the entire list to
  3951. ** see if all the capabilities match.
  3952. */
  3953. for (i = 0; i < number_of_capabilities; i++)
  3954. {
  3955. /*
  3956. ** First we create a temporary ID to compare to the other
  3957. ** capability IDs.
  3958. */
  3959. DBG_SAVE_FILE_LINE
  3960. capability_id = new CCapIDContainer(&capabilities_list[i]->capability_id, &error_value);
  3961. if ((capability_id != NULL) && (error_value == GCC_NO_ERROR))
  3962. {
  3963. APP_CAP_ITEM *lpAppCapData;
  3964. // Start with the return value equal to FALSE
  3965. rc = FALSE;
  3966. /*
  3967. ** Now iterate through the complate internal capability
  3968. ** list looking for a matching capability.
  3969. */
  3970. pAppCapItemList->Reset();
  3971. while (NULL != (lpAppCapData = pAppCapItemList->Iterate()))
  3972. {
  3973. if (*capability_id == *lpAppCapData->pCapID)
  3974. {
  3975. if (lpAppCapData->eCapType == capabilities_list[i]->capability_class.eType)
  3976. {
  3977. if (capabilities_list[i]->capability_class.eType ==
  3978. GCC_UNSIGNED_MINIMUM_CAPABILITY)
  3979. {
  3980. if (capabilities_list[i]->capability_class.nMinOrMax ==
  3981. lpAppCapData->nUnsignedMinimum)
  3982. {
  3983. rc = TRUE;
  3984. }
  3985. }
  3986. else if (capabilities_list[i]->capability_class.eType ==
  3987. GCC_UNSIGNED_MAXIMUM_CAPABILITY)
  3988. {
  3989. if (capabilities_list[i]->capability_class.nMinOrMax ==
  3990. lpAppCapData->nUnsignedMaximum)
  3991. {
  3992. rc = TRUE;
  3993. }
  3994. }
  3995. else
  3996. rc = TRUE;
  3997. }
  3998. break;
  3999. }
  4000. }
  4001. // Delete the capability ID data
  4002. capability_id->Release();
  4003. if (rc == FALSE)
  4004. break;
  4005. }
  4006. else
  4007. {
  4008. if (NULL != capability_id)
  4009. {
  4010. capability_id->Release();
  4011. }
  4012. break;
  4013. }
  4014. }
  4015. return rc;
  4016. }
  4017. void CAppRosterList::DeleteList(void)
  4018. {
  4019. CAppRoster *pAppRoster;
  4020. while (NULL != (pAppRoster = Get()))
  4021. {
  4022. pAppRoster->Release();
  4023. }
  4024. }
  4025. void CListOfAppCapItemList2::DeleteList(void)
  4026. {
  4027. CAppCapItemList *pAppCapItemList;
  4028. while (NULL != (pAppCapItemList = Get()))
  4029. {
  4030. pAppCapItemList->DeleteList();
  4031. delete pAppCapItemList;
  4032. }
  4033. }
  4034.