Introduce a sane interface function, from_backend(), for backends to
[u/mdw/putty] / raw.c
diff --git a/raw.c b/raw.c
index ff37b6d..3f82d7a 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -1,7 +1,13 @@
 #include <windows.h>
 #include <stdio.h>
 #include <stdlib.h>
+#ifndef AUTO_WINSOCK
+#ifdef WINSOCK_TWO
+#include <winsock2.h>
+#else
 #include <winsock.h>
+#endif
+#endif
 
 #include "putty.h"
 
@@ -14,8 +20,6 @@
 
 static SOCKET s = INVALID_SOCKET;
 
-#define iswritable(x) ( (x) != IAC && (x) != CR )
-
 static void raw_size(void);
 
 static int sb_opt, sb_len;
@@ -50,14 +54,7 @@ static void s_write (void *buf, int len) {
 }
 
 static void c_write (char *buf, int len) {
-    while (len--) {
-       int new_head = (inbuf_head + 1) & INBUF_MASK;
-       int c = (unsigned char) *buf;
-       if (new_head != inbuf_reap) {
-           inbuf[inbuf_head] = *buf++;
-           inbuf_head = new_head;
-       }
-    }
+    from_backend(0, buf, len);
 }
 
 /*
@@ -132,13 +129,18 @@ static char *raw_init (HWND hwnd, char *host, int port, char **realhost) {
          default: return "connect(): unknown error";
        }
 
-    if (WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
+    if (hwnd && WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
                        FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
        switch (WSAGetLastError()) {
          case WSAENETDOWN: return "Network is down";
          default: return "WSAAsyncSelect(): unknown error";
        }
 
+    /*
+     * We have no pre-session phase.
+     */
+    begin_session();
+
     return NULL;
 }
 
@@ -150,22 +152,36 @@ static int raw_msg (WPARAM wParam, LPARAM lParam) {
     int ret;
     char buf[256];
 
-    if (s == INVALID_SOCKET)          /* how the hell did we get here?! */
-       return -5000;
+    /*
+     * Because reading less than the whole of the available pending
+     * data can generate an FD_READ event, we need to allow for the
+     * possibility that FD_READ may arrive with FD_CLOSE already in
+     * the queue; so it's possible that we can get here even with s
+     * invalid. If so, we return 1 and don't worry about it.
+     */
+    if (s == INVALID_SOCKET) {
+        closesocket(s);
+        s = INVALID_SOCKET;
+       return 1;
+    }
 
     if (WSAGETSELECTERROR(lParam) != 0)
        return -WSAGETSELECTERROR(lParam);
 
     switch (WSAGETSELECTEVENT(lParam)) {
       case FD_READ:
+      case FD_CLOSE:
        ret = recv(s, buf, sizeof(buf), 0);
        if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
            return 1;
-       if (ret < 0)                   /* any _other_ error */
+       if (ret < 0) {                 /* any _other_ error */
+            closesocket(s);
+            s = INVALID_SOCKET;
            return -10000-WSAGetLastError();
+        }
        if (ret == 0) {
            s = INVALID_SOCKET;
-           return 0;                  /* can't happen, in theory */
+           return 0;
        }
        c_write( buf, ret );
        return 1;
@@ -184,9 +200,6 @@ static int raw_msg (WPARAM wParam, LPARAM lParam) {
        if (outbuf_head != outbuf_reap)
            try_write();
        return 1;
-      case FD_CLOSE:
-       s = INVALID_SOCKET;
-       return 0;
     }
     return 1;                         /* shouldn't happen, but WTF */
 }
@@ -218,10 +231,17 @@ static void raw_special (Telnet_Special code) {
     return;
 }
 
+static SOCKET raw_socket(void) { return s; }
+
+static int raw_sendok(void) { return 1; }
+
 Backend raw_backend = {
     raw_init,
     raw_msg,
     raw_send,
     raw_size,
-    raw_special
+    raw_special,
+    raw_socket,
+    raw_sendok,
+    1
 };