GNU libmicrohttpd  0.9.71
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 
245 int
247  enum MHD_ValueKind kind,
248  MHD_KeyValueIterator iterator,
249  void *iterator_cls)
250 {
251  int ret;
252  struct MHD_HTTP_Header *pos;
253 
254  if (NULL == connection)
255  return -1;
256  ret = 0;
257  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
258  if (0 != (pos->kind & kind))
259  {
260  ret++;
261  if ( (NULL != iterator) &&
262  (MHD_YES != iterator (iterator_cls,
263  pos->kind,
264  pos->header,
265  pos->value)) )
266  return ret;
267  }
268  return ret;
269 }
270 
271 
284 int
286  enum MHD_ValueKind kind,
287  MHD_KeyValueIteratorN iterator,
288  void *iterator_cls)
289 {
290  int ret;
291  struct MHD_HTTP_Header *pos;
292 
293  if (NULL == connection)
294  return -1;
295  ret = 0;
296 
297  if (NULL == iterator)
298  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
299  {
300  if (0 != (kind & pos->kind))
301  ret++;
302  }
303  else
304  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
305  if (0 != (kind & pos->kind))
306  {
307  ret++;
308  if (MHD_NO == iterator (iterator_cls,
309  pos->kind,
310  pos->header,
311  pos->header_size,
312  pos->value,
313  pos->value_size))
314  return ret;
315  }
316  return ret;
317 }
318 
319 
337 static enum MHD_Result
339  enum MHD_ValueKind kind,
340  const char *key,
341  size_t key_size,
342  const char *value,
343  size_t value_size)
344 {
345  struct MHD_HTTP_Header *pos;
346 
347  pos = MHD_pool_allocate (connection->pool,
348  sizeof (struct MHD_HTTP_Header),
349  true);
350  if (NULL == pos)
351  return MHD_NO;
352  pos->header = (char *) key;
353  pos->header_size = key_size;
354  pos->value = (char *) value;
355  pos->value_size = value_size;
356  pos->kind = kind;
357  pos->next = NULL;
358  /* append 'pos' to the linked list of headers */
359  if (NULL == connection->headers_received_tail)
360  {
361  connection->headers_received = pos;
362  connection->headers_received_tail = pos;
363  }
364  else
365  {
366  connection->headers_received_tail->next = pos;
367  connection->headers_received_tail = pos;
368  }
369  return MHD_YES;
370 }
371 
372 
398 enum MHD_Result
400  enum MHD_ValueKind kind,
401  const char *key,
402  size_t key_size,
403  const char *value,
404  size_t value_size)
405 {
406  if ( (MHD_GET_ARGUMENT_KIND != kind) &&
407  ( ((key ? strlen (key) : 0) != key_size) ||
408  ((value ? strlen (value) : 0) != value_size) ) )
409  return MHD_NO; /* binary zero is allowed only in GET arguments */
410 
411  return MHD_set_connection_value_n_nocheck_ (connection,
412  kind,
413  key,
414  key_size,
415  value,
416  value_size);
417 }
418 
419 
445 enum MHD_Result
447  enum MHD_ValueKind kind,
448  const char *key,
449  const char *value)
450 {
451  return MHD_set_connection_value_n_nocheck_ (connection,
452  kind,
453  key,
454  NULL != key
455  ? strlen (key)
456  : 0,
457  value,
458  NULL != value
459  ? strlen (value)
460  : 0);
461 }
462 
463 
474 const char *
476  enum MHD_ValueKind kind,
477  const char *key)
478 {
479  const char *value;
480 
481  value = NULL;
482  (void) MHD_lookup_connection_value_n (connection,
483  kind,
484  key,
485  (NULL == key) ? 0 : strlen (key),
486  &value,
487  NULL);
488  return value;
489 }
490 
491 
513  enum MHD_ValueKind kind,
514  const char *key,
515  size_t key_size,
516  const char **value_ptr,
517  size_t *value_size_ptr)
518 {
519  struct MHD_HTTP_Header *pos;
520 
521  if (NULL == connection)
522  return MHD_NO;
523 
524  if (NULL == key)
525  {
526  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
527  {
528  if ( (0 != (kind & pos->kind)) &&
529  (NULL == pos->header) )
530  break;
531  }
532  }
533  else
534  {
535  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
536  {
537  if ( (0 != (kind & pos->kind)) &&
538  (key_size == pos->header_size) &&
539  ( (key == pos->header) ||
541  pos->header,
542  key_size) ) ) )
543  break;
544  }
545  }
546 
547  if (NULL == pos)
548  return MHD_NO;
549 
550  if (NULL != value_ptr)
551  *value_ptr = pos->value;
552 
553  if (NULL != value_size_ptr)
554  *value_size_ptr = pos->value_size;
555 
556  return MHD_YES;
557 }
558 
559 
575 static bool
576 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
577  const char *header,
578  size_t header_len,
579  const char *token,
580  size_t token_len)
581 {
582  struct MHD_HTTP_Header *pos;
583 
584  if ((NULL == connection) || (NULL == header) || (0 == header[0]) || (NULL ==
585  token) ||
586  (0 ==
587  token
588  [
589  0]) )
590  return false;
591 
592  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
593  {
594  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
595  (header_len == pos->header_size) &&
596  ( (header == pos->header) ||
598  pos->header,
599  header_len)) ) &&
600  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
601  return true;
602  }
603  return false;
604 }
605 
606 
618 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
619  MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
620  (tkn),MHD_STATICSTR_LEN_ (tkn))
621 
622 
630 static bool
631 need_100_continue (struct MHD_Connection *connection)
632 {
633  const char *expect;
634 
635  return ( (NULL != connection->version) &&
636  (MHD_str_equal_caseless_ (connection->version,
638  (MHD_NO != MHD_lookup_connection_value_n (connection,
643  &expect,
644  NULL)) &&
645  (MHD_str_equal_caseless_ (expect,
646  "100-continue")) );
647 }
648 
649 
656 void
658 {
659  const struct MHD_Daemon *daemon = connection->daemon;
660 
661  connection->state = MHD_CONNECTION_CLOSED;
663  if (0 == (daemon->options & MHD_USE_TURBO))
664  {
665 #ifdef HTTPS_SUPPORT
666  /* For TLS connection use shutdown of TLS layer
667  * and do not shutdown TCP socket. This give more
668  * chances to send TLS closure data to remote side.
669  * Closure of TLS layer will be interpreted by
670  * remote side as end of transmission. */if (0 != (daemon->options & MHD_USE_TLS))
671  {
672  if (! MHD_tls_connection_shutdown (connection))
673  shutdown (connection->socket_fd,
674  SHUT_WR);
675  }
676  else /* Combined with next 'shutdown()'. */
677 #endif /* HTTPS_SUPPORT */
678  shutdown (connection->socket_fd,
679  SHUT_WR);
680  }
681 }
682 
683 
693 void
695  enum MHD_RequestTerminationCode termination_code)
696 {
697  struct MHD_Daemon *daemon = connection->daemon;
698  struct MHD_Response *resp = connection->response;
699 
700  MHD_connection_mark_closed_ (connection);
701  if (NULL != resp)
702  {
703  connection->response = NULL;
704  MHD_destroy_response (resp);
705  }
706  if ( (NULL != daemon->notify_completed) &&
707  (connection->client_aware) )
708  daemon->notify_completed (daemon->notify_completed_cls,
709  connection,
710  &connection->client_context,
711  termination_code);
712  connection->client_aware = false;
713 }
714 
715 
716 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
717 
727 void
729 {
730  struct MHD_Daemon *daemon = connection->daemon;
731  struct MHD_UpgradeResponseHandle *urh = connection->urh;
732 
733  if (0 == (daemon->options & MHD_USE_TLS))
734  return; /* Nothing to do with non-TLS connection. */
735 
736  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
737  DLL_remove (daemon->urh_head,
738  daemon->urh_tail,
739  urh);
740 #if EPOLL_SUPPORT
741  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
742  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
743  EPOLL_CTL_DEL,
744  connection->socket_fd,
745  NULL)) )
746  {
747  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
748  }
749  if (urh->in_eready_list)
750  {
751  EDLL_remove (daemon->eready_urh_head,
752  daemon->eready_urh_tail,
753  urh);
754  urh->in_eready_list = false;
755  }
756 #endif /* EPOLL_SUPPORT */
757  if (MHD_INVALID_SOCKET != urh->mhd.socket)
758  {
759 #if EPOLL_SUPPORT
760  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
761  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
762  EPOLL_CTL_DEL,
763  urh->mhd.socket,
764  NULL)) )
765  {
766  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
767  }
768 #endif /* EPOLL_SUPPORT */
769  /* Reflect remote disconnect to application by breaking
770  * socketpair connection. */
771  shutdown (urh->mhd.socket, SHUT_RDWR);
772  }
773  /* Socketpair sockets will remain open as they will be
774  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
775  * closed by MHD_cleanup_upgraded_connection_() during
776  * connection's final cleanup.
777  */}
778 
779 
780 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
781 
782 
790 static void
792  const char *emsg)
793 {
794 #ifdef HAVE_MESSAGES
795  if (NULL != emsg)
796  MHD_DLOG (connection->daemon,
797  emsg);
798 #else /* ! HAVE_MESSAGES */
799  (void) emsg; /* Mute compiler warning. */
800 #endif /* ! HAVE_MESSAGES */
801  MHD_connection_close_ (connection,
803 }
804 
805 
810 #ifdef HAVE_MESSAGES
811 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
812 #else
813 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
814 #endif
815 
816 
829 static enum MHD_Result
831 {
832  ssize_t ret;
833  struct MHD_Response *response;
834 
835  response = connection->response;
836  if (NULL == response->crc)
837  return MHD_YES;
838  if ( (0 == response->total_size) ||
839  (connection->response_write_position == response->total_size) )
840  return MHD_YES; /* 0-byte response is always ready */
841  if ( (response->data_start <=
842  connection->response_write_position) &&
843  (response->data_size + response->data_start >
844  connection->response_write_position) )
845  return MHD_YES; /* response already ready */
846 #if defined(_MHD_HAVE_SENDFILE)
847  if (MHD_resp_sender_sendfile == connection->resp_sender)
848  {
849  /* will use sendfile, no need to bother response crc */
850  return MHD_YES;
851  }
852 #endif /* _MHD_HAVE_SENDFILE */
853 
854  ret = response->crc (response->crc_cls,
855  connection->response_write_position,
856  response->data,
857  (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
858  response->total_size
859  - connection->response_write_position));
860  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
861  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
862  {
863  /* either error or http 1.0 transfer, close socket! */
864  response->total_size = connection->response_write_position;
865 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
866  MHD_mutex_unlock_chk_ (&response->mutex);
867 #endif
868  if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
869  MHD_connection_close_ (connection,
871  else
872  CONNECTION_CLOSE_ERROR (connection,
873  _ (
874  "Closing connection (application reported error generating data).\n"));
875  return MHD_NO;
876  }
877  response->data_start = connection->response_write_position;
878  response->data_size = ret;
879  if (0 == ret)
880  {
882 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
883  MHD_mutex_unlock_chk_ (&response->mutex);
884 #endif
885  return MHD_NO;
886  }
887  return MHD_YES;
888 }
889 
890 
900 static enum MHD_Result
902 {
903  ssize_t ret;
904  struct MHD_Response *response;
905  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
906  int cblen;
907 
908  response = connection->response;
909  if (NULL == response->crc)
910  return MHD_YES;
911  if (0 == connection->write_buffer_size)
912  {
913  size_t size;
914 
915  size = MHD_pool_get_free (connection->pool);
916  if (size < 128)
917  {
918 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
919  MHD_mutex_unlock_chk_ (&response->mutex);
920 #endif
921  /* not enough memory */
922  CONNECTION_CLOSE_ERROR (connection,
923  _ ("Closing connection (out of memory).\n"));
924  return MHD_NO;
925  }
926  if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
927  size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
928  connection->write_buffer = MHD_pool_allocate (connection->pool,
929  size,
930  false);
931  mhd_assert (NULL != connection->write_buffer);
932  connection->write_buffer_size = size;
933  }
934 
935  if (0 == response->total_size)
936  ret = 0; /* response must be empty, don't bother calling crc */
937  else if ( (response->data_start <=
938  connection->response_write_position) &&
939  (response->data_start + response->data_size >
940  connection->response_write_position) )
941  {
942  /* difference between response_write_position and data_start is less
943  than data_size which is size_t type, no need to check for overflow */
944  const size_t data_write_offset
945  = (size_t) (connection->response_write_position - response->data_start);
946  /* buffer already ready, use what is there for the chunk */
947  ret = response->data_size - data_write_offset;
948  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2)
949  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
950  memcpy (&connection->write_buffer[sizeof (cbuf)],
951  &response->data[data_write_offset],
952  ret);
953  }
954  else
955  {
956  /* buffer not in range, try to fill it */
957  ret = response->crc (response->crc_cls,
958  connection->response_write_position,
959  &connection->write_buffer[sizeof (cbuf)],
960  connection->write_buffer_size - sizeof (cbuf) - 2);
961  }
962  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
963  {
964  /* error, close socket! */
965  response->total_size = connection->response_write_position;
966 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
967  MHD_mutex_unlock_chk_ (&response->mutex);
968 #endif
969  CONNECTION_CLOSE_ERROR (connection,
970  _ (
971  "Closing connection (application error generating response).\n"));
972  return MHD_NO;
973  }
974  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
975  (0 == response->total_size) )
976  {
977  /* end of message, signal other side! */
978  memcpy (connection->write_buffer,
979  "0\r\n",
980  3);
981  connection->write_buffer_append_offset = 3;
982  connection->write_buffer_send_offset = 0;
983  response->total_size = connection->response_write_position;
984  return MHD_YES;
985  }
986  if (0 == ret)
987  {
989 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
990  MHD_mutex_unlock_chk_ (&response->mutex);
991 #endif
992  return MHD_NO;
993  }
994  if (ret > 0xFFFFFF)
995  ret = 0xFFFFFF;
996  cblen = MHD_snprintf_ (cbuf,
997  sizeof (cbuf),
998  "%X\r\n",
999  (unsigned int) ret);
1000  mhd_assert (cblen > 0);
1001  mhd_assert ((size_t) cblen < sizeof(cbuf));
1002  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1003  cbuf,
1004  cblen);
1005  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1006  "\r\n",
1007  2);
1008  connection->response_write_position += ret;
1009  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1010  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1011  return MHD_YES;
1012 }
1013 
1014 
1031 static enum MHD_Result
1033 {
1034  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1035  return MHD_NO;
1036  if (NULL == connection->version)
1037  return MHD_NO;
1038  if ( (NULL != connection->response) &&
1039  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1040  return MHD_NO;
1041 
1042  if (MHD_str_equal_caseless_ (connection->version,
1044  ( (NULL == connection->response) ||
1045  (0 == (connection->response->flags
1047  {
1048  if (MHD_lookup_header_s_token_ci (connection,
1050  "upgrade"))
1051  return MHD_NO;
1052 
1053  if (MHD_lookup_header_s_token_ci (connection,
1055  "close"))
1056  return MHD_NO;
1057 
1058  return MHD_YES;
1059  }
1060  if (MHD_str_equal_caseless_ (connection->version,
1062  {
1063  if (MHD_lookup_header_s_token_ci (connection,
1065  "Keep-Alive"))
1066  return MHD_YES;
1067 
1068  return MHD_NO;
1069  }
1070  return MHD_NO;
1071 }
1072 
1073 
1081 static void
1082 get_date_string (char *date,
1083  size_t date_len)
1084 {
1085  static const char *const days[] = {
1086  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1087  };
1088  static const char *const mons[] = {
1089  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1090  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1091  };
1092  struct tm now;
1093  time_t t;
1094 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1095  ! defined(HAVE_GMTIME_R)
1096  struct tm*pNow;
1097 #endif
1098 
1099  date[0] = 0;
1100  time (&t);
1101 #if defined(HAVE_C11_GMTIME_S)
1102  if (NULL == gmtime_s (&t,
1103  &now))
1104  return;
1105 #elif defined(HAVE_W32_GMTIME_S)
1106  if (0 != gmtime_s (&now,
1107  &t))
1108  return;
1109 #elif defined(HAVE_GMTIME_R)
1110  if (NULL == gmtime_r (&t,
1111  &now))
1112  return;
1113 #else
1114  pNow = gmtime (&t);
1115  if (NULL == pNow)
1116  return;
1117  now = *pNow;
1118 #endif
1119  MHD_snprintf_ (date,
1120  date_len,
1121  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1122  days[now.tm_wday % 7],
1123  (unsigned int) now.tm_mday,
1124  mons[now.tm_mon % 12],
1125  (unsigned int) (1900 + now.tm_year),
1126  (unsigned int) now.tm_hour,
1127  (unsigned int) now.tm_min,
1128  (unsigned int) now.tm_sec);
1129 }
1130 
1131 
1144 static bool
1146  bool required)
1147 {
1148  size_t new_size;
1149  size_t avail_size;
1150 
1151  avail_size = MHD_pool_get_free (connection->pool);
1152  if (0 == avail_size)
1153  return false; /* No more space available */
1154  if (0 == connection->read_buffer_size)
1155  new_size = avail_size / 2; /* Use half of available buffer for reading */
1156  else
1157  {
1158  size_t grow_size;
1159 
1160  grow_size = avail_size / 8;
1161  if (MHD_BUF_INC_SIZE > grow_size)
1162  { /* Shortage of space */
1163  if (! required)
1164  return false; /* Grow is not mandatory, leave some space in pool */
1165  else
1166  {
1167  /* Shortage of space, but grow is mandatory */
1168  static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
1169  if (small_inc < avail_size)
1170  grow_size = small_inc;
1171  else
1172  grow_size = avail_size;
1173  }
1174  }
1175  new_size = connection->read_buffer_size + grow_size;
1176  }
1177  /* we can actually grow the buffer, do it! */
1178  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1179  connection->read_buffer,
1180  connection->read_buffer_size,
1181  new_size);
1182  mhd_assert (NULL != connection->read_buffer);
1183  connection->read_buffer_size = new_size;
1184  return true;
1185 }
1186 
1187 
1197 static enum MHD_Result
1199 {
1200  struct MHD_Response *response = connection->response;
1201  size_t size;
1202  size_t off;
1203  struct MHD_HTTP_Header *pos;
1204  char code[256];
1205  char date[128];
1206  size_t datelen;
1207  char content_length_buf[128];
1208  size_t content_length_len;
1209  char *data;
1210  enum MHD_ValueKind kind;
1211  const char *reason_phrase;
1212  uint32_t rc;
1213  bool client_requested_close;
1214  bool response_has_close;
1215  bool response_has_keepalive;
1216  const char *have_encoding;
1217  bool must_add_close;
1218  bool must_add_chunked_encoding;
1219  bool must_add_keep_alive;
1220  bool must_add_content_length;
1221  bool may_add_content_length;
1222 
1223  mhd_assert (NULL != connection->version);
1224  if (0 == connection->version[0])
1225  {
1226  data = MHD_pool_allocate (connection->pool,
1227  0,
1228  true);
1229  connection->write_buffer = data;
1230  connection->write_buffer_append_offset = 0;
1231  connection->write_buffer_send_offset = 0;
1232  connection->write_buffer_size = 0;
1233  return MHD_YES;
1234  }
1235  rc = connection->responseCode & (~MHD_ICY_FLAG);
1236  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1237  {
1238  reason_phrase = MHD_get_reason_phrase_for (rc);
1239  off = MHD_snprintf_ (code,
1240  sizeof (code),
1241  "%s %u %s\r\n",
1242  (0 != (connection->responseCode & MHD_ICY_FLAG))
1243  ? "ICY"
1245  connection->version) ||
1246  (0 != (connection->response->flags
1250  rc,
1251  reason_phrase);
1252  /* estimate size */
1253  size = off + 2; /* +2 for extra "\r\n" at the end */
1255  if ( (0 == (connection->daemon->options
1257  (NULL == MHD_get_response_header (response,
1259  get_date_string (date,
1260  sizeof (date));
1261  else
1262  date[0] = '\0';
1263  datelen = strlen (date);
1264  size += datelen;
1265  }
1266  else
1267  {
1268  /* 2 bytes for final CRLF of a Chunked-Body */
1269  size = 2;
1271  off = 0;
1272  datelen = 0;
1273  }
1274 
1275  /* calculate extra headers we need to add, such as 'Connection: close',
1276  first see what was explicitly requested by the application */
1277  must_add_close = false;
1278  must_add_chunked_encoding = false;
1279  must_add_keep_alive = false;
1280  must_add_content_length = false;
1281  response_has_close = false;
1282  switch (connection->state)
1283  {
1285  response_has_close = MHD_check_response_header_s_token_ci (response,
1287  "close");
1288  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1290  "Keep-Alive");
1291  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1293  "close");
1294 
1295  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1296  connection->keepalive = MHD_CONN_MUST_CLOSE;
1297 #ifdef UPGRADE_SUPPORT
1298  else if (NULL != response->upgrade_handler)
1299  /* If this connection will not be "upgraded", it must be closed. */
1300  connection->keepalive = MHD_CONN_MUST_CLOSE;
1301 #endif /* UPGRADE_SUPPORT */
1302 
1303  /* now analyze chunked encoding situation */
1304  connection->have_chunked_upload = false;
1305  have_encoding = MHD_get_response_header (response,
1307  if (NULL == have_encoding)
1308  may_add_content_length = true;
1309  else
1310  may_add_content_length = false; /* RFC 7230, Section 3.3.2 forbids header */
1311  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1312 #ifdef UPGRADE_SUPPORT
1313  (NULL == response->upgrade_handler) &&
1314 #endif /* UPGRADE_SUPPORT */
1315  (! response_has_close) &&
1316  (! client_requested_close) )
1317  {
1318  /* size is unknown, and close was not explicitly requested;
1319  need to either to HTTP 1.1 chunked encoding or
1320  close the connection */
1321  /* 'close' header doesn't exist yet, see if we need to add one;
1322  if the client asked for a close, no need to start chunk'ing */
1323  if ( (MHD_YES == keepalive_possible (connection)) &&
1325  connection->version) ) )
1326  {
1327  if (NULL == have_encoding)
1328  {
1329  must_add_chunked_encoding = true;
1330  connection->have_chunked_upload = true;
1331  }
1332  else
1333  {
1334  if (MHD_str_equal_caseless_ (have_encoding,
1335  "identity"))
1336  {
1337  /* application forced identity encoding, can't do 'chunked' */
1338  must_add_close = true;
1339  }
1340  else
1341  {
1342  connection->have_chunked_upload = true;
1343  }
1344  }
1345  }
1346  else
1347  {
1348  /* Keep alive or chunking not possible
1349  => set close header (we know response_has_close
1350  is false here) */
1351  must_add_close = true;
1352  }
1353  }
1354 
1355  /* check for other reasons to add 'close' header */
1356  if ( ( (client_requested_close) ||
1357  (connection->read_closed) ||
1358  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1359  (! response_has_close) &&
1360 #ifdef UPGRADE_SUPPORT
1361  (NULL == response->upgrade_handler) &&
1362 #endif /* UPGRADE_SUPPORT */
1363  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1364  must_add_close = true;
1365 
1366  /* check if we must add 'close' header because we cannot add content-length
1367  because it is forbidden AND we don't have a 'chunked' encoding */
1368  if ( (! may_add_content_length) &&
1369  (! connection->have_chunked_upload) &&
1370  (! response_has_close) )
1371  must_add_close = true;
1372  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1373  codes SHOULD NOT have a Content-Length according to spec;
1374  also chunked encoding / unknown length or CONNECT... */
1375  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1376  (MHD_HTTP_NO_CONTENT != rc) &&
1377  (MHD_HTTP_NOT_MODIFIED != rc) &&
1378  (MHD_HTTP_OK <= rc) &&
1379  (NULL == /* this COULD fail if the check in
1380  MHD_add_response_header() was bypassed
1381  via #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH */
1382  MHD_get_response_header (response,
1384  (may_add_content_length) &&
1385  ( (NULL == connection->method) ||
1386  (! MHD_str_equal_caseless_ (connection->method,
1388  {
1389  /*
1390  Here we add a content-length if one is missing; however,
1391  for 'connect' methods, the responses MUST NOT include a
1392  content-length header *if* the response code is 2xx (in
1393  which case we expect there to be no body). Still,
1394  as we don't know the response code here in some cases, we
1395  simply only force adding a content-length header if this
1396  is not a 'connect' or if the response is not empty
1397  (which is kind of more sane, because if some crazy
1398  application did return content with a 2xx status code,
1399  then having a content-length might again be a good idea).
1400 
1401  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1402  a recent development of the HTTP 1.1 specification.
1403  */content_length_len
1404  = MHD_snprintf_ (content_length_buf,
1405  sizeof (content_length_buf),
1408  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1409  must_add_content_length = true;
1410  }
1411 
1412  /* check for adding keep alive */
1413  if ( (! response_has_keepalive) &&
1414  (! response_has_close) &&
1415  (! must_add_close) &&
1416  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1417 #ifdef UPGRADE_SUPPORT
1418  (NULL == response->upgrade_handler) &&
1419 #endif /* UPGRADE_SUPPORT */
1420  (MHD_YES == keepalive_possible (connection)) )
1421  must_add_keep_alive = true;
1422  break;
1424  response_has_keepalive = false;
1425  break;
1426  default:
1427  mhd_assert (0);
1428  return MHD_NO;
1429  }
1430 
1431  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1432  {
1433  if ( (must_add_close) || (response_has_close) )
1434  connection->keepalive = MHD_CONN_MUST_CLOSE;
1435  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1436  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1437  }
1438 
1439  if (must_add_close)
1440  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1441  if (must_add_keep_alive)
1442  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1443  if (must_add_chunked_encoding)
1444  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1445  if (must_add_content_length)
1446  size += content_length_len;
1447  mhd_assert (! (must_add_close && must_add_keep_alive) );
1448  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1449 
1450  for (pos = response->first_header; NULL != pos; pos = pos->next)
1451  {
1452  /* TODO: add proper support for excluding "Keep-Alive" token. */
1453  if ( (pos->kind == kind) &&
1454  (! ( (must_add_close) &&
1455  (response_has_keepalive) &&
1456  (pos->header_size == MHD_STATICSTR_LEN_ (
1463  "Keep-Alive")) ) ) )
1464  size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */
1465  }
1466  /* produce data */
1467  data = MHD_pool_allocate (connection->pool,
1468  size + 1,
1469  false);
1470  if (NULL == data)
1471  {
1472 #ifdef HAVE_MESSAGES
1473  MHD_DLOG (connection->daemon,
1474  "Not enough memory for write!\n");
1475 #endif
1476  return MHD_NO;
1477  }
1478  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1479  {
1480  memcpy (data,
1481  code,
1482  off);
1483  }
1484  if (must_add_close)
1485  {
1486  /* we must add the 'Connection: close' header */
1487  memcpy (&data[off],
1488  "Connection: close\r\n",
1489  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1490  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1491  }
1492  if (must_add_keep_alive)
1493  {
1494  /* we must add the 'Connection: Keep-Alive' header */
1495  memcpy (&data[off],
1496  "Connection: Keep-Alive\r\n",
1497  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1498  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1499  }
1500  if (must_add_chunked_encoding)
1501  {
1502  /* we must add the 'Transfer-Encoding: chunked' header */
1503  memcpy (&data[off],
1504  "Transfer-Encoding: chunked\r\n",
1505  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1506  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1507  }
1508  if (must_add_content_length)
1509  {
1510  /* we must add the 'Content-Length' header */
1511  memcpy (&data[off],
1512  content_length_buf,
1513  content_length_len);
1514  off += content_length_len;
1515  }
1516  for (pos = response->first_header; NULL != pos; pos = pos->next)
1517  {
1518  /* TODO: add proper support for excluding "Keep-Alive" token. */
1519  if ( (pos->kind == kind) &&
1520  (! ( (must_add_close) &&
1521  (response_has_keepalive) &&
1522  (pos->header_size == MHD_STATICSTR_LEN_ (
1529  "Keep-Alive")) ) ) )
1530  off += MHD_snprintf_ (&data[off],
1531  size - off,
1532  "%s: %s\r\n",
1533  pos->header,
1534  pos->value);
1535  }
1536  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1537  {
1538  memcpy (&data[off],
1539  date,
1540  datelen);
1541  off += datelen;
1542  }
1543  memcpy (&data[off],
1544  "\r\n",
1545  2);
1546  off += 2;
1547 
1548  if (off != size)
1550  __FILE__,
1551  __LINE__,
1552  NULL);
1553  connection->write_buffer = data;
1554  connection->write_buffer_append_offset = size;
1555  connection->write_buffer_send_offset = 0;
1556  connection->write_buffer_size = size + 1;
1557  return MHD_YES;
1558 }
1559 
1560 
1570 static void
1572  unsigned int status_code,
1573  const char *message)
1574 {
1575  struct MHD_Response *response;
1576  enum MHD_Result iret;
1577 
1578  if (NULL == connection->version)
1579  {
1580  /* we were unable to process the full header line, so we don't
1581  really know what version the client speaks; assume 1.0 */
1582  connection->version = MHD_HTTP_VERSION_1_0;
1583  }
1584  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1585  connection->read_closed = true;
1586  if (0 != connection->read_buffer_size)
1587  {
1588  /* Read buffer is not needed anymore, discard it
1589  * to free some space for error response. */
1590  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1591  connection->read_buffer,
1592  connection->read_buffer_size,
1593  0);
1594  connection->read_buffer_size = 0;
1595  }
1596 #ifdef HAVE_MESSAGES
1597  MHD_DLOG (connection->daemon,
1598  _ (
1599  "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1600  status_code,
1601  message);
1602 #endif
1603  if (NULL != connection->response)
1604  {
1605  MHD_destroy_response (connection->response);
1606  connection->response = NULL;
1607  }
1608  response = MHD_create_response_from_buffer (strlen (message),
1609  (void *) message,
1611  if (NULL == response)
1612  {
1613  /* can't even send a reply, at least close the connection */
1614  connection->state = MHD_CONNECTION_CLOSED;
1615  return;
1616  }
1617  iret = MHD_queue_response (connection,
1618  status_code,
1619  response);
1620  MHD_destroy_response (response);
1621  if (MHD_YES != iret)
1622  {
1623  /* can't even send a reply, at least close the connection */
1624  CONNECTION_CLOSE_ERROR (connection,
1625  _ (
1626  "Closing connection (failed to queue response).\n"));
1627  return;
1628  }
1629  mhd_assert (NULL != connection->response);
1630  /* Do not reuse this connection. */
1631  connection->keepalive = MHD_CONN_MUST_CLOSE;
1632  if (MHD_NO == build_header_response (connection))
1633  {
1634  /* oops - close! */
1635  CONNECTION_CLOSE_ERROR (connection,
1636  _ (
1637  "Closing connection (failed to create response header).\n"));
1638  }
1639  else
1640  {
1641  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1642  }
1643 }
1644 
1645 
1654 static void
1656 {
1657  /* Do not update states of suspended connection */
1658  if (connection->suspended)
1659  return; /* States will be updated after resume. */
1660 #ifdef HTTPS_SUPPORT
1661  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1662  { /* HTTPS connection. */
1663  switch (connection->tls_state)
1664  {
1665  case MHD_TLS_CONN_INIT:
1667  return;
1669  if (0 == gnutls_record_get_direction (connection->tls_session))
1671  else
1673  return;
1674  default:
1675  break;
1676  }
1677  }
1678 #endif /* HTTPS_SUPPORT */
1679  while (1)
1680  {
1681 #if DEBUG_STATES
1682  MHD_DLOG (connection->daemon,
1683  _ ("In function %s handling connection at state: %s\n"),
1684  __FUNCTION__,
1685  MHD_state_to_string (connection->state));
1686 #endif
1687  switch (connection->state)
1688  {
1689  case MHD_CONNECTION_INIT:
1692  /* while reading headers, we always grow the
1693  read buffer if needed, no size-check required */
1694  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1695  (! try_grow_read_buffer (connection, true)) )
1696  {
1697  transmit_error_response (connection,
1698  (connection->url != NULL)
1701  REQUEST_TOO_BIG);
1702  continue;
1703  }
1704  if (! connection->read_closed)
1706  else
1708  break;
1710  mhd_assert (0);
1711  break;
1713  mhd_assert (0);
1714  break;
1717  break;
1719  if (connection->read_buffer_offset == connection->read_buffer_size)
1720  {
1721  const bool internal_poll = (0 != (connection->daemon->options
1723  if ( (! try_grow_read_buffer (connection, true)) &&
1724  internal_poll)
1725  {
1726  /* failed to grow the read buffer, and the
1727  client which is supposed to handle the
1728  received data in a *blocking* fashion
1729  (in this mode) did not handle the data as
1730  it was supposed to!
1731  => we would either have to do busy-waiting
1732  (on the client, which would likely fail),
1733  or if we do nothing, we would just timeout
1734  on the connection (if a timeout is even
1735  set!).
1736  Solution: we kill the connection with an error */transmit_error_response (connection,
1738  INTERNAL_ERROR);
1739  continue;
1740  }
1741  }
1742  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1743  (! connection->read_closed) )
1745  else
1747  break;
1750  /* while reading footers, we always grow the
1751  read buffer if needed, no size-check required */
1752  if (connection->read_closed)
1753  {
1754  CONNECTION_CLOSE_ERROR (connection,
1755  NULL);
1756  continue;
1757  }
1759  /* transition to FOOTERS_RECEIVED
1760  happens in read handler */
1761  break;
1764  break;
1766  /* headers in buffer, keep writing */
1768  break;
1770  mhd_assert (0);
1771  break;
1774  break;
1777  break;
1780  break;
1783  break;
1785  mhd_assert (0);
1786  break;
1789  break;
1791  mhd_assert (0);
1792  break;
1793  case MHD_CONNECTION_CLOSED:
1795  return; /* do nothing, not even reading */
1796 #ifdef UPGRADE_SUPPORT
1797  case MHD_CONNECTION_UPGRADE:
1798  mhd_assert (0);
1799  break;
1800 #endif /* UPGRADE_SUPPORT */
1801  default:
1802  mhd_assert (0);
1803  }
1804  break;
1805  }
1806 }
1807 
1808 
1822 static char *
1824  size_t *line_len)
1825 {
1826  char *rbuf;
1827  size_t pos;
1828 
1829  if (0 == connection->read_buffer_offset)
1830  return NULL;
1831  pos = 0;
1832  rbuf = connection->read_buffer;
1833  while ( (pos < connection->read_buffer_offset - 1) &&
1834  ('\r' != rbuf[pos]) &&
1835  ('\n' != rbuf[pos]) )
1836  pos++;
1837  if ( (pos == connection->read_buffer_offset - 1) &&
1838  ('\n' != rbuf[pos]) )
1839  {
1840  /* not found, consider growing... */
1841  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1842  (! try_grow_read_buffer (connection, true)) )
1843  {
1844  transmit_error_response (connection,
1845  (NULL != connection->url)
1848  REQUEST_TOO_BIG);
1849  }
1850  if (line_len)
1851  *line_len = 0;
1852  return NULL;
1853  }
1854 
1855  if (line_len)
1856  *line_len = pos;
1857  /* found, check if we have proper LFCR */
1858  if ( ('\r' == rbuf[pos]) &&
1859  ('\n' == rbuf[pos + 1]) )
1860  rbuf[pos++] = '\0'; /* skip both r and n */
1861  rbuf[pos++] = '\0';
1862  connection->read_buffer += pos;
1863  connection->read_buffer_size -= pos;
1864  connection->read_buffer_offset -= pos;
1865  return rbuf;
1866 }
1867 
1868 
1882 static enum MHD_Result
1884  const char *key,
1885  size_t key_size,
1886  const char *value,
1887  size_t value_size,
1888  enum MHD_ValueKind kind)
1889 {
1890  if (MHD_NO ==
1891  MHD_set_connection_value_n (connection,
1892  kind,
1893  key,
1894  key_size,
1895  value,
1896  value_size))
1897  {
1898 #ifdef HAVE_MESSAGES
1899  MHD_DLOG (connection->daemon,
1900  _ ("Not enough memory in pool to allocate header record!\n"));
1901 #endif
1902  transmit_error_response (connection,
1904  REQUEST_TOO_BIG);
1905  return MHD_NO;
1906  }
1907  return MHD_YES;
1908 }
1909 
1910 
1917 static enum MHD_Result
1919 {
1920  const char *hdr;
1921  size_t hdr_len;
1922  char *cpy;
1923  char *pos;
1924  char *sce;
1925  char *semicolon;
1926  char *equals;
1927  char *ekill;
1928  char *end;
1929  char old;
1930  int quotes;
1931 
1932  if (MHD_NO == MHD_lookup_connection_value_n (connection,
1937  &hdr,
1938  &hdr_len))
1939  return MHD_YES;
1940  cpy = MHD_pool_allocate (connection->pool,
1941  hdr_len + 1,
1942  true);
1943  if (NULL == cpy)
1944  {
1945 #ifdef HAVE_MESSAGES
1946  MHD_DLOG (connection->daemon,
1947  _ ("Not enough memory in pool to parse cookies!\n"));
1948 #endif
1949  transmit_error_response (connection,
1951  REQUEST_TOO_BIG);
1952  return MHD_NO;
1953  }
1954  memcpy (cpy,
1955  hdr,
1956  hdr_len);
1957  cpy[hdr_len] = '\0';
1958  pos = cpy;
1959  while (NULL != pos)
1960  {
1961  while (' ' == *pos)
1962  pos++; /* skip spaces */
1963 
1964  sce = pos;
1965  while ( ((*sce) != '\0') &&
1966  ((*sce) != ',') &&
1967  ((*sce) != ';') &&
1968  ((*sce) != '=') )
1969  sce++;
1970  /* remove tailing whitespace (if any) from key */
1971  ekill = sce - 1;
1972  while ( (*ekill == ' ') &&
1973  (ekill >= pos) )
1974  *(ekill--) = '\0';
1975  old = *sce;
1976  *sce = '\0';
1977  if (old != '=')
1978  {
1979  /* value part omitted, use empty string... */
1980  if (MHD_NO ==
1981  connection_add_header (connection,
1982  pos,
1983  ekill - pos + 1,
1984  "",
1985  0,
1986  MHD_COOKIE_KIND))
1987  return MHD_NO;
1988  if (old == '\0')
1989  break;
1990  pos = sce + 1;
1991  continue;
1992  }
1993  equals = sce + 1;
1994  quotes = 0;
1995  semicolon = equals;
1996  while ( ('\0' != semicolon[0]) &&
1997  ( (0 != quotes) ||
1998  ( (';' != semicolon[0]) &&
1999  (',' != semicolon[0]) ) ) )
2000  {
2001  if ('"' == semicolon[0])
2002  quotes = (quotes + 1) & 1;
2003  semicolon++;
2004  }
2005  end = semicolon;
2006  if ('\0' == semicolon[0])
2007  semicolon = NULL;
2008  if (NULL != semicolon)
2009  {
2010  semicolon[0] = '\0';
2011  semicolon++;
2012  }
2013  /* remove quotes */
2014  if ( ('"' == equals[0]) &&
2015  ('"' == end[-1]) )
2016  {
2017  equals++;
2018  end--;
2019  *end = '\0';
2020  }
2021  if (MHD_NO ==
2022  connection_add_header (connection,
2023  pos,
2024  ekill - pos + 1,
2025  equals,
2026  end - equals,
2027  MHD_COOKIE_KIND))
2028  return MHD_NO;
2029  pos = semicolon;
2030  }
2031  return MHD_YES;
2032 }
2033 
2034 
2043 static enum MHD_Result
2045  char *line,
2046  size_t line_len)
2047 {
2048  struct MHD_Daemon *daemon = connection->daemon;
2049  const char *curi;
2050  char *uri;
2051  char *http_version;
2052  char *args;
2053  unsigned int unused_num_headers;
2054 
2055  if (NULL == (uri = memchr (line,
2056  ' ',
2057  line_len)))
2058  return MHD_NO; /* serious error */
2059  uri[0] = '\0';
2060  connection->method = line;
2061  uri++;
2062  /* Skip any spaces. Not required by standard but allow
2063  to be more tolerant. */
2064  while ( (' ' == uri[0]) &&
2065  ( (size_t) (uri - line) < line_len) )
2066  uri++;
2067  if ((size_t) (uri - line) == line_len)
2068  {
2069  /* No URI and no http version given */
2070  curi = "";
2071  uri = NULL;
2072  connection->version = "";
2073  args = NULL;
2074  }
2075  else
2076  {
2077  size_t uri_len;
2078  curi = uri;
2079  /* Search from back to accept misformed URI with space */
2080  http_version = line + line_len - 1;
2081  /* Skip any trailing spaces */
2082  while ( (' ' == http_version[0]) &&
2083  (http_version > uri) )
2084  http_version--;
2085  /* Find first space in reverse direction */
2086  while ( (' ' != http_version[0]) &&
2087  (http_version > uri) )
2088  http_version--;
2089  if (http_version > uri)
2090  {
2091  /* http_version points to character before HTTP version string */
2092  http_version[0] = '\0';
2093  connection->version = http_version + 1;
2094  uri_len = http_version - uri;
2095  }
2096  else
2097  {
2098  connection->version = "";
2099  uri_len = line_len - (uri - line);
2100  }
2101  /* check for spaces in URI if we are "strict" */
2102  if ( (1 <= daemon->strict_for_client) &&
2103  (NULL != memchr (uri,
2104  ' ',
2105  uri_len)) )
2106  {
2107  /* space exists in URI and we are supposed to be strict, reject */
2108  return MHD_NO;
2109  }
2110 
2111  args = memchr (uri,
2112  '?',
2113  uri_len);
2114  }
2115 
2116  /* log callback before we modify URI *or* args */
2117  if (NULL != daemon->uri_log_callback)
2118  {
2119  connection->client_aware = true;
2120  connection->client_context
2121  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2122  uri,
2123  connection);
2124  }
2125 
2126  if (NULL != args)
2127  {
2128  args[0] = '\0';
2129  args++;
2130  /* note that this call clobbers 'args' */
2131  MHD_parse_arguments_ (connection,
2133  args,
2135  &unused_num_headers);
2136  }
2137 
2138  /* unescape URI *after* searching for arguments and log callback */
2139  if (NULL != uri)
2140  daemon->unescape_callback (daemon->unescape_callback_cls,
2141  connection,
2142  uri);
2143  connection->url = curi;
2144  return MHD_YES;
2145 }
2146 
2147 
2155 static void
2157 {
2158  struct MHD_Daemon *daemon = connection->daemon;
2159  size_t processed;
2160 
2161  if (NULL != connection->response)
2162  return; /* already queued a response */
2163  processed = 0;
2164  connection->client_aware = true;
2165  if (MHD_NO ==
2166  daemon->default_handler (daemon->default_handler_cls,
2167  connection,
2168  connection->url,
2169  connection->method,
2170  connection->version,
2171  NULL,
2172  &processed,
2173  &connection->client_context))
2174  {
2175  /* serious internal error, close connection */
2176  CONNECTION_CLOSE_ERROR (connection,
2177  _ (
2178  "Application reported internal error, closing connection.\n"));
2179  return;
2180  }
2181 }
2182 
2183 
2191 static void
2193 {
2194  struct MHD_Daemon *daemon = connection->daemon;
2195  size_t available;
2196  int instant_retry;
2197  char *buffer_head;
2198 
2199  if (NULL != connection->response)
2200  {
2201  /* already queued a response, discard remaining upload
2202  (but not more, there might be another request after it) */
2203  uint64_t purge = MHD_MIN (connection->remaining_upload_size,
2204  connection->read_buffer_offset);
2205  connection->remaining_upload_size -= purge;
2206  if (connection->read_buffer_offset > purge)
2207  memmove (connection->read_buffer,
2208  &connection->read_buffer[purge],
2209  connection->read_buffer_offset - purge);
2210  connection->read_buffer_offset -= purge;
2211  return;
2212  }
2213 
2214  buffer_head = connection->read_buffer;
2215  available = connection->read_buffer_offset;
2216  do
2217  {
2218  size_t to_be_processed;
2219  size_t left_unprocessed;
2220  size_t processed_size;
2221 
2222  instant_retry = MHD_NO;
2223  if ( (connection->have_chunked_upload) &&
2224  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2225  {
2226  if ( (connection->current_chunk_offset ==
2227  connection->current_chunk_size) &&
2228  (0LLU != connection->current_chunk_offset) &&
2229  (available >= 2) )
2230  {
2231  size_t i;
2232  /* skip new line at the *end* of a chunk */
2233  i = 0;
2234  if ( ('\r' == buffer_head[i]) ||
2235  ('\n' == buffer_head[i]) )
2236  i++; /* skip 1st part of line feed */
2237  if ( ('\r' == buffer_head[i]) ||
2238  ('\n' == buffer_head[i]) )
2239  i++; /* skip 2nd part of line feed */
2240  if (0 == i)
2241  {
2242  /* malformed encoding */
2243  CONNECTION_CLOSE_ERROR (connection,
2244  _ (
2245  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2246  return;
2247  }
2248  available -= i;
2249  buffer_head += i;
2250  connection->current_chunk_offset = 0;
2251  connection->current_chunk_size = 0;
2252  }
2253  if (connection->current_chunk_offset <
2254  connection->current_chunk_size)
2255  {
2256  uint64_t cur_chunk_left;
2257  /* we are in the middle of a chunk, give
2258  as much as possible to the client (without
2259  crossing chunk boundaries) */
2260  cur_chunk_left
2261  = connection->current_chunk_size - connection->current_chunk_offset;
2262  if (cur_chunk_left > available)
2263  to_be_processed = available;
2264  else
2265  { /* cur_chunk_left <= (size_t)available */
2266  to_be_processed = (size_t) cur_chunk_left;
2267  if (available > to_be_processed)
2268  instant_retry = MHD_YES;
2269  }
2270  }
2271  else
2272  {
2273  size_t i;
2274  size_t end_size;
2275  bool malformed;
2276 
2277  /* we need to read chunk boundaries */
2278  i = 0;
2279  while (i < available)
2280  {
2281  if ( ('\r' == buffer_head[i]) ||
2282  ('\n' == buffer_head[i]) ||
2283  (';' == buffer_head[i]) )
2284  break;
2285  i++;
2286  if (i >= 16)
2287  break;
2288  }
2289  end_size = i;
2290  /* find beginning of CRLF (skip over chunk extensions) */
2291  if (';' == buffer_head[i])
2292  {
2293  while (i < available)
2294  {
2295  if ( ('\r' == buffer_head[i]) ||
2296  ('\n' == buffer_head[i]) )
2297  break;
2298  i++;
2299  }
2300  }
2301  /* take '\n' into account; if '\n' is the unavailable
2302  character, we will need to wait until we have it
2303  before going further */
2304  if ( (i + 1 >= available) &&
2305  ! ( (1 == i) &&
2306  (2 == available) &&
2307  ('0' == buffer_head[0]) ) )
2308  break; /* need more data... */
2309  i++;
2310  malformed = (end_size >= 16);
2311  if (! malformed)
2312  {
2313  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2314  end_size,
2315  &connection->
2316  current_chunk_size);
2317  malformed = (end_size != num_dig);
2318  }
2319  if (malformed)
2320  {
2321  /* malformed encoding */
2322  CONNECTION_CLOSE_ERROR (connection,
2323  _ (
2324  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2325  return;
2326  }
2327  /* skip 2nd part of line feed */
2328  if ( (i < available) &&
2329  ( ('\r' == buffer_head[i]) ||
2330  ('\n' == buffer_head[i]) ) )
2331  i++;
2332 
2333  buffer_head += i;
2334  available -= i;
2335  connection->current_chunk_offset = 0;
2336 
2337  if (available > 0)
2338  instant_retry = MHD_YES;
2339  if (0LLU == connection->current_chunk_size)
2340  {
2341  connection->remaining_upload_size = 0;
2342  break;
2343  }
2344  continue;
2345  }
2346  }
2347  else
2348  {
2349  /* no chunked encoding, give all to the client */
2350  if ( (0 != connection->remaining_upload_size) &&
2351  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2352  (connection->remaining_upload_size < available) )
2353  {
2354  to_be_processed = (size_t) connection->remaining_upload_size;
2355  }
2356  else
2357  {
2362  to_be_processed = available;
2363  }
2364  }
2365  left_unprocessed = to_be_processed;
2366  connection->client_aware = true;
2367  if (MHD_NO ==
2368  daemon->default_handler (daemon->default_handler_cls,
2369  connection,
2370  connection->url,
2371  connection->method,
2372  connection->version,
2373  buffer_head,
2374  &left_unprocessed,
2375  &connection->client_context))
2376  {
2377  /* serious internal error, close connection */
2378  CONNECTION_CLOSE_ERROR (connection,
2379  _ (
2380  "Application reported internal error, closing connection.\n"));
2381  return;
2382  }
2383  if (left_unprocessed > to_be_processed)
2385  __FILE__,
2386  __LINE__
2387 #ifdef HAVE_MESSAGES
2388  , _ ("libmicrohttpd API violation.\n")
2389 #else
2390  , NULL
2391 #endif
2392  );
2393  if (0 != left_unprocessed)
2394  {
2395  instant_retry = MHD_NO; /* client did not process everything */
2396 #ifdef HAVE_MESSAGES
2397  /* client did not process all upload data, complain if
2398  the setup was incorrect, which may prevent us from
2399  handling the rest of the request */
2400  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2401  (! connection->suspended) )
2402  MHD_DLOG (daemon,
2403  _ (
2404  "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2405 #endif
2406  }
2407  processed_size = to_be_processed - left_unprocessed;
2408  if (connection->have_chunked_upload)
2409  connection->current_chunk_offset += processed_size;
2410  /* dh left "processed" bytes in buffer for next time... */
2411  buffer_head += processed_size;
2412  available -= processed_size;
2413  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2414  connection->remaining_upload_size -= processed_size;
2415  }
2416  while (MHD_YES == instant_retry);
2417  if ( (available > 0) &&
2418  (buffer_head != connection->read_buffer) )
2419  memmove (connection->read_buffer,
2420  buffer_head,
2421  available);
2422  connection->read_buffer_offset = available;
2423 }
2424 
2425 
2434 static enum MHD_Result
2435 check_write_done (struct MHD_Connection *connection,
2436  enum MHD_CONNECTION_STATE next_state)
2437 {
2438  if (connection->write_buffer_append_offset !=
2439  connection->write_buffer_send_offset)
2440  return MHD_NO;
2441  connection->write_buffer_append_offset = 0;
2442  connection->write_buffer_send_offset = 0;
2443  connection->state = next_state;
2444  MHD_pool_reallocate (connection->pool,
2445  connection->write_buffer,
2446  connection->write_buffer_size,
2447  0);
2448  connection->write_buffer = NULL;
2449  connection->write_buffer_size = 0;
2450  return MHD_YES;
2451 }
2452 
2453 
2463 static enum MHD_Result
2465  char *line)
2466 {
2467  char *colon;
2468 
2469  /* line should be normal header line, find colon */
2470  colon = strchr (line, ':');
2471  if (NULL == colon)
2472  {
2473  /* error in header line, die hard */
2474  CONNECTION_CLOSE_ERROR (connection,
2475  _ (
2476  "Received malformed line (no colon). Closing connection.\n"));
2477  return MHD_NO;
2478  }
2479  if (-1 >= connection->daemon->strict_for_client)
2480  {
2481  /* check for whitespace before colon, which is not allowed
2482  by RFC 7230 section 3.2.4; we count space ' ' and
2483  tab '\t', but not '\r\n' as those would have ended the line. */
2484  const char *white;
2485 
2486  white = strchr (line, ' ');
2487  if ( (NULL != white) &&
2488  (white < colon) )
2489  return MHD_NO;
2490  white = strchr (line, '\t');
2491  if ( (NULL != white) &&
2492  (white < colon) )
2493  return MHD_NO;
2494  }
2495  /* zero-terminate header */
2496  colon[0] = '\0';
2497  colon++; /* advance to value */
2498  while ( ('\0' != colon[0]) &&
2499  ( (' ' == colon[0]) ||
2500  ('\t' == colon[0]) ) )
2501  colon++;
2502  /* we do the actual adding of the connection
2503  header at the beginning of the while
2504  loop since we need to be able to inspect
2505  the *next* header line (in case it starts
2506  with a space...) */connection->last = line;
2507  connection->colon = colon;
2508  return MHD_YES;
2509 }
2510 
2511 
2522 static enum MHD_Result
2524  char *line,
2525  enum MHD_ValueKind kind)
2526 {
2527  char *last;
2528  char *tmp;
2529  size_t last_len;
2530  size_t tmp_len;
2531 
2532  last = connection->last;
2533  if ( (' ' == line[0]) ||
2534  ('\t' == line[0]) )
2535  {
2536  /* value was continued on the next line, see
2537  http://www.jmarshall.com/easy/http/ */
2538  last_len = strlen (last);
2539  /* skip whitespace at start of 2nd line */
2540  tmp = line;
2541  while ( (' ' == tmp[0]) ||
2542  ('\t' == tmp[0]) )
2543  tmp++;
2544  tmp_len = strlen (tmp);
2545  /* FIXME: we might be able to do this better (faster!), as most
2546  likely 'last' and 'line' should already be adjacent in
2547  memory; however, doing this right gets tricky if we have a
2548  value continued over multiple lines (in which case we need to
2549  record how often we have done this so we can check for
2550  adjacency); also, in the case where these are not adjacent
2551  (not sure how it can happen!), we would want to allocate from
2552  the end of the pool, so as to not destroy the read-buffer's
2553  ability to grow nicely. */last = MHD_pool_reallocate (connection->pool,
2554  last,
2555  last_len + 1,
2556  last_len + tmp_len + 1);
2557  if (NULL == last)
2558  {
2559  transmit_error_response (connection,
2561  REQUEST_TOO_BIG);
2562  return MHD_NO;
2563  }
2564  memcpy (&last[last_len],
2565  tmp,
2566  tmp_len + 1);
2567  connection->last = last;
2568  return MHD_YES; /* possibly more than 2 lines... */
2569  }
2570  mhd_assert ( (NULL != last) &&
2571  (NULL != connection->colon) );
2572  if (MHD_NO ==
2573  connection_add_header (connection,
2574  last,
2575  strlen (last),
2576  connection->colon,
2577  strlen (connection->colon),
2578  kind))
2579  {
2580  transmit_error_response (connection,
2582  REQUEST_TOO_BIG);
2583  return MHD_NO;
2584  }
2585  /* we still have the current line to deal with... */
2586  if (0 != line[0])
2587  {
2588  if (MHD_NO == process_header_line (connection,
2589  line))
2590  {
2591  transmit_error_response (connection,
2594  return MHD_NO;
2595  }
2596  }
2597  return MHD_YES;
2598 }
2599 
2600 
2608 static void
2610 {
2611  const char *clen;
2612  struct MHD_Response *response;
2613  const char *enc;
2614  const char *end;
2615 
2616  parse_cookie_header (connection);
2617  if ( (1 <= connection->daemon->strict_for_client) &&
2618  (NULL != connection->version) &&
2620  connection->version)) &&
2621  (MHD_NO ==
2622  MHD_lookup_connection_value_n (connection,
2627  NULL,
2628  NULL)) )
2629  {
2630  enum MHD_Result iret;
2631 
2632  /* die, http 1.1 request without host and we are pedantic */
2633  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2634  connection->read_closed = true;
2635 #ifdef HAVE_MESSAGES
2636  MHD_DLOG (connection->daemon,
2637  _ ("Received HTTP 1.1 request without `Host' header.\n"));
2638 #endif
2639  mhd_assert (NULL == connection->response);
2640  response =
2644  if (NULL == response)
2645  {
2646  /* can't even send a reply, at least close the connection */
2647  CONNECTION_CLOSE_ERROR (connection,
2648  _ (
2649  "Closing connection (failed to create response).\n"));
2650  return;
2651  }
2652  iret = MHD_queue_response (connection,
2654  response);
2655  MHD_destroy_response (response);
2656  if (MHD_YES != iret)
2657  {
2658  /* can't even send a reply, at least close the connection */
2659  CONNECTION_CLOSE_ERROR (connection,
2660  _ (
2661  "Closing connection (failed to queue response).\n"));
2662  }
2663  return;
2664  }
2665 
2666  connection->remaining_upload_size = 0;
2667  if (MHD_NO != MHD_lookup_connection_value_n (connection,
2672  &enc,
2673  NULL))
2674  {
2676  if (MHD_str_equal_caseless_ (enc,
2677  "chunked"))
2678  connection->have_chunked_upload = true;
2679  }
2680  else
2681  {
2682  if (MHD_NO != MHD_lookup_connection_value_n (connection,
2687  &clen,
2688  NULL))
2689  {
2690  end = clen + MHD_str_to_uint64_ (clen,
2691  &connection->remaining_upload_size);
2692  if ( (clen == end) ||
2693  ('\0' != *end) )
2694  {
2695  connection->remaining_upload_size = 0;
2696 #ifdef HAVE_MESSAGES
2697  MHD_DLOG (connection->daemon,
2698  "Failed to parse `Content-Length' header. Closing connection.\n");
2699 #endif
2700  CONNECTION_CLOSE_ERROR (connection,
2701  NULL);
2702  return;
2703  }
2704  }
2705  }
2706 }
2707 
2708 
2716 void
2718 {
2719  struct MHD_Daemon *daemon = connection->daemon;
2720 
2721  if (0 == connection->connection_timeout)
2722  return; /* Skip update of activity for connections
2723  without timeout timer. */
2724  if (connection->suspended)
2725  return; /* no activity on suspended connections */
2726 
2727  connection->last_activity = MHD_monotonic_sec_counter ();
2728  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2729  return; /* each connection has personal timeout */
2730 
2731  if (connection->connection_timeout != daemon->connection_timeout)
2732  return; /* custom timeout, no need to move it in "normal" DLL */
2733 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2735 #endif
2736  /* move connection to head of timeout list (by remove + add operation) */
2738  daemon->normal_timeout_tail,
2739  connection);
2741  daemon->normal_timeout_tail,
2742  connection);
2743 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2745 #endif
2746 }
2747 
2748 
2755 void
2757 {
2758  ssize_t bytes_read;
2759 
2760  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2761  (connection->suspended) )
2762  return;
2763 #ifdef HTTPS_SUPPORT
2764  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2765  { /* HTTPS connection. */
2766  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2767  {
2768  if (! MHD_run_tls_handshake_ (connection))
2769  return;
2770  }
2771  }
2772 #endif /* HTTPS_SUPPORT */
2773 
2774  /* make sure "read" has a reasonable number of bytes
2775  in buffer to use per system call (if possible) */
2776  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2777  connection->read_buffer_size)
2778  try_grow_read_buffer (connection,
2779  (connection->read_buffer_size ==
2780  connection->read_buffer_offset));
2781 
2782  if (connection->read_buffer_size == connection->read_buffer_offset)
2783  return; /* No space for receiving data. */
2784  bytes_read = connection->recv_cls (connection,
2785  &connection->read_buffer
2786  [connection->read_buffer_offset],
2787  connection->read_buffer_size
2788  - connection->read_buffer_offset);
2789  if (bytes_read < 0)
2790  {
2791  if (MHD_ERR_AGAIN_ == bytes_read)
2792  return; /* No new data to process. */
2793  if (MHD_ERR_CONNRESET_ == bytes_read)
2794  {
2795  CONNECTION_CLOSE_ERROR (connection,
2796  (MHD_CONNECTION_INIT == connection->state) ?
2797  NULL :
2798  _ (
2799  "Socket disconnected while reading request.\n"));
2800  return;
2801  }
2802  CONNECTION_CLOSE_ERROR (connection,
2803  (MHD_CONNECTION_INIT == connection->state) ?
2804  NULL :
2805  _ (
2806  "Connection socket is closed due to error when reading request.\n"));
2807  return;
2808  }
2809 
2810  if (0 == bytes_read)
2811  { /* Remote side closed connection. */
2812  connection->read_closed = true;
2813  MHD_connection_close_ (connection,
2815  return;
2816  }
2817  connection->read_buffer_offset += bytes_read;
2818  MHD_update_last_activity_ (connection);
2819 #if DEBUG_STATES
2820  MHD_DLOG (connection->daemon,
2821  _ ("In function %s handling connection at state: %s\n"),
2822  __FUNCTION__,
2823  MHD_state_to_string (connection->state));
2824 #endif
2825  switch (connection->state)
2826  {
2827  case MHD_CONNECTION_INIT:
2836  /* nothing to do but default action */
2837  if (connection->read_closed)
2838  {
2839  MHD_connection_close_ (connection,
2841  }
2842  return;
2843  case MHD_CONNECTION_CLOSED:
2844  return;
2845 #ifdef UPGRADE_SUPPORT
2846  case MHD_CONNECTION_UPGRADE:
2847  mhd_assert (0);
2848  return;
2849 #endif /* UPGRADE_SUPPORT */
2850  default:
2851  /* shrink read buffer to how much is actually used */
2852  MHD_pool_reallocate (connection->pool,
2853  connection->read_buffer,
2854  connection->read_buffer_size + 1,
2855  connection->read_buffer_offset);
2856  break;
2857  }
2858  return;
2859 }
2860 
2861 
2868 void
2870 {
2871  struct MHD_Response *response;
2872  ssize_t ret;
2873  if (connection->suspended)
2874  return;
2875 
2876 #ifdef HTTPS_SUPPORT
2877  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2878  { /* HTTPS connection. */
2879  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2880  {
2881  if (! MHD_run_tls_handshake_ (connection))
2882  return;
2883  }
2884  }
2885 #endif /* HTTPS_SUPPORT */
2886 
2887 #if DEBUG_STATES
2888  MHD_DLOG (connection->daemon,
2889  _ ("In function %s handling connection at state: %s\n"),
2890  __FUNCTION__,
2891  MHD_state_to_string (connection->state));
2892 #endif
2893  switch (connection->state)
2894  {
2895  case MHD_CONNECTION_INIT:
2899  mhd_assert (0);
2900  return;
2902  return;
2904  ret = MHD_send_on_connection_ (connection,
2906  [connection->continue_message_write_offset],
2908  - connection->continue_message_write_offset,
2909  MHD_SSO_NO_CORK);
2910  if (ret < 0)
2911  {
2912  if (MHD_ERR_AGAIN_ == ret)
2913  return;
2914 #ifdef HAVE_MESSAGES
2915  MHD_DLOG (connection->daemon,
2916  _ ("Failed to send data in request for %s.\n"),
2917  connection->url);
2918 #endif
2919  CONNECTION_CLOSE_ERROR (connection,
2920  NULL);
2921  return;
2922  }
2923 #if DEBUG_SEND_DATA
2924  fprintf (stderr,
2925  _ ("Sent 100 continue response: `%.*s'\n"),
2926  (int) ret,
2928 #endif
2929  connection->continue_message_write_offset += ret;
2930  MHD_update_last_activity_ (connection);
2931  return;
2936  mhd_assert (0);
2937  return;
2939  {
2940  const size_t wb_ready = connection->write_buffer_append_offset
2941  - connection->write_buffer_send_offset;
2942 
2943  /* if the response body is not available, we use MHD_send_on_connection_() */
2944  if (NULL != connection->response->crc)
2945  {
2946  ret = MHD_send_on_connection_ (connection,
2947  &connection->write_buffer
2948  [connection->write_buffer_send_offset],
2949  wb_ready,
2951  }
2952  else
2953  {
2954  ret = MHD_send_on_connection2_ (connection,
2955  &connection->write_buffer
2956  [connection->write_buffer_send_offset],
2957  wb_ready,
2958  connection->response->data,
2959  connection->response->data_buffer_size);
2960  }
2961 
2962  if (ret < 0)
2963  {
2964  if (MHD_ERR_AGAIN_ == ret)
2965  return;
2966  CONNECTION_CLOSE_ERROR (connection,
2967  _ (
2968  "Connection was closed while sending response headers.\n"));
2969  return;
2970  }
2971  if (ret > wb_ready)
2972  {
2973  mhd_assert (NULL == connection->response->crc);
2974  /* We sent not just header data but also some response data,
2975  update both offsets! */
2976  connection->write_buffer_send_offset += wb_ready;
2977  ret -= wb_ready;
2978  connection->response_write_position += ret;
2979  }
2980  else
2981  connection->write_buffer_send_offset += ret;
2982  MHD_update_last_activity_ (connection);
2983  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
2984  return;
2985  check_write_done (connection,
2987  return;
2988  }
2990  return;
2992  response = connection->response;
2993  if (connection->response_write_position <
2994  connection->response->total_size)
2995  {
2996  uint64_t data_write_offset;
2997 
2998 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2999  if (NULL != response->crc)
3000  MHD_mutex_lock_chk_ (&response->mutex);
3001 #endif
3002  if (MHD_YES != try_ready_normal_body (connection))
3003  {
3004  /* mutex was already unlocked by try_ready_normal_body */
3005  return;
3006  }
3007 #if defined(_MHD_HAVE_SENDFILE)
3008  if (MHD_resp_sender_sendfile == connection->resp_sender)
3009  {
3010  ret = MHD_send_sendfile_ (connection);
3011  }
3012  else
3013 #else /* ! _MHD_HAVE_SENDFILE */
3014  if (1)
3015 #endif /* ! _MHD_HAVE_SENDFILE */
3016  {
3017  data_write_offset = connection->response_write_position
3018  - response->data_start;
3019  if (data_write_offset > (uint64_t) SIZE_MAX)
3020  MHD_PANIC (_ ("Data offset exceeds limit.\n"));
3021  ret = MHD_send_on_connection_ (connection,
3022  &response->data
3023  [(size_t) data_write_offset],
3024  response->data_size
3025  - (size_t) data_write_offset,
3026  MHD_SSO_NO_CORK);
3027 #if DEBUG_SEND_DATA
3028  if (ret > 0)
3029  fprintf (stderr,
3030  _ ("Sent %d-byte DATA response: `%.*s'\n"),
3031  (int) ret,
3032  (int) ret,
3033  &response->data[connection->response_write_position
3034  - response->data_start]);
3035 #endif
3036  }
3037 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3038  if (NULL != response->crc)
3039  MHD_mutex_unlock_chk_ (&response->mutex);
3040 #endif
3041  if (ret < 0)
3042  {
3043  if (MHD_ERR_AGAIN_ == ret)
3044  return;
3045 #ifdef HAVE_MESSAGES
3046  MHD_DLOG (connection->daemon,
3047  _ ("Failed to send data in request for `%s'.\n"),
3048  connection->url);
3049 #endif
3050  CONNECTION_CLOSE_ERROR (connection,
3051  NULL);
3052  return;
3053  }
3054  connection->response_write_position += ret;
3055  MHD_update_last_activity_ (connection);
3056  }
3057  if (connection->response_write_position ==
3058  connection->response->total_size)
3059  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3060  return;
3062  mhd_assert (0);
3063  return;
3065  ret = MHD_send_on_connection_ (connection,
3066  &connection->write_buffer
3067  [connection->write_buffer_send_offset],
3068  connection->write_buffer_append_offset
3069  - connection->write_buffer_send_offset,
3070  MHD_SSO_NO_CORK);
3071  if (ret < 0)
3072  {
3073  if (MHD_ERR_AGAIN_ == ret)
3074  return;
3075  CONNECTION_CLOSE_ERROR (connection,
3076  _ (
3077  "Connection was closed while sending response body.\n"));
3078  return;
3079  }
3080  connection->write_buffer_send_offset += ret;
3081  MHD_update_last_activity_ (connection);
3082  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3083  return;
3084  check_write_done (connection,
3085  (connection->response->total_size ==
3086  connection->response_write_position) ?
3089  return;
3092  mhd_assert (0);
3093  return;
3095  ret = MHD_send_on_connection_ (connection,
3096  &connection->write_buffer
3097  [connection->write_buffer_send_offset],
3098  connection->write_buffer_append_offset
3099  - connection->write_buffer_send_offset,
3101  if (ret < 0)
3102  {
3103  if (MHD_ERR_AGAIN_ == ret)
3104  return;
3105  CONNECTION_CLOSE_ERROR (connection,
3106  _ (
3107  "Connection was closed while sending response body.\n"));
3108  return;
3109  }
3110  connection->write_buffer_send_offset += ret;
3111  MHD_update_last_activity_ (connection);
3112  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3113  return;
3114  check_write_done (connection,
3116  return;
3118  mhd_assert (0);
3119  return;
3120  case MHD_CONNECTION_CLOSED:
3121  return;
3122 #ifdef UPGRADE_SUPPORT
3123  case MHD_CONNECTION_UPGRADE:
3124  mhd_assert (0);
3125  return;
3126 #endif /* UPGRADE_SUPPORT */
3127  default:
3128  mhd_assert (0);
3129  CONNECTION_CLOSE_ERROR (connection,
3130  _ ("Internal error.\n"));
3131  break;
3132  }
3133  return;
3134 }
3135 
3136 
3145 static void
3147 {
3148  struct MHD_Daemon *daemon = connection->daemon;
3149 
3150  if (connection->in_cleanup)
3151  return; /* Prevent double cleanup. */
3152  connection->in_cleanup = true;
3153  if (NULL != connection->response)
3154  {
3155  MHD_destroy_response (connection->response);
3156  connection->response = NULL;
3157  }
3158 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3160 #endif
3161  if (connection->suspended)
3162  {
3165  connection);
3166  connection->suspended = false;
3167  }
3168  else
3169  {
3170  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3171  {
3172  if (connection->connection_timeout == daemon->connection_timeout)
3174  daemon->normal_timeout_tail,
3175  connection);
3176  else
3178  daemon->manual_timeout_tail,
3179  connection);
3180  }
3181  DLL_remove (daemon->connections_head,
3182  daemon->connections_tail,
3183  connection);
3184  }
3185  DLL_insert (daemon->cleanup_head,
3186  daemon->cleanup_tail,
3187  connection);
3188  connection->resuming = false;
3189  connection->in_idle = false;
3190 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3192 #endif
3193  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3194  {
3195  /* if we were at the connection limit before and are in
3196  thread-per-connection mode, signal the main thread
3197  to resume accepting connections */
3198  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3199  (! MHD_itc_activate_ (daemon->itc, "c")) )
3200  {
3201 #ifdef HAVE_MESSAGES
3202  MHD_DLOG (daemon,
3203  _ (
3204  "Failed to signal end of connection via inter-thread communication channel.\n"));
3205 #endif
3206  }
3207  }
3208 }
3209 
3210 
3221 enum MHD_Result
3223 {
3224  struct MHD_Daemon *daemon = connection->daemon;
3225  char *line;
3226  size_t line_len;
3227  enum MHD_Result ret;
3228 
3229  connection->in_idle = true;
3230  while (! connection->suspended)
3231  {
3232 #ifdef HTTPS_SUPPORT
3233  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3234  { /* HTTPS connection. */
3235  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3236  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3237  break;
3238  }
3239 #endif /* HTTPS_SUPPORT */
3240 #if DEBUG_STATES
3241  MHD_DLOG (daemon,
3242  _ ("In function %s handling connection at state: %s\n"),
3243  __FUNCTION__,
3244  MHD_state_to_string (connection->state));
3245 #endif
3246  switch (connection->state)
3247  {
3248  case MHD_CONNECTION_INIT:
3249  line = get_next_header_line (connection,
3250  &line_len);
3251  /* Check for empty string, as we might want
3252  to tolerate 'spurious' empty lines; also
3253  NULL means we didn't get a full line yet;
3254  line is not 0-terminated here. */
3255  if ( (NULL == line) ||
3256  (0 == line[0]) )
3257  {
3258  if (MHD_CONNECTION_INIT != connection->state)
3259  continue;
3260  if (connection->read_closed)
3261  {
3262  CONNECTION_CLOSE_ERROR (connection,
3263  NULL);
3264  continue;
3265  }
3266  break;
3267  }
3268  if (MHD_NO == parse_initial_message_line (connection,
3269  line,
3270  line_len))
3271  CONNECTION_CLOSE_ERROR (connection,
3272  NULL);
3273  else
3274  connection->state = MHD_CONNECTION_URL_RECEIVED;
3275  continue;
3277  line = get_next_header_line (connection,
3278  NULL);
3279  if (NULL == line)
3280  {
3281  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3282  continue;
3283  if (connection->read_closed)
3284  {
3285  CONNECTION_CLOSE_ERROR (connection,
3286  NULL);
3287  continue;
3288  }
3289  break;
3290  }
3291  if (0 == line[0])
3292  {
3293  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3294  connection->header_size = (size_t) (line - connection->read_buffer);
3295  continue;
3296  }
3297  if (MHD_NO == process_header_line (connection,
3298  line))
3299  {
3300  transmit_error_response (connection,
3303  break;
3304  }
3306  continue;
3308  line = get_next_header_line (connection,
3309  NULL);
3310  if (NULL == line)
3311  {
3312  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
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 ==
3323  process_broken_line (connection,
3324  line,
3325  MHD_HEADER_KIND))
3326  continue;
3327  if (0 == line[0])
3328  {
3329  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3330  connection->header_size = (size_t) (line - connection->read_buffer);
3331  continue;
3332  }
3333  continue;
3335  parse_connection_headers (connection);
3336  if (MHD_CONNECTION_CLOSED == connection->state)
3337  continue;
3339  if (connection->suspended)
3340  break;
3341  continue;
3343  call_connection_handler (connection); /* first call */
3344  if (MHD_CONNECTION_CLOSED == connection->state)
3345  continue;
3346  if (connection->suspended)
3347  continue;
3348  if ( (NULL == connection->response) &&
3349  (need_100_continue (connection)) )
3350  {
3351  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3352  break;
3353  }
3354  if ( (NULL != connection->response) &&
3355  (0 != connection->remaining_upload_size) )
3356  {
3357  /* we refused (no upload allowed!) */
3358  connection->remaining_upload_size = 0;
3359  /* force close, in case client still tries to upload... */
3360  connection->read_closed = true;
3361  }
3362  connection->state = (0 == connection->remaining_upload_size)
3365  if (connection->suspended)
3366  break;
3367  continue;
3369  if (connection->continue_message_write_offset ==
3371  {
3372  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3373  continue;
3374  }
3375  break;
3377  if (0 != connection->read_buffer_offset)
3378  {
3379  process_request_body (connection); /* loop call */
3380  if (MHD_CONNECTION_CLOSED == connection->state)
3381  continue;
3382  }
3383  if ( (0 == connection->remaining_upload_size) ||
3384  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3385  (0 == connection->read_buffer_offset) &&
3386  (connection->read_closed) ) )
3387  {
3388  if ( (connection->have_chunked_upload) &&
3389  (! connection->read_closed) )
3390  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3391  else
3392  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3393  if (connection->suspended)
3394  break;
3395  continue;
3396  }
3397  break;
3399  line = get_next_header_line (connection,
3400  NULL);
3401  if (NULL == line)
3402  {
3403  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3404  continue;
3405  if (connection->read_closed)
3406  {
3407  CONNECTION_CLOSE_ERROR (connection,
3408  NULL);
3409  continue;
3410  }
3411  break;
3412  }
3413  if (0 == line[0])
3414  {
3415  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3416  if (connection->suspended)
3417  break;
3418  continue;
3419  }
3420  if (MHD_NO == process_header_line (connection,
3421  line))
3422  {
3423  transmit_error_response (connection,
3426  break;
3427  }
3429  continue;
3431  line = get_next_header_line (connection,
3432  NULL);
3433  if (NULL == line)
3434  {
3435  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3436  continue;
3437  if (connection->read_closed)
3438  {
3439  CONNECTION_CLOSE_ERROR (connection,
3440  NULL);
3441  continue;
3442  }
3443  break;
3444  }
3445  if (MHD_NO ==
3446  process_broken_line (connection,
3447  line,
3448  MHD_FOOTER_KIND))
3449  continue;
3450  if (0 == line[0])
3451  {
3452  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3453  if (connection->suspended)
3454  break;
3455  continue;
3456  }
3457  continue;
3459  call_connection_handler (connection); /* "final" call */
3460  if (connection->state == MHD_CONNECTION_CLOSED)
3461  continue;
3462  if (NULL == connection->response)
3463  break; /* try again next time */
3464  if (MHD_NO == build_header_response (connection))
3465  {
3466  /* oops - close! */
3467  CONNECTION_CLOSE_ERROR (connection,
3468  _ (
3469  "Closing connection (failed to create response header).\n"));
3470  continue;
3471  }
3472  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3473  break;
3475  /* no default action */
3476  break;
3478  /* Some clients may take some actions right after header receive */
3479 #ifdef UPGRADE_SUPPORT
3480  if (NULL != connection->response->upgrade_handler)
3481  {
3482  connection->state = MHD_CONNECTION_UPGRADE;
3483  /* This connection is "upgraded". Pass socket to application. */
3484  if (MHD_YES !=
3486  connection))
3487  {
3488  /* upgrade failed, fail hard */
3489  CONNECTION_CLOSE_ERROR (connection,
3490  NULL);
3491  continue;
3492  }
3493  /* Response is not required anymore for this connection. */
3494  {
3495  struct MHD_Response *const resp = connection->response;
3496 
3497  connection->response = NULL;
3498  MHD_destroy_response (resp);
3499  }
3500  continue;
3501  }
3502 #endif /* UPGRADE_SUPPORT */
3503 
3504  if (connection->have_chunked_upload)
3506  else
3508  continue;
3510  /* nothing to do here */
3511  break;
3513 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3514  if (NULL != connection->response->crc)
3515  MHD_mutex_lock_chk_ (&connection->response->mutex);
3516 #endif
3517  if (0 == connection->response->total_size)
3518  {
3519 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3520  if (NULL != connection->response->crc)
3521  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3522 #endif
3523  connection->state = MHD_CONNECTION_BODY_SENT;
3524  continue;
3525  }
3526  if (MHD_YES == try_ready_normal_body (connection))
3527  {
3528 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3529  if (NULL != connection->response->crc)
3530  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3531 #endif
3533  /* Buffering for flushable socket was already enabled*/
3534 
3535  break;
3536  }
3537  /* mutex was already unlocked by "try_ready_normal_body */
3538  /* not ready, no socket action */
3539  break;
3541  /* nothing to do here */
3542  break;
3544 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3545  if (NULL != connection->response->crc)
3546  MHD_mutex_lock_chk_ (&connection->response->mutex);
3547 #endif
3548  if ( (0 == connection->response->total_size) ||
3549  (connection->response_write_position ==
3550  connection->response->total_size) )
3551  {
3552 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3553  if (NULL != connection->response->crc)
3554  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3555 #endif
3556  connection->state = MHD_CONNECTION_BODY_SENT;
3557  continue;
3558  }
3559  if (MHD_YES == try_ready_chunked_body (connection))
3560  {
3561 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3562  if (NULL != connection->response->crc)
3563  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3564 #endif
3566  /* Buffering for flushable socket was already enabled */
3567 
3568  continue;
3569  }
3570  /* mutex was already unlocked by try_ready_chunked_body */
3571  break;
3573  if (MHD_NO == build_header_response (connection))
3574  {
3575  /* oops - close! */
3576  CONNECTION_CLOSE_ERROR (connection,
3577  _ (
3578  "Closing connection (failed to create response header).\n"));
3579  continue;
3580  }
3581  if ( (! connection->have_chunked_upload) ||
3582  (connection->write_buffer_send_offset ==
3583  connection->write_buffer_append_offset) )
3584  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3585  else
3586  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3587  continue;
3589  /* no default action */
3590  break;
3592  if (MHD_HTTP_PROCESSING == connection->responseCode)
3593  {
3594  /* After this type of response, we allow sending another! */
3596  MHD_destroy_response (connection->response);
3597  connection->response = NULL;
3598  /* FIXME: maybe partially reset memory pool? */
3599  continue;
3600  }
3601  MHD_destroy_response (connection->response);
3602  connection->response = NULL;
3603  if ( (NULL != daemon->notify_completed) &&
3604  (connection->client_aware) )
3605  {
3606  daemon->notify_completed (daemon->notify_completed_cls,
3607  connection,
3608  &connection->client_context,
3610  }
3611  connection->client_aware = false;
3612  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3613  (connection->read_closed) )
3614  {
3615  /* have to close for some reason */
3616  MHD_connection_close_ (connection,
3618  MHD_pool_destroy (connection->pool);
3619  connection->pool = NULL;
3620  connection->read_buffer = NULL;
3621  connection->read_buffer_size = 0;
3622  connection->read_buffer_offset = 0;
3623  }
3624  else
3625  {
3626  /* can try to keep-alive */
3627 
3628  connection->version = NULL;
3629  connection->state = MHD_CONNECTION_INIT;
3630  connection->last = NULL;
3631  connection->colon = NULL;
3632  connection->header_size = 0;
3633  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3634  /* Reset the read buffer to the starting size,
3635  preserving the bytes we have already read. */
3636  connection->read_buffer
3637  = MHD_pool_reset (connection->pool,
3638  connection->read_buffer,
3639  connection->read_buffer_offset,
3640  connection->daemon->pool_size / 2);
3641  connection->read_buffer_size
3642  = connection->daemon->pool_size / 2;
3643  }
3644  connection->client_context = NULL;
3645  connection->continue_message_write_offset = 0;
3646  connection->responseCode = 0;
3647  connection->headers_received = NULL;
3648  connection->headers_received_tail = NULL;
3649  connection->response_write_position = 0;
3650  connection->have_chunked_upload = false;
3651  connection->current_chunk_size = 0;
3652  connection->current_chunk_offset = 0;
3653  connection->method = NULL;
3654  connection->url = NULL;
3655  connection->write_buffer = NULL;
3656  connection->write_buffer_size = 0;
3657  connection->write_buffer_send_offset = 0;
3658  connection->write_buffer_append_offset = 0;
3659  continue;
3660  case MHD_CONNECTION_CLOSED:
3661  cleanup_connection (connection);
3662  connection->in_idle = false;
3663  return MHD_NO;
3664 #ifdef UPGRADE_SUPPORT
3665  case MHD_CONNECTION_UPGRADE:
3666  connection->in_idle = false;
3667  return MHD_YES; /* keep open */
3668 #endif /* UPGRADE_SUPPORT */
3669  default:
3670  mhd_assert (0);
3671  break;
3672  }
3673  break;
3674  }
3675  if (! connection->suspended)
3676  {
3677  time_t timeout;
3678  timeout = connection->connection_timeout;
3679  if ( (0 != timeout) &&
3680  (timeout < (MHD_monotonic_sec_counter ()
3681  - connection->last_activity)) )
3682  {
3683  MHD_connection_close_ (connection,
3685  connection->in_idle = false;
3686  return MHD_YES;
3687  }
3688  }
3690  ret = MHD_YES;
3691 #ifdef EPOLL_SUPPORT
3692  if ( (! connection->suspended) &&
3693  (0 != (daemon->options & MHD_USE_EPOLL)) )
3694  {
3695  ret = MHD_connection_epoll_update_ (connection);
3696  }
3697 #endif /* EPOLL_SUPPORT */
3698  connection->in_idle = false;
3699  return ret;
3700 }
3701 
3702 
3703 #ifdef EPOLL_SUPPORT
3704 
3712 enum MHD_Result
3713 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3714 {
3715  struct MHD_Daemon *daemon = connection->daemon;
3716 
3717  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3718  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3719  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3720  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3721  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3722  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3723  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3724  {
3725  /* add to epoll set */
3726  struct epoll_event event;
3727 
3728  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3729  event.data.ptr = connection;
3730  if (0 != epoll_ctl (daemon->epoll_fd,
3731  EPOLL_CTL_ADD,
3732  connection->socket_fd,
3733  &event))
3734  {
3735 #ifdef HAVE_MESSAGES
3736  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3737  MHD_DLOG (daemon,
3738  _ ("Call to epoll_ctl failed: %s\n"),
3740 #endif
3741  connection->state = MHD_CONNECTION_CLOSED;
3742  cleanup_connection (connection);
3743  return MHD_NO;
3744  }
3745  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3746  }
3747  return MHD_YES;
3748 }
3749 
3750 
3751 #endif
3752 
3753 
3759 void
3761 {
3762  connection->recv_cls = &recv_param_adapter;
3763 }
3764 
3765 
3776 const union MHD_ConnectionInfo *
3778  enum MHD_ConnectionInfoType info_type,
3779  ...)
3780 {
3781  switch (info_type)
3782  {
3783 #ifdef HTTPS_SUPPORT
3785  if (NULL == connection->tls_session)
3786  return NULL;
3787  connection->cipher = gnutls_cipher_get (connection->tls_session);
3788  return (const union MHD_ConnectionInfo *) &connection->cipher;
3790  if (NULL == connection->tls_session)
3791  return NULL;
3792  connection->protocol = gnutls_protocol_get_version (
3793  connection->tls_session);
3794  return (const union MHD_ConnectionInfo *) &connection->protocol;
3796  if (NULL == connection->tls_session)
3797  return NULL;
3798  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3799 #endif /* HTTPS_SUPPORT */
3801  return (const union MHD_ConnectionInfo *) &connection->addr;
3803  return (const union MHD_ConnectionInfo *) &connection->daemon;
3805  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3807  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3809  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3810  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3812  connection->connection_timeout_dummy = (unsigned
3813  int) connection->connection_timeout;
3814  return (const union MHD_ConnectionInfo *) &connection->
3815  connection_timeout_dummy;
3817  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3818  (MHD_CONNECTION_CLOSED == connection->state) )
3819  return NULL; /* invalid, too early! */
3820  return (const union MHD_ConnectionInfo *) &connection->header_size;
3821  default:
3822  return NULL;
3823  }
3824 }
3825 
3826 
3836 enum MHD_Result
3838  enum MHD_CONNECTION_OPTION option,
3839  ...)
3840 {
3841  va_list ap;
3842  struct MHD_Daemon *daemon;
3843 
3844  daemon = connection->daemon;
3845  switch (option)
3846  {
3848  if (0 == connection->connection_timeout)
3849  connection->last_activity = MHD_monotonic_sec_counter ();
3850 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3852 #endif
3853  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3854  (! connection->suspended) )
3855  {
3856  if (connection->connection_timeout == daemon->connection_timeout)
3858  daemon->normal_timeout_tail,
3859  connection);
3860  else
3862  daemon->manual_timeout_tail,
3863  connection);
3864  }
3865  va_start (ap, option);
3866  connection->connection_timeout = va_arg (ap,
3867  unsigned int);
3868  va_end (ap);
3869  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3870  (! connection->suspended) )
3871  {
3872  if (connection->connection_timeout == daemon->connection_timeout)
3874  daemon->normal_timeout_tail,
3875  connection);
3876  else
3878  daemon->manual_timeout_tail,
3879  connection);
3880  }
3881 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3883 #endif
3884  return MHD_YES;
3885  default:
3886  return MHD_NO;
3887  }
3888 }
3889 
3890 
3902 enum MHD_Result
3904  unsigned int status_code,
3905  struct MHD_Response *response)
3906 {
3907  struct MHD_Daemon *daemon;
3908 
3909  if ( (NULL == connection) ||
3910  (NULL == response) ||
3911  (NULL != connection->response) ||
3912  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3913  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3914  return MHD_NO;
3915  daemon = connection->daemon;
3916 
3917  if (daemon->shutdown)
3918  return MHD_YES; /* If daemon was shut down in parallel,
3919  * response will be aborted now or on later stage. */
3920 
3921 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3922  if ( (! connection->suspended) &&
3923  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3924  (! MHD_thread_ID_match_current_ (connection->pid.ID)) )
3925  {
3926 #ifdef HAVE_MESSAGES
3927  MHD_DLOG (daemon,
3928  _ ("Attempted to queue response on wrong thread!\n"));
3929 #endif
3930  return MHD_NO;
3931  }
3932 #endif
3933 #ifdef UPGRADE_SUPPORT
3934  if ( (NULL != response->upgrade_handler) &&
3935  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3936  {
3937 #ifdef HAVE_MESSAGES
3938  MHD_DLOG (daemon,
3939  _ (
3940  "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
3941 #endif
3942  return MHD_NO;
3943  }
3944  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
3945  (NULL != response->upgrade_handler) )
3946  {
3947 #ifdef HAVE_MESSAGES
3948  MHD_DLOG (daemon,
3949  _ (
3950  "Application used invalid status code for 'upgrade' response!\n"));
3951 #endif
3952  return MHD_NO;
3953  }
3954 #endif /* UPGRADE_SUPPORT */
3955  MHD_increment_response_rc (response);
3956  connection->response = response;
3957  connection->responseCode = status_code;
3958 #if defined(_MHD_HAVE_SENDFILE)
3959  if ( (response->fd == -1) ||
3960  (0 != (connection->daemon->options & MHD_USE_TLS)) )
3961  connection->resp_sender = MHD_resp_sender_std;
3962  else
3963  connection->resp_sender = MHD_resp_sender_sendfile;
3964 #endif /* _MHD_HAVE_SENDFILE */
3965 
3966  if ( ( (NULL != connection->method) &&
3967  (MHD_str_equal_caseless_ (connection->method,
3968  MHD_HTTP_METHOD_HEAD)) ) ||
3969  (MHD_HTTP_OK > status_code) ||
3970  (MHD_HTTP_NO_CONTENT == status_code) ||
3971  (MHD_HTTP_NOT_MODIFIED == status_code) )
3972  {
3973  /* if this is a "HEAD" request, or a status code for
3974  which a body is not allowed, pretend that we
3975  have already sent the full message body. */
3976  connection->response_write_position = response->total_size;
3977  }
3978  if (MHD_CONNECTION_HEADERS_PROCESSED == connection->state)
3979  {
3980  /* response was queued "early", refuse to read body / footers or
3981  further requests! */
3982  connection->read_closed = true;
3983  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3984  connection->remaining_upload_size = 0;
3985  }
3986  if (! connection->in_idle)
3987  (void) MHD_connection_handle_idle (connection);
3988  MHD_update_last_activity_ (connection);
3989  return MHD_YES;
3990 }
3991 
3992 
3993 /* end of connection.c */
_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:285
void * unescape_callback_cls
Definition: internal.h:1412
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:582
static enum MHD_Result 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:338
#define MHD_PANIC(msg)
Definition: internal.h:69
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2869
uint64_t total_size
Definition: internal.h:1642
bool have_chunked_upload
Definition: internal.h:944
Header for platform missing functions.
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:475
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:902
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1655
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:3038
_MHD_EXTERN enum MHD_Result MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:446
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:618
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
static enum MHD_Result process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2523
_MHD_EXTERN enum MHD_Result MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3837
#define HTTP_100_CONTINUE
Definition: connection.c:60
#define MHD_ICY_FLAG
Definition: microhttpd.h:536
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:1589
Methods for managing connections.
MHD_PanicCallback mhd_panic
Definition: panic.c:31
_MHD_EXTERN enum MHD_Result 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:512
#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:1012
#define INTERNAL_ERROR
Definition: connection.c:114
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:592
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:694
#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
static enum MHD_Result keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1032
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:373
#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:657
MHD_RequestTerminationCode
Definition: microhttpd.h:1816
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:1571
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1258
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:643
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2156
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:389
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3146
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2717
char * header
Definition: internal.h:347
static bool need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:631
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:298
void * uri_log_callback_cls
Definition: internal.h:1402
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
size_t header_size
Definition: internal.h:811
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
Definition: connection.c:1145
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:576
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1973
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:137
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:702
Header for platform-independent inter-thread communication.
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:791
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3222
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:3777
static enum MHD_Result check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2435
#define DLL_insert(head, tail, element)
Definition: internal.h:1743
int strict_for_client
Definition: internal.h:1610
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1254
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:412
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:3764
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
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
static enum MHD_Result 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:1883
#define REQUEST_MALFORMED
Definition: connection.c:101
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:196
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:1600
static enum MHD_Result process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2464
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:351
LogCallback uri_log_callback
Definition: internal.h:1397
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2756
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:343
time_t connection_timeout
Definition: internal.h:745
static enum MHD_Result parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2044
#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:241
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:174
#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:1082
MHD_ValueKind
Definition: microhttpd.h:1765
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
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3903
ReceiveCallback recv_cls
Definition: internal.h:706
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:1964
uint64_t data_start
Definition: internal.h:1648
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:888
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
MHD_Result
Definition: microhttpd.h:140
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:439
UnescapeCallback unescape_callback
Definition: internal.h:1407
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:384
_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:1447
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
enum MHD_ResponseFlags flags
Definition: internal.h:401
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:586
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2246
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
enum MHD_Result(* 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:2271
struct MHD_HTTP_Header * next
Definition: internal.h:342
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:908
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2609
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:1372
#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:568
bool read_closed
Definition: internal.h:792
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3760
void * notify_completed_cls
Definition: internal.h:1377
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2192
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:887
#define MHD_ERR_NOTCONN_
Definition: internal.h:1874
struct MemoryPool * pool
Definition: internal.h:685
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:246
_MHD_EXTERN enum MHD_Result 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:399
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:445
static enum MHD_Result try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:901
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:175
MHD_ContentReaderCallback crc
Definition: internal.h:1600
static enum MHD_Result build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1198
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:312
bool suspended
Definition: internal.h:764
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:574
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:338
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:419
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:167
#define MHD_MIN(a, b)
Definition: internal.h:110
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
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:1823
void * default_handler_cls
Definition: internal.h:1263
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:813
uint64_t current_chunk_size
Definition: internal.h:952
static enum MHD_Result parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1918
struct MHD_HTTP_Header * headers_received
Definition: internal.h:670
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:336
limits values definitions
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:630
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
#define REQUEST_TOO_BIG
Definition: connection.c:73
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:675
size_t pool_increment
Definition: internal.h:1452
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:408
static enum MHD_Result try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:830