]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Grow some nasty warts on the side of winhandl.c, in preparation for
authorSimon Tatham <anakin@pobox.com>
Sun, 27 Aug 2006 10:00:36 +0000 (10:00 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 27 Aug 2006 10:00:36 +0000 (10:00 +0000)
a serial port backend:
 - In order to do simultaneous reading and writing on the same
   HANDLE, you must enable overlapped access and pass an OVERLAPPED
   structure to each ReadFile and WriteFile call. This would make
   sense if it were an optional thing I could do if I wanted to do
   the reading and writing in the same thread, but making it
   mandatory even if I'm doing them in _different_ threads is just
   annoying and arbitrary.
 - Serial ports occasionally return length 0 from ReadFile, for no
   particularly good reason. Fortunately serial ports also don't
   have a real EOF condition to speak of, so ignoring EOFs is
   actually a viable response in spite of sounding utterly gross.
Hence, handle_{input,output}_new() now accept a flags parameter,
which includes a flag to enable the OVERLAPPED bureaucracy and a
flag to cause EOFs to be ignored on input handles. The current
clients of winhandl.c do not use either of these.

[originally from svn r6813]

windows/winhandl.c
windows/winplink.c
windows/winproxy.c
windows/winstuff.h

index e45eb9b5dec1d705f84a7e1f557f12baae596183..fc641812a1b024a943f3d9318bb17aa4c3912add 100644 (file)
@@ -74,6 +74,11 @@ struct handle_input {
     int busy;                         /* operation currently in progress? */
     void *privdata;                   /* for client to remember who they are */
 
+    /*
+     * Data set at initialisation and then read-only.
+     */
+    int flags;
+
     /*
      * Data set by the input thread before signalling ev_to_main,
      * and read by the main thread after receiving that signal.
@@ -95,13 +100,28 @@ struct handle_input {
 static DWORD WINAPI handle_input_threadfunc(void *param)
 {
     struct handle_input *ctx = (struct handle_input *) param;
+    OVERLAPPED ovl, *povl;
+
+    if (ctx->flags & HANDLE_FLAG_OVERLAPPED)
+       povl = &ovl;
+    else
+       povl = NULL;
 
     while (1) {
+       if (povl)
+           memset(povl, 0, sizeof(OVERLAPPED));
        ctx->readret = ReadFile(ctx->h, ctx->buffer, sizeof(ctx->buffer),
-                               &ctx->len, NULL);
+                               &ctx->len, povl);
+       if (povl && !ctx->readret && GetLastError() == ERROR_IO_PENDING)
+           ctx->readret = GetOverlappedResult(ctx->h, povl, &ctx->len, TRUE);
+
        if (!ctx->readret)
            ctx->len = 0;
 
+       if (ctx->readret && ctx->len == 0 &&
+           (ctx->flags & HANDLE_FLAG_IGNOREEOF))
+           continue;
+
        SetEvent(ctx->ev_to_main);
 
        if (!ctx->len)
@@ -163,6 +183,11 @@ struct handle_output {
     int busy;                         /* operation currently in progress? */
     void *privdata;                   /* for client to remember who they are */
 
+    /*
+     * Data set at initialisation and then read-only.
+     */
+    int flags;
+
     /*
      * Data set by the main thread before signalling ev_from_main,
      * and read by the input thread after receiving that signal.
@@ -192,6 +217,12 @@ struct handle_output {
 static DWORD WINAPI handle_output_threadfunc(void *param)
 {
     struct handle_output *ctx = (struct handle_output *) param;
+    OVERLAPPED ovl, *povl;
+
+    if (ctx->flags & HANDLE_FLAG_OVERLAPPED)
+       povl = &ovl;
+    else
+       povl = NULL;
 
     while (1) {
        WaitForSingleObject(ctx->ev_from_main, INFINITE);
@@ -199,8 +230,14 @@ static DWORD WINAPI handle_output_threadfunc(void *param)
            SetEvent(ctx->ev_to_main);
            break;
        }
+       if (povl)
+           memset(povl, 0, sizeof(OVERLAPPED));
        ctx->writeret = WriteFile(ctx->h, ctx->buffer, ctx->len,
-                                 &ctx->lenwritten, NULL);
+                                 &ctx->lenwritten, povl);
+       if (povl && !ctx->writeret && GetLastError() == ERROR_IO_PENDING)
+           ctx->writeret = GetOverlappedResult(ctx->h, povl,
+                                               &ctx->lenwritten, TRUE);
+
        SetEvent(ctx->ev_to_main);
        if (!ctx->writeret)
            break;
@@ -265,7 +302,7 @@ static int handle_find_evtomain(void *av, void *bv)
 }
 
 struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
-                               void *privdata)
+                               void *privdata, int flags)
 {
     struct handle *h = snew(struct handle);
 
@@ -278,6 +315,7 @@ struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
     h->u.i.moribund = FALSE;
     h->u.i.done = FALSE;
     h->u.i.privdata = privdata;
+    h->u.i.flags = flags;
 
     if (!handles_by_evtomain)
        handles_by_evtomain = newtree234(handle_cmp_evtomain);
@@ -291,7 +329,7 @@ struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
 }
 
 struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
-                                void *privdata)
+                                void *privdata, int flags)
 {
     struct handle *h = snew(struct handle);
 
@@ -306,6 +344,7 @@ struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
     h->u.o.privdata = privdata;
     bufchain_init(&h->u.o.queued_data);
     h->u.o.sentdata = sentdata;
+    h->u.o.flags = flags;
 
     if (!handles_by_evtomain)
        handles_by_evtomain = newtree234(handle_cmp_evtomain);
index c85a6075e6c6d261a1eb2ff72f4c9402087d1fe5..86ad00ff76de3af22988ed50e792f07f8392b57f 100644 (file)
@@ -578,8 +578,8 @@ int main(int argc, char **argv)
      * (The input one we leave until we're through the
      * authentication process.)
      */
-    stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL);
-    stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL);
+    stdout_handle = handle_output_new(outhandle, stdouterr_sent, NULL, 0);
+    stderr_handle = handle_output_new(errhandle, stdouterr_sent, NULL, 0);
 
     main_thread_id = GetCurrentThreadId();
 
