gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] 02/02: process_urh(): process all recv() be


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] 02/02: process_urh(): process all recv() before all send() to overcome limitations on some platforms
Date: Fri, 10 Mar 2017 18:03:05 +0100

This is an automated email from the git hooks/post-receive script.

karlson2k pushed a commit to branch master
in repository libmicrohttpd.

commit 9174eb844bb2a6a23e4fd18c78c5b9ca84a0072c
Author: Evgeny Grin (Karlson2k) <address@hidden>
AuthorDate: Thu Mar 2 11:53:16 2017 +0300

    process_urh(): process all recv() before all send() to overcome limitations 
on some platforms
---
 src/microhttpd/daemon.c | 140 +++++++++++++++++++++++++++---------------------
 1 file changed, 79 insertions(+), 61 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0049b562..f25ccd4d 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -1201,7 +1201,16 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
       connection->tls_read_ready = false;
     }
 
-  /* handle reading from TLS client and writing to application */
+  /* Some platforms (W32, possibly Darwin) may discard data in system buffers
+   * received by system but unread by recv() if remote side was disconnected
+   * and failed send() attempted (send() will always fail after remote 
disconnect
+   * was detected).
+   * So, before trying send() on any socket, recv() must be performed at first
+   * otherwise last part of incoming data may be lost. */
+
+  /*
+   * handle reading from remote TLS client
+   */
   if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->app.celi)) ||
          (connection->tls_read_ready) ) &&
        (urh->in_buffer_used < urh->in_buffer_size) )
@@ -1236,67 +1245,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
           urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
         }
     }
-  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
-       (urh->in_buffer_used > 0) )
-    {
-      ssize_t res;
-      size_t data_size;
-
-      data_size = urh->in_buffer_used;
-      if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
-        data_size = MHD_SCKT_SEND_MAX_SIZE_;
-
-      res = MHD_send_ (urh->mhd.socket,
-                       urh->in_buffer,
-                       data_size);
-      if (0 > res)
-        {
-          int err = MHD_socket_get_error_ ();
-
-          if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
-            urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
-          else if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
-                    (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) )
-            {
-              /* persistent / unrecoverable error, treat as
-                 if connection was shut down. */
-#ifdef HAVE_MESSAGES
-              MHD_DLOG (daemon,
-                        _("Failed to forward to application " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
-                            " bytes of data received from remote side: %s\n"),
-                        (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
-                        MHD_socket_strerr_ (err));
-#endif
-              /* Discard any data received form remote. */
-              urh->in_buffer_used = 0;
-              /* Do not try to push data to application. */
-              urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
-              /* Reading from remote client is not required anymore. */
-              urh->in_buffer_size = 0;
-              urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
-              connection->tls_read_ready = false;
-            }
-        }
-      else
-        {
-          if (urh->in_buffer_used != res)
-            {
-              memmove (urh->in_buffer,
-                       &urh->in_buffer[res],
-                       urh->in_buffer_used - res);
-              urh->in_buffer_used -= res;
-              if (data_size > (size_t)res)
-                urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
-            }
-          else
-            {
-              urh->in_buffer_used = 0;
-            }
-        }
-    }
-
-  /* handle reading from application and writing to HTTPS client */
 
+  /*
+   * handle reading from application
+   */
   /* If application signaled MHD about socket closure then
    * check for any pending data even if socket is not marked
    * as 'ready' (signal may arrive after poll()/select()).
@@ -1356,6 +1308,10 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
           urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
         }
     }
+
+  /*
+   * handle writing to remote HTTPS client
+   */
   if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->app.celi)) &&
        (urh->out_buffer_used > 0) )
     {
@@ -1410,6 +1366,68 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
         }
     }
 
+  /*
+   * handle writing to application
+   */
+  if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->mhd.celi)) &&
+       (urh->in_buffer_used > 0) )
+    {
+      ssize_t res;
+      size_t data_size;
+
+      data_size = urh->in_buffer_used;
+      if (data_size > MHD_SCKT_SEND_MAX_SIZE_)
+        data_size = MHD_SCKT_SEND_MAX_SIZE_;
+
+      res = MHD_send_ (urh->mhd.socket,
+                       urh->in_buffer,
+                       data_size);
+      if (0 > res)
+        {
+          int err = MHD_socket_get_error_ ();
+
+          if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
+            urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+          else if ( (! MHD_SCKT_ERR_IS_EINTR_ (err)) &&
+                    (! MHD_SCKT_ERR_IS_LOW_RESOURCES_(err)) )
+            {
+              /* persistent / unrecoverable error, treat as
+                 if connection was shut down. */
+#ifdef HAVE_MESSAGES
+              MHD_DLOG (daemon,
+                        _("Failed to forward to application " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
+                            " bytes of data received from remote side: %s\n"),
+                        (MHD_UNSIGNED_LONG_LONG) urh->in_buffer_used,
+                        MHD_socket_strerr_ (err));
+#endif
+              /* Discard any data received form remote. */
+              urh->in_buffer_used = 0;
+              /* Do not try to push data to application. */
+              urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+              /* Reading from remote client is not required anymore. */
+              urh->in_buffer_size = 0;
+              urh->app.celi &= ~MHD_EPOLL_STATE_READ_READY;
+              connection->tls_read_ready = false;
+            }
+        }
+      else
+        {
+          if (urh->in_buffer_used != res)
+            {
+              memmove (urh->in_buffer,
+                       &urh->in_buffer[res],
+                       urh->in_buffer_used - res);
+              urh->in_buffer_used -= res;
+              if (data_size > (size_t)res)
+                urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+            }
+          else
+            {
+              urh->in_buffer_used = 0;
+            }
+        }
+    }
+
   /* Check whether data is present in TLS buffers
    * and incoming forward buffer have some space. */
   if ( (connection->tls_read_ready) &&

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]