gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [libmicrohttpd] branch master updated (8d1d0b8 -> 938b9b8)


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated (8d1d0b8 -> 938b9b8)
Date: Thu, 01 Dec 2016 15:42:34 +0100

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

karlson2k pushed a change to branch master
in repository libmicrohttpd.

    from 8d1d0b8  fix comment, rename to match argument
     new 5bbf69f  Fixed precompiler warning for tests
     new 7f9b98e  Fixed thread safety with responses with same file FD, added 
enum value MHD_FEATURE_RESPONSES_SHARED_FD
     new 938b9b8  fileserver_example: used MHD built-in function for sending 
files, added comments

The 3 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:
 configure.ac                      |  2 +-
 src/examples/fileserver_example.c | 63 ++++++++++++++++-----------------------
 src/include/microhttpd.h          | 15 +++++++++-
 src/microhttpd/daemon.c           | 12 +++++++-
 src/microhttpd/response.c         | 63 ++++++++++++++++++++++++++-------------
 src/microhttpd/test_str.c         |  2 +-
 src/microhttpd/test_upgrade.c     |  2 +-
 7 files changed, 96 insertions(+), 63 deletions(-)

diff --git a/configure.ac b/configure.ac
index 6c04181..d9316ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1043,7 +1043,7 @@ AM_CONDITIONAL([HAVE_MAGIC], [[test 
"x$mhd_have_magic_open" = "xyes"]])
 # large file support (> 4 GB)
 AC_SYS_LARGEFILE
 AC_FUNC_FSEEKO
-AC_CHECK_FUNCS([_lseeki64 lseek64 sendfile64])
+AC_CHECK_FUNCS([lseek64 sendfile64 pread64 pread])
 
 # optional: have error messages ?
 AC_MSG_CHECKING([[whether to generate error messages]])
diff --git a/src/examples/fileserver_example.c 
b/src/examples/fileserver_example.c
index 9a46fba..4d71057 100644
--- a/src/examples/fileserver_example.c
+++ b/src/examples/fileserver_example.c
@@ -24,31 +24,21 @@
 
 #include "platform.h"
 #include <microhttpd.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif /* HAVE_FCNTL_H */
 
 #define PAGE "<html><head><title>File not found</title></head><body>File not 
found</body></html>"
 