@@ -594,7 +594,8 @@ int main(int argc, char **argv)
        DWORD ticks;
 
        if (!sending && back->sendok(backhandle)) {
-           stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL);
+           stdin_handle = handle_input_new(inhandle, stdin_gotdata, NULL,
+                                           0);
            sending = TRUE;
        }
 
index 24e68f8ae34d1aec25867565ce2ce67d91a7f347..5fecfc25e84f05626e2c6f65e7458a44fc94857a 100644 (file)
@@ -205,9 +205,10 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
     ret->to_cmd_H = us_to_cmd;\r
     ret->from_cmd_H = us_from_cmd;\r
 \r
-    ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata, ret);\r
-    ret->to_cmd_h = handle_output_new(ret->to_cmd_H,\r
-                                       localproxy_sentdata, ret);\r
+    ret->from_cmd_h = handle_input_new(ret->from_cmd_H, localproxy_gotdata,\r
+                                      ret, 0);\r
+    ret->to_cmd_h = handle_output_new(ret->to_cmd_H, localproxy_sentdata,\r
+                                     ret, 0);\r
 \r
     /* We are responsible for this and don't need it any more */\r
     sk_addr_free(addr);\r
index afc8dde26be82344e4619092f6305fd9517a4604..85c99f433b8cf3814347851adb47704b8ada7391 100644 (file)
@@ -408,13 +408,15 @@ void init_ucs(Config *, struct unicode_data *);
 /*
  * Exports from winhandl.c.
  */
+#define HANDLE_FLAG_OVERLAPPED 1
+#define HANDLE_FLAG_IGNOREEOF 2
 struct handle;
 typedef int (*handle_inputfn_t)(struct handle *h, void *data, int len);
 typedef void (*handle_outputfn_t)(struct handle *h, int new_backlog);
 struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
-                               void *privdata);
+                               void *privdata, int flags);
 struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
-                                void *privdata);
+                                void *privdata, int flags);
 int handle_write(struct handle *h, const void *data, int len);
 HANDLE *handle_get_events(int *nevents);
 void handle_free(struct handle *h);