I've attached a patch to fix this bug.  It includes a 2K buffer and two ints 
in the structure used for the sockets, this is 2056 bytes of extra RAM for 
each connection (even by the standards of 10 years ago it's not much).

Now the minimum read attempt will be 2048 bytes.

I've tested this with my own soap code.  My test program goes from 651 system 
calls (according to strace) to 141 system calls when using the patched 
version of the libraries.

Note that there seems to be some inter-dependencies between the libraries, 
upgrading one without the rest can cause a SEGV.  So the new versions of 
libnanohttp1 and libcsoap1 will have to conflict with the old versions of 
each other.
diff -ru libcsoap-1.1.0.bak/nanohttp/nanohttp-socket.c libcsoap-1.1.0/nanohttp/nanohttp-socket.c
--- libcsoap-1.1.0.bak/nanohttp/nanohttp-socket.c	2006-07-10 02:24:19.000000000 +1000
+++ libcsoap-1.1.0/nanohttp/nanohttp-socket.c	2009-03-28 10:21:04.000000000 +1100
@@ -473,27 +473,69 @@
 /* log_verbose3("Entering hsocket_read(total=%d,force=%d)", total, force); */
 
   totalRead = 0;
+  if(sock->buf_used)
+  {
+    if(total <= sock->buf_used)
+    {
+      memcpy(buffer, &sock->read_buf[sock->buf_start], total);
+      sock->buf_start += total;
+      sock->buf_used -= total;
+      *received = total;
+      return H_OK;
+    }
+    totalRead = sock->buf_used;
+    memcpy(buffer, &sock->read_buf[sock->buf_start], totalRead);
+    sock->buf_used = 0;
+  }
+
   do
   {
 
-    if ((status =
+    if(total - totalRead < sizeof(sock->read_buf))
+    {
+      if ((status =
+         hssl_read(sock, sock->read_buf,
+               sizeof(sock->read_buf), &count)) != H_OK)
+      {
+        log_warn2("hssl_read failed (%s)", herror_message(status));
+        return status;
+      }
+      if(count >= total - totalRead)
+      {
+        memcpy(&buffer[totalRead], sock->read_buf, total - totalRead);
+        *received = total;
+        sock->buf_used = count - total - totalRead;
+        sock->buf_start = total - totalRead;
+        return H_OK;
+      }
+      else
+      {
+        memcpy(&buffer[totalRead], sock->read_buf, count);
+        sock->buf_used = 0;
+        /* 10 lines below we do totalRead += count; */
+      }
+    }
+    else
+    {
+      if ((status =
          hssl_read(sock, &buffer[totalRead], (size_t) total - totalRead,
                    &count)) != H_OK)
-    {
-      log_warn2("hssl_read failed (%s)", herror_message(status));
-      return status;
+      {
+        log_warn2("hssl_read failed (%s)", herror_message(status));
+        return status;
+      }
     }
 
+    totalRead += count;
+
     if (!force)
     {
       /* log_verbose3("Leaving !force (received=%d)(status=%d)", *received,
          status); */
-      *received = count;
+      *received = totalRead;
       return H_OK;
     }
 
-    totalRead += count;
-
     if (totalRead == total)
     {
       *received = totalRead;
diff -ru libcsoap-1.1.0.bak/nanohttp/nanohttp-socket.h libcsoap-1.1.0/nanohttp/nanohttp-socket.h
--- libcsoap-1.1.0.bak/nanohttp/nanohttp-socket.h	2006-05-02 03:56:32.000000000 +1000
+++ libcsoap-1.1.0/nanohttp/nanohttp-socket.h	2009-03-28 10:23:27.000000000 +1100
@@ -55,6 +55,8 @@
 #endif
   struct sockaddr_in addr;
   void *ssl;
+  char read_buf[2048];
+  int buf_start, buf_used;
 }
 hsocket_t;                      /* end of socket definition */
 

Reply via email to