aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/connection.c')
-rw-r--r--src/microhttpd/connection.c4273
1 files changed, 2156 insertions, 2117 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c
index ab760e4a..77fcd849 100644
--- a/src/microhttpd/connection.c
+++ b/src/microhttpd/connection.c
@@ -68,7 +68,8 @@
68 * minimal. 68 * minimal.
69 */ 69 */
70#ifdef HAVE_MESSAGES 70#ifdef HAVE_MESSAGES
71#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>" 71#define REQUEST_TOO_BIG \
72 "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
72#else 73#else
73#define REQUEST_TOO_BIG "" 74#define REQUEST_TOO_BIG ""
74#endif 75#endif
@@ -81,7 +82,8 @@
81 * minimal. 82 * minimal.
82 */ 83 */
83#ifdef HAVE_MESSAGES 84#ifdef HAVE_MESSAGES
84#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>" 85#define REQUEST_LACKS_HOST \
86 "<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>"
85#else 87#else
86#define REQUEST_LACKS_HOST "" 88#define REQUEST_LACKS_HOST ""
87#endif 89#endif
@@ -94,7 +96,8 @@
94 * minimal. 96 * minimal.
95 */ 97 */
96#ifdef HAVE_MESSAGES 98#ifdef HAVE_MESSAGES
97#define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>" 99#define REQUEST_MALFORMED \
100 "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
98#else 101#else
99#define REQUEST_MALFORMED "" 102#define REQUEST_MALFORMED ""
100#endif 103#endif
@@ -106,7 +109,8 @@
106 * minimal. 109 * minimal.
107 */ 110 */
108#ifdef HAVE_MESSAGES 111#ifdef HAVE_MESSAGES
109#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>" 112#define INTERNAL_ERROR \
113 "<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>"
110#else 114#else
111#define INTERNAL_ERROR "" 115#define INTERNAL_ERROR ""
112#endif 116#endif
@@ -157,17 +161,18 @@ MHD_conn_init_static_ (void)
157#ifdef SF_FLAGS 161#ifdef SF_FLAGS
158 long sys_page_size = sysconf (_SC_PAGESIZE); 162 long sys_page_size = sysconf (_SC_PAGESIZE);
159 if (0 > sys_page_size) 163 if (0 > sys_page_size)
160 { /* Failed to get page size. */ 164 { /* Failed to get page size. */
161 freebsd_sendfile_flags_ = SF_NODISKIO; 165 freebsd_sendfile_flags_ = SF_NODISKIO;
162 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO; 166 freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
163 } 167 }
164 else 168 else
165 { 169 {
166 freebsd_sendfile_flags_ = 170 freebsd_sendfile_flags_ =
167 SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO); 171 SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
168 freebsd_sendfile_flags_thd_p_c_ = 172 freebsd_sendfile_flags_thd_p_c_ =
169 SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size), SF_NODISKIO); 173 SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size),
170 } 174 SF_NODISKIO);
175 }
171#endif /* SF_FLAGS */ 176#endif /* SF_FLAGS */
172} 177}
173#endif /* HAVE_FREEBSD_SENDFILE */ 178#endif /* HAVE_FREEBSD_SENDFILE */
@@ -189,9 +194,9 @@ recv_param_adapter (struct MHD_Connection *connection,
189 194
190 if ( (MHD_INVALID_SOCKET == connection->socket_fd) || 195 if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
191 (MHD_CONNECTION_CLOSED == connection->state) ) 196 (MHD_CONNECTION_CLOSED == connection->state) )
192 { 197 {
193 return MHD_ERR_NOTCONN_; 198 return MHD_ERR_NOTCONN_;
194 } 199 }
195 if (i > MHD_SCKT_SEND_MAX_SIZE_) 200 if (i > MHD_SCKT_SEND_MAX_SIZE_)
196 i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */ 201 i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
197 202
@@ -199,25 +204,25 @@ recv_param_adapter (struct MHD_Connection *connection,
199 other, 204 other,
200 i); 205 i);
201 if (0 > ret) 206 if (0 > ret)
207 {
208 const int err = MHD_socket_get_error_ ();
209 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
202 { 210 {
203 const int err = MHD_socket_get_error_ ();
204 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
205 {
206#ifdef EPOLL_SUPPORT 211#ifdef EPOLL_SUPPORT
207 /* Got EAGAIN --- no longer read-ready */ 212 /* Got EAGAIN --- no longer read-ready */
208 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; 213 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
209#endif /* EPOLL_SUPPORT */ 214#endif /* EPOLL_SUPPORT */
210 return MHD_ERR_AGAIN_; 215 return MHD_ERR_AGAIN_;
211 }
212 if (MHD_SCKT_ERR_IS_EINTR_ (err))
213 return MHD_ERR_AGAIN_;
214 if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
215 return MHD_ERR_CONNRESET_;
216 /* Treat any other error as hard error. */
217 return MHD_ERR_NOTCONN_;
218 } 216 }
217 if (MHD_SCKT_ERR_IS_EINTR_ (err))
218 return MHD_ERR_AGAIN_;
219 if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
220 return MHD_ERR_CONNRESET_;
221 /* Treat any other error as hard error. */
222 return MHD_ERR_NOTCONN_;
223 }
219#ifdef EPOLL_SUPPORT 224#ifdef EPOLL_SUPPORT
220 else if (i > (size_t)ret) 225 else if (i > (size_t) ret)
221 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; 226 connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
222#endif /* EPOLL_SUPPORT */ 227#endif /* EPOLL_SUPPORT */
223 return ret; 228 return ret;
@@ -242,9 +247,9 @@ send_param_adapter (struct MHD_Connection *connection,
242 247
243 if ( (MHD_INVALID_SOCKET == connection->socket_fd) || 248 if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
244 (MHD_CONNECTION_CLOSED == connection->state) ) 249 (MHD_CONNECTION_CLOSED == connection->state) )
245 { 250 {
246 return MHD_ERR_NOTCONN_; 251 return MHD_ERR_NOTCONN_;
247 } 252 }
248 if (i > MHD_SCKT_SEND_MAX_SIZE_) 253 if (i > MHD_SCKT_SEND_MAX_SIZE_)
249 i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */ 254 i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
250 255
@@ -252,26 +257,26 @@ send_param_adapter (struct MHD_Connection *connection,
252 other, 257 other,
253 i); 258 i);
254 if (0 > ret) 259 if (0 > ret)
255 { 260 {
256 const int err = MHD_socket_get_error_(); 261 const int err = MHD_socket_get_error_ ();
257 262
258 if (MHD_SCKT_ERR_IS_EAGAIN_(err)) 263 if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
259 { 264 {
260#ifdef EPOLL_SUPPORT 265#ifdef EPOLL_SUPPORT
261 /* EAGAIN --- no longer write-ready */ 266 /* EAGAIN --- no longer write-ready */
262 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; 267 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
263#endif /* EPOLL_SUPPORT */ 268#endif /* EPOLL_SUPPORT */
264 return MHD_ERR_AGAIN_; 269 return MHD_ERR_AGAIN_;
265 }
266 if (MHD_SCKT_ERR_IS_EINTR_ (err))
267 return MHD_ERR_AGAIN_;
268 if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
269 return MHD_ERR_CONNRESET_;
270 /* Treat any other error as hard error. */
271 return MHD_ERR_NOTCONN_;
272 } 270 }
271 if (MHD_SCKT_ERR_IS_EINTR_ (err))
272 return MHD_ERR_AGAIN_;
273 if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
274 return MHD_ERR_CONNRESET_;
275 /* Treat any other error as hard error. */
276 return MHD_ERR_NOTCONN_;
277 }
273#ifdef EPOLL_SUPPORT 278#ifdef EPOLL_SUPPORT
274 else if (i > (size_t)ret) 279 else if (i > (size_t) ret)
275 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; 280 connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
276#endif /* EPOLL_SUPPORT */ 281#endif /* EPOLL_SUPPORT */
277 return ret; 282 return ret;
@@ -298,9 +303,9 @@ send_param_adapter (struct MHD_Connection *connection,
298 * @return true if force push is possible, false otherwise 303 * @return true if force push is possible, false otherwise
299 */ 304 */
300_MHD_static_inline bool 305_MHD_static_inline bool
301socket_flush_possible(struct MHD_Connection *connection) 306socket_flush_possible (struct MHD_Connection *connection)
302{ 307{
303 (void)connection; /* Mute compiler warning. */ 308 (void) connection; /* Mute compiler warning. */
304#if defined(TCP_CORK) || defined(TCP_PUSH) 309#if defined(TCP_CORK) || defined(TCP_PUSH)
305 return true; 310 return true;
306#else /* !TCP_CORK && !TCP_PUSH */ 311#else /* !TCP_CORK && !TCP_PUSH */
@@ -310,20 +315,6 @@ socket_flush_possible(struct MHD_Connection *connection)
310 315
311 316
312/** 317/**
313 * Activate extra buffering mode on connection socket to prevent
314 * sending of partial packets.
315 *
316 * @param connection connection to be processed
317 * @return true on success, false otherwise
318 */
319_MHD_static_inline bool
320socket_start_extra_buffering (struct MHD_Connection *connection)
321{
322 mhd_assert(NULL != connection);
323}
324
325
326/**
327 * Activate no buffering mode (no delay sending) on connection socket 318 * Activate no buffering mode (no delay sending) on connection socket
328 * and push to client data pending in socket buffer. 319 * and push to client data pending in socket buffer.
329 * 320 *
@@ -333,20 +324,20 @@ socket_start_extra_buffering (struct MHD_Connection *connection)
333_MHD_static_inline bool 324_MHD_static_inline bool
334socket_start_no_buffering_flush (struct MHD_Connection *connection) 325socket_start_no_buffering_flush (struct MHD_Connection *connection)
335{ 326{
336 bool res; 327 bool res = false;
337#if defined(TCP_NOPUSH) && !defined(TCP_CORK) 328#if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
338 const int dummy = 0; 329 const int dummy = 0;
339#endif /* !TCP_CORK */ 330#endif /* !TCP_CORK */
340 331
341#if defined(__FreeBSD__) && __FreeBSD__+0 >= 9 332#if defined(__FreeBSD__) && __FreeBSD__ + 0 >= 9
342 /* FreeBSD do not need zero-send for flushing starting from version 9 */ 333 /* FreeBSD do not need zero-send for flushing starting from version 9 */
343#elif defined(TCP_NOPUSH) && !defined(TCP_CORK) 334#elif defined(TCP_NOPUSH) && ! defined(TCP_CORK)
344 /* Force flush data with zero send otherwise Darwin and some BSD systems 335 /* Force flush data with zero send otherwise Darwin and some BSD systems
345 will add 5 seconds delay. Not required with TCP_CORK as switching off 336 will add 5 seconds delay. Not required with TCP_CORK as switching off
346 TCP_CORK always flushes socket buffer. */ 337 TCP_CORK always flushes socket buffer. */
347 res = (0 <= MHD_send_ (connection->socket_fd, 338 res = (0 <= MHD_send_ (connection->socket_fd,
348 &dummy, 339 &dummy,
349 0)) && res; 340 0)) && res;
350#endif /* TCP_NOPUSH && !TCP_CORK*/ 341#endif /* TCP_NOPUSH && !TCP_CORK*/
351 return res; 342 return res;
352} 343}
@@ -378,15 +369,15 @@ MHD_get_connection_values (struct MHD_Connection *connection,
378 ret = 0; 369 ret = 0;
379 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 370 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
380 if (0 != (pos->kind & kind)) 371 if (0 != (pos->kind & kind))
381 { 372 {
382 ret++; 373 ret++;
383 if ( (NULL != iterator) && 374 if ( (NULL != iterator) &&
384 (MHD_YES != iterator (iterator_cls, 375 (MHD_YES != iterator (iterator_cls,
385 pos->kind, 376 pos->kind,
386 pos->header, 377 pos->header,
387 pos->value)) ) 378 pos->value)) )
388 return ret; 379 return ret;
389 } 380 }
390 return ret; 381 return ret;
391} 382}
392 383
@@ -418,23 +409,23 @@ MHD_get_connection_values_n (struct MHD_Connection *connection,
418 409
419 if (NULL == iterator) 410 if (NULL == iterator)
420 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 411 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
421 { 412 {
422 if (kind == pos->kind) 413 if (kind == pos->kind)
423 ret++; 414 ret++;
424 } 415 }
425 else 416 else
426 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 417 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
427 if (kind == pos->kind) 418 if (kind == pos->kind)
428 { 419 {
429 ret++; 420 ret++;
430 if (MHD_NO == iterator (iterator_cls, 421 if (MHD_NO == iterator (iterator_cls,
431 pos->kind, 422 pos->kind,
432 pos->header, 423 pos->header,
433 pos->header_size, 424 pos->header_size,
434 pos->value, 425 pos->value,
435 pos->value_size)) 426 pos->value_size))
436 return ret; 427 return ret;
437 } 428 }
438 return ret; 429 return ret;
439} 430}
440 431
@@ -479,15 +470,15 @@ MHD_set_connection_value_n_nocheck_ (struct MHD_Connection *connection,
479 pos->next = NULL; 470 pos->next = NULL;
480 /* append 'pos' to the linked list of headers */ 471 /* append 'pos' to the linked list of headers */
481 if (NULL == connection->headers_received_tail) 472 if (NULL == connection->headers_received_tail)
482 { 473 {
483 connection->headers_received = pos; 474 connection->headers_received = pos;
484 connection->headers_received_tail = pos; 475 connection->headers_received_tail = pos;
485 } 476 }
486 else 477 else
487 { 478 {
488 connection->headers_received_tail->next = pos; 479 connection->headers_received_tail->next = pos;
489 connection->headers_received_tail = pos; 480 connection->headers_received_tail = pos;
490 } 481 }
491 return MHD_YES; 482 return MHD_YES;
492} 483}
493 484
@@ -526,8 +517,8 @@ MHD_set_connection_value_n (struct MHD_Connection *connection,
526 size_t value_size) 517 size_t value_size)
527{ 518{
528 if ( (MHD_GET_ARGUMENT_KIND != kind) && 519 if ( (MHD_GET_ARGUMENT_KIND != kind) &&
529 ( ((key ? strlen(key) : 0) != key_size) || 520 ( ((key ? strlen (key) : 0) != key_size) ||
530 ((value ? strlen(value) : 0) != value_size) ) ) 521 ((value ? strlen (value) : 0) != value_size) ) )
531 return MHD_NO; /* binary zero is allowed only in GET arguments */ 522 return MHD_NO; /* binary zero is allowed only in GET arguments */
532 523
533 return MHD_set_connection_value_n_nocheck_ (connection, 524 return MHD_set_connection_value_n_nocheck_ (connection,
@@ -604,7 +595,7 @@ MHD_lookup_connection_value (struct MHD_Connection *connection,
604 (void) MHD_lookup_connection_value_n (connection, 595 (void) MHD_lookup_connection_value_n (connection,
605 kind, 596 kind,
606 key, 597 key,
607 (NULL == key) ? 0 : strlen(key), 598 (NULL == key) ? 0 : strlen (key),
608 &value, 599 &value,
609 NULL); 600 NULL);
610 return value; 601 return value;
@@ -644,27 +635,27 @@ MHD_lookup_connection_value_n (struct MHD_Connection *connection,
644 return MHD_NO; 635 return MHD_NO;
645 636
646 if (NULL == key) 637 if (NULL == key)
638 {
639 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
647 { 640 {
648 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 641 if ( (0 != (kind & pos->kind)) &&
649 { 642 (NULL == pos->header) )
650 if ( (0 != (kind & pos->kind)) && 643 break;
651 (NULL == pos->header) )
652 break;
653 }
654 } 644 }
645 }
655 else 646 else
647 {
648 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
656 { 649 {
657 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 650 if ( (0 != (kind & pos->kind)) &&
658 { 651 (key_size == pos->header_size) &&
659 if ( (0 != (kind & pos->kind)) && 652 ( (key == pos->header) ||
660 (key_size == pos->header_size) && 653 (MHD_str_equal_caseless_bin_n_ (key,
661 ( (key == pos->header) || 654 pos->header,
662 (MHD_str_equal_caseless_bin_n_ (key, 655 key_size) ) ) )
663 pos->header, 656 break;
664 key_size) ) ) )
665 break;
666 }
667 } 657 }
658 }
668 659
669 if (NULL == pos) 660 if (NULL == pos)
670 return MHD_NO; 661 return MHD_NO;
@@ -696,27 +687,30 @@ MHD_lookup_connection_value_n (struct MHD_Connection *connection,
696 */ 687 */
697static bool 688static bool
698MHD_lookup_header_token_ci (const struct MHD_Connection *connection, 689MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
699 const char *header, 690 const char *header,
700 size_t header_len, 691 size_t header_len,
701 const char *token, 692 const char *token,
702 size_t token_len) 693 size_t token_len)
703{ 694{
704 struct MHD_HTTP_Header *pos; 695 struct MHD_HTTP_Header *pos;
705 696
706 if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0]) 697 if ((NULL == connection)||(NULL == header)||(0 == header[0])||(NULL ==
698 token) ||(0 ==
699 token
700 [0]) )
707 return false; 701 return false;
708 702
709 for (pos = connection->headers_received; NULL != pos; pos = pos->next) 703 for (pos = connection->headers_received; NULL != pos; pos = pos->next)
710 { 704 {
711 if ((0 != (pos->kind & MHD_HEADER_KIND)) && 705 if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
712 (header_len == pos->header_size) && 706 (header_len == pos->header_size) &&
713 ( (header == pos->header) || 707 ( (header == pos->header) ||
714 (MHD_str_equal_caseless_bin_n_(header, 708 (MHD_str_equal_caseless_bin_n_ (header,
715 pos->header, 709 pos->header,
716 header_len)) ) && 710 header_len)) ) &&
717 (MHD_str_has_token_caseless_ (pos->value, token, token_len))) 711 (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
718 return true; 712 return true;
719 } 713 }
720 return false; 714 return false;
721} 715}
722 716
@@ -733,8 +727,8 @@ MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
733 * false otherwise 727 * false otherwise
734 */ 728 */
735#define MHD_lookup_header_s_token_ci(c,h,tkn) \ 729#define MHD_lookup_header_s_token_ci(c,h,tkn) \
736 MHD_lookup_header_token_ci((c),(h),MHD_STATICSTR_LEN_(h),\ 730 MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
737 (tkn),MHD_STATICSTR_LEN_(tkn)) 731 (tkn),MHD_STATICSTR_LEN_ (tkn))
738 732
739 733
740/** 734/**
@@ -750,19 +744,20 @@ need_100_continue (struct MHD_Connection *connection)
750 const char *expect; 744 const char *expect;
751 745
752 return ( (NULL == connection->response) && 746 return ( (NULL == connection->response) &&
753 (NULL != connection->version) && 747 (NULL != connection->version) &&
754 (MHD_str_equal_caseless_(connection->version, 748 (MHD_str_equal_caseless_ (connection->version,
755 MHD_HTTP_VERSION_1_1)) && 749 MHD_HTTP_VERSION_1_1)) &&
756 (MHD_NO != MHD_lookup_connection_value_n (connection, 750 (MHD_NO != MHD_lookup_connection_value_n (connection,
757 MHD_HEADER_KIND, 751 MHD_HEADER_KIND,
758 MHD_HTTP_HEADER_EXPECT, 752 MHD_HTTP_HEADER_EXPECT,
759 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_EXPECT), 753 MHD_STATICSTR_LEN_ (
754 MHD_HTTP_HEADER_EXPECT),
760 &expect, 755 &expect,
761 NULL)) && 756 NULL)) &&
762 (MHD_str_equal_caseless_(expect, 757 (MHD_str_equal_caseless_ (expect,
763 "100-continue")) && 758 "100-continue")) &&
764 (connection->continue_message_write_offset < 759 (connection->continue_message_write_offset <
765 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) ); 760 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)) );
766} 761}
767 762
768 763
@@ -780,24 +775,24 @@ MHD_connection_mark_closed_ (struct MHD_Connection *connection)
780 connection->state = MHD_CONNECTION_CLOSED; 775 connection->state = MHD_CONNECTION_CLOSED;
781 connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP; 776 connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
782 if (0 == (daemon->options & MHD_USE_TURBO)) 777 if (0 == (daemon->options & MHD_USE_TURBO))
783 { 778 {
784#ifdef HTTPS_SUPPORT 779#ifdef HTTPS_SUPPORT
785 /* For TLS connection use shutdown of TLS layer 780 /* For TLS connection use shutdown of TLS layer
786 * and do not shutdown TCP socket. This give more 781 * and do not shutdown TCP socket. This give more
787 * chances to send TLS closure data to remote side. 782 * chances to send TLS closure data to remote side.
788 * Closure of TLS layer will be interpreted by 783 * Closure of TLS layer will be interpreted by
789 * remote side as end of transmission. */ 784 * remote side as end of transmission. */
790 if (0 != (daemon->options & MHD_USE_TLS)) 785 if (0 != (daemon->options & MHD_USE_TLS))
791 { 786 {
792 if (! MHD_tls_connection_shutdown(connection)) 787 if (! MHD_tls_connection_shutdown (connection))
793 shutdown (connection->socket_fd, 788 shutdown (connection->socket_fd,
794 SHUT_WR); 789 SHUT_WR);
795 }
796 else /* Combined with next 'shutdown()'. */
797#endif /* HTTPS_SUPPORT */
798 shutdown (connection->socket_fd,
799 SHUT_WR);
800 } 790 }
791 else /* Combined with next 'shutdown()'. */
792#endif /* HTTPS_SUPPORT */
793 shutdown (connection->socket_fd,
794 SHUT_WR);
795 }
801} 796}
802 797
803 798
@@ -819,16 +814,16 @@ MHD_connection_close_ (struct MHD_Connection *connection,
819 814
820 MHD_connection_mark_closed_ (connection); 815 MHD_connection_mark_closed_ (connection);
821 if (NULL != resp) 816 if (NULL != resp)
822 { 817 {
823 connection->response = NULL; 818 connection->response = NULL;
824 MHD_destroy_response (resp); 819 MHD_destroy_response (resp);
825 } 820 }
826 if ( (NULL != daemon->notify_completed) && 821 if ( (NULL != daemon->notify_completed) &&
827 (connection->client_aware) ) 822 (connection->client_aware) )
828 daemon->notify_completed (daemon->notify_completed_cls, 823 daemon->notify_completed (daemon->notify_completed_cls,
829 connection, 824 connection,
830 &connection->client_context, 825 &connection->client_context,
831 termination_code); 826 termination_code);
832 connection->client_aware = false; 827 connection->client_aware = false;
833} 828}
834 829
@@ -863,33 +858,33 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection)
863 EPOLL_CTL_DEL, 858 EPOLL_CTL_DEL,
864 connection->socket_fd, 859 connection->socket_fd,
865 NULL)) ) 860 NULL)) )
866 { 861 {
867 MHD_PANIC (_("Failed to remove FD from epoll set\n")); 862 MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
868 } 863 }
869 if (urh->in_eready_list) 864 if (urh->in_eready_list)
870 { 865 {
871 EDLL_remove (daemon->eready_urh_head, 866 EDLL_remove (daemon->eready_urh_head,
872 daemon->eready_urh_tail, 867 daemon->eready_urh_tail,
873 urh); 868 urh);
874 urh->in_eready_list = false; 869 urh->in_eready_list = false;
875 } 870 }
876#endif /* EPOLL_SUPPORT */ 871#endif /* EPOLL_SUPPORT */
877 if (MHD_INVALID_SOCKET != urh->mhd.socket) 872 if (MHD_INVALID_SOCKET != urh->mhd.socket)
878 { 873 {
879#if EPOLL_SUPPORT 874#if EPOLL_SUPPORT
880 if ( (0 != (daemon->options & MHD_USE_EPOLL)) && 875 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
881 (0 != epoll_ctl (daemon->epoll_upgrade_fd, 876 (0 != epoll_ctl (daemon->epoll_upgrade_fd,
882 EPOLL_CTL_DEL, 877 EPOLL_CTL_DEL,
883 urh->mhd.socket, 878 urh->mhd.socket,
884 NULL)) ) 879 NULL)) )
885 { 880 {
886 MHD_PANIC (_("Failed to remove FD from epoll set\n")); 881 MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
887 }
888#endif /* EPOLL_SUPPORT */
889 /* Reflect remote disconnect to application by breaking
890 * socketpair connection. */
891 shutdown (urh->mhd.socket, SHUT_RDWR);
892 } 882 }
883#endif /* EPOLL_SUPPORT */
884 /* Reflect remote disconnect to application by breaking
885 * socketpair connection. */
886 shutdown (urh->mhd.socket, SHUT_RDWR);
887 }
893 /* Socketpair sockets will remain open as they will be 888 /* Socketpair sockets will remain open as they will be
894 * used with MHD_UPGRADE_ACTION_CLOSE. They will be 889 * used with MHD_UPGRADE_ACTION_CLOSE. They will be
895 * closed by MHD_cleanup_upgraded_connection_() during 890 * closed by MHD_cleanup_upgraded_connection_() during
@@ -908,14 +903,14 @@ MHD_connection_finish_forward_ (struct MHD_Connection *connection)
908 */ 903 */
909static void 904static void
910connection_close_error (struct MHD_Connection *connection, 905connection_close_error (struct MHD_Connection *connection,
911 const char *emsg) 906 const char *emsg)
912{ 907{
913#ifdef HAVE_MESSAGES 908#ifdef HAVE_MESSAGES
914 if (NULL != emsg) 909 if (NULL != emsg)
915 MHD_DLOG (connection->daemon, 910 MHD_DLOG (connection->daemon,
916 emsg); 911 emsg);
917#else /* ! HAVE_MESSAGES */ 912#else /* ! HAVE_MESSAGES */
918 (void)emsg; /* Mute compiler warning. */ 913 (void) emsg; /* Mute compiler warning. */
919#endif /* ! HAVE_MESSAGES */ 914#endif /* ! HAVE_MESSAGES */
920 MHD_connection_close_ (connection, 915 MHD_connection_close_ (connection,
921 MHD_REQUEST_TERMINATED_WITH_ERROR); 916 MHD_REQUEST_TERMINATED_WITH_ERROR);
@@ -958,50 +953,51 @@ try_ready_normal_body (struct MHD_Connection *connection)
958 (connection->response_write_position == response->total_size) ) 953 (connection->response_write_position == response->total_size) )
959 return MHD_YES; /* 0-byte response is always ready */ 954 return MHD_YES; /* 0-byte response is always ready */
960 if ( (response->data_start <= 955 if ( (response->data_start <=
961 connection->response_write_position) && 956 connection->response_write_position) &&
962 (response->data_size + response->data_start > 957 (response->data_size + response->data_start >
963 connection->response_write_position) ) 958 connection->response_write_position) )
964 return MHD_YES; /* response already ready */ 959 return MHD_YES; /* response already ready */
965#if defined(_MHD_HAVE_SENDFILE) 960#if defined(_MHD_HAVE_SENDFILE)
966 if (MHD_resp_sender_sendfile == connection->resp_sender) 961 if (MHD_resp_sender_sendfile == connection->resp_sender)
967 { 962 {
968 /* will use sendfile, no need to bother response crc */ 963 /* will use sendfile, no need to bother response crc */
969 return MHD_YES; 964 return MHD_YES;
970 } 965 }
971#endif /* _MHD_HAVE_SENDFILE */ 966#endif /* _MHD_HAVE_SENDFILE */
972 967
973 ret = response->crc (response->crc_cls, 968 ret = response->crc (response->crc_cls,
974 connection->response_write_position, 969 connection->response_write_position,
975 response->data, 970 response->data,
976 (size_t) MHD_MIN ((uint64_t)response->data_buffer_size, 971 (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
977 response->total_size - 972 response->total_size
978 connection->response_write_position)); 973 - connection->response_write_position));
979 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) || 974 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
980 (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) ) 975 (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
981 { 976 {
982 /* either error or http 1.0 transfer, close socket! */ 977 /* either error or http 1.0 transfer, close socket! */
983 response->total_size = connection->response_write_position; 978 response->total_size = connection->response_write_position;
984#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 979#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
985 MHD_mutex_unlock_chk_ (&response->mutex); 980 MHD_mutex_unlock_chk_ (&response->mutex);
986#endif 981#endif
987 if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret) 982 if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
988 MHD_connection_close_ (connection, 983 MHD_connection_close_ (connection,
989 MHD_REQUEST_TERMINATED_COMPLETED_OK); 984 MHD_REQUEST_TERMINATED_COMPLETED_OK);
990 else 985 else
991 CONNECTION_CLOSE_ERROR (connection, 986 CONNECTION_CLOSE_ERROR (connection,
992 _("Closing connection (application reported error generating data)\n")); 987 _ (
993 return MHD_NO; 988 "Closing connection (application reported error generating data)\n"));
994 } 989 return MHD_NO;
990 }
995 response->data_start = connection->response_write_position; 991 response->data_start = connection->response_write_position;
996 response->data_size = ret; 992 response->data_size = ret;
997 if (0 == ret) 993 if (0 == ret)
998 { 994 {
999 connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY; 995 connection->state = MHD_CONNECTION_NORMAL_BODY_UNREADY;
1000#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 996#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1001 MHD_mutex_unlock_chk_ (&response->mutex); 997 MHD_mutex_unlock_chk_ (&response->mutex);
1002#endif 998#endif
1003 return MHD_NO; 999 return MHD_NO;
1004 } 1000 }
1005 return MHD_YES; 1001 return MHD_YES;
1006} 1002}
1007 1003
@@ -1027,95 +1023,96 @@ try_ready_chunked_body (struct MHD_Connection *connection)
1027 if (NULL == response->crc) 1023 if (NULL == response->crc)
1028 return MHD_YES; 1024 return MHD_YES;
1029 if (0 == connection->write_buffer_size) 1025 if (0 == connection->write_buffer_size)
1030 { 1026 {
1031 size_t size; 1027 size_t size;
1032 1028
1033 size = MHD_pool_get_free (connection->pool); 1029 size = MHD_pool_get_free (connection->pool);
1034 if (size < 128) 1030 if (size < 128)
1035 { 1031 {
1036#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 1032#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1037 MHD_mutex_unlock_chk_ (&response->mutex); 1033 MHD_mutex_unlock_chk_ (&response->mutex);
1038#endif 1034#endif
1039 /* not enough memory */ 1035 /* not enough memory */
1040 CONNECTION_CLOSE_ERROR (connection, 1036 CONNECTION_CLOSE_ERROR (connection,
1041 _("Closing connection (out of memory)\n")); 1037 _ ("Closing connection (out of memory)\n"));
1042 return MHD_NO; 1038 return MHD_NO;
1043 }
1044 if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
1045 size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
1046 connection->write_buffer = MHD_pool_allocate (connection->pool,
1047 size,
1048 false);
1049 mhd_assert (NULL != connection->write_buffer);
1050 connection->write_buffer_size = size;
1051 } 1039 }
1040 if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
1041 size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
1042 connection->write_buffer = MHD_pool_allocate (connection->pool,
1043 size,
1044 false);
1045 mhd_assert (NULL != connection->write_buffer);
1046 connection->write_buffer_size = size;
1047 }
1052 1048
1053 if (0 == response->total_size) 1049 if (0 == response->total_size)
1054 ret = 0; /* response must be empty, don't bother calling crc */ 1050 ret = 0; /* response must be empty, don't bother calling crc */
1055 else if ( (response->data_start <= 1051 else if ( (response->data_start <=
1056 connection->response_write_position) && 1052 connection->response_write_position) &&
1057 (response->data_start + response->data_size > 1053 (response->data_start + response->data_size >
1058 connection->response_write_position) ) 1054 connection->response_write_position) )
1059 { 1055 {
1060 /* difference between response_write_position and data_start is less 1056 /* difference between response_write_position and data_start is less
1061 than data_size which is size_t type, no need to check for overflow */ 1057 than data_size which is size_t type, no need to check for overflow */
1062 const size_t data_write_offset 1058 const size_t data_write_offset
1063 = (size_t)(connection->response_write_position - response->data_start); 1059 = (size_t) (connection->response_write_position - response->data_start);
1064 /* buffer already ready, use what is there for the chunk */ 1060 /* buffer already ready, use what is there for the chunk */
1065 ret = response->data_size - data_write_offset; 1061 ret = response->data_size - data_write_offset;
1066 if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 ) 1062 if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
1067 ret = connection->write_buffer_size - sizeof (cbuf) - 2; 1063 ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1068 memcpy (&connection->write_buffer[sizeof (cbuf)], 1064 memcpy (&connection->write_buffer[sizeof (cbuf)],
1069 &response->data[data_write_offset], 1065 &response->data[data_write_offset],
1070 ret); 1066 ret);
1071 } 1067 }
1072 else 1068 else
1073 { 1069 {
1074 /* buffer not in range, try to fill it */ 1070 /* buffer not in range, try to fill it */
1075 ret = response->crc (response->crc_cls, 1071 ret = response->crc (response->crc_cls,
1076 connection->response_write_position, 1072 connection->response_write_position,
1077 &connection->write_buffer[sizeof (cbuf)], 1073 &connection->write_buffer[sizeof (cbuf)],
1078 connection->write_buffer_size - sizeof (cbuf) - 2); 1074 connection->write_buffer_size - sizeof (cbuf) - 2);
1079 } 1075 }
1080 if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) 1076 if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1081 { 1077 {
1082 /* error, close socket! */ 1078 /* error, close socket! */
1083 response->total_size = connection->response_write_position; 1079 response->total_size = connection->response_write_position;
1084#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 1080#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1085 MHD_mutex_unlock_chk_ (&response->mutex); 1081 MHD_mutex_unlock_chk_ (&response->mutex);
1086#endif 1082#endif
1087 CONNECTION_CLOSE_ERROR (connection, 1083 CONNECTION_CLOSE_ERROR (connection,
1088 _("Closing connection (application error generating response)\n")); 1084 _ (
1089 return MHD_NO; 1085 "Closing connection (application error generating response)\n"));
1090 } 1086 return MHD_NO;
1087 }
1091 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) || 1088 if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1092 (0 == response->total_size) ) 1089 (0 == response->total_size) )
1093 { 1090 {
1094 /* end of message, signal other side! */ 1091 /* end of message, signal other side! */
1095 memcpy (connection->write_buffer, 1092 memcpy (connection->write_buffer,
1096 "0\r\n", 1093 "0\r\n",
1097 3); 1094 3);
1098 connection->write_buffer_append_offset = 3; 1095 connection->write_buffer_append_offset = 3;
1099 connection->write_buffer_send_offset = 0; 1096 connection->write_buffer_send_offset = 0;
1100 response->total_size = connection->response_write_position; 1097 response->total_size = connection->response_write_position;
1101 return MHD_YES; 1098 return MHD_YES;
1102 } 1099 }
1103 if (0 == ret) 1100 if (0 == ret)
1104 { 1101 {
1105 connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY; 1102 connection->state = MHD_CONNECTION_CHUNKED_BODY_UNREADY;
1106#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 1103#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1107 MHD_mutex_unlock_chk_ (&response->mutex); 1104 MHD_mutex_unlock_chk_ (&response->mutex);
1108#endif 1105#endif
1109 return MHD_NO; 1106 return MHD_NO;
1110 } 1107 }
1111 if (ret > 0xFFFFFF) 1108 if (ret > 0xFFFFFF)
1112 ret = 0xFFFFFF; 1109 ret = 0xFFFFFF;
1113 cblen = MHD_snprintf_(cbuf, 1110 cblen = MHD_snprintf_ (cbuf,
1114 sizeof (cbuf), 1111 sizeof (cbuf),
1115 "%X\r\n", 1112 "%X\r\n",
1116 (unsigned int) ret); 1113 (unsigned int) ret);
1117 mhd_assert(cblen > 0); 1114 mhd_assert (cblen > 0);
1118 mhd_assert((size_t)cblen < sizeof(cbuf)); 1115 mhd_assert ((size_t) cblen < sizeof(cbuf));
1119 memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], 1116 memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1120 cbuf, 1117 cbuf,
1121 cblen); 1118 cblen);
@@ -1156,33 +1153,34 @@ keepalive_possible (struct MHD_Connection *connection)
1156 (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) ) 1153 (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1157 return MHD_NO; 1154 return MHD_NO;
1158 1155
1159 if (MHD_str_equal_caseless_(connection->version, 1156 if (MHD_str_equal_caseless_ (connection->version,
1160 MHD_HTTP_VERSION_1_1) && 1157 MHD_HTTP_VERSION_1_1) &&
1161 ( (NULL == connection->response) || 1158 ( (NULL == connection->response) ||
1162 (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE) ) ) ) 1159 (0 == (connection->response->flags
1163 { 1160 & MHD_RF_HTTP_VERSION_1_0_RESPONSE) ) ) )
1164 if (MHD_lookup_header_s_token_ci (connection, 1161 {
1165 MHD_HTTP_HEADER_CONNECTION, 1162 if (MHD_lookup_header_s_token_ci (connection,
1166 "upgrade")) 1163 MHD_HTTP_HEADER_CONNECTION,
1167 return MHD_NO; 1164 "upgrade"))
1165 return MHD_NO;
1168 1166
1169 if (MHD_lookup_header_s_token_ci (connection, 1167 if (MHD_lookup_header_s_token_ci (connection,
1170 MHD_HTTP_HEADER_CONNECTION, 1168 MHD_HTTP_HEADER_CONNECTION,
1171 "close")) 1169 "close"))
1172 return MHD_NO; 1170 return MHD_NO;
1173 1171
1172 return MHD_YES;
1173 }
1174 if (MHD_str_equal_caseless_ (connection->version,
1175 MHD_HTTP_VERSION_1_0))
1176 {
1177 if (MHD_lookup_header_s_token_ci (connection,
1178 MHD_HTTP_HEADER_CONNECTION,
1179 "Keep-Alive"))
1174 return MHD_YES; 1180 return MHD_YES;
1175 }
1176 if (MHD_str_equal_caseless_(connection->version,
1177 MHD_HTTP_VERSION_1_0))
1178 {
1179 if (MHD_lookup_header_s_token_ci (connection,
1180 MHD_HTTP_HEADER_CONNECTION,
1181 "Keep-Alive"))
1182 return MHD_YES;
1183 1181
1184 return MHD_NO; 1182 return MHD_NO;
1185 } 1183 }
1186 return MHD_NO; 1184 return MHD_NO;
1187} 1185}
1188 1186
@@ -1196,7 +1194,7 @@ keepalive_possible (struct MHD_Connection *connection)
1196 */ 1194 */
1197static void 1195static void
1198get_date_string (char *date, 1196get_date_string (char *date,
1199 size_t date_len) 1197 size_t date_len)
1200{ 1198{
1201 static const char *const days[] = { 1199 static const char *const days[] = {
1202 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 1200 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
@@ -1207,8 +1205,9 @@ get_date_string (char *date,
1207 }; 1205 };
1208 struct tm now; 1206 struct tm now;
1209 time_t t; 1207 time_t t;
1210#if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R) 1208#if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1211 struct tm* pNow; 1209 ! defined(HAVE_GMTIME_R)
1210 struct tm*pNow;
1212#endif 1211#endif
1213 1212
1214 date[0] = 0; 1213 date[0] = 0;
@@ -1222,25 +1221,25 @@ get_date_string (char *date,
1222 &t)) 1221 &t))
1223 return; 1222 return;
1224#elif defined(HAVE_GMTIME_R) 1223#elif defined(HAVE_GMTIME_R)
1225 if (NULL == gmtime_r(&t, 1224 if (NULL == gmtime_r (&t,
1226 &now)) 1225 &now))
1227 return; 1226 return;
1228#else 1227#else
1229 pNow = gmtime(&t); 1228 pNow = gmtime (&t);
1230 if (NULL == pNow) 1229 if (NULL == pNow)
1231 return; 1230 return;
1232 now = *pNow; 1231 now = *pNow;
1233#endif 1232#endif
1234 MHD_snprintf_ (date, 1233 MHD_snprintf_ (date,
1235 date_len, 1234 date_len,
1236 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n", 1235 "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1237 days[now.tm_wday % 7], 1236 days[now.tm_wday % 7],
1238 (unsigned int) now.tm_mday, 1237 (unsigned int) now.tm_mday,
1239 mons[now.tm_mon % 12], 1238 mons[now.tm_mon % 12],
1240 (unsigned int) (1900 + now.tm_year), 1239 (unsigned int) (1900 + now.tm_year),
1241 (unsigned int) now.tm_hour, 1240 (unsigned int) now.tm_hour,
1242 (unsigned int) now.tm_min, 1241 (unsigned int) now.tm_min,
1243 (unsigned int) now.tm_sec); 1242 (unsigned int) now.tm_sec);
1244} 1243}
1245 1244
1246 1245
@@ -1269,26 +1268,26 @@ try_grow_read_buffer (struct MHD_Connection *connection,
1269 if (0 == connection->read_buffer_size) 1268 if (0 == connection->read_buffer_size)
1270 new_size = avail_size / 2; /* Use half of available buffer for reading */ 1269 new_size = avail_size / 2; /* Use half of available buffer for reading */
1271 else 1270 else
1272 { 1271 {
1273 size_t grow_size; 1272 size_t grow_size;
1274 1273
1275 grow_size = avail_size / 8; 1274 grow_size = avail_size / 8;
1276 if (MHD_BUF_INC_SIZE > grow_size) 1275 if (MHD_BUF_INC_SIZE > grow_size)
1277 { /* Shortage of space */ 1276 { /* Shortage of space */
1278 if (!required) 1277 if (! required)
1279 return false; /* Grow is not mandatory, leave some space in pool */ 1278 return false; /* Grow is not mandatory, leave some space in pool */
1280 else 1279 else
1281 { 1280 {
1282 /* Shortage of space, but grow is mandatory */ 1281 /* Shortage of space, but grow is mandatory */
1283 static const size_t small_inc = MHD_BUF_INC_SIZE / 8; 1282 static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
1284 if (small_inc < avail_size) 1283 if (small_inc < avail_size)
1285 grow_size = small_inc; 1284 grow_size = small_inc;
1286 else 1285 else
1287 grow_size = avail_size; 1286 grow_size = avail_size;
1288 } 1287 }
1289 }
1290 new_size = connection->read_buffer_size + grow_size;
1291 } 1288 }
1289 new_size = connection->read_buffer_size + grow_size;
1290 }
1292 /* we can actually grow the buffer, do it! */ 1291 /* we can actually grow the buffer, do it! */
1293 connection->read_buffer = MHD_pool_reallocate (connection->pool, 1292 connection->read_buffer = MHD_pool_reallocate (connection->pool,
1294 connection->read_buffer, 1293 connection->read_buffer,
@@ -1337,53 +1336,55 @@ build_header_response (struct MHD_Connection *connection)
1337 1336
1338 mhd_assert (NULL != connection->version); 1337 mhd_assert (NULL != connection->version);
1339 if (0 == connection->version[0]) 1338 if (0 == connection->version[0])
1340 { 1339 {
1341 data = MHD_pool_allocate (connection->pool, 1340 data = MHD_pool_allocate (connection->pool,
1342 0, 1341 0,
1343 true); 1342 true);
1344 connection->write_buffer = data; 1343 connection->write_buffer = data;
1345 connection->write_buffer_append_offset = 0; 1344 connection->write_buffer_append_offset = 0;
1346 connection->write_buffer_send_offset = 0; 1345 connection->write_buffer_send_offset = 0;
1347 connection->write_buffer_size = 0; 1346 connection->write_buffer_size = 0;
1348 return MHD_YES; 1347 return MHD_YES;
1349 } 1348 }
1350 rc = connection->responseCode & (~MHD_ICY_FLAG); 1349 rc = connection->responseCode & (~MHD_ICY_FLAG);
1351 if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) 1350 if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1352 { 1351 {
1353 reason_phrase = MHD_get_reason_phrase_for (rc); 1352 reason_phrase = MHD_get_reason_phrase_for (rc);
1354 off = MHD_snprintf_ (code, 1353 off = MHD_snprintf_ (code,
1355 sizeof (code), 1354 sizeof (code),
1356 "%s %u %s\r\n", 1355 "%s %u %s\r\n",
1357 (0 != (connection->responseCode & MHD_ICY_FLAG)) 1356 (0 != (connection->responseCode & MHD_ICY_FLAG))
1358 ? "ICY" 1357 ? "ICY"
1359 : ( (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_0, 1358 : ( (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_0,
1360 connection->version) || 1359 connection->version) ||
1361 (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE)) ) 1360 (0 != (connection->response->flags
1362 ? MHD_HTTP_VERSION_1_0 1361 & MHD_RF_HTTP_VERSION_1_0_RESPONSE)) )
1363 : MHD_HTTP_VERSION_1_1), 1362 ? MHD_HTTP_VERSION_1_0
1364 rc, 1363 : MHD_HTTP_VERSION_1_1),
1365 reason_phrase); 1364 rc,
1366 /* estimate size */ 1365 reason_phrase);
1367 size = off + 2; /* +2 for extra "\r\n" at the end */ 1366 /* estimate size */
1368 kind = MHD_HEADER_KIND; 1367 size = off + 2; /* +2 for extra "\r\n" at the end */
1369 if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) && 1368 kind = MHD_HEADER_KIND;
1370 (NULL == MHD_get_response_header (response, 1369 if ( (0 == (connection->daemon->options
1371 MHD_HTTP_HEADER_DATE)) ) 1370 & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1372 get_date_string (date, 1371 (NULL == MHD_get_response_header (response,
1373 sizeof (date)); 1372 MHD_HTTP_HEADER_DATE)) )
1374 else 1373 get_date_string (date,
1375 date[0] = '\0'; 1374 sizeof (date));
1376 datelen = strlen (date); 1375 else
1377 size += datelen; 1376 date[0] = '\0';
1378 } 1377 datelen = strlen (date);
1378 size += datelen;
1379 }
1379 else 1380 else
1380 { 1381 {
1381 /* 2 bytes for final CRLF of a Chunked-Body */ 1382 /* 2 bytes for final CRLF of a Chunked-Body */
1382 size = 2; 1383 size = 2;
1383 kind = MHD_FOOTER_KIND; 1384 kind = MHD_FOOTER_KIND;
1384 off = 0; 1385 off = 0;
1385 datelen = 0; 1386 datelen = 0;
1386 } 1387 }
1387 1388
1388 /* calculate extra headers we need to add, such as 'Connection: close', 1389 /* calculate extra headers we need to add, such as 'Connection: close',
1389 first see what was explicitly requested by the application */ 1390 first see what was explicitly requested by the application */
@@ -1393,160 +1394,161 @@ build_header_response (struct MHD_Connection *connection)
1393 must_add_content_length = MHD_NO; 1394 must_add_content_length = MHD_NO;
1394 response_has_close = false; 1395 response_has_close = false;
1395 switch (connection->state) 1396 switch (connection->state)
1396 { 1397 {
1397 case MHD_CONNECTION_FOOTERS_RECEIVED: 1398 case MHD_CONNECTION_FOOTERS_RECEIVED:
1398 response_has_close = MHD_check_response_header_s_token_ci (response, 1399 response_has_close = MHD_check_response_header_s_token_ci (response,
1399 MHD_HTTP_HEADER_CONNECTION, 1400 MHD_HTTP_HEADER_CONNECTION,
1400 "close"); 1401 "close");
1401 response_has_keepalive = MHD_check_response_header_s_token_ci (response, 1402 response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1402 MHD_HTTP_HEADER_CONNECTION, 1403 MHD_HTTP_HEADER_CONNECTION,
1403 "Keep-Alive"); 1404 "Keep-Alive");
1404 client_requested_close = MHD_lookup_header_s_token_ci (connection, 1405 client_requested_close = MHD_lookup_header_s_token_ci (connection,
1405 MHD_HTTP_HEADER_CONNECTION, 1406 MHD_HTTP_HEADER_CONNECTION,
1406 "close"); 1407 "close");
1407 1408
1408 if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY)) 1409 if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1409 connection->keepalive = MHD_CONN_MUST_CLOSE; 1410 connection->keepalive = MHD_CONN_MUST_CLOSE;
1410#ifdef UPGRADE_SUPPORT 1411#ifdef UPGRADE_SUPPORT
1411 else if (NULL != response->upgrade_handler) 1412 else if (NULL != response->upgrade_handler)
1412 /* If this connection will not be "upgraded", it must be closed. */ 1413 /* If this connection will not be "upgraded", it must be closed. */
1413 connection->keepalive = MHD_CONN_MUST_CLOSE; 1414 connection->keepalive = MHD_CONN_MUST_CLOSE;
1414#endif /* UPGRADE_SUPPORT */ 1415#endif /* UPGRADE_SUPPORT */
1415 1416
1416 /* now analyze chunked encoding situation */ 1417 /* now analyze chunked encoding situation */
1417 connection->have_chunked_upload = false; 1418 connection->have_chunked_upload = false;
1418 have_encoding = MHD_get_response_header (response, 1419 have_encoding = MHD_get_response_header (response,
1419 MHD_HTTP_HEADER_TRANSFER_ENCODING); 1420 MHD_HTTP_HEADER_TRANSFER_ENCODING);
1420 if (NULL == have_encoding) 1421 if (NULL == have_encoding)
1421 may_add_content_length = MHD_YES; 1422 may_add_content_length = MHD_YES;
1422 else 1423 else
1423 may_add_content_length = MHD_NO; /* RFC 7230, Section 3.3.2 forbids header */ 1424 may_add_content_length = MHD_NO; /* RFC 7230, Section 3.3.2 forbids header */
1424 if ( (MHD_SIZE_UNKNOWN == response->total_size) && 1425 if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1425#ifdef UPGRADE_SUPPORT 1426#ifdef UPGRADE_SUPPORT
1426 (NULL == response->upgrade_handler) && 1427 (NULL == response->upgrade_handler) &&
1427#endif /* UPGRADE_SUPPORT */ 1428#endif /* UPGRADE_SUPPORT */
1428 (! response_has_close) && 1429 (! response_has_close) &&
1429 (! client_requested_close) ) 1430 (! client_requested_close) )
1431 {
1432 /* size is unknown, and close was not explicitly requested;
1433 need to either to HTTP 1.1 chunked encoding or
1434 close the connection */
1435 /* 'close' header doesn't exist yet, see if we need to add one;
1436 if the client asked for a close, no need to start chunk'ing */
1437 if ( (MHD_YES == keepalive_possible (connection)) &&
1438 (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
1439 connection->version) ) )
1440 {
1441 if (NULL == have_encoding)
1442 {
1443 must_add_chunked_encoding = MHD_YES;
1444 connection->have_chunked_upload = true;
1445 }
1446 else
1430 { 1447 {
1431 /* size is unknown, and close was not explicitly requested; 1448 if (MHD_str_equal_caseless_ (have_encoding,
1432 need to either to HTTP 1.1 chunked encoding or 1449 "identity"))
1433 close the connection */ 1450 {
1434 /* 'close' header doesn't exist yet, see if we need to add one; 1451 /* application forced identity encoding, can't do 'chunked' */
1435 if the client asked for a close, no need to start chunk'ing */ 1452 must_add_close = MHD_YES;
1436 if ( (MHD_YES == keepalive_possible (connection)) && 1453 }
1437 (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
1438 connection->version) ) )
1439 {
1440 if (NULL == have_encoding)
1441 {
1442 must_add_chunked_encoding = MHD_YES;
1443 connection->have_chunked_upload = true;
1444 }
1445 else
1446 {
1447 if (MHD_str_equal_caseless_ (have_encoding,
1448 "identity"))
1449 {
1450 /* application forced identity encoding, can't do 'chunked' */
1451 must_add_close = MHD_YES;
1452 }
1453 else
1454 {
1455 connection->have_chunked_upload = true;
1456 }
1457 }
1458 }
1459 else 1454 else
1460 { 1455 {
1461 /* Keep alive or chunking not possible 1456 connection->have_chunked_upload = true;
1462 => set close header if not present */ 1457 }
1463 if (! response_has_close)
1464 must_add_close = MHD_YES;
1465 }
1466 } 1458 }
1459 }
1460 else
1461 {
1462 /* Keep alive or chunking not possible
1463 => set close header if not present */
1464 if (! response_has_close)
1465 must_add_close = MHD_YES;
1466 }
1467 }
1467 1468
1468 /* check for other reasons to add 'close' header */ 1469 /* check for other reasons to add 'close' header */
1469 if ( ( (client_requested_close) || 1470 if ( ( (client_requested_close) ||
1470 (connection->read_closed) || 1471 (connection->read_closed) ||
1471 (MHD_CONN_MUST_CLOSE == connection->keepalive)) && 1472 (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1472 (! response_has_close) && 1473 (! response_has_close) &&
1473#ifdef UPGRADE_SUPPORT 1474#ifdef UPGRADE_SUPPORT
1474 (NULL == response->upgrade_handler) && 1475 (NULL == response->upgrade_handler) &&
1475#endif /* UPGRADE_SUPPORT */ 1476#endif /* UPGRADE_SUPPORT */
1476 (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) ) 1477 (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1477 must_add_close = MHD_YES; 1478 must_add_close = MHD_YES;
1478 1479
1479 /* check if we must add 'close' header because we cannot add content-length 1480 /* check if we must add 'close' header because we cannot add content-length
1480 because it is forbidden AND we don't have a 'chunked' encoding */ 1481 because it is forbidden AND we don't have a 'chunked' encoding */
1481 if ( (! may_add_content_length) && 1482 if ( (! may_add_content_length) &&
1482 (! connection->have_chunked_upload) && 1483 (! connection->have_chunked_upload) &&
1483 (! response_has_close) ) 1484 (! response_has_close) )
1484 must_add_close = MHD_YES; 1485 must_add_close = MHD_YES;
1485 /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status 1486 /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1486 codes SHOULD NOT have a Content-Length according to spec; 1487 codes SHOULD NOT have a Content-Length according to spec;
1487 also chunked encoding / unknown length or CONNECT... */ 1488 also chunked encoding / unknown length or CONNECT... */
1488 if ( (MHD_SIZE_UNKNOWN != response->total_size) && 1489 if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1489 (MHD_HTTP_NO_CONTENT != rc) && 1490 (MHD_HTTP_NO_CONTENT != rc) &&
1490 (MHD_HTTP_NOT_MODIFIED != rc) && 1491 (MHD_HTTP_NOT_MODIFIED != rc) &&
1491 (MHD_HTTP_OK <= rc) && 1492 (MHD_HTTP_OK <= rc) &&
1492 (NULL == /* this should always succeed due to check in 1493 (NULL == /* this should always succeed due to check in
1493 MHD_add_response_header() */ 1494 MHD_add_response_header() */
1494 MHD_get_response_header (response, 1495 MHD_get_response_header (response,
1495 MHD_HTTP_HEADER_CONTENT_LENGTH)) && 1496 MHD_HTTP_HEADER_CONTENT_LENGTH)) &&
1496 (may_add_content_length) && 1497 (may_add_content_length) &&
1497 ( (NULL == connection->method) || 1498 ( (NULL == connection->method) ||
1498 (! MHD_str_equal_caseless_ (connection->method, 1499 (! MHD_str_equal_caseless_ (connection->method,
1499 MHD_HTTP_METHOD_CONNECT)) ) ) 1500 MHD_HTTP_METHOD_CONNECT)) ) )
1500 { 1501 {
1501 /* 1502 /*
1502 Here we add a content-length if one is missing; however, 1503 Here we add a content-length if one is missing; however,
1503 for 'connect' methods, the responses MUST NOT include a 1504 for 'connect' methods, the responses MUST NOT include a
1504 content-length header *if* the response code is 2xx (in 1505 content-length header *if* the response code is 2xx (in
1505 which case we expect there to be no body). Still, 1506 which case we expect there to be no body). Still,
1506 as we don't know the response code here in some cases, we 1507 as we don't know the response code here in some cases, we
1507 simply only force adding a content-length header if this 1508 simply only force adding a content-length header if this
1508 is not a 'connect' or if the response is not empty 1509 is not a 'connect' or if the response is not empty
1509 (which is kind of more sane, because if some crazy 1510 (which is kind of more sane, because if some crazy
1510 application did return content with a 2xx status code, 1511 application did return content with a 2xx status code,
1511 then having a content-length might again be a good idea). 1512 then having a content-length might again be a good idea).
1512 1513
1513 Note that the change from 'SHOULD NOT' to 'MUST NOT' is 1514 Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1514 a recent development of the HTTP 1.1 specification. 1515 a recent development of the HTTP 1.1 specification.
1515 */ 1516 */
1516 content_length_len 1517 content_length_len
1517 = MHD_snprintf_ (content_length_buf, 1518 = MHD_snprintf_ (content_length_buf,
1518 sizeof (content_length_buf), 1519 sizeof (content_length_buf),
1519 MHD_HTTP_HEADER_CONTENT_LENGTH ": " MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n", 1520 MHD_HTTP_HEADER_CONTENT_LENGTH ": "
1520 (MHD_UNSIGNED_LONG_LONG) response->total_size); 1521 MHD_UNSIGNED_LONG_LONG_PRINTF "\r\n",
1521 must_add_content_length = MHD_YES; 1522 (MHD_UNSIGNED_LONG_LONG) response->total_size);
1522 } 1523 must_add_content_length = MHD_YES;
1524 }
1523 1525
1524 /* check for adding keep alive */ 1526 /* check for adding keep alive */
1525 if ( (! response_has_keepalive) && 1527 if ( (! response_has_keepalive) &&
1526 (! response_has_close) && 1528 (! response_has_close) &&
1527 (MHD_NO == must_add_close) && 1529 (MHD_NO == must_add_close) &&
1528 (MHD_CONN_MUST_CLOSE != connection->keepalive) && 1530 (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1529#ifdef UPGRADE_SUPPORT 1531#ifdef UPGRADE_SUPPORT
1530 (NULL == response->upgrade_handler) && 1532 (NULL == response->upgrade_handler) &&
1531#endif /* UPGRADE_SUPPORT */ 1533#endif /* UPGRADE_SUPPORT */
1532 (MHD_YES == keepalive_possible (connection)) ) 1534 (MHD_YES == keepalive_possible (connection)) )
1533 must_add_keep_alive = MHD_YES; 1535 must_add_keep_alive = MHD_YES;
1534 break; 1536 break;
1535 case MHD_CONNECTION_BODY_SENT: 1537 case MHD_CONNECTION_BODY_SENT:
1536 response_has_keepalive = false; 1538 response_has_keepalive = false;
1537 break; 1539 break;
1538 default: 1540 default:
1539 mhd_assert (0); 1541 mhd_assert (0);
1540 return MHD_NO; 1542 return MHD_NO;
1541 } 1543 }
1542 1544
1543 if (MHD_CONN_MUST_CLOSE != connection->keepalive) 1545 if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1544 { 1546 {
1545 if ( (must_add_close) || (response_has_close) ) 1547 if ( (must_add_close) || (response_has_close) )
1546 connection->keepalive = MHD_CONN_MUST_CLOSE; 1548 connection->keepalive = MHD_CONN_MUST_CLOSE;
1547 else if ( (must_add_keep_alive) || (response_has_keepalive) ) 1549 else if ( (must_add_keep_alive) || (response_has_keepalive) )
1548 connection->keepalive = MHD_CONN_USE_KEEPALIVE; 1550 connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1549 } 1551 }
1550 1552
1551 if (must_add_close) 1553 if (must_add_close)
1552 size += MHD_STATICSTR_LEN_ ("Connection: close\r\n"); 1554 size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
@@ -1560,94 +1562,98 @@ build_header_response (struct MHD_Connection *connection)
1560 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) ); 1562 mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1561 1563
1562 for (pos = response->first_header; NULL != pos; pos = pos->next) 1564 for (pos = response->first_header; NULL != pos; pos = pos->next)
1563 { 1565 {
1564 /* TODO: add proper support for excluding "Keep-Alive" token. */ 1566 /* TODO: add proper support for excluding "Keep-Alive" token. */
1565 if ( (pos->kind == kind) && 1567 if ( (pos->kind == kind) &&
1566 (! ( (MHD_YES == must_add_close) && 1568 (! ( (MHD_YES == must_add_close) &&
1567 (response_has_keepalive) && 1569 (response_has_keepalive) &&
1568 (pos->header_size == MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_CONNECTION)) && 1570 (pos->header_size == MHD_STATICSTR_LEN_ (
1569 (MHD_str_equal_caseless_bin_n_(pos->header, 1571 MHD_HTTP_HEADER_CONNECTION)) &&
1570 MHD_HTTP_HEADER_CONNECTION, 1572 (MHD_str_equal_caseless_bin_n_ (pos->header,
1571 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_CONNECTION))) && 1573 MHD_HTTP_HEADER_CONNECTION,
1572 (MHD_str_equal_caseless_(pos->value, 1574 MHD_STATICSTR_LEN_ (
1573 "Keep-Alive")) ) ) ) 1575 MHD_HTTP_HEADER_CONNECTION))) &&
1574 size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */ 1576 (MHD_str_equal_caseless_ (pos->value,
1575 } 1577 "Keep-Alive")) ) ) )
1578 size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */
1579 }
1576 /* produce data */ 1580 /* produce data */
1577 data = MHD_pool_allocate (connection->pool, 1581 data = MHD_pool_allocate (connection->pool,
1578 size + 1, 1582 size + 1,
1579 false); 1583 false);
1580 if (NULL == data) 1584 if (NULL == data)
1581 { 1585 {
1582#ifdef HAVE_MESSAGES 1586#ifdef HAVE_MESSAGES
1583 MHD_DLOG (connection->daemon, 1587 MHD_DLOG (connection->daemon,
1584 "Not enough memory for write!\n"); 1588 "Not enough memory for write!\n");
1585#endif 1589#endif
1586 return MHD_NO; 1590 return MHD_NO;
1587 } 1591 }
1588 if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) 1592 if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1589 { 1593 {
1590 memcpy (data, 1594 memcpy (data,
1591 code, 1595 code,
1592 off); 1596 off);
1593 } 1597 }
1594 if (must_add_close) 1598 if (must_add_close)
1595 { 1599 {
1596 /* we must add the 'Connection: close' header */ 1600 /* we must add the 'Connection: close' header */
1597 memcpy (&data[off], 1601 memcpy (&data[off],
1598 "Connection: close\r\n", 1602 "Connection: close\r\n",
1599 MHD_STATICSTR_LEN_ ("Connection: close\r\n")); 1603 MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1600 off += MHD_STATICSTR_LEN_ ("Connection: close\r\n"); 1604 off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1601 } 1605 }
1602 if (must_add_keep_alive) 1606 if (must_add_keep_alive)
1603 { 1607 {
1604 /* we must add the 'Connection: Keep-Alive' header */ 1608 /* we must add the 'Connection: Keep-Alive' header */
1605 memcpy (&data[off], 1609 memcpy (&data[off],
1606 "Connection: Keep-Alive\r\n", 1610 "Connection: Keep-Alive\r\n",
1607 MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n")); 1611 MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1608 off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"); 1612 off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1609 } 1613 }
1610 if (must_add_chunked_encoding) 1614 if (must_add_chunked_encoding)
1611 { 1615 {
1612 /* we must add the 'Transfer-Encoding: chunked' header */ 1616 /* we must add the 'Transfer-Encoding: chunked' header */
1613 memcpy (&data[off], 1617 memcpy (&data[off],
1614 "Transfer-Encoding: chunked\r\n", 1618 "Transfer-Encoding: chunked\r\n",
1615 MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n")); 1619 MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1616 off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"); 1620 off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1617 } 1621 }
1618 if (must_add_content_length) 1622 if (must_add_content_length)
1619 { 1623 {
1620 /* we must add the 'Content-Length' header */ 1624 /* we must add the 'Content-Length' header */
1621 memcpy (&data[off], 1625 memcpy (&data[off],
1622 content_length_buf, 1626 content_length_buf,
1623 content_length_len); 1627 content_length_len);
1624 off += content_length_len; 1628 off += content_length_len;
1625 } 1629 }
1626 for (pos = response->first_header; NULL != pos; pos = pos->next) 1630 for (pos = response->first_header; NULL != pos; pos = pos->next)
1627 { 1631 {
1628 /* TODO: add proper support for excluding "Keep-Alive" token. */ 1632 /* TODO: add proper support for excluding "Keep-Alive" token. */
1629 if ( (pos->kind == kind) && 1633 if ( (pos->kind == kind) &&
1630 (! ( (MHD_YES == must_add_close) && 1634 (! ( (MHD_YES == must_add_close) &&
1631 (response_has_keepalive) && 1635 (response_has_keepalive) &&
1632 (pos->header_size == MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_CONNECTION)) && 1636 (pos->header_size == MHD_STATICSTR_LEN_ (
1633 (MHD_str_equal_caseless_bin_n_(pos->header, 1637 MHD_HTTP_HEADER_CONNECTION)) &&
1634 MHD_HTTP_HEADER_CONNECTION, 1638 (MHD_str_equal_caseless_bin_n_ (pos->header,
1635 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_CONNECTION))) && 1639 MHD_HTTP_HEADER_CONNECTION,
1636 (MHD_str_equal_caseless_(pos->value, 1640 MHD_STATICSTR_LEN_ (
1637 "Keep-Alive")) ) ) ) 1641 MHD_HTTP_HEADER_CONNECTION))) &&
1638 off += MHD_snprintf_ (&data[off], 1642 (MHD_str_equal_caseless_ (pos->value,
1639 size - off, 1643 "Keep-Alive")) ) ) )
1640 "%s: %s\r\n", 1644 off += MHD_snprintf_ (&data[off],
1641 pos->header, 1645 size - off,
1642 pos->value); 1646 "%s: %s\r\n",
1643 } 1647 pos->header,
1648 pos->value);
1649 }
1644 if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) 1650 if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1645 { 1651 {
1646 memcpy (&data[off], 1652 memcpy (&data[off],
1647 date, 1653 date,
1648 datelen); 1654 datelen);
1649 off += datelen; 1655 off += datelen;
1650 } 1656 }
1651 memcpy (&data[off], 1657 memcpy (&data[off],
1652 "\r\n", 1658 "\r\n",
1653 2); 1659 2);
@@ -1678,73 +1684,76 @@ build_header_response (struct MHD_Connection *connection)
1678static void 1684static void
1679transmit_error_response (struct MHD_Connection *connection, 1685transmit_error_response (struct MHD_Connection *connection,
1680 unsigned int status_code, 1686 unsigned int status_code,
1681 const char *message) 1687 const char *message)
1682{ 1688{
1683 struct MHD_Response *response; 1689 struct MHD_Response *response;
1684 int iret; 1690 int iret;
1685 1691
1686 if (NULL == connection->version) 1692 if (NULL == connection->version)
1687 { 1693 {
1688 /* we were unable to process the full header line, so we don't 1694 /* we were unable to process the full header line, so we don't
1689 really know what version the client speaks; assume 1.0 */ 1695 really know what version the client speaks; assume 1.0 */
1690 connection->version = MHD_HTTP_VERSION_1_0; 1696 connection->version = MHD_HTTP_VERSION_1_0;
1691 } 1697 }
1692 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 1698 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1693 connection->read_closed = true; 1699 connection->read_closed = true;
1694 if (0 != connection->read_buffer_size) 1700 if (0 != connection->read_buffer_size)
1695 { 1701 {
1696 /* Read buffer is not needed anymore, discard it 1702 /* Read buffer is not needed anymore, discard it
1697 * to free some space for error response. */ 1703 * to free some space for error response. */
1698 connection->read_buffer = MHD_pool_reallocate(connection->pool, 1704 connection->read_buffer = MHD_pool_reallocate (connection->pool,
1699 connection->read_buffer, 1705 connection->read_buffer,
1700 connection->read_buffer_size, 1706 connection->read_buffer_size,
1701 0); 1707 0);
1702 connection->read_buffer_size = 0; 1708 connection->read_buffer_size = 0;
1703 } 1709 }
1704#ifdef HAVE_MESSAGES 1710#ifdef HAVE_MESSAGES
1705 MHD_DLOG (connection->daemon, 1711 MHD_DLOG (connection->daemon,
1706 _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"), 1712 _ (
1713 "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1707 status_code, 1714 status_code,
1708 message); 1715 message);
1709#endif 1716#endif
1710 if (NULL != connection->response) 1717 if (NULL != connection->response)
1711 { 1718 {
1712 MHD_destroy_response (connection->response); 1719 MHD_destroy_response (connection->response);
1713 connection->response = NULL; 1720 connection->response = NULL;
1714 } 1721 }
1715 response = MHD_create_response_from_buffer (strlen (message), 1722 response = MHD_create_response_from_buffer (strlen (message),
1716 (void *) message, 1723 (void *) message,
1717 MHD_RESPMEM_PERSISTENT); 1724 MHD_RESPMEM_PERSISTENT);
1718 if (NULL == response) 1725 if (NULL == response)
1719 { 1726 {
1720 /* can't even send a reply, at least close the connection */ 1727 /* can't even send a reply, at least close the connection */
1721 connection->state = MHD_CONNECTION_CLOSED; 1728 connection->state = MHD_CONNECTION_CLOSED;
1722 return; 1729 return;
1723 } 1730 }
1724 iret = MHD_queue_response (connection, 1731 iret = MHD_queue_response (connection,
1725 status_code, 1732 status_code,
1726 response); 1733 response);
1727 MHD_destroy_response (response); 1734 MHD_destroy_response (response);
1728 if (MHD_YES != iret) 1735 if (MHD_YES != iret)
1729 { 1736 {
1730 /* can't even send a reply, at least close the connection */ 1737 /* can't even send a reply, at least close the connection */
1731 CONNECTION_CLOSE_ERROR (connection, 1738 CONNECTION_CLOSE_ERROR (connection,
1732 _("Closing connection (failed to queue response)\n")); 1739 _ (
1733 return; 1740 "Closing connection (failed to queue response)\n"));
1734 } 1741 return;
1742 }
1735 mhd_assert (NULL != connection->response); 1743 mhd_assert (NULL != connection->response);
1736 /* Do not reuse this connection. */ 1744 /* Do not reuse this connection. */
1737 connection->keepalive = MHD_CONN_MUST_CLOSE; 1745 connection->keepalive = MHD_CONN_MUST_CLOSE;
1738 if (MHD_NO == build_header_response (connection)) 1746 if (MHD_NO == build_header_response (connection))
1739 { 1747 {
1740 /* oops - close! */ 1748 /* oops - close! */
1741 CONNECTION_CLOSE_ERROR (connection, 1749 CONNECTION_CLOSE_ERROR (connection,
1742 _("Closing connection (failed to create response header)\n")); 1750 _ (
1743 } 1751 "Closing connection (failed to create response header)\n"));
1752 }
1744 else 1753 else
1745 { 1754 {
1746 connection->state = MHD_CONNECTION_HEADERS_SENDING; 1755 connection->state = MHD_CONNECTION_HEADERS_SENDING;
1747 } 1756 }
1748} 1757}
1749 1758
1750 1759
@@ -1764,151 +1773,151 @@ MHD_connection_update_event_loop_info (struct MHD_Connection *connection)
1764 return; /* States will be updated after resume. */ 1773 return; /* States will be updated after resume. */
1765#ifdef HTTPS_SUPPORT 1774#ifdef HTTPS_SUPPORT
1766 if (MHD_TLS_CONN_NO_TLS != connection->tls_state) 1775 if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1767 { /* HTTPS connection. */ 1776 { /* HTTPS connection. */
1768 switch (connection->tls_state) 1777 switch (connection->tls_state)
1769 { 1778 {
1770 case MHD_TLS_CONN_INIT: 1779 case MHD_TLS_CONN_INIT:
1771 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; 1780 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1772 return; 1781 return;
1773 case MHD_TLS_CONN_HANDSHAKING: 1782 case MHD_TLS_CONN_HANDSHAKING:
1774 if (0 == gnutls_record_get_direction (connection->tls_session)) 1783 if (0 == gnutls_record_get_direction (connection->tls_session))
1775 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ; 1784 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1776 else 1785 else
1777 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE; 1786 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1778 return; 1787 return;
1779 default: 1788 default:
1780 break; 1789 break;
1781 }
1782 } 1790 }
1791 }
1783#endif /* HTTPS_SUPPORT */ 1792#endif /* HTTPS_SUPPORT */
1784 while (1) 1793 while (1)
1785 { 1794 {
1786#if DEBUG_STATES 1795#if DEBUG_STATES
1787 MHD_DLOG (connection->daemon, 1796 MHD_DLOG (connection->daemon,
1788 _("In function %s handling connection at state: %s\n"), 1797 _ ("In function %s handling connection at state: %s\n"),
1789 __FUNCTION__, 1798 __FUNCTION__,
1790 MHD_state_to_string (connection->state)); 1799 MHD_state_to_string (connection->state));
1791#endif 1800#endif
1792 switch (connection->state) 1801 switch (connection->state)
1802 {
1803 case MHD_CONNECTION_INIT:
1804 case MHD_CONNECTION_URL_RECEIVED:
1805 case MHD_CONNECTION_HEADER_PART_RECEIVED:
1806 /* while reading headers, we always grow the
1807 read buffer if needed, no size-check required */
1808 if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1809 (! try_grow_read_buffer (connection, true)) )
1810 {
1811 transmit_error_response (connection,
1812 (connection->url != NULL)
1813 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
1814 : MHD_HTTP_URI_TOO_LONG,
1815 REQUEST_TOO_BIG);
1816 continue;
1817 }
1818 if (! connection->read_closed)
1819 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1820 else
1821 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1822 break;
1823 case MHD_CONNECTION_HEADERS_RECEIVED:
1824 mhd_assert (0);
1825 break;
1826 case MHD_CONNECTION_HEADERS_PROCESSED:
1827 mhd_assert (0);
1828 break;
1829 case MHD_CONNECTION_CONTINUE_SENDING:
1830 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1831 break;
1832 case MHD_CONNECTION_CONTINUE_SENT:
1833 if (connection->read_buffer_offset == connection->read_buffer_size)
1834 {
1835 const bool internal_poll = (0 != (connection->daemon->options
1836 & MHD_USE_INTERNAL_POLLING_THREAD));
1837 if ( (! try_grow_read_buffer (connection, true)) &&
1838 internal_poll)
1793 { 1839 {
1794 case MHD_CONNECTION_INIT: 1840 /* failed to grow the read buffer, and the
1795 case MHD_CONNECTION_URL_RECEIVED: 1841 client which is supposed to handle the
1796 case MHD_CONNECTION_HEADER_PART_RECEIVED: 1842 received data in a *blocking* fashion
1797 /* while reading headers, we always grow the 1843 (in this mode) did not handle the data as
1798 read buffer if needed, no size-check required */ 1844 it was supposed to!
1799 if ( (connection->read_buffer_offset == connection->read_buffer_size) && 1845 => we would either have to do busy-waiting
1800 (!try_grow_read_buffer (connection, true)) ) 1846 (on the client, which would likely fail),
1801 { 1847 or if we do nothing, we would just timeout
1802 transmit_error_response (connection, 1848 on the connection (if a timeout is even
1803 (connection->url != NULL) 1849 set!).
1804 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE 1850 Solution: we kill the connection with an error */
1805 : MHD_HTTP_URI_TOO_LONG, 1851 transmit_error_response (connection,
1806 REQUEST_TOO_BIG); 1852 MHD_HTTP_INTERNAL_SERVER_ERROR,
1807 continue; 1853 INTERNAL_ERROR);
1808 } 1854 continue;
1809 if (! connection->read_closed)
1810 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1811 else
1812 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1813 break;
1814 case MHD_CONNECTION_HEADERS_RECEIVED:
1815 mhd_assert (0);
1816 break;
1817 case MHD_CONNECTION_HEADERS_PROCESSED:
1818 mhd_assert (0);
1819 break;
1820 case MHD_CONNECTION_CONTINUE_SENDING:
1821 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1822 break;
1823 case MHD_CONNECTION_CONTINUE_SENT:
1824 if (connection->read_buffer_offset == connection->read_buffer_size)
1825 {
1826 const bool internal_poll = (0 != (connection->daemon->options &
1827 MHD_USE_INTERNAL_POLLING_THREAD));
1828 if ( (!try_grow_read_buffer (connection, true)) &&
1829 internal_poll)
1830 {
1831 /* failed to grow the read buffer, and the
1832 client which is supposed to handle the
1833 received data in a *blocking* fashion
1834 (in this mode) did not handle the data as
1835 it was supposed to!
1836 => we would either have to do busy-waiting
1837 (on the client, which would likely fail),
1838 or if we do nothing, we would just timeout
1839 on the connection (if a timeout is even
1840 set!).
1841 Solution: we kill the connection with an error */
1842 transmit_error_response (connection,
1843 MHD_HTTP_INTERNAL_SERVER_ERROR,
1844 INTERNAL_ERROR);
1845 continue;
1846 }
1847 }
1848 if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1849 (! connection->read_closed) )
1850 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1851 else
1852 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1853 break;
1854 case MHD_CONNECTION_BODY_RECEIVED:
1855 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
1856 /* while reading footers, we always grow the
1857 read buffer if needed, no size-check required */
1858 if (connection->read_closed)
1859 {
1860 CONNECTION_CLOSE_ERROR (connection,
1861 NULL);
1862 continue;
1863 }
1864 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1865 /* transition to FOOTERS_RECEIVED
1866 happens in read handler */
1867 break;
1868 case MHD_CONNECTION_FOOTERS_RECEIVED:
1869 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1870 break;
1871 case MHD_CONNECTION_HEADERS_SENDING:
1872 /* headers in buffer, keep writing */
1873 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1874 break;
1875 case MHD_CONNECTION_HEADERS_SENT:
1876 mhd_assert (0);
1877 break;
1878 case MHD_CONNECTION_NORMAL_BODY_READY:
1879 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1880 break;
1881 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
1882 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1883 break;
1884 case MHD_CONNECTION_CHUNKED_BODY_READY:
1885 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1886 break;
1887 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
1888 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1889 break;
1890 case MHD_CONNECTION_BODY_SENT:
1891 mhd_assert (0);
1892 break;
1893 case MHD_CONNECTION_FOOTERS_SENDING:
1894 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1895 break;
1896 case MHD_CONNECTION_FOOTERS_SENT:
1897 mhd_assert (0);
1898 break;
1899 case MHD_CONNECTION_CLOSED:
1900 connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
1901 return; /* do nothing, not even reading */
1902#ifdef UPGRADE_SUPPORT
1903 case MHD_CONNECTION_UPGRADE:
1904 mhd_assert (0);
1905 break;
1906#endif /* UPGRADE_SUPPORT */
1907 default:
1908 mhd_assert (0);
1909 } 1855 }
1856 }
1857 if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1858 (! connection->read_closed) )
1859 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1860 else
1861 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1910 break; 1862 break;
1863 case MHD_CONNECTION_BODY_RECEIVED:
1864 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
1865 /* while reading footers, we always grow the
1866 read buffer if needed, no size-check required */
1867 if (connection->read_closed)
1868 {
1869 CONNECTION_CLOSE_ERROR (connection,
1870 NULL);
1871 continue;
1872 }
1873 connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
1874 /* transition to FOOTERS_RECEIVED
1875 happens in read handler */
1876 break;
1877 case MHD_CONNECTION_FOOTERS_RECEIVED:
1878 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1879 break;
1880 case MHD_CONNECTION_HEADERS_SENDING:
1881 /* headers in buffer, keep writing */
1882 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1883 break;
1884 case MHD_CONNECTION_HEADERS_SENT:
1885 mhd_assert (0);
1886 break;
1887 case MHD_CONNECTION_NORMAL_BODY_READY:
1888 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1889 break;
1890 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
1891 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1892 break;
1893 case MHD_CONNECTION_CHUNKED_BODY_READY:
1894 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1895 break;
1896 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
1897 connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
1898 break;
1899 case MHD_CONNECTION_BODY_SENT:
1900 mhd_assert (0);
1901 break;
1902 case MHD_CONNECTION_FOOTERS_SENDING:
1903 connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
1904 break;
1905 case MHD_CONNECTION_FOOTERS_SENT:
1906 mhd_assert (0);
1907 break;
1908 case MHD_CONNECTION_CLOSED:
1909 connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
1910 return; /* do nothing, not even reading */
1911#ifdef UPGRADE_SUPPORT
1912 case MHD_CONNECTION_UPGRADE:
1913 mhd_assert (0);
1914 break;
1915#endif /* UPGRADE_SUPPORT */
1916 default:
1917 mhd_assert (0);
1911 } 1918 }
1919 break;
1920 }
1912} 1921}
1913 1922
1914 1923
@@ -1942,21 +1951,21 @@ get_next_header_line (struct MHD_Connection *connection,
1942 pos++; 1951 pos++;
1943 if ( (pos == connection->read_buffer_offset - 1) && 1952 if ( (pos == connection->read_buffer_offset - 1) &&
1944 ('\n' != rbuf[pos]) ) 1953 ('\n' != rbuf[pos]) )
1954 {
1955 /* not found, consider growing... */
1956 if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1957 (! try_grow_read_buffer (connection, true)) )
1945 { 1958 {
1946 /* not found, consider growing... */ 1959 transmit_error_response (connection,
1947 if ( (connection->read_buffer_offset == connection->read_buffer_size) && 1960 (NULL != connection->url)
1948 (!try_grow_read_buffer (connection, true)) ) 1961 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
1949 { 1962 : MHD_HTTP_URI_TOO_LONG,
1950 transmit_error_response (connection, 1963 REQUEST_TOO_BIG);
1951 (NULL != connection->url)
1952 ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
1953 : MHD_HTTP_URI_TOO_LONG,
1954 REQUEST_TOO_BIG);
1955 }
1956 if (line_len)
1957 *line_len = 0;
1958 return NULL;
1959 } 1964 }
1965 if (line_len)
1966 *line_len = 0;
1967 return NULL;
1968 }
1960 1969
1961 if (line_len) 1970 if (line_len)
1962 *line_len = pos; 1971 *line_len = pos;
@@ -1989,27 +1998,27 @@ static int
1989connection_add_header (struct MHD_Connection *connection, 1998connection_add_header (struct MHD_Connection *connection,
1990 const char *key, 1999 const char *key,
1991 size_t key_size, 2000 size_t key_size,
1992 const char *value, 2001 const char *value,
1993 size_t value_size, 2002 size_t value_size,
1994 enum MHD_ValueKind kind) 2003 enum MHD_ValueKind kind)
1995{ 2004{
1996 if (MHD_NO == 2005 if (MHD_NO ==
1997 MHD_set_connection_value_n (connection, 2006 MHD_set_connection_value_n (connection,
1998 kind, 2007 kind,
1999 key, 2008 key,
2000 key_size, 2009 key_size,
2001 value, 2010 value,
2002 value_size)) 2011 value_size))
2003 { 2012 {
2004#ifdef HAVE_MESSAGES 2013#ifdef HAVE_MESSAGES
2005 MHD_DLOG (connection->daemon, 2014 MHD_DLOG (connection->daemon,
2006 _("Not enough memory in pool to allocate header record!\n")); 2015 _ ("Not enough memory in pool to allocate header record!\n"));
2007#endif 2016#endif
2008 transmit_error_response (connection, 2017 transmit_error_response (connection,
2009 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 2018 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2010 REQUEST_TOO_BIG); 2019 REQUEST_TOO_BIG);
2011 return MHD_NO; 2020 return MHD_NO;
2012 } 2021 }
2013 return MHD_YES; 2022 return MHD_YES;
2014} 2023}
2015 2024
@@ -2038,7 +2047,8 @@ parse_cookie_header (struct MHD_Connection *connection)
2038 if (MHD_NO == MHD_lookup_connection_value_n (connection, 2047 if (MHD_NO == MHD_lookup_connection_value_n (connection,
2039 MHD_HEADER_KIND, 2048 MHD_HEADER_KIND,
2040 MHD_HTTP_HEADER_COOKIE, 2049 MHD_HTTP_HEADER_COOKIE,
2041 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_COOKIE), 2050 MHD_STATICSTR_LEN_ (
2051 MHD_HTTP_HEADER_COOKIE),
2042 &hdr, 2052 &hdr,
2043 &hdr_len)) 2053 &hdr_len))
2044 return MHD_YES; 2054 return MHD_YES;
@@ -2046,93 +2056,93 @@ parse_cookie_header (struct MHD_Connection *connection)
2046 hdr_len + 1, 2056 hdr_len + 1,
2047 true); 2057 true);
2048 if (NULL == cpy) 2058 if (NULL == cpy)
2049 { 2059 {
2050#ifdef HAVE_MESSAGES 2060#ifdef HAVE_MESSAGES
2051 MHD_DLOG (connection->daemon, 2061 MHD_DLOG (connection->daemon,
2052 _("Not enough memory in pool to parse cookies!\n")); 2062 _ ("Not enough memory in pool to parse cookies!\n"));
2053#endif 2063#endif
2054 transmit_error_response (connection, 2064 transmit_error_response (connection,
2055 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 2065 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2056 REQUEST_TOO_BIG); 2066 REQUEST_TOO_BIG);
2057 return MHD_NO; 2067 return MHD_NO;
2058 } 2068 }
2059 memcpy (cpy, 2069 memcpy (cpy,
2060 hdr, 2070 hdr,
2061 hdr_len); 2071 hdr_len);
2062 cpy[hdr_len] = '\0'; 2072 cpy[hdr_len] = '\0';
2063 pos = cpy; 2073 pos = cpy;
2064 while (NULL != pos) 2074 while (NULL != pos)
2075 {
2076 while (' ' == *pos)
2077 pos++; /* skip spaces */
2078
2079 sce = pos;
2080 while ( ((*sce) != '\0') &&
2081 ((*sce) != ',') &&
2082 ((*sce) != ';') &&
2083 ((*sce) != '=') )
2084 sce++;
2085 /* remove tailing whitespace (if any) from key */
2086 ekill = sce - 1;
2087 while ( (*ekill == ' ') &&
2088 (ekill >= pos) )
2089 *(ekill--) = '\0';
2090 old = *sce;
2091 *sce = '\0';
2092 if (old != '=')
2065 { 2093 {
2066 while (' ' == *pos) 2094 /* value part omitted, use empty string... */
2067 pos++; /* skip spaces */
2068
2069 sce = pos;
2070 while ( ((*sce) != '\0') &&
2071 ((*sce) != ',') &&
2072 ((*sce) != ';') &&
2073 ((*sce) != '=') )
2074 sce++;
2075 /* remove tailing whitespace (if any) from key */
2076 ekill = sce - 1;
2077 while ( (*ekill == ' ') &&
2078 (ekill >= pos) )
2079 *(ekill--) = '\0';
2080 old = *sce;
2081 *sce = '\0';
2082 if (old != '=')
2083 {
2084 /* value part omitted, use empty string... */
2085 if (MHD_NO ==
2086 connection_add_header (connection,
2087 pos,
2088 ekill - pos + 1,
2089 "",
2090 0,
2091 MHD_COOKIE_KIND))
2092 return MHD_NO;
2093 if (old == '\0')
2094 break;
2095 pos = sce + 1;
2096 continue;
2097 }
2098 equals = sce + 1;
2099 quotes = 0;
2100 semicolon = equals;
2101 while ( ('\0' != semicolon[0]) &&
2102 ( (0 != quotes) ||
2103 ( (';' != semicolon[0]) &&
2104 (',' != semicolon[0]) ) ) )
2105 {
2106 if ('"' == semicolon[0])
2107 quotes = (quotes + 1) & 1;
2108 semicolon++;
2109 }
2110 end = semicolon;
2111 if ('\0' == semicolon[0])
2112 semicolon = NULL;
2113 if (NULL != semicolon)
2114 {
2115 semicolon[0] = '\0';
2116 semicolon++;
2117 }
2118 /* remove quotes */
2119 if ( ('"' == equals[0]) &&
2120 ('"' == end[-1]) )
2121 {
2122 equals++;
2123 end--;
2124 *end = '\0';
2125 }
2126 if (MHD_NO == 2095 if (MHD_NO ==
2127 connection_add_header (connection, 2096 connection_add_header (connection,
2128 pos, 2097 pos,
2129 ekill - pos + 1, 2098 ekill - pos + 1,
2130 equals, 2099 "",
2131 end - equals, 2100 0,
2132 MHD_COOKIE_KIND)) 2101 MHD_COOKIE_KIND))
2133 return MHD_NO; 2102 return MHD_NO;
2134 pos = semicolon; 2103 if (old == '\0')
2104 break;
2105 pos = sce + 1;
2106 continue;
2107 }
2108 equals = sce + 1;
2109 quotes = 0;
2110 semicolon = equals;
2111 while ( ('\0' != semicolon[0]) &&
2112 ( (0 != quotes) ||
2113 ( (';' != semicolon[0]) &&
2114 (',' != semicolon[0]) ) ) )
2115 {
2116 if ('"' == semicolon[0])
2117 quotes = (quotes + 1) & 1;
2118 semicolon++;
2119 }
2120 end = semicolon;
2121 if ('\0' == semicolon[0])
2122 semicolon = NULL;
2123 if (NULL != semicolon)
2124 {
2125 semicolon[0] = '\0';
2126 semicolon++;
2127 }
2128 /* remove quotes */
2129 if ( ('"' == equals[0]) &&
2130 ('"' == end[-1]) )
2131 {
2132 equals++;
2133 end--;
2134 *end = '\0';
2135 } 2135 }
2136 if (MHD_NO ==
2137 connection_add_header (connection,
2138 pos,
2139 ekill - pos + 1,
2140 equals,
2141 end - equals,
2142 MHD_COOKIE_KIND))
2143 return MHD_NO;
2144 pos = semicolon;
2145 }
2136 return MHD_YES; 2146 return MHD_YES;
2137} 2147}
2138 2148
@@ -2167,84 +2177,84 @@ parse_initial_message_line (struct MHD_Connection *connection,
2167 /* Skip any spaces. Not required by standard but allow 2177 /* Skip any spaces. Not required by standard but allow
2168 to be more tolerant. */ 2178 to be more tolerant. */
2169 while ( (' ' == uri[0]) && 2179 while ( (' ' == uri[0]) &&
2170 ( (size_t)(uri - line) < line_len) ) 2180 ( (size_t) (uri - line) < line_len) )
2171 uri++; 2181 uri++;
2172 if ((size_t)(uri - line) == line_len) 2182 if ((size_t) (uri - line) == line_len)
2183 {
2184 /* No URI and no http version given */
2185 curi = "";
2186 uri = NULL;
2187 connection->version = "";
2188 args = NULL;
2189 }
2190 else
2191 {
2192 size_t uri_len;
2193 curi = uri;
2194 /* Search from back to accept misformed URI with space */
2195 http_version = line + line_len - 1;
2196 /* Skip any trailing spaces */
2197 while ( (' ' == http_version[0]) &&
2198 (http_version > uri) )
2199 http_version--;
2200 /* Find first space in reverse direction */
2201 while ( (' ' != http_version[0]) &&
2202 (http_version > uri) )
2203 http_version--;
2204 if (http_version > uri)
2205 {
2206 /* http_version points to character before HTTP version string */
2207 http_version[0] = '\0';
2208 connection->version = http_version + 1;
2209 uri_len = http_version - uri;
2210 }
2211 else
2173 { 2212 {
2174 /* No URI and no http version given */
2175 curi = "";
2176 uri = NULL;
2177 connection->version = ""; 2213 connection->version = "";
2178 args = NULL; 2214 uri_len = line_len - (uri - line);
2179 } 2215 }
2180 else 2216 /* check for spaces in URI if we are "strict" */
2217 if ( (1 <= daemon->strict_for_client) &&
2218 (NULL != memchr (uri,
2219 ' ',
2220 uri_len)) )
2181 { 2221 {
2182 size_t uri_len; 2222 /* space exists in URI and we are supposed to be strict, reject */
2183 curi = uri; 2223 return MHD_NO;
2184 /* Search from back to accept misformed URI with space */
2185 http_version = line + line_len - 1;
2186 /* Skip any trailing spaces */
2187 while ( (' ' == http_version[0]) &&
2188 (http_version > uri) )
2189 http_version--;
2190 /* Find first space in reverse direction */
2191 while ( (' ' != http_version[0]) &&
2192 (http_version > uri) )
2193 http_version--;
2194 if (http_version > uri)
2195 {
2196 /* http_version points to character before HTTP version string */
2197 http_version[0] = '\0';
2198 connection->version = http_version + 1;
2199 uri_len = http_version - uri;
2200 }
2201 else
2202 {
2203 connection->version = "";
2204 uri_len = line_len - (uri - line);
2205 }
2206 /* check for spaces in URI if we are "strict" */
2207 if ( (1 <= daemon->strict_for_client) &&
2208 (NULL != memchr (uri,
2209 ' ',
2210 uri_len)) )
2211 {
2212 /* space exists in URI and we are supposed to be strict, reject */
2213 return MHD_NO;
2214 }
2215
2216 args = memchr (uri,
2217 '?',
2218 uri_len);
2219 } 2224 }
2220 2225
2226 args = memchr (uri,
2227 '?',
2228 uri_len);
2229 }
2230
2221 /* log callback before we modify URI *or* args */ 2231 /* log callback before we modify URI *or* args */
2222 if (NULL != daemon->uri_log_callback) 2232 if (NULL != daemon->uri_log_callback)
2223 { 2233 {
2224 connection->client_aware = true; 2234 connection->client_aware = true;
2225 connection->client_context 2235 connection->client_context
2226 = daemon->uri_log_callback (daemon->uri_log_callback_cls, 2236 = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2227 uri, 2237 uri,
2228 connection); 2238 connection);
2229 } 2239 }
2230 2240
2231 if (NULL != args) 2241 if (NULL != args)
2232 { 2242 {
2233 args[0] = '\0'; 2243 args[0] = '\0';
2234 args++; 2244 args++;
2235 /* note that this call clobbers 'args' */ 2245 /* note that this call clobbers 'args' */
2236 MHD_parse_arguments_ (connection, 2246 MHD_parse_arguments_ (connection,
2237 MHD_GET_ARGUMENT_KIND, 2247 MHD_GET_ARGUMENT_KIND,
2238 args, 2248 args,
2239 &connection_add_header, 2249 &connection_add_header,
2240 &unused_num_headers); 2250 &unused_num_headers);
2241 } 2251 }
2242 2252
2243 /* unescape URI *after* searching for arguments and log callback */ 2253 /* unescape URI *after* searching for arguments and log callback */
2244 if (NULL != uri) 2254 if (NULL != uri)
2245 daemon->unescape_callback (daemon->unescape_callback_cls, 2255 daemon->unescape_callback (daemon->unescape_callback_cls,
2246 connection, 2256 connection,
2247 uri); 2257 uri);
2248 connection->url = curi; 2258 connection->url = curi;
2249 return MHD_YES; 2259 return MHD_YES;
2250} 2260}
@@ -2276,12 +2286,13 @@ call_connection_handler (struct MHD_Connection *connection)
2276 NULL, 2286 NULL,
2277 &processed, 2287 &processed,
2278 &connection->client_context)) 2288 &connection->client_context))
2279 { 2289 {
2280 /* serious internal error, close connection */ 2290 /* serious internal error, close connection */
2281 CONNECTION_CLOSE_ERROR (connection, 2291 CONNECTION_CLOSE_ERROR (connection,
2282 _("Application reported internal error, closing connection.\n")); 2292 _ (
2283 return; 2293 "Application reported internal error, closing connection.\n"));
2284 } 2294 return;
2295 }
2285} 2296}
2286 2297
2287 2298
@@ -2318,199 +2329,205 @@ process_request_body (struct MHD_Connection *connection)
2318 buffer_head = connection->read_buffer; 2329 buffer_head = connection->read_buffer;
2319 available = connection->read_buffer_offset; 2330 available = connection->read_buffer_offset;
2320 do 2331 do
2321 { 2332 {
2322 size_t to_be_processed; 2333 size_t to_be_processed;
2323 size_t left_unprocessed; 2334 size_t left_unprocessed;
2324 size_t processed_size; 2335 size_t processed_size;
2325 2336
2326 instant_retry = MHD_NO; 2337 instant_retry = MHD_NO;
2327 if ( (connection->have_chunked_upload) && 2338 if ( (connection->have_chunked_upload) &&
2328 (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) ) 2339 (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2340 {
2341 if ( (connection->current_chunk_offset ==
2342 connection->current_chunk_size) &&
2343 (0LLU != connection->current_chunk_offset) &&
2344 (available >= 2) )
2345 {
2346 size_t i;
2347 /* skip new line at the *end* of a chunk */
2348 i = 0;
2349 if ( ('\r' == buffer_head[i]) ||
2350 ('\n' == buffer_head[i]) )
2351 i++; /* skip 1st part of line feed */
2352 if ( ('\r' == buffer_head[i]) ||
2353 ('\n' == buffer_head[i]) )
2354 i++; /* skip 2nd part of line feed */
2355 if (0 == i)
2329 { 2356 {
2330 if ( (connection->current_chunk_offset == connection->current_chunk_size) && 2357 /* malformed encoding */
2331 (0LLU != connection->current_chunk_offset) && 2358 CONNECTION_CLOSE_ERROR (connection,
2332 (available >= 2) ) 2359 _ (
2333 { 2360 "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2334 size_t i; 2361 return;
2335 /* skip new line at the *end* of a chunk */
2336 i = 0;
2337 if ( ('\r' == buffer_head[i]) ||
2338 ('\n' == buffer_head[i]) )
2339 i++; /* skip 1st part of line feed */
2340 if ( ('\r' == buffer_head[i]) ||
2341 ('\n' == buffer_head[i]) )
2342 i++; /* skip 2nd part of line feed */
2343 if (0 == i)
2344 {
2345 /* malformed encoding */
2346 CONNECTION_CLOSE_ERROR (connection,
2347 _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2348 return;
2349 }
2350 available -= i;
2351 buffer_head += i;
2352 connection->current_chunk_offset = 0;
2353 connection->current_chunk_size = 0;
2354 }
2355 if (connection->current_chunk_offset <
2356 connection->current_chunk_size)
2357 {
2358 uint64_t cur_chunk_left;
2359 /* we are in the middle of a chunk, give
2360 as much as possible to the client (without
2361 crossing chunk boundaries) */
2362 cur_chunk_left
2363 = connection->current_chunk_size - connection->current_chunk_offset;
2364 if (cur_chunk_left > available)
2365 to_be_processed = available;
2366 else
2367 { /* cur_chunk_left <= (size_t)available */
2368 to_be_processed = (size_t)cur_chunk_left;
2369 if (available > to_be_processed)
2370 instant_retry = MHD_YES;
2371 }
2372 }
2373 else
2374 {
2375 size_t i;
2376 size_t end_size;
2377 bool malformed;
2378
2379 /* we need to read chunk boundaries */
2380 i = 0;
2381 while (i < available)
2382 {
2383 if ( ('\r' == buffer_head[i]) ||
2384 ('\n' == buffer_head[i]) ||
2385 (';' == buffer_head[i]) )
2386 break;
2387 i++;
2388 if (i >= 16)
2389 break;
2390 }
2391 end_size = i;
2392 /* find beginning of CRLF (skip over chunk extensions) */
2393 if (';' == buffer_head[i])
2394 {
2395 while (i < available)
2396 {
2397 if ( ('\r' == buffer_head[i]) ||
2398 ('\n' == buffer_head[i]) )
2399 break;
2400 i++;
2401 }
2402 }
2403 /* take '\n' into account; if '\n' is the unavailable
2404 character, we will need to wait until we have it
2405 before going further */
2406 if ( (i + 1 >= available) &&
2407 ! ( (1 == i) &&
2408 (2 == available) &&
2409 ('0' == buffer_head[0]) ) )
2410 break; /* need more data... */
2411 i++;
2412 malformed = (end_size >= 16);
2413 if (! malformed)
2414 {
2415 size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2416 end_size,
2417 &connection->current_chunk_size);
2418 malformed = (end_size != num_dig);
2419 }
2420 if (malformed)
2421 {
2422 /* malformed encoding */
2423 CONNECTION_CLOSE_ERROR (connection,
2424 _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2425 return;
2426 }
2427 /* skip 2nd part of line feed */
2428 if ( (i < available) &&
2429 ( ('\r' == buffer_head[i]) ||
2430 ('\n' == buffer_head[i]) ) )
2431 i++;
2432
2433 buffer_head += i;
2434 available -= i;
2435 connection->current_chunk_offset = 0;
2436
2437 if (available > 0)
2438 instant_retry = MHD_YES;
2439 if (0LLU == connection->current_chunk_size)
2440 {
2441 connection->remaining_upload_size = 0;
2442 break;
2443 }
2444 continue;
2445 }
2446 } 2362 }
2363 available -= i;
2364 buffer_head += i;
2365 connection->current_chunk_offset = 0;
2366 connection->current_chunk_size = 0;
2367 }
2368 if (connection->current_chunk_offset <
2369 connection->current_chunk_size)
2370 {
2371 uint64_t cur_chunk_left;
2372 /* we are in the middle of a chunk, give
2373 as much as possible to the client (without
2374 crossing chunk boundaries) */
2375 cur_chunk_left
2376 = connection->current_chunk_size - connection->current_chunk_offset;
2377 if (cur_chunk_left > available)
2378 to_be_processed = available;
2379 else
2380 { /* cur_chunk_left <= (size_t)available */
2381 to_be_processed = (size_t) cur_chunk_left;
2382 if (available > to_be_processed)
2383 instant_retry = MHD_YES;
2384 }
2385 }
2447 else 2386 else
2387 {
2388 size_t i;
2389 size_t end_size;
2390 bool malformed;
2391
2392 /* we need to read chunk boundaries */
2393 i = 0;
2394 while (i < available)
2448 { 2395 {
2449 /* no chunked encoding, give all to the client */ 2396 if ( ('\r' == buffer_head[i]) ||
2450 if ( (0 != connection->remaining_upload_size) && 2397 ('\n' == buffer_head[i]) ||
2451 (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) && 2398 (';' == buffer_head[i]) )
2452 (connection->remaining_upload_size < available) ) 2399 break;
2453 { 2400 i++;
2454 to_be_processed = (size_t)connection->remaining_upload_size; 2401 if (i >= 16)
2455 } 2402 break;
2456 else
2457 {
2458 /**
2459 * 1. no chunked encoding, give all to the client
2460 * 2. client may send large chunked data, but only a smaller part is available at one time.
2461 */
2462 to_be_processed = available;
2463 }
2464 } 2403 }
2465 left_unprocessed = to_be_processed; 2404 end_size = i;
2466 connection->client_aware = true; 2405 /* find beginning of CRLF (skip over chunk extensions) */
2467 if (MHD_NO == 2406 if (';' == buffer_head[i])
2468 daemon->default_handler (daemon->default_handler_cls,
2469 connection,
2470 connection->url,
2471 connection->method,
2472 connection->version,
2473 buffer_head,
2474 &left_unprocessed,
2475 &connection->client_context))
2476 { 2407 {
2477 /* serious internal error, close connection */ 2408 while (i < available)
2409 {
2410 if ( ('\r' == buffer_head[i]) ||
2411 ('\n' == buffer_head[i]) )
2412 break;
2413 i++;
2414 }
2415 }
2416 /* take '\n' into account; if '\n' is the unavailable
2417 character, we will need to wait until we have it
2418 before going further */
2419 if ( (i + 1 >= available) &&
2420 ! ( (1 == i) &&
2421 (2 == available) &&
2422 ('0' == buffer_head[0]) ) )
2423 break; /* need more data... */
2424 i++;
2425 malformed = (end_size >= 16);
2426 if (! malformed)
2427 {
2428 size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2429 end_size,
2430 &connection->
2431 current_chunk_size);
2432 malformed = (end_size != num_dig);
2433 }
2434 if (malformed)
2435 {
2436 /* malformed encoding */
2478 CONNECTION_CLOSE_ERROR (connection, 2437 CONNECTION_CLOSE_ERROR (connection,
2479 _("Application reported internal error, closing connection.\n")); 2438 _ (
2439 "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2480 return; 2440 return;
2481 } 2441 }
2482 if (left_unprocessed > to_be_processed) 2442 /* skip 2nd part of line feed */
2483 mhd_panic (mhd_panic_cls, 2443 if ( (i < available) &&
2484 __FILE__, 2444 ( ('\r' == buffer_head[i]) ||
2485 __LINE__ 2445 ('\n' == buffer_head[i]) ) )
2446 i++;
2447
2448 buffer_head += i;
2449 available -= i;
2450 connection->current_chunk_offset = 0;
2451
2452 if (available > 0)
2453 instant_retry = MHD_YES;
2454 if (0LLU == connection->current_chunk_size)
2455 {
2456 connection->remaining_upload_size = 0;
2457 break;
2458 }
2459 continue;
2460 }
2461 }
2462 else
2463 {
2464 /* no chunked encoding, give all to the client */
2465 if ( (0 != connection->remaining_upload_size) &&
2466 (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2467 (connection->remaining_upload_size < available) )
2468 {
2469 to_be_processed = (size_t) connection->remaining_upload_size;
2470 }
2471 else
2472 {
2473 /**
2474 * 1. no chunked encoding, give all to the client
2475 * 2. client may send large chunked data, but only a smaller part is available at one time.
2476 */
2477 to_be_processed = available;
2478 }
2479 }
2480 left_unprocessed = to_be_processed;
2481 connection->client_aware = true;
2482 if (MHD_NO ==
2483 daemon->default_handler (daemon->default_handler_cls,
2484 connection,
2485 connection->url,
2486 connection->method,
2487 connection->version,
2488 buffer_head,
2489 &left_unprocessed,
2490 &connection->client_context))
2491 {
2492 /* serious internal error, close connection */
2493 CONNECTION_CLOSE_ERROR (connection,
2494 _ (
2495 "Application reported internal error, closing connection.\n"));
2496 return;
2497 }
2498 if (left_unprocessed > to_be_processed)
2499 mhd_panic (mhd_panic_cls,
2500 __FILE__,
2501 __LINE__
2486#ifdef HAVE_MESSAGES 2502#ifdef HAVE_MESSAGES
2487 , _("libmicrohttpd API violation") 2503 , _ ("libmicrohttpd API violation")
2488#else 2504#else
2489 , NULL 2505 , NULL
2490#endif 2506#endif
2491 ); 2507 );
2492 if (0 != left_unprocessed) 2508 if (0 != left_unprocessed)
2493 { 2509 {
2494 instant_retry = MHD_NO; /* client did not process everything */ 2510 instant_retry = MHD_NO; /* client did not process everything */
2495#ifdef HAVE_MESSAGES 2511#ifdef HAVE_MESSAGES
2496 /* client did not process all upload data, complain if 2512 /* client did not process all upload data, complain if
2497 the setup was incorrect, which may prevent us from 2513 the setup was incorrect, which may prevent us from
2498 handling the rest of the request */ 2514 handling the rest of the request */
2499 if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) && 2515 if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2500 (! connection->suspended) ) 2516 (! connection->suspended) )
2501 MHD_DLOG (daemon, 2517 MHD_DLOG (daemon,
2502 _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n")); 2518 _ (
2519 "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2503#endif 2520#endif
2504 }
2505 processed_size = to_be_processed - left_unprocessed;
2506 if (connection->have_chunked_upload)
2507 connection->current_chunk_offset += processed_size;
2508 /* dh left "processed" bytes in buffer for next time... */
2509 buffer_head += processed_size;
2510 available -= processed_size;
2511 if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2512 connection->remaining_upload_size -= processed_size;
2513 } 2521 }
2522 processed_size = to_be_processed - left_unprocessed;
2523 if (connection->have_chunked_upload)
2524 connection->current_chunk_offset += processed_size;
2525 /* dh left "processed" bytes in buffer for next time... */
2526 buffer_head += processed_size;
2527 available -= processed_size;
2528 if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2529 connection->remaining_upload_size -= processed_size;
2530 }
2514 while (MHD_YES == instant_retry); 2531 while (MHD_YES == instant_retry);
2515 if ( (available > 0) && 2532 if ( (available > 0) &&
2516 (buffer_head != connection->read_buffer) ) 2533 (buffer_head != connection->read_buffer) )
@@ -2540,7 +2557,7 @@ check_write_done (struct MHD_Connection *connection,
2540 connection->write_buffer_send_offset = 0; 2557 connection->write_buffer_send_offset = 0;
2541 connection->state = next_state; 2558 connection->state = next_state;
2542 MHD_pool_reallocate (connection->pool, 2559 MHD_pool_reallocate (connection->pool,
2543 connection->write_buffer, 2560 connection->write_buffer,
2544 connection->write_buffer_size, 2561 connection->write_buffer_size,
2545 0); 2562 0);
2546 connection->write_buffer = NULL; 2563 connection->write_buffer = NULL;
@@ -2567,28 +2584,29 @@ process_header_line (struct MHD_Connection *connection,
2567 /* line should be normal header line, find colon */ 2584 /* line should be normal header line, find colon */
2568 colon = strchr (line, ':'); 2585 colon = strchr (line, ':');
2569 if (NULL == colon) 2586 if (NULL == colon)
2570 { 2587 {
2571 /* error in header line, die hard */ 2588 /* error in header line, die hard */
2572 CONNECTION_CLOSE_ERROR (connection, 2589 CONNECTION_CLOSE_ERROR (connection,
2573 _("Received malformed line (no colon). Closing connection.\n")); 2590 _ (
2574 return MHD_NO; 2591 "Received malformed line (no colon). Closing connection.\n"));
2575 } 2592 return MHD_NO;
2593 }
2576 if (-1 >= connection->daemon->strict_for_client) 2594 if (-1 >= connection->daemon->strict_for_client)
2577 { 2595 {
2578 /* check for whitespace before colon, which is not allowed 2596 /* check for whitespace before colon, which is not allowed
2579 by RFC 7230 section 3.2.4; we count space ' ' and 2597 by RFC 7230 section 3.2.4; we count space ' ' and
2580 tab '\t', but not '\r\n' as those would have ended the line. */ 2598 tab '\t', but not '\r\n' as those would have ended the line. */
2581 const char *white; 2599 const char *white;
2582 2600
2583 white = strchr (line, ' '); 2601 white = strchr (line, ' ');
2584 if ( (NULL != white) && 2602 if ( (NULL != white) &&
2585 (white < colon) ) 2603 (white < colon) )
2586 return MHD_NO; 2604 return MHD_NO;
2587 white = strchr (line, '\t'); 2605 white = strchr (line, '\t');
2588 if ( (NULL != white) && 2606 if ( (NULL != white) &&
2589 (white < colon) ) 2607 (white < colon) )
2590 return MHD_NO; 2608 return MHD_NO;
2591 } 2609 }
2592 /* zero-terminate header */ 2610 /* zero-terminate header */
2593 colon[0] = '\0'; 2611 colon[0] = '\0';
2594 colon++; /* advance to value */ 2612 colon++; /* advance to value */
@@ -2630,69 +2648,69 @@ process_broken_line (struct MHD_Connection *connection,
2630 last = connection->last; 2648 last = connection->last;
2631 if ( (' ' == line[0]) || 2649 if ( (' ' == line[0]) ||
2632 ('\t' == line[0]) ) 2650 ('\t' == line[0]) )
2633 { 2651 {
2634 /* value was continued on the next line, see 2652 /* value was continued on the next line, see
2635 http://www.jmarshall.com/easy/http/ */ 2653 http://www.jmarshall.com/easy/http/ */
2636 last_len = strlen (last); 2654 last_len = strlen (last);
2637 /* skip whitespace at start of 2nd line */ 2655 /* skip whitespace at start of 2nd line */
2638 tmp = line; 2656 tmp = line;
2639 while ( (' ' == tmp[0]) || 2657 while ( (' ' == tmp[0]) ||
2640 ('\t' == tmp[0]) ) 2658 ('\t' == tmp[0]) )
2641 tmp++; 2659 tmp++;
2642 tmp_len = strlen (tmp); 2660 tmp_len = strlen (tmp);
2643 /* FIXME: we might be able to do this better (faster!), as most 2661 /* FIXME: we might be able to do this better (faster!), as most
2644 likely 'last' and 'line' should already be adjacent in 2662 likely 'last' and 'line' should already be adjacent in
2645 memory; however, doing this right gets tricky if we have a 2663 memory; however, doing this right gets tricky if we have a
2646 value continued over multiple lines (in which case we need to 2664 value continued over multiple lines (in which case we need to
2647 record how often we have done this so we can check for 2665 record how often we have done this so we can check for
2648 adjacency); also, in the case where these are not adjacent 2666 adjacency); also, in the case where these are not adjacent
2649 (not sure how it can happen!), we would want to allocate from 2667 (not sure how it can happen!), we would want to allocate from
2650 the end of the pool, so as to not destroy the read-buffer's 2668 the end of the pool, so as to not destroy the read-buffer's
2651 ability to grow nicely. */ 2669 ability to grow nicely. */
2652 last = MHD_pool_reallocate (connection->pool, 2670 last = MHD_pool_reallocate (connection->pool,
2653 last, 2671 last,
2654 last_len + 1, 2672 last_len + 1,
2655 last_len + tmp_len + 1); 2673 last_len + tmp_len + 1);
2656 if (NULL == last) 2674 if (NULL == last)
2657 {
2658 transmit_error_response (connection,
2659 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2660 REQUEST_TOO_BIG);
2661 return MHD_NO;
2662 }
2663 memcpy (&last[last_len],
2664 tmp,
2665 tmp_len + 1);
2666 connection->last = last;
2667 return MHD_YES; /* possibly more than 2 lines... */
2668 }
2669 mhd_assert ( (NULL != last) &&
2670 (NULL != connection->colon) );
2671 if (MHD_NO ==
2672 connection_add_header (connection,
2673 last,
2674 strlen (last),
2675 connection->colon,
2676 strlen (connection->colon),
2677 kind))
2678 { 2675 {
2679 transmit_error_response (connection, 2676 transmit_error_response (connection,
2680 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE, 2677 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2681 REQUEST_TOO_BIG); 2678 REQUEST_TOO_BIG);
2682 return MHD_NO; 2679 return MHD_NO;
2683 } 2680 }
2681 memcpy (&last[last_len],
2682 tmp,
2683 tmp_len + 1);
2684 connection->last = last;
2685 return MHD_YES; /* possibly more than 2 lines... */
2686 }
2687 mhd_assert ( (NULL != last) &&
2688 (NULL != connection->colon) );
2689 if (MHD_NO ==
2690 connection_add_header (connection,
2691 last,
2692 strlen (last),
2693 connection->colon,
2694 strlen (connection->colon),
2695 kind))
2696 {
2697 transmit_error_response (connection,
2698 MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE,
2699 REQUEST_TOO_BIG);
2700 return MHD_NO;
2701 }
2684 /* we still have the current line to deal with... */ 2702 /* we still have the current line to deal with... */
2685 if (0 != line[0]) 2703 if (0 != line[0])
2704 {
2705 if (MHD_NO == process_header_line (connection,
2706 line))
2686 { 2707 {
2687 if (MHD_NO == process_header_line (connection, 2708 transmit_error_response (connection,
2688 line)) 2709 MHD_HTTP_BAD_REQUEST,
2689 { 2710 REQUEST_MALFORMED);
2690 transmit_error_response (connection, 2711 return MHD_NO;
2691 MHD_HTTP_BAD_REQUEST,
2692 REQUEST_MALFORMED);
2693 return MHD_NO;
2694 }
2695 } 2712 }
2713 }
2696 return MHD_YES; 2714 return MHD_YES;
2697} 2715}
2698 2716
@@ -2715,88 +2733,93 @@ parse_connection_headers (struct MHD_Connection *connection)
2715 parse_cookie_header (connection); 2733 parse_cookie_header (connection);
2716 if ( (1 <= connection->daemon->strict_for_client) && 2734 if ( (1 <= connection->daemon->strict_for_client) &&
2717 (NULL != connection->version) && 2735 (NULL != connection->version) &&
2718 (MHD_str_equal_caseless_(MHD_HTTP_VERSION_1_1, 2736 (MHD_str_equal_caseless_ (MHD_HTTP_VERSION_1_1,
2719 connection->version)) && 2737 connection->version)) &&
2720 (MHD_NO == 2738 (MHD_NO ==
2721 MHD_lookup_connection_value_n (connection, 2739 MHD_lookup_connection_value_n (connection,
2722 MHD_HEADER_KIND, 2740 MHD_HEADER_KIND,
2723 MHD_HTTP_HEADER_HOST, 2741 MHD_HTTP_HEADER_HOST,
2724 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_HOST), 2742 MHD_STATICSTR_LEN_ (
2743 MHD_HTTP_HEADER_HOST),
2725 NULL, 2744 NULL,
2726 NULL)) ) 2745 NULL)) )
2727 { 2746 {
2728 int iret; 2747 int iret;
2729 2748
2730 /* die, http 1.1 request without host and we are pedantic */ 2749 /* die, http 1.1 request without host and we are pedantic */
2731 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED; 2750 connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2732 connection->read_closed = true; 2751 connection->read_closed = true;
2733#ifdef HAVE_MESSAGES 2752#ifdef HAVE_MESSAGES
2734 MHD_DLOG (connection->daemon, 2753 MHD_DLOG (connection->daemon,
2735 _("Received HTTP 1.1 request without `Host' header.\n")); 2754 _ ("Received HTTP 1.1 request without `Host' header.\n"));
2736#endif 2755#endif
2737 mhd_assert (NULL == connection->response); 2756 mhd_assert (NULL == connection->response);
2738 response = 2757 response =
2739 MHD_create_response_from_buffer (MHD_STATICSTR_LEN_ (REQUEST_LACKS_HOST), 2758 MHD_create_response_from_buffer (MHD_STATICSTR_LEN_ (REQUEST_LACKS_HOST),
2740 REQUEST_LACKS_HOST, 2759 REQUEST_LACKS_HOST,
2741 MHD_RESPMEM_PERSISTENT); 2760 MHD_RESPMEM_PERSISTENT);
2742 if (NULL == response) 2761 if (NULL == response)
2743 { 2762 {
2744 /* can't even send a reply, at least close the connection */ 2763 /* can't even send a reply, at least close the connection */
2745 CONNECTION_CLOSE_ERROR (connection, 2764 CONNECTION_CLOSE_ERROR (connection,
2746 _("Closing connection (failed to create response)\n")); 2765 _ (
2747 return; 2766 "Closing connection (failed to create response)\n"));
2748 }
2749 iret = MHD_queue_response (connection,
2750 MHD_HTTP_BAD_REQUEST,
2751 response);
2752 MHD_destroy_response (response);
2753 if (MHD_YES != iret)
2754 {
2755 /* can't even send a reply, at least close the connection */
2756 CONNECTION_CLOSE_ERROR (connection,
2757 _("Closing connection (failed to queue response)\n"));
2758 }
2759 return; 2767 return;
2760 } 2768 }
2769 iret = MHD_queue_response (connection,
2770 MHD_HTTP_BAD_REQUEST,
2771 response);
2772 MHD_destroy_response (response);
2773 if (MHD_YES != iret)
2774 {
2775 /* can't even send a reply, at least close the connection */
2776 CONNECTION_CLOSE_ERROR (connection,
2777 _ (
2778 "Closing connection (failed to queue response)\n"));
2779 }
2780 return;
2781 }
2761 2782
2762 connection->remaining_upload_size = 0; 2783 connection->remaining_upload_size = 0;
2763 if (MHD_NO != MHD_lookup_connection_value_n (connection, 2784 if (MHD_NO != MHD_lookup_connection_value_n (connection,
2764 MHD_HEADER_KIND, 2785 MHD_HEADER_KIND,
2765 MHD_HTTP_HEADER_TRANSFER_ENCODING, 2786 MHD_HTTP_HEADER_TRANSFER_ENCODING,
2766 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_TRANSFER_ENCODING), 2787 MHD_STATICSTR_LEN_ (
2788 MHD_HTTP_HEADER_TRANSFER_ENCODING),
2767 &enc, 2789 &enc,
2768 NULL)) 2790 NULL))
2769 { 2791 {
2770 connection->remaining_upload_size = MHD_SIZE_UNKNOWN; 2792 connection->remaining_upload_size = MHD_SIZE_UNKNOWN;
2771 if (MHD_str_equal_caseless_(enc, 2793 if (MHD_str_equal_caseless_ (enc,
2772 "chunked")) 2794 "chunked"))
2773 connection->have_chunked_upload = true; 2795 connection->have_chunked_upload = true;
2774 } 2796 }
2775 else 2797 else
2798 {
2799 if (MHD_NO != MHD_lookup_connection_value_n (connection,
2800 MHD_HEADER_KIND,
2801 MHD_HTTP_HEADER_CONTENT_LENGTH,
2802 MHD_STATICSTR_LEN_ (
2803 MHD_HTTP_HEADER_CONTENT_LENGTH),
2804 &clen,
2805 NULL))
2776 { 2806 {
2777 if (MHD_NO != MHD_lookup_connection_value_n (connection, 2807 end = clen + MHD_str_to_uint64_ (clen,
2778 MHD_HEADER_KIND, 2808 &connection->remaining_upload_size);
2779 MHD_HTTP_HEADER_CONTENT_LENGTH, 2809 if ( (clen == end) ||
2780 MHD_STATICSTR_LEN_(MHD_HTTP_HEADER_CONTENT_LENGTH), 2810 ('\0' != *end) )
2781 &clen, 2811 {
2782 NULL)) 2812 connection->remaining_upload_size = 0;
2783 {
2784 end = clen + MHD_str_to_uint64_ (clen,
2785 &connection->remaining_upload_size);
2786 if ( (clen == end) ||
2787 ('\0' != *end) )
2788 {
2789 connection->remaining_upload_size = 0;
2790#ifdef HAVE_MESSAGES 2813#ifdef HAVE_MESSAGES
2791 MHD_DLOG (connection->daemon, 2814 MHD_DLOG (connection->daemon,
2792 "Failed to parse `Content-Length' header. Closing connection.\n"); 2815 "Failed to parse `Content-Length' header. Closing connection.\n");
2793#endif 2816#endif
2794 CONNECTION_CLOSE_ERROR (connection, 2817 CONNECTION_CLOSE_ERROR (connection,
2795 NULL); 2818 NULL);
2796 return; 2819 return;
2797 } 2820 }
2798 }
2799 } 2821 }
2822 }
2800} 2823}
2801 2824
2802 2825
@@ -2818,7 +2841,7 @@ MHD_update_last_activity_ (struct MHD_Connection *connection)
2818 if (connection->suspended) 2841 if (connection->suspended)
2819 return; /* no activity on suspended connections */ 2842 return; /* no activity on suspended connections */
2820 2843
2821 connection->last_activity = MHD_monotonic_sec_counter(); 2844 connection->last_activity = MHD_monotonic_sec_counter ();
2822 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 2845 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2823 return; /* each connection has personal timeout */ 2846 return; /* each connection has personal timeout */
2824 2847
@@ -2829,11 +2852,11 @@ MHD_update_last_activity_ (struct MHD_Connection *connection)
2829#endif 2852#endif
2830 /* move connection to head of timeout list (by remove + add operation) */ 2853 /* move connection to head of timeout list (by remove + add operation) */
2831 XDLL_remove (daemon->normal_timeout_head, 2854 XDLL_remove (daemon->normal_timeout_head,
2832 daemon->normal_timeout_tail, 2855 daemon->normal_timeout_tail,
2833 connection); 2856 connection);
2834 XDLL_insert (daemon->normal_timeout_head, 2857 XDLL_insert (daemon->normal_timeout_head,
2835 daemon->normal_timeout_tail, 2858 daemon->normal_timeout_tail,
2836 connection); 2859 connection);
2837#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 2860#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2838 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex); 2861 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
2839#endif 2862#endif
@@ -2856,13 +2879,13 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
2856 return; 2879 return;
2857#ifdef HTTPS_SUPPORT 2880#ifdef HTTPS_SUPPORT
2858 if (MHD_TLS_CONN_NO_TLS != connection->tls_state) 2881 if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2859 { /* HTTPS connection. */ 2882 { /* HTTPS connection. */
2860 if (MHD_TLS_CONN_CONNECTED > connection->tls_state) 2883 if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2861 { 2884 {
2862 if (!MHD_run_tls_handshake_ (connection)) 2885 if (! MHD_run_tls_handshake_ (connection))
2863 return; 2886 return;
2864 }
2865 } 2887 }
2888 }
2866#endif /* HTTPS_SUPPORT */ 2889#endif /* HTTPS_SUPPORT */
2867 2890
2868 /* make sure "read" has a reasonable number of bytes 2891 /* make sure "read" has a reasonable number of bytes
@@ -2870,82 +2893,85 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
2870 if (connection->read_buffer_offset + connection->daemon->pool_increment > 2893 if (connection->read_buffer_offset + connection->daemon->pool_increment >
2871 connection->read_buffer_size) 2894 connection->read_buffer_size)
2872 try_grow_read_buffer (connection, 2895 try_grow_read_buffer (connection,
2873 (connection->read_buffer_size == connection->read_buffer_offset)); 2896 (connection->read_buffer_size ==
2897 connection->read_buffer_offset));
2874 2898
2875 if (connection->read_buffer_size == connection->read_buffer_offset) 2899 if (connection->read_buffer_size == connection->read_buffer_offset)
2876 return; /* No space for receiving data. */ 2900 return; /* No space for receiving data. */
2877 bytes_read = connection->recv_cls (connection, 2901 bytes_read = connection->recv_cls (connection,
2878 &connection->read_buffer 2902 &connection->read_buffer
2879 [connection->read_buffer_offset], 2903 [connection->read_buffer_offset],
2880 connection->read_buffer_size - 2904 connection->read_buffer_size
2881 connection->read_buffer_offset); 2905 - connection->read_buffer_offset);
2882 if (bytes_read < 0) 2906 if (bytes_read < 0)
2907 {
2908 if (MHD_ERR_AGAIN_ == bytes_read)
2909 return; /* No new data to process. */
2910 if (MHD_ERR_CONNRESET_ == bytes_read)
2883 { 2911 {
2884 if (MHD_ERR_AGAIN_ == bytes_read)
2885 return; /* No new data to process. */
2886 if (MHD_ERR_CONNRESET_ == bytes_read)
2887 {
2888 CONNECTION_CLOSE_ERROR (connection,
2889 (MHD_CONNECTION_INIT == connection->state) ?
2890 NULL :
2891 _("Socket disconnected while reading request.\n"));
2892 return;
2893 }
2894 CONNECTION_CLOSE_ERROR (connection, 2912 CONNECTION_CLOSE_ERROR (connection,
2895 (MHD_CONNECTION_INIT == connection->state) ? 2913 (MHD_CONNECTION_INIT == connection->state) ?
2896 NULL : 2914 NULL :
2897 _("Connection socket is closed due to error when reading request.\n")); 2915 _ (
2916 "Socket disconnected while reading request.\n"));
2898 return; 2917 return;
2899 } 2918 }
2919 CONNECTION_CLOSE_ERROR (connection,
2920 (MHD_CONNECTION_INIT == connection->state) ?
2921 NULL :
2922 _ (
2923 "Connection socket is closed due to error when reading request.\n"));
2924 return;
2925 }
2900 2926
2901 if (0 == bytes_read) 2927 if (0 == bytes_read)
2902 { /* Remote side closed connection. */ 2928 { /* Remote side closed connection. */
2903 connection->read_closed = true; 2929 connection->read_closed = true;
2904 MHD_connection_close_ (connection, 2930 MHD_connection_close_ (connection,
2905 MHD_REQUEST_TERMINATED_CLIENT_ABORT); 2931 MHD_REQUEST_TERMINATED_CLIENT_ABORT);
2906 return; 2932 return;
2907 } 2933 }
2908 connection->read_buffer_offset += bytes_read; 2934 connection->read_buffer_offset += bytes_read;
2909 MHD_update_last_activity_ (connection); 2935 MHD_update_last_activity_ (connection);
2910#if DEBUG_STATES 2936#if DEBUG_STATES
2911 MHD_DLOG (connection->daemon, 2937 MHD_DLOG (connection->daemon,
2912 _("In function %s handling connection at state: %s\n"), 2938 _ ("In function %s handling connection at state: %s\n"),
2913 __FUNCTION__, 2939 __FUNCTION__,
2914 MHD_state_to_string (connection->state)); 2940 MHD_state_to_string (connection->state));
2915#endif 2941#endif
2916 switch (connection->state) 2942 switch (connection->state)
2943 {
2944 case MHD_CONNECTION_INIT:
2945 case MHD_CONNECTION_URL_RECEIVED:
2946 case MHD_CONNECTION_HEADER_PART_RECEIVED:
2947 case MHD_CONNECTION_HEADERS_RECEIVED:
2948 case MHD_CONNECTION_HEADERS_PROCESSED:
2949 case MHD_CONNECTION_CONTINUE_SENDING:
2950 case MHD_CONNECTION_CONTINUE_SENT:
2951 case MHD_CONNECTION_BODY_RECEIVED:
2952 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
2953 /* nothing to do but default action */
2954 if (connection->read_closed)
2917 { 2955 {
2918 case MHD_CONNECTION_INIT: 2956 MHD_connection_close_ (connection,
2919 case MHD_CONNECTION_URL_RECEIVED: 2957 MHD_REQUEST_TERMINATED_READ_ERROR);
2920 case MHD_CONNECTION_HEADER_PART_RECEIVED: 2958 }
2921 case MHD_CONNECTION_HEADERS_RECEIVED: 2959 return;
2922 case MHD_CONNECTION_HEADERS_PROCESSED: 2960 case MHD_CONNECTION_CLOSED:
2923 case MHD_CONNECTION_CONTINUE_SENDING: 2961 return;
2924 case MHD_CONNECTION_CONTINUE_SENT:
2925 case MHD_CONNECTION_BODY_RECEIVED:
2926 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
2927 /* nothing to do but default action */
2928 if (connection->read_closed)
2929 {
2930 MHD_connection_close_ (connection,
2931 MHD_REQUEST_TERMINATED_READ_ERROR);
2932 }
2933 return;
2934 case MHD_CONNECTION_CLOSED:
2935 return;
2936#ifdef UPGRADE_SUPPORT 2962#ifdef UPGRADE_SUPPORT
2937 case MHD_CONNECTION_UPGRADE: 2963 case MHD_CONNECTION_UPGRADE:
2938 mhd_assert (0); 2964 mhd_assert (0);
2939 return; 2965 return;
2940#endif /* UPGRADE_SUPPORT */ 2966#endif /* UPGRADE_SUPPORT */
2941 default: 2967 default:
2942 /* shrink read buffer to how much is actually used */ 2968 /* shrink read buffer to how much is actually used */
2943 MHD_pool_reallocate (connection->pool, 2969 MHD_pool_reallocate (connection->pool,
2944 connection->read_buffer, 2970 connection->read_buffer,
2945 connection->read_buffer_size + 1, 2971 connection->read_buffer_size + 1,
2946 connection->read_buffer_offset); 2972 connection->read_buffer_offset);
2947 break; 2973 break;
2948 } 2974 }
2949 return; 2975 return;
2950} 2976}
2951 2977
@@ -2966,258 +2992,261 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
2966 2992
2967#ifdef HTTPS_SUPPORT 2993#ifdef HTTPS_SUPPORT
2968 if (MHD_TLS_CONN_NO_TLS != connection->tls_state) 2994 if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2969 { /* HTTPS connection. */ 2995 { /* HTTPS connection. */
2970 if (MHD_TLS_CONN_CONNECTED > connection->tls_state) 2996 if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2971 { 2997 {
2972 if (!MHD_run_tls_handshake_ (connection)) 2998 if (! MHD_run_tls_handshake_ (connection))
2973 return; 2999 return;
2974 }
2975 } 3000 }
3001 }
2976#endif /* HTTPS_SUPPORT */ 3002#endif /* HTTPS_SUPPORT */
2977 3003
2978#if DEBUG_STATES 3004#if DEBUG_STATES
2979 MHD_DLOG (connection->daemon, 3005 MHD_DLOG (connection->daemon,
2980 _("In function %s handling connection at state: %s\n"), 3006 _ ("In function %s handling connection at state: %s\n"),
2981 __FUNCTION__, 3007 __FUNCTION__,
2982 MHD_state_to_string (connection->state)); 3008 MHD_state_to_string (connection->state));
2983#endif 3009#endif
2984 switch (connection->state) 3010 switch (connection->state)
3011 {
3012 case MHD_CONNECTION_INIT:
3013 case MHD_CONNECTION_URL_RECEIVED:
3014 case MHD_CONNECTION_HEADER_PART_RECEIVED:
3015 case MHD_CONNECTION_HEADERS_RECEIVED:
3016 mhd_assert (0);
3017 return;
3018 case MHD_CONNECTION_HEADERS_PROCESSED:
3019 return;
3020 case MHD_CONNECTION_CONTINUE_SENDING:
3021 ret = MHD_send_on_connection_ (connection,
3022 &HTTP_100_CONTINUE
3023 [connection->continue_message_write_offset],
3024 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE)
3025 - connection->continue_message_write_offset,
3026 MHD_SSO_NO_CORK);
3027 if (ret < 0)
2985 { 3028 {
2986 case MHD_CONNECTION_INIT: 3029 if (MHD_ERR_AGAIN_ == ret)
2987 case MHD_CONNECTION_URL_RECEIVED: 3030 return;
2988 case MHD_CONNECTION_HEADER_PART_RECEIVED:
2989 case MHD_CONNECTION_HEADERS_RECEIVED:
2990 mhd_assert (0);
2991 return;
2992 case MHD_CONNECTION_HEADERS_PROCESSED:
2993 return;
2994 case MHD_CONNECTION_CONTINUE_SENDING:
2995 ret = MHD_send_on_connection_ (connection,
2996 &HTTP_100_CONTINUE
2997 [connection->continue_message_write_offset],
2998 MHD_STATICSTR_LEN_ (HTTP_100_CONTINUE) -
2999 connection->continue_message_write_offset,
3000 MHD_SSO_NO_CORK);
3001 if (ret < 0)
3002 {
3003 if (MHD_ERR_AGAIN_ == ret)
3004 return;
3005#ifdef HAVE_MESSAGES 3031#ifdef HAVE_MESSAGES
3006 MHD_DLOG (connection->daemon, 3032 MHD_DLOG (connection->daemon,
3007 _("Failed to send data in request for %s.\n"), 3033 _ ("Failed to send data in request for %s.\n"),
3008 connection->url); 3034 connection->url);
3009#endif 3035#endif
3010 CONNECTION_CLOSE_ERROR (connection, 3036 CONNECTION_CLOSE_ERROR (connection,
3011 NULL); 3037 NULL);
3012 return; 3038 return;
3013 } 3039 }
3014#if DEBUG_SEND_DATA 3040#if DEBUG_SEND_DATA
3015 fprintf (stderr, 3041 fprintf (stderr,
3016 _("Sent 100 continue response: `%.*s'\n"), 3042 _ ("Sent 100 continue response: `%.*s'\n"),
3017 (int) ret, 3043 (int) ret,
3018 &HTTP_100_CONTINUE[connection->continue_message_write_offset]); 3044 &HTTP_100_CONTINUE[connection->continue_message_write_offset]);
3019#endif 3045#endif
3020 connection->continue_message_write_offset += ret; 3046 connection->continue_message_write_offset += ret;
3021 MHD_update_last_activity_ (connection); 3047 MHD_update_last_activity_ (connection);
3022 return; 3048 return;
3023 case MHD_CONNECTION_CONTINUE_SENT: 3049 case MHD_CONNECTION_CONTINUE_SENT:
3024 case MHD_CONNECTION_BODY_RECEIVED: 3050 case MHD_CONNECTION_BODY_RECEIVED:
3025 case MHD_CONNECTION_FOOTER_PART_RECEIVED: 3051 case MHD_CONNECTION_FOOTER_PART_RECEIVED:
3026 case MHD_CONNECTION_FOOTERS_RECEIVED: 3052 case MHD_CONNECTION_FOOTERS_RECEIVED:
3027 mhd_assert (0); 3053 mhd_assert (0);
3028 return; 3054 return;
3029 case MHD_CONNECTION_HEADERS_SENDING: 3055 case MHD_CONNECTION_HEADERS_SENDING:
3030 { 3056 {
3031 const size_t wb_ready = connection->write_buffer_append_offset - 3057 const size_t wb_ready = connection->write_buffer_append_offset
3032 connection->write_buffer_send_offset; 3058 - connection->write_buffer_send_offset;
3033 3059
3034 /* if the response body is not available, we use MHD_send_on_connection_() */ 3060 /* if the response body is not available, we use MHD_send_on_connection_() */
3035 if (NULL != connection->response->crc) 3061 if (NULL != connection->response->crc)
3036 { 3062 {
3037 ret = MHD_send_on_connection_ (connection, 3063 ret = MHD_send_on_connection_ (connection,
3038 &connection->write_buffer 3064 &connection->write_buffer
3039 [connection->write_buffer_send_offset], 3065 [connection->write_buffer_send_offset],
3040 wb_ready, 3066 wb_ready,
3041 MHD_SSO_MAY_CORK); 3067 MHD_SSO_MAY_CORK);
3042 } 3068 }
3043 else 3069 else
3044 { 3070 {
3045 ret = MHD_send_on_connection2_ (connection, 3071 ret = MHD_send_on_connection2_ (connection,
3046 &connection->write_buffer 3072 &connection->write_buffer
3047 [connection->write_buffer_send_offset], 3073 [connection->write_buffer_send_offset],
3048 wb_ready, 3074 wb_ready,
3049 connection->response->data, 3075 connection->response->data,
3050 connection->response->data_buffer_size); 3076 connection->response->data_buffer_size);
3051 } 3077 }
3052 3078
3053 if (ret < 0) 3079 if (ret < 0)
3054 { 3080 {
3055 if (MHD_ERR_AGAIN_ == ret) 3081 if (MHD_ERR_AGAIN_ == ret)
3056 return;
3057 CONNECTION_CLOSE_ERROR (connection,
3058 _("Connection was closed while sending response headers.\n"));
3059 return;
3060 }
3061 if (ret > wb_ready)
3062 {
3063 mhd_assert (NULL == connection->repsonse->crc);
3064 /* We sent not just header data but also some response data,
3065 update both offsets! */
3066 connection->write_buffer_send_offset += wb_ready;
3067 ret -= wb_ready;
3068 connection->response_write_position += ret;
3069 }
3070 else
3071 connection->write_buffer_send_offset += ret;
3072 MHD_update_last_activity_ (connection);
3073 if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3074 return; 3082 return;
3075 check_write_done (connection, 3083 CONNECTION_CLOSE_ERROR (connection,
3076 MHD_CONNECTION_HEADERS_SENT); 3084 _ (
3085 "Connection was closed while sending response headers.\n"));
3077 return; 3086 return;
3078 } 3087 }
3079 case MHD_CONNECTION_HEADERS_SENT: 3088 if (ret > wb_ready)
3089 {
3090 mhd_assert (NULL == connection->repsonse->crc);
3091 /* We sent not just header data but also some response data,
3092 update both offsets! */
3093 connection->write_buffer_send_offset += wb_ready;
3094 ret -= wb_ready;
3095 connection->response_write_position += ret;
3096 }
3097 else
3098 connection->write_buffer_send_offset += ret;
3099 MHD_update_last_activity_ (connection);
3100 if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3101 return;
3102 check_write_done (connection,
3103 MHD_CONNECTION_HEADERS_SENT);
3080 return; 3104 return;
3081 case MHD_CONNECTION_NORMAL_BODY_READY: 3105 }
3082 response = connection->response; 3106 case MHD_CONNECTION_HEADERS_SENT:
3083 if (connection->response_write_position < 3107 return;
3084 connection->response->total_size) 3108 case MHD_CONNECTION_NORMAL_BODY_READY:
3085 { 3109 response = connection->response;
3086 uint64_t data_write_offset; 3110 if (connection->response_write_position <
3111 connection->response->total_size)
3112 {
3113 uint64_t data_write_offset;
3087 3114
3088#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3115#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3089 if (NULL != response->crc) 3116 if (NULL != response->crc)
3090 MHD_mutex_lock_chk_ (&response->mutex); 3117 MHD_mutex_lock_chk_ (&response->mutex);
3091#endif 3118#endif
3092 if (MHD_YES != try_ready_normal_body (connection)) 3119 if (MHD_YES != try_ready_normal_body (connection))
3093 { 3120 {
3094 /* mutex was already unlocked by try_ready_normal_body */ 3121 /* mutex was already unlocked by try_ready_normal_body */
3095 return; 3122 return;
3096 } 3123 }
3097#if defined(_MHD_HAVE_SENDFILE) 3124#if defined(_MHD_HAVE_SENDFILE)
3098 if (MHD_resp_sender_sendfile == connection->resp_sender) 3125 if (MHD_resp_sender_sendfile == connection->resp_sender)
3099 { 3126 {
3100 ret = MHD_send_sendfile_ (connection); 3127 ret = MHD_send_sendfile_ (connection);
3101 } 3128 }
3102 else 3129 else
3103#else /* ! _MHD_HAVE_SENDFILE */ 3130#else /* ! _MHD_HAVE_SENDFILE */
3104 if (1) 3131 if (1)
3105#endif /* ! _MHD_HAVE_SENDFILE */ 3132#endif /* ! _MHD_HAVE_SENDFILE */
3106 { 3133 {
3107 data_write_offset = connection->response_write_position 3134 data_write_offset = connection->response_write_position
3108 - response->data_start; 3135 - response->data_start;
3109 if (data_write_offset > (uint64_t)SIZE_MAX) 3136 if (data_write_offset > (uint64_t) SIZE_MAX)
3110 MHD_PANIC (_("Data offset exceeds limit")); 3137 MHD_PANIC (_ ("Data offset exceeds limit"));
3111 ret = MHD_send_on_connection_ (connection, 3138 ret = MHD_send_on_connection_ (connection,
3112 &response->data 3139 &response->data
3113 [(size_t)data_write_offset], 3140 [(size_t) data_write_offset],
3114 response->data_size - 3141 response->data_size
3115 (size_t)data_write_offset, 3142 - (size_t) data_write_offset,
3116 MHD_SSO_NO_CORK); 3143 MHD_SSO_NO_CORK);
3117#if DEBUG_SEND_DATA 3144#if DEBUG_SEND_DATA
3118 if (ret > 0) 3145 if (ret > 0)
3119 fprintf (stderr, 3146 fprintf (stderr,
3120 _("Sent %d-byte DATA response: `%.*s'\n"), 3147 _ ("Sent %d-byte DATA response: `%.*s'\n"),
3121 (int) ret, 3148 (int) ret,
3122 (int) ret, 3149 (int) ret,
3123 &response->data[connection->response_write_position - 3150 &response->data[connection->response_write_position
3124 response->data_start]); 3151 - response->data_start]);
3125#endif 3152#endif
3126 } 3153 }
3127#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3154#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3128 if (NULL != response->crc) 3155 if (NULL != response->crc)
3129 MHD_mutex_unlock_chk_ (&response->mutex); 3156 MHD_mutex_unlock_chk_ (&response->mutex);
3130#endif
3131 if (ret < 0)
3132 {
3133 if (MHD_ERR_AGAIN_ == ret)
3134 return;
3135#ifdef HAVE_MESSAGES
3136 MHD_DLOG (connection->daemon,
3137 _("Failed to send data in request for `%s'.\n"),
3138 connection->url);
3139#endif 3157#endif
3140 CONNECTION_CLOSE_ERROR (connection,
3141 NULL);
3142 return;
3143 }
3144 connection->response_write_position += ret;
3145 MHD_update_last_activity_ (connection);
3146 }
3147 if (connection->response_write_position ==
3148 connection->response->total_size)
3149 connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3150 return;
3151 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
3152 mhd_assert (0);
3153 return;
3154 case MHD_CONNECTION_CHUNKED_BODY_READY:
3155 ret = MHD_send_on_connection_ (connection,
3156 &connection->write_buffer
3157 [connection->write_buffer_send_offset],
3158 connection->write_buffer_append_offset -
3159 connection->write_buffer_send_offset,
3160 MHD_SSO_NO_CORK);
3161 if (ret < 0) 3158 if (ret < 0)
3162 { 3159 {
3163 if (MHD_ERR_AGAIN_ == ret) 3160 if (MHD_ERR_AGAIN_ == ret)
3164 return;
3165 CONNECTION_CLOSE_ERROR (connection,
3166 _("Connection was closed while sending response body.\n"));
3167 return; 3161 return;
3168 } 3162#ifdef HAVE_MESSAGES
3169 connection->write_buffer_send_offset += ret; 3163 MHD_DLOG (connection->daemon,
3164 _ ("Failed to send data in request for `%s'.\n"),
3165 connection->url);
3166#endif
3167 CONNECTION_CLOSE_ERROR (connection,
3168 NULL);
3169 return;
3170 }
3171 connection->response_write_position += ret;
3170 MHD_update_last_activity_ (connection); 3172 MHD_update_last_activity_ (connection);
3171 if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state) 3173 }
3174 if (connection->response_write_position ==
3175 connection->response->total_size)
3176 connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3177 return;
3178 case MHD_CONNECTION_NORMAL_BODY_UNREADY:
3179 mhd_assert (0);
3180 return;
3181 case MHD_CONNECTION_CHUNKED_BODY_READY:
3182 ret = MHD_send_on_connection_ (connection,
3183 &connection->write_buffer
3184 [connection->write_buffer_send_offset],
3185 connection->write_buffer_append_offset
3186 - connection->write_buffer_send_offset,
3187 MHD_SSO_NO_CORK);
3188 if (ret < 0)
3189 {
3190 if (MHD_ERR_AGAIN_ == ret)
3172 return; 3191 return;
3173 check_write_done (connection, 3192 CONNECTION_CLOSE_ERROR (connection,
3174 (connection->response->total_size == 3193 _ (
3175 connection->response_write_position) ? 3194 "Connection was closed while sending response body.\n"));
3176 MHD_CONNECTION_BODY_SENT :
3177 MHD_CONNECTION_CHUNKED_BODY_UNREADY);
3178 return; 3195 return;
3179 case MHD_CONNECTION_CHUNKED_BODY_UNREADY: 3196 }
3180 case MHD_CONNECTION_BODY_SENT: 3197 connection->write_buffer_send_offset += ret;
3181 mhd_assert (0); 3198 MHD_update_last_activity_ (connection);
3199 if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3182 return; 3200 return;
3183 case MHD_CONNECTION_FOOTERS_SENDING: 3201 check_write_done (connection,
3184 ret = MHD_send_on_connection_ (connection, 3202 (connection->response->total_size ==
3185 &connection->write_buffer 3203 connection->response_write_position) ?
3186 [connection->write_buffer_send_offset], 3204 MHD_CONNECTION_BODY_SENT :
3187 connection->write_buffer_append_offset - 3205 MHD_CONNECTION_CHUNKED_BODY_UNREADY);
3188 connection->write_buffer_send_offset, 3206 return;
3189 MHD_SSO_HDR_CORK); 3207 case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
3190 if (ret < 0) 3208 case MHD_CONNECTION_BODY_SENT:
3191 { 3209 mhd_assert (0);
3192 if (MHD_ERR_AGAIN_ == ret) 3210 return;
3193 return; 3211 case MHD_CONNECTION_FOOTERS_SENDING:
3194 CONNECTION_CLOSE_ERROR (connection, 3212 ret = MHD_send_on_connection_ (connection,
3195 _("Connection was closed while sending response body.\n")); 3213 &connection->write_buffer
3196 return; 3214 [connection->write_buffer_send_offset],
3197 } 3215 connection->write_buffer_append_offset
3198 connection->write_buffer_send_offset += ret; 3216 - connection->write_buffer_send_offset,
3199 MHD_update_last_activity_ (connection); 3217 MHD_SSO_HDR_CORK);
3200 if (MHD_CONNECTION_FOOTERS_SENDING != connection->state) 3218 if (ret < 0)
3219 {
3220 if (MHD_ERR_AGAIN_ == ret)
3201 return; 3221 return;
3202 check_write_done (connection, 3222 CONNECTION_CLOSE_ERROR (connection,
3203 MHD_CONNECTION_FOOTERS_SENT); 3223 _ (
3204 return; 3224 "Connection was closed while sending response body.\n"));
3205 case MHD_CONNECTION_FOOTERS_SENT:
3206 mhd_assert (0);
3207 return; 3225 return;
3208 case MHD_CONNECTION_CLOSED: 3226 }
3227 connection->write_buffer_send_offset += ret;
3228 MHD_update_last_activity_ (connection);
3229 if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3209 return; 3230 return;
3231 check_write_done (connection,
3232 MHD_CONNECTION_FOOTERS_SENT);
3233 return;
3234 case MHD_CONNECTION_FOOTERS_SENT:
3235 mhd_assert (0);
3236 return;
3237 case MHD_CONNECTION_CLOSED:
3238 return;
3210#ifdef UPGRADE_SUPPORT 3239#ifdef UPGRADE_SUPPORT
3211 case MHD_CONNECTION_UPGRADE: 3240 case MHD_CONNECTION_UPGRADE:
3212 mhd_assert (0); 3241 mhd_assert (0);
3213 return; 3242 return;
3214#endif /* UPGRADE_SUPPORT */ 3243#endif /* UPGRADE_SUPPORT */
3215 default: 3244 default:
3216 mhd_assert (0); 3245 mhd_assert (0);
3217 CONNECTION_CLOSE_ERROR (connection, 3246 CONNECTION_CLOSE_ERROR (connection,
3218 _("Internal error\n")); 3247 _ ("Internal error\n"));
3219 break; 3248 break;
3220 } 3249 }
3221 return; 3250 return;
3222} 3251}
3223 3252
@@ -3239,59 +3268,60 @@ cleanup_connection (struct MHD_Connection *connection)
3239 return; /* Prevent double cleanup. */ 3268 return; /* Prevent double cleanup. */
3240 connection->in_cleanup = true; 3269 connection->in_cleanup = true;
3241 if (NULL != connection->response) 3270 if (NULL != connection->response)
3242 { 3271 {
3243 MHD_destroy_response (connection->response); 3272 MHD_destroy_response (connection->response);
3244 connection->response = NULL; 3273 connection->response = NULL;
3245 } 3274 }
3246#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3275#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3247 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex); 3276 MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
3248#endif 3277#endif
3249 if (connection->suspended) 3278 if (connection->suspended)
3250 { 3279 {
3251 DLL_remove (daemon->suspended_connections_head, 3280 DLL_remove (daemon->suspended_connections_head,
3252 daemon->suspended_connections_tail, 3281 daemon->suspended_connections_tail,
3253 connection); 3282 connection);
3254 connection->suspended = false; 3283 connection->suspended = false;
3255 } 3284 }
3256 else 3285 else
3286 {
3287 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3257 { 3288 {
3258 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 3289 if (connection->connection_timeout == daemon->connection_timeout)
3259 { 3290 XDLL_remove (daemon->normal_timeout_head,
3260 if (connection->connection_timeout == daemon->connection_timeout) 3291 daemon->normal_timeout_tail,
3261 XDLL_remove (daemon->normal_timeout_head, 3292 connection);
3262 daemon->normal_timeout_tail, 3293 else
3263 connection); 3294 XDLL_remove (daemon->manual_timeout_head,
3264 else 3295 daemon->manual_timeout_tail,
3265 XDLL_remove (daemon->manual_timeout_head, 3296 connection);
3266 daemon->manual_timeout_tail,
3267 connection);
3268 }
3269 DLL_remove (daemon->connections_head,
3270 daemon->connections_tail,
3271 connection);
3272 } 3297 }
3298 DLL_remove (daemon->connections_head,
3299 daemon->connections_tail,
3300 connection);
3301 }
3273 DLL_insert (daemon->cleanup_head, 3302 DLL_insert (daemon->cleanup_head,
3274 daemon->cleanup_tail, 3303 daemon->cleanup_tail,
3275 connection); 3304 connection);
3276 connection->resuming = false; 3305 connection->resuming = false;
3277 connection->in_idle = false; 3306 connection->in_idle = false;
3278#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS) 3307#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3279 MHD_mutex_unlock_chk_(&daemon->cleanup_connection_mutex); 3308 MHD_mutex_unlock_chk_ (&daemon->cleanup_connection_mutex);
3280#endif 3309#endif
3281 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 3310 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3311 {
3312 /* if we were at the connection limit before and are in
3313 thread-per-connection mode, signal the main thread
3314 to resume accepting connections */
3315 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3316 (! MHD_itc_activate_ (daemon->itc, "c")) )
3282 { 3317 {
3283 /* if we were at the connection limit before and are in
3284 thread-per-connection mode, signal the main thread
3285 to resume accepting connections */
3286 if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3287 (! MHD_itc_activate_ (daemon->itc, "c")) )
3288 {
3289#ifdef HAVE_MESSAGES 3318#ifdef HAVE_MESSAGES
3290 MHD_DLOG (daemon, 3319 MHD_DLOG (daemon,
3291 _("Failed to signal end of connection via inter-thread communication channel")); 3320 _ (
3321 "Failed to signal end of connection via inter-thread communication channel"));
3292#endif 3322#endif
3293 }
3294 } 3323 }
3324 }
3295} 3325}
3296 3326
3297 3327
@@ -3315,471 +3345,475 @@ MHD_connection_handle_idle (struct MHD_Connection *connection)
3315 3345
3316 connection->in_idle = true; 3346 connection->in_idle = true;
3317 while (! connection->suspended) 3347 while (! connection->suspended)
3318 { 3348 {
3319#ifdef HTTPS_SUPPORT 3349#ifdef HTTPS_SUPPORT
3320 if (MHD_TLS_CONN_NO_TLS != connection->tls_state) 3350 if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3321 { /* HTTPS connection. */ 3351 { /* HTTPS connection. */
3322 if ((MHD_TLS_CONN_INIT <= connection->tls_state) && 3352 if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3323 (MHD_TLS_CONN_CONNECTED > connection->tls_state)) 3353 (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3324 break; 3354 break;
3325 } 3355 }
3326#endif /* HTTPS_SUPPORT */ 3356#endif /* HTTPS_SUPPORT */
3327#if DEBUG_STATES 3357#if DEBUG_STATES
3328 MHD_DLOG (daemon, 3358 MHD_DLOG (daemon,
3329 _("In function %s handling connection at state: %s\n"), 3359 _ ("In function %s handling connection at state: %s\n"),
3330 __FUNCTION__, 3360 __FUNCTION__,
3331 MHD_state_to_string (connection->state)); 3361 MHD_state_to_string (connection->state));
3332#endif 3362#endif
3333 switch (connection->state) 3363 switch (connection->state)
3364 {
3365 case MHD_CONNECTION_INIT:
3366 line = get_next_header_line (connection,
3367 &line_len);
3368 /* Check for empty string, as we might want
3369 to tolerate 'spurious' empty lines; also
3370 NULL means we didn't get a full line yet;
3371 line is not 0-terminated here. */
3372 if ( (NULL == line) ||
3373 (0 == line[0]) )
3374 {
3375 if (MHD_CONNECTION_INIT != connection->state)
3376 continue;
3377 if (connection->read_closed)
3334 { 3378 {
3335 case MHD_CONNECTION_INIT: 3379 CONNECTION_CLOSE_ERROR (connection,
3336 line = get_next_header_line (connection, 3380 NULL);