Parcourir la source

introducing MHD_create_response_from_buffer, deprecating MHD_create_response_from_data

Christian Grothoff il y a 15 ans
Parent
commit
43542a78c6
49 fichiers modifiés avec 297 ajouts et 143 suppressions
  1. 5 0
      ChangeLog
  2. 4 4
      doc/chapters/basicauthentication.inc
  3. 3 3
      doc/chapters/hellobrowser.inc
  4. 2 2
      doc/chapters/largerpost.inc
  5. 6 6
      doc/chapters/responseheaders.inc
  6. 4 4
      doc/examples/basicauthentication.c
  7. 2 2
      doc/examples/hellobrowser.c
  8. 2 2
      doc/examples/largepost.c
  9. 4 4
      doc/examples/responseheaders.c
  10. 2 2
      doc/examples/simplepost.c
  11. 4 3
      doc/examples/tlsauthentication.c
  12. 63 11
      doc/microhttpd.texi
  13. 6 4
      src/daemon/connection.c
  14. 24 1
      src/daemon/response.c
  15. 6 5
      src/examples/authorization_example.c
  16. 8 8
      src/examples/digest_auth_example.c
  17. 3 3
      src/examples/fileserver_example.c
  18. 3 4
      src/examples/fileserver_example_dirs.c
  19. 3 3
      src/examples/fileserver_example_external_select.c
  20. 3 3
      src/examples/https_fileserver_example.c
  21. 3 2
      src/examples/minimal_example.c
  22. 2 1
      src/examples/querystring_example.c
  23. 6 5
      src/examples/refuse_post_example.c
  24. 50 0
      src/include/microhttpd.h
  25. 8 8
      src/testcurl/daemontest_digestauth.c
  26. 3 2
      src/testcurl/daemontest_get.c
  27. 3 2
      src/testcurl/daemontest_iplimit.c
  28. 3 2
      src/testcurl/daemontest_large_put.c
  29. 3 2
      src/testcurl/daemontest_long_header.c
  30. 3 2
      src/testcurl/daemontest_parse_cookies.c
  31. 5 4
      src/testcurl/daemontest_post.c
  32. 2 1
      src/testcurl/daemontest_post_loop.c
  33. 3 3
      src/testcurl/daemontest_postform.c
  34. 3 2
      src/testcurl/daemontest_process_arguments.c
  35. 3 2
      src/testcurl/daemontest_process_headers.c
  36. 2 2
      src/testcurl/daemontest_put.c
  37. 3 2
      src/testcurl/daemontest_put_chunked.c
  38. 2 1
      src/testcurl/daemontest_termination.c
  39. 3 2
      src/testcurl/daemontest_timeout.c
  40. 3 2
      src/testcurl/https/mhds_get_test_select.c
  41. 3 3
      src/testcurl/https/mhds_session_info_test.c
  42. 3 3
      src/testcurl/https/tls_test_common.c
  43. 3 2
      src/testzzuf/daemontest_get.c
  44. 3 2
      src/testzzuf/daemontest_large_put.c
  45. 3 2
      src/testzzuf/daemontest_long_header.c
  46. 3 3
      src/testzzuf/daemontest_post.c
  47. 3 3
      src/testzzuf/daemontest_postform.c
  48. 3 2
      src/testzzuf/daemontest_put.c
  49. 3 2
      src/testzzuf/daemontest_put_chunked.c

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+Tue Jan  4 13:07:21 CET 2011
+	Added MHD_create_response_from_buffer, deprecating
+	MHD_create_response_from_data.  Deprecating
+	MHD_create_response_from_fd as well. -CG
+
 Sun Dec 26 00:02:15 CET 2010
 	Releasing libmicrohttpd 0.9.4. -CG
 	

+ 4 - 4
doc/chapters/basicauthentication.inc

