File: interactor.c

package info (click to toggle)
putty 0.83-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 13,216 kB
  • sloc: ansic: 148,476; python: 8,466; perl: 1,830; makefile: 128; sh: 117
file content (119 lines) | stat: -rw-r--r-- 3,697 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
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;
}