GNU libmicrohttpd  0.9.65
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2019 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 
690 int
692  enum MHD_ValueKind kind,
693  MHD_KeyValueIterator iterator,
694  void *iterator_cls)
695 {
696  int ret;
697  struct MHD_HTTP_Header *pos;
698 
699  if (NULL == connection)
700  return -1;
701  ret = 0;
702  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
703  if (0 != (pos->kind & kind))
704  {
705  ret++;
706  if ( (NULL != iterator) &&
707  (MHD_YES != iterator (iterator_cls,
708  pos->kind,
709  pos->header,
710  pos->value)) )
711  return ret;
712  }
713  return ret;
714 }
715 
716 
729 int
731  enum MHD_ValueKind kind,
732  MHD_KeyValueIteratorN iterator,
733  void *iterator_cls)
734 {
735  int ret;
736  struct MHD_HTTP_Header *pos;
737 
738  if (NULL == connection)
739  return -1;
740  ret = 0;
741 
742  if (NULL == iterator)
743  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
744  {
745  if (kind == pos->kind)
746  ret++;
747  }
748  else
749  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
750  if (kind == pos->kind)
751  {
752  ret++;
753  if (MHD_NO == iterator (iterator_cls,
754  pos->kind,
755  pos->header,
756  pos->header_size,
757  pos->value,
758  pos->value_size))
759  return ret;
760  }
761  return ret;
762 }
763 
764 
782 static int
784  enum MHD_ValueKind kind,
785  const char *key,
786  size_t key_size,
787  const char *value,
788  size_t value_size)
789 {
790  struct MHD_HTTP_Header *pos;
791 
792  pos = MHD_pool_allocate (connection->pool,
793  sizeof (struct MHD_HTTP_Header),
794  true);
795  if (NULL == pos)
796  return MHD_NO;
797  pos->header = (char *) key;
798  pos->header_size = key_size;
799  pos->value = (char *) value;
800  pos->value_size = value_size;
801  pos->kind = kind;
802  pos->next = NULL;
803  /* append 'pos' to the linked list of headers */
804  if (NULL == connection->headers_received_tail)
805  {
806  connection->headers_received = pos;
807  connection->headers_received_tail = pos;
808  }
809  else
810  {
811  connection->headers_received_tail->next = pos;
812  connection->headers_received_tail = pos;
813  }
814  return MHD_YES;
815 }
816 
817 
843 int
845  enum MHD_ValueKind kind,
846  const char *key,
847  size_t key_size,
848  const char *value,
849  size_t value_size)
850 {
851  if ( (MHD_GET_ARGUMENT_KIND != kind) &&
852  ( ((key ? strlen(key) : 0) != key_size) ||
853  ((value ? strlen(value) : 0) != value_size) ) )
854  return MHD_NO; /* binary zero is allowed only in GET arguments */
855 
856  return MHD_set_connection_value_n_nocheck_ (connection,
857  kind,
858  key,
859  key_size,
860  value,
861  value_size);
862 }
863 
864 
890 int
892  enum MHD_ValueKind kind,
893  const char *key,
894  const char *value)
895 {
896  return MHD_set_connection_value_n_nocheck_ (connection,
897  kind,
898  key,
899  NULL != key
900  ? strlen (key)
901  : 0,
902  value,
903  NULL != value
904  ? strlen (value)
905  : 0);
906 }
907 
908 
919 const char *
921  enum MHD_ValueKind kind,
922  const char *key)
923 {
924  const char *value;
925 
926  value = NULL;
927  (void) MHD_lookup_connection_value_n (connection,
928  kind,
929  key,
930  (NULL == key) ? 0 : strlen(key),
931  &value,
932  NULL);
933  return value;
934 }
935 
936 
956 _MHD_EXTERN int
958  enum MHD_ValueKind kind,
959  const char *key,
960  size_t key_size,
961  const char **value_ptr,
962  size_t *value_size_ptr)
963 {
964  struct MHD_HTTP_Header *pos;
965 
966  if (NULL == connection)
967  return MHD_NO;
968 
969  if (NULL == key)
970  {
971  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
972  {
973  if ( (kind == pos->kind) &&
974  (NULL == pos->header) )
975  break;
976  }
977  }
978  else
979  {
980  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
981  {
982  if ( (kind == pos->kind) &&
983  (key_size == pos->header_size) &&
984  ( (key == pos->header) ||
986  pos->header,
987  key_size) ) ) )
988  break;
989  }
990  }
991 
992  if (NULL == pos)
993  return MHD_NO;
994 
995  if (NULL != value_ptr)
996  *value_ptr = pos->value;
997 
998  if (NULL != value_size_ptr)
999  *value_size_ptr = pos->value_size;
1000 
1001  return MHD_YES;
1002 }
1003 
1004 
1020 static bool
1021 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
1022  const char *header,
1023  size_t header_len,
1024  const char *token,
1025  size_t token_len)
1026 {
1027  struct MHD_HTTP_Header *pos;
1028 
1029  if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0])
1030  return false;
1031 
1032  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
1033  {
1034  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
1035  (header_len == pos->header_size) &&
1036  ( (header == pos->header) ||
1038  pos->header,
1039  header_len)) ) &&
1040  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
1041  return true;
1042  }
1043  return false;
1044 }
1045 
1046 
1058 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
1059  MHD_lookup_header_token_ci((c),(h),MHD_STATICSTR_LEN_(h),\
1060  (tkn),MHD_STATICSTR_LEN_(tkn))
1061 
1062 
1070 static int
1071 need_100_continue (struct MHD_Connection *connection)
1072 {
1073  const char *expect;
1074 
1075  return ( (NULL == connection->response) &&
1076  (NULL != connection->version) &&
1077  (MHD_str_equal_caseless_(connection->version,
1079  (MHD_NO != MHD_lookup_connection_value_n (connection,
1083  &expect,
1084  NULL)) &&
1085  (MHD_str_equal_caseless_(expect,
1086  "100-continue")) &&
1087  (connection->continue_message_write_offset <
1089 }
1090 
1091 
1098 void
1100 {
1101  const struct MHD_Daemon *daemon = connection->daemon;
1102 
1103  connection->state = MHD_CONNECTION_CLOSED;
1105  if (0 == (daemon->options & MHD_USE_TURBO))
1106  {
1107 #ifdef HTTPS_SUPPORT
1108  /* For TLS connection use shutdown of TLS layer
1109  * and do not shutdown TCP socket. This give more
1110  * chances to send TLS closure data to remote side.
1111  * Closure of TLS layer will be interpreted by
1112  * remote side as end of transmission. */
1113  if (0 != (daemon->options & MHD_USE_TLS))
1114  {
1115  if (! MHD_tls_connection_shutdown(connection))
1116  shutdown (connection->socket_fd,
1117  SHUT_WR);
1118  }
1119  else /* Combined with next 'shutdown()'. */
1120 #endif /* HTTPS_SUPPORT */
1121  shutdown (connection->socket_fd,
1122  SHUT_WR);
1123  }
1124 }
1125 
1126 
1136 void
1138  enum MHD_RequestTerminationCode termination_code)
1139 {
1140  struct MHD_Daemon *daemon = connection->daemon;
1141  struct MHD_Response *resp = connection->response;
1142 
1143  MHD_connection_mark_closed_ (connection);
1144  if (NULL != resp)
1145  {
1146  connection->response = NULL;
1147  MHD_destroy_response (resp);
1148  }
1149  if ( (NULL != daemon->notify_completed) &&
1150  (connection->client_aware) )
1151  daemon->notify_completed (daemon->notify_completed_cls,
1152  connection,
1153  &connection->client_context,
1154  termination_code);
1155  connection->client_aware = false;
1156 }
1157 
1158 
1159 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
1160 
1170 void
1172 {
1173  struct MHD_Daemon *daemon = connection->daemon;
1174  struct MHD_UpgradeResponseHandle *urh = connection->urh;
1175 
1176  if (0 == (daemon->options & MHD_USE_TLS))
1177  return; /* Nothing to do with non-TLS connection. */
1178 
1179  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
1180  DLL_remove (daemon->urh_head,
1181  daemon->urh_tail,
1182  urh);
1183 #if EPOLL_SUPPORT
1184  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
1185  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1186  EPOLL_CTL_DEL,
1187  connection->socket_fd,
1188  NULL)) )
1189  {
1190  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
1191  }
1192  if (urh->in_eready_list)
1193  {
1194  EDLL_remove (daemon->eready_urh_head,
1195  daemon->eready_urh_tail,
1196  urh);
1197  urh->in_eready_list = false;
1198  }
1199 #endif /* EPOLL_SUPPORT */
1200  if (MHD_INVALID_SOCKET != urh->mhd.socket)
1201  {
1202 #if EPOLL_SUPPORT
1203  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
1204  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1205  EPOLL_CTL_DEL,
1206  urh->mhd.socket,
1207  NULL)) )
1208  {
1209  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
1210  }
1211 #endif /* EPOLL_SUPPORT */
1212  /* Reflect remote disconnect to application by breaking
1213  * socketpair connection. */
1214  shutdown (urh->mhd.socket, SHUT_RDWR);
1215  }
1216  /* Socketpair sockets will remain open as they will be
1217  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
1218  * closed by MHD_cleanup_upgraded_connection_() during
1219  * connection's final cleanup.
1220  */
1221 }
1222 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
1223 
1224 
1232 static void
1234  const char *emsg)
1235 {
1236 #ifdef HAVE_MESSAGES
1237  if (NULL != emsg)
1238  MHD_DLOG (connection->daemon,
1239  emsg);
1240 #else /* ! HAVE_MESSAGES */
1241  (void)emsg; /* Mute compiler warning. */
1242 #endif /* ! HAVE_MESSAGES */
1243  MHD_connection_close_ (connection,
1245 }
1246 
1247 
1252 #ifdef HAVE_MESSAGES
1253 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
1254 #else
1255 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
1256 #endif
1257 
1258 
1271 static int
1273 {
1274  ssize_t ret;
1275  struct MHD_Response *response;
1276 
1277  response = connection->response;
1278  if (NULL == response->crc)
1279  return MHD_YES;
1280  if ( (0 == response->total_size) ||
1281  (connection->response_write_position == response->total_size) )
1282  return MHD_YES; /* 0-byte response is always ready */
1283  if ( (response->data_start <=
1284  connection->response_write_position) &&
1285  (response->data_size + response->data_start >
1286  connection->response_write_position) )
1287  return MHD_YES; /* response already ready */
1288 #if defined(_MHD_HAVE_SENDFILE)
1289  if (MHD_resp_sender_sendfile == connection->resp_sender)
1290  {
1291  /* will use sendfile, no need to bother response crc */
1292  return MHD_YES;
1293  }
1294 #endif /* _MHD_HAVE_SENDFILE */
1295 
1296  ret = response->crc (response->crc_cls,
1297  connection->response_write_position,
1298  response->data,
1299  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
1300  response->total_size -
1301  connection->response_write_position));
1302  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1303  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
1304  {
1305  /* either error or http 1.0 transfer, close socket! */
1306  response->total_size = connection->response_write_position;
1307 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1308  MHD_mutex_unlock_chk_ (&response->mutex);
1309 #endif
1310  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
1311  MHD_connection_close_ (connection,
1313  else
1314  CONNECTION_CLOSE_ERROR (connection,
1315  _("Closing connection (application reported error generating data)\n"));
1316  return MHD_NO;
1317  }
1318  response->data_start = connection->response_write_position;
1319  response->data_size = ret;
1320  if (0 == ret)
1321  {
1323 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1324  MHD_mutex_unlock_chk_ (&response->mutex);
1325 #endif
1326  return MHD_NO;
1327  }
1328  return MHD_YES;
1329 }
1330 
1331 
1341 static int
1343 {
1344  ssize_t ret;
1345  struct MHD_Response *response;
1346  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
1347  int cblen;
1348 
1349  response = connection->response;
1350  if (NULL == response->crc)
1351  return MHD_YES;
1352  if (0 == connection->write_buffer_size)
1353  {
1354  size_t size;
1355 
1356  size = MHD_pool_get_free (connection->pool);
1357  if (size < 128)
1358  {
1359 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1360  MHD_mutex_unlock_chk_ (&response->mutex);
1361 #endif
1362  /* not enough memory */
1363  CONNECTION_CLOSE_ERROR (connection,
1364  _("Closing connection (out of memory)\n"));
1365  return MHD_NO;
1366  }
1367  if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
1368  size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
1369  connection->write_buffer = MHD_pool_allocate (connection->pool,
1370  size,
1371  false);
1372  mhd_assert (NULL != connection->write_buffer);
1373  connection->write_buffer_size = size;
1374  }
1375 
1376  if (0 == response->total_size)
1377  ret = 0; /* response must be empty, don't bother calling crc */
1378  else if ( (response->data_start <=
1379  connection->response_write_position) &&
1380  (response->data_start + response->data_size >
1381  connection->response_write_position) )
1382  {
1383  /* difference between response_write_position and data_start is less
1384  than data_size which is size_t type, no need to check for overflow */
1385  const size_t data_write_offset
1386  = (size_t)(connection->response_write_position - response->data_start);
1387  /* buffer already ready, use what is there for the chunk */
1388  ret = response->data_size - data_write_offset;
1389  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
1390  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1391  memcpy (&connection->write_buffer[sizeof (cbuf)],
1392  &response->data[data_write_offset],
1393  ret);
1394  }
1395  else
1396  {
1397  /* buffer not in range, try to fill it */
1398  ret = response->crc (response->crc_cls,
1399  connection->response_write_position,
1400  &connection->write_buffer[sizeof (cbuf)],
1401  connection->write_buffer_size - sizeof (cbuf) - 2);
1402  }
1403  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1404  {
1405  /* error, close socket! */
1406  response->total_size = connection->response_write_position;
1407 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1408  MHD_mutex_unlock_chk_ (&response->mutex);
1409 #endif
1410  CONNECTION_CLOSE_ERROR (connection,
1411  _("Closing connection (application error generating response)\n"));
1412  return MHD_NO;
1413  }
1414  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1415  (0 == response->total_size) )
1416  {
1417  /* end of message, signal other side! */
1418  memcpy (connection->write_buffer,
1419  "0\r\n",
1420  3);
1421  connection->write_buffer_append_offset = 3;
1422  connection->write_buffer_send_offset = 0;
1423  response->total_size = connection->response_write_position;
1424  return MHD_YES;
1425  }
1426  if (0 == ret)
1427  {
1429 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1430  MHD_mutex_unlock_chk_ (&response->mutex);
1431 #endif
1432  return MHD_NO;
1433  }
1434  if (ret > 0xFFFFFF)
1435  ret = 0xFFFFFF;
1436  cblen = MHD_snprintf_(cbuf,
1437  sizeof (cbuf),
1438  "%X\r\n",
1439  (unsigned int) ret);
1440  mhd_assert(cblen > 0);
1441  mhd_assert((size_t)cblen < sizeof(cbuf));
1442  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1443  cbuf,
1444  cblen);
1445  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1446  "\r\n",
1447  2);
1448  connection->response_write_position += ret;
1449  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1450  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1451  return MHD_YES;
1452 }
1453 
1454 
1471 static int
1473 {
1474  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1475  return MHD_NO;
1476  if (NULL == connection->version)
1477  return MHD_NO;
1478  if ( (NULL != connection->response) &&
1479  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1480  return MHD_NO;
1481 
1482  if (MHD_str_equal_caseless_(connection->version,
1484  ( (NULL == connection->response) ||
1485  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE) ) ) )
1486  {
1487  if (MHD_lookup_header_s_token_ci (connection,
1489  "upgrade"))
1490  return MHD_NO;
1491 
1492  if (MHD_lookup_header_s_token_ci (connection,
1494  "close"))
1495  return MHD_NO;
1496 
1497  return MHD_YES;
1498  }
1499  if (MHD_str_equal_caseless_(connection->version,
1501  {
1502  if (MHD_lookup_header_s_token_ci (connection,
1504  "Keep-Alive"))
1505  return MHD_YES;
1506 
1507  return MHD_NO;
1508  }
1509  return MHD_NO;
1510 }
1511 
1512 
1520 static void
1521 get_date_string (char *date,
1522  size_t date_len)
1523 {
1524  static const char *const days[] = {
1525  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1526  };
1527  static const char *const mons[] = {
1528  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1529  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1530  };
1531  struct tm now;
1532  time_t t;
1533 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
1534  struct tm* pNow;
1535 #endif
1536 
1537  date[0] = 0;
1538  time (&t);
1539 #if defined(HAVE_C11_GMTIME_S)
1540  if (NULL == gmtime_s (&t,
1541  &now))
1542  return;
1543 #elif defined(HAVE_W32_GMTIME_S)
1544  if (0 != gmtime_s (&now,
1545  &t))
1546  return;
1547 #elif defined(HAVE_GMTIME_R)
1548  if (NULL == gmtime_r(&t,
1549  &now))
1550  return;
1551 #else
1552  pNow = gmtime(&t);
1553  if (NULL == pNow)
1554  return;
1555  now = *pNow;
1556 #endif
1557  MHD_snprintf_ (date,
1558  date_len,
1559  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1560  days[now.tm_wday % 7],
1561  (unsigned int) now.tm_mday,
1562  mons[now.tm_mon % 12],
1563  (unsigned int) (1900 + now.tm_year),
1564  (unsigned int) now.tm_hour,
1565  (unsigned int) now.tm_min,
1566  (unsigned int) now.tm_sec);
1567 }
1568 
1569 
1582 static bool
1584  bool required)
1585 {
1586  size_t new_size;
1587  size_t avail_size;
1588 
1589  avail_size = MHD_pool_get_free (connection->pool);
1590  if (0 == avail_size)
1591  return false; /* No more space available */
1592  if (0 == connection->read_buffer_size)
1593  new_size = avail_size / 2; /* Use half of available buffer for reading */
1594  else
1595  {
1596  size_t grow_size;
1597 
1598  grow_size = avail_size / 8;
1599  if (MHD_BUF_INC_SIZE > grow_size)
1600  { /* Shortage of space */
1601  if (!required)
1602  return false; /* Grow is not mandatory, leave some space in pool */
1603  else
1604  {
1605  /* Shortage of space, but grow is mandatory */
1606  static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
1607  if (small_inc < avail_size)
1608  grow_size = small_inc;
1609  else
1610  grow_size = avail_size;
1611  }
1612  }
1613  new_size = connection->read_buffer_size + grow_size;
1614  }
1615  /* we can actually grow the buffer, do it! */
1616  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1617  connection->read_buffer,
1618  connection->read_buffer_size,
1619  new_size);
1620  mhd_assert (NULL != connection->read_buffer);
1621  connection->read_buffer_size = new_size;
1622  return true;
1623 }
1624 
1625 
1635 static int
1637 {
1638  struct MHD_Response *response = connection->response;
1639  size_t size;
1640  size_t off;
1641  struct MHD_HTTP_Header *pos;
1642  char code[256];
1643  char date[128];
1644  size_t datelen;
1645  char content_length_buf[128];
1646  size_t content_length_len;
1647  char *data;
1648  enum MHD_ValueKind kind;
1649  const char *reason_phrase;
1650  uint32_t rc;
1651  bool client_requested_close;
1652  bool response_has_close;
1653  bool response_has_keepalive;
1654  const char *have_encoding;
1655  int must_add_close;
1656  int must_add_chunked_encoding;
1657  int must_add_keep_alive;
1658  int must_add_content_length;
1659  int may_add_content_length;
1660 
1661  mhd_assert (NULL != connection->version);
1662  if (0 == connection->version[0])
1663  {
1664  data = MHD_pool_allocate (connection->pool,
1665  0,
1666  true);
1667  connection->write_buffer = data;
1668  connection->write_buffer_append_offset = 0;
1669  connection->write_buffer_send_offset = 0;
1670  connection->write_buffer_size = 0;
1671  return MHD_YES;
1672  }
1673  rc = connection->responseCode & (~MHD_ICY_FLAG);
1674  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1675  {
1676  reason_phrase = MHD_get_reason_phrase_for (rc);
1677  off = MHD_snprintf_ (code,
1678  sizeof (code),
1679  "%s %u %s\r\n",
1680  (0 != (connection->responseCode & MHD_ICY_FLAG))
1681  ? "ICY"
1683  connection->version) ||
1684  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE)) )
1687  rc,
1688  reason_phrase);
1689  /* estimate size */
1690  size = off + 2; /* +2 for extra "\r\n" at the end */
1692  if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1693  (NULL == MHD_get_response_header (response,
1695  get_date_string (date,
1696  sizeof (date));
1697  else
1698  date[0] = '\0';
1699  datelen = strlen (date);
1700  size += datelen;
1701  }
1702  else
1703  {
1704  /* 2 bytes for final CRLF of a Chunked-Body */
1705  size = 2;
1707  off = 0;
1708  datelen = 0;
1709  }
1710 
1711  /* calculate extra headers we need to add, such as 'Connection: close',
1712  first see what was explicitly requested by the application */
1713  must_add_close = MHD_NO;
1714  must_add_chunked_encoding = MHD_NO;
1715  must_add_keep_alive = MHD_NO;
1716  must_add_content_length = MHD_NO;
1717  response_has_close = false;
1718  switch (connection->state)
1719  {
1721  response_has_close = MHD_check_response_header_s_token_ci (response,
1723  "close");
1724  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1726  "Keep-Alive");
1727  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1729  "close");
1730 
1731  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1732  connection->keepalive = MHD_CONN_MUST_CLOSE;
1733 #ifdef UPGRADE_SUPPORT
1734  else if (NULL != response->upgrade_handler)
1735  /* If this connection will not be "upgraded", it must be closed. */
1736  connection->keepalive = MHD_CONN_MUST_CLOSE;
1737 #endif /* UPGRADE_SUPPORT */
1738 
1739  /* now analyze chunked encoding situation */
1740  connection->have_chunked_upload = false;
1741  have_encoding = MHD_get_response_header (response,
1743  if (NULL == have_encoding)
1744  may_add_content_length = MHD_YES;
1745  else
1746  may_add_content_length = MHD_NO; /* RFC 7230, Section 3.3.2 forbids header */
1747  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1748 #ifdef UPGRADE_SUPPORT
1749  (NULL == response->upgrade_handler) &&
1750 #endif /* UPGRADE_SUPPORT */
1751  (! response_has_close) &&
1752  (! client_requested_close) )
1753  {
1754  /* size is unknown, and close was not explicitly requested;
1755  need to either to HTTP 1.1 chunked encoding or
1756  close the connection */
1757  /* 'close' header doesn't exist yet, see if we need to add one;
1758  if the client asked for a close, no need to start chunk'ing */
1759  if ( (MHD_YES == keepalive_possible (connection)) &&
1761  connection->version) ) )
1762  {
1763  if (NULL == have_encoding)
1764  {
1765  must_add_chunked_encoding = MHD_YES;
1766  connection->have_chunked_upload = true;
1767  }
1768  else
1769  {
1770  if (MHD_str_equal_caseless_ (have_encoding,
1771  "identity"))
1772  {
1773  /* application forced identity encoding, can't do 'chunked' */
1774  must_add_close = MHD_YES;
1775  }
1776  else
1777  {
1778  connection->have_chunked_upload = true;
1779  }
1780  }
1781  }
1782  else
1783  {
1784  /* Keep alive or chunking not possible
1785  => set close header if not present */
1786  if (! response_has_close)
1787  must_add_close = MHD_YES;
1788  }
1789  }
1790 
1791  /* check for other reasons to add 'close' header */
1792  if ( ( (client_requested_close) ||
1793  (connection->read_closed) ||
1794  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1795  (! response_has_close) &&
1796 #ifdef UPGRADE_SUPPORT
1797  (NULL == response->upgrade_handler) &&
1798 #endif /* UPGRADE_SUPPORT */
1799  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1800  must_add_close = MHD_YES;
1801 
1802  /* check if we must add 'close' header because we cannot add content-length
1803  because it is forbidden AND we don't have a 'chunked' encoding */
1804  if ( (! may_add_content_length) &&
1805  (! connection->have_chunked_upload) &&
1806  (! response_has_close) )
1807  must_add_close = MHD_YES;
1808  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1809  codes SHOULD NOT have a Content-Length according to spec;
1810  also chunked encoding / unknown length or CONNECT... */
1811  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1812  (MHD_HTTP_NO_CONTENT != rc) &&
1813  (MHD_HTTP_NOT_MODIFIED != rc) &&
1814  (MHD_HTTP_OK <= rc) &&
1815  (NULL == /* this should always succeed due to check in
1816  MHD_add_response_header() */
1817  MHD_get_response_header (response,
1819  (may_add_content_length) &&
1820  ( (NULL == connection->method) ||
1821  (! MHD_str_equal_caseless_ (connection->method,
1823  {
1824  /*
1825  Here we add a content-length if one is missing; however,
1826  for 'connect' methods, the responses MUST NOT include a
1827  content-length header *if* the response code is 2xx (in
1828  which case we expect there to be no body). Still,
1829  as we don't know the response code here in some cases, we
1830  simply only force adding a content-length header if this
1831  is not a 'connect' or if the response is not empty
1832  (which is kind of more sane, because if some crazy
1833  application did return content with a 2xx status code,
1834  then having a content-length might again be a good idea).
1835 
1836  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1837  a recent development of the HTTP 1.1 specification.
1838  */
1839  content_length_len
1840  = MHD_snprintf_ (content_length_buf,
1841  sizeof (content_length_buf),
1843  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1844  must_add_content_length = MHD_YES;
1845  }
1846 
1847  /* check for adding keep alive */
1848  if ( (! response_has_keepalive) &&
1849  (! response_has_close) &&
1850  (MHD_NO == must_add_close) &&
1851  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1852 #ifdef UPGRADE_SUPPORT
1853  (NULL == response->upgrade_handler) &&
1854 #endif /* UPGRADE_SUPPORT */
1855  (MHD_YES == keepalive_possible (connection)) )
1856  must_add_keep_alive = MHD_YES;
1857  break;
1859  response_has_keepalive = false;
1860  break;
1861  default:
1862  mhd_assert (0);
1863  return MHD_NO;
1864  }
1865 
1866  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1867  {
1868  if ( (must_add_close) || (response_has_close) )
1869  connection->keepalive = MHD_CONN_MUST_CLOSE;
1870  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1871  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1872  }
1873 
1874  if (must_add_close)
1875  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1876  if (must_add_keep_alive)
1877  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1878  if (must_add_chunked_encoding)
1879  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1880  if (must_add_content_length)
1881  size += content_length_len;
1882  mhd_assert (! (must_add_close && must_add_keep_alive) );
1883  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1884 
1885  for (pos = response->first_header; NULL != pos; pos = pos->next)
1886  {
1887  /* TODO: add proper support for excluding "Keep-Alive" token. */
1888  if ( (pos->kind == kind) &&
1889  (! ( (MHD_YES == must_add_close) &&
1890  (response_has_keepalive) &&
1896  "Keep-Alive")) ) ) )
1897  size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */
1898  }
1899  /* produce data */
1900  data = MHD_pool_allocate (connection->pool,
1901  size + 1,
1902  false);
1903  if (NULL == data)
1904  {
1905 #ifdef HAVE_MESSAGES
1906  MHD_DLOG (connection->daemon,
1907  "Not enough memory for write!\n");
1908 #endif
1909  return MHD_NO;
1910  }
1911  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1912  {
1913  memcpy (data,
1914  code,
1915  off);
1916  }
1917  if (must_add_close)
1918  {
1919  /* we must add the 'Connection: close' header */
1920  memcpy (&data[off],
1921  "Connection: close\r\n",
1922  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1923  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1924  }
1925  if (must_add_keep_alive)
1926  {
1927  /* we must add the 'Connection: Keep-Alive' header */
1928  memcpy (&data[off],
1929  "Connection: Keep-Alive\r\n",
1930  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1931  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1932  }
1933  if (must_add_chunked_encoding)
1934  {
1935  /* we must add the 'Transfer-Encoding: chunked' header */
1936  memcpy (&data[off],
1937  "Transfer-Encoding: chunked\r\n",
1938  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1939  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1940  }
1941  if (must_add_content_length)
1942  {
1943  /* we must add the 'Content-Length' header */
1944  memcpy (&data[off],
1945  content_length_buf,
1946  content_length_len);
1947  off += content_length_len;
1948  }
1949  for (pos = response->first_header; NULL != pos; pos = pos->next)
1950  {
1951  /* TODO: add proper support for excluding "Keep-Alive" token. */
1952  if ( (pos->kind == kind) &&
1953  (! ( (MHD_YES == must_add_close) &&
1954  (response_has_keepalive) &&
1960  "Keep-Alive")) ) ) )
1961  off += MHD_snprintf_ (&data[off],
1962  size - off,
1963  "%s: %s\r\n",
1964  pos->header,
1965  pos->value);
1966  }
1967  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1968  {
1969  memcpy (&data[off],
1970  date,
1971  datelen);
1972  off += datelen;
1973  }
1974  memcpy (&data[off],
1975  "\r\n",
1976  2);
1977  off += 2;
1978 
1979  if (off != size)
1981  __FILE__,
1982  __LINE__,
1983  NULL);
1984  connection->write_buffer = data;
1985  connection->write_buffer_append_offset = size;
1986  connection->write_buffer_send_offset = 0;
1987  connection->write_buffer_size = size + 1;
1988  return MHD_YES;
1989 }
1990 
1991 
2001 static void
2003  unsigned int status_code,
2004  const char *message)
2005 {
2006  struct MHD_Response *response;
2007  int iret;
2008 
2009  if (NULL == connection->version)
2010  {
2011  /* we were unable to process the full header line, so we don't
2012  really know what version the client speaks; assume 1.0 */
2013  connection->version = MHD_HTTP_VERSION_1_0;
2014  }
2015  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2016  connection->read_closed = true;
2017  if (0 != connection->read_buffer_size)
2018  {
2019  /* Read buffer is not needed anymore, discard it
2020  * to free some space for error response. */
2021  connection->read_buffer = MHD_pool_reallocate(connection->pool,
2022  connection->read_buffer,
2023  connection->read_buffer_size,
2024  0);
2025  connection->read_buffer_size = 0;
2026  }
2027 #ifdef HAVE_MESSAGES
2028  MHD_DLOG (connection->daemon,
2029  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
2030  status_code,
2031  message);
2032 #endif
2033  if (NULL != connection->response)
2034  {
2035  MHD_destroy_response (connection->response);
2036  connection->response = NULL;
2037  }
2038  response = MHD_create_response_from_buffer (strlen (message),
2039  (void *) message,
2041  if (NULL == response)
2042  {
2043  /* can't even send a reply, at least close the connection */
2044  connection->state = MHD_CONNECTION_CLOSED;
2045  return;
2046  }
2047  iret = MHD_queue_response (connection,
2048  status_code,
2049  response);
2050  MHD_destroy_response (response);
2051  if (MHD_YES != iret)
2052  {
2053  /* can't even send a reply, at least close the connection */
2054  CONNECTION_CLOSE_ERROR (connection,
2055  _("Closing connection (failed to queue response)\n"));
2056  return;
2057  }
2058  mhd_assert (NULL != connection->response);
2059  /* Do not reuse this connection. */
2060  connection->keepalive = MHD_CONN_MUST_CLOSE;
2061  if (MHD_NO == build_header_response (connection))
2062  {
2063  /* oops - close! */
2064  CONNECTION_CLOSE_ERROR (connection,
2065  _("Closing connection (failed to create response header)\n"));
2066  }
2067  else
2068  {
2069  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2070  }
2071 }
2072 
2073 
2082 static void
2084 {
2085  /* Do not update states of suspended connection */
2086  if (connection->suspended)
2087  return; /* States will be updated after resume. */
2088 #ifdef HTTPS_SUPPORT
2089  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2090  { /* HTTPS connection. */
2091  switch (connection->tls_state)
2092  {
2093  case MHD_TLS_CONN_INIT:
2095  return;
2097  if (0 == gnutls_record_get_direction (connection->tls_session))
2099  else
2101  return;
2102  default:
2103  break;
2104  }
2105  }
2106 #endif /* HTTPS_SUPPORT */
2107  while (1)
2108  {
2109 #if DEBUG_STATES
2110  MHD_DLOG (connection->daemon,
2111  _("In function %s handling connection at state: %s\n"),
2112  __FUNCTION__,
2113  MHD_state_to_string (connection->state));
2114 #endif
2115  switch (connection->state)
2116  {
2117  case MHD_CONNECTION_INIT:
2120  /* while reading headers, we always grow the
2121  read buffer if needed, no size-check required */
2122  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
2123  (!try_grow_read_buffer (connection, true)) )
2124  {
2125  transmit_error_response (connection,
2126  (connection->url != NULL)
2129  REQUEST_TOO_BIG);
2130  continue;
2131  }
2132  if (! connection->read_closed)
2134  else
2136  break;
2138  mhd_assert (0);
2139  break;
2141  mhd_assert (0);
2142  break;
2145  break;
2147  if (connection->read_buffer_offset == connection->read_buffer_size)
2148  {
2149  const bool internal_poll = (0 != (connection->daemon->options &
2151  if ( (!try_grow_read_buffer (connection, true)) &&
2152  internal_poll)
2153  {
2154  /* failed to grow the read buffer, and the
2155  client which is supposed to handle the
2156  received data in a *blocking* fashion
2157  (in this mode) did not handle the data as
2158  it was supposed to!
2159  => we would either have to do busy-waiting
2160  (on the client, which would likely fail),
2161  or if we do nothing, we would just timeout
2162  on the connection (if a timeout is even
2163  set!).
2164  Solution: we kill the connection with an error */
2165  transmit_error_response (connection,
2167  INTERNAL_ERROR);
2168  continue;
2169  }
2170  }
2171  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
2172  (! connection->read_closed) )
2174  else
2176  break;
2179  /* while reading footers, we always grow the
2180  read buffer if needed, no size-check required */
2181  if (connection->read_closed)
2182  {
2183  CONNECTION_CLOSE_ERROR (connection,
2184  NULL);
2185  continue;
2186  }
2188  /* transition to FOOTERS_RECEIVED
2189  happens in read handler */
2190  break;
2193  break;
2195  /* headers in buffer, keep writing */
2197  break;
2199  mhd_assert (0);
2200  break;
2203  break;
2206  break;
2209  break;
2212  break;
2214  mhd_assert (0);
2215  break;
2218  break;
2220  mhd_assert (0);
2221  break;
2222  case MHD_CONNECTION_CLOSED:
2224  return; /* do nothing, not even reading */
2225 #ifdef UPGRADE_SUPPORT
2226  case MHD_CONNECTION_UPGRADE:
2227  mhd_assert (0);
2228  break;
2229 #endif /* UPGRADE_SUPPORT */
2230  default:
2231  mhd_assert (0);
2232  }
2233  break;
2234  }
2235 }
2236 
2237 
2251 static char *
2253  size_t *line_len)
2254 {
2255  char *rbuf;
2256  size_t pos;
2257 
2258  if (0 == connection->read_buffer_offset)
2259  return NULL;
2260  pos = 0;
2261  rbuf = connection->read_buffer;
2262  while ( (pos < connection->read_buffer_offset - 1) &&
2263  ('\r' != rbuf[pos]) &&
2264  ('\n' != rbuf[pos]) )
2265  pos++;
2266  if ( (pos == connection->read_buffer_offset - 1) &&
2267  ('\n' != rbuf[pos]) )
2268  {
2269  /* not found, consider growing... */
2270  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
2271  (!try_grow_read_buffer (connection, true)) )
2272  {
2273  transmit_error_response (connection,
2274  (NULL != connection->url)
2277  REQUEST_TOO_BIG);
2278  }
2279  if (line_len)
2280  *line_len = 0;
2281  return NULL;
2282  }
2283 
2284  if (line_len)
2285  *line_len = pos;
2286  /* found, check if we have proper LFCR */
2287  if ( ('\r' == rbuf[pos]) &&
2288  ('\n' == rbuf[pos + 1]) )
2289  rbuf[pos++] = '\0'; /* skip both r and n */
2290  rbuf[pos++] = '\0';
2291  connection->read_buffer += pos;
2292  connection->read_buffer_size -= pos;
2293  connection->read_buffer_offset -= pos;
2294  return rbuf;
2295 }
2296 
2297 
2311 static int
2313  const char *key,
2314  size_t key_size,
2315  const char *value,
2316  size_t value_size,
2317  enum MHD_ValueKind kind)
2318 {
2319  if (MHD_NO ==
2320  MHD_set_connection_value_n (connection,
2321  kind,
2322  key,
2323  key_size,
2324  value,
2325  value_size))
2326  {
2327 #ifdef HAVE_MESSAGES
2328  MHD_DLOG (connection->daemon,
2329  _("Not enough memory in pool to allocate header record!\n"));
2330 #endif
2331  transmit_error_response (connection,
2333  REQUEST_TOO_BIG);
2334  return MHD_NO;
2335  }
2336  return MHD_YES;
2337 }
2338 
2339 
2346 static int
2348 {
2349  const char *hdr;
2350  size_t hdr_len;
2351  char *cpy;
2352  char *pos;
2353  char *sce;
2354  char *semicolon;
2355  char *equals;
2356  char *ekill;
2357  char *end;
2358  char old;
2359  int quotes;
2360 
2361  if (MHD_NO == MHD_lookup_connection_value_n (connection,
2365  &hdr,
2366  &hdr_len))
2367  return MHD_YES;
2368  cpy = MHD_pool_allocate (connection->pool,
2369  hdr_len + 1,
2370  true);
2371  if (NULL == cpy)
2372  {
2373 #ifdef HAVE_MESSAGES
2374  MHD_DLOG (connection->daemon,
2375  _("Not enough memory in pool to parse cookies!\n"));
2376 #endif
2377  transmit_error_response (connection,
2379  REQUEST_TOO_BIG);
2380  return MHD_NO;
2381  }
2382  memcpy (cpy,
2383  hdr,
2384  hdr_len);
2385  cpy[hdr_len] = '\0';
2386  pos = cpy;
2387  while (NULL != pos)
2388  {
2389  while (' ' == *pos)
2390  pos++; /* skip spaces */
2391 
2392  sce = pos;
2393  while ( ((*sce) != '\0') &&
2394  ((*sce) != ',') &&
2395  ((*sce) != ';') &&
2396  ((*sce) != '=') )
2397  sce++;
2398  /* remove tailing whitespace (if any) from key */
2399  ekill = sce - 1;
2400  while ( (*ekill == ' ') &&
2401  (ekill >= pos) )
2402  *(ekill--) = '\0';
2403  old = *sce;
2404  *sce = '\0';
2405  if (old != '=')
2406  {
2407  /* value part omitted, use empty string... */
2408  if (MHD_NO ==
2409  connection_add_header (connection,
2410  pos,
2411  ekill - pos + 1,
2412  "",
2413  0,
2414  MHD_COOKIE_KIND))
2415  return MHD_NO;
2416  if (old == '\0')
2417  break;
2418  pos = sce + 1;
2419  continue;
2420  }
2421  equals = sce + 1;
2422  quotes = 0;
2423  semicolon = equals;
2424  while ( ('\0' != semicolon[0]) &&
2425  ( (0 != quotes) ||
2426  ( (';' != semicolon[0]) &&
2427  (',' != semicolon[0]) ) ) )
2428  {
2429  if ('"' == semicolon[0])
2430  quotes = (quotes + 1) & 1;
2431  semicolon++;
2432  }
2433  end = semicolon;
2434  if ('\0' == semicolon[0])
2435  semicolon = NULL;
2436  if (NULL != semicolon)
2437  {
2438  semicolon[0] = '\0';
2439  semicolon++;
2440  }
2441  /* remove quotes */
2442  if ( ('"' == equals[0]) &&
2443  ('"' == end[-1]) )
2444  {
2445  equals++;
2446  end--;
2447  *end = '\0';
2448  }
2449  if (MHD_NO ==
2450  connection_add_header (connection,
2451  pos,
2452  ekill - pos + 1,
2453  equals,
2454  end - equals,
2455  MHD_COOKIE_KIND))
2456  return MHD_NO;
2457  pos = semicolon;
2458  }
2459  return MHD_YES;
2460 }
2461 
2462 
2471 static int
2473  char *line,
2474  size_t line_len)
2475 {
2476  struct MHD_Daemon *daemon = connection->daemon;
2477  const char *curi;
2478  char *uri;
2479  char *http_version;
2480  char *args;
2481  unsigned int unused_num_headers;
2482 
2483  if (NULL == (uri = memchr (line,
2484  ' ',
2485  line_len)))
2486  return MHD_NO; /* serious error */
2487  uri[0] = '\0';
2488  connection->method = line;
2489  uri++;
2490  /* Skip any spaces. Not required by standard but allow
2491  to be more tolerant. */
2492  while ( (' ' == uri[0]) &&
2493  ( (size_t)(uri - line) < line_len) )
2494  uri++;
2495  if ((size_t)(uri - line) == line_len)
2496  {
2497  /* No URI and no http version given */
2498  curi = "";
2499  uri = NULL;
2500  connection->version = "";
2501  args = NULL;
2502  }
2503  else
2504  {
2505  size_t uri_len;
2506  curi = uri;
2507  /* Search from back to accept misformed URI with space */
2508  http_version = line + line_len - 1;
2509  /* Skip any trailing spaces */
2510  while ( (' ' == http_version[0]) &&
2511  (http_version > uri) )
2512  http_version--;
2513  /* Find first space in reverse direction */
2514  while ( (' ' != http_version[0]) &&
2515  (http_version > uri) )
2516  http_version--;
2517  if (http_version > uri)
2518  {
2519  /* http_version points to character before HTTP version string */
2520  http_version[0] = '\0';
2521  connection->version = http_version + 1;
2522  uri_len = http_version - uri;
2523  }
2524  else
2525  {
2526  connection->version = "";
2527  uri_len = line_len - (uri - line);
2528  }
2529  /* check for spaces in URI if we are "strict" */
2530  if ( (1 <= daemon->strict_for_client) &&
2531  (NULL != memchr (uri,
2532  ' ',
2533  uri_len)) )
2534  {
2535  /* space exists in URI and we are supposed to be strict, reject */
2536  return MHD_NO;
2537  }
2538 
2539  args = memchr (uri,
2540  '?',
2541  uri_len);
2542  }
2543 
2544  /* log callback before we modify URI *or* args */
2545  if (NULL != daemon->uri_log_callback)
2546  {
2547  connection->client_aware = true;
2548  connection->client_context
2549  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2550  uri,
2551  connection);
2552  }
2553 
2554  if (NULL != args)
2555  {
2556  args[0] = '\0';
2557  args++;
2558  /* note that this call clobbers 'args' */
2559  MHD_parse_arguments_ (connection,
2561  args,
2563  &unused_num_headers);
2564  }
2565 
2566  /* unescape URI *after* searching for arguments and log callback */
2567  if (NULL != uri)
2568  daemon->unescape_callback (daemon->unescape_callback_cls,
2569  connection,
2570  uri);
2571  connection->url = curi;
2572  return MHD_YES;
2573 }
2574 
2575 
2583 static void
2585 {
2586  struct MHD_Daemon *daemon = connection->daemon;
2587  size_t processed;
2588 
2589  if (NULL != connection->response)
2590  return; /* already queued a response */
2591  processed = 0;
2592  connection->client_aware = true;
2593  if (MHD_NO ==
2594  daemon->default_handler (daemon->default_handler_cls,
2595  connection,
2596  connection->url,
2597  connection->method,
2598  connection->version,
2599  NULL,
2600  &processed,
2601  &connection->client_context))
2602  {
2603  /* serious internal error, close connection */
2604  CONNECTION_CLOSE_ERROR (connection,
2605  _("Application reported internal error, closing connection.\n"));
2606  return;
2607  }
2608 }
2609 
2610 
2618 static void
2620 {
2621  struct MHD_Daemon *daemon = connection->daemon;
2622  size_t available;
2623  int instant_retry;
2624  char *buffer_head;
2625 
2626  if (NULL != connection->response)
2627  return; /* already queued a response */
2628 
2629  buffer_head = connection->read_buffer;
2630  available = connection->read_buffer_offset;
2631  do
2632  {
2633  size_t to_be_processed;
2634  size_t left_unprocessed;
2635  size_t processed_size;
2636 
2637  instant_retry = MHD_NO;
2638  if ( (connection->have_chunked_upload) &&
2639  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2640  {
2641  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
2642  (0LLU != connection->current_chunk_offset) &&
2643  (available >= 2) )
2644  {
2645  size_t i;
2646  /* skip new line at the *end* of a chunk */
2647  i = 0;
2648  if ( ('\r' == buffer_head[i]) ||
2649  ('\n' == buffer_head[i]) )
2650  i++; /* skip 1st part of line feed */
2651  if ( ('\r' == buffer_head[i]) ||
2652  ('\n' == buffer_head[i]) )
2653  i++; /* skip 2nd part of line feed */
2654  if (0 == i)
2655  {
2656  /* malformed encoding */
2657  CONNECTION_CLOSE_ERROR (connection,
2658  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2659  return;
2660  }
2661  available -= i;
2662  buffer_head += i;
2663  connection->current_chunk_offset = 0;
2664  connection->current_chunk_size = 0;
2665  }
2666  if (connection->current_chunk_offset <
2667  connection->current_chunk_size)
2668  {
2669  uint64_t cur_chunk_left;
2670  /* we are in the middle of a chunk, give
2671  as much as possible to the client (without
2672  crossing chunk boundaries) */
2673  cur_chunk_left
2674  = connection->current_chunk_size - connection->current_chunk_offset;
2675  if (cur_chunk_left > available)
2676  to_be_processed = available;
2677  else
2678  { /* cur_chunk_left <= (size_t)available */
2679  to_be_processed = (size_t)cur_chunk_left;
2680  if (available > to_be_processed)
2681  instant_retry = MHD_YES;
2682  }
2683  }
2684  else
2685  {
2686  size_t i;
2687  size_t end_size;
2688  bool malformed;
2689 
2690  /* we need to read chunk boundaries */
2691  i = 0;
2692  while (i < available)
2693  {
2694  if ( ('\r' == buffer_head[i]) ||
2695  ('\n' == buffer_head[i]) ||
2696  (';' == buffer_head[i]) )
2697  break;
2698  i++;
2699  if (i >= 16)
2700  break;
2701  }
2702  end_size = i;
2703  /* find beginning of CRLF (skip over chunk extensions) */
2704  if (';' == buffer_head[i])
2705  {
2706  while (i < available)
2707  {
2708  if ( ('\r' == buffer_head[i]) ||
2709  ('\n' == buffer_head[i]) )
2710  break;
2711  i++;
2712  }
2713  }
2714  /* take '\n' into account; if '\n' is the unavailable
2715  character, we will need to wait until we have it
2716  before going further */
2717  if ( (i + 1 >= available) &&
2718  ! ( (1 == i) &&
2719  (2 == available) &&
2720  ('0' == buffer_head[0]) ) )
2721  break; /* need more data... */
2722  i++;
2723  malformed = (end_size >= 16);
2724  if (! malformed)
2725  {
2726  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2727  end_size,
2728  &connection->current_chunk_size);
2729  malformed = (end_size != num_dig);
2730  }
2731  if (malformed)
2732  {
2733  /* malformed encoding */
2734  CONNECTION_CLOSE_ERROR (connection,
2735  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2736  return;
2737  }
2738  /* skip 2nd part of line feed */
2739  if ( (i < available) &&
2740  ( ('\r' == buffer_head[i]) ||
2741  ('\n' == buffer_head[i]) ) )
2742  i++;
2743 
2744  buffer_head += i;
2745  available -= i;
2746  connection->current_chunk_offset = 0;
2747 
2748  if (available > 0)
2749  instant_retry = MHD_YES;
2750  if (0LLU == connection->current_chunk_size)
2751  {
2752  connection->remaining_upload_size = 0;
2753  break;
2754  }
2755  continue;
2756  }
2757  }
2758  else
2759  {
2760  /* no chunked encoding, give all to the client */
2761  if ( (0 != connection->remaining_upload_size) &&
2762  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2763  (connection->remaining_upload_size < available) )
2764  {
2765  to_be_processed = (size_t)connection->remaining_upload_size;
2766  }
2767  else
2768  {
2773  to_be_processed = available;
2774  }
2775  }
2776  left_unprocessed = to_be_processed;
2777  connection->client_aware = true;
2778  if (MHD_NO ==
2779  daemon->default_handler (daemon->default_handler_cls,
2780  connection,
2781  connection->url,
2782  connection->method,
2783  connection->version,
2784  buffer_head,
2785  &left_unprocessed,
2786  &connection->client_context))
2787  {
2788  /* serious internal error, close connection */
2789  CONNECTION_CLOSE_ERROR (connection,
2790  _("Application reported internal error, closing connection.\n"));
2791  return;
2792  }
2793  if (left_unprocessed > to_be_processed)
2795  __FILE__,
2796  __LINE__
2797 #ifdef HAVE_MESSAGES
2798  , _("libmicrohttpd API violation")
2799 #else
2800  , NULL
2801 #endif
2802  );
2803  if (0 != left_unprocessed)
2804  {
2805  instant_retry = MHD_NO; /* client did not process everything */
2806 #ifdef HAVE_MESSAGES
2807  /* client did not process all upload data, complain if
2808  the setup was incorrect, which may prevent us from
2809  handling the rest of the request */
2810  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2811  (! connection->suspended) )
2812  MHD_DLOG (daemon,
2813  _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2814 #endif
2815  }
2816  processed_size = to_be_processed - left_unprocessed;
2817  if (connection->have_chunked_upload)
2818  connection->current_chunk_offset += processed_size;
2819  /* dh left "processed" bytes in buffer for next time... */
2820  buffer_head += processed_size;
2821  available -= processed_size;
2822  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2823  connection->remaining_upload_size -= processed_size;
2824  }
2825  while (MHD_YES == instant_retry);
2826  if ( (available > 0) &&
2827  (buffer_head != connection->read_buffer) )
2828  memmove (connection->read_buffer,
2829  buffer_head,
2830  available);
2831  connection->read_buffer_offset = available;
2832 }
2833 
2834 
2843 static int
2844 check_write_done (struct MHD_Connection *connection,
2845  enum MHD_CONNECTION_STATE next_state)
2846 {
2847  if (connection->write_buffer_append_offset !=
2848  connection->write_buffer_send_offset)
2849  return MHD_NO;
2850  connection->write_buffer_append_offset = 0;
2851  connection->write_buffer_send_offset = 0;
2852  connection->state = next_state;
2853  MHD_pool_reallocate (connection->pool,
2854  connection->write_buffer,
2855  connection->write_buffer_size,
2856  0);
2857  connection->write_buffer = NULL;
2858  connection->write_buffer_size = 0;
2859  return MHD_YES;
2860 }
2861 
2862 
2872 static int
2874  char *line)
2875 {
2876  char *colon;
2877 
2878  /* line should be normal header line, find colon */
2879  colon = strchr (line, ':');
2880  if (NULL == colon)
2881  {
2882  /* error in header line, die hard */
2883  CONNECTION_CLOSE_ERROR (connection,
2884  _("Received malformed line (no colon). Closing connection.\n"));
2885  return MHD_NO;
2886  }
2887  if (-1 >= connection->daemon->strict_for_client)
2888  {
2889  /* check for whitespace before colon, which is not allowed
2890  by RFC 7230 section 3.2.4; we count space ' ' and
2891  tab '\t', but not '\r\n' as those would have ended the line. */
2892  const char *white;
2893 
2894  white = strchr (line, ' ');
2895  if ( (NULL != white) &&
2896  (white < colon) )
2897  return MHD_NO;
2898  white = strchr (line, '\t');
2899  if ( (NULL != white) &&
2900  (white < colon) )
2901  return MHD_NO;
2902  }
2903  /* zero-terminate header */
2904  colon[0] = '\0';
2905  colon++; /* advance to value */
2906  while ( ('\0' != colon[0]) &&
2907  ( (' ' == colon[0]) ||
2908  ('\t' == colon[0]) ) )
2909  colon++;
2910  /* we do the actual adding of the connection
2911  header at the beginning of the while
2912  loop since we need to be able to inspect
2913  the *next* header line (in case it starts
2914  with a space...) */
2915  connection->last = line;
2916  connection->colon = colon;
2917  return MHD_YES;
2918 }
2919 
2920 
2931 static int
2933  char *line,
2934  enum MHD_ValueKind kind)
2935 {
2936  char *last;
2937  char *tmp;
2938  size_t last_len;
2939  size_t tmp_len;
2940 
2941  last = connection->last;
2942  if ( (' ' == line[0]) ||
2943  ('\t' == line[0]) )
2944  {
2945  /* value was continued on the next line, see
2946  http://www.jmarshall.com/easy/http/ */
2947  last_len = strlen (last);
2948  /* skip whitespace at start of 2nd line */
2949  tmp = line;
2950  while ( (' ' == tmp[0]) ||
2951  ('\t' == tmp[0]) )
2952  tmp++;
2953  tmp_len = strlen (tmp);
2954  /* FIXME: we might be able to do this better (faster!), as most
2955  likely 'last' and 'line' should already be adjacent in
2956  memory; however, doing this right gets tricky if we have a
2957  value continued over multiple lines (in which case we need to
2958  record how often we have done this so we can check for
2959  adjacency); also, in the case where these are not adjacent
2960  (not sure how it can happen!), we would want to allocate from
2961  the end of the pool, so as to not destroy the read-buffer's
2962  ability to grow nicely. */
2963  last = MHD_pool_reallocate (connection->pool,
2964  last,
2965  last_len + 1,
2966  last_len + tmp_len + 1);
2967  if (NULL == last)
2968  {
2969  transmit_error_response (connection,
2971  REQUEST_TOO_BIG);
2972  return MHD_NO;
2973  }
2974  memcpy (&last[last_len],
2975  tmp,
2976  tmp_len + 1);
2977  connection->last = last;
2978  return MHD_YES; /* possibly more than 2 lines... */
2979  }
2980  mhd_assert ( (NULL != last) &&
2981  (NULL != connection->colon) );
2982  if (MHD_NO ==
2983  connection_add_header (connection,
2984  last,
2985  strlen (last),
2986  connection->colon,
2987  strlen (connection->colon),
2988  kind))
2989  {
2990  transmit_error_response (connection,
2992  REQUEST_TOO_BIG);
2993  return MHD_NO;
2994  }
2995  /* we still have the current line to deal with... */
2996  if (0 != line[0])
2997  {
2998  if (MHD_NO == process_header_line (connection,
2999  line))
3000  {
3001  transmit_error_response (connection,
3004  return MHD_NO;
3005  }
3006  }
3007  return MHD_YES;
3008 }
3009 
3010 
3018 static void
3020 {
3021  const char *clen;
3022  struct MHD_Response *response;
3023  const char *enc;
3024  const char *end;
3025 
3026  parse_cookie_header (connection);
3027  if ( (1 <= connection->daemon->strict_for_client) &&
3028  (NULL != connection->version) &&
3030  connection->version)) &&
3031  (MHD_NO ==
3032  MHD_lookup_connection_value_n (connection,
3036  NULL,
3037  NULL)) )
3038  {
3039  int iret;
3040 
3041  /* die, http 1.1 request without host and we are pedantic */
3042  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3043  connection->read_closed = true;
3044 #ifdef HAVE_MESSAGES
3045  MHD_DLOG (connection->daemon,
3046  _("Received HTTP 1.1 request without `Host' header.\n"));
3047 #endif
3048  mhd_assert (NULL == connection->response);
3049  response =
3053  if (NULL == response)
3054  {
3055  /* can't even send a reply, at least close the connection */
3056  CONNECTION_CLOSE_ERROR (connection,
3057  _("Closing connection (failed to create response)\n"));
3058  return;
3059  }
3060  iret = MHD_queue_response (connection,
3062  response);
3063  MHD_destroy_response (response);
3064  if (MHD_YES != iret)
3065  {
3066  /* can't even send a reply, at least close the connection */
3067  CONNECTION_CLOSE_ERROR (connection,
3068  _("Closing connection (failed to queue response)\n"));
3069  }
3070  return;
3071  }
3072 
3073  connection->remaining_upload_size = 0;
3074  if (MHD_NO != MHD_lookup_connection_value_n (connection,
3078  &enc,
3079  NULL))
3080  {
3082  if (MHD_str_equal_caseless_(enc,
3083  "chunked"))
3084  connection->have_chunked_upload = true;
3085  }
3086  else
3087  {
3088  if (MHD_NO != MHD_lookup_connection_value_n (connection,
3092  &clen,
3093  NULL))
3094  {
3095  end = clen + MHD_str_to_uint64_ (clen,
3096  &connection->remaining_upload_size);
3097  if ( (clen == end) ||
3098  ('\0' != *end) )
3099  {
3100  connection->remaining_upload_size = 0;
3101 #ifdef HAVE_MESSAGES
3102  MHD_DLOG (connection->daemon,
3103  "Failed to parse `Content-Length' header. Closing connection.\n");
3104 #endif
3105  CONNECTION_CLOSE_ERROR (connection,
3106  NULL);
3107  return;
3108  }
3109  }
3110  }
3111 }
3112 
3113 
3121 void
3123 {
3124  struct MHD_Daemon *daemon = connection->daemon;
3125 
3126  if (0 == connection->connection_timeout)
3127  return; /* Skip update of activity for connections
3128  without timeout timer. */
3129  if (connection->suspended)
3130  return; /* no activity on suspended connections */
3131 
3132  connection->last_activity = MHD_monotonic_sec_counter();
3133  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3134  return; /* each connection has personal timeout */
3135 
3136  if (connection->connection_timeout != daemon->connection_timeout)
3137  return; /* custom timeout, no need to move it in "normal" DLL */
3138 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3140 #endif
3141  /* move connection to head of timeout list (by remove + add operation) */
3143  daemon->normal_timeout_tail,
3144  connection);
3146  daemon->normal_timeout_tail,
3147  connection);
3148 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3150 #endif
3151 }
3152 
3153 
3160 void
3162 {
3163  ssize_t bytes_read;
3164 
3165  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
3166  (connection->suspended) )
3167  return;
3168 #ifdef HTTPS_SUPPORT
3169  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3170  { /* HTTPS connection. */
3171  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
3172  {
3173  if (!MHD_run_tls_handshake_ (connection))
3174  return;
3175  }
3176  }
3177 #endif /* HTTPS_SUPPORT */
3178 
3179  /* make sure "read" has a reasonable number of bytes
3180  in buffer to use per system call (if possible) */
3181  if (connection->read_buffer_offset + connection->daemon->pool_increment >
3182  connection->read_buffer_size)
3183  try_grow_read_buffer (connection,
3184  (connection->read_buffer_size == connection->read_buffer_offset));
3185 
3186  if (connection->read_buffer_size == connection->read_buffer_offset)
3187  return; /* No space for receiving data. */
3188  bytes_read = connection->recv_cls (connection,
3189  &connection->read_buffer
3190  [connection->read_buffer_offset],
3191  connection->read_buffer_size -
3192  connection->read_buffer_offset);
3193  if (bytes_read < 0)
3194  {
3195  if (MHD_ERR_AGAIN_ == bytes_read)
3196  return; /* No new data to process. */
3197  if (MHD_ERR_CONNRESET_ == bytes_read)
3198  {
3199  CONNECTION_CLOSE_ERROR (connection,
3200  (MHD_CONNECTION_INIT == connection->state) ?
3201  NULL :
3202  _("Socket disconnected while reading request.\n"));
3203  return;
3204  }
3205  CONNECTION_CLOSE_ERROR (connection,
3206  (MHD_CONNECTION_INIT == connection->state) ?
3207  NULL :
3208  _("Connection socket is closed due to error when reading request.\n"));
3209  return;
3210  }
3211 
3212  if (0 == bytes_read)
3213  { /* Remote side closed connection. */
3214  connection->read_closed = true;
3215  MHD_connection_close_ (connection,
3217  return;
3218  }
3219  connection->read_buffer_offset += bytes_read;
3220  MHD_update_last_activity_ (connection);
3221 #if DEBUG_STATES
3222  MHD_DLOG (connection->daemon,
3223  _("In function %s handling connection at state: %s\n"),
3224  __FUNCTION__,
3225  MHD_state_to_string (connection->state));
3226 #endif
3227  switch (connection->state)
3228  {
3229  case MHD_CONNECTION_INIT:
3238  /* nothing to do but default action */
3239  if (connection->read_closed)
3240  {
3241  MHD_connection_close_ (connection,
3243  }
3244  return;
3245  case MHD_CONNECTION_CLOSED:
3246  return;
3247 #ifdef UPGRADE_SUPPORT
3248  case MHD_CONNECTION_UPGRADE:
3249  mhd_assert (0);
3250  return;
3251 #endif /* UPGRADE_SUPPORT */
3252  default:
3253  /* shrink read buffer to how much is actually used */
3254  MHD_pool_reallocate (connection->pool,
3255  connection->read_buffer,
3256  connection->read_buffer_size + 1,
3257  connection->read_buffer_offset);
3258  break;
3259  }
3260  return;
3261 }
3262 
3263 
3270 void
3272 {
3273  struct MHD_Response *response;
3274  ssize_t ret;
3275  if (connection->suspended)
3276  return;
3277 
3278 #ifdef HTTPS_SUPPORT
3279  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3280  { /* HTTPS connection. */
3281  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
3282  {
3283  if (!MHD_run_tls_handshake_ (connection))
3284  return;
3285  }
3286  }
3287 #endif /* HTTPS_SUPPORT */
3288 
3289 #if DEBUG_STATES
3290  MHD_DLOG (connection->daemon,
3291  _("In function %s handling connection at state: %s\n"),
3292  __FUNCTION__,
3293  MHD_state_to_string (connection->state));
3294 #endif
3295  switch (connection->state)
3296  {
3297  case MHD_CONNECTION_INIT:
3301  mhd_assert (0);
3302  return;
3304  return;
3306  ret = connection->send_cls (connection,
3308  [connection->continue_message_write_offset],
3310  connection->continue_message_write_offset);
3311  if (ret < 0)
3312  {
3313  if (MHD_ERR_AGAIN_ == ret)
3314  return;
3315 #ifdef HAVE_MESSAGES
3316  MHD_DLOG (connection->daemon,
3317  _("Failed to send data in request for %s.\n"),
3318  connection->url);
3319 #endif
3320  CONNECTION_CLOSE_ERROR (connection,
3321  NULL);
3322  return;
3323  }
3324 #if DEBUG_SEND_DATA
3325  fprintf (stderr,
3326  _("Sent 100 continue response: `%.*s'\n"),
3327  (int) ret,
3329 #endif
3330  connection->continue_message_write_offset += ret;
3331  MHD_update_last_activity_ (connection);
3332  return;
3337  mhd_assert (0);
3338  return;
3340  ret = connection->send_cls (connection,
3341  &connection->write_buffer
3342  [connection->write_buffer_send_offset],
3343  connection->write_buffer_append_offset -
3344  connection->write_buffer_send_offset);
3345  if (ret < 0)
3346  {
3347  if (MHD_ERR_AGAIN_ == ret)
3348  return;
3349  CONNECTION_CLOSE_ERROR (connection,
3350  _("Connection was closed while sending response headers.\n"));
3351  return;
3352  }
3353  connection->write_buffer_send_offset += ret;
3354  MHD_update_last_activity_ (connection);
3355  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3356  return;
3357  check_write_done (connection,
3359  return;
3361  return;
3363  response = connection->response;
3364  if (connection->response_write_position <
3365  connection->response->total_size)
3366  {
3367  uint64_t data_write_offset;
3368 
3369 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3370  if (NULL != response->crc)
3371  MHD_mutex_lock_chk_ (&response->mutex);
3372 #endif
3373  if (MHD_YES != try_ready_normal_body (connection))
3374  {
3375  /* mutex was already unlocked by try_ready_normal_body */
3376  return;
3377  }
3378 #if defined(_MHD_HAVE_SENDFILE)
3379  if (MHD_resp_sender_sendfile == connection->resp_sender)
3380  {
3381  ret = sendfile_adapter (connection);
3382  }
3383  else
3384 #else /* ! _MHD_HAVE_SENDFILE */
3385  if (1)
3386 #endif /* ! _MHD_HAVE_SENDFILE */
3387  {
3388  data_write_offset = connection->response_write_position
3389  - response->data_start;
3390  if (data_write_offset > (uint64_t)SIZE_MAX)
3391  MHD_PANIC (_("Data offset exceeds limit"));
3392  ret = connection->send_cls (connection,
3393  &response->data
3394  [(size_t)data_write_offset],
3395  response->data_size -
3396  (size_t)data_write_offset);
3397 #if DEBUG_SEND_DATA
3398  if (ret > 0)
3399  fprintf (stderr,
3400  _("Sent %d-byte DATA response: `%.*s'\n"),
3401  (int) ret,
3402  (int) ret,
3403  &response->data[connection->response_write_position -
3404  response->data_start]);
3405 #endif
3406  }
3407 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3408  if (NULL != response->crc)
3409  MHD_mutex_unlock_chk_ (&response->mutex);
3410 #endif
3411  if (ret < 0)
3412  {
3413  if (MHD_ERR_AGAIN_ == ret)
3414  return;
3415 #ifdef HAVE_MESSAGES
3416  MHD_DLOG (connection->daemon,
3417  _("Failed to send data in request for `%s'.\n"),
3418  connection->url);
3419 #endif
3420  CONNECTION_CLOSE_ERROR (connection,
3421  NULL);
3422  return;
3423  }
3424  connection->response_write_position += ret;
3425  MHD_update_last_activity_ (connection);
3426  }
3427  if (connection->response_write_position ==
3428  connection->response->total_size)
3429  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3430  return;
3432  mhd_assert (0);
3433  return;
3435  ret = connection->send_cls (connection,
3436  &connection->write_buffer
3437  [connection->write_buffer_send_offset],
3438  connection->write_buffer_append_offset -
3439  connection->write_buffer_send_offset);
3440  if (ret < 0)
3441  {
3442  if (MHD_ERR_AGAIN_ == ret)
3443  return;
3444  CONNECTION_CLOSE_ERROR (connection,
3445  _("Connection was closed while sending response body.\n"));
3446  return;
3447  }
3448  connection->write_buffer_send_offset += ret;
3449  MHD_update_last_activity_ (connection);
3450  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3451  return;
3452  check_write_done (connection,
3453  (connection->response->total_size ==
3454  connection->response_write_position) ?
3457  return;
3460  mhd_assert (0);
3461  return;
3463  ret = connection->send_cls (connection,
3464  &connection->write_buffer
3465  [connection->write_buffer_send_offset],
3466  connection->write_buffer_append_offset -
3467  connection->write_buffer_send_offset);
3468  if (ret < 0)
3469  {
3470  if (MHD_ERR_AGAIN_ == ret)
3471  return;
3472  CONNECTION_CLOSE_ERROR (connection,
3473  _("Connection was closed while sending response body.\n"));
3474  return;
3475  }
3476  connection->write_buffer_send_offset += ret;
3477  MHD_update_last_activity_ (connection);
3478  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3479  return;
3480  check_write_done (connection,
3482  return;
3484  mhd_assert (0);
3485  return;
3486  case MHD_CONNECTION_CLOSED:
3487  return;
3488 #ifdef UPGRADE_SUPPORT
3489  case MHD_CONNECTION_UPGRADE:
3490  mhd_assert (0);
3491  return;
3492 #endif /* UPGRADE_SUPPORT */
3493  default:
3494  mhd_assert (0);
3495  CONNECTION_CLOSE_ERROR (connection,
3496  _("Internal error\n"));
3497  break;
3498  }
3499  return;
3500 }
3501 
3502 
3511 static void
3513 {
3514  struct MHD_Daemon *daemon = connection->daemon;
3515 
3516  if (connection->in_cleanup)
3517  return; /* Prevent double cleanup. */
3518  connection->in_cleanup = true;
3519  if (NULL != connection->response)
3520  {
3521  MHD_destroy_response (connection->response);
3522  connection->response = NULL;
3523  }
3524 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3526 #endif
3527  if (connection->suspended)
3528  {
3531  connection);
3532  connection->suspended = false;
3533  }
3534  else
3535  {
3536  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3537  {
3538  if (connection->connection_timeout == daemon->connection_timeout)
3540  daemon->normal_timeout_tail,
3541  connection);
3542  else
3544  daemon->manual_timeout_tail,
3545  connection);
3546  }
3547  DLL_remove (daemon->connections_head,
3548  daemon->connections_tail,
3549  connection);
3550  }
3551  DLL_insert (daemon->cleanup_head,
3552  daemon->cleanup_tail,
3553  connection);
3554  connection->resuming = false;
3555  connection->in_idle = false;
3556 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3558 #endif
3559  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3560  {
3561  /* if we were at the connection limit before and are in
3562  thread-per-connection mode, signal the main thread
3563  to resume accepting connections */
3564  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3565  (! MHD_itc_activate_ (daemon->itc, "c")) )
3566  {
3567 #ifdef HAVE_MESSAGES
3568  MHD_DLOG (daemon,
3569  _("Failed to signal end of connection via inter-thread communication channel"));
3570 #endif
3571  }
3572  }
3573 }
3574 
3575 
3586 int
3588 {
3589  struct MHD_Daemon *daemon = connection->daemon;
3590  char *line;
3591  size_t line_len;
3592  int ret;
3593 
3594  connection->in_idle = true;
3595  while (! connection->suspended)
3596  {
3597 #ifdef HTTPS_SUPPORT
3598  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3599  { /* HTTPS connection. */
3600  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3601  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3602  break;
3603  }
3604 #endif /* HTTPS_SUPPORT */
3605 #if DEBUG_STATES
3606  MHD_DLOG (daemon,
3607  _("In function %s handling connection at state: %s\n"),
3608  __FUNCTION__,
3609  MHD_state_to_string (connection->state));
3610 #endif
3611  switch (connection->state)
3612  {
3613  case MHD_CONNECTION_INIT:
3614  line = get_next_header_line (connection,
3615  &line_len);
3616  /* Check for empty string, as we might want
3617  to tolerate 'spurious' empty lines; also
3618  NULL means we didn't get a full line yet;
3619  line is not 0-terminated here. */
3620  if ( (NULL == line) ||
3621  (0 == line[0]) )
3622  {
3623  if (MHD_CONNECTION_INIT != connection->state)
3624  continue;
3625  if (connection->read_closed)
3626  {
3627  CONNECTION_CLOSE_ERROR (connection,
3628  NULL);
3629  continue;
3630  }
3631  break;
3632  }
3633  if (MHD_NO == parse_initial_message_line (connection,
3634  line,
3635  line_len))
3636  CONNECTION_CLOSE_ERROR (connection,
3637  NULL);
3638  else
3639  connection->state = MHD_CONNECTION_URL_RECEIVED;
3640  continue;
3642  line = get_next_header_line (connection,
3643  NULL);
3644  if (NULL == line)
3645  {
3646  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3647  continue;
3648  if (connection->read_closed)
3649  {
3650  CONNECTION_CLOSE_ERROR (connection,
3651  NULL);
3652  continue;
3653  }
3654  break;
3655  }
3656  if (0 == line[0])
3657  {
3658  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3659  connection->header_size = (size_t) (line - connection->read_buffer);
3660  continue;
3661  }
3662  if (MHD_NO == process_header_line (connection,
3663  line))
3664  {
3665  transmit_error_response (connection,
3668  break;
3669  }
3671  continue;
3673  line = get_next_header_line (connection,
3674  NULL);
3675  if (NULL == line)
3676  {
3677  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
3678  continue;
3679  if (connection->read_closed)
3680  {
3681  CONNECTION_CLOSE_ERROR (connection,
3682  NULL);
3683  continue;
3684  }
3685  break;
3686  }
3687  if (MHD_NO ==
3688  process_broken_line (connection,
3689  line,
3690  MHD_HEADER_KIND))
3691  continue;
3692  if (0 == line[0])
3693  {
3694  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3695  connection->header_size = (size_t) (line - connection->read_buffer);
3696  continue;
3697  }
3698  continue;
3700  parse_connection_headers (connection);
3701  if (MHD_CONNECTION_CLOSED == connection->state)
3702  continue;
3704  if (connection->suspended)
3705  break;
3706  continue;
3708  call_connection_handler (connection); /* first call */
3709  if (MHD_CONNECTION_CLOSED == connection->state)
3710  continue;
3711  if (need_100_continue (connection))
3712  {
3713  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3714  if (socket_flush_possible (connection))
3715  socket_start_extra_buffering (connection);
3716  else
3717  socket_start_no_buffering (connection);
3718 
3719  break;
3720  }
3721  if ( (NULL != connection->response) &&
3722  ( (MHD_str_equal_caseless_ (connection->method,
3724  (MHD_str_equal_caseless_ (connection->method,
3725  MHD_HTTP_METHOD_PUT))) )
3726  {
3727  /* we refused (no upload allowed!) */
3728  connection->remaining_upload_size = 0;
3729  /* force close, in case client still tries to upload... */
3730  connection->read_closed = true;
3731  }
3732  connection->state = (0 == connection->remaining_upload_size)
3734  if (connection->suspended)
3735  break;
3736  continue;
3738  if (connection->continue_message_write_offset ==
3740  {
3741  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3742  if (socket_flush_possible (connection))
3743  socket_start_no_buffering_flush (connection);
3744  else
3745  socket_start_normal_buffering (connection);
3746 
3747  continue;
3748  }
3749  break;
3751  if (0 != connection->read_buffer_offset)
3752  {
3753  process_request_body (connection); /* loop call */
3754  if (MHD_CONNECTION_CLOSED == connection->state)
3755  continue;
3756  }
3757  if ( (0 == connection->remaining_upload_size) ||
3758  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3759  (0 == connection->read_buffer_offset) &&
3760  (connection->read_closed) ) )
3761  {
3762  if ( (connection->have_chunked_upload) &&
3763  (! connection->read_closed) )
3764  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3765  else
3766  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3767  if (connection->suspended)
3768  break;
3769  continue;
3770  }
3771  break;
3773  line = get_next_header_line (connection,
3774  NULL);
3775  if (NULL == line)
3776  {
3777  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3778  continue;
3779  if (connection->read_closed)
3780  {
3781  CONNECTION_CLOSE_ERROR (connection,
3782  NULL);
3783  continue;
3784  }
3785  break;
3786  }
3787  if (0 == line[0])
3788  {
3789  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3790  if (connection->suspended)
3791  break;
3792  continue;
3793  }
3794  if (MHD_NO == process_header_line (connection,
3795  line))
3796  {
3797  transmit_error_response (connection,
3800  break;
3801  }
3803  continue;
3805  line = get_next_header_line (connection,
3806  NULL);
3807  if (NULL == line)
3808  {
3809  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3810  continue;
3811  if (connection->read_closed)
3812  {
3813  CONNECTION_CLOSE_ERROR (connection,
3814  NULL);
3815  continue;
3816  }
3817  break;
3818  }
3819  if (MHD_NO ==
3820  process_broken_line (connection,
3821  line,
3822  MHD_FOOTER_KIND))
3823  continue;
3824  if (0 == line[0])
3825  {
3826  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3827  if (connection->suspended)
3828  break;
3829  continue;
3830  }
3831  continue;
3833  call_connection_handler (connection); /* "final" call */
3834  if (connection->state == MHD_CONNECTION_CLOSED)
3835  continue;
3836  if (NULL == connection->response)
3837  break; /* try again next time */
3838  if (MHD_NO == build_header_response (connection))
3839  {
3840  /* oops - close! */
3841  CONNECTION_CLOSE_ERROR (connection,
3842  _("Closing connection (failed to create response header)\n"));
3843  continue;
3844  }
3845  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3846  if (socket_flush_possible (connection))
3847  socket_start_extra_buffering (connection);
3848  else
3849  socket_start_no_buffering (connection);
3850 
3851  break;
3853  /* no default action */
3854  break;
3856  /* Some clients may take some actions right after header receive */
3857  if (socket_flush_possible (connection))
3858  socket_start_no_buffering_flush (connection);
3859 
3860 #ifdef UPGRADE_SUPPORT
3861  if (NULL != connection->response->upgrade_handler)
3862  {
3863  socket_start_normal_buffering (connection);
3864  connection->state = MHD_CONNECTION_UPGRADE;
3865  /* This connection is "upgraded". Pass socket to application. */
3866  if (MHD_YES !=
3868  connection))
3869  {
3870  /* upgrade failed, fail hard */
3871  CONNECTION_CLOSE_ERROR (connection,
3872  NULL);
3873  continue;
3874  }
3875  /* Response is not required anymore for this connection. */
3876  {
3877  struct MHD_Response * const resp = connection->response;
3878 
3879  connection->response = NULL;
3880  MHD_destroy_response (resp);
3881  }
3882  continue;
3883  }
3884 #endif /* UPGRADE_SUPPORT */
3885  if (socket_flush_possible (connection))
3886  socket_start_extra_buffering (connection);
3887  else
3888  socket_start_normal_buffering (connection);
3889 
3890  if (connection->have_chunked_upload)
3892  else
3894  continue;
3896  /* nothing to do here */
3897  break;
3899 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3900  if (NULL != connection->response->crc)
3901  MHD_mutex_lock_chk_ (&connection->response->mutex);
3902 #endif
3903  if (0 == connection->response->total_size)
3904  {
3905 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3906  if (NULL != connection->response->crc)
3907  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3908 #endif
3909  connection->state = MHD_CONNECTION_BODY_SENT;
3910  continue;
3911  }
3912  if (MHD_YES == try_ready_normal_body (connection))
3913  {
3914 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3915  if (NULL != connection->response->crc)
3916  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3917 #endif
3919  /* Buffering for flushable socket was already enabled*/
3920  if (socket_flush_possible (connection))
3921  socket_start_no_buffering (connection);
3922  break;
3923  }
3924  /* mutex was already unlocked by "try_ready_normal_body */
3925  /* not ready, no socket action */
3926  break;
3928  /* nothing to do here */
3929  break;
3931 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3932  if (NULL != connection->response->crc)
3933  MHD_mutex_lock_chk_ (&connection->response->mutex);
3934 #endif
3935  if ( (0 == connection->response->total_size) ||
3936  (connection->response_write_position ==
3937  connection->response->total_size) )
3938  {
3939 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3940  if (NULL != connection->response->crc)
3941  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3942 #endif
3943  connection->state = MHD_CONNECTION_BODY_SENT;
3944  continue;
3945  }
3946  if (MHD_YES == try_ready_chunked_body (connection))
3947  {
3948 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3949  if (NULL != connection->response->crc)
3950  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3951 #endif
3953  /* Buffering for flushable socket was already enabled */
3954  if (socket_flush_possible (connection))
3955  socket_start_no_buffering (connection);
3956  continue;
3957  }
3958  /* mutex was already unlocked by try_ready_chunked_body */
3959  break;
3961  if (MHD_NO == build_header_response (connection))
3962  {
3963  /* oops - close! */
3964  CONNECTION_CLOSE_ERROR (connection,
3965  _("Closing connection (failed to create response header)\n"));
3966  continue;
3967  }
3968  if ( (! connection->have_chunked_upload) ||
3969  (connection->write_buffer_send_offset ==
3970  connection->write_buffer_append_offset) )
3971  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3972  else
3973  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3974  continue;
3976  /* no default action */
3977  break;
3979  if (MHD_HTTP_PROCESSING == connection->responseCode)
3980  {
3981  /* After this type of response, we allow sending another! */
3983  MHD_destroy_response (connection->response);
3984  connection->response = NULL;
3985  /* FIXME: maybe partially reset memory pool? */
3986  continue;
3987  }
3988  if (socket_flush_possible (connection))
3989  socket_start_no_buffering_flush (connection);
3990  else
3991  socket_start_normal_buffering (connection);
3992 
3993  MHD_destroy_response (connection->response);
3994  connection->response = NULL;
3995  if ( (NULL != daemon->notify_completed) &&
3996  (connection->client_aware) )
3997  {
3998  daemon->notify_completed (daemon->notify_completed_cls,
3999  connection,
4000  &connection->client_context,
4002  }
4003  connection->client_aware = false;
4004  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
4005  (connection->read_closed) )
4006  {
4007  /* have to close for some reason */
4008  MHD_connection_close_ (connection,
4010  MHD_pool_destroy (connection->pool);
4011  connection->pool = NULL;
4012  connection->read_buffer = NULL;
4013  connection->read_buffer_size = 0;
4014  connection->read_buffer_offset = 0;
4015  }
4016  else
4017  {
4018  /* can try to keep-alive */
4019  if (socket_flush_possible (connection))
4020  socket_start_normal_buffering (connection);
4021  connection->version = NULL;
4022  connection->state = MHD_CONNECTION_INIT;
4023  connection->last = NULL;
4024  connection->colon = NULL;
4025  connection->header_size = 0;
4026  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
4027  /* Reset the read buffer to the starting size,
4028  preserving the bytes we have already read. */
4029  connection->read_buffer
4030  = MHD_pool_reset (connection->pool,
4031  connection->read_buffer,
4032  connection->read_buffer_offset,
4033  connection->daemon->pool_size / 2);
4034  connection->read_buffer_size
4035  = connection->daemon->pool_size / 2;
4036  }
4037  connection->client_context = NULL;
4038  connection->continue_message_write_offset = 0;
4039  connection->responseCode = 0;
4040  connection->headers_received = NULL;
4041  connection->headers_received_tail = NULL;
4042  connection->response_write_position = 0;
4043  connection->have_chunked_upload = false;
4044  connection->current_chunk_size = 0;
4045  connection->current_chunk_offset = 0;
4046  connection->method = NULL;
4047  connection->url = NULL;
4048  connection->write_buffer = NULL;
4049  connection->write_buffer_size = 0;
4050  connection->write_buffer_send_offset = 0;
4051  connection->write_buffer_append_offset = 0;
4052  continue;
4053  case MHD_CONNECTION_CLOSED:
4054  cleanup_connection (connection);
4055  connection->in_idle = false;
4056  return MHD_NO;
4057 #ifdef UPGRADE_SUPPORT
4058  case MHD_CONNECTION_UPGRADE:
4059  connection->in_idle = false;
4060  return MHD_YES; /* keep open */
4061 #endif /* UPGRADE_SUPPORT */
4062  default:
4063  mhd_assert (0);
4064  break;
4065  }
4066  break;
4067  }
4068  if (! connection->suspended)
4069  {
4070  time_t timeout;
4071  timeout = connection->connection_timeout;
4072  if ( (0 != timeout) &&
4073  (timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
4074  {
4075  MHD_connection_close_ (connection,
4077  connection->in_idle = false;
4078  return MHD_YES;
4079  }
4080  }
4082  ret = MHD_YES;
4083 #ifdef EPOLL_SUPPORT
4084  if ( (! connection->suspended) &&
4085  (0 != (daemon->options & MHD_USE_EPOLL)) )
4086  {
4087  ret = MHD_connection_epoll_update_ (connection);
4088  }
4089 #endif /* EPOLL_SUPPORT */
4090  connection->in_idle = false;
4091  return ret;
4092 }
4093 
4094 
4095 #ifdef EPOLL_SUPPORT
4096 
4104 int
4105 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
4106 {
4107  struct MHD_Daemon *daemon = connection->daemon;
4108 
4109  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
4110  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
4111  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
4112  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
4113  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
4114  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
4115  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
4116  {
4117  /* add to epoll set */
4118  struct epoll_event event;
4119 
4120  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
4121  event.data.ptr = connection;
4122  if (0 != epoll_ctl (daemon->epoll_fd,
4123  EPOLL_CTL_ADD,
4124  connection->socket_fd,
4125  &event))
4126  {
4127 #ifdef HAVE_MESSAGES
4128  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
4129  MHD_DLOG (daemon,
4130  _("Call to epoll_ctl failed: %s\n"),
4132 #endif
4133  connection->state = MHD_CONNECTION_CLOSED;
4134  cleanup_connection (connection);
4135  return MHD_NO;
4136  }
4137  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
4138  }
4139  return MHD_YES;
4140 }
4141 #endif
4142 
4143 
4149 void
4151 {
4152  connection->recv_cls = &recv_param_adapter;
4153  connection->send_cls = &send_param_adapter;
4154 }
4155 
4156 
4167 const union MHD_ConnectionInfo *
4169  enum MHD_ConnectionInfoType info_type,
4170  ...)
4171 {
4172  switch (info_type)
4173  {
4174 #ifdef HTTPS_SUPPORT
4176  if (NULL == connection->tls_session)
4177  return NULL;
4178  connection->cipher = gnutls_cipher_get (connection->tls_session);
4179  return (const union MHD_ConnectionInfo *) &connection->cipher;
4181  if (NULL == connection->tls_session)
4182  return NULL;
4183  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
4184  return (const union MHD_ConnectionInfo *) &connection->protocol;
4186  if (NULL == connection->tls_session)
4187  return NULL;
4188  return (const union MHD_ConnectionInfo *) &connection->tls_session;
4189 #endif /* HTTPS_SUPPORT */
4191  return (const union MHD_ConnectionInfo *) &connection->addr;
4193  return (const union MHD_ConnectionInfo *) &connection->daemon;
4195  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
4197  return (const union MHD_ConnectionInfo *) &connection->socket_context;
4199  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
4200  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
4202  connection->connection_timeout_dummy = (unsigned int)connection->connection_timeout;
4203  return (const union MHD_ConnectionInfo *) &connection->connection_timeout_dummy;
4205  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
4206  (MHD_CONNECTION_CLOSED == connection->state) )
4207  return NULL; /* invalid, too early! */
4208  return (const union MHD_ConnectionInfo *) &connection->header_size;
4209  default:
4210  return NULL;
4211  }
4212 }
4213 
4214 
4224 int
4226  enum MHD_CONNECTION_OPTION option,
4227  ...)
4228 {
4229  va_list ap;
4230  struct MHD_Daemon *daemon;
4231 
4232  daemon = connection->daemon;
4233  switch (option)
4234  {
4236  if (0 == connection->connection_timeout)
4237  connection->last_activity = MHD_monotonic_sec_counter();
4238 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4240 #endif
4241  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
4242  (! connection->suspended) )
4243  {
4244  if (connection->connection_timeout == daemon->connection_timeout)
4246  daemon->normal_timeout_tail,
4247  connection);
4248  else
4250  daemon->manual_timeout_tail,
4251  connection);
4252  }
4253  va_start (ap, option);
4254  connection->connection_timeout = va_arg (ap,
4255  unsigned int);
4256  va_end (ap);
4257  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
4258  (! connection->suspended) )
4259  {
4260  if (connection->connection_timeout == daemon->connection_timeout)
4262  daemon->normal_timeout_tail,
4263  connection);
4264  else
4266  daemon->manual_timeout_tail,
4267  connection);
4268  }
4269 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4271 #endif
4272  return MHD_YES;
4273  default:
4274  return MHD_NO;
4275  }
4276 }
4277 
4278 
4290 int
4292  unsigned int status_code,
4293  struct MHD_Response *response)
4294 {
4295  struct MHD_Daemon *daemon;
4296 
4297  if ( (NULL == connection) ||
4298  (NULL == response) ||
4299  (NULL != connection->response) ||
4300  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
4301  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
4302  return MHD_NO;
4303  daemon = connection->daemon;
4304 
4305  if (daemon->shutdown)
4306  return MHD_YES; /* If daemon was shut down in parallel,
4307  * response will be aborted now or on later stage. */
4308 
4309 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4310  if ( (!connection->suspended) &&
4311  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
4312  (!MHD_thread_ID_match_current_(connection->pid.ID)) )
4313  {
4314 #ifdef HAVE_MESSAGES
4315  MHD_DLOG (daemon,
4316  _("Attempted to queue response on wrong thread!\n"));
4317 #endif
4318  return MHD_NO;
4319  }
4320 #endif
4321 #ifdef UPGRADE_SUPPORT
4322  if ( (NULL != response->upgrade_handler) &&
4323  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
4324  {
4325 #ifdef HAVE_MESSAGES
4326  MHD_DLOG (daemon,
4327  _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
4328 #endif
4329  return MHD_NO;
4330  }
4331  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
4332  (NULL != response->upgrade_handler) )
4333  {
4334 #ifdef HAVE_MESSAGES
4335  MHD_DLOG (daemon,
4336  _("Application used invalid status code for 'upgrade' response!\n"));
4337 #endif
4338  return MHD_NO;
4339  }
4340 #endif /* UPGRADE_SUPPORT */
4341  MHD_increment_response_rc (response);
4342  connection->response = response;
4343  connection->responseCode = status_code;
4344 #if defined(_MHD_HAVE_SENDFILE)
4345  if ( (response->fd == -1) ||
4346  (0 != (connection->daemon->options & MHD_USE_TLS)) )
4347  connection->resp_sender = MHD_resp_sender_std;
4348  else
4349  connection->resp_sender = MHD_resp_sender_sendfile;
4350 #endif /* _MHD_HAVE_SENDFILE */
4351 
4352  if ( ( (NULL != connection->method) &&
4353  (MHD_str_equal_caseless_ (connection->method,
4354  MHD_HTTP_METHOD_HEAD)) ) ||
4355  (MHD_HTTP_OK > status_code) ||
4356  (MHD_HTTP_NO_CONTENT == status_code) ||
4357  (MHD_HTTP_NOT_MODIFIED == status_code) )
4358  {
4359  /* if this is a "HEAD" request, or a status code for
4360  which a body is not allowed, pretend that we
4361  have already sent the full message body. */
4362  connection->response_write_position = response->total_size;
4363  }
4364  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
4365  (NULL != connection->method) &&
4366  ( (MHD_str_equal_caseless_ (connection->method,
4368  (MHD_str_equal_caseless_ (connection->method,
4369  MHD_HTTP_METHOD_PUT))) )
4370  {
4371  /* response was queued "early", refuse to read body / footers or
4372  further requests! */
4373  connection->read_closed = true;
4374  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4375  }
4376  if (! connection->in_idle)
4377  (void) MHD_connection_handle_idle (connection);
4378  MHD_update_last_activity_ (connection);
4379  return MHD_YES;
4380 }
4381 
4382 
4383 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2873
#define SSIZE_MAX
Definition: mhd_limits.h:111
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:2163
_MHD_EXTERN int MHD_get_connection_values_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIteratorN iterator, void *iterator_cls)
Definition: connection.c:730
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:2347
void * unescape_callback_cls
Definition: internal.h:1418
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:553
static int connection_add_header(struct MHD_Connection *connection, const char *key, size_t key_size, const char *value, size_t value_size, enum MHD_ValueKind kind)
Definition: connection.c:2312
#define MHD_PANIC(msg)
Definition: internal.h:68
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:3271
uint64_t total_size
Definition: internal.h:1639
bool have_chunked_upload
Definition: internal.h:945
Header for platform missing functions.
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:1272
uint64_t fd_off
Definition: internal.h:1650
uint64_t current_chunk_offset
Definition: internal.h:959
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:920
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:870
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:2083
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:925
void * data
Definition: microhttpd.h:2948
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:1342
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:1058
uint64_t response_write_position
Definition: internal.h:819
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:726
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:507
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:930
#define OFF_T_MAX
Definition: mhd_limits.h:123
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:185
time_t connection_timeout
Definition: internal.h:1589
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:417
char * version
Definition: internal.h:719
int suspended_dummy
Definition: internal.h:1018
#define INTERNAL_ERROR
Definition: connection.c:111
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:563
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:1137
#define MHD_YES
Definition: microhttpd.h:140
#define SIZE_MAX
Definition: mhd_limits.h:99
struct MHD_Response * response
Definition: internal.h:675
char * data
Definition: internal.h:1585
char * colon
Definition: internal.h:756
#define REQUEST_LACKS_HOST
Definition: connection.c:86
char * write_buffer
Definition: internal.h:739
#define MHD_SENFILE_CHUNK_
Definition: connection.c:129
int MHD_set_connection_value_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char *value, size_t value_size)
Definition: connection.c:844
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:356
#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:1099
MHD_RequestTerminationCode
Definition: microhttpd.h:1734
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:2002
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1264
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2584
uint64_t remaining_upload_size
Definition: internal.h:812
unsigned int responseCode
Definition: internal.h:936
#define MHD_ERR_CONNRESET_
Definition: internal.h:1869
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3512
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:3122
char * header
Definition: internal.h:344
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:283
void * uri_log_callback_cls
Definition: internal.h:1408
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:806
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
Definition: connection.c:1583
static bool MHD_lookup_header_token_ci(const struct MHD_Connection *connection, const char *header, size_t header_len, const char *token, size_t token_len)
Definition: connection.c:1021
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1966
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:134
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:673
Header for platform-independent inter-thread communication.
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:1233
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:862
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:4168
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1472
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
int strict_for_client
Definition: internal.h:1610
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1202
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:395
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:3662
size_t write_buffer_send_offset
Definition: internal.h:794
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
static int MHD_set_connection_value_n_nocheck_(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char *value, size_t value_size)
Definition: connection.c:783
size_t read_buffer_size
Definition: internal.h:778
bool sk_tcp_cork_nopush_on
Definition: internal.h:886
void * client_context
Definition: internal.h:693
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:438
const char * url
Definition: internal.h:713
size_t continue_message_write_offset
Definition: internal.h:833
#define REQUEST_MALFORMED
Definition: connection.c:99
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:188
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:707
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
enum MHD_FLAG options
Definition: internal.h:1600
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:334
LogCallback uri_log_callback
Definition: internal.h:1403
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:3161
bool in_cleanup
Definition: internal.h:913
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1162
#define MHD_HTTP_OK
Definition: microhttpd.h:326
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:4225
#define _MHD_EXTERN
Definition: mhd_options.h:51
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
bool sk_tcp_nodelay_on
Definition: internal.h:880
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:166
#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:747
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1521
MHD_ValueKind
Definition: microhttpd.h:1684
Header for string manipulating helpers.
#define DLL_remove(head, tail, element)
Definition: internal.h:1762
char * read_buffer
Definition: internal.h:733
ReceiveCallback recv_cls
Definition: internal.h:703
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:1071
size_t value_size
Definition: internal.h:286
size_t write_buffer_size
Definition: internal.h:789
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
MHD_ConnectionInfoType
Definition: microhttpd.h:1882
uint64_t data_start
Definition: internal.h:1645
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:856
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:422
UnescapeCallback unescape_callback
Definition: internal.h:1413
int off_t offset
Definition: microhttpd.h:3076
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:4291
size_t header_size
Definition: internal.h:276
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:855
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:367
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:734
#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:1453
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:2844
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:3587
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2932
enum MHD_ResponseFlags flags
Definition: internal.h:397
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:557
#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:876
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:3019
size_t write_buffer_append_offset
Definition: internal.h:800
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1132
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1378
#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:539
bool read_closed
Definition: internal.h:789
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:4150
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:882
void * notify_completed_cls
Definition: internal.h:1383
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2619
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:855
#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:691
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:428
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:167
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:2472
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:296
bool suspended
Definition: internal.h:761
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:545
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:321
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:159
_MHD_EXTERN int MHD_lookup_connection_value_n(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, size_t key_size, const char **value_ptr, size_t *value_size_ptr)
Definition: connection.c:957
#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:784
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:2252
void * default_handler_cls
Definition: internal.h:1269
#define MHD_NO
Definition: microhttpd.h:145
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:282
#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:1255
uint64_t current_chunk_size
Definition: internal.h:953
struct MHD_HTTP_Header * headers_received
Definition: internal.h:665
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:319
limits values definitions
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:601
_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:891
#define REQUEST_TOO_BIG
Definition: connection.c:73
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:670
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1636
size_t pool_increment
Definition: internal.h:1458
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:880
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:389
int(* MHD_KeyValueIteratorN)(void *cls, enum MHD_ValueKind kind, const char *key, size_t key_size, const char *value, size_t value_size)
Definition: microhttpd.h:2188