aboutsummaryrefslogtreecommitdiff
path: root/src/lib/connection_call_handlers.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/connection_call_handlers.c')
-rw-r--r--src/lib/connection_call_handlers.c4026
1 files changed, 2029 insertions, 1997 deletions
diff --git a/src/lib/connection_call_handlers.c b/src/lib/connection_call_handlers.c
index af8860d6..c4fb448e 100644
--- a/src/lib/connection_call_handlers.c
+++ b/src/lib/connection_call_handlers.c
@@ -56,7 +56,8 @@
56 * minimal. 56 * minimal.
57 */ 57 */
58#ifdef HAVE_MESSAGES 58#ifdef HAVE_MESSAGES
59#define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>" 59#define REQUEST_TOO_BIG \
60 "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
60#else 61#else
61#define REQUEST_TOO_BIG "" 62#define REQUEST_TOO_BIG ""
62#endif 63#endif
@@ -69,7 +70,8 @@
69 * minimal. 70 * minimal.
70 */ 71 */
71#ifdef HAVE_MESSAGES 72#ifdef HAVE_MESSAGES
72#define REQUEST_LACKS_HOST "<html><head><title>&quot;Host:&quot; header required</title></head><body>In HTTP 1.1, requests must include a &quot;Host:&quot; header, and your HTTP 1.1 request lacked such a header.</body></html>" 73#define REQUEST_LACKS_HOST \
74 "<html><head><title>&quot;Host:&quot; header required</title></head><body>In HTTP 1.1, requests must include a &quot;Host:&quot; header, and your HTTP 1.1 request lacked such a header.</body></html>"
73#else 75#else
74#define REQUEST_LACKS_HOST "" 76#define REQUEST_LACKS_HOST ""
75#endif 77#endif
@@ -82,7 +84,8 @@
82 * minimal. 84 * minimal.
83 */ 85 */
84#ifdef HAVE_MESSAGES 86#ifdef HAVE_MESSAGES
85#define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>" 87#define REQUEST_MALFORMED \
88 "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
86#else 89#else
87#define REQUEST_MALFORMED "" 90#define REQUEST_MALFORMED ""
88#endif 91#endif
@@ -94,7 +97,8 @@
94 * minimal. 97 * minimal.
95 */ 98 */
96#ifdef HAVE_MESSAGES 99#ifdef HAVE_MESSAGES
97#define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>" 100#define INTERNAL_ERROR \
101 "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
98#else 102#else
99#define INTERNAL_ERROR "" 103#define INTERNAL_ERROR ""
100#endif 104#endif
@@ -128,17 +132,18 @@ MHD_conn_init_static_ (void)
128#ifdef SF_FLAGS 132#ifdef SF_FLAGS
129 long sys_page_size = sysconf (_SC_PAGESIZE); 133 long sys_page_size = sysconf (_SC_PAGESIZE);
130 if (0 > sys_page_size) 134 if (0 > sys_page_size)
131 { /* Failed to get page size. */ 135 { /* Failed to get page size. */
132 freebsd_sendfile_flags_ = SF_NODISKIO; 136 freebsd_sendfile_flags_ = SF_NODISKIO;
133 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO; 137 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
134 } 138 }
135 else 139 else
136 { 140 {
137 freebsd_sendfile_flags_ = 141 freebsd_sendfile_flags_ =
138 SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO); 142 SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
139 freebsd_sendfile_flags_thd_p_c_ = 143 freebsd_sendfile_flags_thd_p_c_ =
140 SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size), SF_NODISKIO); 144 SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size),
141 } 145 SF_NODISKIO);
146 }
142#endif /* SF_FLAGS */ 147#endif /* SF_FLAGS */
143} 148}
144#endif /* HAVE_FREEBSD_SENDFILE */ 149#endif /* HAVE_FREEBSD_SENDFILE */
@@ -161,13 +166,13 @@ MHD_conn_init_static_ (void)
161 */ 166 */
162static void 167static void
163connection_close_error (struct MHD_Connection *connection, 168connection_close_error (struct MHD_Connection *connection,
164 enum MHD_StatusCode sc, 169 enum MHD_StatusCode sc,
165 const char *emsg) 170 const char *emsg)
166{ 171{
167#ifdef HAVE_MESSAGES 172#ifdef HAVE_MESSAGES
168 if (NULL != emsg) 173 if (NULL != emsg)
169 MHD_DLOG (connection->daemon, 174 MHD_DLOG (connection->daemon,
170 sc, 175 sc,
171 emsg); 176 emsg);
172#else /* ! HAVE_MESSAGES */ 177#else /* ! HAVE_MESSAGES */
173 (void) emsg; /* Mute compiler warning. */ 178 (void) emsg; /* Mute compiler warning. */
@@ -209,8 +214,8 @@ try_grow_read_buffer (struct MHD_Request *request)
209 if (0 == request->read_buffer_size) 214 if (0 == request->read_buffer_size)
210 new_size = daemon->connection_memory_limit_b / 2; 215 new_size = daemon->connection_memory_limit_b / 2;
211 else 216 else
212 new_size = request->read_buffer_size + 217 new_size = request->read_buffer_size
213 daemon->connection_memory_increment_b; 218 + daemon->connection_memory_increment_b;
214 buf = MHD_pool_reallocate (request->connection->pool, 219 buf = MHD_pool_reallocate (request->connection->pool,
215 request->read_buffer, 220 request->read_buffer,
216 request->read_buffer_size, 221 request->read_buffer_size,
@@ -245,16 +250,16 @@ MHD_request_handle_read_ (struct MHD_Request *request)
245 struct MHD_TLS_Plugin *tls; 250 struct MHD_TLS_Plugin *tls;
246 251
247 if ( (NULL != (tls = daemon->tls_api)) && 252 if ( (NULL != (tls = daemon->tls_api)) &&
248 (! tls->handshake (tls->cls, 253 (! tls->handshake (tls->cls,
249 connection->tls_cs)) ) 254 connection->tls_cs)) )
250 return; 255 return;
251 } 256 }
252#endif /* HTTPS_SUPPORT */ 257#endif /* HTTPS_SUPPORT */
253 258
254 /* make sure "read" has a reasonable number of bytes 259 /* make sure "read" has a reasonable number of bytes
255 in buffer to use per system call (if possible) */ 260 in buffer to use per system call (if possible) */
256 if (request->read_buffer_offset + 261 if (request->read_buffer_offset
257 daemon->connection_memory_increment_b > 262 + daemon->connection_memory_increment_b >
258 request->read_buffer_size) 263 request->read_buffer_size)
259 try_grow_read_buffer (request); 264 try_grow_read_buffer (request);
260 265
@@ -263,82 +268,84 @@ MHD_request_handle_read_ (struct MHD_Request *request)
263 bytes_read = connection->recv_cls (connection, 268 bytes_read = connection->recv_cls (connection,
264 &request->read_buffer 269 &request->read_buffer
265 [request->read_buffer_offset], 270 [request->read_buffer_offset],
266 request->read_buffer_size - 271 request->read_buffer_size
267 request->read_buffer_offset); 272 - request->read_buffer_offset);
268 if (bytes_read < 0) 273 if (bytes_read < 0)
274 {
275 if (MHD_ERR_AGAIN_ == bytes_read)
276 return; /* No new data to process. */
277 if (MHD_ERR_CONNRESET_ == bytes_read)
269 { 278 {
270 if (MHD_ERR_AGAIN_ == bytes_read)
271 return; /* No new data to process. */
272 if (MHD_ERR_CONNRESET_ == bytes_read)
273 {
274 CONNECTION_CLOSE_ERROR (connection,
275 (MHD_REQUEST_INIT == request->state)
276 ? MHD_SC_CONNECTION_CLOSED
277 : MHD_SC_CONNECTION_RESET_CLOSED,
278 (MHD_REQUEST_INIT == request->state)
279 ? NULL
280 : _("Socket disconnected while reading request.\n"));
281 return;
282 }
283 CONNECTION_CLOSE_ERROR (connection, 279 CONNECTION_CLOSE_ERROR (connection,
284 (MHD_REQUEST_INIT == request->state)
285 ? MHD_SC_CONNECTION_CLOSED
286 : MHD_SC_CONNECTION_READ_FAIL_CLOSED,
287 (MHD_REQUEST_INIT == request->state) 280 (MHD_REQUEST_INIT == request->state)
288 ? NULL 281 ? MHD_SC_CONNECTION_CLOSED
289 : _("Connection socket is closed due to error when reading request.\n")); 282 : MHD_SC_CONNECTION_RESET_CLOSED,
283 (MHD_REQUEST_INIT == request->state)
284 ? NULL
285 : _ (
286 "Socket disconnected while reading request.\n"));
290 return; 287 return;
291 } 288 }
289 CONNECTION_CLOSE_ERROR (connection,
290 (MHD_REQUEST_INIT == request->state)
291 ? MHD_SC_CONNECTION_CLOSED
292 : MHD_SC_CONNECTION_READ_FAIL_CLOSED,
293 (MHD_REQUEST_INIT == request->state)
294 ? NULL
295 : _ (
296 "Connection socket is closed due to error when reading request.\n"));
297 return;
298 }
292 299
293 if (0 == bytes_read) 300 if (0 == bytes_read)
294 { /* Remote side closed connection. */ 301 { /* Remote side closed connection. */
295 connection->read_closed = true; 302 connection->read_closed = true;
296 MHD_connection_close_ (connection, 303 MHD_connection_close_ (connection,
297 MHD_REQUEST_TERMINATED_CLIENT_ABORT); 304 MHD_REQUEST_TERMINATED_CLIENT_ABORT);
298 return; 305 return;
299 } 306 }
300 request->read_buffer_offset += bytes_read; 307 request->read_buffer_offset += bytes_read;
301 MHD_connection_update_last_activity_ (connection); 308 MHD_connection_update_last_activity_ (connection);
302#if DEBUG_STATES 309#if DEBUG_STATES
303 MHD_DLOG (daemon, 310 MHD_DLOG (daemon,
304 MHD_SC_STATE_MACHINE_STATUS_REPORT, 311 MHD_SC_STATE_MACHINE_STATUS_REPORT,
305 _("In function %s handling connection at state: %s\n"), 312 _ ("In function %s handling connection at state: %s\n"),
306 __FUNCTION__, 313 __FUNCTION__,
307 MHD_state_to_string (request->state)); 314 MHD_state_to_string (request->state));
308#endif 315#endif
309 switch (request->state) 316 switch (request->state)
317 {
318 case MHD_REQUEST_INIT:
319 case MHD_REQUEST_URL_RECEIVED:
320 case MHD_REQUEST_HEADER_PART_RECEIVED:
321 case MHD_REQUEST_HEADERS_RECEIVED:
322 case MHD_REQUEST_HEADERS_PROCESSED:
323 case MHD_REQUEST_CONTINUE_SENDING:
324 case MHD_REQUEST_CONTINUE_SENT:
325 case MHD_REQUEST_BODY_RECEIVED:
326 case MHD_REQUEST_FOOTER_PART_RECEIVED:
327 /* nothing to do but default action */
328 if (connection->read_closed)
310 { 329 {
311 case MHD_REQUEST_INIT: 330 MHD_connection_close_ (connection,
312 case MHD_REQUEST_URL_RECEIVED: 331 MHD_REQUEST_TERMINATED_READ_ERROR);
313 case MHD_REQUEST_HEADER_PART_RECEIVED: 332 }
314 case MHD_REQUEST_HEADERS_RECEIVED: 333 return;
315 case MHD_REQUEST_HEADERS_PROCESSED: 334 case MHD_REQUEST_CLOSED:
316 case MHD_REQUEST_CONTINUE_SENDING: 335 return;
317 case MHD_REQUEST_CONTINUE_SENT:
318 case MHD_REQUEST_BODY_RECEIVED:
319 case MHD_REQUEST_FOOTER_PART_RECEIVED:
320 /* nothing to do but default action */
321 if (connection->read_closed)
322 {
323 MHD_connection_close_ (connection,
324 MHD_REQUEST_TERMINATED_READ_ERROR);
325 }
326 return;
327 case MHD_REQUEST_CLOSED:
328 return;
329#ifdef UPGRADE_SUPPORT 336#ifdef UPGRADE_SUPPORT
330 case MHD_REQUEST_UPGRADE: 337 case MHD_REQUEST_UPGRADE:
331 mhd_assert (0); 338 mhd_assert (0);
332 return; 339 return;
333#endif /* UPGRADE_SUPPORT */ 340#endif /* UPGRADE_SUPPORT */
334 default: 341 default:
335 /* shrink read buffer to how much is actually used */ 342 /* shrink read buffer to how much is actually used */
336 MHD_pool_reallocate (connection->pool, 343 MHD_pool_reallocate (connection->pool,
337 request->read_buffer, 344 request->read_buffer,
338 request->read_buffer_size + 1, 345 request->read_buffer_size + 1,
339 request->read_buffer_offset); 346 request->read_buffer_offset);
340 break; 347 break;
341 } 348 }
342 return; 349 return;
343} 350}
344 351
@@ -361,9 +368,9 @@ sendfile_adapter (struct MHD_Connection *connection)
361 uint64_t left; 368 uint64_t left;
362 uint64_t offsetu64; 369 uint64_t offsetu64;
363#ifndef HAVE_SENDFILE64 370#ifndef HAVE_SENDFILE64
364 const uint64_t max_off_t = (uint64_t)OFF_T_MAX; 371 const uint64_t max_off_t = (uint64_t) OFF_T_MAX;
365#else /* HAVE_SENDFILE64 */ 372#else /* HAVE_SENDFILE64 */
366 const uint64_t max_off_t = (uint64_t)OFF64_T_MAX; 373 const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
367#endif /* HAVE_SENDFILE64 */ 374#endif /* HAVE_SENDFILE64 */
368#ifdef MHD_LINUX_SOLARIS_SENDFILE 375#ifdef MHD_LINUX_SOLARIS_SENDFILE
369#ifndef HAVE_SENDFILE64 376#ifndef HAVE_SENDFILE64
@@ -379,8 +386,10 @@ sendfile_adapter (struct MHD_Connection *connection)
379#ifdef HAVE_DARWIN_SENDFILE 386#ifdef HAVE_DARWIN_SENDFILE
380 off_t len; 387 off_t len;
381#endif /* HAVE_DARWIN_SENDFILE */ 388#endif /* HAVE_DARWIN_SENDFILE */
382 const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode); 389 const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION ==
383 const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : MHD_SENFILE_CHUNK_; 390 daemon->threading_mode);
391 const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ :
392 MHD_SENFILE_CHUNK_;
384 size_t send_size = 0; 393 size_t send_size = 0;
385 394
386 mhd_assert (MHD_resp_sender_sendfile == request->resp_sender); 395 mhd_assert (MHD_resp_sender_sendfile == request->resp_sender);
@@ -390,10 +399,10 @@ sendfile_adapter (struct MHD_Connection *connection)
390 * use 128KiB chunks (2MiB for thread-per-connection). */ 399 * use 128KiB chunks (2MiB for thread-per-connection). */
391 send_size = (left > chunk_size) ? chunk_size : (size_t) left; 400 send_size = (left > chunk_size) ? chunk_size : (size_t) left;
392 if (max_off_t < offsetu64) 401 if (max_off_t < offsetu64)
393 { /* Retry to send with standard 'send()'. */ 402 { /* Retry to send with standard 'send()'. */
394 request->resp_sender = MHD_resp_sender_std; 403 request->resp_sender = MHD_resp_sender_std;
395 return MHD_ERR_AGAIN_; 404 return MHD_ERR_AGAIN_;
396 } 405 }
397#ifdef MHD_LINUX_SOLARIS_SENDFILE 406#ifdef MHD_LINUX_SOLARIS_SENDFILE
398#ifndef HAVE_SENDFILE64 407#ifndef HAVE_SENDFILE64
399 offset = (off_t) offsetu64; 408 offset = (off_t) offsetu64;
@@ -409,54 +418,54 @@ sendfile_adapter (struct MHD_Connection *connection)
409 send_size); 418 send_size);
410#endif /* HAVE_SENDFILE64 */ 419#endif /* HAVE_SENDFILE64 */
411 if (0 > ret) 420 if (0 > ret)
412 { 421 {
413 const int err = MHD_socket_get_error_(); 422 const int err = MHD_socket_get_error_ ();
414 423
415 if (MHD_SCKT_ERR_IS_EAGAIN_(err)) 424 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
416 { 425 {
417#ifdef EPOLL_SUPPORT 426#ifdef EPOLL_SUPPORT
418 /* EAGAIN --- no longer write-ready */ 427 /* EAGAIN --- no longer write-ready */
419 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; 428 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
420#endif /* EPOLL_SUPPORT */ 429#endif /* EPOLL_SUPPORT */
421 return MHD_ERR_AGAIN_; 430 return MHD_ERR_AGAIN_;
422 } 431 }
423 if (MHD_SCKT_ERR_IS_EINTR_ (err)) 432 if (MHD_SCKT_ERR_IS_EINTR_ (err))
424 return MHD_ERR_AGAIN_; 433 return MHD_ERR_AGAIN_;
425#ifdef HAVE_LINUX_SENDFILE 434#ifdef HAVE_LINUX_SENDFILE
426 if (MHD_SCKT_ERR_IS_(err, 435 if (MHD_SCKT_ERR_IS_ (err,
427 MHD_SCKT_EBADF_)) 436 MHD_SCKT_EBADF_))
428 return MHD_ERR_BADF_; 437 return MHD_ERR_BADF_;
429 /* sendfile() failed with EINVAL if mmap()-like operations are not 438 /* sendfile() failed with EINVAL if mmap()-like operations are not
430 supported for FD or other 'unusual' errors occurred, so we should try 439 supported for FD or other 'unusual' errors occurred, so we should try
431 to fall back to 'SEND'; see also this thread for info on 440 to fall back to 'SEND'; see also this thread for info on
432 odd libc/Linux behavior with sendfile: 441 odd libc/Linux behavior with sendfile:
433 http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */ 442 http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
443 request->resp_sender = MHD_resp_sender_std;
444 return MHD_ERR_AGAIN_;
445#else /* HAVE_SOLARIS_SENDFILE */
446 if ( (EAFNOSUPPORT == err) ||
447 (EINVAL == err) ||
448 (EOPNOTSUPP == err) )
449 { /* Retry with standard file reader. */
434 request->resp_sender = MHD_resp_sender_std; 450 request->resp_sender = MHD_resp_sender_std;
435 return MHD_ERR_AGAIN_; 451 return MHD_ERR_AGAIN_;
436#else /* HAVE_SOLARIS_SENDFILE */
437 if ( (EAFNOSUPPORT == err) ||
438 (EINVAL == err) ||
439 (EOPNOTSUPP == err) )
440 { /* Retry with standard file reader. */
441 request->resp_sender = MHD_resp_sender_std;
442 return MHD_ERR_AGAIN_;
443 }
444 if ( (ENOTCONN == err) ||
445 (EPIPE == err) )
446 {
447 return MHD_ERR_CONNRESET_;
448 }
449 return MHD_ERR_BADF_; /* Fail hard */
450#endif /* HAVE_SOLARIS_SENDFILE */
451 } 452 }
453 if ( (ENOTCONN == err) ||
454 (EPIPE == err) )
455 {
456 return MHD_ERR_CONNRESET_;
457 }
458 return MHD_ERR_BADF_; /* Fail hard */
459#endif /* HAVE_SOLARIS_SENDFILE */
460 }
452#ifdef EPOLL_SUPPORT 461#ifdef EPOLL_SUPPORT
453 else if (send_size > (size_t)ret) 462 else if (send_size > (size_t) ret)
454 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; 463 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
455#endif /* EPOLL_SUPPORT */ 464#endif /* EPOLL_SUPPORT */
456#elif defined(HAVE_FREEBSD_SENDFILE) 465#elif defined(HAVE_FREEBSD_SENDFILE)
457#ifdef SF_FLAGS 466#ifdef SF_FLAGS
458 flags = used_thr_p_c ? 467 flags = used_thr_p_c ?
459 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_; 468 freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
460#endif /* SF_FLAGS */ 469#endif /* SF_FLAGS */
461 if (0 != sendfile (file_fd, 470 if (0 != sendfile (file_fd,
462 connection->socket_fd, 471 connection->socket_fd,
@@ -465,26 +474,26 @@ sendfile_adapter (struct MHD_Connection *connection)
465 NULL, 474 NULL,
466 &sent_bytes, 475 &sent_bytes,
467 flags)) 476 flags))
477 {
478 const int err = MHD_socket_get_error_ ();
479 if (MHD_SCKT_ERR_IS_EAGAIN_ (err) ||
480 MHD_SCKT_ERR_IS_EINTR_ (err) ||
481 (EBUSY == err) )
468 { 482 {
469 const int err = MHD_socket_get_error_(); 483 mhd_assert (SSIZE_MAX >= sent_bytes);
470 if (MHD_SCKT_ERR_IS_EAGAIN_(err) || 484 if (0 != sent_bytes)
471 MHD_SCKT_ERR_IS_EINTR_(err) || 485 return (ssize_t) sent_bytes;
472 EBUSY == err)
473 {
474 mhd_assert (SSIZE_MAX >= sent_bytes);
475 if (0 != sent_bytes)
476 return (ssize_t)sent_bytes;
477 486
478 return MHD_ERR_AGAIN_;
479 }
480 /* Some unrecoverable error. Possibly file FD is not suitable
481 * for sendfile(). Retry with standard send(). */
482 request->resp_sender = MHD_resp_sender_std;
483 return MHD_ERR_AGAIN_; 487 return MHD_ERR_AGAIN_;
484 } 488 }
489 /* Some unrecoverable error. Possibly file FD is not suitable
490 * for sendfile(). Retry with standard send(). */
491 request->resp_sender = MHD_resp_sender_std;
492 return MHD_ERR_AGAIN_;
493 }
485 mhd_assert (0 < sent_bytes); 494 mhd_assert (0 < sent_bytes);
486 mhd_assert (SSIZE_MAX >= sent_bytes); 495 mhd_assert (SSIZE_MAX >= sent_bytes);
487 ret = (ssize_t)sent_bytes; 496 ret = (ssize_t) sent_bytes;
488#elif defined(HAVE_DARWIN_SENDFILE) 497#elif defined(HAVE_DARWIN_SENDFILE)
489 len = (off_t) send_size; /* chunk always fit */ 498 len = (off_t) send_size; /* chunk always fit */
490 if (0 != sendfile (file_fd, 499 if (0 != sendfile (file_fd,
@@ -493,35 +502,35 @@ sendfile_adapter (struct MHD_Connection *connection)
493 &len, 502 &len,
494 NULL, 503 NULL,
495 0)) 504 0))
505 {
506 const int err = MHD_socket_get_error_ ();
507 if (MHD_SCKT_ERR_IS_EAGAIN_ (err) ||
508 MHD_SCKT_ERR_IS_EINTR_ (err))
496 { 509 {
497 const int err = MHD_socket_get_error_(); 510 mhd_assert (0 <= len);
498 if (MHD_SCKT_ERR_IS_EAGAIN_(err) || 511 mhd_assert (SSIZE_MAX >= len);
499 MHD_SCKT_ERR_IS_EINTR_(err)) 512 mhd_assert (send_size >= (size_t) len);
500 { 513 if (0 != len)
501 mhd_assert (0 <= len); 514 return (ssize_t) len;
502 mhd_assert (SSIZE_MAX >= len);
503 mhd_assert (send_size >= (size_t)len);
504 if (0 != len)
505 return (ssize_t)len;
506 515
507 return MHD_ERR_AGAIN_; 516 return MHD_ERR_AGAIN_;
508 } 517 }
509 if (ENOTCONN == err || 518 if ((ENOTCONN == err) ||
510 EPIPE == err) 519 (EPIPE == err) )
511 return MHD_ERR_CONNRESET_; 520 return MHD_ERR_CONNRESET_;
512 if (ENOTSUP == err || 521 if ((ENOTSUP == err) ||
513 EOPNOTSUPP == err) 522 (EOPNOTSUPP == err) )
514 { /* This file FD is not suitable for sendfile(). 523 { /* This file FD is not suitable for sendfile().
515 * Retry with standard send(). */ 524 * Retry with standard send(). */
516 request->resp_sender = MHD_resp_sender_std; 525 request->resp_sender = MHD_resp_sender_std;
517 return MHD_ERR_AGAIN_; 526 return MHD_ERR_AGAIN_;
518 }
519 return MHD_ERR_BADF_; /* Return hard error. */
520 } 527 }
528 return MHD_ERR_BADF_; /* Return hard error. */
529 }
521 mhd_assert (0 <= len); 530 mhd_assert (0 <= len);
522 mhd_assert (SSIZE_MAX >= len); 531 mhd_assert (SSIZE_MAX >= len);
523 mhd_assert (send_size >= (size_t)len); 532 mhd_assert (send_size >= (size_t) len);
524 ret = (ssize_t)len; 533 ret = (ssize_t) len;
525#endif /* HAVE_FREEBSD_SENDFILE */ 534#endif /* HAVE_FREEBSD_SENDFILE */
526 return ret; 535 return ret;
527} 536}
@@ -547,7 +556,7 @@ check_write_done (struct MHD_Request *request,
547 request->write_buffer_send_offset = 0; 556 request->write_buffer_send_offset = 0;
548 request->state = next_state; 557 request->state = next_state;
549 MHD_pool_reallocate (request->connection->pool, 558 MHD_pool_reallocate (request->connection->pool,
550 request->write_buffer, 559 request->write_buffer,
551 request->write_buffer_size, 560 request->write_buffer_size,
552 0); 561 0);
553 request->write_buffer = NULL; 562 request->write_buffer = NULL;
@@ -579,47 +588,48 @@ try_ready_normal_body (struct MHD_Request *request)
579 (request->response_write_position == response->total_size) ) 588 (request->response_write_position == response->total_size) )
580 return true; /* 0-byte response is always ready */ 589 return true; /* 0-byte response is always ready */
581 if ( (response->data_start <= 590 if ( (response->data_start <=
582 request->response_write_position) && 591 request->response_write_position) &&
583 (response->data_size + response->data_start > 592 (response->data_size + response->data_start >
584 request->response_write_position) ) 593 request->response_write_position) )
585 return true; /* response already ready */ 594 return true; /* response already ready */
586#if defined(_MHD_HAVE_SENDFILE) 595#if defined(_MHD_HAVE_SENDFILE)
587 if (MHD_resp_sender_sendfile == request->resp_sender) 596 if (MHD_resp_sender_sendfile == request->resp_sender)
588 { 597 {
589 /* will use sendfile, no need to bother response crc */ 598 /* will use sendfile, no need to bother response crc */
590 return true; 599 return true;
591 } 600 }
592#endif /* _MHD_HAVE_SENDFILE */ 601#endif /* _MHD_HAVE_SENDFILE */
593 602
594 ret = response->crc (response->crc_cls, 603 ret = response->crc (response->crc_cls,
595 request->response_write_position, 604 request->response_write_position,
596 response->data, 605 response->data,
597 (size_t) MHD_MIN ((uint64_t) response->data_buffer_size, 606 (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
598 response->total_size - 607 response->total_size
599 request->response_write_position)); 608 - request->response_write_position));
600 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) || 609 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
601 (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) ) 610 (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
602 { 611 {
603 /* either error or http 1.0 transfer, close socket! */ 612 /* either error or http 1.0 transfer, close socket! */
604 response->total_size = request->response_write_position; 613 response->total_size = request->response_write_position;
605 MHD_mutex_unlock_chk_ (&response->mutex); 614 MHD_mutex_unlock_chk_ (&response->mutex);
606 if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret) 615 if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
607 MHD_connection_close_ (connection, 616 MHD_connection_close_ (connection,
608 MHD_REQUEST_TERMINATED_COMPLETED_OK); 617 MHD_REQUEST_TERMINATED_COMPLETED_OK);
609 else 618 else
610 CONNECTION_CLOSE_ERROR (connection, 619 CONNECTION_CLOSE_ERROR (connection,
611 MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED, 620 MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
612 _("Closing connection (application reported error generating data)\n")); 621 _ (
613 return false; 622 "Closing connection (application reported error generating data)\n"));
614 } 623 return false;
624 }
615 response->data_start = request->response_write_position; 625 response->data_start = request->response_write_position;
616 response->data_size = ret; 626 response->data_size = ret;
617 if (0 == ret) 627 if (0 == ret)
618 { 628 {
619 request->state = MHD_REQUEST_NORMAL_BODY_UNREADY; 629 request->state = MHD_REQUEST_NORMAL_BODY_UNREADY;
620 MHD_mutex_unlock_chk_ (&response->mutex); 630 MHD_mutex_unlock_chk_ (&response->mutex);
621 return false; 631 return false;
622 } 632 }
623 return true; 633 return true;
624} 634}
625 635
@@ -647,93 +657,94 @@ try_ready_chunked_body (struct MHD_Request *request)
647 if (NULL == response->crc) 657 if (NULL == response->crc)
648 return true; 658 return true;
649 if (0 == request->write_buffer_size) 659 if (0 == request->write_buffer_size)
650 { 660 {
651 size = MHD_MIN (daemon->connection_memory_limit_b, 661 size = MHD_MIN (daemon->connection_memory_limit_b,
652 2 * (0xFFFFFF + sizeof(cbuf) + 2)); 662 2 * (0xFFFFFF + sizeof(cbuf) + 2));
653 do 663 do
654 { 664 {
655 size /= 2; 665 size /= 2;
656 if (size < 128) 666 if (size < 128)
657 { 667 {
658 MHD_mutex_unlock_chk_ (&response->mutex); 668 MHD_mutex_unlock_chk_ (&response->mutex);
659 /* not enough memory */ 669 /* not enough memory */
660 CONNECTION_CLOSE_ERROR (connection, 670 CONNECTION_CLOSE_ERROR (connection,
661 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE, 671 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
662 _("Closing connection (out of memory)\n")); 672 _ ("Closing connection (out of memory)\n"));
663 return false; 673 return false;
664 } 674 }
665 buf = MHD_pool_allocate (connection->pool, 675 buf = MHD_pool_allocate (connection->pool,
666 size, 676 size,
667 MHD_NO); 677 MHD_NO);
668 } 678 }
669 while (NULL == buf); 679 while (NULL == buf);
670 request->write_buffer_size = size; 680 request->write_buffer_size = size;
671 request->write_buffer = buf; 681 request->write_buffer = buf;
672 } 682 }
673 683
674 if (0 == response->total_size) 684 if (0 == response->total_size)
675 ret = 0; /* response must be empty, don't bother calling crc */ 685 ret = 0; /* response must be empty, don't bother calling crc */
676 else if ( (response->data_start <= 686 else if ( (response->data_start <=
677 request->response_write_position) && 687 request->response_write_position) &&
678 (response->data_start + response->data_size > 688 (response->data_start + response->data_size >
679 request->response_write_position) ) 689 request->response_write_position) )
680 { 690 {
681 /* difference between response_write_position and data_start is less 691 /* difference between response_write_position and data_start is less
682 than data_size which is size_t type, no need to check for overflow */ 692 than data_size which is size_t type, no need to check for overflow */
683 const size_t data_write_offset 693 const size_t data_write_offset
684 = (size_t)(request->response_write_position - response->data_start); 694 = (size_t) (request->response_write_position - response->data_start);
685 /* buffer already ready, use what is there for the chunk */ 695 /* buffer already ready, use what is there for the chunk */
686 ret = response->data_size - data_write_offset; 696 ret = response->data_size - data_write_offset;
687 if ( ((size_t) ret) > request->write_buffer_size - sizeof (cbuf) - 2 ) 697 if ( ((size_t) ret) > request->write_buffer_size - sizeof (cbuf) - 2 )
688 ret = request->write_buffer_size - sizeof (cbuf) - 2; 698 ret = request->write_buffer_size - sizeof (cbuf) - 2;
689 memcpy (&request->write_buffer[sizeof (cbuf)], 699 memcpy (&request->write_buffer[sizeof (cbuf)],
690 &response->data[data_write_offset], 700 &response->data[data_write_offset],
691 ret); 701 ret);
692 } 702 }
693 else 703 else
694 { 704 {
695 /* buffer not in range, try to fill it */ 705 /* buffer not in range, try to fill it */
696 ret = response->crc (response->crc_cls, 706 ret = response->crc (response->crc_cls,
697 request->response_write_position, 707 request->response_write_position,
698 &request->write_buffer[sizeof (cbuf)], 708 &request->write_buffer[sizeof (cbuf)],
699 request->write_buffer_size - sizeof (cbuf) - 2); 709 request->write_buffer_size - sizeof (cbuf) - 2);
700 } 710 }
701 if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) 711 if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
702 { 712 {
703 /* error, close socket! */ 713 /* error, close socket! */
704 response->total_size = request->response_write_position; 714 response->total_size = request->response_write_position;
705 MHD_mutex_unlock_chk_ (&response->mutex); 715 MHD_mutex_unlock_chk_ (&response->mutex);
706 CONNECTION_CLOSE_ERROR (connection, 716 CONNECTION_CLOSE_ERROR (connection,
707 MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED, 717 MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
708 _("Closing connection (application error generating response)\n")); 718 _ (
709 return false; 719 "Closing connection (application error generating response)\n"));
710 } 720 return false;
721 }
711 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) || 722 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
712 (0 == response->total_size) ) 723 (0 == response->total_size) )
713 { 724 {
714 /* end of message, signal other side! */ 725 /* end of message, signal other side! */
715 memcpy (request->write_buffer, 726 memcpy (request->write_buffer,
716 "0\r\n", 727 "0\r\n",
717 3); 728 3);
718 request->write_buffer_append_offset = 3; 729 request->write_buffer_append_offset = 3;
719 request->write_buffer_send_offset = 0; 730 request->write_buffer_send_offset = 0;
720 response->total_size = request->response_write_position; 731 response->total_size = request->response_write_position;
721 return true; 732 return true;
722 } 733 }
723 if (0 == ret) 734 if (0 == ret)
724 { 735 {
725 request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY; 736 request->state = MHD_REQUEST_CHUNKED_BODY_UNREADY;
726 MHD_mutex_unlock_chk_ (&response->mutex); 737 MHD_mutex_unlock_chk_ (&response->mutex);
727 return false; 738 return false;
728 } 739 }
729 if (ret > 0xFFFFFF) 740 if (ret > 0xFFFFFF)
730 ret = 0xFFFFFF; 741 ret = 0xFFFFFF;
731 cblen = MHD_snprintf_(cbuf, 742 cblen = MHD_snprintf_ (cbuf,
732 sizeof (cbuf), 743 sizeof (cbuf),
733 "%X\r\n", 744 "%X\r\n",
734 (unsigned int) ret); 745 (unsigned int) ret);
735 mhd_assert(cblen > 0); 746 mhd_assert (cblen > 0);
736 mhd_assert((size_t)cblen < sizeof(cbuf)); 747 mhd_assert ((size_t) cblen < sizeof(cbuf));
737 memcpy (&request->write_buffer[sizeof (cbuf) - cblen], 748 memcpy (&request->write_buffer[sizeof (cbuf) - cblen],
738 cbuf, 749 cbuf,
739 cblen); 750 cblen);
@@ -768,221 +779,224 @@ MHD_request_handle_write_ (struct MHD_Request *request)
768 struct MHD_TLS_Plugin *tls; 779 struct MHD_TLS_Plugin *tls;
769 780
770 if ( (NULL != (tls = daemon->tls_api)) && 781 if ( (NULL != (tls = daemon->tls_api)) &&
771 (! tls->handshake (tls->cls, 782 (! tls->handshake (tls->cls,
772 connection->tls_cs)) ) 783 connection->tls_cs)) )
773 return; 784 return;
774 } 785 }
775#endif /* HTTPS_SUPPORT */ 786#endif /* HTTPS_SUPPORT */
776 787
777#if DEBUG_STATES 788#if DEBUG_STATES
778 MHD_DLOG (daemon, 789 MHD_DLOG (daemon,
779 MHD_SC_STATE_MACHINE_STATUS_REPORT, 790 MHD_SC_STATE_MACHINE_STATUS_REPORT,
780 _("In function %s handling connection at state: %s\n"), 791 _ ("In function %s handling connection at state: %s\n"),
781 __FUNCTION__, 792 __FUNCTION__,
782 MHD_state_to_string (request->state)); 793 MHD_state_to_string (request->state));
783#endif 794#endif
784 switch (request->state) 795 switch (request->state)
785 { 796 {
786 case MHD_REQUEST_INIT: 797 case MHD_REQUEST_INIT:
787 case MHD_REQUEST_URL_RECEIVED: 798 case MHD_REQUEST_URL_RECEIVED:
788 case MHD_REQUEST_HEADER_PART_RECEIVED: 799 case MHD_REQUEST_HEADER_PART_RECEIVED:
789 case MHD_REQUEST_HEADERS_RECEIVED: 800 case MHD_REQUEST_HEADERS_RECEIVED:
790 mhd_assert (0); 801 mhd_assert (0);
791 return; 802 return;
792 case MHD_REQUEST_HEADERS_PROCESSED: 803 case MHD_REQUEST_HEADERS_PROCESSED:
793 return; 804 return;
794 case MHD_REQUEST_CONTINUE_SENDING: 805 case MHD_REQUEST_CONTINUE_SENDING:
795 ret = connection->send_cls (connection, 806 ret = connection->send_cls (connection,
796 &HTTP_100_CONTINUE 807 &HTTP_100_CONTINUE
797 [request->continue_message_write_offset], 808 [request->continue_message_write_offset],
798 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE) - 809 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)
799 request->continue_message_write_offset); 810 - request->continue_message_write_offset);
800 if (ret < 0) 811 if (ret < 0)
801 { 812 {
802 if (MHD_ERR_AGAIN_ == ret) 813 if (MHD_ERR_AGAIN_ == ret)
803 return; 814 return;
804#ifdef HAVE_MESSAGES 815#ifdef HAVE_MESSAGES
805 MHD_DLOG (daemon, 816 MHD_DLOG (daemon,
806 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED, 817 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
807 _("Failed to send data in request for %s.\n"), 818 _ ("Failed to send data in request for %s.\n"),
808 request->url); 819 request->url);
809#endif 820#endif
810 CONNECTION_CLOSE_ERROR (connection, 821 CONNECTION_CLOSE_ERROR (connection,
811 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED, 822 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
812 NULL); 823 NULL);
813 return;
814 }
815 request->continue_message_write_offset += ret;
816 MHD_connection_update_last_activity_ (connection);
817 return;
818 case MHD_REQUEST_CONTINUE_SENT:
819 case MHD_REQUEST_BODY_RECEIVED:
820 case MHD_REQUEST_FOOTER_PART_RECEIVED:
821 case MHD_REQUEST_FOOTERS_RECEIVED:
822 mhd_assert (0);
823 return; 824 return;
824 case MHD_REQUEST_HEADERS_SENDING: 825 }
825 ret = connection->send_cls (connection, 826 request->continue_message_write_offset += ret;
826 &request->write_buffer 827 MHD_connection_update_last_activity_ (connection);
827 [request->write_buffer_send_offset], 828 return;
828 request->write_buffer_append_offset - 829 case MHD_REQUEST_CONTINUE_SENT:
829 request->write_buffer_send_offset); 830 case MHD_REQUEST_BODY_RECEIVED:
830 if (ret < 0) 831 case MHD_REQUEST_FOOTER_PART_RECEIVED:
831 { 832 case MHD_REQUEST_FOOTERS_RECEIVED:
832 if (MHD_ERR_AGAIN_ == ret) 833 mhd_assert (0);
833 return; 834 return;
834 CONNECTION_CLOSE_ERROR (connection, 835 case MHD_REQUEST_HEADERS_SENDING:
835 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED, 836 ret = connection->send_cls (connection,
836 _("Connection was closed while sending response headers.\n")); 837 &request->write_buffer
837 return; 838 [request->write_buffer_send_offset],
838 } 839 request->write_buffer_append_offset
839 request->write_buffer_send_offset += ret; 840 - request->write_buffer_send_offset);
840 MHD_connection_update_last_activity_ (connection); 841 if (ret < 0)
841 if (MHD_REQUEST_HEADERS_SENDING != request->state) 842 {
843 if (MHD_ERR_AGAIN_ == ret)
842 return; 844 return;
843 check_write_done (request, 845 CONNECTION_CLOSE_ERROR (connection,
844 MHD_REQUEST_HEADERS_SENT); 846 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
847 _ (
848 "Connection was closed while sending response headers.\n"));
845 return; 849 return;
846 case MHD_REQUEST_HEADERS_SENT: 850 }
851 request->write_buffer_send_offset += ret;
852 MHD_connection_update_last_activity_ (connection);
853 if (MHD_REQUEST_HEADERS_SENDING != request->state)
847 return; 854 return;
848 case MHD_REQUEST_NORMAL_BODY_READY: 855 check_write_done (request,
849 response = request->response; 856 MHD_REQUEST_HEADERS_SENT);
850 if (request->response_write_position < 857 return;
851 request->response->total_size) 858 case MHD_REQUEST_HEADERS_SENT:
852 { 859 return;
853 uint64_t data_write_offset; 860 case MHD_REQUEST_NORMAL_BODY_READY:
854 861 response = request->response;
855 if (NULL != response->crc) 862 if (request->response_write_position <
856 MHD_mutex_lock_chk_ (&response->mutex); 863 request->response->total_size)
857 if (! try_ready_normal_body (request)) 864 {
858 { 865 uint64_t data_write_offset;
859 /* mutex was already unlocked by try_ready_normal_body */ 866
860 return; 867 if (NULL != response->crc)
861 } 868 MHD_mutex_lock_chk_ (&response->mutex);
869 if (! try_ready_normal_body (request))
870 {
871 /* mutex was already unlocked by try_ready_normal_body */
872 return;
873 }
862#if defined(_MHD_HAVE_SENDFILE) 874#if defined(_MHD_HAVE_SENDFILE)
863 if (MHD_resp_sender_sendfile == request->resp_sender) 875 if (MHD_resp_sender_sendfile == request->resp_sender)
864 { 876 {
865 ret = sendfile_adapter (connection); 877 ret = sendfile_adapter (connection);
866 } 878 }
867 else 879 else
868#else /* ! _MHD_HAVE_SENDFILE */ 880#else /* ! _MHD_HAVE_SENDFILE */
869 if (1) 881 if (1)
870#endif /* ! _MHD_HAVE_SENDFILE */ 882#endif /* ! _MHD_HAVE_SENDFILE */
871 { 883 {
872 data_write_offset = request->response_write_position 884 data_write_offset = request->response_write_position
873 - response->data_start; 885 - response->data_start;
874 if (data_write_offset > (uint64_t)SIZE_MAX) 886 if (data_write_offset > (uint64_t) SIZE_MAX)
875 MHD_PANIC (_("Data offset exceeds limit")); 887 MHD_PANIC (_ ("Data offset exceeds limit"));
876 ret = connection->send_cls (connection, 888 ret = connection->send_cls (connection,
877 &response->data 889 &response->data
878 [(size_t)data_write_offset], 890 [(size_t) data_write_offset],
879 response->data_size - 891 response->data_size
880 (size_t)data_write_offset); 892 - (size_t) data_write_offset);
881#if DEBUG_SEND_DATA 893#if DEBUG_SEND_DATA
882 if (ret > 0) 894 if (ret > 0)
883 fprintf (stderr, 895 fprintf (stderr,
884 _("Sent %d-byte DATA response: `%.*s'\n"), 896 _ ("Sent %d-byte DATA response: `%.*s'\n"),
885 (int) ret, 897 (int) ret,
886 (int) ret, 898 (int) ret,
887 &response->data[request->response_write_position - 899 &response->data[request->response_write_position
888 response->data_start]); 900 - response->data_start]);
889#endif 901#endif
890 } 902 }
891 if (NULL != response->crc) 903 if (NULL != response->crc)
892 MHD_mutex_unlock_chk_ (&response->mutex); 904 MHD_mutex_unlock_chk_ (&response->mutex);
893 if (ret < 0)
894 {
895 if (MHD_ERR_AGAIN_ == ret)
896 return;
897#ifdef HAVE_MESSAGES
898 MHD_DLOG (daemon,
899 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
900 _("Failed to send data in request for `%s'.\n"),
901 request->url);
902#endif
903 CONNECTION_CLOSE_ERROR (connection,
904 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
905 NULL);
906 return;
907 }
908 request->response_write_position += ret;
909 MHD_connection_update_last_activity_ (connection);
910 }
911 if (request->response_write_position ==
912 request->response->total_size)
913 request->state = MHD_REQUEST_FOOTERS_SENT; /* have no footers */
914 return;
915 case MHD_REQUEST_NORMAL_BODY_UNREADY:
916 mhd_assert (0);
917 return;
918 case MHD_REQUEST_CHUNKED_BODY_READY:
919 ret = connection->send_cls (connection,
920 &request->write_buffer
921 [request->write_buffer_send_offset],
922 request->write_buffer_append_offset -
923 request->write_buffer_send_offset);
924 if (ret < 0) 905 if (ret < 0)
925 { 906 {
926 if (MHD_ERR_AGAIN_ == ret) 907 if (MHD_ERR_AGAIN_ == ret)
927 return;
928 CONNECTION_CLOSE_ERROR (connection,
929 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
930 _("Connection was closed while sending response body.\n"));
931 return; 908 return;
932 } 909#ifdef HAVE_MESSAGES
933 request->write_buffer_send_offset += ret; 910 MHD_DLOG (daemon,
911 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
912 _ ("Failed to send data in request for `%s'.\n"),
913 request->url);
914#endif
915 CONNECTION_CLOSE_ERROR (connection,
916 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
917 NULL);
918 return;
919 }
920 request->response_write_position += ret;
934 MHD_connection_update_last_activity_ (connection); 921 MHD_connection_update_last_activity_ (connection);
935 if (MHD_REQUEST_CHUNKED_BODY_READY != request->state) 922 }
923 if (request->response_write_position ==
924 request->response->total_size)
925 request->state = MHD_REQUEST_FOOTERS_SENT; /* have no footers */
926 return;
927 case MHD_REQUEST_NORMAL_BODY_UNREADY:
928 mhd_assert (0);
929 return;
930 case MHD_REQUEST_CHUNKED_BODY_READY:
931 ret = connection->send_cls (connection,
932 &request->write_buffer
933 [request->write_buffer_send_offset],
934 request->write_buffer_append_offset
935 - request->write_buffer_send_offset);
936 if (ret < 0)
937 {
938 if (MHD_ERR_AGAIN_ == ret)
936 return; 939 return;
937 check_write_done (request, 940 CONNECTION_CLOSE_ERROR (connection,
938 (request->response->total_size == 941 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
939 request->response_write_position) ? 942 _ (
940 MHD_REQUEST_BODY_SENT : 943 "Connection was closed while sending response body.\n"));
941 MHD_REQUEST_CHUNKED_BODY_UNREADY);
942 return; 944 return;
943 case MHD_REQUEST_CHUNKED_BODY_UNREADY: 945 }
944 case MHD_REQUEST_BODY_SENT: 946 request->write_buffer_send_offset += ret;
945 mhd_assert (0); 947 MHD_connection_update_last_activity_ (connection);
948 if (MHD_REQUEST_CHUNKED_BODY_READY != request->state)
946 return; 949 return;
947 case MHD_REQUEST_FOOTERS_SENDING: 950 check_write_done (request,
948 ret = connection->send_cls (connection, 951 (request->response->total_size ==
949 &request->write_buffer 952 request->response_write_position) ?
950 [request->write_buffer_send_offset], 953 MHD_REQUEST_BODY_SENT :
951 request->write_buffer_append_offset - 954 MHD_REQUEST_CHUNKED_BODY_UNREADY);
952 request->write_buffer_send_offset); 955 return;
953 if (ret < 0) 956 case MHD_REQUEST_CHUNKED_BODY_UNREADY:
954 { 957 case MHD_REQUEST_BODY_SENT:
955 if (MHD_ERR_AGAIN_ == ret) 958 mhd_assert (0);
956 return; 959 return;
957 CONNECTION_CLOSE_ERROR (connection, 960 case MHD_REQUEST_FOOTERS_SENDING:
958 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED, 961 ret = connection->send_cls (connection,
959 _("Connection was closed while sending response body.\n")); 962 &request->write_buffer
960 return; 963 [request->write_buffer_send_offset],
961 } 964 request->write_buffer_append_offset
962 request->write_buffer_send_offset += ret; 965 - request->write_buffer_send_offset);
963 MHD_connection_update_last_activity_ (connection); 966 if (ret < 0)
964 if (MHD_REQUEST_FOOTERS_SENDING != request->state) 967 {
968 if (MHD_ERR_AGAIN_ == ret)
965 return; 969 return;
966 check_write_done (request, 970 CONNECTION_CLOSE_ERROR (connection,
967 MHD_REQUEST_FOOTERS_SENT); 971 MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
968 return; 972 _ (
969 case MHD_REQUEST_FOOTERS_SENT: 973 "Connection was closed while sending response body.\n"));
970 mhd_assert (0);
971 return; 974 return;
972 case MHD_REQUEST_CLOSED: 975 }
976 request->write_buffer_send_offset += ret;
977 MHD_connection_update_last_activity_ (connection);
978 if (MHD_REQUEST_FOOTERS_SENDING != request->state)
973 return; 979 return;
980 check_write_done (request,
981 MHD_REQUEST_FOOTERS_SENT);
982 return;
983 case MHD_REQUEST_FOOTERS_SENT:
984 mhd_assert (0);
985 return;
986 case MHD_REQUEST_CLOSED:
987 return;
974#ifdef UPGRADE_SUPPORT 988#ifdef UPGRADE_SUPPORT
975 case MHD_REQUEST_UPGRADE: 989 case MHD_REQUEST_UPGRADE:
976 mhd_assert (0); 990 mhd_assert (0);
977 return; 991 return;
978#endif /* UPGRADE_SUPPORT */ 992#endif /* UPGRADE_SUPPORT */
979 default: 993 default:
980 mhd_assert (0); 994 mhd_assert (0);
981 CONNECTION_CLOSE_ERROR (connection, 995 CONNECTION_CLOSE_ERROR (connection,
982 MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED, 996 MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED,
983 _("Internal error\n")); 997 _ ("Internal error\n"));
984 break; 998 break;
985 } 999 }
986} 1000}
987 1001
988 1002
@@ -1001,9 +1015,9 @@ MHD_request_handle_write_ (struct MHD_Request *request)
1001 */ 1015 */
1002static bool 1016static bool
1003MHD_lookup_header_token_ci (const struct MHD_Request *request, 1017MHD_lookup_header_token_ci (const struct MHD_Request *request,
1004 const char *header, 1018 const char *header,
1005 const char *token, 1019 const char *token,
1006 size_t token_len) 1020 size_t token_len)
1007{ 1021{
1008 struct MHD_HTTP_Header *pos; 1022 struct MHD_HTTP_Header *pos;
1009 1023
@@ -1014,16 +1028,16 @@ MHD_lookup_header_token_ci (const struct MHD_Request *request,
1014 (0 == token[0]) ) 1028 (0 == token[0]) )
1015 return false; 1029 return false;
1016 for (pos = request->headers_received; NULL != pos; pos = pos->next) 1030 for (pos = request->headers_received; NULL != pos; pos = pos->next)
1017 { 1031 {
1018 if ( (0 != (pos->kind & MHD_HEADER_KIND)) && 1032 if ( (0 != (pos->kind & MHD_HEADER_KIND)) &&
1019 ( (header == pos->header) || 1033 ( (header == pos->header) ||
1020 (MHD_str_equal_caseless_(header, 1034 (MHD_str_equal_caseless_ (header,
1021 pos->header)) ) && 1035 pos->header)) ) &&
1022 (MHD_str_has_token_caseless_ (pos->value, 1036 (MHD_str_has_token_caseless_ (pos->value,
1023 token, 1037 token,
1024 token_len)) ) 1038 token_len)) )
1025 return true; 1039 return true;
1026 } 1040 }
1027 return false; 1041 return false;
1028} 1042}
1029 1043
@@ -1040,7 +1054,7 @@ MHD_lookup_header_token_ci (const struct MHD_Request *request,
1040 * false otherwise 1054 * false otherwise
1041 */ 1055 */
1042#define MHD_lookup_header_s_token_ci(r,h,tkn) \ 1056#define MHD_lookup_header_s_token_ci(r,h,tkn) \
1043 MHD_lookup_header_token_ci((r),(h),(tkn),MHD_STATICSTR_LEN_(tkn)) 1057 MHD_lookup_header_token_ci ((r),(h),(tkn),MHD_STATICSTR_LEN_ (tkn))
1044 1058
1045 1059
1046/** 1060/**
@@ -1071,27 +1085,27 @@ keepalive_possible (struct MHD_Request *request)
1071 return false; 1085 return false;
1072 1086
1073 if (MHD_str_equal_caseless_ (request->version_s, 1087 if (MHD_str_equal_caseless_ (request->version_s,
1074 MHD_HTTP_VERSION_1_1)) 1088 MHD_HTTP_VERSION_1_1))
1075 { 1089 {
1076 if (MHD_lookup_header_s_token_ci (request, 1090 if (MHD_lookup_header_s_token_ci (request,
1077 MHD_HTTP_HEADER_CONNECTION, 1091 MHD_HTTP_HEADER_CONNECTION,
1078 "upgrade")) 1092 "upgrade"))
1079 return false;
1080 if (MHD_lookup_header_s_token_ci (request,
1081 MHD_HTTP_HEADER_CONNECTION,
1082 "close"))
1083 return false;
1084 return true;
1085 }
1086 if (MHD_str_equal_caseless_ (request->version_s,
1087 MHD_HTTP_VERSION_1_0))
1088 {
1089 if (MHD_lookup_header_s_token_ci (request,
1090 MHD_HTTP_HEADER_CONNECTION,
1091 "Keep-Alive"))
1092 return true;
1093 return false; 1093 return false;
1094 } 1094 if (MHD_lookup_header_s_token_ci (request,
1095 MHD_HTTP_HEADER_CONNECTION,
1096 "close"))
1097 return false;
1098 return true;
1099 }
1100 if (MHD_str_equal_caseless_ (request->version_s,
1101 MHD_HTTP_VERSION_1_0))
1102 {
1103 if (MHD_lookup_header_s_token_ci (request,
1104 MHD_HTTP_HEADER_CONNECTION,
1105 "Keep-Alive"))
1106 return true;
1107 return false;
1108 }
1095 return false; 1109 return false;
1096} 1110}
1097 1111
@@ -1105,7 +1119,7 @@ keepalive_possible (struct MHD_Request *request)
1105 */ 1119 */
1106static void 1120static void
1107get_date_string (char *date, 1121get_date_string (char *date,
1108 size_t date_len) 1122 size_t date_len)
1109{ 1123{
1110 static const char *const days[] = { 1124 static const char *const days[] = {
1111 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 1125 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
@@ -1116,8 +1130,9 @@ get_date_string (char *date,
1116 }; 1130 };
1117 struct tm now; 1131 struct tm now;
1118 time_t t; 1132 time_t t;
1119#if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R) 1133#if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1120 struct tm* pNow; 1134 ! defined(HAVE_GMTIME_R)
1135 struct tm*pNow;
1121#endif 1136#endif
1122 1137
1123 date[0] = 0; 1138 date[0] = 0;
@@ -1131,25 +1146,25 @@ get_date_string (char *date,
1131 &t)) 1146 &t))
1132 return; 1147 return;
1133#elif defined(HAVE_GMTIME_R) 1148#elif defined(HAVE_GMTIME_R)
1134 if (NULL == gmtime_r(&t, 1149 if (NULL == gmtime_r (&t,
1135 &now)) 1150 &now))
1136 return; 1151 return;
1137#else 1152#else
1138 pNow = gmtime(&t); 1153 pNow = gmtime (&t);
1139 if (NULL == pNow) 1154 if (NULL == pNow)
1140 return; 1155 return;
1141 now = *pNow; 1156 now = *pNow;
1142#endif 1157#endif
1143 MHD_snprintf_ (date, 1158 MHD_snprintf_ (date,
1144 date_len, 1159 date_len,
1145 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", 1160 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1146 days[now.tm_wday % 7], 1161 days[now.tm_wday % 7],
1147 (unsigned int) now.tm_mday, 1162 (unsigned int) now.tm_mday,
1148 mons[now.tm_mon % 12], 1163 mons[now.tm_mon % 12],
1149 (unsigned int) (1900 + now.tm_year), 1164 (unsigned int) (1900 + now.tm_year),
1150 (unsigned int) now.tm_hour, 1165 (unsigned int) now.tm_hour,
1151 (unsigned int) now.tm_min, 1166 (unsigned int) now.tm_min,
1152 (unsigned int) now.tm_sec); 1167 (unsigned int) now.tm_sec);
1153} 1168}
1154 1169
1155 1170
@@ -1168,9 +1183,9 @@ get_date_string (char *date,
1168 */ 1183 */
1169static bool 1184static bool
1170check_response_header_token_ci (const struct MHD_Response *response, 1185check_response_header_token_ci (const struct MHD_Response *response,
1171 const char *key, 1186 const char *key,
1172 const char *token, 1187 const char *token,
1173 size_t token_len) 1188 size_t token_len)
1174{ 1189{
1175 struct MHD_HTTP_Header *pos; 1190 struct MHD_HTTP_Header *pos;
1176 1191
@@ -1183,15 +1198,15 @@ check_response_header_token_ci (const struct MHD_Response *response,
1183 for (pos = response->first_header; 1198 for (pos = response->first_header;
1184 NULL != pos; 1199 NULL != pos;
1185 pos = pos->next) 1200 pos = pos->next)
1186 { 1201 {
1187 if ( (pos->kind == MHD_HEADER_KIND) && 1202 if ( (pos->kind == MHD_HEADER_KIND) &&
1188 MHD_str_equal_caseless_ (pos->header, 1203 MHD_str_equal_caseless_ (pos->header,
1189 key) && 1204 key) &&
1190 MHD_str_has_token_caseless_ (pos->value, 1205 MHD_str_has_token_caseless_ (pos->value,
1191 token, 1206 token,
1192 token_len) ) 1207 token_len) )
1193 return true; 1208 return true;
1194 } 1209 }
1195 return false; 1210 return false;
1196} 1211}
1197 1212
@@ -1208,7 +1223,7 @@ check_response_header_token_ci (const struct MHD_Response *response,
1208 * false otherwise 1223 * false otherwise
1209 */ 1224 */
1210#define check_response_header_s_token_ci(r,k,tkn) \ 1225#define check_response_header_s_token_ci(r,k,tkn) \
1211 check_response_header_token_ci((r),(k),(tkn),MHD_STATICSTR_LEN_(tkn)) 1226 check_response_header_token_ci ((r),(k),(tkn),MHD_STATICSTR_LEN_ (tkn))
1212 1227
1213 1228
1214/** 1229/**
@@ -1248,58 +1263,58 @@ build_header_response (struct MHD_Request *request)
1248 1263
1249 mhd_assert (NULL != request->version_s); 1264 mhd_assert (NULL != request->version_s);
1250 if (0 == request->version_s[0]) 1265 if (0 == request->version_s[0])
1251 { 1266 {
1252 data = MHD_pool_allocate (connection->pool, 1267 data = MHD_pool_allocate (connection->pool,
1253 0, 1268 0,
1254 MHD_YES); 1269 MHD_YES);
1255 request->write_buffer = data; 1270 request->write_buffer = data;
1256 request->write_buffer_append_offset = 0; 1271 request->write_buffer_append_offset = 0;
1257 request->write_buffer_send_offset = 0; 1272 request->write_buffer_send_offset = 0;
1258 request->write_buffer_size = 0; 1273 request->write_buffer_size = 0;
1259 return true; 1274 return true;
1260 } 1275 }
1261 if (MHD_REQUEST_FOOTERS_RECEIVED == request->state) 1276 if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
1262 { 1277 {
1263 const char *reason_phrase; 1278 const char *reason_phrase;
1264 const char *version; 1279 const char *version;
1265 1280
1266 reason_phrase 1281 reason_phrase
1267 = MHD_get_reason_phrase_for (response->status_code); 1282 = MHD_get_reason_phrase_for (response->status_code);
1268 version 1283 version
1269 = (response->icy) 1284 = (response->icy)
1270 ? "ICY" 1285 ? "ICY"
1271 : ( (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_0, 1286 : ( (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_0,
1272 request->version_s)) 1287 request->version_s))
1273 ? MHD_HTTP_VERSION_1_0 1288 ? MHD_HTTP_VERSION_1_0
1274 : MHD_HTTP_VERSION_1_1); 1289 : MHD_HTTP_VERSION_1_1);
1275 MHD_snprintf_ (code, 1290 MHD_snprintf_ (code,
1276 sizeof (code), 1291 sizeof (code),
1277 "%s %u %s\r\n", 1292 "%s %u %s\r\n",
1278 version, 1293 version,
1279 response->status_code, 1294 response->status_code,
1280 reason_phrase); 1295 reason_phrase);
1281 off = strlen (code); 1296 off = strlen (code);
1282 /* estimate size */ 1297 /* estimate size */
1283 size = off + 2; /* +2 for extra "\r\n" at the end */ 1298 size = off + 2; /* +2 for extra "\r\n" at the end */
1284 kind = MHD_HEADER_KIND; 1299 kind = MHD_HEADER_KIND;
1285 if ( (! daemon->suppress_date) && 1300 if ( (! daemon->suppress_date) &&
1286 (NULL == MHD_response_get_header (response, 1301 (NULL == MHD_response_get_header (response,
1287 MHD_HTTP_HEADER_DATE)) ) 1302 MHD_HTTP_HEADER_DATE)) )
1288 get_date_string (date, 1303 get_date_string (date,
1289 sizeof (date)); 1304 sizeof (date));
1290 else 1305 else
1291 date[0] = '\0'; 1306 date[0] = '\0';
1292 datelen = strlen (date); 1307 datelen = strlen (date);
1293 size += datelen; 1308 size += datelen;
1294 } 1309 }
1295 else 1310 else
1296 { 1311 {
1297 /* 2 bytes for final CRLF of a Chunked-Body */ 1312 /* 2 bytes for final CRLF of a Chunked-Body */
1298 size = 2; 1313 size = 2;
1299 kind = MHD_FOOTER_KIND; 1314 kind = MHD_FOOTER_KIND;
1300 off = 0; 1315 off = 0;
1301 datelen = 0; 1316 datelen = 0;
1302 } 1317 }
1303 1318
1304 /* calculate extra headers we need to add, such as 'Connection: close', 1319 /* calculate extra headers we need to add, such as 'Connection: close',
1305 first see what was explicitly requested by the application */ 1320 first see what was explicitly requested by the application */
@@ -1309,153 +1324,154 @@ build_header_response (struct MHD_Request *request)
1309 must_add_content_length = false; 1324 must_add_content_length = false;
1310 response_has_close = false; 1325 response_has_close = false;
1311 switch (request->state) 1326 switch (request->state)
1312 { 1327 {
1313 case MHD_REQUEST_FOOTERS_RECEIVED: 1328 case MHD_REQUEST_FOOTERS_RECEIVED:
1314 response_has_close 1329 response_has_close
1315 = check_response_header_s_token_ci (response, 1330 = check_response_header_s_token_ci (response,
1316 MHD_HTTP_HEADER_CONNECTION, 1331 MHD_HTTP_HEADER_CONNECTION,
1317 "close"); 1332 "close");
1318 response_has_keepalive 1333 response_has_keepalive
1319 = check_response_header_s_token_ci (response, 1334 = check_response_header_s_token_ci (response,
1320 MHD_HTTP_HEADER_CONNECTION, 1335 MHD_HTTP_HEADER_CONNECTION,
1321 "Keep-Alive"); 1336 "Keep-Alive");
1322 client_requested_close 1337 client_requested_close
1323 = MHD_lookup_header_s_token_ci (request, 1338 = MHD_lookup_header_s_token_ci (request,
1324 MHD_HTTP_HEADER_CONNECTION, 1339 MHD_HTTP_HEADER_CONNECTION,
1325 "close"); 1340 "close");
1326 1341
1327 if (response->v10_only) 1342 if (response->v10_only)
1328 request->keepalive = MHD_CONN_MUST_CLOSE; 1343 request->keepalive = MHD_CONN_MUST_CLOSE;
1329#ifdef UPGRADE_SUPPORT 1344#ifdef UPGRADE_SUPPORT
1330 else if (NULL != response->upgrade_handler) 1345 else if (NULL != response->upgrade_handler)
1331 /* If this connection will not be "upgraded", it must be closed. */ 1346 /* If this connection will not be "upgraded", it must be closed. */
1332 request->keepalive = MHD_CONN_MUST_CLOSE; 1347 request->keepalive = MHD_CONN_MUST_CLOSE;
1333#endif /* UPGRADE_SUPPORT */ 1348#endif /* UPGRADE_SUPPORT */
1334 1349
1335 /* now analyze chunked encoding situation */ 1350 /* now analyze chunked encoding situation */
1336 request->have_chunked_upload = false; 1351 request->have_chunked_upload = false;
1337 1352
1338 if ( (MHD_SIZE_UNKNOWN == response->total_size) && 1353 if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1339#ifdef UPGRADE_SUPPORT 1354#ifdef UPGRADE_SUPPORT
1340 (NULL == response->upgrade_handler) && 1355 (NULL == response->upgrade_handler) &&
1341#endif /* UPGRADE_SUPPORT */ 1356#endif /* UPGRADE_SUPPORT */
1342 (! response_has_close) && 1357 (! response_has_close) &&
1343 (! client_requested_close) ) 1358 (! client_requested_close) )
1359 {
1360 /* size is unknown, and close was not explicitly requested;
1361 need to either to HTTP 1.1 chunked encoding or
1362 close the connection */
1363 /* 'close' header doesn't exist yet, see if we need to add one;
1364 if the client asked for a close, no need to start chunk'ing */
1365 if ( (keepalive_possible (request)) &&
1366 (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
1367 request->version_s)) )
1368 {
1369 have_encoding
1370 = MHD_response_get_header (response,
1371 MHD_HTTP_HEADER_TRANSFER_ENCODING);
1372 if (NULL == have_encoding)
1344 { 1373 {
1345 /* size is unknown, and close was not explicitly requested; 1374 must_add_chunked_encoding = true;
1346 need to either to HTTP 1.1 chunked encoding or 1375 request->have_chunked_upload = true;
1347 close the connection */
1348 /* 'close' header doesn't exist yet, see if we need to add one;
1349 if the client asked for a close, no need to start chunk'ing */
1350 if ( (keepalive_possible (request)) &&
1351 (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
1352 request->version_s)) )
1353 {
1354 have_encoding
1355 = MHD_response_get_header (response,
1356 MHD_HTTP_HEADER_TRANSFER_ENCODING);
1357 if (NULL == have_encoding)
1358 {
1359 must_add_chunked_encoding = true;
1360 request->have_chunked_upload = true;
1361 }
1362 else if (MHD_str_equal_caseless_ (have_encoding,
1363 "identity"))
1364 {
1365 /* application forced identity encoding, can't do 'chunked' */
1366 must_add_close = true;
1367 }
1368 else
1369 {
1370 request->have_chunked_upload = true;
1371 }
1372 }
1373 else
1374 {
1375 /* Keep alive or chunking not possible
1376 => set close header if not present */
1377 if (! response_has_close)
1378 must_add_close = true;
1379 }
1380 } 1376 }
1381 1377 else if (MHD_str_equal_caseless_ (have_encoding,
1382 /* check for other reasons to add 'close' header */ 1378 "identity"))
1383 if ( ( (client_requested_close) ||
1384 (connection->read_closed) ||
1385 (MHD_CONN_MUST_CLOSE == request->keepalive)) &&
1386 (! response_has_close) &&
1387#ifdef UPGRADE_SUPPORT
1388 (NULL == response->upgrade_handler) &&
1389#endif /* UPGRADE_SUPPORT */
1390 (! response->v10_only) )
1391 must_add_close = true;
1392
1393 /* check if we should add a 'content length' header */
1394 have_content_length
1395 = MHD_response_get_header (response,
1396 MHD_HTTP_HEADER_CONTENT_LENGTH);
1397
1398 /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1399 codes SHOULD NOT have a Content-Length according to spec;
1400 also chunked encoding / unknown length or CONNECT... */
1401 if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1402 (MHD_HTTP_NO_CONTENT != response->status_code) &&
1403 (MHD_HTTP_NOT_MODIFIED != response->status_code) &&
1404 (MHD_HTTP_OK <= response->status_code) &&
1405 (NULL == have_content_length) &&
1406 (request->method != MHD_METHOD_CONNECT) )
1407 { 1379 {
1408 /* 1380 /* application forced identity encoding, can't do 'chunked' */
1409 Here we add a content-length if one is missing; however, 1381 must_add_close = true;
1410 for 'connect' methods, the responses MUST NOT include a
1411 content-length header *if* the response code is 2xx (in
1412 which case we expect there to be no body). Still,
1413 as we don't know the response code here in some cases, we
1414 simply only force adding a content-length header if this
1415 is not a 'connect' or if the response is not empty
1416 (which is kind of more sane, because if some crazy
1417 application did return content with a 2xx status code,
1418 then having a content-length might again be a good idea).
1419
1420 Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1421 a recent development of the HTTP 1.1 specification.
1422 */
1423 content_length_len
1424 = MHD_snprintf_ (content_length_buf,
1425 sizeof (content_length_buf),
1426 MHD_HTTP_HEADER_CONTENT_LENGTH ": " MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n",
1427 (MHD_UNSIGNED_LONG_LONG) response->total_size);
1428 must_add_content_length = true;
1429 } 1382 }
1430 1383 else
1431 /* check for adding keep alive */ 1384 {
1432 if ( (! response_has_keepalive) && 1385 request->have_chunked_upload = true;
1433 (! response_has_close) && 1386 }
1434 (! must_add_close) && 1387 }
1435 (MHD_CONN_MUST_CLOSE != request->keepalive) && 1388 else
1389 {
1390 /* Keep alive or chunking not possible
1391 => set close header if not present */
1392 if (! response_has_close)
1393 must_add_close = true;
1394 }
1395 }
1396
1397 /* check for other reasons to add 'close' header */
1398 if ( ( (client_requested_close) ||
1399 (connection->read_closed) ||
1400 (MHD_CONN_MUST_CLOSE == request->keepalive)) &&
1401 (! response_has_close) &&
1436#ifdef UPGRADE_SUPPORT 1402#ifdef UPGRADE_SUPPORT
1437 (NULL == response->upgrade_handler) && 1403 (NULL == response->upgrade_handler) &&
1438#endif /* UPGRADE_SUPPORT */ 1404#endif /* UPGRADE_SUPPORT */
1439 (keepalive_possible (request)) ) 1405 (! response->v10_only) )
1440 must_add_keep_alive = true; 1406 must_add_close = true;
1441 break; 1407
1442 case MHD_REQUEST_BODY_SENT: 1408 /* check if we should add a 'content length' header */
1443 response_has_keepalive = false; 1409 have_content_length
1444 break; 1410 = MHD_response_get_header (response,
1445 default: 1411 MHD_HTTP_HEADER_CONTENT_LENGTH);
1446 mhd_assert (0); 1412
1447 return MHD_NO; 1413 /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1448 } 1414 codes SHOULD NOT have a Content-Length according to spec;
1415 also chunked encoding / unknown length or CONNECT... */
1416 if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1417 (MHD_HTTP_NO_CONTENT != response->status_code) &&
1418 (MHD_HTTP_NOT_MODIFIED != response->status_code) &&
1419 (MHD_HTTP_OK <= response->status_code) &&
1420 (NULL == have_content_length) &&
1421 (request->method != MHD_METHOD_CONNECT) )
1422 {
1423 /*
1424 Here we add a content-length if one is missing; however,
1425 for 'connect' methods, the responses MUST NOT include a
1426 content-length header *if* the response code is 2xx (in
1427 which case we expect there to be no body). Still,
1428 as we don't know the response code here in some cases, we
1429 simply only force adding a content-length header if this
1430 is not a 'connect' or if the response is not empty
1431 (which is kind of more sane, because if some crazy
1432 application did return content with a 2xx status code,
1433 then having a content-length might again be a good idea).
1434
1435 Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1436 a recent development of the HTTP 1.1 specification.
1437 */
1438 content_length_len
1439 = MHD_snprintf_ (content_length_buf,
1440 sizeof (content_length_buf),
1441 MHD_HTTP_HEADER_CONTENT_LENGTH ": "
1442 MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n",
1443 (MHD_UNSIGNED_LONG_LONG) response->total_size);
1444 must_add_content_length = true;
1445 }
1446
1447 /* check for adding keep alive */
1448 if ( (! response_has_keepalive) &&
1449 (! response_has_close) &&
1450 (! must_add_close) &&
1451 (MHD_CONN_MUST_CLOSE != request->keepalive) &&
1452#ifdef UPGRADE_SUPPORT
1453 (NULL == response->upgrade_handler) &&
1454#endif /* UPGRADE_SUPPORT */
1455 (keepalive_possible (request)) )
1456 must_add_keep_alive = true;
1457 break;
1458 case MHD_REQUEST_BODY_SENT:
1459 response_has_keepalive = false;
1460 break;
1461 default:
1462 mhd_assert (0);
1463 return MHD_NO;
1464 }
1449 1465
1450 if (MHD_CONN_MUST_CLOSE != request->keepalive) 1466 if (MHD_CONN_MUST_CLOSE != request->keepalive)
1451 { 1467 {
1452 if ( (must_add_close) || 1468 if ( (must_add_close) ||
1453 (response_has_close) ) 1469 (response_has_close) )
1454 request->keepalive = MHD_CONN_MUST_CLOSE; 1470 request->keepalive = MHD_CONN_MUST_CLOSE;
1455 else if ( (must_add_keep_alive) || 1471 else if ( (must_add_keep_alive) ||
1456 (response_has_keepalive) ) 1472 (response_has_keepalive) )
1457 request->keepalive = MHD_CONN_USE_KEEPALIVE; 1473 request->keepalive = MHD_CONN_USE_KEEPALIVE;
1458 } 1474 }
1459 1475
1460 if (must_add_close) 1476 if (must_add_close)
1461 size += MHD_STATICSTR_LEN_ ("Connection: close\r\n"); 1477 size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
@@ -1469,91 +1485,91 @@ build_header_response (struct MHD_Request *request)
1469 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) ); 1485 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1470 1486
1471 for (pos = response->first_header; NULL != pos; pos = pos->next) 1487 for (pos = response->first_header; NULL != pos; pos = pos->next)
1472 { 1488 {
1473 /* TODO: add proper support for excluding "Keep-Alive" token. */ 1489 /* TODO: add proper support for excluding "Keep-Alive" token. */
1474 if ( (pos->kind == kind) && 1490 if ( (pos->kind == kind) &&
1475 (! ( (must_add_close) && 1491 (! ( (must_add_close) &&
1476 (response_has_keepalive) && 1492 (response_has_keepalive) &&
1477 (MHD_str_equal_caseless_(pos->header, 1493 (MHD_str_equal_caseless_ (pos->header,
1478 MHD_HTTP_HEADER_CONNECTION)) && 1494 MHD_HTTP_HEADER_CONNECTION)) &&
1479 (MHD_str_equal_caseless_(pos->value, 1495 (MHD_str_equal_caseless_ (pos->value,
1480 "Keep-Alive")) ) ) ) 1496 "Keep-Alive")) ) ) )
1481 size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */ 1497 size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1482 } 1498 }
1483 /* produce data */ 1499 /* produce data */
1484 data = MHD_pool_allocate (connection->pool, 1500 data = MHD_pool_allocate (connection->pool,
1485 size + 1, 1501 size + 1,
1486 MHD_NO); 1502 MHD_NO);
1487 if (NULL == data) 1503 if (NULL == data)
1488 { 1504 {
1489#ifdef HAVE_MESSAGES 1505#ifdef HAVE_MESSAGES
1490 MHD_DLOG (daemon, 1506 MHD_DLOG (daemon,
1491 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE, 1507 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
1492 "Not enough memory for write!\n"); 1508 "Not enough memory for write!\n");
1493#endif 1509#endif
1494 return false; 1510 return false;
1495 } 1511 }
1496 if (MHD_REQUEST_FOOTERS_RECEIVED == request->state) 1512 if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
1497 { 1513 {
1498 memcpy (data, 1514 memcpy (data,
1499 code, 1515 code,
1500 off); 1516 off);
1501 } 1517 }
1502 if (must_add_close) 1518 if (must_add_close)
1503 { 1519 {
1504 /* we must add the 'Connection: close' header */ 1520 /* we must add the 'Connection: close' header */
1505 memcpy (&data[off], 1521 memcpy (&data[off],
1506 "Connection: close\r\n", 1522 "Connection: close\r\n",
1507 MHD_STATICSTR_LEN_ ("Connection: close\r\n")); 1523 MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1508 off += MHD_STATICSTR_LEN_ ("Connection: close\r\n"); 1524 off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1509 } 1525 }
1510 if (must_add_keep_alive) 1526 if (must_add_keep_alive)
1511 { 1527 {
1512 /* we must add the 'Connection: Keep-Alive' header */ 1528 /* we must add the 'Connection: Keep-Alive' header */
1513 memcpy (&data[off], 1529 memcpy (&data[off],
1514 "Connection: Keep-Alive\r\n", 1530 "Connection: Keep-Alive\r\n",
1515 MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n")); 1531 MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1516 off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"); 1532 off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1517 } 1533 }
1518 if (must_add_chunked_encoding) 1534 if (must_add_chunked_encoding)
1519 { 1535 {
1520 /* we must add the 'Transfer-Encoding: chunked' header */ 1536 /* we must add the 'Transfer-Encoding: chunked' header */
1521 memcpy (&data[off], 1537 memcpy (&data[off],
1522 "Transfer-Encoding: chunked\r\n", 1538 "Transfer-Encoding: chunked\r\n",
1523 MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n")); 1539 MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1524 off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"); 1540 off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1525 } 1541 }
1526 if (must_add_content_length) 1542 if (must_add_content_length)
1527 { 1543 {
1528 /* we must add the 'Content-Length' header */ 1544 /* we must add the 'Content-Length' header */
1529 memcpy (&data[off], 1545 memcpy (&data[off],
1530 content_length_buf, 1546 content_length_buf,
1531 content_length_len); 1547 content_length_len);
1532 off += content_length_len; 1548 off += content_length_len;
1533 } 1549 }
1534 for (pos = response->first_header; NULL != pos; pos = pos->next) 1550 for (pos = response->first_header; NULL != pos; pos = pos->next)
1535 { 1551 {
1536 /* TODO: add proper support for excluding "Keep-Alive" token. */ 1552 /* TODO: add proper support for excluding "Keep-Alive" token. */
1537 if ( (pos->kind == kind) && 1553 if ( (pos->kind == kind) &&
1538 (! ( (must_add_close) && 1554 (! ( (must_add_close) &&
1539 (response_has_keepalive) && 1555 (response_has_keepalive) &&
1540 (MHD_str_equal_caseless_(pos->header, 1556 (MHD_str_equal_caseless_ (pos->header,
1541 MHD_HTTP_HEADER_CONNECTION)) && 1557 MHD_HTTP_HEADER_CONNECTION)) &&
1542 (MHD_str_equal_caseless_(pos->value, 1558 (MHD_str_equal_caseless_ (pos->value,
1543 "Keep-Alive")) ) ) ) 1559 "Keep-Alive")) ) ) )
1544 off += MHD_snprintf_ (&data[off], 1560 off += MHD_snprintf_ (&data[off],
1545 size - off, 1561 size - off,
1546 "%s: %s\r\n", 1562 "%s: %s\r\n",
1547 pos->header, 1563 pos->header,
1548 pos->value); 1564 pos->value);
1549 } 1565 }
1550 if (MHD_REQUEST_FOOTERS_RECEIVED == request->state) 1566 if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
1551 { 1567 {
1552 memcpy (&data[off], 1568 memcpy (&data[off],
1553 date, 1569 date,
1554 datelen); 1570 datelen);
1555 off += datelen; 1571 off += datelen;
1556 } 1572 }
1557 memcpy (&data[off], 1573 memcpy (&data[off],
1558 "\r\n", 1574 "\r\n",
1559 2); 1575 2);
@@ -1584,50 +1600,52 @@ build_header_response (struct MHD_Request *request)
1584 */ 1600 */
1585static void 1601static void
1586transmit_error_response (struct MHD_Request *request, 1602transmit_error_response (struct MHD_Request *request,
1587 enum MHD_StatusCode ec, 1603 enum MHD_StatusCode ec,
1588 enum MHD_HTTP_StatusCode status_code, 1604 enum MHD_HTTP_StatusCode status_code,
1589 const char *message) 1605 const char *message)
1590{ 1606{
1591 struct MHD_Response *response; 1607 struct MHD_Response *response;
1592 1608
1593 if (NULL == request->version_s) 1609 if (NULL == request->version_s)
1594 { 1610 {
1595 /* we were unable to process the full header line, so we don't 1611 /* we were unable to process the full header line, so we don't
1596 really know what version the client speaks; assume 1.0 */ 1612 really know what version the client speaks; assume 1.0 */
1597 request->version_s = MHD_HTTP_VERSION_1_0; 1613 request->version_s = MHD_HTTP_VERSION_1_0;
1598 } 1614 }
1599 request->state = MHD_REQUEST_FOOTERS_RECEIVED; 1615 request->state = MHD_REQUEST_FOOTERS_RECEIVED;
1600 request->connection->read_closed = true; 1616 request->connection->read_closed = true;
1601#ifdef HAVE_MESSAGES 1617#ifdef HAVE_MESSAGES
1602 MHD_DLOG (request->daemon, 1618 MHD_DLOG (request->daemon,
1603 ec, 1619 ec,
1604 _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"), 1620 _ (
1621 "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1605 status_code, 1622 status_code,
1606 message); 1623 message);
1607#endif 1624#endif
1608 if (NULL != request->response) 1625 if (NULL != request->response)
1609 { 1626 {
1610 MHD_response_queue_for_destroy (request->response); 1627 MHD_response_queue_for_destroy (request->response);
1611 request->response = NULL; 1628 request->response = NULL;
1612 } 1629 }
1613 response = MHD_response_from_buffer (status_code, 1630 response = MHD_response_from_buffer (status_code,
1614 strlen (message), 1631 strlen (message),
1615 (void *) message, 1632 (void *) message,
1616 MHD_RESPMEM_PERSISTENT); 1633 MHD_RESPMEM_PERSISTENT);
1617 request->response = response; 1634 request->response = response;
1618 /* Do not reuse this connection. */ 1635 /* Do not reuse this connection. */
1619 request->keepalive = MHD_CONN_MUST_CLOSE; 1636 request->keepalive = MHD_CONN_MUST_CLOSE;
1620 if (! build_header_response (request)) 1637 if (! build_header_response (request))
1621 { 1638 {
1622 /* oops - close! */ 1639 /* oops - close! */
1623 CONNECTION_CLOSE_ERROR (request->connection, 1640 CONNECTION_CLOSE_ERROR (request->connection,
1624 ec, 1641 ec,
1625 _("Closing connection (failed to create response header)\n")); 1642 _ (
1626 } 1643 "Closing connection (failed to create response header)\n"));
1644 }
1627 else 1645 else
1628 { 1646 {
1629 request->state = MHD_REQUEST_HEADERS_SENDING; 1647 request->state = MHD_REQUEST_HEADERS_SENDING;
1630 } 1648 }
1631} 1649}
1632 1650
1633 1651
@@ -1640,7 +1658,8 @@ transmit_error_response (struct MHD_Request *request,
1640static enum MHD_Method 1658static enum MHD_Method
1641method_string_to_enum (const char *method) 1659method_string_to_enum (const char *method)
1642{ 1660{
1643 static const struct { 1661 static const struct
1662 {
1644 const char *key; 1663 const char *key;
1645 enum MHD_Method value; 1664 enum MHD_Method value;
1646 } methods[] = { 1665 } methods[] = {
@@ -1685,10 +1704,10 @@ method_string_to_enum (const char *method)
1685 }; 1704 };
1686 unsigned int i; 1705 unsigned int i;
1687 1706
1688 for (i=0;NULL != methods[i].key;i++) 1707 for (i = 0; NULL != methods[i].key; i++)
1689 if (0 == 1708 if (0 ==
1690 MHD_str_equal_caseless_ (method, 1709 MHD_str_equal_caseless_ (method,
1691 methods[i].key)) 1710 methods[i].key))
1692 return methods[i].value; 1711 return methods[i].value;
1693 return MHD_METHOD_UNKNOWN; 1712 return MHD_METHOD_UNKNOWN;
1694} 1713}
@@ -1706,27 +1725,27 @@ method_string_to_enum (const char *method)
1706 */ 1725 */
1707static bool 1726static bool
1708request_add_header (struct MHD_Request *request, 1727request_add_header (struct MHD_Request *request,
1709 const char *key, 1728 const char *key,
1710 const char *value, 1729 const char *value,
1711 enum MHD_ValueKind kind) 1730 enum MHD_ValueKind kind)
1712{ 1731{
1713 if (MHD_NO == 1732 if (MHD_NO ==
1714 MHD_request_set_value (request, 1733 MHD_request_set_value (request,
1715 kind, 1734 kind,
1716 key, 1735 key,
1717 value)) 1736 value))
1718 { 1737 {
1719#ifdef HAVE_MESSAGES 1738#ifdef HAVE_MESSAGES
1720 MHD_DLOG (request->daemon, 1739 MHD_DLOG (request->daemon,
1721 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE, 1740 MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
1722 _("Not enough memory in pool to allocate header record!\n")); 1741 _ ("Not enough memory in pool to allocate header record!\n"));
1723#endif 1742#endif
1724 transmit_error_response (request, 1743 transmit_error_response (request,
1725 MHD_SC_CLIENT_HEADER_TOO_BIG, 1744 MHD_SC_CLIENT_HEADER_TOO_BIG,
1726 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 1745 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
1727 REQUEST_TOO_BIG); 1746 REQUEST_TOO_BIG);
1728 return false; 1747 return false;
1729 } 1748 }
1730 return true; 1749 return true;
1731} 1750}
1732 1751
@@ -1763,76 +1782,76 @@ parse_initial_message_line (struct MHD_Request *request,
1763 /* Skip any spaces. Not required by standard but allow 1782 /* Skip any spaces. Not required by standard but allow
1764 to be more tolerant. */ 1783 to be more tolerant. */
1765 while ( (' ' == uri[0]) && 1784 while ( (' ' == uri[0]) &&
1766 ( (size_t)(uri - line) < line_len) ) 1785 ( (size_t) (uri - line) < line_len) )
1767 uri++; 1786 uri++;
1768 if ((size_t)(uri - line) == line_len) 1787 if ((size_t) (uri - line) == line_len)
1769 { 1788 {
1770 curi = ""; 1789 curi = "";
1771 uri = NULL; 1790 uri = NULL;
1772 request->version_s = ""; 1791 request->version_s = "";
1773 args = NULL; 1792 args = NULL;
1774 url_end = line_len - (line - uri); // EH, this is garbage. FIXME! 1793 url_end = line_len - (line - uri); // EH, this is garbage. FIXME!
1775 } 1794 }
1776 else 1795 else
1796 {
1797 curi = uri;
1798 /* Search from back to accept misformed URI with space */
1799 http_version = line + line_len - 1;
1800 /* Skip any trailing spaces */
1801 while ( (' ' == http_version[0]) &&
1802 (http_version > uri) )
1803 http_version--;
1804 /* Find first space in reverse direction */
1805 while ( (' ' != http_version[0]) &&
1806 (http_version > uri) )
1807 http_version--;
1808 if (http_version > uri)
1809 {
1810 http_version[0] = '\0';
1811 request->version_s = http_version + 1;
1812 args = memchr (uri,
1813 '?',
1814 http_version - uri);
1815 }
1816 else
1777 { 1817 {
1778 curi = uri; 1818 request->version_s = "";
1779 /* Search from back to accept misformed URI with space */ 1819 args = memchr (uri,
1780 http_version = line + line_len - 1; 1820 '?',
1781 /* Skip any trailing spaces */ 1821 line_len - (uri - line));
1782 while ( (' ' == http_version[0]) &&
1783 (http_version > uri) )
1784 http_version--;
1785 /* Find first space in reverse direction */
1786 while ( (' ' != http_version[0]) &&
1787 (http_version > uri) )
1788 http_version--;
1789 if (http_version > uri)
1790 {
1791 http_version[0] = '\0';
1792 request->version_s = http_version + 1;
1793 args = memchr (uri,
1794 '?',
1795 http_version - uri);
1796 }
1797 else
1798 {
1799 request->version_s = "";
1800 args = memchr (uri,
1801 '?',
1802 line_len - (uri - line));
1803 }
1804 url_end = http_version - uri;
1805 } 1822 }
1823 url_end = http_version - uri;
1824 }
1806 if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) && 1825 if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) &&
1807 (NULL != memchr (curi, 1826 (NULL != memchr (curi,
1808 ' ', 1827 ' ',
1809 url_end)) ) 1828 url_end)) )
1810 { 1829 {
1811 /* space exists in URI and we are supposed to be strict, reject */ 1830 /* space exists in URI and we are supposed to be strict, reject */
1812 return MHD_NO; 1831 return MHD_NO;
1813 } 1832 }
1814 if (NULL != daemon->early_uri_logger_cb) 1833 if (NULL != daemon->early_uri_logger_cb)
1815 { 1834 {
1816 request->client_context 1835 request->client_context
1817 = daemon->early_uri_logger_cb (daemon->early_uri_logger_cb_cls, 1836 = daemon->early_uri_logger_cb (daemon->early_uri_logger_cb_cls,
1818 curi, 1837 curi,
1819 request); 1838 request);
1820 } 1839 }
1821 if (NULL != args) 1840 if (NULL != args)
1822 { 1841 {
1823 args[0] = '\0'; 1842 args[0] = '\0';
1824 args++; 1843 args++;
1825 /* note that this call clobbers 'args' */ 1844 /* note that this call clobbers 'args' */
1826 MHD_parse_arguments_ (request, 1845 MHD_parse_arguments_ (request,
1827 MHD_GET_ARGUMENT_KIND, 1846 MHD_GET_ARGUMENT_KIND,
1828 args, 1847 args,
1829 &request_add_header, 1848 &request_add_header,
1830 &unused_num_headers); 1849 &unused_num_headers);
1831 } 1850 }
1832 if (NULL != uri) 1851 if (NULL != uri)
1833 daemon->unescape_cb (daemon->unescape_cb_cls, 1852 daemon->unescape_cb (daemon->unescape_cb_cls,
1834 request, 1853 request,
1835 uri); 1854 uri);
1836 request->url = curi; 1855 request->url = curi;
1837 return true; 1856 return true;
1838} 1857}
@@ -1856,43 +1875,46 @@ process_header_line (struct MHD_Request *request,
1856 1875
1857 /* line should be normal header line, find colon */ 1876 /* line should be normal header line, find colon */
1858 colon = strchr (line, 1877 colon = strchr (line,
1859 ':'); 1878 ':');
1860 if (NULL == colon) 1879 if (NULL == colon)
1880 {
1881 /* error in header line, die hard */
1882 CONNECTION_CLOSE_ERROR (connection,
1883 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1884 _ (
1885 "Received malformed line (no colon). Closing connection.\n"));
1886 return false;
1887 }
1888 if (MHD_PSL_PERMISSIVE != request->daemon->protocol_strict_level)
1889 {
1890 /* check for whitespace before colon, which is not allowed
1891 by RFC 7230 section 3.2.4; we count space ' ' and
1892 tab '\t', but not '\r\n' as those would have ended the line. */
1893 const char *white;
1894
1895 white = strchr (line,
1896 (unsigned char) ' ');
1897 if ( (NULL != white) &&
1898 (white < colon) )
1861 { 1899 {
1862 /* error in header line, die hard */
1863 CONNECTION_CLOSE_ERROR (connection, 1900 CONNECTION_CLOSE_ERROR (connection,
1864 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED, 1901 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1865 _("Received malformed line (no colon). Closing connection.\n")); 1902 _ (
1903 "Whitespace before colon forbidden by RFC 7230. Closing connection.\n"));
1866 return false; 1904 return false;
1867 } 1905 }
1868 if (MHD_PSL_PERMISSIVE != request->daemon->protocol_strict_level) 1906 white = strchr (line,
1907 (unsigned char) '\t');
1908 if ( (NULL != white) &&
1909 (white < colon) )
1869 { 1910 {
1870 /* check for whitespace before colon, which is not allowed 1911 CONNECTION_CLOSE_ERROR (connection,
1871 by RFC 7230 section 3.2.4; we count space ' ' and 1912 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1872 tab '\t', but not '\r\n' as those would have ended the line. */ 1913 _ (
1873 const char *white; 1914 "Tab before colon forbidden by RFC 7230. Closing connection.\n"));
1874 1915 return false;
1875 white = strchr (line,
1876 (unsigned char) ' ');
1877 if ( (NULL != white) &&
1878 (white < colon) )
1879 {
1880 CONNECTION_CLOSE_ERROR (connection,
1881 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1882 _("Whitespace before colon forbidden by RFC 7230. Closing connection.\n"));
1883 return false;
1884 }
1885 white = strchr (line,
1886 (unsigned char) '\t');
1887 if ( (NULL != white) &&
1888 (white < colon) )
1889 {
1890 CONNECTION_CLOSE_ERROR (connection,
1891 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1892 _("Tab before colon forbidden by RFC 7230. Closing connection.\n"));
1893 return false;
1894 }
1895 } 1916 }
1917 }
1896 /* zero-terminate header */ 1918 /* zero-terminate header */
1897 colon[0] = '\0'; 1919 colon[0] = '\0';
1898 colon++; /* advance to value */ 1920 colon++; /* advance to value */
@@ -1935,69 +1957,69 @@ process_broken_line (struct MHD_Request *request,
1935 last = request->last; 1957 last = request->last;
1936 if ( (' ' == line[0]) || 1958 if ( (' ' == line[0]) ||
1937 ('\t' == line[0]) ) 1959 ('\t' == line[0]) )
1938 { 1960 {
1939 /* value was continued on the next line, see 1961 /* value was continued on the next line, see
1940 http://www.jmarshall.com/easy/http/ */ 1962 http://www.jmarshall.com/easy/http/ */
1941 last_len = strlen (last); 1963 last_len = strlen (last);
1942 /* skip whitespace at start of 2nd line */ 1964 /* skip whitespace at start of 2nd line */
1943 tmp = line; 1965 tmp = line;
1944 while ( (' ' == tmp[0]) || 1966 while ( (' ' == tmp[0]) ||
1945 ('\t' == tmp[0]) ) 1967 ('\t' == tmp[0]) )
1946 tmp++; 1968 tmp++;
1947 tmp_len = strlen (tmp); 1969 tmp_len = strlen (tmp);
1948 /* FIXME: we might be able to do this better (faster!), as most 1970 /* FIXME: we might be able to do this better (faster!), as most
1949 likely 'last' and 'line' should already be adjacent in 1971 likely 'last' and 'line' should already be adjacent in
1950 memory; however, doing this right gets tricky if we have a 1972 memory; however, doing this right gets tricky if we have a
1951 value continued over multiple lines (in which case we need to 1973 value continued over multiple lines (in which case we need to
1952 record how often we have done this so we can check for 1974 record how often we have done this so we can check for
1953 adjacency); also, in the case where these are not adjacent 1975 adjacency); also, in the case where these are not adjacent
1954 (not sure how it can happen!), we would want to allocate from 1976 (not sure how it can happen!), we would want to allocate from
1955 the end of the pool, so as to not destroy the read-buffer's 1977 the end of the pool, so as to not destroy the read-buffer's
1956 ability to grow nicely. */ 1978 ability to grow nicely. */
1957 last = MHD_pool_reallocate (connection->pool, 1979 last = MHD_pool_reallocate (connection->pool,
1958 last, 1980 last,
1959 last_len + 1, 1981 last_len + 1,
1960 last_len + tmp_len + 1); 1982 last_len + tmp_len + 1);
1961 if (NULL == last) 1983 if (NULL == last)
1962 {
1963 transmit_error_response (request,
1964 MHD_SC_CLIENT_HEADER_TOO_BIG,
1965 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
1966 REQUEST_TOO_BIG);
1967 return MHD_NO;
1968 }
1969 memcpy (&last[last_len],
1970 tmp,
1971 tmp_len + 1);
1972 request->last = last;
1973 return MHD_YES; /* possibly more than 2 lines... */
1974 }
1975 mhd_assert ( (NULL != last) &&
1976 (NULL != request->colon) );
1977 if (! request_add_header (request,
1978 last,
1979 request->colon,
1980 kind))
1981 { 1984 {
1982 transmit_error_response (request, 1985 transmit_error_response (request,
1983 MHD_SC_CLIENT_HEADER_TOO_BIG, 1986 MHD_SC_CLIENT_HEADER_TOO_BIG,
1984 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 1987 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
1985 REQUEST_TOO_BIG); 1988 REQUEST_TOO_BIG);
1986 return false; 1989 return MHD_NO;
1987 } 1990 }
1991 memcpy (&last[last_len],
1992 tmp,
1993 tmp_len + 1);
1994 request->last = last;
1995 return MHD_YES; /* possibly more than 2 lines... */
1996 }
1997 mhd_assert ( (NULL != last) &&
1998 (NULL != request->colon) );
1999 if (! request_add_header (request,
2000 last,
2001 request->colon,
2002 kind))
2003 {
2004 transmit_error_response (request,
2005 MHD_SC_CLIENT_HEADER_TOO_BIG,
2006 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2007 REQUEST_TOO_BIG);
2008 return false;
2009 }
1988 /* we still have the current line to deal with... */ 2010 /* we still have the current line to deal with... */
1989 if ('\0' != line[0]) 2011 if ('\0' != line[0])
2012 {
2013 if (! process_header_line (request,
2014 line))
1990 { 2015 {
1991 if (! process_header_line (request, 2016 transmit_error_response (request,
1992 line)) 2017 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1993 { 2018 MHD_HTTP_BAD_REQUEST,
1994 transmit_error_response (request, 2019 REQUEST_MALFORMED);
1995 MHD_SC_CONNECTION_PARSE_FAIL_CLOSED, 2020 return false;
1996 MHD_HTTP_BAD_REQUEST,
1997 REQUEST_MALFORMED);
1998 return false;
1999 }
2000 } 2021 }
2022 }
2001 return true; 2023 return true;
2002} 2024}
2003 2025
@@ -2032,22 +2054,22 @@ get_next_header_line (struct MHD_Request *request,
2032 pos++; 2054 pos++;
2033 if ( (pos == request->read_buffer_offset - 1) && 2055 if ( (pos == request->read_buffer_offset - 1) &&
2034 ('\n' != rbuf[pos]) ) 2056 ('\n' != rbuf[pos]) )
2057 {
2058 /* not found, consider growing... */
2059 if ( (request->read_buffer_offset == request->read_buffer_size) &&
2060 (! try_grow_read_buffer (request)) )
2035 { 2061 {
2036 /* not found, consider growing... */ 2062 transmit_error_response (request,
2037 if ( (request->read_buffer_offset == request->read_buffer_size) && 2063 MHD_SC_CLIENT_HEADER_TOO_BIG,
2038 (! try_grow_read_buffer (request)) ) 2064 (NULL != request->url)
2039 { 2065 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
2040 transmit_error_response (request, 2066 : MHD_HTTP_URI_TOO_LONG,
2041 MHD_SC_CLIENT_HEADER_TOO_BIG, 2067 REQUEST_TOO_BIG);
2042 (NULL != request->url)
2043 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
2044 : MHD_HTTP_URI_TOO_LONG,
2045 REQUEST_TOO_BIG);
2046 }
2047 if (line_len)
2048 *line_len = 0;
2049 return NULL;
2050 } 2068 }
2069 if (line_len)
2070 *line_len = 0;
2071 return NULL;
2072 }
2051 2073
2052 if (line_len) 2074 if (line_len)
2053 *line_len = pos; 2075 *line_len = pos;
@@ -2083,7 +2105,7 @@ get_next_header_line (struct MHD_Request *request,
2083 * @return true if force push is possible, false otherwise 2105 * @return true if force push is possible, false otherwise
2084 */ 2106 */
2085static bool 2107static bool
2086socket_flush_possible(struct MHD_Connection *connection) 2108socket_flush_possible (struct MHD_Connection *connection)
2087{ 2109{
2088 (void) connection; /* Mute compiler warning. */ 2110 (void) connection; /* Mute compiler warning. */
2089#if defined(TCP_CORK) || defined(TCP_PUSH) 2111#if defined(TCP_CORK) || defined(TCP_PUSH)
@@ -2105,21 +2127,21 @@ static bool
2105socket_start_extra_buffering (struct MHD_Connection *connection) 2127socket_start_extra_buffering (struct MHD_Connection *connection)
2106{ 2128{
2107 bool res = false; 2129 bool res = false;
2108 (void)connection; /* Mute compiler warning. */ 2130 (void) connection; /* Mute compiler warning. */
2109#if defined(TCP_CORK) || defined(TCP_NOPUSH) 2131#if defined(TCP_CORK) || defined(TCP_NOPUSH)
2110 const MHD_SCKT_OPT_BOOL_ on_val = 1; 2132 const MHD_SCKT_OPT_BOOL_ on_val = 1;
2111#if defined(TCP_NODELAY) 2133#if defined(TCP_NODELAY)
2112 const MHD_SCKT_OPT_BOOL_ off_val = 0; 2134 const MHD_SCKT_OPT_BOOL_ off_val = 0;
2113#endif /* TCP_NODELAY */ 2135#endif /* TCP_NODELAY */
2114 mhd_assert(NULL != connection); 2136 mhd_assert (NULL != connection);
2115#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 2137#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2116 /* Buffer data before sending */ 2138 /* Buffer data before sending */
2117 res = (0 == setsockopt (connection->socket_fd, 2139 res = (0 == setsockopt (connection->socket_fd,
2118 IPPROTO_TCP, 2140 IPPROTO_TCP,
2119 TCP_NOPUSH, 2141 TCP_NOPUSH,
2120 (const void *) &on_val, 2142 (const void *) &on_val,
2121 sizeof (on_val))) 2143 sizeof (on_val)))
2122 ? true : false; 2144 ? true : false;
2123#if defined(TCP_NODELAY) 2145#if defined(TCP_NODELAY)
2124 /* Enable Nagle's algorithm */ 2146 /* Enable Nagle's algorithm */
2125 /* TCP_NODELAY may interfere with TCP_NOPUSH */ 2147 /* TCP_NODELAY may interfere with TCP_NOPUSH */
@@ -2128,7 +2150,7 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
2128 TCP_NODELAY, 2150 TCP_NODELAY,
2129 (const void *) &off_val, 2151 (const void *) &off_val,
2130 sizeof (off_val))) 2152 sizeof (off_val)))
2131 ? true : false; 2153 ? true : false;
2132#endif /* TCP_NODELAY */ 2154#endif /* TCP_NODELAY */
2133#else /* TCP_CORK */ 2155#else /* TCP_CORK */
2134#if defined(TCP_NODELAY) 2156#if defined(TCP_NODELAY)
@@ -2147,7 +2169,7 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
2147 TCP_CORK, 2169 TCP_CORK,
2148 (const void *) &on_val, 2170 (const void *) &on_val,
2149 sizeof (on_val))) 2171 sizeof (on_val)))
2150 ? true : false; 2172 ? true : false;
2151#endif /* TCP_CORK */ 2173#endif /* TCP_CORK */
2152#endif /* TCP_CORK || TCP_NOPUSH */ 2174#endif /* TCP_CORK || TCP_NOPUSH */
2153 return res; 2175 return res;
@@ -2170,8 +2192,8 @@ socket_start_no_buffering (struct MHD_Connection *connection)
2170 const MHD_SCKT_OPT_BOOL_ off_val = 0; 2192 const MHD_SCKT_OPT_BOOL_ off_val = 0;
2171#endif /* TCP_CORK || TCP_NOPUSH */ 2193#endif /* TCP_CORK || TCP_NOPUSH */
2172 2194
2173 (void)connection; /* Mute compiler warning. */ 2195 (void) connection; /* Mute compiler warning. */
2174 mhd_assert(NULL != connection); 2196 mhd_assert (NULL != connection);
2175#if defined(TCP_CORK) 2197#if defined(TCP_CORK)
2176 /* Allow partial packets */ 2198 /* Allow partial packets */
2177 res &= (0 == setsockopt (connection->socket_fd, 2199 res &= (0 == setsockopt (connection->socket_fd,
@@ -2179,7 +2201,7 @@ socket_start_no_buffering (struct MHD_Connection *connection)
2179 TCP_CORK, 2201 TCP_CORK,
2180 (const void *) &off_val, 2202 (const void *) &off_val,
2181 sizeof (off_val))) 2203 sizeof (off_val)))
2182 ? true : false; 2204 ? true : false;
2183#endif /* TCP_CORK */ 2205#endif /* TCP_CORK */
2184#if defined(TCP_NODELAY) 2206#if defined(TCP_NODELAY)
2185 /* Disable Nagle's algorithm for sending packets without delay */ 2207 /* Disable Nagle's algorithm for sending packets without delay */
@@ -2188,16 +2210,16 @@ socket_start_no_buffering (struct MHD_Connection *connection)
2188 TCP_NODELAY, 2210 TCP_NODELAY,
2189 (const void *) &on_val, 2211 (const void *) &on_val,
2190 sizeof (on_val))) 2212 sizeof (on_val)))
2191 ? true : false; 2213 ? true : false;
2192#endif /* TCP_NODELAY */ 2214#endif /* TCP_NODELAY */
2193#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 2215#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2194 /* Disable extra buffering */ 2216 /* Disable extra buffering */
2195 res &= (0 == setsockopt (connection->socket_fd, 2217 res &= (0 == setsockopt (connection->socket_fd,
2196 IPPROTO_TCP, 2218 IPPROTO_TCP,
2197 TCP_NOPUSH, 2219 TCP_NOPUSH,
2198 (const void *) &off_val, 2220 (const void *) &off_val,
2199 sizeof (off_val))) 2221 sizeof (off_val)))
2200 ? true : false; 2222 ? true : false;
2201#endif /* TCP_NOPUSH && !TCP_CORK */ 2223#endif /* TCP_NOPUSH && !TCP_CORK */
2202 return res; 2224 return res;
2203#else /* !TCP_NODELAY */ 2225#else /* !TCP_NODELAY */
@@ -2217,21 +2239,21 @@ static bool
2217socket_start_no_buffering_flush (struct MHD_Connection *connection) 2239socket_start_no_buffering_flush (struct MHD_Connection *connection)
2218{ 2240{
2219 bool res = true; 2241 bool res = true;
2220#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 2242#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2221 const int dummy = 0; 2243 const int dummy = 0;
2222#endif /* !TCP_CORK */ 2244#endif /* !TCP_CORK */
2223 2245
2224 if (NULL == connection) 2246 if (NULL == connection)
2225 return false; /* FIXME: use MHD_NONNULL? */ 2247 return false; /* FIXME: use MHD_NONNULL? */
2226 res = socket_start_no_buffering (connection); 2248 res = socket_start_no_buffering (connection);
2227#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 2249#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2228 /* Force flush data with zero send otherwise Darwin and some BSD systems 2250 /* Force flush data with zero send otherwise Darwin and some BSD systems
2229 will add 5 seconds delay. Not required with TCP_CORK as switching off 2251 will add 5 seconds delay. Not required with TCP_CORK as switching off
2230 TCP_CORK always flushes socket buffer. */ 2252 TCP_CORK always flushes socket buffer. */
2231 res &= (0 <= MHD_send_ (connection->socket_fd, 2253 res &= (0 <= MHD_send_ (connection->socket_fd,
2232 &dummy, 2254 &dummy,
2233 0)) 2255 0))
2234 ? true : false; 2256 ? true : false;
2235#endif /* TCP_NOPUSH && !TCP_CORK*/ 2257#endif /* TCP_NOPUSH && !TCP_CORK*/
2236 return res; 2258 return res;
2237} 2259}
@@ -2254,7 +2276,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
2254 socklen_t param_size = sizeof (cork_val); 2276 socklen_t param_size = sizeof (cork_val);
2255#endif /* TCP_CORK */ 2277#endif /* TCP_CORK */
2256 2278
2257 mhd_assert(NULL != connection); 2279 mhd_assert (NULL != connection);
2258#if defined(TCP_CORK) 2280#if defined(TCP_CORK)
2259 /* Allow partial packets */ 2281 /* Allow partial packets */
2260 /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before 2282 /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
@@ -2262,7 +2284,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
2262 if ( (0 != getsockopt (connection->socket_fd, 2284 if ( (0 != getsockopt (connection->socket_fd,
2263 IPPROTO_TCP, 2285 IPPROTO_TCP,
2264 TCP_CORK, 2286 TCP_CORK,
2265 (void*)&cork_val, 2287 (void*) &cork_val,
2266 &param_size)) || 2288 &param_size)) ||
2267 (0 != cork_val)) 2289 (0 != cork_val))
2268 res &= (0 == setsockopt (connection->socket_fd, 2290 res &= (0 == setsockopt (connection->socket_fd,
@@ -2270,7 +2292,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
2270 TCP_CORK, 2292 TCP_CORK,
2271 (const void *) &off_val, 2293 (const void *) &off_val,
2272 sizeof (off_val))) 2294 sizeof (off_val)))
2273 ? true : false; 2295 ? true : false;
2274#elif defined(TCP_NOPUSH) 2296#elif defined(TCP_NOPUSH)
2275 /* Disable extra buffering */ 2297 /* Disable extra buffering */
2276 /* No need to check current value as disabling TCP_NOPUSH will not flush partial 2298 /* No need to check current value as disabling TCP_NOPUSH will not flush partial
@@ -2280,7 +2302,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
2280 TCP_NOPUSH, 2302 TCP_NOPUSH,
2281 (const void *) &off_val, 2303 (const void *) &off_val,
2282 sizeof (off_val))) 2304 sizeof (off_val)))
2283 ? true : false; 2305 ? true : false;
2284#endif /* TCP_NOPUSH && !TCP_CORK */ 2306#endif /* TCP_NOPUSH && !TCP_CORK */
2285 /* Enable Nagle's algorithm for normal buffering */ 2307 /* Enable Nagle's algorithm for normal buffering */
2286 res &= (0 == setsockopt (connection->socket_fd, 2308 res &= (0 == setsockopt (connection->socket_fd,
@@ -2288,7 +2310,7 @@ socket_start_normal_buffering (struct MHD_Connection *connection)
2288 TCP_NODELAY, 2310 TCP_NODELAY,
2289 (const void *) &off_val, 2311 (const void *) &off_val,
2290 sizeof (off_val))) 2312 sizeof (off_val)))
2291 ? true : false; 2313 ? true : false;
2292 return res; 2314 return res;
2293#else /* !TCP_NODELAY */ 2315#else /* !TCP_NODELAY */
2294 return false; 2316 return false;
@@ -2309,16 +2331,17 @@ need_100_continue (struct MHD_Request *request)
2309 const char *expect; 2331 const char *expect;
2310 2332
2311 return ( (NULL == request->response) && 2333 return ( (NULL == request->response) &&
2312 (NULL != request->version_s) && 2334 (NULL != request->version_s) &&
2313 (MHD_str_equal_caseless_(request->version_s, 2335 (MHD_str_equal_caseless_ (request->version_s,
2314 MHD_HTTP_VERSION_1_1)) && 2336 MHD_HTTP_VERSION_1_1)) &&
2315 (NULL != (expect = MHD_request_lookup_value (request, 2337 (NULL != (expect = MHD_request_lookup_value (request,
2316 MHD_HEADER_KIND, 2338 MHD_HEADER_KIND,
2317 MHD_HTTP_HEADER_EXPECT))) && 2339 MHD_HTTP_HEADER_EXPECT)))
2318 (MHD_str_equal_caseless_(expect, 2340 &&
2319 "100-continue")) && 2341 (MHD_str_equal_caseless_ (expect,
2320 (request->continue_message_write_offset < 2342 "100-continue")) &&
2321 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) ); 2343 (request->continue_message_write_offset <
2344 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) );
2322} 2345}
2323 2346
2324 2347
@@ -2342,94 +2365,94 @@ parse_cookie_header (struct MHD_Request *request)
2342 int quotes; 2365 int quotes;
2343 2366
2344 hdr = MHD_request_lookup_value (request, 2367 hdr = MHD_request_lookup_value (request,
2345 MHD_HEADER_KIND, 2368 MHD_HEADER_KIND,
2346 MHD_HTTP_HEADER_COOKIE); 2369 MHD_HTTP_HEADER_COOKIE);
2347 if (NULL == hdr) 2370 if (NULL == hdr)
2348 return true; 2371 return true;
2349 cpy = MHD_pool_allocate (request->connection->pool, 2372 cpy = MHD_pool_allocate (request->connection->pool,
2350 strlen (hdr) + 1, 2373 strlen (hdr) + 1,
2351 MHD_YES); 2374 MHD_YES);
2352 if (NULL == cpy) 2375 if (NULL == cpy)
2353 { 2376 {
2354#ifdef HAVE_MESSAGES 2377#ifdef HAVE_MESSAGES
2355 MHD_DLOG (request->daemon, 2378 MHD_DLOG (request->daemon,
2356 MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE, 2379 MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
2357 _("Not enough memory in pool to parse cookies!\n")); 2380 _ ("Not enough memory in pool to parse cookies!\n"));
2358#endif 2381#endif
2359 transmit_error_response (request, 2382 transmit_error_response (request,
2360 MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE, 2383 MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
2361 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 2384 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2362 REQUEST_TOO_BIG); 2385 REQUEST_TOO_BIG);
2363 return false; 2386 return false;
2364 } 2387 }
2365 memcpy (cpy, 2388 memcpy (cpy,
2366 hdr, 2389 hdr,
2367 strlen (hdr) + 1); 2390 strlen (hdr) + 1);
2368 pos = cpy; 2391 pos = cpy;
2369 while (NULL != pos) 2392 while (NULL != pos)
2370 { 2393 {
2371 while (' ' == *pos) 2394 while (' ' == *pos)
2372 pos++; /* skip spaces */ 2395 pos++; /* skip spaces */
2373 2396
2374 sce = pos; 2397 sce = pos;
2375 while ( ((*sce) != '\0') && 2398 while ( ((*sce) != '\0') &&
2376 ((*sce) != ',') && 2399 ((*sce) != ',') &&
2377 ((*sce) != ';') && 2400 ((*sce) != ';') &&
2378 ((*sce) != '=') ) 2401 ((*sce) != '=') )
2379 sce++; 2402 sce++;
2380 /* remove tailing whitespace (if any) from key */ 2403 /* remove tailing whitespace (if any) from key */
2381 ekill = sce - 1; 2404 ekill = sce - 1;
2382 while ( (*ekill == ' ') && 2405 while ( (*ekill == ' ') &&
2383 (ekill >= pos) ) 2406 (ekill >= pos) )
2384 *(ekill--) = '\0'; 2407 *(ekill--) = '\0';
2385 old = *sce; 2408 old = *sce;
2386 *sce = '\0'; 2409 *sce = '\0';
2387 if (old != '=') 2410 if (old != '=')
2388 { 2411 {
2389 /* value part omitted, use empty string... */ 2412 /* value part omitted, use empty string... */
2390 if (! request_add_header (request,
2391 pos,
2392 "",
2393 MHD_COOKIE_KIND))
2394 return false;
2395 if (old == '\0')
2396 break;
2397 pos = sce + 1;
2398 continue;
2399 }
2400 equals = sce + 1;
2401 quotes = 0;
2402 semicolon = equals;
2403 while ( ('\0' != semicolon[0]) &&
2404 ( (0 != quotes) ||
2405 ( (';' != semicolon[0]) &&
2406 (',' != semicolon[0]) ) ) )
2407 {
2408 if ('"' == semicolon[0])
2409 quotes = (quotes + 1) & 1;
2410 semicolon++;
2411 }
2412 if ('\0' == semicolon[0])
2413 semicolon = NULL;
2414 if (NULL != semicolon)
2415 {
2416 semicolon[0] = '\0';
2417 semicolon++;
2418 }
2419 /* remove quotes */
2420 if ( ('"' == equals[0]) &&
2421 ('"' == equals[strlen (equals) - 1]) )
2422 {
2423 equals[strlen (equals) - 1] = '\0';
2424 equals++;
2425 }
2426 if (! request_add_header (request, 2413 if (! request_add_header (request,
2427 pos, 2414 pos,
2428 equals, 2415 "",
2429 MHD_COOKIE_KIND)) 2416 MHD_COOKIE_KIND))
2430 return false; 2417 return false;
2431 pos = semicolon; 2418 if (old == '\0')
2432 } 2419 break;
2420 pos = sce + 1;
2421 continue;
2422 }
2423 equals = sce + 1;
2424 quotes = 0;
2425 semicolon = equals;
2426 while ( ('\0' != semicolon[0]) &&
2427 ( (0 != quotes) ||
2428 ( (';' != semicolon[0]) &&
2429 (',' != semicolon[0]) ) ) )
2430 {
2431 if ('"' == semicolon[0])
2432 quotes = (quotes + 1) & 1;
2433 semicolon++;
2434 }
2435 if ('\0' == semicolon[0])
2436 semicolon = NULL;
2437 if (NULL != semicolon)
2438 {
2439 semicolon[0] = '\0';
2440 semicolon++;
2441 }
2442 /* remove quotes */
2443 if ( ('"' == equals[0]) &&
2444 ('"' == equals[strlen (equals) - 1]) )
2445 {
2446 equals[strlen (equals) - 1] = '\0';
2447 equals++;
2448 }
2449 if (! request_add_header (request,
2450 pos,
2451 equals,
2452 MHD_COOKIE_KIND))
2453 return false;
2454 pos = semicolon;
2455 }
2433 return true; 2456 return true;
2434} 2457}
2435 2458
@@ -2454,64 +2477,64 @@ parse_request_headers (struct MHD_Request *request)
2454 parse_cookie_header (request); /* FIXME: return value ignored! */ 2477 parse_cookie_header (request); /* FIXME: return value ignored! */
2455 if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) && 2478 if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) &&
2456 (NULL != request->version_s) && 2479 (NULL != request->version_s) &&
2457 (MHD_str_equal_caseless_(MHD_HTTP_VERSION_1_1, 2480 (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
2458 request->version_s)) && 2481 request->version_s)) &&
2459 (NULL == 2482 (NULL ==
2460 MHD_request_lookup_value (request, 2483 MHD_request_lookup_value (request,
2461 MHD_HEADER_KIND, 2484 MHD_HEADER_KIND,
2462 MHD_HTTP_HEADER_HOST)) ) 2485 MHD_HTTP_HEADER_HOST)) )
2463 { 2486 {
2464 /* die, http 1.1 request without host and we are pedantic */ 2487 /* die, http 1.1 request without host and we are pedantic */
2465 request->state = MHD_REQUEST_FOOTERS_RECEIVED; 2488 request->state = MHD_REQUEST_FOOTERS_RECEIVED;
2466 connection->read_closed = true; 2489 connection->read_closed = true;
2467#ifdef HAVE_MESSAGES 2490#ifdef HAVE_MESSAGES
2468 MHD_DLOG (daemon, 2491 MHD_DLOG (daemon,
2469 MHD_SC_HOST_HEADER_MISSING, 2492 MHD_SC_HOST_HEADER_MISSING,
2470 _("Received HTTP 1.1 request without `Host' header.\n")); 2493 _ ("Received HTTP 1.1 request without `Host' header.\n"));
2471#endif 2494#endif
2472 mhd_assert (NULL == request->response); 2495 mhd_assert (NULL == request->response);
2473 response = 2496 response =
2474 MHD_response_from_buffer (MHD_HTTP_BAD_REQUEST, 2497 MHD_response_from_buffer (MHD_HTTP_BAD_REQUEST,
2475 MHD_STATICSTR_LEN_ (REQUEST_LACKS_HOST), 2498 MHD_STATICSTR_LEN_ (REQUEST_LACKS_HOST),
2476 REQUEST_LACKS_HOST, 2499 REQUEST_LACKS_HOST,
2477 MHD_RESPMEM_PERSISTENT); 2500 MHD_RESPMEM_PERSISTENT);
2478 request->response = response; 2501 request->response = response;
2479 // FIXME: state machine advance? 2502 // FIXME: state machine advance?
2480 return; 2503 return;
2481 } 2504 }
2482 2505
2483 request->remaining_upload_size = 0; 2506 request->remaining_upload_size = 0;
2484 enc = MHD_request_lookup_value (request, 2507 enc = MHD_request_lookup_value (request,
2485 MHD_HEADER_KIND, 2508 MHD_HEADER_KIND,
2486 MHD_HTTP_HEADER_TRANSFER_ENCODING); 2509 MHD_HTTP_HEADER_TRANSFER_ENCODING);
2487 if (NULL != enc) 2510 if (NULL != enc)
2488 { 2511 {
2489 request->remaining_upload_size = MHD_SIZE_UNKNOWN; 2512 request->remaining_upload_size = MHD_SIZE_UNKNOWN;
2490 if (MHD_str_equal_caseless_ (enc, 2513 if (MHD_str_equal_caseless_ (enc,
2491 "chunked")) 2514 "chunked"))
2492 request->have_chunked_upload = true; 2515 request->have_chunked_upload = true;
2493 return; 2516 return;
2494 } 2517 }
2495 clen = MHD_request_lookup_value (request, 2518 clen = MHD_request_lookup_value (request,
2496 MHD_HEADER_KIND, 2519 MHD_HEADER_KIND,
2497 MHD_HTTP_HEADER_CONTENT_LENGTH); 2520 MHD_HTTP_HEADER_CONTENT_LENGTH);
2498 if (NULL == clen) 2521 if (NULL == clen)
2499 return; 2522 return;
2500 end = clen + MHD_str_to_uint64_ (clen, 2523 end = clen + MHD_str_to_uint64_ (clen,
2501 &request->remaining_upload_size); 2524 &request->remaining_upload_size);
2502 if ( (clen == end) || 2525 if ( (clen == end) ||
2503 ('\0' != *end) ) 2526 ('\0' != *end) )
2504 { 2527 {
2505 request->remaining_upload_size = 0; 2528 request->remaining_upload_size = 0;
2506#ifdef HAVE_MESSAGES 2529#ifdef HAVE_MESSAGES
2507 MHD_DLOG (request->daemon, 2530 MHD_DLOG (request->daemon,
2508 MHD_SC_CONTENT_LENGTH_MALFORMED, 2531 MHD_SC_CONTENT_LENGTH_MALFORMED,
2509 "Failed to parse `Content-Length' header. Closing connection.\n"); 2532 "Failed to parse `Content-Length' header. Closing connection.\n");
2510#endif 2533#endif
2511 CONNECTION_CLOSE_ERROR (connection, 2534 CONNECTION_CLOSE_ERROR (connection,
2512 MHD_SC_CONTENT_LENGTH_MALFORMED, 2535 MHD_SC_CONTENT_LENGTH_MALFORMED,
2513 NULL); 2536 NULL);
2514 } 2537 }
2515} 2538}
2516 2539
2517 2540
@@ -2531,19 +2554,20 @@ call_request_handler (struct MHD_Request *request)
2531 if (NULL != request->response) 2554 if (NULL != request->response)
2532 return; /* already queued a response */ 2555 return; /* already queued a response */
2533 if (NULL == (action = 2556 if (NULL == (action =
2534 daemon->rc (daemon->rc_cls, 2557 daemon->rc (daemon->rc_cls,
2535 request, 2558 request,
2536 request->url, 2559 request->url,
2537 request->method))) 2560 request->method)))
2538 { 2561 {
2539 /* serious internal error, close connection */ 2562 /* serious internal error, close connection */
2540 CONNECTION_CLOSE_ERROR (connection, 2563 CONNECTION_CLOSE_ERROR (connection,
2541 MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED, 2564 MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
2542 _("Application reported internal error, closing connection.\n")); 2565 _ (
2543 return; 2566 "Application reported internal error, closing connection.\n"));
2544 } 2567 return;
2568 }
2545 action->action (action->action_cls, 2569 action->action (action->action_cls,
2546 request); 2570 request);
2547} 2571}
2548 2572
2549 2573
@@ -2568,208 +2592,212 @@ process_request_body (struct MHD_Request *request)
2568 buffer_head = request->read_buffer; 2592 buffer_head = request->read_buffer;
2569 available = request->read_buffer_offset; 2593 available = request->read_buffer_offset;
2570 do 2594 do
2571 { 2595 {
2572 size_t to_be_processed; 2596 size_t to_be_processed;
2573 size_t left_unprocessed; 2597 size_t left_unprocessed;
2574 size_t processed_size; 2598 size_t processed_size;
2575 2599
2576 instant_retry = false; 2600 instant_retry = false;
2577 if ( (request->have_chunked_upload) && 2601 if ( (request->have_chunked_upload) &&
2578 (MHD_SIZE_UNKNOWN == request->remaining_upload_size) ) 2602 (MHD_SIZE_UNKNOWN == request->remaining_upload_size) )
2603 {
2604 if ( (request->current_chunk_offset == request->current_chunk_size) &&
2605 (0LLU != request->current_chunk_offset) &&
2606 (available >= 2) )
2607 {
2608 size_t i;
2609
2610 /* skip new line at the *end* of a chunk */
2611 i = 0;
2612 if ( ('\r' == buffer_head[i]) ||
2613 ('\n' == buffer_head[i]) )
2614 i++; /* skip 1st part of line feed */
2615 if ( ('\r' == buffer_head[i]) ||
2616 ('\n' == buffer_head[i]) )
2617 i++; /* skip 2nd part of line feed */
2618 if (0 == i)
2579 { 2619 {
2580 if ( (request->current_chunk_offset == request->current_chunk_size) && 2620 /* malformed encoding */
2581 (0LLU != request->current_chunk_offset) && 2621 CONNECTION_CLOSE_ERROR (connection,
2582 (available >= 2) ) 2622 MHD_SC_CHUNKED_ENCODING_MALFORMED,
2583 { 2623 _ (
2584 size_t i; 2624 "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2585 2625 return;
2586 /* skip new line at the *end* of a chunk */
2587 i = 0;
2588 if ( ('\r' == buffer_head[i]) ||
2589 ('\n' == buffer_head[i]) )
2590 i++; /* skip 1st part of line feed */
2591 if ( ('\r' == buffer_head[i]) ||
2592 ('\n' == buffer_head[i]) )
2593 i++; /* skip 2nd part of line feed */
2594 if (0 == i)
2595 {
2596 /* malformed encoding */
2597 CONNECTION_CLOSE_ERROR (connection,
2598 MHD_SC_CHUNKED_ENCODING_MALFORMED,
2599 _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2600 return;
2601 }
2602 available -= i;
2603 buffer_head += i;
2604 request->current_chunk_offset = 0;
2605 request->current_chunk_size = 0;
2606 }
2607 if (request->current_chunk_offset <
2608 request->current_chunk_size)
2609 {
2610 uint64_t cur_chunk_left;
2611
2612 /* we are in the middle of a chunk, give
2613 as much as possible to the client (without
2614 crossing chunk boundaries) */
2615 cur_chunk_left
2616 = request->current_chunk_size - request->current_chunk_offset;
2617 if (cur_chunk_left > available)
2618 {
2619 to_be_processed = available;
2620 }
2621 else
2622 { /* cur_chunk_left <= (size_t)available */
2623 to_be_processed = (size_t)cur_chunk_left;
2624 if (available > to_be_processed)
2625 instant_retry = true;
2626 }
2627 }
2628 else
2629 {
2630 size_t i;
2631 size_t end_size;
2632 bool malformed;
2633
2634 /* we need to read chunk boundaries */
2635 i = 0;
2636 while (i < available)
2637 {
2638 if ( ('\r' == buffer_head[i]) ||
2639 ('\n' == buffer_head[i]) ||
2640 (';' == buffer_head[i]) )
2641 break;
2642 i++;
2643 if (i >= 16)
2644 break;
2645 }
2646 end_size = i;
2647 /* find beginning of CRLF (skip over chunk extensions) */
2648 if (';' == buffer_head[i])
2649 {
2650 while (i < available)
2651 {
2652 if ( ('\r' == buffer_head[i]) ||
2653 ('\n' == buffer_head[i]) )
2654 break;
2655 i++;
2656 }
2657 }
2658 /* take '\n' into account; if '\n' is the unavailable
2659 character, we will need to wait until we have it
2660 before going further */
2661 if ( (i + 1 >= available) &&
2662 ! ( (1 == i) &&
2663 (2 == available) &&
2664 ('0' == buffer_head[0]) ) )
2665 break; /* need more data... */
2666 i++;
2667 malformed = (end_size >= 16);
2668 if (! malformed)
2669 {
2670 size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2671 end_size,
2672 &request->current_chunk_size);
2673 malformed = (end_size != num_dig);
2674 }
2675 if (malformed)
2676 {
2677 /* malformed encoding */
2678 CONNECTION_CLOSE_ERROR (connection,
2679 MHD_SC_CHUNKED_ENCODING_MALFORMED,
2680 _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2681 return;
2682 }
2683 /* skip 2nd part of line feed */
2684 if ( (i < available) &&
2685 ( ('\r' == buffer_head[i]) ||
2686 ('\n' == buffer_head[i]) ) )
2687 i++;
2688
2689 buffer_head += i;
2690 available -= i;
2691 request->current_chunk_offset = 0;
2692
2693 if (available > 0)
2694 instant_retry = true;
2695 if (0LLU == request->current_chunk_size)
2696 {
2697 request->remaining_upload_size = 0;
2698 break;
2699 }
2700 continue;
2701 }
2702 } 2626 }
2627 available -= i;
2628 buffer_head += i;
2629 request->current_chunk_offset = 0;
2630 request->current_chunk_size = 0;
2631 }
2632 if (request->current_chunk_offset <
2633 request->current_chunk_size)
2634 {
2635 uint64_t cur_chunk_left;
2636
2637 /* we are in the middle of a chunk, give
2638 as much as possible to the client (without
2639 crossing chunk boundaries) */
2640 cur_chunk_left
2641 = request->current_chunk_size - request->current_chunk_offset;
2642 if (cur_chunk_left > available)
2643 {
2644 to_be_processed = available;
2645 }
2646 else
2647 { /* cur_chunk_left <= (size_t)available */
2648 to_be_processed = (size_t) cur_chunk_left;
2649 if (available > to_be_processed)
2650 instant_retry = true;
2651 }
2652 }
2703 else 2653 else
2654 {
2655 size_t i;
2656 size_t end_size;
2657 bool malformed;
2658
2659 /* we need to read chunk boundaries */
2660 i = 0;
2661 while (i < available)
2704 { 2662 {
2705 /* no chunked encoding, give all to the client */ 2663 if ( ('\r' == buffer_head[i]) ||
2706 if ( (0 != request->remaining_upload_size) && 2664 ('\n' == buffer_head[i]) ||
2707 (MHD_SIZE_UNKNOWN != request->remaining_upload_size) && 2665 (';' == buffer_head[i]) )
2708 (request->remaining_upload_size < available) ) 2666 break;
2709 { 2667 i++;
2710 to_be_processed = (size_t)request->remaining_upload_size; 2668 if (i >= 16)
2711 } 2669 break;
2712 else
2713 {
2714 /**
2715 * 1. no chunked encoding, give all to the client
2716 * 2. client may send large chunked data, but only a smaller part is available at one time.
2717 */
2718 to_be_processed = available;
2719 }
2720 } 2670 }
2721 left_unprocessed = to_be_processed; 2671 end_size = i;
2722#if FIXME_OLD_STYLE 2672 /* find beginning of CRLF (skip over chunk extensions) */
2723 if (MHD_NO == 2673 if (';' == buffer_head[i])
2724 daemon->rc (daemon->rc_cls, 2674 {
2725 request, 2675 while (i < available)
2726 request->url, 2676 {
2727 request->method, 2677 if ( ('\r' == buffer_head[i]) ||
2728 request->version, 2678 ('\n' == buffer_head[i]) )
2729 buffer_head, 2679 break;
2730 &left_unprocessed, 2680 i++;
2731 &request->client_context)) 2681 }
2682 }
2683 /* take '\n' into account; if '\n' is the unavailable
2684 character, we will need to wait until we have it
2685 before going further */
2686 if ( (i + 1 >= available) &&
2687 ! ( (1 == i) &&
2688 (2 == available) &&
2689 ('0' == buffer_head[0]) ) )
2690 break; /* need more data... */
2691 i++;
2692 malformed = (end_size >= 16);
2693 if (! malformed)
2694 {
2695 size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2696 end_size,
2697 &request->current_chunk_size);
2698 malformed = (end_size != num_dig);
2699 }
2700 if (malformed)
2732 { 2701 {
2733 /* serious internal error, close connection */ 2702 /* malformed encoding */
2734 CONNECTION_CLOSE_ERROR (connection, 2703 CONNECTION_CLOSE_ERROR (connection,
2735 MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED, 2704 MHD_SC_CHUNKED_ENCODING_MALFORMED,
2736 _("Application reported internal error, closing connection.\n")); 2705 _ (
2706 "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2737 return; 2707 return;
2738 } 2708 }
2709 /* skip 2nd part of line feed */
2710 if ( (i < available) &&
2711 ( ('\r' == buffer_head[i]) ||
2712 ('\n' == buffer_head[i]) ) )
2713 i++;
2714
2715 buffer_head += i;
2716 available -= i;
2717 request->current_chunk_offset = 0;
2718
2719 if (available > 0)
2720 instant_retry = true;
2721 if (0LLU == request->current_chunk_size)
2722 {
2723 request->remaining_upload_size = 0;
2724 break;
2725 }
2726 continue;
2727 }
2728 }
2729 else
2730 {
2731 /* no chunked encoding, give all to the client */
2732 if ( (0 != request->remaining_upload_size) &&
2733 (MHD_SIZE_UNKNOWN != request->remaining_upload_size) &&
2734 (request->remaining_upload_size < available) )
2735 {
2736 to_be_processed = (size_t) request->remaining_upload_size;
2737 }
2738 else
2739 {
2740 /**
2741 * 1. no chunked encoding, give all to the client
2742 * 2. client may send large chunked data, but only a smaller part is available at one time.
2743 */
2744 to_be_processed = available;
2745 }
2746 }
2747 left_unprocessed = to_be_processed;
2748#if FIXME_OLD_STYLE
2749 if (MHD_NO ==
2750 daemon->rc (daemon->rc_cls,
2751 request,
2752 request->url,
2753 request->method,
2754 request->version,
2755 buffer_head,
2756 &left_unprocessed,
2757 &request->client_context))
2758 {
2759 /* serious internal error, close connection */
2760 CONNECTION_CLOSE_ERROR (connection,
2761 MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
2762 _ (
2763 "Application reported internal error, closing connection.\n"));
2764 return;
2765 }
2739#endif 2766#endif
2740 if (left_unprocessed > to_be_processed) 2767 if (left_unprocessed > to_be_processed)
2741 mhd_panic (mhd_panic_cls, 2768 mhd_panic (mhd_panic_cls,
2742 __FILE__, 2769 __FILE__,
2743 __LINE__ 2770 __LINE__
2744#ifdef HAVE_MESSAGES 2771#ifdef HAVE_MESSAGES
2745 , _("libmicrohttpd API violation") 2772 , _ ("libmicrohttpd API violation")
2746#else 2773#else
2747 , NULL 2774 , NULL
2748#endif 2775#endif
2749 ); 2776 );
2750 if (0 != left_unprocessed) 2777 if (0 != left_unprocessed)
2751 { 2778 {
2752 instant_retry = false; /* client did not process everything */ 2779 instant_retry = false; /* client did not process everything */
2753#ifdef HAVE_MESSAGES 2780#ifdef HAVE_MESSAGES
2754 /* client did not process all upload data, complain if 2781 /* client did not process all upload data, complain if
2755 the setup was incorrect, which may prevent us from 2782 the setup was incorrect, which may prevent us from
2756 handling the rest of the request */ 2783 handling the rest of the request */
2757 if ( (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode) && 2784 if ( (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode) &&
2758 (! connection->suspended) ) 2785 (! connection->suspended) )
2759 MHD_DLOG (daemon, 2786 MHD_DLOG (daemon,
2760 MHD_SC_APPLICATION_HUNG_CONNECTION, 2787 MHD_SC_APPLICATION_HUNG_CONNECTION,
2761 _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n")); 2788 _ (
2789 "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2762#endif 2790#endif
2763 }
2764 processed_size = to_be_processed - left_unprocessed;
2765 if (request->have_chunked_upload)
2766 request->current_chunk_offset += processed_size;
2767 /* dh left "processed" bytes in buffer for next time... */
2768 buffer_head += processed_size;
2769 available -= processed_size;
2770 if (MHD_SIZE_UNKNOWN != request->remaining_upload_size)
2771 request->remaining_upload_size -= processed_size;
2772 } 2791 }
2792 processed_size = to_be_processed - left_unprocessed;
2793 if (request->have_chunked_upload)
2794 request->current_chunk_offset += processed_size;
2795 /* dh left "processed" bytes in buffer for next time... */
2796 buffer_head += processed_size;
2797 available -= processed_size;
2798 if (MHD_SIZE_UNKNOWN != request->remaining_upload_size)
2799 request->remaining_upload_size -= processed_size;
2800 }
2773 while (instant_retry); 2801 while (instant_retry);
2774 if (available > 0) 2802 if (available > 0)
2775 memmove (request->read_buffer, 2803 memmove (request->read_buffer,
@@ -2796,58 +2824,59 @@ cleanup_connection (struct MHD_Connection *connection)
2796 return; /* Prevent double cleanup. */ 2824 return; /* Prevent double cleanup. */
2797 connection->request.in_cleanup = true; 2825 connection->request.in_cleanup = true;
2798 if (NULL != connection->request.response) 2826 if (NULL != connection->request.response)
2799 { 2827 {
2800 MHD_response_queue_for_destroy (connection->request.response); 2828 MHD_response_queue_for_destroy (connection->request.response);
2801 connection->request.response = NULL; 2829 connection->request.response = NULL;
2802 } 2830 }
2803 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 2831 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
2804 if (connection->suspended) 2832 if (connection->suspended)
2805 { 2833 {
2806 DLL_remove (daemon->suspended_connections_head, 2834 DLL_remove (daemon->suspended_connections_head,
2807 daemon->suspended_connections_tail, 2835 daemon->suspended_connections_tail,
2808 connection); 2836 connection);
2809 connection->suspended = false; 2837 connection->suspended = false;
2810 } 2838 }
2811 else 2839 else
2840 {
2841 if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
2812 { 2842 {
2813 if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) 2843 if (connection->connection_timeout ==
2814 { 2844 daemon->connection_default_timeout)
2815 if (connection->connection_timeout == 2845 XDLL_remove (daemon->normal_timeout_head,
2816 daemon->connection_default_timeout) 2846 daemon->normal_timeout_tail,
2817 XDLL_remove (daemon->normal_timeout_head, 2847 connection);
2818 daemon->normal_timeout_tail, 2848 else
2819 connection); 2849 XDLL_remove (daemon->manual_timeout_head,
2820 else 2850 daemon->manual_timeout_tail,
2821 XDLL_remove (daemon->manual_timeout_head, 2851 connection);
2822 daemon->manual_timeout_tail,
2823 connection);
2824 }
2825 DLL_remove (daemon->connections_head,
2826 daemon->connections_tail,
2827 connection);
2828 } 2852 }
2853 DLL_remove (daemon->connections_head,
2854 daemon->connections_tail,
2855 connection);
2856 }
2829 DLL_insert (daemon->cleanup_head, 2857 DLL_insert (daemon->cleanup_head,
2830 daemon->cleanup_tail, 2858 daemon->cleanup_tail,
2831 connection); 2859 connection);
2832 connection->resuming = false; 2860 connection->resuming = false;
2833 connection->request.in_idle = false; 2861 connection->request.in_idle = false;
2834 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); 2862 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2835 if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode) 2863 if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
2864 {
2865 /* if we were at the connection limit before and are in
2866 thread-per-connection mode, signal the main thread
2867 to resume accepting connections */
2868 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2869 (! MHD_itc_activate_ (daemon->itc,
2870 "c")) )
2836 { 2871 {
2837 /* if we were at the connection limit before and are in
2838 thread-per-connection mode, signal the main thread
2839 to resume accepting connections */
2840 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2841 (! MHD_itc_activate_ (daemon->itc,
2842 "c")) )
2843 {
2844#ifdef HAVE_MESSAGES 2872#ifdef HAVE_MESSAGES
2845 MHD_DLOG (daemon, 2873 MHD_DLOG (daemon,
2846 MHD_SC_ITC_USE_FAILED, 2874 MHD_SC_ITC_USE_FAILED,
2847 _("Failed to signal end of connection via inter-thread communication channel")); 2875 _ (
2876 "Failed to signal end of connection via inter-thread communication channel"));
2848#endif 2877#endif
2849 }
2850 } 2878 }
2879 }
2851} 2880}
2852 2881
2853 2882
@@ -2870,31 +2899,31 @@ connection_epoll_update_ (struct MHD_Connection *connection)
2870 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) && 2899 (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2871 ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->request.event_loop_info) && 2900 ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->request.event_loop_info) &&
2872 (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) || 2901 (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
2873 ( (MHD_EVENT_LOOP_INFO_READ == connection->request.event_loop_info) && 2902 ( (MHD_EVENT_LOOP_INFO_READ == connection->request.event_loop_info) &&
2874 (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) ) 2903 (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
2904 {
2905 /* add to epoll set */
2906 struct epoll_event event;
2907
2908 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2909 event.data.ptr = connection;
2910 if (0 != epoll_ctl (daemon->epoll_fd,
2911 EPOLL_CTL_ADD,
2912 connection->socket_fd,
2913 &event))
2875 { 2914 {
2876 /* add to epoll set */
2877 struct epoll_event event;
2878
2879 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2880 event.data.ptr = connection;
2881 if (0 != epoll_ctl (daemon->epoll_fd,
2882 EPOLL_CTL_ADD,
2883 connection->socket_fd,
2884 &event))
2885 {
2886#ifdef HAVE_MESSAGES 2915#ifdef HAVE_MESSAGES
2887 MHD_DLOG (daemon, 2916 MHD_DLOG (daemon,
2888 MHD_SC_EPOLL_CTL_ADD_FAILED, 2917 MHD_SC_EPOLL_CTL_ADD_FAILED,
2889 _("Call to epoll_ctl failed: %s\n"), 2918 _ ("Call to epoll_ctl failed: %s\n"),
2890 MHD_socket_last_strerr_ ()); 2919 MHD_socket_last_strerr_ ());
2891#endif 2920#endif
2892 connection->request.state = MHD_REQUEST_CLOSED; 2921 connection->request.state = MHD_REQUEST_CLOSED;
2893 cleanup_connection (connection); 2922 cleanup_connection (connection);
2894 return false; 2923 return false;
2895 }
2896 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2897 } 2924 }
2925 connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2926 }
2898 return true; 2927 return true;
2899} 2928}
2900#endif 2929#endif
@@ -2922,142 +2951,142 @@ connection_update_event_loop_info (struct MHD_Connection *connection)
2922 struct MHD_TLS_Plugin *tls; 2951 struct MHD_TLS_Plugin *tls;
2923 2952
2924 if ( (NULL != (tls = daemon->tls_api)) && 2953 if ( (NULL != (tls = daemon->tls_api)) &&
2925 (tls->update_event_loop_info (tls->cls, 2954 (tls->update_event_loop_info (tls->cls,
2926 connection->tls_cs, 2955 connection->tls_cs,
2927 &request->event_loop_info)) ) 2956 &request->event_loop_info)) )
2928 return; /* TLS has decided what to do */ 2957 return; /* TLS has decided what to do */
2929 } 2958 }
2930#endif /* HTTPS_SUPPORT */ 2959#endif /* HTTPS_SUPPORT */
2931 while (1) 2960 while (1)
2932 { 2961 {
2933#if DEBUG_STATES 2962#if DEBUG_STATES
2934 MHD_DLOG (daemon, 2963 MHD_DLOG (daemon,
2935 MHD_SC_STATE_MACHINE_STATUS_REPORT, 2964 MHD_SC_STATE_MACHINE_STATUS_REPORT,
2936 _("In function %s handling connection at state: %s\n"), 2965 _ ("In function %s handling connection at state: %s\n"),
2937 __FUNCTION__, 2966 __FUNCTION__,
2938 MHD_state_to_string (request->state)); 2967 MHD_state_to_string (request->state));
2939#endif 2968#endif
2940 switch (request->state) 2969 switch (request->state)
2970 {
2971 case MHD_REQUEST_INIT:
2972 case MHD_REQUEST_URL_RECEIVED:
2973 case MHD_REQUEST_HEADER_PART_RECEIVED:
2974 /* while reading headers, we always grow the
2975 read buffer if needed, no size-check required */
2976 if ( (request->read_buffer_offset == request->read_buffer_size) &&
2977 (! try_grow_read_buffer (request)) )
2978 {
2979 transmit_error_response (request,
2980 MHD_SC_CLIENT_HEADER_TOO_BIG,
2981 (NULL != request->url)
2982 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
2983 : MHD_HTTP_URI_TOO_LONG,
2984 REQUEST_TOO_BIG);
2985 continue;
2986 }
2987 if (! connection->read_closed)
2988 request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
2989 else
2990 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
2991 break;
2992 case MHD_REQUEST_HEADERS_RECEIVED:
2993 mhd_assert (0);
2994 break;
2995 case MHD_REQUEST_HEADERS_PROCESSED:
2996 mhd_assert (0);
2997 break;
2998 case MHD_REQUEST_CONTINUE_SENDING:
2999 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3000 break;
3001 case MHD_REQUEST_CONTINUE_SENT:
3002 if (request->read_buffer_offset == request->read_buffer_size)
3003 {
3004 if ( (! try_grow_read_buffer (request)) &&
3005 (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) )
2941 { 3006 {
2942 case MHD_REQUEST_INIT: 3007 /* failed to grow the read buffer, and the client
2943 case MHD_REQUEST_URL_RECEIVED: 3008 which is supposed to handle the received data in
2944 case MHD_REQUEST_HEADER_PART_RECEIVED: 3009 a *blocking* fashion (in this mode) did not
2945 /* while reading headers, we always grow the 3010 handle the data as it was supposed to!
2946 read buffer if needed, no size-check required */ 3011
2947 if ( (request->read_buffer_offset == request->read_buffer_size) && 3012 => we would either have to do busy-waiting
2948 (! try_grow_read_buffer (request)) ) 3013 (on the client, which would likely fail),
2949 { 3014 or if we do nothing, we would just timeout
2950 transmit_error_response (request, 3015 on the connection (if a timeout is even set!).
2951 MHD_SC_CLIENT_HEADER_TOO_BIG, 3016
2952 (NULL != request->url) 3017 Solution: we kill the connection with an error */
2953 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE 3018 transmit_error_response (request,
2954 : MHD_HTTP_URI_TOO_LONG, 3019 MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
2955 REQUEST_TOO_BIG); 3020 MHD_HTTP_INTERNAL_SERVER_ERROR,
2956 continue; 3021 INTERNAL_ERROR);
2957 } 3022 continue;
2958 if (! connection->read_closed)
2959 request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
2960 else
2961 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
2962 break;
2963 case MHD_REQUEST_HEADERS_RECEIVED:
2964 mhd_assert (0);
2965 break;
2966 case MHD_REQUEST_HEADERS_PROCESSED:
2967 mhd_assert (0);
2968 break;
2969 case MHD_REQUEST_CONTINUE_SENDING:
2970 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
2971 break;
2972 case MHD_REQUEST_CONTINUE_SENT:
2973 if (request->read_buffer_offset == request->read_buffer_size)
2974 {
2975 if ( (! try_grow_read_buffer (request)) &&
2976 (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) )
2977 {
2978 /* failed to grow the read buffer, and the client
2979 which is supposed to handle the received data in
2980 a *blocking* fashion (in this mode) did not
2981 handle the data as it was supposed to!
2982
2983 => we would either have to do busy-waiting
2984 (on the client, which would likely fail),
2985 or if we do nothing, we would just timeout
2986 on the connection (if a timeout is even set!).
2987
2988 Solution: we kill the connection with an error */
2989 transmit_error_response (request,
2990 MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
2991 MHD_HTTP_INTERNAL_SERVER_ERROR,
2992 INTERNAL_ERROR);
2993 continue;
2994 }
2995 }
2996 if ( (request->read_buffer_offset < request->read_buffer_size) &&
2997 (! connection->read_closed) )
2998 request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
2999 else
3000 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3001 break;
3002 case MHD_REQUEST_BODY_RECEIVED:
3003 case MHD_REQUEST_FOOTER_PART_RECEIVED:
3004 /* while reading footers, we always grow the
3005 read buffer if needed, no size-check required */
3006 if (connection->read_closed)
3007 {
3008 CONNECTION_CLOSE_ERROR (connection,
3009 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3010 NULL);
3011 continue;
3012 }
3013 request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
3014 /* transition to FOOTERS_RECEIVED
3015 happens in read handler */
3016 break;
3017 case MHD_REQUEST_FOOTERS_RECEIVED:
3018 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3019 break;
3020 case MHD_REQUEST_HEADERS_SENDING:
3021 /* headers in buffer, keep writing */
3022 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3023 break;
3024 case MHD_REQUEST_HEADERS_SENT:
3025 mhd_assert (0);
3026 break;
3027 case MHD_REQUEST_NORMAL_BODY_READY:
3028 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3029 break;
3030 case MHD_REQUEST_NORMAL_BODY_UNREADY:
3031 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3032 break;
3033 case MHD_REQUEST_CHUNKED_BODY_READY:
3034 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3035 break;
3036 case MHD_REQUEST_CHUNKED_BODY_UNREADY:
3037 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3038 break;
3039 case MHD_REQUEST_BODY_SENT:
3040 mhd_assert (0);
3041 break;
3042 case MHD_REQUEST_FOOTERS_SENDING:
3043 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3044 break;
3045 case MHD_REQUEST_FOOTERS_SENT:
3046 mhd_assert (0);
3047 break;
3048 case MHD_REQUEST_CLOSED:
3049 request->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
3050 return; /* do nothing, not even reading */
3051#ifdef UPGRADE_SUPPORT
3052 case MHD_REQUEST_UPGRADE:
3053 mhd_assert (0);
3054 break;
3055#endif /* UPGRADE_SUPPORT */
3056 default:
3057 mhd_assert (0);
3058 } 3023 }
3024 }
3025 if ( (request->read_buffer_offset < request->read_buffer_size) &&
3026 (! connection->read_closed) )
3027 request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
3028 else
3029 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3030 break;
3031 case MHD_REQUEST_BODY_RECEIVED:
3032 case MHD_REQUEST_FOOTER_PART_RECEIVED:
3033 /* while reading footers, we always grow the
3034 read buffer if needed, no size-check required */
3035 if (connection->read_closed)
3036 {
3037 CONNECTION_CLOSE_ERROR (connection,
3038 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3039 NULL);
3040 continue;
3041 }
3042 request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
3043 /* transition to FOOTERS_RECEIVED
3044 happens in read handler */
3045 break;
3046 case MHD_REQUEST_FOOTERS_RECEIVED:
3047 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3048 break;
3049 case MHD_REQUEST_HEADERS_SENDING:
3050 /* headers in buffer, keep writing */
3051 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3052 break;
3053 case MHD_REQUEST_HEADERS_SENT:
3054 mhd_assert (0);
3055 break;
3056 case MHD_REQUEST_NORMAL_BODY_READY:
3057 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3058 break;
3059 case MHD_REQUEST_NORMAL_BODY_UNREADY:
3060 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3061 break;
3062 case MHD_REQUEST_CHUNKED_BODY_READY:
3063 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3064 break;
3065 case MHD_REQUEST_CHUNKED_BODY_UNREADY:
3066 request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
3067 break;
3068 case MHD_REQUEST_BODY_SENT:
3069 mhd_assert (0);
3070 break;
3071 case MHD_REQUEST_FOOTERS_SENDING:
3072 request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
3059 break; 3073 break;
3074 case MHD_REQUEST_FOOTERS_SENT:
3075 mhd_assert (0);
3076 break;
3077 case MHD_REQUEST_CLOSED:
3078 request->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
3079 return; /* do nothing, not even reading */
3080#ifdef UPGRADE_SUPPORT
3081 case MHD_REQUEST_UPGRADE:
3082 mhd_assert (0);
3083 break;
3084#endif /* UPGRADE_SUPPORT */
3085 default:
3086 mhd_assert (0);
3060 } 3087 }
3088 break;
3089 }
3061} 3090}
3062 3091
3063 3092
@@ -3082,491 +3111,494 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
3082 3111
3083 request->in_idle = true; 3112 request->in_idle = true;
3084 while (! connection->suspended) 3113 while (! connection->suspended)
3085 { 3114 {
3086#ifdef HTTPS_SUPPORT 3115#ifdef HTTPS_SUPPORT
3087 struct MHD_TLS_Plugin *tls; 3116 struct MHD_TLS_Plugin *tls;
3088 3117
3089 if ( (NULL != (tls = daemon->tls_api)) && 3118 if ( (NULL != (tls = daemon->tls_api)) &&
3090 (! tls->idle_ready (tls->cls, 3119 (! tls->idle_ready (tls->cls,
3091 connection->tls_cs)) ) 3120 connection->tls_cs)) )
3092 break; 3121 break;
3093#endif /* HTTPS_SUPPORT */ 3122#endif /* HTTPS_SUPPORT */
3094#if DEBUG_STATES 3123#if DEBUG_STATES
3095 MHD_DLOG (daemon, 3124 MHD_DLOG (daemon,
3096 MHD_SC_STATE_MACHINE_STATUS_REPORT, 3125 MHD_SC_STATE_MACHINE_STATUS_REPORT,
3097 _("In function %s handling connection at state: %s\n"), 3126 _ ("In function %s handling connection at state: %s\n"),
3098 __FUNCTION__, 3127 __FUNCTION__,
3099 MHD_state_to_string (request->state)); 3128 MHD_state_to_string (request->state));
3100#endif 3129#endif
3101 switch (request->state) 3130 switch (request->state)
3131 {
3132 case MHD_REQUEST_INIT:
3133 line = get_next_header_line (request,
3134 &line_len);
3135 /* Check for empty string, as we might want
3136 to tolerate 'spurious' empty lines; also
3137 NULL means we didn't get a full line yet;
3138 line is not 0-terminated here. */
3139 if ( (NULL == line) ||
3140 (0 == line[0]) )
3141 {
3142 if (MHD_REQUEST_INIT != request->state)
3143 continue;
3144 if (connection->read_closed)
3102 { 3145 {
3103 case MHD_REQUEST_INIT: 3146 CONNECTION_CLOSE_ERROR (connection,
3104 line = get_next_header_line (request, 3147 MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3105 &line_len); 3148 NULL);
3106 /* Check for empty string, as we might want
3107 to tolerate 'spurious' empty lines; also
3108 NULL means we didn't get a full line yet;
3109 line is not 0-terminated here. */
3110 if ( (NULL == line) ||
3111 (0 == line[0]) )
3112 {
3113 if (MHD_REQUEST_INIT != request->state)
3114 continue;
3115 if (connection->read_closed)
3116 {
3117 CONNECTION_CLOSE_ERROR (connection,
3118 MHD_SC_CONNECTION_READ_FAIL_CLOSED,