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