123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- /*
- * Centralised functions for the Interactor trait.
- */
- #include "putty.h"
- Seat *interactor_borrow_seat(Interactor *itr)
- {
- Seat *clientseat = interactor_get_seat(itr);
- if (!clientseat)
- return NULL;
- /* If the client has already had its Seat borrowed, then look
- * through the existing TempSeat to find the underlying one. */
- if (is_tempseat(clientseat))
- return tempseat_get_real(clientseat);
- /* Otherwise, make a new TempSeat and give that to the client. */
- Seat *tempseat = tempseat_new(clientseat);
- interactor_set_seat(itr, tempseat);
- return clientseat;
- }
- static Interactor *interactor_toplevel(Interactor *itr, unsigned *level_out)
- {
- /*
- * Find the Interactor at the top of the chain, so that all the
- * Interactors in a stack can share that one's last-to-talk field.
- * Also, count how far we had to go to get to it, to put in the
- * message.
- */
- Interactor *itr_top = itr;
- unsigned level = 0;
- while (itr_top->parent) {
- itr_top = itr_top->parent;
- level++;
- }
- if (level_out)
- *level_out = level;
- return itr_top;
- }
- void interactor_return_seat(Interactor *itr)
- {
- Seat *tempseat = interactor_get_seat(itr);
- if (!is_tempseat(tempseat))
- return; /* no-op */
- /*
- * We're about to hand this seat back to the parent Interactor to
- * do its own thing with. It will typically expect to start in the
- * same state as if the seat had never been borrowed, i.e. in the
- * starting trust state.
- *
- * However, this may be overridden by the tempseat_flush call.
- */
- Seat *realseat = tempseat_get_real(tempseat);
- seat_set_trust_status(realseat, true);
- tempseat_flush(tempseat);
- interactor_set_seat(itr, realseat);
- tempseat_free(tempseat);
- /*
- * If we have a parent Interactor, and anyone has ever called
- * interactor_announce, then all Interactors from now on will
- * announce themselves even if they have nothing to say.
- */
- Interactor *itr_top = interactor_toplevel(itr, NULL);
- if (itr_top->last_to_talk)
- interactor_announce(itr);
- }
- InteractionReadySeat interactor_announce(Interactor *itr)
- {
- Seat *seat = interactor_get_seat(itr);
- assert(!is_tempseat(seat) &&
- "Shouldn't call announce when someone else is using our seat");
- InteractionReadySeat iseat;
- iseat.seat = seat;
- unsigned level;
- Interactor *itr_top = interactor_toplevel(itr, &level);
- /*
- * Generally, we should announce ourself if the previous
- * Interactor that said anything was not us. That includes if
- * there was no previous Interactor to talk (i.e. if we're the
- * first to say anything) - *except* that the primary Interactor
- * doesn't need to announce itself, if no proxy has intervened
- * before it.
- */
- bool need_announcement = (itr_top->last_to_talk != itr);
- if (!itr->parent && !itr_top->last_to_talk)
- need_announcement = false;
- if (need_announcement) {
- const char *prefix = "";
- if (itr_top->last_to_talk != NULL)
- seat_antispoof_msg(iseat, ""); /* leave a separating blank line */
- char *desc = interactor_description(itr);
- char *adjective = (level == 0 ? dupstr("primary") :
- level == 1 ? dupstr("proxy") :
- dupprintf("proxy^%u", level));
- char *msg = dupprintf("%sMaking %s %s", prefix, adjective, desc);
- sfree(adjective);
- sfree(desc);
- seat_antispoof_msg(iseat, msg);
- sfree(msg);
- itr_top->last_to_talk = itr;
- }
- return iseat;
- }
|