diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | src/daemon/Makefile.am | 2 | ||||
-rw-r--r-- | src/daemon/daemon.c | 53 | ||||
-rw-r--r-- | src/daemon/daemontest_get.c | 13 | ||||
-rw-r--r-- | src/daemon/daemontest_post.c | 12 | ||||
-rw-r--r-- | src/daemon/daemontest_put.c | 12 | ||||
-rw-r--r-- | src/daemon/fileserver_example.c | 1 | ||||
-rw-r--r-- | src/daemon/internal.h | 14 | ||||
-rw-r--r-- | src/daemon/response.c | 23 | ||||
-rw-r--r-- | src/include/microhttpd.h | 15 |
11 files changed, 127 insertions, 27 deletions
@@ -1,3 +1,8 @@ | |||
1 | Wed Aug 15 01:46:44 MDT 2007 | ||
2 | Extending API to allow timeout of connections. | ||
3 | Changed API (MHD_create_response_from_callback) to | ||
4 | allow user to specify IO buffer size. - CG | ||
5 | |||
1 | Tue Aug 14 19:45:49 MDT 2007 | 6 | Tue Aug 14 19:45:49 MDT 2007 |
2 | Changed license to LGPL (with consent from all contributors). | 7 | Changed license to LGPL (with consent from all contributors). |
3 | Released libmicrohttpd 0.0.2. - CG | 8 | Released libmicrohttpd 0.0.2. - CG |
diff --git a/configure.ac b/configure.ac index b87f8d95..44afee9e 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -21,8 +21,8 @@ | |||
21 | # | 21 | # |
22 | # | 22 | # |
23 | AC_PREREQ(2.57) | 23 | AC_PREREQ(2.57) |
24 | AC_INIT([libmicrohttpd], [0.0.1],[libmicrohttpd@gnunet.org]) | 24 | AC_INIT([libmicrohttpd], [0.0.3],[libmicrohttpd@gnunet.org]) |
25 | AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.1]) | 25 | AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.3]) |
26 | AM_CONFIG_HEADER([config.h]) | 26 | AM_CONFIG_HEADER([config.h]) |
27 | 27 | ||
28 | AH_TOP([#define _GNU_SOURCE 1]) | 28 | AH_TOP([#define _GNU_SOURCE 1]) |
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am index 0f11b662..8a0aa4b2 100644 --- a/src/daemon/Makefile.am +++ b/src/daemon/Makefile.am | |||
@@ -6,7 +6,7 @@ lib_LTLIBRARIES = \ | |||
6 | libmicrohttpd.la | 6 | libmicrohttpd.la |
7 | 7 | ||
8 | libmicrohttpd_la_LDFLAGS = \ | 8 | libmicrohttpd_la_LDFLAGS = \ |
9 | -export-dynamic -version-info 0:1:0 | 9 | -export-dynamic -version-info 1:0:0 |
10 | libmicrohttpd_la_SOURCES = \ | 10 | libmicrohttpd_la_SOURCES = \ |
11 | connection.c connection.h \ | 11 | connection.c connection.h \ |
12 | daemon.c \ | 12 | daemon.c \ |
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index 3caade12..0c198454 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -163,20 +163,35 @@ MHD_handle_connection (void *data) | |||
163 | fd_set ws; | 163 | fd_set ws; |
164 | fd_set es; | 164 | fd_set es; |
165 | int max; | 165 | int max; |
166 | struct timeval tv; | ||
167 | unsigned int timeout; | ||
168 | time_t now; | ||
166 | 169 | ||
167 | if (con == NULL) | 170 | if (con == NULL) |
168 | abort (); | 171 | abort (); |
169 | while ((!con->daemon->shutdown) && (con->socket_fd != -1)) | 172 | timeout = con->daemon->connection_timeout; |
173 | now = time(NULL); | ||
174 | while ( (!con->daemon->shutdown) && | ||
175 | (con->socket_fd != -1) && | ||
176 | ( (timeout == 0) || | ||
177 | (now - timeout > con->last_activity) ) ) | ||
170 | { | 178 | { |
171 | FD_ZERO (&rs); | 179 | FD_ZERO (&rs); |
172 | FD_ZERO (&ws); | 180 | FD_ZERO (&ws); |
173 | FD_ZERO (&es); | 181 | FD_ZERO (&es); |
174 | max = 0; | 182 | max = 0; |
175 | MHD_connection_get_fdset (con, &rs, &ws, &es, &max); | 183 | MHD_connection_get_fdset (con, &rs, &ws, &es, &max); |
176 | num_ready = SELECT (max + 1, &rs, &ws, &es, NULL); | 184 | tv.tv_usec = 0; |
177 | if (num_ready <= 0) | 185 | tv.tv_sec = timeout - (now - con->last_activity); |
186 | num_ready = SELECT (max + 1, | ||
187 | &rs, | ||
188 | &ws, | ||
189 | &es, | ||
190 | (tv.tv_sec != 0) ? &tv : NULL); | ||
191 | now = time(NULL); | ||
192 | if (num_ready < 0) | ||
178 | { | 193 | { |
179 | if (errno == EINTR) | 194 | if (errno == EINTR) |
180 | continue; | 195 | continue; |
181 | break; | 196 | break; |
182 | } | 197 | } |
@@ -188,6 +203,10 @@ MHD_handle_connection (void *data) | |||
188 | break; | 203 | break; |
189 | if ((con->headersReceived == 1) && (con->response == NULL)) | 204 | if ((con->headersReceived == 1) && (con->response == NULL)) |
190 | MHD_call_connection_handler (con); | 205 | MHD_call_connection_handler (con); |
206 | if ( (con->socket_fd != -1) && | ||
207 | ( (FD_ISSET (con->socket_fd, &rs)) || | ||
208 | (FD_ISSET (con->socket_fd, &ws)) ) ) | ||
209 | con->last_activity = now; | ||
191 | } | 210 | } |
192 | if (con->socket_fd != -1) | 211 | if (con->socket_fd != -1) |
193 | { | 212 | { |
@@ -261,6 +280,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
261 | free (connection); | 280 | free (connection); |
262 | return MHD_NO; | 281 | return MHD_NO; |
263 | } | 282 | } |
283 | connection->last_activity = time(NULL); | ||
264 | connection->next = daemon->connections; | 284 | connection->next = daemon->connections; |
265 | daemon->connections = connection; | 285 | daemon->connections = connection; |
266 | daemon->max_connections--; | 286 | daemon->max_connections--; |
@@ -284,11 +304,22 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
284 | struct MHD_Connection *pos; | 304 | struct MHD_Connection *pos; |
285 | struct MHD_Connection *prev; | 305 | struct MHD_Connection *prev; |
286 | void *unused; | 306 | void *unused; |
307 | time_t timeout; | ||
287 | 308 | ||
309 | timeout = time(NULL); | ||
310 | if (daemon->connection_timeout != 0) | ||
311 | timeout -= daemon->connection_timeout; | ||
312 | else | ||
313 | timeout = 0; | ||
288 | pos = daemon->connections; | 314 | pos = daemon->connections; |
289 | prev = NULL; | 315 | prev = NULL; |
290 | while (pos != NULL) | 316 | while (pos != NULL) |
291 | { | 317 | { |
318 | if ( (pos->last_activity < timeout) && | ||
319 | (pos->socket_fd != -1) ) { | ||
320 | CLOSE(pos->socket_fd); | ||
321 | pos->socket_fd = -1; | ||
322 | } | ||
292 | if (pos->socket_fd == -1) | 323 | if (pos->socket_fd == -1) |
293 | { | 324 | { |
294 | if (prev == NULL) | 325 | if (prev == NULL) |
@@ -339,6 +370,7 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
339 | int max; | 370 | int max; |
340 | struct timeval timeout; | 371 | struct timeval timeout; |
341 | int ds; | 372 | int ds; |
373 | time_t now; | ||
342 | 374 | ||
343 | timeout.tv_sec = 0; | 375 | timeout.tv_sec = 0; |
344 | timeout.tv_usec = 0; | 376 | timeout.tv_usec = 0; |
@@ -378,6 +410,7 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
378 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | 410 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
379 | { | 411 | { |
380 | /* do not have a thread per connection, process all connections now */ | 412 | /* do not have a thread per connection, process all connections now */ |
413 | now = time(NULL); | ||
381 | pos = daemon->connections; | 414 | pos = daemon->connections; |
382 | while (pos != NULL) | 415 | while (pos != NULL) |
383 | { | 416 | { |
@@ -387,10 +420,14 @@ MHD_select (struct MHD_Daemon *daemon, int may_block) | |||
387 | pos = pos->next; | 420 | pos = pos->next; |
388 | continue; | 421 | continue; |
389 | } | 422 | } |
390 | if (FD_ISSET (ds, &rs)) | 423 | if (FD_ISSET (ds, &rs)) { |
424 | pos->last_activity = now; | ||
391 | MHD_connection_handle_read (pos); | 425 | MHD_connection_handle_read (pos); |
392 | if (FD_ISSET (ds, &ws)) | 426 | } |
427 | if (FD_ISSET (ds, &ws)) { | ||
428 | pos->last_activity = now; | ||
393 | MHD_connection_handle_write (pos); | 429 | MHD_connection_handle_write (pos); |
430 | } | ||
394 | pos = pos->next; | 431 | pos = pos->next; |
395 | } | 432 | } |
396 | } | 433 | } |
@@ -530,6 +567,7 @@ MHD_start_daemon (unsigned int options, | |||
530 | retVal->default_handler.next = NULL; | 567 | retVal->default_handler.next = NULL; |
531 | retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; | 568 | retVal->max_connections = MHD_MAX_CONNECTIONS_DEFAULT; |
532 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; | 569 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; |
570 | retVal->connection_timeout = 0; /* no timeout */ | ||
533 | va_start (ap, dh_cls); | 571 | va_start (ap, dh_cls); |
534 | while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) | 572 | while (MHD_OPTION_END != (opt = va_arg (ap, enum MHD_OPTION))) |
535 | { | 573 | { |
@@ -541,6 +579,9 @@ MHD_start_daemon (unsigned int options, | |||
541 | case MHD_OPTION_CONNECTION_LIMIT: | 579 | case MHD_OPTION_CONNECTION_LIMIT: |
542 | retVal->max_connections = va_arg (ap, unsigned int); | 580 | retVal->max_connections = va_arg (ap, unsigned int); |
543 | break; | 581 | break; |
582 | case MHD_OPTION_CONNECTION_TIMEOUT: | ||
583 | retVal->connection_timeout = va_arg (ap, unsigned int); | ||
584 | break; | ||
544 | default: | 585 | default: |
545 | fprintf (stderr, | 586 | fprintf (stderr, |
546 | "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); | 587 | "Invalid MHD_OPTION argument! (Did you terminate the list with MHD_OPTION_END?)\n"); |
diff --git a/src/daemon/daemontest_get.c b/src/daemon/daemontest_get.c index c144d368..daea7a39 100644 --- a/src/daemon/daemontest_get.c +++ b/src/daemon/daemontest_get.c | |||
@@ -86,6 +86,7 @@ testInternalGet () | |||
86 | CURL *c; | 86 | CURL *c; |
87 | char buf[2048]; | 87 | char buf[2048]; |
88 | struct CBC cbc; | 88 | struct CBC cbc; |
89 | CURLcode errornum; | ||
89 | 90 | ||
90 | cbc.buf = buf; | 91 | cbc.buf = buf; |
91 | cbc.size = 2048; | 92 | cbc.size = 2048; |
@@ -109,8 +110,11 @@ testInternalGet () | |||
109 | // setting NOSIGNAL results in really weird | 110 | // setting NOSIGNAL results in really weird |
110 | // crashes on my system! | 111 | // crashes on my system! |
111 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | 112 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); |
112 | if (CURLE_OK != curl_easy_perform (c)) | 113 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
113 | { | 114 | { |
115 | fprintf(stderr, | ||
116 | "curl_easy_perform failed: `%s'\n", | ||
117 | curl_easy_strerror(errornum)); | ||
114 | curl_easy_cleanup (c); | 118 | curl_easy_cleanup (c); |
115 | MHD_stop_daemon (d); | 119 | MHD_stop_daemon (d); |
116 | return 2; | 120 | return 2; |
@@ -139,6 +143,7 @@ testMultithreadedGet () | |||
139 | CURL *c; | 143 | CURL *c; |
140 | char buf[2048]; | 144 | char buf[2048]; |
141 | struct CBC cbc; | 145 | struct CBC cbc; |
146 | CURLcode errornum; | ||
142 | 147 | ||
143 | cbc.buf = buf; | 148 | cbc.buf = buf; |
144 | cbc.size = 2048; | 149 | cbc.size = 2048; |
@@ -162,8 +167,12 @@ testMultithreadedGet () | |||
162 | // setting NOSIGNAL results in really weird | 167 | // setting NOSIGNAL results in really weird |
163 | // crashes on my system! | 168 | // crashes on my system! |
164 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | 169 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); |
165 | if (CURLE_OK != curl_easy_perform (c)) | 170 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
166 | { | 171 | { |
172 | fprintf(stderr, | ||
173 | "curl_easy_perform failed: `%s'\n", | ||
174 | curl_easy_strerror(errornum)); | ||
175 | curl_easy_cleanup (c); | ||
167 | MHD_stop_daemon (d); | 176 | MHD_stop_daemon (d); |
168 | return 32; | 177 | return 32; |
169 | } | 178 | } |
diff --git a/src/daemon/daemontest_post.c b/src/daemon/daemontest_post.c index 19c79556..eed25e1d 100644 --- a/src/daemon/daemontest_post.c +++ b/src/daemon/daemontest_post.c | |||
@@ -105,6 +105,7 @@ testInternalPost () | |||
105 | CURL *c; | 105 | CURL *c; |
106 | char buf[2048]; | 106 | char buf[2048]; |
107 | struct CBC cbc; | 107 | struct CBC cbc; |
108 | CURLcode errornum; | ||
108 | 109 | ||
109 | cbc.buf = buf; | 110 | cbc.buf = buf; |
110 | cbc.size = 2048; | 111 | cbc.size = 2048; |
@@ -131,8 +132,11 @@ testInternalPost () | |||
131 | // setting NOSIGNAL results in really weird | 132 | // setting NOSIGNAL results in really weird |
132 | // crashes on my system! | 133 | // crashes on my system! |
133 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | 134 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); |
134 | if (CURLE_OK != curl_easy_perform (c)) | 135 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
135 | { | 136 | { |
137 | fprintf(stderr, | ||
138 | "curl_easy_perform failed: `%s'\n", | ||
139 | curl_easy_strerror(errornum)); | ||
136 | curl_easy_cleanup (c); | 140 | curl_easy_cleanup (c); |
137 | MHD_stop_daemon (d); | 141 | MHD_stop_daemon (d); |
138 | return 2; | 142 | return 2; |
@@ -161,6 +165,7 @@ testMultithreadedPost () | |||
161 | CURL *c; | 165 | CURL *c; |
162 | char buf[2048]; | 166 | char buf[2048]; |
163 | struct CBC cbc; | 167 | struct CBC cbc; |
168 | CURLcode errornum; | ||
164 | 169 | ||
165 | cbc.buf = buf; | 170 | cbc.buf = buf; |
166 | cbc.size = 2048; | 171 | cbc.size = 2048; |
@@ -187,8 +192,11 @@ testMultithreadedPost () | |||
187 | // setting NOSIGNAL results in really weird | 192 | // setting NOSIGNAL results in really weird |
188 | // crashes on my system! | 193 | // crashes on my system! |
189 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | 194 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); |
190 | if (CURLE_OK != curl_easy_perform (c)) | 195 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
191 | { | 196 | { |
197 | fprintf(stderr, | ||
198 | "curl_easy_perform failed: `%s'\n", | ||
199 | curl_easy_strerror(errornum)); | ||
192 | curl_easy_cleanup (c); | 200 | curl_easy_cleanup (c); |
193 | MHD_stop_daemon (d); | 201 | MHD_stop_daemon (d); |
194 | return 32; | 202 | return 32; |
diff --git a/src/daemon/daemontest_put.c b/src/daemon/daemontest_put.c index 17a2f1c4..7c047887 100644 --- a/src/daemon/daemontest_put.c +++ b/src/daemon/daemontest_put.c | |||
@@ -117,6 +117,7 @@ testInternalPut () | |||
117 | struct CBC cbc; | 117 | struct CBC cbc; |
118 | unsigned int pos = 0; | 118 | unsigned int pos = 0; |
119 | int done_flag = 0; | 119 | int done_flag = 0; |
120 | CURLcode errornum; | ||
120 | 121 | ||
121 | cbc.buf = buf; | 122 | cbc.buf = buf; |
122 | cbc.size = 2048; | 123 | cbc.size = 2048; |
@@ -145,8 +146,11 @@ testInternalPut () | |||
145 | // setting NOSIGNAL results in really weird | 146 | // setting NOSIGNAL results in really weird |
146 | // crashes on my system! | 147 | // crashes on my system! |
147 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | 148 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); |
148 | if (CURLE_OK != curl_easy_perform (c)) | 149 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
149 | { | 150 | { |
151 | fprintf(stderr, | ||
152 | "curl_easy_perform failed: `%s'\n", | ||
153 | curl_easy_strerror(errornum)); | ||
150 | curl_easy_cleanup (c); | 154 | curl_easy_cleanup (c); |
151 | MHD_stop_daemon (d); | 155 | MHD_stop_daemon (d); |
152 | return 2; | 156 | return 2; |
@@ -177,6 +181,7 @@ testMultithreadedPut () | |||
177 | struct CBC cbc; | 181 | struct CBC cbc; |
178 | unsigned int pos = 0; | 182 | unsigned int pos = 0; |
179 | int done_flag = 0; | 183 | int done_flag = 0; |
184 | CURLcode errornum; | ||
180 | 185 | ||
181 | cbc.buf = buf; | 186 | cbc.buf = buf; |
182 | cbc.size = 2048; | 187 | cbc.size = 2048; |
@@ -205,8 +210,11 @@ testMultithreadedPut () | |||
205 | // setting NOSIGNAL results in really weird | 210 | // setting NOSIGNAL results in really weird |
206 | // crashes on my system! | 211 | // crashes on my system! |
207 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); | 212 | curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1); |
208 | if (CURLE_OK != curl_easy_perform (c)) | 213 | if (CURLE_OK != (errornum = curl_easy_perform (c))) |
209 | { | 214 | { |
215 | fprintf(stderr, | ||
216 | "curl_easy_perform failed: `%s'\n", | ||
217 | curl_easy_strerror(errornum)); | ||
210 | curl_easy_cleanup (c); | 218 | curl_easy_cleanup (c); |
211 | MHD_stop_daemon (d); | 219 | MHD_stop_daemon (d); |
212 | return 32; | 220 | return 32; |
diff --git a/src/daemon/fileserver_example.c b/src/daemon/fileserver_example.c index 6f39f491..7574cd20 100644 --- a/src/daemon/fileserver_example.c +++ b/src/daemon/fileserver_example.c | |||
@@ -74,6 +74,7 @@ ahc_echo (void *cls, | |||
74 | { | 74 | { |
75 | stat (&url[1], &buf); | 75 | stat (&url[1], &buf); |
76 | response = MHD_create_response_from_callback (buf.st_size, | 76 | response = MHD_create_response_from_callback (buf.st_size, |
77 | 32 * 1024, /* 32k page size */ | ||
77 | &file_reader, | 78 | &file_reader, |
78 | file, | 79 | file, |
79 | (MHD_ContentReaderFreeCallback) | 80 | (MHD_ContentReaderFreeCallback) |
diff --git a/src/daemon/internal.h b/src/daemon/internal.h index b4e3698e..c4180d3b 100644 --- a/src/daemon/internal.h +++ b/src/daemon/internal.h | |||
@@ -54,6 +54,8 @@ | |||
54 | 54 | ||
55 | /** | 55 | /** |
56 | * Size by which MHD usually tries to increment read/write buffers. | 56 | * Size by which MHD usually tries to increment read/write buffers. |
57 | * TODO: we should probably get rid of this magic constant and | ||
58 | * put in code to automatically determine a good value. | ||
57 | */ | 59 | */ |
58 | #define MHD_BUF_INC_SIZE 2048 | 60 | #define MHD_BUF_INC_SIZE 2048 |
59 | 61 | ||
@@ -294,6 +296,12 @@ struct MHD_Connection | |||
294 | socklen_t addr_len; | 296 | socklen_t addr_len; |
295 | 297 | ||
296 | /** | 298 | /** |
299 | * Last time this connection had any activity | ||
300 | * (reading or writing). | ||
301 | */ | ||
302 | time_t last_activity; | ||
303 | |||
304 | /** | ||
297 | * Socket for this connection. Set to -1 if | 305 | * Socket for this connection. Set to -1 if |
298 | * this connection has died (daemon should clean | 306 | * this connection has died (daemon should clean |
299 | * up in that case). | 307 | * up in that case). |
@@ -385,6 +393,12 @@ struct MHD_Daemon | |||
385 | unsigned int max_connections; | 393 | unsigned int max_connections; |
386 | 394 | ||
387 | /** | 395 | /** |
396 | * After how many seconds of inactivity should | ||
397 | * connections time out? Zero for no timeout. | ||
398 | */ | ||
399 | unsigned int connection_timeout; | ||
400 | |||
401 | /** | ||
388 | * Daemon's options. | 402 | * Daemon's options. |
389 | */ | 403 | */ |
390 | enum MHD_OPTION options; | 404 | enum MHD_OPTION options; |
diff --git a/src/daemon/response.c b/src/daemon/response.c index f52bb2df..3adb6bc9 100644 --- a/src/daemon/response.c +++ b/src/daemon/response.c | |||
@@ -148,6 +148,11 @@ MHD_get_response_header (struct MHD_Response *response, const char *key) | |||
148 | * header information and then be used any number of times. | 148 | * header information and then be used any number of times. |
149 | * | 149 | * |
150 | * @param size size of the data portion of the response, -1 for unknown | 150 | * @param size size of the data portion of the response, -1 for unknown |
151 | * @param block_size preferred block size for querying crc (advisory only, | ||
152 | * MHD may still call crc using smaller chunks); this | ||
153 | * is essentially the buffer size used for IO, clients | ||
154 | * should pick a value that is appropriate for IO and | ||
155 | * memory performance requirements | ||
151 | * @param crc callback to use to obtain response data | 156 | * @param crc callback to use to obtain response data |
152 | * @param crc_cls extra argument to crc | 157 | * @param crc_cls extra argument to crc |
153 | * @param crfc callback to call to free crc_cls resources | 158 | * @param crfc callback to call to free crc_cls resources |
@@ -155,26 +160,24 @@ MHD_get_response_header (struct MHD_Response *response, const char *key) | |||
155 | */ | 160 | */ |
156 | struct MHD_Response * | 161 | struct MHD_Response * |
157 | MHD_create_response_from_callback (size_t size, | 162 | MHD_create_response_from_callback (size_t size, |
163 | unsigned int block_size, | ||
158 | MHD_ContentReaderCallback crc, | 164 | MHD_ContentReaderCallback crc, |
159 | void *crc_cls, | 165 | void *crc_cls, |
160 | MHD_ContentReaderFreeCallback crfc) | 166 | MHD_ContentReaderFreeCallback crfc) |
161 | { | 167 | { |
162 | struct MHD_Response *retVal; | 168 | struct MHD_Response *retVal; |
163 | 169 | ||
164 | if (crc == NULL) | 170 | if ( (crc == NULL) || |
171 | (block_size == 0) ) | ||
172 | return NULL; | ||
173 | retVal = malloc (sizeof (struct MHD_Response) + block_size); | ||
174 | if (retVal == NULL) | ||
165 | return NULL; | 175 | return NULL; |
166 | retVal = malloc (sizeof (struct MHD_Response)); | ||
167 | memset (retVal, 0, sizeof (struct MHD_Response)); | 176 | memset (retVal, 0, sizeof (struct MHD_Response)); |
168 | retVal->data = malloc (MHD_BUF_INC_SIZE); | 177 | retVal->data = (void*) &retVal[1]; |
169 | if (retVal->data == NULL) | ||
170 | { | ||
171 | free (retVal); | ||
172 | return NULL; | ||
173 | } | ||
174 | retVal->data_buffer_size = MHD_BUF_INC_SIZE; | 178 | retVal->data_buffer_size = MHD_BUF_INC_SIZE; |
175 | if (pthread_mutex_init (&retVal->mutex, NULL) != 0) | 179 | if (pthread_mutex_init (&retVal->mutex, NULL) != 0) |
176 | { | 180 | { |
177 | free (retVal->data); | ||
178 | free (retVal); | 181 | free (retVal); |
179 | return NULL; | 182 | return NULL; |
180 | } | 183 | } |
@@ -262,8 +265,6 @@ MHD_destroy_response (struct MHD_Response *response) | |||
262 | free (pos->value); | 265 | free (pos->value); |
263 | free (pos); | 266 | free (pos); |
264 | } | 267 | } |
265 | if (response->crc != NULL) | ||
266 | free (response->data); | ||
267 | free (response); | 268 | free (response); |
268 | } | 269 | } |
269 | 270 | ||
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h index eb96e807..76c1be0b 100644 --- a/src/include/microhttpd.h +++ b/src/include/microhttpd.h | |||
@@ -62,7 +62,7 @@ extern "C" | |||
62 | /** | 62 | /** |
63 | * Current version of the library. | 63 | * Current version of the library. |
64 | */ | 64 | */ |
65 | #define MHD_VERSION 0x00000000 | 65 | #define MHD_VERSION 0x00000003 |
66 | 66 | ||
67 | /** | 67 | /** |
68 | * MHD-internal return codes. | 68 | * MHD-internal return codes. |
@@ -279,6 +279,13 @@ enum MHD_OPTION | |||
279 | */ | 279 | */ |
280 | MHD_OPTION_CONNECTION_LIMIT = 2, | 280 | MHD_OPTION_CONNECTION_LIMIT = 2, |
281 | 281 | ||
282 | /** | ||
283 | * After how many seconds of inactivity should a | ||
284 | * connection automatically be timed out? (followed | ||
285 | * by an unsigned int; use zero for no timeout). | ||
286 | */ | ||
287 | MHD_OPTION_CONNECTION_TIMEOUT = 3, | ||
288 | |||
282 | }; | 289 | }; |
283 | 290 | ||
284 | /** | 291 | /** |
@@ -560,12 +567,18 @@ MHD_queue_response (struct MHD_Connection *connection, | |||
560 | * header information and then be used any number of times. | 567 | * header information and then be used any number of times. |
561 | * | 568 | * |
562 | * @param size size of the data portion of the response, -1 for unknown | 569 | * @param size size of the data portion of the response, -1 for unknown |
570 | * @param block_size preferred block size for querying crc (advisory only, | ||
571 | * MHD may still call crc using smaller chunks); this | ||
572 | * is essentially the buffer size used for IO, clients | ||
573 | * should pick a value that is appropriate for IO and | ||
574 | * memory performance requirements | ||
563 | * @param crc callback to use to obtain response data | 575 | * @param crc callback to use to obtain response data |
564 | * @param crc_cls extra argument to crc | 576 | * @param crc_cls extra argument to crc |
565 | * @param crfc callback to call to free crc_cls resources | 577 | * @param crfc callback to call to free crc_cls resources |
566 | * @return NULL on error (i.e. invalid arguments, out of memory) | 578 | * @return NULL on error (i.e. invalid arguments, out of memory) |
567 | */ | 579 | */ |
568 | struct MHD_Response *MHD_create_response_from_callback (size_t size, | 580 | struct MHD_Response *MHD_create_response_from_callback (size_t size, |
581 | unsigned int block_size, | ||
569 | MHD_ContentReaderCallback | 582 | MHD_ContentReaderCallback |
570 | crc, void *crc_cls, | 583 | crc, void *crc_cls, |
571 | MHD_ContentReaderFreeCallback | 584 | MHD_ContentReaderFreeCallback |