aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--configure.ac4
-rw-r--r--src/daemon/Makefile.am2
-rw-r--r--src/daemon/daemon.c53
-rw-r--r--src/daemon/daemontest_get.c13
-rw-r--r--src/daemon/daemontest_post.c12
-rw-r--r--src/daemon/daemontest_put.c12
-rw-r--r--src/daemon/fileserver_example.c1
-rw-r--r--src/daemon/internal.h14
-rw-r--r--src/daemon/response.c23
-rw-r--r--src/include/microhttpd.h15
11 files changed, 127 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 405a772c..cc6ae7b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
1Wed 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
1Tue Aug 14 19:45:49 MDT 2007 6Tue 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#
23AC_PREREQ(2.57) 23AC_PREREQ(2.57)
24AC_INIT([libmicrohttpd], [0.0.1],[libmicrohttpd@gnunet.org]) 24AC_INIT([libmicrohttpd], [0.0.3],[libmicrohttpd@gnunet.org])
25AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.1]) 25AM_INIT_AUTOMAKE([libmicrohttpd], [0.0.3])
26AM_CONFIG_HEADER([config.h]) 26AM_CONFIG_HEADER([config.h])
27 27
28AH_TOP([#define _GNU_SOURCE 1]) 28AH_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
8libmicrohttpd_la_LDFLAGS = \ 8libmicrohttpd_la_LDFLAGS = \
9 -export-dynamic -version-info 0:1:0 9 -export-dynamic -version-info 1:0:0
10libmicrohttpd_la_SOURCES = \ 10libmicrohttpd_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 */
156struct MHD_Response * 161struct MHD_Response *
157MHD_create_response_from_callback (size_t size, 162MHD_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 */
568struct MHD_Response *MHD_create_response_from_callback (size_t size, 580struct 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