gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [libmicrohttpd] branch master updated (d9461187 -> 9174eb84


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated (d9461187 -> 9174eb84)
Date: Fri, 10 Mar 2017 18:03:03 +0100

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

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from d9461187 fix NPE (COV 164294)
     new 26b63fcb process_urh(): Rearranged comments, fixed wrong "unready" 
mark.
     new 9174eb84 process_urh(): process all recv() before all send() to 
overcome limitations on some platforms

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/microhttpd/daemon.c | 182 +++++++++++++++++++++++++++---------------------
 1 file changed, 104 insertions(+), 78 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index f93dbd21..f25ccd4d 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -1191,15 +1191,26 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
 #endif
 
         }
-      urh->in_buffer_size = 0;
+      /* 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;
     }
 
-  /* 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) )
@@ -1229,80 +1240,24 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
                 (GNUTLS_E_INTERRUPTED != res) )
         {
           /* Connection was shut down or got unrecoverable error.
-           * signal by shrinking buffer so no more attempts will be
-           * performed to receive data. */
+           * Reading from remote client is not required anymore. */
           urh->in_buffer_size = 0;
           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 (-1 == 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.
-                 Do not try to receive to 'in_buffer' and
-                 discard any unsent data. */
-#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
-              urh->in_buffer_size = 0;
-              urh->in_buffer_used = 0;
-              urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
-              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()).
+   * Socketpair for forwarding is always in non-blocking mode
+   * so no risk that recv() will block the thread. */
   if ( ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->mhd.celi)) ||
          (urh->was_closed) ) &&
        (urh->out_buffer_used < urh->out_buffer_size) )
     {
-      /* 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()).
-       * Socketpair for forwarding is always in non-blocking mode
-       * so no risk that recv() will block the thread. */
       ssize_t res;
       size_t buf_size;
 
@@ -1313,12 +1268,13 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
       res = MHD_recv_ (urh->mhd.socket,
                        &urh->out_buffer[urh->out_buffer_used],
                        buf_size);
-      if (-1 == res)
+      if (0 > res)
         {
           if (urh->was_closed)
             {
-              /* Connection was shut down or all data received and
-               * application will not forward any more data. */
+              /* All data was received and application will not
+               * forward any more data. */
+              /* Do not try to pull data from application. */
               urh->out_buffer_size = 0;
               urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
             }
@@ -1332,6 +1288,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
                 {
                   /* persistent / unrecoverable error, treat as
                      if connection was shut down */
+                  /* Do not try to pull data from application. */
                   urh->out_buffer_size = 0;
                   urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
                 }
@@ -1346,12 +1303,15 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
       if (0 == res)
         {
           /* Connection was shut down or got unrecoverable error.
-           * signal by shrinking buffer so no more attempts will be
-           * performed to receive data. */
+          /* Do not try to pull data from application. */
           urh->out_buffer_size = 0;
-          urh->mhd.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+          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) )
     {
@@ -1388,9 +1348,7 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
       else if (GNUTLS_E_INTERRUPTED != res)
         {
           /* persistent / unrecoverable error, treat as
-             if connection was shut down.
-             Do not try to receive to 'out_buffer' and
-             discard any unsent data. */
+             if connection was shut down. */
 #ifdef HAVE_MESSAGES
           MHD_DLOG (daemon,
                     _("Failed to forward to remote client " 
MHD_UNSIGNED_LONG_LONG_PRINTF \
@@ -1398,13 +1356,78 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
                     (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used,
                     gnutls_strerror(res));
 #endif
-          urh->out_buffer_size = 0;
+          /* Discard any data unsent to remote. */
           urh->out_buffer_used = 0;
+          /* Do not try to sent to remote anymore. */
           urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+          /* Do not try to pull more data from application. */
+          urh->out_buffer_size = 0;
           urh->mhd.celi &= ~MHD_EPOLL_STATE_READ_READY;
         }
     }
 
+  /*
+   * 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) &&
@@ -1424,9 +1447,12 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
                       " bytes of data received from application: daemon shut 
down\n"),
                   (MHD_UNSIGNED_LONG_LONG) urh->out_buffer_used);
 #endif
-      urh->out_buffer_size = 0;
+      /* Discard any data unsent to remote. */
       urh->out_buffer_used = 0;
+      /* Do not try to sent to remote anymore. */
       urh->app.celi &= ~MHD_EPOLL_STATE_WRITE_READY;
+      /* Do not try to pull more data from application. */
+      urh->out_buffer_size = 0;
       urh->mhd.celi &= ~MHD_EPOLL_STATE_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]