GNU libmicrohttpd  0.9.68
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 #include "mhd_send.h"
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 \
72  "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
73 #else
74 #define REQUEST_TOO_BIG ""
75 #endif
76 
84 #ifdef HAVE_MESSAGES
85 #define REQUEST_LACKS_HOST \
86  "<html><head><title>&quot;Host:&quot; header required</title></head><body>In HTTP 1.1, requests must include a &quot;Host:&quot; header, and your HTTP 1.1 request lacked such a header.</body></html>"
87 #else
88 #define REQUEST_LACKS_HOST ""
89 #endif
90 
98 #ifdef HAVE_MESSAGES
99 #define REQUEST_MALFORMED \
100  "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
101 #else
102 #define REQUEST_MALFORMED ""
103 #endif
104 
111 #ifdef HAVE_MESSAGES
112 #define INTERNAL_ERROR \
113  "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
114 #else
115 #define INTERNAL_ERROR ""
116 #endif
117 
122 #define DEBUG_CLOSE MHD_NO
123 
127 #define DEBUG_SEND_DATA MHD_NO
128 
129 
133 #define MHD_SENFILE_CHUNK_ (0x20000)
134 
138 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
139 
140 #ifdef HAVE_FREEBSD_SENDFILE
141 #ifdef SF_FLAGS
142 
145 static int freebsd_sendfile_flags_;
146 
150 static int freebsd_sendfile_flags_thd_p_c_;
151 #endif /* SF_FLAGS */
152 
155 void
156 MHD_conn_init_static_ (void)
157 {
158 /* FreeBSD 11 and later allow to specify read-ahead size
159  * and handles SF_NODISKIO differently.
160  * SF_FLAGS defined only on FreeBSD 11 and later. */
161 #ifdef SF_FLAGS
162  long sys_page_size = sysconf (_SC_PAGESIZE);
163  if (0 > sys_page_size)
164  { /* Failed to get page size. */
165  freebsd_sendfile_flags_ = SF_NODISKIO;
166  freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
167  }
168  else
169  {
170  freebsd_sendfile_flags_ =
171  SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
172  freebsd_sendfile_flags_thd_p_c_ =
173  SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size),
174  SF_NODISKIO);
175  }
176 #endif /* SF_FLAGS */
177 }
178 #endif /* HAVE_FREEBSD_SENDFILE */
179 
188 static ssize_t
189 recv_param_adapter (struct MHD_Connection *connection,
190  void *other,
191  size_t i)
192 {
193  ssize_t ret;
194 
195  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
196  (MHD_CONNECTION_CLOSED == connection->state) )
197  {
198  return MHD_ERR_NOTCONN_;
199  }
200  if (i > MHD_SCKT_SEND_MAX_SIZE_)
201  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
202 
203  ret = MHD_recv_ (connection->socket_fd,
204  other,
205  i);
206  if (0 > ret)
207  {
208  const int err = MHD_socket_get_error_ ();
209  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
210  {
211 #ifdef EPOLL_SUPPORT
212  /* Got EAGAIN --- no longer read-ready */
213  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
214 #endif /* EPOLL_SUPPORT */
215  return MHD_ERR_AGAIN_;
216  }
217  if (MHD_SCKT_ERR_IS_EINTR_ (err))
218  return MHD_ERR_AGAIN_;
220  return MHD_ERR_CONNRESET_;
221  /* Treat any other error as hard error. */
222  return MHD_ERR_NOTCONN_;
223  }
224 #ifdef EPOLL_SUPPORT
225  else if (i > (size_t) ret)
226  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
227 #endif /* EPOLL_SUPPORT */
228  return ret;
229 }
230 
231 
241 static ssize_t
242 send_param_adapter (struct MHD_Connection *connection,
243  const void *other,
244  size_t i)
245 {
246  ssize_t ret;
247 
248  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
249  (MHD_CONNECTION_CLOSED == connection->state) )
250  {
251  return MHD_ERR_NOTCONN_;
252  }
253  if (i > MHD_SCKT_SEND_MAX_SIZE_)
254  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
255 
256  ret = MHD_send_ (connection->socket_fd,
257  other,
258  i);
259  if (0 > ret)
260  {
261  const int err = MHD_socket_get_error_ ();
262 
263  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
264  {
265 #ifdef EPOLL_SUPPORT
266  /* EAGAIN --- no longer write-ready */
267  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
268 #endif /* EPOLL_SUPPORT */
269  return MHD_ERR_AGAIN_;
270  }
271  if (MHD_SCKT_ERR_IS_EINTR_ (err))
272  return MHD_ERR_AGAIN_;
274  return MHD_ERR_CONNRESET_;
275  /* Treat any other error as hard error. */
276  return MHD_ERR_NOTCONN_;
277  }
278 #ifdef EPOLL_SUPPORT
279  else if (i > (size_t) ret)
280  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
281 #endif /* EPOLL_SUPPORT */
282  return ret;
283 }
284 
285 
298 int
300  enum MHD_ValueKind kind,
301  MHD_KeyValueIterator iterator,
302  void *iterator_cls)
303 {
304  int ret;
305  struct MHD_HTTP_Header *pos;
306 
307  if (NULL == connection)
308  return -1;
309  ret = 0;
310  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
311  if (0 != (pos->kind & kind))
312  {
313  ret++;
314  if ( (NULL != iterator) &&
315  (MHD_YES != iterator (iterator_cls,
316  pos->kind,
317  pos->header,
318  pos->value)) )
319  return ret;
320  }
321  return ret;
322 }
323 
324 
337 int
339  enum MHD_ValueKind kind,
340  MHD_KeyValueIteratorN iterator,
341  void *iterator_cls)
342 {
343  int ret;
344  struct MHD_HTTP_Header *pos;
345 
346  if (NULL == connection)
347  return -1;
348  ret = 0;
349 
350  if (NULL == iterator)
351  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
352  {
353  if (0 != (kind & pos->kind))
354  ret++;
355  }
356  else
357  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
358  if (0 != (kind & pos->kind))
359  {
360  ret++;
361  if (MHD_NO == iterator (iterator_cls,
362  pos->kind,
363  pos->header,
364  pos->header_size,
365  pos->value,
366  pos->value_size))
367  return ret;
368  }
369  return ret;
370 }
371 
372 
390 static int
392  enum MHD_ValueKind kind,
393  const char *key,
394  size_t key_size,
395  const char *value,
396  size_t value_size)
397 {
398  struct MHD_HTTP_Header *pos;
399 
400  pos = MHD_pool_allocate (connection->pool,
401  sizeof (struct MHD_HTTP_Header),
402  true);
403  if (NULL == pos)
404  return MHD_NO;
405  pos->header = (char *) key;
406  pos->header_size = key_size;
407  pos->value = (char *) value;
408  pos->value_size = value_size;
409  pos->kind = kind;
410  pos->next = NULL;
411  /* append 'pos' to the linked list of headers */
412  if (NULL == connection->headers_received_tail)
413  {
414  connection->headers_received = pos;
415  connection->headers_received_tail = pos;
416  }
417  else
418  {
419  connection->headers_received_tail->next = pos;
420  connection->headers_received_tail = pos;
421  }
422  return MHD_YES;
423 }
424 
425 
451 int
453  enum MHD_ValueKind kind,
454  const char *key,
455  size_t key_size,
456  const char *value,
457  size_t value_size)
458 {
459  if ( (MHD_GET_ARGUMENT_KIND != kind) &&
460  ( ((key ? strlen (key) : 0) != key_size) ||
461  ((value ? strlen (value) : 0) != value_size) ) )
462  return MHD_NO; /* binary zero is allowed only in GET arguments */
463 
464  return MHD_set_connection_value_n_nocheck_ (connection,
465  kind,
466  key,
467  key_size,
468  value,
469  value_size);
470 }
471 
472 
498 int
500  enum MHD_ValueKind kind,
501  const char *key,
502  const char *value)
503 {
504  return MHD_set_connection_value_n_nocheck_ (connection,
505  kind,
506  key,
507  NULL != key
508  ? strlen (key)
509  : 0,
510  value,
511  NULL != value
512  ? strlen (value)
513  : 0);
514 }
515 
516 
527 const char *
529  enum MHD_ValueKind kind,
530  const char *key)
531 {
532  const char *value;
533 
534  value = NULL;
535  (void) MHD_lookup_connection_value_n (connection,
536  kind,
537  key,
538  (NULL == key) ? 0 : strlen (key),
539  &value,
540  NULL);
541  return value;
542 }
543 
544 
564 _MHD_EXTERN int
566  enum MHD_ValueKind kind,
567  const char *key,
568  size_t key_size,
569  const char **value_ptr,
570  size_t *value_size_ptr)
571 {
572  struct MHD_HTTP_Header *pos;
573 
574  if (NULL == connection)
575  return MHD_NO;
576 
577  if (NULL == key)
578  {
579  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
580  {
581  if ( (0 != (kind & pos->kind)) &&
582  (NULL == pos->header) )
583  break;
584  }
585  }
586  else
587  {
588  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
589  {
590  if ( (0 != (kind & pos->kind)) &&
591  (key_size == pos->header_size) &&
592  ( (key == pos->header) ||
594  pos->header,
595  key_size) ) ) )
596  break;
597  }
598  }
599 
600  if (NULL == pos)
601  return MHD_NO;
602 
603  if (NULL != value_ptr)
604  *value_ptr = pos->value;
605 
606  if (NULL != value_size_ptr)
607  *value_size_ptr = pos->value_size;
608 
609  return MHD_YES;
610 }
611 
612 
628 static bool
629 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
630  const char *header,
631  size_t header_len,
632  const char *token,
633  size_t token_len)
634 {
635  struct MHD_HTTP_Header *pos;
636 
637  if ((NULL == connection)||(NULL == header)||(0 == header[0])||(NULL ==
638  token) ||(0 ==
639  token
640  [0]) )
641  return false;
642 
643  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
644  {
645  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
646  (header_len == pos->header_size) &&
647  ( (header == pos->header) ||
649  pos->header,
650  header_len)) ) &&
651  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
652  return true;
653  }
654  return false;
655 }
656 
657 
669 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
670  MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
671  (tkn),MHD_STATICSTR_LEN_ (tkn))
672 
673 
681 static int
682 need_100_continue (struct MHD_Connection *connection)
683 {
684  const char *expect;
685 
686  return ( (NULL == connection->response) &&
687  (NULL != connection->version) &&
688  (MHD_str_equal_caseless_ (connection->version,
690  (MHD_NO != MHD_lookup_connection_value_n (connection,
695  &expect,
696  NULL)) &&
697  (MHD_str_equal_caseless_ (expect,
698  "100-continue")) &&
699  (connection->continue_message_write_offset <
701 }
702 
703 
710 void
712 {
713  const struct MHD_Daemon *daemon = connection->daemon;
714 
715  connection->state = MHD_CONNECTION_CLOSED;
717  if (0 == (daemon->options & MHD_USE_TURBO))
718  {
719 #ifdef HTTPS_SUPPORT
720  /* For TLS connection use shutdown of TLS layer
721  * and do not shutdown TCP socket. This give more
722  * chances to send TLS closure data to remote side.
723  * Closure of TLS layer will be interpreted by
724  * remote side as end of transmission. */
725  if (0 != (daemon->options & MHD_USE_TLS))
726  {
727  if (! MHD_tls_connection_shutdown (connection))
728  shutdown (connection->socket_fd,
729  SHUT_WR);
730  }
731  else /* Combined with next 'shutdown()'. */
732 #endif /* HTTPS_SUPPORT */
733  shutdown (connection->socket_fd,
734  SHUT_WR);
735  }
736 }
737 
738 
748 void
750  enum MHD_RequestTerminationCode termination_code)
751 {
752  struct MHD_Daemon *daemon = connection->daemon;
753  struct MHD_Response *resp = connection->response;
754 
755  MHD_connection_mark_closed_ (connection);
756  if (NULL != resp)
757  {
758  connection->response = NULL;
759  MHD_destroy_response (resp);
760  }
761  if ( (NULL != daemon->notify_completed) &&
762  (connection->client_aware) )
763  daemon->notify_completed (daemon->notify_completed_cls,
764  connection,
765  &connection->client_context,
766  termination_code);
767  connection->client_aware = false;
768 }
769 
770 
771 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
772 
782 void
784 {
785  struct MHD_Daemon *daemon = connection->daemon;
786  struct MHD_UpgradeResponseHandle *urh = connection->urh;
787 
788  if (0 == (daemon->options & MHD_USE_TLS))
789  return; /* Nothing to do with non-TLS connection. */
790 
791  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
792  DLL_remove (daemon->urh_head,
793  daemon->urh_tail,
794  urh);
795 #if EPOLL_SUPPORT
796  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
797  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
798  EPOLL_CTL_DEL,
799  connection->socket_fd,
800  NULL)) )
801  {
802  MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
803  }
804  if (urh->in_eready_list)
805  {
806  EDLL_remove (daemon->eready_urh_head,
807  daemon->eready_urh_tail,
808  urh);
809  urh->in_eready_list = false;
810  }
811 #endif /* EPOLL_SUPPORT */
812  if (MHD_INVALID_SOCKET != urh->mhd.socket)
813  {
814 #if EPOLL_SUPPORT
815  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
816  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
817  EPOLL_CTL_DEL,
818  urh->mhd.socket,
819  NULL)) )
820  {
821  MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
822  }
823 #endif /* EPOLL_SUPPORT */
824  /* Reflect remote disconnect to application by breaking
825  * socketpair connection. */
826  shutdown (urh->mhd.socket, SHUT_RDWR);
827  }
828  /* Socketpair sockets will remain open as they will be
829  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
830  * closed by MHD_cleanup_upgraded_connection_() during
831  * connection's final cleanup.
832  */
833 }
834 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
835 
836 
844 static void
846  const char *emsg)
847 {
848 #ifdef HAVE_MESSAGES
849  if (NULL != emsg)
850  MHD_DLOG (connection->daemon,
851  emsg);
852 #else /* ! HAVE_MESSAGES */
853  (void) emsg; /* Mute compiler warning. */
854 #endif /* ! HAVE_MESSAGES */
855  MHD_connection_close_ (connection,
857 }
858 
859 
864 #ifdef HAVE_MESSAGES
865 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
866 #else
867 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
868 #endif
869 
870 
883 static int
885 {
886  ssize_t ret;
887  struct MHD_Response *response;
888 
889  response = connection->response;
890  if (NULL == response->crc)
891  return MHD_YES;
892  if ( (0 == response->total_size) ||
893  (connection->response_write_position == response->total_size) )
894  return MHD_YES; /* 0-byte response is always ready */
895  if ( (response->data_start <=
896  connection->response_write_position) &&
897  (response->data_size + response->data_start >
898  connection->response_write_position) )
899  return MHD_YES; /* response already ready */
900 #if defined(_MHD_HAVE_SENDFILE)
901  if (MHD_resp_sender_sendfile == connection->resp_sender)
902  {
903  /* will use sendfile, no need to bother response crc */
904  return MHD_YES;
905  }
906 #endif /* _MHD_HAVE_SENDFILE */
907 
908  ret = response->crc (response->crc_cls,
909  connection->response_write_position,
910  response->data,
911  (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
912  response->total_size
913  - connection->response_write_position));
914  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
915  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
916  {
917  /* either error or http 1.0 transfer, close socket! */
918  response->total_size = connection->response_write_position;
919 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
920  MHD_mutex_unlock_chk_ (&response->mutex);
921 #endif
922  if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
923  MHD_connection_close_ (connection,
925  else
926  CONNECTION_CLOSE_ERROR (connection,
927  _ (
928  "Closing connection (application reported error generating data)\n"));
929  return MHD_NO;
930  }
931  response->data_start = connection->response_write_position;
932  response->data_size = ret;
933  if (0 == ret)
934  {
936 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
937  MHD_mutex_unlock_chk_ (&response->mutex);
938 #endif
939  return MHD_NO;
940  }
941  return MHD_YES;
942 }
943 
944 
954 static int
956 {
957  ssize_t ret;
958  struct MHD_Response *response;
959  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
960  int cblen;
961 
962  response = connection->response;
963  if (NULL == response->crc)
964  return MHD_YES;
965  if (0 == connection->write_buffer_size)
966  {
967  size_t size;
968 
969  size = MHD_pool_get_free (connection->pool);
970  if (size < 128)
971  {
972 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
973  MHD_mutex_unlock_chk_ (&response->mutex);
974 #endif
975  /* not enough memory */
976  CONNECTION_CLOSE_ERROR (connection,
977  _ ("Closing connection (out of memory)\n"));
978  return MHD_NO;
979  }
980  if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
981  size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
982  connection->write_buffer = MHD_pool_allocate (connection->pool,
983  size,
984  false);
985  mhd_assert (NULL != connection->write_buffer);
986  connection->write_buffer_size = size;
987  }
988 
989  if (0 == response->total_size)
990  ret = 0; /* response must be empty, don't bother calling crc */
991  else if ( (response->data_start <=
992  connection->response_write_position) &&
993  (response->data_start + response->data_size >
994  connection->response_write_position) )
995  {
996  /* difference between response_write_position and data_start is less
997  than data_size which is size_t type, no need to check for overflow */
998  const size_t data_write_offset
999  = (size_t) (connection->response_write_position - response->data_start);
1000  /* buffer already ready, use what is there for the chunk */
1001  ret = response->data_size - data_write_offset;
1002  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
1003  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1004  memcpy (&connection->write_buffer[sizeof (cbuf)],
1005  &response->data[data_write_offset],
1006  ret);
1007  }
1008  else
1009  {
1010  /* buffer not in range, try to fill it */
1011  ret = response->crc (response->crc_cls,
1012  connection->response_write_position,
1013  &connection->write_buffer[sizeof (cbuf)],
1014  connection->write_buffer_size - sizeof (cbuf) - 2);
1015  }
1016  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1017  {
1018  /* error, close socket! */
1019  response->total_size = connection->response_write_position;
1020 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1021  MHD_mutex_unlock_chk_ (&response->mutex);
1022 #endif
1023  CONNECTION_CLOSE_ERROR (connection,
1024  _ (
1025  "Closing connection (application error generating response)\n"));
1026  return MHD_NO;
1027  }
1028  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1029  (0 == response->total_size) )
1030  {
1031  /* end of message, signal other side! */
1032  memcpy (connection->write_buffer,
1033  "0\r\n",
1034  3);
1035  connection->write_buffer_append_offset = 3;
1036  connection->write_buffer_send_offset = 0;
1037  response->total_size = connection->response_write_position;
1038  return MHD_YES;
1039  }
1040  if (0 == ret)
1041  {
1043 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1044  MHD_mutex_unlock_chk_ (&response->mutex);
1045 #endif
1046  return MHD_NO;
1047  }
1048  if (ret > 0xFFFFFF)
1049  ret = 0xFFFFFF;
1050  cblen = MHD_snprintf_ (cbuf,
1051  sizeof (cbuf),
1052  "%X\r\n",
1053  (unsigned int) ret);
1054  mhd_assert (cblen > 0);
1055  mhd_assert ((size_t) cblen < sizeof(cbuf));
1056  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1057  cbuf,
1058  cblen);
1059  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1060  "\r\n",
1061  2);
1062  connection->response_write_position += ret;
1063  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1064  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1065  return MHD_YES;
1066 }
1067 
1068 
1085 static int
1087 {
1088  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1089  return MHD_NO;
1090  if (NULL == connection->version)
1091  return MHD_NO;
1092  if ( (NULL != connection->response) &&
1093  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1094  return MHD_NO;
1095 
1096  if (MHD_str_equal_caseless_ (connection->version,
1098  ( (NULL == connection->response) ||
1099  (0 == (connection->response->flags
1101  {
1102  if (MHD_lookup_header_s_token_ci (connection,
1104  "upgrade"))
1105  return MHD_NO;
1106 
1107  if (MHD_lookup_header_s_token_ci (connection,
1109  "close"))
1110  return MHD_NO;
1111 
1112  return MHD_YES;
1113  }
1114  if (MHD_str_equal_caseless_ (connection->version,
1116  {
1117  if (MHD_lookup_header_s_token_ci (connection,
1119  "Keep-Alive"))
1120  return MHD_YES;
1121 
1122  return MHD_NO;
1123  }
1124  return MHD_NO;
1125 }
1126 
1127 
1135 static void
1136 get_date_string (char *date,
1137  size_t date_len)
1138 {
1139  static const char *const days[] = {
1140  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1141  };
1142  static const char *const mons[] = {
1143  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1144  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1145  };
1146  struct tm now;
1147  time_t t;
1148 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1149  ! defined(HAVE_GMTIME_R)
1150  struct tm*pNow;
1151 #endif
1152 
1153  date[0] = 0;
1154  time (&t);
1155 #if defined(HAVE_C11_GMTIME_S)
1156  if (NULL == gmtime_s (&t,
1157  &now))
1158  return;
1159 #elif defined(HAVE_W32_GMTIME_S)
1160  if (0 != gmtime_s (&now,
1161  &t))
1162  return;
1163 #elif defined(HAVE_GMTIME_R)
1164  if (NULL == gmtime_r (&t,
1165  &now))
1166  return;
1167 #else
1168  pNow = gmtime (&t);
1169  if (NULL == pNow)
1170  return;
1171  now = *pNow;
1172 #endif
1173  MHD_snprintf_ (date,
1174  date_len,
1175  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1176  days[now.tm_wday % 7],
1177  (unsigned int) now.tm_mday,
1178  mons[now.tm_mon % 12],
1179  (unsigned int) (1900 + now.tm_year),
1180  (unsigned int) now.tm_hour,
1181  (unsigned int) now.tm_min,
1182  (unsigned int) now.tm_sec);
1183 }
1184 
1185 
1198 static bool
1200  bool required)
1201 {
1202  size_t new_size;
1203  size_t avail_size;
1204 
1205  avail_size = MHD_pool_get_free (connection->pool);
1206  if (0 == avail_size)
1207  return false; /* No more space available */
1208  if (0 == connection->read_buffer_size)
1209  new_size = avail_size / 2; /* Use half of available buffer for reading */
1210  else
1211  {
1212  size_t grow_size;
1213 
1214  grow_size = avail_size / 8;
1215  if (MHD_BUF_INC_SIZE > grow_size)
1216  { /* Shortage of space */
1217  if (! required)
1218  return false; /* Grow is not mandatory, leave some space in pool */
1219  else
1220  {
1221  /* Shortage of space, but grow is mandatory */
1222  static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
1223  if (small_inc < avail_size)
1224  grow_size = small_inc;
1225  else
1226  grow_size = avail_size;
1227  }
1228  }
1229  new_size = connection->read_buffer_size + grow_size;
1230  }
1231  /* we can actually grow the buffer, do it! */
1232  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1233  connection->read_buffer,
1234  connection->read_buffer_size,
1235  new_size);
1236  mhd_assert (NULL != connection->read_buffer);
1237  connection->read_buffer_size = new_size;
1238  return true;
1239 }
1240 
1241 
1251 static int
1253 {
1254  struct MHD_Response *response = connection->response;
1255  size_t size;
1256  size_t off;
1257  struct MHD_HTTP_Header *pos;
1258  char code[256];
1259  char date[128];
1260  size_t datelen;
1261  char content_length_buf[128];
1262  size_t content_length_len;
1263  char *data;
1264  enum MHD_ValueKind kind;
1265  const char *reason_phrase;
1266  uint32_t rc;
1267  bool client_requested_close;
1268  bool response_has_close;
1269  bool response_has_keepalive;
1270  const char *have_encoding;
1271  bool must_add_close;
1272  bool must_add_chunked_encoding;
1273  bool must_add_keep_alive;
1274  bool must_add_content_length;
1275  bool may_add_content_length;
1276 
1277  mhd_assert (NULL != connection->version);
1278  if (0 == connection->version[0])
1279  {
1280  data = MHD_pool_allocate (connection->pool,
1281  0,
1282  true);
1283  connection->write_buffer = data;
1284  connection->write_buffer_append_offset = 0;
1285  connection->write_buffer_send_offset = 0;
1286  connection->write_buffer_size = 0;
1287  return MHD_YES;
1288  }
1289  rc = connection->responseCode & (~MHD_ICY_FLAG);
1290  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1291  {
1292  reason_phrase = MHD_get_reason_phrase_for (rc);
1293  off = MHD_snprintf_ (code,
1294  sizeof (code),
1295  "%s %u %s\r\n",
1296  (0 != (connection->responseCode & MHD_ICY_FLAG))
1297  ? "ICY"
1299  connection->version) ||
1300  (0 != (connection->response->flags
1304  rc,
1305  reason_phrase);
1306  /* estimate size */
1307  size = off + 2; /* +2 for extra "\r\n" at the end */
1309  if ( (0 == (connection->daemon->options
1311  (NULL == MHD_get_response_header (response,
1313  get_date_string (date,
1314  sizeof (date));
1315  else
1316  date[0] = '\0';
1317  datelen = strlen (date);
1318  size += datelen;
1319  }
1320  else
1321  {
1322  /* 2 bytes for final CRLF of a Chunked-Body */
1323  size = 2;
1325  off = 0;
1326  datelen = 0;
1327  }
1328 
1329  /* calculate extra headers we need to add, such as 'Connection: close',
1330  first see what was explicitly requested by the application */
1331  must_add_close = false;
1332  must_add_chunked_encoding = false;
1333  must_add_keep_alive = false;
1334  must_add_content_length = false;
1335  response_has_close = false;
1336  switch (connection->state)
1337  {
1339  response_has_close = MHD_check_response_header_s_token_ci (response,
1341  "close");
1342  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1344  "Keep-Alive");
1345  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1347  "close");
1348 
1349  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1350  connection->keepalive = MHD_CONN_MUST_CLOSE;
1351 #ifdef UPGRADE_SUPPORT
1352  else if (NULL != response->upgrade_handler)
1353  /* If this connection will not be "upgraded", it must be closed. */
1354  connection->keepalive = MHD_CONN_MUST_CLOSE;
1355 #endif /* UPGRADE_SUPPORT */
1356 
1357  /* now analyze chunked encoding situation */
1358  connection->have_chunked_upload = false;
1359  have_encoding = MHD_get_response_header (response,
1361  if (NULL == have_encoding)
1362  may_add_content_length = true;
1363  else
1364  may_add_content_length = false; /* RFC 7230, Section 3.3.2 forbids header */
1365  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1366 #ifdef UPGRADE_SUPPORT
1367  (NULL == response->upgrade_handler) &&
1368 #endif /* UPGRADE_SUPPORT */
1369  (! response_has_close) &&
1370  (! client_requested_close) )
1371  {
1372  /* size is unknown, and close was not explicitly requested;
1373  need to either to HTTP 1.1 chunked encoding or
1374  close the connection */
1375  /* 'close' header doesn't exist yet, see if we need to add one;
1376  if the client asked for a close, no need to start chunk'ing */
1377  if ( (MHD_YES == keepalive_possible (connection)) &&
1379  connection->version) ) )
1380  {
1381  if (NULL == have_encoding)
1382  {
1383  must_add_chunked_encoding = true;
1384  connection->have_chunked_upload = true;
1385  }
1386  else
1387  {
1388  if (MHD_str_equal_caseless_ (have_encoding,
1389  "identity"))
1390  {
1391  /* application forced identity encoding, can't do 'chunked' */
1392  must_add_close = true;
1393  }
1394  else
1395  {
1396  connection->have_chunked_upload = true;
1397  }
1398  }
1399  }
1400  else
1401  {
1402  /* Keep alive or chunking not possible
1403  => set close header if not present */
1404  if (! response_has_close)
1405  must_add_close = true;
1406  }
1407  }
1408 
1409  /* check for other reasons to add 'close' header */
1410  if ( ( (client_requested_close) ||
1411  (connection->read_closed) ||
1412  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1413  (! response_has_close) &&
1414 #ifdef UPGRADE_SUPPORT
1415  (NULL == response->upgrade_handler) &&
1416 #endif /* UPGRADE_SUPPORT */
1417  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1418  must_add_close = true;
1419 
1420  /* check if we must add 'close' header because we cannot add content-length
1421  because it is forbidden AND we don't have a 'chunked' encoding */
1422  if ( (! may_add_content_length) &&
1423  (! connection->have_chunked_upload) &&
1424  (! response_has_close) )
1425  must_add_close = true;
1426  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1427  codes SHOULD NOT have a Content-Length according to spec;
1428  also chunked encoding / unknown length or CONNECT... */
1429  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1430  (MHD_HTTP_NO_CONTENT != rc) &&
1431  (MHD_HTTP_NOT_MODIFIED != rc) &&
1432  (MHD_HTTP_OK <= rc) &&
1433  (NULL == /* this COULD fail if the check in
1434  MHD_add_response_header() was bypassed
1435  via #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH */
1436  MHD_get_response_header (response,
1438  (may_add_content_length) &&
1439  ( (NULL == connection->method) ||
1440  (! MHD_str_equal_caseless_ (connection->method,
1442  {
1443  /*
1444  Here we add a content-length if one is missing; however,
1445  for 'connect' methods, the responses MUST NOT include a
1446  content-length header *if* the response code is 2xx (in
1447  which case we expect there to be no body). Still,
1448  as we don't know the response code here in some cases, we
1449  simply only force adding a content-length header if this
1450  is not a 'connect' or if the response is not empty
1451  (which is kind of more sane, because if some crazy
1452  application did return content with a 2xx status code,
1453  then having a content-length might again be a good idea).
1454 
1455  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1456  a recent development of the HTTP 1.1 specification.
1457  */
1458  content_length_len
1459  = MHD_snprintf_ (content_length_buf,
1460  sizeof (content_length_buf),
1463  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1464  must_add_content_length = true;
1465  }
1466 
1467  /* check for adding keep alive */
1468  if ( (! response_has_keepalive) &&
1469  (! response_has_close) &&
1470  (! must_add_close) &&
1471  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1472 #ifdef UPGRADE_SUPPORT
1473  (NULL == response->upgrade_handler) &&
1474 #endif /* UPGRADE_SUPPORT */
1475  (MHD_YES == keepalive_possible (connection)) )
1476  must_add_keep_alive = true;
1477  break;
1479  response_has_keepalive = false;
1480  break;
1481  default:
1482  mhd_assert (0);
1483  return MHD_NO;
1484  }
1485 
1486  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1487  {
1488  if ( (must_add_close) || (response_has_close) )
1489  connection->keepalive = MHD_CONN_MUST_CLOSE;
1490  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1491  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1492  }
1493 
1494  if (must_add_close)
1495  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1496  if (must_add_keep_alive)
1497  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1498  if (must_add_chunked_encoding)
1499  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1500  if (must_add_content_length)
1501  size += content_length_len;
1502  mhd_assert (! (must_add_close && must_add_keep_alive) );
1503  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1504 
1505  for (pos = response->first_header; NULL != pos; pos = pos->next)
1506  {
1507  /* TODO: add proper support for excluding "Keep-Alive" token. */
1508  if ( (pos->kind == kind) &&
1509  (! ( (must_add_close) &&
1510  (response_has_keepalive) &&
1511  (pos->header_size == MHD_STATICSTR_LEN_ (
1518  "Keep-Alive")) ) ) )
1519  size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */
1520  }
1521  /* produce data */
1522  data = MHD_pool_allocate (connection->pool,
1523  size + 1,
1524  false);
1525  if (NULL == data)
1526  {
1527 #ifdef HAVE_MESSAGES
1528  MHD_DLOG (connection->daemon,
1529  "Not enough memory for write!\n");
1530 #endif
1531  return MHD_NO;
1532  }
1533  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1534  {
1535  memcpy (data,
1536  code,
1537  off);
1538  }
1539  if (must_add_close)
1540  {
1541  /* we must add the 'Connection: close' header */
1542  memcpy (&data[off],
1543  "Connection: close\r\n",
1544  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1545  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1546  }
1547  if (must_add_keep_alive)
1548  {
1549  /* we must add the 'Connection: Keep-Alive' header */
1550  memcpy (&data[off],
1551  "Connection: Keep-Alive\r\n",
1552  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1553  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1554  }
1555  if (must_add_chunked_encoding)
1556  {
1557  /* we must add the 'Transfer-Encoding: chunked' header */
1558  memcpy (&data[off],
1559  "Transfer-Encoding: chunked\r\n",
1560  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1561  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1562  }
1563  if (must_add_content_length)
1564  {
1565  /* we must add the 'Content-Length' header */
1566  memcpy (&data[off],
1567  content_length_buf,
1568  content_length_len);
1569  off += content_length_len;
1570  }
1571  for (pos = response->first_header; NULL != pos; pos = pos->next)
1572  {
1573  /* TODO: add proper support for excluding "Keep-Alive" token. */
1574  if ( (pos->kind == kind) &&
1575  (! ( (must_add_close) &&
1576  (response_has_keepalive) &&
1577  (pos->header_size == MHD_STATICSTR_LEN_ (
1584  "Keep-Alive")) ) ) )
1585  off += MHD_snprintf_ (&data[off],
1586  size - off,
1587  "%s: %s\r\n",
1588  pos->header,
1589  pos->value);
1590  }
1591  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1592  {
1593  memcpy (&data[off],
1594  date,
1595  datelen);
1596  off += datelen;
1597  }
1598  memcpy (&data[off],
1599  "\r\n",
1600  2);
1601  off += 2;
1602 
1603  if (off != size)
1605  __FILE__,
1606  __LINE__,
1607  NULL);
1608  connection->write_buffer = data;
1609  connection->write_buffer_append_offset = size;
1610  connection->write_buffer_send_offset = 0;
1611  connection->write_buffer_size = size + 1;
1612  return MHD_YES;
1613 }
1614 
1615 
1625 static void
1627  unsigned int status_code,
1628  const char *message)
1629 {
1630  struct MHD_Response *response;
1631  int iret;
1632 
1633  if (NULL == connection->version)
1634  {
1635  /* we were unable to process the full header line, so we don't
1636  really know what version the client speaks; assume 1.0 */
1637  connection->version = MHD_HTTP_VERSION_1_0;
1638  }
1639  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1640  connection->read_closed = true;
1641  if (0 != connection->read_buffer_size)
1642  {
1643  /* Read buffer is not needed anymore, discard it
1644  * to free some space for error response. */
1645  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1646  connection->read_buffer,
1647  connection->read_buffer_size,
1648  0);
1649  connection->read_buffer_size = 0;
1650  }
1651 #ifdef HAVE_MESSAGES
1652  MHD_DLOG (connection->daemon,
1653  _ (
1654  "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1655  status_code,
1656  message);
1657 #endif
1658  if (NULL != connection->response)
1659  {
1660  MHD_destroy_response (connection->response);
1661  connection->response = NULL;
1662  }
1663  response = MHD_create_response_from_buffer (strlen (message),
1664  (void *) message,
1666  if (NULL == response)
1667  {
1668  /* can't even send a reply, at least close the connection */
1669  connection->state = MHD_CONNECTION_CLOSED;
1670  return;
1671  }
1672  iret = MHD_queue_response (connection,
1673  status_code,
1674  response);
1675  MHD_destroy_response (response);
1676  if (MHD_YES != iret)
1677  {
1678  /* can't even send a reply, at least close the connection */
1679  CONNECTION_CLOSE_ERROR (connection,
1680  _ (
1681  "Closing connection (failed to queue response)\n"));
1682  return;
1683  }
1684  mhd_assert (NULL != connection->response);
1685  /* Do not reuse this connection. */
1686  connection->keepalive = MHD_CONN_MUST_CLOSE;
1687  if (MHD_NO == build_header_response (connection))
1688  {
1689  /* oops - close! */
1690  CONNECTION_CLOSE_ERROR (connection,
1691  _ (
1692  "Closing connection (failed to create response header)\n"));
1693  }
1694  else
1695  {
1696  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1697  }
1698 }
1699 
1700 
1709 static void
1711 {
1712  /* Do not update states of suspended connection */
1713  if (connection->suspended)
1714  return; /* States will be updated after resume. */
1715 #ifdef HTTPS_SUPPORT
1716  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1717  { /* HTTPS connection. */
1718  switch (connection->tls_state)
1719  {
1720  case MHD_TLS_CONN_INIT:
1722  return;
1724  if (0 == gnutls_record_get_direction (connection->tls_session))
1726  else
1728  return;
1729  default:
1730  break;
1731  }
1732  }
1733 #endif /* HTTPS_SUPPORT */
1734  while (1)
1735  {
1736 #if DEBUG_STATES
1737  MHD_DLOG (connection->daemon,
1738  _ ("In function %s handling connection at state: %s\n"),
1739  __FUNCTION__,
1740  MHD_state_to_string (connection->state));
1741 #endif
1742  switch (connection->state)
1743  {
1744  case MHD_CONNECTION_INIT:
1747  /* while reading headers, we always grow the
1748  read buffer if needed, no size-check required */
1749  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1750  (! try_grow_read_buffer (connection, true)) )
1751  {
1752  transmit_error_response (connection,
1753  (connection->url != NULL)
1756  REQUEST_TOO_BIG);
1757  continue;
1758  }
1759  if (! connection->read_closed)
1761  else
1763  break;
1765  mhd_assert (0);
1766  break;
1768  mhd_assert (0);
1769  break;
1772  break;
1774  if (connection->read_buffer_offset == connection->read_buffer_size)
1775  {
1776  const bool internal_poll = (0 != (connection->daemon->options
1778  if ( (! try_grow_read_buffer (connection, true)) &&
1779  internal_poll)
1780  {
1781  /* failed to grow the read buffer, and the
1782  client which is supposed to handle the
1783  received data in a *blocking* fashion
1784  (in this mode) did not handle the data as
1785  it was supposed to!
1786  => we would either have to do busy-waiting
1787  (on the client, which would likely fail),
1788  or if we do nothing, we would just timeout
1789  on the connection (if a timeout is even
1790  set!).
1791  Solution: we kill the connection with an error */
1792  transmit_error_response (connection,
1794  INTERNAL_ERROR);
1795  continue;
1796  }
1797  }
1798  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1799  (! connection->read_closed) )
1801  else
1803  break;
1806  /* while reading footers, we always grow the
1807  read buffer if needed, no size-check required */
1808  if (connection->read_closed)
1809  {
1810  CONNECTION_CLOSE_ERROR (connection,
1811  NULL);
1812  continue;
1813  }
1815  /* transition to FOOTERS_RECEIVED
1816  happens in read handler */
1817  break;
1820  break;
1822  /* headers in buffer, keep writing */
1824  break;
1826  mhd_assert (0);
1827  break;
1830  break;
1833  break;
1836  break;
1839  break;
1841  mhd_assert (0);
1842  break;
1845  break;
1847  mhd_assert (0);
1848  break;
1849  case MHD_CONNECTION_CLOSED:
1851  return; /* do nothing, not even reading */
1852 #ifdef UPGRADE_SUPPORT
1853  case MHD_CONNECTION_UPGRADE:
1854  mhd_assert (0);
1855  break;
1856 #endif /* UPGRADE_SUPPORT */
1857  default:
1858  mhd_assert (0);
1859  }
1860  break;
1861  }
1862 }
1863 
1864 
1878 static char *
1880  size_t *line_len)
1881 {
1882  char *rbuf;
1883  size_t pos;
1884 
1885  if (0 == connection->read_buffer_offset)
1886  return NULL;
1887  pos = 0;
1888  rbuf = connection->read_buffer;
1889  while ( (pos < connection->read_buffer_offset - 1) &&
1890  ('\r' != rbuf[pos]) &&
1891  ('\n' != rbuf[pos]) )
1892  pos++;
1893  if ( (pos == connection->read_buffer_offset - 1) &&
1894  ('\n' != rbuf[pos]) )
1895  {
1896  /* not found, consider growing... */
1897  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1898  (! try_grow_read_buffer (connection, true)) )
1899  {
1900  transmit_error_response (connection,
1901  (NULL != connection->url)
1904  REQUEST_TOO_BIG);
1905  }
1906  if (line_len)
1907  *line_len = 0;
1908  return NULL;
1909  }
1910 
1911  if (line_len)
1912  *line_len = pos;
1913  /* found, check if we have proper LFCR */
1914  if ( ('\r' == rbuf[pos]) &&
1915  ('\n' == rbuf[pos + 1]) )
1916  rbuf[pos++] = '\0'; /* skip both r and n */
1917  rbuf[pos++] = '\0';
1918  connection->read_buffer += pos;
1919  connection->read_buffer_size -= pos;
1920  connection->read_buffer_offset -= pos;
1921  return rbuf;
1922 }
1923 
1924 
1938 static int
1940  const char *key,
1941  size_t key_size,
1942  const char *value,
1943  size_t value_size,
1944  enum MHD_ValueKind kind)
1945 {
1946  if (MHD_NO ==
1947  MHD_set_connection_value_n (connection,
1948  kind,
1949  key,
1950  key_size,
1951  value,
1952  value_size))
1953  {
1954 #ifdef HAVE_MESSAGES
1955  MHD_DLOG (connection->daemon,
1956  _ ("Not enough memory in pool to allocate header record!\n"));
1957 #endif
1958  transmit_error_response (connection,
1960  REQUEST_TOO_BIG);
1961  return MHD_NO;
1962  }
1963  return MHD_YES;
1964 }
1965 
1966 
1973 static int
1975 {
1976  const char *hdr;
1977  size_t hdr_len;
1978  char *cpy;
1979  char *pos;
1980  char *sce;
1981  char *semicolon;
1982  char *equals;
1983  char *ekill;
1984  char *end;
1985  char old;
1986  int quotes;
1987 
1988  if (MHD_NO == MHD_lookup_connection_value_n (connection,
1993  &hdr,
1994  &hdr_len))
1995  return MHD_YES;
1996  cpy = MHD_pool_allocate (connection->pool,
1997  hdr_len + 1,
1998  true);
1999  if (NULL == cpy)
2000  {
2001 #ifdef HAVE_MESSAGES
2002  MHD_DLOG (connection->daemon,
2003  _ ("Not enough memory in pool to parse cookies!\n"));
2004 #endif
2005  transmit_error_response (connection,
2007  REQUEST_TOO_BIG);
2008  return MHD_NO;
2009  }
2010  memcpy (cpy,
2011  hdr,
2012  hdr_len);
2013  cpy[hdr_len] = '\0';
2014  pos = cpy;
2015  while (NULL != pos)
2016  {
2017  while (' ' == *pos)
2018  pos++; /* skip spaces */
2019 
2020  sce = pos;
2021  while ( ((*sce) != '\0') &&
2022  ((*sce) != ',') &&
2023  ((*sce) != ';') &&
2024  ((*sce) != '=') )
2025  sce++;
2026  /* remove tailing whitespace (if any) from key */
2027  ekill = sce - 1;
2028  while ( (*ekill == ' ') &&
2029  (ekill >= pos) )
2030  *(ekill--) = '\0';
2031  old = *sce;
2032  *sce = '\0';
2033  if (old != '=')
2034  {
2035  /* value part omitted, use empty string... */
2036  if (MHD_NO ==
2037  connection_add_header (connection,
2038  pos,
2039  ekill - pos + 1,
2040  "",
2041  0,
2042  MHD_COOKIE_KIND))
2043  return MHD_NO;
2044  if (old == '\0')
2045  break;
2046  pos = sce + 1;
2047  continue;
2048  }
2049  equals = sce + 1;
2050  quotes = 0;
2051  semicolon = equals;
2052  while ( ('\0' != semicolon[0]) &&
2053  ( (0 != quotes) ||
2054  ( (';' != semicolon[0]) &&
2055  (',' != semicolon[0]) ) ) )
2056  {
2057  if ('"' == semicolon[0])
2058  quotes = (quotes + 1) & 1;
2059  semicolon++;
2060  }
2061  end = semicolon;
2062  if ('\0' == semicolon[0])
2063  semicolon = NULL;
2064  if (NULL != semicolon)
2065  {
2066  semicolon[0] = '\0';
2067  semicolon++;
2068  }
2069  /* remove quotes */
2070  if ( ('"' == equals[0]) &&
2071  ('"' == end[-1]) )
2072  {
2073  equals++;
2074  end--;
2075  *end = '\0';
2076  }
2077  if (MHD_NO ==
2078  connection_add_header (connection,
2079  pos,
2080  ekill - pos + 1,
2081  equals,
2082  end - equals,
2083  MHD_COOKIE_KIND))
2084  return MHD_NO;
2085  pos = semicolon;
2086  }
2087  return MHD_YES;
2088 }
2089 
2090 
2099 static int
2101  char *line,
2102  size_t line_len)
2103 {
2104  struct MHD_Daemon *daemon = connection->daemon;
2105  const char *curi;
2106  char *uri;
2107  char *http_version;
2108  char *args;
2109  unsigned int unused_num_headers;
2110 
2111  if (NULL == (uri = memchr (line,
2112  ' ',
2113  line_len)))
2114  return MHD_NO; /* serious error */
2115  uri[0] = '\0';
2116  connection->method = line;
2117  uri++;
2118  /* Skip any spaces. Not required by standard but allow
2119  to be more tolerant. */
2120  while ( (' ' == uri[0]) &&
2121  ( (size_t) (uri - line) < line_len) )
2122  uri++;
2123  if ((size_t) (uri - line) == line_len)
2124  {
2125  /* No URI and no http version given */
2126  curi = "";
2127  uri = NULL;
2128  connection->version = "";
2129  args = NULL;
2130  }
2131  else
2132  {
2133  size_t uri_len;
2134  curi = uri;
2135  /* Search from back to accept misformed URI with space */
2136  http_version = line + line_len - 1;
2137  /* Skip any trailing spaces */
2138  while ( (' ' == http_version[0]) &&
2139  (http_version > uri) )
2140  http_version--;
2141  /* Find first space in reverse direction */
2142  while ( (' ' != http_version[0]) &&
2143  (http_version > uri) )
2144  http_version--;
2145  if (http_version > uri)
2146  {
2147  /* http_version points to character before HTTP version string */
2148  http_version[0] = '\0';
2149  connection->version = http_version + 1;
2150  uri_len = http_version - uri;
2151  }
2152  else
2153  {
2154  connection->version = "";
2155  uri_len = line_len - (uri - line);
2156  }
2157  /* check for spaces in URI if we are "strict" */
2158  if ( (1 <= daemon->strict_for_client) &&
2159  (NULL != memchr (uri,
2160  ' ',
2161  uri_len)) )
2162  {
2163  /* space exists in URI and we are supposed to be strict, reject */
2164  return MHD_NO;
2165  }
2166 
2167  args = memchr (uri,
2168  '?',
2169  uri_len);
2170  }
2171 
2172  /* log callback before we modify URI *or* args */
2173  if (NULL != daemon->uri_log_callback)
2174  {
2175  connection->client_aware = true;
2176  connection->client_context
2177  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2178  uri,
2179  connection);
2180  }
2181 
2182  if (NULL != args)
2183  {
2184  args[0] = '\0';
2185  args++;
2186  /* note that this call clobbers 'args' */
2187  MHD_parse_arguments_ (connection,
2189  args,
2191  &unused_num_headers);
2192  }
2193 
2194  /* unescape URI *after* searching for arguments and log callback */
2195  if (NULL != uri)
2196  daemon->unescape_callback (daemon->unescape_callback_cls,
2197  connection,
2198  uri);
2199  connection->url = curi;
2200  return MHD_YES;
2201 }
2202 
2203 
2211 static void
2213 {
2214  struct MHD_Daemon *daemon = connection->daemon;
2215  size_t processed;
2216 
2217  if (NULL != connection->response)
2218  return; /* already queued a response */
2219  processed = 0;
2220  connection->client_aware = true;
2221  if (MHD_NO ==
2222  daemon->default_handler (daemon->default_handler_cls,
2223  connection,
2224  connection->url,
2225  connection->method,
2226  connection->version,
2227  NULL,
2228  &processed,
2229  &connection->client_context))
2230  {
2231  /* serious internal error, close connection */
2232  CONNECTION_CLOSE_ERROR (connection,
2233  _ (
2234  "Application reported internal error, closing connection.\n"));
2235  return;
2236  }
2237 }
2238 
2239 
2247 static void
2249 {
2250  struct MHD_Daemon *daemon = connection->daemon;
2251  size_t available;
2252  int instant_retry;
2253  char *buffer_head;
2254 
2255  if (NULL != connection->response)
2256  {
2257  /* already queued a response, discard remaining upload
2258  (but not more, there might be another request after it) */
2259  uint64_t purge = MHD_MIN (connection->remaining_upload_size,
2260  connection->read_buffer_offset);
2261  connection->remaining_upload_size -= purge;
2262  if (connection->read_buffer_offset > purge)
2263  memmove (connection->read_buffer,
2264  &connection->read_buffer[purge],
2265  connection->read_buffer_offset - purge);
2266  connection->read_buffer_offset -= purge;
2267  return;
2268  }
2269 
2270  buffer_head = connection->read_buffer;
2271  available = connection->read_buffer_offset;
2272  do
2273  {
2274  size_t to_be_processed;
2275  size_t left_unprocessed;
2276  size_t processed_size;
2277 
2278  instant_retry = MHD_NO;
2279  if ( (connection->have_chunked_upload) &&
2280  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2281  {
2282  if ( (connection->current_chunk_offset ==
2283  connection->current_chunk_size) &&
2284  (0LLU != connection->current_chunk_offset) &&
2285  (available >= 2) )
2286  {
2287  size_t i;
2288  /* skip new line at the *end* of a chunk */
2289  i = 0;
2290  if ( ('\r' == buffer_head[i]) ||
2291  ('\n' == buffer_head[i]) )
2292  i++; /* skip 1st part of line feed */
2293  if ( ('\r' == buffer_head[i]) ||
2294  ('\n' == buffer_head[i]) )
2295  i++; /* skip 2nd part of line feed */
2296  if (0 == i)
2297  {
2298  /* malformed encoding */
2299  CONNECTION_CLOSE_ERROR (connection,
2300  _ (
2301  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2302  return;
2303  }
2304  available -= i;
2305  buffer_head += i;
2306  connection->current_chunk_offset = 0;
2307  connection->current_chunk_size = 0;
2308  }
2309  if (connection->current_chunk_offset <
2310  connection->current_chunk_size)
2311  {
2312  uint64_t cur_chunk_left;
2313  /* we are in the middle of a chunk, give
2314  as much as possible to the client (without
2315  crossing chunk boundaries) */
2316  cur_chunk_left
2317  = connection->current_chunk_size - connection->current_chunk_offset;
2318  if (cur_chunk_left > available)
2319  to_be_processed = available;
2320  else
2321  { /* cur_chunk_left <= (size_t)available */
2322  to_be_processed = (size_t) cur_chunk_left;
2323  if (available > to_be_processed)
2324  instant_retry = MHD_YES;
2325  }
2326  }
2327  else
2328  {
2329  size_t i;
2330  size_t end_size;
2331  bool malformed;
2332 
2333  /* we need to read chunk boundaries */
2334  i = 0;
2335  while (i < available)
2336  {
2337  if ( ('\r' == buffer_head[i]) ||
2338  ('\n' == buffer_head[i]) ||
2339  (';' == buffer_head[i]) )
2340  break;
2341  i++;
2342  if (i >= 16)
2343  break;
2344  }
2345  end_size = i;
2346  /* find beginning of CRLF (skip over chunk extensions) */
2347  if (';' == buffer_head[i])
2348  {
2349  while (i < available)
2350  {
2351  if ( ('\r' == buffer_head[i]) ||
2352  ('\n' == buffer_head[i]) )
2353  break;
2354  i++;
2355  }
2356  }
2357  /* take '\n' into account; if '\n' is the unavailable
2358  character, we will need to wait until we have it
2359  before going further */
2360  if ( (i + 1 >= available) &&
2361  ! ( (1 == i) &&
2362  (2 == available) &&
2363  ('0' == buffer_head[0]) ) )
2364  break; /* need more data... */
2365  i++;
2366  malformed = (end_size >= 16);
2367  if (! malformed)
2368  {
2369  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2370  end_size,
2371  &connection->
2372  current_chunk_size);
2373  malformed = (end_size != num_dig);
2374  }
2375  if (malformed)
2376  {
2377  /* malformed encoding */
2378  CONNECTION_CLOSE_ERROR (connection,
2379  _ (
2380  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2381  return;
2382  }
2383  /* skip 2nd part of line feed */
2384  if ( (i < available) &&
2385  ( ('\r' == buffer_head[i]) ||
2386  ('\n' == buffer_head[i]) ) )
2387  i++;
2388 
2389  buffer_head += i;
2390  available -= i;
2391  connection->current_chunk_offset = 0;
2392 
2393  if (available > 0)
2394  instant_retry = MHD_YES;
2395  if (0LLU == connection->current_chunk_size)
2396  {
2397  connection->remaining_upload_size = 0;
2398  break;
2399  }
2400  continue;
2401  }
2402  }
2403  else
2404  {
2405  /* no chunked encoding, give all to the client */
2406  if ( (0 != connection->remaining_upload_size) &&
2407  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2408  (connection->remaining_upload_size < available) )
2409  {
2410  to_be_processed = (size_t) connection->remaining_upload_size;
2411  }
2412  else
2413  {
2418  to_be_processed = available;
2419  }
2420  }
2421  left_unprocessed = to_be_processed;
2422  connection->client_aware = true;
2423  if (MHD_NO ==
2424  daemon->default_handler (daemon->default_handler_cls,
2425  connection,
2426  connection->url,
2427  connection->method,
2428  connection->version,
2429  buffer_head,
2430  &left_unprocessed,
2431  &connection->client_context))
2432  {
2433  /* serious internal error, close connection */
2434  CONNECTION_CLOSE_ERROR (connection,
2435  _ (
2436  "Application reported internal error, closing connection.\n"));
2437  return;
2438  }
2439  if (left_unprocessed > to_be_processed)
2441  __FILE__,
2442  __LINE__
2443 #ifdef HAVE_MESSAGES
2444  , _ ("libmicrohttpd API violation")
2445 #else
2446  , NULL
2447 #endif
2448  );
2449  if (0 != left_unprocessed)
2450  {
2451  instant_retry = MHD_NO; /* client did not process everything */
2452 #ifdef HAVE_MESSAGES
2453  /* client did not process all upload data, complain if
2454  the setup was incorrect, which may prevent us from
2455  handling the rest of the request */
2456  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2457  (! connection->suspended) )
2458  MHD_DLOG (daemon,
2459  _ (
2460  "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2461 #endif
2462  }
2463  processed_size = to_be_processed - left_unprocessed;
2464  if (connection->have_chunked_upload)
2465  connection->current_chunk_offset += processed_size;
2466  /* dh left "processed" bytes in buffer for next time... */
2467  buffer_head += processed_size;
2468  available -= processed_size;
2469  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2470  connection->remaining_upload_size -= processed_size;
2471  }
2472  while (MHD_YES == instant_retry);
2473  if ( (available > 0) &&
2474  (buffer_head != connection->read_buffer) )
2475  memmove (connection->read_buffer,
2476  buffer_head,
2477  available);
2478  connection->read_buffer_offset = available;
2479 }
2480 
2481 
2490 static int
2491 check_write_done (struct MHD_Connection *connection,
2492  enum MHD_CONNECTION_STATE next_state)
2493 {
2494  if (connection->write_buffer_append_offset !=
2495  connection->write_buffer_send_offset)
2496  return MHD_NO;
2497  connection->write_buffer_append_offset = 0;
2498  connection->write_buffer_send_offset = 0;
2499  connection->state = next_state;
2500  MHD_pool_reallocate (connection->pool,
2501  connection->write_buffer,
2502  connection->write_buffer_size,
2503  0);
2504  connection->write_buffer = NULL;
2505  connection->write_buffer_size = 0;
2506  return MHD_YES;
2507 }
2508 
2509 
2519 static int
2521  char *line)
2522 {
2523  char *colon;
2524 
2525  /* line should be normal header line, find colon */
2526  colon = strchr (line, ':');
2527  if (NULL == colon)
2528  {
2529  /* error in header line, die hard */
2530  CONNECTION_CLOSE_ERROR (connection,
2531  _ (
2532  "Received malformed line (no colon). Closing connection.\n"));
2533  return MHD_NO;
2534  }
2535  if (-1 >= connection->daemon->strict_for_client)
2536  {
2537  /* check for whitespace before colon, which is not allowed
2538  by RFC 7230 section 3.2.4; we count space ' ' and
2539  tab '\t', but not '\r\n' as those would have ended the line. */
2540  const char *white;
2541 
2542  white = strchr (line, ' ');
2543  if ( (NULL != white) &&
2544  (white < colon) )
2545  return MHD_NO;
2546  white = strchr (line, '\t');
2547  if ( (NULL != white) &&
2548  (white < colon) )
2549  return MHD_NO;
2550  }
2551  /* zero-terminate header */
2552  colon[0] = '\0';
2553  colon++; /* advance to value */
2554  while ( ('\0' != colon[0]) &&
2555  ( (' ' == colon[0]) ||
2556  ('\t' == colon[0]) ) )
2557  colon++;
2558  /* we do the actual adding of the connection
2559  header at the beginning of the while
2560  loop since we need to be able to inspect
2561  the *next* header line (in case it starts
2562  with a space...) */
2563  connection->last = line;
2564  connection->colon = colon;
2565  return MHD_YES;
2566 }
2567 
2568 
2579 static int
2581  char *line,
2582  enum MHD_ValueKind kind)
2583 {
2584  char *last;
2585  char *tmp;
2586  size_t last_len;
2587  size_t tmp_len;
2588 
2589  last = connection->last;
2590  if ( (' ' == line[0]) ||
2591  ('\t' == line[0]) )
2592  {
2593  /* value was continued on the next line, see
2594  http://www.jmarshall.com/easy/http/ */
2595  last_len = strlen (last);
2596  /* skip whitespace at start of 2nd line */
2597  tmp = line;
2598  while ( (' ' == tmp[0]) ||
2599  ('\t' == tmp[0]) )
2600  tmp++;
2601  tmp_len = strlen (tmp);
2602  /* FIXME: we might be able to do this better (faster!), as most
2603  likely 'last' and 'line' should already be adjacent in
2604  memory; however, doing this right gets tricky if we have a
2605  value continued over multiple lines (in which case we need to
2606  record how often we have done this so we can check for
2607  adjacency); also, in the case where these are not adjacent
2608  (not sure how it can happen!), we would want to allocate from
2609  the end of the pool, so as to not destroy the read-buffer's
2610  ability to grow nicely. */
2611  last = MHD_pool_reallocate (connection->pool,
2612  last,
2613  last_len + 1,
2614  last_len + tmp_len + 1);
2615  if (NULL == last)
2616  {
2617  transmit_error_response (connection,
2619  REQUEST_TOO_BIG);
2620  return MHD_NO;
2621  }
2622  memcpy (&last[last_len],
2623  tmp,
2624  tmp_len + 1);
2625  connection->last = last;
2626  return MHD_YES; /* possibly more than 2 lines... */
2627  }
2628  mhd_assert ( (NULL != last) &&
2629  (NULL != connection->colon) );
2630  if (MHD_NO ==
2631  connection_add_header (connection,
2632  last,
2633  strlen (last),
2634  connection->colon,
2635  strlen (connection->colon),
2636  kind))
2637  {
2638  transmit_error_response (connection,
2640  REQUEST_TOO_BIG);
2641  return MHD_NO;
2642  }
2643  /* we still have the current line to deal with... */
2644  if (0 != line[0])
2645  {
2646  if (MHD_NO == process_header_line (connection,
2647  line))
2648  {
2649  transmit_error_response (connection,
2652  return MHD_NO;
2653  }
2654  }
2655  return MHD_YES;
2656 }
2657 
2658 
2666 static void
2668 {
2669  const char *clen;
2670  struct MHD_Response *response;
2671  const char *enc;
2672  const char *end;
2673 
2674  parse_cookie_header (connection);
2675  if ( (1 <= connection->daemon->strict_for_client) &&
2676  (NULL != connection->version) &&
2678  connection->version)) &&
2679  (MHD_NO ==
2680  MHD_lookup_connection_value_n (connection,
2685  NULL,
2686  NULL)) )
2687  {
2688  int iret;
2689 
2690  /* die, http 1.1 request without host and we are pedantic */
2691  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2692  connection->read_closed = true;
2693 #ifdef HAVE_MESSAGES
2694  MHD_DLOG (connection->daemon,
2695  _ ("Received HTTP 1.1 request without `Host' header.\n"));
2696 #endif
2697  mhd_assert (NULL == connection->response);
2698  response =
2702  if (NULL == response)
2703  {
2704  /* can't even send a reply, at least close the connection */
2705  CONNECTION_CLOSE_ERROR (connection,
2706  _ (
2707  "Closing connection (failed to create response)\n"));
2708  return;
2709  }
2710  iret = MHD_queue_response (connection,
2712  response);
2713  MHD_destroy_response (response);
2714  if (MHD_YES != iret)
2715  {
2716  /* can't even send a reply, at least close the connection */
2717  CONNECTION_CLOSE_ERROR (connection,
2718  _ (
2719  "Closing connection (failed to queue response)\n"));
2720  }
2721  return;
2722  }
2723 
2724  connection->remaining_upload_size = 0;
2725  if (MHD_NO != MHD_lookup_connection_value_n (connection,
2730  &enc,
2731  NULL))
2732  {
2734  if (MHD_str_equal_caseless_ (enc,
2735  "chunked"))
2736  connection->have_chunked_upload = true;
2737  }
2738  else
2739  {
2740  if (MHD_NO != MHD_lookup_connection_value_n (connection,
2745  &clen,
2746  NULL))
2747  {
2748  end = clen + MHD_str_to_uint64_ (clen,
2749  &connection->remaining_upload_size);
2750  if ( (clen == end) ||
2751  ('\0' != *end) )
2752  {
2753  connection->remaining_upload_size = 0;
2754 #ifdef HAVE_MESSAGES
2755  MHD_DLOG (connection->daemon,
2756  "Failed to parse `Content-Length' header. Closing connection.\n");
2757 #endif
2758  CONNECTION_CLOSE_ERROR (connection,
2759  NULL);
2760  return;
2761  }
2762  }
2763  }
2764 }
2765 
2766 
2774 void
2776 {
2777  struct MHD_Daemon *daemon = connection->daemon;
2778 
2779  if (0 == connection->connection_timeout)
2780  return; /* Skip update of activity for connections
2781  without timeout timer. */
2782  if (connection->suspended)
2783  return; /* no activity on suspended connections */
2784 
2785  connection->last_activity = MHD_monotonic_sec_counter ();
2786  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2787  return; /* each connection has personal timeout */
2788 
2789  if (connection->connection_timeout != daemon->connection_timeout)
2790  return; /* custom timeout, no need to move it in "normal" DLL */
2791 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2793 #endif
2794  /* move connection to head of timeout list (by remove + add operation) */
2796  daemon->normal_timeout_tail,
2797  connection);
2799  daemon->normal_timeout_tail,
2800  connection);
2801 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2803 #endif
2804 }
2805 
2806 
2813 void
2815 {
2816  ssize_t bytes_read;
2817 
2818  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2819  (connection->suspended) )
2820  return;
2821 #ifdef HTTPS_SUPPORT
2822  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2823  { /* HTTPS connection. */
2824  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2825  {
2826  if (! MHD_run_tls_handshake_ (connection))
2827  return;
2828  }
2829  }
2830 #endif /* HTTPS_SUPPORT */
2831 
2832  /* make sure "read" has a reasonable number of bytes
2833  in buffer to use per system call (if possible) */
2834  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2835  connection->read_buffer_size)
2836  try_grow_read_buffer (connection,
2837  (connection->read_buffer_size ==
2838  connection->read_buffer_offset));
2839 
2840  if (connection->read_buffer_size == connection->read_buffer_offset)
2841  return; /* No space for receiving data. */
2842  bytes_read = connection->recv_cls (connection,
2843  &connection->read_buffer
2844  [connection->read_buffer_offset],
2845  connection->read_buffer_size
2846  - connection->read_buffer_offset);
2847  if (bytes_read < 0)
2848  {
2849  if (MHD_ERR_AGAIN_ == bytes_read)
2850  return; /* No new data to process. */
2851  if (MHD_ERR_CONNRESET_ == bytes_read)
2852  {
2853  CONNECTION_CLOSE_ERROR (connection,
2854  (MHD_CONNECTION_INIT == connection->state) ?
2855  NULL :
2856  _ (
2857  "Socket disconnected while reading request.\n"));
2858  return;
2859  }
2860  CONNECTION_CLOSE_ERROR (connection,
2861  (MHD_CONNECTION_INIT == connection->state) ?
2862  NULL :
2863  _ (
2864  "Connection socket is closed due to error when reading request.\n"));
2865  return;
2866  }
2867 
2868  if (0 == bytes_read)
2869  { /* Remote side closed connection. */
2870  connection->read_closed = true;
2871  MHD_connection_close_ (connection,
2873  return;
2874  }
2875  connection->read_buffer_offset += bytes_read;
2876  MHD_update_last_activity_ (connection);
2877 #if DEBUG_STATES
2878  MHD_DLOG (connection->daemon,
2879  _ ("In function %s handling connection at state: %s\n"),
2880  __FUNCTION__,
2881  MHD_state_to_string (connection->state));
2882 #endif
2883  switch (connection->state)
2884  {
2885  case MHD_CONNECTION_INIT:
2894  /* nothing to do but default action */
2895  if (connection->read_closed)
2896  {
2897  MHD_connection_close_ (connection,
2899  }
2900  return;
2901  case MHD_CONNECTION_CLOSED:
2902  return;
2903 #ifdef UPGRADE_SUPPORT
2904  case MHD_CONNECTION_UPGRADE:
2905  mhd_assert (0);
2906  return;
2907 #endif /* UPGRADE_SUPPORT */
2908  default:
2909  /* shrink read buffer to how much is actually used */
2910  MHD_pool_reallocate (connection->pool,
2911  connection->read_buffer,
2912  connection->read_buffer_size + 1,
2913  connection->read_buffer_offset);
2914  break;
2915  }
2916  return;
2917 }
2918 
2919 
2926 void
2928 {
2929  struct MHD_Response *response;
2930  ssize_t ret;
2931  if (connection->suspended)
2932  return;
2933 
2934 #ifdef HTTPS_SUPPORT
2935  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2936  { /* HTTPS connection. */
2937  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2938  {
2939  if (! MHD_run_tls_handshake_ (connection))
2940  return;
2941  }
2942  }
2943 #endif /* HTTPS_SUPPORT */
2944 
2945 #if DEBUG_STATES
2946  MHD_DLOG (connection->daemon,
2947  _ ("In function %s handling connection at state: %s\n"),
2948  __FUNCTION__,
2949  MHD_state_to_string (connection->state));
2950 #endif
2951  switch (connection->state)
2952  {
2953  case MHD_CONNECTION_INIT:
2957  mhd_assert (0);
2958  return;
2960  return;
2962  ret = MHD_send_on_connection_ (connection,
2964  [connection->continue_message_write_offset],
2966  - connection->continue_message_write_offset,
2967  MHD_SSO_NO_CORK);
2968  if (ret < 0)
2969  {
2970  if (MHD_ERR_AGAIN_ == ret)
2971  return;
2972 #ifdef HAVE_MESSAGES
2973  MHD_DLOG (connection->daemon,
2974  _ ("Failed to send data in request for %s.\n"),
2975  connection->url);
2976 #endif
2977  CONNECTION_CLOSE_ERROR (connection,
2978  NULL);
2979  return;
2980  }
2981 #if DEBUG_SEND_DATA
2982  fprintf (stderr,
2983  _ ("Sent 100 continue response: `%.*s'\n"),
2984  (int) ret,
2986 #endif
2987  connection->continue_message_write_offset += ret;
2988  MHD_update_last_activity_ (connection);
2989  return;
2994  mhd_assert (0);
2995  return;
2997  {
2998  const size_t wb_ready = connection->write_buffer_append_offset
2999  - connection->write_buffer_send_offset;
3000 
3001  /* if the response body is not available, we use MHD_send_on_connection_() */
3002  if (NULL != connection->response->crc)
3003  {
3004  ret = MHD_send_on_connection_ (connection,
3005  &connection->write_buffer
3006  [connection->write_buffer_send_offset],
3007  wb_ready,
3009  }
3010  else
3011  {
3012  ret = MHD_send_on_connection2_ (connection,
3013  &connection->write_buffer
3014  [connection->write_buffer_send_offset],
3015  wb_ready,
3016  connection->response->data,
3017  connection->response->data_buffer_size);
3018  }
3019 
3020  if (ret < 0)
3021  {
3022  if (MHD_ERR_AGAIN_ == ret)
3023  return;
3024  CONNECTION_CLOSE_ERROR (connection,
3025  _ (
3026  "Connection was closed while sending response headers.\n"));
3027  return;
3028  }
3029  if (ret > wb_ready)
3030  {
3031  mhd_assert (NULL == connection->response->crc);
3032  /* We sent not just header data but also some response data,
3033  update both offsets! */
3034  connection->write_buffer_send_offset += wb_ready;
3035  ret -= wb_ready;
3036  connection->response_write_position += ret;
3037  }
3038  else
3039  connection->write_buffer_send_offset += ret;
3040  MHD_update_last_activity_ (connection);
3041  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3042  return;
3043  check_write_done (connection,
3045  return;
3046  }
3048  return;
3050  response = connection->response;
3051  if (connection->response_write_position <
3052  connection->response->total_size)
3053  {
3054  uint64_t data_write_offset;
3055 
3056 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3057  if (NULL != response->crc)
3058  MHD_mutex_lock_chk_ (&response->mutex);
3059 #endif
3060  if (MHD_YES != try_ready_normal_body (connection))
3061  {
3062  /* mutex was already unlocked by try_ready_normal_body */
3063  return;
3064  }
3065 #if defined(_MHD_HAVE_SENDFILE)
3066  if (MHD_resp_sender_sendfile == connection->resp_sender)
3067  {
3068  ret = MHD_send_sendfile_ (connection);
3069  }
3070  else
3071 #else /* ! _MHD_HAVE_SENDFILE */
3072  if (1)
3073 #endif /* ! _MHD_HAVE_SENDFILE */
3074  {
3075  data_write_offset = connection->response_write_position
3076  - response->data_start;
3077  if (data_write_offset > (uint64_t) SIZE_MAX)
3078  MHD_PANIC (_ ("Data offset exceeds limit"));
3079  ret = MHD_send_on_connection_ (connection,
3080  &response->data
3081  [(size_t) data_write_offset],
3082  response->data_size
3083  - (size_t) data_write_offset,
3084  MHD_SSO_NO_CORK);
3085 #if DEBUG_SEND_DATA
3086  if (ret > 0)
3087  fprintf (stderr,
3088  _ ("Sent %d-byte DATA response: `%.*s'\n"),
3089  (int) ret,
3090  (int) ret,
3091  &response->data[connection->response_write_position
3092  - response->data_start]);
3093 #endif
3094  }
3095 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3096  if (NULL != response->crc)
3097  MHD_mutex_unlock_chk_ (&response->mutex);
3098 #endif
3099  if (ret < 0)
3100  {
3101  if (MHD_ERR_AGAIN_ == ret)
3102  return;
3103 #ifdef HAVE_MESSAGES
3104  MHD_DLOG (connection->daemon,
3105  _ ("Failed to send data in request for `%s'.\n"),
3106  connection->url);
3107 #endif
3108  CONNECTION_CLOSE_ERROR (connection,
3109  NULL);
3110  return;
3111  }
3112  connection->response_write_position += ret;
3113  MHD_update_last_activity_ (connection);
3114  }
3115  if (connection->response_write_position ==
3116  connection->response->total_size)
3117  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3118  return;
3120  mhd_assert (0);
3121  return;
3123  ret = MHD_send_on_connection_ (connection,
3124  &connection->write_buffer
3125  [connection->write_buffer_send_offset],
3126  connection->write_buffer_append_offset
3127  - connection->write_buffer_send_offset,
3128  MHD_SSO_NO_CORK);
3129  if (ret < 0)
3130  {
3131  if (MHD_ERR_AGAIN_ == ret)
3132  return;
3133  CONNECTION_CLOSE_ERROR (connection,
3134  _ (
3135  "Connection was closed while sending response body.\n"));
3136  return;
3137  }
3138  connection->write_buffer_send_offset += ret;
3139  MHD_update_last_activity_ (connection);
3140  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3141  return;
3142  check_write_done (connection,
3143  (connection->response->total_size ==
3144  connection->response_write_position) ?
3147  return;
3150  mhd_assert (0);
3151  return;
3153  ret = MHD_send_on_connection_ (connection,
3154  &connection->write_buffer
3155  [connection->write_buffer_send_offset],
3156  connection->write_buffer_append_offset
3157  - connection->write_buffer_send_offset,
3159  if (ret < 0)
3160  {
3161  if (MHD_ERR_AGAIN_ == ret)
3162  return;
3163  CONNECTION_CLOSE_ERROR (connection,
3164  _ (
3165  "Connection was closed while sending response body.\n"));
3166  return;
3167  }
3168  connection->write_buffer_send_offset += ret;
3169  MHD_update_last_activity_ (connection);
3170  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3171  return;
3172  check_write_done (connection,
3174  return;
3176  mhd_assert (0);
3177  return;
3178  case MHD_CONNECTION_CLOSED:
3179  return;
3180 #ifdef UPGRADE_SUPPORT
3181  case MHD_CONNECTION_UPGRADE:
3182  mhd_assert (0);
3183  return;
3184 #endif /* UPGRADE_SUPPORT */
3185  default:
3186  mhd_assert (0);
3187  CONNECTION_CLOSE_ERROR (connection,
3188  _ ("Internal error\n"));
3189  break;
3190  }
3191  return;
3192 }
3193 
3194 
3203 static void
3205 {
3206  struct MHD_Daemon *daemon = connection->daemon;
3207 
3208  if (connection->in_cleanup)
3209  return; /* Prevent double cleanup. */
3210  connection->in_cleanup = true;
3211  if (NULL != connection->response)
3212  {
3213  MHD_destroy_response (connection->response);
3214  connection->response = NULL;
3215  }
3216 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3218 #endif
3219  if (connection->suspended)
3220  {
3223  connection);
3224  connection->suspended = false;
3225  }
3226  else
3227  {
3228  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3229  {
3230  if (connection->connection_timeout == daemon->connection_timeout)
3232  daemon->normal_timeout_tail,
3233  connection);
3234  else
3236  daemon->manual_timeout_tail,
3237  connection);
3238  }
3239  DLL_remove (daemon->connections_head,
3240  daemon->connections_tail,
3241  connection);
3242  }
3243  DLL_insert (daemon->cleanup_head,
3244  daemon->cleanup_tail,
3245  connection);
3246  connection->resuming = false;
3247  connection->in_idle = false;
3248 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3250 #endif
3251  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3252  {
3253  /* if we were at the connection limit before and are in
3254  thread-per-connection mode, signal the main thread
3255  to resume accepting connections */
3256  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3257  (! MHD_itc_activate_ (daemon->itc, "c")) )
3258  {
3259 #ifdef HAVE_MESSAGES
3260  MHD_DLOG (daemon,
3261  _ (
3262  "Failed to signal end of connection via inter-thread communication channel"));
3263 #endif
3264  }
3265  }
3266 }
3267 
3268 
3279 int
3281 {
3282  struct MHD_Daemon *daemon = connection->daemon;
3283  char *line;
3284  size_t line_len;
3285  int ret;
3286 
3287  connection->in_idle = true;
3288  while (! connection->suspended)
3289  {
3290 #ifdef HTTPS_SUPPORT
3291  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3292  { /* HTTPS connection. */
3293  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3294  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3295  break;
3296  }
3297 #endif /* HTTPS_SUPPORT */
3298 #if DEBUG_STATES
3299  MHD_DLOG (daemon,
3300  _ ("In function %s handling connection at state: %s\n"),
3301  __FUNCTION__,
3302  MHD_state_to_string (connection->state));
3303 #endif
3304  switch (connection->state)
3305  {
3306  case MHD_CONNECTION_INIT:
3307  line = get_next_header_line (connection,
3308  &line_len);
3309  /* Check for empty string, as we might want
3310  to tolerate 'spurious' empty lines; also
3311  NULL means we didn't get a full line yet;
3312  line is not 0-terminated here. */
3313  if ( (NULL == line) ||
3314  (0 == line[0]) )
3315  {
3316  if (MHD_CONNECTION_INIT != connection->state)
3317  continue;
3318  if (connection->read_closed)
3319  {
3320  CONNECTION_CLOSE_ERROR (connection,
3321  NULL);
3322  continue;
3323  }
3324  break;
3325  }
3326  if (MHD_NO == parse_initial_message_line (connection,
3327  line,
3328  line_len))
3329  CONNECTION_CLOSE_ERROR (connection,
3330  NULL);
3331  else
3332  connection->state = MHD_CONNECTION_URL_RECEIVED;
3333  continue;
3335  line = get_next_header_line (connection,
3336  NULL);
3337  if (NULL == line)
3338  {
3339  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3340  continue;
3341  if (connection->read_closed)
3342  {
3343  CONNECTION_CLOSE_ERROR (connection,
3344  NULL);
3345  continue;
3346  }
3347  break;
3348  }
3349  if (0 == line[0])
3350  {
3351  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3352  connection->header_size = (size_t) (line - connection->read_buffer);
3353  continue;
3354  }
3355  if (MHD_NO == process_header_line (connection,
3356  line))
3357  {
3358  transmit_error_response (connection,
3361  break;
3362  }
3364  continue;
3366  line = get_next_header_line (connection,
3367  NULL);
3368  if (NULL == line)
3369  {
3370  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
3371  continue;
3372  if (connection->read_closed)
3373  {
3374  CONNECTION_CLOSE_ERROR (connection,
3375  NULL);
3376  continue;
3377  }
3378  break;
3379  }
3380  if (MHD_NO ==
3381  process_broken_line (connection,
3382  line,
3383  MHD_HEADER_KIND))
3384  continue;
3385  if (0 == line[0])
3386  {
3387  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3388  connection->header_size = (size_t) (line - connection->read_buffer);
3389  continue;
3390  }
3391  continue;
3393  parse_connection_headers (connection);
3394  if (MHD_CONNECTION_CLOSED == connection->state)
3395  continue;
3397  if (connection->suspended)
3398  break;
3399  continue;
3401  call_connection_handler (connection); /* first call */
3402  if (MHD_CONNECTION_CLOSED == connection->state)
3403  continue;
3404  if (need_100_continue (connection))
3405  {
3406  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3407  break;
3408  }
3409  if ( (NULL != connection->response) &&
3410  ( (MHD_str_equal_caseless_ (connection->method,
3412  (MHD_str_equal_caseless_ (connection->method,
3413  MHD_HTTP_METHOD_PUT))) )
3414  {
3415  /* we refused (no upload allowed!) */
3416  connection->remaining_upload_size = 0;
3417  /* force close, in case client still tries to upload... */
3418  connection->read_closed = true;
3419  }
3420  connection->state = (0 == connection->remaining_upload_size)
3423  if (connection->suspended)
3424  break;
3425  continue;
3427  if (connection->continue_message_write_offset ==
3429  {
3430  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3431  continue;
3432  }
3433  break;
3435  if (0 != connection->read_buffer_offset)
3436  {
3437  process_request_body (connection); /* loop call */
3438  if (MHD_CONNECTION_CLOSED == connection->state)
3439  continue;
3440  }
3441  if ( (0 == connection->remaining_upload_size) ||
3442  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3443  (0 == connection->read_buffer_offset) &&
3444  (connection->read_closed) ) )
3445  {
3446  if ( (connection->have_chunked_upload) &&
3447  (! connection->read_closed) )
3448  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3449  else
3450  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3451  if (connection->suspended)
3452  break;
3453  continue;
3454  }
3455  break;
3457  line = get_next_header_line (connection,
3458  NULL);
3459  if (NULL == line)
3460  {
3461  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3462  continue;
3463  if (connection->read_closed)
3464  {
3465  CONNECTION_CLOSE_ERROR (connection,
3466  NULL);
3467  continue;
3468  }
3469  break;
3470  }
3471  if (0 == line[0])
3472  {
3473  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3474  if (connection->suspended)
3475  break;
3476  continue;
3477  }
3478  if (MHD_NO == process_header_line (connection,
3479  line))
3480  {
3481  transmit_error_response (connection,
3484  break;
3485  }
3487  continue;
3489  line = get_next_header_line (connection,
3490  NULL);
3491  if (NULL == line)
3492  {
3493  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3494  continue;
3495  if (connection->read_closed)
3496  {
3497  CONNECTION_CLOSE_ERROR (connection,
3498  NULL);
3499  continue;
3500  }
3501  break;
3502  }
3503  if (MHD_NO ==
3504  process_broken_line (connection,
3505  line,
3506  MHD_FOOTER_KIND))
3507  continue;
3508  if (0 == line[0])
3509  {
3510  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3511  if (connection->suspended)
3512  break;
3513  continue;
3514  }
3515  continue;
3517  call_connection_handler (connection); /* "final" call */
3518  if (connection->state == MHD_CONNECTION_CLOSED)
3519  continue;
3520  if (NULL == connection->response)
3521  break; /* try again next time */
3522  if (MHD_NO == build_header_response (connection))
3523  {
3524  /* oops - close! */
3525  CONNECTION_CLOSE_ERROR (connection,
3526  _ (
3527  "Closing connection (failed to create response header)\n"));
3528  continue;
3529  }
3530  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3531  break;
3533  /* no default action */
3534  break;
3536  /* Some clients may take some actions right after header receive */
3537 #ifdef UPGRADE_SUPPORT
3538  if (NULL != connection->response->upgrade_handler)
3539  {
3540  connection->state = MHD_CONNECTION_UPGRADE;
3541  /* This connection is "upgraded". Pass socket to application. */
3542  if (MHD_YES !=
3544  connection))
3545  {
3546  /* upgrade failed, fail hard */
3547  CONNECTION_CLOSE_ERROR (connection,
3548  NULL);
3549  continue;
3550  }
3551  /* Response is not required anymore for this connection. */
3552  {
3553  struct MHD_Response *const resp = connection->response;
3554 
3555  connection->response = NULL;
3556  MHD_destroy_response (resp);
3557  }
3558  continue;
3559  }
3560 #endif /* UPGRADE_SUPPORT */
3561 
3562  if (connection->have_chunked_upload)
3564  else
3566  continue;
3568  /* nothing to do here */
3569  break;
3571 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3572  if (NULL != connection->response->crc)
3573  MHD_mutex_lock_chk_ (&connection->response->mutex);
3574 #endif
3575  if (0 == connection->response->total_size)
3576  {
3577 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3578  if (NULL != connection->response->crc)
3579  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3580 #endif
3581  connection->state = MHD_CONNECTION_BODY_SENT;
3582  continue;
3583  }
3584  if (MHD_YES == try_ready_normal_body (connection))
3585  {
3586 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3587  if (NULL != connection->response->crc)
3588  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3589 #endif
3591  /* Buffering for flushable socket was already enabled*/
3592 
3593  break;
3594  }
3595  /* mutex was already unlocked by "try_ready_normal_body */
3596  /* not ready, no socket action */
3597  break;
3599  /* nothing to do here */
3600  break;
3602 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3603  if (NULL != connection->response->crc)
3604  MHD_mutex_lock_chk_ (&connection->response->mutex);
3605 #endif
3606  if ( (0 == connection->response->total_size) ||
3607  (connection->response_write_position ==
3608  connection->response->total_size) )
3609  {
3610 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3611  if (NULL != connection->response->crc)
3612  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3613 #endif
3614  connection->state = MHD_CONNECTION_BODY_SENT;
3615  continue;
3616  }
3617  if (MHD_YES == try_ready_chunked_body (connection))
3618  {
3619 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3620  if (NULL != connection->response->crc)
3621  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3622 #endif
3624  /* Buffering for flushable socket was already enabled */
3625 
3626  continue;
3627  }
3628  /* mutex was already unlocked by try_ready_chunked_body */
3629  break;
3631  if (MHD_NO == build_header_response (connection))
3632  {
3633  /* oops - close! */
3634  CONNECTION_CLOSE_ERROR (connection,
3635  _ (
3636  "Closing connection (failed to create response header)\n"));
3637  continue;
3638  }
3639  if ( (! connection->have_chunked_upload) ||
3640  (connection->write_buffer_send_offset ==
3641  connection->write_buffer_append_offset) )
3642  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3643  else
3644  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3645  continue;
3647  /* no default action */
3648  break;
3650  if (MHD_HTTP_PROCESSING == connection->responseCode)
3651  {
3652  /* After this type of response, we allow sending another! */
3654  MHD_destroy_response (connection->response);
3655  connection->response = NULL;
3656  /* FIXME: maybe partially reset memory pool? */
3657  continue;
3658  }
3659  MHD_destroy_response (connection->response);
3660  connection->response = NULL;
3661  if ( (NULL != daemon->notify_completed) &&
3662  (connection->client_aware) )
3663  {
3664  daemon->notify_completed (daemon->notify_completed_cls,
3665  connection,
3666  &connection->client_context,
3668  }
3669  connection->client_aware = false;
3670  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3671  (connection->read_closed) )
3672  {
3673  /* have to close for some reason */
3674  MHD_connection_close_ (connection,
3676  MHD_pool_destroy (connection->pool);
3677  connection->pool = NULL;
3678  connection->read_buffer = NULL;
3679  connection->read_buffer_size = 0;
3680  connection->read_buffer_offset = 0;
3681  }
3682  else
3683  {
3684  /* can try to keep-alive */
3685 
3686  connection->version = NULL;
3687  connection->state = MHD_CONNECTION_INIT;
3688  connection->last = NULL;
3689  connection->colon = NULL;
3690  connection->header_size = 0;
3691  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3692  /* Reset the read buffer to the starting size,
3693  preserving the bytes we have already read. */
3694  connection->read_buffer
3695  = MHD_pool_reset (connection->pool,
3696  connection->read_buffer,
3697  connection->read_buffer_offset,
3698  connection->daemon->pool_size / 2);
3699  connection->read_buffer_size
3700  = connection->daemon->pool_size / 2;
3701  }
3702  connection->client_context = NULL;
3703  connection->continue_message_write_offset = 0;
3704  connection->responseCode = 0;
3705  connection->headers_received = NULL;
3706  connection->headers_received_tail = NULL;
3707  connection->response_write_position = 0;
3708  connection->have_chunked_upload = false;
3709  connection->current_chunk_size = 0;
3710  connection->current_chunk_offset = 0;
3711  connection->method = NULL;
3712  connection->url = NULL;
3713  connection->write_buffer = NULL;
3714  connection->write_buffer_size = 0;
3715  connection->write_buffer_send_offset = 0;
3716  connection->write_buffer_append_offset = 0;
3717  continue;
3718  case MHD_CONNECTION_CLOSED:
3719  cleanup_connection (connection);
3720  connection->in_idle = false;
3721  return MHD_NO;
3722 #ifdef UPGRADE_SUPPORT
3723  case MHD_CONNECTION_UPGRADE:
3724  connection->in_idle = false;
3725  return MHD_YES; /* keep open */
3726 #endif /* UPGRADE_SUPPORT */
3727  default:
3728  mhd_assert (0);
3729  break;
3730  }
3731  break;
3732  }
3733  if (! connection->suspended)
3734  {
3735  time_t timeout;
3736  timeout = connection->connection_timeout;
3737  if ( (0 != timeout) &&
3738  (timeout < (MHD_monotonic_sec_counter ()
3739  - connection->last_activity)) )
3740  {
3741  MHD_connection_close_ (connection,
3743  connection->in_idle = false;
3744  return MHD_YES;
3745  }
3746  }
3748  ret = MHD_YES;
3749 #ifdef EPOLL_SUPPORT
3750  if ( (! connection->suspended) &&
3751  (0 != (daemon->options & MHD_USE_EPOLL)) )
3752  {
3753  ret = MHD_connection_epoll_update_ (connection);
3754  }
3755 #endif /* EPOLL_SUPPORT */
3756  connection->in_idle = false;
3757  return ret;
3758 }
3759 
3760 
3761 #ifdef EPOLL_SUPPORT
3762 
3770 int
3771 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3772 {
3773  struct MHD_Daemon *daemon = connection->daemon;
3774 
3775  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3776  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3777  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3778  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3779  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3780  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3781  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3782  {
3783  /* add to epoll set */
3784  struct epoll_event event;
3785 
3786  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3787  event.data.ptr = connection;
3788  if (0 != epoll_ctl (daemon->epoll_fd,
3789  EPOLL_CTL_ADD,
3790  connection->socket_fd,
3791  &event))
3792  {
3793 #ifdef HAVE_MESSAGES
3794  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3795  MHD_DLOG (daemon,
3796  _ ("Call to epoll_ctl failed: %s\n"),
3798 #endif
3799  connection->state = MHD_CONNECTION_CLOSED;
3800  cleanup_connection (connection);
3801  return MHD_NO;
3802  }
3803  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3804  }
3805  return MHD_YES;
3806 }
3807 #endif
3808 
3809 
3815 void
3817 {
3818  connection->recv_cls = &recv_param_adapter;
3819  connection->send_cls = &send_param_adapter;
3820 }
3821 
3822 
3833 const union MHD_ConnectionInfo *
3835  enum MHD_ConnectionInfoType info_type,
3836  ...)
3837 {
3838  switch (info_type)
3839  {
3840 #ifdef HTTPS_SUPPORT
3842  if (NULL == connection->tls_session)
3843  return NULL;
3844  connection->cipher = gnutls_cipher_get (connection->tls_session);
3845  return (const union MHD_ConnectionInfo *) &connection->cipher;
3847  if (NULL == connection->tls_session)
3848  return NULL;
3849  connection->protocol = gnutls_protocol_get_version (
3850  connection->tls_session);
3851  return (const union MHD_ConnectionInfo *) &connection->protocol;
3853  if (NULL == connection->tls_session)
3854  return NULL;
3855  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3856 #endif /* HTTPS_SUPPORT */
3858  return (const union MHD_ConnectionInfo *) &connection->addr;
3860  return (const union MHD_ConnectionInfo *) &connection->daemon;
3862  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3864  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3866  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3867  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3869  connection->connection_timeout_dummy = (unsigned
3870  int) connection->connection_timeout;
3871  return (const union MHD_ConnectionInfo *) &connection->
3872  connection_timeout_dummy;
3874  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3875  (MHD_CONNECTION_CLOSED == connection->state) )
3876  return NULL; /* invalid, too early! */
3877  return (const union MHD_ConnectionInfo *) &connection->header_size;
3878  default:
3879  return NULL;
3880  }
3881 }
3882 
3883 
3893 int
3895  enum MHD_CONNECTION_OPTION option,
3896  ...)
3897 {
3898  va_list ap;
3899  struct MHD_Daemon *daemon;
3900 
3901  daemon = connection->daemon;
3902  switch (option)
3903  {
3905  if (0 == connection->connection_timeout)
3906  connection->last_activity = MHD_monotonic_sec_counter ();
3907 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3909 #endif
3910  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3911  (! connection->suspended) )
3912  {
3913  if (connection->connection_timeout == daemon->connection_timeout)
3915  daemon->normal_timeout_tail,
3916  connection);
3917  else
3919  daemon->manual_timeout_tail,
3920  connection);
3921  }
3922  va_start (ap, option);
3923  connection->connection_timeout = va_arg (ap,
3924  unsigned int);
3925  va_end (ap);
3926  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3927  (! connection->suspended) )
3928  {
3929  if (connection->connection_timeout == daemon->connection_timeout)
3931  daemon->normal_timeout_tail,
3932  connection);
3933  else
3935  daemon->manual_timeout_tail,
3936  connection);
3937  }
3938 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3940 #endif
3941  return MHD_YES;
3942  default:
3943  return MHD_NO;
3944  }
3945 }
3946 
3947 
3959 int
3961  unsigned int status_code,
3962  struct MHD_Response *response)
3963 {
3964  struct MHD_Daemon *daemon;
3965 
3966  if ( (NULL == connection) ||
3967  (NULL == response) ||
3968  (NULL != connection->response) ||
3969  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3970  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3971  return MHD_NO;
3972  daemon = connection->daemon;
3973 
3974  if (daemon->shutdown)
3975  return MHD_YES; /* If daemon was shut down in parallel,
3976  * response will be aborted now or on later stage. */
3977 
3978 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3979  if ( (! connection->suspended) &&
3980  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3981  (! MHD_thread_ID_match_current_ (connection->pid.ID)) )
3982  {
3983 #ifdef HAVE_MESSAGES
3984  MHD_DLOG (daemon,
3985  _ ("Attempted to queue response on wrong thread!\n"));
3986 #endif
3987  return MHD_NO;
3988  }
3989 #endif
3990 #ifdef UPGRADE_SUPPORT
3991  if ( (NULL != response->upgrade_handler) &&
3992  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3993  {
3994 #ifdef HAVE_MESSAGES
3995  MHD_DLOG (daemon,
3996  _ (
3997  "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
3998 #endif
3999  return MHD_NO;
4000  }
4001  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
4002  (NULL != response->upgrade_handler) )
4003  {
4004 #ifdef HAVE_MESSAGES
4005  MHD_DLOG (daemon,
4006  _ (
4007  "Application used invalid status code for 'upgrade' response!\n"));
4008 #endif
4009  return MHD_NO;
4010  }
4011 #endif /* UPGRADE_SUPPORT */
4012  MHD_increment_response_rc (response);
4013  connection->response = response;
4014  connection->responseCode = status_code;
4015 #if defined(_MHD_HAVE_SENDFILE)
4016  if ( (response->fd == -1) ||
4017  (0 != (connection->daemon->options & MHD_USE_TLS)) )
4018  connection->resp_sender = MHD_resp_sender_std;
4019  else
4020  connection->resp_sender = MHD_resp_sender_sendfile;
4021 #endif /* _MHD_HAVE_SENDFILE */
4022 
4023  if ( ( (NULL != connection->method) &&
4024  (MHD_str_equal_caseless_ (connection->method,
4025  MHD_HTTP_METHOD_HEAD)) ) ||
4026  (MHD_HTTP_OK > status_code) ||
4027  (MHD_HTTP_NO_CONTENT == status_code) ||
4028  (MHD_HTTP_NOT_MODIFIED == status_code) )
4029  {
4030  /* if this is a "HEAD" request, or a status code for
4031  which a body is not allowed, pretend that we
4032  have already sent the full message body. */
4033  connection->response_write_position = response->total_size;
4034  }
4035  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
4036  (NULL != connection->method) &&
4037  ( (MHD_str_equal_caseless_ (connection->method,
4039  (MHD_str_equal_caseless_ (connection->method,
4040  MHD_HTTP_METHOD_PUT))) )
4041  {
4042  /* response was queued "early", refuse to read body / footers or
4043  further requests! */
4044  connection->read_closed = true;
4045  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4046  }
4047  if (! connection->in_idle)
4048  (void) MHD_connection_handle_idle (connection);
4049  MHD_update_last_activity_ (connection);
4050  return MHD_YES;
4051 }
4052 
4053 
4054 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2520
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: connection.c:242
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:261
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2237
_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:338
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1974
void * unescape_callback_cls
Definition: internal.h:1415
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:574
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:1939
#define MHD_PANIC(msg)
Definition: internal.h:69
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2927
uint64_t total_size
Definition: internal.h:1642
bool have_chunked_upload
Definition: internal.h:942
Header for platform missing functions.
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:884
uint64_t current_chunk_offset
Definition: internal.h:956
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:528
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:894
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1710
struct sockaddr_storage addr
Definition: internal.h:728
struct MHD_Connection * cleanup_head
Definition: internal.h:1177
enum MHD_CONNECTION_STATE state
Definition: internal.h:922
void * data
Definition: microhttpd.h:3031
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:955
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:669
uint64_t response_write_position
Definition: internal.h:822
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:729
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:457
void * mhd_panic_cls
Definition: panic.c:36
#define HTTP_100_CONTINUE
Definition: connection.c:61
#define MHD_ICY_FLAG
Definition: microhttpd.h:528
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:927
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:180
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:185
time_t connection_timeout
Definition: internal.h:1592
Methods for managing connections.
MHD_PanicCallback mhd_panic
Definition: panic.c:31
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
internal monotonic clock functions implementations
MHD_CONNECTION_STATE
Definition: internal.h:420
char * version
Definition: internal.h:722
int suspended_dummy
Definition: internal.h:1015
#define INTERNAL_ERROR
Definition: connection.c:115
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:584
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:749
#define MHD_YES
Definition: microhttpd.h:140
#define SIZE_MAX
Definition: mhd_limits.h:99
struct MHD_Response * response
Definition: internal.h:678
char * data
Definition: internal.h:1588
char * colon
Definition: internal.h:759
#define REQUEST_LACKS_HOST
Definition: connection.c:88
char * write_buffer
Definition: internal.h:742
#define MHD_SENFILE_CHUNK_
Definition: connection.c:133
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:452
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:365
#define MHD_ERR_AGAIN_
Definition: internal.h:1867
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:397
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:1143
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:711
MHD_RequestTerminationCode
Definition: microhttpd.h:1808
size_t data_size
Definition: internal.h:1659
MHD_thread_handle_ID_ pid
Definition: internal.h:723
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:333
time_t MHD_monotonic_sec_counter(void)
char * value
Definition: internal.h:352
enum MHD_ValueKind kind
Definition: internal.h:358
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1626
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1261
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:642
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2212
uint64_t remaining_upload_size
Definition: internal.h:815
unsigned int responseCode
Definition: internal.h:933
#define MHD_ERR_CONNRESET_
Definition: internal.h:1872
ssize_t MHD_send_on_connection2_(struct MHD_Connection *connection, const char *header, size_t header_size, const char *buffer, size_t buffer_size)
Definition: mhd_send.c:378
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3204
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2775
char * header
Definition: internal.h:347
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:290
void * uri_log_callback_cls
Definition: internal.h:1405
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:189
struct MHD_Daemon * daemon
Definition: internal.h:675
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t header_size
Definition: internal.h:809
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
Definition: connection.c:1199
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:629
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1977
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:138
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:694
Header for platform-independent inter-thread communication.
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:845
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:865
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3834
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1086
#define DLL_insert(head, tail, element)
Definition: internal.h:1745
int strict_for_client
Definition: internal.h:1613
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1251
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:404
void * socket_context
Definition: internal.h:694
struct MHD_HTTP_Header * first_header
Definition: internal.h:1582
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:548
size_t data_buffer_size
Definition: internal.h:1664
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3759
size_t write_buffer_send_offset
Definition: internal.h:797
void * crc_cls
Definition: internal.h:1594
struct MHD_Connection * connections_tail
Definition: internal.h:1160
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:391
size_t read_buffer_size
Definition: internal.h:781
void * client_context
Definition: internal.h:696
const char * url
Definition: internal.h:716
size_t continue_message_write_offset
Definition: internal.h:836
#define REQUEST_MALFORMED
Definition: connection.c:102
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:188
MHD_socket socket_fd
Definition: internal.h:752
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:676
internal shared structures
enum MHD_HTTP_StatusCode status_code
Definition: internal.h:1669
char * method
Definition: internal.h:710
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
enum MHD_FLAG options
Definition: internal.h:1603
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:1155
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:343
LogCallback uri_log_callback
Definition: internal.h:1400
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2814
bool in_cleanup
Definition: internal.h:910
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1211
#define MHD_HTTP_OK
Definition: microhttpd.h:335
time_t connection_timeout
Definition: internal.h:745
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3894
#define _MHD_EXTERN
Definition: mhd_options.h:51
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:610
Methods for managing connections.
ssize_t MHD_send_on_connection_(struct MHD_Connection *connection, const char *buffer, size_t buffer_size, enum MHD_SendSocketOptions options)
Definition: mhd_send.c:233
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:166
#define EDLL_remove(head, tail, element)
Definition: internal.h:1850
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
#define NULL
Definition: reason_phrase.c:30
char * last
Definition: internal.h:750
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1136
MHD_ValueKind
Definition: microhttpd.h:1757
Header for string manipulating helpers.
Implementation of send() wrappers.
#define DLL_remove(head, tail, element)
Definition: internal.h:1765
char * read_buffer
Definition: internal.h:736
ReceiveCallback recv_cls
Definition: internal.h:706
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:682
size_t value_size
Definition: internal.h:289
size_t write_buffer_size
Definition: internal.h:792
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
MHD_ConnectionInfoType
Definition: microhttpd.h:1956
uint64_t data_start
Definition: internal.h:1648
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:880
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:431
UnescapeCallback unescape_callback
Definition: internal.h:1410
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3960
size_t header_size
Definition: internal.h:279
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
#define XDLL_remove(head, tail, element)
Definition: internal.h:1809
unsigned int connection_timeout_dummy
Definition: internal.h:858
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:376
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:737
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
size_t pool_size
Definition: internal.h:1450
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2491
struct MHD_itc_ itc
Definition: internal.h:1410
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:739
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3280
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2580
enum MHD_ResponseFlags flags
Definition: internal.h:400
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:578
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
struct MHD_HTTP_Header * next
Definition: internal.h:342
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:900
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2667
size_t write_buffer_append_offset
Definition: internal.h:803
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1375
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
#define MHD_BUF_INC_SIZE
Definition: internal.h:119
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:560
bool read_closed
Definition: internal.h:792
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3816
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:906
void * notify_completed_cls
Definition: internal.h:1380
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2248
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:879
#define MHD_ERR_NOTCONN_
Definition: internal.h:1878
struct MemoryPool * pool
Definition: internal.h:685
TransmitCallback send_cls
Definition: internal.h:711
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:299
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:437
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:167
MHD_ContentReaderCallback crc
Definition: internal.h:1600
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2100
MHD_mutex_ mutex
Definition: internal.h:1637
#define XDLL_insert(head, tail, element)
Definition: internal.h:1789
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:304
bool suspended
Definition: internal.h:764
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:566
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:330
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:419
#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:565
#define MHD_MIN(a, b)
Definition: internal.h:109
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
size_t read_buffer_offset
Definition: internal.h:787
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1879
void * default_handler_cls
Definition: internal.h:1266
#define MHD_NO
Definition: microhttpd.h:145
volatile bool shutdown
Definition: internal.h:1526
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:284
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:633
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:867
uint64_t current_chunk_size
Definition: internal.h:950
struct MHD_HTTP_Header * headers_received
Definition: internal.h:668
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:328
limits values definitions
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:622
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:499
#define REQUEST_TOO_BIG
Definition: connection.c:74
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:673
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1252
size_t pool_increment
Definition: internal.h:1455
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:904
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:393
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:2262