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.

2109 lines
55 KiB

  1. #include "precomp.h"
  2. #include "fsdiag.h"
  3. DEBUG_FILEZONE(ZONE_T120_MCSNC);
  4. /*
  5. * token.cpp
  6. *
  7. * Copyright (c) 1993 - 1995 by DataBeam Corporation, Lexington, KY
  8. *
  9. * Abstract:
  10. * This is the implementation file for the Token class. It contains all
  11. * code necessary to implement tokens as defined in the MCS specification.
  12. *
  13. * Whenever a user allocates a token (by grabbing or inhibiting it), one
  14. * of these objects is created (if domain parameters allow it). This
  15. * object then handles all requests related to that token ID. It also
  16. * issues confirms back to the originators of those requests.
  17. *
  18. * This class includes code to maintain a list of user IDs that
  19. * correspond to the current "owners" of the token. A user is said to
  20. * own a token if it has it grabbed or inhibited. This code implements
  21. * the rules concerning who can grab or inhibit tokens at any given
  22. * time (which is affected by current state).
  23. *
  24. * This class also contains the code that allows a current grabber of
  25. * the token to give it away to another user in the domain.
  26. *
  27. * This class also includes code to merge itself upward during a domain
  28. * merge operation.
  29. *
  30. * Private Instance Variables:
  31. * Token_ID
  32. * This is the token ID for the token that this object represents.
  33. * m_pDomain
  34. * This is a pointer to the local provider (the domain that owns this
  35. * token). This field is used when a command is issued on behalf of
  36. * this provider.
  37. * m_pConnToTopProvider
  38. * This is the top provider of the current domain.
  39. * m_pChannelList2
  40. * This is the channel list that is maintained by the domain. It is
  41. * used by this class to perform validation of user IDs.
  42. * m_pAttachmentList
  43. * This is the attachment list that is maintained by the domain. It is
  44. * used by this class to determine what users are locally attached,
  45. * when it becomes necessary to send certain indications.
  46. * Token_State
  47. * This contains the current state of the token, which will be one of
  48. * the following: available; grabbed; inhibited; giving; or given.
  49. * m_uidGrabber
  50. * This is the user that current has the token grabbed. This variable
  51. * is only valid in the grabbed and giving states.
  52. * m_InhibitorList
  53. * This is a list of users that have the token inhibited. This
  54. * list is only valid when the token is in the inhibited state.
  55. * m_uidRecipient
  56. * This is the user to whom the token is being given. This variable
  57. * is only valid in the giving or given states.
  58. *
  59. * Private Member Functions:
  60. * ValidateUserID
  61. * This function is used to verify that a specified user is valid in
  62. * the sub-tree of the local provider.
  63. * GetUserAttachment
  64. * This function is used to determine which attachment leads to a
  65. * particular attachment.
  66. * IssueTokenReleaseIndication
  67. * This function is used to issue a token release indication to a
  68. * specified user. It first checks to see if the user is locally
  69. * attached, and if so, it sends the indication.
  70. * BuildAttachmentList
  71. * This function is used to build a list of unique attachments to
  72. * send please indications to.
  73. *
  74. * Caveats:
  75. * None.
  76. *
  77. * Author:
  78. * James P. Galvin, Jr.
  79. */
  80. /*
  81. * External Interfaces
  82. */
  83. #include "token.h"
  84. /*
  85. * Token ()
  86. *
  87. * Public
  88. *
  89. * Functional Description:
  90. * This is the constructor for the token class. It does nothing more than
  91. * set the initial states of instance variables.
  92. */
  93. Token::Token (
  94. TokenID token_id,
  95. PDomain local_provider,
  96. PConnection top_provider,
  97. CChannelList2 *channel_list,
  98. CAttachmentList *attachment_list)
  99. :
  100. m_InhibitorList(),
  101. Token_ID(token_id),
  102. m_pDomain(local_provider),
  103. m_pConnToTopProvider(top_provider),
  104. m_pChannelList2(channel_list),
  105. m_pAttachmentList(attachment_list),
  106. Token_State(TOKEN_AVAILABLE)
  107. {
  108. /*
  109. * Save all parameters in their associated instance variables for later
  110. * use.
  111. */
  112. /*
  113. * Mark the token as available for use.
  114. */
  115. }
  116. /*
  117. * Token ()
  118. *
  119. * Public
  120. *
  121. * Functional Description:
  122. * This is an alternate constructor for the token class. It is used when
  123. * creating a token during a merge operation. It accepts a current state
  124. * as well as a list of current owners as parameters.
  125. */
  126. Token::Token (
  127. TokenID token_id,
  128. PDomain local_provider,
  129. PConnection top_provider,
  130. CChannelList2 *channel_list,
  131. CAttachmentList *attachment_list,
  132. TokenState token_state,
  133. UserID grabber,
  134. CUidList *inhibitor_list,
  135. UserID recipient)
  136. :
  137. m_InhibitorList(),
  138. Token_ID(token_id),
  139. m_pDomain(local_provider),
  140. m_pConnToTopProvider(top_provider),
  141. m_pChannelList2(channel_list),
  142. m_pAttachmentList(attachment_list),
  143. Token_State(token_state)
  144. {
  145. UserID uid;
  146. /*
  147. * Save all parameters in their associated instance variables for later
  148. * use.
  149. */
  150. /*
  151. * Indicate the current state of the token (as passed in).
  152. */
  153. /*
  154. * Depending on token state, copy the pertinent information into local
  155. * instance variables.
  156. */
  157. switch (Token_State)
  158. {
  159. case TOKEN_AVAILABLE:
  160. break;
  161. case TOKEN_GRABBED:
  162. m_uidGrabber = grabber;
  163. break;
  164. case TOKEN_INHIBITED:
  165. {
  166. /*
  167. * Add all user IDs in the inhibitor list to the local
  168. * inhibitor list.
  169. */
  170. inhibitor_list->Reset();
  171. while (NULL != (uid = inhibitor_list->Iterate()))
  172. {
  173. m_InhibitorList.Append(uid);
  174. }
  175. }
  176. break;
  177. case TOKEN_GIVING:
  178. m_uidGrabber = grabber;
  179. m_uidRecipient = recipient;
  180. break;
  181. case TOKEN_GIVEN:
  182. m_uidRecipient = recipient;
  183. break;
  184. }
  185. }
  186. /*
  187. * ~Token ()
  188. *
  189. * Public
  190. *
  191. * Functional Description:
  192. * This is the token destructor. It iterates through its current owner
  193. * list, issuing TokenReleaseIndications to any owners that correspond
  194. * to locally attached users.
  195. */
  196. Token::~Token ()
  197. {
  198. /*
  199. * Depending on the current state of the token, release resources and
  200. * issue release indications to all owners.
  201. */
  202. switch (Token_State)
  203. {
  204. case TOKEN_AVAILABLE:
  205. break;
  206. case TOKEN_GRABBED:
  207. /*
  208. * Send a release indication to the grabber, if it is locally
  209. * attached.
  210. */
  211. IssueTokenReleaseIndication (m_uidGrabber);
  212. break;
  213. case TOKEN_INHIBITED:
  214. {
  215. UserID uid;
  216. /*
  217. * Iterate through the current inhibitor list, to make sure
  218. * that everyone is properly informed of the demise of this
  219. * token.
  220. */
  221. m_InhibitorList.Reset();
  222. while (NULL != (uid = m_InhibitorList.Iterate()))
  223. {
  224. IssueTokenReleaseIndication(uid);
  225. }
  226. }
  227. break;
  228. case TOKEN_GIVING:
  229. /*
  230. * Send a release indication to the grabber, if it is locally
  231. * attached.
  232. */
  233. IssueTokenReleaseIndication (m_uidGrabber);
  234. /*
  235. * Send a release indication to the recipient, if it is locally
  236. * attached. Note that this will not be sent in the case where
  237. * the grabber and the recipient are one and the same. This
  238. * prevents the sending of two release indications to the same
  239. * user for the same token.
  240. */
  241. if (m_uidGrabber != m_uidRecipient)
  242. IssueTokenReleaseIndication (m_uidRecipient);
  243. break;
  244. case TOKEN_GIVEN:
  245. /*
  246. * Send a release indication to the recipient, if it is locally
  247. * attached.
  248. */
  249. IssueTokenReleaseIndication (m_uidRecipient);
  250. break;
  251. }
  252. }
  253. /*
  254. * BOOL IsValid ()
  255. *
  256. * Public
  257. *
  258. * Functional Description:
  259. * This function checks the validity of each of its owners. It then
  260. * returns TRUE if there are any valid owners left. FALSE otherwise.
  261. */
  262. BOOL Token::IsValid ()
  263. {
  264. BOOL valid;
  265. /*
  266. * We must check for the validity of this token. How this is checked for
  267. * is a function of token state. So switch on the state.
  268. */
  269. switch (Token_State)
  270. {
  271. case TOKEN_AVAILABLE:
  272. break;
  273. case TOKEN_GRABBED:
  274. /*
  275. * When a token is grabbed, the grabber must be in the sub-tree
  276. * of the current provider. If this is not true, then mark the
  277. * token as available (which will cause it to be deleted).
  278. */
  279. if (ValidateUserID (m_uidGrabber) == FALSE)
  280. Token_State = TOKEN_AVAILABLE;
  281. break;
  282. case TOKEN_INHIBITED:
  283. {
  284. UserID uid;
  285. CUidList deletion_list;
  286. /*
  287. * Iterate through the current inhibitor list of this token,
  288. * checking to make sure that each user is still valid. Each
  289. * one that is not will be put into a deletion list (it is
  290. * invalid to remove items from a list while using an iterator
  291. * on the list).
  292. */
  293. m_InhibitorList.Reset();
  294. while (NULL != (uid = m_InhibitorList.Iterate()))
  295. {
  296. if (ValidateUserID(uid) == FALSE)
  297. deletion_list.Append(uid);
  298. }
  299. /*
  300. * Iterate through the deletion list that was built above,
  301. * removing each contained user from the token's inhibitor
  302. * list. These correspond to users that have detached from the
  303. * domain for one reason or another.
  304. */
  305. deletion_list.Reset();
  306. while (NULL != (uid = deletion_list.Iterate()))
  307. {
  308. m_InhibitorList.Remove(uid);
  309. }
  310. }
  311. /*
  312. * Check to see if there are any inhibitors left. If not, then
  313. * we must change the state of the token to available (which will
  314. * cause it to be deleted).
  315. */
  316. if (m_InhibitorList.IsEmpty())
  317. Token_State = TOKEN_AVAILABLE;
  318. break;
  319. case TOKEN_GIVING:
  320. /*
  321. * When a token is in the giving state, the recipient must be in
  322. * the sub-tree of the current provider. If it is not, then the
  323. * token MUST change state. The state it changes to depends on
  324. * whether or not the grabber is in the sub-tree of the current
  325. * provider.
  326. */
  327. if (ValidateUserID (m_uidRecipient) == FALSE)
  328. {
  329. /*
  330. * The recipient of the token is gone. Check to see if the
  331. * grabber is in the sub-tree of this provider.
  332. */
  333. if (ValidateUserID (m_uidGrabber) == FALSE)
  334. {
  335. /*
  336. * The grabber is not in the sub-tree of this provider,
  337. * meaning that the token is no longer valid.
  338. */
  339. Token_State = TOKEN_AVAILABLE;
  340. }
  341. else
  342. {
  343. /*
  344. * The grabber is in the sub-tree of this provider, so the
  345. * token state will transition back to grabbed.
  346. */
  347. Token_State = TOKEN_GRABBED;
  348. /*
  349. * If this is the top provider, it is necessary to issue a
  350. * give confirm to the grabber telling it that the give
  351. * failed.
  352. */
  353. if (m_pConnToTopProvider == NULL)
  354. {
  355. /*
  356. * Find out what attachment leads to the current
  357. * grabber of the token, and issue the appropriate
  358. * token give confirm.
  359. */
  360. CAttachment *pAtt = GetUserAttachment(m_uidGrabber);
  361. if (pAtt)
  362. {
  363. pAtt->TokenGiveConfirm(RESULT_NO_SUCH_USER, m_uidGrabber, Token_ID,
  364. TOKEN_SELF_GRABBED);
  365. }
  366. }
  367. }
  368. }
  369. break;
  370. case TOKEN_GIVEN:
  371. /*
  372. * When a token is in the given state, the recipient must be in
  373. * the sub-tree of the current provider. If it is not, then the
  374. * token is no longer valid, and should transition to the
  375. * available state.
  376. */
  377. if (ValidateUserID (m_uidRecipient) == FALSE)
  378. Token_State = TOKEN_AVAILABLE;
  379. break;
  380. }
  381. /*
  382. * Check to see if the token is still in use. If it is marked as
  383. * available, then it is not, and we will return FALSE.
  384. */
  385. if (Token_State != TOKEN_AVAILABLE)
  386. valid = TRUE;
  387. else
  388. valid = FALSE;
  389. return (valid);
  390. }
  391. /*
  392. * Void IssueMergeRequest ()
  393. *
  394. * Public
  395. *
  396. * Functional Description:
  397. * This function tells the token object to pack its state into a merge
  398. * request and send it to the specified provider.
  399. */
  400. Void Token::IssueMergeRequest ()
  401. {
  402. TokenAttributes merge_token;
  403. CTokenAttributesList merge_token_list;
  404. CTokenIDList purge_token_list;
  405. if (m_pConnToTopProvider != NULL)
  406. {
  407. /*
  408. * Check the state to make sure that the token really is in use. If
  409. * the state is set to available, then do not issue a merge request.
  410. */
  411. if (Token_State != TOKEN_AVAILABLE)
  412. {
  413. /*
  414. * Fill in a token attributes structure to represent the state of
  415. * this token. Then put it into the merge token list in
  416. * preparation for issuing the merge request.
  417. */
  418. merge_token.token_state = Token_State;
  419. switch (Token_State)
  420. {
  421. case TOKEN_GRABBED:
  422. merge_token.u.grabbed_token_attributes.token_id = Token_ID;
  423. merge_token.u.grabbed_token_attributes.grabber = m_uidGrabber;
  424. break;
  425. case TOKEN_INHIBITED:
  426. merge_token.u.inhibited_token_attributes.token_id =
  427. Token_ID;
  428. merge_token.u.inhibited_token_attributes.inhibitors =
  429. &m_InhibitorList;
  430. break;
  431. case TOKEN_GIVING:
  432. merge_token.u.giving_token_attributes.token_id = Token_ID;
  433. merge_token.u.giving_token_attributes.grabber = m_uidGrabber;
  434. merge_token.u.giving_token_attributes.recipient = m_uidRecipient;
  435. break;
  436. case TOKEN_GIVEN:
  437. merge_token.u.given_token_attributes.token_id = Token_ID;
  438. merge_token.u.given_token_attributes.recipient = m_uidRecipient;
  439. break;
  440. }
  441. merge_token_list.Append(&merge_token);
  442. /*
  443. * Send the resulting merge request to the indicated provider.
  444. */
  445. m_pConnToTopProvider->MergeTokensRequest(&merge_token_list, &purge_token_list);
  446. }
  447. else
  448. {
  449. /*
  450. * Report that the token is not in use, but do NOT send a merge
  451. * request.
  452. */
  453. TRACE_OUT(("Token::IssueMergeRequest: token not in use"));
  454. }
  455. }
  456. }
  457. /*
  458. * Void TokenGrabRequest ()
  459. *
  460. * Public
  461. *
  462. * Functional Description:
  463. * This function is called when a user tries to grab a token. The request
  464. * will either succeed or fail depending on the current state of the token.
  465. * Either way, a confirm will be sent to the user originating the request.
  466. */
  467. Void Token::TokenGrabRequest (
  468. CAttachment *pOrigAtt,
  469. UserID uidInitiator,
  470. TokenID)
  471. {
  472. Result result;
  473. TokenStatus token_status;
  474. /*
  475. * Check to see if this provider is the Top Provider. If so, then process
  476. * this request here. Otherwise, forward the request upward.
  477. */
  478. if (IsTopProvider())
  479. {
  480. /*
  481. * Determine what state we are, which greatly affects how we process
  482. * the request.
  483. */
  484. switch (Token_State)
  485. {
  486. case TOKEN_AVAILABLE:
  487. /*
  488. * Since the token is available, the request automatically
  489. * succeeds. Change the state to grabbed, and mark the
  490. * initiator as the grabber.
  491. */
  492. Token_State = TOKEN_GRABBED;
  493. m_uidGrabber = uidInitiator;
  494. result = RESULT_SUCCESSFUL;
  495. token_status = TOKEN_SELF_GRABBED;
  496. break;
  497. case TOKEN_GRABBED:
  498. /*
  499. * If the token is already grabbed, then we must fail the
  500. * request. However, we need to determine if the token is
  501. * grabbed by the same user who is currently requesting it, or
  502. * another user.
  503. */
  504. result = RESULT_TOKEN_NOT_AVAILABLE;
  505. if (uidInitiator == m_uidGrabber)
  506. token_status = TOKEN_SELF_GRABBED;
  507. else
  508. token_status = TOKEN_OTHER_GRABBED;
  509. break;
  510. case TOKEN_INHIBITED:
  511. /*
  512. * If the token is inhibited, this request can still succeed if
  513. * the only inhibitor is the user that is attempting to grab
  514. * the token. Check to see if this is the case.
  515. */
  516. if (m_InhibitorList.Find(uidInitiator))
  517. {
  518. if (m_InhibitorList.GetCount() == 1)
  519. {
  520. /*
  521. * The user attempting to grab the token is the only
  522. * inhibitor, so convert the state to grabbed.
  523. */
  524. Token_State = TOKEN_GRABBED;
  525. m_uidGrabber = uidInitiator;
  526. m_InhibitorList.Clear();
  527. result = RESULT_SUCCESSFUL;
  528. token_status = TOKEN_SELF_GRABBED;
  529. }
  530. else
  531. {
  532. /*
  533. * The token is inhibited by at least one other user,
  534. * so the grab request must fail.
  535. */
  536. result = RESULT_TOKEN_NOT_AVAILABLE;
  537. token_status = TOKEN_SELF_INHIBITED;
  538. }
  539. }
  540. else
  541. {
  542. /*
  543. * The token is not inhibited by the requestor, so it must
  544. * be inhibited by someone else.
  545. */
  546. result = RESULT_TOKEN_NOT_AVAILABLE;
  547. token_status = TOKEN_OTHER_INHIBITED;
  548. }
  549. break;
  550. case TOKEN_GIVING:
  551. /*
  552. * If the token is in the process of being given from one to
  553. * another, then a grab request must fail. All we need to
  554. * figure out is the proper token status to report.
  555. */
  556. result = RESULT_TOKEN_NOT_AVAILABLE;
  557. if (uidInitiator == m_uidRecipient)
  558. token_status = TOKEN_SELF_RECIPIENT;
  559. else if (uidInitiator == m_uidGrabber)
  560. token_status = TOKEN_SELF_GIVING;
  561. else
  562. token_status = TOKEN_OTHER_GIVING;
  563. break;
  564. case TOKEN_GIVEN:
  565. /*
  566. * If the token is in the process of being given from one to
  567. * another, then a grab request must fail. All we need to
  568. * figure out is the proper token status to report.
  569. */
  570. result = RESULT_TOKEN_NOT_AVAILABLE;
  571. if (uidInitiator == m_uidRecipient)
  572. token_status = TOKEN_SELF_RECIPIENT;
  573. else
  574. token_status = TOKEN_OTHER_GIVING;
  575. break;
  576. }
  577. /*
  578. * Issue the token grab confirm to the initiating user.
  579. */
  580. pOrigAtt->TokenGrabConfirm(result, uidInitiator, Token_ID, token_status);
  581. }
  582. else
  583. {
  584. /*
  585. * Forward this request upward towards the Top Provider.
  586. */
  587. TRACE_OUT(("Token::TokenGrabRequest: forwarding request to Top Provider"));
  588. m_pConnToTopProvider->TokenGrabRequest(uidInitiator, Token_ID);
  589. }
  590. }
  591. /*
  592. * Void TokenGrabConfirm ()
  593. *
  594. * Public
  595. *
  596. * Functional Description:
  597. * This function is called as a part of sending a response to a user for
  598. * a previous request. It tells the user the result of the request.
  599. */
  600. Void Token::TokenGrabConfirm (
  601. Result result,
  602. UserID uidInitiator,
  603. TokenID,
  604. TokenStatus token_status)
  605. {
  606. /*
  607. * Make sure that the initiator ID is valid, since we must forward this
  608. * confirm in the direction of that user. If it is not valid, ignore
  609. * this confirm.
  610. */
  611. if (ValidateUserID(uidInitiator))
  612. {
  613. /*
  614. * Check to see if this request was successful.
  615. */
  616. if (result == RESULT_SUCCESSFUL)
  617. {
  618. /*
  619. * Force this token to conform to the results of this confirm.
  620. */
  621. Token_State = TOKEN_GRABBED;
  622. m_uidGrabber = uidInitiator;
  623. m_InhibitorList.Clear();
  624. }
  625. /*
  626. * Determine what attachment leads to the initiator, and forward the
  627. * confirm in that direction.
  628. */
  629. CAttachment *pAtt = GetUserAttachment(uidInitiator);
  630. if (pAtt)
  631. {
  632. pAtt->TokenGrabConfirm(result, uidInitiator, Token_ID, token_status);
  633. }
  634. }
  635. else
  636. {
  637. /*
  638. * The initiator is not in the sub-tree of this provider. So ignore
  639. * this confirm.
  640. */
  641. ERROR_OUT(("Token::TokenGrabConfirm: invalid initiator ID"));
  642. }
  643. }
  644. /*
  645. * Void TokenInhibitRequest ()
  646. *
  647. * Public
  648. *
  649. * Functional Description:
  650. * This function is called when a user tries to inhibit a token. The
  651. * request will either succeed or fail depending on the current state of
  652. * the token. Either way, a confirm will be sent to the user originating
  653. * the request.
  654. */
  655. Void Token::TokenInhibitRequest (
  656. CAttachment *pOrigAtt,
  657. UserID uidInitiator,
  658. TokenID)
  659. {
  660. Result result;
  661. TokenStatus token_status;
  662. /*
  663. * Check to see if this is the Top Provider.
  664. */
  665. if (IsTopProvider())
  666. {
  667. /*
  668. * Determine what state we are, which greatly affects how we process
  669. * the request.
  670. */
  671. switch (Token_State)
  672. {
  673. case TOKEN_AVAILABLE:
  674. /*
  675. * Since the token is available, the request automatically
  676. * succeeds. Set the token state to inhibited, and add the
  677. * initiator to the list of inhibitors.
  678. */
  679. Token_State = TOKEN_INHIBITED;
  680. m_InhibitorList.Append(uidInitiator);
  681. result = RESULT_SUCCESSFUL;
  682. token_status = TOKEN_SELF_INHIBITED;
  683. break;
  684. case TOKEN_GRABBED:
  685. /*
  686. * If the token is grabbed, this request can still succeed if
  687. * the grabber is the user that is attempting to inhibit the
  688. * token. Check to see if this is the case.
  689. */
  690. if (uidInitiator == m_uidGrabber)
  691. {
  692. /*
  693. * The current grabber is attempting to convert the state
  694. * of the token to inhibited. This is valid, so set the
  695. * state appropriately.
  696. */
  697. Token_State = TOKEN_INHIBITED;
  698. m_InhibitorList.Append(uidInitiator);
  699. result = RESULT_SUCCESSFUL;
  700. token_status = TOKEN_SELF_INHIBITED;
  701. }
  702. else
  703. {
  704. /*
  705. * The token is grabbed by someone else, so the inhibit
  706. * request must fail.
  707. */
  708. result = RESULT_TOKEN_NOT_AVAILABLE;
  709. token_status = TOKEN_OTHER_GRABBED;
  710. }
  711. break;
  712. case TOKEN_INHIBITED:
  713. /*
  714. * The token is already inhibited, but this is okay. Add this
  715. * user to the list of inhibitors (if it is not already there).
  716. */
  717. if (m_InhibitorList.Find(uidInitiator) == FALSE)
  718. m_InhibitorList.Append(uidInitiator);
  719. result = RESULT_SUCCESSFUL;
  720. token_status = TOKEN_SELF_INHIBITED;
  721. break;
  722. case TOKEN_GIVING:
  723. /*
  724. * If the token is in the process of being given from one to
  725. * another, then an inhibit request must fail. All we need to
  726. * figure out is the proper token status to report.
  727. */
  728. result = RESULT_TOKEN_NOT_AVAILABLE;
  729. if (uidInitiator == m_uidRecipient)
  730. token_status = TOKEN_SELF_RECIPIENT;
  731. else if (uidInitiator == m_uidGrabber)
  732. token_status = TOKEN_SELF_GIVING;
  733. else
  734. token_status = TOKEN_OTHER_GIVING;
  735. break;
  736. case TOKEN_GIVEN:
  737. /*
  738. * If the token is in the process of being given from one to
  739. * another, then an inhibit request must fail. All we need to
  740. * figure out is the proper token status to report.
  741. */
  742. result = RESULT_TOKEN_NOT_AVAILABLE;
  743. if (uidInitiator == m_uidRecipient)
  744. token_status = TOKEN_SELF_RECIPIENT;
  745. else
  746. token_status = TOKEN_OTHER_GIVING;
  747. break;
  748. }
  749. /*
  750. * If the originator is NULL, then this inhibit request is happening as
  751. * part of a merge operation, in which case we do NOT want to send a
  752. * token inhibit confirm. Otherwise we do send one.
  753. */
  754. if (pOrigAtt != NULL)
  755. {
  756. pOrigAtt->TokenInhibitConfirm(result, uidInitiator, Token_ID, token_status);
  757. }
  758. }
  759. else
  760. {
  761. /*
  762. * Forward the request toward the top provider.
  763. */
  764. TRACE_OUT(("Token::TokenInhibitRequest: forwarding request to Top Provider"));
  765. m_pConnToTopProvider->TokenInhibitRequest(uidInitiator, Token_ID);
  766. }
  767. }
  768. /*
  769. * Void TokenInhibitConfirm ()
  770. *
  771. * Public
  772. *
  773. * Functional Description:
  774. * This function is called as a part of sending a response to a user for
  775. * a previous request. It tells the user the result of the request.
  776. */
  777. Void Token::TokenInhibitConfirm (
  778. Result result,
  779. UserID uidInitiator,
  780. TokenID,
  781. TokenStatus token_status)
  782. {
  783. /*
  784. * Make sure that the initiator ID is valid, since we must forward this
  785. * confirm in the direction of that user. If it is not valid, ignore
  786. * this confirm.
  787. */
  788. if (ValidateUserID (uidInitiator) )
  789. {
  790. /*
  791. * Check to see if this request was successful.
  792. */
  793. if (result == RESULT_SUCCESSFUL)
  794. {
  795. /*
  796. * Force this token to conform to the results of this confirm.
  797. */
  798. Token_State = TOKEN_INHIBITED;
  799. if (m_InhibitorList.Find(uidInitiator) == FALSE)
  800. m_InhibitorList.Append(uidInitiator);
  801. }
  802. /*
  803. * Determine what attachment leads to the initiator, and issue the
  804. * token confirm in that direction.
  805. */
  806. CAttachment *pAtt = GetUserAttachment(uidInitiator);
  807. if (pAtt)
  808. {
  809. pAtt->TokenInhibitConfirm(result, uidInitiator, Token_ID, token_status);
  810. }
  811. }
  812. else
  813. {
  814. /*
  815. * The initiator is not in the sub-tree of this provider. So ignore
  816. * this confirm.
  817. */
  818. ERROR_OUT(("Token::TokenInhibitConfirm: invalid initiator ID"));
  819. }
  820. }
  821. /*
  822. * Void TokenGiveRequest ()
  823. *
  824. * Public
  825. *
  826. * Functional Description:
  827. * This function is called when one user asks to give a token to another
  828. * user.
  829. */
  830. Void Token::TokenGiveRequest (
  831. CAttachment *pOrigAtt,
  832. PTokenGiveRecord pTokenGiveRec)
  833. {
  834. Result result;
  835. TokenStatus token_status;
  836. /*
  837. * Check to see if this provider is the Top Provider. If so, then process
  838. * this request here. Otherwise, forward the request upward.
  839. */
  840. if (m_pConnToTopProvider == NULL)
  841. {
  842. UserID uidInitiator = pTokenGiveRec->uidInitiator;
  843. UserID receiver_id = pTokenGiveRec->receiver_id;
  844. /*
  845. * Determine what state we are, which greatly affects how we process
  846. * the request.
  847. */
  848. switch (Token_State)
  849. {
  850. case TOKEN_AVAILABLE:
  851. /*
  852. * The token is not in use, and therefore cannot be given by
  853. * anyone to anyone. So fail this request.
  854. */
  855. result = RESULT_TOKEN_NOT_POSSESSED;
  856. token_status = TOKEN_NOT_IN_USE;
  857. break;
  858. case TOKEN_GRABBED:
  859. /*
  860. * Check to see if the requestor really is the grabber of this
  861. * token.
  862. */
  863. if (uidInitiator == m_uidGrabber)
  864. {
  865. /*
  866. * Check to see if the intended recipient is a valid user
  867. * in the domain.
  868. */
  869. if (ValidateUserID (receiver_id) )
  870. {
  871. /*
  872. * Everything checks out. Set the result to success
  873. * to disable transmission of the give confirm below.
  874. * Change the state of the token to giving, and
  875. * save the ID of the intended recipient. Then issue
  876. * the give indication toward the recipient.
  877. */
  878. result = RESULT_SUCCESSFUL;
  879. Token_State = TOKEN_GIVING;
  880. m_uidRecipient = receiver_id;
  881. CAttachment *pAtt = GetUserAttachment(receiver_id);
  882. ASSERT (Token_ID == pTokenGiveRec->token_id);
  883. if (pAtt)
  884. {
  885. pAtt->TokenGiveIndication(pTokenGiveRec);
  886. }
  887. }
  888. else
  889. {
  890. /*
  891. * The recipient does not exist in the domain, so
  892. * fail the request.
  893. */
  894. result = RESULT_NO_SUCH_USER;
  895. token_status = TOKEN_SELF_GRABBED;
  896. }
  897. }
  898. else
  899. {
  900. /*
  901. * The requestor does not own the token, so the request
  902. * must fail.
  903. */
  904. result = RESULT_TOKEN_NOT_POSSESSED;
  905. token_status = TOKEN_OTHER_GRABBED;
  906. }
  907. break;
  908. case TOKEN_INHIBITED:
  909. /*
  910. * Inhibited tokens cannot be given by anyone to anyone. So
  911. * fail this request with the proper status.
  912. */
  913. result = RESULT_TOKEN_NOT_POSSESSED;
  914. if (m_InhibitorList.Find(uidInitiator) )
  915. token_status = TOKEN_SELF_INHIBITED;
  916. else
  917. token_status = TOKEN_OTHER_INHIBITED;
  918. break;
  919. case TOKEN_GIVING:
  920. /*
  921. * This token is already in the process of being given. So
  922. * this request must fail.
  923. */
  924. result = RESULT_TOKEN_NOT_POSSESSED;
  925. if (uidInitiator == m_uidRecipient)
  926. token_status = TOKEN_SELF_RECIPIENT;
  927. else if (uidInitiator == m_uidGrabber)
  928. token_status = TOKEN_SELF_GIVING;
  929. else
  930. token_status = TOKEN_OTHER_GIVING;
  931. break;
  932. case TOKEN_GIVEN:
  933. /*
  934. * This token is already in the process of being given. So
  935. * this request must fail.
  936. */
  937. result = RESULT_TOKEN_NOT_POSSESSED;
  938. if (uidInitiator == m_uidRecipient)
  939. token_status = TOKEN_SELF_RECIPIENT;
  940. else
  941. token_status = TOKEN_OTHER_GIVING;
  942. break;
  943. }
  944. /*
  945. * If necessary, issue a token give confirm to the initiating user.
  946. */
  947. if (result != RESULT_SUCCESSFUL)
  948. {
  949. pOrigAtt->TokenGiveConfirm(result, uidInitiator, Token_ID, token_status);
  950. }
  951. }
  952. else
  953. {
  954. /*
  955. * Forward this request upward towards the Top Provider.
  956. */
  957. TRACE_OUT(("Token::TokenGiveRequest: forwarding request to Top Provider"));
  958. ASSERT (Token_ID == pTokenGiveRec->token_id);
  959. m_pConnToTopProvider->TokenGiveRequest(pTokenGiveRec);
  960. }
  961. }
  962. /*
  963. * Void TokenGiveIndication ()
  964. *
  965. * Public
  966. *
  967. * Functional Description:
  968. * This function is called in order to deliver a message to a user that
  969. * another user is trying to give them a token.
  970. */
  971. Void Token::TokenGiveIndication (
  972. PTokenGiveRecord pTokenGiveRec)
  973. {
  974. UserID receiver_id;
  975. receiver_id = pTokenGiveRec->receiver_id;
  976. /*
  977. * Make sure that the receiver ID is valid, since we must forward this
  978. * indication in the direction of that user. If it is not valid, ignore
  979. * this indication.
  980. */
  981. if (ValidateUserID (receiver_id) )
  982. {
  983. /*
  984. * Force this token to conform to the state implied by this indication.
  985. */
  986. Token_State = TOKEN_GIVING;
  987. m_uidGrabber = pTokenGiveRec->uidInitiator;
  988. m_InhibitorList.Clear();
  989. m_uidRecipient = receiver_id;
  990. /*
  991. * Determine what attachment leads to the recipient, and forward the
  992. * indication in that direction.
  993. */
  994. CAttachment *pAtt = GetUserAttachment(receiver_id);
  995. ASSERT (Token_ID == pTokenGiveRec->token_id);
  996. if (pAtt)
  997. {
  998. pAtt->TokenGiveIndication(pTokenGiveRec);
  999. }
  1000. }
  1001. else
  1002. {
  1003. /*
  1004. * The recipient is not in the sub-tree of this provider. So ignore
  1005. * this indication.
  1006. */
  1007. ERROR_OUT(("Token::TokenGiveIndication: invalid receiver ID"));
  1008. }
  1009. }
  1010. /*
  1011. * Void TokenGiveResponse ()
  1012. *
  1013. * Public
  1014. *
  1015. * Functional Description:
  1016. * This function is called when a potential recipient decides whether or
  1017. * not to accept an offered token.
  1018. */
  1019. Void Token::TokenGiveResponse (
  1020. Result result,
  1021. UserID receiver_id,
  1022. TokenID)
  1023. {
  1024. UserID uidInitiator;
  1025. TokenStatus token_status;
  1026. /*
  1027. * Process the response according to the current state of this token.
  1028. */
  1029. switch (Token_State)
  1030. {
  1031. case TOKEN_AVAILABLE:
  1032. case TOKEN_GRABBED:
  1033. case TOKEN_INHIBITED:
  1034. /*
  1035. * The token is not in the process of being given to anyone, so
  1036. * this response must be ignored.
  1037. */
  1038. break;
  1039. case TOKEN_GIVING:
  1040. /*
  1041. * The token is being given to someone. Check to see if this is
  1042. * the proper recipient. If not, don't do anything.
  1043. */
  1044. if (receiver_id == m_uidRecipient)
  1045. {
  1046. /*
  1047. * Save the ID of the initiator, for use in issuing a give
  1048. * confirm (if necessary).
  1049. */
  1050. uidInitiator = m_uidGrabber;
  1051. /*
  1052. * Check to see if the token was accepted. A result of
  1053. * anything but successful would indicate that it was not.
  1054. */
  1055. if (result == RESULT_SUCCESSFUL)
  1056. {
  1057. /*
  1058. * The token was accepted by the intended recipient.
  1059. * Change the state of the token to being grabbed by the
  1060. * receiver.
  1061. */
  1062. Token_State = TOKEN_GRABBED;
  1063. m_uidGrabber = receiver_id;
  1064. }
  1065. else
  1066. {
  1067. /*
  1068. * The token was not accepted. It must either revert to
  1069. * being grabbed by the donor, or deleted, depending on
  1070. * whether or not the donor is in the sub-tree of this
  1071. * provider.
  1072. */
  1073. if (ValidateUserID(uidInitiator))
  1074. {
  1075. /*
  1076. * The donor is in the sub-tree of this provider, so
  1077. * change the state of the token back to grabbed.
  1078. */
  1079. Token_State = TOKEN_GRABBED;
  1080. }
  1081. else
  1082. {
  1083. /*
  1084. * The donor is not in the sub-tree of this provider,
  1085. * so the token will be marked as available (which
  1086. * will cause it to be deleted).
  1087. */
  1088. Token_State = TOKEN_AVAILABLE;
  1089. }
  1090. }
  1091. /*
  1092. * Check to see if this is the Top Provider.
  1093. */
  1094. if (m_pConnToTopProvider == NULL)
  1095. {
  1096. /*
  1097. * If the donor is still a valid user in the domain, a
  1098. * token give confirm must be issued in its direction.
  1099. */
  1100. if (ValidateUserID(uidInitiator))
  1101. {
  1102. /*
  1103. * Determine which attachment leads to the donor, and
  1104. * issue the token give confirm.
  1105. */
  1106. if (uidInitiator == m_uidGrabber)
  1107. token_status = TOKEN_SELF_GRABBED;
  1108. else
  1109. token_status = TOKEN_OTHER_GRABBED;
  1110. CAttachment *pAtt = GetUserAttachment(uidInitiator);
  1111. if (pAtt)
  1112. {
  1113. pAtt->TokenGiveConfirm(result, uidInitiator, Token_ID, token_status);
  1114. }
  1115. }
  1116. }
  1117. else
  1118. {
  1119. /*
  1120. * If this is not the Top Provider, then the valid give
  1121. * response must be forwarded to the Top Provider.
  1122. */
  1123. m_pConnToTopProvider->TokenGiveResponse(result, receiver_id, Token_ID);
  1124. }
  1125. }
  1126. break;
  1127. case TOKEN_GIVEN:
  1128. /*
  1129. * The token is being given to someone. Check to see if this is
  1130. * the proper recipient. If not, don't do anything.
  1131. */
  1132. if (receiver_id == m_uidRecipient)
  1133. {
  1134. /*
  1135. * Check to see if the token was accepted. A result of
  1136. * anything but successful would indicate that it was not.
  1137. */
  1138. if (result == RESULT_SUCCESSFUL)
  1139. {
  1140. /*
  1141. * The token was accepted by the intended recipient.
  1142. * Change the state of the token to being grabbed by the
  1143. * receiver.
  1144. */
  1145. Token_State = TOKEN_GRABBED;
  1146. m_uidGrabber = receiver_id;
  1147. }
  1148. else
  1149. {
  1150. /*
  1151. * The token was not accepted. Since the donor has
  1152. * already relinquished control of the token, the token
  1153. * will marked as available (which will cause it to be
  1154. * deleted).
  1155. */
  1156. Token_State = TOKEN_AVAILABLE;
  1157. }
  1158. /*
  1159. * Check to see if this is the Top Provider.
  1160. */
  1161. if (m_pConnToTopProvider != NULL)
  1162. {
  1163. /*
  1164. * If this is not the Top Provider, then the valid give
  1165. * response must be forwarded to the Top Provider.
  1166. */
  1167. m_pConnToTopProvider->TokenGiveResponse(result, receiver_id, Token_ID);
  1168. }
  1169. }
  1170. break;
  1171. }
  1172. }
  1173. /*
  1174. * Void TokenGiveConfirm ()
  1175. *
  1176. * Public
  1177. *
  1178. * Functional Description:
  1179. * This function is called as a potential giver of a token is told whether
  1180. * or not the token was successfully given to the intended recipient.
  1181. */
  1182. Void Token::TokenGiveConfirm (
  1183. Result result,
  1184. UserID uidInitiator,
  1185. TokenID,
  1186. TokenStatus token_status)
  1187. {
  1188. /*
  1189. * Make sure that the initiator ID is valid, since we must forward this
  1190. * confirm in the direction of that user. If it is not valid, ignore
  1191. * this confirm.
  1192. */
  1193. if (ValidateUserID(uidInitiator))
  1194. {
  1195. /*
  1196. * The token should be in the grabbed state, or else this confirm
  1197. * was generated in error.
  1198. */
  1199. if (Token_State == TOKEN_GRABBED)
  1200. {
  1201. /*
  1202. * Check to see if this request was successful.
  1203. */
  1204. if (result == RESULT_SUCCESSFUL)
  1205. {
  1206. /*
  1207. * If this token is marked as being owned by the initiator of
  1208. * the give, but the status indicates that the token is now
  1209. * owned by someone else (as a result of the successful give),
  1210. * then release the token.*
  1211. */
  1212. if ((uidInitiator == m_uidGrabber) &&
  1213. (token_status == TOKEN_OTHER_GRABBED))
  1214. Token_State = TOKEN_AVAILABLE;
  1215. }
  1216. }
  1217. else
  1218. {
  1219. /*
  1220. * The token is in an invalid state. Report the error, but do
  1221. * not change the state of the token.
  1222. */
  1223. ERROR_OUT(("Token::TokenGiveConfirm: invalid token state"));
  1224. }
  1225. /*
  1226. * Determine what attachment leads to the initiator, and forward the
  1227. * confirm in that direction.
  1228. */
  1229. CAttachment *pAtt = GetUserAttachment(uidInitiator);
  1230. if (pAtt)
  1231. {
  1232. pAtt->TokenGiveConfirm(result, uidInitiator, Token_ID, token_status);
  1233. }
  1234. }
  1235. else
  1236. {
  1237. /*
  1238. * The initiator is not in the sub-tree of this provider. So ignore
  1239. * this confirm.
  1240. */
  1241. ERROR_OUT(("Token::TokenGiveConfirm: invalid initiator ID"));
  1242. }
  1243. }
  1244. /*
  1245. * Void TokenPleaseRequest ()
  1246. *
  1247. * Public
  1248. *
  1249. * Functional Description:
  1250. * This function is called when a user wishes to ask all current owners
  1251. * of a token to relinquish their ownership.
  1252. */
  1253. Void Token::TokenPleaseRequest (
  1254. UserID uidInitiator,
  1255. TokenID)
  1256. {
  1257. CUidList please_indication_list;
  1258. /*
  1259. * Check to see if this is the Top Provider.
  1260. */
  1261. if (IsTopProvider())
  1262. {
  1263. CAttachmentList attachment_list;
  1264. CAttachment *pAtt;
  1265. /*
  1266. * Determine the state of the token, to determine who to send the
  1267. * please indication to. Each state will place the appropriate user
  1268. * IDs in the please indication list.
  1269. */
  1270. switch (Token_State)
  1271. {
  1272. case TOKEN_AVAILABLE:
  1273. break;
  1274. case TOKEN_GRABBED:
  1275. /*
  1276. * Put the grabber into the list.
  1277. */
  1278. please_indication_list.Append(m_uidGrabber);
  1279. break;
  1280. case TOKEN_INHIBITED:
  1281. {
  1282. UserID uid;
  1283. /*
  1284. * Put all current inhibitors into the list.
  1285. */
  1286. m_InhibitorList.Reset();
  1287. while (NULL != (uid = m_InhibitorList.Iterate()))
  1288. {
  1289. please_indication_list.Append(uid);
  1290. }
  1291. }
  1292. break;
  1293. case TOKEN_GIVING:
  1294. /*
  1295. * Put the grabber into the list. And if the recipient is
  1296. * different from the grabber, put it in as well. Remember
  1297. * that it is valid for someone to give a token to themselves.
  1298. */
  1299. please_indication_list.Append(m_uidGrabber);
  1300. if (m_uidGrabber != m_uidRecipient)
  1301. please_indication_list.Append(m_uidRecipient);
  1302. break;
  1303. case TOKEN_GIVEN:
  1304. /*
  1305. * Put the recipient into the list.
  1306. */
  1307. please_indication_list.Append(m_uidRecipient);
  1308. break;
  1309. }
  1310. /*
  1311. * Build lists of unique attachments that lead to the users in the
  1312. * please indication list (built above).
  1313. */
  1314. BuildAttachmentList (&please_indication_list, &attachment_list);
  1315. /*
  1316. * Iterate through the newly created attachment list, issuing token
  1317. * please indications to all attachments contained therein.
  1318. */
  1319. attachment_list.Reset();
  1320. while (NULL != (pAtt = attachment_list.Iterate()))
  1321. {
  1322. pAtt->TokenPleaseIndication(uidInitiator, Token_ID);
  1323. }
  1324. }
  1325. else
  1326. {
  1327. /*
  1328. * Forward the request toward the top provider.
  1329. */
  1330. TRACE_OUT(("Token::TokenPleaseRequest: forwarding request to Top Provider"));
  1331. m_pConnToTopProvider->TokenPleaseRequest(uidInitiator, Token_ID);
  1332. }
  1333. }
  1334. /*
  1335. * Void TokenPleaseIndication ()
  1336. *
  1337. * Public
  1338. *
  1339. * Functional Description:
  1340. * This function is called in order to deliver a message to all current
  1341. * owners of a token that someone else wishes to own the token.
  1342. */
  1343. Void Token::TokenPleaseIndication (
  1344. UserID uidInitiator,
  1345. TokenID)
  1346. {
  1347. CUidList please_indication_list;
  1348. CAttachmentList attachment_list;
  1349. CAttachment *pAtt;
  1350. /*
  1351. * Determine the state of the token, to determine who to forward the
  1352. * please indication to. Each state will place the appropriate user
  1353. * IDs in the please indication list.
  1354. */
  1355. switch (Token_State)
  1356. {
  1357. case TOKEN_AVAILABLE:
  1358. break;
  1359. case TOKEN_GRABBED:
  1360. /*
  1361. * Put the grabber into the list.
  1362. */
  1363. please_indication_list.Append(m_uidGrabber);
  1364. break;
  1365. case TOKEN_INHIBITED:
  1366. {
  1367. UserID uid;
  1368. /*
  1369. * Put all current inhibitors into the list.
  1370. */
  1371. m_InhibitorList.Reset();
  1372. while (NULL != (uid = m_InhibitorList.Iterate()))
  1373. {
  1374. please_indication_list.Append(uid);
  1375. }
  1376. }
  1377. break;
  1378. case TOKEN_GIVING:
  1379. /*
  1380. * Put the grabber into the list. And if the recipient is
  1381. * different from the grabber, put it in as well. Remember
  1382. * that it is valid for someone to give a token to themselves.
  1383. */
  1384. please_indication_list.Append(m_uidGrabber);
  1385. if (m_uidGrabber != m_uidRecipient)
  1386. please_indication_list.Append(m_uidRecipient);
  1387. break;
  1388. case TOKEN_GIVEN:
  1389. /*
  1390. * Put the recipient into the list.
  1391. */
  1392. please_indication_list.Append(m_uidRecipient);
  1393. break;
  1394. }
  1395. /*
  1396. * Build lists of unique attachments that lead to the users in the
  1397. * please indication list (built above).
  1398. */
  1399. BuildAttachmentList (&please_indication_list, &attachment_list);
  1400. /*
  1401. * Iterate through the newly created attachment list, issuing token
  1402. * please indications to all attachments contained therein.
  1403. */
  1404. attachment_list.Reset();
  1405. while (NULL != (pAtt = attachment_list.Iterate()))
  1406. {
  1407. pAtt->TokenPleaseIndication(uidInitiator, Token_ID);
  1408. }
  1409. }
  1410. /*
  1411. * Void TokenReleaseRequest ()
  1412. *
  1413. * Public
  1414. *
  1415. * Functional Description:
  1416. * This function is called when a user wished to release a token. If the
  1417. * requesting user really is an owner of the token, the request will
  1418. * succeed. Otherwise it will fail. Either way, an appropriate token
  1419. * release confirm will be issued.
  1420. */
  1421. Void Token::TokenReleaseRequest (
  1422. CAttachment *pAtt,
  1423. UserID uidInitiator,
  1424. TokenID)
  1425. {
  1426. Result result;
  1427. TokenStatus token_status;
  1428. /*
  1429. * Check to see if this is the Top Provider.
  1430. */
  1431. if (IsTopProvider())
  1432. {
  1433. /*
  1434. * Determine the current state of the token before proceeding.
  1435. */
  1436. switch (Token_State)
  1437. {
  1438. case TOKEN_AVAILABLE:
  1439. /*
  1440. * If the token is available, then the requestor cannot be an
  1441. * owner. This means that the request must fail.
  1442. */
  1443. result = RESULT_TOKEN_NOT_POSSESSED;
  1444. token_status = TOKEN_NOT_IN_USE;
  1445. break;
  1446. case TOKEN_GRABBED:
  1447. /*
  1448. * The token is in the grabbed state. See if the requesting
  1449. * user is the one who has it grabbed.
  1450. */
  1451. if (uidInitiator == m_uidGrabber)
  1452. {
  1453. /*
  1454. * The current grabber of the token wishes to release it.
  1455. * Set the state back to available, and send the
  1456. * appropriate token release confirm.
  1457. */
  1458. Token_State = TOKEN_AVAILABLE;
  1459. result = RESULT_SUCCESSFUL;
  1460. token_status = TOKEN_NOT_IN_USE;
  1461. }
  1462. else
  1463. {
  1464. /*
  1465. * Someone is trying to release someone elses token. This
  1466. * request must fail. Send the appropriate token release
  1467. * confirm.
  1468. */
  1469. result = RESULT_TOKEN_NOT_POSSESSED;
  1470. token_status = TOKEN_OTHER_GRABBED;
  1471. }
  1472. break;
  1473. case TOKEN_INHIBITED:
  1474. /*
  1475. * The token is in the inhibited state. See if the requesting
  1476. * user is one of the inhibitors.
  1477. */
  1478. if (m_InhibitorList.Remove(uidInitiator))
  1479. {
  1480. /*
  1481. * The user is an inhibitor. Remove the user from the
  1482. * list. Then check to see if this has resulted in an
  1483. * "ownerless" token.
  1484. */
  1485. if (m_InhibitorList.IsEmpty())
  1486. {
  1487. /*
  1488. * The token has no other inhibitors. Return the token
  1489. * to the available state, and issue the appropriate
  1490. * token release confirm.
  1491. */
  1492. Token_State = TOKEN_AVAILABLE;
  1493. result = RESULT_SUCCESSFUL;
  1494. token_status = TOKEN_NOT_IN_USE;
  1495. }
  1496. else
  1497. {
  1498. /*
  1499. * There are still other inhibitors of the token.
  1500. * Simply issue the appropriate token release confirm.
  1501. */
  1502. result = RESULT_SUCCESSFUL;
  1503. token_status = TOKEN_OTHER_INHIBITED;
  1504. }
  1505. }
  1506. else
  1507. {
  1508. /*
  1509. * The user attempting to release the token is not one of
  1510. * the inhibitors. Therefore the request must fail. Issue
  1511. * the appropriate token release indication.
  1512. */
  1513. result = RESULT_TOKEN_NOT_POSSESSED;
  1514. token_status = TOKEN_OTHER_INHIBITED;
  1515. }
  1516. break;
  1517. case TOKEN_GIVING:
  1518. /*
  1519. * See if the requestor is the current owner of the token.
  1520. */
  1521. if (uidInitiator == m_uidGrabber)
  1522. {
  1523. /*
  1524. * The token must transition to the given state. This
  1525. * state indicates that if the recipient rejects the offer
  1526. * or detaches, the token will be freed instead of
  1527. * returning to the grabbed state. Issue the appropriate
  1528. * release confirm.
  1529. */
  1530. Token_State = TOKEN_GIVEN;
  1531. result = RESULT_SUCCESSFUL;
  1532. token_status = TOKEN_OTHER_GIVING;
  1533. }
  1534. else
  1535. {
  1536. /*
  1537. * If the requestor is not the current owner, then this
  1538. * request must fail. We first need to determine the
  1539. * proper token status, and then issue the confirm.
  1540. */
  1541. result = RESULT_TOKEN_NOT_POSSESSED;
  1542. if (uidInitiator == m_uidRecipient)
  1543. token_status = TOKEN_SELF_RECIPIENT;
  1544. else
  1545. token_status = TOKEN_OTHER_GIVING;
  1546. }
  1547. break;
  1548. case TOKEN_GIVEN:
  1549. /*
  1550. * When the token is in the given state, there is no true
  1551. * owner (only a pending owner). This request must therefore
  1552. * fail. We first need to determine the proper token status,
  1553. * and then issue the confirm.
  1554. */
  1555. result = RESULT_TOKEN_NOT_POSSESSED;
  1556. if (uidInitiator == m_uidRecipient)
  1557. token_status = TOKEN_SELF_RECIPIENT;
  1558. else
  1559. token_status = TOKEN_OTHER_GIVING;
  1560. break;
  1561. }
  1562. /*
  1563. * Issue the token release confirm to the initiator.
  1564. */
  1565. pAtt->TokenReleaseConfirm(result, uidInitiator, Token_ID, token_status);
  1566. }
  1567. else
  1568. {
  1569. /*
  1570. * Forward the request toward the top provider.
  1571. */
  1572. TRACE_OUT(("Token::TokenReleaseRequest: forwarding request to Top Provider"));
  1573. m_pConnToTopProvider->TokenReleaseRequest(uidInitiator, Token_ID);
  1574. }
  1575. }
  1576. /*
  1577. * Void TokenReleaseConfirm ()
  1578. *
  1579. * Public
  1580. *
  1581. * Functional Description:
  1582. * This function is called as a part of sending a response to a user for
  1583. * a previous request. It tells the user the result of the request.
  1584. */
  1585. Void Token::TokenReleaseConfirm (
  1586. Result result,
  1587. UserID uidInitiator,
  1588. TokenID,
  1589. TokenStatus token_status)
  1590. {
  1591. /*
  1592. * Make sure that the initiator ID is valid, since we must forward this
  1593. * confirm in the direction of that user. If it is not valid, ignore
  1594. * this confirm.
  1595. */
  1596. if (ValidateUserID (uidInitiator) )
  1597. {
  1598. /*
  1599. * Check to see if this request was successful.
  1600. */
  1601. if (result == RESULT_SUCCESSFUL)
  1602. {
  1603. /*
  1604. * Process the confirm according to current state.
  1605. */
  1606. switch (Token_State)
  1607. {
  1608. case TOKEN_AVAILABLE:
  1609. break;
  1610. case TOKEN_GRABBED:
  1611. /*
  1612. * If the grabber has released the token, then is becomes
  1613. * available.
  1614. */
  1615. if (uidInitiator == m_uidGrabber)
  1616. Token_State = TOKEN_AVAILABLE;
  1617. break;
  1618. case TOKEN_INHIBITED:
  1619. /*
  1620. * If an inhibitor releases the token, then remove it from
  1621. * the list. If there are no more entries in the list,
  1622. * then the token becomes available.
  1623. */
  1624. if (m_InhibitorList.Remove(uidInitiator))
  1625. {
  1626. if (m_InhibitorList.IsEmpty())
  1627. Token_State = TOKEN_AVAILABLE;
  1628. }
  1629. break;
  1630. case TOKEN_GIVING:
  1631. /*
  1632. * If the grabber releases the token, then it transitions
  1633. * to an intermediate state. This state indicates that
  1634. * if the recipient rejects the token, it will be freed
  1635. * instead of returning to the grabbed state.
  1636. */
  1637. if (uidInitiator == m_uidGrabber)
  1638. Token_State = TOKEN_GIVEN;
  1639. break;
  1640. case TOKEN_GIVEN:
  1641. break;
  1642. }
  1643. }
  1644. /*
  1645. * Determine what attachment leads to the initiator, and forward the
  1646. * confirm in that direction.
  1647. */
  1648. CAttachment *pAtt = GetUserAttachment(uidInitiator);
  1649. if (pAtt)
  1650. {
  1651. pAtt->TokenReleaseConfirm(result, uidInitiator, Token_ID, token_status);
  1652. }
  1653. }
  1654. else
  1655. {
  1656. /*
  1657. * The initiator is not in the sub-tree of this provider. So ignore
  1658. * this confirm.
  1659. */
  1660. ERROR_OUT(("Token::TokenReleaseConfirm: invalid initiator ID"));
  1661. }
  1662. }
  1663. /*
  1664. * Void TokenTestRequest ()
  1665. *
  1666. * Public
  1667. *
  1668. * Functional Description:
  1669. * This function is called when a user wishes to test the current state
  1670. * of a token. The only action is to issue a token test confirm containing
  1671. * the state information.
  1672. */
  1673. Void Token::TokenTestRequest (
  1674. CAttachment *pAtt,
  1675. UserID uidInitiator,
  1676. TokenID)
  1677. {
  1678. TokenStatus token_status;
  1679. /*
  1680. * Check to see if this is the Top Provider.
  1681. */
  1682. if (m_pConnToTopProvider == NULL)
  1683. {
  1684. /*
  1685. * Determine the state of the token before proceeding.
  1686. */
  1687. switch (Token_State)
  1688. {
  1689. case TOKEN_AVAILABLE:
  1690. /*
  1691. * The token is not in use.
  1692. */
  1693. token_status = TOKEN_NOT_IN_USE;
  1694. break;
  1695. case TOKEN_GRABBED:
  1696. /*
  1697. * The token is grabbed. See if the originating user is the
  1698. * grabber. If so, return the state as self grabbed. If not,
  1699. * return the state as other grabbed.
  1700. */
  1701. if (uidInitiator == m_uidGrabber)
  1702. token_status = TOKEN_SELF_GRABBED;
  1703. else
  1704. token_status = TOKEN_OTHER_GRABBED;
  1705. break;
  1706. case TOKEN_INHIBITED:
  1707. /*
  1708. * The token is inhibited. See if the originating user is one
  1709. * of the inhibitors. If so, return the state as self
  1710. * inhibited. If not, return the state as other inhibited.
  1711. */
  1712. if (m_InhibitorList.Find(uidInitiator))
  1713. token_status = TOKEN_SELF_INHIBITED;
  1714. else
  1715. token_status = TOKEN_OTHER_INHIBITED;
  1716. break;
  1717. case TOKEN_GIVING:
  1718. /*
  1719. * The token is being given from one user to another. See if
  1720. * the requestor is one of the users involved.
  1721. */
  1722. if (uidInitiator == m_uidRecipient)
  1723. token_status = TOKEN_SELF_RECIPIENT;
  1724. else if (uidInitiator == m_uidGrabber)
  1725. token_status = TOKEN_SELF_GIVING;
  1726. else
  1727. token_status = TOKEN_OTHER_GIVING;
  1728. break;
  1729. case TOKEN_GIVEN:
  1730. /*
  1731. * The token has been given from one user to another. See if
  1732. * the requestor is the receiver.
  1733. */
  1734. if (uidInitiator == m_uidRecipient)
  1735. token_status = TOKEN_SELF_RECIPIENT;
  1736. else
  1737. token_status = TOKEN_OTHER_GIVING;
  1738. break;
  1739. }
  1740. /*
  1741. * Issue the test confirm with the appropriate status information.
  1742. */
  1743. pAtt->TokenTestConfirm(uidInitiator, Token_ID, token_status);
  1744. }
  1745. else
  1746. {
  1747. /*
  1748. * Forward the request toward the top provider.
  1749. */
  1750. TRACE_OUT(("Token::TokenTestRequest: forwarding request to Top Provider"));
  1751. m_pConnToTopProvider->TokenTestRequest(uidInitiator, Token_ID);
  1752. }
  1753. }
  1754. /*
  1755. * Void TokenTestConfirm ()
  1756. *
  1757. * Public
  1758. *
  1759. * Functional Description:
  1760. * This function is called as a part of sending a response to a user for
  1761. * a previous request. It tells the user the result of the request.
  1762. */
  1763. Void Token::TokenTestConfirm (
  1764. UserID uidInitiator,
  1765. TokenID,
  1766. TokenStatus token_status)
  1767. {
  1768. /*
  1769. * Make sure that the initiator ID is valid, since we must forward this
  1770. * confirm in the direction of that user. If it is not valid, ignore
  1771. * this confirm.
  1772. */
  1773. if (ValidateUserID(uidInitiator))
  1774. {
  1775. /*
  1776. * Determine what attachment leads to the initiator, and forward the
  1777. * confirm in that direction.
  1778. */
  1779. CAttachment *pAtt = GetUserAttachment(uidInitiator);
  1780. if (pAtt)
  1781. {
  1782. pAtt->TokenTestConfirm(uidInitiator, Token_ID, token_status);
  1783. }
  1784. }
  1785. else
  1786. {
  1787. /*
  1788. * The initiator is not in the sub-tree of this provider. So ignore
  1789. * this confirm.
  1790. */
  1791. ERROR_OUT(("Token::TokenReleaseConfirm: invalid initiator ID"));
  1792. }
  1793. }
  1794. /*
  1795. * BOOL ValidateUserID ()
  1796. *
  1797. * Private
  1798. *
  1799. * Functional Description:
  1800. * This function is used to verify the existence of the specified user
  1801. * in the sub-tree of this provider.
  1802. *
  1803. * Formal Parameters:
  1804. * user_id (i)
  1805. * This is the ID of the user the caller wishes to validate.
  1806. *
  1807. * Return Value:
  1808. * TRUE if the user is valid. FALSE otherwise.
  1809. *
  1810. * Side Effects:
  1811. * None.
  1812. */
  1813. BOOL Token::ValidateUserID (
  1814. UserID user_id)
  1815. {
  1816. /*
  1817. * Initialize the return value to FALSE, indicating that if any of the
  1818. * following checks fail, the ID does NOT refer to a valid user ID.
  1819. */
  1820. BOOL valid=FALSE;
  1821. PChannel channel;
  1822. /*
  1823. * First check to see if the user ID is in the channel list at all. This
  1824. * prevents an attempt to read an invalid entry from the dictionary.
  1825. */
  1826. if (NULL != (channel = m_pChannelList2->Find(user_id)))
  1827. {
  1828. /*
  1829. * We know that the ID is in the dictionary, but we don't know for sure
  1830. * whether or not it is a user ID channel. So check this. If it is a
  1831. * user channel, then set the valid flag to TRUE.
  1832. */
  1833. if (channel->GetChannelType () == USER_CHANNEL)
  1834. valid = TRUE;
  1835. }
  1836. return (valid);
  1837. }
  1838. /*
  1839. * PCommandTarget GetUserAttachment ()
  1840. *
  1841. * Private
  1842. *
  1843. * Functional Description:
  1844. * This function returns the attachment which leads to the specified
  1845. * user.
  1846. *
  1847. * Formal Parameters:
  1848. * user_id (i)
  1849. * This is the ID of the user the caller wishes to find the attachment
  1850. * for.
  1851. *
  1852. * Return Value:
  1853. * A pointer to the attachment that leads to the user.
  1854. *
  1855. * Side Effects:
  1856. * None.
  1857. */
  1858. CAttachment *Token::GetUserAttachment (
  1859. UserID user_id)
  1860. {
  1861. PChannel lpChannel;
  1862. /*
  1863. * Read and return a pointer to the attachment that leads to the
  1864. * specified user. Note that this routine does NOT check to see if the
  1865. * user is in the channel list. It assumes that the user is known to
  1866. * be valid BEFORE this routine is called.
  1867. */
  1868. return ((NULL != (lpChannel = m_pChannelList2->Find(user_id))) ?
  1869. lpChannel->GetAttachment() :
  1870. NULL);
  1871. }
  1872. /*
  1873. * Void IssueTokenReleaseIndication ()
  1874. *
  1875. * Private
  1876. *
  1877. * Functional Description:
  1878. * This function is used to issue a token release indication to a
  1879. * particular user. It first check to make sure that the user id valid,
  1880. * and that it is a local user.
  1881. *
  1882. * Formal Parameters:
  1883. * user_id (i)
  1884. * This is the ID of the user the caller wishes to send a token
  1885. * release indication to.
  1886. *
  1887. * Return Value:
  1888. * None.
  1889. *
  1890. * Side Effects:
  1891. * None.
  1892. */
  1893. Void Token::IssueTokenReleaseIndication (
  1894. UserID user_id)
  1895. {
  1896. /*
  1897. * Make sure that the specified user exists in the sub-tree of this
  1898. * provider.
  1899. */
  1900. if (ValidateUserID (user_id) )
  1901. {
  1902. /*
  1903. * Determine which attachment leads to the grabber.
  1904. */
  1905. CAttachment *pAtt = GetUserAttachment(user_id);
  1906. /*
  1907. * Is this attachment a local one? If so, then issue a token
  1908. * release indication to let the user know that the token has
  1909. * been taken away.
  1910. */
  1911. if ( ( pAtt != NULL ) && m_pAttachmentList->Find(pAtt) && pAtt->IsUserAttachment())
  1912. {
  1913. PUser pUser = (PUser) pAtt;
  1914. pUser->TokenReleaseIndication(REASON_TOKEN_PURGED, Token_ID);
  1915. }
  1916. }
  1917. }
  1918. /*
  1919. * Void BuildAttachmentList ()
  1920. *
  1921. * Private
  1922. *
  1923. * Functional Description:
  1924. * This function builds a list of unique attachments out of the list of
  1925. * user IDs that is poassed in. This is done to insure that no given
  1926. * attachment receives more than one indication, even when there are more
  1927. * than one user in the same direction.
  1928. *
  1929. * Formal Parameters:
  1930. * user_id_list (i)
  1931. * This is a list of user IDs that the caller wishes to send a token
  1932. * please indication to.
  1933. * attachment_list (i)
  1934. * This is the list that all unique attachments will be added to.
  1935. *
  1936. * Return Value:
  1937. * None.
  1938. *
  1939. * Side Effects:
  1940. * None.
  1941. */
  1942. Void Token::BuildAttachmentList (
  1943. CUidList *user_id_list,
  1944. CAttachmentList *attachment_list)
  1945. {
  1946. UserID uid;
  1947. /*
  1948. * Loop through the passed in user ID list building a list of unique
  1949. * attachments. This will be used to send indications downward without
  1950. * sending one twice over the same attachment.
  1951. */
  1952. user_id_list->Reset();
  1953. while (NULL != (uid = user_id_list->Iterate()))
  1954. {
  1955. /*
  1956. * Check to see if the user ID refers to a valid user in the sub-tree
  1957. * of this provider.
  1958. */
  1959. if (ValidateUserID(uid))
  1960. {
  1961. /*
  1962. * Determine which attachment leads to the user in question. Then
  1963. * check to see if it is already in the attachment list. If not,
  1964. * then put it there.
  1965. */
  1966. CAttachment *pAtt = GetUserAttachment(uid);
  1967. if (attachment_list->Find(pAtt) == FALSE)
  1968. attachment_list->Append(pAtt);
  1969. }
  1970. else
  1971. {
  1972. /*
  1973. * This user ID does not correspond to a valid user in the sub-tree
  1974. * of this provider. Therefore, discard the ID.
  1975. */
  1976. ERROR_OUT(("Token::BuildAttachmentList: user ID not valid"));
  1977. }
  1978. }
  1979. }