GNU libmicrohttpd  0.9.72
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 
117 
121 #define MHD_SENFILE_CHUNK_ (0x20000)
122 
126 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
127 
137 static ssize_t
138 recv_param_adapter (struct MHD_Connection *connection,
139  void *other,
140  size_t i)
141 {
142  ssize_t ret;
143 
144  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
145  (MHD_CONNECTION_CLOSED == connection->state) )
146  {
147  return MHD_ERR_NOTCONN_;
148  }
149  if (i > MHD_SCKT_SEND_MAX_SIZE_)
150  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
151 
152  ret = MHD_recv_ (connection->socket_fd,
153  other,
154  i);
155  if (0 > ret)
156  {
157  const int err = MHD_socket_get_error_ ();
158  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
159  {
160 #ifdef EPOLL_SUPPORT
161  /* Got EAGAIN --- no longer read-ready */
162  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
163 #endif /* EPOLL_SUPPORT */
164  return MHD_ERR_AGAIN_;
165  }
166  if (MHD_SCKT_ERR_IS_EINTR_ (err))
167  return MHD_ERR_AGAIN_;
169  return MHD_ERR_CONNRESET_;
170  /* Treat any other error as hard error. */
171  return MHD_ERR_NOTCONN_;
172  }
173 #ifdef EPOLL_SUPPORT
174  else if (i > (size_t) ret)
175  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
176 #endif /* EPOLL_SUPPORT */
177  return ret;
178 }
179 
180 
193 int
195  enum MHD_ValueKind kind,
196  MHD_KeyValueIterator iterator,
197  void *iterator_cls)
198 {
199  int ret;
200  struct MHD_HTTP_Header *pos;
201 
202  if (NULL == connection)
203  return -1;
204  ret = 0;
205  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
206  if (0 != (pos->kind & kind))
207  {
208  ret++;
209  if ( (NULL != iterator) &&
210  (MHD_NO == iterator (iterator_cls,
211  pos->kind,
212  pos->header,
213  pos->value)) )
214  return ret;
215  }
216  return ret;
217 }
218 
219 
232 int
234  enum MHD_ValueKind kind,
235  MHD_KeyValueIteratorN iterator,
236  void *iterator_cls)
237 {
238  int ret;
239  struct MHD_HTTP_Header *pos;
240 
241  if (NULL == connection)
242  return -1;
243  ret = 0;
244 
245  if (NULL == iterator)
246  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
247  {
248  if (0 != (kind & pos->kind))
249  ret++;
250  }
251  else
252  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
253  if (0 != (kind & pos->kind))
254  {
255  ret++;
256  if (MHD_NO == iterator (iterator_cls,
257  pos->kind,
258  pos->header,
259  pos->header_size,
260  pos->value,
261  pos->value_size))
262  return ret;
263  }
264  return ret;
265 }
266 
267 
285 static enum MHD_Result
287  enum MHD_ValueKind kind,
288  const char *key,
289  size_t key_size,
290  const char *value,
291  size_t value_size)
292 {
293  struct MHD_HTTP_Header *pos;
294 
295  pos = MHD_pool_allocate (connection->pool,
296  sizeof (struct MHD_HTTP_Header),
297  true);
298  if (NULL == pos)
299  return MHD_NO;
300  pos->header = (char *) key;
301  pos->header_size = key_size;
302  pos->value = (char *) value;
303  pos->value_size = value_size;
304  pos->kind = kind;
305  pos->next = NULL;
306  /* append 'pos' to the linked list of headers */
307  if (NULL == connection->headers_received_tail)
308  {
309  connection->headers_received = pos;
310  connection->headers_received_tail = pos;
311  }
312  else
313  {
314  connection->headers_received_tail->next = pos;
315  connection->headers_received_tail = pos;
316  }
317  return MHD_YES;
318 }
319 
320 
346 enum MHD_Result
347 MHD_set_connection_value_n (struct MHD_Connection *connection,
348  enum MHD_ValueKind kind,
349  const char *key,
350  size_t key_size,
351  const char *value,
352  size_t value_size)
353 {
354  if ( (MHD_GET_ARGUMENT_KIND != kind) &&
355  ( ((key ? strlen (key) : 0) != key_size) ||
356  ((value ? strlen (value) : 0) != value_size) ) )
357  return MHD_NO; /* binary zero is allowed only in GET arguments */
358 
359  return MHD_set_connection_value_n_nocheck_ (connection,
360  kind,
361  key,
362  key_size,
363  value,
364  value_size);
365 }
366 
367 
393 enum MHD_Result
394 MHD_set_connection_value (struct MHD_Connection *connection,
395  enum MHD_ValueKind kind,
396  const char *key,
397  const char *value)
398 {
399  return MHD_set_connection_value_n_nocheck_ (connection,
400  kind,
401  key,
402  NULL != key
403  ? strlen (key)
404  : 0,
405  value,
406  NULL != value
407  ? strlen (value)
408  : 0);
409 }
410 
411 
422 const char *
424  enum MHD_ValueKind kind,
425  const char *key)
426 {
427  const char *value;
428 
429  value = NULL;
430  (void) MHD_lookup_connection_value_n (connection,
431  kind,
432  key,
433  (NULL == key) ? 0 : strlen (key),
434  &value,
435  NULL);
436  return value;
437 }
438 
439 
461  enum MHD_ValueKind kind,
462  const char *key,
463  size_t key_size,
464  const char **value_ptr,
465  size_t *value_size_ptr)
466 {
467  struct MHD_HTTP_Header *pos;
468 
469  if (NULL == connection)
470  return MHD_NO;
471 
472  if (NULL == key)
473  {
474  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
475  {
476  if ( (0 != (kind & pos->kind)) &&
477  (NULL == pos->header) )
478  break;
479  }
480  }
481  else
482  {
483  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
484  {
485  if ( (0 != (kind & pos->kind)) &&
486  (key_size == pos->header_size) &&
487  ( (key == pos->header) ||
489  pos->header,
490  key_size) ) ) )
491  break;
492  }
493  }
494 
495  if (NULL == pos)
496  return MHD_NO;
497 
498  if (NULL != value_ptr)
499  *value_ptr = pos->value;
500 
501  if (NULL != value_size_ptr)
502  *value_size_ptr = pos->value_size;
503 
504  return MHD_YES;
505 }
506 
507 
523 static bool
524 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
525  const char *header,
526  size_t header_len,
527  const char *token,
528  size_t token_len)
529 {
530  struct MHD_HTTP_Header *pos;
531 
532  if ((NULL == connection) || (NULL == header) || (0 == header[0]) || (NULL ==
533  token) ||
534  (0 ==
535  token
536  [
537  0]) )
538  return false;
539 
540  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
541  {
542  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
543  (header_len == pos->header_size) &&
544  ( (header == pos->header) ||
546  pos->header,
547  header_len)) ) &&
548  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
549  return true;
550  }
551  return false;
552 }
553 
554 
566 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
567  MHD_lookup_header_token_ci ((c),(h),MHD_STATICSTR_LEN_ (h), \
568  (tkn),MHD_STATICSTR_LEN_ (tkn))
569 
570 
578 static bool
579 need_100_continue (struct MHD_Connection *connection)
580 {
581  const char *expect;
582 
583  return ( (NULL != connection->version) &&
584  (MHD_str_equal_caseless_ (connection->version,
586  (MHD_NO != MHD_lookup_connection_value_n (connection,
591  &expect,
592  NULL)) &&
593  (MHD_str_equal_caseless_ (expect,
594  "100-continue")) );
595 }
596 
597 
604 void
606 {
607  const struct MHD_Daemon *daemon = connection->daemon;
608 
609  connection->state = MHD_CONNECTION_CLOSED;
611  if (0 == (daemon->options & MHD_USE_TURBO))
612  {
613 #ifdef HTTPS_SUPPORT
614  /* For TLS connection use shutdown of TLS layer
615  * and do not shutdown TCP socket. This give more
616  * chances to send TLS closure data to remote side.
617  * Closure of TLS layer will be interpreted by
618  * remote side as end of transmission. */
619  if (0 != (daemon->options & MHD_USE_TLS))
620  {
621  if (! MHD_tls_connection_shutdown (connection))
622  shutdown (connection->socket_fd,
623  SHUT_WR);
624  }
625  else /* Combined with next 'shutdown()'. */
626 #endif /* HTTPS_SUPPORT */
627  shutdown (connection->socket_fd,
628  SHUT_WR);
629  }
630 }
631 
632 
642 void
644  enum MHD_RequestTerminationCode termination_code)
645 {
646  struct MHD_Daemon *daemon = connection->daemon;
647  struct MHD_Response *resp = connection->response;
648 
649 #ifdef MHD_USE_THREADS
650  mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
651  MHD_thread_ID_match_current_ (connection->pid) );
652 #endif /* MHD_USE_THREADS */
653 
654  MHD_connection_mark_closed_ (connection);
655  if (NULL != resp)
656  {
657  connection->response = NULL;
658  MHD_destroy_response (resp);
659  }
660  if ( (NULL != daemon->notify_completed) &&
661  (connection->client_aware) )
662  daemon->notify_completed (daemon->notify_completed_cls,
663  connection,
664  &connection->client_context,
665  termination_code);
666  connection->client_aware = false;
667 }
668 
669 
670 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
681 void
683 {
684  struct MHD_Daemon *daemon = connection->daemon;
685  struct MHD_UpgradeResponseHandle *urh = connection->urh;
686 
687 #ifdef MHD_USE_THREADS
688  mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
689  (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || \
690  MHD_thread_ID_match_current_ (daemon->pid) );
691 #endif /* MHD_USE_THREADS */
692 
693  if (0 == (daemon->options & MHD_USE_TLS))
694  return; /* Nothing to do with non-TLS connection. */
695 
696  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
697  DLL_remove (daemon->urh_head,
698  daemon->urh_tail,
699  urh);
700 #if EPOLL_SUPPORT
701  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
702  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
703  EPOLL_CTL_DEL,
704  connection->socket_fd,
705  NULL)) )
706  {
707  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
708  }
709  if (urh->in_eready_list)
710  {
711  EDLL_remove (daemon->eready_urh_head,
712  daemon->eready_urh_tail,
713  urh);
714  urh->in_eready_list = false;
715  }
716 #endif /* EPOLL_SUPPORT */
717  if (MHD_INVALID_SOCKET != urh->mhd.socket)
718  {
719 #if EPOLL_SUPPORT
720  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
721  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
722  EPOLL_CTL_DEL,
723  urh->mhd.socket,
724  NULL)) )
725  {
726  MHD_PANIC (_ ("Failed to remove FD from epoll set.\n"));
727  }
728 #endif /* EPOLL_SUPPORT */
729  /* Reflect remote disconnect to application by breaking
730  * socketpair connection. */
731  shutdown (urh->mhd.socket, SHUT_RDWR);
732  }
733  /* Socketpair sockets will remain open as they will be
734  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
735  * closed by cleanup_upgraded_connection() during
736  * connection's final cleanup.
737  */
738 }
739 
740 
741 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
742 
743 
751 static void
753  const char *emsg)
754 {
755 #ifdef HAVE_MESSAGES
756  if (NULL != emsg)
757  MHD_DLOG (connection->daemon,
758  emsg);
759 #else /* ! HAVE_MESSAGES */
760  (void) emsg; /* Mute compiler warning. */
761 #endif /* ! HAVE_MESSAGES */
762  MHD_connection_close_ (connection,
764 }
765 
766 
771 #ifdef HAVE_MESSAGES
772 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
773 #else
774 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
775 #endif
776 
777 
790 static enum MHD_Result
791 try_ready_normal_body (struct MHD_Connection *connection)
792 {
793  ssize_t ret;
794  struct MHD_Response *response;
795 
796  response = connection->response;
797  if (NULL == response->crc)
798  return MHD_YES;
799  if ( (0 == response->total_size) ||
800  (connection->response_write_position == response->total_size) )
801  return MHD_YES; /* 0-byte response is always ready */
802  if ( (response->data_start <=
803  connection->response_write_position) &&
804  (response->data_size + response->data_start >
805  connection->response_write_position) )
806  return MHD_YES; /* response already ready */
807 #if defined(_MHD_HAVE_SENDFILE)
808  if (MHD_resp_sender_sendfile == connection->resp_sender)
809  {
810  /* will use sendfile, no need to bother response crc */
811  return MHD_YES;
812  }
813 #endif /* _MHD_HAVE_SENDFILE */
814 
815  ret = response->crc (response->crc_cls,
816  connection->response_write_position,
817  response->data,
818  (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
819  response->total_size
820  - connection->response_write_position));
821  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
822  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
823  {
824  /* either error or http 1.0 transfer, close socket! */
825  response->total_size = connection->response_write_position;
826 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
827  MHD_mutex_unlock_chk_ (&response->mutex);
828 #endif
829  if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
830  MHD_connection_close_ (connection,
832  else
833  CONNECTION_CLOSE_ERROR (connection,
834  _ (
835  "Closing connection (application reported error generating data).\n"));
836  return MHD_NO;
837  }
838  response->data_start = connection->response_write_position;
839  response->data_size = ret;
840  if (0 == ret)
841  {
843 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
844  MHD_mutex_unlock_chk_ (&response->mutex);
845 #endif
846  return MHD_NO;
847  }
848  return MHD_YES;
849 }
850 
851 
861 static enum MHD_Result
862 try_ready_chunked_body (struct MHD_Connection *connection)
863 {
864  ssize_t ret;
865  struct MHD_Response *response;
866  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
867  int cblen;
868 
869  response = connection->response;
870  if (NULL == response->crc)
871  return MHD_YES;
872  if (0 == connection->write_buffer_size)
873  {
874  size_t size;
875 
876  size = MHD_pool_get_free (connection->pool);
877  if (size < 128)
878  {
879 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
880  MHD_mutex_unlock_chk_ (&response->mutex);
881 #endif
882  /* not enough memory */
883  CONNECTION_CLOSE_ERROR (connection,
884  _ ("Closing connection (out of memory).\n"));
885  return MHD_NO;
886  }
887  if ( (2 * (0xFFFFFF + sizeof(cbuf) + 2)) < size)
888  size = 2 * (0xFFFFFF + sizeof(cbuf) + 2);
889  connection->write_buffer = MHD_pool_allocate (connection->pool,
890  size,
891  false);
892  mhd_assert (NULL != connection->write_buffer);
893  connection->write_buffer_size = size;
894  }
895 
896  if (0 == response->total_size)
897  ret = 0; /* response must be empty, don't bother calling crc */
898  else if ( (response->data_start <=
899  connection->response_write_position) &&
900  (response->data_start + response->data_size >
901  connection->response_write_position) )
902  {
903  /* difference between response_write_position and data_start is less
904  than data_size which is size_t type, no need to check for overflow */
905  const size_t data_write_offset
906  = (size_t) (connection->response_write_position - response->data_start);
907  /* buffer already ready, use what is there for the chunk */
908  ret = response->data_size - data_write_offset;
909  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2)
910  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
911  memcpy (&connection->write_buffer[sizeof (cbuf)],
912  &response->data[data_write_offset],
913  ret);
914  }
915  else
916  {
917  /* buffer not in range, try to fill it */
918  ret = response->crc (response->crc_cls,
919  connection->response_write_position,
920  &connection->write_buffer[sizeof (cbuf)],
921  connection->write_buffer_size - sizeof (cbuf) - 2);
922  }
923  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
924  {
925  /* error, close socket! */
926  response->total_size = connection->response_write_position;
927 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
928  MHD_mutex_unlock_chk_ (&response->mutex);
929 #endif
930  CONNECTION_CLOSE_ERROR (connection,
931  _ (
932  "Closing connection (application error generating response).\n"));
933  return MHD_NO;
934  }
935  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
936  (0 == response->total_size) )
937  {
938  /* end of message, signal other side! */
939  memcpy (connection->write_buffer,
940  "0\r\n",
941  3);
942  connection->write_buffer_append_offset = 3;
943  connection->write_buffer_send_offset = 0;
944  response->total_size = connection->response_write_position;
945  return MHD_YES;
946  }
947  if (0 == ret)
948  {
950 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
951  MHD_mutex_unlock_chk_ (&response->mutex);
952 #endif
953  return MHD_NO;
954  }
955  if (ret > 0xFFFFFF)
956  ret = 0xFFFFFF;
957  cblen = MHD_snprintf_ (cbuf,
958  sizeof (cbuf),
959  "%X\r\n",
960  (unsigned int) ret);
961  mhd_assert (cblen > 0);
962  mhd_assert ((size_t) cblen < sizeof(cbuf));
963  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
964  cbuf,
965  cblen);
966  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
967  "\r\n",
968  2);
969  connection->response_write_position += ret;
970  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
971  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
972  return MHD_YES;
973 }
974 
975 
992 static enum MHD_Result
993 keepalive_possible (struct MHD_Connection *connection)
994 {
995  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
996  return MHD_NO;
997  if (NULL == connection->version)
998  return MHD_NO;
999  if ( (NULL != connection->response) &&
1000  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1001  return MHD_NO;
1002 
1003  if (MHD_str_equal_caseless_ (connection->version,
1005  ( (NULL == connection->response) ||
1006  (0 == (connection->response->flags
1008  {
1009  if (MHD_lookup_header_s_token_ci (connection,
1011  "upgrade"))
1012  return MHD_NO;
1013 
1014  if (MHD_lookup_header_s_token_ci (connection,
1016  "close"))
1017  return MHD_NO;
1018 
1019  return MHD_YES;
1020  }
1021  if (MHD_str_equal_caseless_ (connection->version,
1023  {
1024  if (MHD_lookup_header_s_token_ci (connection,
1026  "Keep-Alive"))
1027  return MHD_YES;
1028 
1029  return MHD_NO;
1030  }
1031  return MHD_NO;
1032 }
1033 
1034 
1042 static void
1043 get_date_string (char *date,
1044  size_t date_len)
1045 {
1046  static const char *const days[] = {
1047  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1048  };
1049  static const char *const mons[] = {
1050  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1051  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1052  };
1053  struct tm now;
1054  time_t t;
1055 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1056  ! defined(HAVE_GMTIME_R)
1057  struct tm*pNow;
1058 #endif
1059 
1060  date[0] = 0;
1061  time (&t);
1062 #if defined(HAVE_C11_GMTIME_S)
1063  if (NULL == gmtime_s (&t,
1064  &now))
1065  return;
1066 #elif defined(HAVE_W32_GMTIME_S)
1067  if (0 != gmtime_s (&now,
1068  &t))
1069  return;
1070 #elif defined(HAVE_GMTIME_R)
1071  if (NULL == gmtime_r (&t,
1072  &now))
1073  return;
1074 #else
1075  pNow = gmtime (&t);
1076  if (NULL == pNow)
1077  return;
1078  now = *pNow;
1079 #endif
1080  MHD_snprintf_ (date,
1081  date_len,
1082  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1083  days[now.tm_wday % 7],
1084  (unsigned int) now.tm_mday,
1085  mons[now.tm_mon % 12],
1086  (unsigned int) (1900 + now.tm_year),
1087  (unsigned int) now.tm_hour,
1088  (unsigned int) now.tm_min,
1089  (unsigned int) now.tm_sec);
1090 }
1091 
1092 
1105 static bool
1107  bool required)
1108 {
1109  size_t new_size;
1110  size_t avail_size;
1111  void *rb;
1112 
1113  avail_size = MHD_pool_get_free (connection->pool);
1114  if (0 == avail_size)
1115  return false; /* No more space available */
1116  if (0 == connection->read_buffer_size)
1117  new_size = avail_size / 2; /* Use half of available buffer for reading */
1118  else
1119  {
1120  size_t grow_size;
1121 
1122  grow_size = avail_size / 8;
1123  if (MHD_BUF_INC_SIZE > grow_size)
1124  { /* Shortage of space */
1125  if (! required)
1126  return false; /* Grow is not mandatory, leave some space in pool */
1127  else
1128  {
1129  /* Shortage of space, but grow is mandatory */
1130  static const size_t small_inc = MHD_BUF_INC_SIZE / 8;
1131  if (small_inc < avail_size)
1132  grow_size = small_inc;
1133  else
1134  grow_size = avail_size;
1135  }
1136  }
1137  new_size = connection->read_buffer_size + grow_size;
1138  }
1139  /* we can actually grow the buffer, do it! */
1140  rb = MHD_pool_reallocate (connection->pool,
1141  connection->read_buffer,
1142  connection->read_buffer_size,
1143  new_size);
1144  if (NULL == rb)
1145  {
1146  /* This should NOT be possible: we just computed 'new_size' so that
1147  it should fit. If it happens, somehow our read buffer is not in
1148  the right position in the pool, say because someone called
1149  MHD_pool_allocate() without 'from_end' set to 'true'? Anyway,
1150  should be investigated! (Ideally provide all data from
1151  *pool and connection->read_buffer and new_size for debugging). */
1152  mhd_assert (0);
1153  return false;
1154  }
1155  connection->read_buffer = rb;
1156  mhd_assert (NULL != connection->read_buffer);
1157  connection->read_buffer_size = new_size;
1158  return true;
1159 }
1160 
1161 
1171 static enum MHD_Result
1172 build_header_response (struct MHD_Connection *connection)
1173 {
1174  struct MHD_Response *response = connection->response;
1175  size_t size;
1176  size_t off;
1177  struct MHD_HTTP_Header *pos;
1178  char code[256];
1179  char date[128];
1180  size_t datelen;
1181  char content_length_buf[128];
1182  size_t content_length_len;
1183  char *data;
1184  enum MHD_ValueKind kind;
1185  const char *reason_phrase;
1186  uint32_t rc;
1187  bool client_requested_close;
1188  bool response_has_close;
1189  bool response_has_keepalive;
1190  const char *have_encoding;
1191  bool must_add_close;
1192  bool must_add_chunked_encoding;
1193  bool must_add_keep_alive;
1194  bool must_add_content_length;
1195  bool may_add_content_length;
1196 
1197  mhd_assert (NULL != connection->version);
1198  if (0 == connection->version[0])
1199  {
1200  data = MHD_pool_allocate (connection->pool,
1201  0,
1202  true);
1203  connection->write_buffer = data;
1204  connection->write_buffer_append_offset = 0;
1205  connection->write_buffer_send_offset = 0;
1206  connection->write_buffer_size = 0;
1207  return MHD_YES;
1208  }
1209  rc = connection->responseCode & (~MHD_ICY_FLAG);
1210  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1211  {
1212  reason_phrase = MHD_get_reason_phrase_for (rc);
1213  off = MHD_snprintf_ (code,
1214  sizeof (code),
1215  "%s %u %s\r\n",
1216  (0 != (connection->responseCode & MHD_ICY_FLAG))
1217  ? "ICY"
1219  connection->version) ||
1220  (0 != (connection->response->flags
1224  rc,
1225  reason_phrase);
1226  /* estimate size */
1227  size = off + 2; /* +2 for extra "\r\n" at the end */
1229  if ( (0 == (connection->daemon->options
1231  (NULL == MHD_get_response_header (response,
1233  get_date_string (date,
1234  sizeof (date));
1235  else
1236  date[0] = '\0';
1237  datelen = strlen (date);
1238  size += datelen;
1239  }
1240  else
1241  {
1242  /* 2 bytes for final CRLF of a Chunked-Body */
1243  size = 2;
1245  off = 0;
1246  datelen = 0;
1247  }
1248 
1249  /* calculate extra headers we need to add, such as 'Connection: close',
1250  first see what was explicitly requested by the application */
1251  must_add_close = false;
1252  must_add_chunked_encoding = false;
1253  must_add_keep_alive = false;
1254  must_add_content_length = false;
1255  response_has_close = false;
1256  switch (connection->state)
1257  {
1259  response_has_close = MHD_check_response_header_s_token_ci (response,
1261  "close");
1262  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1264  "Keep-Alive");
1265  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1267  "close");
1268 
1269  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1270  connection->keepalive = MHD_CONN_MUST_CLOSE;
1271 #ifdef UPGRADE_SUPPORT
1272  else if (NULL != response->upgrade_handler)
1273  /* If this connection will not be "upgraded", it must be closed. */
1274  connection->keepalive = MHD_CONN_MUST_CLOSE;
1275 #endif /* UPGRADE_SUPPORT */
1276 
1277  /* now analyze chunked encoding situation */
1278  connection->have_chunked_upload = false;
1279  have_encoding = MHD_get_response_header (response,
1281  if (NULL == have_encoding)
1282  may_add_content_length = true;
1283  else
1284  may_add_content_length = false; /* RFC 7230, Section 3.3.2 forbids header */
1285  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1286 #ifdef UPGRADE_SUPPORT
1287  (NULL == response->upgrade_handler) &&
1288 #endif /* UPGRADE_SUPPORT */
1289  (! response_has_close) &&
1290  (! client_requested_close) )
1291  {
1292  /* size is unknown, and close was not explicitly requested;
1293  need to either to HTTP 1.1 chunked encoding or
1294  close the connection */
1295  /* 'close' header doesn't exist yet, see if we need to add one;
1296  if the client asked for a close, no need to start chunk'ing */
1297  if ( (MHD_NO != keepalive_possible (connection)) &&
1299  connection->version) ) )
1300  {
1301  if (NULL == have_encoding)
1302  {
1303  must_add_chunked_encoding = true;
1304  connection->have_chunked_upload = true;
1305  }
1306  else
1307  {
1308  if (MHD_str_equal_caseless_ (have_encoding,
1309  "identity"))
1310  {
1311  /* application forced identity encoding, can't do 'chunked' */
1312  must_add_close = true;
1313  }
1314  else
1315  {
1316  connection->have_chunked_upload = true;
1317  }
1318  }
1319  }
1320  else
1321  {
1322  /* Keep alive or chunking not possible
1323  => set close header (we know response_has_close
1324  is false here) */
1325  must_add_close = true;
1326  }
1327  }
1328 
1329  /* check for other reasons to add 'close' header */
1330  if ( ( (client_requested_close) ||
1331  (connection->read_closed) ||
1332  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1333  (! response_has_close) &&
1334 #ifdef UPGRADE_SUPPORT
1335  (NULL == response->upgrade_handler) &&
1336 #endif /* UPGRADE_SUPPORT */
1337  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1338  must_add_close = true;
1339 
1340  /* check if we must add 'close' header because we cannot add content-length
1341  because it is forbidden AND we don't have a 'chunked' encoding */
1342  if ( (! may_add_content_length) &&
1343  (! connection->have_chunked_upload) &&
1344  (! response_has_close) )
1345  must_add_close = true;
1346  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1347  codes SHOULD NOT have a Content-Length according to spec;
1348  also chunked encoding / unknown length or CONNECT... */
1349  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1350  (MHD_HTTP_NO_CONTENT != rc) &&
1351  (MHD_HTTP_NOT_MODIFIED != rc) &&
1352  (MHD_HTTP_OK <= rc) &&
1353  (NULL == /* this COULD fail if the check in
1354  MHD_add_response_header() was bypassed
1355  via #MHD_RF_INSANITY_HEADER_CONTENT_LENGTH */
1356  MHD_get_response_header (response,
1358  (may_add_content_length) &&
1359  ( (NULL == connection->method) ||
1360  (! MHD_str_equal_caseless_ (connection->method,
1362  {
1363  /*
1364  Here we add a content-length if one is missing; however,
1365  for 'connect' methods, the responses MUST NOT include a
1366  content-length header *if* the response code is 2xx (in
1367  which case we expect there to be no body). Still,
1368  as we don't know the response code here in some cases, we
1369  simply only force adding a content-length header if this
1370  is not a 'connect' or if the response is not empty
1371  (which is kind of more sane, because if some crazy
1372  application did return content with a 2xx status code,
1373  then having a content-length might again be a good idea).
1374 
1375  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1376  a recent development of the HTTP 1.1 specification.
1377  */
1378  content_length_len
1379  = MHD_snprintf_ (content_length_buf,
1380  sizeof (content_length_buf),
1383  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1384  must_add_content_length = true;
1385  }
1386 
1387  /* check for adding keep alive */
1388  if ( (! response_has_keepalive) &&
1389  (! response_has_close) &&
1390  (! must_add_close) &&
1391  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1392 #ifdef UPGRADE_SUPPORT
1393  (NULL == response->upgrade_handler) &&
1394 #endif /* UPGRADE_SUPPORT */
1395  (MHD_NO != keepalive_possible (connection)) )
1396  must_add_keep_alive = true;
1397  break;
1399  response_has_keepalive = false;
1400  break;
1401  default:
1402  mhd_assert (0);
1403  return MHD_NO;
1404  }
1405 
1406  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1407  {
1408  if ( (must_add_close) || (response_has_close) )
1409  connection->keepalive = MHD_CONN_MUST_CLOSE;
1410  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1411  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1412  }
1413 
1414  if (must_add_close)
1415  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1416  if (must_add_keep_alive)
1417  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1418  if (must_add_chunked_encoding)
1419  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1420  if (must_add_content_length)
1421  size += content_length_len;
1422  mhd_assert (! (must_add_close && must_add_keep_alive) );
1423  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1424 
1425  for (pos = response->first_header; NULL != pos; pos = pos->next)
1426  {
1427  /* TODO: add proper support for excluding "Keep-Alive" token. */
1428  if ( (pos->kind == kind) &&
1429  (! ( (must_add_close) &&
1430  (response_has_keepalive) &&
1431  (pos->header_size == MHD_STATICSTR_LEN_ (
1438  "Keep-Alive")) ) ) )
1439  size += pos->header_size + pos->value_size + 4; /* colon, space, linefeeds */
1440  }
1441  /* produce data */
1442  data = MHD_pool_allocate (connection->pool,
1443  size + 1,
1444  false);
1445  if (NULL == data)
1446  {
1447 #ifdef HAVE_MESSAGES
1448  MHD_DLOG (connection->daemon,
1449  "Not enough memory for write!\n");
1450 #endif
1451  return MHD_NO;
1452  }
1453  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1454  {
1455  memcpy (data,
1456  code,
1457  off);
1458  }
1459  if (must_add_close)
1460  {
1461  /* we must add the 'Connection: close' header */
1462  memcpy (&data[off],
1463  "Connection: close\r\n",
1464  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1465  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1466  }
1467  if (must_add_keep_alive)
1468  {
1469  /* we must add the 'Connection: Keep-Alive' header */
1470  memcpy (&data[off],
1471  "Connection: Keep-Alive\r\n",
1472  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1473  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1474  }
1475  if (must_add_chunked_encoding)
1476  {
1477  /* we must add the 'Transfer-Encoding: chunked' header */
1478  memcpy (&data[off],
1479  "Transfer-Encoding: chunked\r\n",
1480  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1481  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1482  }
1483  if (must_add_content_length)
1484  {
1485  /* we must add the 'Content-Length' header */
1486  memcpy (&data[off],
1487  content_length_buf,
1488  content_length_len);
1489  off += content_length_len;
1490  }
1491  for (pos = response->first_header; NULL != pos; pos = pos->next)
1492  {
1493  /* TODO: add proper support for excluding "Keep-Alive" token. */
1494  if ( (pos->kind == kind) &&
1495  (! ( (must_add_close) &&
1496  (response_has_keepalive) &&
1497  (pos->header_size == MHD_STATICSTR_LEN_ (
1504  "Keep-Alive")) ) ) )
1505  off += MHD_snprintf_ (&data[off],
1506  size - off,
1507  "%s: %s\r\n",
1508  pos->header,
1509  pos->value);
1510  }
1511  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1512  {
1513  memcpy (&data[off],
1514  date,
1515  datelen);
1516  off += datelen;
1517  }
1518  memcpy (&data[off],
1519  "\r\n",
1520  2);
1521  off += 2;
1522 
1523  if (off != size)
1525  __FILE__,
1526  __LINE__,
1527  NULL);
1528  connection->write_buffer = data;
1529  connection->write_buffer_append_offset = size;
1530  connection->write_buffer_send_offset = 0;
1531  connection->write_buffer_size = size + 1;
1532  return MHD_YES;
1533 }
1534 
1535 
1545 static void
1547  unsigned int status_code,
1548  const char *message)
1549 {
1550  struct MHD_Response *response;
1551  enum MHD_Result iret;
1552 
1553  if (NULL == connection->version)
1554  {
1555  /* we were unable to process the full header line, so we don't
1556  really know what version the client speaks; assume 1.0 */
1557  connection->version = MHD_HTTP_VERSION_1_0;
1558  }
1559  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1560  connection->read_closed = true;
1561  if (0 != connection->read_buffer_size)
1562  {
1563  /* Read buffer is not needed anymore, discard it
1564  * to free some space for error response. */
1565  connection->read_buffer = MHD_pool_reallocate (connection->pool,
1566  connection->read_buffer,
1567  connection->read_buffer_size,
1568  0);
1569  connection->read_buffer_size = 0;
1570  }
1571 #ifdef HAVE_MESSAGES
1572  MHD_DLOG (connection->daemon,
1573  _ (
1574  "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1575  status_code,
1576  message);
1577 #endif
1578  if (NULL != connection->response)
1579  {
1580  MHD_destroy_response (connection->response);
1581  connection->response = NULL;
1582  }
1583  response = MHD_create_response_from_buffer (strlen (message),
1584  (void *) message,
1586  if (NULL == response)
1587  {
1588  /* can't even send a reply, at least close the connection */
1589  connection->state = MHD_CONNECTION_CLOSED;
1590  return;
1591  }
1592  iret = MHD_queue_response (connection,
1593  status_code,
1594  response);
1595  MHD_destroy_response (response);
1596  if (MHD_NO == iret)
1597  {
1598  /* can't even send a reply, at least close the connection */
1599  CONNECTION_CLOSE_ERROR (connection,
1600  _ (
1601  "Closing connection (failed to queue response).\n"));
1602  return;
1603  }
1604  mhd_assert (NULL != connection->response);
1605  /* Do not reuse this connection. */
1606  connection->keepalive = MHD_CONN_MUST_CLOSE;
1607  if (MHD_NO == build_header_response (connection))
1608  {
1609  /* oops - close! */
1610  CONNECTION_CLOSE_ERROR (connection,
1611  _ (
1612  "Closing connection (failed to create response header).\n"));
1613  }
1614  else
1615  {
1616  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1617  }
1618 }
1619 
1620 
1629 static void
1631 {
1632  /* Do not update states of suspended connection */
1633  if (connection->suspended)
1634  return; /* States will be updated after resume. */
1635 #ifdef HTTPS_SUPPORT
1636  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1637  { /* HTTPS connection. */
1638  switch (connection->tls_state)
1639  {
1640  case MHD_TLS_CONN_INIT:
1642  return;
1644  if (0 == gnutls_record_get_direction (connection->tls_session))
1646  else
1648  return;
1649  default:
1650  break;
1651  }
1652  }
1653 #endif /* HTTPS_SUPPORT */
1654  while (1)
1655  {
1656 #if DEBUG_STATES
1657  MHD_DLOG (connection->daemon,
1658  _ ("In function %s handling connection at state: %s\n"),
1659  __FUNCTION__,
1660  MHD_state_to_string (connection->state));
1661 #endif
1662  switch (connection->state)
1663  {
1664  case MHD_CONNECTION_INIT:
1667  /* while reading headers, we always grow the
1668  read buffer if needed, no size-check required */
1669  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1670  (! try_grow_read_buffer (connection, true)) )
1671  {
1672  transmit_error_response (connection,
1673  (connection->url != NULL)
1676  REQUEST_TOO_BIG);
1677  continue;
1678  }
1679  if (! connection->read_closed)
1681  else
1683  break;
1685  mhd_assert (0);
1686  break;
1688  mhd_assert (0);
1689  break;
1692  break;
1694  if (connection->read_buffer_offset == connection->read_buffer_size)
1695  {
1696  const bool internal_poll = (0 != (connection->daemon->options
1698  if ( (! try_grow_read_buffer (connection, true)) &&
1699  internal_poll)
1700  {
1701  /* failed to grow the read buffer, and the
1702  client which is supposed to handle the
1703  received data in a *blocking* fashion
1704  (in this mode) did not handle the data as
1705  it was supposed to!
1706  => we would either have to do busy-waiting
1707  (on the client, which would likely fail),
1708  or if we do nothing, we would just timeout
1709  on the connection (if a timeout is even
1710  set!).
1711  Solution: we kill the connection with an error */
1712  transmit_error_response (connection,
1714  INTERNAL_ERROR);
1715  continue;
1716  }
1717  }
1718  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1719  (! connection->read_closed) )
1721  else
1723  break;
1726  /* while reading footers, we always grow the
1727  read buffer if needed, no size-check required */
1728  if (connection->read_closed)
1729  {
1730  CONNECTION_CLOSE_ERROR (connection,
1731  NULL);
1732  continue;
1733  }
1735  /* transition to FOOTERS_RECEIVED
1736  happens in read handler */
1737  break;
1740  break;
1742  /* headers in buffer, keep writing */
1744  break;
1746  mhd_assert (0);
1747  break;
1750  break;
1753  break;
1756  break;
1759  break;
1761  mhd_assert (0);
1762  break;
1765  break;
1767  mhd_assert (0);
1768  break;
1769  case MHD_CONNECTION_CLOSED:
1771  return; /* do nothing, not even reading */
1772 #ifdef UPGRADE_SUPPORT
1773  case MHD_CONNECTION_UPGRADE:
1774  mhd_assert (0);
1775  break;
1776 #endif /* UPGRADE_SUPPORT */
1777  default:
1778  mhd_assert (0);
1779  }
1780  break;
1781  }
1782 }
1783 
1784 
1798 static char *
1800  size_t *line_len)
1801 {
1802  char *rbuf;
1803  size_t pos;
1804 
1805  if (0 == connection->read_buffer_offset)
1806  return NULL;
1807  pos = 0;
1808  rbuf = connection->read_buffer;
1809  while ( (pos < connection->read_buffer_offset - 1) &&
1810  ('\r' != rbuf[pos]) &&
1811  ('\n' != rbuf[pos]) )
1812  pos++;
1813  if ( (pos == connection->read_buffer_offset - 1) &&
1814  ('\n' != rbuf[pos]) )
1815  {
1816  /* not found, consider growing... */
1817  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1818  (! try_grow_read_buffer (connection, true)) )
1819  {
1820  transmit_error_response (connection,
1821  (NULL != connection->url)
1824  REQUEST_TOO_BIG);
1825  }
1826  if (line_len)
1827  *line_len = 0;
1828  return NULL;
1829  }
1830 
1831  if (line_len)
1832  *line_len = pos;
1833  /* found, check if we have proper LFCR */
1834  if ( ('\r' == rbuf[pos]) &&
1835  ('\n' == rbuf[pos + 1]) )
1836  rbuf[pos++] = '\0'; /* skip both r and n */
1837  rbuf[pos++] = '\0';
1838  connection->read_buffer += pos;
1839  connection->read_buffer_size -= pos;
1840  connection->read_buffer_offset -= pos;
1841  return rbuf;
1842 }
1843 
1844 
1858 static enum MHD_Result
1859 connection_add_header (struct MHD_Connection *connection,
1860  const char *key,
1861  size_t key_size,
1862  const char *value,
1863  size_t value_size,
1864  enum MHD_ValueKind kind)
1865 {
1866  if (MHD_NO ==
1867  MHD_set_connection_value_n (connection,
1868  kind,
1869  key,
1870  key_size,
1871  value,
1872  value_size))
1873  {
1874 #ifdef HAVE_MESSAGES
1875  MHD_DLOG (connection->daemon,
1876  _ ("Not enough memory in pool to allocate header record!\n"));
1877 #endif
1878  transmit_error_response (connection,
1880  REQUEST_TOO_BIG);
1881  return MHD_NO;
1882  }
1883  return MHD_YES;
1884 }
1885 
1886 
1893 static enum MHD_Result
1894 parse_cookie_header (struct MHD_Connection *connection)
1895 {
1896  const char *hdr;
1897  size_t hdr_len;
1898  char *cpy;
1899  char *pos;
1900  char *sce;
1901  char *semicolon;
1902  char *equals;
1903  char *ekill;
1904  char *end;
1905  char old;
1906  int quotes;
1907 
1908  if (MHD_NO == MHD_lookup_connection_value_n (connection,
1913  &hdr,
1914  &hdr_len))
1915  return MHD_YES;
1916  cpy = MHD_pool_allocate (connection->pool,
1917  hdr_len + 1,
1918  true);
1919  if (NULL == cpy)
1920  {
1921 #ifdef HAVE_MESSAGES
1922  MHD_DLOG (connection->daemon,
1923  _ ("Not enough memory in pool to parse cookies!\n"));
1924 #endif
1925  transmit_error_response (connection,
1927  REQUEST_TOO_BIG);
1928  return MHD_NO;
1929  }
1930  memcpy (cpy,
1931  hdr,
1932  hdr_len);
1933  cpy[hdr_len] = '\0';
1934  pos = cpy;
1935  while (NULL != pos)
1936  {
1937  while (' ' == *pos)
1938  pos++; /* skip spaces */
1939 
1940  sce = pos;
1941  while ( ((*sce) != '\0') &&
1942  ((*sce) != ',') &&
1943  ((*sce) != ';') &&
1944  ((*sce) != '=') )
1945  sce++;
1946  /* remove tailing whitespace (if any) from key */
1947  ekill = sce - 1;
1948  while ( (*ekill == ' ') &&
1949  (ekill >= pos) )
1950  *(ekill--) = '\0';
1951  old = *sce;
1952  *sce = '\0';
1953  if (old != '=')
1954  {
1955  /* value part omitted, use empty string... */
1956  if (MHD_NO ==
1957  connection_add_header (connection,
1958  pos,
1959  ekill - pos + 1,
1960  "",
1961  0,
1962  MHD_COOKIE_KIND))
1963  return MHD_NO;
1964  if (old == '\0')
1965  break;
1966  pos = sce + 1;
1967  continue;
1968  }
1969  equals = sce + 1;
1970  quotes = 0;
1971  semicolon = equals;
1972  while ( ('\0' != semicolon[0]) &&
1973  ( (0 != quotes) ||
1974  ( (';' != semicolon[0]) &&
1975  (',' != semicolon[0]) ) ) )
1976  {
1977  if ('"' == semicolon[0])
1978  quotes = (quotes + 1) & 1;
1979  semicolon++;
1980  }
1981  end = semicolon;
1982  if ('\0' == semicolon[0])
1983  semicolon = NULL;
1984  if (NULL != semicolon)
1985  {
1986  semicolon[0] = '\0';
1987  semicolon++;
1988  }
1989  /* remove quotes */
1990  if ( ('"' == equals[0]) &&
1991  ('"' == end[-1]) )
1992  {
1993  equals++;
1994  end--;
1995  *end = '\0';
1996  }
1997  if (MHD_NO ==
1998  connection_add_header (connection,
1999  pos,
2000  ekill - pos + 1,
2001  equals,
2002  end - equals,
2003  MHD_COOKIE_KIND))
2004  return MHD_NO;
2005  pos = semicolon;
2006  }
2007  return MHD_YES;
2008 }
2009 
2010 
2019 static enum MHD_Result
2020 parse_initial_message_line (struct MHD_Connection *connection,
2021  char *line,
2022  size_t line_len)
2023 {
2024  struct MHD_Daemon *daemon = connection->daemon;
2025  const char *curi;
2026  char *uri;
2027  char *http_version;
2028  char *args;
2029  unsigned int unused_num_headers;
2030 
2031  if (NULL == (uri = memchr (line,
2032  ' ',
2033  line_len)))
2034  return MHD_NO; /* serious error */
2035  uri[0] = '\0';
2036  connection->method = line;
2037  uri++;
2038  /* Skip any spaces. Not required by standard but allow
2039  to be more tolerant. */
2040  while ( (' ' == uri[0]) &&
2041  ( (size_t) (uri - line) < line_len) )
2042  uri++;
2043  if ((size_t) (uri - line) == line_len)
2044  {
2045  /* No URI and no http version given */
2046  curi = "";
2047  uri = NULL;
2048  connection->version = "";
2049  args = NULL;
2050  }
2051  else
2052  {
2053  size_t uri_len;
2054  curi = uri;
2055  /* Search from back to accept malformed URI with space */
2056  http_version = line + line_len - 1;
2057  /* Skip any trailing spaces */
2058  while ( (' ' == http_version[0]) &&
2059  (http_version > uri) )
2060  http_version--;
2061  /* Find first space in reverse direction */
2062  while ( (' ' != http_version[0]) &&
2063  (http_version > uri) )
2064  http_version--;
2065  if (http_version > uri)
2066  {
2067  /* http_version points to character before HTTP version string */
2068  http_version[0] = '\0';
2069  connection->version = http_version + 1;
2070  uri_len = http_version - uri;
2071  }
2072  else
2073  {
2074  connection->version = "";
2075  uri_len = line_len - (uri - line);
2076  }
2077  /* check for spaces in URI if we are "strict" */
2078  if ( (1 <= daemon->strict_for_client) &&
2079  (NULL != memchr (uri,
2080  ' ',
2081  uri_len)) )
2082  {
2083  /* space exists in URI and we are supposed to be strict, reject */
2084  return MHD_NO;
2085  }
2086 
2087  args = memchr (uri,
2088  '?',
2089  uri_len);
2090  }
2091 
2092  /* log callback before we modify URI *or* args */
2093  if (NULL != daemon->uri_log_callback)
2094  {
2095  connection->client_aware = true;
2096  connection->client_context
2097  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2098  uri,
2099  connection);
2100  }
2101 
2102  if (NULL != args)
2103  {
2104  args[0] = '\0';
2105  args++;
2106  /* note that this call clobbers 'args' */
2107  MHD_parse_arguments_ (connection,
2109  args,
2111  &unused_num_headers);
2112  }
2113 
2114  /* unescape URI *after* searching for arguments and log callback */
2115  if (NULL != uri)
2116  daemon->unescape_callback (daemon->unescape_callback_cls,
2117  connection,
2118  uri);
2119  connection->url = curi;
2120  return MHD_YES;
2121 }
2122 
2123 
2131 static void
2133 {
2134  struct MHD_Daemon *daemon = connection->daemon;
2135  size_t processed;
2136 
2137  if (NULL != connection->response)
2138  return; /* already queued a response */
2139  processed = 0;
2140  connection->client_aware = true;
2141  if (MHD_NO ==
2142  daemon->default_handler (daemon->default_handler_cls,
2143  connection,
2144  connection->url,
2145  connection->method,
2146  connection->version,
2147  NULL,
2148  &processed,
2149  &connection->client_context))
2150  {
2151  /* serious internal error, close connection */
2152  CONNECTION_CLOSE_ERROR (connection,
2153  _ (
2154  "Application reported internal error, closing connection.\n"));
2155  return;
2156  }
2157 }
2158 
2159 
2167 static void
2169 {
2170  struct MHD_Daemon *daemon = connection->daemon;
2171  size_t available;
2172  int instant_retry;
2173  char *buffer_head;
2174 
2175  if (NULL != connection->response)
2176  {
2177  /* already queued a response, discard remaining upload
2178  (but not more, there might be another request after it) */
2179  size_t purge;
2180 
2181  purge = (size_t) MHD_MIN (connection->remaining_upload_size,
2182  (uint64_t) connection->read_buffer_offset);
2183  connection->remaining_upload_size -= purge;
2184  if (connection->read_buffer_offset > purge)
2185  memmove (connection->read_buffer,
2186  &connection->read_buffer[purge],
2187  connection->read_buffer_offset - purge);
2188  connection->read_buffer_offset -= purge;
2189  return;
2190  }
2191 
2192  buffer_head = connection->read_buffer;
2193  available = connection->read_buffer_offset;
2194  do
2195  {
2196  size_t to_be_processed;
2197  size_t left_unprocessed;
2198  size_t processed_size;
2199 
2200  instant_retry = MHD_NO;
2201  if ( (connection->have_chunked_upload) &&
2202  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2203  {
2204  if ( (connection->current_chunk_offset ==
2205  connection->current_chunk_size) &&
2206  (0LLU != connection->current_chunk_offset) &&
2207  (available >= 2) )
2208  {
2209  size_t i;
2210  /* skip new line at the *end* of a chunk */
2211  i = 0;
2212  if ( ('\r' == buffer_head[i]) ||
2213  ('\n' == buffer_head[i]) )
2214  i++; /* skip 1st part of line feed */
2215  if ( ('\r' == buffer_head[i]) ||
2216  ('\n' == buffer_head[i]) )
2217  i++; /* skip 2nd part of line feed */
2218  if (0 == i)
2219  {
2220  /* malformed encoding */
2221  CONNECTION_CLOSE_ERROR (connection,
2222  _ (
2223  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2224  return;
2225  }
2226  available -= i;
2227  buffer_head += i;
2228  connection->current_chunk_offset = 0;
2229  connection->current_chunk_size = 0;
2230  }
2231  if (connection->current_chunk_offset <
2232  connection->current_chunk_size)
2233  {
2234  uint64_t cur_chunk_left;
2235  /* we are in the middle of a chunk, give
2236  as much as possible to the client (without
2237  crossing chunk boundaries) */
2238  cur_chunk_left
2239  = connection->current_chunk_size - connection->current_chunk_offset;
2240  if (cur_chunk_left > available)
2241  to_be_processed = available;
2242  else
2243  { /* cur_chunk_left <= (size_t)available */
2244  to_be_processed = (size_t) cur_chunk_left;
2245  if (available > to_be_processed)
2246  instant_retry = MHD_YES;
2247  }
2248  }
2249  else
2250  {
2251  size_t i;
2252  size_t end_size;
2253  bool malformed;
2254 
2255  /* we need to read chunk boundaries */
2256  i = 0;
2257  while (i < available)
2258  {
2259  if ( ('\r' == buffer_head[i]) ||
2260  ('\n' == buffer_head[i]) ||
2261  (';' == buffer_head[i]) )
2262  break;
2263  i++;
2264  if (i >= 16)
2265  break;
2266  }
2267  end_size = i;
2268  /* find beginning of CRLF (skip over chunk extensions) */
2269  if (';' == buffer_head[i])
2270  {
2271  while (i < available)
2272  {
2273  if ( ('\r' == buffer_head[i]) ||
2274  ('\n' == buffer_head[i]) )
2275  break;
2276  i++;
2277  }
2278  }
2279  /* take '\n' into account; if '\n' is the unavailable
2280  character, we will need to wait until we have it
2281  before going further */
2282  if ( (i + 1 >= available) &&
2283  ! ( (1 == i) &&
2284  (2 == available) &&
2285  ('0' == buffer_head[0]) ) )
2286  break; /* need more data... */
2287  i++;
2288  malformed = (end_size >= 16);
2289  if (! malformed)
2290  {
2291  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2292  end_size,
2293  &connection->
2294  current_chunk_size);
2295  malformed = (end_size != num_dig);
2296  }
2297  if (malformed)
2298  {
2299  /* malformed encoding */
2300  CONNECTION_CLOSE_ERROR (connection,
2301  _ (
2302  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2303  return;
2304  }
2305  /* skip 2nd part of line feed */
2306  if ( (i < available) &&
2307  ( ('\r' == buffer_head[i]) ||
2308  ('\n' == buffer_head[i]) ) )
2309  i++;
2310 
2311  buffer_head += i;
2312  available -= i;
2313  connection->current_chunk_offset = 0;
2314 
2315  if (available > 0)
2316  instant_retry = MHD_YES;
2317  if (0LLU == connection->current_chunk_size)
2318  {
2319  connection->remaining_upload_size = 0;
2320  break;
2321  }
2322  continue;
2323  }
2324  }
2325  else
2326  {
2327  /* no chunked encoding, give all to the client */
2328  if ( (0 != connection->remaining_upload_size) &&
2329  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2330  (connection->remaining_upload_size < available) )
2331  {
2332  to_be_processed = (size_t) connection->remaining_upload_size;
2333  }
2334  else
2335  {
2340  to_be_processed = available;
2341  }
2342  }
2343  left_unprocessed = to_be_processed;
2344  connection->client_aware = true;
2345  if (MHD_NO ==
2346  daemon->default_handler (daemon->default_handler_cls,
2347  connection,
2348  connection->url,
2349  connection->method,
2350  connection->version,
2351  buffer_head,
2352  &left_unprocessed,
2353  &connection->client_context))
2354  {
2355  /* serious internal error, close connection */
2356  CONNECTION_CLOSE_ERROR (connection,
2357  _ (
2358  "Application reported internal error, closing connection.\n"));
2359  return;
2360  }
2361  if (left_unprocessed > to_be_processed)
2363  __FILE__,
2364  __LINE__
2365 #ifdef HAVE_MESSAGES
2366  , _ ("libmicrohttpd API violation.\n")
2367 #else
2368  , NULL
2369 #endif
2370  );
2371  if (0 != left_unprocessed)
2372  {
2373  instant_retry = MHD_NO; /* client did not process everything */
2374 #ifdef HAVE_MESSAGES
2375  /* client did not process all upload data, complain if
2376  the setup was incorrect, which may prevent us from
2377  handling the rest of the request */
2378  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2379  (! connection->suspended) )
2380  MHD_DLOG (daemon,
2381  _ (
2382  "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2383 #endif
2384  }
2385  processed_size = to_be_processed - left_unprocessed;
2386  if (connection->have_chunked_upload)
2387  connection->current_chunk_offset += processed_size;
2388  /* dh left "processed" bytes in buffer for next time... */
2389  buffer_head += processed_size;
2390  available -= processed_size;
2391  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2392  connection->remaining_upload_size -= processed_size;
2393  }
2394  while (MHD_NO != instant_retry);
2395  if ( (available > 0) &&
2396  (buffer_head != connection->read_buffer) )
2397  memmove (connection->read_buffer,
2398  buffer_head,
2399  available);
2400  connection->read_buffer_offset = available;
2401 }
2402 
2403 
2412 static enum MHD_Result
2413 check_write_done (struct MHD_Connection *connection,
2414  enum MHD_CONNECTION_STATE next_state)
2415 {
2416  if ( (connection->write_buffer_append_offset !=
2417  connection->write_buffer_send_offset)
2418  /* || data_in_tls_buffers == true */
2419  )
2420  return MHD_NO;
2421  connection->write_buffer_append_offset = 0;
2422  connection->write_buffer_send_offset = 0;
2423  connection->state = next_state;
2424  MHD_pool_reallocate (connection->pool,
2425  connection->write_buffer,
2426  connection->write_buffer_size,
2427  0);
2428  connection->write_buffer = NULL;
2429  connection->write_buffer_size = 0;
2430  return MHD_YES;
2431 }
2432 
2433 
2443 static enum MHD_Result
2444 process_header_line (struct MHD_Connection *connection,
2445  char *line)
2446 {
2447  char *colon;
2448 
2449  /* line should be normal header line, find colon */
2450  colon = strchr (line, ':');
2451  if (NULL == colon)
2452  {
2453  /* error in header line, die hard */
2454  CONNECTION_CLOSE_ERROR (connection,
2455  _ (
2456  "Received malformed line (no colon). Closing connection.\n"));
2457  return MHD_NO;
2458  }
2459  if (-1 >= connection->daemon->strict_for_client)
2460  {
2461  /* check for whitespace before colon, which is not allowed
2462  by RFC 7230 section 3.2.4; we count space ' ' and
2463  tab '\t', but not '\r\n' as those would have ended the line. */
2464  const char *white;
2465 
2466  white = strchr (line, ' ');
2467  if ( (NULL != white) &&
2468  (white < colon) )
2469  return MHD_NO;
2470  white = strchr (line, '\t');
2471  if ( (NULL != white) &&
2472  (white < colon) )
2473  return MHD_NO;
2474  }
2475  /* zero-terminate header */
2476  colon[0] = '\0';
2477  colon++; /* advance to value */
2478  while ( ('\0' != colon[0]) &&
2479  ( (' ' == colon[0]) ||
2480  ('\t' == colon[0]) ) )
2481  colon++;
2482  /* we do the actual adding of the connection
2483  header at the beginning of the while
2484  loop since we need to be able to inspect
2485  the *next* header line (in case it starts
2486  with a space...) */
2487  connection->last = line;
2488  connection->colon = colon;
2489  return MHD_YES;
2490 }
2491 
2492 
2503 static enum MHD_Result
2504 process_broken_line (struct MHD_Connection *connection,
2505  char *line,
2506  enum MHD_ValueKind kind)
2507 {
2508  char *last;
2509  char *tmp;
2510  size_t last_len;
2511  size_t tmp_len;
2512 
2513  last = connection->last;
2514  if ( (' ' == line[0]) ||
2515  ('\t' == line[0]) )
2516  {
2517  /* value was continued on the next line, see
2518  http://www.jmarshall.com/easy/http/ */
2519  last_len = strlen (last);
2520  /* skip whitespace at start of 2nd line */
2521  tmp = line;
2522  while ( (' ' == tmp[0]) ||
2523  ('\t' == tmp[0]) )
2524  tmp++;
2525  tmp_len = strlen (tmp);
2526  /* FIXME: we might be able to do this better (faster!), as most
2527  likely 'last' and 'line' should already be adjacent in
2528  memory; however, doing this right gets tricky if we have a
2529  value continued over multiple lines (in which case we need to
2530  record how often we have done this so we can check for
2531  adjacency); also, in the case where these are not adjacent
2532  (not sure how it can happen!), we would want to allocate from
2533  the end of the pool, so as to not destroy the read-buffer's
2534  ability to grow nicely. */
2535  last = MHD_pool_reallocate (connection->pool,
2536  last,
2537  last_len + 1,
2538  last_len + tmp_len + 1);
2539  if (NULL == last)
2540  {
2541  transmit_error_response (connection,
2543  REQUEST_TOO_BIG);
2544  return MHD_NO;
2545  }
2546  memcpy (&last[last_len],
2547  tmp,
2548  tmp_len + 1);
2549  connection->last = last;
2550  return MHD_YES; /* possibly more than 2 lines... */
2551  }
2552  mhd_assert ( (NULL != last) &&
2553  (NULL != connection->colon) );
2554  if (MHD_NO ==
2555  connection_add_header (connection,
2556  last,
2557  strlen (last),
2558  connection->colon,
2559  strlen (connection->colon),
2560  kind))
2561  {
2562  transmit_error_response (connection,
2564  REQUEST_TOO_BIG);
2565  return MHD_NO;
2566  }
2567  /* we still have the current line to deal with... */
2568  if (0 != line[0])
2569  {
2570  if (MHD_NO == process_header_line (connection,
2571  line))
2572  {
2573  transmit_error_response (connection,
2576  return MHD_NO;
2577  }
2578  }
2579  return MHD_YES;
2580 }
2581 
2582 
2590 static void
2592 {
2593  const char *clen;
2594  struct MHD_Response *response;
2595  const char *enc;
2596  const char *end;
2597 
2598  parse_cookie_header (connection);
2599  if ( (1 <= connection->daemon->strict_for_client) &&
2600  (NULL != connection->version) &&
2602  connection->version)) &&
2603  (MHD_NO ==
2604  MHD_lookup_connection_value_n (connection,
2609  NULL,
2610  NULL)) )
2611  {
2612  enum MHD_Result iret;
2613 
2614  /* die, http 1.1 request without host and we are pedantic */
2615  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2616  connection->read_closed = true;
2617 #ifdef HAVE_MESSAGES
2618  MHD_DLOG (connection->daemon,
2619  _ ("Received HTTP 1.1 request without `Host' header.\n"));
2620 #endif
2621  mhd_assert (NULL == connection->response);
2622  response =
2626  if (NULL == response)
2627  {
2628  /* can't even send a reply, at least close the connection */
2629  CONNECTION_CLOSE_ERROR (connection,
2630  _ (
2631  "Closing connection (failed to create response).\n"));
2632  return;
2633  }
2634  iret = MHD_queue_response (connection,
2636  response);
2637  MHD_destroy_response (response);
2638  if (MHD_NO == iret)
2639  {
2640  /* can't even send a reply, at least close the connection */
2641  CONNECTION_CLOSE_ERROR (connection,
2642  _ (
2643  "Closing connection (failed to queue response).\n"));
2644  }
2645  return;
2646  }
2647 
2648  connection->remaining_upload_size = 0;
2649  if (MHD_NO != MHD_lookup_connection_value_n (connection,
2654  &enc,
2655  NULL))
2656  {
2658  if (MHD_str_equal_caseless_ (enc,
2659  "chunked"))
2660  connection->have_chunked_upload = true;
2661  }
2662  else
2663  {
2664  if (MHD_NO != MHD_lookup_connection_value_n (connection,
2669  &clen,
2670  NULL))
2671  {
2672  end = clen + MHD_str_to_uint64_ (clen,
2673  &connection->remaining_upload_size);
2674  if ( (clen == end) ||
2675  ('\0' != *end) )
2676  {
2677  connection->remaining_upload_size = 0;
2678 #ifdef HAVE_MESSAGES
2679  MHD_DLOG (connection->daemon,
2680  "Failed to parse `Content-Length' header. Closing connection.\n");
2681 #endif
2682  CONNECTION_CLOSE_ERROR (connection,
2683  NULL);
2684  return;
2685  }
2686  }
2687  }
2688 }
2689 
2690 
2698 void
2700 {
2701  struct MHD_Daemon *daemon = connection->daemon;
2702 
2703  if (0 == connection->connection_timeout)
2704  return; /* Skip update of activity for connections
2705  without timeout timer. */
2706  if (connection->suspended)
2707  return; /* no activity on suspended connections */
2708 
2709  connection->last_activity = MHD_monotonic_sec_counter ();
2710  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2711  return; /* each connection has personal timeout */
2712 
2713  if (connection->connection_timeout != daemon->connection_timeout)
2714  return; /* custom timeout, no need to move it in "normal" DLL */
2715 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2717 #endif
2718  /* move connection to head of timeout list (by remove + add operation) */
2720  daemon->normal_timeout_tail,
2721  connection);
2723  daemon->normal_timeout_tail,
2724  connection);
2725 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2727 #endif
2728 }
2729 
2730 
2737 void
2739 {
2740  ssize_t bytes_read;
2741 
2742  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2743  (connection->suspended) )
2744  return;
2745 #ifdef HTTPS_SUPPORT
2746  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2747  { /* HTTPS connection. */
2748  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2749  {
2750  if (! MHD_run_tls_handshake_ (connection))
2751  return;
2752  }
2753  }
2754 #endif /* HTTPS_SUPPORT */
2755 
2756  /* make sure "read" has a reasonable number of bytes
2757  in buffer to use per system call (if possible) */
2758  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2759  connection->read_buffer_size)
2760  try_grow_read_buffer (connection,
2761  (connection->read_buffer_size ==
2762  connection->read_buffer_offset));
2763 
2764  if (connection->read_buffer_size == connection->read_buffer_offset)
2765  return; /* No space for receiving data. */
2766  bytes_read = connection->recv_cls (connection,
2767  &connection->read_buffer
2768  [connection->read_buffer_offset],
2769  connection->read_buffer_size
2770  - connection->read_buffer_offset);
2771  if (bytes_read < 0)
2772  {
2773  if (MHD_ERR_AGAIN_ == bytes_read)
2774  return; /* No new data to process. */
2775  if (MHD_ERR_CONNRESET_ == bytes_read)
2776  {
2777  CONNECTION_CLOSE_ERROR (connection,
2778  (MHD_CONNECTION_INIT == connection->state) ?
2779  NULL :
2780  _ (
2781  "Socket disconnected while reading request.\n"));
2782  return;
2783  }
2784  CONNECTION_CLOSE_ERROR (connection,
2785  (MHD_CONNECTION_INIT == connection->state) ?
2786  NULL :
2787  _ (
2788  "Connection socket is closed due to error when reading request.\n"));
2789  return;
2790  }
2791 
2792  if (0 == bytes_read)
2793  { /* Remote side closed connection. */
2794  connection->read_closed = true;
2795  MHD_connection_close_ (connection,
2797  return;
2798  }
2799  connection->read_buffer_offset += bytes_read;
2800  MHD_update_last_activity_ (connection);
2801 #if DEBUG_STATES
2802  MHD_DLOG (connection->daemon,
2803  _ ("In function %s handling connection at state: %s\n"),
2804  __FUNCTION__,
2805  MHD_state_to_string (connection->state));
2806 #endif
2807  switch (connection->state)
2808  {
2809  case MHD_CONNECTION_INIT:
2818  /* nothing to do but default action */
2819  if (connection->read_closed)
2820  {
2821  MHD_connection_close_ (connection,
2823  }
2824  return;
2825  case MHD_CONNECTION_CLOSED:
2826  return;
2827 #ifdef UPGRADE_SUPPORT
2828  case MHD_CONNECTION_UPGRADE:
2829  mhd_assert (0);
2830  return;
2831 #endif /* UPGRADE_SUPPORT */
2832  default:
2833  /* shrink read buffer to how much is actually used */
2834  MHD_pool_reallocate (connection->pool,
2835  connection->read_buffer,
2836  connection->read_buffer_size + 1,
2837  connection->read_buffer_offset);
2838  break;
2839  }
2840  return;
2841 }
2842 
2843 
2850 void
2852 {
2853  struct MHD_Response *response;
2854  ssize_t ret;
2855  if (connection->suspended)
2856  return;
2857 
2858 #ifdef HTTPS_SUPPORT
2859  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2860  { /* HTTPS connection. */
2861  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2862  {
2863  if (! MHD_run_tls_handshake_ (connection))
2864  return;
2865  }
2866  }
2867 #endif /* HTTPS_SUPPORT */
2868 
2869 #if DEBUG_STATES
2870  MHD_DLOG (connection->daemon,
2871  _ ("In function %s handling connection at state: %s\n"),
2872  __FUNCTION__,
2873  MHD_state_to_string (connection->state));
2874 #endif
2875  switch (connection->state)
2876  {
2877  case MHD_CONNECTION_INIT:
2881  mhd_assert (0);
2882  return;
2884  return;
2886  ret = MHD_send_data_ (connection,
2888  [connection->continue_message_write_offset],
2890  - connection->continue_message_write_offset,
2891  true);
2892  if (ret < 0)
2893  {
2894  if (MHD_ERR_AGAIN_ == ret)
2895  return;
2896 #ifdef HAVE_MESSAGES
2897  MHD_DLOG (connection->daemon,
2898  _ ("Failed to send data in request for %s.\n"),
2899  connection->url);
2900 #endif
2901  CONNECTION_CLOSE_ERROR (connection,
2902  NULL);
2903  return;
2904  }
2905 #if _MHD_DEBUG_SEND_DATA
2906  fprintf (stderr,
2907  _ ("Sent 100 continue response: `%.*s'\n"),
2908  (int) ret,
2910 #endif
2911  connection->continue_message_write_offset += ret;
2912  MHD_update_last_activity_ (connection);
2913  return;
2918  mhd_assert (0);
2919  return;
2921  {
2922  struct MHD_Response *const resp = connection->response;
2923  const size_t wb_ready = connection->write_buffer_append_offset
2924  - connection->write_buffer_send_offset;
2925  mhd_assert (connection->write_buffer_append_offset >= \
2926  connection->write_buffer_send_offset);
2927  mhd_assert (NULL != resp);
2928  mhd_assert ( (0 == resp->data_size) || \
2929  (0 == resp->data_start) || \
2930  (NULL != resp->crc) );
2931  mhd_assert ( (0 == connection->response_write_position) || \
2932  (resp->total_size ==
2933  connection->response_write_position) || \
2934  (MHD_SIZE_UNKNOWN ==
2935  connection->response_write_position) );
2936 
2937  if ( (NULL == resp->crc) &&
2938  (0 == connection->response_write_position) )
2939  {
2940  mhd_assert (resp->total_size >= resp->data_size);
2941  /* Send response headers alongside the response body, if the body
2942  * data is available. */
2943  ret = MHD_send_hdr_and_body_ (connection,
2944  &connection->write_buffer
2945  [connection->write_buffer_send_offset],
2946  wb_ready,
2947  false,
2948  resp->data,
2949  resp->data_size,
2950  (resp->total_size == resp->data_size));
2951  }
2952  else
2953  {
2954  /* This is response for HEAD request or reply body is not allowed
2955  * for any other reason or reply body is dynamically generated. */
2956  /* Do not send the body data even if it's available. */
2957  ret = MHD_send_hdr_and_body_ (connection,
2958  &connection->write_buffer
2959  [connection->write_buffer_send_offset],
2960  wb_ready,
2961  false,
2962  NULL,
2963  0,
2964  ((0 == resp->total_size) ||
2965  (resp->total_size ==
2966  connection->response_write_position)));
2967  }
2968 
2969  if (ret < 0)
2970  {
2971  if (MHD_ERR_AGAIN_ == ret)
2972  return;
2973  CONNECTION_CLOSE_ERROR (connection,
2974  _ (
2975  "Connection was closed while sending response headers.\n"));
2976  return;
2977  }
2978  /* 'ret' is not negative, it's safe to cast it to 'size_t'. */
2979  if (((size_t) ret) > wb_ready)
2980  {
2981  /* The complete header and some response data have been sent,
2982  * update both offsets. */
2983  mhd_assert (0 == connection->response_write_position);
2984  mhd_assert (! connection->have_chunked_upload);
2985  connection->write_buffer_send_offset += wb_ready;
2986  connection->response_write_position = ret - wb_ready;
2987  }
2988  else
2989  connection->write_buffer_send_offset += ret;
2990  MHD_update_last_activity_ (connection);
2991  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
2992  return;
2993  check_write_done (connection,
2995  return;
2996  }
2998  return;
3000  response = connection->response;
3001  if (connection->response_write_position <
3002  connection->response->total_size)
3003  {
3004  uint64_t data_write_offset;
3005 
3006 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3007  if (NULL != response->crc)
3008  MHD_mutex_lock_chk_ (&response->mutex);
3009 #endif
3010  if (MHD_NO == try_ready_normal_body (connection))
3011  {
3012  /* mutex was already unlocked by try_ready_normal_body */
3013  return;
3014  }
3015 #if defined(_MHD_HAVE_SENDFILE)
3016  if (MHD_resp_sender_sendfile == connection->resp_sender)
3017  {
3018  ret = MHD_send_sendfile_ (connection);
3019  }
3020  else
3021 #else /* ! _MHD_HAVE_SENDFILE */
3022  if (1)
3023 #endif /* ! _MHD_HAVE_SENDFILE */
3024  {
3025  data_write_offset = connection->response_write_position
3026  - response->data_start;
3027  if (data_write_offset > (uint64_t) SIZE_MAX)
3028  MHD_PANIC (_ ("Data offset exceeds limit.\n"));
3029  ret = MHD_send_data_ (connection,
3030  &response->data
3031  [(size_t) data_write_offset],
3032  response->data_size
3033  - (size_t) data_write_offset,
3034  true);
3035 #if _MHD_DEBUG_SEND_DATA
3036  if (ret > 0)
3037  fprintf (stderr,
3038  _ ("Sent %d-byte DATA response: `%.*s'\n"),
3039  (int) ret,
3040  (int) ret,
3041  &response->data[connection->response_write_position
3042  - response->data_start]);
3043 #endif
3044  }
3045 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3046  if (NULL != response->crc)
3047  MHD_mutex_unlock_chk_ (&response->mutex);
3048 #endif
3049  if (ret < 0)
3050  {
3051  if (MHD_ERR_AGAIN_ == ret)
3052  return;
3053 #ifdef HAVE_MESSAGES
3054  MHD_DLOG (connection->daemon,
3055  _ ("Failed to send data in request for `%s'.\n"),
3056  connection->url);
3057 #endif
3058  CONNECTION_CLOSE_ERROR (connection,
3059  NULL);
3060  return;
3061  }
3062  connection->response_write_position += ret;
3063  MHD_update_last_activity_ (connection);
3064  }
3065  if (connection->response_write_position ==
3066  connection->response->total_size)
3067  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3068  return;
3070  mhd_assert (0);
3071  return;
3073  ret = MHD_send_data_ (connection,
3074  &connection->write_buffer
3075  [connection->write_buffer_send_offset],
3076  connection->write_buffer_append_offset
3077  - connection->write_buffer_send_offset,
3078  true);
3079  if (ret < 0)
3080  {
3081  if (MHD_ERR_AGAIN_ == ret)
3082  return;
3083  CONNECTION_CLOSE_ERROR (connection,
3084  _ (
3085  "Connection was closed while sending response body.\n"));
3086  return;
3087  }
3088  connection->write_buffer_send_offset += ret;
3089  MHD_update_last_activity_ (connection);
3090  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3091  return;
3092  check_write_done (connection,
3093  (connection->response->total_size ==
3094  connection->response_write_position) ?
3097  return;
3100  mhd_assert (0);
3101  return;
3103  ret = MHD_send_data_ (connection,
3104  &connection->write_buffer
3105  [connection->write_buffer_send_offset],
3106  connection->write_buffer_append_offset
3107  - connection->write_buffer_send_offset,
3108  true);
3109  if (ret < 0)
3110  {
3111  if (MHD_ERR_AGAIN_ == ret)
3112  return;
3113  CONNECTION_CLOSE_ERROR (connection,
3114  _ (
3115  "Connection was closed while sending response body.\n"));
3116  return;
3117  }
3118  connection->write_buffer_send_offset += ret;
3119  MHD_update_last_activity_ (connection);
3120  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3121  return;
3122  check_write_done (connection,
3124  return;
3126  mhd_assert (0);
3127  return;
3128  case MHD_CONNECTION_CLOSED:
3129  return;
3130 #ifdef UPGRADE_SUPPORT
3131  case MHD_CONNECTION_UPGRADE:
3132  mhd_assert (0);
3133  return;
3134 #endif /* UPGRADE_SUPPORT */
3135  default:
3136  mhd_assert (0);
3137  CONNECTION_CLOSE_ERROR (connection,
3138  _ ("Internal error.\n"));
3139  break;
3140  }
3141  return;
3142 }
3143 
3144 
3153 static void
3155 {
3156  struct MHD_Daemon *daemon = connection->daemon;
3157 #ifdef MHD_USE_THREADS
3158  mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3159  MHD_thread_ID_match_current_ (connection->pid) );
3160 #endif /* MHD_USE_THREADS */
3161 
3162  if (connection->in_cleanup)
3163  return; /* Prevent double cleanup. */
3164  connection->in_cleanup = true;
3165  if (NULL != connection->response)
3166  {
3167  MHD_destroy_response (connection->response);
3168  connection->response = NULL;
3169  }
3170 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3172 #endif
3173  if (connection->suspended)
3174  {
3177  connection);
3178  connection->suspended = false;
3179  }
3180  else
3181  {
3182  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3183  {
3184  if (connection->connection_timeout == daemon->connection_timeout)
3186  daemon->normal_timeout_tail,
3187  connection);
3188  else
3190  daemon->manual_timeout_tail,
3191  connection);
3192  }
3193  DLL_remove (daemon->connections_head,
3194  daemon->connections_tail,
3195  connection);
3196  }
3197  DLL_insert (daemon->cleanup_head,
3198  daemon->cleanup_tail,
3199  connection);
3200  connection->resuming = false;
3201  connection->in_idle = false;
3202 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3204 #endif
3205  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3206  {
3207  /* if we were at the connection limit before and are in
3208  thread-per-connection mode, signal the main thread
3209  to resume accepting connections */
3210  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3211  (! MHD_itc_activate_ (daemon->itc, "c")) )
3212  {
3213 #ifdef HAVE_MESSAGES
3214  MHD_DLOG (daemon,
3215  _ (
3216  "Failed to signal end of connection via inter-thread communication channel.\n"));
3217 #endif
3218  }
3219  }
3220 }
3221 
3222 
3233 enum MHD_Result
3234 MHD_connection_handle_idle (struct MHD_Connection *connection)
3235 {
3236  struct MHD_Daemon *daemon = connection->daemon;
3237  char *line;
3238  size_t line_len;
3239  enum MHD_Result ret;
3240 #ifdef MHD_USE_THREADS
3241  mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
3242  MHD_thread_ID_match_current_ (connection->pid) );
3243 #endif /* MHD_USE_THREADS */
3244 
3245  connection->in_idle = true;
3246  while (! connection->suspended)
3247  {
3248 #ifdef HTTPS_SUPPORT
3249  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3250  { /* HTTPS connection. */
3251  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3252  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3253  break;
3254  }
3255 #endif /* HTTPS_SUPPORT */
3256 #if DEBUG_STATES
3257  MHD_DLOG (daemon,
3258  _ ("In function %s handling connection at state: %s\n"),
3259  __FUNCTION__,
3260  MHD_state_to_string (connection->state));
3261 #endif
3262  switch (connection->state)
3263  {
3264  case MHD_CONNECTION_INIT:
3265  line = get_next_header_line (connection,
3266  &line_len);
3267  /* Check for empty string, as we might want
3268  to tolerate 'spurious' empty lines; also
3269  NULL means we didn't get a full line yet;
3270  line is not 0-terminated here. */
3271  if ( (NULL == line) ||
3272  (0 == line[0]) )
3273  {
3274  if (MHD_CONNECTION_INIT != connection->state)
3275  continue;
3276  if (connection->read_closed)
3277  {
3278  CONNECTION_CLOSE_ERROR (connection,
3279  NULL);
3280  continue;
3281  }
3282  break;
3283  }
3284  if (MHD_NO == parse_initial_message_line (connection,
3285  line,
3286  line_len))
3287  CONNECTION_CLOSE_ERROR (connection,
3288  NULL);
3289  else
3290  connection->state = MHD_CONNECTION_URL_RECEIVED;
3291  continue;
3293  line = get_next_header_line (connection,
3294  NULL);
3295  if (NULL == line)
3296  {
3297  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3298  continue;
3299  if (connection->read_closed)
3300  {
3301  CONNECTION_CLOSE_ERROR (connection,
3302  NULL);
3303  continue;
3304  }
3305  break;
3306  }
3307  if (0 == line[0])
3308  {
3309  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3310  connection->header_size = (size_t) (line - connection->read_buffer);
3311  continue;
3312  }
3313  if (MHD_NO == process_header_line (connection,
3314  line))
3315  {
3316  transmit_error_response (connection,
3319  break;
3320  }
3322  continue;
3324  line = get_next_header_line (connection,
3325  NULL);
3326  if (NULL == line)
3327  {
3328  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
3329  continue;
3330  if (connection->read_closed)
3331  {
3332  CONNECTION_CLOSE_ERROR (connection,
3333  NULL);
3334  continue;
3335  }
3336  break;
3337  }
3338  if (MHD_NO ==
3339  process_broken_line (connection,
3340  line,
3341  MHD_HEADER_KIND))
3342  continue;
3343  if (0 == line[0])
3344  {
3345  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3346  connection->header_size = (size_t) (line - connection->read_buffer);
3347  continue;
3348  }
3349  continue;
3351  parse_connection_headers (connection);
3352  if (MHD_CONNECTION_CLOSED == connection->state)
3353  continue;
3355  if (connection->suspended)
3356  break;
3357  continue;
3359  call_connection_handler (connection); /* first call */
3360  if (MHD_CONNECTION_CLOSED == connection->state)
3361  continue;
3362  if (connection->suspended)
3363  continue;
3364  if ( (NULL == connection->response) &&
3365  (need_100_continue (connection)) )
3366  {
3367  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3368  break;
3369  }
3370  if ( (NULL != connection->response) &&
3371  (0 != connection->remaining_upload_size) )
3372  {
3373  /* we refused (no upload allowed!) */
3374  connection->remaining_upload_size = 0;
3375  /* force close, in case client still tries to upload... */
3376  connection->read_closed = true;
3377  }
3378  connection->state = (0 == connection->remaining_upload_size)
3381  if (connection->suspended)
3382  break;
3383  continue;
3385  if (connection->continue_message_write_offset ==
3387  {
3388  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3389  continue;
3390  }
3391  break;
3393  if (0 != connection->read_buffer_offset)
3394  {
3395  process_request_body (connection); /* loop call */
3396  if (MHD_CONNECTION_CLOSED == connection->state)
3397  continue;
3398  }
3399  if ( (0 == connection->remaining_upload_size) ||
3400  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3401  (0 == connection->read_buffer_offset) &&
3402  (connection->read_closed) ) )
3403  {
3404  if ( (connection->have_chunked_upload) &&
3405  (! connection->read_closed) )
3406  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3407  else
3408  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3409  if (connection->suspended)
3410  break;
3411  continue;
3412  }
3413  break;
3415  line = get_next_header_line (connection,
3416  NULL);
3417  if (NULL == line)
3418  {
3419  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3420  continue;
3421  if (connection->read_closed)
3422  {
3423  CONNECTION_CLOSE_ERROR (connection,
3424  NULL);
3425  continue;
3426  }
3427  break;
3428  }
3429  if (0 == line[0])
3430  {
3431  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3432  if (connection->suspended)
3433  break;
3434  continue;
3435  }
3436  if (MHD_NO == process_header_line (connection,
3437  line))
3438  {
3439  transmit_error_response (connection,
3442  break;
3443  }
3445  continue;
3447  line = get_next_header_line (connection,
3448  NULL);
3449  if (NULL == line)
3450  {
3451  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3452  continue;
3453  if (connection->read_closed)
3454  {
3455  CONNECTION_CLOSE_ERROR (connection,
3456  NULL);
3457  continue;
3458  }
3459  break;
3460  }
3461  if (MHD_NO ==
3462  process_broken_line (connection,
3463  line,
3464  MHD_FOOTER_KIND))
3465  continue;
3466  if (0 == line[0])
3467  {
3468  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3469  if (connection->suspended)
3470  break;
3471  continue;
3472  }
3473  continue;
3475  call_connection_handler (connection); /* "final" call */
3476  if (connection->state == MHD_CONNECTION_CLOSED)
3477  continue;
3478  if (NULL == connection->response)
3479  break; /* try again next time */
3480  if (MHD_NO == build_header_response (connection))
3481  {
3482  /* oops - close! */
3483  CONNECTION_CLOSE_ERROR (connection,
3484  _ (
3485  "Closing connection (failed to create response header).\n"));
3486  continue;
3487  }
3488  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3489  break;
3491  /* no default action */
3492  break;
3494  /* Some clients may take some actions right after header receive */
3495 #ifdef UPGRADE_SUPPORT
3496  if (NULL != connection->response->upgrade_handler)
3497  {
3498  connection->state = MHD_CONNECTION_UPGRADE;
3499  /* This connection is "upgraded". Pass socket to application. */
3500  if (MHD_NO ==
3502  connection))
3503  {
3504  /* upgrade failed, fail hard */
3505  CONNECTION_CLOSE_ERROR (connection,
3506  NULL);
3507  continue;
3508  }
3509  /* Response is not required anymore for this connection. */
3510  {
3511  struct MHD_Response *const resp = connection->response;
3512 
3513  connection->response = NULL;
3514  MHD_destroy_response (resp);
3515  }
3516  continue;
3517  }
3518 #endif /* UPGRADE_SUPPORT */
3519 
3520  if (connection->have_chunked_upload)
3522  else
3524  continue;
3526  /* nothing to do here */
3527  break;
3529 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3530  if (NULL != connection->response->crc)
3531  MHD_mutex_lock_chk_ (&connection->response->mutex);
3532 #endif
3533  if (0 == connection->response->total_size)
3534  {
3535 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3536  if (NULL != connection->response->crc)
3537  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3538 #endif
3539  connection->state = MHD_CONNECTION_BODY_SENT;
3540  continue;
3541  }
3542  if (MHD_NO != try_ready_normal_body (connection))
3543  {
3544 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3545  if (NULL != connection->response->crc)
3546  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3547 #endif
3549  /* Buffering for flushable socket was already enabled*/
3550 
3551  break;
3552  }
3553  /* mutex was already unlocked by "try_ready_normal_body */
3554  /* not ready, no socket action */
3555  break;
3557  /* nothing to do here */
3558  break;
3560 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3561  if (NULL != connection->response->crc)
3562  MHD_mutex_lock_chk_ (&connection->response->mutex);
3563 #endif
3564  if ( (0 == connection->response->total_size) ||
3565  (connection->response_write_position ==
3566  connection->response->total_size) )
3567  {
3568 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3569  if (NULL != connection->response->crc)
3570  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3571 #endif
3572  connection->state = MHD_CONNECTION_BODY_SENT;
3573  continue;
3574  }
3575  if (MHD_NO != try_ready_chunked_body (connection))
3576  {
3577 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3578  if (NULL != connection->response->crc)
3579  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3580 #endif
3582  /* Buffering for flushable socket was already enabled */
3583 
3584  continue;
3585  }
3586  /* mutex was already unlocked by try_ready_chunked_body */
3587  break;
3589  if (MHD_NO == build_header_response (connection))
3590  {
3591  /* oops - close! */
3592  CONNECTION_CLOSE_ERROR (connection,
3593  _ (
3594  "Closing connection (failed to create response header).\n"));
3595  continue;
3596  }
3597  if ( (! connection->have_chunked_upload) ||
3598  (connection->write_buffer_send_offset ==
3599  connection->write_buffer_append_offset) )
3600  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3601  else
3602  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3603  continue;
3605  /* no default action */
3606  break;
3608  if (MHD_HTTP_PROCESSING == connection->responseCode)
3609  {
3610  /* After this type of response, we allow sending another! */
3612  MHD_destroy_response (connection->response);
3613  connection->response = NULL;
3614  /* FIXME: maybe partially reset memory pool? */
3615  continue;
3616  }
3617  MHD_destroy_response (connection->response);
3618  connection->response = NULL;
3619  if ( (NULL != daemon->notify_completed) &&
3620  (connection->client_aware) )
3621  {
3622  daemon->notify_completed (daemon->notify_completed_cls,
3623  connection,
3624  &connection->client_context,
3626  }
3627  connection->client_aware = false;
3628  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3629  (connection->read_closed) )
3630  {
3631  /* have to close for some reason */
3632  MHD_connection_close_ (connection,
3634  MHD_pool_destroy (connection->pool);
3635  connection->pool = NULL;
3636  connection->read_buffer = NULL;
3637  connection->read_buffer_size = 0;
3638  connection->read_buffer_offset = 0;
3639  }
3640  else
3641  {
3642  /* can try to keep-alive */
3643 
3644  connection->version = NULL;
3645  connection->state = MHD_CONNECTION_INIT;
3646  connection->last = NULL;
3647  connection->colon = NULL;
3648  connection->header_size = 0;
3649  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3650  /* Reset the read buffer to the starting size,
3651  preserving the bytes we have already read. */
3652  connection->read_buffer
3653  = MHD_pool_reset (connection->pool,
3654  connection->read_buffer,
3655  connection->read_buffer_offset,
3656  connection->daemon->pool_size / 2);
3657  connection->read_buffer_size
3658  = connection->daemon->pool_size / 2;
3659  }
3660  connection->client_context = NULL;
3661  connection->continue_message_write_offset = 0;
3662  connection->responseCode = 0;
3663  connection->headers_received = NULL;
3664  connection->headers_received_tail = NULL;
3665  connection->response_write_position = 0;
3666  connection->have_chunked_upload = false;
3667  connection->current_chunk_size = 0;
3668  connection->current_chunk_offset = 0;
3669  connection->method = NULL;
3670  connection->url = NULL;
3671  connection->write_buffer = NULL;
3672  connection->write_buffer_size = 0;
3673  connection->write_buffer_send_offset = 0;
3674  connection->write_buffer_append_offset = 0;
3675  continue;
3676  case MHD_CONNECTION_CLOSED:
3677  cleanup_connection (connection);
3678  connection->in_idle = false;
3679  return MHD_NO;
3680 #ifdef UPGRADE_SUPPORT
3681  case MHD_CONNECTION_UPGRADE:
3682  connection->in_idle = false;
3683  return MHD_YES; /* keep open */
3684 #endif /* UPGRADE_SUPPORT */
3685  default:
3686  mhd_assert (0);
3687  break;
3688  }
3689  break;
3690  }
3691  if (! connection->suspended)
3692  {
3693  time_t timeout;
3694  timeout = connection->connection_timeout;
3695  if ( (0 != timeout) &&
3696  (timeout < (MHD_monotonic_sec_counter ()
3697  - connection->last_activity)) )
3698  {
3699  MHD_connection_close_ (connection,
3701  connection->in_idle = false;
3702  return MHD_YES;
3703  }
3704  }
3706  ret = MHD_YES;
3707 #ifdef EPOLL_SUPPORT
3708  if ( (! connection->suspended) &&
3709  (0 != (daemon->options & MHD_USE_EPOLL)) )
3710  {
3711  ret = MHD_connection_epoll_update_ (connection);
3712  }
3713 #endif /* EPOLL_SUPPORT */
3714  connection->in_idle = false;
3715  return ret;
3716 }
3717 
3718 
3719 #ifdef EPOLL_SUPPORT
3728 enum MHD_Result
3729 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3730 {
3731  struct MHD_Daemon *daemon = connection->daemon;
3732 
3733  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3734  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3735  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3736  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3737  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3738  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3739  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3740  {
3741  /* add to epoll set */
3742  struct epoll_event event;
3743 
3744  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3745  event.data.ptr = connection;
3746  if (0 != epoll_ctl (daemon->epoll_fd,
3747  EPOLL_CTL_ADD,
3748  connection->socket_fd,
3749  &event))
3750  {
3751 #ifdef HAVE_MESSAGES
3752  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3753  MHD_DLOG (daemon,
3754  _ ("Call to epoll_ctl failed: %s\n"),
3756 #endif
3757  connection->state = MHD_CONNECTION_CLOSED;
3758  cleanup_connection (connection);
3759  return MHD_NO;
3760  }
3761  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3762  }
3763  return MHD_YES;
3764 }
3765 
3766 
3767 #endif
3768 
3769 
3775 void
3777 {
3778  connection->recv_cls = &recv_param_adapter;
3779 }
3780 
3781 
3792 const union MHD_ConnectionInfo *
3794  enum MHD_ConnectionInfoType info_type,
3795  ...)
3796 {
3797  switch (info_type)
3798  {
3799 #ifdef HTTPS_SUPPORT
3801  if (NULL == connection->tls_session)
3802  return NULL;
3803  connection->cipher = gnutls_cipher_get (connection->tls_session);
3804  return (const union MHD_ConnectionInfo *) &connection->cipher;
3806  if (NULL == connection->tls_session)
3807  return NULL;
3808  connection->protocol = gnutls_protocol_get_version (
3809  connection->tls_session);
3810  return (const union MHD_ConnectionInfo *) &connection->protocol;
3812  if (NULL == connection->tls_session)
3813  return NULL;
3814  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3815 #endif /* HTTPS_SUPPORT */
3817  return (const union MHD_ConnectionInfo *) &connection->addr;
3819  return (const union MHD_ConnectionInfo *) &connection->daemon;
3821  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3823  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3825  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3826  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3828  connection->connection_timeout_dummy = (unsigned
3829  int) connection->connection_timeout;
3830  return (const union MHD_ConnectionInfo *) &connection->
3831  connection_timeout_dummy;
3833  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3834  (MHD_CONNECTION_CLOSED == connection->state) )
3835  return NULL; /* invalid, too early! */
3836  return (const union MHD_ConnectionInfo *) &connection->header_size;
3837  default:
3838  return NULL;
3839  }
3840 }
3841 
3842 
3852 enum MHD_Result
3853 MHD_set_connection_option (struct MHD_Connection *connection,
3854  enum MHD_CONNECTION_OPTION option,
3855  ...)
3856 {
3857  va_list ap;
3858  struct MHD_Daemon *daemon;
3859 
3860  daemon = connection->daemon;
3861  switch (option)
3862  {
3864  if (0 == connection->connection_timeout)
3865  connection->last_activity = MHD_monotonic_sec_counter ();
3866 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3868 #endif
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  va_start (ap, option);
3882  connection->connection_timeout = va_arg (ap,
3883  unsigned int);
3884  va_end (ap);
3885  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3886  (! connection->suspended) )
3887  {
3888  if (connection->connection_timeout == daemon->connection_timeout)
3890  daemon->normal_timeout_tail,
3891  connection);
3892  else
3894  daemon->manual_timeout_tail,
3895  connection);
3896  }
3897 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3899 #endif
3900  return MHD_YES;
3901  default:
3902  return MHD_NO;
3903  }
3904 }
3905 
3906 
3918 enum MHD_Result
3919 MHD_queue_response (struct MHD_Connection *connection,
3920  unsigned int status_code,
3921  struct MHD_Response *response)
3922 {
3923  struct MHD_Daemon *daemon;
3924 
3925  if ( (NULL == connection) ||
3926  (NULL == response) ||
3927  (NULL != connection->response) ||
3928  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3929  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3930  return MHD_NO;
3931  daemon = connection->daemon;
3932 
3933  if (daemon->shutdown)
3934  return MHD_YES; /* If daemon was shut down in parallel,
3935  * response will be aborted now or on later stage. */
3936 
3937 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3938  if ( (! connection->suspended) &&
3939  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3940  (! MHD_thread_ID_match_current_ (connection->pid)) )
3941  {
3942 #ifdef HAVE_MESSAGES
3943  MHD_DLOG (daemon,
3944  _ ("Attempted to queue response on wrong thread!\n"));
3945 #endif
3946  return MHD_NO;
3947  }
3948 #endif
3949 #ifdef UPGRADE_SUPPORT
3950  if ( (NULL != response->upgrade_handler) &&
3951  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3952  {
3953 #ifdef HAVE_MESSAGES
3954  MHD_DLOG (daemon,
3955  _ (
3956  "Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
3957 #endif
3958  return MHD_NO;
3959  }
3960  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
3961  (NULL != response->upgrade_handler) )
3962  {
3963 #ifdef HAVE_MESSAGES
3964  MHD_DLOG (daemon,
3965  _ (
3966  "Application used invalid status code for 'upgrade' response!\n"));
3967 #endif
3968  return MHD_NO;
3969  }
3970 #endif /* UPGRADE_SUPPORT */
3971  MHD_increment_response_rc (response);
3972  connection->response = response;
3973  connection->responseCode = status_code;
3974 #if defined(_MHD_HAVE_SENDFILE)
3975  if ( (response->fd == -1) ||
3976  (response->is_pipe) ||
3977  (0 != (connection->daemon->options & MHD_USE_TLS))
3978 #if ! defined(MHD_WINSOCK_SOCKETS) && defined(HAVE_SEND_SIGPIPE_SUPPRESS)
3979  || (! daemon->sigpipe_blocked && ! connection->sk_spipe_suppress)
3980 #endif /* ! MHD_WINSOCK_SOCKETS && ! HAVE_SEND_SIGPIPE_SUPPRESS */
3981  )
3982  connection->resp_sender = MHD_resp_sender_std;
3983  else
3984  connection->resp_sender = MHD_resp_sender_sendfile;
3985 #endif /* _MHD_HAVE_SENDFILE */
3986  /* FIXME: if 'is_pipe' is set, TLS is off, and we have *splice*, we could use splice()
3987  to avoid two user-space copies... */
3988 
3989  if ( ( (NULL != connection->method) &&
3990  (MHD_str_equal_caseless_ (connection->method,
3991  MHD_HTTP_METHOD_HEAD)) ) ||
3992  (MHD_HTTP_OK > status_code) ||
3993  (MHD_HTTP_NO_CONTENT == status_code) ||
3994  (MHD_HTTP_NOT_MODIFIED == status_code) )
3995  {
3996  /* if this is a "HEAD" request, or a status code for
3997  which a body is not allowed, pretend that we
3998  have already sent the full message body. */
3999  connection->response_write_position = response->total_size;
4000  }
4001  if (MHD_CONNECTION_HEADERS_PROCESSED == connection->state)
4002  {
4003  /* response was queued "early", refuse to read body / footers or
4004  further requests! */
4005  connection->read_closed = true;
4006  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4007  connection->remaining_upload_size = 0;
4008  }
4009  if (! connection->in_idle)
4010  (void) MHD_connection_handle_idle (connection);
4011  MHD_update_last_activity_ (connection);
4012  return MHD_YES;
4013 }
4014 
4015 
4016 /* end of connection.c */
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:138
static enum MHD_Result build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1172
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:752
static enum MHD_Result process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2444
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:566
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2738
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2851
#define INTERNAL_ERROR
Definition: connection.c:114
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1630
static enum MHD_Result try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:791
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2132
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2168
#define REQUEST_TOO_BIG
Definition: connection.c:73
#define HTTP_100_CONTINUE
Definition: connection.c:60
static enum MHD_Result keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:993
static enum MHD_Result parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1894
#define REQUEST_MALFORMED
Definition: connection.c:101
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3776
#define REQUEST_LACKS_HOST
Definition: connection.c:87
static bool try_grow_read_buffer(struct MHD_Connection *connection, bool required)
Definition: connection.c:1106
static bool need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:579
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1546
enum MHD_Result MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3234
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3154
static enum MHD_Result try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:862
static enum MHD_Result process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2504
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1799
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2591
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2699
static enum MHD_Result parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2020
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1043
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:643
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:1859
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:605
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:774
static enum MHD_Result check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2413
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:524
Methods for managing connections.
void MHD_connection_finish_forward_(struct MHD_Connection *connection) MHD_NONNULL(1)
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
Methods for managing connections.
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:575
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:569
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:583
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:631
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:709
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:587
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:593
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:446
#define MHD_HTTP_OK
Definition: microhttpd.h:344
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:413
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:440
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:339
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:337
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:374
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:352
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:385
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:923
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:917
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2261
_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:233
_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:347
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:2286
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:286
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:423
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:194
MHD_ConnectionInfoType
Definition: microhttpd.h:1980
_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:394
_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:460
MHD_RequestTerminationCode
Definition: microhttpd.h:1832
@ MHD_CONNECTION_INFO_CONNECTION_TIMEOUT
Definition: microhttpd.h:2052
@ MHD_CONNECTION_INFO_SOCKET_CONTEXT
Definition: microhttpd.h:2040
@ MHD_CONNECTION_INFO_GNUTLS_SESSION
Definition: microhttpd.h:2008
@ MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE
Definition: microhttpd.h:2058
@ MHD_CONNECTION_INFO_CIPHER_ALGO
Definition: microhttpd.h:1986
@ MHD_CONNECTION_INFO_CONNECTION_SUSPENDED
Definition: microhttpd.h:2046
@ MHD_CONNECTION_INFO_CLIENT_ADDRESS
Definition: microhttpd.h:2002
@ MHD_CONNECTION_INFO_DAEMON
Definition: microhttpd.h:2022
@ MHD_CONNECTION_INFO_CONNECTION_FD
Definition: microhttpd.h:2030
@ MHD_CONNECTION_INFO_PROTOCOL
Definition: microhttpd.h:1993
@ MHD_REQUEST_TERMINATED_TIMEOUT_REACHED
Definition: microhttpd.h:1854
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
Definition: microhttpd.h:1838
@ MHD_REQUEST_TERMINATED_WITH_ERROR
Definition: microhttpd.h:1846
@ MHD_REQUEST_TERMINATED_READ_ERROR
Definition: microhttpd.h:1871
@ MHD_REQUEST_TERMINATED_CLIENT_ABORT
Definition: microhttpd.h:1879
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:809
_MHD_EXTERN enum MHD_Result MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3919
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1268
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:284
@ MHD_RESPMEM_PERSISTENT
Definition: microhttpd.h:3072
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3793
#define MHD_ICY_FLAG
Definition: microhttpd.h:537
_MHD_EXTERN enum MHD_Result MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3853
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:902
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:903
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
#define MHD_ERR_CONNRESET_
Definition: internal.h:1868
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
MHD_PanicCallback mhd_panic
Definition: panic.c:31
@ MHD_EPOLL_STATE_SUSPENDED
Definition: internal.h:621
@ MHD_EPOLL_STATE_READ_READY
Definition: internal.h:600
@ MHD_EPOLL_STATE_IN_EPOLL_SET
Definition: internal.h:616
@ MHD_EPOLL_STATE_WRITE_READY
Definition: internal.h:606
#define DLL_insert(head, tail, element)
Definition: internal.h:1743
#define MHD_PANIC(msg)
Definition: internal.h:69
#define MHD_MIN(a, b)
Definition: internal.h:110
@ MHD_CONN_USE_KEEPALIVE
Definition: internal.h:169
@ MHD_CONN_MUST_CLOSE
Definition: internal.h:159
@ MHD_CONN_KEEPALIVE_UNKOWN
Definition: internal.h:164
#define MHD_ERR_AGAIN_
Definition: internal.h:1863
#define MHD_BUF_INC_SIZE
Definition: internal.h:120
#define EDLL_remove(head, tail, element)
Definition: internal.h:1847
#define XDLL_remove(head, tail, element)
Definition: internal.h:1806
#define DLL_remove(head, tail, element)
Definition: internal.h:1763
void * mhd_panic_cls
Definition: panic.c:36
#define MHD_ERR_NOTCONN_
Definition: internal.h:1874
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:248
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:185
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
#define SIZE_MAX
Definition: mhd_limits.h:99
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:180
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
time_t MHD_monotonic_sec_counter(void)
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:611
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:643
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:549
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:634
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:222
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:273
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:419
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:346
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:692
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:473
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:412
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
#define NULL
Definition: reason_phrase.c:30
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:50
ssize_t MHD_send_hdr_and_body_(struct MHD_Connection *connection, const char *header, size_t header_size, bool never_push_hdr, const char *body, size_t body_size, bool complete_response)
Definition: mhd_send.c:789
ssize_t MHD_send_data_(struct MHD_Connection *connection, const char *buffer, size_t buffer_size, bool push_data)
Definition: mhd_send.c:662
Declarations of send() wrappers.
internal shared structures
MHD_CONNECTION_STATE
Definition: internal.h:472
@ MHD_CONNECTION_BODY_RECEIVED
Definition: internal.h:512
@ MHD_CONNECTION_HEADER_PART_RECEIVED
Definition: internal.h:487
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:530
@ MHD_CONNECTION_FOOTERS_SENDING
Definition: internal.h:566
@ MHD_CONNECTION_FOOTERS_RECEIVED
Definition: internal.h:524
@ MHD_CONNECTION_HEADERS_SENT
Definition: internal.h:535
@ MHD_CONNECTION_HEADERS_PROCESSED
Definition: internal.h:497
@ MHD_CONNECTION_INIT
Definition: internal.h:477
@ MHD_CONNECTION_CLOSED
Definition: internal.h:576
@ MHD_CONNECTION_NORMAL_BODY_UNREADY
Definition: internal.h:546
@ MHD_CONNECTION_HEADERS_RECEIVED
Definition: internal.h:492
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:540
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:551
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
Definition: internal.h:518
@ MHD_CONNECTION_CONTINUE_SENT
Definition: internal.h:507
@ MHD_CONNECTION_FOOTERS_SENT
Definition: internal.h:571
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
Definition: internal.h:556
@ MHD_CONNECTION_BODY_SENT
Definition: internal.h:561
@ MHD_CONNECTION_CONTINUE_SENDING
Definition: internal.h:502
@ MHD_CONNECTION_URL_RECEIVED
Definition: internal.h:482
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:2071
@ MHD_TLS_CONN_NO_TLS
Definition: internal.h:594
@ MHD_TLS_CONN_INIT
Definition: internal.h:595
@ MHD_TLS_CONN_CONNECTED
Definition: internal.h:597
@ MHD_TLS_CONN_HANDSHAKING
Definition: internal.h:596
@ MHD_EVENT_LOOP_INFO_READ
Definition: internal.h:234
@ MHD_EVENT_LOOP_INFO_WRITE
Definition: internal.h:239
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition: internal.h:249
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition: internal.h:244
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
Header for platform missing functions.
Header for platform-independent inter-thread communication.
limits values definitions
internal monotonic clock functions implementations
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:408
Header for string manipulating helpers.
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1308
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:168
MHD_Result
Definition: microhttpd.h:142
@ MHD_YES
Definition: microhttpd.h:151
@ MHD_NO
Definition: microhttpd.h:146
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:175
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:299
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:313
void * data
Definition: microhttpd.h:3053
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:197
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:176
MHD_ValueKind
Definition: microhttpd.h:1781
@ MHD_FOOTER_KIND
Definition: microhttpd.h:1822
@ MHD_COOKIE_KIND
Definition: microhttpd.h:1802
@ MHD_HEADER_KIND
Definition: microhttpd.h:1796
@ MHD_GET_ARGUMENT_KIND
Definition: microhttpd.h:1817
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
@ MHD_USE_EPOLL
Definition: microhttpd.h:1196
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1090
@ MHD_USE_TURBO
Definition: microhttpd.h:1267
@ MHD_USE_SUPPRESS_DATE_NO_CLOCK
Definition: microhttpd.h:1169
@ MHD_USE_TLS
Definition: microhttpd.h:1075
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1305
@ MHD_USE_ERROR_LOG
Definition: microhttpd.h:1064
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1101
@ MHD_RF_HTTP_VERSION_1_0_RESPONSE
Definition: microhttpd.h:2974
@ MHD_RF_HTTP_VERSION_1_0_ONLY
Definition: microhttpd.h:2967
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3794
@ MHD_CONNECTION_OPTION_TIMEOUT
Definition: microhttpd.h:3803
Methods for managing response objects.
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
MHD_socket socket_fd
Definition: internal.h:752
size_t write_buffer_size
Definition: internal.h:844
size_t write_buffer_send_offset
Definition: internal.h:849
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:988
size_t write_buffer_append_offset
Definition: internal.h:855
char * last
Definition: internal.h:802
char * write_buffer
Definition: internal.h:794
uint64_t remaining_upload_size
Definition: internal.h:867
void * socket_context
Definition: internal.h:694
bool suspended
Definition: internal.h:764
ReceiveCallback recv_cls
Definition: internal.h:706
char * colon
Definition: internal.h:811
size_t header_size
Definition: internal.h:861
struct MHD_Response * response
Definition: internal.h:730
const char * url
Definition: internal.h:768
char * version
Definition: internal.h:774
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:781
time_t connection_timeout
Definition: internal.h:745
struct MHD_HTTP_Header * headers_received
Definition: internal.h:720
size_t continue_message_write_offset
Definition: internal.h:888
uint64_t response_write_position
Definition: internal.h:874
struct sockaddr_storage addr
Definition: internal.h:728
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:725
char * method
Definition: internal.h:762
uint64_t current_chunk_offset
Definition: internal.h:1017
struct MemoryPool * pool
Definition: internal.h:685
size_t read_buffer_offset
Definition: internal.h:839
uint64_t current_chunk_size
Definition: internal.h:1011
int suspended_dummy
Definition: internal.h:1071
bool client_aware
Definition: internal.h:917
unsigned int responseCode
Definition: internal.h:994
MHD_thread_handle_ID_ pid
Definition: internal.h:723
bool have_chunked_upload
Definition: internal.h:1003
bool read_closed
Definition: internal.h:792
time_t last_activity
Definition: internal.h:739
bool in_cleanup
Definition: internal.h:971
void * client_context
Definition: internal.h:748
enum MHD_CONNECTION_STATE state
Definition: internal.h:983
char * read_buffer
Definition: internal.h:788
struct MHD_Daemon * daemon
Definition: internal.h:675
unsigned int connection_timeout_dummy
Definition: internal.h:910
bool sk_spipe_suppress
Definition: internal.h:934
size_t read_buffer_size
Definition: internal.h:833
size_t pool_size
Definition: internal.h:1576
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1317
LogCallback uri_log_callback
Definition: internal.h:1502
void * unescape_callback_cls
Definition: internal.h:1517
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
struct MHD_Connection * connections_head
Definition: internal.h:1155
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1477
struct MHD_itc_ itc
Definition: internal.h:1410
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1330
bool sigpipe_blocked
Definition: internal.h:1708
UnescapeCallback unescape_callback
Definition: internal.h:1512
void * notify_completed_cls
Definition: internal.h:1482
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
MHD_thread_handle_ID_ pid
Definition: internal.h:1249
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
void * default_handler_cls
Definition: internal.h:1322
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
time_t connection_timeout
Definition: internal.h:1692
struct MHD_Connection * cleanup_head
Definition: internal.h:1177
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
size_t pool_increment
Definition: internal.h:1581
void * uri_log_callback_cls
Definition: internal.h:1507
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
struct MHD_Connection * connections_tail
Definition: internal.h:1160
int strict_for_client
Definition: internal.h:1703
size_t value_size
Definition: internal.h:335
char * header
Definition: internal.h:347
enum MHD_ValueKind kind
Definition: internal.h:358
size_t header_size
Definition: internal.h:325
struct MHD_HTTP_Header * next
Definition: internal.h:342
char * value
Definition: internal.h:352
struct MHD_HTTP_Header * first_header
Definition: internal.h:1582
void * crc_cls
Definition: internal.h:1594
size_t data_buffer_size
Definition: internal.h:1664
enum MHD_HTTP_StatusCode status_code
Definition: internal.h:1669
uint64_t data_start
Definition: internal.h:1648
MHD_ContentReaderCallback crc
Definition: internal.h:1600
bool is_pipe
Definition: internal.h:451
size_t data_size
Definition: internal.h:1659
enum MHD_ResponseFlags flags
Definition: internal.h:446
char * data
Definition: internal.h:1588
MHD_mutex_ mutex
Definition: internal.h:1637
uint64_t total_size
Definition: internal.h:1642