@@ -107,8 +107,8 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
     {
       const char *page = "<html><body>Go away.</body></html>";
       response =
-	MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-				       MHD_NO);
+	MHD_create_response_from_buffer (strlen (page), (void *) page, 
+				       MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_basic_auth_fail_response (connection,
 						"my realm",
 						response);
@@ -117,8 +117,8 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
     {
       const char *page = "<html><body>A secret.</body></html>";
       response =
-	MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-				       MHD_NO);
+	MHD_create_response_from_buffer (strlen (page), (void *) page, 
+				       MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     }
   MHD_destroy_response (response);

+ 3 - 3
doc/chapters/hellobrowser.inc

@@ -54,7 +54,7 @@ HTTP is a rather strict protocol and the client would certainly consider it "ina
 just sent the answer string "as is". Instead, it has to be wrapped with additional information stored in so-called headers and footers.  Most of the work in this area is done by the library for us---we
 just have to ask. Our reply string packed in the necessary layers will be called a "response".
 To obtain such a response we hand our data (the reply--string) and its size over to the 
-@code{MHD_create_response_from_data} function. The last two parameters basically tell @emph{MHD}
+@code{MHD_create_response_from_buffer} function. The last two parameters basically tell @emph{MHD}
 that we do not want it to dispose the message data for us when it has been sent and there also needs
 no internal copy to be done because the @emph{constant} string won't change anyway.
 
@@ -62,8 +62,8 @@ no internal copy to be done because the @emph{constant} string won't change anyw
   struct MHD_Response *response;
   int ret;
 
-  response = MHD_create_response_from_data (strlen (page),
-                                            (void*) page, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (page),
+                                            (void*) page, MHD_RESPMEM_PERSISTENT);
 
 @end verbatim
 

+ 2 - 2
doc/chapters/largerpost.inc

@@ -67,8 +67,8 @@ send_page (struct MHD_Connection *connection,
   int ret;
   struct MHD_Response *response;
   
-  response = MHD_create_response_from_data (strlen (page), (void*) page, 
-  	     				    MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (page), (void*) page, 
+  	     				      MHD_RESPMEM_MUST_COPY);
   if (!response) return MHD_NO;
  
   ret = MHD_queue_response (connection, status_code, response);

+ 6 - 6
doc/chapters/responseheaders.inc

@@ -63,9 +63,9 @@ server side and if so, the client should be informed with @code{MHD_HTTP_INTERNA
         "<html><body>An internal server error has occured!\
                               </body></html>";
       response =
-	MHD_create_response_from_data (strlen (errorstr), 
-				       (void *) errorstr, 
-				       MHD_NO, MHD_NO);
+	MHD_create_response_from_buffer (strlen (errorstr), 
+				         (void *) errorstr, 
+				         MHD_RESPMEM_PERSISTENT);
       if (response)
         {
           ret =
@@ -84,8 +84,8 @@ server side and if so, the client should be informed with @code{MHD_HTTP_INTERNA
 
       if (buffer) free(buffer);
     
-      response = MHD_create_response_from_data(strlen(errorstr), (void*)errorstr,
-                                               MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (strlen(errorstr), (void*) errorstr,
+                                                  MHD_RESPMEM_PERSISTENT);
 
       if (response)
         {     
@@ -113,7 +113,7 @@ But in the case of success a response will be constructed directly from the file
     }
 
   response =
-    MHD_create_response_from_fd (fd, sbuf.st_size);
+    MHD_create_response_from_fd_at_offset (fd, sbuf.st_size, 0);
   MHD_add_response_header (response, "Content-Type", MIMETYPE);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);

+ 4 - 4
doc/examples/basicauthentication.c

@@ -40,8 +40,8 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
     {
       const char *page = "<html><body>Go away.</body></html>";
       response =
-	MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-				       MHD_NO);
+	MHD_create_response_from_buffer (strlen (page), (void *) page,
+					 MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_basic_auth_fail_response (connection,
 						"my realm",
 						response);
@@ -50,8 +50,8 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
     {
       const char *page = "<html><body>A secret.</body></html>";
       response =
-	MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-				       MHD_NO);
+	MHD_create_response_from_buffer (strlen (page), (void *) page,
+					 MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
     }
   MHD_destroy_response (response);

+ 2 - 2
doc/examples/hellobrowser.c

@@ -16,8 +16,8 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
   int ret;
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
+    MHD_create_response_from_buffer (strlen (page), (void *) page, 
+				     MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
 

+ 2 - 2
doc/examples/largepost.c

@@ -51,8 +51,8 @@ send_page (struct MHD_Connection *connection, const char *page,
   struct MHD_Response *response;
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_YES);
+    MHD_create_response_from_buffer (strlen (page), (void *) page,
+				     MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 

+ 4 - 4
doc/examples/responseheaders.c

@@ -31,9 +31,9 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
         "<html><body>An internal server error has occured!\
                               </body></html>";
       response =
-	MHD_create_response_from_data (strlen (errorstr), 
-				       (void *) errorstr, 
-				       MHD_NO, MHD_NO);
+	MHD_create_response_from_buffer (strlen (errorstr), 
+					 (void *) errorstr, 
+					 MHD_RESPMEM_PERSISTENT);
       if (response)
         {
           ret =
@@ -47,7 +47,7 @@ answer_to_connection (void *cls, struct MHD_Connection *connection,
         return MHD_NO;
     }
   response =
-    MHD_create_response_from_fd (fd, sbuf.st_size);
+    MHD_create_response_from_fd_at_offset (fd, sbuf.st_size, 0);
   MHD_add_response_header (response, "Content-Type", MIMETYPE);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);

+ 2 - 2
doc/examples/simplepost.c

@@ -40,8 +40,8 @@ send_page (struct MHD_Connection *connection, const char *page)
 
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
+    MHD_create_response_from_buffer (strlen (page), (void *) page,
+				     MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 

+ 4 - 3
doc/examples/tlsauthentication.c

@@ -113,7 +113,8 @@ ask_for_authentication (struct MHD_Connection *connection, const char *realm)
   char *headervalue;
   const char *strbase = "Basic realm=";
 
-  response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (0, NULL, 
+					      MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 
@@ -186,8 +187,8 @@ secret_page (struct MHD_Connection *connection)
   const char *page = "<html><body>A secret.</body></html>";
 
   response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
+    MHD_create_response_from_buffer (strlen (page), (void *) page, 
+				     MHD_RESPMEM_PERSISTENT);
   if (!response)
     return MHD_NO;
 

+ 63 - 11
doc/microhttpd.texi

@@ -674,6 +674,31 @@ We had to close the session since @mhd{} was being shut down.
 @end deftp
 
 
+@deftp {Enumeration} MHD_ResponseMemoryMode
+The @code{MHD_ResponeMemoryMode} specifies how MHD should treat
+the memory buffer given for the response in 
+@code{MHD_create_response_from_buffer}.
+
+@table @code
+@item MHD_RESPMEM_PERSISTENT
+Buffer is a persistent (static/global) buffer that won't change
+for at least the lifetime of the response, MHD should just use
+it, not free it, not copy it, just keep an alias to it.
+ 
+@item MHD_RESPMEM_MUST_FREE
+Buffer is heap-allocated with @code{malloc} (or equivalent) and
+should be freed by MHD after processing the response has
+concluded (response reference counter reaches zero).
+  
+@item MHD_RESPMEM_MUST_COPY
+Buffer is in transient memory, but not on the heap (for example,
+on the stack or non-malloc allocated) and only valid during the
+call to @code{MHD_create_response_from_buffer}.  MHD must make its
+own private copy of the data for processing.
+
+@end table
+@end deftp
+
 
 @deftp {Enumeration} MHD_ConnectionInfoType
 Values of this enum are used to specify what information about a
@@ -1245,7 +1270,7 @@ structures through @cfunction{Tcl_IncrRefCount} and
 a @code{MHD_Response} object is allocated:
 
 @example
-struct MHD_Response * response = MHD_create_response_from_data(...);
+struct MHD_Response * response = MHD_create_response_from_buffer(...);
 /* here: reference counter = 1 */
 @end example
 
@@ -1312,6 +1337,8 @@ Return @mynull{} on error (i.e. invalid arguments, out of memory).
 @deftypefun {struct MHD_Response *} MHD_create_response_from_fd (uint64_t size, int fd)
 Create a response object.  The response object can be extended with
 header information and then it can be used any number of times.
+Function is deprecated, use @code{MHD_create_response_from_fd_at_offset}
+instead (with an offset of zero).
 
 @table @var
 @item size
@@ -1352,9 +1379,34 @@ Return @mynull{} on error (i.e. invalid arguments, out of memory).
 @end deftypefun
 
 
+@deftypefun {struct MHD_Response *} MHD_create_response_from_buffer (size_t size, void *data, enum MHD_ResponseMemoryMode mode)
+Create a response object.  The response object can be extended with
+header information and then it can be used any number of times.
+
+@table @var
+@item size
+size of the data portion of the response;
+
+@item buffer
+the data itself;
+
+@item mode 
+memory management options for buffer; use 
+MHD_RESPMEM_PERSISTENT if the buffer is static/global memory,
+use MHD_RESPMEM_MUST_FREE if the buffer is heap-allocated and
+should be freed by @mhd{} and MHD_RESPMEM_MUST_COPY if the
+buffer is in transient memory (i.e. on the stack) and must
+be copied by @mhd{};
+@end table
+
+Return @mynull{} on error (i.e. invalid arguments, out of memory).
+@end deftypefun
+
+
 @deftypefun {struct MHD_Response *} MHD_create_response_from_data (size_t size, void *data, int must_free, int must_copy)
 Create a response object.  The response object can be extended with
 header information and then it can be used any number of times.
+This function is deprecated, use @code{MHD_create_response_from_buffer} instead.
 
 @table @var
 @item size
@@ -1385,8 +1437,8 @@ const char * data = "<html><body><p>Error!</p></body></html>";
 struct MHD_Connection * connection = ...;
 struct MHD_Response *   response;
 
-response = MHD_create_response_from_data(strlen(data), data,
-                                         MHD_NO, MHD_NO);
+response = MHD_create_response_from_buffer (strlen(data), data,
+                                            MHD_RESPMEM_PERSISTENT);
 MHD_queue_response(connection, 404, response);
 MHD_destroy_response(response);
 @end example
@@ -1599,9 +1651,9 @@ ahc_echo (void *cls,
   username = MHD_digest_auth_get_username(connection);
   if (username == NULL) 
     @{
-      response = MHD_create_response_from_data(strlen (DENIED), 
-					       DENIED,
-					       MHD_NO, MHD_NO);  
+      response = MHD_create_response_from_buffer(strlen (DENIED), 
+					         DENIED,
+					         MHD_RESPMEM_PERSISTENT);  
       ret = MHD_queue_auth_fail_response(connection, realm,
 					 OPAQUE,
 					 response,
@@ -1617,9 +1669,9 @@ ahc_echo (void *cls,
   if ( (ret == MHD_INVALID_NONCE) ||
        (ret == MHD_NO) )
     @{
-      response = MHD_create_response_from_data(strlen (DENIED), 
-					       DENIED,
-					       MHD_NO, MHD_NO);  
+      response = MHD_create_response_from_buffer(strlen (DENIED), 
+					         DENIED,
+					         MHD_RESPMEM_PERSISTENT);  
       if (NULL == response) 
 	return MHD_NO;
       ret = MHD_queue_auth_fail_response(connection, realm,
@@ -1629,8 +1681,8 @@ ahc_echo (void *cls,
       MHD_destroy_response(response);  
       return ret;
     @}
-  response = MHD_create_response_from_data(strlen(PAGE), PAGE,
-					   MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen(PAGE), PAGE,
+ 					      MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response(connection, MHD_HTTP_OK, response);  
   MHD_destroy_response(response);
   return ret;

+ 6 - 4
src/daemon/connection.c

@@ -716,8 +716,9 @@ transmit_error_response (struct MHD_Connection *connection,
             status_code, message);
 #endif
   EXTRA_CHECK (connection->response == NULL);
-  response = MHD_create_response_from_data (strlen (message),
-                                            (void *) message, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (message),
+					      (void *) message, 
+					      MHD_RESPMEM_PERSISTENT);
   MHD_queue_response (connection, status_code, response);
   EXTRA_CHECK (connection->response != NULL);
   MHD_destroy_response (response);
@@ -1663,8 +1664,9 @@ parse_connection_headers (struct MHD_Connection *connection)
 #endif
       EXTRA_CHECK (connection->response == NULL);
       response =
-        MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
-                                       REQUEST_LACKS_HOST, MHD_NO, MHD_NO);
+        MHD_create_response_from_buffer (strlen (REQUEST_LACKS_HOST),
+					 REQUEST_LACKS_HOST,
+					 MHD_RESPMEM_PERSISTENT);
       MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
       MHD_destroy_response (response);
       return;

+ 24 - 1
src/daemon/response.c

@@ -352,6 +352,7 @@ struct MHD_Response *MHD_create_response_from_fd (size_t size,
  *        right away, the data maybe released anytime after
  *        this call returns
  * @return NULL on error (i.e. invalid arguments, out of memory)
+ * @deprecated use MHD_create_response_from_buffer instead
  */
 struct MHD_Response *
 MHD_create_response_from_data (size_t size,
@@ -382,7 +383,7 @@ MHD_create_response_from_data (size_t size,
           return NULL;
         }
       memcpy (tmp, data, size);
-      must_free = 1;
+      must_free = MHD_YES;
       data = tmp;
     }
   retVal->crc = NULL;
@@ -395,6 +396,28 @@ MHD_create_response_from_data (size_t size,
   return retVal;
 }
 
+
+/**
+ * Create a response object.  The response object can be extended with
+ * header information and then be used any number of times.
+ *
+ * @param size size of the data portion of the response
+ * @param buffer size bytes containing the response's data portion
+ * @param mode flags for buffer management
+ * @return NULL on error (i.e. invalid arguments, out of memory)
+ */
+struct MHD_Response *
+MHD_create_response_from_buffer (size_t size,
+				 void *buffer,
+				 enum MHD_ResponseMemoryMode mode)
+{
+  return MHD_create_response_from_data (size,
+					buffer,
+					mode == MHD_RESPMEM_MUST_FREE,
+					mode == MHD_RESPMEM_MUST_COPY);
+}
+
+
 /**
  * Destroy a response object and associated resources.  Note that
  * libmicrohttpd may keep some of the resources around if the response

+ 6 - 5
src/examples/authorization_example.c

@@ -63,17 +63,18 @@ ahc_echo (void *cls,
       (0 != strcmp (auth, "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==")))
     {
       /* require: "Aladdin" with password "open sesame" */
-      response = MHD_create_response_from_data (strlen (DENIED),
-                                                (void *) DENIED, MHD_NO,
-                                                MHD_NO);
+      response = MHD_create_response_from_buffer (strlen (DENIED),
+						  (void *) DENIED, 
+						  MHD_RESPMEM_PERSISTENT);
       MHD_add_response_header (response, MHD_HTTP_HEADER_WWW_AUTHENTICATE,
                                "Basic realm=\"TestRealm\"");
       code = MHD_HTTP_UNAUTHORIZED;
     }
   else
     {
-      response = MHD_create_response_from_data (strlen (me),
-                                                (void *) me, MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (strlen (me),
+						  (void *) me, 
+						  MHD_RESPMEM_PERSISTENT);
       code = MHD_HTTP_OK;
     }
   ret = MHD_queue_response (connection, code, response);

+ 8 - 8
src/examples/digest_auth_example.c

@@ -49,9 +49,9 @@ ahc_echo (void *cls,
   username = MHD_digest_auth_get_username(connection);
   if (username == NULL) 
     {
-      response = MHD_create_response_from_data(strlen (DENIED), 
-					       DENIED,
-					       MHD_NO, MHD_NO);  
+      response = MHD_create_response_from_buffer(strlen (DENIED), 
+						 DENIED,
+						 MHD_RESPMEM_PERSISTENT);  
       ret = MHD_queue_auth_fail_response(connection, realm,
 					 OPAQUE,
 					 response,
@@ -67,9 +67,9 @@ ahc_echo (void *cls,
   if ( (ret == MHD_INVALID_NONCE) ||
        (ret == MHD_NO) )
     {
-      response = MHD_create_response_from_data(strlen (DENIED), 
-					       DENIED,
-					       MHD_NO, MHD_NO);  
+      response = MHD_create_response_from_buffer(strlen (DENIED), 
+						 DENIED,
+						 MHD_RESPMEM_PERSISTENT);  
       if (NULL == response) 
 	return MHD_NO;
       ret = MHD_queue_auth_fail_response(connection, realm,
@@ -79,8 +79,8 @@ ahc_echo (void *cls,
       MHD_destroy_response(response);  
       return ret;
     }
-  response = MHD_create_response_from_data(strlen(PAGE), PAGE,
-					   MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer(strlen(PAGE), PAGE,
+					     MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response(connection, MHD_HTTP_OK, response);  
   MHD_destroy_response(response);
   return ret;

+ 3 - 3
src/examples/fileserver_example.c

@@ -75,9 +75,9 @@ ahc_echo (void *cls,
     file = NULL;
   if (file == NULL)
     {
-      response = MHD_create_response_from_data (strlen (PAGE),
-                                                (void *) PAGE,
-                                                MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (strlen (PAGE),
+						  (void *) PAGE,
+						  MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
       MHD_destroy_response (response);
     }

+ 3 - 4
src/examples/fileserver_example_dirs.c

@@ -117,10 +117,9 @@ ahc_echo (void *cls,
 		    sizeof (emsg),
 		    "Failed to open directory `.': %s\n",
 		    strerror (errno));
-	  response = MHD_create_response_from_data (strlen (emsg),
-						    emsg,
-						    MHD_NO,
-						    MHD_YES);
+	  response = MHD_create_response_from_buffer (strlen (emsg),
+						      emsg,
+						      MHD_RESPMEM_MUST_COPY);
 	  if (response == NULL)
 	    return MHD_NO;	    
 	  ret = MHD_queue_response (connection, MHD_HTTP_SERVICE_UNAVAILABLE, response);

+ 3 - 3
src/examples/fileserver_example_external_select.c

@@ -76,9 +76,9 @@ ahc_echo (void *cls,
     file = NULL;
   if (file == NULL)
     {
-      response = MHD_create_response_from_data (strlen (PAGE),
-                                                (void *) PAGE,
-                                                MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (strlen (PAGE),
+						  (void *) PAGE,
+						  MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
       MHD_destroy_response (response);
     }

+ 3 - 3
src/examples/https_fileserver_example.c

@@ -144,9 +144,9 @@ http_ahc (void *cls,
     file = NULL;
   if (file == NULL)
     {
-      response = MHD_create_response_from_data (strlen (EMPTY_PAGE),
-                                                (void *) EMPTY_PAGE,
-                                                MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
+						  (void *) EMPTY_PAGE,
+						  MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
       MHD_destroy_response (response);
     }

+ 3 - 2
src/examples/minimal_example.c

@@ -49,8 +49,9 @@ ahc_echo (void *cls,
       return MHD_YES;
     }
   *ptr = NULL;                  /* reset when done */
-  response = MHD_create_response_from_data (strlen (me),
-                                            (void *) me, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (me),
+					      (void *) me,
+					      MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 2 - 1
src/examples/querystring_example.c

@@ -57,7 +57,8 @@ ahc_echo (void *cls,
   if (me == NULL)
     return MHD_NO;
   sprintf (me, fmt, "q", val);
-  response = MHD_create_response_from_data (strlen (me), me, MHD_YES, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (me), me,
+					      MHD_RESPMEM_MUST_FREE);
   if (response == NULL)
     {
       free (me);

+ 6 - 5
src/examples/refuse_post_example.c

@@ -56,9 +56,9 @@ ahc_echo (void *cls,
       /* always to busy for POST requests */
       if (0 == strcmp (method, "POST"))
         {
-          response = MHD_create_response_from_data (strlen (BUSYPAGE),
-                                                    (void *) BUSYPAGE, MHD_NO,
-                                                    MHD_NO);
+          response = MHD_create_response_from_buffer (strlen (BUSYPAGE),
+						      (void *) BUSYPAGE, 
+						      MHD_RESPMEM_PERSISTENT);
           ret =
             MHD_queue_response (connection, MHD_HTTP_SERVICE_UNAVAILABLE,
                                 response);
@@ -68,8 +68,9 @@ ahc_echo (void *cls,
     }
 
   *ptr = NULL;                  /* reset when done */
-  response = MHD_create_response_from_data (strlen (me),
-                                            (void *) me, MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (me),
+					      (void *) me,
+					      MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 50 - 0
src/include/microhttpd.h

@@ -1199,6 +1199,8 @@ struct MHD_Response *MHD_create_response_from_callback (uint64_t size,
                                                         MHD_ContentReaderFreeCallback
                                                         crfc);
 
+
+
 /**
  * Create a response object.  The response object can be extended with
  * header information and then be used any number of times.
@@ -1210,6 +1212,7 @@ struct MHD_Response *MHD_create_response_from_callback (uint64_t size,
  *        right away, the data maybe released anytime after
  *        this call returns
  * @return NULL on error (i.e. invalid arguments, out of memory)
+ * @deprecated use MHD_create_response_from_buffer instead
  */
 struct MHD_Response *MHD_create_response_from_data (size_t size,
                                                     void *data,
@@ -1217,6 +1220,52 @@ struct MHD_Response *MHD_create_response_from_data (size_t size,
                                                     int must_copy);
 
 
+/**
+ * Specification for how MHD should treat the memory buffer
+ * given for the response.
+ */
+enum MHD_ResponseMemoryMode {
+
+  /**
+   * Buffer is a persistent (static/global) buffer that won't change
+   * for at least the lifetime of the response, MHD should just use
+   * it, not free it, not copy it, just keep an alias to it.
+   */
+  MHD_RESPMEM_PERSISTENT,
+
+  /**
+   * Buffer is heap-allocated with 'malloc' (or equivalent) and
+   * should be freed by MHD after processing the response has
+   * concluded (response reference counter reaches zero).
+   */
+  MHD_RESPMEM_MUST_FREE,
+
+  /**
+   * Buffer is in transient memory, but not on the heap (for example,
+   * on the stack or non-malloc allocated) and only valid during the
+   * call to 'MHD_create_response_from_buffer'.  MHD must make its
+   * own private copy of the data for processing.
+   */
+  MHD_RESPMEM_MUST_COPY
+
+};
+
+
+/**
+ * Create a response object.  The response object can be extended with
+ * header information and then be used any number of times.
+ *
+ * @param size size of the data portion of the response
+ * @param buffer size bytes containing the response's data portion
+ * @param mode flags for buffer management
+ * @return NULL on error (i.e. invalid arguments, out of memory)
+ */
+struct MHD_Response *
+MHD_create_response_from_buffer (size_t size,
+				 void *buffer,
+				 enum MHD_ResponseMemoryMode mode);
+
+
 /**
  * Create a response object.  The response object can be extended with
  * header information and then be used any number of times.
@@ -1224,6 +1273,7 @@ struct MHD_Response *MHD_create_response_from_data (size_t size,
  * @param size size of the data portion of the response
  * @param fd file descriptor referring to a file on disk with the data; will be closed when response is destroyed
  * @return NULL on error (i.e. invalid arguments, out of memory)
+ * @deprecated use MHD_create_response_from_fd_at_offset instead
  */
 struct MHD_Response *MHD_create_response_from_fd (size_t size,
 						  int fd);

+ 8 - 8
src/testcurl/daemontest_digestauth.c

@@ -81,9 +81,9 @@ ahc_echo (void *cls,
   if ( (username == NULL) ||
        (0 != strcmp (username, "testuser")) )
     {
-      response = MHD_create_response_from_data(strlen (DENIED), 
-					       DENIED,
-					       MHD_NO, MHD_NO);  
+      response = MHD_create_response_from_buffer(strlen (DENIED), 
+						 DENIED,
+						 MHD_RESPMEM_PERSISTENT);  
       ret = MHD_queue_auth_fail_response(connection, realm,
 					 OPAQUE,
 					 response,
@@ -99,9 +99,9 @@ ahc_echo (void *cls,
   if ( (ret == MHD_INVALID_NONCE) ||
        (ret == MHD_NO) )
     {
-      response = MHD_create_response_from_data(strlen (DENIED), 
-					       DENIED,
-					       MHD_NO, MHD_NO);  
+      response = MHD_create_response_from_buffer(strlen (DENIED), 
+						 DENIED,
+						 MHD_RESPMEM_PERSISTENT);  
       if (NULL == response) 
 	return MHD_NO;
       ret = MHD_queue_auth_fail_response(connection, realm,
@@ -111,8 +111,8 @@ ahc_echo (void *cls,
       MHD_destroy_response(response);  
       return ret;
     }
-  response = MHD_create_response_from_data(strlen(PAGE), PAGE,
-					   MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer(strlen(PAGE), PAGE,
+					     MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response(connection, MHD_HTTP_OK, response);  
   MHD_destroy_response(response);
   return ret;

+ 3 - 2
src/testcurl/daemontest_get.c

@@ -85,8 +85,9 @@ ahc_echo (void *cls,
       return MHD_YES;
     }
   *unused = NULL;
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   if (ret == MHD_NO)

+ 3 - 2
src/testcurl/daemontest_iplimit.c

@@ -80,8 +80,9 @@ ahc_echo (void *cls,
       return MHD_YES;
     }
   *unused = NULL;
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   if (ret == MHD_NO)

+ 3 - 2
src/testcurl/daemontest_large_put.c

@@ -122,8 +122,9 @@ ahc_echo (void *cls,
       *done = 1;
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url, 
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testcurl/daemontest_long_header.c

@@ -79,8 +79,9 @@ ahc_echo (void *cls,
 
   if (0 != strcmp (me, method))
     return MHD_NO;              /* unexpected method */
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testcurl/daemontest_parse_cookies.c

@@ -95,8 +95,9 @@ ahc_echo (void *cls,
   hdr = MHD_lookup_connection_value (connection, MHD_COOKIE_KIND, "name4");
   if ((hdr == NULL) || (0 != strcmp (hdr, "var4 with spaces")))
     abort ();
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   if (ret == MHD_NO)

+ 5 - 4
src/testcurl/daemontest_post.c

@@ -113,9 +113,9 @@ ahc_echo (void *cls,
   MHD_post_process (pp, upload_data, *upload_data_size);
   if ((eok == 3) && (0 == *upload_data_size))
     {
-      response = MHD_create_response_from_data (strlen (url),
-                                                (void *) url,
-                                                MHD_NO, MHD_YES);
+      response = MHD_create_response_from_buffer (strlen (url),
+						  (void *) url,
+						  MHD_RESPMEM_MUST_COPY);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
       MHD_destroy_response (response);
       MHD_destroy_post_processor (pp);
@@ -432,7 +432,8 @@ ahc_cancel (void *cls,
     {
       *unused = "wibble";
       /* We don't want the body. Send a 500. */
-      response = MHD_create_response_from_data(0, NULL, 0, 0);
+      response = MHD_create_response_from_buffer (0, NULL, 
+						  MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response(connection, 500, response);
       if (ret != MHD_YES)
 	fprintf(stderr, "Failed to queue response\n");

+ 2 - 1
src/testcurl/daemontest_post_loop.c

@@ -83,7 +83,8 @@ ahc_echo (void *cls,
     {
       if (*mptr != &marker)
         abort ();
-      response = MHD_create_response_from_data (2, "OK", MHD_NO, MHD_NO);
+      response = MHD_create_response_from_buffer (2, "OK", 
+						  MHD_RESPMEM_PERSISTENT);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
       MHD_destroy_response (response);
       *mptr = NULL;

+ 3 - 3
src/testcurl/daemontest_postform.c

@@ -116,9 +116,9 @@ ahc_echo (void *cls,
   MHD_post_process (pp, upload_data, *upload_data_size);
   if ((eok == 3) && (0 == *upload_data_size))
     {
-      response = MHD_create_response_from_data (strlen (url),
-                                                (void *) url,
-                                                MHD_NO, MHD_YES);
+      response = MHD_create_response_from_buffer (strlen (url),
+						  (void *) url,
+						  MHD_RESPMEM_MUST_COPY);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
       MHD_destroy_response (response);
       MHD_destroy_post_processor (pp);

+ 3 - 2
src/testcurl/daemontest_process_arguments.c

@@ -88,8 +88,9 @@ ahc_echo (void *cls,
                                      MHD_GET_ARGUMENT_KIND, "hash");
   if ((hdr == NULL) || (0 != strcmp (hdr, "#")))
     abort ();
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url, 
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   if (ret == MHD_NO)

+ 3 - 2
src/testcurl/daemontest_process_headers.c

@@ -115,8 +115,9 @@ ahc_echo (void *cls,
   if ((hdr == NULL) || (0 != strcmp (hdr, "NowPresent")))
     abort ();
 
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   MHD_add_response_header (response, "MyHeader", "MyValue");
   hdr = MHD_get_response_header (response, "MyHeader");
   if (0 != strcmp ("MyValue", hdr))

+ 2 - 2
src/testcurl/daemontest_put.c

@@ -102,8 +102,8 @@ ahc_echo (void *cls,
       *done = 1;
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url), (void*) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testcurl/daemontest_put_chunked.c

@@ -111,8 +111,9 @@ ahc_echo (void *cls,
 #endif
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 2 - 1
src/testcurl/daemontest_termination.c

@@ -65,7 +65,8 @@ connection_handler (void *cls,
     }
 
   struct MHD_Response *response =
-    MHD_create_response_from_data (strlen ("Response"), "Response", 0, 0);
+    MHD_create_response_from_buffer (strlen ("Response"), "Response",
+				     MHD_RESPMEM_PERSISTENT);
   int ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
 

+ 3 - 2
src/testcurl/daemontest_timeout.c

@@ -113,8 +113,9 @@ ahc_echo (void *cls,
       *done = 1;
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url, 
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testcurl/https/mhds_get_test_select.c

@@ -61,8 +61,9 @@ ahc_echo (void *cls,
       return MHD_YES;
     }
   *unused = NULL;
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   if (ret == MHD_NO)

+ 3 - 3
src/testcurl/https/mhds_session_info_test.c

@@ -78,9 +78,9 @@ query_session_ahc (void *cls, struct MHD_Connection *connection,
       return -1;
     }
 
-  response = MHD_create_response_from_data (strlen (EMPTY_PAGE),
-                                            (void *) EMPTY_PAGE,
-                                            MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (EMPTY_PAGE),
+					      (void *) EMPTY_PAGE,
+					      MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 3
src/testcurl/https/tls_test_common.c

@@ -178,9 +178,9 @@ http_ahc (void *cls, struct MHD_Connection *connection,
       return MHD_YES;
     }
   *ptr = NULL;                  /* reset when done */
-  response = MHD_create_response_from_data (strlen (test_data),
-					    (void *) test_data,
-					    MHD_NO, MHD_NO);
+  response = MHD_create_response_from_buffer (strlen (test_data),
+					      (void *) test_data,
+					      MHD_RESPMEM_PERSISTENT);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testzzuf/daemontest_get.c

@@ -81,8 +81,9 @@ ahc_echo (void *cls,
       return MHD_YES;
     }
   *unused = NULL;
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   if (ret == MHD_NO)

+ 3 - 2
src/testzzuf/daemontest_large_put.c

@@ -119,8 +119,9 @@ ahc_echo (void *cls,
       *done = 1;
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url, 
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testzzuf/daemontest_long_header.c

@@ -81,8 +81,9 @@ ahc_echo (void *cls,
 
   if (0 != strcmp (me, method))
     return MHD_NO;              /* unexpected method */
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 3
src/testzzuf/daemontest_post.c

@@ -115,9 +115,9 @@ ahc_echo (void *cls,
   MHD_post_process (pp, upload_data, *upload_data_size);
   if ((eok == 3) && (0 == *upload_data_size))
     {
-      response = MHD_create_response_from_data (strlen (url),
-                                                (void *) url,
-                                                MHD_NO, MHD_YES);
+      response = MHD_create_response_from_buffer (strlen (url),
+						  (void *) url,
+						  MHD_RESPMEM_MUST_COPY);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
       MHD_destroy_response (response);
       MHD_destroy_post_processor (pp);

+ 3 - 3
src/testzzuf/daemontest_postform.c

@@ -120,9 +120,9 @@ ahc_echo (void *cls,
   MHD_post_process (pp, upload_data, *upload_data_size);
   if ((eok == 3) && (0 == *upload_data_size))
     {
-      response = MHD_create_response_from_data (strlen (url),
-                                                (void *) url,
-                                                MHD_NO, MHD_YES);
+      response = MHD_create_response_from_buffer (strlen (url),
+						  (void *) url,
+						  MHD_RESPMEM_MUST_COPY);
       ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
       MHD_destroy_response (response);
       MHD_destroy_post_processor (pp);

+ 3 - 2
src/testzzuf/daemontest_put.c

@@ -105,8 +105,9 @@ ahc_echo (void *cls,
       *done = 1;
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;

+ 3 - 2
src/testzzuf/daemontest_put_chunked.c

@@ -111,8 +111,9 @@ ahc_echo (void *cls,
 #endif
       return MHD_YES;
     }
-  response = MHD_create_response_from_data (strlen (url),
-                                            (void *) url, MHD_NO, MHD_YES);
+  response = MHD_create_response_from_buffer (strlen (url),
+					      (void *) url,
+					      MHD_RESPMEM_MUST_COPY);
   ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
   MHD_destroy_response (response);
   return ret;