GNU libmicrohttpd  0.9.63
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2017 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
28 #include "internal.h"
29 #include "mhd_limits.h"
30 #include "connection.h"
31 #include "memorypool.h"
32 #include "response.h"
33 #include "mhd_mono_clock.h"
34 #include "mhd_str.h"
35 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
36 #include "mhd_locks.h"
37 #endif
38 #include "mhd_sockets.h"
39 #include "mhd_compat.h"
40 #include "mhd_itc.h"
41 #ifdef MHD_LINUX_SOLARIS_SENDFILE
42 #include <sys/sendfile.h>
43 #endif /* MHD_LINUX_SOLARIS_SENDFILE */
44 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <sys/uio.h>
48 #endif /* HAVE_FREEBSD_SENDFILE || HAVE_DARWIN_SENDFILE */
49 #ifdef HTTPS_SUPPORT
50 #include "connection_https.h"
51 #endif /* HTTPS_SUPPORT */
52 #ifdef HAVE_SYS_PARAM_H
53 /* For FreeBSD version identification */
54 #include <sys/param.h>
55 #endif /* HAVE_SYS_PARAM_H */
56 
57 
61 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
62 
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>"
72 #else
73 #define REQUEST_TOO_BIG ""
74 #endif
75 
83 #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 #else
86 #define REQUEST_LACKS_HOST ""
87 #endif
88 
96 #ifdef HAVE_MESSAGES
97 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
98 #else
99 #define REQUEST_MALFORMED ""
100 #endif
101 
108 #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>"
110 #else
111 #define INTERNAL_ERROR ""
112 #endif
113 
118 #define DEBUG_CLOSE MHD_NO
119 
123 #define DEBUG_SEND_DATA MHD_NO
124 
125 
129 #define MHD_SENFILE_CHUNK_ (0x20000)
130 
134 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
135 
136 #ifdef HAVE_FREEBSD_SENDFILE
137 #ifdef SF_FLAGS
138 
141 static int freebsd_sendfile_flags_;
142 
146 static int freebsd_sendfile_flags_thd_p_c_;
147 #endif /* SF_FLAGS */
148 
151 void
152 MHD_conn_init_static_ (void)
153 {
154 /* FreeBSD 11 and later allow to specify read-ahead size
155  * and handles SF_NODISKIO differently.
156  * SF_FLAGS defined only on FreeBSD 11 and later. */
157 #ifdef SF_FLAGS
158  long sys_page_size = sysconf (_SC_PAGESIZE);
159  if (0 > sys_page_size)
160  { /* Failed to get page size. */
161  freebsd_sendfile_flags_ = SF_NODISKIO;
162  freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
163  }
164  else
165  {
166  freebsd_sendfile_flags_ =
167  SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
168  freebsd_sendfile_flags_thd_p_c_ =
169  SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size), SF_NODISKIO);
170  }
171 #endif /* SF_FLAGS */
172 }
173 #endif /* HAVE_FREEBSD_SENDFILE */
174 
183 static ssize_t
184 recv_param_adapter (struct MHD_Connection *connection,
185  void *other,
186  size_t i)
187 {
188  ssize_t ret;
189 
190  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
191  (MHD_CONNECTION_CLOSED == connection->state) )
192  {
193  return MHD_ERR_NOTCONN_;
194  }
195  if (i > MHD_SCKT_SEND_MAX_SIZE_)
196  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
197 
198  ret = MHD_recv_ (connection->socket_fd,
199  other,
200  i);
201  if (0 > ret)
202  {
203  const int err = MHD_socket_get_error_ ();
204  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
205  {
206 #ifdef EPOLL_SUPPORT
207  /* Got EAGAIN --- no longer read-ready */
208  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
209 #endif /* EPOLL_SUPPORT */
210  return MHD_ERR_AGAIN_;
211  }
212  if (MHD_SCKT_ERR_IS_EINTR_ (err))
213  return MHD_ERR_AGAIN_;
215  return MHD_ERR_CONNRESET_;
216  /* Treat any other error as hard error. */
217  return MHD_ERR_NOTCONN_;
218  }
219 #ifdef EPOLL_SUPPORT
220  else if (i > (size_t)ret)
221  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
222 #endif /* EPOLL_SUPPORT */
223  return ret;
224 }
225 
226 
236 static ssize_t
237 send_param_adapter (struct MHD_Connection *connection,
238  const void *other,
239  size_t i)
240 {
241  ssize_t ret;
242 
243  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
244  (MHD_CONNECTION_CLOSED == connection->state) )
245  {
246  return MHD_ERR_NOTCONN_;
247  }
248  if (i > MHD_SCKT_SEND_MAX_SIZE_)
249  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
250 
251  ret = MHD_send_ (connection->socket_fd,
252  other,
253  i);
254  if (0 > ret)
255  {
256  const int err = MHD_socket_get_error_();
257 
258  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
259  {
260 #ifdef EPOLL_SUPPORT
261  /* EAGAIN --- no longer write-ready */
262  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
263 #endif /* EPOLL_SUPPORT */
264  return MHD_ERR_AGAIN_;
265  }
266  if (MHD_SCKT_ERR_IS_EINTR_ (err))
267  return MHD_ERR_AGAIN_;
269  return MHD_ERR_CONNRESET_;
270  /* Treat any other error as hard error. */
271  return MHD_ERR_NOTCONN_;
272  }
273 #ifdef EPOLL_SUPPORT
274  else if (i > (size_t)ret)
275  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
276 #endif /* EPOLL_SUPPORT */
277  return ret;
278 }
279 
280 
281 #if defined(_MHD_HAVE_SENDFILE)
282 
288 static ssize_t
289 sendfile_adapter (struct MHD_Connection *connection)
290 {
291  ssize_t ret;
292  const int file_fd = connection->response->fd;
293  uint64_t left;
294  uint64_t offsetu64;
295 #ifndef HAVE_SENDFILE64
296  const uint64_t max_off_t = (uint64_t)OFF_T_MAX;
297 #else /* HAVE_SENDFILE64 */
298  const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
299 #endif /* HAVE_SENDFILE64 */
300 #ifdef MHD_LINUX_SOLARIS_SENDFILE
301 #ifndef HAVE_SENDFILE64
302  off_t offset;
303 #else /* HAVE_SENDFILE64 */
304  off64_t offset;
305 #endif /* HAVE_SENDFILE64 */
306 #endif /* MHD_LINUX_SOLARIS_SENDFILE */
307 #ifdef HAVE_FREEBSD_SENDFILE
308  off_t sent_bytes;
309  int flags = 0;
310 #endif
311 #ifdef HAVE_DARWIN_SENDFILE
312  off_t len;
313 #endif /* HAVE_DARWIN_SENDFILE */
314  const bool used_thr_p_c = (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION));
315  const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : MHD_SENFILE_CHUNK_;
316  size_t send_size = 0;
317  mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
318 
319  offsetu64 = connection->response_write_position + connection->response->fd_off;
320  left = connection->response->total_size - connection->response_write_position;
321  /* Do not allow system to stick sending on single fast connection:
322  * use 128KiB chunks (2MiB for thread-per-connection). */
323  send_size = (left > chunk_size) ? chunk_size : (size_t) left;
324  if (max_off_t < offsetu64)
325  { /* Retry to send with standard 'send()'. */
326  connection->resp_sender = MHD_resp_sender_std;
327  return MHD_ERR_AGAIN_;
328  }
329 #ifdef MHD_LINUX_SOLARIS_SENDFILE
330 #ifndef HAVE_SENDFILE64
331  offset = (off_t) offsetu64;
332  ret = sendfile (connection->socket_fd,
333  file_fd,
334  &offset,
335  send_size);
336 #else /* HAVE_SENDFILE64 */
337  offset = (off64_t) offsetu64;
338  ret = sendfile64 (connection->socket_fd,
339  file_fd,
340  &offset,
341  send_size);
342 #endif /* HAVE_SENDFILE64 */
343  if (0 > ret)
344  {
345  const int err = MHD_socket_get_error_();
346  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
347  {
348 #ifdef EPOLL_SUPPORT
349  /* EAGAIN --- no longer write-ready */
350  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
351 #endif /* EPOLL_SUPPORT */
352  return MHD_ERR_AGAIN_;
353  }
354  if (MHD_SCKT_ERR_IS_EINTR_ (err))
355  return MHD_ERR_AGAIN_;
356 #ifdef HAVE_LINUX_SENDFILE
357  if (MHD_SCKT_ERR_IS_(err,
359  return MHD_ERR_BADF_;
360  /* sendfile() failed with EINVAL if mmap()-like operations are not
361  supported for FD or other 'unusual' errors occurred, so we should try
362  to fall back to 'SEND'; see also this thread for info on
363  odd libc/Linux behavior with sendfile:
364  http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
365  connection->resp_sender = MHD_resp_sender_std;
366  return MHD_ERR_AGAIN_;
367 #else /* HAVE_SOLARIS_SENDFILE */
368  if ( (EAFNOSUPPORT == err) ||
369  (EINVAL == err) ||
370  (EOPNOTSUPP == err) )
371  { /* Retry with standard file reader. */
372  connection->resp_sender = MHD_resp_sender_std;
373  return MHD_ERR_AGAIN_;
374  }
375  if ( (ENOTCONN == err) ||
376  (EPIPE == err) )
377  {
378  return MHD_ERR_CONNRESET_;
379  }
380  return MHD_ERR_BADF_; /* Fail hard */
381 #endif /* HAVE_SOLARIS_SENDFILE */
382  }
383 #ifdef EPOLL_SUPPORT
384  else if (send_size > (size_t)ret)
385  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
386 #endif /* EPOLL_SUPPORT */
387 #elif defined(HAVE_FREEBSD_SENDFILE)
388 #ifdef SF_FLAGS
389  flags = used_thr_p_c ?
390  freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
391 #endif /* SF_FLAGS */
392  if (0 != sendfile (file_fd,
393  connection->socket_fd,
394  (off_t) offsetu64,
395  send_size,
396  NULL,
397  &sent_bytes,
398  flags))
399  {
400  const int err = MHD_socket_get_error_();
401  if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
402  MHD_SCKT_ERR_IS_EINTR_(err) ||
403  EBUSY == err)
404  {
405  mhd_assert (SSIZE_MAX >= sent_bytes);
406  if (0 != sent_bytes)
407  return (ssize_t)sent_bytes;
408 
409  return MHD_ERR_AGAIN_;
410  }
411  /* Some unrecoverable error. Possibly file FD is not suitable
412  * for sendfile(). Retry with standard send(). */
413  connection->resp_sender = MHD_resp_sender_std;
414  return MHD_ERR_AGAIN_;
415  }
416  mhd_assert (0 < sent_bytes);
417  mhd_assert (SSIZE_MAX >= sent_bytes);
418  ret = (ssize_t)sent_bytes;
419 #elif defined(HAVE_DARWIN_SENDFILE)
420  len = (off_t)send_size; /* chunk always fit */
421  if (0 != sendfile (file_fd,
422  connection->socket_fd,
423  (off_t) offsetu64,
424  &len,
425  NULL,
426  0))
427  {
428  const int err = MHD_socket_get_error_();
429  if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
431  {
432  mhd_assert (0 <= len);
433  mhd_assert (SSIZE_MAX >= len);
434  mhd_assert (send_size >= (size_t)len);
435  if (0 != len)
436  return (ssize_t)len;
437 
438  return MHD_ERR_AGAIN_;
439  }
440  if (ENOTCONN == err ||
441  EPIPE == err)
442  return MHD_ERR_CONNRESET_;
443  if (ENOTSUP == err ||
444  EOPNOTSUPP == err)
445  { /* This file FD is not suitable for sendfile().
446  * Retry with standard send(). */
447  connection->resp_sender = MHD_resp_sender_std;
448  return MHD_ERR_AGAIN_;
449  }
450  return MHD_ERR_BADF_; /* Return hard error. */
451  }
452  mhd_assert (0 <= len);
453  mhd_assert (SSIZE_MAX >= len);
454  mhd_assert (send_size >= (size_t)len);
455  ret = (ssize_t)len;
456 #endif /* HAVE_FREEBSD_SENDFILE */
457  return ret;
458 }
459 #endif /* _MHD_HAVE_SENDFILE */
460 
461 
481 _MHD_static_inline bool
483 {
484  (void)connection; /* Mute compiler warning. */
485 #if defined(TCP_CORK) || defined(TCP_PUSH)
486  return true;
487 #else /* !TCP_CORK && !TCP_PUSH */
488  return false;
489 #endif /* !TCP_CORK && !TCP_PUSH */
490 }
491 
492 
500 _MHD_static_inline bool
502 {
503  mhd_assert(NULL != connection);
504 #if defined(TCP_NODELAY)
505  if (connection->sk_tcp_nodelay_on)
506  {
507  const MHD_SCKT_OPT_BOOL_ off_val = 0;
508  /* Enable Nagle's algorithm */
509  /* TCP_NODELAY may interfere with TCP_NOPUSH */
510  if (0 == setsockopt (connection->socket_fd,
511  IPPROTO_TCP,
512  TCP_NODELAY,
513  (const void *) &off_val,
514  sizeof (off_val)))
515  {
516  connection->sk_tcp_nodelay_on = false;
517  }
518  }
519 #endif /* TCP_NODELAY */
520 
521 #if defined(MHD_TCP_CORK_NOPUSH)
522  if (!connection->sk_tcp_cork_nopush_on)
523  {
524  const MHD_SCKT_OPT_BOOL_ on_val = 1;
525  /* Buffer data before sending (TCP_CORK) or
526  * Send only full frames (TCP_NOPUSH) */
527  if (0 == setsockopt (connection->socket_fd,
528  IPPROTO_TCP,
529  MHD_TCP_CORK_NOPUSH,
530  (const void *) &on_val,
531  sizeof (on_val)))
532  {
533  connection->sk_tcp_cork_nopush_on = true;
534  }
535  }
536 #endif /* MHD_TCP_CORK_NOPUSH */
537 
538 #if defined(TCP_NODELAY)
539  return connection->sk_tcp_cork_nopush_on && !connection->sk_tcp_nodelay_on;
540 #else /* ! TCP_NODELAY */
541  return connection->sk_tcp_cork_nopush_on;
542 #endif /* ! TCP_NODELAY */
543 }
544 
545 
552 _MHD_static_inline bool
554 {
555 #if defined(MHD_TCP_CORK_NOPUSH)
556  if (connection->sk_tcp_cork_nopush_on)
557  {
558  const MHD_SCKT_OPT_BOOL_ off_val = 0;
559  /* Disable extra buffering */
560  if (0 == setsockopt (connection->socket_fd,
561  IPPROTO_TCP,
562  MHD_TCP_CORK_NOPUSH,
563  (const void *) &off_val,
564  sizeof (off_val)))
565  {
566  connection->sk_tcp_cork_nopush_on = false;
567  }
568  }
569 #endif /* MHD_TCP_CORK_NOPUSH */
570 
571 #if defined(TCP_NODELAY)
572  if (!connection->sk_tcp_nodelay_on)
573  {
574  const MHD_SCKT_OPT_BOOL_ on_val = 1;
575  /* Enable sending without delay */
576  if (0 == setsockopt (connection->socket_fd,
577  IPPROTO_TCP,
578  TCP_NODELAY,
579  (const void *) &on_val,
580  sizeof (on_val)))
581  {
582  connection->sk_tcp_nodelay_on = true;
583  }
584  }
585 #endif /* TCP_NODELAY */
586  return connection->sk_tcp_nodelay_on && !connection->sk_tcp_cork_nopush_on;
587 }
588 
589 
597 _MHD_static_inline bool
599 {
600  bool res;
601 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
602  const int dummy = 0;
603 #endif /* !TCP_CORK */
604 #if defined(TCP_CORK) || (defined(__FreeBSD__) && __FreeBSD__+0 >= 9)
605  const MHD_SCKT_OPT_BOOL_ off_val = 0;
606  /* Switching off TCP_CORK flush buffer even
607  * if TCP_CORK was not enabled */
608  if (0 == setsockopt (connection->socket_fd,
609  IPPROTO_TCP,
610  MHD_TCP_CORK_NOPUSH,
611  (const void *) &off_val,
612  sizeof (off_val)))
613  {
614  connection->sk_tcp_cork_nopush_on = false;
615  }
616 #endif /* MHD_TCP_CORK_NOPUSH */
617 
618  res = socket_start_no_buffering (connection);
619 #if defined(__FreeBSD__) && __FreeBSD__+0 >= 9
620  /* FreeBSD do not need zero-send for flushing starting from version 9 */
621 #elif defined(TCP_NOPUSH) && !defined(TCP_CORK)
622  /* Force flush data with zero send otherwise Darwin and some BSD systems
623  will add 5 seconds delay. Not required with TCP_CORK as switching off
624  TCP_CORK always flushes socket buffer. */
625  res = (0 <= MHD_send_ (connection->socket_fd,
626  &dummy,
627  0)) && res;
628 #endif /* TCP_NOPUSH && !TCP_CORK*/
629  return res;
630 }
631 
632 
639 _MHD_static_inline bool
641 {
642  mhd_assert(NULL != connection);
643 #if defined(MHD_TCP_CORK_NOPUSH)
644  if (connection->sk_tcp_cork_nopush_on)
645  {
646  const MHD_SCKT_OPT_BOOL_ off_val = 0;
647  /* Disable extra buffering */
648  if (0 == setsockopt (connection->socket_fd,
649  IPPROTO_TCP,
650  MHD_TCP_CORK_NOPUSH,
651  (const void *) &off_val,
652  sizeof (off_val)))
653  {
654  connection->sk_tcp_cork_nopush_on = false;
655  }
656  }
657 #endif /* MHD_TCP_CORK_NOPUSH */
658 
659 #if defined(TCP_NODELAY)
660  if (connection->sk_tcp_nodelay_on)
661  {
662  const MHD_SCKT_OPT_BOOL_ off_val = 0;
663  /* Enable Nagle's algorithm */
664  if (0 == setsockopt (connection->socket_fd,
665  IPPROTO_TCP,
666  TCP_NODELAY,
667  (const void *) &off_val,
668  sizeof (off_val)))
669  {
670  connection->sk_tcp_nodelay_on = false;
671  }
672  }
673 #endif /* TCP_NODELAY */
674  return !connection->sk_tcp_nodelay_on && !connection->sk_tcp_cork_nopush_on;
675 }
676 
677 
689 int
691  enum MHD_ValueKind kind,
692  MHD_KeyValueIterator iterator,
693  void *iterator_cls)
694 {
695  int ret;
696  struct MHD_HTTP_Header *pos;
697 
698  if (NULL == connection)
699  return -1;
700  ret = 0;
701  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
702  if (0 != (pos->kind & kind))
703  {
704  ret++;
705  if ( (NULL != iterator) &&
706  (MHD_YES != iterator (iterator_cls,
707  pos->kind,
708  pos->header,
709  pos->value)) )
710  return ret;
711  }
712  return ret;
713 }
714 
715 
741 int
743  enum MHD_ValueKind kind,
744  const char *key,
745  const char *value)
746 {
747  struct MHD_HTTP_Header *pos;
748 
749  pos = MHD_pool_allocate (connection->pool,
750  sizeof (struct MHD_HTTP_Header),
751  MHD_YES);
752  if (NULL == pos)
753  return MHD_NO;
754  pos->header = (char *) key;
755  pos->value = (char *) value;
756  pos->kind = kind;
757  pos->next = NULL;
758  /* append 'pos' to the linked list of headers */
759  if (NULL == connection->headers_received_tail)
760  {
761  connection->headers_received = pos;
762  connection->headers_received_tail = pos;
763  }
764  else
765  {
766  connection->headers_received_tail->next = pos;
767  connection->headers_received_tail = pos;
768  }
769  return MHD_YES;
770 }
771 
772 
783 const char *
785  enum MHD_ValueKind kind,
786  const char *key)
787 {
788  struct MHD_HTTP_Header *pos;
789 
790  if (NULL == connection)
791  return NULL;
792  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
793  if ((0 != (pos->kind & kind)) &&
794  ( (key == pos->header) ||
795  ( (NULL != pos->header) &&
796  (NULL != key) &&
798  pos->header)))))
799  return pos->value;
800  return NULL;
801 }
802 
803 
817 static bool
818 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
819  const char *header,
820  const char *token,
821  size_t token_len)
822 {
823  struct MHD_HTTP_Header *pos;
824 
825  if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0])
826  return false;
827  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
828  {
829  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
830  ( (header == pos->header) ||
832  pos->header)) ) &&
833  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
834  return true;
835  }
836  return false;
837 }
838 
839 
851 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
852  MHD_lookup_header_token_ci((c),(h),(tkn),MHD_STATICSTR_LEN_(tkn))
853 
854 
862 static int
863 need_100_continue (struct MHD_Connection *connection)
864 {
865  const char *expect;
866 
867  return ( (NULL == connection->response) &&
868  (NULL != connection->version) &&
869  (MHD_str_equal_caseless_(connection->version,
871  (NULL != (expect = MHD_lookup_connection_value (connection,
874  (MHD_str_equal_caseless_(expect,
875  "100-continue")) &&
876  (connection->continue_message_write_offset <
878 }
879 
880 
887 void
889 {
890  const struct MHD_Daemon *daemon = connection->daemon;
891 
892  connection->state = MHD_CONNECTION_CLOSED;
894  if (0 == (daemon->options & MHD_USE_TURBO))
895  {
896 #ifdef HTTPS_SUPPORT
897  /* For TLS connection use shutdown of TLS layer
898  * and do not shutdown TCP socket. This give more
899  * chances to send TLS closure data to remote side.
900  * Closure of TLS layer will be interpreted by
901  * remote side as end of transmission. */
902  if (0 != (daemon->options & MHD_USE_TLS))
903  {
904  if (! MHD_tls_connection_shutdown(connection))
905  shutdown (connection->socket_fd,
906  SHUT_WR);
907  }
908  else /* Combined with next 'shutdown()'. */
909 #endif /* HTTPS_SUPPORT */
910  shutdown (connection->socket_fd,
911  SHUT_WR);
912  }
913 }
914 
915 
925 void
927  enum MHD_RequestTerminationCode termination_code)
928 {
929  struct MHD_Daemon *daemon = connection->daemon;
930  struct MHD_Response *resp = connection->response;
931 
932  MHD_connection_mark_closed_ (connection);
933  if (NULL != resp)
934  {
935  connection->response = NULL;
936  MHD_destroy_response (resp);
937  }
938  if ( (NULL != daemon->notify_completed) &&
939  (connection->client_aware) )
940  daemon->notify_completed (daemon->notify_completed_cls,
941  connection,
942  &connection->client_context,
943  termination_code);
944  connection->client_aware = false;
945 }
946 
947 
948 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
949 
959 void
961 {
962  struct MHD_Daemon *daemon = connection->daemon;
963  struct MHD_UpgradeResponseHandle *urh = connection->urh;
964 
965  if (0 == (daemon->options & MHD_USE_TLS))
966  return; /* Nothing to do with non-TLS connection. */
967 
968  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
969  DLL_remove (daemon->urh_head,
970  daemon->urh_tail,
971  urh);
972 #if EPOLL_SUPPORT
973  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
974  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
975  EPOLL_CTL_DEL,
976  connection->socket_fd,
977  NULL)) )
978  {
979  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
980  }
981  if (urh->in_eready_list)
982  {
983  EDLL_remove (daemon->eready_urh_head,
984  daemon->eready_urh_tail,
985  urh);
986  urh->in_eready_list = false;
987  }
988 #endif /* EPOLL_SUPPORT */
989  if (MHD_INVALID_SOCKET != urh->mhd.socket)
990  {
991 #if EPOLL_SUPPORT
992  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
993  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
994  EPOLL_CTL_DEL,
995  urh->mhd.socket,
996  NULL)) )
997  {
998  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
999  }
1000 #endif /* EPOLL_SUPPORT */
1001  /* Reflect remote disconnect to application by breaking
1002  * socketpair connection. */
1003  shutdown (urh->mhd.socket, SHUT_RDWR);
1004  }
1005  /* Socketpair sockets will remain open as they will be
1006  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
1007  * closed by MHD_cleanup_upgraded_connection_() during
1008  * connection's final cleanup.
1009  */
1010 }
1011 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
1012 
1013 
1021 static void
1023  const char *emsg)
1024 {
1025 #ifdef HAVE_MESSAGES
1026  if (NULL != emsg)
1027  MHD_DLOG (connection->daemon,
1028  emsg);
1029 #else /* ! HAVE_MESSAGES */
1030  (void)emsg; /* Mute compiler warning. */
1031 #endif /* ! HAVE_MESSAGES */
1032  MHD_connection_close_ (connection,
1034 }
1035 
1036 
1041 #ifdef HAVE_MESSAGES
1042 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
1043 #else
1044 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
1045 #endif
1046 
1047 
1060 static int
1062 {
1063  ssize_t ret;
1064  struct MHD_Response *response;
1065 
1066  response = connection->response;
1067  if (NULL == response->crc)
1068  return MHD_YES;
1069  if ( (0 == response->total_size) ||
1070  (connection->response_write_position == response->total_size) )
1071  return MHD_YES; /* 0-byte response is always ready */
1072  if ( (response->data_start <=
1073  connection->response_write_position) &&
1074  (response->data_size + response->data_start >
1075  connection->response_write_position) )
1076  return MHD_YES; /* response already ready */
1077 #if defined(_MHD_HAVE_SENDFILE)
1078  if (MHD_resp_sender_sendfile == connection->resp_sender)
1079  {
1080  /* will use sendfile, no need to bother response crc */
1081  return MHD_YES;
1082  }
1083 #endif /* _MHD_HAVE_SENDFILE */
1084 
1085  ret = response->crc (response->crc_cls,
1086  connection->response_write_position,
1087  response->data,
1088  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
1089  response->total_size -
1090  connection->response_write_position));
1091  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1092  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
1093  {
1094  /* either error or http 1.0 transfer, close socket! */
1095  response->total_size = connection->response_write_position;
1096 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1097  MHD_mutex_unlock_chk_ (&response->mutex);
1098 #endif
1099  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
1100  MHD_connection_close_ (connection,
1102  else
1103  CONNECTION_CLOSE_ERROR (connection,
1104  _("Closing connection (application reported error generating data)\n"));
1105  return MHD_NO;
1106  }
1107  response->data_start = connection->response_write_position;
1108  response->data_size = ret;
1109  if (0 == ret)
1110  {
1112 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1113  MHD_mutex_unlock_chk_ (&response->mutex);
1114 #endif
1115  return MHD_NO;
1116  }
1117  return MHD_YES;
1118 }
1119 
1120 
1130 static int
1132 {
1133  ssize_t ret;
1134  char *buf;
1135  struct MHD_Response *response;
1136  size_t size;
1137  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
1138  int cblen;
1139 
1140  response = connection->response;
1141  if (NULL == response->crc)
1142  return MHD_YES;
1143  if (0 == connection->write_buffer_size)
1144  {
1145  size = MHD_MIN (connection->daemon->pool_size,
1146  2 * (0xFFFFFF + sizeof(cbuf) + 2));
1147  do
1148  {
1149  size /= 2;
1150  if (size < 128)
1151  {
1152 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1153  MHD_mutex_unlock_chk_ (&response->mutex);
1154 #endif
1155  /* not enough memory */
1156  CONNECTION_CLOSE_ERROR (connection,
1157  _("Closing connection (out of memory)\n"));
1158  return MHD_NO;
1159  }
1160  buf = MHD_pool_allocate (connection->pool,
1161  size,
1162  MHD_NO);
1163  }
1164  while (NULL == buf);
1165  connection->write_buffer_size = size;
1166  connection->write_buffer = buf;
1167  }
1168 
1169  if (0 == response->total_size)
1170  ret = 0; /* response must be empty, don't bother calling crc */
1171  else if ( (response->data_start <=
1172  connection->response_write_position) &&
1173  (response->data_start + response->data_size >
1174  connection->response_write_position) )
1175  {
1176  /* difference between response_write_position and data_start is less
1177  than data_size which is size_t type, no need to check for overflow */
1178  const size_t data_write_offset
1179  = (size_t)(connection->response_write_position - response->data_start);
1180  /* buffer already ready, use what is there for the chunk */
1181  ret = response->data_size - data_write_offset;
1182  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
1183  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1184  memcpy (&connection->write_buffer[sizeof (cbuf)],
1185  &response->data[data_write_offset],
1186  ret);
1187  }
1188  else
1189  {
1190  /* buffer not in range, try to fill it */
1191  ret = response->crc (response->crc_cls,
1192  connection->response_write_position,
1193  &connection->write_buffer[sizeof (cbuf)],
1194  connection->write_buffer_size - sizeof (cbuf) - 2);
1195  }
1196  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1197  {
1198  /* error, close socket! */
1199  response->total_size = connection->response_write_position;
1200 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1201  MHD_mutex_unlock_chk_ (&response->mutex);
1202 #endif
1203  CONNECTION_CLOSE_ERROR (connection,
1204  _("Closing connection (application error generating response)\n"));
1205  return MHD_NO;
1206  }
1207  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1208  (0 == response->total_size) )
1209  {
1210  /* end of message, signal other side! */
1211  memcpy (connection->write_buffer,
1212  "0\r\n",
1213  3);
1214  connection->write_buffer_append_offset = 3;
1215  connection->write_buffer_send_offset = 0;
1216  response->total_size = connection->response_write_position;
1217  return MHD_YES;
1218  }
1219  if (0 == ret)
1220  {
1222 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1223  MHD_mutex_unlock_chk_ (&response->mutex);
1224 #endif
1225  return MHD_NO;
1226  }
1227  if (ret > 0xFFFFFF)
1228  ret = 0xFFFFFF;
1229  cblen = MHD_snprintf_(cbuf,
1230  sizeof (cbuf),
1231  "%X\r\n",
1232  (unsigned int) ret);
1233  mhd_assert(cblen > 0);
1234  mhd_assert((size_t)cblen < sizeof(cbuf));
1235  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1236  cbuf,
1237  cblen);
1238  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1239  "\r\n",
1240  2);
1241  connection->response_write_position += ret;
1242  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1243  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1244  return MHD_YES;
1245 }
1246 
1247 
1264 static int
1266 {
1267  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1268  return MHD_NO;
1269  if (NULL == connection->version)
1270  return MHD_NO;
1271  if ( (NULL != connection->response) &&
1272  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1273  return MHD_NO;
1274 
1275  if (MHD_str_equal_caseless_(connection->version,
1277  ( (NULL == connection->response) ||
1278  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE) ) ) )
1279  {
1280  if (MHD_lookup_header_s_token_ci (connection,
1282  "upgrade"))
1283  return MHD_NO;
1284 
1285  if (MHD_lookup_header_s_token_ci (connection,
1287  "close"))
1288  return MHD_NO;
1289 
1290  return MHD_YES;
1291  }
1292  if (MHD_str_equal_caseless_(connection->version,
1294  {
1295  if (MHD_lookup_header_s_token_ci (connection,
1297  "Keep-Alive"))
1298  return MHD_YES;
1299 
1300  return MHD_NO;
1301  }
1302  return MHD_NO;
1303 }
1304 
1305 
1313 static void
1314 get_date_string (char *date,
1315  size_t date_len)
1316 {
1317  static const char *const days[] = {
1318  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1319  };
1320  static const char *const mons[] = {
1321  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1322  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1323  };
1324  struct tm now;
1325  time_t t;
1326 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
1327  struct tm* pNow;
1328 #endif
1329 
1330  date[0] = 0;
1331  time (&t);
1332 #if defined(HAVE_C11_GMTIME_S)
1333  if (NULL == gmtime_s (&t,
1334  &now))
1335  return;
1336 #elif defined(HAVE_W32_GMTIME_S)
1337  if (0 != gmtime_s (&now,
1338  &t))
1339  return;
1340 #elif defined(HAVE_GMTIME_R)
1341  if (NULL == gmtime_r(&t,
1342  &now))
1343  return;
1344 #else
1345  pNow = gmtime(&t);
1346  if (NULL == pNow)
1347  return;
1348  now = *pNow;
1349 #endif
1350  MHD_snprintf_ (date,
1351  date_len,
1352  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1353  days[now.tm_wday % 7],
1354  (unsigned int) now.tm_mday,
1355  mons[now.tm_mon % 12],
1356  (unsigned int) (1900 + now.tm_year),
1357  (unsigned int) now.tm_hour,
1358  (unsigned int) now.tm_min,
1359  (unsigned int) now.tm_sec);
1360 }
1361 
1362 
1373 static int
1375 {
1376  void *buf;
1377  size_t new_size;
1378 
1379  if (0 == connection->read_buffer_size)
1380  new_size = connection->daemon->pool_size / 2;
1381  else
1382  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
1383  buf = MHD_pool_reallocate (connection->pool,
1384  connection->read_buffer,
1385  connection->read_buffer_size,
1386  new_size);
1387  if (NULL == buf)
1388  return MHD_NO;
1389  /* we can actually grow the buffer, do it! */
1390  connection->read_buffer = buf;
1391  connection->read_buffer_size = new_size;
1392  return MHD_YES;
1393 }
1394 
1395 
1405 static int
1407 {
1408  struct MHD_Response *response = connection->response;
1409  size_t size;
1410  size_t off;
1411  struct MHD_HTTP_Header *pos;
1412  char code[256];
1413  char date[128];
1414  size_t datelen;
1415  char content_length_buf[128];
1416  size_t content_length_len;
1417  char *data;
1418  enum MHD_ValueKind kind;
1419  const char *reason_phrase;
1420  uint32_t rc;
1421  bool client_requested_close;
1422  bool response_has_close;
1423  bool response_has_keepalive;
1424  const char *have_encoding;
1425  int must_add_close;
1426  int must_add_chunked_encoding;
1427  int must_add_keep_alive;
1428  int must_add_content_length;
1429  int may_add_content_length;
1430 
1431  mhd_assert (NULL != connection->version);
1432  if (0 == connection->version[0])
1433  {
1434  data = MHD_pool_allocate (connection->pool,
1435  0,
1436  MHD_YES);
1437  connection->write_buffer = data;
1438  connection->write_buffer_append_offset = 0;
1439  connection->write_buffer_send_offset = 0;
1440  connection->write_buffer_size = 0;
1441  return MHD_YES;
1442  }
1443  rc = connection->responseCode & (~MHD_ICY_FLAG);
1444  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1445  {
1446  reason_phrase = MHD_get_reason_phrase_for (rc);
1447  MHD_snprintf_ (code,
1448  sizeof (code),
1449  "%s %u %s\r\n",
1450  (0 != (connection->responseCode & MHD_ICY_FLAG))
1451  ? "ICY"
1453  connection->version) ||
1454  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE)) )
1457  rc,
1458  reason_phrase);
1459  off = strlen (code);
1460  /* estimate size */
1461  size = off + 2; /* +2 for extra "\r\n" at the end */
1463  if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1464  (NULL == MHD_get_response_header (response,
1466  get_date_string (date,
1467  sizeof (date));
1468  else
1469  date[0] = '\0';
1470  datelen = strlen (date);
1471  size += datelen;
1472  }
1473  else
1474  {
1475  /* 2 bytes for final CRLF of a Chunked-Body */
1476  size = 2;
1478  off = 0;
1479  datelen = 0;
1480  }
1481 
1482  /* calculate extra headers we need to add, such as 'Connection: close',
1483  first see what was explicitly requested by the application */
1484  must_add_close = MHD_NO;
1485  must_add_chunked_encoding = MHD_NO;
1486  must_add_keep_alive = MHD_NO;
1487  must_add_content_length = MHD_NO;
1488  response_has_close = false;
1489  switch (connection->state)
1490  {
1492  response_has_close = MHD_check_response_header_s_token_ci (response,
1494  "close");
1495  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1497  "Keep-Alive");
1498  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1500  "close");
1501 
1502  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1503  connection->keepalive = MHD_CONN_MUST_CLOSE;
1504 #ifdef UPGRADE_SUPPORT
1505  else if (NULL != response->upgrade_handler)
1506  /* If this connection will not be "upgraded", it must be closed. */
1507  connection->keepalive = MHD_CONN_MUST_CLOSE;
1508 #endif /* UPGRADE_SUPPORT */
1509 
1510  /* now analyze chunked encoding situation */
1511  connection->have_chunked_upload = false;
1512  have_encoding = MHD_get_response_header (response,
1514  if (NULL == have_encoding)
1515  may_add_content_length = MHD_YES;
1516  else
1517  may_add_content_length = MHD_NO; /* RFC 7230, Section 3.3.2 forbids header */
1518  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1519 #ifdef UPGRADE_SUPPORT
1520  (NULL == response->upgrade_handler) &&
1521 #endif /* UPGRADE_SUPPORT */
1522  (! response_has_close) &&
1523  (! client_requested_close) )
1524  {
1525  /* size is unknown, and close was not explicitly requested;
1526  need to either to HTTP 1.1 chunked encoding or
1527  close the connection */
1528  /* 'close' header doesn't exist yet, see if we need to add one;
1529  if the client asked for a close, no need to start chunk'ing */
1530  if ( (MHD_YES == keepalive_possible (connection)) &&
1532  connection->version) ) )
1533  {
1534  if (NULL == have_encoding)
1535  {
1536  must_add_chunked_encoding = MHD_YES;
1537  connection->have_chunked_upload = true;
1538  }
1539  else
1540  {
1541  if (MHD_str_equal_caseless_ (have_encoding,
1542  "identity"))
1543  {
1544  /* application forced identity encoding, can't do 'chunked' */
1545  must_add_close = MHD_YES;
1546  }
1547  else
1548  {
1549  connection->have_chunked_upload = true;
1550  }
1551  }
1552  }
1553  else
1554  {
1555  /* Keep alive or chunking not possible
1556  => set close header if not present */
1557  if (! response_has_close)
1558  must_add_close = MHD_YES;
1559  }
1560  }
1561 
1562  /* check for other reasons to add 'close' header */
1563  if ( ( (client_requested_close) ||
1564  (connection->read_closed) ||
1565  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1566  (! response_has_close) &&
1567 #ifdef UPGRADE_SUPPORT
1568  (NULL == response->upgrade_handler) &&
1569 #endif /* UPGRADE_SUPPORT */
1570  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1571  must_add_close = MHD_YES;
1572 
1573  /* check if we must add 'close' header because we cannot add content-length
1574  because it is forbidden AND we don't have a 'chunked' encoding */
1575  if ( (! may_add_content_length) &&
1576  (! connection->have_chunked_upload) &&
1577  (! response_has_close) )
1578  must_add_close = MHD_YES;
1579  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1580  codes SHOULD NOT have a Content-Length according to spec;
1581  also chunked encoding / unknown length or CONNECT... */
1582  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1583  (MHD_HTTP_NO_CONTENT != rc) &&
1584  (MHD_HTTP_NOT_MODIFIED != rc) &&
1585  (MHD_HTTP_OK <= rc) &&
1586  (NULL == /* this should always succeed due to check in
1587  MHD_add_response_header() */
1588  MHD_get_response_header (response,
1590  (may_add_content_length) &&
1591  ( (NULL == connection->method) ||
1592  (! MHD_str_equal_caseless_ (connection->method,
1594  {
1595  /*
1596  Here we add a content-length if one is missing; however,
1597  for 'connect' methods, the responses MUST NOT include a
1598  content-length header *if* the response code is 2xx (in
1599  which case we expect there to be no body). Still,
1600  as we don't know the response code here in some cases, we
1601  simply only force adding a content-length header if this
1602  is not a 'connect' or if the response is not empty
1603  (which is kind of more sane, because if some crazy
1604  application did return content with a 2xx status code,
1605  then having a content-length might again be a good idea).
1606 
1607  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1608  a recent development of the HTTP 1.1 specification.
1609  */
1610  content_length_len
1611  = MHD_snprintf_ (content_length_buf,
1612  sizeof (content_length_buf),
1614  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1615  must_add_content_length = MHD_YES;
1616  }
1617 
1618  /* check for adding keep alive */
1619  if ( (! response_has_keepalive) &&
1620  (! response_has_close) &&
1621  (MHD_NO == must_add_close) &&
1622  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1623 #ifdef UPGRADE_SUPPORT
1624  (NULL == response->upgrade_handler) &&
1625 #endif /* UPGRADE_SUPPORT */
1626  (MHD_YES == keepalive_possible (connection)) )
1627  must_add_keep_alive = MHD_YES;
1628  break;
1630  response_has_keepalive = false;
1631  break;
1632  default:
1633  mhd_assert (0);
1634  return MHD_NO;
1635  }
1636 
1637  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1638  {
1639  if ( (must_add_close) || (response_has_close) )
1640  connection->keepalive = MHD_CONN_MUST_CLOSE;
1641  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1642  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1643  }
1644 
1645  if (must_add_close)
1646  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1647  if (must_add_keep_alive)
1648  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1649  if (must_add_chunked_encoding)
1650  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1651  if (must_add_content_length)
1652  size += content_length_len;
1653  mhd_assert (! (must_add_close && must_add_keep_alive) );
1654  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1655 
1656  for (pos = response->first_header; NULL != pos; pos = pos->next)
1657  {
1658  /* TODO: add proper support for excluding "Keep-Alive" token. */
1659  if ( (pos->kind == kind) &&
1660  (! ( (MHD_YES == must_add_close) &&
1661  (response_has_keepalive) &&
1665  "Keep-Alive")) ) ) )
1666  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1667  }
1668  /* produce data */
1669  data = MHD_pool_allocate (connection->pool,
1670  size + 1,
1671  MHD_NO);
1672  if (NULL == data)
1673  {
1674 #ifdef HAVE_MESSAGES
1675  MHD_DLOG (connection->daemon,
1676  "Not enough memory for write!\n");
1677 #endif
1678  return MHD_NO;
1679  }
1680  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1681  {
1682  memcpy (data,
1683  code,
1684  off);
1685  }
1686  if (must_add_close)
1687  {
1688  /* we must add the 'Connection: close' header */
1689  memcpy (&data[off],
1690  "Connection: close\r\n",
1691  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1692  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1693  }
1694  if (must_add_keep_alive)
1695  {
1696  /* we must add the 'Connection: Keep-Alive' header */
1697  memcpy (&data[off],
1698  "Connection: Keep-Alive\r\n",
1699  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1700  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1701  }
1702  if (must_add_chunked_encoding)
1703  {
1704  /* we must add the 'Transfer-Encoding: chunked' header */
1705  memcpy (&data[off],
1706  "Transfer-Encoding: chunked\r\n",
1707  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1708  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1709  }
1710  if (must_add_content_length)
1711  {
1712  /* we must add the 'Content-Length' header */
1713  memcpy (&data[off],
1714  content_length_buf,
1715  content_length_len);
1716  off += content_length_len;
1717  }
1718  for (pos = response->first_header; NULL != pos; pos = pos->next)
1719  {
1720  /* TODO: add proper support for excluding "Keep-Alive" token. */
1721  if ( (pos->kind == kind) &&
1722  (! ( (MHD_YES == must_add_close) &&
1723  (response_has_keepalive) &&
1727  "Keep-Alive")) ) ) )
1728  off += MHD_snprintf_ (&data[off],
1729  size - off,
1730  "%s: %s\r\n",
1731  pos->header,
1732  pos->value);
1733  }
1734  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1735  {
1736  memcpy (&data[off],
1737  date,
1738  datelen);
1739  off += datelen;
1740  }
1741  memcpy (&data[off],
1742  "\r\n",
1743  2);
1744  off += 2;
1745 
1746  if (off != size)
1748  __FILE__,
1749  __LINE__,
1750  NULL);
1751  connection->write_buffer = data;
1752  connection->write_buffer_append_offset = size;
1753  connection->write_buffer_send_offset = 0;
1754  connection->write_buffer_size = size + 1;
1755  return MHD_YES;
1756 }
1757 
1758 
1768 static void
1770  unsigned int status_code,
1771  const char *message)
1772 {
1773  struct MHD_Response *response;
1774  int iret;
1775 
1776  if (NULL == connection->version)
1777  {
1778  /* we were unable to process the full header line, so we don't
1779  really know what version the client speaks; assume 1.0 */
1780  connection->version = MHD_HTTP_VERSION_1_0;
1781  }
1782  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1783  connection->read_closed = true;
1784 #ifdef HAVE_MESSAGES
1785  MHD_DLOG (connection->daemon,
1786  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1787  status_code,
1788  message);
1789 #endif
1790  if (NULL != connection->response)
1791  {
1792  MHD_destroy_response (connection->response);
1793  connection->response = NULL;
1794  }
1795  response = MHD_create_response_from_buffer (strlen (message),
1796  (void *) message,
1798  if (NULL == response)
1799  {
1800  /* can't even send a reply, at least close the connection */
1801  connection->state = MHD_CONNECTION_CLOSED;
1802  return;
1803  }
1804  iret = MHD_queue_response (connection,
1805  status_code,
1806  response);
1807  MHD_destroy_response (response);
1808  if (MHD_YES != iret)
1809  {
1810  /* can't even send a reply, at least close the connection */
1811  CONNECTION_CLOSE_ERROR (connection,
1812  _("Closing connection (failed to queue response)\n"));
1813  return;
1814  }
1815  mhd_assert (NULL != connection->response);
1816  /* Do not reuse this connection. */
1817  connection->keepalive = MHD_CONN_MUST_CLOSE;
1818  if (MHD_NO == build_header_response (connection))
1819  {
1820  /* oops - close! */
1821  CONNECTION_CLOSE_ERROR (connection,
1822  _("Closing connection (failed to create response header)\n"));
1823  }
1824  else
1825  {
1826  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1827  }
1828 }
1829 
1830 
1839 static void
1841 {
1842  /* Do not update states of suspended connection */
1843  if (connection->suspended)
1844  return; /* States will be updated after resume. */
1845 #ifdef HTTPS_SUPPORT
1846  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1847  { /* HTTPS connection. */
1848  switch (connection->tls_state)
1849  {
1850  case MHD_TLS_CONN_INIT:
1852  return;
1854  if (0 == gnutls_record_get_direction (connection->tls_session))
1856  else
1858  return;
1859  default:
1860  break;
1861  }
1862  }
1863 #endif /* HTTPS_SUPPORT */
1864  while (1)
1865  {
1866 #if DEBUG_STATES
1867  MHD_DLOG (connection->daemon,
1868  _("In function %s handling connection at state: %s\n"),
1869  __FUNCTION__,
1870  MHD_state_to_string (connection->state));
1871 #endif
1872  switch (connection->state)
1873  {
1874  case MHD_CONNECTION_INIT:
1877  /* while reading headers, we always grow the
1878  read buffer if needed, no size-check required */
1879  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1880  (MHD_NO == try_grow_read_buffer (connection)) )
1881  {
1882  transmit_error_response (connection,
1883  (connection->url != NULL)
1886  REQUEST_TOO_BIG);
1887  continue;
1888  }
1889  if (! connection->read_closed)
1891  else
1893  break;
1895  mhd_assert (0);
1896  break;
1898  mhd_assert (0);
1899  break;
1902  break;
1904  if (connection->read_buffer_offset == connection->read_buffer_size)
1905  {
1906  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1907  (0 != (connection->daemon->options &
1909  {
1910  /* failed to grow the read buffer, and the
1911  client which is supposed to handle the
1912  received data in a *blocking* fashion
1913  (in this mode) did not handle the data as
1914  it was supposed to!
1915  => we would either have to do busy-waiting
1916  (on the client, which would likely fail),
1917  or if we do nothing, we would just timeout
1918  on the connection (if a timeout is even
1919  set!).
1920  Solution: we kill the connection with an error */
1921  transmit_error_response (connection,
1923  INTERNAL_ERROR);
1924  continue;
1925  }
1926  }
1927  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1928  (! connection->read_closed) )
1930  else
1932  break;
1935  /* while reading footers, we always grow the
1936  read buffer if needed, no size-check required */
1937  if (connection->read_closed)
1938  {
1939  CONNECTION_CLOSE_ERROR (connection,
1940  NULL);
1941  continue;
1942  }
1944  /* transition to FOOTERS_RECEIVED
1945  happens in read handler */
1946  break;
1949  break;
1951  /* headers in buffer, keep writing */
1953  break;
1955  mhd_assert (0);
1956  break;
1959  break;
1962  break;
1965  break;
1968  break;
1970  mhd_assert (0);
1971  break;
1974  break;
1976  mhd_assert (0);
1977  break;
1978  case MHD_CONNECTION_CLOSED:
1980  return; /* do nothing, not even reading */
1981 #ifdef UPGRADE_SUPPORT
1982  case MHD_CONNECTION_UPGRADE:
1983  mhd_assert (0);
1984  break;
1985 #endif /* UPGRADE_SUPPORT */
1986  default:
1987  mhd_assert (0);
1988  }
1989  break;
1990  }
1991 }
1992 
1993 
2007 static char *
2009  size_t *line_len)
2010 {
2011  char *rbuf;
2012  size_t pos;
2013 
2014  if (0 == connection->read_buffer_offset)
2015  return NULL;
2016  pos = 0;
2017  rbuf = connection->read_buffer;
2018  while ( (pos < connection->read_buffer_offset - 1) &&
2019  ('\r' != rbuf[pos]) &&
2020  ('\n' != rbuf[pos]) )
2021  pos++;
2022  if ( (pos == connection->read_buffer_offset - 1) &&
2023  ('\n' != rbuf[pos]) )
2024  {
2025  /* not found, consider growing... */
2026  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
2027  (MHD_NO ==
2028  try_grow_read_buffer (connection)) )
2029  {
2030  transmit_error_response (connection,
2031  (NULL != connection->url)
2034  REQUEST_TOO_BIG);
2035  }
2036  if (line_len)
2037  *line_len = 0;
2038  return NULL;
2039  }
2040 
2041  if (line_len)
2042  *line_len = pos;
2043  /* found, check if we have proper LFCR */
2044  if ( ('\r' == rbuf[pos]) &&
2045  ('\n' == rbuf[pos + 1]) )
2046  rbuf[pos++] = '\0'; /* skip both r and n */
2047  rbuf[pos++] = '\0';
2048  connection->read_buffer += pos;
2049  connection->read_buffer_size -= pos;
2050  connection->read_buffer_offset -= pos;
2051  return rbuf;
2052 }
2053 
2054 
2066 static int
2068  const char *key,
2069  const char *value,
2070  enum MHD_ValueKind kind)
2071 {
2072  if (MHD_NO ==
2073  MHD_set_connection_value (connection,
2074  kind,
2075  key,
2076  value))
2077  {
2078 #ifdef HAVE_MESSAGES
2079  MHD_DLOG (connection->daemon,
2080  _("Not enough memory in pool to allocate header record!\n"));
2081 #endif
2082  transmit_error_response (connection,
2084  REQUEST_TOO_BIG);
2085  return MHD_NO;
2086  }
2087  return MHD_YES;
2088 }
2089 
2090 
2097 static int
2099 {
2100  const char *hdr;
2101  char *cpy;
2102  char *pos;
2103  char *sce;
2104  char *semicolon;
2105  char *equals;
2106  char *ekill;
2107  char old;
2108  int quotes;
2109 
2110  hdr = MHD_lookup_connection_value (connection,
2113  if (NULL == hdr)
2114  return MHD_YES;
2115  cpy = MHD_pool_allocate (connection->pool,
2116  strlen (hdr) + 1,
2117  MHD_YES);
2118  if (NULL == cpy)
2119  {
2120 #ifdef HAVE_MESSAGES
2121  MHD_DLOG (connection->daemon,
2122  _("Not enough memory in pool to parse cookies!\n"));
2123 #endif
2124  transmit_error_response (connection,
2126  REQUEST_TOO_BIG);
2127  return MHD_NO;
2128  }
2129  memcpy (cpy,
2130  hdr,
2131  strlen (hdr) + 1);
2132  pos = cpy;
2133  while (NULL != pos)
2134  {
2135  while (' ' == *pos)
2136  pos++; /* skip spaces */
2137 
2138  sce = pos;
2139  while ( ((*sce) != '\0') &&
2140  ((*sce) != ',') &&
2141  ((*sce) != ';') &&
2142  ((*sce) != '=') )
2143  sce++;
2144  /* remove tailing whitespace (if any) from key */
2145  ekill = sce - 1;
2146  while ( (*ekill == ' ') &&
2147  (ekill >= pos) )
2148  *(ekill--) = '\0';
2149  old = *sce;
2150  *sce = '\0';
2151  if (old != '=')
2152  {
2153  /* value part omitted, use empty string... */
2154  if (MHD_NO ==
2155  connection_add_header (connection,
2156  pos,
2157  "",
2158  MHD_COOKIE_KIND))
2159  return MHD_NO;
2160  if (old == '\0')
2161  break;
2162  pos = sce + 1;
2163  continue;
2164  }
2165  equals = sce + 1;
2166  quotes = 0;
2167  semicolon = equals;
2168  while ( ('\0' != semicolon[0]) &&
2169  ( (0 != quotes) ||
2170  ( (';' != semicolon[0]) &&
2171  (',' != semicolon[0]) ) ) )
2172  {
2173  if ('"' == semicolon[0])
2174  quotes = (quotes + 1) & 1;
2175  semicolon++;
2176  }
2177  if ('\0' == semicolon[0])
2178  semicolon = NULL;
2179  if (NULL != semicolon)
2180  {
2181  semicolon[0] = '\0';
2182  semicolon++;
2183  }
2184  /* remove quotes */
2185  if ( ('"' == equals[0]) &&
2186  ('"' == equals[strlen (equals) - 1]) )
2187  {
2188  equals[strlen (equals) - 1] = '\0';
2189  equals++;
2190  }
2191  if (MHD_NO ==
2192  connection_add_header (connection,
2193  pos,
2194  equals,
2195  MHD_COOKIE_KIND))
2196  return MHD_NO;
2197  pos = semicolon;
2198  }
2199  return MHD_YES;
2200 }
2201 
2202 
2211 static int
2213  char *line,
2214  size_t line_len)
2215 {
2216  struct MHD_Daemon *daemon = connection->daemon;
2217  const char *curi;
2218  char *uri;
2219  char *http_version;
2220  char *args;
2221  unsigned int unused_num_headers;
2222  size_t uri_len;
2223 
2224  if (NULL == (uri = memchr (line,
2225  ' ',
2226  line_len)))
2227  return MHD_NO; /* serious error */
2228  uri[0] = '\0';
2229  connection->method = line;
2230  uri++;
2231  /* Skip any spaces. Not required by standard but allow
2232  to be more tolerant. */
2233  while ( (' ' == uri[0]) &&
2234  ( (size_t)(uri - line) < line_len) )
2235  uri++;
2236  if ((size_t)(uri - line) == line_len)
2237  {
2238  /* No URI and no http version given */
2239  curi = "";
2240  uri_len = 0;
2241  uri = NULL;
2242  connection->version = "";
2243  args = NULL;
2244  }
2245  else
2246  {
2247  curi = uri;
2248  /* Search from back to accept misformed URI with space */
2249  http_version = line + line_len - 1;
2250  /* Skip any trailing spaces */
2251  while ( (' ' == http_version[0]) &&
2252  (http_version > uri) )
2253  http_version--;
2254  /* Find first space in reverse direction */
2255  while ( (' ' != http_version[0]) &&
2256  (http_version > uri) )
2257  http_version--;
2258  if (http_version > uri)
2259  {
2260  /* http_version points to character before HTTP version string */
2261  http_version[0] = '\0';
2262  connection->version = http_version + 1;
2263  uri_len = http_version - uri;
2264  }
2265  else
2266  {
2267  connection->version = "";
2268  uri_len = line_len - (uri - line);
2269  }
2270  /* check for spaces in URI if we are "strict" */
2271  if ( (1 <= daemon->strict_for_client) &&
2272  (NULL != memchr (uri,
2273  ' ',
2274  uri_len)) )
2275  {
2276  /* space exists in URI and we are supposed to be strict, reject */
2277  return MHD_NO;
2278  }
2279 
2280  args = memchr (uri,
2281  '?',
2282  uri_len);
2283  }
2284 
2285  /* log callback before we modify URI *or* args */
2286  if (NULL != daemon->uri_log_callback)
2287  {
2288  connection->client_aware = true;
2289  connection->client_context
2290  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2291  uri,
2292  connection);
2293  }
2294 
2295  if (NULL != args)
2296  {
2297  args[0] = '\0';
2298  args++;
2299  /* note that this call clobbers 'args' */
2300  MHD_parse_arguments_ (connection,
2302  args,
2304  &unused_num_headers);
2305  }
2306 
2307  /* unescape URI *after* searching for arguments and log callback */
2308  if (NULL != uri)
2309  daemon->unescape_callback (daemon->unescape_callback_cls,
2310  connection,
2311  uri);
2312  connection->url = curi;
2313  return MHD_YES;
2314 }
2315 
2316 
2324 static void
2326 {
2327  struct MHD_Daemon *daemon = connection->daemon;
2328  size_t processed;
2329 
2330  if (NULL != connection->response)
2331  return; /* already queued a response */
2332  processed = 0;
2333  connection->client_aware = true;
2334  if (MHD_NO ==
2335  daemon->default_handler (daemon->default_handler_cls,
2336  connection,
2337  connection->url,
2338  connection->method,
2339  connection->version,
2340  NULL,
2341  &processed,
2342  &connection->client_context))
2343  {
2344  /* serious internal error, close connection */
2345  CONNECTION_CLOSE_ERROR (connection,
2346  _("Application reported internal error, closing connection.\n"));
2347  return;
2348  }
2349 }
2350 
2351 
2359 static void
2361 {
2362  struct MHD_Daemon *daemon = connection->daemon;
2363  size_t available;
2364  int instant_retry;
2365  char *buffer_head;
2366 
2367  if (NULL != connection->response)
2368  return; /* already queued a response */
2369 
2370  buffer_head = connection->read_buffer;
2371  available = connection->read_buffer_offset;
2372  do
2373  {
2374  size_t to_be_processed;
2375  size_t left_unprocessed;
2376  size_t processed_size;
2377 
2378  instant_retry = MHD_NO;
2379  if ( (connection->have_chunked_upload) &&
2380  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2381  {
2382  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
2383  (0LLU != connection->current_chunk_offset) &&
2384  (available >= 2) )
2385  {
2386  size_t i;
2387  /* skip new line at the *end* of a chunk */
2388  i = 0;
2389  if ( ('\r' == buffer_head[i]) ||
2390  ('\n' == buffer_head[i]) )
2391  i++; /* skip 1st part of line feed */
2392  if ( ('\r' == buffer_head[i]) ||
2393  ('\n' == buffer_head[i]) )
2394  i++; /* skip 2nd part of line feed */
2395  if (0 == i)
2396  {
2397  /* malformed encoding */
2398  CONNECTION_CLOSE_ERROR (connection,
2399  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2400  return;
2401  }
2402  available -= i;
2403  buffer_head += i;
2404  connection->current_chunk_offset = 0;
2405  connection->current_chunk_size = 0;
2406  }
2407  if (connection->current_chunk_offset <
2408  connection->current_chunk_size)
2409  {
2410  uint64_t cur_chunk_left;
2411  /* we are in the middle of a chunk, give
2412  as much as possible to the client (without
2413  crossing chunk boundaries) */
2414  cur_chunk_left
2415  = connection->current_chunk_size - connection->current_chunk_offset;
2416  if (cur_chunk_left > available)
2417  to_be_processed = available;
2418  else
2419  { /* cur_chunk_left <= (size_t)available */
2420  to_be_processed = (size_t)cur_chunk_left;
2421  if (available > to_be_processed)
2422  instant_retry = MHD_YES;
2423  }
2424  }
2425  else
2426  {
2427  size_t i;
2428  size_t end_size;
2429  bool malformed;
2430 
2431  /* we need to read chunk boundaries */
2432  i = 0;
2433  while (i < available)
2434  {
2435  if ( ('\r' == buffer_head[i]) ||
2436  ('\n' == buffer_head[i]) ||
2437  (';' == buffer_head[i]) )
2438  break;
2439  i++;
2440  if (i >= 16)
2441  break;
2442  }
2443  end_size = i;
2444  /* find beginning of CRLF (skip over chunk extensions) */
2445  if (';' == buffer_head[i])
2446  {
2447  while (i < available)
2448  {
2449  if ( ('\r' == buffer_head[i]) ||
2450  ('\n' == buffer_head[i]) )
2451  break;
2452  i++;
2453  }
2454  }
2455  /* take '\n' into account; if '\n' is the unavailable
2456  character, we will need to wait until we have it
2457  before going further */
2458  if ( (i + 1 >= available) &&
2459  ! ( (1 == i) &&
2460  (2 == available) &&
2461  ('0' == buffer_head[0]) ) )
2462  break; /* need more data... */
2463  i++;
2464  malformed = (end_size >= 16);
2465  if (! malformed)
2466  {
2467  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2468  end_size,
2469  &connection->current_chunk_size);
2470  malformed = (end_size != num_dig);
2471  }
2472  if (malformed)
2473  {
2474  /* malformed encoding */
2475  CONNECTION_CLOSE_ERROR (connection,
2476  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2477  return;
2478  }
2479  /* skip 2nd part of line feed */
2480  if ( (i < available) &&
2481  ( ('\r' == buffer_head[i]) ||
2482  ('\n' == buffer_head[i]) ) )
2483  i++;
2484 
2485  buffer_head += i;
2486  available -= i;
2487  connection->current_chunk_offset = 0;
2488 
2489  if (available > 0)
2490  instant_retry = MHD_YES;
2491  if (0LLU == connection->current_chunk_size)
2492  {
2493  connection->remaining_upload_size = 0;
2494  break;
2495  }
2496  continue;
2497  }
2498  }
2499  else
2500  {
2501  /* no chunked encoding, give all to the client */
2502  if ( (0 != connection->remaining_upload_size) &&
2503  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2504  (connection->remaining_upload_size < available) )
2505  {
2506  to_be_processed = (size_t)connection->remaining_upload_size;
2507  }
2508  else
2509  {
2514  to_be_processed = available;
2515  }
2516  }
2517  left_unprocessed = to_be_processed;
2518  connection->client_aware = true;
2519  if (MHD_NO ==
2520  daemon->default_handler (daemon->default_handler_cls,
2521  connection,
2522  connection->url,
2523  connection->method,
2524  connection->version,
2525  buffer_head,
2526  &left_unprocessed,
2527  &connection->client_context))
2528  {
2529  /* serious internal error, close connection */
2530  CONNECTION_CLOSE_ERROR (connection,
2531  _("Application reported internal error, closing connection.\n"));
2532  return;
2533  }
2534  if (left_unprocessed > to_be_processed)
2536  __FILE__,
2537  __LINE__
2538 #ifdef HAVE_MESSAGES
2539  , _("libmicrohttpd API violation")
2540 #else
2541  , NULL
2542 #endif
2543  );
2544  if (0 != left_unprocessed)
2545  {
2546  instant_retry = MHD_NO; /* client did not process everything */
2547 #ifdef HAVE_MESSAGES
2548  /* client did not process all upload data, complain if
2549  the setup was incorrect, which may prevent us from
2550  handling the rest of the request */
2551  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2552  (! connection->suspended) )
2553  MHD_DLOG (daemon,
2554  _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2555 #endif
2556  }
2557  processed_size = to_be_processed - left_unprocessed;
2558  if (connection->have_chunked_upload)
2559  connection->current_chunk_offset += processed_size;
2560  /* dh left "processed" bytes in buffer for next time... */
2561  buffer_head += processed_size;
2562  available -= processed_size;
2563  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2564  connection->remaining_upload_size -= processed_size;
2565  }
2566  while (MHD_YES == instant_retry);
2567  if (available > 0)
2568  memmove (connection->read_buffer,
2569  buffer_head,
2570  available);
2571  connection->read_buffer_offset = available;
2572 }
2573 
2574 
2583 static int
2584 check_write_done (struct MHD_Connection *connection,
2585  enum MHD_CONNECTION_STATE next_state)
2586 {
2587  if (connection->write_buffer_append_offset !=
2588  connection->write_buffer_send_offset)
2589  return MHD_NO;
2590  connection->write_buffer_append_offset = 0;
2591  connection->write_buffer_send_offset = 0;
2592  connection->state = next_state;
2593  MHD_pool_reallocate (connection->pool,
2594  connection->write_buffer,
2595  connection->write_buffer_size,
2596  0);
2597  connection->write_buffer = NULL;
2598  connection->write_buffer_size = 0;
2599  return MHD_YES;
2600 }
2601 
2602 
2612 static int
2614  char *line)
2615 {
2616  char *colon;
2617 
2618  /* line should be normal header line, find colon */
2619  colon = strchr (line, ':');
2620  if (NULL == colon)
2621  {
2622  /* error in header line, die hard */
2623  CONNECTION_CLOSE_ERROR (connection,
2624  _("Received malformed line (no colon). Closing connection.\n"));
2625  return MHD_NO;
2626  }
2627  if (-1 >= connection->daemon->strict_for_client)
2628  {
2629  /* check for whitespace before colon, which is not allowed
2630  by RFC 7230 section 3.2.4; we count space ' ' and
2631  tab '\t', but not '\r\n' as those would have ended the line. */
2632  const char *white;
2633 
2634  white = strchr (line, ' ');
2635  if ( (NULL != white) &&
2636  (white < colon) )
2637  return MHD_NO;
2638  white = strchr (line, '\t');
2639  if ( (NULL != white) &&
2640  (white < colon) )
2641  return MHD_NO;
2642  }
2643  /* zero-terminate header */
2644  colon[0] = '\0';
2645  colon++; /* advance to value */
2646  while ( ('\0' != colon[0]) &&
2647  ( (' ' == colon[0]) ||
2648  ('\t' == colon[0]) ) )
2649  colon++;
2650  /* we do the actual adding of the connection
2651  header at the beginning of the while
2652  loop since we need to be able to inspect
2653  the *next* header line (in case it starts
2654  with a space...) */
2655  connection->last = line;
2656  connection->colon = colon;
2657  return MHD_YES;
2658 }
2659 
2660 
2671 static int
2673  char *line,
2674  enum MHD_ValueKind kind)
2675 {
2676  char *last;
2677  char *tmp;
2678  size_t last_len;
2679  size_t tmp_len;
2680 
2681  last = connection->last;
2682  if ( (' ' == line[0]) ||
2683  ('\t' == line[0]) )
2684  {
2685  /* value was continued on the next line, see
2686  http://www.jmarshall.com/easy/http/ */
2687  last_len = strlen (last);
2688  /* skip whitespace at start of 2nd line */
2689  tmp = line;
2690  while ( (' ' == tmp[0]) ||
2691  ('\t' == tmp[0]) )
2692  tmp++;
2693  tmp_len = strlen (tmp);
2694  /* FIXME: we might be able to do this better (faster!), as most
2695  likely 'last' and 'line' should already be adjacent in
2696  memory; however, doing this right gets tricky if we have a
2697  value continued over multiple lines (in which case we need to
2698  record how often we have done this so we can check for
2699  adjacency); also, in the case where these are not adjacent
2700  (not sure how it can happen!), we would want to allocate from
2701  the end of the pool, so as to not destroy the read-buffer's
2702  ability to grow nicely. */
2703  last = MHD_pool_reallocate (connection->pool,
2704  last,
2705  last_len + 1,
2706  last_len + tmp_len + 1);
2707  if (NULL == last)
2708  {
2709  transmit_error_response (connection,
2711  REQUEST_TOO_BIG);
2712  return MHD_NO;
2713  }
2714  memcpy (&last[last_len], tmp, tmp_len + 1);
2715  connection->last = last;
2716  return MHD_YES; /* possibly more than 2 lines... */
2717  }
2718  mhd_assert ( (NULL != last) &&
2719  (NULL != connection->colon) );
2720  if ((MHD_NO == connection_add_header (connection,
2721  last,
2722  connection->colon,
2723  kind)))
2724  {
2725  transmit_error_response (connection,
2727  REQUEST_TOO_BIG);
2728  return MHD_NO;
2729  }
2730  /* we still have the current line to deal with... */
2731  if (0 != line[0])
2732  {
2733  if (MHD_NO == process_header_line (connection,
2734  line))
2735  {
2736  transmit_error_response (connection,
2739  return MHD_NO;
2740  }
2741  }
2742  return MHD_YES;
2743 }
2744 
2745 
2753 static void
2755 {
2756  const char *clen;
2757  struct MHD_Response *response;
2758  const char *enc;
2759  const char *end;
2760 
2761  parse_cookie_header (connection);
2762  if ( (1 <= connection->daemon->strict_for_client) &&
2763  (NULL != connection->version) &&
2765  connection->version)) &&
2766  (NULL ==
2767  MHD_lookup_connection_value (connection,
2770  {
2771  int iret;
2772 
2773  /* die, http 1.1 request without host and we are pedantic */
2774  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2775  connection->read_closed = true;
2776 #ifdef HAVE_MESSAGES
2777  MHD_DLOG (connection->daemon,
2778  _("Received HTTP 1.1 request without `Host' header.\n"));
2779 #endif
2780  mhd_assert (NULL == connection->response);
2781  response =
2785  if (NULL == response)
2786  {
2787  /* can't even send a reply, at least close the connection */
2788  CONNECTION_CLOSE_ERROR (connection,
2789  _("Closing connection (failed to create response)\n"));
2790  return;
2791  }
2792  iret = MHD_queue_response (connection,
2794  response);
2795  MHD_destroy_response (response);
2796  if (MHD_YES != iret)
2797  {
2798  /* can't even send a reply, at least close the connection */
2799  CONNECTION_CLOSE_ERROR (connection,
2800  _("Closing connection (failed to queue response)\n"));
2801  }
2802  return;
2803  }
2804 
2805  connection->remaining_upload_size = 0;
2806  enc = MHD_lookup_connection_value (connection,
2809  if (NULL != enc)
2810  {
2812  if (MHD_str_equal_caseless_(enc,
2813  "chunked"))
2814  connection->have_chunked_upload = true;
2815  }
2816  else
2817  {
2818  clen = MHD_lookup_connection_value (connection,
2821  if (NULL != clen)
2822  {
2823  end = clen + MHD_str_to_uint64_ (clen,
2824  &connection->remaining_upload_size);
2825  if ( (clen == end) ||
2826  ('\0' != *end) )
2827  {
2828  connection->remaining_upload_size = 0;
2829 #ifdef HAVE_MESSAGES
2830  MHD_DLOG (connection->daemon,
2831  "Failed to parse `Content-Length' header. Closing connection.\n");
2832 #endif
2833  CONNECTION_CLOSE_ERROR (connection,
2834  NULL);
2835  return;
2836  }
2837  }
2838  }
2839 }
2840 
2841 
2849 void
2851 {
2852  struct MHD_Daemon *daemon = connection->daemon;
2853 
2854  if (0 == connection->connection_timeout)
2855  return; /* Skip update of activity for connections
2856  without timeout timer. */
2857  if (connection->suspended)
2858  return; /* no activity on suspended connections */
2859 
2860  connection->last_activity = MHD_monotonic_sec_counter();
2861  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2862  return; /* each connection has personal timeout */
2863 
2864  if (connection->connection_timeout != daemon->connection_timeout)
2865  return; /* custom timeout, no need to move it in "normal" DLL */
2866 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2868 #endif
2869  /* move connection to head of timeout list (by remove + add operation) */
2871  daemon->normal_timeout_tail,
2872  connection);
2874  daemon->normal_timeout_tail,
2875  connection);
2876 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2878 #endif
2879 }
2880 
2881 
2888 void
2890 {
2891  ssize_t bytes_read;
2892 
2893  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2894  (connection->suspended) )
2895  return;
2896 #ifdef HTTPS_SUPPORT
2897  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2898  { /* HTTPS connection. */
2899  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2900  {
2901  if (!MHD_run_tls_handshake_ (connection))
2902  return;
2903  }
2904  }
2905 #endif /* HTTPS_SUPPORT */
2906 
2907  /* make sure "read" has a reasonable number of bytes
2908  in buffer to use per system call (if possible) */
2909  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2910  connection->read_buffer_size)
2911  try_grow_read_buffer (connection);
2912 
2913  if (connection->read_buffer_size == connection->read_buffer_offset)
2914  return; /* No space for receiving data. */
2915  bytes_read = connection->recv_cls (connection,
2916  &connection->read_buffer
2917  [connection->read_buffer_offset],
2918  connection->read_buffer_size -
2919  connection->read_buffer_offset);
2920  if (bytes_read < 0)
2921  {
2922  if (MHD_ERR_AGAIN_ == bytes_read)
2923  return; /* No new data to process. */
2924  if (MHD_ERR_CONNRESET_ == bytes_read)
2925  {
2926  CONNECTION_CLOSE_ERROR (connection,
2927  (MHD_CONNECTION_INIT == connection->state) ?
2928  NULL :
2929  _("Socket disconnected while reading request.\n"));
2930  return;
2931  }
2932  CONNECTION_CLOSE_ERROR (connection,
2933  (MHD_CONNECTION_INIT == connection->state) ?
2934  NULL :
2935  _("Connection socket is closed due to error when reading request.\n"));
2936  return;
2937  }
2938 
2939  if (0 == bytes_read)
2940  { /* Remote side closed connection. */
2941  connection->read_closed = true;
2942  MHD_connection_close_ (connection,
2944  return;
2945  }
2946  connection->read_buffer_offset += bytes_read;
2947  MHD_update_last_activity_ (connection);
2948 #if DEBUG_STATES
2949  MHD_DLOG (connection->daemon,
2950  _("In function %s handling connection at state: %s\n"),
2951  __FUNCTION__,
2952  MHD_state_to_string (connection->state));
2953 #endif
2954  switch (connection->state)
2955  {
2956  case MHD_CONNECTION_INIT:
2965  /* nothing to do but default action */
2966  if (connection->read_closed)
2967  {
2968  MHD_connection_close_ (connection,
2970  }
2971  return;
2972  case MHD_CONNECTION_CLOSED:
2973  return;
2974 #ifdef UPGRADE_SUPPORT
2975  case MHD_CONNECTION_UPGRADE:
2976  mhd_assert (0);
2977  return;
2978 #endif /* UPGRADE_SUPPORT */
2979  default:
2980  /* shrink read buffer to how much is actually used */
2981  MHD_pool_reallocate (connection->pool,
2982  connection->read_buffer,
2983  connection->read_buffer_size + 1,
2984  connection->read_buffer_offset);
2985  break;
2986  }
2987  return;
2988 }
2989 
2990 
2997 void
2999 {
3000  struct MHD_Response *response;
3001  ssize_t ret;
3002  if (connection->suspended)
3003  return;
3004 
3005 #ifdef HTTPS_SUPPORT
3006  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3007  { /* HTTPS connection. */
3008  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
3009  {
3010  if (!MHD_run_tls_handshake_ (connection))
3011  return;
3012  }
3013  }
3014 #endif /* HTTPS_SUPPORT */
3015 
3016 #if DEBUG_STATES
3017  MHD_DLOG (connection->daemon,
3018  _("In function %s handling connection at state: %s\n"),
3019  __FUNCTION__,
3020  MHD_state_to_string (connection->state));
3021 #endif
3022  switch (connection->state)
3023  {
3024  case MHD_CONNECTION_INIT:
3028  mhd_assert (0);
3029  return;
3031  return;
3033  ret = connection->send_cls (connection,
3035  [connection->continue_message_write_offset],
3037  connection->continue_message_write_offset);
3038  if (ret < 0)
3039  {
3040  if (MHD_ERR_AGAIN_ == ret)
3041  return;
3042 #ifdef HAVE_MESSAGES
3043  MHD_DLOG (connection->daemon,
3044  _("Failed to send data in request for %s.\n"),
3045  connection->url);
3046 #endif
3047  CONNECTION_CLOSE_ERROR (connection,
3048  NULL);
3049  return;
3050  }
3051 #if DEBUG_SEND_DATA
3052  fprintf (stderr,
3053  _("Sent 100 continue response: `%.*s'\n"),
3054  (int) ret,
3056 #endif
3057  connection->continue_message_write_offset += ret;
3058  MHD_update_last_activity_ (connection);
3059  return;
3064  mhd_assert (0);
3065  return;
3067  ret = connection->send_cls (connection,
3068  &connection->write_buffer
3069  [connection->write_buffer_send_offset],
3070  connection->write_buffer_append_offset -
3071  connection->write_buffer_send_offset);
3072  if (ret < 0)
3073  {
3074  if (MHD_ERR_AGAIN_ == ret)
3075  return;
3076  CONNECTION_CLOSE_ERROR (connection,
3077  _("Connection was closed while sending response headers.\n"));
3078  return;
3079  }
3080  connection->write_buffer_send_offset += ret;
3081  MHD_update_last_activity_ (connection);
3082  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3083  return;
3084  check_write_done (connection,
3086  return;
3088  return;
3090  response = connection->response;
3091  if (connection->response_write_position <
3092  connection->response->total_size)
3093  {
3094  uint64_t data_write_offset;
3095 
3096 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3097  if (NULL != response->crc)
3098  MHD_mutex_lock_chk_ (&response->mutex);
3099 #endif
3100  if (MHD_YES != try_ready_normal_body (connection))
3101  {
3102  /* mutex was already unlocked by try_ready_normal_body */
3103  return;
3104  }
3105 #if defined(_MHD_HAVE_SENDFILE)
3106  if (MHD_resp_sender_sendfile == connection->resp_sender)
3107  {
3108  ret = sendfile_adapter (connection);
3109  }
3110  else
3111 #else /* ! _MHD_HAVE_SENDFILE */
3112  if (1)
3113 #endif /* ! _MHD_HAVE_SENDFILE */
3114  {
3115  data_write_offset = connection->response_write_position
3116  - response->data_start;
3117  if (data_write_offset > (uint64_t)SIZE_MAX)
3118  MHD_PANIC (_("Data offset exceeds limit"));
3119  ret = connection->send_cls (connection,
3120  &response->data
3121  [(size_t)data_write_offset],
3122  response->data_size -
3123  (size_t)data_write_offset);
3124 #if DEBUG_SEND_DATA
3125  if (ret > 0)
3126  fprintf (stderr,
3127  _("Sent %d-byte DATA response: `%.*s'\n"),
3128  (int) ret,
3129  (int) ret,
3130  &response->data[connection->response_write_position -
3131  response->data_start]);
3132 #endif
3133  }
3134 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3135  if (NULL != response->crc)
3136  MHD_mutex_unlock_chk_ (&response->mutex);
3137 #endif
3138  if (ret < 0)
3139  {
3140  if (MHD_ERR_AGAIN_ == ret)
3141  return;
3142 #ifdef HAVE_MESSAGES
3143  MHD_DLOG (connection->daemon,
3144  _("Failed to send data in request for `%s'.\n"),
3145  connection->url);
3146 #endif
3147  CONNECTION_CLOSE_ERROR (connection,
3148  NULL);
3149  return;
3150  }
3151  connection->response_write_position += ret;
3152  MHD_update_last_activity_ (connection);
3153  }
3154  if (connection->response_write_position ==
3155  connection->response->total_size)
3156  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3157  return;
3159  mhd_assert (0);
3160  return;
3162  ret = connection->send_cls (connection,
3163  &connection->write_buffer
3164  [connection->write_buffer_send_offset],
3165  connection->write_buffer_append_offset -
3166  connection->write_buffer_send_offset);
3167  if (ret < 0)
3168  {
3169  if (MHD_ERR_AGAIN_ == ret)
3170  return;
3171  CONNECTION_CLOSE_ERROR (connection,
3172  _("Connection was closed while sending response body.\n"));
3173  return;
3174  }
3175  connection->write_buffer_send_offset += ret;
3176  MHD_update_last_activity_ (connection);
3177  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3178  return;
3179  check_write_done (connection,
3180  (connection->response->total_size ==
3181  connection->response_write_position) ?
3184  return;
3187  mhd_assert (0);
3188  return;
3190  ret = connection->send_cls (connection,
3191  &connection->write_buffer
3192  [connection->write_buffer_send_offset],
3193  connection->write_buffer_append_offset -
3194  connection->write_buffer_send_offset);
3195  if (ret < 0)
3196  {
3197  if (MHD_ERR_AGAIN_ == ret)
3198  return;
3199  CONNECTION_CLOSE_ERROR (connection,
3200  _("Connection was closed while sending response body.\n"));
3201  return;
3202  }
3203  connection->write_buffer_send_offset += ret;
3204  MHD_update_last_activity_ (connection);
3205  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3206  return;
3207  check_write_done (connection,
3209  return;
3211  mhd_assert (0);
3212  return;
3213  case MHD_CONNECTION_CLOSED:
3214  return;
3215 #ifdef UPGRADE_SUPPORT
3216  case MHD_CONNECTION_UPGRADE:
3217  mhd_assert (0);
3218  return;
3219 #endif /* UPGRADE_SUPPORT */
3220  default:
3221  mhd_assert (0);
3222  CONNECTION_CLOSE_ERROR (connection,
3223  _("Internal error\n"));
3224  break;
3225  }
3226  return;
3227 }
3228 
3229 
3238 static void
3240 {
3241  struct MHD_Daemon *daemon = connection->daemon;
3242 
3243  if (connection->in_cleanup)
3244  return; /* Prevent double cleanup. */
3245  connection->in_cleanup = true;
3246  if (NULL != connection->response)
3247  {
3248  MHD_destroy_response (connection->response);
3249  connection->response = NULL;
3250  }
3251 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3253 #endif
3254  if (connection->suspended)
3255  {
3258  connection);
3259  connection->suspended = false;
3260  }
3261  else
3262  {
3263  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3264  {
3265  if (connection->connection_timeout == daemon->connection_timeout)
3267  daemon->normal_timeout_tail,
3268  connection);
3269  else
3271  daemon->manual_timeout_tail,
3272  connection);
3273  }
3274  DLL_remove (daemon->connections_head,
3275  daemon->connections_tail,
3276  connection);
3277  }
3278  DLL_insert (daemon->cleanup_head,
3279  daemon->cleanup_tail,
3280  connection);
3281  connection->resuming = false;
3282  connection->in_idle = false;
3283 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3285 #endif
3286  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3287  {
3288  /* if we were at the connection limit before and are in
3289  thread-per-connection mode, signal the main thread
3290  to resume accepting connections */
3291  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3292  (! MHD_itc_activate_ (daemon->itc, "c")) )
3293  {
3294 #ifdef HAVE_MESSAGES
3295  MHD_DLOG (daemon,
3296  _("Failed to signal end of connection via inter-thread communication channel"));
3297 #endif
3298  }
3299  }
3300 }
3301 
3302 
3313 int
3315 {
3316  struct MHD_Daemon *daemon = connection->daemon;
3317  char *line;
3318  size_t line_len;
3319  int ret;
3320 
3321  connection->in_idle = true;
3322  while (! connection->suspended)
3323  {
3324 #ifdef HTTPS_SUPPORT
3325  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3326  { /* HTTPS connection. */
3327  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3328  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3329  break;
3330  }
3331 #endif /* HTTPS_SUPPORT */
3332 #if DEBUG_STATES
3333  MHD_DLOG (daemon,
3334  _("In function %s handling connection at state: %s\n"),
3335  __FUNCTION__,
3336  MHD_state_to_string (connection->state));
3337 #endif
3338  switch (connection->state)
3339  {
3340  case MHD_CONNECTION_INIT:
3341  line = get_next_header_line (connection,
3342  &line_len);
3343  /* Check for empty string, as we might want
3344  to tolerate 'spurious' empty lines; also
3345  NULL means we didn't get a full line yet;
3346  line is not 0-terminated here. */
3347  if ( (NULL == line) ||
3348  (0 == line[0]) )
3349  {
3350  if (MHD_CONNECTION_INIT != connection->state)
3351  continue;
3352  if (connection->read_closed)
3353  {
3354  CONNECTION_CLOSE_ERROR (connection,
3355  NULL);
3356  continue;
3357  }
3358  break;
3359  }
3360  if (MHD_NO == parse_initial_message_line (connection,
3361  line,
3362  line_len))
3363  CONNECTION_CLOSE_ERROR (connection,
3364  NULL);
3365  else
3366  connection->state = MHD_CONNECTION_URL_RECEIVED;
3367  continue;
3369  line = get_next_header_line (connection,
3370  NULL);
3371  if (NULL == line)
3372  {
3373  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3374  continue;
3375  if (connection->read_closed)
3376  {
3377  CONNECTION_CLOSE_ERROR (connection,
3378  NULL);
3379  continue;
3380  }
3381  break;
3382  }
3383  if (0 == line[0])
3384  {
3385  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3386  connection->header_size = (size_t) (line - connection->read_buffer);
3387  continue;
3388  }
3389  if (MHD_NO == process_header_line (connection,
3390  line))
3391  {
3392  transmit_error_response (connection,
3395  break;
3396  }
3398  continue;
3400  line = get_next_header_line (connection,
3401  NULL);
3402  if (NULL == line)
3403  {
3404  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
3405  continue;
3406  if (connection->read_closed)
3407  {
3408  CONNECTION_CLOSE_ERROR (connection,
3409  NULL);
3410  continue;
3411  }
3412  break;
3413  }
3414  if (MHD_NO ==
3415  process_broken_line (connection,
3416  line,
3417  MHD_HEADER_KIND))
3418  continue;
3419  if (0 == line[0])
3420  {
3421  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3422  connection->header_size = (size_t) (line - connection->read_buffer);
3423  continue;
3424  }
3425  continue;
3427  parse_connection_headers (connection);
3428  if (MHD_CONNECTION_CLOSED == connection->state)
3429  continue;
3431  if (connection->suspended)
3432  break;
3433  continue;
3435  call_connection_handler (connection); /* first call */
3436  if (MHD_CONNECTION_CLOSED == connection->state)
3437  continue;
3438  if (need_100_continue (connection))
3439  {
3440  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3441  if (socket_flush_possible (connection))
3442  socket_start_extra_buffering (connection);
3443  else
3444  socket_start_no_buffering (connection);
3445 
3446  break;
3447  }
3448  if ( (NULL != connection->response) &&
3449  ( (MHD_str_equal_caseless_ (connection->method,
3451  (MHD_str_equal_caseless_ (connection->method,
3452  MHD_HTTP_METHOD_PUT))) )
3453  {
3454  /* we refused (no upload allowed!) */
3455  connection->remaining_upload_size = 0;
3456  /* force close, in case client still tries to upload... */
3457  connection->read_closed = true;
3458  }
3459  connection->state = (0 == connection->remaining_upload_size)
3461  if (connection->suspended)
3462  break;
3463  continue;
3465  if (connection->continue_message_write_offset ==
3467  {
3468  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3469  if (socket_flush_possible (connection))
3470  socket_start_no_buffering_flush (connection);
3471  else
3472  socket_start_normal_buffering (connection);
3473 
3474  continue;
3475  }
3476  break;
3478  if (0 != connection->read_buffer_offset)
3479  {
3480  process_request_body (connection); /* loop call */
3481  if (MHD_CONNECTION_CLOSED == connection->state)
3482  continue;
3483  }
3484  if ( (0 == connection->remaining_upload_size) ||
3485  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3486  (0 == connection->read_buffer_offset) &&
3487  (connection->read_closed) ) )
3488  {
3489  if ( (connection->have_chunked_upload) &&
3490  (! connection->read_closed) )
3491  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3492  else
3493  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3494  if (connection->suspended)
3495  break;
3496  continue;
3497  }
3498  break;
3500  line = get_next_header_line (connection,
3501  NULL);
3502  if (NULL == line)
3503  {
3504  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3505  continue;
3506  if (connection->read_closed)
3507  {
3508  CONNECTION_CLOSE_ERROR (connection,
3509  NULL);
3510  continue;
3511  }
3512  break;
3513  }
3514  if (0 == line[0])
3515  {
3516  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3517  if (connection->suspended)
3518  break;
3519  continue;
3520  }
3521  if (MHD_NO == process_header_line (connection,
3522  line))
3523  {
3524  transmit_error_response (connection,
3527  break;
3528  }
3530  continue;
3532  line = get_next_header_line (connection,
3533  NULL);
3534  if (NULL == line)
3535  {
3536  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3537  continue;
3538  if (connection->read_closed)
3539  {
3540  CONNECTION_CLOSE_ERROR (connection,
3541  NULL);
3542  continue;
3543  }
3544  break;
3545  }
3546  if (MHD_NO ==
3547  process_broken_line (connection,
3548  line,
3549  MHD_FOOTER_KIND))
3550  continue;
3551  if (0 == line[0])
3552  {
3553  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3554  if (connection->suspended)
3555  break;
3556  continue;
3557  }
3558  continue;
3560  call_connection_handler (connection); /* "final" call */
3561  if (connection->state == MHD_CONNECTION_CLOSED)
3562  continue;
3563  if (NULL == connection->response)
3564  break; /* try again next time */
3565  if (MHD_NO == build_header_response (connection))
3566  {
3567  /* oops - close! */
3568  CONNECTION_CLOSE_ERROR (connection,
3569  _("Closing connection (failed to create response header)\n"));
3570  continue;
3571  }
3572  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3573  if (socket_flush_possible (connection))
3574  socket_start_extra_buffering (connection);
3575  else
3576  socket_start_no_buffering (connection);
3577 
3578  break;
3580  /* no default action */
3581  break;
3583  /* Some clients may take some actions right after header receive */
3584  if (socket_flush_possible (connection))
3585  socket_start_no_buffering_flush (connection);
3586 
3587 #ifdef UPGRADE_SUPPORT
3588  if (NULL != connection->response->upgrade_handler)
3589  {
3590  socket_start_normal_buffering (connection);
3591  connection->state = MHD_CONNECTION_UPGRADE;
3592  /* This connection is "upgraded". Pass socket to application. */
3593  if (MHD_YES !=
3595  connection))
3596  {
3597  /* upgrade failed, fail hard */
3598  CONNECTION_CLOSE_ERROR (connection,
3599  NULL);
3600  continue;
3601  }
3602  /* Response is not required anymore for this connection. */
3603  {
3604  struct MHD_Response * const resp = connection->response;
3605 
3606  connection->response = NULL;
3607  MHD_destroy_response (resp);
3608  }
3609  continue;
3610  }
3611 #endif /* UPGRADE_SUPPORT */
3612  if (socket_flush_possible (connection))
3613  socket_start_extra_buffering (connection);
3614  else
3615  socket_start_normal_buffering (connection);
3616 
3617  if (connection->have_chunked_upload)
3619  else
3621  continue;
3623  /* nothing to do here */
3624  break;
3626 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3627  if (NULL != connection->response->crc)
3628  MHD_mutex_lock_chk_ (&connection->response->mutex);
3629 #endif
3630  if (0 == connection->response->total_size)
3631  {
3632 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3633  if (NULL != connection->response->crc)
3634  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3635 #endif
3636  connection->state = MHD_CONNECTION_BODY_SENT;
3637  continue;
3638  }
3639  if (MHD_YES == try_ready_normal_body (connection))
3640  {
3641 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3642  if (NULL != connection->response->crc)
3643  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3644 #endif
3646  /* Buffering for flushable socket was already enabled*/
3647  if (socket_flush_possible (connection))
3648  socket_start_no_buffering (connection);
3649  break;
3650  }
3651  /* mutex was already unlocked by "try_ready_normal_body */
3652  /* not ready, no socket action */
3653  break;
3655  /* nothing to do here */
3656  break;
3658 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3659  if (NULL != connection->response->crc)
3660  MHD_mutex_lock_chk_ (&connection->response->mutex);
3661 #endif
3662  if ( (0 == connection->response->total_size) ||
3663  (connection->response_write_position ==
3664  connection->response->total_size) )
3665  {
3666 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3667  if (NULL != connection->response->crc)
3668  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3669 #endif
3670  connection->state = MHD_CONNECTION_BODY_SENT;
3671  continue;
3672  }
3673  if (MHD_YES == try_ready_chunked_body (connection))
3674  {
3675 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3676  if (NULL != connection->response->crc)
3677  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3678 #endif
3680  /* Buffering for flushable socket was already enabled */
3681  if (socket_flush_possible (connection))
3682  socket_start_no_buffering (connection);
3683  continue;
3684  }
3685  /* mutex was already unlocked by try_ready_chunked_body */
3686  break;
3688  if (MHD_NO == build_header_response (connection))
3689  {
3690  /* oops - close! */
3691  CONNECTION_CLOSE_ERROR (connection,
3692  _("Closing connection (failed to create response header)\n"));
3693  continue;
3694  }
3695  if ( (! connection->have_chunked_upload) ||
3696  (connection->write_buffer_send_offset ==
3697  connection->write_buffer_append_offset) )
3698  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3699  else
3700  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3701  continue;
3703  /* no default action */
3704  break;
3706  if (MHD_HTTP_PROCESSING == connection->responseCode)
3707  {
3708  /* After this type of response, we allow sending another! */
3710  MHD_destroy_response (connection->response);
3711  connection->response = NULL;
3712  /* FIXME: maybe partially reset memory pool? */
3713  continue;
3714  }
3715  if (socket_flush_possible (connection))
3716  socket_start_no_buffering_flush (connection);
3717  else
3718  socket_start_normal_buffering (connection);
3719 
3720  MHD_destroy_response (connection->response);
3721  connection->response = NULL;
3722  if ( (NULL != daemon->notify_completed) &&
3723  (connection->client_aware) )
3724  {
3725  daemon->notify_completed (daemon->notify_completed_cls,
3726  connection,
3727  &connection->client_context,
3729  }
3730  connection->client_aware = false;
3731  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3732  (connection->read_closed) )
3733  {
3734  /* have to close for some reason */
3735  MHD_connection_close_ (connection,
3737  MHD_pool_destroy (connection->pool);
3738  connection->pool = NULL;
3739  connection->read_buffer = NULL;
3740  connection->read_buffer_size = 0;
3741  connection->read_buffer_offset = 0;
3742  }
3743  else
3744  {
3745  /* can try to keep-alive */
3746  if (socket_flush_possible (connection))
3747  socket_start_normal_buffering (connection);
3748  connection->version = NULL;
3749  connection->state = MHD_CONNECTION_INIT;
3750  connection->last = NULL;
3751  connection->colon = NULL;
3752  connection->header_size = 0;
3753  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3754  /* Reset the read buffer to the starting size,
3755  preserving the bytes we have already read. */
3756  connection->read_buffer
3757  = MHD_pool_reset (connection->pool,
3758  connection->read_buffer,
3759  connection->read_buffer_offset,
3760  connection->daemon->pool_size / 2);
3761  connection->read_buffer_size
3762  = connection->daemon->pool_size / 2;
3763  }
3764  connection->client_context = NULL;
3765  connection->continue_message_write_offset = 0;
3766  connection->responseCode = 0;
3767  connection->headers_received = NULL;
3768  connection->headers_received_tail = NULL;
3769  connection->response_write_position = 0;
3770  connection->have_chunked_upload = false;
3771  connection->current_chunk_size = 0;
3772  connection->current_chunk_offset = 0;
3773  connection->method = NULL;
3774  connection->url = NULL;
3775  connection->write_buffer = NULL;
3776  connection->write_buffer_size = 0;
3777  connection->write_buffer_send_offset = 0;
3778  connection->write_buffer_append_offset = 0;
3779  continue;
3780  case MHD_CONNECTION_CLOSED:
3781  cleanup_connection (connection);
3782  connection->in_idle = false;
3783  return MHD_NO;
3784 #ifdef UPGRADE_SUPPORT
3785  case MHD_CONNECTION_UPGRADE:
3786  connection->in_idle = false;
3787  return MHD_YES; /* keep open */
3788 #endif /* UPGRADE_SUPPORT */
3789  default:
3790  mhd_assert (0);
3791  break;
3792  }
3793  break;
3794  }
3795  if (! connection->suspended)
3796  {
3797  time_t timeout;
3798  timeout = connection->connection_timeout;
3799  if ( (0 != timeout) &&
3800  (timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
3801  {
3802  MHD_connection_close_ (connection,
3804  connection->in_idle = false;
3805  return MHD_YES;
3806  }
3807  }
3809  ret = MHD_YES;
3810 #ifdef EPOLL_SUPPORT
3811  if ( (! connection->suspended) &&
3812  (0 != (daemon->options & MHD_USE_EPOLL)) )
3813  {
3814  ret = MHD_connection_epoll_update_ (connection);
3815  }
3816 #endif /* EPOLL_SUPPORT */
3817  connection->in_idle = false;
3818  return ret;
3819 }
3820 
3821 
3822 #ifdef EPOLL_SUPPORT
3823 
3831 int
3832 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3833 {
3834  struct MHD_Daemon *daemon = connection->daemon;
3835 
3836  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3837  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3838  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3839  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3840  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3841  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3842  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3843  {
3844  /* add to epoll set */
3845  struct epoll_event event;
3846 
3847  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3848  event.data.ptr = connection;
3849  if (0 != epoll_ctl (daemon->epoll_fd,
3850  EPOLL_CTL_ADD,
3851  connection->socket_fd,
3852  &event))
3853  {
3854 #ifdef HAVE_MESSAGES
3855  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3856  MHD_DLOG (daemon,
3857  _("Call to epoll_ctl failed: %s\n"),
3859 #endif
3860  connection->state = MHD_CONNECTION_CLOSED;
3861  cleanup_connection (connection);
3862  return MHD_NO;
3863  }
3864  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3865  }
3866  return MHD_YES;
3867 }
3868 #endif
3869 
3870 
3876 void
3878 {
3879  connection->recv_cls = &recv_param_adapter;
3880  connection->send_cls = &send_param_adapter;
3881 }
3882 
3883 
3894 const union MHD_ConnectionInfo *
3896  enum MHD_ConnectionInfoType info_type,
3897  ...)
3898 {
3899  switch (info_type)
3900  {
3901 #ifdef HTTPS_SUPPORT
3903  if (NULL == connection->tls_session)
3904  return NULL;
3905  connection->cipher = gnutls_cipher_get (connection->tls_session);
3906  return (const union MHD_ConnectionInfo *) &connection->cipher;
3908  if (NULL == connection->tls_session)
3909  return NULL;
3910  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3911  return (const union MHD_ConnectionInfo *) &connection->protocol;
3913  if (NULL == connection->tls_session)
3914  return NULL;
3915  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3916 #endif /* HTTPS_SUPPORT */
3918  return (const union MHD_ConnectionInfo *) &connection->addr;
3920  return (const union MHD_ConnectionInfo *) &connection->daemon;
3922  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3924  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3926  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3927  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3929  connection->connection_timeout_dummy = (unsigned int)connection->connection_timeout;
3930  return (const union MHD_ConnectionInfo *) &connection->connection_timeout_dummy;
3932  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3933  (MHD_CONNECTION_CLOSED == connection->state) )
3934  return NULL; /* invalid, too early! */
3935  return (const union MHD_ConnectionInfo *) &connection->header_size;
3936  default:
3937  return NULL;
3938  }
3939 }
3940 
3941 
3951 int
3953  enum MHD_CONNECTION_OPTION option,
3954  ...)
3955 {
3956  va_list ap;
3957  struct MHD_Daemon *daemon;
3958 
3959  daemon = connection->daemon;
3960  switch (option)
3961  {
3963  if (0 == connection->connection_timeout)
3964  connection->last_activity = MHD_monotonic_sec_counter();
3965 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3967 #endif
3968  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3969  (! connection->suspended) )
3970  {
3971  if (connection->connection_timeout == daemon->connection_timeout)
3973  daemon->normal_timeout_tail,
3974  connection);
3975  else
3977  daemon->manual_timeout_tail,
3978  connection);
3979  }
3980  va_start (ap, option);
3981  connection->connection_timeout = va_arg (ap,
3982  unsigned int);
3983  va_end (ap);
3984  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3985  (! connection->suspended) )
3986  {
3987  if (connection->connection_timeout == daemon->connection_timeout)
3989  daemon->normal_timeout_tail,
3990  connection);
3991  else
3993  daemon->manual_timeout_tail,
3994  connection);
3995  }
3996 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3998 #endif
3999  return MHD_YES;
4000  default:
4001  return MHD_NO;
4002  }
4003 }
4004 
4005 
4017 int
4019  unsigned int status_code,
4020  struct MHD_Response *response)
4021 {
4022  struct MHD_Daemon *daemon;
4023 
4024  if ( (NULL == connection) ||
4025  (NULL == response) ||
4026  (NULL != connection->response) ||
4027  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
4028  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
4029  return MHD_NO;
4030  daemon = connection->daemon;
4031 
4032  if (daemon->shutdown)
4033  return MHD_YES; /* If daemon was shut down in parallel,
4034  * response will be aborted now or on later stage. */
4035 
4036 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4037  if ( (!connection->suspended) &&
4038  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
4039  (!MHD_thread_ID_match_current_(connection->pid.ID)) )
4040  {
4041 #ifdef HAVE_MESSAGES
4042  MHD_DLOG (daemon,
4043  _("Attempted to queue response on wrong thread!\n"));
4044 #endif
4045  return MHD_NO;
4046  }
4047 #endif
4048 #ifdef UPGRADE_SUPPORT
4049  if ( (NULL != response->upgrade_handler) &&
4050  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
4051  {
4052 #ifdef HAVE_MESSAGES
4053  MHD_DLOG (daemon,
4054  _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
4055 #endif
4056  return MHD_NO;
4057  }
4058  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
4059  (NULL != response->upgrade_handler) )
4060  {
4061 #ifdef HAVE_MESSAGES
4062  MHD_DLOG (daemon,
4063  _("Application used invalid status code for 'upgrade' response!\n"));
4064 #endif
4065  return MHD_NO;
4066  }
4067 #endif /* UPGRADE_SUPPORT */
4068  MHD_increment_response_rc (response);
4069  connection->response = response;
4070  connection->responseCode = status_code;
4071 #if defined(_MHD_HAVE_SENDFILE)
4072  if ( (response->fd == -1) ||
4073  (0 != (connection->daemon->options & MHD_USE_TLS)) )
4074  connection->resp_sender = MHD_resp_sender_std;
4075  else
4076  connection->resp_sender = MHD_resp_sender_sendfile;
4077 #endif /* _MHD_HAVE_SENDFILE */
4078 
4079  if ( ( (NULL != connection->method) &&
4080  (MHD_str_equal_caseless_ (connection->method,
4081  MHD_HTTP_METHOD_HEAD)) ) ||
4082  (MHD_HTTP_OK > status_code) ||
4083  (MHD_HTTP_NO_CONTENT == status_code) ||
4084  (MHD_HTTP_NOT_MODIFIED == status_code) )
4085  {
4086  /* if this is a "HEAD" request, or a status code for
4087  which a body is not allowed, pretend that we
4088  have already sent the full message body. */
4089  connection->response_write_position = response->total_size;
4090  }
4091  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
4092  (NULL != connection->method) &&
4093  ( (MHD_str_equal_caseless_ (connection->method,
4095  (MHD_str_equal_caseless_ (connection->method,
4096  MHD_HTTP_METHOD_PUT))) )
4097  {
4098  /* response was queued "early", refuse to read body / footers or
4099  further requests! */
4100  connection->read_closed = true;
4101  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4102  }
4103  if (! connection->in_idle)
4104  (void) MHD_connection_handle_idle (connection);
4105  MHD_update_last_activity_ (connection);
4106  return MHD_YES;
4107 }
4108 
4109 
4110 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2613
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: connection.c:237
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2033
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:2098
void * unescape_callback_cls
Definition: internal.h:1408
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:460
#define MHD_PANIC(msg)
Definition: internal.h:68
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2998
uint64_t total_size
Definition: internal.h:1639
bool have_chunked_upload
Definition: internal.h:935
Header for platform missing functions.
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:1061
uint64_t fd_off
Definition: internal.h:1650
uint64_t current_chunk_offset
Definition: internal.h:949
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:784
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:754
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1840
struct sockaddr_storage addr
Definition: internal.h:725
struct MHD_Connection * cleanup_head
Definition: internal.h:1174
enum MHD_CONNECTION_STATE state
Definition: internal.h:915
void * data
Definition: microhttpd.h:2709
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:1131
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:851
uint64_t response_write_position
Definition: internal.h:809
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:716
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:450
void * mhd_panic_cls
Definition: panic.c:36
#define HTTP_100_CONTINUE
Definition: connection.c:61
#define MHD_ICY_FLAG
Definition: microhttpd.h:414
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:920
#define OFF_T_MAX
Definition: mhd_limits.h:123
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
time_t connection_timeout
Definition: internal.h:1579
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:2067
Methods for managing connections.
MHD_PanicCallback mhd_panic
Definition: panic.c:31
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
internal monotonic clock functions implementations
MHD_CONNECTION_STATE
Definition: internal.h:407
char * version
Definition: internal.h:709
int suspended_dummy
Definition: internal.h:1008
#define INTERNAL_ERROR
Definition: connection.c:111
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:470
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:926
#define MHD_YES
Definition: microhttpd.h:134
#define SIZE_MAX
Definition: mhd_limits.h:99
struct MHD_Response * response
Definition: internal.h:665
char * data
Definition: internal.h:1585
char * colon
Definition: internal.h:746
#define REQUEST_LACKS_HOST
Definition: connection.c:86
char * write_buffer
Definition: internal.h:729
#define MHD_SENFILE_CHUNK_
Definition: connection.c:129
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:329
#define MHD_ERR_AGAIN_
Definition: internal.h:1864
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:393
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:186
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1140
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:888
MHD_RequestTerminationCode
Definition: microhttpd.h:1604
size_t data_size
Definition: internal.h:1656
MHD_thread_handle_ID_ pid
Definition: internal.h:720
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:329
_MHD_static_inline bool socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:598
time_t MHD_monotonic_sec_counter(void)
char * value
Definition: internal.h:349
enum MHD_ValueKind kind
Definition: internal.h:355
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1769
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1254
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2325
uint64_t remaining_upload_size
Definition: internal.h:802
unsigned int responseCode
Definition: internal.h:926
#define MHD_ERR_CONNRESET_
Definition: internal.h:1869
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3239
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2850
char * header
Definition: internal.h:344
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1398
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:184
struct MHD_Daemon * daemon
Definition: internal.h:672
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t header_size
Definition: internal.h:796
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1948
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:134
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:574
static bool MHD_lookup_header_token_ci(const struct MHD_Connection *connection, const char *header, const char *token, size_t token_len)
Definition: connection.c:818
Header for platform-independent inter-thread communication.
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:1022
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
bool client_aware
Definition: internal.h:852
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3895
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1265
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
int strict_for_client
Definition: internal.h:1600
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1167
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:355
void * socket_context
Definition: internal.h:691
struct MHD_HTTP_Header * first_header
Definition: internal.h:1579
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
size_t data_buffer_size
Definition: internal.h:1661
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3422
size_t write_buffer_send_offset
Definition: internal.h:784
void * crc_cls
Definition: internal.h:1591
struct MHD_Connection * connections_tail
Definition: internal.h:1157
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
size_t read_buffer_size
Definition: internal.h:768
bool sk_tcp_cork_nopush_on
Definition: internal.h:876
void * client_context
Definition: internal.h:683
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:438
const char * url
Definition: internal.h:703
size_t continue_message_write_offset
Definition: internal.h:823
#define REQUEST_MALFORMED
Definition: connection.c:99
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:749
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:666
internal shared structures
enum MHD_HTTP_StatusCode status_code
Definition: internal.h:1666
char * method
Definition: internal.h:697
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
enum MHD_FLAG options
Definition: internal.h:1590
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:248
struct MHD_Connection * connections_head
Definition: internal.h:1152
_MHD_static_inline bool socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:640
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:317
LogCallback uri_log_callback
Definition: internal.h:1393
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2889
bool in_cleanup
Definition: internal.h:903
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1127
#define MHD_HTTP_OK
Definition: microhttpd.h:313
time_t connection_timeout
Definition: internal.h:742
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3952
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
bool sk_tcp_nodelay_on
Definition: internal.h:870
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
#define EDLL_remove(head, tail, element)
Definition: internal.h:1847
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1147
#define NULL
Definition: reason_phrase.c:30
char * last
Definition: internal.h:737
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1314
MHD_ValueKind
Definition: microhttpd.h:1554
Header for string manipulating helpers.
#define DLL_remove(head, tail, element)
Definition: internal.h:1762
char * read_buffer
Definition: internal.h:723
ReceiveCallback recv_cls
Definition: internal.h:703
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:863
size_t write_buffer_size
Definition: internal.h:779
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
MHD_ConnectionInfoType
Definition: microhttpd.h:1752
uint64_t data_start
Definition: internal.h:1645
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:741
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1125
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:375
UnescapeCallback unescape_callback
Definition: internal.h:1403
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:1374
int off_t offset
Definition: microhttpd.h:2837
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:4018
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
#define XDLL_remove(head, tail, element)
Definition: internal.h:1806
unsigned int connection_timeout_dummy
Definition: internal.h:845
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:335
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:699
#define MHD_ERR_BADF_
Definition: internal.h:1885
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1169
size_t pool_size
Definition: internal.h:1443
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2584
struct MHD_itc_ itc
Definition: internal.h:1407
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:736
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
struct MHD_Connection * cleanup_tail
Definition: internal.h:1179
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3314
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2672
enum MHD_ResponseFlags flags
Definition: internal.h:387
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:464
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
struct MHD_HTTP_Header * next
Definition: internal.h:339
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:760
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2754
size_t write_buffer_append_offset
Definition: internal.h:790
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1132
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1368
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
#define MHD_BUF_INC_SIZE
Definition: internal.h:117
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:446
bool read_closed
Definition: internal.h:789
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3877
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:766
void * notify_completed_cls
Definition: internal.h:1373
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2360
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:740
#define MHD_ERR_NOTCONN_
Definition: internal.h:1875
struct MemoryPool * pool
Definition: internal.h:682
TransmitCallback send_cls
Definition: internal.h:708
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:690
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:383
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:1597
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2212
MHD_mutex_ mutex
Definition: internal.h:1634
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
_MHD_static_inline bool socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:482
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
bool suspended
Definition: internal.h:761
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:452
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:311
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
#define MHD_MIN(a, b)
Definition: internal.h:107
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1163
_MHD_static_inline bool socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:553
size_t read_buffer_offset
Definition: internal.h:774
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:2008
void * default_handler_cls
Definition: internal.h:1259
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1523
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:259
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1262
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:1044
uint64_t current_chunk_size
Definition: internal.h:943
struct MHD_HTTP_Header * headers_received
Definition: internal.h:655
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:310
limits values definitions
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:508
_MHD_static_inline bool socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:501
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
_MHD_EXTERN int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:742
#define REQUEST_TOO_BIG
Definition: connection.c:73
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:660
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1406
size_t pool_increment
Definition: internal.h:1448
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:764