Added SILC Server library.
[silc.git] / lib / silcutil / win32 / silcwin32sockconn.c
index c78640308398c344bde074d1226a055db1d60693..31f702f48ec2b913e05b2be89563522e8ac15439 100644 (file)
@@ -4,12 +4,11 @@
 
   Author: Pekka Riikonen <priikone@silcnet.org>
 
-  Copyright (C) 1997 - 2001 Pekka Riikonen
+  Copyright (C) 1997 - 2005 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
+  the Free Software Foundation; version 2 of the License.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -19,7 +18,7 @@
 */
 /* $Id$ */
 
-#include "silcincludes.h"
+#include "silc.h"
 
 /* Writes data from encrypted buffer to the socket connection. If the
    data cannot be written at once, it will be written later with a timeout. 
@@ -33,6 +32,11 @@ int silc_socket_write(SilcSocketConnection sock)
   SOCKET fd = sock->sock;
   SilcBuffer src = sock->outbuf;
 
+  if (!src)
+    return -2;
+  if (SILC_IS_DISABLED(sock))
+    return -1;
+
   SILC_LOG_DEBUG(("Writing data to socket %d", fd));
 
   if (src->len > 0) {
@@ -41,20 +45,25 @@ int silc_socket_write(SilcSocketConnection sock)
       err = WSAGetLastError();
       if (err == WSAEWOULDBLOCK) {
        SILC_LOG_DEBUG(("Could not write immediately, will do it later"));
-       silc_net_set_socket_nonblock(fd);
        return -2;
       }
       SILC_LOG_ERROR(("Cannot write to socket: %d", (int)fd));
-      silc_net_set_socket_nonblock(fd);
+      sock->sock_error = err;
       return -1;
     }
 
+    if (ret < src->len) {
+      SILC_LOG_DEBUG(("Wrote data %d of %d bytes, will write rest later",
+                     ret, src->len));
+      silc_buffer_pull(src, ret);
+      return -2;
+    }
+
     silc_buffer_pull(src, ret);
   }
 
   SILC_LOG_DEBUG(("Wrote data %d bytes", ret));
 
-  silc_net_set_socket_nonblock(fd);
   return ret;
 }
 
@@ -68,25 +77,36 @@ int silc_socket_read(SilcSocketConnection sock)
   int len = 0, err;
   unsigned char buf[SILC_SOCKET_READ_SIZE];
   SOCKET fd = sock->sock;
+  int argp;
+
+  if (SILC_IS_DISABLED(sock))
+    return -1;
 
   SILC_LOG_DEBUG(("Reading data from socket %d", fd));
 
+  /* Check whether there is data available, without calling recv(). */
+  ioctlsocket(fd, FIONREAD, (unsigned long *)&argp);
+  if (argp == 0) {
+    /* Is this kludge or what? Without this thing this contraption
+       does not work at all!?. */
+    SleepEx(1, TRUE);
+    SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
+    return -2;
+  }
+
   /* Read the data from the socket. */
   len = recv(fd, buf, sizeof(buf), 0);
   if (len == SOCKET_ERROR) {
     err = WSAGetLastError();
     if (err == WSAEWOULDBLOCK || err == WSAEINTR) {
       SILC_LOG_DEBUG(("Could not read immediately, will do it later"));
-      silc_net_set_socket_nonblock(fd);
       return -2;
     }
     SILC_LOG_ERROR(("Cannot read from socket: %d", (int)fd));
-    silc_net_set_socket_nonblock(fd);
+    sock->sock_error = err;
     return -1;
   }
 
-  silc_net_set_socket_nonblock(fd);
-
   if (!len)
     return 0;
 
@@ -106,3 +126,12 @@ int silc_socket_read(SilcSocketConnection sock)
 
   return len;
 }
+
+/* Returns human readable socket error message */
+
+SilcBool silc_socket_get_error(SilcSocketConnection sock, char *error,
+                          SilcUInt32 error_len)
+{
+  /* XXX TODO */
+  return FALSE;
+}