Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5872 lines
148 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_GCCNC);
  3. /*
  4. * conf2.cpp
  5. *
  6. * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the second part of the imlementation file for the CConf
  10. * Class. The 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. * This second part of the implementation file deals mainly with the
  17. * command target calls and any callbacks received by the Owner Callback
  18. * function. It also contains many of the utility functions used by the
  19. * conference object.
  20. *
  21. * FOR A MORE DETAILED EXPLANATION OF THIS CLASS SEE THE INTERFACE FILE.
  22. *
  23. *
  24. * Private Instance Variables
  25. *
  26. * ALL PRIVATE INSTANCE VARIABLES ARE DEFINED IN CONF.CPP
  27. *
  28. * Portable:
  29. * Yes
  30. *
  31. * Caveats:
  32. * None.
  33. *
  34. * Author:
  35. * blp
  36. */
  37. #include "conf.h"
  38. #include "gcontrol.h"
  39. #include "translat.h"
  40. #include "ogcccode.h"
  41. #include "string.h"
  42. #define TERMINATE_TIMER_DURATION 10000 // Duration in milliseconds
  43. static const struct ASN1objectidentifier_s WB_ASN1_OBJ_IDEN[6] = {
  44. { (ASN1objectidentifier_t) &(WB_ASN1_OBJ_IDEN[1]), 0 },
  45. { (ASN1objectidentifier_t) &(WB_ASN1_OBJ_IDEN[2]), 0 },
  46. { (ASN1objectidentifier_t) &(WB_ASN1_OBJ_IDEN[3]), 20 },
  47. { (ASN1objectidentifier_t) &(WB_ASN1_OBJ_IDEN[4]), 126 },
  48. { (ASN1objectidentifier_t) &(WB_ASN1_OBJ_IDEN[5]), 0 },
  49. { NULL, 1 }
  50. };
  51. static const struct Key WB_APP_PROTO_KEY = {
  52. 1, (ASN1objectidentifier_t)&WB_ASN1_OBJ_IDEN};
  53. static const struct ASN1objectidentifier_s FT_ASN1_OBJ_IDEN[6] = {
  54. { (ASN1objectidentifier_t) &(FT_ASN1_OBJ_IDEN[1]), 0 },
  55. { (ASN1objectidentifier_t) &(FT_ASN1_OBJ_IDEN[2]), 0 },
  56. { (ASN1objectidentifier_t) &(FT_ASN1_OBJ_IDEN[3]), 20 },
  57. { (ASN1objectidentifier_t) &(FT_ASN1_OBJ_IDEN[4]), 127 },
  58. { (ASN1objectidentifier_t) &(FT_ASN1_OBJ_IDEN[5]), 0 },
  59. { NULL, 1 }
  60. };
  61. static const struct Key FT_APP_PROTO_KEY = {
  62. 1, (ASN1objectidentifier_t)&FT_ASN1_OBJ_IDEN};
  63. struct Key CHAT_APP_PROTO_KEY;
  64. /*
  65. * This is a global variable that has a pointer to the one GCC coder that
  66. * is instantiated by the GCC Controller. Most objects know in advance
  67. * whether they need to use the MCS or the GCC coder, so, they do not need
  68. * this pointer in their constructors.
  69. */
  70. extern CGCCCoder *g_GCCCoder;
  71. extern MCSDLLInterface *g_pMCSIntf;
  72. /*
  73. ** These are GCCCommandTarget Calls. The only command targets that
  74. ** conference is connected to are Application SAPs and the Control SAP, so
  75. ** these Public member functions are only called from above.
  76. */
  77. /*
  78. * CConf::ConfJoinReqResponse()
  79. *
  80. * Public Function Description
  81. * This routine is called when a node controller responds to a join
  82. * request that was issued by a join from a node connected to a subnode.
  83. */
  84. GCCError CConf::
  85. ConfJoinReqResponse
  86. (
  87. UserID receiver_id,
  88. CPassword *password_challenge,
  89. CUserDataListContainer *user_data_list,
  90. GCCResult result
  91. )
  92. {
  93. DebugEntry(CConf::ConfJoinReqResponse);
  94. /*
  95. ** Since the joining node is not directly connected to this
  96. ** node we send the response back through the user channel.
  97. ** It is the user attachment objects responsibility to
  98. ** encode this PDU.
  99. */
  100. if (m_pMcsUserObject != NULL)
  101. {
  102. m_pMcsUserObject->ConferenceJoinResponse(
  103. receiver_id,
  104. m_fClearPassword,
  105. m_fConfLocked,
  106. m_fConfListed,
  107. m_eTerminationMethod,
  108. password_challenge,
  109. user_data_list,
  110. result);
  111. }
  112. DebugExitINT(CConf::ConfJoinReqResponse, GCC_NO_ERROR);
  113. return (GCC_NO_ERROR);
  114. }
  115. /*
  116. * CConf::ConfInviteRequest()
  117. *
  118. * Public Function Description
  119. * This routine is called from the owner object when a
  120. * ConfInviteRequest primitive needs to be processed.
  121. */
  122. GCCError CConf::
  123. ConfInviteRequest
  124. (
  125. LPWSTR pwszCallerID,
  126. TransportAddress calling_address,
  127. TransportAddress called_address,
  128. BOOL fSecure,
  129. CUserDataListContainer *user_data_list,
  130. PConnectionHandle connection_handle
  131. )
  132. {
  133. GCCError rc = GCC_NO_ERROR;
  134. PUChar encoded_pdu;
  135. UINT encoded_pdu_length;
  136. MCSError mcs_error;
  137. ConnectGCCPDU connect_pdu;
  138. INVITE_REQ_INFO *invite_request_info;
  139. DebugEntry(CConf::ConfInviteRequest);
  140. if (! m_fConfIsEstablished)
  141. {
  142. ERROR_OUT(("CConf::ConfInviteRequest: Conference not established"));
  143. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  144. goto MyExit;
  145. }
  146. /*
  147. ** If the conference is locked, we only allow invite request if there
  148. ** are outstanding adds. T.124 states that when a conference is
  149. ** locked you can only use ADD to bring in new nodes to the conference.
  150. */
  151. if (m_fConfLocked && m_AddResponseList.IsEmpty())
  152. {
  153. WARNING_OUT(("CConf::ConfInviteRequest: Conference is locked"));
  154. rc = GCC_INVALID_CONFERENCE;
  155. goto MyExit;
  156. }
  157. // Create the ConfInviteRequest PDU here.
  158. connect_pdu.choice = CONFERENCE_INVITE_REQUEST_CHOSEN;
  159. connect_pdu.u.conference_invite_request.bit_mask = 0;
  160. /*
  161. ** First get the numeric and text (if it exists) portion of the
  162. ** conference name.
  163. */
  164. connect_pdu.u.conference_invite_request.conference_name.bit_mask =0;
  165. ::lstrcpyA(connect_pdu.u.conference_invite_request.conference_name.numeric,
  166. m_pszConfNumericName);
  167. if (m_pwszConfTextName != NULL)
  168. {
  169. connect_pdu.u.conference_invite_request.conference_name.bit_mask |=
  170. CONFERENCE_NAME_TEXT_PRESENT;
  171. connect_pdu.u.conference_invite_request.conference_name.conference_name_text.value =
  172. m_pwszConfTextName;
  173. connect_pdu.u.conference_invite_request.conference_name.conference_name_text.length =
  174. ::lstrlenW(m_pwszConfTextName);
  175. }
  176. // Now set up the privilege list PDU data
  177. if (m_pConductorPrivilegeList != NULL)
  178. {
  179. rc = m_pConductorPrivilegeList->GetPrivilegeListPDU(
  180. &connect_pdu.u.conference_invite_request.cirq_conductor_privs);
  181. if (GCC_NO_ERROR != rc)
  182. {
  183. ERROR_OUT(("CConf::ConfInviteRequest: can't get conductor privilege list, rc=%d", rc));
  184. goto MyExit;
  185. }
  186. connect_pdu.u.conference_invite_request.bit_mask |= CIRQ_CONDUCTOR_PRIVS_PRESENT;
  187. }
  188. if (m_pConductModePrivilegeList != NULL)
  189. {
  190. rc = m_pConductModePrivilegeList->GetPrivilegeListPDU(
  191. &connect_pdu.u.conference_invite_request.cirq_conducted_privs);
  192. if (GCC_NO_ERROR != rc)
  193. {
  194. ERROR_OUT(("CConf::ConfInviteRequest: can't get conduct mode privilege list, rc=%d", rc));
  195. goto MyExit;
  196. }
  197. connect_pdu.u.conference_invite_request.bit_mask |= CIRQ_CONDUCTED_PRIVS_PRESENT;
  198. }
  199. if (m_pNonConductModePrivilegeList != NULL)
  200. {
  201. rc = m_pNonConductModePrivilegeList->GetPrivilegeListPDU(
  202. &connect_pdu.u.conference_invite_request.cirq_non_conducted_privs);
  203. if (GCC_NO_ERROR != rc)
  204. {
  205. ERROR_OUT(("CConf::ConfInviteRequest: can't get non-conduct mode privilege list, rc=%d", rc));
  206. goto MyExit;
  207. }
  208. connect_pdu.u.conference_invite_request.bit_mask |= CIRQ_NON_CONDUCTED_PRIVS_PRESENT;
  209. }
  210. if (m_pwszConfDescription != NULL)
  211. {
  212. connect_pdu.u.conference_invite_request.cirq_description.value =
  213. m_pwszConfDescription;
  214. connect_pdu.u.conference_invite_request.cirq_description.length =
  215. ::lstrlenW(m_pwszConfDescription);
  216. connect_pdu.u.conference_invite_request.bit_mask |= CIRQ_DESCRIPTION_PRESENT;
  217. }
  218. if (pwszCallerID != NULL)
  219. {
  220. connect_pdu.u.conference_invite_request.cirq_caller_id.value = pwszCallerID;
  221. connect_pdu.u.conference_invite_request.cirq_caller_id.length = ::lstrlenW(pwszCallerID);
  222. connect_pdu.u.conference_invite_request.bit_mask |= CIRQ_CALLER_ID_PRESENT;
  223. }
  224. if (user_data_list != NULL)
  225. {
  226. rc = user_data_list->GetUserDataPDU(
  227. &connect_pdu.u.conference_invite_request.cirq_user_data);
  228. if (GCC_NO_ERROR != rc)
  229. {
  230. ERROR_OUT(("CConf::ConfInviteRequest: can't get user data, rc=%d", rc));
  231. goto MyExit;
  232. }
  233. connect_pdu.u.conference_invite_request.bit_mask |= CIRQ_USER_DATA_PRESENT;
  234. }
  235. connect_pdu.u.conference_invite_request.node_id = m_pMcsUserObject->GetMyNodeID();
  236. connect_pdu.u.conference_invite_request.top_node_id = m_pMcsUserObject->GetTopNodeID();
  237. connect_pdu.u.conference_invite_request.tag = GetNewUserIDTag();
  238. connect_pdu.u.conference_invite_request.clear_password_required = (ASN1bool_t)m_fClearPassword;
  239. connect_pdu.u.conference_invite_request.conference_is_locked = (ASN1bool_t)m_fConfLocked;
  240. connect_pdu.u.conference_invite_request.conference_is_conductible = (ASN1bool_t)m_fConfConductible;
  241. connect_pdu.u.conference_invite_request.conference_is_listed = (ASN1bool_t)m_fConfListed;
  242. connect_pdu.u.conference_invite_request.termination_method = (TerminationMethod)m_eTerminationMethod;
  243. if (! g_GCCCoder->Encode((LPVOID) &connect_pdu,
  244. CONNECT_GCC_PDU,
  245. PACKED_ENCODING_RULES,
  246. &encoded_pdu,
  247. &encoded_pdu_length))
  248. {
  249. ERROR_OUT(("CConf::ConfInviteRequest: can't encode"));
  250. rc = GCC_ALLOCATION_FAILURE;
  251. goto MyExit;
  252. }
  253. mcs_error = g_pMCSIntf->ConnectProviderRequest (
  254. &m_nConfID, // calling domain selector
  255. &m_nConfID, // called domain selector
  256. calling_address,
  257. called_address,
  258. fSecure,
  259. FALSE, // Downward connection
  260. encoded_pdu,
  261. encoded_pdu_length,
  262. connection_handle,
  263. m_pDomainParameters,
  264. this);
  265. g_GCCCoder->FreeEncoded(encoded_pdu);
  266. if (MCS_NO_ERROR != mcs_error)
  267. {
  268. ERROR_OUT(("CConf::ConfInviteRequest: ConnectProviderRequest failed: rc=%d", mcs_error));
  269. /*
  270. ** DataBeam's current implementation of MCS returns
  271. ** MCS_INVALID_PARAMETER when something other than
  272. ** the transport prefix is wrong with the specified
  273. ** transport address.
  274. */
  275. rc = (mcs_error == MCS_INVALID_PARAMETER) ?
  276. GCC_INVALID_TRANSPORT_ADDRESS :
  277. g_pMCSIntf->TranslateMCSIFErrorToGCCError(mcs_error);
  278. goto MyExit;
  279. }
  280. /*
  281. ** Add the user's tag number to the list of
  282. ** outstanding user ids along with its associated
  283. ** connection.
  284. */
  285. m_ConnHdlTagNumberList2.Append(connect_pdu.u.conference_invite_request.tag, *connection_handle);
  286. // Add connection handle to the list of connections
  287. ASSERT(0 != *connection_handle);
  288. m_ConnHandleList.Append(*connection_handle);
  289. /*
  290. ** Add the connection handle and the Node Id tag to
  291. ** the list of outstanding invite request.
  292. */
  293. DBG_SAVE_FILE_LINE
  294. invite_request_info = new INVITE_REQ_INFO;
  295. if (NULL == invite_request_info)
  296. {
  297. ERROR_OUT(("CConf::ConfInviteRequest: can't create invite request info"));
  298. rc = GCC_ALLOCATION_FAILURE;
  299. goto MyExit;
  300. }
  301. invite_request_info->connection_handle = *connection_handle;
  302. invite_request_info->invite_tag = m_nUserIDTagNumber;
  303. invite_request_info->user_data_list = NULL;
  304. m_InviteRequestList.Append(invite_request_info);
  305. // Free the privilege list packed into structures for encoding
  306. if (connect_pdu.u.conference_invite_request.bit_mask & CIRQ_CONDUCTOR_PRIVS_PRESENT)
  307. {
  308. m_pConductorPrivilegeList->FreePrivilegeListPDU(
  309. connect_pdu.u.conference_invite_request.cirq_conductor_privs);
  310. }
  311. if (connect_pdu.u.conference_invite_request.bit_mask & CIRQ_CONDUCTED_PRIVS_PRESENT)
  312. {
  313. m_pConductModePrivilegeList->FreePrivilegeListPDU(
  314. connect_pdu.u.conference_invite_request.cirq_conducted_privs);
  315. }
  316. if (connect_pdu.u.conference_invite_request.bit_mask & CIRQ_NON_CONDUCTED_PRIVS_PRESENT)
  317. {
  318. m_pNonConductModePrivilegeList->FreePrivilegeListPDU(
  319. connect_pdu.u.conference_invite_request.cirq_non_conducted_privs);
  320. }
  321. ASSERT(GCC_NO_ERROR == rc);
  322. MyExit:
  323. DebugExitINT(CConf::ConfInviteRequest, rc);
  324. return rc;
  325. }
  326. /*
  327. * CConf::ConfLockRequest()
  328. *
  329. * Public Function Description:
  330. * This routine is called from Control Sap when a
  331. * ConfLockRequest primitive needs to be processed.
  332. */
  333. #ifdef JASPER
  334. GCCError CConf::
  335. ConfLockRequest ( void )
  336. {
  337. GCCError rc = GCC_NO_ERROR;
  338. DebugEntry(CConf::ConfLockRequest);
  339. if (m_fConfIsEstablished)
  340. {
  341. if (m_fConfLocked == CONFERENCE_IS_NOT_LOCKED)
  342. {
  343. if (IsConfTopProvider())
  344. {
  345. ProcessConferenceLockRequest((UserID)m_pMcsUserObject->GetMyNodeID());
  346. }
  347. else
  348. {
  349. rc = m_pMcsUserObject->SendConferenceLockRequest();
  350. }
  351. }
  352. else // the conference is already locked
  353. {
  354. #ifdef JASPER
  355. g_pControlSap->ConfLockConfirm(GCC_RESULT_CONFERENCE_ALREADY_LOCKED, m_nConfID);
  356. #endif // JASPER
  357. }
  358. }
  359. else
  360. {
  361. ERROR_OUT(("CConf::ConfLockRequest: conference not established"));
  362. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  363. }
  364. DebugExitINT(CConf::ConfLockRequest, rc);
  365. return rc;
  366. }
  367. #endif // JASPER
  368. /*
  369. * CConf::ConfLockResponse()
  370. *
  371. * Public Function Description:
  372. * This routine is called from Control Sap when a
  373. * ConfLockResponse primitive needs to be processed.
  374. */
  375. GCCError CConf::
  376. ConfLockResponse
  377. (
  378. UserID requesting_node,
  379. GCCResult result
  380. )
  381. {
  382. GCCError rc = GCC_NO_ERROR;
  383. DebugEntry(CConf::ConfLockResponse);
  384. if (m_fConfIsEstablished)
  385. {
  386. if (requesting_node == m_pMcsUserObject->GetTopNodeID())
  387. {
  388. #ifdef JASPER
  389. g_pControlSap->ConfLockConfirm(result, m_nConfID);
  390. #endif // JASPER
  391. }
  392. else
  393. {
  394. rc = m_pMcsUserObject->SendConferenceLockResponse(requesting_node, result);
  395. }
  396. if (rc == GCC_NO_ERROR && result == GCC_RESULT_SUCCESSFUL)
  397. {
  398. m_fConfLocked = CONFERENCE_IS_LOCKED;
  399. rc = m_pMcsUserObject->SendConferenceLockIndication(
  400. TRUE, //indicates uniform send
  401. 0);
  402. }
  403. }
  404. else
  405. {
  406. ERROR_OUT(("CConf::ConfLockResponse: conference not established"));
  407. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  408. }
  409. DebugExitINT(CConf::ConfLockResponse, rc);
  410. return rc;
  411. }
  412. /*
  413. * CConf::ConfUnlockRequest()
  414. *
  415. * Public Function Description:
  416. * This routine is called from Control Sap when a
  417. * ConferenceUnlockRequest primitive needs to be processed.
  418. */
  419. #ifdef JASPER
  420. GCCError CConf::
  421. ConfUnlockRequest ( void )
  422. {
  423. GCCError rc = GCC_NO_ERROR;
  424. DebugEntry(CConf::ConfUnlockRequest);
  425. if (m_fConfIsEstablished)
  426. {
  427. if (m_fConfLocked == CONFERENCE_IS_LOCKED)
  428. {
  429. if (IsConfTopProvider())
  430. {
  431. ProcessConferenceUnlockRequest((UserID)m_pMcsUserObject->GetMyNodeID());
  432. }
  433. else
  434. {
  435. rc = m_pMcsUserObject->SendConferenceUnlockRequest();
  436. }
  437. }
  438. else // the conference is already unlocked
  439. {
  440. #ifdef JASPER
  441. g_pControlSap->ConfUnlockConfirm(GCC_RESULT_CONFERENCE_ALREADY_UNLOCKED, m_nConfID);
  442. #endif // JASPER
  443. }
  444. }
  445. else
  446. {
  447. ERROR_OUT(("CConf::ConfUnlockRequest: conference not established"));
  448. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  449. }
  450. DebugExitINT(CConf::ConfUnlockRequest, rc);
  451. return rc;
  452. }
  453. #endif // JASPER
  454. /*
  455. * CConf::ConfUnlockResponse()
  456. *
  457. * Public Function Description:
  458. * This routine is called from Control Sap when a
  459. * ConfUnlockResponse primitive needs to be processed.
  460. */
  461. #ifdef JASPER
  462. GCCError CConf::
  463. ConfUnlockResponse
  464. (
  465. UserID requesting_node,
  466. GCCResult result
  467. )
  468. {
  469. GCCError rc = GCC_NO_ERROR;
  470. DebugEntry(CConf::ConfUnlockResponse);
  471. if (m_fConfIsEstablished)
  472. {
  473. if (requesting_node == m_pMcsUserObject->GetTopNodeID())
  474. {
  475. #ifdef JASPER
  476. g_pControlSap->ConfUnlockConfirm(result, m_nConfID);
  477. #endif // JASPER
  478. }
  479. else
  480. {
  481. rc = m_pMcsUserObject->SendConferenceUnlockResponse(requesting_node, result);
  482. }
  483. if (rc == GCC_NO_ERROR && result == GCC_RESULT_SUCCESSFUL)
  484. {
  485. m_fConfLocked = CONFERENCE_IS_NOT_LOCKED;
  486. rc = m_pMcsUserObject->SendConferenceUnlockIndication(
  487. TRUE, //indicates uniform send
  488. 0);
  489. }
  490. }
  491. else
  492. {
  493. ERROR_OUT(("CConf::ConfUnlockResponse: conference not established"));
  494. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  495. }
  496. DebugExitINT(CConf::ConfUnlockResponse, rc);
  497. return rc;
  498. }
  499. #endif // JASPER
  500. /*
  501. * CConf::ConfEjectUserRequest ()
  502. *
  503. * Private Function Description
  504. * This function initiates an eject user for the specified node id.
  505. */
  506. GCCError CConf::
  507. ConfEjectUserRequest
  508. (
  509. UserID ejected_node_id,
  510. GCCReason reason
  511. )
  512. {
  513. GCCError rc = GCC_NO_ERROR;
  514. DebugEntry(CConf::ConfEjectUserRequest);
  515. if (m_fConfIsEstablished)
  516. {
  517. if (IsConfTopProvider())
  518. {
  519. if (IsThisNodeParticipant(ejected_node_id))
  520. {
  521. ConnectionHandle nConnHdl;
  522. BOOL fChildNode = FALSE;
  523. // First check to see if it is a child node that is being ejected.
  524. m_ConnHandleList.Reset();
  525. while (0 != (nConnHdl = m_ConnHandleList.Iterate()))
  526. {
  527. if (m_pMcsUserObject->GetUserIDFromConnection(nConnHdl) == ejected_node_id)
  528. {
  529. fChildNode = TRUE;
  530. break;
  531. }
  532. }
  533. if (fChildNode ||
  534. DoesRequesterHavePrivilege(m_pMcsUserObject->GetMyNodeID(), EJECT_USER_PRIVILEGE))
  535. {
  536. // Add this ejected node to the list of Ejected Nodes
  537. m_EjectedNodeConfirmList.Append(ejected_node_id);
  538. /*
  539. ** The user attachment object decides where the ejct should
  540. ** be sent (either to the Top Provider or conference wide as
  541. ** an indication.
  542. */
  543. m_pMcsUserObject->EjectNodeFromConference(ejected_node_id, reason);
  544. }
  545. else
  546. {
  547. #ifdef JASPER
  548. /*
  549. ** The top provider does not have the privilege to eject
  550. ** a node from the conference. Send the appropriate
  551. ** confirm.
  552. */
  553. g_pControlSap->ConfEjectUserConfirm(
  554. m_nConfID,
  555. ejected_node_id,
  556. GCC_RESULT_INVALID_REQUESTER);
  557. #endif // JASPER
  558. rc = fChildNode ? GCC_INSUFFICIENT_PRIVILEGE : GCC_INVALID_MCS_USER_ID;
  559. WARNING_OUT(("CConf::ConfEjectUserRequest: failed, rc=%d", rc));
  560. }
  561. }
  562. else
  563. {
  564. rc = GCC_INVALID_MCS_USER_ID;
  565. WARNING_OUT(("CConf::ConfEjectUserRequest: failed, rc=%d", rc));
  566. }
  567. }
  568. else
  569. {
  570. // Add this ejected node to the list of Ejected Nodes
  571. m_EjectedNodeConfirmList.Append(ejected_node_id);
  572. /*
  573. ** The user attachment object decides where the ejct should
  574. ** be sent (either to the Top Provider or conference wide as
  575. ** an indication.
  576. */
  577. m_pMcsUserObject->EjectNodeFromConference(ejected_node_id, reason);
  578. }
  579. }
  580. else
  581. {
  582. ERROR_OUT(("CConf::ConfEjectUserRequest: conf not established"));
  583. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  584. }
  585. DebugExitINT(CConf::ConfEjectUserRequest, rc);
  586. return rc;
  587. }
  588. /*
  589. * CConf::ConfAnnouncePresenceRequest ()
  590. *
  591. * Private Function Description
  592. * This function forces a roster update indication and a confirm to be
  593. * sent.
  594. */
  595. GCCError CConf::
  596. ConfAnnouncePresenceRequest ( PGCCNodeRecord node_record )
  597. {
  598. GCCError rc;
  599. DebugEntry(CConf::ConfAnnouncePresenceRequest);
  600. // If the conference is not established send back a negative confirm
  601. if (! m_fConfIsEstablished)
  602. {
  603. WARNING_OUT(("CConf::ConfAnnouncePresenceRequest: conf not established"));
  604. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  605. goto MyExit;
  606. }
  607. /*
  608. ** This takes care of setting up the nodes record in the
  609. ** appropriate conference roster.
  610. */
  611. rc = m_pConfRosterMgr->AddNodeRecord(node_record);
  612. if (GCC_NO_ERROR != rc)
  613. {
  614. TRACE_OUT(("CConf::ConfAnnouncePresenceRequest: updating previous record"));
  615. rc = m_pConfRosterMgr->UpdateNodeRecord(node_record);
  616. if (GCC_NO_ERROR != rc)
  617. {
  618. ERROR_OUT(("CConf::ConfAnnouncePresenceRequest: can't update node record, rc=%d", rc));
  619. goto MyExit;
  620. }
  621. }
  622. // Only flush the roster data here if there is no startup alarm.
  623. rc = AsynchFlushRosterData();
  624. if (GCC_NO_ERROR != rc)
  625. {
  626. ERROR_OUT(("CConf::ConfAnnouncePresenceRequest: can't flush roster data, rc=%d", rc));
  627. goto MyExit;
  628. }
  629. g_pControlSap->ConfAnnouncePresenceConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  630. ASSERT(GCC_NO_ERROR == rc);
  631. MyExit:
  632. DebugExitINT(CConf::ConfAnnouncePresenceRequest, rc);
  633. return rc;
  634. }
  635. /*
  636. * GCCError ConfDisconnectRequest ()
  637. *
  638. * Public Function Description
  639. * This function initiates a disconnect of this node from the conference.
  640. * This involves ejecting all subordinate nodes before actually
  641. * disconnecting the parent connection.
  642. */
  643. GCCError CConf::
  644. ConfDisconnectRequest ( void )
  645. {
  646. GCCError rc = GCC_NO_ERROR;
  647. UserID child_node_id;
  648. ConnectionHandle nConnHdl;
  649. DebugEntry(CConf::ConfDisconnectRequest);
  650. /*
  651. ** Before we start the disconnect process we must remove all the
  652. ** outstanding invite request from our list and send back associated
  653. ** confirms. Here we go ahead disconnect all connection associated with
  654. ** the invites.
  655. */
  656. DeleteOutstandingInviteRequests();
  657. /*
  658. ** We set conference established to FALSE since the conference is
  659. ** no longer established (this also prevents a terminate indication
  660. ** from being sent).
  661. */
  662. m_fConfIsEstablished = FALSE;
  663. /*
  664. ** Iterate through the list of connection handles and eject each
  665. ** of the child nodes that is associated with it.
  666. */
  667. m_ConnHandleList.Reset();
  668. while (0 != (nConnHdl = m_ConnHandleList.Iterate()))
  669. {
  670. child_node_id = m_pMcsUserObject->GetUserIDFromConnection(nConnHdl);
  671. rc = m_pMcsUserObject->EjectNodeFromConference (child_node_id,
  672. GCC_REASON_HIGHER_NODE_DISCONNECTED);
  673. if (rc != GCC_NO_ERROR)
  674. {
  675. ERROR_OUT(("CConf::ConfDisconnectRequest: can't eject node from conference"));
  676. break;
  677. }
  678. }
  679. // If there is an error we go ahead and do a hard disconnect
  680. if (m_ConnHandleList.IsEmpty() || rc != GCC_NO_ERROR)
  681. {
  682. /*
  683. ** First inform the control SAP that this node has successfuly
  684. ** disconnected.
  685. */
  686. rc = g_pControlSap->ConfDisconnectConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  687. // Tell the owner object to terminate this conference
  688. InitiateTermination(GCC_REASON_NORMAL_TERMINATION, 0);
  689. }
  690. else
  691. {
  692. /*
  693. ** Wait for all the ejects to complete before the conference is
  694. ** terminated.
  695. */
  696. m_fConfDisconnectPending = TRUE;
  697. }
  698. DebugExitINT(CConf::ConfDisconnectRequest, rc);
  699. return rc;
  700. }
  701. /*
  702. * GCCError ConfTerminateRequest ()
  703. *
  704. * Public Function Description
  705. * This routine initiates a terminate sequence which starts with a request
  706. * to the Top Provider if this node is not already the Top Provider.
  707. */
  708. #ifdef JASPER
  709. GCCError CConf::
  710. ConfTerminateRequest ( GCCReason reason )
  711. {
  712. GCCError rc;
  713. DebugEntry(CConf::ConfTerminateRequest);
  714. if (m_fConfIsEstablished)
  715. {
  716. /*
  717. ** Before we start the termination process we must remove all the
  718. ** outstanding invite request from our list and send back associated
  719. ** confirms. Here we go ahead disconnect all connections associated
  720. ** with these invites.
  721. */
  722. DeleteOutstandingInviteRequests();
  723. if (IsConfTopProvider())
  724. {
  725. if (DoesRequesterHavePrivilege( m_pMcsUserObject->GetMyNodeID(),
  726. TERMINATE_PRIVILEGE))
  727. {
  728. TRACE_OUT(("CConf::ConfTerminateRequest: Node has permission to terminate"));
  729. /*
  730. ** Since the terminate was successful, we go ahead and
  731. ** set the m_fConfIsEstablished instance variable to
  732. ** FALSE. This prevents any other messages from flowing
  733. ** to the SAPs other than terminate messages.
  734. */
  735. m_fConfIsEstablished = FALSE;
  736. // Send the terminate confirm.
  737. g_pControlSap->ConfTerminateConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  738. // This call takes care of both the local and remote terminate
  739. m_pMcsUserObject->ConferenceTerminateIndication(reason);
  740. }
  741. else
  742. {
  743. WARNING_OUT(("CConf::ConfTerminateRequest: Node does NOT have permission to terminate"));
  744. g_pControlSap->ConfTerminateConfirm(m_nConfID, GCC_RESULT_INVALID_REQUESTER);
  745. }
  746. }
  747. else
  748. {
  749. m_pMcsUserObject->ConferenceTerminateRequest(reason);
  750. }
  751. rc = GCC_NO_ERROR;
  752. }
  753. else
  754. {
  755. ERROR_OUT(("CConf::ConfTerminateRequest: conference not established"));
  756. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  757. }
  758. DebugExitINT(CConf::ConfTerminateRequest, rc);
  759. return rc;
  760. }
  761. #endif // JASPER
  762. /********************* Registry Calls ***********************************/
  763. /*
  764. * GCCError RegistryRegisterChannelRequest ()
  765. *
  766. * Public Function Description
  767. * This initiates a registry request sequence. Note that the registry
  768. * response is handled by the registry class.
  769. */
  770. GCCError CConf::
  771. RegistryRegisterChannelRequest
  772. (
  773. PGCCRegistryKey registry_key,
  774. ChannelID nChnlID,
  775. CAppSap *pAppSap
  776. )
  777. {
  778. GCCError rc;
  779. EntityID eid;
  780. DebugEntry(CConf::RegistryRegisterChannelRequest);
  781. rc = GetEntityIDFromAPEList(pAppSap, &registry_key->session_key, &eid);
  782. if (rc == GCC_NO_ERROR)
  783. {
  784. rc = m_pAppRegistry->RegisterChannel(registry_key, nChnlID, eid);
  785. }
  786. DebugExitINT(CConf::RegistryRegisterChannelRequest, rc);
  787. return rc;
  788. }
  789. /*
  790. * GCCError RegistryAssignTokenRequest ()
  791. *
  792. * Public Function Description
  793. * This initiates a registry request sequence. Note that the registry
  794. * response is handled by the registry class.
  795. */
  796. GCCError CConf::
  797. RegistryAssignTokenRequest
  798. (
  799. PGCCRegistryKey registry_key,
  800. CAppSap *pAppSap
  801. )
  802. {
  803. GCCError rc;
  804. GCCEntityID eid;
  805. DebugEntry(CConf::RegistryAssignTokenRequest);
  806. rc = GetEntityIDFromAPEList(pAppSap, &registry_key->session_key, &eid);
  807. if (rc == GCC_NO_ERROR)
  808. {
  809. rc = m_pAppRegistry->AssignToken(registry_key, eid);
  810. }
  811. DebugExitINT(CConf::RegistryAssignTokenRequest, rc);
  812. return rc;
  813. }
  814. /*
  815. * GCCError RegistrySetParameterRequest ()
  816. *
  817. * Public Function Description
  818. * This initiates a registry request sequence. Note that the registry
  819. * response is handled by the registry class.
  820. */
  821. GCCError CConf::
  822. RegistrySetParameterRequest
  823. (
  824. PGCCRegistryKey registry_key,
  825. LPOSTR parameter_value,
  826. GCCModificationRights modification_rights,
  827. CAppSap *pAppSap
  828. )
  829. {
  830. GCCError rc;
  831. GCCEntityID eid;
  832. DebugEntry(CConf::RegistrySetParameterRequest);
  833. rc = GetEntityIDFromAPEList(pAppSap, &registry_key->session_key, &eid);
  834. if (rc == GCC_NO_ERROR)
  835. {
  836. rc = m_pAppRegistry->SetParameter(registry_key,
  837. parameter_value,
  838. modification_rights,
  839. eid);
  840. }
  841. DebugExitINT(CConf::RegistrySetParameterRequest, rc);
  842. return rc;
  843. }
  844. /*
  845. * GCCError RegistryRetrieveEntryRequest ()
  846. *
  847. * Public Function Description
  848. * This initiates a registry request sequence. Note that the registry
  849. * response is handled by the registry class.
  850. */
  851. GCCError CConf::
  852. RegistryRetrieveEntryRequest
  853. (
  854. PGCCRegistryKey registry_key,
  855. CAppSap *pAppSap
  856. )
  857. {
  858. GCCError rc;
  859. GCCEntityID eid;
  860. DebugEntry(CConf::RegistryRetrieveEntryRequest);
  861. rc = GetEntityIDFromAPEList(pAppSap, &registry_key->session_key, &eid);
  862. if (rc == GCC_NO_ERROR)
  863. {
  864. rc = m_pAppRegistry->RetrieveEntry(registry_key, eid);
  865. }
  866. DebugExitINT(CConf::RegistryRetrieveEntryRequest, rc);
  867. return rc;
  868. }
  869. /*
  870. * GCCError RegistryDeleteEntryRequest ()
  871. *
  872. * Public Function Description
  873. * This initiates a registry request sequence. Note that the registry
  874. * response is handled by the registry class.
  875. */
  876. GCCError CConf::
  877. RegistryDeleteEntryRequest
  878. (
  879. PGCCRegistryKey registry_key,
  880. CAppSap *pAppSap
  881. )
  882. {
  883. GCCError rc;
  884. EntityID eid;
  885. DebugEntry(CConf::RegistryDeleteEntryRequest);
  886. rc = GetEntityIDFromAPEList(pAppSap, &registry_key->session_key, &eid);
  887. if (rc == GCC_NO_ERROR)
  888. {
  889. rc = m_pAppRegistry->DeleteEntry(registry_key, eid);
  890. }
  891. DebugExitINT(CConf::RegistryDeleteEntryRequest, rc);
  892. return rc;
  893. }
  894. /*
  895. * GCCError RegistryMonitorRequest ()
  896. *
  897. * Public Function Description
  898. * This initiates a registry request sequence. Note that the registry
  899. * response is handled by the registry class.
  900. */
  901. GCCError CConf::
  902. RegistryMonitorRequest
  903. (
  904. BOOL fEnableDelivery,
  905. PGCCRegistryKey registry_key,
  906. CAppSap *pAppSap)
  907. {
  908. GCCError rc;
  909. GCCEntityID eid;
  910. DebugEntry(CConf::RegistryMonitorRequest);
  911. rc = GetEntityIDFromAPEList(pAppSap, &registry_key->session_key, &eid);
  912. if (rc == GCC_NO_ERROR)
  913. {
  914. rc = m_pAppRegistry->MonitorRequest(registry_key, fEnableDelivery, eid);
  915. }
  916. DebugExitINT(CConf:RegistryMonitorRequest, rc);
  917. return rc;
  918. }
  919. /*
  920. * GCCError RegistryAllocateHandleRequest ()
  921. *
  922. * Public Function Description
  923. * This initiates a registry request sequence. Note that the registry
  924. * response is handled by the registry class. This registry call is
  925. * a bit different from the other registry calls. Notice that there is
  926. * no registry key associated with this call so there is no way to
  927. * explicitly determine the entity ID. Luckily, the entity ID is not
  928. * passed back in the allocate confirm so we just pick an entity id
  929. * that is associated with this SAP. It makes no difference which one
  930. * we pick because they all accomplish the same thing.
  931. */
  932. GCCError CConf::
  933. RegistryAllocateHandleRequest
  934. (
  935. UINT cHandles,
  936. CAppSap *pAppSap
  937. )
  938. {
  939. GCCError rc;
  940. ENROLLED_APE_INFO *lpEnrAPEInfo;
  941. GCCEntityID eid;
  942. DebugEntry(CConf::RegistryAllocateHandleRequest);
  943. // First we must find a single entity id that is associated with this SAP.
  944. if (NULL != (lpEnrAPEInfo = GetEnrolledAPEbySap(pAppSap, &eid)))
  945. {
  946. ASSERT(GCC_INVALID_EID != eid);
  947. rc = m_pAppRegistry->AllocateHandleRequest(cHandles, eid);
  948. }
  949. else
  950. {
  951. WARNING_OUT(("CConf::RegistryAllocateHandleRequest: Application not enrolled"));
  952. rc = GCC_APP_NOT_ENROLLED;
  953. }
  954. DebugExitINT(CConf::RegistryAllocateHandleRequest, rc);
  955. return rc;
  956. }
  957. /********************* Conductorship Calls ***********************************/
  958. /*
  959. * GCCError ConductorAssignRequest ()
  960. *
  961. * Public Function Description
  962. * This initiates a Conductor assign request sequence. Here the node is
  963. * requesting to become the conductor.
  964. */
  965. #ifdef JASPER
  966. GCCError CConf::
  967. ConductorAssignRequest ( void )
  968. {
  969. GCCError rc = GCC_NO_ERROR;
  970. GCCResult eResult = INVALID_GCC_RESULT;
  971. DebugEntry(CConf::ConductorAssignRequest);
  972. // Return an error if the conference is not established.
  973. if (m_fConfIsEstablished)
  974. {
  975. if (m_fConfConductible)
  976. {
  977. if (m_nConductorNodeID != m_pMcsUserObject->GetMyNodeID())
  978. {
  979. if ((m_nPendingConductorNodeID == 0) && ! m_fConductorGiveResponsePending)
  980. {
  981. m_fConductorAssignRequestPending = TRUE;
  982. rc = m_pMcsUserObject->ConductorTokenGrab();
  983. }
  984. else
  985. {
  986. TRACE_OUT(("CConf::ConductorAssignConfirm:Give Pending"));
  987. eResult = GCC_RESULT_CONDUCTOR_GIVE_IS_PENDING;
  988. }
  989. }
  990. else
  991. {
  992. ERROR_OUT(("CConf::ConductorAssignRequest: Already Conductor"));
  993. /*
  994. ** Since we are already the conductor send back a successful
  995. ** result
  996. */
  997. //
  998. // LONCHANC: Why not GCC_RESULT_ALREADY_CONDUCTOR?
  999. //
  1000. eResult = GCC_RESULT_SUCCESSFUL;
  1001. }
  1002. }
  1003. else
  1004. {
  1005. ERROR_OUT(("CConf::ConductorAssignRequest: not conductible"));
  1006. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1007. }
  1008. }
  1009. else
  1010. {
  1011. ERROR_OUT(("CConf::ConductorAssignRequest: conference not established"));
  1012. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1013. }
  1014. #ifdef JASPER
  1015. if (INVALID_GCC_RESULT != eResult)
  1016. {
  1017. g_pControlSap->ConductorAssignConfirm(eResult, m_nConfID);
  1018. }
  1019. #endif // JASPER
  1020. DebugExitINT(CConf::ConductorAssignRequest, rc);
  1021. return rc;
  1022. }
  1023. #endif // JASPER
  1024. /*
  1025. * GCCError ConductorReleaseRequest ()
  1026. *
  1027. * Public Function Description
  1028. * Here the node is attempting to give up conductorship.
  1029. */
  1030. #ifdef JASPER
  1031. GCCError CConf::
  1032. ConductorReleaseRequest ( void )
  1033. {
  1034. GCCError rc = GCC_NO_ERROR;
  1035. GCCResult eResult = INVALID_GCC_RESULT;
  1036. DebugEntry(CConf::ConductorReleaseRequest);
  1037. if (m_fConfConductible)
  1038. {
  1039. if (m_nConductorNodeID == m_pMcsUserObject->GetMyNodeID())
  1040. {
  1041. if (m_nPendingConductorNodeID == 0)
  1042. {
  1043. /*
  1044. ** This does not seem right, but this is the way that T.124
  1045. ** defines it should work.
  1046. */
  1047. m_nConductorNodeID = 0; // Set back to non-conducted mode
  1048. m_fConductorGrantedPermission = FALSE;
  1049. rc = m_pMcsUserObject->SendConductorReleaseIndication();
  1050. if (rc == GCC_NO_ERROR)
  1051. {
  1052. rc = m_pMcsUserObject->ConductorTokenRelease();
  1053. /*
  1054. ** Inform the control SAP and all the enrolled application
  1055. ** SAPs that the conductor was released. We do this here
  1056. ** because we will not process the release indication
  1057. ** when it comes back in.
  1058. */
  1059. if (rc == GCC_NO_ERROR)
  1060. {
  1061. g_pControlSap->ConductorReleaseIndication(m_nConfID);
  1062. /*
  1063. ** We iterate on a temporary list to avoid any problems
  1064. ** if the application sap leaves during the callback.
  1065. */
  1066. CAppSap *pAppSap;
  1067. CAppSapList TempList(m_RegisteredAppSapList);
  1068. TempList.Reset();
  1069. while (NULL != (pAppSap = TempList.Iterate()))
  1070. {
  1071. if (DoesSAPHaveEnrolledAPE(pAppSap))
  1072. {
  1073. pAppSap->ConductorReleaseIndication(m_nConfID);
  1074. }
  1075. }
  1076. }
  1077. }
  1078. }
  1079. else
  1080. {
  1081. TRACE_OUT(("CConf: ConductorReleaseRequest: Give Pending"));
  1082. eResult = GCC_RESULT_CONDUCTOR_GIVE_IS_PENDING;
  1083. }
  1084. }
  1085. else
  1086. {
  1087. ERROR_OUT(("CConf::ConductorReleaseRequest: Not the Conductor"));
  1088. eResult = GCC_RESULT_NOT_THE_CONDUCTOR;
  1089. }
  1090. }
  1091. else
  1092. {
  1093. ERROR_OUT(("CConf::ConductorReleaseRequest: not conductible"));
  1094. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1095. }
  1096. #ifdef JASPER
  1097. if (INVALID_GCC_RESULT != eResult)
  1098. {
  1099. g_pControlSap->ConductorReleaseConfirm(eResult, m_nConfID);
  1100. }
  1101. #endif // JASPER
  1102. DebugExitINT(CConf::ConductorReleaseRequest, rc);
  1103. return rc;
  1104. }
  1105. #endif // JASPER
  1106. /*
  1107. * GCCError ConductorPleaseRequest ()
  1108. *
  1109. * Public Function Description
  1110. * Here the node is asking to be given conductorship.
  1111. */
  1112. #ifdef JASPER
  1113. GCCError CConf::
  1114. ConductorPleaseRequest ( void )
  1115. {
  1116. GCCError rc = GCC_NO_ERROR;
  1117. GCCResult eResult = INVALID_GCC_RESULT;
  1118. DebugEntry(CConf::ConductorPleaseRequest);
  1119. if (m_fConfConductible)
  1120. {
  1121. // Return an error if the conference is not established
  1122. if (m_nConductorNodeID != 0)
  1123. {
  1124. if (m_nConductorNodeID != m_pMcsUserObject->GetMyNodeID())
  1125. {
  1126. rc = m_pMcsUserObject->ConductorTokenPlease();
  1127. if (rc == GCC_NO_ERROR)
  1128. {
  1129. // Send back positive confirm if successful
  1130. eResult = GCC_RESULT_SUCCESSFUL;
  1131. }
  1132. }
  1133. else
  1134. {
  1135. WARNING_OUT(("CConf::ConductorPleaseRequest: already conductor"));
  1136. eResult = GCC_RESULT_ALREADY_CONDUCTOR;
  1137. }
  1138. }
  1139. else
  1140. {
  1141. ERROR_OUT(("CConf::ConductorPleaseRequest: not in conducted mode"));
  1142. eResult = GCC_RESULT_NOT_IN_CONDUCTED_MODE;
  1143. }
  1144. }
  1145. else
  1146. {
  1147. ERROR_OUT(("CConf::ConductorPleaseRequest: not conductible"));
  1148. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1149. }
  1150. #ifdef JASPER
  1151. if (INVALID_GCC_RESULT != eResult)
  1152. {
  1153. g_pControlSap->ConductorPleaseConfirm(eResult, m_nConfID);
  1154. }
  1155. #endif // JASPER
  1156. DebugExitINT(CConf::ConductorPleaseRequest, rc);
  1157. return rc;
  1158. }
  1159. #endif // JASPER
  1160. /*
  1161. * GCCError ConductorGiveRequest ()
  1162. *
  1163. * Public Function Description
  1164. * The function is called when the conductor wants to pass off
  1165. * conductorship to a different node.
  1166. */
  1167. #ifdef JASPER
  1168. GCCError CConf::
  1169. ConductorGiveRequest ( UserID recipient_node_id )
  1170. {
  1171. GCCError rc = GCC_NO_ERROR;
  1172. GCCResult eResult = INVALID_GCC_RESULT;
  1173. DebugEntry(CConf::ConductorGiveRequest);
  1174. if (m_fConfConductible)
  1175. {
  1176. // Am I in conducted mode?
  1177. if (m_nConductorNodeID != 0)
  1178. {
  1179. // Am I the conductor?
  1180. if (m_nConductorNodeID == m_pMcsUserObject->GetMyNodeID())
  1181. {
  1182. if (recipient_node_id != m_pMcsUserObject->GetMyNodeID())
  1183. {
  1184. if (m_nPendingConductorNodeID == 0)
  1185. {
  1186. /*
  1187. ** We don't assume that the recipient node is the new
  1188. ** conductor until we get a confirm or an
  1189. ** AssignIndication. The m_nPendingConductorNodeID is
  1190. ** used to buffer the recipient until the give confirm
  1191. ** is received.
  1192. */
  1193. m_nPendingConductorNodeID = recipient_node_id;
  1194. rc = m_pMcsUserObject->ConductorTokenGive(recipient_node_id);
  1195. }
  1196. else
  1197. {
  1198. TRACE_OUT(("CConf::ConductorGiveRequest: conductor give is pending"));
  1199. eResult = GCC_RESULT_CONDUCTOR_GIVE_IS_PENDING;
  1200. }
  1201. }
  1202. else
  1203. {
  1204. WARNING_OUT(("CConf::ConductorGiveRequest: already conductor"));
  1205. eResult = GCC_RESULT_ALREADY_CONDUCTOR;
  1206. }
  1207. }
  1208. else
  1209. {
  1210. ERROR_OUT(("CConf::ConductorGiveRequest: not the conductor"));
  1211. eResult = GCC_RESULT_NOT_THE_CONDUCTOR;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. ERROR_OUT(("CConf::ConductorGiveRequest: not in conduct mode"));
  1217. eResult = GCC_RESULT_NOT_IN_CONDUCTED_MODE;
  1218. }
  1219. }
  1220. else
  1221. {
  1222. ERROR_OUT(("CConf::ConductorGiveRequest: not conductible"));
  1223. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1224. }
  1225. #ifdef JASPER
  1226. if (INVALID_GCC_RESULT != eResult)
  1227. {
  1228. g_pControlSap->ConductorGiveConfirm(eResult, m_nConfID, recipient_node_id);
  1229. }
  1230. #endif // JASPER
  1231. DebugExitINT(CConf::ConductorGiveRequest, rc);
  1232. return rc;
  1233. }
  1234. #endif // JASPER
  1235. /*
  1236. * GCCError ConductorGiveResponse ()
  1237. *
  1238. * Public Function Description
  1239. * This function gets called in response to a Conductor Give Indication.
  1240. * If result is success then this node is the new conductor.
  1241. */
  1242. GCCError CConf::
  1243. ConductorGiveResponse ( GCCResult eResult )
  1244. {
  1245. GCCError rc = GCC_NO_ERROR;
  1246. DebugEntry(CConf::ConductorGiveResponse);
  1247. if (! m_fConductorGiveResponsePending)
  1248. {
  1249. ERROR_OUT(("CConf::ConductorGiveResponse: no give response pending"));
  1250. rc = GCC_NO_GIVE_RESPONSE_PENDING;
  1251. goto MyExit;
  1252. }
  1253. m_fConductorGiveResponsePending = FALSE;
  1254. if (eResult == GCC_RESULT_SUCCESSFUL)
  1255. {
  1256. // Set the conductor id to my user id if the response is success.
  1257. m_nConductorNodeID = m_pMcsUserObject->GetMyNodeID();
  1258. // The new conductor always has permission.
  1259. m_fConductorGrantedPermission = TRUE;
  1260. /*
  1261. ** We must perform the give response before sending the dummy to
  1262. ** the top provider so that MCS knows that the conductor token
  1263. ** belongs to this node.
  1264. */
  1265. rc = m_pMcsUserObject->ConductorTokenGiveResponse(RESULT_SUCCESSFUL);
  1266. if (GCC_NO_ERROR != rc)
  1267. {
  1268. ERROR_OUT(("CConf::ConductorGiveResponse: ConductorTokenGiveResponse failed, rc=%d", rc));
  1269. goto MyExit;
  1270. }
  1271. /*
  1272. ** If this node is not the Top Provider, we must try to Give the
  1273. ** Conductor token to the Top Provider. The Top Provider is used
  1274. ** to issue the Assign Indication whenever the conductor changes
  1275. ** hands.
  1276. */
  1277. if (m_pMcsUserObject->GetMyNodeID() != m_pMcsUserObject->GetTopNodeID())
  1278. {
  1279. rc = m_pMcsUserObject->ConductorTokenGive(m_pMcsUserObject->GetTopNodeID());
  1280. }
  1281. else
  1282. {
  1283. /*
  1284. ** Here we go ahead and send the assign indication because we
  1285. ** are already at the Top Provider.
  1286. */
  1287. rc = m_pMcsUserObject->SendConductorAssignIndication(m_nConductorNodeID);
  1288. }
  1289. }
  1290. else
  1291. {
  1292. // Inform that giver that we are not interested
  1293. rc = m_pMcsUserObject->ConductorTokenGiveResponse(RESULT_USER_REJECTED);
  1294. }
  1295. MyExit:
  1296. DebugExitINT(CConf::ConductorGiveResponse, rc);
  1297. return rc;
  1298. }
  1299. /*
  1300. * GCCError ConductorPermitAskRequest ()
  1301. *
  1302. * Public Function Description
  1303. * This call is made when a node wants to request permission from the
  1304. * conductor.
  1305. */
  1306. #ifdef JASPER
  1307. GCCError CConf::
  1308. ConductorPermitAskRequest ( BOOL grant_permission )
  1309. {
  1310. GCCError rc = GCC_NO_ERROR;
  1311. GCCResult eResult = INVALID_GCC_RESULT;
  1312. DebugEntry(CConf::ConductorPermitAskRequest);
  1313. if (m_fConfConductible)
  1314. {
  1315. // Am I in conducted mode?
  1316. if (m_nConductorNodeID != 0)
  1317. {
  1318. if (m_nConductorNodeID != m_pMcsUserObject->GetMyNodeID())
  1319. {
  1320. rc = m_pMcsUserObject->SendConductorPermitAsk(grant_permission);
  1321. if (rc == GCC_NO_ERROR)
  1322. {
  1323. eResult = GCC_RESULT_SUCCESSFUL;
  1324. }
  1325. }
  1326. else
  1327. {
  1328. WARNING_OUT(("CConf::ConductorPermitAskRequest: already conductor"));
  1329. eResult = GCC_RESULT_ALREADY_CONDUCTOR;
  1330. }
  1331. }
  1332. else
  1333. {
  1334. ERROR_OUT(("CConf::ConductorPermitAskRequest: not in conducted mode"));
  1335. eResult = GCC_RESULT_NOT_IN_CONDUCTED_MODE;
  1336. }
  1337. }
  1338. else
  1339. {
  1340. ERROR_OUT(("CConf::ConductorPermitAskRequest: not conductible"));
  1341. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1342. }
  1343. #ifdef JASPER
  1344. if (INVALID_GCC_RESULT != eResult)
  1345. {
  1346. g_pControlSap->ConductorPermitAskConfirm(eResult, grant_permission, m_nConfID);
  1347. }
  1348. #endif // JASPER
  1349. DebugExitINT(CConf::ConductorPermitAskRequest, rc);
  1350. return rc;
  1351. }
  1352. #endif // JASPER
  1353. /*
  1354. * GCCError ConductorPermitGrantRequest ()
  1355. *
  1356. * Public Function Description
  1357. * This function is called when a conductor wishes to grant permission
  1358. * to a specific node or to a list of nodes.
  1359. */
  1360. #ifdef JASPER
  1361. GCCError CConf::
  1362. ConductorPermitGrantRequest
  1363. (
  1364. UINT number_granted,
  1365. PUserID granted_node_list,
  1366. UINT number_waiting,
  1367. PUserID waiting_node_list
  1368. )
  1369. {
  1370. GCCError rc = GCC_NO_ERROR;
  1371. GCCResult eResult = INVALID_GCC_RESULT;
  1372. DebugEntry(CConf::ConductorPermitGrantRequest);
  1373. if (m_fConfConductible)
  1374. {
  1375. // Am I in conducted mode?
  1376. if (m_nConductorNodeID != 0)
  1377. {
  1378. // Am I the conductor?
  1379. if (m_nConductorNodeID == m_pMcsUserObject->GetMyNodeID())
  1380. {
  1381. TRACE_OUT(("CConf: ConductorPermitGrantRequest: SEND: number_granted = %d", number_granted));
  1382. rc = m_pMcsUserObject->SendConductorPermitGrant(
  1383. number_granted,
  1384. granted_node_list,
  1385. number_waiting,
  1386. waiting_node_list);
  1387. if (rc == GCC_NO_ERROR)
  1388. {
  1389. eResult = GCC_RESULT_SUCCESSFUL;
  1390. }
  1391. }
  1392. else
  1393. {
  1394. ERROR_OUT(("CConf::ConductorPermitGrantRequest: not the conductor"));
  1395. eResult = GCC_RESULT_NOT_THE_CONDUCTOR;
  1396. }
  1397. }
  1398. else
  1399. {
  1400. ERROR_OUT(("CConf::ConductorPermitGrantRequest: not in conducted mode"));
  1401. eResult = GCC_RESULT_NOT_IN_CONDUCTED_MODE;
  1402. }
  1403. }
  1404. else
  1405. {
  1406. ERROR_OUT(("CConf::ConductorPermitGrantRequest: not conductible"));
  1407. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1408. }
  1409. #ifdef JASPER
  1410. if (INVALID_GCC_RESULT != eResult)
  1411. {
  1412. g_pControlSap->ConductorPermitGrantConfirm(eResult, m_nConfID);
  1413. }
  1414. #endif // JASPER
  1415. DebugExitINT(CConf::ConductorPermitGrantRequest, rc);
  1416. return rc;
  1417. }
  1418. #endif // JASPER
  1419. /*
  1420. * GCCError ConductorInquireRequest ()
  1421. *
  1422. * Public Function Description
  1423. * This function is called when a node request conductorship information.
  1424. */
  1425. GCCError CConf::
  1426. ConductorInquireRequest ( CBaseSap *pSap )
  1427. {
  1428. GCCError rc = GCC_NO_ERROR;
  1429. GCCResult eResult = INVALID_GCC_RESULT;
  1430. DebugEntry(CConf::ConductorInquireRequest);
  1431. if (m_fConfConductible)
  1432. {
  1433. if (m_nConductorNodeID != 0)
  1434. {
  1435. rc = m_pMcsUserObject->ConductorTokenTest();
  1436. /*
  1437. ** We must "push" the command target to the to the list of
  1438. ** outstanding conductor test request. When the test confirm
  1439. ** comes back the command target will be "poped" of the list.
  1440. ** Note that all test request must be processed in the order that
  1441. ** they are requested.
  1442. */
  1443. m_ConductorTestList.Append(pSap);
  1444. }
  1445. else
  1446. {
  1447. // If not in conducted mode send back NO conductor information
  1448. ERROR_OUT(("CConf::ConductorInquireRequest: not in conducted mode"));
  1449. eResult = GCC_RESULT_NOT_IN_CONDUCTED_MODE;
  1450. }
  1451. }
  1452. else
  1453. {
  1454. ERROR_OUT(("CConf::ConductorInquireRequest: not conductible"));
  1455. eResult = GCC_RESULT_NOT_CONDUCTIBLE;
  1456. }
  1457. if (INVALID_GCC_RESULT != eResult)
  1458. {
  1459. pSap->ConductorInquireConfirm(NULL,
  1460. eResult,
  1461. m_fConductorGrantedPermission,
  1462. FALSE,
  1463. m_nConfID);
  1464. }
  1465. DebugExitINT(CConf:ConductorInquireRequest, rc);
  1466. return rc;
  1467. }
  1468. /********************** Miscelaneous Finctions **********************/
  1469. /*
  1470. * GCCError ConferenceTimeRemainingRequest ()
  1471. *
  1472. * Public Function Description
  1473. * This function initiates a TimeRemainingRequest sequence.
  1474. */
  1475. GCCError CConf::
  1476. ConferenceTimeRemainingRequest
  1477. (
  1478. UINT time_remaining,
  1479. UserID node_id
  1480. )
  1481. {
  1482. GCCError rc;
  1483. DebugEntry(CConf::ConferenceTimeRemainingRequest);
  1484. if (m_fConfIsEstablished)
  1485. {
  1486. rc = m_pMcsUserObject->TimeRemainingRequest(time_remaining, node_id);
  1487. #ifdef JASPER
  1488. if (rc == GCC_NO_ERROR)
  1489. {
  1490. g_pControlSap->ConfTimeRemainingConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  1491. }
  1492. #endif // JASPER
  1493. }
  1494. else
  1495. {
  1496. ERROR_OUT(("CConf::ConferenceTimeRemainingRequest: conference not established"));
  1497. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1498. }
  1499. DebugExitINT(CConf::ConferenceTimeRemainingRequest, rc);
  1500. return rc;
  1501. }
  1502. /*
  1503. * GCCError ConfTimeInquireRequest ()
  1504. *
  1505. * Public Function Description
  1506. * This function initiates a ConfTimeInquireRequest sequence.
  1507. */
  1508. #ifdef JASPER
  1509. GCCError CConf::
  1510. ConfTimeInquireRequest ( BOOL time_is_conference_wide )
  1511. {
  1512. GCCError rc = GCC_NO_ERROR;
  1513. DebugEntry(CConf::ConfTimeInquireRequest);
  1514. if (m_fConfIsEstablished)
  1515. {
  1516. if ((m_eNodeType == CONVENER_NODE) ||
  1517. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE)||
  1518. (m_eNodeType == JOINED_CONVENER_NODE))
  1519. {
  1520. g_pControlSap->ConfTimeInquireIndication(
  1521. m_nConfID,
  1522. time_is_conference_wide,
  1523. m_pMcsUserObject->GetMyNodeID());
  1524. }
  1525. else
  1526. {
  1527. rc = m_pMcsUserObject->TimeInquireRequest(time_is_conference_wide);
  1528. }
  1529. #ifdef JASPER
  1530. if (rc == GCC_NO_ERROR)
  1531. {
  1532. g_pControlSap->ConfTimeInquireConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  1533. }
  1534. #endif // JASPER
  1535. }
  1536. else
  1537. {
  1538. ERROR_OUT(("CConf::ConfTimeInquireRequest: conference not established"));
  1539. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1540. }
  1541. DebugExitINT(CConf::ConfTimeInquireRequest, rc);
  1542. return rc;
  1543. }
  1544. #endif // JASPER
  1545. /*
  1546. * GCCError ConfExtendRequest ()
  1547. *
  1548. * Public Function Description
  1549. * This function initiates a ConfExtendRequest sequence.
  1550. */
  1551. #ifdef JASPER
  1552. GCCError CConf::
  1553. ConfExtendRequest
  1554. (
  1555. UINT extension_time,
  1556. BOOL time_is_conference_wide
  1557. )
  1558. {
  1559. GCCError rc = GCC_NO_ERROR;
  1560. DebugEntry(CConf::ConfExtendRequest);
  1561. if (m_fConfIsEstablished)
  1562. {
  1563. if ((m_eNodeType == CONVENER_NODE) ||
  1564. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE)||
  1565. (m_eNodeType == JOINED_CONVENER_NODE))
  1566. {
  1567. #ifdef JASPER
  1568. g_pControlSap->ConfExtendIndication(
  1569. m_nConfID,
  1570. extension_time,
  1571. time_is_conference_wide,
  1572. m_pMcsUserObject->GetMyNodeID());
  1573. #endif // JASPER
  1574. }
  1575. else
  1576. {
  1577. rc = m_pMcsUserObject->ConferenceExtendIndication(
  1578. extension_time,
  1579. time_is_conference_wide);
  1580. }
  1581. #ifdef JASPER
  1582. if (rc == GCC_NO_ERROR)
  1583. {
  1584. g_pControlSap->ConfExtendConfirm(
  1585. m_nConfID,
  1586. extension_time,
  1587. GCC_RESULT_SUCCESSFUL);
  1588. }
  1589. #endif // JASPER
  1590. }
  1591. else
  1592. {
  1593. ERROR_OUT(("CConf::ConfExtendRequest: conference not established"));
  1594. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1595. }
  1596. DebugExitINT(CConf::ConfExtendRequest, rc);
  1597. return rc;
  1598. }
  1599. #endif // JASPER
  1600. /*
  1601. * GCCError ConfAssistanceRequest ()
  1602. *
  1603. * Public Function Description
  1604. * This function initiates a ConfAssistanceRequest sequence.
  1605. */
  1606. #ifdef JASPER
  1607. GCCError CConf::
  1608. ConfAssistanceRequest
  1609. (
  1610. UINT number_of_user_data_members,
  1611. PGCCUserData *user_data_list
  1612. )
  1613. {
  1614. GCCError rc;
  1615. DebugEntry(CConf::ConfAssistanceRequest);
  1616. if (m_fConfIsEstablished)
  1617. {
  1618. rc = m_pMcsUserObject->ConferenceAssistanceIndication(
  1619. number_of_user_data_members,
  1620. user_data_list);
  1621. #ifdef JASPER
  1622. if (rc == GCC_NO_ERROR)
  1623. {
  1624. g_pControlSap->ConfAssistanceConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  1625. }
  1626. #endif // JASPER
  1627. }
  1628. else
  1629. {
  1630. ERROR_OUT(("CConf::ConfAssistanceRequest: conference not established"));
  1631. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1632. }
  1633. DebugExitINT(CConf::ConfAssistanceRequest, rc);
  1634. return rc;
  1635. }
  1636. #endif // JASPER
  1637. /*
  1638. * GCCError AppInvokeRequest()
  1639. *
  1640. * Public Function Description
  1641. * This function initiates an ApplicationInvokeRequest sequence.
  1642. */
  1643. GCCError CConf::
  1644. AppInvokeRequest
  1645. (
  1646. CInvokeSpecifierListContainer *invoke_list,
  1647. GCCSimpleNodeList *pNodeList,
  1648. CBaseSap *pSap,
  1649. GCCRequestTag nReqTag
  1650. )
  1651. {
  1652. GCCError rc;
  1653. DebugEntry(CConf::AppInvokeRequest);
  1654. if (m_fConfIsEstablished)
  1655. {
  1656. rc = m_pMcsUserObject->AppInvokeIndication(invoke_list, pNodeList);
  1657. if (rc == GCC_NO_ERROR)
  1658. {
  1659. pSap->AppInvokeConfirm(m_nConfID, invoke_list, GCC_RESULT_SUCCESSFUL, nReqTag);
  1660. }
  1661. }
  1662. else
  1663. {
  1664. ERROR_OUT(("CConf::AppInvokeRequest: conference not established"));
  1665. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1666. }
  1667. DebugExitINT(CConf::AppInvokeRequest, rc);
  1668. return rc;
  1669. }
  1670. /*
  1671. * GCCError TextMessageRequest ()
  1672. *
  1673. * Public Function Description
  1674. * This function initiates an TextMessageRequest sequence.
  1675. */
  1676. #ifdef JASPER
  1677. GCCError CConf::
  1678. TextMessageRequest
  1679. (
  1680. LPWSTR pwszTextMsg,
  1681. UserID destination_node
  1682. )
  1683. {
  1684. GCCError rc;
  1685. DebugEntry(CConf::TextMessageRequest);
  1686. if (m_fConfIsEstablished)
  1687. {
  1688. if (destination_node != m_pMcsUserObject->GetMyNodeID())
  1689. {
  1690. rc = m_pMcsUserObject->TextMessageIndication(pwszTextMsg, destination_node);
  1691. #ifdef JASPER
  1692. if (rc == GCC_NO_ERROR)
  1693. {
  1694. g_pControlSap->TextMessageConfirm(m_nConfID, GCC_RESULT_SUCCESSFUL);
  1695. }
  1696. #endif // JASPER
  1697. }
  1698. else
  1699. {
  1700. WARNING_OUT(("CConf::TextMessageRequest: invalid user ID"));
  1701. rc = GCC_INVALID_MCS_USER_ID;
  1702. }
  1703. }
  1704. else
  1705. {
  1706. ERROR_OUT(("CConf::TextMessageRequest: conference not established"));
  1707. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1708. }
  1709. DebugExitINT(CConf::TextMessageRequest, rc);
  1710. return rc;
  1711. }
  1712. #endif // JASPER
  1713. /*
  1714. * GCCError ConfTransferRequest ()
  1715. *
  1716. * Public Function Description
  1717. * This function initiates an ConfTransferRequest sequence.
  1718. */
  1719. #ifdef JASPER
  1720. GCCError CConf::
  1721. ConfTransferRequest
  1722. (
  1723. PGCCConferenceName destination_conference_name,
  1724. GCCNumericString destination_conference_modifier,
  1725. CNetAddrListContainer *destination_address_list,
  1726. UINT number_of_destination_nodes,
  1727. PUserID destination_node_list,
  1728. CPassword *password
  1729. )
  1730. {
  1731. GCCError rc = GCC_NO_ERROR;
  1732. DebugEntry(CConf::ConfTransferRequest);
  1733. if (m_fConfIsEstablished)
  1734. {
  1735. if (IsConfTopProvider())
  1736. {
  1737. if (DoesRequesterHavePrivilege( m_pMcsUserObject->GetMyNodeID(),
  1738. TRANSFER_PRIVILEGE))
  1739. {
  1740. rc = m_pMcsUserObject->ConferenceTransferIndication(
  1741. destination_conference_name,
  1742. destination_conference_modifier,
  1743. destination_address_list,
  1744. number_of_destination_nodes,
  1745. destination_node_list,
  1746. password);
  1747. #ifdef JASPER
  1748. if (rc == GCC_NO_ERROR)
  1749. {
  1750. g_pControlSap->ConfTransferConfirm(
  1751. m_nConfID,
  1752. destination_conference_name,
  1753. destination_conference_modifier,
  1754. number_of_destination_nodes,
  1755. destination_node_list,
  1756. GCC_RESULT_SUCCESSFUL);
  1757. }
  1758. #endif // JASPER
  1759. }
  1760. else
  1761. {
  1762. WARNING_OUT(("CConf::ConfTransferRequest: insufficient privilege to transfer conference"));
  1763. }
  1764. }
  1765. else
  1766. {
  1767. rc = m_pMcsUserObject->ConferenceTransferRequest(
  1768. destination_conference_name,
  1769. destination_conference_modifier,
  1770. destination_address_list,
  1771. number_of_destination_nodes,
  1772. destination_node_list,
  1773. password);
  1774. }
  1775. }
  1776. else
  1777. {
  1778. ERROR_OUT(("CConf::ConfTransferRequest: conference not established"));
  1779. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1780. }
  1781. DebugExitINT(CConf::ConfTransferRequest, rc);
  1782. return rc;
  1783. }
  1784. #endif // JASPER
  1785. /*
  1786. * GCCError ConfAddRequest ()
  1787. *
  1788. * Public Function Description
  1789. * This function initiates an ConfAddRequest sequence.
  1790. */
  1791. #ifdef JASPER
  1792. GCCError CConf::
  1793. ConfAddRequest
  1794. (
  1795. CNetAddrListContainer *network_address_container,
  1796. UserID adding_node,
  1797. CUserDataListContainer *user_data_container
  1798. )
  1799. {
  1800. GCCError rc = GCC_NO_ERROR;
  1801. TagNumber conference_add_tag;
  1802. UserID target_node;
  1803. DebugEntry(CConf::ConfAddRequest);
  1804. if (! m_fConfIsEstablished)
  1805. {
  1806. ERROR_OUT(("CConf::ConfAddRequest: conference not established"));
  1807. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1808. goto MyExit;
  1809. }
  1810. /*
  1811. ** A node cannot tell itself to add because of the way the
  1812. ** Add Response call works. Since an Add Response is sent non-
  1813. ** uniformly directly to the node that made the request the response
  1814. ** would never reach the requesting node. Therefore, this is flaged
  1815. ** as an error condition here.
  1816. */
  1817. if (adding_node == m_pMcsUserObject->GetMyNodeID())
  1818. {
  1819. ERROR_OUT(("CConf::ConfAddRequest: can't tell myself to add"));
  1820. rc = GCC_BAD_ADDING_NODE;
  1821. goto MyExit;
  1822. }
  1823. /*
  1824. ** Note that the way the standard reads, it looks like you
  1825. ** do not have to check the privileges for the top provider
  1826. ** on an Add. We do though check to see if the Top Provider is
  1827. ** making the request to a node other than the top provider. If
  1828. ** not this is considered an error here.
  1829. */
  1830. if (IsConfTopProvider())
  1831. {
  1832. /*
  1833. ** If the adding node is zero at the top provider, this is
  1834. ** the same as specifying ones self to be the adding node.
  1835. */
  1836. if (adding_node == 0)
  1837. {
  1838. ERROR_OUT(("CConf::ConfAddRequest: can't tell myself to add"));
  1839. rc = GCC_BAD_ADDING_NODE;
  1840. goto MyExit;
  1841. }
  1842. else
  1843. {
  1844. target_node = adding_node;
  1845. }
  1846. }
  1847. else
  1848. {
  1849. target_node = m_pMcsUserObject->GetTopNodeID();
  1850. }
  1851. // First determine the conference add tag
  1852. while (1)
  1853. {
  1854. conference_add_tag = ++m_nConfAddRequestTagNumber;
  1855. if (NULL == m_AddRequestList.Find(conference_add_tag))
  1856. break;
  1857. }
  1858. // Send out the PDU
  1859. rc = m_pMcsUserObject->ConferenceAddRequest(
  1860. conference_add_tag,
  1861. m_pMcsUserObject->GetMyNodeID(),
  1862. adding_node,
  1863. target_node,
  1864. network_address_container,
  1865. user_data_container);
  1866. if (GCC_NO_ERROR != rc)
  1867. {
  1868. ERROR_OUT(("CConf::ConfAddRequest: ConferenceAddRequest failed, rc=%d", rc));
  1869. goto MyExit;
  1870. }
  1871. /*
  1872. ** We must lock the network address to keep it from
  1873. ** being deleted upon returning.
  1874. */
  1875. if (network_address_container != NULL)
  1876. {
  1877. network_address_container->LockNetworkAddressList();
  1878. }
  1879. // Add this entry to the add request list.
  1880. m_AddRequestList.Append(conference_add_tag, network_address_container);
  1881. ASSERT(GCC_NO_ERROR == rc);
  1882. MyExit:
  1883. DebugExitINT(CConf::ConfAddRequest, rc);
  1884. return rc;
  1885. }
  1886. #endif // JASPER
  1887. /*
  1888. * GCCError ConfAddResponse ()
  1889. *
  1890. * Public Function Description
  1891. * This call is made in response to an Add indication. It is initiated
  1892. * by the Node Controller.
  1893. */
  1894. GCCError CConf::
  1895. ConfAddResponse
  1896. (
  1897. GCCResponseTag add_response_tag,
  1898. UserID requesting_node,
  1899. CUserDataListContainer *user_data_container,
  1900. GCCResult result
  1901. )
  1902. {
  1903. GCCError rc;
  1904. TagNumber lTagNum;
  1905. DebugEntry(CConf::ConfAddResponse);
  1906. if (m_fConfIsEstablished)
  1907. {
  1908. if (0 != (lTagNum = m_AddResponseList.Find(add_response_tag)))
  1909. {
  1910. // Send out the response PDU
  1911. rc = m_pMcsUserObject->ConferenceAddResponse(lTagNum, requesting_node,
  1912. user_data_container, result);
  1913. if (rc == GCC_NO_ERROR)
  1914. {
  1915. m_AddResponseList.Remove(add_response_tag);
  1916. }
  1917. else
  1918. {
  1919. ERROR_OUT(("CConf::ConfAddResponse: ConferenceAddResponse failed, rc=%d", rc));
  1920. }
  1921. }
  1922. else
  1923. {
  1924. ERROR_OUT(("CConf::ConfAddResponse: invalid add response tag"));
  1925. rc = GCC_INVALID_ADD_RESPONSE_TAG;
  1926. }
  1927. }
  1928. else
  1929. {
  1930. ERROR_OUT(("CConf::ConfAddResponse: conference not established"));
  1931. rc = GCC_CONFERENCE_NOT_ESTABLISHED;
  1932. }
  1933. DebugExitINT(CConf::ConfAddResponse, rc);
  1934. return rc;
  1935. }
  1936. /*
  1937. ** These calls are received from the User Attachment object via the
  1938. ** Owner-Callback routine. Note that all calls received from the
  1939. ** user attachment object are preceeded by the word Process.
  1940. */
  1941. /*
  1942. * CConf::ProcessRosterUpdateIndication ()
  1943. *
  1944. * Private Function Description
  1945. * This routine is responsible for processing all the incomming roster
  1946. * update PDUs which are received from subordinate nodes. These
  1947. * roster updates typically only include additions, changes or deletions
  1948. * of a few records within each PDU.
  1949. *
  1950. * Formal Parameters:
  1951. * roster_update - This is the PDU structure that contains the data
  1952. * associated with the roster update.
  1953. * sender_id - User ID of node that sent the roster update.
  1954. *
  1955. * Return Value
  1956. * None.
  1957. *
  1958. * Side Effects
  1959. * None.
  1960. *
  1961. * Caveats
  1962. * None.
  1963. */
  1964. void CConf::
  1965. ProcessRosterUpdatePDU
  1966. (
  1967. PGCCPDU roster_update,
  1968. UserID sender_id
  1969. )
  1970. {
  1971. GCCError err = GCC_NO_ERROR;
  1972. DebugEntry(CConf::ProcessRosterUpdatePDU);
  1973. if (m_pConfRosterMgr != NULL)
  1974. {
  1975. err = m_pConfRosterMgr->RosterUpdateIndication(roster_update, sender_id);
  1976. if (err != GCC_NO_ERROR)
  1977. {
  1978. goto MyExit;
  1979. }
  1980. // Process the whole PDU before performing the flush.
  1981. err = ProcessAppRosterIndicationPDU(roster_update, sender_id);
  1982. if (err != GCC_NO_ERROR)
  1983. {
  1984. goto MyExit;
  1985. }
  1986. UpdateNodeVersionList(roster_update, sender_id);
  1987. /*
  1988. ** If this is the top provider and we are adding new nodes
  1989. ** then we must update the new node with various roster
  1990. ** information. That is what is going on here. If no new
  1991. ** nodes have been added we go ahead and perform the
  1992. ** Flush here.
  1993. */
  1994. if (IsConfTopProvider() &&
  1995. roster_update->u.indication.u.roster_update_indication.node_information.nodes_are_added)
  1996. {
  1997. err = UpdateNewConferenceNode ();
  1998. }
  1999. else
  2000. {
  2001. //
  2002. // We just got an roster update from the wire.
  2003. //
  2004. err = FlushRosterData();
  2005. }
  2006. }
  2007. MyExit:
  2008. if (err != GCC_NO_ERROR)
  2009. {
  2010. ERROR_OUT(("CConf::ProcessRosterUpdatePDU: error processing roster refresh indication"));
  2011. InitiateTermination(GCC_REASON_ERROR_TERMINATION, 0);
  2012. }
  2013. DebugExitVOID(CConf::ProcessRosterUpdatePDU);
  2014. }
  2015. /*
  2016. * GCCError ProcessAppRosterIndicationPDU ()
  2017. *
  2018. * Private Function Description
  2019. * This function operates specifically on the application roster
  2020. * portion of a roster PDU.
  2021. *
  2022. * Formal Parameters:
  2023. * roster_update - This is the PDU structure that contains the data
  2024. * associated with the roster update.
  2025. * sender_id - User ID of node that sent the roster update.
  2026. *
  2027. * Return Value
  2028. * GCC_NO_ERROR - No error.
  2029. * GCC_ALLOCATION_FAILURE - A resource error occured.
  2030. * GCC_BAD_SESSION_KEY - A bad session key exists in the update.
  2031. *
  2032. * Side Effects
  2033. * None.
  2034. *
  2035. * Caveats
  2036. * None.
  2037. */
  2038. GCCError CConf::
  2039. ProcessAppRosterIndicationPDU
  2040. (
  2041. PGCCPDU roster_update,
  2042. UserID sender_id
  2043. )
  2044. {
  2045. GCCError rc = GCC_NO_ERROR;
  2046. PSetOfApplicationInformation set_of_application_info;
  2047. CAppRosterMgr *app_roster_manager;
  2048. CAppRosterMgr *new_app_roster_manager;
  2049. PSessionKey session_key;
  2050. DebugEntry(CConf::ProcessAppRosterIndicationPDU);
  2051. set_of_application_info = roster_update->u.indication.u.
  2052. roster_update_indication.application_information;
  2053. /*
  2054. ** First we iterate through the complete set of application information
  2055. ** to determine if there is information here for an application roster
  2056. ** manager that does not yet exists. If we find one that does not
  2057. ** exists we must go ahead and create it.
  2058. */
  2059. while (set_of_application_info != NULL)
  2060. {
  2061. CAppRosterMgr *pMgr;
  2062. // First set up the session key PDU pointer
  2063. session_key = &set_of_application_info->value.session_key;
  2064. /*
  2065. ** We first iterate through the complete list of application
  2066. ** roster manager objects looking for one with an application key that
  2067. ** matches the key in the PDU. If it is not found we create it.
  2068. */
  2069. app_roster_manager = NULL;
  2070. new_app_roster_manager = NULL;
  2071. //
  2072. // LONCHANC: We should be able to move this as separate common subroutine.
  2073. //
  2074. m_AppRosterMgrList.Reset();
  2075. while (NULL != (pMgr = m_AppRosterMgrList.Iterate()))
  2076. {
  2077. if (pMgr->IsThisYourSessionKeyPDU(session_key))
  2078. {
  2079. // This application roster manager exist so return it.
  2080. app_roster_manager = pMgr;
  2081. break;
  2082. }
  2083. }
  2084. /*
  2085. ** If a roster manager associated with this app key does not exist
  2086. ** we must create it here.
  2087. */
  2088. if (app_roster_manager == NULL)
  2089. {
  2090. DBG_SAVE_FILE_LINE
  2091. app_roster_manager = new CAppRosterMgr(
  2092. NULL,
  2093. session_key,
  2094. m_nConfID,
  2095. m_pMcsUserObject,
  2096. this,
  2097. &rc);
  2098. if (NULL == app_roster_manager || GCC_NO_ERROR != rc)
  2099. {
  2100. ERROR_OUT(("CConf::ProcessAppRosterIndicationPDU: can't create app roster mgr, rc=%d", rc));
  2101. if (NULL != app_roster_manager)
  2102. {
  2103. app_roster_manager->Release();
  2104. }
  2105. else
  2106. {
  2107. rc = GCC_ALLOCATION_FAILURE;
  2108. }
  2109. goto MyExit;
  2110. }
  2111. new_app_roster_manager = app_roster_manager;
  2112. }
  2113. /*
  2114. ** We no process this set of application information. We pass it
  2115. ** to the app roster manager found or created above.
  2116. */
  2117. rc = app_roster_manager->ProcessRosterUpdateIndicationPDU(
  2118. set_of_application_info,
  2119. sender_id);
  2120. if (GCC_NO_ERROR != rc)
  2121. {
  2122. //
  2123. // LONCHANC: We should delete the newly created roster mgr.
  2124. //
  2125. if (NULL != new_app_roster_manager)
  2126. {
  2127. new_app_roster_manager->Release();
  2128. }
  2129. goto MyExit;
  2130. }
  2131. /*
  2132. ** Save the new application roster manager if one was created
  2133. ** when processing this roster update.
  2134. */
  2135. if (new_app_roster_manager != NULL)
  2136. {
  2137. m_AppRosterMgrList.Append(new_app_roster_manager);
  2138. }
  2139. // Load the next application information structure.
  2140. set_of_application_info = set_of_application_info->next;
  2141. }
  2142. ASSERT(GCC_NO_ERROR == rc);
  2143. MyExit:
  2144. DebugExitINT(CConf::ProcessAppRosterIndicationPDU, rc);
  2145. return rc;
  2146. }
  2147. /*
  2148. * CConf::ProcessDetachUserIndication ()
  2149. *
  2150. * Private Function Description
  2151. * This routine sends the detach user indication to the node controler
  2152. * and updates the roster.
  2153. *
  2154. * Formal Parameters:
  2155. * detached_user - User ID of user that detached from the conference.
  2156. * reason - Reason that the user detached.
  2157. *
  2158. * Return Value
  2159. * None.
  2160. *
  2161. * Side Effects
  2162. * None.
  2163. *
  2164. * Caveats
  2165. * None.
  2166. */
  2167. void CConf::
  2168. ProcessDetachUserIndication
  2169. (
  2170. UserID detached_user,
  2171. GCCReason reason
  2172. )
  2173. {
  2174. GCCError err = GCC_NO_ERROR;
  2175. UINT cRecords;
  2176. DebugEntry(CConf::ProcessDetachUserIndication);
  2177. if (m_fConfIsEstablished)
  2178. {
  2179. CAppRosterMgr *lpAppRosterMgr;
  2180. /*
  2181. ** Send a disconnect indication to the node controller if this
  2182. ** detached user corresponds to a GCC user id.
  2183. */
  2184. if (m_pConfRosterMgr->Contains(detached_user))
  2185. {
  2186. g_pControlSap->ConfDisconnectIndication(
  2187. m_nConfID,
  2188. reason,
  2189. detached_user);
  2190. }
  2191. // Here we update the CConf Roster and the Application Roster.
  2192. err = m_pConfRosterMgr->RemoveUserReference(detached_user);
  2193. if (err == GCC_NO_ERROR)
  2194. {
  2195. if (IsConfTopProvider())
  2196. {
  2197. cRecords = m_pConfRosterMgr->GetNumberOfNodeRecords();
  2198. /*
  2199. ** If only one record remains in the conference roster
  2200. ** it must be the local nodes record. Therefore, if
  2201. ** the conference is set up to be automatically
  2202. ** terminated the owner object is notified to delete
  2203. ** the conference.
  2204. */
  2205. if ((m_eTerminationMethod == GCC_AUTOMATIC_TERMINATION_METHOD)
  2206. && (cRecords == 1))
  2207. {
  2208. TRACE_OUT(("CConf::ProcessDetachUserIndication: AUTOMATIC_TERMINATION"));
  2209. InitiateTermination(GCC_REASON_NORMAL_TERMINATION, 0);
  2210. }
  2211. // If this is the convener set its node id back to 0
  2212. if (m_nConvenerNodeID == detached_user)
  2213. {
  2214. m_nConvenerNodeID = 0;
  2215. }
  2216. }
  2217. }
  2218. else
  2219. if (err == GCC_INVALID_PARAMETER)
  2220. {
  2221. err = GCC_NO_ERROR;
  2222. }
  2223. /*
  2224. ** Cleanup the Application Rosters of any records owned by this node.
  2225. */
  2226. m_AppRosterMgrList.Reset();
  2227. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  2228. {
  2229. err = lpAppRosterMgr->RemoveUserReference(detached_user);
  2230. if (GCC_NO_ERROR != err)
  2231. {
  2232. WARNING_OUT(("CConf::ProcessDetachUserIndication: can't remove user reference from app roster mgr, err=%d", err));
  2233. break;
  2234. }
  2235. }
  2236. // Remove ownership rights this user had on any registry entries.
  2237. m_pAppRegistry->RemoveNodeOwnership(detached_user);
  2238. // Cleanup Conductorship if detached user was the conductor
  2239. if (detached_user == m_nConductorNodeID)
  2240. {
  2241. ProcessConductorReleaseIndication(0);
  2242. }
  2243. /*
  2244. ** Here we give the roster managers a chance to flush any PDUs
  2245. ** or data that might have gotten queued when removing the user
  2246. ** reference. An error here is considered FATAL in that the conference
  2247. ** information base at this node is now corrupted therefore we
  2248. ** terminate the conference.
  2249. */
  2250. if (err == GCC_NO_ERROR)
  2251. {
  2252. //
  2253. // We just got detach user indication from the wire.
  2254. //
  2255. err = FlushRosterData();
  2256. }
  2257. if (err != GCC_NO_ERROR)
  2258. {
  2259. ERROR_OUT(("CConf::ProcessDetachUserIndication: Error occured when flushing the rosters, err=%d", err));
  2260. InitiateTermination((err == GCC_ALLOCATION_FAILURE) ?
  2261. GCC_REASON_ERROR_LOW_RESOURCES :
  2262. GCC_REASON_ERROR_TERMINATION,
  2263. 0);
  2264. }
  2265. }
  2266. DebugExitVOID(CConf::ProcessDetachUserIndication);
  2267. }
  2268. /*
  2269. * CConf::ProcessTerminateRequest ()
  2270. *
  2271. * Private Function Description
  2272. * This routine processes a terminate request received from the MCSUser
  2273. * object.
  2274. *
  2275. * Formal Parameters:
  2276. * requester_id - User ID of node that is requesting the terminate.
  2277. * reason - Reason for termination.
  2278. *
  2279. * Return Value
  2280. * None.
  2281. *
  2282. * Side Effects
  2283. * None.
  2284. *
  2285. * Caveats
  2286. * None.
  2287. */
  2288. void CConf::
  2289. ProcessTerminateRequest
  2290. (
  2291. UserID requester_id,
  2292. GCCReason reason
  2293. )
  2294. {
  2295. DebugEntry(CConf::ProcessTerminateRequest);
  2296. if (DoesRequesterHavePrivilege(requester_id, TERMINATE_PRIVILEGE))
  2297. {
  2298. TRACE_OUT(("CConf::ProcessTerminateRequest: Node has permission to terminate"));
  2299. /*
  2300. ** Since the terminate was successful, we go ahead and set the
  2301. ** m_fConfIsEstablished instance variable to FALSE. This prevents
  2302. ** any other messages from flowing to the SAPs other than terminate
  2303. ** messages.
  2304. */
  2305. m_fConfIsEstablished = FALSE;
  2306. // Send a positive response to the requesting node
  2307. m_pMcsUserObject->ConferenceTerminateResponse(requester_id, GCC_RESULT_SUCCESSFUL);
  2308. /*
  2309. ** This request will kick off a terminate at this node as well as
  2310. ** all the nodes below this node in the connection hierarchy.
  2311. */
  2312. m_pMcsUserObject->ConferenceTerminateIndication(reason);
  2313. }
  2314. else
  2315. {
  2316. WARNING_OUT(("CConf::ProcessTerminateRequest: Node does NOT have permission to terminate"));
  2317. // Send a negative response to the requesting node
  2318. m_pMcsUserObject->ConferenceTerminateResponse(requester_id, GCC_RESULT_INVALID_REQUESTER);
  2319. }
  2320. DebugExitVOID(CConf::ProcessTerminateRequest);
  2321. }
  2322. /*
  2323. * CConf::ProcessTerminateIndication ()
  2324. *
  2325. * Private Function Description
  2326. * This routine takes care of both a normal termination through
  2327. * a terminate pdu and termination that occurs due to a parent
  2328. * node disconnecting.
  2329. *
  2330. * Formal Parameters:
  2331. * reason - Reason for termination.
  2332. *
  2333. * Return Value
  2334. * None.
  2335. *
  2336. * Side Effects
  2337. * None.
  2338. *
  2339. * Caveats
  2340. * None.
  2341. */
  2342. void CConf::
  2343. ProcessTerminateIndication ( GCCReason gcc_reason )
  2344. {
  2345. UserID user_id;
  2346. DebugEntry(CConf::ProcessTerminateIndication);
  2347. /*
  2348. ** Setting this to true here will insure that a terminate indication
  2349. ** will be delivered to the control SAP.
  2350. */
  2351. m_fConfTerminatePending = TRUE;
  2352. if (gcc_reason == GCC_REASON_PARENT_DISCONNECTED)
  2353. {
  2354. TRACE_OUT(("CConf::ProcessTerminateIndication: Terminate due to parent disconnecting"));
  2355. user_id = m_pMcsUserObject->GetMyNodeID();
  2356. }
  2357. else
  2358. if (m_ConnHandleList.IsEmpty())
  2359. {
  2360. TRACE_OUT(("CConf: ProcessTerminateIndication: Terminate due to request (no child connections)"));
  2361. /*
  2362. ** Since there is a flaw in the terminate indication PDU were the
  2363. ** node id that requested the termination is not sent we always
  2364. ** assume here that the request came from the top provider (which
  2365. ** is only partially true).
  2366. */
  2367. user_id = m_pMcsUserObject->GetTopNodeID();
  2368. }
  2369. else
  2370. {
  2371. TRACE_OUT(("CConf::ProcessTerminateIndication: Wait till children disconnect before terminating"));
  2372. /*
  2373. ** Wait until disconnect provider indications are received on all the
  2374. ** child connections before terminating the conference.
  2375. */
  2376. m_eConfTerminateReason = gcc_reason;
  2377. DBG_SAVE_FILE_LINE
  2378. m_pConfTerminateAlarm = new Alarm (TERMINATE_TIMER_DURATION);
  2379. if (NULL != m_pConfTerminateAlarm)
  2380. {
  2381. // let's wait, bail out without initiating termination.
  2382. goto MyExit;
  2383. }
  2384. // Go ahead and terminate if there is a resource error
  2385. ERROR_OUT(("CConf: ProcessTerminateIndication: can't create terminate alarm"));
  2386. user_id = m_pMcsUserObject->GetTopNodeID();
  2387. }
  2388. InitiateTermination(gcc_reason, user_id);
  2389. MyExit:
  2390. DebugExitVOID(CConf::ProcessTerminateIndication);
  2391. }
  2392. /*
  2393. * CConf::ProcessUserIDIndication ()
  2394. *
  2395. * Private Function Description
  2396. * This routine is responsible for matching incomming user IDs with
  2397. * tag numbers returned by the subordinate node.
  2398. *
  2399. * Formal Parameters:
  2400. * tag_number - Tag used to match incomming user ID indication.
  2401. * user_id - User ID of node sending the indication.
  2402. *
  2403. * Return Value
  2404. * None.
  2405. *
  2406. * Side Effects
  2407. * None.
  2408. *
  2409. * Caveats
  2410. * None.
  2411. */
  2412. // checkpoint
  2413. void CConf::
  2414. ProcessUserIDIndication
  2415. (
  2416. TagNumber tag_number,
  2417. UserID user_id
  2418. )
  2419. {
  2420. INVITE_REQ_INFO *invite_request_info;
  2421. ConnectionHandle nConnHdl;
  2422. DebugEntry(CConf::ProcessUserIDIndication);
  2423. if (0 != (nConnHdl = m_ConnHdlTagNumberList2.Remove(tag_number)))
  2424. {
  2425. INVITE_REQ_INFO *lpInvReqInfo;
  2426. if (m_pMcsUserObject != NULL)
  2427. {
  2428. TRACE_OUT(("CConf: ProcessUserIDIndication: ID is set"));
  2429. m_pMcsUserObject->SetChildUserIDAndConnection(user_id, nConnHdl);
  2430. }
  2431. else
  2432. {
  2433. TRACE_OUT(("CConf::UserIDIndication: Error User Att. is NULL"));
  2434. }
  2435. /*
  2436. ** Here we send an indication informing the node controller that
  2437. ** a subordinate node has completed initialization.
  2438. */
  2439. g_pControlSap->SubInitializationCompleteIndication (user_id, nConnHdl);
  2440. /*
  2441. ** Now we determine if the responding node is the convener and if it
  2442. ** is we will set up the m_nConvenerNodeID. This node id is used to
  2443. ** determine privileges on certain GCC operations.
  2444. */
  2445. if (m_nConvenerUserIDTagNumber == tag_number)
  2446. {
  2447. TRACE_OUT(("CConf::UserIDIndication: Convener Node ID is being set"));
  2448. m_nConvenerUserIDTagNumber = 0;
  2449. m_nConvenerNodeID = user_id;
  2450. }
  2451. /*
  2452. ** If this is a User ID from an invited node we must pass the invite
  2453. ** confirm to the Node Controller.
  2454. */
  2455. m_InviteRequestList.Reset();
  2456. invite_request_info = NULL;
  2457. while (NULL != (lpInvReqInfo = m_InviteRequestList.Iterate()))
  2458. {
  2459. if (tag_number == lpInvReqInfo->invite_tag)
  2460. {
  2461. invite_request_info = lpInvReqInfo;
  2462. break;
  2463. }
  2464. }
  2465. if (invite_request_info != NULL)
  2466. {
  2467. g_pControlSap->ConfInviteConfirm(
  2468. m_nConfID,
  2469. invite_request_info->user_data_list,
  2470. GCC_RESULT_SUCCESSFUL,
  2471. invite_request_info->connection_handle);
  2472. // Free up user data if it exists
  2473. if (invite_request_info->user_data_list != NULL)
  2474. {
  2475. invite_request_info->user_data_list->Release();
  2476. }
  2477. // Cleanup the invite request list
  2478. m_InviteRequestList.Remove(invite_request_info);
  2479. // Free up the invite request info structure
  2480. delete invite_request_info;
  2481. }
  2482. }
  2483. else
  2484. {
  2485. TRACE_OUT(("CConf::ProcessUserIDIndication: Bad User ID Tag Number received"));
  2486. }
  2487. DebugExitVOID(CConf::ProcessUserIDIndication);
  2488. }
  2489. /*
  2490. * CConf::ProcessUserCreateConfirm ()
  2491. *
  2492. * Private Function Description
  2493. * This routine handles the processes that occur after a user
  2494. * create confirm is received. This process will differ depending
  2495. * on what the node type is.
  2496. *
  2497. * Formal Parameters:
  2498. * result_value - Result of the user attachment being created.
  2499. * node_id - This nodes node id.
  2500. *
  2501. * Return Value
  2502. * None.
  2503. *
  2504. * Side Effects
  2505. * None.
  2506. *
  2507. * Caveats
  2508. * None.
  2509. */
  2510. void CConf::
  2511. ProcessUserCreateConfirm
  2512. (
  2513. UserResultType result_value,
  2514. UserID node_id
  2515. )
  2516. {
  2517. GCCError err = GCC_NO_ERROR;
  2518. PUChar encoded_pdu;
  2519. UINT encoded_pdu_length;
  2520. ConnectGCCPDU connect_pdu;
  2521. MCSError mcs_error;
  2522. GCCConferenceName conference_name;
  2523. GCCNumericString conference_modifier;
  2524. GCCNumericString remote_modifier = NULL;
  2525. BOOL is_top_provider;
  2526. DebugEntry(CConf::ProcessUserCreateConfirm);
  2527. if (result_value == USER_RESULT_SUCCESSFUL)
  2528. {
  2529. switch (m_eNodeType)
  2530. {
  2531. case TOP_PROVIDER_NODE:
  2532. /*
  2533. ** Encode the tag number into the ConferenceCreateResponse
  2534. ** PDU. If we have gotten this far the result is success.
  2535. */
  2536. connect_pdu.choice = CONFERENCE_CREATE_RESPONSE_CHOSEN;
  2537. connect_pdu.u.conference_create_response.bit_mask = 0;
  2538. connect_pdu.u.conference_create_response.node_id = node_id;
  2539. /*
  2540. ** Here we save this particular User ID tag and mark it as the
  2541. ** conveners so that when the convener's user ID is returned
  2542. ** the m_nConvenerNodeID instance variable can be properly
  2543. ** initialized.
  2544. */
  2545. m_nConvenerUserIDTagNumber = GetNewUserIDTag ();
  2546. connect_pdu.u.conference_create_response.tag = m_nConvenerUserIDTagNumber;
  2547. if (m_pUserDataList != NULL)
  2548. {
  2549. connect_pdu.u.conference_create_response.bit_mask |= CCRS_USER_DATA_PRESENT;
  2550. err = m_pUserDataList->GetUserDataPDU(
  2551. &connect_pdu.u.conference_create_response.ccrs_user_data);
  2552. if (err != GCC_NO_ERROR)
  2553. {
  2554. // Terminate conference due to resource error
  2555. InitiateTermination ( GCC_REASON_ERROR_LOW_RESOURCES,
  2556. 0);
  2557. break;
  2558. }
  2559. }
  2560. connect_pdu.u.conference_create_response.result =
  2561. ::TranslateGCCResultToCreateResult(GCC_RESULT_SUCCESSFUL);
  2562. if (g_GCCCoder->Encode((LPVOID) &connect_pdu,
  2563. CONNECT_GCC_PDU,
  2564. PACKED_ENCODING_RULES,
  2565. &encoded_pdu,
  2566. &encoded_pdu_length))
  2567. {
  2568. mcs_error = g_pMCSIntf->ConnectProviderResponse (
  2569. m_hConvenerConnection,
  2570. &m_nConfID,
  2571. m_pDomainParameters,
  2572. RESULT_SUCCESSFUL,
  2573. encoded_pdu,
  2574. encoded_pdu_length);
  2575. g_GCCCoder->FreeEncoded(encoded_pdu);
  2576. if (mcs_error == MCS_NO_ERROR)
  2577. {
  2578. m_fConfIsEstablished = TRUE;
  2579. /*
  2580. ** Add the user's tag number to the list of
  2581. ** outstanding user ids along with its associated
  2582. ** connection.
  2583. */
  2584. ASSERT(0 != m_hConvenerConnection);
  2585. m_ConnHdlTagNumberList2.Append(connect_pdu.u.conference_create_response.tag,
  2586. m_hConvenerConnection);
  2587. }
  2588. else if (mcs_error == MCS_DOMAIN_PARAMETERS_UNACCEPTABLE)
  2589. {
  2590. /*
  2591. ** Inform the node controller that the reason
  2592. ** the conference was terminated was that the
  2593. ** domain parameter passed in the Create Response
  2594. ** were unacceptable.
  2595. */
  2596. InitiateTermination(GCC_REASON_DOMAIN_PARAMETERS_UNACCEPTABLE, 0);
  2597. }
  2598. else
  2599. {
  2600. InitiateTermination(GCC_REASON_MCS_RESOURCE_FAILURE, 0);
  2601. }
  2602. }
  2603. else
  2604. {
  2605. /*
  2606. ** A Fatal Resource error has occured. At this point
  2607. ** the conference is invalid and should be terminated.
  2608. */
  2609. ERROR_OUT(("CConf::ProcessUserCreateConfirm: can't encode. Terminate Conference"));
  2610. InitiateTermination(GCC_REASON_ERROR_LOW_RESOURCES, 0);
  2611. }
  2612. break;
  2613. case CONVENER_NODE:
  2614. /*
  2615. ** Send the GCC User ID is here. This will require a call to
  2616. ** the User Object. The tag number that was returned in
  2617. ** the ConfCreateResponse call is used here.
  2618. */
  2619. if (m_pMcsUserObject != NULL)
  2620. {
  2621. m_pMcsUserObject->SendUserIDRequest(m_nParentIDTagNumber);
  2622. }
  2623. // Fill in the conference name data pointers.
  2624. GetConferenceNameAndModifier(&conference_name, &conference_modifier);
  2625. g_pControlSap->ConfCreateConfirm(&conference_name,
  2626. conference_modifier,
  2627. m_nConfID,
  2628. m_pDomainParameters,
  2629. m_pUserDataList,
  2630. GCC_RESULT_SUCCESSFUL,
  2631. m_hParentConnection);
  2632. // Free up the User Data List
  2633. if (m_pUserDataList != NULL)
  2634. {
  2635. m_pUserDataList->Release();
  2636. m_pUserDataList = NULL;
  2637. }
  2638. m_fConfIsEstablished = TRUE;
  2639. break;
  2640. case TOP_PROVIDER_AND_CONVENER_NODE:
  2641. /*
  2642. ** First set up the convener node id. In this case it is
  2643. ** identical to the node ID of the Top Provider which is this
  2644. ** node.
  2645. */
  2646. m_nConvenerNodeID = m_pMcsUserObject->GetMyNodeID();
  2647. // Fill in the conference name data pointers.
  2648. GetConferenceNameAndModifier( &conference_name,
  2649. &conference_modifier);
  2650. g_pControlSap->ConfCreateConfirm(
  2651. &conference_name,
  2652. conference_modifier,
  2653. m_nConfID,
  2654. m_pDomainParameters,
  2655. NULL,
  2656. GCC_RESULT_SUCCESSFUL,
  2657. 0); //Parent Connection
  2658. m_fConfIsEstablished = TRUE;
  2659. break;
  2660. case JOINED_NODE:
  2661. case JOINED_CONVENER_NODE:
  2662. /*
  2663. ** Send the GCC User ID is here. This will require a call to
  2664. ** the User Object. The tag number that was returned in
  2665. ** the ConfCreateResponse call is used here.
  2666. */
  2667. if (m_pMcsUserObject != NULL)
  2668. {
  2669. m_pMcsUserObject->SendUserIDRequest(m_nParentIDTagNumber);
  2670. }
  2671. // Fill in the conference name data pointers.
  2672. GetConferenceNameAndModifier( &conference_name,
  2673. &conference_modifier);
  2674. if (m_pszRemoteModifier != NULL)
  2675. {
  2676. remote_modifier = (GCCNumericString) m_pszRemoteModifier;
  2677. }
  2678. g_pControlSap->ConfJoinConfirm(
  2679. &conference_name,
  2680. remote_modifier,
  2681. conference_modifier,
  2682. m_nConfID,
  2683. NULL,
  2684. m_pDomainParameters,
  2685. m_fClearPassword,
  2686. m_fConfLocked,
  2687. m_fConfListed,
  2688. m_fConfConductible,
  2689. m_eTerminationMethod,
  2690. m_pConductorPrivilegeList,
  2691. m_pConductModePrivilegeList,
  2692. m_pNonConductModePrivilegeList,
  2693. m_pwszConfDescription,
  2694. m_pUserDataList,
  2695. GCC_RESULT_SUCCESSFUL,
  2696. m_hParentConnection,
  2697. NULL,
  2698. 0);
  2699. m_fConfIsEstablished = TRUE;
  2700. break;
  2701. case INVITED_NODE:
  2702. /*
  2703. ** Send the GCC User ID here. This will require a call to
  2704. ** the User Object.
  2705. */
  2706. if (m_pMcsUserObject != NULL)
  2707. m_pMcsUserObject->SendUserIDRequest(m_nParentIDTagNumber);
  2708. m_fConfIsEstablished = TRUE;
  2709. break;
  2710. default:
  2711. TRACE_OUT(("CConf:UserCreateConfirm: Error: Bad User Type"));
  2712. break;
  2713. }
  2714. if (m_fConfIsEstablished)
  2715. {
  2716. /*
  2717. ** We now instantiate the conference roster manager to be used
  2718. ** with this conference.
  2719. */
  2720. if ((m_eNodeType == TOP_PROVIDER_NODE) ||
  2721. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE))
  2722. {
  2723. is_top_provider = TRUE;
  2724. }
  2725. else
  2726. is_top_provider = FALSE;
  2727. DBG_SAVE_FILE_LINE
  2728. m_pConfRosterMgr = new CConfRosterMgr(
  2729. m_pMcsUserObject,
  2730. this,
  2731. is_top_provider,
  2732. &err);
  2733. if (m_pConfRosterMgr == NULL)
  2734. err = GCC_ALLOCATION_FAILURE;
  2735. /*
  2736. ** We create the application registry object here because we now
  2737. ** know the node type.
  2738. */
  2739. if (err == GCC_NO_ERROR)
  2740. {
  2741. if ((m_eNodeType == TOP_PROVIDER_NODE) ||
  2742. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE))
  2743. {
  2744. DBG_SAVE_FILE_LINE
  2745. m_pAppRegistry = new CRegistry(
  2746. m_pMcsUserObject,
  2747. TRUE,
  2748. m_nConfID,
  2749. &m_AppRosterMgrList,
  2750. &err);
  2751. }
  2752. else
  2753. {
  2754. DBG_SAVE_FILE_LINE
  2755. m_pAppRegistry = new CRegistry(
  2756. m_pMcsUserObject,
  2757. FALSE,
  2758. m_nConfID,
  2759. &m_AppRosterMgrList,
  2760. &err);
  2761. }
  2762. }
  2763. if ((m_pAppRegistry != NULL) &&
  2764. (err == GCC_NO_ERROR))
  2765. {
  2766. /*
  2767. ** Inform the node controller that it is time to do an announce
  2768. ** presence for this conference.
  2769. */
  2770. g_pControlSap->ConfPermissionToAnnounce(m_nConfID, node_id);
  2771. /*
  2772. ** Make the owner callback to inform that the owner object that
  2773. ** the conference object was successfully created. This also
  2774. ** kicks off the permission to enroll process.
  2775. */
  2776. g_pGCCController->ProcessConfEstablished(m_nConfID);
  2777. /*
  2778. ** For all nodes except the top provider node we allocate a
  2779. ** startup alarm that is used to hold back all roster flushes
  2780. ** for a certain length of time giving all the local APEs
  2781. ** time to enroll. An allocation failure here is not FATAL
  2782. ** since everything will work with or without this alarm.
  2783. ** Without the Alarm there may be a bit more network traffic
  2784. ** during the startup process. Note that there is no need
  2785. ** for a startup alarm if there are no application SAPs.
  2786. */
  2787. if ((m_eNodeType != TOP_PROVIDER_NODE) &&
  2788. (m_eNodeType != TOP_PROVIDER_AND_CONVENER_NODE))
  2789. {
  2790. TRACE_OUT(("CConf:ProcessUserCreateConfirm: Creating Startup Alarm"));
  2791. // m_pConfStartupAlarm = new Alarm(STARTUP_TIMER_DURATION);
  2792. }
  2793. }
  2794. else
  2795. {
  2796. TRACE_OUT(("CConf: UserCreateConfirm: Error initializing"));
  2797. InitiateTermination(GCC_REASON_ERROR_LOW_RESOURCES, 0);
  2798. }
  2799. }
  2800. }
  2801. else
  2802. {
  2803. TRACE_OUT(("CConf: UserCreateConfirm: Create of User Att. Failed"));
  2804. /*
  2805. ** Try to properly cleanup here. Since the user creation failed
  2806. ** the conference is no longer valid and needs to be cleaned up.
  2807. */
  2808. switch (m_eNodeType)
  2809. {
  2810. case TOP_PROVIDER_NODE:
  2811. g_pMCSIntf->ConnectProviderResponse (
  2812. m_hConvenerConnection,
  2813. &m_nConfID,
  2814. m_pDomainParameters,
  2815. RESULT_UNSPECIFIED_FAILURE,
  2816. NULL, 0);
  2817. break;
  2818. case CONVENER_NODE:
  2819. case TOP_PROVIDER_AND_CONVENER_NODE:
  2820. GetConferenceNameAndModifier( &conference_name,
  2821. &conference_modifier);
  2822. g_pControlSap->ConfCreateConfirm(
  2823. &conference_name,
  2824. conference_modifier,
  2825. m_nConfID,
  2826. m_pDomainParameters,
  2827. NULL,
  2828. GCC_RESULT_RESOURCES_UNAVAILABLE,
  2829. m_hParentConnection);
  2830. break;
  2831. case JOINED_NODE:
  2832. case JOINED_CONVENER_NODE:
  2833. GetConferenceNameAndModifier( &conference_name,
  2834. &conference_modifier);
  2835. if (m_pszRemoteModifier != NULL)
  2836. {
  2837. remote_modifier = (GCCNumericString) m_pszRemoteModifier;
  2838. }
  2839. g_pControlSap->ConfJoinConfirm(
  2840. &conference_name,
  2841. remote_modifier,
  2842. conference_modifier,
  2843. m_nConfID,
  2844. NULL,
  2845. m_pDomainParameters,
  2846. m_fClearPassword,
  2847. m_fConfLocked,
  2848. m_fConfListed,
  2849. m_fConfConductible,
  2850. m_eTerminationMethod,
  2851. m_pConductorPrivilegeList,
  2852. m_pConductModePrivilegeList,
  2853. m_pNonConductModePrivilegeList,
  2854. m_pwszConfDescription,
  2855. m_pUserDataList,
  2856. GCC_RESULT_RESOURCES_UNAVAILABLE,
  2857. m_hParentConnection,
  2858. NULL,
  2859. 0);
  2860. break;
  2861. case INVITED_NODE:
  2862. default:
  2863. break;
  2864. }
  2865. /*
  2866. ** A Fatal Resource error has occured. At this point
  2867. ** the conference is invalid and should be terminated.
  2868. */
  2869. InitiateTermination(GCC_REASON_MCS_RESOURCE_FAILURE, 0);
  2870. }
  2871. DebugExitVOID(CConf::ProcessUserCreateConfirm);
  2872. }
  2873. // Calls received from the MCS interface
  2874. /*
  2875. * CConf::ProcessConnectProviderConfirm ()
  2876. *
  2877. * Private Function Description
  2878. * This routine processes connect provider confirms received
  2879. * directly from MCS.
  2880. *
  2881. * Formal Parameters:
  2882. * connect_provider_confirm - This structure contains the MCS related
  2883. * data such as sender id and connection
  2884. * Handle as well as the PDU data.
  2885. *
  2886. * Return Value
  2887. * None.
  2888. *
  2889. * Side Effects
  2890. * None.
  2891. *
  2892. * Caveats
  2893. * None.
  2894. */
  2895. void CConf::
  2896. ProcessConnectProviderConfirm ( PConnectProviderConfirm connect_provider_confirm )
  2897. {
  2898. PPacket packet;
  2899. PConnectGCCPDU connect_pdu;
  2900. PacketError packet_error;
  2901. GCCResult result = GCC_RESULT_SUCCESSFUL;
  2902. GCCConferenceName conference_name;
  2903. GCCNumericString conference_modifier;
  2904. GCCNumericString remote_modifier = NULL;
  2905. INVITE_REQ_INFO *invite_request_info;
  2906. DebugEntry(CConf::ProcessConnectProviderConfirm);
  2907. if (connect_provider_confirm->user_data_length != 0)
  2908. {
  2909. /*
  2910. ** If the result is success create the packet to be decoded from
  2911. ** the PDU passed back in the MCS user data field. If creation
  2912. ** failes this again is a FATAL error and the conference must be
  2913. ** terminated.
  2914. */
  2915. DBG_SAVE_FILE_LINE
  2916. packet = new Packet((PPacketCoder) g_GCCCoder,
  2917. PACKED_ENCODING_RULES,
  2918. connect_provider_confirm->user_data,
  2919. connect_provider_confirm->user_data_length,
  2920. CONNECT_GCC_PDU,
  2921. TRUE,
  2922. &packet_error);
  2923. if ((packet != NULL) && (packet_error == PACKET_NO_ERROR))
  2924. {
  2925. connect_pdu = (PConnectGCCPDU)packet->GetDecodedData();
  2926. /*
  2927. ** If all the above succeeds then decode the packet based on
  2928. ** which node type this is.
  2929. */
  2930. switch (connect_pdu->choice)
  2931. {
  2932. case CONFERENCE_CREATE_RESPONSE_CHOSEN:
  2933. ProcessConferenceCreateResponsePDU (
  2934. &connect_pdu->u.conference_create_response,
  2935. connect_provider_confirm);
  2936. break;
  2937. case CONNECT_JOIN_RESPONSE_CHOSEN:
  2938. ProcessConferenceJoinResponsePDU (
  2939. &connect_pdu->u.connect_join_response,
  2940. connect_provider_confirm);
  2941. break;
  2942. case CONFERENCE_INVITE_RESPONSE_CHOSEN:
  2943. ProcessConferenceInviteResponsePDU (
  2944. &connect_pdu->u.conference_invite_response,
  2945. connect_provider_confirm );
  2946. break;
  2947. default:
  2948. ERROR_OUT(("CConf:ProcessConnectProviderConfirm: "
  2949. "Error: Received Invalid Connect Provider Confirm"));
  2950. break;
  2951. }
  2952. // Free the decoded packet
  2953. packet->Unlock ();
  2954. }
  2955. else
  2956. {
  2957. ERROR_OUT(("CConf: ProcessConnectProviderConfirm:"
  2958. "Incompatible protocol occured"));
  2959. result = GCC_RESULT_INCOMPATIBLE_PROTOCOL;
  2960. }
  2961. }
  2962. else
  2963. {
  2964. ERROR_OUT(("CConf::ProcessConnectProviderConfirm: result=%d", (UINT) connect_provider_confirm->result));
  2965. /*
  2966. ** This section of the code assumes that there is no connect PDU in
  2967. ** the returned packet. First determine what the result is. We
  2968. ** assume that if the MCS connection was rejected due to
  2969. ** parameters being unacceptable and no GCC pdu was returned that there
  2970. ** was a protocol incompatibility.
  2971. */
  2972. if (connect_provider_confirm->result == RESULT_PARAMETERS_UNACCEPTABLE)
  2973. result = GCC_RESULT_INCOMPATIBLE_PROTOCOL;
  2974. else
  2975. {
  2976. result = ::TranslateMCSResultToGCCResult(connect_provider_confirm->result);
  2977. }
  2978. }
  2979. // Handle any errors that might have occured.
  2980. if (result != GCC_RESULT_SUCCESSFUL)
  2981. {
  2982. INVITE_REQ_INFO *lpInvReqInfo;
  2983. // First check to see if there are any outstanding invite request
  2984. m_InviteRequestList.Reset();
  2985. invite_request_info = NULL;
  2986. while (NULL != (lpInvReqInfo = m_InviteRequestList.Iterate()))
  2987. {
  2988. if (connect_provider_confirm->connection_handle == lpInvReqInfo->connection_handle)
  2989. {
  2990. TRACE_OUT(("CConf: ProcessConnectProviderConfirm: Found Invite Request Match"));
  2991. invite_request_info = lpInvReqInfo;
  2992. break;
  2993. }
  2994. }
  2995. if (invite_request_info != NULL)
  2996. {
  2997. // This must be the confirm of an invite
  2998. ProcessConferenceInviteResponsePDU (NULL, connect_provider_confirm);
  2999. }
  3000. else
  3001. {
  3002. switch (m_eNodeType)
  3003. {
  3004. case CONVENER_NODE:
  3005. case TOP_PROVIDER_AND_CONVENER_NODE:
  3006. GetConferenceNameAndModifier ( &conference_name,
  3007. &conference_modifier);
  3008. g_pControlSap->ConfCreateConfirm(
  3009. &conference_name,
  3010. conference_modifier,
  3011. m_nConfID,
  3012. m_pDomainParameters,
  3013. NULL,
  3014. result,
  3015. connect_provider_confirm->connection_handle);
  3016. InitiateTermination ( GCC_REASON_ERROR_TERMINATION,
  3017. 0);
  3018. break;
  3019. case JOINED_NODE:
  3020. case JOINED_CONVENER_NODE:
  3021. TRACE_OUT(("CConf::ProcessConnectProviderConfirm:"
  3022. "Joined Node connect provider failed"));
  3023. GetConferenceNameAndModifier ( &conference_name,
  3024. &conference_modifier);
  3025. if (m_pszRemoteModifier != NULL)
  3026. {
  3027. remote_modifier = (GCCNumericString) m_pszRemoteModifier;
  3028. }
  3029. TRACE_OUT(("CConf::ProcessConnectProviderConfirm: Before conference Join Confirm"));
  3030. g_pControlSap->ConfJoinConfirm(
  3031. &conference_name,
  3032. remote_modifier,
  3033. conference_modifier,
  3034. m_nConfID,
  3035. NULL,
  3036. m_pDomainParameters,
  3037. m_fClearPassword,
  3038. m_fConfLocked,
  3039. m_fConfListed,
  3040. m_fConfConductible,
  3041. m_eTerminationMethod,
  3042. m_pConductorPrivilegeList,
  3043. m_pConductModePrivilegeList,
  3044. m_pNonConductModePrivilegeList,
  3045. NULL,
  3046. NULL,
  3047. result,
  3048. connect_provider_confirm->connection_handle,
  3049. NULL,
  3050. 0);
  3051. TRACE_OUT(("CConf::ProcessConnectProviderConfirm: After conference Join Confirm"));
  3052. InitiateTermination(GCC_REASON_ERROR_TERMINATION, 0);
  3053. break;
  3054. default:
  3055. TRACE_OUT(("CConf: ProcessConnectProviderConfirm:"
  3056. "Assertion Failure: Bad confirm received"));
  3057. break;
  3058. }
  3059. }
  3060. }
  3061. DebugExitVOID(CConf::ProcessConnectProviderConfirm);
  3062. }
  3063. /*
  3064. * void ProcessConferenceCreateResponsePDU ()
  3065. *
  3066. * Private Function Description
  3067. * This routine processes a Conference Create Response PDU that is
  3068. * delivered as part of a Connect Provider Confirm.
  3069. *
  3070. * Formal Parameters:
  3071. * create_response - This is the Conference Create response
  3072. * PDU.
  3073. * connect_provider_confirm - This structure contains the MCS related
  3074. * data such as sender id and connection
  3075. * Handle as well as the PDU data.
  3076. *
  3077. * Return Value
  3078. * None.
  3079. *
  3080. * Side Effects
  3081. * None.
  3082. *
  3083. * Caveats
  3084. * None.
  3085. */
  3086. void CConf::
  3087. ProcessConferenceCreateResponsePDU
  3088. (
  3089. PConferenceCreateResponse create_response,
  3090. PConnectProviderConfirm connect_provider_confirm
  3091. )
  3092. {
  3093. GCCError err = GCC_NO_ERROR;
  3094. GCCResult result;
  3095. UserID top_gcc_node_id;
  3096. UserID parent_user_id;
  3097. GCCConferenceName conference_name;
  3098. GCCNumericString conference_modifier;
  3099. DebugEntry(CConf::ProcessConnectProviderConfirm);
  3100. // Translate the result back to GCC Result
  3101. result = ::TranslateCreateResultToGCCResult(create_response->result);
  3102. if ((result == GCC_RESULT_SUCCESSFUL) &&
  3103. (connect_provider_confirm->result == RESULT_SUCCESSFUL))
  3104. {
  3105. /*
  3106. ** Save the domain parameters. The domain parameters returned in
  3107. ** the connect provider confirm should always be up to date.
  3108. */
  3109. if (m_pDomainParameters == NULL)
  3110. {
  3111. DBG_SAVE_FILE_LINE
  3112. m_pDomainParameters = new DomainParameters;
  3113. }
  3114. if (m_pDomainParameters != NULL)
  3115. *m_pDomainParameters = connect_provider_confirm->domain_parameters;
  3116. else
  3117. err = GCC_ALLOCATION_FAILURE;
  3118. // Get any user data that might exists
  3119. if ((create_response->bit_mask & CCRS_USER_DATA_PRESENT) &&
  3120. (err == GCC_NO_ERROR))
  3121. {
  3122. DBG_SAVE_FILE_LINE
  3123. m_pUserDataList = new CUserDataListContainer(create_response->ccrs_user_data, &err);
  3124. if (m_pUserDataList == NULL)
  3125. err = GCC_ALLOCATION_FAILURE;
  3126. }
  3127. if (err == GCC_NO_ERROR)
  3128. {
  3129. m_nParentIDTagNumber = create_response->tag;
  3130. top_gcc_node_id = create_response->node_id;
  3131. parent_user_id = top_gcc_node_id;
  3132. // Create the user attachment object.
  3133. DBG_SAVE_FILE_LINE
  3134. m_pMcsUserObject = new MCSUser(this, top_gcc_node_id, parent_user_id, &err);
  3135. if (m_pMcsUserObject == NULL || GCC_NO_ERROR != err)
  3136. {
  3137. if (NULL != m_pMcsUserObject)
  3138. {
  3139. m_pMcsUserObject->Release();
  3140. m_pMcsUserObject = NULL;
  3141. }
  3142. else
  3143. {
  3144. err = GCC_ALLOCATION_FAILURE;
  3145. }
  3146. }
  3147. }
  3148. }
  3149. else
  3150. {
  3151. TRACE_OUT(("CConf: ProcessConnectProviderConfirm: conference create result was Failure"));
  3152. // Go ahead and translate the mcs error to a gcc error if one occured.
  3153. if ((result == GCC_RESULT_SUCCESSFUL) &&
  3154. (connect_provider_confirm->result != RESULT_SUCCESSFUL))
  3155. {
  3156. result = ::TranslateMCSResultToGCCResult(connect_provider_confirm->result);
  3157. }
  3158. // Get the conference name to pass back in the create confirm
  3159. GetConferenceNameAndModifier ( &conference_name,
  3160. &conference_modifier);
  3161. g_pControlSap->ConfCreateConfirm(
  3162. &conference_name,
  3163. conference_modifier,
  3164. m_nConfID,
  3165. m_pDomainParameters,
  3166. NULL,
  3167. result,
  3168. connect_provider_confirm->connection_handle);
  3169. // Terminate the conference
  3170. InitiateTermination ( GCC_REASON_NORMAL_TERMINATION,
  3171. 0);
  3172. }
  3173. if (err != GCC_NO_ERROR)
  3174. {
  3175. InitiateTermination ( GCC_REASON_ERROR_LOW_RESOURCES,
  3176. 0);
  3177. }
  3178. DebugExitVOID(CConf::ProcessConnectProviderConfirm);
  3179. }
  3180. /*
  3181. * void ProcessConferenceJoinResponsePDU ()
  3182. *
  3183. * Private Function Description
  3184. * This routine processes a Conference Join Response PDU that is
  3185. * delivered as part of a Connect Provider Confirm.
  3186. *
  3187. * Formal Parameters:
  3188. * join_response - This is the Conference Join response
  3189. * PDU.
  3190. * connect_provider_confirm - This structure contains the MCS related
  3191. * data such as sender id and connection
  3192. * Handle as well as the PDU data.
  3193. *
  3194. * Return Value
  3195. * None.
  3196. *
  3197. * Side Effects
  3198. * None.
  3199. *
  3200. * Caveats
  3201. * None.
  3202. */
  3203. void CConf::
  3204. ProcessConferenceJoinResponsePDU
  3205. (
  3206. PConferenceJoinResponse join_response,
  3207. PConnectProviderConfirm connect_provider_confirm
  3208. )
  3209. {
  3210. GCCError err = GCC_NO_ERROR;
  3211. GCCResult result;
  3212. UserID top_gcc_node_id;
  3213. UserID parent_user_id;
  3214. CPassword *password_challenge = NULL;
  3215. CUserDataListContainer *user_data_list = NULL;
  3216. GCCConferenceName conference_name;
  3217. GCCNumericString local_modifier;
  3218. GCCNumericString remote_modifier = NULL;
  3219. DebugEntry(CConf::ProcessConferenceJoinResponsePDU);
  3220. // Translate the result back to GCC Result
  3221. result = ::TranslateJoinResultToGCCResult (join_response->result);
  3222. if ((result == GCC_RESULT_SUCCESSFUL) &&
  3223. (connect_provider_confirm->result == RESULT_SUCCESSFUL))
  3224. {
  3225. /*
  3226. ** Save the domain parameters. The domain parameters returned in
  3227. ** the connect provider confirm should always be up to date.
  3228. */
  3229. if (m_pDomainParameters == NULL)
  3230. {
  3231. DBG_SAVE_FILE_LINE
  3232. m_pDomainParameters = new DomainParameters;
  3233. }
  3234. if (m_pDomainParameters != NULL)
  3235. *m_pDomainParameters = connect_provider_confirm->domain_parameters;
  3236. else
  3237. err = GCC_ALLOCATION_FAILURE;
  3238. // Get the conference name alias if one exists
  3239. if ((join_response->bit_mask & CONFERENCE_NAME_ALIAS_PRESENT) &&
  3240. (err == GCC_NO_ERROR))
  3241. {
  3242. if (join_response->conference_name_alias.choice ==
  3243. NAME_SELECTOR_NUMERIC_CHOSEN)
  3244. {
  3245. delete m_pszConfNumericName;
  3246. if (NULL == (m_pszConfNumericName = ::My_strdupA(
  3247. join_response->conference_name_alias.u.name_selector_numeric)))
  3248. {
  3249. err = GCC_ALLOCATION_FAILURE;
  3250. }
  3251. }
  3252. else
  3253. {
  3254. delete m_pwszConfTextName;
  3255. if (NULL == (m_pwszConfTextName = ::My_strdupW2(
  3256. join_response->conference_name_alias.u.name_selector_text.length,
  3257. join_response->conference_name_alias.u.name_selector_text.value)))
  3258. {
  3259. err = GCC_ALLOCATION_FAILURE;
  3260. }
  3261. }
  3262. }
  3263. // Get the conductor privilege list if one exists
  3264. if ((join_response->bit_mask & CJRS_CONDUCTOR_PRIVS_PRESENT) &&
  3265. (err == GCC_NO_ERROR))
  3266. {
  3267. delete m_pConductorPrivilegeList;
  3268. DBG_SAVE_FILE_LINE
  3269. m_pConductorPrivilegeList = new PrivilegeListData(join_response->cjrs_conductor_privs);
  3270. if (m_pConductorPrivilegeList == NULL)
  3271. err = GCC_ALLOCATION_FAILURE;
  3272. }
  3273. // Get the conducted mode privilege list if one exists
  3274. if ((join_response->bit_mask & CJRS_CONDUCTED_PRIVS_PRESENT) &&
  3275. (err == GCC_NO_ERROR))
  3276. {
  3277. delete m_pConductModePrivilegeList;
  3278. DBG_SAVE_FILE_LINE
  3279. m_pConductModePrivilegeList = new PrivilegeListData(join_response->cjrs_conducted_privs);
  3280. if (m_pConductModePrivilegeList == NULL)
  3281. err = GCC_ALLOCATION_FAILURE;
  3282. }
  3283. // Get the non-conducted mode privilege list if one exists
  3284. if ((join_response->bit_mask & CJRS_NON_CONDUCTED_PRIVS_PRESENT) &&
  3285. (err == GCC_NO_ERROR))
  3286. {
  3287. delete m_pNonConductModePrivilegeList;
  3288. DBG_SAVE_FILE_LINE
  3289. m_pNonConductModePrivilegeList = new PrivilegeListData(join_response->cjrs_non_conducted_privs);
  3290. if (m_pNonConductModePrivilegeList == NULL)
  3291. err = GCC_ALLOCATION_FAILURE;
  3292. }
  3293. // Get the conference description if it exists
  3294. if ((join_response->bit_mask & CJRS_DESCRIPTION_PRESENT) &&
  3295. (err == GCC_NO_ERROR))
  3296. {
  3297. delete m_pwszConfDescription;
  3298. if (NULL == (m_pwszConfDescription = ::My_strdupW2(
  3299. join_response->cjrs_description.length,
  3300. join_response->cjrs_description.value)))
  3301. {
  3302. err = GCC_ALLOCATION_FAILURE;
  3303. }
  3304. }
  3305. // Get the user data if it exists
  3306. if ((join_response->bit_mask & CJRS_USER_DATA_PRESENT) &&
  3307. (err == GCC_NO_ERROR))
  3308. {
  3309. if (NULL != m_pUserDataList)
  3310. {
  3311. m_pUserDataList->Release();
  3312. }
  3313. DBG_SAVE_FILE_LINE
  3314. m_pUserDataList = new CUserDataListContainer(join_response->cjrs_user_data, &err);
  3315. // in case of err but valid m_pUserDataList, the destructor will clean it up.
  3316. if (m_pUserDataList == NULL)
  3317. {
  3318. err = GCC_ALLOCATION_FAILURE;
  3319. }
  3320. }
  3321. if (err == GCC_NO_ERROR)
  3322. {
  3323. parent_user_id = (join_response->bit_mask & CJRS_NODE_ID_PRESENT) ?
  3324. (UserID) join_response->cjrs_node_id :
  3325. (UserID) join_response->top_node_id;
  3326. m_nParentIDTagNumber = join_response->tag;
  3327. top_gcc_node_id = (UserID)join_response->top_node_id;
  3328. m_fClearPassword = join_response->clear_password_required;
  3329. m_fConfLocked = join_response->conference_is_locked;
  3330. m_fConfListed = join_response->conference_is_listed;
  3331. m_eTerminationMethod = (GCCTerminationMethod)join_response->termination_method;
  3332. m_fConfConductible = join_response->conference_is_conductible;
  3333. // Create the user attachment object.
  3334. ASSERT(NULL == m_pMcsUserObject);
  3335. DBG_SAVE_FILE_LINE
  3336. m_pMcsUserObject = new MCSUser(this, top_gcc_node_id, parent_user_id, &err);
  3337. // in case of err but valid m_pMcsUserObject, the destructor will clean it up.
  3338. if (m_pMcsUserObject == NULL)
  3339. {
  3340. err = GCC_ALLOCATION_FAILURE;
  3341. }
  3342. }
  3343. }
  3344. else
  3345. {
  3346. if ((join_response->bit_mask & CJRS_PASSWORD_PRESENT) &&
  3347. (err == GCC_NO_ERROR))
  3348. {
  3349. DBG_SAVE_FILE_LINE
  3350. password_challenge = new CPassword(&join_response->cjrs_password, &err);
  3351. if (password_challenge == NULL)
  3352. {
  3353. err = GCC_ALLOCATION_FAILURE;
  3354. }
  3355. }
  3356. // Get the user data if it exists
  3357. if ((join_response->bit_mask & CJRS_USER_DATA_PRESENT) &&
  3358. (err == GCC_NO_ERROR))
  3359. {
  3360. DBG_SAVE_FILE_LINE
  3361. user_data_list = new CUserDataListContainer(join_response->cjrs_user_data, &err);
  3362. if (user_data_list == NULL)
  3363. {
  3364. err = GCC_ALLOCATION_FAILURE;
  3365. }
  3366. }
  3367. if (err == GCC_NO_ERROR)
  3368. {
  3369. /*
  3370. ** Go ahead and translate the mcs error to a gcc error if
  3371. ** one occured.
  3372. */
  3373. if ((result == GCC_RESULT_SUCCESSFUL) &&
  3374. (connect_provider_confirm->result != RESULT_SUCCESSFUL))
  3375. {
  3376. result = ::TranslateMCSResultToGCCResult(connect_provider_confirm->result);
  3377. }
  3378. // Fill in the conference name data pointers.
  3379. GetConferenceNameAndModifier(&conference_name, &local_modifier);
  3380. if (m_pszRemoteModifier != NULL)
  3381. {
  3382. remote_modifier = (GCCNumericString) m_pszRemoteModifier;
  3383. }
  3384. //
  3385. // LONCHANC: To get rid of the conference object
  3386. // in GCC Controller's active conference list.
  3387. // The conference object will then be moved to
  3388. // the deletion list.
  3389. //
  3390. InitiateTermination ( GCC_REASON_NORMAL_TERMINATION, 0);
  3391. g_pControlSap->ConfJoinConfirm(
  3392. &conference_name,
  3393. remote_modifier,
  3394. local_modifier,
  3395. m_nConfID,
  3396. password_challenge,
  3397. m_pDomainParameters,
  3398. m_fClearPassword,
  3399. m_fConfLocked,
  3400. m_fConfListed,
  3401. m_fConfConductible,
  3402. m_eTerminationMethod,
  3403. m_pConductorPrivilegeList,
  3404. m_pConductModePrivilegeList,
  3405. m_pNonConductModePrivilegeList,
  3406. NULL,
  3407. user_data_list,
  3408. result,
  3409. connect_provider_confirm->connection_handle,
  3410. connect_provider_confirm->pb_cred,
  3411. connect_provider_confirm->cb_cred);
  3412. }
  3413. if (password_challenge != NULL)
  3414. {
  3415. password_challenge->Release();
  3416. }
  3417. if (user_data_list != NULL)
  3418. {
  3419. user_data_list->Release();
  3420. }
  3421. }
  3422. if (err != GCC_NO_ERROR)
  3423. {
  3424. InitiateTermination (GCC_REASON_ERROR_LOW_RESOURCES, 0);
  3425. }
  3426. DebugExitVOID(CConf::ProcessConferenceJoinResponsePDU);
  3427. }
  3428. /*
  3429. * void ProcessConferenceInviteResponsePDU ()
  3430. *
  3431. * Private Function Description
  3432. * This routine processes a Conference Invite Response PDU that is
  3433. * delivered as part of a Connect Provider Confirm.
  3434. *
  3435. * Formal Parameters:
  3436. * invite_response - This is the Conference Invite response
  3437. * PDU.
  3438. * connect_provider_confirm - This structure contains the MCS related
  3439. * data such as sender id and connection
  3440. * Handle as well as the PDU data.
  3441. *
  3442. * Return Value
  3443. * None.
  3444. *
  3445. * Side Effects
  3446. * None.
  3447. *
  3448. * Caveats
  3449. * None.
  3450. */
  3451. void CConf::
  3452. ProcessConferenceInviteResponsePDU
  3453. (
  3454. PConferenceInviteResponse invite_response,
  3455. PConnectProviderConfirm connect_provider_confirm
  3456. )
  3457. {
  3458. GCCError err;
  3459. GCCResult result;
  3460. CUserDataListContainer *user_data_list = NULL;
  3461. INVITE_REQ_INFO *invite_request_info = NULL;
  3462. INVITE_REQ_INFO *lpInvReqInfo;
  3463. DebugEntry(CConf::ProcessConferenceInviteResponsePDU);
  3464. // First obtain the info request info structure.
  3465. m_InviteRequestList.Reset();
  3466. while (NULL != (lpInvReqInfo = m_InviteRequestList.Iterate()))
  3467. {
  3468. if (connect_provider_confirm->connection_handle == lpInvReqInfo->connection_handle)
  3469. {
  3470. invite_request_info = lpInvReqInfo;
  3471. break;
  3472. }
  3473. }
  3474. if (invite_request_info == NULL)
  3475. return;
  3476. if (invite_response != NULL)
  3477. {
  3478. // Get the user data list if one exists
  3479. if (invite_response->bit_mask & CIRS_USER_DATA_PRESENT)
  3480. {
  3481. DBG_SAVE_FILE_LINE
  3482. user_data_list = new CUserDataListContainer(invite_response->cirs_user_data, &err);
  3483. }
  3484. // Translate the result to GCCResult
  3485. result = ::TranslateInviteResultToGCCResult(invite_response->result);
  3486. }
  3487. else
  3488. {
  3489. result = (connect_provider_confirm->result == RESULT_USER_REJECTED) ?
  3490. GCC_RESULT_INCOMPATIBLE_PROTOCOL :
  3491. ::TranslateMCSResultToGCCResult(connect_provider_confirm->result);
  3492. }
  3493. if ((result == GCC_RESULT_SUCCESSFUL) &&
  3494. (connect_provider_confirm->result == RESULT_SUCCESSFUL))
  3495. {
  3496. TRACE_OUT(("CConf::ProcessConferenceInviteResponsePDU:"
  3497. "Received Connect Provider confirm on Invite"));
  3498. /*
  3499. ** Save the domain parameters. The domain parameters returned in
  3500. ** the connect provider confirm should always be up to date.
  3501. */
  3502. if (m_pDomainParameters == NULL)
  3503. {
  3504. DBG_SAVE_FILE_LINE
  3505. m_pDomainParameters = new DomainParameters;
  3506. }
  3507. if (m_pDomainParameters != NULL)
  3508. *m_pDomainParameters = connect_provider_confirm->domain_parameters;
  3509. else
  3510. err = GCC_ALLOCATION_FAILURE;
  3511. // Save the user data list for the invite confirm
  3512. invite_request_info->user_data_list = user_data_list;
  3513. // Wait for user ID from invited node before sending invite confirm.
  3514. }
  3515. else
  3516. {
  3517. /*
  3518. ** Go ahead and translate the mcs error to a gcc error if
  3519. ** one occured.
  3520. */
  3521. if ((result == GCC_RESULT_SUCCESSFUL) &&
  3522. (connect_provider_confirm->result != RESULT_SUCCESSFUL))
  3523. {
  3524. result = ::TranslateMCSResultToGCCResult(connect_provider_confirm->result);
  3525. }
  3526. // Cleanup the connection handle list
  3527. ASSERT(0 != connect_provider_confirm->connection_handle);
  3528. m_ConnHandleList.Remove(connect_provider_confirm->connection_handle);
  3529. // In case of error, the node controller will delete this conference.
  3530. // AddRef here to protect itself from going away.
  3531. AddRef();
  3532. g_pControlSap->ConfInviteConfirm(
  3533. m_nConfID,
  3534. user_data_list,
  3535. result,
  3536. connect_provider_confirm->connection_handle);
  3537. // Free up the user data
  3538. if (user_data_list != NULL)
  3539. {
  3540. user_data_list->Release();
  3541. }
  3542. // The reason that we check this is because in some cases, in the call to
  3543. // g_pControlSap->ConfInviteConfirm, someone was calling DeleteOutstandingInviteRequests
  3544. // which was killing the list via a call to m_InviteRequestList.Clear...
  3545. // This happens when the calee refuses to accept the call
  3546. if(m_InviteRequestList.Remove(invite_request_info))
  3547. {
  3548. // Free up the invite request info structure
  3549. delete invite_request_info;
  3550. }
  3551. // To match AddRef above.
  3552. Release();
  3553. }
  3554. DebugExitVOID(CConf::ProcessConferenceInviteResponsePDU);
  3555. }
  3556. /*
  3557. * CConf::ProcessEjectUserIndication ()
  3558. *
  3559. * Private Function Description
  3560. * This routine processes an Eject User Indication.
  3561. *
  3562. * Formal Parameters:
  3563. * reason - Reason that this node is being ejected.
  3564. *
  3565. * Return Value
  3566. * None.
  3567. *
  3568. * Side Effects
  3569. * None.
  3570. *
  3571. * Caveats
  3572. * None.
  3573. */
  3574. void CConf::
  3575. ProcessEjectUserIndication ( GCCReason reason )
  3576. {
  3577. DebugEntry(CConf::ProcessEjectUserIndication);
  3578. if (m_fConfIsEstablished)
  3579. {
  3580. /*
  3581. ** First inform the control SAP that this node has been ejected from this
  3582. ** particular conference.
  3583. */
  3584. g_pControlSap->ConfEjectUserIndication(
  3585. m_nConfID,
  3586. reason,
  3587. m_pMcsUserObject->GetMyNodeID());
  3588. /*
  3589. ** Next we set conference established to FALSE since the conference is
  3590. ** no longer established (this also prevents a terminate indication from
  3591. ** being sent).
  3592. */
  3593. m_fConfIsEstablished = FALSE;
  3594. InitiateTermination(reason, m_pMcsUserObject->GetMyNodeID());
  3595. }
  3596. DebugExitVOID(CConf::ProcessEjectUserIndication);
  3597. }
  3598. /*
  3599. * CConf::ProcessEjectUserRequest ()
  3600. *
  3601. * Private Function Description
  3602. * This routine processes an eject user request PDU. This routine should
  3603. * only be called from the Top Provider.
  3604. *
  3605. * Formal Parameters:
  3606. * eject_node_request - This is the PDU data associated with the
  3607. * eject user request.
  3608. *
  3609. * Return Value
  3610. * None.
  3611. *
  3612. * Side Effects
  3613. * None.
  3614. *
  3615. * Caveats
  3616. * None.
  3617. */
  3618. void CConf::
  3619. ProcessEjectUserRequest ( PUserEjectNodeRequestInfo eject_node_request )
  3620. {
  3621. GCCResult result;
  3622. DebugEntry(CConf::ProcessEjectUserRequest);
  3623. // Check to make sure that the requesting node has the proper privileges
  3624. if (DoesRequesterHavePrivilege( eject_node_request->requester_id,
  3625. EJECT_USER_PRIVILEGE))
  3626. {
  3627. /*
  3628. ** The user attachment object decides where the eject should
  3629. ** be sent (either to the Top Provider or conference wide as
  3630. ** an indication.
  3631. */
  3632. m_pMcsUserObject->EjectNodeFromConference (
  3633. eject_node_request->node_to_eject,
  3634. eject_node_request->reason);
  3635. result = GCC_RESULT_SUCCESSFUL;
  3636. }
  3637. else
  3638. result = GCC_RESULT_INVALID_REQUESTER;
  3639. m_pMcsUserObject->SendEjectNodeResponse (eject_node_request->requester_id,
  3640. eject_node_request->node_to_eject,
  3641. result);
  3642. DebugExitVOID(CConf::ProcessEjectUserRequest);
  3643. }
  3644. /*
  3645. * CConf::ProcessEjectUserResponse ()
  3646. *
  3647. * Private Function Description
  3648. * This routine processes an eject user response PDU. This routine is
  3649. * called in response to an eject user request.
  3650. *
  3651. * Formal Parameters:
  3652. * eject_node_response - This is the PDU data associated with the
  3653. * eject user response.
  3654. *
  3655. * Return Value
  3656. * None.
  3657. *
  3658. * Side Effects
  3659. * None.
  3660. *
  3661. * Caveats
  3662. * None.
  3663. */
  3664. void CConf::
  3665. ProcessEjectUserResponse ( PUserEjectNodeResponseInfo eject_node_response )
  3666. {
  3667. DebugEntry(CConf::ProcessEjectUserResponse);
  3668. if (m_EjectedNodeConfirmList.Remove(eject_node_response->node_to_eject))
  3669. {
  3670. #ifdef JASPER
  3671. g_pControlSap->ConfEjectUserConfirm(
  3672. m_nConfID,
  3673. eject_node_response->node_to_eject,
  3674. eject_node_response->result);
  3675. #endif // JASPER
  3676. }
  3677. else
  3678. {
  3679. ERROR_OUT(("CConf::ProcessEjectUserResponse: Assertion: Bad ejected node response received"));
  3680. }
  3681. DebugExitVOID(CConf::ProcessEjectUserResponse);
  3682. }
  3683. /*
  3684. * CConf::ProcessConferenceLockRequest()
  3685. *
  3686. * Private Function Description
  3687. * This routine processes a conference lock request PDU.
  3688. *
  3689. * Formal Parameters:
  3690. * requester_id - Node ID of node making the lock request.
  3691. *
  3692. * Return Value
  3693. * None.
  3694. *
  3695. * Side Effects
  3696. * None.
  3697. *
  3698. * Caveats
  3699. * None.
  3700. */
  3701. void CConf::
  3702. ProcessConferenceLockRequest ( UserID requester_id )
  3703. {
  3704. DebugEntry(CConf::ProcessConferenceLockRequest);
  3705. if (DoesRequesterHavePrivilege (requester_id,
  3706. LOCK_UNLOCK_PRIVILEGE))
  3707. {
  3708. g_pControlSap->ConfLockIndication(m_nConfID, requester_id);
  3709. }
  3710. else
  3711. {
  3712. if (requester_id == m_pMcsUserObject->GetTopNodeID())
  3713. {
  3714. #ifdef JASPER
  3715. g_pControlSap->ConfLockConfirm(GCC_RESULT_INVALID_REQUESTER, m_nConfID);
  3716. #endif // JASPER
  3717. }
  3718. else
  3719. {
  3720. m_pMcsUserObject->SendConferenceLockResponse(
  3721. requester_id,
  3722. GCC_RESULT_INVALID_REQUESTER);
  3723. }
  3724. }
  3725. DebugExitVOID(CConf::ProcessConferenceLockRequest);
  3726. }
  3727. /*
  3728. * CConf::ProcessConferenceUnlockRequest()
  3729. *
  3730. * Private Function Description
  3731. * This routine processes a conference unlock request PDU.
  3732. *
  3733. * Formal Parameters:
  3734. * requester_id - Node ID of node making the unlock request.
  3735. *
  3736. * Return Value
  3737. * None.
  3738. *
  3739. * Side Effects
  3740. * None.
  3741. *
  3742. * Caveats
  3743. * None.
  3744. */
  3745. void CConf::
  3746. ProcessConferenceUnlockRequest ( UserID requester_id )
  3747. {
  3748. DebugEntry(CConf::ProcessConferenceUnlockRequest);
  3749. if (DoesRequesterHavePrivilege (requester_id,
  3750. LOCK_UNLOCK_PRIVILEGE))
  3751. {
  3752. #ifdef JASPER
  3753. g_pControlSap->ConfUnlockIndication(m_nConfID, requester_id);
  3754. #endif // JASPER
  3755. }
  3756. else
  3757. {
  3758. if (requester_id == m_pMcsUserObject->GetTopNodeID())
  3759. {
  3760. #ifdef JASPER
  3761. g_pControlSap->ConfUnlockConfirm(GCC_RESULT_INVALID_REQUESTER, m_nConfID);
  3762. #endif // JASPER
  3763. }
  3764. else
  3765. {
  3766. m_pMcsUserObject->SendConferenceUnlockResponse(
  3767. requester_id,
  3768. GCC_RESULT_INVALID_REQUESTER);
  3769. }
  3770. }
  3771. DebugExitVOID(CConf::ProcessConferenceUnlockRequest);
  3772. }
  3773. /*
  3774. * CConf::ProcessConferenceLockIndication()
  3775. *
  3776. * Private Function Description
  3777. * This routine processes a conference lock indication PDU.
  3778. *
  3779. * Formal Parameters:
  3780. * source_id - Node ID which sent out the lock indication. Should
  3781. * only be sent by the top provider.
  3782. *
  3783. * Return Value
  3784. * None.
  3785. *
  3786. * Side Effects
  3787. * None.
  3788. *
  3789. * Caveats
  3790. * None.
  3791. */
  3792. void CConf::
  3793. ProcessConferenceLockIndication ( UserID source_id )
  3794. {
  3795. DebugEntry(CConf::ProcessConferenceLockIndication);
  3796. if (source_id == m_pMcsUserObject->GetTopNodeID())
  3797. {
  3798. m_fConfLocked = CONFERENCE_IS_LOCKED;
  3799. #ifdef JASPER
  3800. g_pControlSap->ConfLockReport(m_nConfID, m_fConfLocked);
  3801. #endif // JASPER
  3802. }
  3803. DebugExitVOID(CConf::ProcessConferenceLockIndication);
  3804. }
  3805. /*
  3806. * CConf::ProcessConferenceUnlockIndication()
  3807. *
  3808. * Private Function Description
  3809. * This routine processes a conference unlock indication PDU.
  3810. *
  3811. * Formal Parameters:
  3812. * source_id - Node ID which sent out the unlock indication. Should
  3813. * only be sent by the top provider.
  3814. *
  3815. * Return Value
  3816. * None.
  3817. *
  3818. * Side Effects
  3819. * None.
  3820. *
  3821. * Caveats
  3822. * None.
  3823. */
  3824. void CConf::
  3825. ProcessConferenceUnlockIndication ( UserID source_id )
  3826. {
  3827. DebugEntry(CConf::ProcessConferenceUnlockIndication);
  3828. if (source_id == m_pMcsUserObject->GetTopNodeID())
  3829. {
  3830. m_fConfLocked = CONFERENCE_IS_NOT_LOCKED;
  3831. #ifdef JASPER
  3832. g_pControlSap->ConfLockReport(m_nConfID, m_fConfLocked);
  3833. #endif // JASPER
  3834. }
  3835. DebugExitVOID(CConf::ProcessConferenceUnlockIndication);
  3836. }
  3837. /*
  3838. * void ProcessConferenceTransferRequest ()
  3839. *
  3840. * Public Function Description
  3841. * This routine processes a conference transfer request PDU.
  3842. *
  3843. * Formal Parameters:
  3844. * requesting_node_id - Node ID that made the transfer
  3845. * request.
  3846. * destination_conference_name - The name of the conference to
  3847. * transfer to.
  3848. * destination_conference_modifier - The name of the conference modifier
  3849. * to transfer to.
  3850. * destination_address_list - Network address list of the
  3851. * conference to transfer to.
  3852. * number_of_destination_nodes - The number of nodes in the list of
  3853. * nodes that should perform the
  3854. * transfer.
  3855. * destination_node_list - The list of nodes that should
  3856. * perform the transfer.
  3857. * password - The password needed to join the
  3858. * new conference.
  3859. *
  3860. * Return Value
  3861. * None.
  3862. *
  3863. * Side Effects
  3864. * None.
  3865. *
  3866. * Caveats
  3867. * None.
  3868. */
  3869. void CConf::
  3870. ProcessConferenceTransferRequest
  3871. (
  3872. UserID requesting_node_id,
  3873. PGCCConferenceName destination_conference_name,
  3874. GCCNumericString destination_conference_modifier,
  3875. CNetAddrListContainer *destination_address_list,
  3876. UINT number_of_destination_nodes,
  3877. PUserID destination_node_list,
  3878. CPassword *password
  3879. )
  3880. {
  3881. GCCResult result;
  3882. DebugEntry(CConf::ProcessConferenceTransferRequest);
  3883. if (DoesRequesterHavePrivilege( requesting_node_id,
  3884. TRANSFER_PRIVILEGE))
  3885. {
  3886. result = GCC_RESULT_SUCCESSFUL;
  3887. }
  3888. else
  3889. result = GCC_RESULT_INVALID_REQUESTER;
  3890. m_pMcsUserObject->ConferenceTransferResponse (
  3891. requesting_node_id,
  3892. destination_conference_name,
  3893. destination_conference_modifier,
  3894. number_of_destination_nodes,
  3895. destination_node_list,
  3896. result);
  3897. if (result == GCC_RESULT_SUCCESSFUL)
  3898. {
  3899. m_pMcsUserObject->ConferenceTransferIndication (
  3900. destination_conference_name,
  3901. destination_conference_modifier,
  3902. destination_address_list,
  3903. number_of_destination_nodes,
  3904. destination_node_list,
  3905. password);
  3906. }
  3907. DebugExitVOID(CConf::ProcessConferenceTransferRequest);
  3908. }
  3909. /*
  3910. * CConf::ProcessConferenceAddRequest ()
  3911. *
  3912. * Private Function Description
  3913. * This routine processes a conference add request PDU.
  3914. *
  3915. * Formal Parameters:
  3916. * requesting_node_id - Node ID that made the transfer
  3917. * request.
  3918. * destination_conference_name - The name of the conference to
  3919. * transfer to.
  3920. * destination_conference_modifier - The name of the conference modifier
  3921. * to transfer to.
  3922. * destination_address_list - Network address list of the
  3923. * conference to transfer to.
  3924. * number_of_destination_nodes - The number of nodes in the list of
  3925. * nodes that should perform the
  3926. * transfer.
  3927. * destination_node_list - The list of nodes that should
  3928. * perform the transfer.
  3929. * password - The password needed to join the
  3930. * new conference.
  3931. *
  3932. * Return Value
  3933. * None.
  3934. *
  3935. * Side Effects
  3936. * None.
  3937. *
  3938. * Caveats
  3939. * None.
  3940. */
  3941. void CConf::
  3942. ProcessConferenceAddRequest
  3943. (
  3944. CNetAddrListContainer *network_address_list,
  3945. CUserDataListContainer *user_data_list,
  3946. UserID adding_node,
  3947. TagNumber add_request_tag,
  3948. UserID requesting_node
  3949. )
  3950. {
  3951. BOOL generate_add_indication = FALSE;
  3952. GCCResponseTag add_response_tag;
  3953. DebugEntry(CConf::ProcessConferenceAddRequest);
  3954. if (m_pMcsUserObject->GetMyNodeID() == m_pMcsUserObject->GetTopNodeID())
  3955. {
  3956. if (DoesRequesterHavePrivilege(requesting_node, ADD_PRIVILEGE))
  3957. {
  3958. if ((m_pMcsUserObject->GetMyNodeID() == adding_node) ||
  3959. (adding_node == 0))
  3960. {
  3961. generate_add_indication = TRUE;
  3962. }
  3963. else
  3964. {
  3965. /*
  3966. ** Here we send the add request on to the MCU that is
  3967. ** supposed to do the adding.
  3968. */
  3969. m_pMcsUserObject->ConferenceAddRequest(
  3970. add_request_tag,
  3971. requesting_node,
  3972. adding_node,
  3973. adding_node,
  3974. network_address_list,
  3975. user_data_list);
  3976. }
  3977. }
  3978. else
  3979. {
  3980. // Send back negative response stating inproper privileges
  3981. m_pMcsUserObject->ConferenceAddResponse(
  3982. add_request_tag,
  3983. requesting_node,
  3984. NULL,
  3985. GCC_RESULT_INVALID_REQUESTER);
  3986. }
  3987. }
  3988. else if (m_pMcsUserObject->GetMyNodeID() == adding_node)
  3989. {
  3990. /*
  3991. ** This is the node that is supposed to get the add indication
  3992. ** so send it on.
  3993. */
  3994. generate_add_indication = TRUE;
  3995. }
  3996. if (generate_add_indication)
  3997. {
  3998. // First set up the Add Response Tag
  3999. while (1)
  4000. {
  4001. add_response_tag = m_nConfAddResponseTag++;
  4002. if (0 == m_AddResponseList.Find(add_response_tag))
  4003. break;
  4004. }
  4005. m_AddResponseList.Append(add_response_tag, add_request_tag);
  4006. g_pControlSap->ConfAddIndication(m_nConfID,
  4007. add_response_tag,
  4008. network_address_list,
  4009. user_data_list,
  4010. requesting_node);
  4011. }
  4012. DebugExitVOID(CConf::ProcessConferenceAddRequest);
  4013. }
  4014. /***************Conductorship Callbacks from User object*******************/
  4015. /*
  4016. * void ProcessConductorGrabConfirm ()
  4017. *
  4018. * Private Function Description
  4019. * The routine processes a conductor grab confirm received from the
  4020. * MCSUser object.
  4021. *
  4022. * Formal Parameters:
  4023. * result - This is the result from the grab request.
  4024. *
  4025. * Return Value
  4026. * None.
  4027. *
  4028. * Side Effects
  4029. * None.
  4030. *
  4031. * Caveats
  4032. * None.
  4033. */
  4034. void CConf::
  4035. ProcessConductorGrabConfirm ( GCCResult result )
  4036. {
  4037. DebugEntry(CConf::ProcessConductorGrabConfirm);
  4038. TRACE_OUT(("CConf::ProcessConductorGrabConfirm: result = %d", result));
  4039. if ((m_eNodeType == TOP_PROVIDER_NODE) ||
  4040. (m_eNodeType == TOP_PROVIDER_AND_CONVENER_NODE))
  4041. {
  4042. #ifdef JASPER
  4043. // Inform the control SAP of the result
  4044. g_pControlSap->ConductorAssignConfirm ( result,
  4045. m_nConfID);
  4046. #endif // JASPER
  4047. /*
  4048. ** If we were successful, we must send a Conductor Assign Indication
  4049. ** PDU to every node in the conference to inform them that the
  4050. ** conductor has changed.
  4051. */
  4052. if (result == GCC_RESULT_SUCCESSFUL)
  4053. {
  4054. /*
  4055. ** We use NULL for the conductor ID because the conductor can be
  4056. ** determined from the sender of the Assign Indication PDU.
  4057. */
  4058. m_pMcsUserObject->SendConductorAssignIndication(
  4059. m_pMcsUserObject->GetTopNodeID());
  4060. m_nConductorNodeID = m_pMcsUserObject->GetMyNodeID();
  4061. m_fConductorGrantedPermission = TRUE;
  4062. }
  4063. // Reset the Assign Request Pending flag back to FALSE.
  4064. m_fConductorAssignRequestPending = FALSE;
  4065. }
  4066. else
  4067. {
  4068. if (result == GCC_RESULT_SUCCESSFUL)
  4069. {
  4070. /*
  4071. ** If this node is not the Top Provider, we must try to Give the
  4072. ** Conductor token to the Top Provider. The Top Provider is used to
  4073. ** monitor the use of the conductor token. I the give to the Top
  4074. ** Provider is unsuccessful then this node is the new conductor.
  4075. */
  4076. m_pMcsUserObject->ConductorTokenGive(m_pMcsUserObject->GetTopNodeID());
  4077. }
  4078. else
  4079. {
  4080. #ifdef JASPER
  4081. // Inform the control SAP of the result
  4082. g_pControlSap->ConductorAssignConfirm(result, m_nConfID);
  4083. #endif // JASPER
  4084. }
  4085. }
  4086. DebugExitVOID(CConf::ProcessConductorGrabConfirm);
  4087. }
  4088. /*
  4089. * void ProcessConductorAssignIndication ()
  4090. *
  4091. * Private Function Description
  4092. * This routine processes a conductor assign indication received from
  4093. * the MCSUser object.
  4094. *
  4095. * Formal Parameters:
  4096. * new_conductor_id - This is the node id of the new conductor.
  4097. * sender_id - Node ID of node that sent the indication.
  4098. * Should be the Top Provider.
  4099. *
  4100. * Return Value
  4101. * None.
  4102. *
  4103. * Side Effects
  4104. * None.
  4105. *
  4106. * Caveats
  4107. * None.
  4108. */
  4109. void CConf::
  4110. ProcessConductorAssignIndication
  4111. (
  4112. UserID new_conductor_id,
  4113. UserID sender_id
  4114. )
  4115. {
  4116. DebugEntry(CConf::ProcessConductorAssignIndication);
  4117. if (sender_id == m_pMcsUserObject->GetTopNodeID())
  4118. {
  4119. TRACE_OUT(("CConf: ConductAssignInd: Received from top provider"));
  4120. // Ignore this indication if the conference is not conductible
  4121. if (m_fConfConductible)
  4122. {
  4123. // Save UserID of the new conductor if not the Top Provider
  4124. if (sender_id != m_pMcsUserObject->GetMyNodeID())
  4125. {
  4126. m_nConductorNodeID = new_conductor_id;
  4127. }
  4128. /*
  4129. ** Inform the control SAP and all the enrolled application SAPs
  4130. ** that there is a new conductor.
  4131. */
  4132. TRACE_OUT(("CConf: ConductAssignInd: Send to Control SAP"));
  4133. g_pControlSap->ConductorAssignIndication(m_nConductorNodeID, m_nConfID);
  4134. /*
  4135. ** We iterate on a temporary list to avoid any problems
  4136. ** if the application sap leaves during the callback.
  4137. */
  4138. CAppSap *pAppSap;
  4139. CAppSapList TempList(m_RegisteredAppSapList);
  4140. TempList.Reset();
  4141. while (NULL != (pAppSap = TempList.Iterate()))
  4142. {
  4143. if (DoesSAPHaveEnrolledAPE(pAppSap))
  4144. {
  4145. pAppSap->ConductorAssignIndication(m_nConductorNodeID, m_nConfID);
  4146. }
  4147. }
  4148. }
  4149. else
  4150. {
  4151. ERROR_OUT(("CConf:ProcessConductorAssignInd: Conductor Assign sent in non-conductible conference"));
  4152. }
  4153. }
  4154. else
  4155. {
  4156. ERROR_OUT(("CConf:ProcessConductorAssignInd: Conductor Assign sent from NON-Top Provider"));
  4157. }
  4158. DebugExitVOID(CConf::ProcessConductorAssignIndication);
  4159. }
  4160. /*
  4161. * void ProcessConductorReleaseIndication ()
  4162. *
  4163. * Private Function Description
  4164. * This routine processes a conductor release indication received from
  4165. * the MCSUser object.
  4166. *
  4167. * Formal Parameters:
  4168. * sender_id - Node ID of node that sent the indication.
  4169. * Should be the Top Provider or the conductor.
  4170. *
  4171. * Return Value
  4172. * None.
  4173. *
  4174. * Side Effects
  4175. * None.
  4176. *
  4177. * Caveats
  4178. * None.
  4179. */
  4180. void CConf::
  4181. ProcessConductorReleaseIndication ( UserID sender_id )
  4182. {
  4183. DebugEntry(CConf::ProcessConductorReleaseIndication);
  4184. if ((sender_id == m_pMcsUserObject->GetTopNodeID()) ||
  4185. (sender_id == m_nConductorNodeID) ||
  4186. (sender_id == 0))
  4187. {
  4188. // Ignore this indication if the conference is not conductible
  4189. if (m_fConfConductible)
  4190. {
  4191. m_fConductorGrantedPermission = FALSE;
  4192. // Reset to Non-Conducted mode
  4193. m_nConductorNodeID = 0;
  4194. /*
  4195. ** Inform the control SAP and all the enrolled application SAPs
  4196. ** that the conductor was released.
  4197. */
  4198. g_pControlSap->ConductorReleaseIndication( m_nConfID );
  4199. /*
  4200. ** We iterate on a temporary list to avoid any problems
  4201. ** if the application sap leaves during the callback.
  4202. */
  4203. CAppSap *pAppSap;
  4204. CAppSapList TempList(m_RegisteredAppSapList);
  4205. TempList.Reset();
  4206. while (NULL != (pAppSap = TempList.Iterate()))
  4207. {
  4208. if (DoesSAPHaveEnrolledAPE(pAppSap))
  4209. {
  4210. pAppSap->ConductorReleaseIndication(m_nConfID);
  4211. }
  4212. }
  4213. }
  4214. }
  4215. DebugExitVOID(CConf::ProcessConductorReleaseIndication);
  4216. }
  4217. /*
  4218. * void ProcessConductorGiveIndication ()
  4219. *
  4220. * Private Function Description
  4221. * This routine processes a conductor give indication received from
  4222. * the MCSUser object.
  4223. *
  4224. * Formal Parameters:
  4225. * giving_node_id - Node ID of node that is givving up
  4226. * conductorship.
  4227. *
  4228. * Return Value
  4229. * None.
  4230. *
  4231. * Side Effects
  4232. * None.
  4233. *
  4234. * Caveats
  4235. * None.
  4236. */
  4237. void CConf::
  4238. ProcessConductorGiveIndication ( UserID giving_node_id )
  4239. {
  4240. DebugEntry(CConf::ProcessConductorGiveIndication);
  4241. // Ignore this indication if the conference is not conductible
  4242. if (m_fConfConductible)
  4243. {
  4244. /*
  4245. ** If this node is the Top Provider and node giving conductor ship is
  4246. ** not the current Conductor, this node must check to make sure that
  4247. ** it is valid for this node to become the Top Conductor. Otherwise,
  4248. ** we can assume this is a real give.
  4249. */
  4250. if ((giving_node_id == m_nConductorNodeID) ||
  4251. (m_pMcsUserObject->GetMyNodeID() != m_pMcsUserObject->GetTopNodeID()))
  4252. {
  4253. // This flag is set when there is an outstanding give.
  4254. m_fConductorGiveResponsePending = TRUE;
  4255. /*
  4256. ** Inform the control SAP.
  4257. */
  4258. g_pControlSap->ConductorGiveIndication(m_nConfID);
  4259. }
  4260. else
  4261. {
  4262. TRACE_OUT(("CConf: ProcessConductorGiveInd: Send REAL Assign Ind"));
  4263. m_nConductorNodeID = giving_node_id;
  4264. m_pMcsUserObject->SendConductorAssignIndication(m_nConductorNodeID);
  4265. m_pMcsUserObject->ConductorTokenGiveResponse(RESULT_USER_REJECTED);
  4266. }
  4267. }
  4268. DebugExitVOID(CConf::ProcessConductorGiveIndication);
  4269. }
  4270. /*
  4271. * void ProcessConductorGiveConfirm ()
  4272. *
  4273. * Private Function Description
  4274. * This routine processes a conductor give confirm received from
  4275. * the MCSUser object.
  4276. *
  4277. * Formal Parameters:
  4278. * result - This is the result of the give request.
  4279. *
  4280. * Return Value
  4281. * None.
  4282. *
  4283. * Side Effects
  4284. * None.
  4285. *
  4286. * Caveats
  4287. * None.
  4288. */
  4289. void CConf::
  4290. ProcessConductorGiveConfirm ( GCCResult result )
  4291. {
  4292. DebugEntry(CConf::ProcessConductorGiveConfirm);
  4293. TRACE_OUT(("CConf::ProcessConductorGiveConfirm: result = %d", result));
  4294. // Ignore this indication if the conference is not conductible
  4295. if (m_fConfConductible)
  4296. {
  4297. /*
  4298. ** First we must determine if this Give Confirm is from
  4299. ** a Give Request to the Top Provider that was associated with an
  4300. ** Assign Request. This type of Give Confirm is from the Top Provider.
  4301. ** If not, we check to make sure that this is a Give Confirm associated
  4302. ** with a give request issued by the Node Controller. Otherwise, we
  4303. ** dont process it.
  4304. */
  4305. if (m_fConductorAssignRequestPending)
  4306. {
  4307. #ifdef JASPER
  4308. /*
  4309. ** The proper result is for the Top Provider to reject the give
  4310. ** to the Donor User ID that is the new Conductor. This is
  4311. ** straight out of the T.124 document.
  4312. */
  4313. if (result != GCC_RESULT_SUCCESSFUL)
  4314. result = GCC_RESULT_SUCCESSFUL;
  4315. else
  4316. result = GCC_RESULT_UNSPECIFIED_FAILURE;
  4317. // Inform the control SAP of the result
  4318. g_pControlSap->ConductorAssignConfirm(result, m_nConfID);
  4319. #endif // JASPER
  4320. m_fConductorAssignRequestPending = FALSE;
  4321. }
  4322. else if (m_nPendingConductorNodeID != 0)
  4323. {
  4324. if (result == GCC_RESULT_SUCCESSFUL)
  4325. m_fConductorGrantedPermission = FALSE;
  4326. #ifdef JASPER
  4327. g_pControlSap->ConductorGiveConfirm(result, m_nConfID, m_nPendingConductorNodeID);
  4328. #endif // JASPER
  4329. // Set the pending conductor node ID back to zero.
  4330. m_nPendingConductorNodeID = 0;
  4331. }
  4332. }
  4333. DebugExitVOID(CConf::ProcessConductorGiveConfirm);
  4334. }
  4335. /*
  4336. * void ProcessConductorPermitGrantInd ()
  4337. *
  4338. * Private Function Description
  4339. * This routine processes a conductor permission grant indication received
  4340. * from the MCSUser object.
  4341. *
  4342. * Formal Parameters:
  4343. * permission_grant_indication - This is the PDU data structure
  4344. * associated with the conductor
  4345. * permission grant indication.
  4346. * sender_id - This is the node ID of the node
  4347. * that sent the indication.
  4348. *
  4349. * Return Value
  4350. * None.
  4351. *
  4352. * Side Effects
  4353. * None.
  4354. *
  4355. * Caveats
  4356. * None.
  4357. */
  4358. void CConf::
  4359. ProcessConductorPermitGrantInd
  4360. (
  4361. PUserPermissionGrantIndicationInfo permission_grant_indication,
  4362. UserID sender_id
  4363. )
  4364. {
  4365. UINT i;
  4366. DebugEntry(CConf::ProcessConductorPermitGrantInd);
  4367. if (m_fConfConductible)
  4368. {
  4369. if (sender_id == m_nConductorNodeID)
  4370. {
  4371. // First check to see if we have been given permission
  4372. m_fConductorGrantedPermission = FALSE;
  4373. for (i = 0; i < permission_grant_indication->number_granted; i++)
  4374. {
  4375. if (permission_grant_indication->granted_node_list[i] ==
  4376. m_pMcsUserObject->GetMyNodeID())
  4377. {
  4378. TRACE_OUT(("CConf::ProcessConductorPermitGrantInd: Permission was Granted"));
  4379. m_fConductorGrantedPermission = TRUE;
  4380. break;
  4381. }
  4382. }
  4383. /*
  4384. ** This indication goes to the control SAP and all the application
  4385. ** SAPs.
  4386. */
  4387. g_pControlSap->ConductorPermitGrantIndication (
  4388. m_nConfID,
  4389. permission_grant_indication->number_granted,
  4390. permission_grant_indication->granted_node_list,
  4391. permission_grant_indication->number_waiting,
  4392. permission_grant_indication->waiting_node_list,
  4393. m_fConductorGrantedPermission);
  4394. /*
  4395. ** We iterate on a temporary list to avoid any problems
  4396. ** if the application sap leaves during the callback.
  4397. */
  4398. CAppSap *pAppSap;
  4399. CAppSapList TempList(m_RegisteredAppSapList);
  4400. TempList.Reset();
  4401. while (NULL != (pAppSap = TempList.Iterate()))
  4402. {
  4403. if (DoesSAPHaveEnrolledAPE(pAppSap))
  4404. {
  4405. pAppSap->ConductorPermitGrantIndication(
  4406. m_nConfID,
  4407. permission_grant_indication->number_granted,
  4408. permission_grant_indication->granted_node_list,
  4409. permission_grant_indication->number_waiting,
  4410. permission_grant_indication->waiting_node_list,
  4411. m_fConductorGrantedPermission);
  4412. }
  4413. }
  4414. }
  4415. }
  4416. DebugExitVOID(CConf::ProcessConductorPermitGrantInd);
  4417. }
  4418. /*
  4419. * void ProcessConductorTestConfirm ()
  4420. *
  4421. * Private Function Description
  4422. * This routine processes a conductor test confirm received
  4423. * from the MCSUser object.
  4424. *
  4425. * Formal Parameters:
  4426. * result - This is the result of the conductor test request
  4427. *
  4428. * Return Value
  4429. * None.
  4430. *
  4431. * Side Effects
  4432. * None.
  4433. *
  4434. * Caveats
  4435. * None.
  4436. */
  4437. void CConf::
  4438. ProcessConductorTestConfirm ( GCCResult result )
  4439. {
  4440. BOOL conducted_mode;
  4441. CBaseSap *pSap;
  4442. DebugEntry(CConf::ProcessConductorTestConfirm);
  4443. if (! m_ConductorTestList.IsEmpty())
  4444. {
  4445. if (result == GCC_RESULT_SUCCESSFUL)
  4446. conducted_mode = TRUE;
  4447. else
  4448. conducted_mode = FALSE;
  4449. /*
  4450. ** Pop the next command target of the list of command targets.
  4451. ** Note that all token test request are processed in the order
  4452. ** that they were issued so we are gauranteed to send the confirms
  4453. ** to the correct target.
  4454. */
  4455. pSap = m_ConductorTestList.Get();
  4456. pSap->ConductorInquireConfirm(m_nConductorNodeID,
  4457. result,
  4458. m_fConductorGrantedPermission,
  4459. conducted_mode,
  4460. m_nConfID);
  4461. }
  4462. DebugExitVOID(CConf::ProcessConductorTestConfirm);
  4463. }
  4464. /*************************************************************************/
  4465. /*
  4466. * CConf::InitiateTermination ()
  4467. *
  4468. * Private Function Description
  4469. * This routine informs the owner object that the conference has
  4470. * self terminated. It also directs a disconnect provider request at
  4471. * the parent connection.
  4472. *
  4473. * Formal Parameters:
  4474. * reason - This is the reason for the termination.
  4475. * requesting_node_id - This is the node ID of the node that is
  4476. * making the request,
  4477. *
  4478. * Return Value
  4479. * None.
  4480. *
  4481. * Side Effects
  4482. * None.
  4483. *
  4484. * Caveats
  4485. * None.
  4486. */
  4487. void CConf::
  4488. InitiateTermination
  4489. (
  4490. GCCReason reason,
  4491. UserID requesting_node_id
  4492. )
  4493. {
  4494. DebugEntry(CConf::InitiateTermination);
  4495. if (! m_fTerminationInitiated)
  4496. {
  4497. m_fTerminationInitiated = TRUE;
  4498. if (m_fConfIsEstablished ||
  4499. (reason == GCC_REASON_DOMAIN_PARAMETERS_UNACCEPTABLE) ||
  4500. m_fConfTerminatePending)
  4501. {
  4502. g_pControlSap->ConfTerminateIndication(m_nConfID, requesting_node_id, reason);
  4503. m_fConfIsEstablished = FALSE;
  4504. }
  4505. // Disconnect from the MCS parent connection if it exists
  4506. if (m_hParentConnection != NULL)
  4507. {
  4508. g_pMCSIntf->DisconnectProviderRequest(m_hParentConnection);
  4509. m_hParentConnection = NULL;
  4510. }
  4511. g_pGCCController->ProcessConfTerminated(m_nConfID, reason);
  4512. /*
  4513. ** Here we cleanup the registered application list. If any Application
  4514. ** SAPs are still registered we will first send them PermitToEnroll
  4515. ** indications revoking the permission to enroll and then we will
  4516. ** unregister them (the unregister call takes care of this). First set up
  4517. ** a temporary list of the registered applications to iterate on since
  4518. ** members of this list will be removed during this process.
  4519. */
  4520. if (! m_RegisteredAppSapList.IsEmpty())
  4521. {
  4522. CAppSapList TempList(m_RegisteredAppSapList);
  4523. CAppSap *pAppSap;
  4524. TempList.Reset();
  4525. while (NULL != (pAppSap = TempList.Iterate()))
  4526. {
  4527. UnRegisterAppSap(pAppSap);
  4528. }
  4529. }
  4530. }
  4531. DebugExitVOID(CConf::InitiateTermination);
  4532. }
  4533. /*
  4534. * CConf::GetConferenceNameAndModifier ()
  4535. *
  4536. * Private Function Description
  4537. * This routine returns pointers to the conference name and modifier.
  4538. *
  4539. * Formal Parameters:
  4540. * conference_name - Pointer to structure that holds the conference
  4541. * name.
  4542. * requesting_node_id - This is a pointer to a pointer that holds the
  4543. * conference modifier.
  4544. *
  4545. * Return Value
  4546. * None.
  4547. *
  4548. * Side Effects
  4549. * None.
  4550. *
  4551. * Caveats
  4552. * None.
  4553. */
  4554. void CConf::
  4555. GetConferenceNameAndModifier
  4556. (
  4557. PGCCConferenceName pConfName,
  4558. PGCCNumericString ppszConfModifier
  4559. )
  4560. {
  4561. pConfName->numeric_string = m_pszConfNumericName;
  4562. pConfName->text_string = m_pwszConfTextName;
  4563. *ppszConfModifier = (GCCNumericString) m_pszConfModifier;
  4564. }
  4565. /*
  4566. * CAppRosterMgr * CConf::GetAppRosterManager ()
  4567. *
  4568. * Private Function Description
  4569. * This call returns a pointer to the application manager that
  4570. * matches the passed in key. It returns NULL is the application
  4571. * does not exists.
  4572. *
  4573. * Formal Parameters:
  4574. * session_key - This is the session key associated with the
  4575. * application roster manager that is being
  4576. * requested.
  4577. *
  4578. * Return Value
  4579. * A pointer to the appropriate application roster manager.
  4580. * NULL if on does not exists.
  4581. *
  4582. * Side Effects
  4583. * None.
  4584. *
  4585. * Caveats
  4586. * None.
  4587. */
  4588. CAppRosterMgr * CConf::
  4589. GetAppRosterManager ( PGCCSessionKey session_key )
  4590. {
  4591. CAppRosterMgr *app_roster_manager = NULL;
  4592. if (session_key != NULL)
  4593. {
  4594. CAppRosterMgr *lpAppRosterMgr;
  4595. m_AppRosterMgrList.Reset();
  4596. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  4597. {
  4598. if (lpAppRosterMgr->IsThisYourSessionKey(session_key))
  4599. {
  4600. app_roster_manager = lpAppRosterMgr;
  4601. break;
  4602. }
  4603. }
  4604. }
  4605. return (app_roster_manager);
  4606. }
  4607. /*
  4608. * CConf::GetNewUserIDTag ()
  4609. *
  4610. * Private Function Description
  4611. * This routine generates a User ID Tag number that is used in a
  4612. * User ID indication sent betweek two connected nodes.
  4613. *
  4614. * Formal Parameters:
  4615. * None.
  4616. *
  4617. * Return Value
  4618. * This is the User ID tag number generated by this routine.
  4619. *
  4620. * Side Effects
  4621. * None.
  4622. *
  4623. * Caveats
  4624. * Zero is not a valid. We initialize the convener user ID tag to
  4625. * zero which is an invalid tag.
  4626. */
  4627. TagNumber CConf::
  4628. GetNewUserIDTag ( void )
  4629. {
  4630. /*
  4631. ** Determine the tag number to associate with the GCC User ID
  4632. ** that will be returned after the pending request or confirm.
  4633. */
  4634. while (1)
  4635. {
  4636. if (++m_nUserIDTagNumber != 0)
  4637. {
  4638. if (m_ConnHdlTagNumberList2.Find(m_nUserIDTagNumber) == 0)
  4639. break;
  4640. }
  4641. }
  4642. return (m_nUserIDTagNumber);
  4643. }
  4644. /*
  4645. * CConf::DoesRequesterHavePrivilege ()
  4646. *
  4647. * Private Function Description
  4648. * This routine determines if the specified user has the specified
  4649. * privilege.
  4650. *
  4651. * Formal Parameters:
  4652. * requester_id - This is the node ID that is being checked for
  4653. * the specified privilege.
  4654. * privilege - Privilege being checked for.
  4655. *
  4656. * Return Value
  4657. * TRUE - If requester has privilege.
  4658. * FALSE - If requester does NOT have privilege.
  4659. *
  4660. * Side Effects
  4661. * None.
  4662. *
  4663. * Caveats
  4664. * None.
  4665. */
  4666. BOOL CConf::
  4667. DoesRequesterHavePrivilege
  4668. (
  4669. UserID requester_id,
  4670. ConferencePrivilegeType privilege
  4671. )
  4672. {
  4673. BOOL rc = FALSE;
  4674. if (requester_id == m_nConvenerNodeID)
  4675. rc = TRUE;
  4676. else
  4677. {
  4678. /*
  4679. ** First check to see if the node is the conductor and a conductor
  4680. ** privilege list exists. Next check to see if the conference is in
  4681. ** conducted mode and a conducted mode privilege list exists.
  4682. ** Else, if not in conducted mode and a Non-Conducted mode privilege
  4683. ** list exists use it.
  4684. */
  4685. if (m_nConductorNodeID == requester_id)
  4686. {
  4687. if (m_pConductorPrivilegeList != NULL)
  4688. {
  4689. rc = m_pConductorPrivilegeList->
  4690. IsPrivilegeAvailable(privilege);
  4691. }
  4692. }
  4693. if (rc == FALSE)
  4694. {
  4695. if (m_nConductorNodeID != 0)
  4696. {
  4697. if (m_pConductModePrivilegeList != NULL)
  4698. {
  4699. rc = m_pConductModePrivilegeList->IsPrivilegeAvailable(privilege);
  4700. }
  4701. }
  4702. else
  4703. {
  4704. if (m_pNonConductModePrivilegeList != NULL)
  4705. {
  4706. rc = m_pNonConductModePrivilegeList->IsPrivilegeAvailable(privilege);
  4707. }
  4708. }
  4709. }
  4710. }
  4711. return rc;
  4712. }
  4713. /*
  4714. * CConf::SendFullRosterRefresh ()
  4715. *
  4716. * Private Function Description
  4717. * When a new node is added to the conference it is the Top Provider's
  4718. * responsiblity to send out a complete refresh of all the rosters
  4719. * including both the conference roster and all the application rosters.
  4720. * That is the responsiblity of the routine.
  4721. *
  4722. * Formal Parameters:
  4723. * None.
  4724. *
  4725. * Return Value
  4726. * GCC_NO_ERROR - No error.
  4727. * GCC_ALLOCATION_FAILURE - A resource error occured.
  4728. *
  4729. * Side Effects
  4730. * None.
  4731. *
  4732. * Caveats
  4733. * None.
  4734. */
  4735. GCCError CConf::
  4736. SendFullRosterRefresh ( void )
  4737. {
  4738. GCCError rc;
  4739. GCCPDU gcc_pdu;
  4740. PSetOfApplicationInformation * application_information;
  4741. PSetOfApplicationInformation next_set_of_information;
  4742. DebugEntry(CConf::SendFullRosterRefresh);
  4743. /*
  4744. ** Start building the roster update indication. Not that this update
  4745. ** will include the conference roster as well as all the application
  4746. ** rosters.
  4747. */
  4748. gcc_pdu.choice = INDICATION_CHOSEN;
  4749. gcc_pdu.u.indication.choice = ROSTER_UPDATE_INDICATION_CHOSEN;
  4750. gcc_pdu.u.indication.u.roster_update_indication.application_information =
  4751. NULL;
  4752. gcc_pdu.u.indication.u.roster_update_indication.refresh_is_full = TRUE;
  4753. // Call on the base class to fill in the PDU structure
  4754. rc = m_pConfRosterMgr->GetFullRosterRefreshPDU (
  4755. &gcc_pdu.u.indication.u.roster_update_indication.node_information);
  4756. /*
  4757. ** If the conference roster get was successful we will iterate through
  4758. ** all the application roster managers making the same request for a
  4759. ** full refresh. Note that the application_information pointer is updated
  4760. ** after every request to an app roster manager. This is because new
  4761. ** sets of application information are being allocated everytime this call
  4762. ** is made.
  4763. */
  4764. if (rc == GCC_NO_ERROR)
  4765. {
  4766. CAppRosterMgr *lpAppRosterMgr;
  4767. application_information = &gcc_pdu.u.indication.u.
  4768. roster_update_indication.application_information;
  4769. m_AppRosterMgrList.Reset();
  4770. while (NULL != (lpAppRosterMgr = m_AppRosterMgrList.Iterate()))
  4771. {
  4772. next_set_of_information = lpAppRosterMgr->GetFullRosterRefreshPDU (
  4773. application_information,
  4774. &rc);
  4775. if (rc == GCC_NO_ERROR)
  4776. {
  4777. if (next_set_of_information != NULL)
  4778. application_information = &next_set_of_information->next;
  4779. //
  4780. // LONCHANC: If next_set_of_information is NULL,
  4781. // then application_information is unchanged.
  4782. // This means we effectively ignore this iteration.
  4783. // This is good because we do not lose anything.
  4784. //
  4785. }
  4786. else
  4787. break;
  4788. }
  4789. }
  4790. /*
  4791. ** If no errors have occured up to this point we will go ahead and send
  4792. ** out the PDU.
  4793. */
  4794. if (rc == GCC_NO_ERROR)
  4795. m_pMcsUserObject->RosterUpdateIndication (&gcc_pdu, FALSE);
  4796. DebugExitINT(CConf::SendFullRosterRefresh, rc);
  4797. return rc;
  4798. }
  4799. /*
  4800. * CConf::UpdateNewConferenceNode ()
  4801. *
  4802. * Private Function Description
  4803. *
  4804. * Formal Parameters:
  4805. * None.
  4806. *
  4807. * Return Value
  4808. * GCC_NO_ERROR - No error.
  4809. * GCC_ALLOCATION_FAILURE - A resource error occured.
  4810. *
  4811. * Side Effects
  4812. * None.
  4813. *
  4814. * Caveats
  4815. * None.
  4816. */
  4817. GCCError CConf::
  4818. UpdateNewConferenceNode ( void )
  4819. {
  4820. GCCError rc = GCC_NO_ERROR;
  4821. DebugEntry(CConf::UpdateNewConferenceNode);
  4822. // Here we send a full roster refresh for the node that added
  4823. rc = SendFullRosterRefresh ();
  4824. if (rc == GCC_NO_ERROR)
  4825. {
  4826. /*
  4827. ** We must inform the new node of the current conductorship
  4828. ** status. Note that we only do this if the conference is
  4829. ** conductible and we are the Top Provider.
  4830. */
  4831. if (m_fConfLocked == CONFERENCE_IS_LOCKED)
  4832. {
  4833. m_pMcsUserObject->SendConferenceLockIndication(
  4834. TRUE, // Indicates uniform send
  4835. 0);
  4836. }
  4837. else
  4838. {
  4839. m_pMcsUserObject->SendConferenceUnlockIndication(
  4840. TRUE, // Indicates uniform send
  4841. 0);
  4842. }
  4843. if (m_fConfConductible)
  4844. {
  4845. if (m_nConductorNodeID != 0)
  4846. {
  4847. m_pMcsUserObject->SendConductorAssignIndication(m_nConductorNodeID);
  4848. }
  4849. else
  4850. m_pMcsUserObject->SendConductorReleaseIndication();
  4851. }
  4852. }
  4853. else
  4854. {
  4855. ERROR_OUT(("CConf: UpdateNewConferenceNode: Error sending full refresh"));
  4856. InitiateTermination(GCC_REASON_ERROR_LOW_RESOURCES, 0);
  4857. }
  4858. DebugExitINT(CConf::UpdateNewConferenceNode, rc);
  4859. return rc;
  4860. }
  4861. /*
  4862. ** Before we start the disconnect/termination process we must remove all the
  4863. ** outstanding invite request from our list and send back associated
  4864. ** confirms. Here we go ahead disconnect all connection associated with
  4865. ** the invites.
  4866. */
  4867. void CConf::
  4868. DeleteOutstandingInviteRequests ( void )
  4869. {
  4870. INVITE_REQ_INFO *pInvReqInfo;
  4871. while (NULL != (pInvReqInfo = m_InviteRequestList.Get()))
  4872. {
  4873. DeleteInviteRequest(pInvReqInfo);
  4874. }
  4875. }
  4876. void CConf::
  4877. CancelInviteRequest ( ConnectionHandle hInviteReqConn )
  4878. {
  4879. INVITE_REQ_INFO *pInvReqInfo;
  4880. m_InviteRequestList.Reset();
  4881. while (NULL != (pInvReqInfo = m_InviteRequestList.Iterate()))
  4882. {
  4883. if (hInviteReqConn == pInvReqInfo->connection_handle)
  4884. {
  4885. m_InviteRequestList.Remove(pInvReqInfo);
  4886. DeleteInviteRequest(pInvReqInfo);
  4887. return;
  4888. }
  4889. }
  4890. }
  4891. void CConf::
  4892. DeleteInviteRequest ( INVITE_REQ_INFO *pInvReqInfo )
  4893. {
  4894. // Cleanup the connection handle list
  4895. ASSERT(NULL != pInvReqInfo);
  4896. ASSERT(0 != pInvReqInfo->connection_handle);
  4897. m_ConnHandleList.Remove(pInvReqInfo->connection_handle);
  4898. g_pMCSIntf->DisconnectProviderRequest(pInvReqInfo->connection_handle);
  4899. // Send the invite confirm
  4900. g_pControlSap->ConfInviteConfirm(m_nConfID,
  4901. NULL,
  4902. GCC_RESULT_INVALID_CONFERENCE,
  4903. pInvReqInfo->connection_handle);
  4904. // Free up the invite request info structure
  4905. if (NULL != pInvReqInfo->user_data_list)
  4906. {
  4907. pInvReqInfo->user_data_list->Release();
  4908. }
  4909. delete pInvReqInfo;
  4910. }
  4911. void CConf::
  4912. ProcessConfJoinResponse
  4913. (
  4914. PUserJoinResponseInfo join_response_info
  4915. )
  4916. {
  4917. BOOL_PTR bptr;
  4918. if (NULL != (bptr = m_JoinRespNamePresentConnHdlList2.Remove(join_response_info->connection_handle)))
  4919. {
  4920. ConfJoinIndResponse (
  4921. (ConnectionHandle)join_response_info->connection_handle,
  4922. join_response_info->password_challenge,
  4923. join_response_info->user_data_list,
  4924. (bptr != FALSE_PTR),
  4925. FALSE,
  4926. join_response_info->result);
  4927. }
  4928. }
  4929. void CConf::
  4930. ProcessAppInvokeIndication
  4931. (
  4932. CInvokeSpecifierListContainer *pInvokeList,
  4933. UserID uidInvoker
  4934. )
  4935. {
  4936. /*
  4937. ** Here we pass the invoke along to all the enrolled application
  4938. ** SAPs as well as the control SAP.
  4939. */
  4940. g_pControlSap->AppInvokeIndication(m_nConfID, pInvokeList, uidInvoker);
  4941. /*
  4942. ** We iterate on a temporary list to avoid any problems
  4943. ** if the application sap leaves during the callback.
  4944. */
  4945. CAppSap *pAppSap;
  4946. CAppSapList TempList(m_RegisteredAppSapList);
  4947. TempList.Reset();
  4948. while (NULL != (pAppSap = TempList.Iterate()))
  4949. {
  4950. if (DoesSAPHaveEnrolledAPE(pAppSap))
  4951. {
  4952. pAppSap->AppInvokeIndication(m_nConfID, pInvokeList, uidInvoker);
  4953. }
  4954. }
  4955. }
  4956. #ifdef JASPER
  4957. void CConf::
  4958. ProcessConductorPermitAskIndication
  4959. (
  4960. PPermitAskIndicationInfo indication_info
  4961. )
  4962. {
  4963. // Ignore this indication if the conference is not conductible
  4964. if (m_fConfConductible &&
  4965. (m_nConductorNodeID == m_pMcsUserObject->GetMyNodeID()))
  4966. {
  4967. g_pControlSap->ConductorPermitAskIndication(
  4968. m_nConfID,
  4969. indication_info->permission_is_granted,
  4970. indication_info->sender_id);
  4971. }
  4972. }
  4973. #endif // JASPER
  4974. void CConf::
  4975. ProcessConfAddResponse
  4976. (
  4977. PAddResponseInfo add_response_info
  4978. )
  4979. {
  4980. CNetAddrListContainer *network_address_list;
  4981. if (NULL != (network_address_list = m_AddRequestList.Remove(add_response_info->add_request_tag)))
  4982. {
  4983. g_pControlSap->ConfAddConfirm(
  4984. m_nConfID,
  4985. network_address_list,
  4986. add_response_info->user_data_list,
  4987. add_response_info->result);
  4988. // Unlock and remove the net address list
  4989. network_address_list->UnLockNetworkAddressList();
  4990. }
  4991. }
  4992. void CConf::
  4993. ConfRosterReportIndication ( CConfRosterMsg * pMsg )
  4994. {
  4995. // First send the update to the Control Sap.
  4996. g_pControlSap->ConfRosterReportIndication(m_nConfID, pMsg);
  4997. // Next send the update to all the Enrolled Application Saps
  4998. #if 0 // LONCHANC: app sap does not support conf roster report indication
  4999. /*
  5000. ** We iterate on a temporary list to avoid any problems
  5001. ** if the application sap leaves during the callback.
  5002. */
  5003. CAppSap *pAppSap;
  5004. CAppSapList TempList(m_RegisteredAppSapList);
  5005. TempList.Reset();
  5006. while (NULL != (pAppSap = TempList.Iterate()))
  5007. {
  5008. if (DoesSAPHaveEnrolledAPE(pAppSap))
  5009. {
  5010. pAppSap->ConfRosterReportIndication(m_nConfID, pMsg);
  5011. }
  5012. }
  5013. #endif // 0
  5014. }
  5015. int KeyCompare(const struct Key *key1, const struct Key *key2)
  5016. {
  5017. if (key1->choice != key2->choice)
  5018. return 1;
  5019. switch (key1->choice) {
  5020. case object_chosen:
  5021. return ASN1objectidentifier_cmp((struct ASN1objectidentifier_s **) &key1->u.object,
  5022. (struct ASN1objectidentifier_s **) &key2->u.object);
  5023. case h221_non_standard_chosen:
  5024. if (key1->u.h221_non_standard.length != key2->u.h221_non_standard.length)
  5025. return 1;
  5026. return memcmp(&key1->u.h221_non_standard.value,
  5027. &key2->u.h221_non_standard.value,
  5028. key1->u.h221_non_standard.length);
  5029. }
  5030. return 1;
  5031. }
  5032. BOOL CConf::
  5033. DoesRosterPDUContainApplet(PGCCPDU roster_update,
  5034. const struct Key *app_proto_key, BOOL refreshonly)
  5035. {
  5036. BOOL rc = FALSE;
  5037. PSetOfApplicationInformation set_of_application_info;
  5038. ASN1choice_t choice;
  5039. PSessionKey session_key;
  5040. DebugEntry(CConf::DoesRosterPDUContainApplet);
  5041. set_of_application_info = roster_update->u.indication.u.
  5042. roster_update_indication.application_information;
  5043. while (set_of_application_info != NULL)
  5044. {
  5045. choice = set_of_application_info->value.application_record_list.choice;
  5046. session_key = &set_of_application_info->value.session_key;
  5047. if (refreshonly && (choice != application_record_refresh_chosen))
  5048. continue;
  5049. if (!refreshonly && (choice == application_no_change_chosen))
  5050. continue;
  5051. if (0 == KeyCompare(&session_key->application_protocol_key,
  5052. app_proto_key))
  5053. {
  5054. rc = TRUE;
  5055. break;
  5056. }
  5057. set_of_application_info = set_of_application_info->next;
  5058. }
  5059. DebugExitINT(CConf::DoesRosterPDUContainApplet, rc);
  5060. return rc;
  5061. }
  5062. UINT HexaStringToUINT(LPCTSTR pcszString)
  5063. {
  5064. ASSERT(pcszString);
  5065. UINT uRet = 0;
  5066. LPTSTR pszStr = (LPTSTR) pcszString;
  5067. while (_T('\0') != pszStr[0])
  5068. {
  5069. if ((pszStr[0] >= _T('0')) && (pszStr[0] <= _T('9')))
  5070. {
  5071. uRet = (16 * uRet) + (BYTE) (pszStr[0] - _T('0'));
  5072. }
  5073. else if ((pszStr[0] >= _T('a')) && (pszStr[0] <= _T('f')))
  5074. {
  5075. uRet = (16 * uRet) + (BYTE) (pszStr[0] - _T('a') + 10);
  5076. }
  5077. else if ((pszStr[0] >= _T('A')) && (pszStr[0] <= _T('F')))
  5078. {
  5079. uRet = (16 * uRet) + (BYTE) (pszStr[0] - _T('A') + 10);
  5080. }
  5081. else
  5082. ASSERT(0);
  5083. pszStr++; // NOTE: DBCS characters are not allowed!
  5084. }
  5085. return uRet;
  5086. }
  5087. void CConf::AddNodeVersion(UserID NodeId, NodeRecord *pNodeRecord)
  5088. {
  5089. PSetOfUserData set_of_user_data;
  5090. ASN1octetstring_t user_data;
  5091. ASN1octet_t *currpos;
  5092. TCHAR szVersion[256];
  5093. if (pNodeRecord->bit_mask&RECORD_USER_DATA_PRESENT)
  5094. {
  5095. set_of_user_data = pNodeRecord->record_user_data;
  5096. while (set_of_user_data)
  5097. {
  5098. if (set_of_user_data->user_data_element.bit_mask & USER_DATA_FIELD_PRESENT)
  5099. {
  5100. user_data = set_of_user_data->user_data_element.user_data_field;
  5101. // Looking for the octet string L"VER:"
  5102. currpos = user_data.value;
  5103. while (currpos + sizeof(L"VER:") < user_data.value + user_data.length)
  5104. {
  5105. if (!memcmp(currpos, L"VER:", 8))
  5106. {
  5107. break;
  5108. }
  5109. currpos++;
  5110. }
  5111. if (currpos + sizeof(L"VER:") < user_data.value + user_data.length)
  5112. { // found
  5113. WideCharToMultiByte(CP_ACP, 0, (const unsigned short*)(currpos+8),
  5114. 4 /* only need version num, "0404" */,
  5115. szVersion, 256, 0, 0);
  5116. szVersion[4] = '\0';
  5117. DWORD dwVer = HexaStringToUINT(szVersion);
  5118. m_NodeVersionList2.Append(NodeId, dwVer);
  5119. WARNING_OUT(("Insert version %x0x for node %d.\n", dwVer, NodeId));
  5120. }
  5121. }
  5122. set_of_user_data = set_of_user_data->next;
  5123. }
  5124. }
  5125. }
  5126. GCCError CConf::UpdateNodeVersionList(PGCCPDU roster_update,
  5127. GCCNodeID sender_id)
  5128. {
  5129. GCCError rc = GCC_NO_ERROR;
  5130. NodeRecordList node_record_list;
  5131. ASN1choice_t choice;
  5132. PSetOfNodeRecordRefreshes set_of_node_refresh;
  5133. PSetOfNodeRecordUpdates set_of_node_update;
  5134. UserID node_id;
  5135. NodeRecord *pNodeRecord;
  5136. node_record_list = roster_update->u.indication.u.roster_update_indication.
  5137. node_information.node_record_list;
  5138. switch(node_record_list.choice)
  5139. {
  5140. case node_no_change_chosen:
  5141. break;
  5142. case node_record_refresh_chosen:
  5143. set_of_node_refresh = node_record_list.u.node_record_refresh;
  5144. while (set_of_node_refresh)
  5145. {
  5146. node_id = set_of_node_refresh->value.node_id;
  5147. pNodeRecord = &set_of_node_refresh->value.node_record;
  5148. AddNodeVersion(node_id, pNodeRecord);
  5149. set_of_node_refresh = set_of_node_refresh->next;
  5150. }
  5151. break;
  5152. case node_record_update_chosen:
  5153. set_of_node_update = node_record_list.u.node_record_update;
  5154. while (set_of_node_update)
  5155. {
  5156. node_id = set_of_node_update->value.node_id;
  5157. switch(set_of_node_update->value.node_update.choice)
  5158. {
  5159. case node_remove_record_chosen:
  5160. m_NodeVersionList2.Remove(node_id);
  5161. break;
  5162. case node_add_record_chosen:
  5163. pNodeRecord = &set_of_node_update->value.node_update.u.node_add_record;
  5164. AddNodeVersion(node_id, pNodeRecord);
  5165. break;
  5166. }
  5167. set_of_node_update = set_of_node_update->next;
  5168. }
  5169. break;
  5170. }
  5171. return rc;
  5172. }
  5173. BOOL CConf::HasNM2xNode(void)
  5174. {
  5175. DWORD dwVer;
  5176. m_NodeVersionList2.Reset();
  5177. while (NULL != (dwVer = m_NodeVersionList2.Iterate()))
  5178. {
  5179. if (dwVer < 0x0404)
  5180. return TRUE;
  5181. }
  5182. return FALSE;
  5183. }
  5184. DWORD WINAPI T120_GetNodeVersion(GCCConfID ConfId, GCCNodeID NodeId)
  5185. {
  5186. CConf *pConf = g_pGCCController->GetConfObject(ConfId);
  5187. DWORD version;
  5188. if (pConf)
  5189. {
  5190. version = pConf->GetNodeVersion(NodeId);
  5191. return version;
  5192. }
  5193. return 0;
  5194. }
  5195.