aboutsummaryrefslogtreecommitdiff
path: root/tools/plink/winhandl.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/plink/winhandl.c')
-rw-r--r--tools/plink/winhandl.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/tools/plink/winhandl.c b/tools/plink/winhandl.c
index dbcab2b2a..06c2a6a07 100644
--- a/tools/plink/winhandl.c
+++ b/tools/plink/winhandl.c
@@ -250,6 +250,7 @@ struct handle_output {
* Data only ever read or written by the main thread.
*/
bufchain queued_data; /* data still waiting to be written */
+ enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
/*
* Callback function called when the backlog in the bufchain
@@ -320,6 +321,11 @@ static void handle_try_output(struct handle_output *ctx)
ctx->len = sendlen;
SetEvent(ctx->ev_from_main);
ctx->busy = TRUE;
+ } else if (!ctx->busy && bufchain_size(&ctx->queued_data) == 0 &&
+ ctx->outgoingeof == EOF_PENDING) {
+ CloseHandle(ctx->h);
+ ctx->h = INVALID_HANDLE_VALUE;
+ ctx->outgoingeof = EOF_SENT;
}
}
@@ -408,6 +414,7 @@ struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
h->u.o.done = FALSE;
h->u.o.privdata = privdata;
bufchain_init(&h->u.o.queued_data);
+ h->u.o.outgoingeof = EOF_NO;
h->u.o.sentdata = sentdata;
h->u.o.flags = flags;
@@ -424,11 +431,28 @@ struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
int handle_write(struct handle *h, const void *data, int len)
{
assert(h->output);
+ assert(h->u.o.outgoingeof == EOF_NO);
bufchain_add(&h->u.o.queued_data, data, len);
handle_try_output(&h->u.o);
return bufchain_size(&h->u.o.queued_data);
}
+void handle_write_eof(struct handle *h)
+{
+ /*
+ * This function is called when we want to proactively send an
+ * end-of-file notification on the handle. We can only do this by
+ * actually closing the handle - so never call this on a
+ * bidirectional handle if we're still interested in its incoming
+ * direction!
+ */
+ assert(h->output);
+ if (!h->u.o.outgoingeof == EOF_NO) {
+ h->u.o.outgoingeof = EOF_PENDING;
+ handle_try_output(&h->u.o);
+ }
+}
+
HANDLE *handle_get_events(int *nevents)
{
HANDLE *ret;