interactor.c 4.0 KB

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