interactor.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Centralised functions for the Interactor trait.
  3. */
  4. #include "putty.h"
  5. Seat *interactor_borrow_seat(Interactor *itr)
  6. {
  7. Seat *clientseat = interactor_get_seat(itr);
  8. if (!clientseat)
  9. return NULL;
  10. /* If the client has already had its Seat borrowed, then look
  11. * through the existing TempSeat to find the underlying one. */
  12. if (is_tempseat(clientseat))
  13. return tempseat_get_real(clientseat);
  14. /* Otherwise, make a new TempSeat and give that to the client. */
  15. Seat *tempseat = tempseat_new(clientseat);
  16. interactor_set_seat(itr, tempseat);
  17. return clientseat;
  18. }
  19. static Interactor *interactor_toplevel(Interactor *itr, unsigned *level_out)
  20. {
  21. /*
  22. * Find the Interactor at the top of the chain, so that all the
  23. * Interactors in a stack can share that one's last-to-talk field.
  24. * Also, count how far we had to go to get to it, to put in the
  25. * message.
  26. */
  27. Interactor *itr_top = itr;
  28. unsigned level = 0;
  29. while (itr_top->parent) {
  30. itr_top = itr_top->parent;
  31. level++;
  32. }
  33. if (level_out)
  34. *level_out = level;
  35. return itr_top;
  36. }
  37. void interactor_return_seat(Interactor *itr)
  38. {
  39. Seat *tempseat = interactor_get_seat(itr);
  40. if (!is_tempseat(tempseat))
  41. return; /* no-op */
  42. /*
  43. * We're about to hand this seat back to the parent Interactor to
  44. * do its own thing with. It will typically expect to start in the
  45. * same state as if the seat had never been borrowed, i.e. in the
  46. * starting trust state.
  47. *
  48. * However, this may be overridden by the tempseat_flush call.
  49. */
  50. Seat *realseat = tempseat_get_real(tempseat);
  51. seat_set_trust_status(realseat, true);
  52. tempseat_flush(tempseat);
  53. interactor_set_seat(itr, realseat);
  54. tempseat_free(tempseat);
  55. /*
  56. * If we have a parent Interactor, and anyone has ever called
  57. * interactor_announce, then all Interactors from now on will
  58. * announce themselves even if they have nothing to say.
  59. */
  60. Interactor *itr_top = interactor_toplevel(itr, NULL);
  61. if (itr_top->last_to_talk)
  62. interactor_announce(itr);
  63. }
  64. InteractionReadySeat interactor_announce(Interactor *itr)
  65. {
  66. Seat *seat = interactor_get_seat(itr);
  67. assert(!is_tempseat(seat) &&
  68. "Shouldn't call announce when someone else is using our seat");
  69. InteractionReadySeat iseat;
  70. iseat.seat = seat;
  71. unsigned level;
  72. Interactor *itr_top = interactor_toplevel(itr, &level);
  73. /*
  74. * Generally, we should announce ourself if the previous
  75. * Interactor that said anything was not us. That includes if
  76. * there was no previous Interactor to talk (i.e. if we're the
  77. * first to say anything) - *except* that the primary Interactor
  78. * doesn't need to announce itself, if no proxy has intervened
  79. * before it.
  80. */
  81. bool need_announcement = (itr_top->last_to_talk != itr);
  82. if (!itr->parent && !itr_top->last_to_talk)
  83. need_announcement = false;
  84. if (need_announcement) {
  85. const char *prefix = "";
  86. if (itr_top->last_to_talk != NULL)
  87. seat_antispoof_msg(iseat, ""); /* leave a separating blank line */
  88. char *desc = interactor_description(itr);
  89. char *adjective = (level == 0 ? dupstr("primary") :
  90. level == 1 ? dupstr("proxy") :
  91. dupprintf("proxy^%u", level));
  92. char *msg = dupprintf("%sMaking %s %s", prefix, adjective, desc);
  93. sfree(adjective);
  94. sfree(desc);
  95. seat_antispoof_msg(iseat, msg);
  96. sfree(msg);
  97. itr_top->last_to_talk = itr;
  98. }
  99. return iseat;
  100. }