source: filezilla/trunk/fuentes/src/putty/windows/winhandl.c @ 130

Last change on this file since 130 was 130, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 20.5 KB
Line 
1/*
2 * winhandl.c: Module to give Windows front ends the general
3 * ability to deal with consoles, pipes, serial ports, or any other
4 * type of data stream accessed through a Windows API HANDLE rather
5 * than a WinSock SOCKET.
6 *
7 * We do this by spawning a subthread to continuously try to read
8 * from the handle. Every time a read successfully returns some
9 * data, the subthread sets an event object which is picked up by
10 * the main thread, and the main thread then sets an event in
11 * return to instruct the subthread to resume reading.
12 *
13 * Output works precisely the other way round, in a second
14 * subthread. The output subthread should not be attempting to
15 * write all the time, because it hasn't always got data _to_
16 * write; so the output thread waits for an event object notifying
17 * it to _attempt_ a write, and then it sets an event in return
18 * when one completes.
19 *
20 * (It's terribly annoying having to spawn a subthread for each
21 * direction of each handle. Technically it isn't necessary for
22 * serial ports, since we could use overlapped I/O within the main
23 * thread and wait directly on the event objects in the OVERLAPPED
24 * structures. However, we can't use this trick for some types of
25 * file handle at all - for some reason Windows restricts use of
26 * OVERLAPPED to files which were opened with the overlapped flag -
27 * and so we must use threads for those. This being the case, it's
28 * simplest just to use threads for everything rather than trying
29 * to keep track of multiple completely separate mechanisms.)
30 */
31
32#include <assert.h>
33
34#include "putty.h"
35
36/* ----------------------------------------------------------------------
37 * Generic definitions.
38 */
39
40/*
41 * Maximum amount of backlog we will allow to build up on an input
42 * handle before we stop reading from it.
43 */
44#define MAX_BACKLOG 32768
45
46struct handle_generic {
47    /*
48     * Initial fields common to both handle_input and handle_output
49     * structures.
50     *
51     * The three HANDLEs are set up at initialisation time and are
52     * thereafter read-only to both main thread and subthread.
53     * `moribund' is only used by the main thread; `done' is
54     * written by the main thread before signalling to the
55     * subthread. `defunct' and `busy' are used only by the main
56     * thread.
57     */
58    HANDLE h;                          /* the handle itself */
59    HANDLE ev_to_main;                 /* event used to signal main thread */
60    HANDLE ev_from_main;               /* event used to signal back to us */
61    int moribund;                      /* are we going to kill this soon? */
62    int done;                          /* request subthread to terminate */
63    int defunct;                       /* has the subthread already gone? */
64    int busy;                          /* operation currently in progress? */
65    void *privdata;                    /* for client to remember who they are */
66};
67
68typedef enum { HT_INPUT, HT_OUTPUT, HT_FOREIGN } HandleType;
69
70/* ----------------------------------------------------------------------
71 * Input threads.
72 */
73
74/*
75 * Data required by an input thread.
76 */
77struct handle_input {
78    /*
79     * Copy of the handle_generic structure.
80     */
81    HANDLE h;                          /* the handle itself */
82    HANDLE ev_to_main;                 /* event used to signal main thread */
83    HANDLE ev_from_main;               /* event used to signal back to us */
84    int moribund;                      /* are we going to kill this soon? */
85    int done;                          /* request subthread to terminate */
86    int defunct;                       /* has the subthread already gone? */
87    int busy;                          /* operation currently in progress? */
88    void *privdata;                    /* for client to remember who they are */
89
90    /*
91     * Data set at initialisation and then read-only.
92     */
93    int flags;
94
95    /*
96     * Data set by the input thread before signalling ev_to_main,
97     * and read by the main thread after receiving that signal.
98     */
99    char buffer[4096];                 /* the data read from the handle */
100    DWORD len;                         /* how much data that was */
101    int readerr;                       /* lets us know about read errors */
102
103    /*
104     * Callback function called by this module when data arrives on
105     * an input handle.
106     */
107    handle_inputfn_t gotdata;
108};
109
110/*
111 * The actual thread procedure for an input thread.
112 */
113static DWORD WINAPI handle_input_threadfunc(void *param)
114{
115    struct handle_input *ctx = (struct handle_input *) param;
116    OVERLAPPED ovl, *povl;
117    HANDLE oev;
118    int readret, readlen, finished;
119
120    if (ctx->flags & HANDLE_FLAG_OVERLAPPED) {
121        povl = &ovl;
122        oev = CreateEvent(NULL, TRUE, FALSE, NULL);
123    } else {
124        povl = NULL;
125    }
126
127    if (ctx->flags & HANDLE_FLAG_UNITBUFFER)
128        readlen = 1;
129    else
130        readlen = sizeof(ctx->buffer);
131
132    while (1) {
133        if (povl) {
134            memset(povl, 0, sizeof(OVERLAPPED));
135            povl->hEvent = oev;
136        }
137        readret = ReadFile(ctx->h, ctx->buffer,readlen, &ctx->len, povl);
138        if (!readret)
139            ctx->readerr = GetLastError();
140        else
141            ctx->readerr = 0;
142        if (povl && !readret && ctx->readerr == ERROR_IO_PENDING) {
143            WaitForSingleObject(povl->hEvent, INFINITE);
144            readret = GetOverlappedResult(ctx->h, povl, &ctx->len, FALSE);
145            if (!readret)
146                ctx->readerr = GetLastError();
147            else
148                ctx->readerr = 0;
149        }
150
151        if (!readret) {
152            /*
153             * Windows apparently sends ERROR_BROKEN_PIPE when a
154             * pipe we're reading from is closed normally from the
155             * writing end. This is ludicrous; if that situation
156             * isn't a natural EOF, _nothing_ is. So if we get that
157             * particular error, we pretend it's EOF.
158             */
159            if (ctx->readerr == ERROR_BROKEN_PIPE)
160                ctx->readerr = 0;
161            ctx->len = 0;
162        }
163
164        if (readret && ctx->len == 0 &&
165            (ctx->flags & HANDLE_FLAG_IGNOREEOF))
166            continue;
167
168        /*
169         * If we just set ctx->len to 0, that means the read operation
170         * has returned end-of-file. Telling that to the main thread
171         * will cause it to set its 'defunct' flag and dispose of the
172         * handle structure at the next opportunity, in which case we
173         * mustn't touch ctx at all after the SetEvent. (Hence we do
174         * even _this_ check before the SetEvent.)
175         */
176        finished = (ctx->len == 0);
177
178        SetEvent(ctx->ev_to_main);
179
180        if (finished)
181            break;
182
183        WaitForSingleObject(ctx->ev_from_main, INFINITE);
184        if (ctx->done) {
185            /*
186             * The main thread has asked us to shut down. Send back an
187             * event indicating that we've done so. Hereafter we must
188             * not touch ctx at all, because the main thread might
189             * have freed it.
190             */
191            SetEvent(ctx->ev_to_main);
192            break;
193        }
194    }
195
196    if (povl)
197        CloseHandle(oev);
198
199    return 0;
200}
201
202/*
203 * This is called after a succcessful read, or from the
204 * `unthrottle' function. It decides whether or not to begin a new
205 * read operation.
206 */
207static void handle_throttle(struct handle_input *ctx, int backlog)
208{
209    if (ctx->defunct)
210        return;
211
212    /*
213     * If there's a read operation already in progress, do nothing:
214     * when that completes, we'll come back here and be in a
215     * position to make a better decision.
216     */
217    if (ctx->busy)
218        return;
219
220    /*
221     * Otherwise, we must decide whether to start a new read based
222     * on the size of the backlog.
223     */
224    if (backlog < MAX_BACKLOG) {
225        SetEvent(ctx->ev_from_main);
226        ctx->busy = TRUE;
227    }
228}
229
230/* ----------------------------------------------------------------------
231 * Output threads.
232 */
233
234/*
235 * Data required by an output thread.
236 */
237struct handle_output {
238    /*
239     * Copy of the handle_generic structure.
240     */
241    HANDLE h;                          /* the handle itself */
242    HANDLE ev_to_main;                 /* event used to signal main thread */
243    HANDLE ev_from_main;               /* event used to signal back to us */
244    int moribund;                      /* are we going to kill this soon? */
245    int done;                          /* request subthread to terminate */
246    int defunct;                       /* has the subthread already gone? */
247    int busy;                          /* operation currently in progress? */
248    void *privdata;                    /* for client to remember who they are */
249
250    /*
251     * Data set at initialisation and then read-only.
252     */
253    int flags;
254
255    /*
256     * Data set by the main thread before signalling ev_from_main,
257     * and read by the input thread after receiving that signal.
258     */
259    char *buffer;                      /* the data to write */
260    DWORD len;                         /* how much data there is */
261
262    /*
263     * Data set by the input thread before signalling ev_to_main,
264     * and read by the main thread after receiving that signal.
265     */
266    DWORD lenwritten;                  /* how much data we actually wrote */
267    int writeerr;                      /* return value from WriteFile */
268
269    /*
270     * Data only ever read or written by the main thread.
271     */
272    bufchain queued_data;              /* data still waiting to be written */
273    enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
274
275    /*
276     * Callback function called when the backlog in the bufchain
277     * drops.
278     */
279    handle_outputfn_t sentdata;
280};
281
282static DWORD WINAPI handle_output_threadfunc(void *param)
283{
284    struct handle_output *ctx = (struct handle_output *) param;
285    OVERLAPPED ovl, *povl;
286    HANDLE oev;
287    int writeret;
288
289    if (ctx->flags & HANDLE_FLAG_OVERLAPPED) {
290        povl = &ovl;
291        oev = CreateEvent(NULL, TRUE, FALSE, NULL);
292    } else {
293        povl = NULL;
294    }
295
296    while (1) {
297        WaitForSingleObject(ctx->ev_from_main, INFINITE);
298        if (ctx->done) {
299            /*
300             * The main thread has asked us to shut down. Send back an
301             * event indicating that we've done so. Hereafter we must
302             * not touch ctx at all, because the main thread might
303             * have freed it.
304             */
305            SetEvent(ctx->ev_to_main);
306            break;
307        }
308        if (povl) {
309            memset(povl, 0, sizeof(OVERLAPPED));
310            povl->hEvent = oev;
311        }
312
313        writeret = WriteFile(ctx->h, ctx->buffer, ctx->len,
314                             &ctx->lenwritten, povl);
315        if (!writeret)
316            ctx->writeerr = GetLastError();
317        else
318            ctx->writeerr = 0;
319        if (povl && !writeret && GetLastError() == ERROR_IO_PENDING) {
320            writeret = GetOverlappedResult(ctx->h, povl,
321                                           &ctx->lenwritten, TRUE);
322            if (!writeret)
323                ctx->writeerr = GetLastError();
324            else
325                ctx->writeerr = 0;
326        }
327
328        SetEvent(ctx->ev_to_main);
329        if (!writeret) {
330            /*
331             * The write operation has suffered an error. Telling that
332             * to the main thread will cause it to set its 'defunct'
333             * flag and dispose of the handle structure at the next
334             * opportunity, so we must not touch ctx at all after
335             * this.
336             */
337            break;
338        }
339    }
340
341    if (povl)
342        CloseHandle(oev);
343
344    return 0;
345}
346
347static void handle_try_output(struct handle_output *ctx)
348{
349    void *senddata;
350    int sendlen;
351
352    if (!ctx->busy && bufchain_size(&ctx->queued_data)) {
353        bufchain_prefix(&ctx->queued_data, &senddata, &sendlen);
354        ctx->buffer = senddata;
355        ctx->len = sendlen;
356        SetEvent(ctx->ev_from_main);
357        ctx->busy = TRUE;
358    } else if (!ctx->busy && bufchain_size(&ctx->queued_data) == 0 &&
359               ctx->outgoingeof == EOF_PENDING) {
360        CloseHandle(ctx->h);
361        ctx->h = INVALID_HANDLE_VALUE;
362        ctx->outgoingeof = EOF_SENT;
363    }
364}
365
366/* ----------------------------------------------------------------------
367 * 'Foreign events'. These are handle structures which just contain a
368 * single event object passed to us by another module such as
369 * winnps.c, so that they can make use of our handle_get_events /
370 * handle_got_event mechanism for communicating with application main
371 * loops.
372 */
373struct handle_foreign {
374    /*
375     * Copy of the handle_generic structure.
376     */
377    HANDLE h;                          /* the handle itself */
378    HANDLE ev_to_main;                 /* event used to signal main thread */
379    HANDLE ev_from_main;               /* event used to signal back to us */
380    int moribund;                      /* are we going to kill this soon? */
381    int done;                          /* request subthread to terminate */
382    int defunct;                       /* has the subthread already gone? */
383    int busy;                          /* operation currently in progress? */
384    void *privdata;                    /* for client to remember who they are */
385
386    /*
387     * Our own data, just consisting of knowledge of who to call back.
388     */
389    void (*callback)(void *);
390    void *ctx;
391};
392
393/* ----------------------------------------------------------------------
394 * Unified code handling both input and output threads.
395 */
396
397struct handle {
398    HandleType type;
399    union {
400        struct handle_generic g;
401        struct handle_input i;
402        struct handle_output o;
403        struct handle_foreign f;
404    } u;
405};
406
407static tree234 *handles_by_evtomain;
408
409static int handle_cmp_evtomain(void *av, void *bv)
410{
411    struct handle *a = (struct handle *)av;
412    struct handle *b = (struct handle *)bv;
413
414    if ((uintptr_t)a->u.g.ev_to_main < (uintptr_t)b->u.g.ev_to_main)
415        return -1;
416    else if ((uintptr_t)a->u.g.ev_to_main > (uintptr_t)b->u.g.ev_to_main)
417        return +1;
418    else
419        return 0;
420}
421
422static int handle_find_evtomain(void *av, void *bv)
423{
424    HANDLE *a = (HANDLE *)av;
425    struct handle *b = (struct handle *)bv;
426
427    if ((uintptr_t)*a < (uintptr_t)b->u.g.ev_to_main)
428        return -1;
429    else if ((uintptr_t)*a > (uintptr_t)b->u.g.ev_to_main)
430        return +1;
431    else
432        return 0;
433}
434
435struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
436                                void *privdata, int flags)
437{
438    struct handle *h = snew(struct handle);
439    DWORD in_threadid; /* required for Win9x */
440
441    h->type = HT_INPUT;
442    h->u.i.h = handle;
443    h->u.i.ev_to_main = CreateEvent(NULL, FALSE, FALSE, NULL);
444    h->u.i.ev_from_main = CreateEvent(NULL, FALSE, FALSE, NULL);
445    h->u.i.gotdata = gotdata;
446    h->u.i.defunct = FALSE;
447    h->u.i.moribund = FALSE;
448    h->u.i.done = FALSE;
449    h->u.i.privdata = privdata;
450    h->u.i.flags = flags;
451
452    if (!handles_by_evtomain)
453        handles_by_evtomain = newtree234(handle_cmp_evtomain);
454    add234(handles_by_evtomain, h);
455
456    CreateThread(NULL, 0, handle_input_threadfunc,
457                 &h->u.i, 0, &in_threadid);
458    h->u.i.busy = TRUE;
459
460    return h;
461}
462
463struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
464                                 void *privdata, int flags)
465{
466    struct handle *h = snew(struct handle);
467    DWORD out_threadid; /* required for Win9x */
468
469    h->type = HT_OUTPUT;
470    h->u.o.h = handle;
471    h->u.o.ev_to_main = CreateEvent(NULL, FALSE, FALSE, NULL);
472    h->u.o.ev_from_main = CreateEvent(NULL, FALSE, FALSE, NULL);
473    h->u.o.busy = FALSE;
474    h->u.o.defunct = FALSE;
475    h->u.o.moribund = FALSE;
476    h->u.o.done = FALSE;
477    h->u.o.privdata = privdata;
478    bufchain_init(&h->u.o.queued_data);
479    h->u.o.outgoingeof = EOF_NO;
480    h->u.o.sentdata = sentdata;
481    h->u.o.flags = flags;
482
483    if (!handles_by_evtomain)
484        handles_by_evtomain = newtree234(handle_cmp_evtomain);
485    add234(handles_by_evtomain, h);
486
487    CreateThread(NULL, 0, handle_output_threadfunc,
488                 &h->u.o, 0, &out_threadid);
489
490    return h;
491}
492
493struct handle *handle_add_foreign_event(HANDLE event,
494                                        void (*callback)(void *), void *ctx)
495{
496    struct handle *h = snew(struct handle);
497
498    h->type = HT_FOREIGN;
499    h->u.f.h = INVALID_HANDLE_VALUE;
500    h->u.f.ev_to_main = event;
501    h->u.f.ev_from_main = INVALID_HANDLE_VALUE;
502    h->u.f.defunct = TRUE;  /* we have no thread in the first place */
503    h->u.f.moribund = FALSE;
504    h->u.f.done = FALSE;
505    h->u.f.privdata = NULL;
506    h->u.f.callback = callback;
507    h->u.f.ctx = ctx;
508    h->u.f.busy = TRUE;
509
510    if (!handles_by_evtomain)
511        handles_by_evtomain = newtree234(handle_cmp_evtomain);
512    add234(handles_by_evtomain, h);
513
514    return h;
515}
516
517int handle_write(struct handle *h, const void *data, int len)
518{
519    assert(h->type == HT_OUTPUT);
520    assert(h->u.o.outgoingeof == EOF_NO);
521    bufchain_add(&h->u.o.queued_data, data, len);
522    handle_try_output(&h->u.o);
523    return bufchain_size(&h->u.o.queued_data);
524}
525
526void handle_write_eof(struct handle *h)
527{
528    /*
529     * This function is called when we want to proactively send an
530     * end-of-file notification on the handle. We can only do this by
531     * actually closing the handle - so never call this on a
532     * bidirectional handle if we're still interested in its incoming
533     * direction!
534     */
535    assert(h->type == HT_OUTPUT);
536    if (!h->u.o.outgoingeof == EOF_NO) {
537        h->u.o.outgoingeof = EOF_PENDING;
538        handle_try_output(&h->u.o);
539    }
540}
541
542HANDLE *handle_get_events(int *nevents)
543{
544    HANDLE *ret;
545    struct handle *h;
546    int i, n, size;
547
548    /*
549     * Go through our tree counting the handle objects currently
550     * engaged in useful activity.
551     */
552    ret = NULL;
553    n = size = 0;
554    if (handles_by_evtomain) {
555        for (i = 0; (h = index234(handles_by_evtomain, i)) != NULL; i++) {
556            if (h->u.g.busy) {
557                if (n >= size) {
558                    size += 32;
559                    ret = sresize(ret, size, HANDLE);
560                }
561                ret[n++] = h->u.g.ev_to_main;
562            }
563        }
564    }
565
566    *nevents = n;
567    return ret;
568}
569
570static void handle_destroy(struct handle *h)
571{
572    if (h->type == HT_OUTPUT)
573        bufchain_clear(&h->u.o.queued_data);
574    CloseHandle(h->u.g.ev_from_main);
575    CloseHandle(h->u.g.ev_to_main);
576    del234(handles_by_evtomain, h);
577    sfree(h);
578}
579
580void handle_free(struct handle *h)
581{
582    assert(h && !h->u.g.moribund);
583    if (h->u.g.busy && h->type != HT_FOREIGN) {
584        /*
585         * If the handle is currently busy, we cannot immediately free
586         * it, because its subthread is in the middle of something.
587         * (Exception: foreign handles don't have a subthread.)
588         *
589         * Instead we must wait until it's finished its current
590         * operation, because otherwise the subthread will write to
591         * invalid memory after we free its context from under it. So
592         * we set the moribund flag, which will be noticed next time
593         * an operation completes.
594         */
595        h->u.g.moribund = TRUE;
596    } else if (h->u.g.defunct) {
597        /*
598         * There isn't even a subthread; we can go straight to
599         * handle_destroy.
600         */
601        handle_destroy(h);
602    } else {
603        /*
604         * The subthread is alive but not busy, so we now signal it
605         * to die. Set the moribund flag to indicate that it will
606         * want destroying after that.
607         */
608        h->u.g.moribund = TRUE;
609        h->u.g.done = TRUE;
610        h->u.g.busy = TRUE;
611        SetEvent(h->u.g.ev_from_main);
612    }
613}
614
615void handle_got_event(HANDLE event)
616{
617    struct handle *h;
618
619    assert(handles_by_evtomain);
620    h = find234(handles_by_evtomain, &event, handle_find_evtomain);
621    if (!h) {
622        /*
623         * This isn't an error condition. If two or more event
624         * objects were signalled during the same select operation,
625         * and processing of the first caused the second handle to
626         * be closed, then it will sometimes happen that we receive
627         * an event notification here for a handle which is already
628         * deceased. In that situation we simply do nothing.
629         */
630        return;
631    }
632
633    if (h->u.g.moribund) {
634        /*
635         * A moribund handle is one which we have either already
636         * signalled to die, or are waiting until its current I/O op
637         * completes to do so. Either way, it's treated as already
638         * dead from the external user's point of view, so we ignore
639         * the actual I/O result. We just signal the thread to die if
640         * we haven't yet done so, or destroy the handle if not.
641         */
642        if (h->u.g.done) {
643            handle_destroy(h);
644        } else {
645            h->u.g.done = TRUE;
646            h->u.g.busy = TRUE;
647            SetEvent(h->u.g.ev_from_main);
648        }
649        return;
650    }
651
652    switch (h->type) {
653        int backlog;
654
655      case HT_INPUT:
656        h->u.i.busy = FALSE;
657
658        /*
659         * A signal on an input handle means data has arrived.
660         */
661        if (h->u.i.len == 0) {
662            /*
663             * EOF, or (nearly equivalently) read error.
664             */
665            h->u.i.defunct = TRUE;
666            h->u.i.gotdata(h, NULL, -h->u.i.readerr);
667        } else {
668            backlog = h->u.i.gotdata(h, h->u.i.buffer, h->u.i.len);
669            handle_throttle(&h->u.i, backlog);
670        }
671        break;
672
673      case HT_OUTPUT:
674        h->u.o.busy = FALSE;
675
676        /*
677         * A signal on an output handle means we have completed a
678         * write. Call the callback to indicate that the output
679         * buffer size has decreased, or to indicate an error.
680         */
681        if (h->u.o.writeerr) {
682            /*
683             * Write error. Send a negative value to the callback,
684             * and mark the thread as defunct (because the output
685             * thread is terminating by now).
686             */
687            h->u.o.defunct = TRUE;
688            h->u.o.sentdata(h, -h->u.o.writeerr);
689        } else {
690            bufchain_consume(&h->u.o.queued_data, h->u.o.lenwritten);
691            h->u.o.sentdata(h, bufchain_size(&h->u.o.queued_data));
692            handle_try_output(&h->u.o);
693        }
694        break;
695
696      case HT_FOREIGN:
697        /* Just call the callback. */
698        h->u.f.callback(h->u.f.ctx);
699        break;
700    }
701}
702
703void handle_unthrottle(struct handle *h, int backlog)
704{
705    assert(h->type == HT_INPUT);
706    handle_throttle(&h->u.i, backlog);
707}
708
709int handle_backlog(struct handle *h)
710{
711    assert(h->type == HT_OUTPUT);
712    return bufchain_size(&h->u.o.queued_data);
713}
714
715void *handle_get_privdata(struct handle *h)
716{
717    return h->u.g.privdata;
718}
Note: See TracBrowser for help on using the repository browser.