Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'proxy/interactor.c')
-rw-r--r--proxy/interactor.c119
1 files changed, 119 insertions, 0 deletions
diff --git a/proxy/interactor.c b/proxy/interactor.c
new file mode 100644
index 00000000..d069d226
--- /dev/null
+++ b/proxy/interactor.c
@@ -0,0 +1,119 @@
+/*
+ * 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;
+}