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.

3092 lines
88 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_GCCNC);
  3. /*
  4. * conf.cpp
  5. *
  6. * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the imlementation file for the CConf Class. The
  10. * conference class is the heart of GCC. It maintains all the
  11. * information basses for a single conference including conference and
  12. * application rosters as well as registry information. It also
  13. * routes, encodes and decodes various PDU's and primitives supported
  14. * by GCC.
  15. *
  16. * FOR A MORE DETAILED EXPLANATION OF THIS CLASS SEE THE INTERFACE FILE.
  17. *
  18. * Portable:
  19. * Yes
  20. *
  21. * Private Instance Variables
  22. * m_JoinRespNamePresentConnHdlList2
  23. * This list keeps up with outstanding joins at an intermediate node.
  24. * Enrolled_App_List
  25. * This list keeps up with all the enrolled applications.
  26. * m_ConnHandleList
  27. * This list keeps up with all the child node connection handles.
  28. * m_ConnHdlTagNumberList2
  29. * This list keeps up with all the outstanding user ID Tag numbers.
  30. * m_EjectedNodeConfirmList
  31. * This list keeps up with all the nodes that have been ejected but
  32. * have yet to disconnect. Used to disconnect any misbehaving apps.
  33. * m_pMcsUserObject
  34. * Holds a pointer to the MCSUser object owned by this conference.
  35. * m_pszConfNumericName
  36. * Holds the numeric conference name.
  37. * m_pwszConfTextName
  38. * Holds a pointer to a unicode string object that contains the text
  39. * conference name. NULL if empty.
  40. * m_pszConfModifier
  41. * Holds a pointer to the conference modifier. NULL if empty.
  42. * m_pszRemoteModifier
  43. * Holds a pointer to the remote modifier. Only used in Join Confirms.
  44. * m_nConfID
  45. * Holds the conference ID associated with this conference object.
  46. * m_fConfLocked
  47. * Flag that indicates if the conference is locked.
  48. * m_fConfListed
  49. * Flag that indicates if the conference is listed.
  50. * m_fConfConductible
  51. * Flag that indicates if the conference is conductible.
  52. * m_fClearPassword
  53. * Flag that indicates if password in the clear is used.
  54. * m_nConvenerNodeID
  55. * Holds the MCS user ID of the convener. Zero if convener has left.
  56. * m_eTerminationMethod
  57. * Holds the enumeration that defines the termination method.
  58. * m_pDomainParameters
  59. * Holds the domain parameters that are returned in a number
  60. * of confirms.
  61. * m_nUserIDTagNumber
  62. * The tag number that must be included when sending this nodes user ID
  63. * back to a connected node.
  64. * m_nConvenerUserIDTagNumber
  65. * Used to uniquely mark the convener when it is rejoining a
  66. * conference.
  67. * m_nParentIDTagNumber
  68. * Used to uniquely mark the parent user ID for an invited node.
  69. * m_eNodeType
  70. * Holds the enumerated Node Type for this particular node.
  71. * m_hParentConnection
  72. * Holds the parent logical connection handle.
  73. * m_hConvenerConnection
  74. * Holds the convener connection handle.
  75. * m_fConfIsEstablished
  76. * Flag which is set to TRUE when the confernce is completely
  77. * established and ready for enrolls and announces.
  78. * m_fConfDisconnectPending
  79. * Flag which is set to TRUE when a disconnect has been issued but
  80. * the conference is waiting for subordinate nodes to disconnect.
  81. * m_fConfTerminatePending
  82. * Flag which is set to TRUE when a terminate has been issued but
  83. * the conference is waiting for subordinate nodes to disconnect.
  84. * m_eConfTerminateReason
  85. * Maintains the terminate reason for delivery in the indication.
  86. * m_pConfTerminateAlarm
  87. * Alarm that is used to force automatic termination when
  88. * subordinate nodes will not disconnect.
  89. * m_pConfStartupAlarm
  90. * Alarm used to hold back the flush of the first roster update
  91. * indication until all the APEs that wish to enroll have had time
  92. * to enroll.
  93. * m_pConductorPrivilegeList
  94. * Holds a pointer to the conductor privilege list object.
  95. * m_pConductModePrivilegeList
  96. * Holds a pointer to the conducted mode privilege list object.
  97. * m_pNonConductModePrivilegeList
  98. * Holds a pointer to the non-conducted mode privilege list object.
  99. * m_pwszConfDescription
  100. * Holds a pointer to a unicode string which holds the conference
  101. * description.
  102. * m_pNetworkAddressList
  103. * Holds a pointer to an object that contains all the local network
  104. * addresses.
  105. * m_pUserDataList
  106. * Holds a pointer to a user data object needed to deliver an
  107. * asynchronus confirm message.
  108. * m_nConfAddRequestTagNumber
  109. * This instance variable is used to generate the add request tag that
  110. * is returned in an add response.
  111. * m_nConfAddResponseTag
  112. * This instance variable is used to generate a response tag that is
  113. * passed in an add indication and returned in an add response.
  114. * m_AddRequestList
  115. * List that keeps up with all the outstanding add request tags.
  116. * m_AddResponseList
  117. * List that keeps up with all the outstanding add response tags.
  118. * m_pConfRosterMgr
  119. * Pointer to the Conference Roster manager.
  120. * m_AppRosterMgrList
  121. * List which holds pointers to all ofthe Application Roster managers.
  122. * m_pAppRegistry
  123. * Pointer to the Application Registry object used by this conference.
  124. * m_InviteRequestList
  125. * List which keeps up with the info associated with all of the
  126. * outstanding invite request. Used for cleanup when the invited
  127. * node never responds.
  128. * m_nConductorNodeID
  129. * The MCS user ID associated with the conducting node. Zero if the
  130. * conference is not in conducted mode.
  131. * m_nPendingConductorNodeID
  132. * Used to keep up with the new conductor node ID when conductorship
  133. * is being passed from one node to another.
  134. * m_fConductorGrantedPermission
  135. * Flag which when TRUE specifies that this node has conductor granted
  136. * permission.
  137. * m_ConductorTestList
  138. * List that is used to keep up with all the command targets that have
  139. * issued conductor inquire request.
  140. * m_fConductorGiveResponsePending
  141. * Flag that states if this node is waiting on a conductor give
  142. * response.
  143. * m_fConductorAssignRequestPending
  144. * Flag that states if this node is waiting to here back from an
  145. * assign request.
  146. * APE_Enitity_ID
  147. * This is a counter used to generate application enityt ids.
  148. *
  149. * Caveats:
  150. * Note that the conference object is now split into two seperate files
  151. * to prevent text segment problems. This file contains the constructors
  152. * and all the entry points for the Owner Object.
  153. *
  154. * Author:
  155. * blp
  156. */
  157. #include "conf.h"
  158. #include "gcontrol.h"
  159. #include "translat.h"
  160. #include "ogcccode.h"
  161. #ifdef _DEBUG
  162. #define STARTUP_TIMER_DURATION 10000 // Ten second startup time
  163. #else
  164. #define STARTUP_TIMER_DURATION 2000 // Two second startup time
  165. #endif
  166. extern MCSDLLInterface *g_pMCSIntf;
  167. /*
  168. * This is a global variable that has a pointer to the one GCC coder that
  169. * is instantiated by the GCC Controller. Most objects know in advance
  170. * whether they need to use the MCS or the GCC coder, so, they do not need
  171. * this pointer in their constructors.
  172. */
  173. extern CGCCCoder *g_GCCCoder;
  174. /*
  175. * CConf::CConf ()
  176. *
  177. * Public Function Description
  178. * When pConfSpecParams != NULL
  179. * This is the conference constructor. It is responsible for
  180. * initializing all the instance variables used by this class.
  181. * It also creates the MCS domain based on the conference id.
  182. * Fatal errors are returned from this constructor in the
  183. * return value. Note that this constructor is used when the
  184. * Conference specification parameters such as termination
  185. * method or known in advance of conference creation. This is
  186. * the case for a CONVENOR node and a TOP PROVIDER. It is not
  187. * used for joining nodes.
  188. *
  189. * When pConfSpecParams == NULL
  190. * This is the conference constructor. It is responsible for
  191. * initializing all the instance variables used by this class.
  192. * It also creates the MCS domain based on the conference id.
  193. * Fatal errors are returned from this constructor in the
  194. * return value. Note that this constructor is used by nodes that
  195. * do not know the Conference specification parameters such as
  196. * termination method in advance of conference creation. This is
  197. * the case for joining nodes.
  198. */
  199. CConf::
  200. CConf
  201. (
  202. PGCCConferenceName pConfName,
  203. GCCNumericString pszConfModifier,
  204. GCCConfID nConfID,
  205. CONF_SPEC_PARAMS *pConfSpecParams,
  206. UINT cNetworkAddresses,
  207. PGCCNetworkAddress *pLocalNetworkAddress,
  208. PGCCError pRetCode
  209. )
  210. :
  211. CRefCount(MAKE_STAMP_ID('C','o','n','f')),
  212. m_RegisteredAppSapList(DESIRED_MAX_APP_SAP_ITEMS),
  213. m_EnrolledApeEidList2(DESIRED_MAX_APP_SAP_ITEMS),
  214. m_ConnHdlTagNumberList2(DESIRED_MAX_CONN_HANDLES),
  215. m_JoinRespNamePresentConnHdlList2(CLIST_DEFAULT_MAX_ITEMS),
  216. m_InviteRequestList(CLIST_DEFAULT_MAX_ITEMS),
  217. m_ConnHandleList(DESIRED_MAX_CONN_HANDLES),
  218. m_EjectedNodeConfirmList(CLIST_DEFAULT_MAX_ITEMS),
  219. m_AddRequestList(CLIST_DEFAULT_MAX_ITEMS),
  220. m_AddResponseList(CLIST_DEFAULT_MAX_ITEMS),
  221. m_NodeVersionList2(CLIST_DEFAULT_MAX_ITEMS),
  222. m_cEnrollRequests(0),
  223. m_fFirstAppRosterSent(FALSE),
  224. m_nConfID(nConfID),
  225. m_pMcsUserObject(NULL),
  226. m_pDomainParameters(NULL),
  227. m_pUserDataList(NULL),
  228. m_pszRemoteModifier(NULL),
  229. m_pConfRosterMgr(NULL),
  230. m_pAppRegistry(NULL),
  231. m_nConductorNodeID(0),
  232. m_nPendingConductorNodeID(0),
  233. m_fConductorGrantedPermission(FALSE),
  234. m_fConductorGiveResponsePending(FALSE),
  235. m_fConductorAssignRequestPending(FALSE),
  236. m_hParentConnection(0),
  237. m_hConvenerConnection(0),
  238. m_pConfTerminateAlarm(NULL),
  239. m_nUserIDTagNumber(0),
  240. m_nConfAddRequestTagNumber(0),
  241. m_nConfAddResponseTag(0),
  242. m_nConvenerNodeID(0),
  243. m_nConvenerUserIDTagNumber(0),
  244. m_nAPEEntityID(0),
  245. m_pwszConfTextName(NULL),
  246. m_pszConfModifier(NULL),
  247. m_pConductorPrivilegeList(NULL),
  248. m_pConductModePrivilegeList(NULL),
  249. m_pNonConductModePrivilegeList(NULL),
  250. m_pwszConfDescription(NULL),
  251. m_pNetworkAddressList(NULL),
  252. /* This variable transitions to TRUE when the conference has completely
  253. ** stabilized. Once it is set to TRUE applications may enroll with the
  254. ** conference. */
  255. m_fConfIsEstablished(FALSE),
  256. /* This variable is transitioned to TRUE if the node that is
  257. ** disconnected is connected to child nodes. */
  258. m_fConfDisconnectPending(FALSE),
  259. /* This variable is transitioned to TRUE if a valid Terminate request
  260. ** is processed. */
  261. m_fConfTerminatePending(FALSE),
  262. /* This variable is set to TRUE if InitiateTermination is called once */
  263. m_fTerminationInitiated(FALSE),
  264. m_fSecure(FALSE),
  265. m_fWBEnrolled(FALSE),
  266. m_fFTEnrolled(FALSE),
  267. m_fChatEnrolled(FALSE)
  268. {
  269. GCCError rc = GCC_ALLOCATION_FAILURE;
  270. DebugEntry(CConf::CConf);
  271. // Conference Specification
  272. if (NULL != pConfSpecParams)
  273. {
  274. m_fClearPassword = pConfSpecParams->fClearPassword;
  275. m_fConfLocked = pConfSpecParams->fConfLocked;
  276. m_fConfListed = pConfSpecParams->fConfListed;
  277. m_fConfConductible = pConfSpecParams->fConfConductable;
  278. m_eTerminationMethod = pConfSpecParams->eTerminationMethod;
  279. }
  280. // m_pConfStartupAlarm = NULL;
  281. DBG_SAVE_FILE_LINE
  282. m_pConfStartupAlarm = new Alarm(STARTUP_TIMER_DURATION);
  283. if (NULL == m_pConfStartupAlarm)
  284. {
  285. ERROR_OUT(("CConf::CConf: Error allocating startup alarm"));
  286. goto MyExit;
  287. }
  288. // Save the numeric conference name.
  289. if (NULL != pConfName->numeric_string)
  290. {
  291. if (NULL == (m_pszConfNumericName = ::My_strdupA(pConfName->numeric_string)))
  292. {
  293. ERROR_OUT(("CConf::CConf: Error allocating conf numeric name"));
  294. goto MyExit;
  295. }
  296. TRACE_OUT(("CConf::CConf: m_strConfNumericName = %s", m_pszConfNumericName));
  297. }
  298. else
  299. {
  300. m_pszConfNumericName = NULL;
  301. if (NULL != pConfSpecParams)
  302. {
  303. //
  304. // LONCHANC: It is an error for top-provider.
  305. //
  306. ERROR_OUT(("CConf::CConf: Error: Numeric Name not present"));
  307. rc = GCC_INVALID_CONFERENCE_NAME;
  308. goto MyExit;
  309. }
  310. //
  311. // LONCHANC: It is not an error for joining node.
  312. //
  313. }
  314. // Save the text conference name if one exists
  315. if (NULL != pConfName->text_string)
  316. {
  317. if (NULL == (m_pwszConfTextName = ::My_strdupW(pConfName->text_string)))
  318. {
  319. ERROR_OUT(("CConf::CConf: Error allocating unicode string"));
  320. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  321. goto MyExit;
  322. }
  323. }
  324. // Save the conference modifier if one exists
  325. if (NULL != pszConfModifier)
  326. {
  327. if (NULL == (m_pszConfModifier = ::My_strdupA(pszConfModifier)))
  328. {
  329. ERROR_OUT(("CConf::CConf: Error allocating conf modifier"));
  330. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  331. goto MyExit;
  332. }
  333. else
  334. {
  335. TRACE_OUT(("CConf::CConf: Conference_Modifier = %s", m_pszConfModifier));
  336. }
  337. }
  338. // Set up the privilege list as needed
  339. if (NULL != pConfSpecParams)
  340. {
  341. if (NULL != pConfSpecParams->pConductPrivilege)
  342. {
  343. DBG_SAVE_FILE_LINE
  344. m_pConductorPrivilegeList = new PrivilegeListData(pConfSpecParams->pConductPrivilege);
  345. if (NULL == m_pConductorPrivilegeList)
  346. {
  347. ERROR_OUT(("CConf::CConf: Error allocating conductor privilege list"));
  348. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  349. goto MyExit;
  350. }
  351. }
  352. if (NULL != pConfSpecParams->pConductModePrivilege)
  353. {
  354. DBG_SAVE_FILE_LINE
  355. m_pConductModePrivilegeList = new PrivilegeListData(pConfSpecParams->pConductModePrivilege);
  356. if (NULL == m_pConductModePrivilegeList)
  357. {
  358. ERROR_OUT(("CConf::CConf: Error allocating conduct mode privilege list"));
  359. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  360. goto MyExit;
  361. }
  362. }
  363. if (NULL != pConfSpecParams->pNonConductPrivilege)
  364. {
  365. DBG_SAVE_FILE_LINE
  366. m_pNonConductModePrivilegeList = new PrivilegeListData(pConfSpecParams->pNonConductPrivilege);
  367. if (NULL == m_pNonConductModePrivilegeList)
  368. {
  369. ERROR_OUT(("CConf::CConf: Error allocating non-conduct mode privilege list"));
  370. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  371. goto MyExit;
  372. }
  373. }
  374. if (NULL != pConfSpecParams->pwszConfDescriptor)
  375. {
  376. if (NULL == (m_pwszConfDescription =
  377. ::My_strdupW(pConfSpecParams->pwszConfDescriptor)))
  378. {
  379. ERROR_OUT(("CConf::CConf: Error allocating conf descriptor"));
  380. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  381. goto MyExit;
  382. }
  383. }
  384. }
  385. // Save the network address(es)
  386. if (0 != cNetworkAddresses)
  387. {
  388. DBG_SAVE_FILE_LINE
  389. m_pNetworkAddressList = new CNetAddrListContainer(cNetworkAddresses, pLocalNetworkAddress, &rc);
  390. if (NULL == m_pNetworkAddressList || GCC_NO_ERROR != rc)
  391. {
  392. ERROR_OUT(("CConf::CConf: Error allocating network address list"));
  393. rc = GCC_ALLOCATION_FAILURE; // rc could be a different value
  394. goto MyExit;
  395. }
  396. }
  397. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  398. /*
  399. ** Create the Domain based on the conference name that was
  400. ** passed in.
  401. */
  402. if (MCS_NO_ERROR != g_pMCSIntf->CreateDomain(&m_nConfID))
  403. {
  404. ERROR_OUT(("CConf::CConf: Error creating domain"));
  405. rc = GCC_FAILURE_CREATING_DOMAIN;
  406. goto MyExit;
  407. }
  408. rc = GCC_NO_ERROR;
  409. MyExit:
  410. *pRetCode = rc;
  411. DebugExitINT(CConf::CConf, rc);
  412. }
  413. /*
  414. * CConf::~CConf ()
  415. *
  416. * Public Function Description
  417. * This is the conference destructor. It is responsible for
  418. * deleting the User Attachment and freeing up any outstanding
  419. * resources used by the conference class. It also calls
  420. * MCS Disconnect Provider to disconnect fron all its connections
  421. * including both parent and child connections. In addition, it
  422. * unregisters its command target from the controller and application
  423. * SAPs and deletes the MCS domain it is associated with.
  424. *
  425. * Caveats
  426. * none
  427. */
  428. CConf::
  429. ~CConf ( void )
  430. {
  431. ConnectionHandle nConnHdl;
  432. //CAppRosterMgr *lpAppRosterMgr;
  433. ENROLLED_APE_INFO *lpEnrAPEInfo;
  434. //CAppSap *pAppSap;
  435. DebugEntry(CConf::~CConf);
  436. // Delete the terminate alarm if it exists
  437. delete m_pConfTerminateAlarm;
  438. // Delete the startup alarm if it exists
  439. delete m_pConfStartupAlarm;
  440. // Delete Conference Roster Managers
  441. if (NULL != m_pConfRosterMgr)
  442. {
  443. m_pConfRosterMgr->Release();
  444. }
  445. // Delete Application Roster Managers
  446. m_AppRosterMgrList.DeleteList();
  447. // Delete the application registry
  448. if (NULL != m_pAppRegistry)
  449. {
  450. m_pAppRegistry->Release();
  451. }
  452. // Delete the text conference name if it exist
  453. delete m_pszConfNumericName;
  454. delete m_pwszConfTextName;
  455. // Delete the conference modifier if it exist
  456. delete m_pszConfModifier;
  457. // Delete the remote modifier if it exist
  458. delete m_pszRemoteModifier;
  459. /*
  460. ** The privilege list are not directly deleted here instead Free is called
  461. ** to prevent the list from being deleted in the case where it has been
  462. ** locked outside the conference object.
  463. */
  464. // Delete all the privilege list (Free is needed incase the list
  465. delete m_pConductorPrivilegeList;
  466. delete m_pConductModePrivilegeList;
  467. delete m_pNonConductModePrivilegeList;
  468. // Delete the conference descriptor
  469. delete m_pwszConfDescription;
  470. // Delete the network address list
  471. if (NULL != m_pNetworkAddressList)
  472. {
  473. m_pNetworkAddressList->Release();
  474. }
  475. if (NULL != m_pUserDataList)
  476. {
  477. m_pUserDataList->Release();
  478. }
  479. // Delete the Domain Parameters if they exist
  480. delete m_pDomainParameters;
  481. // Delete the User Attachment object if they exist
  482. if (NULL != m_pMcsUserObject)
  483. {
  484. m_pMcsUserObject->Release();
  485. }
  486. // Disconnect from the MCS parent connection
  487. if (m_hParentConnection != NULL)
  488. {
  489. g_pMCSIntf->DisconnectProviderRequest(m_hParentConnection);
  490. }
  491. // Disconnect from all MCS child connections
  492. m_ConnHandleList.Reset();
  493. while (0 != (nConnHdl = m_ConnHandleList.Iterate()))
  494. {
  495. g_pMCSIntf->DisconnectProviderRequest(nConnHdl);
  496. }
  497. // Delete the MCS domain
  498. g_pMCSIntf->DeleteDomain(&m_nConfID);
  499. // Cleanup up the m_EnrolledApeEidList2
  500. m_EnrolledApeEidList2.Reset();
  501. while (NULL != (lpEnrAPEInfo = m_EnrolledApeEidList2.Iterate()))
  502. {
  503. if (NULL != lpEnrAPEInfo->session_key)
  504. {
  505. lpEnrAPEInfo->session_key->Release();
  506. }
  507. delete lpEnrAPEInfo;
  508. }
  509. DebugExitVOID(CConf::~CConf);
  510. }
  511. /*
  512. ** Non-CommandTarget Calls. Initiated from the Owner Object. Note that
  513. ** all calls received from the owner object are preceeded by GCC.
  514. */
  515. /*
  516. * CConf::ConfCreateRequest()
  517. *
  518. * Public Function Description
  519. * This routine is called from the owner object when a
  520. * ConferenceCreateRequest primitive needs to be processed.
  521. * If the calling address equals the called address then an
  522. * empty conference is created at this node (this node will
  523. * then be both the convenor and the top provider).
  524. *
  525. * Caveats
  526. * All errors should be handled directly by the calling application.
  527. * This includes deletion of the conference object.
  528. */
  529. GCCError CConf::
  530. ConfCreateRequest
  531. (
  532. TransportAddress calling_address,
  533. TransportAddress called_address,
  534. BOOL fSecure,
  535. CPassword *convener_password,
  536. CPassword *password,
  537. LPWSTR pwszCallerID,
  538. PDomainParameters domain_parameters,
  539. CUserDataListContainer *user_data_list,
  540. PConnectionHandle connection_handle
  541. )
  542. {
  543. GCCError rc = GCC_ALLOCATION_FAILURE;
  544. ConnectGCCPDU connect_pdu;
  545. LPBYTE encoded_pdu;
  546. UINT encoded_pdu_length;
  547. MCSError mcs_error;
  548. DebugEntry(CConf::ConfCreateRequest);
  549. /*
  550. ** First make a copy of the new domain parameters if they exists. These
  551. ** will be copied over when the connect provider confirm comes in.
  552. */
  553. if (NULL != domain_parameters)
  554. {
  555. DBG_SAVE_FILE_LINE
  556. m_pDomainParameters = new DomainParameters;
  557. if (NULL == m_pDomainParameters)
  558. {
  559. ERROR_OUT(("CConf::ConfCreateRequest: can't create DomainParameters"));
  560. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  561. goto MyExit;
  562. }
  563. // structure-wide shallow copy
  564. *m_pDomainParameters = *domain_parameters;
  565. }
  566. /*
  567. ** If the called address equals NULL this node will be both the Top
  568. ** Provider and the Convener. In this case there is no need to send out the
  569. ** ConfCreateRq PDU. Instead we go ahead and create the User Object. If the
  570. ** conference is created with someone else, wait until the response is
  571. ** returned before creating the User Object.
  572. */
  573. if (NULL != called_address)
  574. {
  575. // Set up the node type
  576. m_eNodeType = CONVENER_NODE;
  577. /*
  578. ** Create the ConferenceCreateRequest PDU here.
  579. */
  580. connect_pdu.choice = CONFERENCE_CREATE_REQUEST_CHOSEN;
  581. connect_pdu.u.conference_create_request.bit_mask = 0;
  582. // Encode the conference name
  583. connect_pdu.u.conference_create_request.conference_name.bit_mask = 0;
  584. // Encode the numeric portion of the name
  585. ::lstrcpyA(connect_pdu.u.conference_create_request.conference_name.numeric,
  586. m_pszConfNumericName);
  587. // Encode the text portion of the conference name if it exists
  588. if (NULL != m_pwszConfTextName)
  589. {
  590. connect_pdu.u.conference_create_request.conference_name.bit_mask |=
  591. CONFERENCE_NAME_TEXT_PRESENT;
  592. connect_pdu.u.conference_create_request.conference_name.conference_name_text.value =
  593. m_pwszConfTextName;
  594. connect_pdu.u.conference_create_request.conference_name.conference_name_text.length =
  595. ::lstrlenW(m_pwszConfTextName);
  596. }
  597. // Encode the convener password if one exists.
  598. if (NULL != convener_password)
  599. {
  600. rc = convener_password->GetPasswordPDU(
  601. &connect_pdu.u.conference_create_request.ccrq_convener_password);
  602. if (GCC_NO_ERROR != rc)
  603. {
  604. ERROR_OUT(("CConf::ConfCreateRequest: can't get convenor password, rc=%d", rc));
  605. goto MyExit;
  606. }
  607. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_CONVENER_PASSWORD_PRESENT;
  608. }
  609. // Encode the convener password if one exists.
  610. if (NULL != password)
  611. {
  612. rc = password->GetPasswordPDU(
  613. &connect_pdu.u.conference_create_request.ccrq_password);
  614. if (GCC_NO_ERROR != rc)
  615. {
  616. ERROR_OUT(("CConf::ConfCreateRequest: can't get password, rc=%d", rc));
  617. goto MyExit;
  618. }
  619. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_PASSWORD_PRESENT;
  620. }
  621. // Encode the privilege list
  622. if (NULL != m_pConductorPrivilegeList)
  623. {
  624. rc = m_pConductorPrivilegeList->GetPrivilegeListPDU(
  625. &connect_pdu.u.conference_create_request.ccrq_conductor_privs);
  626. if (GCC_NO_ERROR != rc)
  627. {
  628. ERROR_OUT(("CConf::ConfCreateRequest: can't get conductor's privileges, rc=%d", rc));
  629. goto MyExit;
  630. }
  631. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_CONDUCTOR_PRIVS_PRESENT;
  632. }
  633. if (NULL != m_pConductModePrivilegeList)
  634. {
  635. rc = m_pConductModePrivilegeList->GetPrivilegeListPDU(
  636. &connect_pdu.u.conference_create_request.ccrq_conducted_privs);
  637. if (GCC_NO_ERROR != rc)
  638. {
  639. ERROR_OUT(("CConf::ConfCreateRequest: can't get conduct mode privileges, rc=%d", rc));
  640. goto MyExit;
  641. }
  642. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_CONDUCTED_PRIVS_PRESENT;
  643. }
  644. if (NULL != m_pNonConductModePrivilegeList)
  645. {
  646. rc = m_pNonConductModePrivilegeList->GetPrivilegeListPDU(
  647. &connect_pdu.u.conference_create_request.ccrq_non_conducted_privs);
  648. if (GCC_NO_ERROR != rc)
  649. {
  650. ERROR_OUT(("CConf::ConfCreateRequest: can't get non-conduct mode privileges, rc=%d", rc));
  651. goto MyExit;
  652. }
  653. connect_pdu.u.conference_create_request.bit_mask |=
  654. CCRQ_NON_CONDUCTED_PRIVS_PRESENT;
  655. }
  656. // Encode the conference descriptor
  657. if (NULL != m_pwszConfDescription)
  658. {
  659. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_DESCRIPTION_PRESENT;
  660. connect_pdu.u.conference_create_request.ccrq_description.length =
  661. ::lstrlenW(m_pwszConfDescription);
  662. connect_pdu.u.conference_create_request.ccrq_description.value =
  663. m_pwszConfDescription;
  664. }
  665. // Encode the caller identifier if on exists.
  666. if (NULL != pwszCallerID)
  667. {
  668. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_CALLER_ID_PRESENT;
  669. connect_pdu.u.conference_create_request.ccrq_caller_id.length = ::lstrlenW(pwszCallerID);
  670. connect_pdu.u.conference_create_request.ccrq_caller_id.value = pwszCallerID;
  671. }
  672. // Encode the user data if any exists
  673. if (NULL != user_data_list)
  674. {
  675. rc = user_data_list->GetUserDataPDU(
  676. &connect_pdu.u.conference_create_request.ccrq_user_data);
  677. if (GCC_NO_ERROR != NULL)
  678. {
  679. ERROR_OUT(("CConf::ConfCreateRequest: can't get user data, rc=%d", rc));
  680. goto MyExit;
  681. }
  682. connect_pdu.u.conference_create_request.bit_mask |= CCRQ_USER_DATA_PRESENT;
  683. }
  684. connect_pdu.u.conference_create_request.conference_is_locked = (ASN1bool_t)m_fConfLocked;
  685. connect_pdu.u.conference_create_request.conference_is_listed = (ASN1bool_t)m_fConfListed;
  686. connect_pdu.u.conference_create_request.conference_is_conductible = (ASN1bool_t)m_fConfConductible;
  687. connect_pdu.u.conference_create_request.termination_method = (TerminationMethod)m_eTerminationMethod;
  688. if (! g_GCCCoder->Encode((LPVOID) &connect_pdu,
  689. CONNECT_GCC_PDU,
  690. PACKED_ENCODING_RULES,
  691. &encoded_pdu,
  692. &encoded_pdu_length))
  693. {
  694. ERROR_OUT(("CConf::ConfCreateRequest: can't encode"));
  695. rc = GCC_ALLOCATION_FAILURE;
  696. goto MyExit;
  697. }
  698. mcs_error = g_pMCSIntf->ConnectProviderRequest (
  699. &m_nConfID, // calling domain selector
  700. &m_nConfID, // called domain selector
  701. calling_address,
  702. called_address,
  703. fSecure,
  704. TRUE, // Upward connection
  705. encoded_pdu,
  706. encoded_pdu_length,
  707. &m_hParentConnection,
  708. m_pDomainParameters,
  709. this);
  710. g_GCCCoder->FreeEncoded(encoded_pdu);
  711. *connection_handle = m_hParentConnection;
  712. if (MCS_NO_ERROR != mcs_error)
  713. {
  714. ERROR_OUT(("CConf::ConfCreateRequest: ConnectProviderRequest call failed, rc=%d", mcs_error));
  715. /*
  716. ** DataBeam's current implementation of MCS returns
  717. ** MCS_INVALID_PARAMETER when something other than
  718. ** the transport prefix is wrong with the specified
  719. ** transport address.
  720. */
  721. rc = (mcs_error == MCS_INVALID_PARAMETER) ?
  722. GCC_INVALID_TRANSPORT_ADDRESS :
  723. g_pMCSIntf->TranslateMCSIFErrorToGCCError(mcs_error);
  724. goto MyExit;
  725. }
  726. // Free the privilege list packed into structures for encoding
  727. if (connect_pdu.u.conference_create_request.bit_mask & CCRQ_CONDUCTOR_PRIVS_PRESENT)
  728. {
  729. m_pConductorPrivilegeList->FreePrivilegeListPDU(
  730. connect_pdu.u.conference_create_request.ccrq_conductor_privs);
  731. }
  732. if (connect_pdu.u.conference_create_request.bit_mask & CCRQ_CONDUCTED_PRIVS_PRESENT)
  733. {
  734. m_pConductModePrivilegeList->FreePrivilegeListPDU(
  735. connect_pdu.u.conference_create_request.ccrq_conducted_privs);
  736. }
  737. if (connect_pdu.u.conference_create_request.bit_mask & CCRQ_NON_CONDUCTED_PRIVS_PRESENT)
  738. {
  739. m_pNonConductModePrivilegeList->FreePrivilegeListPDU(
  740. connect_pdu.u.conference_create_request.ccrq_non_conducted_privs);
  741. }
  742. }
  743. else
  744. {
  745. *connection_handle = NULL;
  746. m_eNodeType = TOP_PROVIDER_AND_CONVENER_NODE;
  747. DBG_SAVE_FILE_LINE
  748. m_pMcsUserObject = new MCSUser(this, 0, 0, &rc);
  749. if (NULL == m_pMcsUserObject || GCC_NO_ERROR != rc)
  750. {
  751. ERROR_OUT(("CConf: ConfCreateRequest: can't create mcs user object, rc=%d", rc));
  752. if (NULL != m_pMcsUserObject)
  753. {
  754. m_pMcsUserObject->Release();
  755. m_pMcsUserObject = NULL;
  756. }
  757. else
  758. {
  759. rc = GCC_ALLOCATION_FAILURE; // rc may be a different value
  760. }
  761. goto MyExit;
  762. }
  763. }
  764. m_fSecure = fSecure;
  765. rc = GCC_NO_ERROR;
  766. MyExit:
  767. if (GCC_NO_ERROR != rc)
  768. {
  769. if (NULL != domain_parameters)
  770. {
  771. delete m_pDomainParameters;
  772. m_pDomainParameters = NULL;
  773. }
  774. }
  775. DebugExitINT(CConf::ConferenceCreateRequest, rc);
  776. return rc;
  777. }
  778. /*
  779. * CConf::ConfCreateResponse ()
  780. *
  781. * Public Function Description
  782. * This routine is called from the owner object when a
  783. * ConferenceCreateResponse primitive needs to be processed.
  784. * Note that this should only be called when the result of
  785. * the response is success. Only the top provider receives the
  786. * conference create response.
  787. *
  788. * Caveats
  789. * All errors should be handled directly by the calling application.
  790. * This includes deletion of the conference object and notification
  791. * to the node controller that the conference was abnormally
  792. * terminated.
  793. */
  794. GCCError CConf::
  795. ConfCreateResponse
  796. (
  797. ConnectionHandle connection_handle,
  798. PDomainParameters domain_parameters,
  799. CUserDataListContainer *user_data_list
  800. )
  801. {
  802. GCCError rc = GCC_ALLOCATION_FAILURE;
  803. DebugEntry(CConf::ConfCreateResponse);
  804. // Conference Create Responses can only be received at the top provider
  805. m_eNodeType = TOP_PROVIDER_NODE;
  806. /*
  807. ** First make a copy of the new domain parameters if they exists. We do
  808. ** this here so that they can be passed in when we perform the Connect
  809. ** Provider Response.
  810. */
  811. if (domain_parameters != NULL)
  812. {
  813. DBG_SAVE_FILE_LINE
  814. m_pDomainParameters = new DomainParameters;
  815. if (NULL == m_pDomainParameters)
  816. {
  817. ERROR_OUT(("CConf::ConfCreateResponse: can't create domain parameters"));
  818. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  819. goto MyExit;
  820. }
  821. // structure-wide shallow copy
  822. *m_pDomainParameters = *domain_parameters;
  823. }
  824. // Store the child connection in the list of connection handles
  825. ASSERT(0 != connection_handle);
  826. m_ConnHandleList.Append(connection_handle);
  827. /*
  828. ** The convener connection handle is stored seperately so that
  829. ** the Connect Provider response can be sent on the right
  830. ** connection. This may be overkill but I was a little concerned
  831. ** about pulling this out of the list even though this should be
  832. ** the only entry in the list when it's time to send the response.
  833. */
  834. m_hConvenerConnection = connection_handle;
  835. if (user_data_list != NULL)
  836. {
  837. /*
  838. ** Since we must wait until the user attachment is fully
  839. ** established before we send the response we must save the user
  840. ** data list in a temporary container.
  841. */
  842. m_pUserDataList = user_data_list;
  843. // Lock the user data in memory
  844. m_pUserDataList->LockUserDataList();
  845. }
  846. /*
  847. ** Now create the user attachment object and wait for the confirm
  848. ** which occurs after all the proper channels are joined. The
  849. ** user object will determine the top provider ID. When the user
  850. ** create confirm is received the response PDU will be sent out
  851. ** in the Connect Provider Response.
  852. */
  853. DBG_SAVE_FILE_LINE
  854. m_pMcsUserObject = new MCSUser(this, 0, 0, &rc);
  855. if (NULL == m_pMcsUserObject || GCC_NO_ERROR != rc)
  856. {
  857. ERROR_OUT(("CConf::ConfCreateResponse: can't create mcs user object, rc=%d", rc));
  858. if (NULL != m_pMcsUserObject)
  859. {
  860. m_pMcsUserObject->Release();
  861. m_pMcsUserObject = NULL;
  862. }
  863. else
  864. {
  865. rc = GCC_ALLOCATION_FAILURE; // rc may be a different value
  866. }
  867. goto MyExit;
  868. }
  869. rc = GCC_NO_ERROR;
  870. MyExit:
  871. if (GCC_NO_ERROR != rc)
  872. {
  873. if (NULL != domain_parameters)
  874. {
  875. delete m_pDomainParameters;
  876. m_pDomainParameters = NULL;
  877. }
  878. }
  879. DebugExitINT(CConf::ConferenceCreateResponse, rc);
  880. return rc;
  881. }
  882. /*
  883. * CConf::ConfJoinRequest()
  884. *
  885. * Public Function Description
  886. * This routine is called from the owner object when a
  887. * ConferenceJoinRequest primitive received from the node controller needs
  888. * to be processed. This routine sends a JoinRequest PDU to its parent
  889. * node through an MCS Connect Provider Request.
  890. *
  891. * Caveats
  892. * All errors should be handled directly by the calling application.
  893. * This includes deletion of the conference object.
  894. */
  895. GCCError CConf::
  896. ConfJoinRequest
  897. (
  898. GCCNumericString called_node_modifier,
  899. CPassword *convener_password,
  900. CPassword *password_challenge,
  901. LPWSTR pwszCallerID,
  902. TransportAddress calling_address,
  903. TransportAddress called_address,
  904. BOOL fSecure,
  905. PDomainParameters domain_parameters,
  906. CUserDataListContainer *user_data_list,
  907. PConnectionHandle connection_handle
  908. )
  909. {
  910. GCCError rc = GCC_ALLOCATION_FAILURE;
  911. LPBYTE encoded_pdu;
  912. UINT encoded_pdu_length;
  913. MCSError mcs_error;
  914. ConnectGCCPDU connect_pdu;
  915. DebugEntry(CConf::ConfJoinRequest);
  916. ASSERT(FALSE == m_fSecure);
  917. m_fSecure = fSecure;
  918. /*
  919. ** First make a copy of the new domain parameters if they exists. These
  920. ** will be copied over when the connect provider confirm comes in.
  921. */
  922. if (domain_parameters != NULL)
  923. {
  924. DBG_SAVE_FILE_LINE
  925. m_pDomainParameters = new DomainParameters;
  926. if (NULL == m_pDomainParameters)
  927. {
  928. ERROR_OUT(("CConf::ConfJoinRequest: can't create domain parameters"));
  929. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  930. goto MyExit;
  931. }
  932. *m_pDomainParameters = *domain_parameters;
  933. }
  934. m_eNodeType = (NULL == convener_password) ?
  935. // Node type must be joined when receiving this request
  936. JOINED_NODE :
  937. // Node type must be joined convener when receiving this request
  938. JOINED_CONVENER_NODE;
  939. // Create the ConferenceJoinRequest PDU here.
  940. connect_pdu.choice = CONNECT_JOIN_REQUEST_CHOSEN;
  941. connect_pdu.u.connect_join_request.bit_mask = CONFERENCE_NAME_PRESENT;
  942. if (NULL != m_pszConfNumericName && '\0' != *m_pszConfNumericName)
  943. {
  944. // Send the numeric portion of the conference name
  945. connect_pdu.u.connect_join_request.conference_name.choice = NAME_SELECTOR_NUMERIC_CHOSEN;
  946. ::lstrcpyA(connect_pdu.u.connect_join_request.conference_name.u.name_selector_numeric,
  947. m_pszConfNumericName);
  948. }
  949. else
  950. {
  951. // Send the text portion of the conference name
  952. connect_pdu.u.connect_join_request.conference_name.choice = NAME_SELECTOR_TEXT_CHOSEN;
  953. connect_pdu.u.connect_join_request.conference_name.u.name_selector_text.length =
  954. ::lstrlenW(m_pwszConfTextName);
  955. connect_pdu.u.connect_join_request.conference_name.u.name_selector_text.value =
  956. m_pwszConfTextName;
  957. }
  958. // Fill in the remote node modifier if one exists
  959. if (NULL != called_node_modifier)
  960. {
  961. // Save the remote modifier so that it can be returned in the confirm
  962. if (NULL == (m_pszRemoteModifier = ::My_strdupA(called_node_modifier)))
  963. {
  964. ERROR_OUT(("CConf::ConfJoinRequest: can't create remote modifier"));
  965. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  966. goto MyExit;
  967. }
  968. connect_pdu.u.connect_join_request.bit_mask |= CJRQ_CONFERENCE_MODIFIER_PRESENT;
  969. ::lstrcpyA(connect_pdu.u.connect_join_request.cjrq_conference_modifier,
  970. (LPCSTR) called_node_modifier);
  971. }
  972. // Fill in the convener password selector.
  973. if (NULL != convener_password)
  974. {
  975. rc = convener_password->GetPasswordSelectorPDU(
  976. &connect_pdu.u.connect_join_request.cjrq_convener_password);
  977. if (GCC_NO_ERROR != rc)
  978. {
  979. ERROR_OUT(("CConf::ConfJoinRequest: can't get password selector, rc=%d", rc));
  980. goto MyExit;
  981. }
  982. connect_pdu.u.connect_join_request.bit_mask |= CJRQ_CONVENER_PASSWORD_PRESENT;
  983. }
  984. // Fill in the password challenge
  985. if (NULL != password_challenge)
  986. {
  987. rc = password_challenge->GetPasswordChallengeResponsePDU(
  988. &connect_pdu.u.connect_join_request.cjrq_password);
  989. if (GCC_NO_ERROR != rc)
  990. {
  991. ERROR_OUT(("CConf::ConfJoinRequest: can't get password challenge response, rc=%d", rc));
  992. goto MyExit;
  993. }
  994. connect_pdu.u.connect_join_request.bit_mask |=CJRQ_PASSWORD_PRESENT;
  995. }
  996. // Fill in the caller identifier if one exists
  997. if (NULL != pwszCallerID)
  998. {
  999. connect_pdu.u.connect_join_request.bit_mask |= CJRQ_CALLER_ID_PRESENT;
  1000. connect_pdu.u.connect_join_request.cjrq_caller_id.value = pwszCallerID;
  1001. connect_pdu.u.connect_join_request.cjrq_caller_id.length = ::lstrlenW(pwszCallerID);
  1002. }
  1003. // Fill in the user data if it exists
  1004. if (NULL != user_data_list)
  1005. {
  1006. rc = user_data_list->GetUserDataPDU(
  1007. &connect_pdu.u.connect_join_request.cjrq_user_data);
  1008. if (GCC_NO_ERROR != rc)
  1009. {
  1010. ERROR_OUT(("CConf::ConfJoinRequest: can't get user data, rc=%d", rc));
  1011. goto MyExit;
  1012. }
  1013. connect_pdu.u.connect_join_request.bit_mask |= CJRQ_USER_DATA_PRESENT;
  1014. }
  1015. if (! g_GCCCoder->Encode((LPVOID) &connect_pdu,
  1016. CONNECT_GCC_PDU,
  1017. PACKED_ENCODING_RULES,
  1018. &encoded_pdu,
  1019. &encoded_pdu_length))
  1020. {
  1021. ERROR_OUT(("CConf::ConfJoinRequest: can't encode"));
  1022. rc = GCC_ALLOCATION_FAILURE;
  1023. goto MyExit;
  1024. }
  1025. /*
  1026. ** Note that the TransportStrings are casted twice here. It
  1027. ** must be done this way to satisfy the compiler. Sorry about
  1028. ** not adhearing to coding standards.
  1029. */
  1030. mcs_error = g_pMCSIntf->ConnectProviderRequest(
  1031. &m_nConfID, // calling domain selector
  1032. &m_nConfID, // called domain selector
  1033. calling_address,
  1034. called_address,
  1035. m_fSecure,
  1036. TRUE, // Upward connection
  1037. encoded_pdu,
  1038. encoded_pdu_length,
  1039. &m_hParentConnection,
  1040. m_pDomainParameters,
  1041. this);
  1042. g_GCCCoder->FreeEncoded(encoded_pdu);
  1043. *connection_handle = m_hParentConnection;
  1044. if (MCS_NO_ERROR != mcs_error)
  1045. {
  1046. ERROR_OUT(("CConf::ConfJoinRequest: can't connect provider request, rc=%d", mcs_error));
  1047. /*
  1048. ** DataBeam's current implementation of MCS returns
  1049. ** MCS_INVALID_PARAMETER when something other than
  1050. ** the transport prefix is wrong with the specified
  1051. ** transport address.
  1052. */
  1053. rc = (mcs_error == MCS_INVALID_PARAMETER) ?
  1054. GCC_INVALID_TRANSPORT_ADDRESS :
  1055. g_pMCSIntf->TranslateMCSIFErrorToGCCError(mcs_error);
  1056. goto MyExit;
  1057. }
  1058. rc = GCC_NO_ERROR;
  1059. MyExit:
  1060. if (GCC_NO_ERROR != rc)
  1061. {
  1062. if (NULL != domain_parameters)
  1063. {
  1064. delete m_pDomainParameters;
  1065. m_pDomainParameters = NULL;
  1066. }
  1067. if (NULL != called_node_modifier)
  1068. {
  1069. delete m_pszRemoteModifier;
  1070. m_pszRemoteModifier = NULL;
  1071. }
  1072. }
  1073. DebugExitINT(CConf:ConferenceJoinRequest, rc);
  1074. return rc;
  1075. }
  1076. /*
  1077. * CConf::ForwardConfJoinRequest ()
  1078. *
  1079. * Public Function Description
  1080. * This routine is called from the owner object when a conference join
  1081. * request is received for a conference that is at a node that is not the
  1082. * Top Provider. This routine forwards the request on up to the Top
  1083. * Provider.
  1084. *
  1085. * Caveats
  1086. * This routine should never be called if this node is the Top Provider.
  1087. */
  1088. GCCError CConf::
  1089. ForwardConfJoinRequest
  1090. (
  1091. CPassword *convener_password,
  1092. CPassword *password_challange,
  1093. LPWSTR pwszCallerID,
  1094. CUserDataListContainer *user_data_list,
  1095. BOOL numeric_name_present,
  1096. ConnectionHandle connection_handle
  1097. )
  1098. {
  1099. GCCError rc;
  1100. DebugEntry(CConf::ForwardConfJoinRequest);
  1101. /*
  1102. ** If the node is the top provider we will go ahead and send the
  1103. ** join indication to the node controller, otherwise we will pass
  1104. ** the request on up to the top provider.
  1105. */
  1106. if (IsConfTopProvider())
  1107. {
  1108. WARNING_OUT(("CConf::GCCConferenceJoinIndication: not top provider"));
  1109. rc = GCC_INVALID_CONFERENCE;
  1110. goto MyExit;
  1111. }
  1112. /*
  1113. ** The connection handle is used as the tag which is sent in the request
  1114. ** and returned in the response. Note that it is the user objects
  1115. ** responsiblity to resolve any type conflicts with the tag.
  1116. */
  1117. if (NULL == m_pMcsUserObject)
  1118. {
  1119. ERROR_OUT(("CConf::GCCConferenceJoinIndication: invalid mcs user object"));
  1120. rc = GCC_INVALID_CONFERENCE;
  1121. goto MyExit;
  1122. }
  1123. /*
  1124. ** This list holds information about the conference name alias that
  1125. ** must be returned in the join response. When the reponse comes
  1126. ** back from the top provider, the information can be obtained from
  1127. ** this list.
  1128. */
  1129. m_JoinRespNamePresentConnHdlList2.Append(connection_handle, numeric_name_present ? TRUE_PTR : FALSE_PTR);
  1130. // The user object is responsible for encoding this PDU
  1131. rc = m_pMcsUserObject->ConferenceJoinRequest(convener_password,
  1132. password_challange,
  1133. pwszCallerID,
  1134. user_data_list,
  1135. connection_handle);
  1136. MyExit:
  1137. DebugExitINT(CConf::ForwardConfJoinRequest, rc);
  1138. return rc;
  1139. }
  1140. /*
  1141. * CConf::ConfJoinIndResponse()
  1142. *
  1143. * Public Function Description
  1144. * This routine is called from the owner object when a
  1145. * ConferenceJoinResponse primitive is received from the node controller.
  1146. * It is also called when a ConferenceJoinResponse is received from the
  1147. * Top Provider.
  1148. *
  1149. * Caveats
  1150. * If the GCC_DOMAIN_PARAMETERS_UNACCEPTABLE error is returned from this
  1151. * routine, MCS will automatically reject the connection sending a
  1152. * result to the other side stating the the Domain Parameters were
  1153. * unacceptable.
  1154. */
  1155. GCCError CConf::
  1156. ConfJoinIndResponse
  1157. (
  1158. ConnectionHandle connection_handle,
  1159. CPassword *password_challenge,
  1160. CUserDataListContainer *user_data_list,
  1161. BOOL numeric_name_present,
  1162. BOOL convener_is_joining,
  1163. GCCResult result
  1164. )
  1165. {
  1166. GCCError rc = GCC_NO_ERROR;
  1167. MCSError mcs_error;
  1168. LPBYTE encoded_pdu;
  1169. UINT encoded_pdu_length;
  1170. ConnectGCCPDU connect_pdu;
  1171. Result mcs_result;
  1172. DebugEntry(CConf::ConfJoinIndResponse);
  1173. // Set up the MCS result for the connect provider response.
  1174. mcs_result = (result == GCC_RESULT_SUCCESSFUL) ?
  1175. RESULT_SUCCESSFUL :
  1176. RESULT_USER_REJECTED;
  1177. // Encode the PDU
  1178. connect_pdu.choice = CONNECT_JOIN_RESPONSE_CHOSEN;
  1179. connect_pdu.u.connect_join_response.bit_mask = CJRS_NODE_ID_PRESENT;
  1180. if (result == GCC_RESULT_SUCCESSFUL)
  1181. {
  1182. // Check to see if it is necessary to send the conference name alias
  1183. if (numeric_name_present && (m_pwszConfTextName != NULL))
  1184. {
  1185. connect_pdu.u.connect_join_response.bit_mask |= CONFERENCE_NAME_ALIAS_PRESENT;
  1186. connect_pdu.u.connect_join_response.conference_name_alias.choice =
  1187. NAME_SELECTOR_TEXT_CHOSEN;
  1188. connect_pdu.u.connect_join_response.conference_name_alias.u.name_selector_text.value =
  1189. m_pwszConfTextName;
  1190. connect_pdu.u.connect_join_response.conference_name_alias.u.name_selector_text.length =
  1191. ::lstrlenW(m_pwszConfTextName);
  1192. }
  1193. else
  1194. if (! numeric_name_present)
  1195. {
  1196. connect_pdu.u.connect_join_response.bit_mask |=
  1197. CONFERENCE_NAME_ALIAS_PRESENT;
  1198. connect_pdu.u.connect_join_response.conference_name_alias.choice =
  1199. NAME_SELECTOR_NUMERIC_CHOSEN;
  1200. lstrcpy (connect_pdu.u.connect_join_response.conference_name_alias.u.name_selector_numeric,
  1201. m_pszConfNumericName);
  1202. }
  1203. // Get the conductor privilege list
  1204. if (NULL != m_pConductorPrivilegeList)
  1205. {
  1206. rc = m_pConductorPrivilegeList->GetPrivilegeListPDU(
  1207. &connect_pdu.u.connect_join_response.cjrs_conductor_privs);
  1208. if (GCC_NO_ERROR != rc)
  1209. {
  1210. ERROR_OUT(("CConf::ConfJoinIndResponse: can't get privilege, rc=%d", rc));
  1211. goto MyExit;
  1212. }
  1213. connect_pdu.u.connect_join_response.bit_mask |= CJRS_CONDUCTOR_PRIVS_PRESENT;
  1214. }
  1215. // Get the conducted mode privilege list
  1216. if (NULL != m_pConductModePrivilegeList)
  1217. {
  1218. rc = m_pConductModePrivilegeList->GetPrivilegeListPDU(
  1219. &connect_pdu.u.connect_join_response.cjrs_conducted_privs);
  1220. if (GCC_NO_ERROR != rc)
  1221. {
  1222. ERROR_OUT(("CConf::ConfJoinIndResponse: can't get conduct mode privilege, rc=%d", rc));
  1223. goto MyExit;
  1224. }
  1225. connect_pdu.u.connect_join_response.bit_mask |= CJRS_CONDUCTED_PRIVS_PRESENT;
  1226. }
  1227. // Get the non conducted mode privilege list
  1228. if (NULL != m_pNonConductModePrivilegeList)
  1229. {
  1230. rc = m_pNonConductModePrivilegeList->GetPrivilegeListPDU(
  1231. &connect_pdu.u.connect_join_response.cjrs_non_conducted_privs);
  1232. if (GCC_NO_ERROR != rc)
  1233. {
  1234. ERROR_OUT(("CConf::ConfJoinIndResponse: can't get non-conduct mode privilege, rc=%d", rc));
  1235. goto MyExit;
  1236. }
  1237. connect_pdu.u.connect_join_response.bit_mask |= CJRS_NON_CONDUCTED_PRIVS_PRESENT;
  1238. }
  1239. // Get the conference description
  1240. if (NULL != m_pwszConfDescription)
  1241. {
  1242. connect_pdu.u.connect_join_response.cjrs_description.length =
  1243. ::lstrlenW(m_pwszConfDescription);
  1244. connect_pdu.u.connect_join_response.cjrs_description.value =
  1245. m_pwszConfDescription;
  1246. connect_pdu.u.connect_join_response.bit_mask |= CJRS_DESCRIPTION_PRESENT;
  1247. }
  1248. }
  1249. // Get the password challenge
  1250. if (NULL != password_challenge)
  1251. {
  1252. rc = password_challenge->GetPasswordChallengeResponsePDU (
  1253. &connect_pdu.u.connect_join_response.cjrs_password);
  1254. if (GCC_NO_ERROR != rc)
  1255. {
  1256. ERROR_OUT(("CConf::ConfJoinIndResponse: can't get password challenge response, rc=%d", rc));
  1257. goto MyExit;
  1258. }
  1259. connect_pdu.u.connect_join_response.bit_mask |= CJRS_PASSWORD_PRESENT;
  1260. }
  1261. // Get the user data list
  1262. if (NULL != user_data_list)
  1263. {
  1264. rc = user_data_list->GetUserDataPDU(&connect_pdu.u.connect_join_response.cjrs_user_data);
  1265. if (GCC_NO_ERROR != rc)
  1266. {
  1267. ERROR_OUT(("CConf::ConfJoinIndResponse: can't get user data, rc=%d", rc));
  1268. goto MyExit;
  1269. }
  1270. connect_pdu.u.connect_join_response.bit_mask |= CJRS_USER_DATA_PRESENT;
  1271. }
  1272. connect_pdu.u.connect_join_response.tag = GetNewUserIDTag ();
  1273. /*
  1274. ** if this is the convener rejoining the conference, we save
  1275. ** the user id tag so that we can record the convener id when it
  1276. ** is returned in the user id indication.
  1277. */
  1278. if (convener_is_joining &&
  1279. ((m_eNodeType == TOP_PROVIDER_NODE) ||
  1280. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE)))
  1281. {
  1282. m_nConvenerUserIDTagNumber = connect_pdu.u.connect_join_response.tag;
  1283. }
  1284. connect_pdu.u.connect_join_response.cjrs_node_id = m_pMcsUserObject->GetMyNodeID();
  1285. connect_pdu.u.connect_join_response.top_node_id = m_pMcsUserObject->GetTopNodeID();
  1286. connect_pdu.u.connect_join_response.clear_password_required = (ASN1bool_t)m_fClearPassword;
  1287. connect_pdu.u.connect_join_response.conference_is_locked = (ASN1bool_t)m_fConfLocked;
  1288. connect_pdu.u.connect_join_response.conference_is_listed = (ASN1bool_t)m_fConfListed;
  1289. connect_pdu.u.connect_join_response.conference_is_conductible = (ASN1bool_t)m_fConfConductible;
  1290. connect_pdu.u.connect_join_response.termination_method = (TerminationMethod)m_eTerminationMethod;
  1291. connect_pdu.u.connect_join_response.result = ::TranslateGCCResultToJoinResult(result);
  1292. if (! g_GCCCoder->Encode((LPVOID) &connect_pdu,
  1293. CONNECT_GCC_PDU,
  1294. PACKED_ENCODING_RULES,
  1295. &encoded_pdu,
  1296. &encoded_pdu_length))
  1297. {
  1298. ERROR_OUT(("CConf::ConfJoinIndResponse: can't encode"));
  1299. rc = GCC_ALLOCATION_FAILURE;
  1300. goto MyExit;
  1301. }
  1302. mcs_error = g_pMCSIntf->ConnectProviderResponse(
  1303. connection_handle,
  1304. &m_nConfID,
  1305. m_pDomainParameters,
  1306. mcs_result,
  1307. encoded_pdu,
  1308. encoded_pdu_length);
  1309. g_GCCCoder->FreeEncoded(encoded_pdu);
  1310. if ((mcs_error == MCS_NO_ERROR) &&
  1311. (result == GCC_RESULT_SUCCESSFUL))
  1312. {
  1313. /*
  1314. ** Add the connection handle to our list of
  1315. ** connection handles.
  1316. */
  1317. ASSERT(0 != connection_handle);
  1318. m_ConnHandleList.Append(connection_handle);
  1319. /*
  1320. ** Add the user's tag number to the list of outstanding
  1321. ** user ids along with its associated connection.
  1322. */
  1323. m_ConnHdlTagNumberList2.Append(connect_pdu.u.connect_join_response.tag, connection_handle);
  1324. }
  1325. else
  1326. {
  1327. WARNING_OUT(("CConf::ConfJoinIndResponse: ConnectProviderResponse failed, mcs_error=%d, result=%d", mcs_error, result));
  1328. rc = g_pMCSIntf->TranslateMCSIFErrorToGCCError(mcs_error);
  1329. goto MyExit;
  1330. }
  1331. // Free up any memory allocated by the conatiners to build the PDU structs
  1332. if (connect_pdu.u.connect_join_response.bit_mask & CJRS_CONDUCTOR_PRIVS_PRESENT)
  1333. {
  1334. m_pConductorPrivilegeList->FreePrivilegeListPDU(
  1335. connect_pdu.u.connect_join_response.cjrs_conductor_privs);
  1336. }
  1337. if (connect_pdu.u.connect_join_response.bit_mask & CJRS_CONDUCTED_PRIVS_PRESENT)
  1338. {
  1339. m_pConductModePrivilegeList->FreePrivilegeListPDU(
  1340. connect_pdu.u.connect_join_response.cjrs_conducted_privs);
  1341. }
  1342. if (connect_pdu.u.connect_join_response.bit_mask & CJRS_NON_CONDUCTED_PRIVS_PRESENT)
  1343. {
  1344. m_pNonConductModePrivilegeList->FreePrivilegeListPDU(
  1345. connect_pdu.u.connect_join_response.cjrs_non_conducted_privs);
  1346. }
  1347. ASSERT(GCC_NO_ERROR == rc);
  1348. MyExit:
  1349. if (GCC_NO_ERROR != rc)
  1350. {
  1351. g_pGCCController->FailConfJoinIndResponse(m_nConfID, connection_handle);
  1352. }
  1353. g_pGCCController->RemoveConfJoinInfo(connection_handle);
  1354. DebugExitINT(CConf::ConfJoinIndResponse, rc);
  1355. return rc;
  1356. }
  1357. /*
  1358. * CConf::ConfInviteResponse()
  1359. *
  1360. * Public Function Description
  1361. * This routine is called from the owner object when a
  1362. * ConferenceInviteResponse primitive needs to be processed.
  1363. */
  1364. GCCError CConf::
  1365. ConfInviteResponse
  1366. (
  1367. UserID parent_user_id,
  1368. UserID top_user_id,
  1369. TagNumber tag_number,
  1370. ConnectionHandle connection_handle,
  1371. BOOL fSecure,
  1372. PDomainParameters domain_parameters,
  1373. CUserDataListContainer *user_data_list
  1374. )
  1375. {
  1376. GCCError rc = GCC_ALLOCATION_FAILURE;
  1377. LPBYTE encoded_pdu;
  1378. UINT encoded_pdu_length;
  1379. MCSError mcs_error;
  1380. ConnectGCCPDU connect_pdu;
  1381. DebugEntry(CConf::ConfInviteResponse);
  1382. ASSERT(FALSE == m_fSecure);
  1383. m_fSecure = fSecure;
  1384. // First make a copy of the new domain parameters if they exists
  1385. if (domain_parameters != NULL)
  1386. {
  1387. DBG_SAVE_FILE_LINE
  1388. m_pDomainParameters = new DomainParameters;
  1389. if (NULL == m_pDomainParameters)
  1390. {
  1391. ERROR_OUT(("CConf::ConfInviteResponse: can't create domain parameters"));
  1392. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  1393. goto MyExit;
  1394. }
  1395. // structure-wide shallow copy
  1396. *m_pDomainParameters = *domain_parameters;
  1397. }
  1398. m_eNodeType = INVITED_NODE;
  1399. m_nParentIDTagNumber = tag_number;
  1400. m_hParentConnection = connection_handle;
  1401. /*
  1402. ** First we must send the invite response back to the requester.
  1403. ** If we've gotten this far it will always be a positive response.
  1404. */
  1405. // Create the ConferenceInviteRequest PDU here.
  1406. connect_pdu.choice = CONFERENCE_INVITE_RESPONSE_CHOSEN;
  1407. connect_pdu.u.conference_invite_response.bit_mask = 0;
  1408. if (user_data_list != NULL)
  1409. {
  1410. rc = user_data_list->GetUserDataPDU(
  1411. &connect_pdu.u.conference_invite_response.cirs_user_data);
  1412. if (GCC_NO_ERROR != rc)
  1413. {
  1414. ERROR_OUT(("CConf::ConfInviteResponse: can't get user data, rc=%d", rc));
  1415. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  1416. goto MyExit;
  1417. }
  1418. connect_pdu.u.conference_invite_response.bit_mask |= CIRS_USER_DATA_PRESENT;
  1419. }
  1420. connect_pdu.u.conference_invite_response.result =
  1421. ::TranslateGCCResultToInviteResult(GCC_RESULT_SUCCESSFUL);
  1422. if (! g_GCCCoder->Encode((LPVOID) &connect_pdu,
  1423. CONNECT_GCC_PDU,
  1424. PACKED_ENCODING_RULES,
  1425. &encoded_pdu,
  1426. &encoded_pdu_length))
  1427. {
  1428. ERROR_OUT(("CConf::ConfInviteResponse: can't encode"));
  1429. rc = GCC_ALLOCATION_FAILURE;
  1430. goto MyExit;
  1431. }
  1432. /*
  1433. ** Note that the TransportStrings are casted twice here. It
  1434. ** must be done this way to satisfy the compiler. Sorry about
  1435. ** not adhearing to coding standards.
  1436. */
  1437. mcs_error = g_pMCSIntf->ConnectProviderResponse (
  1438. connection_handle,
  1439. &m_nConfID,
  1440. m_pDomainParameters,
  1441. RESULT_SUCCESSFUL,
  1442. encoded_pdu,
  1443. encoded_pdu_length);
  1444. g_GCCCoder->FreeEncoded(encoded_pdu);
  1445. if (MCS_NO_ERROR != mcs_error)
  1446. {
  1447. WARNING_OUT(("CConf::ConfInviteResponse: ConnectProviderRequest failed: rc=%d", mcs_error));
  1448. rc = g_pMCSIntf->TranslateMCSIFErrorToGCCError(mcs_error);
  1449. goto MyExit;
  1450. }
  1451. /*
  1452. ** Now create the user attachment object and wait for the
  1453. ** confirm which occurs after all the proper channels are
  1454. ** joined. The user object will determine the top provider ID.
  1455. ** When the user create confirm is received the response PDU
  1456. ** will be sent out in the Connect Provider Response.
  1457. */
  1458. DBG_SAVE_FILE_LINE
  1459. m_pMcsUserObject = new MCSUser(this, top_user_id, parent_user_id, &rc);
  1460. if (NULL == m_pMcsUserObject || GCC_NO_ERROR != rc)
  1461. {
  1462. ERROR_OUT(("CConf::ConfInviteResponse: Creation of User Attachment failed, rc=%d", rc));
  1463. if (NULL != m_pMcsUserObject)
  1464. {
  1465. m_pMcsUserObject->Release();
  1466. m_pMcsUserObject = NULL;
  1467. }
  1468. else
  1469. {
  1470. rc = GCC_ALLOCATION_FAILURE;
  1471. }
  1472. goto MyExit;
  1473. }
  1474. rc = GCC_NO_ERROR;
  1475. MyExit:
  1476. if (GCC_NO_ERROR != rc)
  1477. {
  1478. if (NULL != domain_parameters)
  1479. {
  1480. delete m_pDomainParameters;
  1481. m_pDomainParameters = NULL;
  1482. }
  1483. }
  1484. DebugExitINT(CConf::ConfInviteResponse, rc);
  1485. return rc;
  1486. }
  1487. /*
  1488. * CConf::RegisterAppSap()
  1489. *
  1490. * Public Function Description
  1491. * This routine is called from the owner object whenever an application
  1492. * SAP becomes a candidate for Enrollment. This will happen whenever
  1493. * Applications SAPs exists at the same time a conference becomes
  1494. * established. It will also be called whenever a conference exists
  1495. * and a new application SAP is created.
  1496. */
  1497. GCCError CConf::
  1498. RegisterAppSap ( CAppSap *pAppSap )
  1499. {
  1500. GCCError rc;
  1501. GCCConferenceName conference_name;
  1502. GCCNumericString conference_modifier;
  1503. DebugEntry(CConf::RegisterAppSap);
  1504. if (m_fConfIsEstablished)
  1505. {
  1506. /*
  1507. ** We first check to see if the application is already registered.
  1508. ** If so, we do not add it to the list of registered applications
  1509. ** again.
  1510. */
  1511. if (NULL == m_RegisteredAppSapList.Find(pAppSap))
  1512. {
  1513. // Add the application sap pointer to the registered sap list.
  1514. pAppSap->AddRef();
  1515. m_RegisteredAppSapList.Append(pAppSap);
  1516. /*
  1517. ** Get the conference name and modifier to send back in the
  1518. ** permission to enroll indication.
  1519. */
  1520. GetConferenceNameAndModifier(&conference_name, &conference_modifier);
  1521. // Inform the application that it can now enroll.
  1522. pAppSap->PermissionToEnrollIndication(m_nConfID, TRUE);
  1523. }
  1524. rc = GCC_NO_ERROR;
  1525. }
  1526. else
  1527. {
  1528. ERROR_OUT(("CConf::RegisterAppSap: CConf not established"));
  1529. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1530. }
  1531. DebugExitINT(CConf::RegisterAppSap, rc);
  1532. return rc;
  1533. }
  1534. /*
  1535. * CConf::UnRegisterAppSap ()
  1536. *
  1537. * Public Function Description
  1538. * This routine is called from the owner object whenever an application
  1539. * SAP becomes unavailable due to whatever reason. This routine is
  1540. * responsible for unenrolling any APEs from any rosters that it might have
  1541. * used this SAP to enroll with.
  1542. */
  1543. GCCError CConf::
  1544. UnRegisterAppSap ( CAppSap *pAppSap )
  1545. {
  1546. GCCError rc = GCC_NO_ERROR;
  1547. GCCConferenceName conference_name;
  1548. GCCNumericString conference_modifier;
  1549. DebugEntry(CConf::UnRegisterAppSap);
  1550. /*
  1551. ** We first check to see if the application is already registered.
  1552. ** If so, we do not add it to the list of registered applications
  1553. ** again.
  1554. */
  1555. if (! m_RegisteredAppSapList.Find(pAppSap))
  1556. {
  1557. TRACE_OUT(("CConf::UnRegisterAppSap: app not registered"));
  1558. rc = GCC_APPLICATION_NOT_REGISTERED;
  1559. goto MyExit;
  1560. }
  1561. /*
  1562. ** Get the conference name and modifier to send back in the
  1563. ** permission to enroll indication.
  1564. */
  1565. GetConferenceNameAndModifier(&conference_name, &conference_modifier);
  1566. // Inform the application that it can no longer enroll.
  1567. pAppSap->PermissionToEnrollIndication(m_nConfID, FALSE);
  1568. /*
  1569. ** We unenroll the appropriate APE. Note that we will only send roster updates
  1570. ** if the conference is established.
  1571. */
  1572. RemoveSAPFromAPEList(pAppSap);
  1573. #if 0 // LONCHANC: UnRegisterAppSap should not affect the roster.
  1574. // Only UnenrollApp will affect the app roster.
  1575. if (m_fConfIsEstablished)
  1576. {
  1577. /*
  1578. ** Here we flush any PDU data or messages that might have gotten
  1579. ** queued up when this SAP we was being unenrolled.
  1580. ** An error here is considered FATAL in that the conference
  1581. ** information base at this node is now corrupted therefore we
  1582. ** terminate the conference.
  1583. */
  1584. rc = AsynchFlushRosterData();
  1585. if (GCC_NO_ERROR != rc)
  1586. {
  1587. ERROR_OUT(("CConf::UnRegisterAppSap: can't flush roster data, rc=%d", rc));
  1588. //
  1589. // Do not need to initiate termination because we are
  1590. // either already in termination procedure or
  1591. // the application is going away.
  1592. //
  1593. #if 0
  1594. InitiateTermination((rc == GCC_ALLOCATION_FAILURE) ?
  1595. GCC_REASON_ERROR_LOW_RESOURCES :
  1596. GCC_REASON_ERROR_TERMINATION,
  1597. 0);
  1598. #endif // 0
  1599. goto MyExit;
  1600. }
  1601. }
  1602. #endif // 0
  1603. // Remove the application sap from list of registered SAPs
  1604. if (m_RegisteredAppSapList.Remove(pAppSap))
  1605. {
  1606. //
  1607. // Only when this app sap is still in the list, we then can
  1608. // release it. It is possible that this app sap has been
  1609. // unregistered by the app due to permission-to-enroll-ind
  1610. // we just sent earlier.
  1611. //
  1612. pAppSap->Release();
  1613. }
  1614. ASSERT(GCC_NO_ERROR == rc);
  1615. MyExit:
  1616. DebugExitINT(CConf::UnRegisterAppSap, rc);
  1617. return rc;
  1618. }
  1619. /*
  1620. * CConf::AppEnrollRequest()
  1621. *
  1622. * Public Function Description
  1623. * This routine is called from the owner object when an
  1624. * Application is requesting to enroll with this conference.
  1625. *
  1626. * Caveats
  1627. * Enroll confirms are performed by the application roster manager so
  1628. * anyplace where the application roster manager isn't informed of the
  1629. * enroll we must perform the enroll confirm here in this routine.
  1630. */
  1631. GCCError CConf::
  1632. AppEnrollRequest
  1633. (
  1634. CAppSap *pAppSap,
  1635. GCCEnrollRequest *pReq,
  1636. GCCRequestTag nReqTag
  1637. )
  1638. {
  1639. GCCError rc = GCC_NO_ERROR;
  1640. CAppRosterMgr *pAppRosterMgr;
  1641. CAppRosterMgr *pNewAppRosterMgr = NULL; // a must
  1642. EntityID eid, new_eid = GCC_INVALID_EID; // a must
  1643. GCCNodeID nid;
  1644. GCCAppEnrollConfirm aec;
  1645. DebugEntry(CConf::AppEnrollRequest);
  1646. TRACE_OUT_EX(ZONE_T120_APP_ROSTER, ("CConf::AppEnrollRequest: "
  1647. "enrolled?=%u\r\n", (UINT) pReq->fEnroll));
  1648. // If the conference is not established return an error.
  1649. if (! m_fConfIsEstablished)
  1650. {
  1651. WARNING_OUT(("CConf::AppEnrollRequest: CConf not established"));
  1652. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1653. goto MyExit;
  1654. }
  1655. if (! m_RegisteredAppSapList.Find(pAppSap))
  1656. {
  1657. WARNING_OUT(("CConf::AppEnrollRequest: app not registered"));
  1658. rc = GCC_APPLICATION_NOT_REGISTERED;
  1659. goto MyExit;
  1660. }
  1661. if (pReq->fEnroll)
  1662. {
  1663. m_cEnrollRequests++;
  1664. }
  1665. else
  1666. {
  1667. m_cEnrollRequests--;
  1668. }
  1669. TRACE_OUT_EX(ZONE_T120_APP_ROSTER, ("CConf::AppEnrollRequest: cEnroll=%d\r\n", m_cEnrollRequests));
  1670. if (m_cEnrollRequests < 0)
  1671. {
  1672. //
  1673. // LONCHANC: It seems to me that the upper layer does unenroll without
  1674. // enroll first. it happens when someone calls me.
  1675. // We should change this later and have a way to know whether the app
  1676. // already enrolled or not.
  1677. //
  1678. m_cEnrollRequests = 0;
  1679. }
  1680. // get the node id
  1681. nid = m_pMcsUserObject->GetMyNodeID();
  1682. /*
  1683. ** Is the application enrolling or unenrolling? Here we set up the
  1684. ** application roster and APE information if enrolling.
  1685. */
  1686. if (pReq->fEnroll) // Appplication is enrolling
  1687. {
  1688. TRACE_OUT(("CConf::AppEnrollRequest: Application is Enrolling"));
  1689. /*
  1690. ** First determine if this APE has already enrolled with this
  1691. ** conference. If it hasn't we must generate a new EntityID for
  1692. ** this APE.
  1693. */
  1694. rc = GetEntityIDFromAPEList(pAppSap, pReq->pSessionKey, &eid);
  1695. if (rc == GCC_APP_NOT_ENROLLED)
  1696. {
  1697. rc = GenerateEntityIDForAPEList(pAppSap, pReq->pSessionKey, &new_eid);
  1698. if (GCC_NO_ERROR != rc)
  1699. {
  1700. ERROR_OUT(("CConf::AppEnrollRequest: can't generate entity id, rc=%d", rc));
  1701. goto MyExit;
  1702. }
  1703. eid = new_eid;
  1704. m_pAppRegistry->EnrollAPE(eid, pAppSap);
  1705. }
  1706. /*
  1707. ** This takes care of setting up the application roster manager
  1708. ** if none exists or it will call the appropriate manager with
  1709. ** the enroll.
  1710. */
  1711. pAppRosterMgr = GetAppRosterManager(pReq->pSessionKey);
  1712. if (pAppRosterMgr == NULL)
  1713. {
  1714. DBG_SAVE_FILE_LINE
  1715. pNewAppRosterMgr = new CAppRosterMgr(
  1716. pReq->pSessionKey,
  1717. NULL,
  1718. m_nConfID,
  1719. m_pMcsUserObject,
  1720. this,
  1721. &rc);
  1722. if (NULL == pNewAppRosterMgr || GCC_NO_ERROR != rc)
  1723. {
  1724. ERROR_OUT(("CConf::AppEnrollRequest: can't create app roster mgr, rc=%d", rc));
  1725. rc = GCC_ALLOCATION_FAILURE;
  1726. goto MyExit;
  1727. }
  1728. pAppRosterMgr = pNewAppRosterMgr;
  1729. }
  1730. /*
  1731. ** Doing the enroll here ensures that an empty roster
  1732. ** manager will not get put in to the roster manager
  1733. ** list if the Enroll Fails.
  1734. */
  1735. rc = pAppRosterMgr->EnrollRequest(pReq, eid, nid, pAppSap);
  1736. if (GCC_NO_ERROR != rc)
  1737. {
  1738. ERROR_OUT(("CConf::AppEnrollRequest: EnrollRequest failed, rc=%d", rc));
  1739. goto MyExit;
  1740. }
  1741. /*
  1742. ** If this is a new roster manager we will append it to
  1743. ** the list of roster managers here if no errors occcured.
  1744. */
  1745. if (pNewAppRosterMgr != NULL)
  1746. {
  1747. m_AppRosterMgrList.Append(pNewAppRosterMgr);
  1748. }
  1749. /*
  1750. ** Here we inform the newly enrolled application of the
  1751. ** conductor status if the conference is conductible.
  1752. */
  1753. if (m_fConfConductible)
  1754. {
  1755. if (m_nConductorNodeID != 0)
  1756. {
  1757. pAppSap->ConductorAssignIndication(m_nConductorNodeID, m_nConfID);
  1758. }
  1759. else
  1760. {
  1761. pAppSap->ConductorReleaseIndication(m_nConfID);
  1762. }
  1763. }
  1764. }
  1765. else // Appplication is unenrolling
  1766. {
  1767. TRACE_OUT(("CConf::AppEnrollRequest: Application is UnEnrolling"));
  1768. if (pReq->pSessionKey != NULL)
  1769. {
  1770. rc = GetEntityIDFromAPEList(pAppSap, pReq->pSessionKey, &eid);
  1771. if (rc != GCC_NO_ERROR)
  1772. {
  1773. WARNING_OUT(("CConf::AppEnrollRequest: app not enrolled"));
  1774. goto MyExit;
  1775. }
  1776. pAppRosterMgr = GetAppRosterManager(pReq->pSessionKey);
  1777. if (NULL == pAppRosterMgr)
  1778. {
  1779. WARNING_OUT(("CConf::AppEnrollRequest: app not enrolled"));
  1780. rc = GCC_APP_NOT_ENROLLED;
  1781. goto MyExit;
  1782. }
  1783. /*
  1784. ** UnEnroll this APE from the specified session.
  1785. ** Note that the application roster manager will send
  1786. ** the enroll confirm.
  1787. */
  1788. pAppRosterMgr->UnEnrollRequest(pReq->pSessionKey, eid);
  1789. // UnEnroll this APE from the registry
  1790. m_pAppRegistry->UnEnrollAPE(eid);
  1791. /*
  1792. ** Since this APE is no longer enrolled remove it from
  1793. ** the list of APEs.
  1794. */
  1795. DeleteEnrolledAPE(eid);
  1796. }
  1797. else
  1798. {
  1799. TRACE_OUT(("CConf::AppEnrollRequest: null session key"));
  1800. /*
  1801. ** Since a null session key was passed in we will go ahead
  1802. ** and unenroll all the APEs associated with this sap.
  1803. */
  1804. RemoveSAPFromAPEList(pAppSap);
  1805. }
  1806. }
  1807. /*
  1808. ** Here we take care of sending the enroll confirm to the application
  1809. ** SAP that enrolled. We also flush any roster PDUs and messages that
  1810. ** might have been queued up during the enrollment process above. Note
  1811. ** that we only send a successful enroll confirm if no errors occured.
  1812. */
  1813. ASSERT(GCC_NO_ERROR == rc);
  1814. /*
  1815. ** First we sent the enroll confirm. It is important to send this
  1816. ** before the flush so that the node ID and entity ID will be
  1817. ** received by a top provider node before the roster is delivered
  1818. ** with the applications record in it. This makes it easier on the
  1819. ** developer when trying to determine if the enrolled record is in
  1820. ** the roster when the roster report is received.
  1821. */
  1822. aec.nConfID = m_nConfID;
  1823. aec.sidMyself = pReq->pSessionKey->session_id;
  1824. aec.eidMyself = eid;
  1825. aec.nidMyself = nid;
  1826. aec.nResult = GCC_RESULT_SUCCESSFUL;
  1827. aec.nReqTag = nReqTag;
  1828. pAppSap->AppEnrollConfirm(&aec);
  1829. /*
  1830. ** Now we flush all the application roster managers of any PDU data
  1831. ** that might have been queued up during enrollment. This also
  1832. ** gives the roster managers a chance to deliver roster update if
  1833. ** necessary. Note that we build and deliver the high level
  1834. ** portion of the PDU here. Since only application roster stuff will be
  1835. ** sent in this pdu we must set the pointer to the conference
  1836. ** information to NULL so that the encoder wont try to encode it.
  1837. ** An error here is considered FATAL in that the conference information
  1838. ** base at this node is now corrupted therefore we terminate the
  1839. ** conference. Note that we only do the flush here if the start up
  1840. ** alarm has expired.
  1841. */
  1842. rc = AsynchFlushRosterData();
  1843. if (rc != GCC_NO_ERROR)
  1844. {
  1845. ERROR_OUT(("CConf::AppEnrollRequest: can't flush roster data, rc=%d", rc));
  1846. InitiateTermination((rc == GCC_ALLOCATION_FAILURE) ?
  1847. GCC_REASON_ERROR_LOW_RESOURCES :
  1848. GCC_REASON_ERROR_TERMINATION,
  1849. 0);
  1850. goto MyExit;
  1851. }
  1852. ASSERT(GCC_NO_ERROR == rc);
  1853. MyExit:
  1854. if (GCC_NO_ERROR != rc && pReq->fEnroll)
  1855. {
  1856. if (NULL != pNewAppRosterMgr)
  1857. {
  1858. pNewAppRosterMgr->Release();
  1859. }
  1860. if (new_eid != GCC_INVALID_EID)
  1861. {
  1862. // UnEnroll this APE from the registry
  1863. m_pAppRegistry->UnEnrollAPE(new_eid);
  1864. DeleteEnrolledAPE(new_eid);
  1865. }
  1866. }
  1867. DebugExitINT(CConf::AppEnrollRequest, rc);
  1868. return rc;
  1869. }
  1870. /*
  1871. * CConf::DisconnectProviderIndication ()
  1872. *
  1873. * Public Function Description
  1874. * This routine is called from the owner object when a
  1875. * Disconnect Provider is received from the MCS interface.
  1876. * Since the owner object has no way of knowing which connections
  1877. * are associated with which conferences it may be possible to
  1878. * receive a disconnect provider for a connection that is not in
  1879. * the conferences list.
  1880. */
  1881. GCCError CConf::
  1882. DisconnectProviderIndication ( ConnectionHandle connection_handle )
  1883. {
  1884. GCCError rc = GCC_NO_ERROR;
  1885. GCCNodeID nidDisconnected;
  1886. DebugEntry(CConf::DisconnectProviderIndication);
  1887. TRACE_OUT(("CConf::DisconnectProviderIndication: connection_handle = %d", connection_handle));
  1888. // reject any pending join ind response
  1889. ConnectionHandle hConn;
  1890. while (NULL != m_JoinRespNamePresentConnHdlList2.Get(&hConn))
  1891. {
  1892. if (NULL != g_pGCCController)
  1893. {
  1894. g_pGCCController->FailConfJoinIndResponse(0, hConn);
  1895. }
  1896. }
  1897. // First check for the parent connection going down.
  1898. if (m_hParentConnection == connection_handle)
  1899. {
  1900. TRACE_OUT(("CConf::DisconnectProviderIndication: Connection == PARENT"));
  1901. /*
  1902. ** If the Parent Connection is broken the conference must be
  1903. ** terminated since this node no longer has access to the top
  1904. ** gcc provider.
  1905. */
  1906. m_hParentConnection = NULL;
  1907. InitiateTermination ( GCC_REASON_PARENT_DISCONNECTED, 0);
  1908. }
  1909. else
  1910. {
  1911. /*
  1912. ** Now check to see if this connection is associated with an ejected
  1913. ** node.
  1914. */
  1915. nidDisconnected = m_pMcsUserObject->GetUserIDFromConnection(connection_handle);
  1916. if (m_EjectedNodeConfirmList.Remove(nidDisconnected))
  1917. {
  1918. #ifdef JASPER
  1919. g_pControlSap->ConfEjectUserConfirm(m_nConfID,
  1920. nidDisconnected,
  1921. GCC_RESULT_SUCCESSFUL);
  1922. #endif // JASPER
  1923. }
  1924. // If this is the convener set its node id back to 0
  1925. if (m_nConvenerNodeID == nidDisconnected)
  1926. m_nConvenerNodeID = 0;
  1927. // Inform the User Attachment object that another user disconnected
  1928. m_pMcsUserObject->UserDisconnectIndication (nidDisconnected);
  1929. ASSERT(0 != connection_handle);
  1930. if (m_ConnHandleList.Remove(connection_handle))
  1931. {
  1932. TRACE_OUT(("CConf::DisconnectProviderIndication: Connection = CHILD"));
  1933. /*
  1934. ** If there is a disconnect pending we must send the disconnect
  1935. ** confirm here and terminate the conference. Note that in this
  1936. ** case, the m_fConfIsEstablished variable was set to FALSE
  1937. ** when the Disconnect Request was issued (therefore a terminate
  1938. ** indication will not be sent).
  1939. */
  1940. if (m_ConnHandleList.IsEmpty() && m_fConfDisconnectPending)
  1941. {
  1942. TRACE_OUT(("CConf::DisconnectProviderIndication: conf disconnect confirm"));
  1943. /*
  1944. ** First inform the control SAP that this node has successfuly
  1945. ** disconnected.
  1946. */
  1947. g_pControlSap->ConfDisconnectConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  1948. // Tell the owner object to terminate this conference
  1949. InitiateTermination(GCC_REASON_NORMAL_TERMINATION, m_pMcsUserObject->GetMyNodeID());
  1950. }
  1951. else
  1952. if (m_ConnHandleList.IsEmpty() && m_fConfTerminatePending)
  1953. {
  1954. TRACE_OUT(("CConf::DisconnectProviderIndication: Terminate Request is Completed"));
  1955. InitiateTermination(m_eConfTerminateReason, m_pMcsUserObject->GetMyNodeID());
  1956. }
  1957. else
  1958. if (m_ConnHandleList.IsEmpty() &&
  1959. ((m_eNodeType == TOP_PROVIDER_NODE) ||
  1960. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE)) &&
  1961. (m_eTerminationMethod == GCC_AUTOMATIC_TERMINATION_METHOD))
  1962. {
  1963. /*
  1964. ** If nothing is left in our connection list and we are the Top
  1965. ** Provider and automatic termination is enabled then terminate
  1966. ** the conference.
  1967. */
  1968. TRACE_OUT(("CConf::DisconnectProviderIndication: AUTOMATIC_TERMINATION"));
  1969. InitiateTermination( GCC_REASON_NORMAL_TERMINATION, 0);
  1970. }
  1971. }
  1972. else
  1973. {
  1974. rc = GCC_INVALID_PARAMETER;
  1975. }
  1976. }
  1977. DebugExitINT(CConf::DisconnectProviderIndication, rc);
  1978. return rc;
  1979. }
  1980. /*
  1981. * void ConfRosterInquireRequest()
  1982. *
  1983. * Public Function Description
  1984. * This function is used to obtain a conference roster. The conference
  1985. * roster is delivered to the requesting command target in a Conference
  1986. * Roster inquire confirm.
  1987. */
  1988. GCCError CConf::
  1989. ConfRosterInquireRequest
  1990. (
  1991. CBaseSap *pSap,
  1992. GCCAppSapMsgEx **ppMsgEx
  1993. )
  1994. {
  1995. GCCError rc = GCC_NO_ERROR;
  1996. CConfRoster *conference_roster;
  1997. LPWSTR pwszConfDescription = NULL;
  1998. GCCConferenceName conference_name;
  1999. GCCNumericString conference_modifier;
  2000. DebugEntry(CConf::ConfRosterInquireRequest);
  2001. if (m_fConfIsEstablished)
  2002. {
  2003. /*
  2004. ** We use the actual conference roster here to build the roster
  2005. ** inquire confirm message. Note that the SAP should NOT free this
  2006. ** roster.
  2007. */
  2008. conference_roster = m_pConfRosterMgr->GetConferenceRosterPointer();
  2009. if (conference_roster != NULL)
  2010. {
  2011. GetConferenceNameAndModifier(&conference_name, &conference_modifier);
  2012. if (m_pwszConfDescription != NULL)
  2013. {
  2014. pwszConfDescription= m_pwszConfDescription;
  2015. }
  2016. pSap->ConfRosterInquireConfirm(m_nConfID,
  2017. &conference_name,
  2018. conference_modifier,
  2019. pwszConfDescription,
  2020. conference_roster,
  2021. GCC_RESULT_SUCCESSFUL,
  2022. ppMsgEx);
  2023. }
  2024. else
  2025. {
  2026. ERROR_OUT(("CConf::ConfRosterInquireRequest: conf roster does not exist"));
  2027. rc = GCC_ALLOCATION_FAILURE;
  2028. }
  2029. }
  2030. else
  2031. {
  2032. ERROR_OUT(("CConf::ConfRosterInquireRequest: conference not established"));
  2033. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  2034. }
  2035. DebugExitINT(CConf:ConfRosterInquireRequest, rc);
  2036. return rc;
  2037. }
  2038. /*
  2039. * CConf::AppRosterInquireRequest()
  2040. *
  2041. * Public Function Description
  2042. * This function is used to obtain a list of application rosters. This
  2043. * list is delivered to the requesting SAP through an Application Roster
  2044. * inquire confirm message.
  2045. */
  2046. GCCError CConf::
  2047. AppRosterInquireRequest
  2048. (
  2049. PGCCSessionKey session_key,
  2050. CAppRosterMsg **ppAppRosterMsgOut
  2051. )
  2052. {
  2053. GCCError rc;
  2054. BOOL roster_manager_found = FALSE;
  2055. CAppRosterMsg *roster_message = NULL;
  2056. CAppRosterMgr *lpAppRosterMgr;
  2057. DebugEntry(CConf::AppRosterInquireRequest);
  2058. if (m_AppRosterMgrList.IsEmpty())
  2059. {
  2060. WARNING_OUT(("CConf::AppRosterInquireRequest: app roster mgr is empty"));
  2061. rc = GCC_NO_SUCH_APPLICATION;
  2062. goto MyExit;
  2063. }
  2064. // First allocate the application roster message
  2065. DBG_SAVE_FILE_LINE
  2066. roster_message = new CAppRosterMsg();
  2067. if (NULL == roster_message)
  2068. {
  2069. ERROR_OUT(("CConf::AppRosterInquireRequest: can't create app roster msg"));
  2070. rc = GCC_ALLOCATION_FAILURE;
  2071. goto MyExit;
  2072. }
  2073. rc = GCC_NO_ERROR;
  2074. m_AppRosterMgrList.Reset();
  2075. if (session_key != NULL)
  2076. {
  2077. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  2078. {
  2079. roster_manager_found = lpAppRosterMgr->IsThisYourSessionKey (session_key);
  2080. if (roster_manager_found)
  2081. {
  2082. rc = lpAppRosterMgr->ApplicationRosterInquire(session_key, roster_message);
  2083. break;
  2084. }
  2085. }
  2086. }
  2087. else
  2088. {
  2089. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  2090. {
  2091. rc = lpAppRosterMgr->ApplicationRosterInquire (NULL, roster_message);
  2092. if (rc != GCC_NO_ERROR)
  2093. break;
  2094. }
  2095. }
  2096. MyExit:
  2097. if (GCC_NO_ERROR == rc)
  2098. {
  2099. *ppAppRosterMsgOut = roster_message;
  2100. // do not call roster_message->Release() because the sap will call it as needed
  2101. }
  2102. else
  2103. {
  2104. if (NULL != roster_message)
  2105. {
  2106. roster_message->Release();
  2107. }
  2108. }
  2109. DebugExitINT(CConf::AppRosterInquireRequest, rc);
  2110. return rc;
  2111. }
  2112. /*
  2113. * CConf::FlushOutgoingPDU()
  2114. *
  2115. * Public Function Description
  2116. * This is the heartbeat for the conference object. The conference
  2117. * is responsible for giving the User Attachment object its
  2118. * heartbeat.
  2119. * Return value:
  2120. * TRUE, if there remain un-processed msgs in the CConf message queue
  2121. * FALSE, if all the msgs in the conference msg queue were processed.
  2122. */
  2123. BOOL CConf::
  2124. FlushOutgoingPDU ( void )
  2125. {
  2126. //GCCError error_value;
  2127. BOOL fFlushMoreData = FALSE;
  2128. if (m_fConfTerminatePending && m_pConfTerminateAlarm != NULL)
  2129. {
  2130. if (m_pConfTerminateAlarm->IsExpired())
  2131. {
  2132. delete m_pConfTerminateAlarm;
  2133. m_pConfTerminateAlarm = NULL;
  2134. InitiateTermination(m_eConfTerminateReason, m_pMcsUserObject->GetTopNodeID());
  2135. }
  2136. else
  2137. {
  2138. fFlushMoreData = TRUE;
  2139. }
  2140. }
  2141. if (m_pMcsUserObject != NULL)
  2142. {
  2143. m_pMcsUserObject->CheckEjectedNodeAlarms();
  2144. fFlushMoreData |= m_pMcsUserObject->FlushOutgoingPDU();
  2145. }
  2146. return fFlushMoreData;
  2147. }
  2148. /*
  2149. * BOOL IsConfEstablished ()
  2150. *
  2151. * Public Function Description
  2152. * The conference is established when it is ready to be enrolled
  2153. * with. No application permission to enrolls should be sent until
  2154. * this routine returns TRUE.
  2155. */
  2156. /*
  2157. * BOOL IsConfTopProvider ()
  2158. *
  2159. * Public Function Description
  2160. * Function informs whether this node is the Top Provider of the
  2161. * conference.
  2162. */
  2163. /*
  2164. * GCCNodeID GetTopProvider ()
  2165. *
  2166. * Public Function Description
  2167. * Function returns the GCCNodeID of the Top Provider of the conference.
  2168. */
  2169. /*
  2170. * BOOL DoesConvenerExists ()
  2171. *
  2172. * Public Function Description
  2173. * This function informs whether or not the convener is still joined to
  2174. * this conference.
  2175. */
  2176. /*
  2177. * LPSTR GetNumericConfName()
  2178. *
  2179. * Public Function Description
  2180. * Returns a pointer to the numeric portion of the conference name. Used
  2181. * for comparisons.
  2182. */
  2183. /*
  2184. * LPWSTR GetTextConfName()
  2185. *
  2186. * Public Function Description
  2187. * Returns a pointer to the text portion of the conference name. Used for
  2188. * comparisons.
  2189. */
  2190. /*
  2191. * LPSTR GetConfModifier()
  2192. *
  2193. * Public Function Description
  2194. * Returns a pointer to the conference name modifier.
  2195. */
  2196. /*
  2197. * LPWSTR GetConfDescription()
  2198. *
  2199. * Public Function Description
  2200. * Returns a pointer to the conference description.
  2201. */
  2202. /*
  2203. * CNetAddrListContainer *GetNetworkAddressList()
  2204. *
  2205. * Public Function Description
  2206. * Returns a pointer to the network address list.
  2207. */
  2208. /*
  2209. * GCCConfID GetConfID()
  2210. *
  2211. * Public Function Description
  2212. * Returns the conference ID.
  2213. */
  2214. /*
  2215. * BOOL IsConfListed()
  2216. *
  2217. * Public Function Description
  2218. * Returns the listed flag.
  2219. */
  2220. /*
  2221. * BOOL IsConfPasswordInTheClear()
  2222. *
  2223. * Public Function Description
  2224. * Returns the password protected flag.
  2225. */
  2226. /*
  2227. * BOOL IsConfLocked()
  2228. *
  2229. * Public Function Description
  2230. * Returns the locked flag.
  2231. */
  2232. /*
  2233. ** These routines operate on the m_EnrolledApeEidList2.
  2234. */
  2235. /*
  2236. * CConf::GetEntityIDFromAPEList ()
  2237. *
  2238. * Private Function Description
  2239. * This routine determines what the entity id is for the specified APE
  2240. * (note that an APE is defined by its SAP handle and the session key
  2241. * of the session it is enrolled in). If there is no entity ID associated
  2242. * with this APE an error is returned.
  2243. *
  2244. * Formal Parameters:
  2245. * hSap - (i) SAP handle associated with the entity ID being
  2246. * searched for.
  2247. * session_key - (i) Session key associated with the entity ID being
  2248. * searched for.
  2249. * entity_id - (o) The found entity ID is returned here (or zero if
  2250. * none is found).
  2251. *
  2252. * Return Value
  2253. * GCC_NO_ERROR - No error occured.
  2254. * GCC_ALLOCATION_FAILURE - A resource error occured allocating session
  2255. * key data.
  2256. * GCC_APP_NOT_ENROLLED - Entity ID was not found.
  2257. *
  2258. * Side Effects
  2259. * None.
  2260. *
  2261. * Caveats
  2262. * None.
  2263. */
  2264. GCCError CConf::
  2265. GetEntityIDFromAPEList
  2266. (
  2267. CAppSap *pAppSap,
  2268. PGCCSessionKey session_key,
  2269. GCCEntityID *pEid
  2270. )
  2271. {
  2272. GCCError rc = GCC_ALLOCATION_FAILURE;
  2273. CSessKeyContainer *pSessKey;
  2274. *pEid = GCC_INVALID_EID;
  2275. DBG_SAVE_FILE_LINE
  2276. pSessKey = new CSessKeyContainer(session_key, &rc);
  2277. if (pSessKey != NULL && rc == GCC_NO_ERROR)
  2278. {
  2279. GCCEntityID eid;
  2280. ENROLLED_APE_INFO *lpEnrAPEInfo;
  2281. m_EnrolledApeEidList2.Reset();
  2282. while (NULL != (lpEnrAPEInfo = m_EnrolledApeEidList2.Iterate(&eid)))
  2283. {
  2284. if (pAppSap == lpEnrAPEInfo->pAppSap &&
  2285. *pSessKey == *lpEnrAPEInfo->session_key)
  2286. {
  2287. *pEid = eid;
  2288. break;
  2289. }
  2290. }
  2291. if (*pEid == GCC_INVALID_EID)
  2292. {
  2293. TRACE_OUT(("CConf::GetEntityIDFromAPEList: App NOT Enrolled"));
  2294. rc = GCC_APP_NOT_ENROLLED;
  2295. }
  2296. }
  2297. // Free up the temporary session key.
  2298. if (NULL != pSessKey)
  2299. {
  2300. pSessKey->Release();
  2301. }
  2302. return rc;
  2303. }
  2304. /*
  2305. * CConf::GenerateEntityIDForAPEList ()
  2306. *
  2307. * Private Function Description
  2308. * This function is responsible for generating a unqiue entity ID for
  2309. * the specified APE.
  2310. *
  2311. * Formal Parameters:
  2312. * hSap - (i) SAP handle associated with the entity ID being
  2313. * generated.
  2314. * session_key - (i) Session key associated with the entity ID being
  2315. * generated.
  2316. * entity_id - (o) The generated entity ID is returned here.
  2317. *
  2318. * Return Value
  2319. * GCC_NO_ERROR - No error occured.
  2320. * GCC_ALLOCATION_FAILURE - A resource error occured.
  2321. *
  2322. * Side Effects
  2323. * None.
  2324. *
  2325. * Caveats
  2326. * None.
  2327. */
  2328. GCCError CConf::
  2329. GenerateEntityIDForAPEList
  2330. (
  2331. CAppSap *pAppSap,
  2332. PGCCSessionKey session_key,
  2333. GCCEntityID *pEid
  2334. )
  2335. {
  2336. GCCError rc = GCC_ALLOCATION_FAILURE;
  2337. CSessKeyContainer *pSessKey = NULL; // a must
  2338. EntityID eidOriginal;
  2339. ENROLLED_APE_INFO *enrolled_ape_info = NULL; // a must
  2340. /*
  2341. ** First find an entity id that has not been used. If all of the IDs
  2342. ** are in use we return an allocation failure.
  2343. */
  2344. *pEid = GCC_INVALID_EID;
  2345. eidOriginal = m_nAPEEntityID;
  2346. while (TRUE)
  2347. {
  2348. if (++m_nAPEEntityID != GCC_INVALID_EID)
  2349. {
  2350. if (NULL == m_EnrolledApeEidList2.Find(m_nAPEEntityID))
  2351. {
  2352. // the new entity ID does not exist. job is done.
  2353. *pEid = m_nAPEEntityID;
  2354. break;
  2355. }
  2356. if (m_nAPEEntityID == eidOriginal)
  2357. {
  2358. ERROR_OUT(("CConf::GenerateEntityIDForAPEList: use up all entity IDs"));
  2359. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  2360. goto MyExit;
  2361. }
  2362. }
  2363. }
  2364. ASSERT(GCC_INVALID_EID != *pEid);
  2365. /*
  2366. ** Now if no errors occured we will create the enrolled APE info structure
  2367. ** that will be stored in the enrolled APE list.
  2368. */
  2369. //
  2370. // LONCHANC: We should avoid this memory allocation. ENROLLED_APE_INFO has only 2 dwords!
  2371. //
  2372. DBG_SAVE_FILE_LINE
  2373. enrolled_ape_info = new ENROLLED_APE_INFO;
  2374. if (NULL == enrolled_ape_info)
  2375. {
  2376. ERROR_OUT(("CConf::GenerateEntityIDForAPEList: can't create ENROLLED_APE_INFO"));
  2377. ASSERT(GCC_ALLOCATION_FAILURE == rc);
  2378. goto MyExit;
  2379. }
  2380. enrolled_ape_info->pAppSap = pAppSap;
  2381. DBG_SAVE_FILE_LINE
  2382. pSessKey = new CSessKeyContainer(session_key, &rc);
  2383. if (pSessKey != NULL && rc == GCC_NO_ERROR)
  2384. {
  2385. enrolled_ape_info->session_key = pSessKey;
  2386. m_EnrolledApeEidList2.Append(*pEid, enrolled_ape_info);
  2387. }
  2388. MyExit:
  2389. if (GCC_NO_ERROR != rc)
  2390. {
  2391. delete enrolled_ape_info;
  2392. if (NULL != pSessKey)
  2393. {
  2394. pSessKey->Release();
  2395. }
  2396. }
  2397. return rc;
  2398. }
  2399. /*
  2400. * CConf::RemoveSAPFromAPEList ()
  2401. *
  2402. * Private Function Description
  2403. * This routine takes care of removing all the references to a single
  2404. * sap from the m_EnrolledApeEidList2. It is also responsible for unenrolling
  2405. * all of these APEs from the appropriate Application SAPs.
  2406. *
  2407. * Formal Parameters:
  2408. * hSap - (i) SAP handle to remove and unenroll.
  2409. *
  2410. * Return Value
  2411. * None.
  2412. *
  2413. * Side Effects
  2414. * None.
  2415. *
  2416. * Caveats
  2417. * None.
  2418. */
  2419. void CConf::
  2420. RemoveSAPFromAPEList ( CAppSap *pAppSap )
  2421. {
  2422. GCCEntityID eid;
  2423. ENROLLED_APE_INFO *lpEnrAPEInfo;
  2424. /*
  2425. ** We make a temporary copy of the list here so that we can remove
  2426. ** members from it while we are iterating on it.
  2427. */
  2428. while (NULL != (lpEnrAPEInfo = GetEnrolledAPEbySap(pAppSap, &eid)))
  2429. {
  2430. CAppRosterMgr *lpAppRosterMgr;
  2431. /*
  2432. ** Here we remove the entities associated with this application
  2433. ** from any application rosters it is enrolled in.
  2434. */
  2435. m_AppRosterMgrList.Reset();
  2436. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  2437. {
  2438. TRACE_OUT(("CConf::RemoveSAPFromAPEList: remove entity = %d", (int) eid));
  2439. lpAppRosterMgr->RemoveEntityReference(eid);
  2440. }
  2441. /*
  2442. ** We must remove any references to this SAP from the
  2443. ** registry so that any outstanding request by this SAP
  2444. ** will not be processed.
  2445. */
  2446. m_pAppRegistry->UnEnrollAPE(eid);
  2447. /*
  2448. ** Since this APE is no longer enrolled remove it from
  2449. ** the list of APEs.
  2450. */
  2451. DeleteEnrolledAPE(eid);
  2452. }
  2453. }
  2454. /*
  2455. * CConf::DoesSAPHaveEnrolledAPE ()
  2456. *
  2457. * Private Function Description
  2458. * This routine is responsible for determining if there is a single
  2459. * (or multiple) APEs enrolled through the specified SAP handle.
  2460. *
  2461. * Formal Parameters:
  2462. * sap_handle - (i) SAP handle of SAP being checked.
  2463. *
  2464. * Return Value
  2465. * TRUE - If SAP does have an enrolled APE.
  2466. * FALSE - If SAP does not have an enrolled APE.
  2467. *
  2468. * Side Effects
  2469. * None.
  2470. *
  2471. * Caveats
  2472. * None.
  2473. */
  2474. ENROLLED_APE_INFO *CConf::
  2475. GetEnrolledAPEbySap
  2476. (
  2477. CAppSap *pAppSap,
  2478. GCCEntityID *pEid
  2479. )
  2480. {
  2481. ENROLLED_APE_INFO *pEnrAPEInfo;
  2482. GCCEntityID eid;
  2483. m_EnrolledApeEidList2.Reset();
  2484. while (NULL != (pEnrAPEInfo = m_EnrolledApeEidList2.Iterate(&eid)))
  2485. {
  2486. if (pAppSap == pEnrAPEInfo->pAppSap)
  2487. {
  2488. if (NULL != pEid)
  2489. {
  2490. *pEid = eid;
  2491. }
  2492. return pEnrAPEInfo;
  2493. }
  2494. }
  2495. return NULL;
  2496. }
  2497. void CConf::
  2498. DeleteEnrolledAPE ( EntityID nEntityID )
  2499. {
  2500. ENROLLED_APE_INFO *lpEnrAPEInfo;
  2501. if (NULL != (lpEnrAPEInfo = m_EnrolledApeEidList2.Remove(nEntityID)))
  2502. {
  2503. if (NULL != lpEnrAPEInfo->session_key)
  2504. {
  2505. lpEnrAPEInfo->session_key->Release();
  2506. }
  2507. delete lpEnrAPEInfo;
  2508. }
  2509. }
  2510. /*
  2511. * GCCError FlushRosterData()
  2512. *
  2513. * Private Function Description
  2514. * This routine flushes all the application roster managers of any PDU data
  2515. * that might be queued up. This also gives the roster managers a chance
  2516. * to deliver roster update if necessary. Note that we build and deliver
  2517. * the high level portion of the PDU here. Since only application roster
  2518. * stuff will be sent in this pdu we must set the pointer to the conference
  2519. * information to NULL so that the encoder wont try to encode it.
  2520. */
  2521. GCCError CConf::
  2522. AsynchFlushRosterData ( void )
  2523. {
  2524. if (NULL != g_pControlSap)
  2525. {
  2526. AddRef();
  2527. ::PostMessage(g_pControlSap->GetHwnd(), CONF_FLUSH_ROSTER_DATA, 0, (LPARAM) this);
  2528. }
  2529. return GCC_NO_ERROR;
  2530. }
  2531. void CConf::
  2532. WndMsgHandler ( UINT uMsg )
  2533. {
  2534. if (CONF_FLUSH_ROSTER_DATA == uMsg)
  2535. {
  2536. FlushRosterData();
  2537. //
  2538. // We AddRef while posting the message.
  2539. //
  2540. Release();
  2541. }
  2542. else
  2543. {
  2544. ERROR_OUT(("WndMsgHandler: invalid msg=%u", uMsg));
  2545. }
  2546. }
  2547. GCCError CConf::
  2548. FlushRosterData ( void )
  2549. {
  2550. GCCError rc = GCC_NO_ERROR;
  2551. DebugEntry(CConf::FlushRosterData);
  2552. if (m_fConfIsEstablished)
  2553. {
  2554. GCCPDU gcc_pdu;
  2555. CAppRosterMgrList RosterMgrDeleteList;
  2556. CAppRosterMgr *lpAppRosterMgr;
  2557. gcc_pdu.choice = INDICATION_CHOSEN;
  2558. gcc_pdu.u.indication.choice = ROSTER_UPDATE_INDICATION_CHOSEN;
  2559. gcc_pdu.u.indication.u.roster_update_indication.refresh_is_full = FALSE;
  2560. gcc_pdu.u.indication.u.roster_update_indication.application_information= NULL;
  2561. // First get any CConf Roster PDU data that exists.
  2562. rc = m_pConfRosterMgr->FlushRosterUpdateIndication(
  2563. &gcc_pdu.u.indication.u.roster_update_indication.node_information);
  2564. if (GCC_NO_ERROR != rc)
  2565. {
  2566. ERROR_OUT(("CConf::FlushRosterData: can't flush conf roster update, rc=%d", rc));
  2567. goto MyExit;
  2568. }
  2569. if (IsReadyToSendAppRosterUpdate())
  2570. {
  2571. PSetOfApplicationInformation *ppSetOfAppInfo;
  2572. PSetOfApplicationInformation pNextSetOfInfo;
  2573. // Set up the pointer to the first application information.
  2574. ppSetOfAppInfo = &gcc_pdu.u.indication.u.roster_update_indication.application_information;
  2575. /*
  2576. ** Here we iterate through all the application roster managers
  2577. ** giving each a chance to append their roster updates to the
  2578. ** roster update PDU and to deliver any necessary roster update
  2579. ** messages.
  2580. */
  2581. m_AppRosterMgrList.Reset();
  2582. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  2583. {
  2584. pNextSetOfInfo = lpAppRosterMgr->FlushRosterUpdateIndication(ppSetOfAppInfo, &rc);
  2585. if (GCC_NO_ERROR != rc)
  2586. {
  2587. ERROR_OUT(("CConf::FlushRosterData: can't flush app roster update, rc=%d", rc));
  2588. goto MyExit;
  2589. }
  2590. if (NULL != pNextSetOfInfo)
  2591. {
  2592. ppSetOfAppInfo = &pNextSetOfInfo->next;
  2593. }
  2594. /*
  2595. ** Here we add the application roster manager to the list of
  2596. ** managers to delete. They we be deleted and removed from the
  2597. ** roster manager list below after the PDU is delivered.
  2598. */
  2599. if (lpAppRosterMgr->IsEmpty())
  2600. {
  2601. m_AppRosterMgrList.Remove(lpAppRosterMgr);
  2602. RosterMgrDeleteList.Append(lpAppRosterMgr);
  2603. }
  2604. }
  2605. } // if ready-to-send-app-roster-update
  2606. else
  2607. {
  2608. TRACE_OUT(("CConf::FlushRosterData: not ready to send app roster update"));
  2609. TRACE_OUT(("cApps=%u, m_cEnrollRequests=%u", m_RegisteredAppSapList.GetCount(), m_cEnrollRequests));
  2610. }
  2611. /*
  2612. ** Here, if there are no errors and there is actual application
  2613. ** information, we go ahead and send out the roster update.
  2614. */
  2615. if (NULL != gcc_pdu.u.indication.u.roster_update_indication.
  2616. application_information
  2617. ||
  2618. NODE_NO_CHANGE_CHOSEN != gcc_pdu.u.indication.u.roster_update_indication.
  2619. node_information.node_record_list.choice)
  2620. {
  2621. TRACE_OUT(("CConf::FlushRosterData: sending roster update indication to mcs"));
  2622. m_pMcsUserObject->RosterUpdateIndication(
  2623. &gcc_pdu,
  2624. IsConfTopProvider() ? FALSE : TRUE);
  2625. }
  2626. /*
  2627. ** Here we cleanup any empty roster managers. Note that we must do this
  2628. ** after delivering the PDU to avoid deleting a roster manager before
  2629. ** using data associated with it (data obtained in the flush).
  2630. */
  2631. RosterMgrDeleteList.DeleteList();
  2632. } // if m_fConfIsEstablished
  2633. ASSERT(GCC_NO_ERROR == rc);
  2634. MyExit:
  2635. DebugExitINT(CConf::FlushRosterData, rc);
  2636. return rc;
  2637. }
  2638. #define MIN_REGISTERED_APPS 2
  2639. BOOL CConf::
  2640. IsReadyToSendAppRosterUpdate ( void )
  2641. {
  2642. if (m_fFirstAppRosterSent)
  2643. {
  2644. TRACE_OUT_EX(ZONE_T120_APP_ROSTER, ("CConf::IsReadyToSendAppRosterUpdate: "
  2645. "YES <first one sent>\r\n"));
  2646. return TRUE;
  2647. }
  2648. BOOL fRet = TRUE;
  2649. if (NULL != m_pConfStartupAlarm &&
  2650. m_pConfStartupAlarm->IsExpired())
  2651. {
  2652. TRACE_OUT_EX(ZONE_T120_APP_ROSTER, ("CConf::IsReadyToSendAppRosterUpdate: "
  2653. "YES <alarm expired>\r\n"));
  2654. // fRet = TRUE;
  2655. }
  2656. else
  2657. {
  2658. UINT cApps = m_RegisteredAppSapList.GetCount();
  2659. if (cApps >= MIN_REGISTERED_APPS &&
  2660. (int) cApps <= m_cEnrollRequests)
  2661. {
  2662. TRACE_OUT_EX(ZONE_T120_APP_ROSTER, ("CConf::IsReadyToSendAppRosterUpdate: "
  2663. "YES <cApp=%u, cEnroll=%d>\r\n", cApps, m_cEnrollRequests));
  2664. // fRet = TRUE;
  2665. }
  2666. else
  2667. {
  2668. TRACE_OUT_EX(ZONE_T120_APP_ROSTER, ("CConf::IsReadyToSendAppRosterUpdate: "
  2669. "NO <cApp=%u, cEnroll=%d>\r\n", cApps, m_cEnrollRequests));
  2670. fRet = FALSE;
  2671. }
  2672. }
  2673. if (fRet)
  2674. {
  2675. m_fFirstAppRosterSent = TRUE;
  2676. delete m_pConfStartupAlarm;
  2677. m_pConfStartupAlarm = NULL;
  2678. }
  2679. return fRet;
  2680. }
  2681. // look for this node ID in the roster's record set.
  2682. BOOL CConf::
  2683. IsThisNodeParticipant ( GCCNodeID nid )
  2684. {
  2685. return ((NULL != m_pConfRosterMgr) ?
  2686. m_pConfRosterMgr->IsThisNodeParticipant(nid) :
  2687. FALSE);
  2688. }
  2689. void CConfList::
  2690. DeleteList ( void )
  2691. {
  2692. CConf *pConf;
  2693. while (NULL != (pConf = Get()))
  2694. {
  2695. pConf->Release();
  2696. }
  2697. }
  2698. void CConfList2::
  2699. DeleteList ( void )
  2700. {
  2701. CConf *pConf;
  2702. while (NULL != (pConf = Get()))
  2703. {
  2704. pConf->Release();
  2705. }
  2706. }
  2707.