-
-static ssize_t
-file_reader (void *cls,
-             uint64_t pos,
-             char *buf,
-             size_t max)
-{
-  FILE *file = cls;
-
-  (void)  fseek (file, pos, SEEK_SET);
-  return fread (buf, 1, max, file);
-}
-
-
-static void
-free_callback (void *cls)
-{
-  FILE *file = cls;
-  fclose (file);
-}
-
+#ifndef S_ISREG
+#define S_ISREG(x) (S_IFREG == (x & S_IFREG))
+#endif /* S_ISREG */
 
 static int
 ahc_echo (void *cls,
@@ -62,7 +52,6 @@ ahc_echo (void *cls,
   static int aptr;
   struct MHD_Response *response;
   int ret;
-  FILE *file;
   int fd;
   struct stat buf;
 
@@ -76,24 +65,25 @@ ahc_echo (void *cls,
       return MHD_YES;
     }
   *ptr = NULL;                  /* reset when done */
-  file = fopen (&url[1], "rb");
-  if (NULL != file)
+  /* WARNING: direct usage of url as filename is for example only!
+   * NEVER pass received data directly as parameter to file manipulation
+   * functions. Always check validity of data before using.
+   */
+  if (NULL != strstr(url, "../")) /* Very simplified check! */
+    fd = -1; /* Do not allow usage of parent directories. */
+  else
+    fd = open (url + 1, O_RDONLY);
+  if (-1 != fd)
     {
-      fd = fileno (file);
-      if (-1 == fd)
-        {
-          (void) fclose (file);
-          return MHD_NO; /* internal error */
-        }
       if ( (0 != fstat (fd, &buf)) ||
            (! S_ISREG (buf.st_mode)) )
         {
           /* not a regular file, refuse to serve */
-          fclose (file);
-          file = NULL;
+          close (fd);
+          fd = -1;
         }
     }
-  if (NULL == file)
+  if (-1 == fd)
     {
       response = MHD_create_response_from_buffer (strlen (PAGE),
                                                  (void *) PAGE,
@@ -103,13 +93,10 @@ ahc_echo (void *cls,
     }
   else
     {
-      response = MHD_create_response_from_callback (buf.st_size, 32 * 1024,    
 /* 32k page size */
-                                                    &file_reader,
-                                                    file,
-                                                    &free_callback);
+      response = MHD_create_response_from_fd64(buf.st_size, fd);
       if (NULL == response)
        {
-         fclose (file);
+         close (fd);
          return MHD_NO;
        }
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index b72173e..32bf41b 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -2952,7 +2952,20 @@ enum MHD_FEATURE
    * If supported then #MHD_ALLOW_UPGRADE, #MHD_upgrade_action() and
    * #MHD_create_response_for_upgrade() can be used.
    */
-  MHD_FEATURE_UPGRADE = 17
+  MHD_FEATURE_UPGRADE = 17,
+
+  /**
+   * Get whether it's safe to use same FD for multiple calls of
+   * #MHD_create_response_from_fd() and whether it's safe to use single
+   * response generated by #MHD_create_response_from_fd() with multiple
+   * connections at same time.
+   * If #MHD_is_feature_supported() return #MHD_NO for this feature then
+   * usage of responses with same file FD in multiple parallel threads may
+   * results in incorrect data sent to remote client.
+   * It's always safe to use same file FD in multiple responses if MHD
+   * is run in any single thread mode.
+   */
+  MHD_FEATURE_RESPONSES_SHARED_FD = 18
 };
 
 
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 1b0a42b..97640ba 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -6018,7 +6018,11 @@ MHD_is_feature_supported(enum MHD_FEATURE feature)
       return MHD_NO;
 #endif /* !HTTPS_SUPPORT || GNUTLS_VERSION_NUMBER < 0x030111 */
     case MHD_FEATURE_LARGE_FILE:
-#if defined(HAVE___LSEEKI64) || defined(HAVE_LSEEK64)
+#if defined(HAVE_PREAD64) || defined(_WIN32)
+      return MHD_YES;
+#elif defined(HAVE_PREAD)
+      return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
+#elif defined(HAVE_LSEEK64)
       return MHD_YES;
 #else
       return (sizeof(uint64_t) > sizeof(off_t)) ? MHD_NO : MHD_YES;
@@ -6035,6 +6039,12 @@ MHD_is_feature_supported(enum MHD_FEATURE feature)
 #else
       return MHD_NO;
 #endif
+    case MHD_FEATURE_RESPONSES_SHARED_FD:
+#if defined(HAVE_PREAD64) || defined(HAVE_PREAD) || defined(_WIN32)
+      return MHD_YES;
+#else
+      return MHD_NO;
+#endif
     }
   return MHD_NO;
 }
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index 8b89c5f..ad52f80 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -30,6 +30,9 @@
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif /* HAVE_SYS_IOCTL_H */
+#ifdef _WIN32
+#include <windows.h>
+#endif /* _WIN32 */
 
 #include "internal.h"
 #include "response.h"
@@ -341,23 +344,35 @@ file_reader (void *cls,
              size_t max)
 {
   struct MHD_Response *response = cls;
+#ifndef _WIN32
   ssize_t n;
+#else  /* _WIN32 */
+  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
+#endif /* _WIN32 */
   const int64_t offset64 = (int64_t)(pos + response->fd_off);
 
   if (offset64 < 0)
     return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is 
not possible */
 
+#ifndef _WIN32
+  if (max > SSIZE_MAX)
+    max = SSIZE_MAX; /* Clamp to maximum return value. */
+
+#if defined(HAVE_PREAD64)
+  n = pread64(response->fd, buf, max, offset64);
+#elif defined(HAVE_PREAD)
+  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
+       (offset64 > (uint64_t)INT32_MAX) )
+    return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is 
not possible. */
+
+  n = pread(response->fd, buf, max, (off_t) offset64);
+#else  /* ! HAVE_PREAD */
 #if defined(HAVE_LSEEK64)
   if (lseek64 (response->fd,
                offset64,
                SEEK_SET) != offset64)
     return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required 
position */
-#elif defined(HAVE___LSEEKI64)
-  if (_lseeki64 (response->fd,
-                 offset64,
-                 SEEK_SET) != offset64)
-    return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required 
position */
-#else /* !HAVE___LSEEKI64 */
+#else  /* ! HAVE_LSEEK64 */
   if ( (sizeof(off_t) < sizeof (uint64_t)) &&
        (offset64 > (uint64_t)INT32_MAX) )
     return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is 
not possible */
@@ -366,29 +381,37 @@ file_reader (void *cls,
              (off_t) offset64,
              SEEK_SET) != (off_t) offset64)
     return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required 
position */
-#endif
-
-#ifndef _WIN32
-  if (max > SSIZE_MAX)
-    max = SSIZE_MAX;
-
+#endif /* ! HAVE_LSEEK64 */
   n = read (response->fd,
             buf,
             max);
-#else  /* _WIN32 */
-  if (max > INT32_MAX)
-    max = INT32_MAX;
-
-  n = read (response->fd,
-            buf,
-            (unsigned int) max);
-#endif /* _WIN32 */
 
+#endif /* ! HAVE_PREAD */
   if (0 == n)
     return MHD_CONTENT_READER_END_OF_STREAM;
   if (n < 0)
     return MHD_CONTENT_READER_END_WITH_ERROR;
   return n;
+#else /* _WIN32 */
+  if (INVALID_HANDLE_VALUE == fh)
+    return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is 
not valid. */
+  else
+    {
+      OVERLAPPED f_ol = {0, 0, 0, 0}; /* Initialize to zero. */
+      ULARGE_INTEGER pos_uli;
+      DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
+      DWORD resRead;
+
+      pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit 
-> 2x32bit. */
+      f_ol.Offset = pos_uli.LowPart;
+      f_ol.OffsetHigh = pos_uli.HighPart;
+      if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
+        return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
+      if (0 == resRead)
+        return MHD_CONTENT_READER_END_OF_STREAM;
+      return (ssize_t) resRead;
+    }
+#endif /* _WIN32 */
 }
 
 
