1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00
putty-source/proxy/interactor.c
Simon Tatham 215b9d1775 Actually print announcements of Interactors' identity.
Finally, the payoff from all of this refactoring: now, when a proxy
prompts interactively during connection setup, you get a message in
advance telling you which Interactor is originating the following
messages.

To achieve this, I've arranged to link Interactors together into a
list, so that any Interactor created by a proxy has a 'parent' pointer
pointing to the Interactor its client passed to new_connection().

This allows interactor_announce() to follow the links back up the
chain and count them, so that it knows whether it's a primary
connection, or a proxy, or a proxy-for-a-proxy, or more generally an
nth-order proxy, and can include that in its announcement.

And secondly, once interactor_announce() reaches the top of the chain,
it can use that as a storage location agreed on by all Interactors in
the whole setup, to tell each other which one of them was the last to
do anything interactive. Then, whenever there's a change of
Interactor, a message can be printed to indicate it to the user; and
when the same Interactor does multiple things in succession, you don't
get a slew of pointless messages in between them all.
2021-10-30 18:20:58 +01:00

106 lines
3.2 KiB
C

/*
* 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;
}
void interactor_return_seat(Interactor *itr)
{
Seat *tempseat = interactor_get_seat(itr);
if (!is_tempseat(tempseat))
return; /* no-op */
tempseat_flush(tempseat);
Seat *realseat = tempseat_get_real(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_announce(itr);
/*
* 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.
*/
seat_set_trust_status(realseat, true);
}
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;
/*
* 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++;
}
/*
* 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)
prefix = "\r\n";
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;
}