Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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