aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--doc/microhttpd.texi25
-rw-r--r--src/daemon/connection.c20
-rw-r--r--src/examples/fileserver_example_dirs.c2
-rw-r--r--src/examples/minimal_example_comet.c2
-rw-r--r--src/include/microhttpd.h40
-rw-r--r--src/testcurl/daemontest_get_chunked.c4
-rw-r--r--src/testzzuf/daemontest_get_chunked.c4
8 files changed, 85 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index fdd30848..da5a23f0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
1Wed Nov 17 12:16:53 CET 2010
2 Allowing signalling of errors in generating chunked responses to
3 clients (by closing connectins) using the new
4 MHD_CONTENT_READER_END_WITH_ERROR ((size_t)-2) return value. Also
5 introducing MHD_CONTENT_READER_END_OF_STREAM constant instead
6 of (size_t) -1 / SIZE_MAX.
7
1Sun Nov 14 20:45:45 CET 2010 8Sun Nov 14 20:45:45 CET 2010
2 Adding API call to generate HTTP footers in response. -CG 9 Adding API call to generate HTTP footers in response. -CG
3 10
diff --git a/doc/microhttpd.texi b/doc/microhttpd.texi
index a2df1136..9f509814 100644
--- a/doc/microhttpd.texi
+++ b/doc/microhttpd.texi
@@ -857,7 +857,7 @@ iteration.
857@end deftypefn 857@end deftypefn
858 858
859 859
860@deftypefn {Function Pointer} int {*MHD_ContentReaderCallback} (void *cls, uint64_t pos, char *buf, int max) 860@deftypefn {Function Pointer} int {*MHD_ContentReaderCallback} (void *cls, uint64_t pos, char *buf, size_t max)
861Callback used by @mhd{} in order to obtain content. The callback has to 861Callback used by @mhd{} in order to obtain content. The callback has to
862copy at most @var{max} bytes of content into @var{buf}. The total 862copy at most @var{max} bytes of content into @var{buf}. The total
863number of bytes that has been placed into @var{buf} should be returned. 863number of bytes that has been placed into @var{buf} should be returned.
@@ -870,6 +870,29 @@ that runs in internal @cfunction{select} mode is an error (since it
870would result in busy waiting) and cause the program to be aborted 870would result in busy waiting) and cause the program to be aborted
871(@cfunction{abort}). 871(@cfunction{abort}).
872 872
873While usually the callback simply returns the number of bytes written
874into @var{buf}, there are two special return value:
875
876@code{MHD_CONTENT_READER_END_OF_STREAM} (-1) should be returned
877for the regular end of transmission (with chunked encoding, MHD will then
878terminate the chunk and send any HTTP footers that might be
879present; without chunked encoding and given an unknown
880response size, @mhd{} will simply close the connection; note
881that while returning @code{MHD_CONTENT_READER_END_OF_STREAM} is not technically
882legal if a response size was specified, MHD accepts this
883and treats it just as @code{MHD_CONTENT_READER_END_WITH_ERROR}.
884
885@code{MHD_CONTENT_READER_END_WITH_ERROR} (-2) is used to indicate a server
886error generating the response; this will cause @mhd{} to simply
887close the connection immediately. If a response size was
888given or if chunked encoding is in use, this will indicate
889an error to the client. Note, however, that if the client
890does not know a response size and chunked encoding is not in
891use, then clients will not be able to tell the difference between
892@code{MHD_CONTENT_READER_END_WITH_ERROR} and
893@code{MHD_CONTENT_READER_END_OF_STREAM}.
894This is not a limitation of @mhd{} but rather of the HTTP protocol.
895
873@table @var 896@table @var
874@item cls 897@item cls
875custom value selected at callback registration time; 898custom value selected at callback registration time;
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index cd8b6141..247ec178 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -357,14 +357,15 @@ try_ready_normal_body (struct MHD_Connection *connection)
357 NULL 357 NULL
358#endif 358#endif
359 ); 359 );
360 if (ret == -1) 360 if ( (ret == MHD_CONTENT_READER_END_OF_STREAM) ||
361 (ret == MHD_CONTENT_READER_END_WITH_ERROR) )
361 { 362 {
362 /* either error or http 1.0 transfer, close 363 /* either error or http 1.0 transfer, close
363 socket! */ 364 socket! */
364#if DEBUG_CLOSE 365#if DEBUG_CLOSE
365#if HAVE_MESSAGES 366#if HAVE_MESSAGES
366 MHD_DLOG (connection->daemon, 367 MHD_DLOG (connection->daemon,
367 "Closing connection (end of response)\n"); 368 "Closing connection (end of response or error)\n");
368#endif 369#endif
369#endif 370#endif
370 response->total_size = connection->response_write_position; 371 response->total_size = connection->response_write_position;
@@ -444,7 +445,20 @@ try_ready_chunked_body (struct MHD_Connection *connection)
444 &connection->write_buffer[sizeof (cbuf)], 445 &connection->write_buffer[sizeof (cbuf)],
445 connection->write_buffer_size - sizeof (cbuf) - 2); 446 connection->write_buffer_size - sizeof (cbuf) - 2);
446 } 447 }
447 if (ret == -1) 448 if (ret == MHD_CONTENT_READER_END_WITH_ERROR)
449 {
450 /* error, close socket! */
451#if DEBUG_CLOSE
452#if HAVE_MESSAGES
453 MHD_DLOG (connection->daemon,
454 "Closing connection (error generating response)\n");
455#endif
456#endif
457 response->total_size = connection->response_write_position;
458 connection_close_error (connection);
459 return MHD_NO;
460 }
461 if (ret == MHD_CONTENT_READER_END_OF_STREAM)
448 { 462 {
449 /* end of message, signal other side! */ 463 /* end of message, signal other side! */
450 strcpy (connection->write_buffer, "0\r\n"); 464 strcpy (connection->write_buffer, "0\r\n");
diff --git a/src/examples/fileserver_example_dirs.c b/src/examples/fileserver_example_dirs.c
index 8c874994..836c0623 100644
--- a/src/examples/fileserver_example_dirs.c
+++ b/src/examples/fileserver_example_dirs.c
@@ -66,7 +66,7 @@ dir_reader (void *cls, uint64_t pos, char *buf, size_t max)
66 { 66 {
67 e = readdir (dir); 67 e = readdir (dir);
68 if (e == NULL) 68 if (e == NULL)
69 return -1; 69 return MHD_CONTENT_READER_END_OF_STREAM;
70 } while (e->d_name[0] == '.'); 70 } while (e->d_name[0] == '.');
71 return snprintf (buf, max, 71 return snprintf (buf, max,
72 "<a href=\"/%s\">%s</a><br>", 72 "<a href=\"/%s\">%s</a><br>",
diff --git a/src/examples/minimal_example_comet.c b/src/examples/minimal_example_comet.c
index 9b25889e..83493243 100644
--- a/src/examples/minimal_example_comet.c
+++ b/src/examples/minimal_example_comet.c
@@ -56,7 +56,7 @@ ahc_echo (void *cls,
56 return MHD_YES; 56 return MHD_YES;
57 } 57 }
58 *ptr = NULL; /* reset when done */ 58 *ptr = NULL; /* reset when done */
59 response = MHD_create_response_from_callback (-1, 59 response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
60 80, 60 80,
61 &data_generator, NULL, NULL); 61 &data_generator, NULL, NULL);
62 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 62 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index 1b1a986d..7d99948e 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -133,6 +133,15 @@ extern "C"
133#define MHD_SIZE_UNKNOWN ((uint64_t) -1LL) 133#define MHD_SIZE_UNKNOWN ((uint64_t) -1LL)
134#endif 134#endif
135 135
136#ifdef SIZE_MAX
137#define MHD_CONTENT_READER_END_OF_STREAM SIZE_MAX
138#define MHD_CONTENT_READER_END_WITH_ERROR (SIZE_MAX - 1)
139#else
140#define MHD_CONTENT_READER_END ((size_t) -1LL)
141#define MHD_CONTENT_READER_END_WITH_ERROR (((size_t) -LL) - 1)
142#endif
143
144
136/** 145/**
137 * HTTP response codes. 146 * HTTP response codes.
138 */ 147 */
@@ -868,15 +877,28 @@ typedef int
868 * obtained from the content reader so far. 877 * obtained from the content reader so far.
869 * @param buf where to copy the data 878 * @param buf where to copy the data
870 * @param max maximum number of bytes to copy to buf (size of buf) 879 * @param max maximum number of bytes to copy to buf (size of buf)
871 * @return -1 for the end of transmission (or on error); 880 * @return number of bytes written to 'buf';
872 * if a content transfer size was pre-set and the callback 881 * 0 is legal unless we are running in internal select mode (since
873 * has provided fewer than that amount of data, 882 * this would cause busy-waiting); 0 in external select mode
874 * MHD will close the connection with the client; 883 * will cause this function to be called again once the external
875 * if no content size was specified and this is an 884 * select calls MHD again;
876 * http 1.1 connection using chunked encoding, MHD will 885 * MHD_CONTENT_READER_END_OF_STREAM (-1) for the regular
877 * interpret "-1" as the normal end of the transfer 886 * end of transmission (with chunked encoding, MHD will then
878 * (possibly allowing the client to perform additional 887 * terminate the chunk and send any HTTP footers that might be
879 * requests using the same TCP connection). 888 * present; without chunked encoding and given an unknown
889 * response size, MHD will simply close the connection; note
890 * that while returning END_OF_STREAM is not technically
891 * legal if a response size was specified, MHD accepts this
892 * and treats it just as MHD_CONTENT_READER_END_WITH_ERROR;
893 * MHD_CONTENT_READER_END_WITH_ERROR (-2) to indicate a server
894 * error generating the response; this will cause MHD to simply
895 * close the connection immediately. If a response size was
896 * given or if chunked encoding is in use, this will indicate
897 * an error to the client. Note, however, that if the client
898 * does not know a response size and chunked encoding is not in
899 * use, then clients will not be able to tell the difference between
900 * MHD_CONTENT_READER_END_WITH_ERROR and MHD_CONTENT_READER_END_OF_STREAM.
901 * This is not a limitation of MHD but rather of the HTTP protocol.
880 */ 902 */
881typedef ssize_t 903typedef ssize_t
882 (*MHD_ContentReaderCallback) (void *cls, 904 (*MHD_ContentReaderCallback) (void *cls,
diff --git a/src/testcurl/daemontest_get_chunked.c b/src/testcurl/daemontest_get_chunked.c
index e5b1a73a..fd2561ca 100644
--- a/src/testcurl/daemontest_get_chunked.c
+++ b/src/testcurl/daemontest_get_chunked.c
@@ -71,7 +71,7 @@ crc (void *cls, uint64_t pos, char *buf, size_t max)
71 if (pos == 128 * 10) 71 if (pos == 128 * 10)
72 { 72 {
73 MHD_add_response_header (*responseptr, "Footer", "working"); 73 MHD_add_response_header (*responseptr, "Footer", "working");
74 return -1; /* end of stream */ 74 return MHD_CONTENT_READER_END_OF_STREAM;
75 } 75 }
76 if (max < 128) 76 if (max < 128)
77 abort (); /* should not happen in this testcase... */ 77 abort (); /* should not happen in this testcase... */
@@ -113,7 +113,7 @@ ahc_echo (void *cls,
113 responseptr = malloc (sizeof (struct MHD_Response *)); 113 responseptr = malloc (sizeof (struct MHD_Response *));
114 if (responseptr == NULL) 114 if (responseptr == NULL)
115 return MHD_NO; 115 return MHD_NO;
116 response = MHD_create_response_from_callback (-1, 116 response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
117 1024, 117 1024,
118 &crc, responseptr, &crcf); 118 &crc, responseptr, &crcf);
119 *responseptr = response; 119 *responseptr = response;
diff --git a/src/testzzuf/daemontest_get_chunked.c b/src/testzzuf/daemontest_get_chunked.c
index 655f402a..35eed49d 100644
--- a/src/testzzuf/daemontest_get_chunked.c
+++ b/src/testzzuf/daemontest_get_chunked.c
@@ -69,7 +69,7 @@ crc (void *cls, uint64_t pos, char *buf, size_t max)
69 if (pos == 128 * 10) 69 if (pos == 128 * 10)
70 { 70 {
71 MHD_add_response_header (*responseptr, "Footer", "working"); 71 MHD_add_response_header (*responseptr, "Footer", "working");
72 return -1; /* end of stream */ 72 return MHD_CONTENT_READER_END_OF_STREAM;
73 } 73 }
74 if (max < 128) 74 if (max < 128)
75 abort (); /* should not happen in this testcase... */ 75 abort (); /* should not happen in this testcase... */
@@ -109,7 +109,7 @@ ahc_echo (void *cls,
109 return MHD_YES; 109 return MHD_YES;
110 } 110 }
111 responseptr = malloc (sizeof (struct MHD_Response *)); 111 responseptr = malloc (sizeof (struct MHD_Response *));
112 response = MHD_create_response_from_callback (-1, 112 response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
113 1024, 113 1024,
114 &crc, responseptr, &crcf); 114 &crc, responseptr, &crcf);
115 *responseptr = response; 115 *responseptr = response;