diff --git a/src/microhttpd/test_str.c b/src/microhttpd/test_str.c
index ae94917..3f92130 100644
--- a/src/microhttpd/test_str.c
+++ b/src/microhttpd/test_str.c
@@ -23,10 +23,10 @@
  * @author Karlson2k (Evgeny Grin)
  */
 
+#include "mhd_options.h"
 #include <stdio.h>
 #include <locale.h>
 #include <string.h>
-#include "mhd_options.h"
 #ifdef HAVE_INTTYPES_H
 #include <inttypes.h>
 #else  /* ! HAVE_INTTYPES_H */
diff --git a/src/microhttpd/test_upgrade.c b/src/microhttpd/test_upgrade.c
index 68ff20d..710af1a 100644
--- a/src/microhttpd/test_upgrade.c
+++ b/src/microhttpd/test_upgrade.c
@@ -25,6 +25,7 @@
  * @author Karlson2k (Evgeny Grin)
  */
 
+#include "mhd_options.h"
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -34,7 +35,6 @@
 #ifndef WINDOWS
 #include <unistd.h>
 #endif
-#include "mhd_options.h"
 #ifdef HAVE_STDBOOL_H
 #include <stdbool.h>
 #endif /* HAVE_STDBOOL_H */

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



reply via email to

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