GNU libmicrohttpd  0.9.69
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 
179 
180 #endif /* HAVE_FREEBSD_SENDFILE */
181 
190 static ssize_t
191 recv_param_adapter (struct MHD_Connection *connection,
192  void *other,
193  size_t i)
194 {
195  ssize_t ret;
196 
197  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
198  (MHD_CONNECTION_CLOSED == connection->state) )
199  {
200  return MHD_ERR_NOTCONN_;
201  }
202  if (i > MHD_SCKT_SEND_MAX_SIZE_)
203  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
204 
205  ret = MHD_recv_ (connection->socket_fd,
206  other,
207  i);
208  if (0 > ret)
209  {
210  const int err = MHD_socket_get_error_ ();
211  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
212  {
213 #ifdef EPOLL_SUPPORT
214  /* Got EAGAIN --- no longer read-ready */
215  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
216 #endif /* EPOLL_SUPPORT */
217  return MHD_ERR_AGAIN_;
218  }
219  if (MHD_SCKT_ERR_IS_EINTR_ (err))
220  return MHD_ERR_AGAIN_;
222  return MHD_ERR_CONNRESET_;
223  /* Treat any other error as hard error. */
224  return MHD_ERR_NOTCONN_;
225  }
226 #ifdef EPOLL_SUPPORT
227  else if (i > (size_t) ret)
228  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
229 #endif /* EPOLL_SUPPORT */
230  return ret;
231 }
232 
233 
243 static ssize_t
244 send_param_adapter (struct MHD_Connection *connection,
245  const void *other,
246  size_t i)
247 {
248  ssize_t ret;
249 
250  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
251  (MHD_CONNECTION_CLOSED == connection->state) )
252  {
253  return MHD_ERR_NOTCONN_;
254  }
255  if (i > MHD_SCKT_SEND_MAX_SIZE_)
256  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
257 
258  ret = MHD_send_ (connection->socket_fd,
259  other,
260  i);
261  if (0 > ret)
262  {
263  const int err = MHD_socket_get_error_ ();
264 
265  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
266  {
267 #ifdef EPOLL_SUPPORT
268  /* EAGAIN --- no longer write-ready */
269  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
270 #endif /* EPOLL_SUPPORT */
271  return MHD_ERR_AGAIN_;
272  }
273  if (MHD_SCKT_ERR_IS_EINTR_ (err))
274  return MHD_ERR_AGAIN_;
276  return MHD_ERR_CONNRESET_;
277  /* Treat any other error as hard error. */
278  return MHD_ERR_NOTCONN_;
279  }
280 #ifdef EPOLL_SUPPORT
281  else if (i > (size_t) ret)
282  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
283 #endif /* EPOLL_SUPPORT */
284  return ret;
285 }
286 
287 
300 int
302  enum MHD_ValueKind kind,
303  MHD_KeyValueIterator iterator,
304  void *iterator_cls)
305 {
306  int ret;
307  struct MHD_HTTP_Header *pos;
308 
309  if (NULL == connection)
310  return -1;
311  ret = 0;
312  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
313  if (0 != (pos->kind & kind))
314  {
315  ret++;
316  if ( (NULL != iterator) &&
317  (MHD_YES != iterator (iterator_cls,
318  pos->kind,
319  pos->header,
320  pos->value)) )
321  return ret;
322  }
323  return ret;
324 }
325 
326 
339 int
341  enum MHD_ValueKind kind,
342  MHD_KeyValueIteratorN iterator,
343  void *iterator_cls)
344 {
345  int ret;
346  struct MHD_HTTP_Header *pos;
347 
348  if (NULL == connection)
349  return -1;
350  ret = 0;
351 
352  if (NULL == iterator)
353  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
354  {
355  if (0 != (kind & pos->kind))
356  ret++;
357  }
358  else
359  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
360  if (0 != (kind & pos->kind))
361  {
362  ret++;
363  if (MHD_NO == iterator (iterator_cls,
364  pos->kind,
365  pos->header,
366  pos->header_size,
367  pos->value,
368  pos->value_size))
369  return ret;
370  }
371  return ret;
372 }
373 
374 
392 static int
394  enum MHD_ValueKind kind,
395  const char *key,
396  size_t key_size,
397  const char *value,
398  size_t value_size)
399 {
400  struct MHD_HTTP_Header *pos;
401 
402  pos = MHD_pool_allocate (connection->pool,
403  sizeof (struct MHD_HTTP_Header),
404  true);
405  if (NULL == pos)
406  return MHD_NO;
407  pos->header = (char *) key;
408  pos->header_size = key_size;
409  pos->value = (char *) value;
410  pos->value_size = value_size;
411  pos->kind = kind;
412  pos->next = NULL;
413  /* append 'pos' to the linked list of headers */
414  if (NULL == connection->headers_received_tail)
415  {
416  connection->headers_received = pos;
417  connection->headers_received_tail = pos;
418  }
419  else
420  {
421  connection->headers_received_tail->next = pos;
422  connection->headers_received_tail = pos;
423  }
424  return MHD_YES;
425 }
426 
427 
453 int
455  enum MHD_ValueKind kind,
456  const char *key,
457  size_t key_size,
458  const char *value,
459  size_t value_size)
460 {
461  if ( (MHD_GET_ARGUMENT_KIND != kind) &&
462  ( ((key ? strlen (key) : 0) != key_size) ||
463  ((value ? strlen (value) : 0) != value_size) ) )
464  return MHD_NO; /* binary zero is allowed only in GET arguments */
465 
466  return MHD_set_connection_value_n_nocheck_ (connection,
467  kind,
468  key,
469  key_size,
470  value,
471  value_size);
472 }
473 
474 
500 int
502  enum MHD_ValueKind kind,
503  const char *key,
504  const char *value)
505 {
506  return MHD_set_connection_value_n_nocheck_ (connection,
507  kind,
508  key,
509  NULL != key
510  ? strlen (key)
511  : 0,
512  value,
513  NULL != value
514  ? strlen (value)
515  : 0);
516 }
517 
518 
529 const char *
531  enum MHD_ValueKind kind,
532  const char *key)
533 {
534  const char *value;
535 
536  value = NULL;
537  (void) MHD_lookup_connection_value_n (connection,
538  kind,
539  key,
540  (NULL == key) ? 0 : strlen (key),
541  &value,
542  NULL);
543  return value;
544 }
545 
546 
566 _MHD_EXTERN int
568  enum MHD_ValueKind kind,
569  const char *key,
570  size_t key_size,
571  const char **value_ptr,
572  size_t *value_size_ptr)
573 {
574  struct MHD_HTTP_Header *pos;
575 
576  if (NULL == connection)
577  return MHD_NO;
578 
579  if (NULL == key)
580  {
581  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
582  {
583  if ( (0 != (kind & pos->kind)) &&
584  (NULL == pos->header) )
585  break;
586  }
587  }
588  else
589  {
590  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
591  {
592  if ( (0 != (kind & pos->kind)) &&
593  (key_size == pos->header_size) &&
594  ( (key == pos->header) ||
596  pos->header,
597  key_size) ) ) )
598  break;
599  }
600  }
601 
602  if (NULL == pos)
603  return MHD_NO;
604 
605  if (NULL != value_ptr)
606  *value_ptr = pos->value;
607 
608  if (NULL != value_size_ptr)
609  *value_size_ptr = pos->value_size;
610 
611  return MHD_YES;
612 }
613 
614 
630 static bool
631 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
632  const char *header,
633  size_t header_len,
634  const char *token,
635  size_t token_len)
636 {
637  struct MHD_HTTP_Header *pos;
638 
639  if ((NULL == connection) || (NULL == header) || (0 == header[0]) || (NULL ==
640  token) ||
641  (0 ==
642  token
643  [
644  0]) )
645  return false;
646 
647  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
648  {
649  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
650  (header_len == pos->header_size) &&
651  ( (header == pos->header) ||
653  pos->header,
654  header_len)) ) &&
655  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
656  return true;
657  }
658  return false;
659 }
660 
661 
673 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
674  MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
675  (tkn),MHD_STATICSTR_LEN_ (tkn))
676 
677 
685 static int
686 need_100_continue (struct MHD_Connection *connection)
687 {
688  const char *expect;
689 
690  return ( (NULL == connection->response) &&
691  (NULL != connection->version) &&
692  (MHD_str_equal_caseless_ (connection->version,
694  (MHD_NO != MHD_lookup_connection_value_n (connection,
699  &expect,
700  NULL)) &&
701  (MHD_str_equal_caseless_ (expect,
702  "100-continue")) &&
703  (connection->continue_message_write_offset <
705 }
706 
707 
714 void
716 {
717  const struct MHD_Daemon *daemon = connection->daemon;
718 
719  connection->state = MHD_CONNECTION_CLOSED;
721  if (0 == (daemon->options & MHD_USE_TURBO))
722  {
723 #ifdef HTTPS_SUPPORT
724  /* For TLS connection use shutdown of TLS layer
725  * and do not shutdown TCP socket. This give more
726  * chances to send TLS closure data to remote side.
727  * Closure of TLS layer will be interpreted by
728  * remote side as end of transmission. */if (0 != (daemon->options & MHD_USE_TLS))
729  {
730  if (! MHD_tls_connection_shutdown (connection))
731  shutdown (connection->socket_fd,
732  SHUT_WR);
733  }
734  else /* Combined with next 'shutdown()'. */
735 #endif /* HTTPS_SUPPORT */
736  shutdown (connection->socket_fd,
737  SHUT_WR);
738  }
739 }
740 
741 
751 void
753  enum MHD_RequestTerminationCode termination_code)
754 {
755  struct MHD_Daemon *daemon = connection->daemon;
756  struct MHD_Response *resp = connection->response;
757 
758  MHD_connection_mark_closed_ (connection);
759  if (NULL != resp)
760  {
761  connection->response = NULL;
762  MHD_destroy_response (resp);
763  }
764  if ( (NULL != daemon->notify_completed) &&
765  (connection->client_aware) )
766  daemon->notify_completed (daemon->notify_completed_cls,
767  connection,
768  &connection->client_context,
769  termination_code);
770  connection->client_aware = false;
771 }
772 
773 
774 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
775 
785 void
787 {
788  struct MHD_Daemon *daemon = connection->daemon;
789  struct MHD_UpgradeResponseHandle *urh = connection->urh;
790 
791  if (0 == (daemon->options & MHD_USE_TLS))
792  return; /* Nothing to do with non-TLS connection. */
793 
794  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
795  DLL_remove (daemon->urh_head,
796  daemon->urh_tail,
797  urh);
798 #if EPOLL_SUPPORT
799  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
800  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
801  EPOLL_CTL_DEL,
802  connection->socket_fd,
803  NULL)) )
804  {
805  MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
806  }
807  if (urh->in_eready_list)
808  {
809  EDLL_remove (daemon->eready_urh_head,
810  daemon->eready_urh_tail,
811  urh);
812  urh->in_eready_list = false;
813  }
814 #endif /* EPOLL_SUPPORT */
815  if (MHD_INVALID_SOCKET != urh->mhd.socket)
816  {
817 #if EPOLL_SUPPORT
818  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
819  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
820  EPOLL_CTL_DEL,
821  urh->mhd.socket,
822  NULL)) )
823  {
824  MHD_PANIC (_ ("Failed to remove FD from epoll set\n"));
825  }
826 #endif /* EPOLL_SUPPORT */
827  /* Reflect remote disconnect to application by breaking
828  * socketpair connection. */
829  shutdown (urh->mhd.socket, SHUT_RDWR);
830  }
831  /* Socketpair sockets will remain open as they will be
832  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
833  * closed by MHD_cleanup_upgraded_connection_() during
834  * connection's final cleanup.
835  */}
836 
837 
838 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
839 
840 
848 static void
850  const char *emsg)
851 {
852 #ifdef HAVE_MESSAGES
853  if (NULL != emsg)
854  MHD_DLOG (connection->daemon,
855  emsg);
856 #else /* ! HAVE_MESSAGES */
857  (void) emsg; /* Mute compiler warning. */
858 #endif /* ! HAVE_MESSAGES */
859  MHD_connection_close_ (connection,
861 }
862 
863 
868 #ifdef HAVE_MESSAGES
869 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
870 #else
871 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
872 #endif
873 
874 
887 static int
889 {
890  ssize_t ret;
891  struct MHD_Response *response;
892 
893  response = connection->response;
894  if (NULL == response->crc)
895  return MHD_YES;
896  if ( (0 == response->total_size) ||
897  (connection->response_write_position == response->total_size) )
898  return MHD_YES; /* 0-byte response is always ready */
899  if ( (response->data_start <=
900  connection->response_write_position) &&
901  (response->data_size + response->data_start >
902  connection->response_write_position) )
903  return MHD_YES; /* response already ready */
904 #if defined(_MHD_HAVE_SENDFILE)
905  if (MHD_resp_sender_sendfile == connection->resp_sender)
906  {
907  /* will use sendfile, no need to bother response crc */
908  return MHD_YES;
909  }
910 #endif /* _MHD_HAVE_SENDFILE */
911 
912  ret = response->crc (response->crc_cls,
913  connection->response_write_position,
914  response->data,
915  (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
916  response->total_size
917  - connection->response_write_position));
918  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
919  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
920  {
921  /* either error or http 1.0 transfer, close socket! */
922  response->total_size = connection->response_write_position;
923 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
924  MHD_mutex_unlock_chk_ (&response->mutex);
925 #endif
926  if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
927  MHD_connection_close_ (connection,
929  else
930  CONNECTION_CLOSE_ERROR (connection,
931  _ (
932  "Closing connection (application reported error generating data)\n"));
933  return MHD_NO;
934  }
935  response->data_start = connection->response_write_position;
936  response->data_size = ret;
937  if (0 == ret)
938  {
940 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
941  MHD_mutex_unlock_chk_ (&response->mutex);
942 #endif
943  return MHD_NO;
944  }
945  return MHD_YES;
946 }
947 
948 
958 static int
960 {
961  ssize_t ret;
962  struct MHD_Response *response;
963  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
964  int cblen;
965 
966  response = connection->response;
967  if (NULL == response->crc)
968  return MHD_YES;
969  if (0 == connection->write_buffer_size)
970  {
971  size_t size;
972 
973  size = MHD_pool_get_free (connection->pool);
974  if (size < 128)
975  {
976 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
977  MHD_mutex_unlock_chk_ (&response->mutex);
978 #endif
979  /* not enough memory */
980  CONNECTION_CLOSE_ERROR (connection,
981  _ ("Closing connection (out of memory)\n"));
982  return MHD_NO;
983  }
984  if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
985  size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
986  connection->write_buffer = MHD_pool_allocate (connection->pool,
987  size,
988  false);
989  mhd_assert (NULL != connection->write_buffer);
990  connection->write_buffer_size = size;
991  }
992 
993  if (0 == response->total_size)
994  ret = 0; /* response must be empty, don't bother calling crc */
995  else if ( (response->data_start <=
996  connection->response_write_position) &&
997  (response->data_start + response->data_size >
998  connection->response_write_position) )
999  {
1000  /* difference between response_write_position and data_start is less
1001  than data_size which is size_t type, no need to check for overflow */
1002  const size_t data_write_offset
1003  = (size_t) (connection->response_write_position - response->data_start);
1004  /* buffer already ready, use what is there for the chunk */
1005  ret = response->data_size - data_write_offset;
1006  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2)
1007  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1008  memcpy (&connection->write_buffer[sizeof (cbuf)],
1009  &response->data[data_write_offset],
1010  ret);
1011  }
1012  else
1013  {
1014  /* buffer not in range, try to fill it */
1015  ret = response->crc (response->crc_cls,
1016  connection->response_write_position,
1017  &connection->write_buffer[sizeof (cbuf)],
1018  connection->write_buffer_size - sizeof (cbuf) - 2);
1019  }
1020  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1021  {
1022  /* error, close socket! */
1023  response->total_size = connection->response_write_position;
1024 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1025  MHD_mutex_unlock_chk_ (&response->mutex);
1026 #endif
1027  CONNECTION_CLOSE_ERROR (connection,
1028  _ (
1029  "Closing connection (application error generating response)\n"));
1030  return MHD_NO;
1031  }
1032  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1033  (0 == response->total_size) )
1034  {
1035  /* end of message, signal other side! */
1036  memcpy (connection->write_buffer,
1037  "0\r\n",
1038  3);
1039  connection->write_buffer_append_offset = 3;
1040  connection->write_buffer_send_offset = 0;
1041  response->total_size = connection->response_write_position;
1042  return MHD_YES;
1043  }
1044  if (0 == ret)
1045  {
1047 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1048  MHD_mutex_unlock_chk_ (&response->mutex);
1049 #endif
1050  return MHD_NO;
1051  }
1052  if (ret > 0xFFFFFF)
1053  ret = 0xFFFFFF;
1054  cblen = MHD_snprintf_ (cbuf,
1055  sizeof (cbuf),
1056  "%X\r\n",
1057  (unsigned int) ret);
1058  mhd_assert (cblen > 0);
1059  mhd_assert ((size_t) cblen < sizeof(cbuf));
1060  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1061  cbuf,
1062  cblen);
1063  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1064  "\r\n",
1065  2);
1066  connection->response_write_position += ret;
1067  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1068  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1069  return MHD_YES;
1070 }
1071 
1072 
1089 static int
1091 {
1092  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1093  return MHD_NO;
1094  if (NULL == connection->version)
1095  return MHD_NO;
1096  if ( (NULL != connection->response) &&
1097  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1098  return MHD_NO;
1099 
1100  if (MHD_str_equal_caseless_ (connection->version,
1102  ( (NULL == connection->response) ||
1103  (0 == (connection->response->flags
1105  {
1106  if (MHD_lookup_header_s_token_ci (connection,
1108  "upgrade"))
1109  return MHD_NO;
1110 
1111  if (MHD_lookup_header_s_token_ci (connection,
1113  "close"))
1114  return MHD_NO;
1115 
1116  return MHD_YES;
1117  }
1118  if (MHD_str_equal_caseless_ (connection->version,
1120  {
1121  if (MHD_lookup_header_s_token_ci (connection,
1123  "Keep-Alive"))
1124  return MHD_YES;
1125 
1126  return MHD_NO;
1127  }
1128  return MHD_NO;
1129 }
1130 
1131 
1139 static void
1140 get_date_string (char *date,
1141  size_t date_len)
1142 {
1143  static const char *const days[] = {
1144  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1145  };
1146  static const char *const mons[] = {
1147  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1148  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1149  };
1150  struct tm now;
1151  time_t t;
1152 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1153  ! defined(HAVE_GMTIME_R)
1154  struct tm*pNow;
1155 #endif
1156 
1157  date[0] = 0;
1158  time (&t);
1159 #if defined(HAVE_C11_GMTIME_S)
1160  if (NULL == gmtime_s (&t,
1161  &now))
1162  return;
1163 #elif defined(HAVE_W32_GMTIME_S)
1164  if (0 != gmtime_s (&now,
1165  &t))
1166  return;
1167 #elif defined(HAVE_GMTIME_R)
1168  if (NULL == gmtime_r (&t,
1169  &now))
1170  return;
1171 #else
1172  pNow = gmtime (&t);
1173  if (NULL == pNow)
1174  return;
1175  now = *pNow;
1176 #endif
1177  MHD_snprintf_ (date,
1178  date_len,
1179  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1180  days[now.tm_wday % 7],
1181  (unsigned int) now.tm_mday,
1182  mons[now.tm_mon % 12],
1183  (unsigned int) (1900 + now.tm_year),
1184  (unsigned int) now.tm_hour,
1185  (unsigned int) now.tm_min,
1186  (unsigned int) now.tm_sec);
1187 }
1188 
1189 
1202 static bool
1204  bool required)
1205 {
1206  size_t new_size;
1207  size_t avail_size;
1208 
1209  avail_size = MHD_pool_get_free (connection->pool);
1210  if (0 == avail_size)
1211  return false; /* No more space available */
1212  if (0 == connection->read_buffer_size)
1213  new_size = avail_size / 2; /* Use half of available buffer for reading */
1214  else
1215  {
1216  size_t grow_size;
1217 
1218  grow_size = avail_size / 8;
1219  if (MHD_BUF_INC_SIZE > grow_size)
1220  { /* Shortage of space */
1221  if (! required)
1222  return false; /* Grow is not mandatory, leave some space in pool */
1223  else
1224  {
1225  /* Shortage of space, but grow is mandatory */
1226  static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
1227  if (small_inc < avail_size)
1228  grow_size = small_inc;
1229  else
1230  grow_size = avail_size;
1231  }
1232  }
1233  new_size = connection->read_buffer_size + grow_size;
1234  }
1235  /* we can actually grow the buffer, do it! */
1236  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1237  connection->read_buffer,
1238  connection->read_buffer_size,
1239  new_size);
1240  mhd_assert (NULL != connection->read_buffer);
1241  connection->read_buffer_size = new_size;
1242  return true;
1243 }
1244 
1245 
1255 static int
1257 {
1258  struct MHD_Response *response = connection->response;
1259  size_t size;
1260  size_t off;
1261  struct MHD_HTTP_Header *pos;
1262  char code[256];
1263  char date[128];
1264  size_t datelen;
1265  char content_length_buf[128];
1266  size_t content_length_len;
1267  char *data;
1268  enum MHD_ValueKind kind;
1269  const char *reason_phrase;
1270  uint32_t rc;
1271  bool client_requested_close;
1272  bool response_has_close;
1273  bool response_has_keepalive;
1274  const char *have_encoding;
1275  bool must_add_close;
1276  bool must_add_chunked_encoding;
1277  bool must_add_keep_alive;
1278  bool must_add_content_length;
1279  bool may_add_content_length;
1280 
1281  mhd_assert (NULL != connection->version);
1282  if (0 == connection->version[0])
1283  {
1284  data = MHD_pool_allocate (connection->pool,
1285  0,
1286  true);
1287  connection->write_buffer = data;
1288  connection->write_buffer_append_offset = 0;
1289  connection->write_buffer_send_offset = 0;
1290  connection->write_buffer_size = 0;
1291  return MHD_YES;
1292  }
1293  rc = connection->responseCode & (~MHD_ICY_FLAG);
1294  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1295  {
1296  reason_phrase = MHD_get_reason_phrase_for (rc);
1297  off = MHD_snprintf_ (code,
1298  sizeof (code),
1299  "%s %u %s\r\n",
1300  (0 != (connection->responseCode & MHD_ICY_FLAG))
1301  ? "ICY"
1303  connection->version) ||
1304  (0 != (connection->response->flags
1308  rc,
1309  reason_phrase);
1310  /* estimate size */
1311  size = off + 2; /* +2 for extra "\r\n" at the end */
1313  if ( (0 == (connection->daemon->options
1315  (NULL == MHD_get_response_header (response,
1317  get_date_string (date,
1318  sizeof (date));
1319  else
1320  date[0] = '\0';
1321  datelen = strlen (date);
1322  size += datelen;
1323  }
1324  else
1325  {
1326  /* 2 bytes for final CRLF of a Chunked-Body */
1327  size = 2;
1329  off = 0;
1330  datelen = 0;
1331  }
1332 
1333  /* calculate extra headers we need to add, such as 'Connection: close',
1334  first see what was explicitly requested by the application */
1335  must_add_close = false;
1336  must_add_chunked_encoding = false;
1337  must_add_keep_alive = false;
1338  must_add_content_length = false;
1339  response_has_close = false;
1340  switch (connection->state)
1341  {
1343  response_has_close = MHD_check_response_header_s_token_ci (response,
1345  "close");
1346  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1348  "Keep-Alive");
1349  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1351  "close");
1352 
1353  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1354  connection->keepalive = MHD_CONN_MUST_CLOSE;
1355 #ifdef UPGRADE_SUPPORT
1356  else if (NULL != response->upgrade_handler)
1357  /* If this connection will not be "upgraded", it must be closed. */
1358  connection->keepalive = MHD_CONN_MUST_CLOSE;
1359 #endif /* UPGRADE_SUPPORT */
1360 
1361  /* now analyze chunked encoding situation */
1362  connection->have_chunked_upload = false;
1363  have_encoding = MHD_get_response_header (response,
1365  if (NULL == have_encoding)
1366  may_add_content_length = true;
1367  else
1368  may_add_content_length = false; /* RFC 7230, Section 3.3.2 forbids header */
1369  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1370 #ifdef UPGRADE_SUPPORT
1371  (NULL == response->upgrade_handler) &&
1372 #endif /* UPGRADE_SUPPORT */
1373  (! response_has_close) &&
1374  (! client_requested_close) )
1375  {
1376  /* size is unknown, and close was not explicitly requested;
1377  need to either to HTTP 1.1 chunked encoding or
1378  close the connection */
1379  /* 'close' header doesn't exist yet, see if we need to add one;
1380  if the client asked for a close, no need to start chunk'ing */
1381  if ( (MHD_YES == keepalive_possible (connection)) &&
1383  connection->version) ) )
1384  {
1385  if (NULL == have_encoding)
1386  {
1387  must_add_chunked_encoding = true;
1388  connection->have_chunked_upload = true;
1389  }
1390  else
1391  {
1392  if (MHD_str_equal_caseless_ (have_encoding,
1393  "identity"))
1394  {
1395  /* application forced identity encoding, can't do 'chunked' */
1396  must_add_close = true;
1397  }
1398  else
1399  {
1400  connection->have_chunked_upload = true;
1401  }
1402  }
1403  }
1404  else
1405  {
1406  /* Keep alive or chunking not possible
1407  => set close header if not present */
1408  if (! response_has_close)
1409  must_add_close = true;
1410  }
1411  }
1412 
1413  /* check for other reasons to add 'close' header */
1414  if ( ( (client_requested_close) ||
1415  (connection->read_closed) ||
1416  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1417  (! response_has_close) &&
1418 #ifdef UPGRADE_SUPPORT
1419  (NULL == response->upgrade_handler) &&
1420 #endif /* UPGRADE_SUPPORT */
1421  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1422  must_add_close = true;
1423 
1424  /* check if we must add 'close' header because we cannot add content-length
1425  because it is forbidden AND we don't have a 'chunked' encoding */
1426  if ( (! may_add_content_length) &&
1427  (! connection->have_chunked_upload) &&
1428  (! response_has_close) )
1429  must_add_close = true;
1430  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1431  codes SHOULD NOT have a Content-Length according to spec;
1432  also chunked encoding / unknown length or CONNECT... */
1433  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1434  (MHD_HTTP_NO_CONTENT != rc) &&
1435  (MHD_HTTP_NOT_MODIFIED != rc) &&
1436  (MHD_HTTP_OK <= rc) &&
1437  (NULL == /* this COULD fail if the check in
1438  MHD_add_response_header() was bypassed
1439  via #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH */
1440  MHD_get_response_header (response,
1442  (may_add_content_length) &&
1443  ( (NULL == connection->method) ||
1444  (! MHD_str_equal_caseless_ (connection->method,
1446  {
1447  /*
1448  Here we add a content-length if one is missing; however,
1449  for 'connect' methods, the responses MUST NOT include a
1450  content-length header *if* the response code is 2xx (in
1451  which case we expect there to be no body). Still,
1452  as we don't know the response code here in some cases, we
1453  simply only force adding a content-length header if this
1454  is not a 'connect' or if the response is not empty
1455  (which is kind of more sane, because if some crazy
1456  application did return content with a 2xx status code,
1457  then having a content-length might again be a good idea).
1458 
1459  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1460  a recent development of the HTTP 1.1 specification.
1461  */content_length_len
1462  = MHD_snprintf_ (content_length_buf,
1463  sizeof (content_length_buf),
1466  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1467  must_add_content_length = true;
1468  }
1469 
1470  /* check for adding keep alive */
1471  if ( (! response_has_keepalive) &&
1472  (! response_has_close) &&
1473  (! must_add_close) &&
1474  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1475 #ifdef UPGRADE_SUPPORT
1476  (NULL == response->upgrade_handler) &&
1477 #endif /* UPGRADE_SUPPORT */
1478  (MHD_YES == keepalive_possible (connection)) )
1479  must_add_keep_alive = true;
1480  break;
1482  response_has_keepalive = false;
1483  break;
1484  default:
1485  mhd_assert (0);
1486  return MHD_NO;
1487  }
1488 
1489  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1490  {
1491  if ( (must_add_close) || (response_has_close) )
1492  connection->keepalive = MHD_CONN_MUST_CLOSE;
1493  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1494  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1495  }
1496 
1497  if (must_add_close)
1498  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1499  if (must_add_keep_alive)
1500  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1501  if (must_add_chunked_encoding)
1502  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1503  if (must_add_content_length)
1504  size += content_length_len;
1505  mhd_assert (! (must_add_close && must_add_keep_alive) );
1506  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1507 
1508  for (pos = response->first_header; NULL != pos; pos = pos->next)
1509  {
1510  /* TODO: add proper support for excluding "Keep-Alive" token. */
1511  if ( (pos->kind == kind) &&
1512  (! ( (must_add_close) &&
1513  (response_has_keepalive) &&
1514  (pos->header_size == MHD_STATICSTR_LEN_ (
1521  "Keep-Alive")) ) ) )
1522  size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */
1523  }
1524  /* produce data */
1525  data = MHD_pool_allocate (connection->pool,
1526  size + 1,
1527  false);
1528  if (NULL == data)
1529  {
1530 #ifdef HAVE_MESSAGES
1531  MHD_DLOG (connection->daemon,
1532  "Not enough memory for write!\n");
1533 #endif
1534  return MHD_NO;
1535  }
1536  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1537  {
1538  memcpy (data,
1539  code,
1540  off);
1541  }
1542  if (must_add_close)
1543  {
1544  /* we must add the 'Connection: close' header */
1545  memcpy (&data[off],
1546  "Connection: close\r\n",
1547  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1548  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1549  }
1550  if (must_add_keep_alive)
1551  {
1552  /* we must add the 'Connection: Keep-Alive' header */
1553  memcpy (&data[off],
1554  "Connection: Keep-Alive\r\n",
1555  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1556  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1557  }
1558  if (must_add_chunked_encoding)
1559  {
1560  /* we must add the 'Transfer-Encoding: chunked' header */
1561  memcpy (&data[off],
1562  "Transfer-Encoding: chunked\r\n",
1563  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1564  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1565  }
1566  if (must_add_content_length)
1567  {
1568  /* we must add the 'Content-Length' header */
1569  memcpy (&data[off],
1570  content_length_buf,
1571  content_length_len);
1572  off += content_length_len;
1573  }
1574  for (pos = response->first_header; NULL != pos; pos = pos->next)
1575  {
1576  /* TODO: add proper support for excluding "Keep-Alive" token. */
1577  if ( (pos->kind == kind) &&
1578  (! ( (must_add_close) &&
1579  (response_has_keepalive) &&
1580  (pos->header_size == MHD_STATICSTR_LEN_ (
1587  "Keep-Alive")) ) ) )
1588  off += MHD_snprintf_ (&data[off],
1589  size - off,
1590  "%s: %s\r\n",
1591  pos->header,
1592  pos->value);
1593  }
1594  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1595  {
1596  memcpy (&data[off],
1597  date,
1598  datelen);
1599  off += datelen;
1600  }
1601  memcpy (&data[off],
1602  "\r\n",
1603  2);
1604  off += 2;
1605 
1606  if (off != size)
1608  __FILE__,
1609  __LINE__,
1610  NULL);
1611  connection->write_buffer = data;
1612  connection->write_buffer_append_offset = size;
1613  connection->write_buffer_send_offset = 0;
1614  connection->write_buffer_size = size + 1;
1615  return MHD_YES;
1616 }
1617 
1618 
1628 static void
1630  unsigned int status_code,
1631  const char *message)
1632 {
1633  struct MHD_Response *response;
1634  int iret;
1635 
1636  if (NULL == connection->version)
1637  {
1638  /* we were unable to process the full header line, so we don't
1639  really know what version the client speaks; assume 1.0 */
1640  connection->version = MHD_HTTP_VERSION_1_0;
1641  }
1642  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1643  connection->read_closed = true;
1644  if (0 != connection->read_buffer_size)
1645  {
1646  /* Read buffer is not needed anymore, discard it
1647  * to free some space for error response. */
1648  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1649  connection->read_buffer,
1650  connection->read_buffer_size,
1651  0);
1652  connection->read_buffer_size = 0;
1653  }
1654 #ifdef HAVE_MESSAGES
1655  MHD_DLOG (connection->daemon,
1656  _ (
1657  "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1658  status_code,
1659  message);
1660 #endif
1661  if (NULL != connection->response)
1662  {
1663  MHD_destroy_response (connection->response);
1664  connection->response = NULL;
1665  }
1666  response = MHD_create_response_from_buffer (strlen (message),
1667  (void *) message,
1669  if (NULL == response)
1670  {
1671  /* can't even send a reply, at least close the connection */
1672  connection->state = MHD_CONNECTION_CLOSED;
1673  return;
1674  }
1675  iret = MHD_queue_response (connection,
1676  status_code,
1677  response);
1678  MHD_destroy_response (response);
1679  if (MHD_YES != iret)
1680  {
1681  /* can't even send a reply, at least close the connection */
1682  CONNECTION_CLOSE_ERROR (connection,
1683  _ (
1684  "Closing connection (failed to queue response)\n"));
1685  return;
1686  }
1687  mhd_assert (NULL != connection->response);
1688  /* Do not reuse this connection. */
1689  connection->keepalive = MHD_CONN_MUST_CLOSE;
1690  if (MHD_NO == build_header_response (connection))
1691  {
1692  /* oops - close! */
1693  CONNECTION_CLOSE_ERROR (connection,
1694  _ (
1695  "Closing connection (failed to create response header)\n"));
1696  }
1697  else
1698  {
1699  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1700  }
1701 }
1702 
1703 
1712 static void
1714 {
1715  /* Do not update states of suspended connection */
1716  if (connection->suspended)
1717  return; /* States will be updated after resume. */
1718 #ifdef HTTPS_SUPPORT
1719  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1720  { /* HTTPS connection. */
1721  switch (connection->tls_state)
1722  {
1723  case MHD_TLS_CONN_INIT:
1725  return;
1727  if (0 == gnutls_record_get_direction (connection->tls_session))
1729  else
1731  return;
1732  default:
1733  break;
1734  }
1735  }
1736 #endif /* HTTPS_SUPPORT */
1737  while (1)
1738  {
1739 #if DEBUG_STATES
1740  MHD_DLOG (connection->daemon,
1741  _ ("In function %s handling connection at state: %s\n"),
1742  __FUNCTION__,
1743  MHD_state_to_string (connection->state));
1744 #endif
1745  switch (connection->state)
1746  {
1747  case MHD_CONNECTION_INIT:
1750  /* while reading headers, we always grow the
1751  read buffer if needed, no size-check required */
1752  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1753  (! try_grow_read_buffer (connection, true)) )
1754  {
1755  transmit_error_response (connection,
1756  (connection->url != NULL)
1759  REQUEST_TOO_BIG);
1760  continue;
1761  }
1762  if (! connection->read_closed)
1764  else
1766  break;
1768  mhd_assert (0);
1769  break;
1771  mhd_assert (0);
1772  break;
1775  break;
1777  if (connection->read_buffer_offset == connection->read_buffer_size)
1778  {
1779  const bool internal_poll = (0 != (connection->daemon->options
1781  if ( (! try_grow_read_buffer (connection, true)) &&
1782  internal_poll)
1783  {
1784  /* failed to grow the read buffer, and the
1785  client which is supposed to handle the
1786  received data in a *blocking* fashion
1787  (in this mode) did not handle the data as
1788  it was supposed to!
1789  => we would either have to do busy-waiting
1790  (on the client, which would likely fail),
1791  or if we do nothing, we would just timeout
1792  on the connection (if a timeout is even
1793  set!).
1794  Solution: we kill the connection with an error */transmit_error_response (connection,
1796  INTERNAL_ERROR);
1797  continue;
1798  }
1799  }
1800  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1801  (! connection->read_closed) )
1803  else
1805  break;
1808  /* while reading footers, we always grow the
1809  read buffer if needed, no size-check required */
1810  if (connection->read_closed)
1811  {
1812  CONNECTION_CLOSE_ERROR (connection,
1813  NULL);
1814  continue;
1815  }
1817  /* transition to FOOTERS_RECEIVED
1818  happens in read handler */
1819  break;
1822  break;
1824  /* headers in buffer, keep writing */
1826  break;
1828  mhd_assert (0);
1829  break;
1832  break;
1835  break;
1838  break;
1841  break;
1843  mhd_assert (0);
1844  break;
1847  break;
1849  mhd_assert (0);
1850  break;
1851  case MHD_CONNECTION_CLOSED:
1853  return; /* do nothing, not even reading */
1854 #ifdef UPGRADE_SUPPORT
1855  case MHD_CONNECTION_UPGRADE:
1856  mhd_assert (0);
1857  break;
1858 #endif /* UPGRADE_SUPPORT */
1859  default:
1860  mhd_assert (0);
1861  }
1862  break;
1863  }
1864 }
1865 
1866 
1880 static char *
1882  size_t *line_len)
1883 {
1884  char *rbuf;
1885  size_t pos;
1886 
1887  if (0 == connection->read_buffer_offset)
1888  return NULL;
1889  pos = 0;
1890  rbuf = connection->read_buffer;
1891  while ( (pos < connection->read_buffer_offset - 1) &&
1892  ('\r' != rbuf[pos]) &&
1893  ('\n' != rbuf[pos]) )
1894  pos++;
1895  if ( (pos == connection->read_buffer_offset - 1) &&
1896  ('\n' != rbuf[pos]) )
1897  {
1898  /* not found, consider growing... */
1899  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1900  (! try_grow_read_buffer (connection, true)) )
1901  {
1902  transmit_error_response (connection,
1903  (NULL != connection->url)
1906  REQUEST_TOO_BIG);
1907  }
1908  if (line_len)
1909  *line_len = 0;
1910  return NULL;
1911  }
1912 
1913  if (line_len)
1914  *line_len = pos;
1915  /* found, check if we have proper LFCR */
1916  if ( ('\r' == rbuf[pos]) &&
1917  ('\n' == rbuf[pos + 1]) )
1918  rbuf[pos++] = '\0'; /* skip both r and n */
1919  rbuf[pos++] = '\0';
1920  connection->read_buffer += pos;
1921  connection->read_buffer_size -= pos;
1922  connection->read_buffer_offset -= pos;
1923  return rbuf;
1924 }
1925 
1926 
1940 static int
1942  const char *key,
1943  size_t key_size,
1944  const char *value,
1945  size_t value_size,
1946  enum MHD_ValueKind kind)
1947 {
1948  if (MHD_NO ==
1949  MHD_set_connection_value_n (connection,
1950  kind,
1951  key,
1952  key_size,
1953  value,
1954  value_size))
1955  {
1956 #ifdef HAVE_MESSAGES
1957  MHD_DLOG (connection->daemon,
1958  _ ("Not enough memory in pool to allocate header record!\n"));
1959 #endif
1960  transmit_error_response (connection,
1962  REQUEST_TOO_BIG);
1963  return MHD_NO;
1964  }
1965  return MHD_YES;
1966 }
1967 
1968 
1975 static int
1977 {
1978  const char *hdr;
1979  size_t hdr_len;
1980  char *cpy;
1981  char *pos;
1982  char *sce;
1983  char *semicolon;
1984  char *equals;
1985  char *ekill;
1986  char *end;
1987  char old;
1988  int quotes;
1989 
1990  if (MHD_NO == MHD_lookup_connection_value_n (connection,
1995  &hdr,
1996  &hdr_len))
1997  return MHD_YES;
1998  cpy = MHD_pool_allocate (connection->pool,
1999  hdr_len + 1,
2000  true);
2001  if (NULL == cpy)
2002  {
2003 #ifdef HAVE_MESSAGES
2004  MHD_DLOG (connection->daemon,
2005  _ ("Not enough memory in pool to parse cookies!\n"));
2006 #endif
2007  transmit_error_response (connection,
2009  REQUEST_TOO_BIG);
2010  return MHD_NO;
2011  }
2012  memcpy (cpy,
2013  hdr,
2014  hdr_len);
2015  cpy[hdr_len] = '\0';
2016  pos = cpy;
2017  while (NULL != pos)
2018  {
2019  while (' ' == *pos)
2020  pos++; /* skip spaces */
2021 
2022  sce = pos;
2023  while ( ((*sce) != '\0') &&
2024  ((*sce) != ',') &&
2025  ((*sce) != ';') &&
2026  ((*sce) != '=') )
2027  sce++;
2028  /* remove tailing whitespace (if any) from key */
2029  ekill = sce - 1;
2030  while ( (*ekill == ' ') &&
2031  (ekill >= pos) )
2032  *(ekill--) = '\0';
2033  old = *sce;
2034  *sce = '\0';
2035  if (old != '=')
2036  {
2037  /* value part omitted, use empty string... */
2038  if (MHD_NO ==
2039  connection_add_header (connection,
2040  pos,
2041  ekill - pos + 1,
2042  "",
2043  0,
2044  MHD_COOKIE_KIND))
2045  return MHD_NO;
2046  if (old == '\0')
2047  break;
2048  pos = sce + 1;
2049  continue;
2050  }
2051  equals = sce + 1;
2052  quotes = 0;
2053  semicolon = equals;
2054  while ( ('\0' != semicolon[0]) &&
2055  ( (0 != quotes) ||
2056  ( (';' != semicolon[0]) &&
2057  (',' != semicolon[0]) ) ) )
2058  {
2059  if ('"' == semicolon[0])
2060  quotes = (quotes + 1) & 1;
2061  semicolon++;
2062  }
2063  end = semicolon;
2064  if ('\0' == semicolon[0])
2065  semicolon = NULL;
2066  if (NULL != semicolon)
2067  {
2068  semicolon[0] = '\0';
2069  semicolon++;
2070  }
2071  /* remove quotes */
2072  if ( ('"' == equals[0]) &&
2073  ('"' == end[-1]) )
2074  {
2075  equals++;
2076  end--;
2077  *end = '\0';
2078  }
2079  if (MHD_NO ==
2080  connection_add_header (connection,
2081  pos,
2082  ekill - pos + 1,
2083  equals,
2084  end - equals,
2085  MHD_COOKIE_KIND))
2086  return MHD_NO;
2087  pos = semicolon;
2088  }
2089  return MHD_YES;
2090 }
2091 
2092 
2101 static int
2103  char *line,
2104  size_t line_len)
2105 {
2106  struct MHD_Daemon *daemon = connection->daemon;
2107  const char *curi;
2108  char *uri;
2109  char *http_version;
2110  char *args;
2111  unsigned int unused_num_headers;
2112 
2113  if (NULL == (uri = memchr (line,
2114  ' ',
2115  line_len)))
2116  return MHD_NO; /* serious error */
2117  uri[0] = '\0';
2118  connection->method = line;
2119  uri++;
2120  /* Skip any spaces. Not required by standard but allow
2121  to be more tolerant. */
2122  while ( (' ' == uri[0]) &&
2123  ( (size_t) (uri - line) < line_len) )
2124  uri++;
2125  if ((size_t) (uri - line) == line_len)
2126  {
2127  /* No URI and no http version given */
2128  curi = "";
2129  uri = NULL;
2130  connection->version = "";
2131  args = NULL;
2132  }
2133  else
2134  {
2135  size_t uri_len;
2136  curi = uri;
2137  /* Search from back to accept misformed URI with space */
2138  http_version = line + line_len - 1;
2139  /* Skip any trailing spaces */
2140  while ( (' ' == http_version[0]) &&
2141  (http_version > uri) )
2142  http_version--;
2143  /* Find first space in reverse direction */
2144  while ( (' ' != http_version[0]) &&
2145  (http_version > uri) )
2146  http_version--;
2147  if (http_version > uri)
2148  {
2149  /* http_version points to character before HTTP version string */
2150  http_version[0] = '\0';
2151  connection->version = http_version + 1;
2152  uri_len = http_version - uri;
2153  }
2154  else
2155  {
2156  connection->version = "";
2157  uri_len = line_len - (uri - line);
2158  }
2159  /* check for spaces in URI if we are "strict" */
2160  if ( (1 <= daemon->strict_for_client) &&
2161  (NULL != memchr (uri,
2162  ' ',
2163  uri_len)) )
2164  {
2165  /* space exists in URI and we are supposed to be strict, reject */
2166  return MHD_NO;
2167  }
2168 
2169  args = memchr (uri,
2170  '?',
2171  uri_len);
2172  }
2173 
2174  /* log callback before we modify URI *or* args */
2175  if (NULL != daemon->uri_log_callback)
2176  {
2177  connection->client_aware = true;
2178  connection->client_context
2179  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2180  uri,
2181  connection);
2182  }
2183 
2184  if (NULL != args)
2185  {
2186  args[0] = '\0';
2187  args++;
2188  /* note that this call clobbers 'args' */
2189  MHD_parse_arguments_ (connection,
2191  args,
2193  &unused_num_headers);
2194  }
2195 
2196  /* unescape URI *after* searching for arguments and log callback */
2197  if (NULL != uri)
2198  daemon->unescape_callback (daemon->unescape_callback_cls,
2199  connection,
2200  uri);
2201  connection->url = curi;
2202  return MHD_YES;
2203 }
2204 
2205 
2213 static void
2215 {
2216  struct MHD_Daemon *daemon = connection->daemon;
2217  size_t processed;
2218 
2219  if (NULL != connection->response)
2220  return; /* already queued a response */
2221  processed = 0;
2222  connection->client_aware = true;
2223  if (MHD_NO ==
2224  daemon->default_handler (daemon->default_handler_cls,
2225  connection,
2226  connection->url,
2227  connection->method,
2228  connection->version,
2229  NULL,
2230  &processed,
2231  &connection->client_context))
2232  {
2233  /* serious internal error, close connection */
2234  CONNECTION_CLOSE_ERROR (connection,
2235  _ (
2236  "Application reported internal error, closing connection.\n"));
2237  return;
2238  }
2239 }
2240 
2241 
2249 static void
2251 {
2252  struct MHD_Daemon *daemon = connection->daemon;
2253  size_t available;
2254  int instant_retry;
2255  char *buffer_head;
2256 
2257  if (NULL != connection->response)
2258  {
2259  /* already queued a response, discard remaining upload
2260  (but not more, there might be another request after it) */
2261  uint64_t purge = MHD_MIN (connection->remaining_upload_size,
2262  connection->read_buffer_offset);
2263  connection->remaining_upload_size -= purge;
2264  if (connection->read_buffer_offset > purge)
2265  memmove (connection->read_buffer,
2266  &connection->read_buffer[purge],
2267  connection->read_buffer_offset - purge);
2268  connection->read_buffer_offset -= purge;
2269  return;
2270  }
2271 
2272  buffer_head = connection->read_buffer;
2273  available = connection->read_buffer_offset;
2274  do
2275  {
2276  size_t to_be_processed;
2277  size_t left_unprocessed;
2278  size_t processed_size;
2279 
2280  instant_retry = MHD_NO;
2281  if ( (connection->have_chunked_upload) &&
2282  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2283  {
2284  if ( (connection->current_chunk_offset ==
2285  connection->current_chunk_size) &&
2286  (0LLU != connection->current_chunk_offset) &&
2287  (available >= 2) )
2288  {
2289  size_t i;
2290  /* skip new line at the *end* of a chunk */
2291  i = 0;
2292  if ( ('\r' == buffer_head[i]) ||
2293  ('\n' == buffer_head[i]) )
2294  i++; /* skip 1st part of line feed */
2295  if ( ('\r' == buffer_head[i]) ||
2296  ('\n' == buffer_head[i]) )
2297  i++; /* skip 2nd part of line feed */
2298  if (0 == i)
2299  {
2300  /* malformed encoding */
2301  CONNECTION_CLOSE_ERROR (connection,
2302  _ (
2303  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2304  return;
2305  }
2306  available -= i;
2307  buffer_head += i;
2308  connection->current_chunk_offset = 0;
2309  connection->current_chunk_size = 0;
2310  }
2311  if (connection->current_chunk_offset <
2312  connection->current_chunk_size)
2313  {
2314  uint64_t cur_chunk_left;
2315  /* we are in the middle of a chunk, give
2316  as much as possible to the client (without
2317  crossing chunk boundaries) */
2318  cur_chunk_left
2319  = connection->current_chunk_size - connection->current_chunk_offset;
2320  if (cur_chunk_left > available)
2321  to_be_processed = available;
2322  else
2323  { /* cur_chunk_left <= (size_t)available */
2324  to_be_processed = (size_t) cur_chunk_left;
2325  if (available > to_be_processed)
2326  instant_retry = MHD_YES;
2327  }
2328  }
2329  else
2330  {
2331  size_t i;
2332  size_t end_size;
2333  bool malformed;
2334 
2335  /* we need to read chunk boundaries */
2336  i = 0;
2337  while (i < available)
2338  {
2339  if ( ('\r' == buffer_head[i]) ||
2340  ('\n' == buffer_head[i]) ||
2341  (';' == buffer_head[i]) )
2342  break;
2343  i++;
2344  if (i >= 16)
2345  break;
2346  }
2347  end_size = i;
2348  /* find beginning of CRLF (skip over chunk extensions) */
2349  if (';' == buffer_head[i])
2350  {
2351  while (i < available)
2352  {
2353  if ( ('\r' == buffer_head[i]) ||
2354  ('\n' == buffer_head[i]) )
2355  break;
2356  i++;
2357  }
2358  }
2359  /* take '\n' into account; if '\n' is the unavailable
2360  character, we will need to wait until we have it
2361  before going further */
2362  if ( (i + 1 >= available) &&
2363  ! ( (1 == i) &&
2364  (2 == available) &&
2365  ('0' == buffer_head[0]) ) )
2366  break; /* need more data... */
2367  i++;
2368  malformed = (end_size >= 16);
2369  if (! malformed)
2370  {
2371  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2372  end_size,
2373  &connection->
2374  current_chunk_size);
2375  malformed = (end_size != num_dig);
2376  }
2377  if (malformed)
2378  {
2379  /* malformed encoding */
2380  CONNECTION_CLOSE_ERROR (connection,
2381  _ (
2382  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2383  return;
2384  }
2385  /* skip 2nd part of line feed */
2386  if ( (i < available) &&
2387  ( ('\r' == buffer_head[i]) ||
2388  ('\n' == buffer_head[i]) ) )
2389  i++;
2390 
2391  buffer_head += i;
2392  available -= i;
2393  connection->current_chunk_offset = 0;
2394 
2395  if (available > 0)
2396  instant_retry = MHD_YES;
2397  if (0LLU == connection->current_chunk_size)
2398  {
2399  connection->remaining_upload_size = 0;
2400  break;
2401  }
2402  continue;
2403  }
2404  }
2405  else
2406  {
2407  /* no chunked encoding, give all to the client */
2408  if ( (0 != connection->remaining_upload_size) &&
2409  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2410  (connection->remaining_upload_size < available) )
2411  {
2412  to_be_processed = (size_t) connection->remaining_upload_size;
2413  }
2414  else
2415  {
2420  to_be_processed = available;
2421  }
2422  }
2423  left_unprocessed = to_be_processed;
2424  connection->client_aware = true;
2425  if (MHD_NO ==
2426  daemon->default_handler (daemon->default_handler_cls,
2427  connection,
2428  connection->url,
2429  connection->method,
2430  connection->version,
2431  buffer_head,
2432  &left_unprocessed,
2433  &connection->client_context))
2434  {
2435  /* serious internal error, close connection */
2436  CONNECTION_CLOSE_ERROR (connection,
2437  _ (
2438  "Application reported internal error, closing connection.\n"));
2439  return;
2440  }
2441  if (left_unprocessed > to_be_processed)
2443  __FILE__,
2444  __LINE__
2445 #ifdef HAVE_MESSAGES
2446  , _ ("libmicrohttpd API violation")
2447 #else
2448  , NULL
2449 #endif
2450  );
2451  if (0 != left_unprocessed)
2452  {
2453  instant_retry = MHD_NO; /* client did not process everything */
2454 #ifdef HAVE_MESSAGES
2455  /* client did not process all upload data, complain if
2456  the setup was incorrect, which may prevent us from
2457  handling the rest of the request */
2458  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2459  (! connection->suspended) )
2460  MHD_DLOG (daemon,
2461  _ (
2462  "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2463 #endif
2464  }
2465  processed_size = to_be_processed - left_unprocessed;
2466  if (connection->have_chunked_upload)
2467  connection->current_chunk_offset += processed_size;
2468  /* dh left "processed" bytes in buffer for next time... */
2469  buffer_head += processed_size;
2470  available -= processed_size;
2471  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2472  connection->remaining_upload_size -= processed_size;
2473  }
2474  while (MHD_YES == instant_retry);
2475  if ( (available > 0) &&
2476  (buffer_head != connection->read_buffer) )
2477  memmove (connection->read_buffer,
2478  buffer_head,
2479  available);
2480  connection->read_buffer_offset = available;
2481 }
2482 
2483 
2492 static int
2493 check_write_done (struct MHD_Connection *connection,
2494  enum MHD_CONNECTION_STATE next_state)
2495 {
2496  if (connection->write_buffer_append_offset !=
2497  connection->write_buffer_send_offset)
2498  return MHD_NO;
2499  connection->write_buffer_append_offset = 0;
2500  connection->write_buffer_send_offset = 0;
2501  connection->state = next_state;
2502  MHD_pool_reallocate (connection->pool,
2503  connection->write_buffer,
2504  connection->write_buffer_size,
2505  0);
2506  connection->write_buffer = NULL;
2507  connection->write_buffer_size = 0;
2508  return MHD_YES;
2509 }
2510 
2511 
2521 static int
2523  char *line)
2524 {
2525  char *colon;
2526 
2527  /* line should be normal header line, find colon */
2528  colon = strchr (line, ':');
2529  if (NULL == colon)
2530  {
2531  /* error in header line, die hard */
2532  CONNECTION_CLOSE_ERROR (connection,
2533  _ (
2534  "Received malformed line (no colon). Closing connection.\n"));
2535  return MHD_NO;
2536  }
2537  if (-1 >= connection->daemon->strict_for_client)
2538  {
2539  /* check for whitespace before colon, which is not allowed
2540  by RFC 7230 section 3.2.4; we count space ' ' and
2541  tab '\t', but not '\r\n' as those would have ended the line. */
2542  const char *white;
2543 
2544  white = strchr (line, ' ');
2545  if ( (NULL != white) &&
2546  (white < colon) )
2547  return MHD_NO;
2548  white = strchr (line, '\t');
2549  if ( (NULL != white) &&
2550  (white < colon) )
2551  return MHD_NO;
2552  }
2553  /* zero-terminate header */
2554  colon[0] = '\0';
2555  colon++; /* advance to value */
2556  while ( ('\0' != colon[0]) &&
2557  ( (' ' == colon[0]) ||
2558  ('\t' == colon[0]) ) )
2559  colon++;
2560  /* we do the actual adding of the connection
2561  header at the beginning of the while
2562  loop since we need to be able to inspect
2563  the *next* header line (in case it starts
2564  with a space...) */connection->last = line;
2565  connection->colon = colon;
2566  return MHD_YES;
2567 }
2568 
2569 
2580 static int
2582  char *line,
2583  enum MHD_ValueKind kind)
2584 {
2585  char *last;
2586  char *tmp;
2587  size_t last_len;
2588  size_t tmp_len;
2589 
2590  last = connection->last;
2591  if ( (' ' == line[0]) ||
2592  ('\t' == line[0]) )
2593  {
2594  /* value was continued on the next line, see
2595  http://www.jmarshall.com/easy/http/ */
2596  last_len = strlen (last);
2597  /* skip whitespace at start of 2nd line */
2598  tmp = line;
2599  while ( (' ' == tmp[0]) ||
2600  ('\t' == tmp[0]) )
2601  tmp++;
2602  tmp_len = strlen (tmp);
2603  /* FIXME: we might be able to do this better (faster!), as most
2604  likely 'last' and 'line' should already be adjacent in
2605  memory; however, doing this right gets tricky if we have a
2606  value continued over multiple lines (in which case we need to
2607  record how often we have done this so we can check for
2608  adjacency); also, in the case where these are not adjacent
2609  (not sure how it can happen!), we would want to allocate from
2610  the end of the pool, so as to not destroy the read-buffer's
2611  ability to grow nicely. */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 (connection->suspended)
3405  continue;
3406  if (need_100_continue (connection))
3407  {
3408  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3409  break;
3410  }
3411  if ( (NULL != connection->response) &&
3412  ( (MHD_str_equal_caseless_ (connection->method,
3414  (MHD_str_equal_caseless_ (connection->method,
3415  MHD_HTTP_METHOD_PUT))) )
3416  {
3417  /* we refused (no upload allowed!) */
3418  connection->remaining_upload_size = 0;
3419  /* force close, in case client still tries to upload... */
3420  connection->read_closed = true;
3421  }
3422  connection->state = (0 == connection->remaining_upload_size)
3425  if (connection->suspended)
3426  break;
3427  continue;
3429  if (connection->continue_message_write_offset ==
3431  {
3432  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3433  continue;
3434  }
3435  break;
3437  if (0 != connection->read_buffer_offset)
3438  {
3439  process_request_body (connection); /* loop call */
3440  if (MHD_CONNECTION_CLOSED == connection->state)
3441  continue;
3442  }
3443  if ( (0 == connection->remaining_upload_size) ||
3444  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3445  (0 == connection->read_buffer_offset) &&
3446  (connection->read_closed) ) )
3447  {
3448  if ( (connection->have_chunked_upload) &&
3449  (! connection->read_closed) )
3450  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3451  else
3452  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3453  if (connection->suspended)
3454  break;
3455  continue;
3456  }
3457  break;
3459  line = get_next_header_line (connection,
3460  NULL);
3461  if (NULL == line)
3462  {
3463  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3464  continue;
3465  if (connection->read_closed)
3466  {
3467  CONNECTION_CLOSE_ERROR (connection,
3468  NULL);
3469  continue;
3470  }
3471  break;
3472  }
3473  if (0 == line[0])
3474  {
3475  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3476  if (connection->suspended)
3477  break;
3478  continue;
3479  }
3480  if (MHD_NO == process_header_line (connection,
3481  line))
3482  {
3483  transmit_error_response (connection,
3486  break;
3487  }
3489  continue;
3491  line = get_next_header_line (connection,
3492  NULL);
3493  if (NULL == line)
3494  {
3495  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3496  continue;
3497  if (connection->read_closed)
3498  {
3499  CONNECTION_CLOSE_ERROR (connection,
3500  NULL);
3501  continue;
3502  }
3503  break;
3504  }
3505  if (MHD_NO ==
3506  process_broken_line (connection,
3507  line,
3508  MHD_FOOTER_KIND))
3509  continue;
3510  if (0 == line[0])
3511  {
3512  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3513  if (connection->suspended)
3514  break;
3515  continue;
3516  }
3517  continue;
3519  call_connection_handler (connection); /* "final" call */
3520  if (connection->state == MHD_CONNECTION_CLOSED)
3521  continue;
3522  if (NULL == connection->response)
3523  break; /* try again next time */
3524  if (MHD_NO == build_header_response (connection))
3525  {
3526  /* oops - close! */
3527  CONNECTION_CLOSE_ERROR (connection,
3528  _ (
3529  "Closing connection (failed to create response header)\n"));
3530  continue;
3531  }
3532  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3533  break;
3535  /* no default action */
3536  break;
3538  /* Some clients may take some actions right after header receive */
3539 #ifdef UPGRADE_SUPPORT
3540  if (NULL != connection->response->upgrade_handler)
3541  {
3542  connection->state = MHD_CONNECTION_UPGRADE;
3543  /* This connection is "upgraded". Pass socket to application. */
3544  if (MHD_YES !=
3546  connection))
3547  {
3548  /* upgrade failed, fail hard */
3549  CONNECTION_CLOSE_ERROR (connection,
3550  NULL);
3551  continue;
3552  }
3553  /* Response is not required anymore for this connection. */
3554  {
3555  struct MHD_Response *const resp = connection->response;
3556 
3557  connection->response = NULL;
3558  MHD_destroy_response (resp);
3559  }
3560  continue;
3561  }
3562 #endif /* UPGRADE_SUPPORT */
3563 
3564  if (connection->have_chunked_upload)
3566  else
3568  continue;
3570  /* nothing to do here */
3571  break;
3573 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3574  if (NULL != connection->response->crc)
3575  MHD_mutex_lock_chk_ (&connection->response->mutex);
3576 #endif
3577  if (0 == connection->response->total_size)
3578  {
3579 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3580  if (NULL != connection->response->crc)
3581  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3582 #endif
3583  connection->state = MHD_CONNECTION_BODY_SENT;
3584  continue;
3585  }
3586  if (MHD_YES == try_ready_normal_body (connection))
3587  {
3588 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3589  if (NULL != connection->response->crc)
3590  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3591 #endif
3593  /* Buffering for flushable socket was already enabled*/
3594 
3595  break;
3596  }
3597  /* mutex was already unlocked by "try_ready_normal_body */
3598  /* not ready, no socket action */
3599  break;
3601  /* nothing to do here */
3602  break;
3604 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3605  if (NULL != connection->response->crc)
3606  MHD_mutex_lock_chk_ (&connection->response->mutex);
3607 #endif
3608  if ( (0 == connection->response->total_size) ||
3609  (connection->response_write_position ==
3610  connection->response->total_size) )
3611  {
3612 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3613  if (NULL != connection->response->crc)
3614  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3615 #endif
3616  connection->state = MHD_CONNECTION_BODY_SENT;
3617  continue;
3618  }
3619  if (MHD_YES == try_ready_chunked_body (connection))
3620  {
3621 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3622  if (NULL != connection->response->crc)
3623  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3624 #endif
3626  /* Buffering for flushable socket was already enabled */
3627 
3628  continue;
3629  }
3630  /* mutex was already unlocked by try_ready_chunked_body */
3631  break;
3633  if (MHD_NO == build_header_response (connection))
3634  {
3635  /* oops - close! */
3636  CONNECTION_CLOSE_ERROR (connection,
3637  _ (
3638  "Closing connection (failed to create response header)\n"));
3639  continue;
3640  }
3641  if ( (! connection->have_chunked_upload) ||
3642  (connection->write_buffer_send_offset ==
3643  connection->write_buffer_append_offset) )
3644  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3645  else
3646  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3647  continue;
3649  /* no default action */
3650  break;
3652  if (MHD_HTTP_PROCESSING == connection->responseCode)
3653  {
3654  /* After this type of response, we allow sending another! */
3656  MHD_destroy_response (connection->response);
3657  connection->response = NULL;
3658  /* FIXME: maybe partially reset memory pool? */
3659  continue;
3660  }
3661  MHD_destroy_response (connection->response);
3662  connection->response = NULL;
3663  if ( (NULL != daemon->notify_completed) &&
3664  (connection->client_aware) )
3665  {
3666  daemon->notify_completed (daemon->notify_completed_cls,
3667  connection,
3668  &connection->client_context,
3670  }
3671  connection->client_aware = false;
3672  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3673  (connection->read_closed) )
3674  {
3675  /* have to close for some reason */
3676  MHD_connection_close_ (connection,
3678  MHD_pool_destroy (connection->pool);
3679  connection->pool = NULL;
3680  connection->read_buffer = NULL;
3681  connection->read_buffer_size = 0;
3682  connection->read_buffer_offset = 0;
3683  }
3684  else
3685  {
3686  /* can try to keep-alive */
3687 
3688  connection->version = NULL;
3689  connection->state = MHD_CONNECTION_INIT;
3690  connection->last = NULL;
3691  connection->colon = NULL;
3692  connection->header_size = 0;
3693  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3694  /* Reset the read buffer to the starting size,
3695  preserving the bytes we have already read. */
3696  connection->read_buffer
3697  = MHD_pool_reset (connection->pool,
3698  connection->read_buffer,
3699  connection->read_buffer_offset,
3700  connection->daemon->pool_size / 2);
3701  connection->read_buffer_size
3702  = connection->daemon->pool_size / 2;
3703  }
3704  connection->client_context = NULL;
3705  connection->continue_message_write_offset = 0;
3706  connection->responseCode = 0;
3707  connection->headers_received = NULL;
3708  connection->headers_received_tail = NULL;
3709  connection->response_write_position = 0;
3710  connection->have_chunked_upload = false;
3711  connection->current_chunk_size = 0;
3712  connection->current_chunk_offset = 0;
3713  connection->method = NULL;
3714  connection->url = NULL;
3715  connection->write_buffer = NULL;
3716  connection->write_buffer_size = 0;
3717  connection->write_buffer_send_offset = 0;
3718  connection->write_buffer_append_offset = 0;
3719  continue;
3720  case MHD_CONNECTION_CLOSED:
3721  cleanup_connection (connection);
3722  connection->in_idle = false;
3723  return MHD_NO;
3724 #ifdef UPGRADE_SUPPORT
3725  case MHD_CONNECTION_UPGRADE:
3726  connection->in_idle = false;
3727  return MHD_YES; /* keep open */
3728 #endif /* UPGRADE_SUPPORT */
3729  default:
3730  mhd_assert (0);
3731  break;
3732  }
3733  break;
3734  }
3735  if (! connection->suspended)
3736  {
3737  time_t timeout;
3738  timeout = connection->connection_timeout;
3739  if ( (0 != timeout) &&
3740  (timeout < (MHD_monotonic_sec_counter ()
3741  - connection->last_activity)) )
3742  {
3743  MHD_connection_close_ (connection,
3745  connection->in_idle = false;
3746  return MHD_YES;
3747  }
3748  }
3750  ret = MHD_YES;
3751 #ifdef EPOLL_SUPPORT
3752  if ( (! connection->suspended) &&
3753  (0 != (daemon->options & MHD_USE_EPOLL)) )
3754  {
3755  ret = MHD_connection_epoll_update_ (connection);
3756  }
3757 #endif /* EPOLL_SUPPORT */
3758  connection->in_idle = false;
3759  return ret;
3760 }
3761 
3762 
3763 #ifdef EPOLL_SUPPORT
3764 
3772 int
3773 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3774 {
3775  struct MHD_Daemon *daemon = connection->daemon;
3776 
3777  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3778  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3779  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3780  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3781  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3782  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3783  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3784  {
3785  /* add to epoll set */
3786  struct epoll_event event;
3787 
3788  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3789  event.data.ptr = connection;
3790  if (0 != epoll_ctl (daemon->epoll_fd,
3791  EPOLL_CTL_ADD,
3792  connection->socket_fd,
3793  &event))
3794  {
3795 #ifdef HAVE_MESSAGES
3796  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3797  MHD_DLOG (daemon,
3798  _ ("Call to epoll_ctl failed: %s\n"),
3800 #endif
3801  connection->state = MHD_CONNECTION_CLOSED;
3802  cleanup_connection (connection);
3803  return MHD_NO;
3804  }
3805  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3806  }
3807  return MHD_YES;
3808 }
3809 
3810 
3811 #endif
3812 
3813 
3819 void
3821 {
3822  connection->recv_cls = &recv_param_adapter;
3823  connection->send_cls = &send_param_adapter;
3824 }
3825 
3826 
3837 const union MHD_ConnectionInfo *
3839  enum MHD_ConnectionInfoType info_type,
3840  ...)
3841 {
3842  switch (info_type)
3843  {
3844 #ifdef HTTPS_SUPPORT
3846  if (NULL == connection->tls_session)
3847  return NULL;
3848  connection->cipher = gnutls_cipher_get (connection->tls_session);
3849  return (const union MHD_ConnectionInfo *) &connection->cipher;
3851  if (NULL == connection->tls_session)
3852  return NULL;
3853  connection->protocol = gnutls_protocol_get_version (
3854  connection->tls_session);
3855  return (const union MHD_ConnectionInfo *) &connection->protocol;
3857  if (NULL == connection->tls_session)
3858  return NULL;
3859  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3860 #endif /* HTTPS_SUPPORT */
3862  return (const union MHD_ConnectionInfo *) &connection->addr;
3864  return (const union MHD_ConnectionInfo *) &connection->daemon;
3866  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3868  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3870  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3871  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3873  connection->connection_timeout_dummy = (unsigned
3874  int) connection->connection_timeout;
3875  return (const union MHD_ConnectionInfo *) &connection->
3876  connection_timeout_dummy;
3878  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3879  (MHD_CONNECTION_CLOSED == connection->state) )
3880  return NULL; /* invalid, too early! */
3881  return (const union MHD_ConnectionInfo *) &connection->header_size;
3882  default:
3883  return NULL;
3884  }
3885 }
3886 
3887 
3897 int
3899  enum MHD_CONNECTION_OPTION option,
3900  ...)
3901 {
3902  va_list ap;
3903  struct MHD_Daemon *daemon;
3904 
3905  daemon = connection->daemon;
3906  switch (option)
3907  {
3909  if (0 == connection->connection_timeout)
3910  connection->last_activity = MHD_monotonic_sec_counter ();
3911 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3913 #endif
3914  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3915  (! connection->suspended) )
3916  {
3917  if (connection->connection_timeout == daemon->connection_timeout)
3919  daemon->normal_timeout_tail,
3920  connection);
3921  else
3923  daemon->manual_timeout_tail,
3924  connection);
3925  }
3926  va_start (ap, option);
3927  connection->connection_timeout = va_arg (ap,
3928  unsigned int);
3929  va_end (ap);
3930  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3931  (! connection->suspended) )
3932  {
3933  if (connection->connection_timeout == daemon->connection_timeout)
3935  daemon->normal_timeout_tail,
3936  connection);
3937  else
3939  daemon->manual_timeout_tail,
3940  connection);
3941  }
3942 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3944 #endif
3945  return MHD_YES;
3946  default:
3947  return MHD_NO;
3948  }
3949 }
3950 
3951 
3963 int
3965  unsigned int status_code,
3966  struct MHD_Response *response)
3967 {
3968  struct MHD_Daemon *daemon;
3969 
3970  if ( (NULL == connection) ||
3971  (NULL == response) ||
3972  (NULL != connection->response) ||
3973  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3974  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3975  return MHD_NO;
3976  daemon = connection->daemon;
3977 
3978  if (daemon->shutdown)
3979  return MHD_YES; /* If daemon was shut down in parallel,
3980  * response will be aborted now or on later stage. */
3981 
3982 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3983  if ( (! connection->suspended) &&
3984  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3985  (! MHD_thread_ID_match_current_ (connection->pid.ID)) )
3986  {
3987 #ifdef HAVE_MESSAGES
3988  MHD_DLOG (daemon,
3989  _ ("Attempted to queue response on wrong thread!\n"));
3990 #endif
3991  return MHD_NO;
3992  }
3993 #endif
3994 #ifdef UPGRADE_SUPPORT
3995  if ( (NULL != response->upgrade_handler) &&
3996  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3997  {
3998 #ifdef HAVE_MESSAGES
3999  MHD_DLOG (daemon,
4000  _ (
4001  "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
4002 #endif
4003  return MHD_NO;
4004  }
4005  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
4006  (NULL != response->upgrade_handler) )
4007  {
4008 #ifdef HAVE_MESSAGES
4009  MHD_DLOG (daemon,
4010  _ (
4011  "Application used invalid status code for 'upgrade' response!\n"));
4012 #endif
4013  return MHD_NO;
4014  }
4015 #endif /* UPGRADE_SUPPORT */
4016  MHD_increment_response_rc (response);
4017  connection->response = response;
4018  connection->responseCode = status_code;
4019 #if defined(_MHD_HAVE_SENDFILE)
4020  if ( (response->fd == -1) ||
4021  (0 != (connection->daemon->options & MHD_USE_TLS)) )
4022  connection->resp_sender = MHD_resp_sender_std;
4023  else
4024  connection->resp_sender = MHD_resp_sender_sendfile;
4025 #endif /* _MHD_HAVE_SENDFILE */
4026 
4027  if ( ( (NULL != connection->method) &&
4028  (MHD_str_equal_caseless_ (connection->method,
4029  MHD_HTTP_METHOD_HEAD)) ) ||
4030  (MHD_HTTP_OK > status_code) ||
4031  (MHD_HTTP_NO_CONTENT == status_code) ||
4032  (MHD_HTTP_NOT_MODIFIED == status_code) )
4033  {
4034  /* if this is a "HEAD" request, or a status code for
4035  which a body is not allowed, pretend that we
4036  have already sent the full message body. */
4037  connection->response_write_position = response->total_size;
4038  }
4039  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
4040  (NULL != connection->method) &&
4041  ( (MHD_str_equal_caseless_ (connection->method,
4043  (MHD_str_equal_caseless_ (connection->method,
4044  MHD_HTTP_METHOD_PUT))) )
4045  {
4046  /* response was queued "early", refuse to read body / footers or
4047  further requests! */
4048  connection->read_closed = true;
4049  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4050  }
4051  if (! connection->in_idle)
4052  (void) MHD_connection_handle_idle (connection);
4053  MHD_update_last_activity_ (connection);
4054  return MHD_YES;
4055 }
4056 
4057 
4058 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2522
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: connection.c:244
#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:340
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1976
void * unescape_callback_cls
Definition: internal.h:1417
#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:1941
#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:944
Header for platform missing functions.
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:888
uint64_t current_chunk_offset
Definition: internal.h:958
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:530
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:894
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1713
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:924
void * data
Definition: microhttpd.h:3029
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:959
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:673
uint64_t response_write_position
Definition: internal.h:824
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:731
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:473
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:929
#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:1594
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:421
char * version
Definition: internal.h:724
int suspended_dummy
Definition: internal.h:1017
#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:752
#define MHD_YES
Definition: microhttpd.h:140
#define SIZE_MAX
Definition: mhd_limits.h:99
struct MHD_Response * response
Definition: internal.h:680
char * data
Definition: internal.h:1588
char * colon
Definition: internal.h:761
#define REQUEST_LACKS_HOST
Definition: connection.c:88
char * write_buffer
Definition: internal.h:744
#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:454
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:365
#define MHD_ERR_AGAIN_
Definition: internal.h:1863
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:412
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:190
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:715
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:346
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:1629
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1263
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:643
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2214
uint64_t remaining_upload_size
Definition: internal.h:817
unsigned int responseCode
Definition: internal.h:935
#define MHD_ERR_CONNRESET_
Definition: internal.h:1868
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:1407
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:191
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:811
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
Definition: connection.c:1203
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:631
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1978
#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:849
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:867
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3838
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1090
#define DLL_insert(head, tail, element)
Definition: internal.h:1743
int strict_for_client
Definition: internal.h:1615
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1254
#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:549
size_t data_buffer_size
Definition: internal.h:1664
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3755
size_t write_buffer_send_offset
Definition: internal.h:799
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:393
size_t read_buffer_size
Definition: internal.h:783
void * client_context
Definition: internal.h:698
const char * url
Definition: internal.h:718
size_t continue_message_write_offset
Definition: internal.h:838
#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:692
internal shared structures
enum MHD_HTTP_StatusCode status_code
Definition: internal.h:1669
char * method
Definition: internal.h:712
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
enum MHD_FLAG options
Definition: internal.h:1605
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:1402
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2814
bool in_cleanup
Definition: internal.h:912
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1214
#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:3898
#define _MHD_EXTERN
Definition: mhd_options.h:50
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:611
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:1847
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
#define NULL
Definition: reason_phrase.c:30
char * last
Definition: internal.h:752
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1140
MHD_ValueKind
Definition: microhttpd.h:1757
Header for string manipulating helpers.
Implementation of send() wrappers.
#define DLL_remove(head, tail, element)
Definition: internal.h:1763
char * read_buffer
Definition: internal.h:738
ReceiveCallback recv_cls
Definition: internal.h:706
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:686
size_t value_size
Definition: internal.h:290
size_t write_buffer_size
Definition: internal.h:794
#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:1412
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3964
size_t header_size
Definition: internal.h:280
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
#define XDLL_remove(head, tail, element)
Definition: internal.h:1806
unsigned int connection_timeout_dummy
Definition: internal.h:860
#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:738
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
size_t pool_size
Definition: internal.h:1452
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2493
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:2581
enum MHD_ResponseFlags flags
Definition: internal.h:401
#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:805
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1377
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
#define MHD_BUF_INC_SIZE
Definition: internal.h:120
#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:3820
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:906
void * notify_completed_cls
Definition: internal.h:1382
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2250
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:879
#define MHD_ERR_NOTCONN_
Definition: internal.h:1874
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:301
#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:2102
MHD_mutex_ mutex
Definition: internal.h:1637
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
#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:567
#define MHD_MIN(a, b)
Definition: internal.h:110
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
size_t read_buffer_offset
Definition: internal.h:789
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1881
void * default_handler_cls
Definition: internal.h:1268
#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:634
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:871
uint64_t current_chunk_size
Definition: internal.h:952
struct MHD_HTTP_Header * headers_received
Definition: internal.h:670
#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:501
#define REQUEST_TOO_BIG
Definition: connection.c:74
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:675
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1256
size_t pool_increment
Definition: internal.h:1457
#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:408
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