GNU libmicrohttpd  0.9.29
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2016 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 <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 #include "mhd_locks.h"
35 #include "mhd_sockets.h"
36 #include "mhd_compat.h"
37 #include "mhd_itc.h"
38 
39 
43 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
44 
52 #ifdef HAVE_MESSAGES
53 #define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
54 #else
55 #define REQUEST_TOO_BIG ""
56 #endif
57 
65 #ifdef HAVE_MESSAGES
66 #define REQUEST_LACKS_HOST "<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>"
67 #else
68 #define REQUEST_LACKS_HOST ""
69 #endif
70 
78 #ifdef HAVE_MESSAGES
79 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
80 #else
81 #define REQUEST_MALFORMED ""
82 #endif
83 
90 #ifdef HAVE_MESSAGES
91 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
92 #else
93 #define INTERNAL_ERROR ""
94 #endif
95 
100 #define DEBUG_CLOSE MHD_NO
101 
105 #define DEBUG_SEND_DATA MHD_NO
106 
107 
127 static int
129 {
130 #if defined(TCP_CORK) || defined(TCP_PUSH)
131  return MHD_YES;
132 #else /* !TCP_CORK && !TCP_PUSH */
133  return MHD_NO;
134 #endif /* !TCP_CORK && !TCP_PUSH */
135 }
136 
137 
145 static int
147 {
148  int res = MHD_NO;
149 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
150  const MHD_SCKT_OPT_BOOL_ on_val = 1;
151 #if defined(TCP_NODELAY)
152  const MHD_SCKT_OPT_BOOL_ off_val = 0;
153 #endif /* TCP_NODELAY */
154  if (!connection)
155  return MHD_NO;
156 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
157  /* Buffer data before sending */
158  res = (0 == setsockopt (connection->socket_fd,
159  IPPROTO_TCP,
160  TCP_NOPUSH,
161  (const void *) &on_val,
162  sizeof (on_val)))
163  ? MHD_YES : MHD_NO;
164 #if defined(TCP_NODELAY)
165  /* Enable Nagle's algorithm */
166  /* TCP_NODELAY may interfere with TCP_NOPUSH */
167  res &= (0 == setsockopt (connection->socket_fd,
168  IPPROTO_TCP,
169  TCP_NODELAY,
170  (const void *) &off_val,
171  sizeof (off_val)))
172  ? MHD_YES : MHD_NO;
173 #endif /* TCP_NODELAY */
174 #else /* TCP_CORK */
175 #if defined(TCP_NODELAY)
176  /* Enable Nagle's algorithm */
177  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
178  solely on TCP_CORK result, so ignoring return code here. */
179  (void) setsockopt (connection->socket_fd,
180  IPPROTO_TCP,
181  TCP_NODELAY,
182  (const void *) &off_val,
183  sizeof (off_val));
184 #endif /* TCP_NODELAY */
185  /* Send only full packets */
186  res = (0 == setsockopt (connection->socket_fd,
187  IPPROTO_TCP,
188  TCP_CORK,
189  (const void *) &on_val,
190  sizeof (on_val)))
191  ? MHD_YES : MHD_NO;
192 #endif /* TCP_CORK */
193 #endif /* TCP_CORK || TCP_NOPUSH */
194  return res;
195 }
196 
197 
204 static int
206 {
207 #if defined(TCP_NODELAY)
208  int res = MHD_YES;
209  const MHD_SCKT_OPT_BOOL_ on_val = 1;
210 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
211  const MHD_SCKT_OPT_BOOL_ off_val = 0;
212 #endif /* TCP_CORK || TCP_NOPUSH */
213 
214  if (NULL == connection)
215  return MHD_NO;
216 #if defined(TCP_CORK)
217  /* Allow partial packets */
218  res &= (0 == setsockopt (connection->socket_fd,
219  IPPROTO_TCP,
220  TCP_CORK,
221  (const void *) &off_val,
222  sizeof (off_val)))
223  ? MHD_YES : MHD_NO;
224 #endif /* TCP_CORK */
225 #if defined(TCP_NODELAY)
226  /* Disable Nagle's algorithm for sending packets without delay */
227  res &= (0 == setsockopt (connection->socket_fd,
228  IPPROTO_TCP,
229  TCP_NODELAY,
230  (const void *) &on_val,
231  sizeof (on_val)))
232  ? MHD_YES : MHD_NO;
233 #endif /* TCP_NODELAY */
234 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
235  /* Disable extra buffering */
236  res &= (0 == setsockopt (connection->socket_fd,
237  IPPROTO_TCP,
238  TCP_NOPUSH,
239  (const void *) &off_val,
240  sizeof (off_val)))
241  ? MHD_YES : MHD_NO;
242 #endif /* TCP_NOPUSH && !TCP_CORK */
243  return res;
244 #else /* !TCP_NODELAY */
245  return MHD_NO;
246 #endif /* !TCP_NODELAY */
247 }
248 
249 
257 static int
259 {
260  int res = MHD_YES;
261 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
262  const int dummy = 0;
263 #endif /* !TCP_CORK */
264 
265  if (NULL == connection)
266  return MHD_NO;
267  res = socket_start_no_buffering (connection);
268 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
269  /* Force flush data with zero send otherwise Darwin and some BSD systems
270  will add 5 seconds delay. Not required with TCP_CORK as switching off
271  TCP_CORK always flushes socket buffer. */
272  res &= (0 <= MHD_send_ (connection->socket_fd,
273  &dummy,
274  0))
275  ? MHD_YES : MHD_NO;
276 #endif /* TCP_NOPUSH && !TCP_CORK*/
277  return res;
278 }
279 
280 
287 static int
289 {
290 #if defined(TCP_NODELAY)
291  int res = MHD_YES;
292  const MHD_SCKT_OPT_BOOL_ off_val = 0;
293 #if defined(TCP_CORK)
294  MHD_SCKT_OPT_BOOL_ cork_val = 0;
295  socklen_t param_size = sizeof (cork_val);
296 #endif /* TCP_CORK */
297  if (!connection)
298  return MHD_NO;
299 #if defined(TCP_CORK)
300  /* Allow partial packets */
301  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
302  so try to check current value of TCP_CORK to prevent unrequested flushing */
303  if ( (0 != getsockopt (connection->socket_fd,
304  IPPROTO_TCP,
305  TCP_CORK,
306  (void*)&cork_val,
307  &param_size)) ||
308  (0 != cork_val))
309  res &= (0 == setsockopt (connection->socket_fd,
310  IPPROTO_TCP,
311  TCP_CORK,
312  (const void *) &off_val,
313  sizeof (off_val)))
314  ? MHD_YES : MHD_NO;
315 #elif defined(TCP_NOPUSH)
316  /* Disable extra buffering */
317  /* No need to check current value as disabling TCP_NOPUSH will not flush partial
318  packet if TCP_NOPUSH wasn't enabled before */
319  res &= (0 == setsockopt (connection->socket_fd,
320  IPPROTO_TCP,
321  TCP_NOPUSH,
322  (const void *) &off_val,
323  sizeof (off_val)))
324  ? MHD_YES : MHD_NO;
325 #endif /* TCP_NOPUSH && !TCP_CORK */
326  /* Enable Nagle's algorithm for normal buffering */
327  res &= (0 == setsockopt (connection->socket_fd,
328  IPPROTO_TCP,
329  TCP_NODELAY,
330  (const void *) &off_val,
331  sizeof (off_val)))
332  ? MHD_YES : MHD_NO;
333  return res;
334 #else /* !TCP_NODELAY */
335  return MHD_NO;
336 #endif /* !TCP_NODELAY */
337 }
338 
339 
351 int
353  enum MHD_ValueKind kind,
354  MHD_KeyValueIterator iterator,
355  void *iterator_cls)
356 {
357  int ret;
358  struct MHD_HTTP_Header *pos;
359 
360  if (NULL == connection)
361  return -1;
362  ret = 0;
363  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
364  if (0 != (pos->kind & kind))
365  {
366  ret++;
367  if ( (NULL != iterator) &&
368  (MHD_YES != iterator (iterator_cls,
369  pos->kind,
370  pos->header,
371  pos->value)) )
372  return ret;
373  }
374  return ret;
375 }
376 
377 
403 int
405  enum MHD_ValueKind kind,
406  const char *key,
407  const char *value)
408 {
409  struct MHD_HTTP_Header *pos;
410 
411  pos = MHD_pool_allocate (connection->pool,
412  sizeof (struct MHD_HTTP_Header),
413  MHD_YES);
414  if (NULL == pos)
415  return MHD_NO;
416  pos->header = (char *) key;
417  pos->value = (char *) value;
418  pos->kind = kind;
419  pos->next = NULL;
420  /* append 'pos' to the linked list of headers */
421  if (NULL == connection->headers_received_tail)
422  {
423  connection->headers_received = pos;
424  connection->headers_received_tail = pos;
425  }
426  else
427  {
428  connection->headers_received_tail->next = pos;
429  connection->headers_received_tail = pos;
430  }
431  return MHD_YES;
432 }
433 
434 
445 const char *
447  enum MHD_ValueKind kind,
448  const char *key)
449 {
450  struct MHD_HTTP_Header *pos;
451 
452  if (NULL == connection)
453  return NULL;
454  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
455  if ((0 != (pos->kind & kind)) &&
456  ( (key == pos->header) ||
457  ( (NULL != pos->header) &&
458  (NULL != key) &&
460  pos->header)))))
461  return pos->value;
462  return NULL;
463 }
464 
465 
473 static int
474 need_100_continue (struct MHD_Connection *connection)
475 {
476  const char *expect;
477 
478  return ( (NULL == connection->response) &&
479  (NULL != connection->version) &&
480  (MHD_str_equal_caseless_(connection->version,
482  (NULL != (expect = MHD_lookup_connection_value (connection,
485  (MHD_str_equal_caseless_(expect,
486  "100-continue")) &&
487  (connection->continue_message_write_offset <
488  strlen (HTTP_100_CONTINUE)) );
489 }
490 
491 
499 void
501  enum MHD_RequestTerminationCode termination_code)
502 {
503  struct MHD_Daemon *daemon;
504 
505  daemon = connection->daemon;
506  if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
507  shutdown (connection->socket_fd,
508  SHUT_WR);
509  connection->state = MHD_CONNECTION_CLOSED;
511  if ( (NULL != daemon->notify_completed) &&
512  (MHD_YES == connection->client_aware) )
513  daemon->notify_completed (daemon->notify_completed_cls,
514  connection,
515  &connection->client_context,
516  termination_code);
517  connection->client_aware = MHD_NO;
518 
519  /* if we were at the connection limit before and are in
520  thread-per-connection mode, signal the main thread
521  to resume accepting connections */
522  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
523  (MHD_ITC_IS_VALID_ (daemon->itc)) &&
524  (! MHD_itc_activate_ (daemon->itc, "c")) )
525  {
526 #ifdef HAVE_MESSAGES
527  MHD_DLOG (daemon,
528  _("Failed to signal end of connection via inter-thread communication channel"));
529 #endif
530  }
531 }
532 
533 
541 static void
543  const char *emsg)
544 {
545 #ifdef HAVE_MESSAGES
546  if (NULL != emsg)
547  MHD_DLOG (connection->daemon,
548  emsg);
549 #endif
550  MHD_connection_close_ (connection,
552 }
553 
554 
559 #ifdef HAVE_MESSAGES
560 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
561 #else
562 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
563 #endif
564 
565 
578 static int
580 {
581  ssize_t ret;
582  struct MHD_Response *response;
583 
584  response = connection->response;
585  if (NULL == response->crc)
586  return MHD_YES;
587  if ( (0 == response->total_size) ||
588  (connection->response_write_position == response->total_size) )
589  return MHD_YES; /* 0-byte response is always ready */
590  if ( (response->data_start <=
591  connection->response_write_position) &&
592  (response->data_size + response->data_start >
593  connection->response_write_position) )
594  return MHD_YES; /* response already ready */
595 #if LINUX
596  if ( (MHD_INVALID_SOCKET != response->fd) &&
597  (0 == (connection->daemon->options & MHD_USE_TLS)) )
598  {
599  /* will use sendfile, no need to bother response crc */
600  return MHD_YES;
601  }
602 #endif
603 
604  ret = response->crc (response->crc_cls,
605  connection->response_write_position,
606  response->data,
607  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
608  response->total_size -
609  connection->response_write_position));
610  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
611  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
612  {
613  /* either error or http 1.0 transfer, close socket! */
614  response->total_size = connection->response_write_position;
615  MHD_mutex_unlock_chk_ (&response->mutex);
616  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
617  MHD_connection_close_ (connection,
619  else
620  CONNECTION_CLOSE_ERROR (connection,
621  _("Closing connection (application reported error generating data)\n"));
622  return MHD_NO;
623  }
624  response->data_start = connection->response_write_position;
625  response->data_size = ret;
626  if (0 == ret)
627  {
629  MHD_mutex_unlock_chk_ (&response->mutex);
630  return MHD_NO;
631  }
632  return MHD_YES;
633 }
634 
635 
645 static int
647 {
648  ssize_t ret;
649  char *buf;
650  struct MHD_Response *response;
651  size_t size;
652  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
653  int cblen;
654 
655  response = connection->response;
656  if (0 == connection->write_buffer_size)
657  {
658  size = MHD_MIN (connection->daemon->pool_size,
659  2 * (0xFFFFFF + sizeof(cbuf) + 2));
660  do
661  {
662  size /= 2;
663  if (size < 128)
664  {
665  /* not enough memory */
666  CONNECTION_CLOSE_ERROR (connection,
667  _("Closing connection (out of memory)\n"));
668  return MHD_NO;
669  }
670  buf = MHD_pool_allocate (connection->pool,
671  size,
672  MHD_NO);
673  }
674  while (NULL == buf);
675  connection->write_buffer_size = size;
676  connection->write_buffer = buf;
677  }
678 
679  if (0 == response->total_size)
680  ret = 0; /* response must be empty, don't bother calling crc */
681  else if ( (response->data_start <=
682  connection->response_write_position) &&
683  (response->data_start + response->data_size >
684  connection->response_write_position) )
685  {
686  /* difference between response_write_position and data_start is less
687  than data_size which is size_t type, no need to check for overflow */
688  const size_t data_write_offset
689  = (size_t)(connection->response_write_position - response->data_start);
690  /* buffer already ready, use what is there for the chunk */
691  ret = response->data_size - data_write_offset;
692  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
693  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
694  memcpy (&connection->write_buffer[sizeof (cbuf)],
695  &response->data[data_write_offset],
696  ret);
697  }
698  else
699  {
700  /* buffer not in range, try to fill it */
701  ret = response->crc (response->crc_cls,
702  connection->response_write_position,
703  &connection->write_buffer[sizeof (cbuf)],
704  connection->write_buffer_size - sizeof (cbuf) - 2);
705  }
706  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
707  {
708  /* error, close socket! */
709  response->total_size = connection->response_write_position;
710  CONNECTION_CLOSE_ERROR (connection,
711  _("Closing connection (application error generating response)\n"));
712  return MHD_NO;
713  }
714  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
715  (0 == response->total_size) )
716  {
717  /* end of message, signal other side! */
718  strcpy (connection->write_buffer,
719  "0\r\n");
720  connection->write_buffer_append_offset = 3;
721  connection->write_buffer_send_offset = 0;
722  response->total_size = connection->response_write_position;
723  return MHD_YES;
724  }
725  if (0 == ret)
726  {
728  return MHD_NO;
729  }
730  if (ret > 0xFFFFFF)
731  ret = 0xFFFFFF;
732  cblen = MHD_snprintf_(cbuf,
733  sizeof (cbuf),
734  "%X\r\n",
735  (unsigned int) ret);
736  EXTRA_CHECK(cblen > 0);
737  EXTRA_CHECK(cblen < sizeof(cbuf));
738  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
739  cbuf,
740  cblen);
741  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
742  "\r\n",
743  2);
744  connection->response_write_position += ret;
745  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
746  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
747  return MHD_YES;
748 }
749 
750 
767 static int
768 keepalive_possible (struct MHD_Connection *connection)
769 {
770  const char *end;
771 
772  if (NULL == connection->version)
773  return MHD_NO;
774  if ( (NULL != connection->response) &&
775  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
776  return MHD_NO;
777  end = MHD_lookup_connection_value (connection,
780  if (MHD_str_equal_caseless_(connection->version,
782  {
783  if (NULL == end)
784  return MHD_YES;
785  if ( (MHD_str_equal_caseless_ (end,
786  "close")) ||
787  ( (MHD_str_equal_caseless_ (end,
788  "upgrade")) &&
789  (NULL == connection->response->upgrade_handler) ) )
790  return MHD_NO;
791  return MHD_YES;
792  }
793  if (MHD_str_equal_caseless_(connection->version,
795  {
796  if (NULL == end)
797  return MHD_NO;
798  if (MHD_str_equal_caseless_(end,
799  "Keep-Alive"))
800  return MHD_YES;
801  return MHD_NO;
802  }
803  return MHD_NO;
804 }
805 
806 
813 static void
814 get_date_string (char *date)
815 {
816  static const char *const days[] = {
817  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
818  };
819  static const char *const mons[] = {
820  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
821  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
822  };
823  struct tm now;
824  time_t t;
825 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
826  struct tm* pNow;
827 #endif
828 
829  date[0] = 0;
830  time (&t);
831 #if defined(HAVE_C11_GMTIME_S)
832  if (NULL == gmtime_s (&t,
833  &now))
834  return;
835 #elif defined(HAVE_W32_GMTIME_S)
836  if (0 != gmtime_s (&now,
837  &t))
838  return;
839 #elif defined(HAVE_GMTIME_R)
840  if (NULL == gmtime_r(&t,
841  &now))
842  return;
843 #else
844  pNow = gmtime(&t);
845  if (NULL == pNow)
846  return;
847  now = *pNow;
848 #endif
849  sprintf (date,
850  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
851  days[now.tm_wday % 7],
852  (unsigned int) now.tm_mday,
853  mons[now.tm_mon % 12],
854  (unsigned int) (1900 + now.tm_year),
855  (unsigned int) now.tm_hour,
856  (unsigned int) now.tm_min,
857  (unsigned int) now.tm_sec);
858 }
859 
860 
871 static int
873 {
874  void *buf;
875  size_t new_size;
876 
877  if (0 == connection->read_buffer_size)
878  new_size = connection->daemon->pool_size / 2;
879  else
880  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
881  buf = MHD_pool_reallocate (connection->pool,
882  connection->read_buffer,
883  connection->read_buffer_size,
884  new_size);
885  if (NULL == buf)
886  return MHD_NO;
887  /* we can actually grow the buffer, do it! */
888  connection->read_buffer = buf;
889  connection->read_buffer_size = new_size;
890  return MHD_YES;
891 }
892 
893 
903 static int
905 {
906  size_t size;
907  size_t off;
908  struct MHD_HTTP_Header *pos;
909  char code[256];
910  char date[128];
911  char content_length_buf[128];
912  size_t content_length_len;
913  char *data;
914  enum MHD_ValueKind kind;
915  const char *reason_phrase;
916  uint32_t rc;
917  const char *client_requested_close;
918  const char *response_has_close;
919  const char *response_has_keepalive;
920  const char *have_encoding;
921  const char *have_content_length;
922  int must_add_close;
923  int must_add_chunked_encoding;
924  int must_add_keep_alive;
925  int must_add_content_length;
926 
927  EXTRA_CHECK (NULL != connection->version);
928  if (0 == connection->version[0])
929  {
930  data = MHD_pool_allocate (connection->pool,
931  0,
932  MHD_YES);
933  connection->write_buffer = data;
934  connection->write_buffer_append_offset = 0;
935  connection->write_buffer_send_offset = 0;
936  connection->write_buffer_size = 0;
937  return MHD_YES;
938  }
939  rc = connection->responseCode & (~MHD_ICY_FLAG);
940  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
941  {
942  reason_phrase = MHD_get_reason_phrase_for (rc);
943  sprintf (code,
944  "%s %u %s\r\n",
945  (0 != (connection->responseCode & MHD_ICY_FLAG))
946  ? "ICY"
948  connection->version))
951  rc,
952  reason_phrase);
953  off = strlen (code);
954  /* estimate size */
955  size = off + 2; /* +2 for extra "\r\n" at the end */
956  kind = MHD_HEADER_KIND;
957  if ( (0 == (connection->daemon->options & MHD_SUPPRESS_DATE_NO_CLOCK)) &&
958  (NULL == MHD_get_response_header (connection->response,
960  get_date_string (date);
961  else
962  date[0] = '\0';
963  size += strlen (date);
964  }
965  else
966  {
967  /* 2 bytes for final CRLF of a Chunked-Body */
968  size = 2;
969  kind = MHD_FOOTER_KIND;
970  off = 0;
971  }
972 
973  /* calculate extra headers we need to add, such as 'Connection: close',
974  first see what was explicitly requested by the application */
975  must_add_close = MHD_NO;
976  must_add_chunked_encoding = MHD_NO;
977  must_add_keep_alive = MHD_NO;
978  must_add_content_length = MHD_NO;
979  response_has_keepalive = NULL;
980  switch (connection->state)
981  {
983  response_has_close = MHD_get_response_header (connection->response,
985  response_has_keepalive = response_has_close;
986  if ( (NULL != response_has_close) &&
987  (! MHD_str_equal_caseless_ (response_has_close,
988  "close")) )
989  response_has_close = NULL;
990  if ( (NULL != response_has_keepalive) &&
991  (! MHD_str_equal_caseless_ (response_has_keepalive,
992  "Keep-Alive")) )
993  response_has_keepalive = NULL;
994  client_requested_close = MHD_lookup_connection_value (connection,
997  if ( (NULL != client_requested_close) &&
998  (! MHD_str_equal_caseless_ (client_requested_close,
999  "close")) )
1000  client_requested_close = NULL;
1001 
1002  /* now analyze chunked encoding situation */
1003  connection->have_chunked_upload = MHD_NO;
1004 
1005  if ( (MHD_SIZE_UNKNOWN == connection->response->total_size) &&
1006  (NULL == response_has_close) &&
1007  (NULL == client_requested_close) )
1008  {
1009  /* size is unknown, and close was not explicitly requested;
1010  need to either to HTTP 1.1 chunked encoding or
1011  close the connection */
1012  /* 'close' header doesn't exist yet, see if we need to add one;
1013  if the client asked for a close, no need to start chunk'ing */
1014  if ( (MHD_YES == keepalive_possible (connection)) &&
1016  connection->version) ) )
1017  {
1018  have_encoding = MHD_get_response_header (connection->response,
1020  if (NULL == have_encoding)
1021  {
1022  must_add_chunked_encoding = MHD_YES;
1023  connection->have_chunked_upload = MHD_YES;
1024  }
1025  else if (MHD_str_equal_caseless_ (have_encoding,
1026  "identity"))
1027  {
1028  /* application forced identity encoding, can't do 'chunked' */
1029  must_add_close = MHD_YES;
1030  }
1031  else
1032  {
1033  connection->have_chunked_upload = MHD_YES;
1034  }
1035  }
1036  else
1037  {
1038  /* Keep alive or chunking not possible
1039  => set close header if not present */
1040  if (NULL == response_has_close)
1041  must_add_close = MHD_YES;
1042  }
1043  }
1044 
1045  /* check for other reasons to add 'close' header */
1046  if ( ( (NULL != client_requested_close) ||
1047  (MHD_YES == connection->read_closed) ) &&
1048  (NULL == response_has_close) &&
1049  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1050  must_add_close = MHD_YES;
1051 
1052  /* check if we should add a 'content length' header */
1053  have_content_length = MHD_get_response_header (connection->response,
1055 
1056  /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1057  codes SHOULD NOT have a Content-Length according to spec;
1058  also chunked encoding / unknown length or CONNECT... */
1059  if ( (MHD_SIZE_UNKNOWN != connection->response->total_size) &&
1060  (MHD_HTTP_NO_CONTENT != rc) &&
1061  (MHD_HTTP_NOT_MODIFIED != rc) &&
1062  (MHD_HTTP_OK <= rc) &&
1063  (NULL == have_content_length) &&
1064  ( (NULL == connection->method) ||
1065  (! MHD_str_equal_caseless_ (connection->method,
1067  {
1068  /*
1069  Here we add a content-length if one is missing; however,
1070  for 'connect' methods, the responses MUST NOT include a
1071  content-length header *if* the response code is 2xx (in
1072  which case we expect there to be no body). Still,
1073  as we don't know the response code here in some cases, we
1074  simply only force adding a content-length header if this
1075  is not a 'connect' or if the response is not empty
1076  (which is kind of more sane, because if some crazy
1077  application did return content with a 2xx status code,
1078  then having a content-length might again be a good idea).
1079 
1080  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1081  a recent development of the HTTP 1.1 specification.
1082  */
1083  content_length_len
1084  = sprintf (content_length_buf,
1086  (MHD_UNSIGNED_LONG_LONG) connection->response->total_size);
1087  must_add_content_length = MHD_YES;
1088  }
1089 
1090  /* check for adding keep alive */
1091  if ( (NULL == response_has_keepalive) &&
1092  (NULL == response_has_close) &&
1093  (MHD_NO == must_add_close) &&
1094  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) &&
1095  (MHD_YES == keepalive_possible (connection)) )
1096  must_add_keep_alive = MHD_YES;
1097  break;
1099  response_has_keepalive = NULL;
1100  break;
1101  default:
1102  EXTRA_CHECK (0);
1103  }
1104 
1105  if (must_add_close)
1106  size += strlen ("Connection: close\r\n");
1107  if (must_add_keep_alive)
1108  size += strlen ("Connection: Keep-Alive\r\n");
1109  if (must_add_chunked_encoding)
1110  size += strlen ("Transfer-Encoding: chunked\r\n");
1111  if (must_add_content_length)
1112  size += content_length_len;
1113  EXTRA_CHECK (! (must_add_close && must_add_keep_alive) );
1114  EXTRA_CHECK (! (must_add_chunked_encoding && must_add_content_length) );
1115 
1116  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1117  if ( (pos->kind == kind) &&
1118  (! ( (MHD_YES == must_add_close) &&
1119  (pos->value == response_has_keepalive) &&
1122  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1123  /* produce data */
1124  data = MHD_pool_allocate (connection->pool,
1125  size + 1,
1126  MHD_NO);
1127  if (NULL == data)
1128  {
1129 #ifdef HAVE_MESSAGES
1130  MHD_DLOG (connection->daemon,
1131  "Not enough memory for write!\n");
1132 #endif
1133  return MHD_NO;
1134  }
1135  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1136  {
1137  memcpy (data,
1138  code,
1139  off);
1140  }
1141  if (must_add_close)
1142  {
1143  /* we must add the 'Connection: close' header */
1144  memcpy (&data[off],
1145  "Connection: close\r\n",
1146  strlen ("Connection: close\r\n"));
1147  off += strlen ("Connection: close\r\n");
1148  }
1149  if (must_add_keep_alive)
1150  {
1151  /* we must add the 'Connection: Keep-Alive' header */
1152  memcpy (&data[off],
1153  "Connection: Keep-Alive\r\n",
1154  strlen ("Connection: Keep-Alive\r\n"));
1155  off += strlen ("Connection: Keep-Alive\r\n");
1156  }
1157  if (must_add_chunked_encoding)
1158  {
1159  /* we must add the 'Transfer-Encoding: chunked' header */
1160  memcpy (&data[off],
1161  "Transfer-Encoding: chunked\r\n",
1162  strlen ("Transfer-Encoding: chunked\r\n"));
1163  off += strlen ("Transfer-Encoding: chunked\r\n");
1164  }
1165  if (must_add_content_length)
1166  {
1167  /* we must add the 'Content-Length' header */
1168  memcpy (&data[off],
1169  content_length_buf,
1170  content_length_len);
1171  off += content_length_len;
1172  }
1173  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1174  if ( (pos->kind == kind) &&
1175  (! ( (pos->value == response_has_keepalive) &&
1176  (MHD_YES == must_add_close) &&
1179  off += sprintf (&data[off],
1180  "%s: %s\r\n",
1181  pos->header,
1182  pos->value);
1183  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1184  {
1185  strcpy (&data[off],
1186  date);
1187  off += strlen (date);
1188  }
1189  memcpy (&data[off],
1190  "\r\n",
1191  2);
1192  off += 2;
1193 
1194  if (off != size)
1196  __FILE__,
1197  __LINE__,
1198  NULL);
1199  connection->write_buffer = data;
1200  connection->write_buffer_append_offset = size;
1201  connection->write_buffer_send_offset = 0;
1202  connection->write_buffer_size = size + 1;
1203  return MHD_YES;
1204 }
1205 
1206 
1216 static void
1218  unsigned int status_code,
1219  const char *message)
1220 {
1221  struct MHD_Response *response;
1222 
1223  if (NULL == connection->version)
1224  {
1225  /* we were unable to process the full header line, so we don't
1226  really know what version the client speaks; assume 1.0 */
1227  connection->version = MHD_HTTP_VERSION_1_0;
1228  }
1229  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1230  connection->read_closed = MHD_YES;
1231 #ifdef HAVE_MESSAGES
1232  MHD_DLOG (connection->daemon,
1233  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1234  status_code,
1235  message);
1236 #endif
1237  EXTRA_CHECK (NULL == connection->response);
1238  response = MHD_create_response_from_buffer (strlen (message),
1239  (void *) message,
1241  MHD_queue_response (connection,
1242  status_code,
1243  response);
1244  EXTRA_CHECK (NULL != connection->response);
1245  MHD_destroy_response (response);
1246  if (MHD_NO == build_header_response (connection))
1247  {
1248  /* oops - close! */
1249  CONNECTION_CLOSE_ERROR (connection,
1250  _("Closing connection (failed to create response header)\n"));
1251  }
1252  else
1253  {
1254  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1255  }
1256 }
1257 
1258 
1267 static void
1269 {
1270  while (1)
1271  {
1272 #if DEBUG_STATES
1273  MHD_DLOG (connection->daemon,
1274  _("In function %s handling connection at state: %s\n"),
1275  __FUNCTION__,
1276  MHD_state_to_string (connection->state));
1277 #endif
1278  switch (connection->state)
1279  {
1280 #if HTTPS_SUPPORT
1282  if (0 == gnutls_record_get_direction (connection->tls_session))
1284  else
1286  break;
1287 #endif
1288  case MHD_CONNECTION_INIT:
1291  /* while reading headers, we always grow the
1292  read buffer if needed, no size-check required */
1293  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1294  (MHD_NO == try_grow_read_buffer (connection)) )
1295  {
1296  transmit_error_response (connection,
1297  (connection->url != NULL)
1300  REQUEST_TOO_BIG);
1301  continue;
1302  }
1303  if (MHD_NO == connection->read_closed)
1305  else
1307  break;
1309  EXTRA_CHECK (0);
1310  break;
1312  EXTRA_CHECK (0);
1313  break;
1316  break;
1318  if (connection->read_buffer_offset == connection->read_buffer_size)
1319  {
1320  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1321  (0 != (connection->daemon->options &
1324  {
1325  /* failed to grow the read buffer, and the
1326  client which is supposed to handle the
1327  received data in a *blocking* fashion
1328  (in this mode) did not handle the data as
1329  it was supposed to!
1330  => we would either have to do busy-waiting
1331  (on the client, which would likely fail),
1332  or if we do nothing, we would just timeout
1333  on the connection (if a timeout is even
1334  set!).
1335  Solution: we kill the connection with an error */
1336  transmit_error_response (connection,
1338  INTERNAL_ERROR);
1339  continue;
1340  }
1341  }
1342  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1343  (MHD_NO == connection->read_closed) )
1345  else
1347  break;
1350  /* while reading footers, we always grow the
1351  read buffer if needed, no size-check required */
1352  if (MHD_YES == connection->read_closed)
1353  {
1354  CONNECTION_CLOSE_ERROR (connection,
1355  NULL);
1356  continue;
1357  }
1359  /* transition to FOOTERS_RECEIVED
1360  happens in read handler */
1361  break;
1364  break;
1366  /* headers in buffer, keep writing */
1368  break;
1370  EXTRA_CHECK (0);
1371  break;
1374  break;
1377  break;
1380  break;
1383  break;
1385  EXTRA_CHECK (0);
1386  break;
1389  break;
1391  EXTRA_CHECK (0);
1392  break;
1393  case MHD_CONNECTION_CLOSED:
1395  return; /* do nothing, not even reading */
1396  default:
1397  EXTRA_CHECK (0);
1398  }
1399  break;
1400  }
1401 }
1402 
1403 
1417 static char *
1419  size_t *line_len)
1420 {
1421  char *rbuf;
1422  size_t pos;
1423 
1424  if (0 == connection->read_buffer_offset)
1425  return NULL;
1426  pos = 0;
1427  rbuf = connection->read_buffer;
1428  while ( (pos < connection->read_buffer_offset - 1) &&
1429  ('\r' != rbuf[pos]) &&
1430  ('\n' != rbuf[pos]) )
1431  pos++;
1432  if ( (pos == connection->read_buffer_offset - 1) &&
1433  ('\n' != rbuf[pos]) )
1434  {
1435  /* not found, consider growing... */
1436  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1437  (MHD_NO ==
1438  try_grow_read_buffer (connection)) )
1439  {
1440  transmit_error_response (connection,
1441  (NULL != connection->url)
1444  REQUEST_TOO_BIG);
1445  }
1446  if (line_len)
1447  *line_len = 0;
1448  return NULL;
1449  }
1450 
1451  if (line_len)
1452  *line_len = pos;
1453  /* found, check if we have proper LFCR */
1454  if ( ('\r' == rbuf[pos]) &&
1455  ('\n' == rbuf[pos + 1]) )
1456  rbuf[pos++] = '\0'; /* skip both r and n */
1457  rbuf[pos++] = '\0';
1458  connection->read_buffer += pos;
1459  connection->read_buffer_size -= pos;
1460  connection->read_buffer_offset -= pos;
1461  return rbuf;
1462 }
1463 
1464 
1476 static int
1478  const char *key,
1479  const char *value,
1480  enum MHD_ValueKind kind)
1481 {
1482  if (MHD_NO ==
1483  MHD_set_connection_value (connection,
1484  kind,
1485  key,
1486  value))
1487  {
1488 #ifdef HAVE_MESSAGES
1489  MHD_DLOG (connection->daemon,
1490  _("Not enough memory in pool to allocate header record!\n"));
1491 #endif
1492  transmit_error_response (connection,
1494  REQUEST_TOO_BIG);
1495  return MHD_NO;
1496  }
1497  return MHD_YES;
1498 }
1499 
1500 
1507 static int
1509 {
1510  const char *hdr;
1511  char *cpy;
1512  char *pos;
1513  char *sce;
1514  char *semicolon;
1515  char *equals;
1516  char *ekill;
1517  char old;
1518  int quotes;
1519 
1520  hdr = MHD_lookup_connection_value (connection,
1523  if (NULL == hdr)
1524  return MHD_YES;
1525  cpy = MHD_pool_allocate (connection->pool,
1526  strlen (hdr) + 1,
1527  MHD_YES);
1528  if (NULL == cpy)
1529  {
1530 #ifdef HAVE_MESSAGES
1531  MHD_DLOG (connection->daemon,
1532  _("Not enough memory in pool to parse cookies!\n"));
1533 #endif
1534  transmit_error_response (connection,
1536  REQUEST_TOO_BIG);
1537  return MHD_NO;
1538  }
1539  memcpy (cpy,
1540  hdr,
1541  strlen (hdr) + 1);
1542  pos = cpy;
1543  while (NULL != pos)
1544  {
1545  while (' ' == *pos)
1546  pos++; /* skip spaces */
1547 
1548  sce = pos;
1549  while ( ((*sce) != '\0') &&
1550  ((*sce) != ',') &&
1551  ((*sce) != ';') &&
1552  ((*sce) != '=') )
1553  sce++;
1554  /* remove tailing whitespace (if any) from key */
1555  ekill = sce - 1;
1556  while ( (*ekill == ' ') &&
1557  (ekill >= pos) )
1558  *(ekill--) = '\0';
1559  old = *sce;
1560  *sce = '\0';
1561  if (old != '=')
1562  {
1563  /* value part omitted, use empty string... */
1564  if (MHD_NO ==
1565  connection_add_header (connection,
1566  pos,
1567  "",
1568  MHD_COOKIE_KIND))
1569  return MHD_NO;
1570  if (old == '\0')
1571  break;
1572  pos = sce + 1;
1573  continue;
1574  }
1575  equals = sce + 1;
1576  quotes = 0;
1577  semicolon = equals;
1578  while ( ('\0' != semicolon[0]) &&
1579  ( (0 != quotes) ||
1580  ( (';' != semicolon[0]) &&
1581  (',' != semicolon[0]) ) ) )
1582  {
1583  if ('"' == semicolon[0])
1584  quotes = (quotes + 1) & 1;
1585  semicolon++;
1586  }
1587  if ('\0' == semicolon[0])
1588  semicolon = NULL;
1589  if (NULL != semicolon)
1590  {
1591  semicolon[0] = '\0';
1592  semicolon++;
1593  }
1594  /* remove quotes */
1595  if ( ('"' == equals[0]) &&
1596  ('"' == equals[strlen (equals) - 1]) )
1597  {
1598  equals[strlen (equals) - 1] = '\0';
1599  equals++;
1600  }
1601  if (MHD_NO ==
1602  connection_add_header (connection,
1603  pos,
1604  equals,
1605  MHD_COOKIE_KIND))
1606  return MHD_NO;
1607  pos = semicolon;
1608  }
1609  return MHD_YES;
1610 }
1611 
1612 
1621 static int
1623  char *line,
1624  size_t line_len)
1625 {
1626  struct MHD_Daemon *daemon = connection->daemon;
1627  const char *curi;
1628  char *uri;
1629  char *http_version;
1630  char *args;
1631  unsigned int unused_num_headers;
1632 
1633  if (NULL == (uri = memchr (line,
1634  ' ',
1635  line_len)))
1636  return MHD_NO; /* serious error */
1637  uri[0] = '\0';
1638  connection->method = line;
1639  uri++;
1640  /* Skip any spaces. Not required by standard but allow
1641  to be more tolerant. */
1642  while ( (' ' == uri[0]) &&
1643  ( (size_t)(uri - line) < line_len) )
1644  uri++;
1645  if (uri - line == line_len)
1646  {
1647  curi = "";
1648  uri = NULL;
1649  connection->version = "";
1650  args = NULL;
1651  }
1652  else
1653  {
1654  curi = uri;
1655  /* Search from back to accept misformed URI with space */
1656  http_version = line + line_len - 1;
1657  /* Skip any trailing spaces */
1658  while ( (' ' == http_version[0]) &&
1659  (http_version > uri) )
1660  http_version--;
1661  /* Find first space in reverse direction */
1662  while ( (' ' != http_version[0]) &&
1663  (http_version > uri) )
1664  http_version--;
1665  if (http_version > uri)
1666  {
1667  http_version[0] = '\0';
1668  connection->version = http_version + 1;
1669  args = memchr (uri,
1670  '?',
1671  http_version - uri);
1672  }
1673  else
1674  {
1675  connection->version = "";
1676  args = memchr (uri,
1677  '?',
1678  line_len - (uri - line));
1679  }
1680  }
1681  if (NULL != daemon->uri_log_callback)
1682  {
1683  connection->client_context
1684  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
1685  curi,
1686  connection);
1687  connection->client_aware = MHD_YES;
1688  }
1689  if (NULL != args)
1690  {
1691  args[0] = '\0';
1692  args++;
1693  /* note that this call clobbers 'args' */
1694  MHD_parse_arguments_ (connection,
1696  args,
1698  &unused_num_headers);
1699  }
1700  if (NULL != uri)
1701  daemon->unescape_callback (daemon->unescape_callback_cls,
1702  connection,
1703  uri);
1704  connection->url = curi;
1705  return MHD_YES;
1706 }
1707 
1708 
1716 static void
1718 {
1719  size_t processed;
1720 
1721  if (NULL != connection->response)
1722  return; /* already queued a response */
1723  processed = 0;
1724  connection->client_aware = MHD_YES;
1725  if (MHD_NO ==
1726  connection->daemon->default_handler (connection->daemon-> default_handler_cls,
1727  connection,
1728  connection->url,
1729  connection->method,
1730  connection->version,
1731  NULL,
1732  &processed,
1733  &connection->client_context))
1734  {
1735  /* serious internal error, close connection */
1736  CONNECTION_CLOSE_ERROR (connection,
1737  _("Application reported internal error, closing connection.\n"));
1738  return;
1739  }
1740 }
1741 
1742 
1743 
1751 static void
1753 {
1754  size_t processed;
1755  size_t available;
1756  size_t used;
1757  size_t i;
1758  int instant_retry;
1759  int malformed;
1760  char *buffer_head;
1761 
1762  if (NULL != connection->response)
1763  return; /* already queued a response */
1764 
1765  buffer_head = connection->read_buffer;
1766  available = connection->read_buffer_offset;
1767  do
1768  {
1769  instant_retry = MHD_NO;
1770  if ( (MHD_YES == connection->have_chunked_upload) &&
1771  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
1772  {
1773  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
1774  (0 != connection->current_chunk_offset) &&
1775  (available >= 2) )
1776  {
1777  /* skip new line at the *end* of a chunk */
1778  i = 0;
1779  if ( ('\r' == buffer_head[i]) ||
1780  ('\n' == buffer_head[i]) )
1781  i++; /* skip 1st part of line feed */
1782  if ( ('\r' == buffer_head[i]) ||
1783  ('\n' == buffer_head[i]) )
1784  i++; /* skip 2nd part of line feed */
1785  if (0 == i)
1786  {
1787  /* malformed encoding */
1788  CONNECTION_CLOSE_ERROR (connection,
1789  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
1790  return;
1791  }
1792  available -= i;
1793  buffer_head += i;
1794  connection->current_chunk_offset = 0;
1795  connection->current_chunk_size = 0;
1796  }
1797  if (connection->current_chunk_offset <
1798  connection->current_chunk_size)
1799  {
1800  /* we are in the middle of a chunk, give
1801  as much as possible to the client (without
1802  crossing chunk boundaries) */
1803  processed
1804  = connection->current_chunk_size - connection->current_chunk_offset;
1805  if (processed > available)
1806  processed = available;
1807  if (available > processed)
1808  instant_retry = MHD_YES;
1809  }
1810  else
1811  {
1812  /* we need to read chunk boundaries */
1813  i = 0;
1814  while (i < available)
1815  {
1816  if ( ('\r' == buffer_head[i]) ||
1817  ('\n' == buffer_head[i]) )
1818  break;
1819  i++;
1820  if (i >= 6)
1821  break;
1822  }
1823  /* take '\n' into account; if '\n'
1824  is the unavailable character, we
1825  will need to wait until we have it
1826  before going further */
1827  if ( (i + 1 >= available) &&
1828  ! ( (1 == i) &&
1829  (2 == available) &&
1830  ('0' == buffer_head[0]) ) )
1831  break; /* need more data... */
1832  malformed = (i >= 6);
1833  if (! malformed)
1834  {
1835  size_t num_dig = MHD_strx_to_sizet_n_ (buffer_head,
1836  i,
1837  &connection->current_chunk_size);
1838  malformed = (i != num_dig);
1839  }
1840  if (malformed)
1841  {
1842  /* malformed encoding */
1843  CONNECTION_CLOSE_ERROR (connection,
1844  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
1845  return;
1846  }
1847  i++;
1848  if ( (i < available) &&
1849  ( ('\r' == buffer_head[i]) ||
1850  ('\n' == buffer_head[i]) ) )
1851  i++; /* skip 2nd part of line feed */
1852 
1853  buffer_head += i;
1854  available -= i;
1855  connection->current_chunk_offset = 0;
1856 
1857  if (available > 0)
1858  instant_retry = MHD_YES;
1859  if (0 == connection->current_chunk_size)
1860  {
1861  connection->remaining_upload_size = 0;
1862  break;
1863  }
1864  continue;
1865  }
1866  }
1867  else
1868  {
1869  /* no chunked encoding, give all to the client */
1870  if ( (0 != connection->remaining_upload_size) &&
1871  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
1872  (connection->remaining_upload_size < available) )
1873  {
1874  processed = (size_t)connection->remaining_upload_size;
1875  }
1876  else
1877  {
1882  processed = available;
1883  }
1884  }
1885  used = processed;
1886  connection->client_aware = MHD_YES;
1887  if (MHD_NO ==
1888  connection->daemon->default_handler (connection->daemon->default_handler_cls,
1889  connection,
1890  connection->url,
1891  connection->method,
1892  connection->version,
1893  buffer_head,
1894  &processed,
1895  &connection->client_context))
1896  {
1897  /* serious internal error, close connection */
1898  CONNECTION_CLOSE_ERROR (connection,
1899  _("Application reported internal error, closing connection.\n"));
1900  return;
1901  }
1902  if (processed > used)
1904  __FILE__,
1905  __LINE__
1906 #ifdef HAVE_MESSAGES
1907  , _("libmicrohttpd API violation")
1908 #else
1909  , NULL
1910 #endif
1911  );
1912  if (0 != processed)
1913  {
1914  instant_retry = MHD_NO; /* client did not process everything */
1915 #ifdef HAVE_MESSAGES
1916  /* client did not process all POST data, complain if
1917  the setup was incorrect, which may prevent us from
1918  handling the rest of the request */
1919  if ( ( (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) ||
1920  (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY)) ) &&
1921  (MHD_NO == connection->suspended) )
1922  MHD_DLOG (connection->daemon,
1923  _("WARNING: incomplete POST processing and connection not suspended will result in hung connection.\n"));
1924 #endif
1925  }
1926  used -= processed;
1927  if (MHD_YES == connection->have_chunked_upload)
1928  connection->current_chunk_offset += used;
1929  /* dh left "processed" bytes in buffer for next time... */
1930  buffer_head += used;
1931  available -= used;
1932  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
1933  connection->remaining_upload_size -= used;
1934  }
1935  while (MHD_YES == instant_retry);
1936  if (available > 0)
1937  memmove (connection->read_buffer,
1938  buffer_head,
1939  available);
1940  connection->read_buffer_offset = available;
1941 }
1942 
1943 
1953 static int
1954 do_read (struct MHD_Connection *connection)
1955 {
1956  ssize_t bytes_read;
1957 
1958  if (connection->read_buffer_size == connection->read_buffer_offset)
1959  return MHD_NO;
1960  bytes_read = connection->recv_cls (connection,
1961  &connection->read_buffer
1962  [connection->read_buffer_offset],
1963  connection->read_buffer_size -
1964  connection->read_buffer_offset);
1965  if (bytes_read < 0)
1966  {
1967  const int err = MHD_socket_get_error_ ();
1968  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
1970  return MHD_NO;
1972  {
1973  CONNECTION_CLOSE_ERROR (connection,
1974  NULL);
1975  return MHD_NO;
1976  }
1977  CONNECTION_CLOSE_ERROR (connection,
1978  NULL);
1979  return MHD_YES;
1980  }
1981  if (0 == bytes_read)
1982  {
1983  /* other side closed connection; RFC 2616, section 8.1.4 suggests
1984  we should then shutdown ourselves as well. */
1985  connection->read_closed = MHD_YES;
1986  MHD_connection_close_ (connection,
1988  return MHD_YES;
1989  }
1990  connection->read_buffer_offset += bytes_read;
1991  return MHD_YES;
1992 }
1993 
1994 
2003 static int
2004 do_write (struct MHD_Connection *connection)
2005 {
2006  ssize_t ret;
2007  size_t max;
2008 
2009  max = connection->write_buffer_append_offset - connection->write_buffer_send_offset;
2010  ret = connection->send_cls (connection,
2011  &connection->write_buffer
2012  [connection->write_buffer_send_offset],
2013  max);
2014 
2015  if (ret < 0)
2016  {
2017  const int err = MHD_socket_get_error_ ();
2018  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2020  return MHD_NO;
2021  CONNECTION_CLOSE_ERROR (connection,
2022  NULL);
2023  return MHD_YES;
2024  }
2025 #if DEBUG_SEND_DATA
2026  fprintf (stderr,
2027  _("Sent response: `%.*s'\n"),
2028  ret,
2029  &connection->write_buffer[connection->write_buffer_send_offset]);
2030 #endif
2031  /* only increment if this wasn't a "sendfile" transmission without
2032  buffer involvement! */
2033  if (0 != max)
2034  connection->write_buffer_send_offset += ret;
2035  return MHD_YES;
2036 }
2037 
2038 
2047 static int
2048 check_write_done (struct MHD_Connection *connection,
2049  enum MHD_CONNECTION_STATE next_state)
2050 {
2051  if (connection->write_buffer_append_offset !=
2052  connection->write_buffer_send_offset)
2053  return MHD_NO;
2054  connection->write_buffer_append_offset = 0;
2055  connection->write_buffer_send_offset = 0;
2056  connection->state = next_state;
2057  MHD_pool_reallocate (connection->pool,
2058  connection->write_buffer,
2059  connection->write_buffer_size,
2060  0);
2061  connection->write_buffer = NULL;
2062  connection->write_buffer_size = 0;
2063  return MHD_YES;
2064 }
2065 
2066 
2076 static int
2078  char *line)
2079 {
2080  char *colon;
2081 
2082  /* line should be normal header line, find colon */
2083  colon = strchr (line, ':');
2084  if (NULL == colon)
2085  {
2086  /* error in header line, die hard */
2087  CONNECTION_CLOSE_ERROR (connection,
2088  _("Received malformed line (no colon). Closing connection.\n"));
2089  return MHD_NO;
2090  }
2091  /* zero-terminate header */
2092  colon[0] = '\0';
2093  colon++; /* advance to value */
2094  while ( ('\0' != colon[0]) &&
2095  ( (' ' == colon[0]) ||
2096  ('\t' == colon[0]) ) )
2097  colon++;
2098  /* we do the actual adding of the connection
2099  header at the beginning of the while
2100  loop since we need to be able to inspect
2101  the *next* header line (in case it starts
2102  with a space...) */
2103  connection->last = line;
2104  connection->colon = colon;
2105  return MHD_YES;
2106 }
2107 
2108 
2119 static int
2121  char *line,
2122  enum MHD_ValueKind kind)
2123 {
2124  char *last;
2125  char *tmp;
2126  size_t last_len;
2127  size_t tmp_len;
2128 
2129  last = connection->last;
2130  if ( (' ' == line[0]) ||
2131  ('\t' == line[0]) )
2132  {
2133  /* value was continued on the next line, see
2134  http://www.jmarshall.com/easy/http/ */
2135  last_len = strlen (last);
2136  /* skip whitespace at start of 2nd line */
2137  tmp = line;
2138  while ( (' ' == tmp[0]) ||
2139  ('\t' == tmp[0]) )
2140  tmp++;
2141  tmp_len = strlen (tmp);
2142  /* FIXME: we might be able to do this better (faster!), as most
2143  likely 'last' and 'line' should already be adjacent in
2144  memory; however, doing this right gets tricky if we have a
2145  value continued over multiple lines (in which case we need to
2146  record how often we have done this so we can check for
2147  adjacency); also, in the case where these are not adjacent
2148  (not sure how it can happen!), we would want to allocate from
2149  the end of the pool, so as to not destroy the read-buffer's
2150  ability to grow nicely. */
2151  last = MHD_pool_reallocate (connection->pool,
2152  last,
2153  last_len + 1,
2154  last_len + tmp_len + 1);
2155  if (NULL == last)
2156  {
2157  transmit_error_response (connection,
2159  REQUEST_TOO_BIG);
2160  return MHD_NO;
2161  }
2162  memcpy (&last[last_len], tmp, tmp_len + 1);
2163  connection->last = last;
2164  return MHD_YES; /* possibly more than 2 lines... */
2165  }
2166  EXTRA_CHECK ( (NULL != last) &&
2167  (NULL != connection->colon) );
2168  if ((MHD_NO == connection_add_header (connection,
2169  last,
2170  connection->colon,
2171  kind)))
2172  {
2173  transmit_error_response (connection,
2175  REQUEST_TOO_BIG);
2176  return MHD_NO;
2177  }
2178  /* we still have the current line to deal with... */
2179  if (0 != line[0])
2180  {
2181  if (MHD_NO == process_header_line (connection,
2182  line))
2183  {
2184  transmit_error_response (connection,
2187  return MHD_NO;
2188  }
2189  }
2190  return MHD_YES;
2191 }
2192 
2193 
2201 static void
2203 {
2204  const char *clen;
2205  struct MHD_Response *response;
2206  const char *enc;
2207  const char *end;
2208 
2209  parse_cookie_header (connection);
2210  if ( (0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) &&
2211  (NULL != connection->version) &&
2213  connection->version)) &&
2214  (NULL ==
2215  MHD_lookup_connection_value (connection,
2218  {
2219  /* die, http 1.1 request without host and we are pedantic */
2220  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2221  connection->read_closed = MHD_YES;
2222 #ifdef HAVE_MESSAGES
2223  MHD_DLOG (connection->daemon,
2224  _("Received HTTP 1.1 request without `Host' header.\n"));
2225 #endif
2226  EXTRA_CHECK (NULL == connection->response);
2227  response =
2231  MHD_queue_response (connection,
2233  response);
2234  MHD_destroy_response (response);
2235  return;
2236  }
2237 
2238  connection->remaining_upload_size = 0;
2239  enc = MHD_lookup_connection_value (connection,
2242  if (NULL != enc)
2243  {
2245  if (MHD_str_equal_caseless_(enc,
2246  "chunked"))
2247  connection->have_chunked_upload = MHD_YES;
2248  }
2249  else
2250  {
2251  clen = MHD_lookup_connection_value (connection,
2254  if (NULL != clen)
2255  {
2256  end = clen + MHD_str_to_uint64_ (clen,
2257  &connection->remaining_upload_size);
2258  if ( (clen == end) ||
2259  ('\0' != *end) )
2260  {
2261  connection->remaining_upload_size = 0;
2262 #ifdef HAVE_MESSAGES
2263  MHD_DLOG (connection->daemon,
2264  "Failed to parse `Content-Length' header. Closing connection.\n");
2265 #endif
2266  CONNECTION_CLOSE_ERROR (connection,
2267  NULL);
2268  return;
2269  }
2270  }
2271  }
2272 }
2273 
2274 
2282 static void
2284 {
2285  struct MHD_Daemon *daemon = connection->daemon;
2286 
2287  connection->last_activity = MHD_monotonic_sec_counter();
2288  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2289  return; /* each connection has personal timeout */
2290 
2291  if (connection->connection_timeout != daemon->connection_timeout)
2292  return; /* custom timeout, no need to move it in "normal" DLL */
2293 
2294  /* move connection to head of timeout list (by remove + add operation) */
2296  daemon->normal_timeout_tail,
2297  connection);
2299  daemon->normal_timeout_tail,
2300  connection);
2301 }
2302 
2303 
2312 int
2314 {
2315  update_last_activity (connection);
2316  if (MHD_CONNECTION_CLOSED == connection->state)
2317  return MHD_YES;
2318  /* make sure "read" has a reasonable number of bytes
2319  in buffer to use per system call (if possible) */
2320  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2321  connection->read_buffer_size)
2322  try_grow_read_buffer (connection);
2323  if (MHD_NO == do_read (connection))
2324  return MHD_YES;
2325  while (1)
2326  {
2327 #if DEBUG_STATES
2328  MHD_DLOG (connection->daemon,
2329  _("In function %s handling connection at state: %s\n"),
2330  __FUNCTION__,
2331  MHD_state_to_string (connection->state));
2332 #endif
2333  switch (connection->state)
2334  {
2335  case MHD_CONNECTION_INIT:
2344  /* nothing to do but default action */
2345  if (MHD_YES == connection->read_closed)
2346  {
2347  MHD_connection_close_ (connection,
2349  continue;
2350  }
2351  break;
2352  case MHD_CONNECTION_CLOSED:
2353  return MHD_YES;
2355  EXTRA_CHECK (0);
2356  break;
2357  default:
2358  /* shrink read buffer to how much is actually used */
2359  MHD_pool_reallocate (connection->pool,
2360  connection->read_buffer,
2361  connection->read_buffer_size + 1,
2362  connection->read_buffer_offset);
2363  break;
2364  }
2365  break;
2366  }
2367  return MHD_YES;
2368 }
2369 
2370 
2379 int
2381 {
2382  struct MHD_Response *response;
2383  ssize_t ret;
2384 
2385  update_last_activity (connection);
2386  while (1)
2387  {
2388 #if DEBUG_STATES
2389  MHD_DLOG (connection->daemon,
2390  _("In function %s handling connection at state: %s\n"),
2391  __FUNCTION__,
2392  MHD_state_to_string (connection->state));
2393 #endif
2394  switch (connection->state)
2395  {
2396  case MHD_CONNECTION_INIT:
2400  EXTRA_CHECK (0);
2401  break;
2403  break;
2405  ret = connection->send_cls (connection,
2407  [connection->continue_message_write_offset],
2408  strlen (HTTP_100_CONTINUE) -
2409  connection->continue_message_write_offset);
2410  if (ret < 0)
2411  {
2412  const int err = MHD_socket_get_error_ ();
2413 
2414  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2416  break;
2417 #ifdef HAVE_MESSAGES
2418  MHD_DLOG (connection->daemon,
2419  _("Failed to send data: %s\n"),
2420  MHD_socket_strerr_ (err));
2421 #endif
2422  CONNECTION_CLOSE_ERROR (connection,
2423  NULL);
2424  return MHD_YES;
2425  }
2426 #if DEBUG_SEND_DATA
2427  fprintf (stderr,
2428  _("Sent 100 continue response: `%.*s'\n"),
2429  (int) ret,
2431 #endif
2432  connection->continue_message_write_offset += ret;
2433  break;
2438  EXTRA_CHECK (0);
2439  break;
2441  do_write (connection);
2442  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
2443  break;
2444  check_write_done (connection,
2446  break;
2448  EXTRA_CHECK (0);
2449  break;
2451  response = connection->response;
2452  if (connection->response_write_position <
2453  connection->response->total_size)
2454  {
2455  int err;
2456  uint64_t data_write_offset;
2457 
2458  if (NULL != response->crc)
2459  MHD_mutex_lock_chk_ (&response->mutex);
2460  if (MHD_YES != try_ready_normal_body (connection))
2461  {
2462  /* mutex was already unlocked by try_ready_normal_body */
2463  break;
2464  }
2465  data_write_offset = connection->response_write_position
2466  - response->data_start;
2467  if (data_write_offset > (uint64_t)SIZE_MAX)
2468  MHD_PANIC (_("Data offset exceeds limit"));
2469  ret = connection->send_cls (connection,
2470  &response->data
2471  [(size_t)data_write_offset],
2472  response->data_size -
2473  (size_t)data_write_offset);
2474  err = MHD_socket_get_error_ ();
2475 #if DEBUG_SEND_DATA
2476  if (ret > 0)
2477  fprintf (stderr,
2478  _("Sent %d-byte DATA response: `%.*s'\n"),
2479  (int) ret,
2480  (int) ret,
2481  &response->data[connection->response_write_position -
2482  response->data_start]);
2483 #endif
2484  if (NULL != response->crc)
2485  MHD_mutex_unlock_chk_ (&response->mutex);
2486  if (ret < 0)
2487  {
2488  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2490  return MHD_YES;
2491 #ifdef HAVE_MESSAGES
2492  MHD_DLOG (connection->daemon,
2493  _("Failed to send data: %s\n"),
2494  MHD_socket_strerr_ (err));
2495 #endif
2496  CONNECTION_CLOSE_ERROR (connection,
2497  NULL);
2498  return MHD_YES;
2499  }
2500  connection->response_write_position += ret;
2501  }
2502  if (connection->response_write_position ==
2503  connection->response->total_size)
2504  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
2505  break;
2507  EXTRA_CHECK (0);
2508  break;
2510  do_write (connection);
2511  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
2512  break;
2513  check_write_done (connection,
2514  (connection->response->total_size ==
2515  connection->response_write_position) ?
2518  break;
2521  EXTRA_CHECK (0);
2522  break;
2524  do_write (connection);
2525  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
2526  break;
2527  check_write_done (connection,
2529  break;
2531  EXTRA_CHECK (0);
2532  break;
2533  case MHD_CONNECTION_CLOSED:
2534  return MHD_YES;
2536  EXTRA_CHECK (0);
2537  break;
2539  EXTRA_CHECK (0);
2540  break;
2541  default:
2542  EXTRA_CHECK (0);
2543  CONNECTION_CLOSE_ERROR (connection,
2544  _("Internal error\n"));
2545  return MHD_YES;
2546  }
2547  break;
2548  }
2549  return MHD_YES;
2550 }
2551 
2552 
2559 static void
2561 {
2562  struct MHD_Daemon *daemon = connection->daemon;
2563 
2564  if (NULL != connection->response)
2565  {
2566  MHD_destroy_response (connection->response);
2567  connection->response = NULL;
2568  }
2569  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2570  {
2572  }
2573  else
2574  {
2575  if (connection->connection_timeout == daemon->connection_timeout)
2577  daemon->normal_timeout_tail,
2578  connection);
2579  else
2581  daemon->manual_timeout_tail,
2582  connection);
2583  }
2584  if (MHD_YES == connection->suspended)
2587  connection);
2588  else
2589  DLL_remove (daemon->connections_head,
2590  daemon->connections_tail,
2591  connection);
2592  DLL_insert (daemon->cleanup_head,
2593  daemon->cleanup_tail,
2594  connection);
2595  connection->suspended = MHD_NO;
2596  connection->resuming = MHD_NO;
2597  connection->in_idle = MHD_NO;
2598  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2600 }
2601 
2602 
2611 int
2613 {
2614  struct MHD_Daemon *daemon = connection->daemon;
2615  unsigned int timeout;
2616  const char *end;
2617  char *line;
2618  size_t line_len;
2619  int client_close;
2620 
2621  connection->in_idle = MHD_YES;
2622  while (1)
2623  {
2624 #if DEBUG_STATES
2625  MHD_DLOG (daemon,
2626  _("In function %s handling connection at state: %s\n"),
2627  __FUNCTION__,
2628  MHD_state_to_string (connection->state));
2629 #endif
2630  switch (connection->state)
2631  {
2632  case MHD_CONNECTION_INIT:
2633  line = get_next_header_line (connection,
2634  &line_len);
2635  /* Check for empty string, as we might want
2636  to tolerate 'spurious' empty lines; also
2637  NULL means we didn't get a full line yet;
2638  line is not 0-terminated here. */
2639  if ( (NULL == line) ||
2640  (0 == line[0]) )
2641  {
2642  if (MHD_CONNECTION_INIT != connection->state)
2643  continue;
2644  if (MHD_YES == connection->read_closed)
2645  {
2646  CONNECTION_CLOSE_ERROR (connection,
2647  NULL);
2648  continue;
2649  }
2650  break;
2651  }
2652  if (MHD_NO == parse_initial_message_line (connection,
2653  line,
2654  line_len))
2655  CONNECTION_CLOSE_ERROR (connection,
2656  NULL);
2657  else
2658  connection->state = MHD_CONNECTION_URL_RECEIVED;
2659  continue;
2661  line = get_next_header_line (connection,
2662  NULL);
2663  if (NULL == line)
2664  {
2665  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
2666  continue;
2667  if (MHD_YES == connection->read_closed)
2668  {
2669  CONNECTION_CLOSE_ERROR (connection,
2670  NULL);
2671  continue;
2672  }
2673  break;
2674  }
2675  if (0 == line[0])
2676  {
2677  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2678  continue;
2679  }
2680  if (MHD_NO == process_header_line (connection,
2681  line))
2682  {
2683  transmit_error_response (connection,
2686  break;
2687  }
2689  continue;
2691  line = get_next_header_line (connection,
2692  NULL);
2693  if (NULL == line)
2694  {
2695  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2696  continue;
2697  if (MHD_YES == connection->read_closed)
2698  {
2699  CONNECTION_CLOSE_ERROR (connection,
2700  NULL);
2701  continue;
2702  }
2703  break;
2704  }
2705  if (MHD_NO ==
2706  process_broken_line (connection,
2707  line,
2708  MHD_HEADER_KIND))
2709  continue;
2710  if (0 == line[0])
2711  {
2712  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2713  continue;
2714  }
2715  continue;
2717  parse_connection_headers (connection);
2718  if (MHD_CONNECTION_CLOSED == connection->state)
2719  continue;
2721  if (MHD_YES == connection->suspended)
2722  break;
2723  continue;
2725  call_connection_handler (connection); /* first call */
2726  if (MHD_CONNECTION_CLOSED == connection->state)
2727  continue;
2728  if (need_100_continue (connection))
2729  {
2730  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2731  if (MHD_NO != socket_flush_possible (connection))
2732  socket_start_extra_buffering (connection);
2733  else
2734  socket_start_no_buffering (connection);
2735 
2736  break;
2737  }
2738  if ( (NULL != connection->response) &&
2739  ( (MHD_str_equal_caseless_ (connection->method,
2741  (MHD_str_equal_caseless_ (connection->method,
2742  MHD_HTTP_METHOD_PUT))) )
2743  {
2744  /* we refused (no upload allowed!) */
2745  connection->remaining_upload_size = 0;
2746  /* force close, in case client still tries to upload... */
2747  connection->read_closed = MHD_YES;
2748  }
2749  connection->state = (0 == connection->remaining_upload_size)
2751  if (MHD_YES == connection->suspended)
2752  break;
2753  continue;
2755  if (connection->continue_message_write_offset ==
2756  strlen (HTTP_100_CONTINUE))
2757  {
2758  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2759  if (MHD_NO != socket_flush_possible (connection))
2760  socket_start_no_buffering_flush (connection);
2761  else
2762  socket_start_normal_buffering (connection);
2763 
2764  continue;
2765  }
2766  break;
2768  if (0 != connection->read_buffer_offset)
2769  {
2770  process_request_body (connection); /* loop call */
2771  if (MHD_CONNECTION_CLOSED == connection->state)
2772  continue;
2773  }
2774  if ( (0 == connection->remaining_upload_size) ||
2775  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
2776  (0 == connection->read_buffer_offset) &&
2777  (MHD_YES == connection->read_closed) ) )
2778  {
2779  if ((MHD_YES == connection->have_chunked_upload) &&
2780  (MHD_NO == connection->read_closed))
2781  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2782  else
2783  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2784  if (MHD_YES == connection->suspended)
2785  break;
2786  continue;
2787  }
2788  break;
2790  line = get_next_header_line (connection,
2791  NULL);
2792  if (NULL == line)
2793  {
2794  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2795  continue;
2796  if (MHD_YES == connection->read_closed)
2797  {
2798  CONNECTION_CLOSE_ERROR (connection,
2799  NULL);
2800  continue;
2801  }
2802  break;
2803  }
2804  if (0 == line[0])
2805  {
2806  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2807  if (MHD_YES == connection->suspended)
2808  break;
2809  continue;
2810  }
2811  if (MHD_NO == process_header_line (connection,
2812  line))
2813  {
2814  transmit_error_response (connection,
2817  break;
2818  }
2820  continue;
2822  line = get_next_header_line (connection,
2823  NULL);
2824  if (NULL == line)
2825  {
2826  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2827  continue;
2828  if (MHD_YES == connection->read_closed)
2829  {
2830  CONNECTION_CLOSE_ERROR (connection,
2831  NULL);
2832  continue;
2833  }
2834  break;
2835  }
2836  if (MHD_NO ==
2837  process_broken_line (connection,
2838  line,
2839  MHD_FOOTER_KIND))
2840  continue;
2841  if (0 == line[0])
2842  {
2843  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2844  if (MHD_YES == connection->suspended)
2845  break;
2846  continue;
2847  }
2848  continue;
2850  call_connection_handler (connection); /* "final" call */
2851  if (connection->state == MHD_CONNECTION_CLOSED)
2852  continue;
2853  if (NULL == connection->response)
2854  break; /* try again next time */
2855  if (MHD_NO == build_header_response (connection))
2856  {
2857  /* oops - close! */
2858  CONNECTION_CLOSE_ERROR (connection,
2859  _("Closing connection (failed to create response header)\n"));
2860  continue;
2861  }
2862  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2863  if (MHD_NO != socket_flush_possible (connection))
2864  socket_start_extra_buffering (connection);
2865  else
2866  socket_start_no_buffering (connection);
2867 
2868  break;
2870  /* no default action */
2871  break;
2873  /* Some clients may take some actions right after header receive */
2874  if (MHD_NO != socket_flush_possible (connection))
2875  socket_start_no_buffering_flush (connection);
2876 
2877  if (NULL != connection->response->upgrade_handler)
2878  {
2879  socket_start_normal_buffering (connection);
2880  /* This connection is "upgraded". Pass socket to application. */
2881  if (MHD_YES !=
2883  connection))
2884  {
2885  /* upgrade failed, fail hard */
2886  CONNECTION_CLOSE_ERROR (connection,
2887  NULL);
2888  continue;
2889  }
2890  connection->state = MHD_CONNECTION_UPGRADE;
2891  continue;
2892  }
2893  if (MHD_NO != socket_flush_possible (connection))
2894  socket_start_extra_buffering (connection);
2895  else
2896  socket_start_normal_buffering (connection);
2897 
2898  if (connection->have_chunked_upload)
2900  else
2902  continue;
2904  /* nothing to do here */
2905  break;
2907  if (NULL != connection->response->crc)
2908  MHD_mutex_lock_chk_ (&connection->response->mutex);
2909  if (0 == connection->response->total_size)
2910  {
2911  if (NULL != connection->response->crc)
2912  MHD_mutex_unlock_chk_ (&connection->response->mutex);
2913  connection->state = MHD_CONNECTION_BODY_SENT;
2914  continue;
2915  }
2916  if (MHD_YES == try_ready_normal_body (connection))
2917  {
2918  if (NULL != connection->response->crc)
2919  MHD_mutex_unlock_chk_ (&connection->response->mutex);
2921  /* Buffering for flushable socket was already enabled*/
2922  if (MHD_NO == socket_flush_possible (connection))
2923  socket_start_no_buffering (connection);
2924  break;
2925  }
2926  /* mutex was already unlocked by "try_ready_normal_body */
2927  /* not ready, no socket action */
2928  break;
2930  /* nothing to do here */
2931  break;
2933  if (NULL != connection->response->crc)
2934  MHD_mutex_lock_chk_ (&connection->response->mutex);
2935  if ( (0 == connection->response->total_size) ||
2936  (connection->response_write_position ==
2937  connection->response->total_size) )
2938  {
2939  if (NULL != connection->response->crc)
2940  MHD_mutex_unlock_chk_ (&connection->response->mutex);
2941  connection->state = MHD_CONNECTION_BODY_SENT;
2942  continue;
2943  }
2944  if (MHD_YES == try_ready_chunked_body (connection))
2945  {
2946  if (NULL != connection->response->crc)
2947  MHD_mutex_unlock_chk_ (&connection->response->mutex);
2949  /* Buffering for flushable socket was already enabled */
2950  if (MHD_NO == socket_flush_possible (connection))
2951  socket_start_no_buffering (connection);
2952  continue;
2953  }
2954  if (NULL != connection->response->crc)
2955  MHD_mutex_unlock_chk_ (&connection->response->mutex);
2956  break;
2958  if (MHD_NO == build_header_response (connection))
2959  {
2960  /* oops - close! */
2961  CONNECTION_CLOSE_ERROR (connection,
2962  _("Closing connection (failed to create response header)\n"));
2963  continue;
2964  }
2965  if ( (MHD_NO == connection->have_chunked_upload) ||
2966  (connection->write_buffer_send_offset ==
2967  connection->write_buffer_append_offset) )
2968  connection->state = MHD_CONNECTION_FOOTERS_SENT;
2969  else
2970  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
2971  continue;
2973  /* no default action */
2974  break;
2976  if (MHD_NO != socket_flush_possible (connection))
2977  socket_start_no_buffering_flush (connection);
2978  else
2979  socket_start_normal_buffering (connection);
2980 
2981  end =
2982  MHD_get_response_header (connection->response,
2984  client_close = ( (NULL != end) &&
2986  "close")));
2987  MHD_destroy_response (connection->response);
2988  connection->response = NULL;
2989  if ( (NULL != daemon->notify_completed) &&
2990  (MHD_YES == connection->client_aware) )
2991  {
2992  daemon->notify_completed (daemon->notify_completed_cls,
2993  connection,
2994  &connection->client_context,
2996  connection->client_aware = MHD_NO;
2997  }
2998  end =
2999  MHD_lookup_connection_value (connection,
3002  if ( (MHD_YES == connection->read_closed) ||
3003  (client_close) ||
3004  ( (NULL != end) &&
3006  "close")) ) )
3007  {
3008  connection->read_closed = MHD_YES;
3009  connection->read_buffer_offset = 0;
3010  }
3011  if (((MHD_YES == connection->read_closed) &&
3012  (0 == connection->read_buffer_offset)) ||
3013  (MHD_NO == keepalive_possible (connection)))
3014  {
3015  /* have to close for some reason */
3016  MHD_connection_close_ (connection,
3018  MHD_pool_destroy (connection->pool);
3019  connection->pool = NULL;
3020  connection->read_buffer = NULL;
3021  connection->read_buffer_size = 0;
3022  connection->read_buffer_offset = 0;
3023  }
3024  else
3025  {
3026  /* can try to keep-alive */
3027  if (MHD_NO != socket_flush_possible (connection))
3028  socket_start_normal_buffering (connection);
3029  connection->version = NULL;
3030  connection->state = MHD_CONNECTION_INIT;
3031  /* Reset the read buffer to the starting size,
3032  preserving the bytes we have already read. */
3033  connection->read_buffer
3034  = MHD_pool_reset (connection->pool,
3035  connection->read_buffer,
3036  connection->read_buffer_offset,
3037  connection->daemon->pool_size / 2);
3038  connection->read_buffer_size
3039  = connection->daemon->pool_size / 2;
3040  }
3041  connection->client_aware = MHD_NO;
3042  connection->client_context = NULL;
3043  connection->continue_message_write_offset = 0;
3044  connection->responseCode = 0;
3045  connection->headers_received = NULL;
3046  connection->headers_received_tail = NULL;
3047  connection->response_write_position = 0;
3048  connection->have_chunked_upload = MHD_NO;
3049  connection->method = NULL;
3050  connection->url = NULL;
3051  connection->write_buffer = NULL;
3052  connection->write_buffer_size = 0;
3053  connection->write_buffer_send_offset = 0;
3054  connection->write_buffer_append_offset = 0;
3055  continue;
3056  case MHD_CONNECTION_CLOSED:
3057  cleanup_connection (connection);
3058  return MHD_NO;
3060  return MHD_YES; /* keep open */
3061  default:
3062  EXTRA_CHECK (0);
3063  break;
3064  }
3065  break;
3066  }
3067  timeout = connection->connection_timeout;
3068  if ( (0 != timeout) &&
3069  (timeout <= (MHD_monotonic_sec_counter() - connection->last_activity)) )
3070  {
3071  MHD_connection_close_ (connection,
3073  connection->in_idle = MHD_NO;
3074  return MHD_YES;
3075  }
3077 #ifdef EPOLL_SUPPORT
3078  if (0 != (daemon->options & MHD_USE_EPOLL))
3079  {
3080  switch (connection->event_loop_info)
3081  {
3083  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
3084  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3085  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
3086  {
3087  EDLL_insert (daemon->eready_head,
3088  daemon->eready_tail,
3089  connection);
3090  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
3091  }
3092  break;
3094  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
3095  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3096  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
3097  {
3098  EDLL_insert (daemon->eready_head,
3099  daemon->eready_tail,
3100  connection);
3101  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
3102  }
3103  break;
3105  /* we should look at this connection again in the next iteration
3106  of the event loop, as we're waiting on the application */
3107  if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) &&
3108  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) )
3109  {
3110  EDLL_insert (daemon->eready_head,
3111  daemon->eready_tail,
3112  connection);
3113  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
3114  }
3115  break;
3117  /* This connection is finished, nothing left to do */
3118  break;
3119  }
3120  }
3121  return MHD_connection_epoll_update_ (connection);
3122 #else
3123  return MHD_YES;
3124 #endif
3125 }
3126 
3127 
3128 #ifdef EPOLL_SUPPORT
3129 
3137 int
3138 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3139 {
3140  struct MHD_Daemon *daemon = connection->daemon;
3141 
3142  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3143  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3144  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3145  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
3146  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
3147  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) ||
3148  (connection->read_buffer_size > connection->read_buffer_offset) ) &&
3149  (MHD_NO == connection->read_closed) ) ) )
3150  {
3151  /* add to epoll set */
3152  struct epoll_event event;
3153 
3154  event.events = EPOLLIN | EPOLLOUT | EPOLLET;
3155  event.data.ptr = connection;
3156  if (0 != epoll_ctl (daemon->epoll_fd,
3157  EPOLL_CTL_ADD,
3158  connection->socket_fd,
3159  &event))
3160  {
3161 #ifdef HAVE_MESSAGES
3162  if (0 != (daemon->options & MHD_USE_DEBUG))
3163  MHD_DLOG (daemon,
3164  _("Call to epoll_ctl failed: %s\n"),
3166 #endif
3167  connection->state = MHD_CONNECTION_CLOSED;
3168  cleanup_connection (connection);
3169  return MHD_NO;
3170  }
3171  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3172  }
3173  connection->in_idle = MHD_NO;
3174  return MHD_YES;
3175 }
3176 #endif
3177 
3178 
3184 void
3186 {
3190 }
3191 
3192 
3203 const union MHD_ConnectionInfo *
3205  enum MHD_ConnectionInfoType info_type,
3206  ...)
3207 {
3208  switch (info_type)
3209  {
3210 #if HTTPS_SUPPORT
3212  if (NULL == connection->tls_session)
3213  return NULL;
3214  connection->cipher = gnutls_cipher_get (connection->tls_session);
3215  return (const union MHD_ConnectionInfo *) &connection->cipher;
3217  if (NULL == connection->tls_session)
3218  return NULL;
3219  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3220  return (const union MHD_ConnectionInfo *) &connection->protocol;
3222  if (NULL == connection->tls_session)
3223  return NULL;
3224  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3225 #endif
3227  return (const union MHD_ConnectionInfo *) &connection->addr;
3229  return (const union MHD_ConnectionInfo *) &connection->daemon;
3231  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3233  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3235  return (const union MHD_ConnectionInfo *) &connection->suspended;
3236  default:
3237  return NULL;
3238  };
3239 }
3240 
3241 
3251 int
3253  enum MHD_CONNECTION_OPTION option,
3254  ...)
3255 {
3256  va_list ap;
3257  struct MHD_Daemon *daemon;
3258 
3259  daemon = connection->daemon;
3260  switch (option)
3261  {
3263  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3264  (MHD_YES != connection->suspended) )
3265  {
3266  if (connection->connection_timeout == daemon->connection_timeout)
3268  daemon->normal_timeout_tail,
3269  connection);
3270  else
3272  daemon->manual_timeout_tail,
3273  connection);
3274  }
3275  va_start (ap, option);
3276  connection->connection_timeout = va_arg (ap,
3277  unsigned int);
3278  va_end (ap);
3279  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3280  (MHD_YES != connection->suspended) )
3281  {
3282  if (connection->connection_timeout == daemon->connection_timeout)
3284  daemon->normal_timeout_tail,
3285  connection);
3286  else
3288  daemon->manual_timeout_tail,
3289  connection);
3290  }
3291  return MHD_YES;
3292  default:
3293  return MHD_NO;
3294  }
3295 }
3296 
3297 
3309 int
3311  unsigned int status_code,
3312  struct MHD_Response *response)
3313 {
3314  struct MHD_Daemon *daemon;
3315 
3316  if ( (NULL == connection) ||
3317  (NULL == response) ||
3318  (NULL != connection->response) ||
3319  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3320  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3321  return MHD_NO;
3322  daemon = connection->daemon;
3323  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
3324  (NULL != response->upgrade_handler) )
3325  {
3326 #ifdef HAVE_MESSAGES
3327  MHD_DLOG (daemon,
3328  _("Application used invalid status code for 'upgrade' response!\n"));
3329 #endif
3330  return MHD_NO;
3331  }
3332  if ( (NULL != response->upgrade_handler) &&
3333  (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3334  (0 == (daemon->options & MHD_USE_SUSPEND_RESUME)) )
3335  {
3336 #ifdef HAVE_MESSAGES
3337  MHD_DLOG (daemon,
3338  _("Application attempted 'upgrade' without setting MHD_USE_SUSPEND_RESUME!\n"));
3339 #endif
3340  return MHD_NO;
3341  }
3342  if ( (NULL != response->upgrade_handler) &&
3343  (0 != (MHD_USE_EPOLL & daemon->options)) &&
3344  (0 != (MHD_USE_TLS & daemon->options)) &&
3346  {
3347 #ifdef HAVE_MESSAGES
3348  MHD_DLOG (daemon,
3349  _("Application attempted 'upgrade' HTTPS connection in epoll mode without setting MHD_USE_HTTPS_EPOLL_UPGRADE!\n"));
3350 #endif
3351  return MHD_NO;
3352  }
3353  MHD_increment_response_rc (response);
3354  connection->response = response;
3355  connection->responseCode = status_code;
3356  if ( ( (NULL != connection->method) &&
3357  (MHD_str_equal_caseless_ (connection->method,
3358  MHD_HTTP_METHOD_HEAD)) ) ||
3359  (MHD_HTTP_OK > status_code) ||
3360  (MHD_HTTP_NO_CONTENT == status_code) ||
3361  (MHD_HTTP_NOT_MODIFIED == status_code) )
3362  {
3363  /* if this is a "HEAD" request, or a status code for
3364  which a body is not allowed, pretend that we
3365  have already sent the full message body. */
3366  connection->response_write_position = response->total_size;
3367  }
3368  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
3369  (NULL != connection->method) &&
3370  ( (MHD_str_equal_caseless_ (connection->method,
3372  (MHD_str_equal_caseless_ (connection->method,
3373  MHD_HTTP_METHOD_PUT))) )
3374  {
3375  /* response was queued "early", refuse to read body / footers or
3376  further requests! */
3377  connection->read_closed = MHD_YES;
3378  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3379  }
3380  if (MHD_NO == connection->in_idle)
3381  (void) MHD_connection_handle_idle (connection);
3382  return MHD_YES;
3383 }
3384 
3385 
3386 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2077
#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
Definition: microhttpd.h:340
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1482
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1508
void * unescape_callback_cls
Definition: internal.h:1247
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:410
uint64_t total_size
Definition: internal.h:319
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:579
#define DLL_insert(head, tail, element)
Definition: internal.h:1548
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:446
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:464
void * socket_context
Definition: internal.h:643
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1268
enum MHD_CONNECTION_STATE state
Definition: internal.h:813
void * data
Definition: microhttpd.h:2108
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:646
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:299
uint64_t response_write_position
Definition: internal.h:745
#define NULL
Definition: reason_phrase.c:30
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:142
#define HTTP_100_CONTINUE
Definition: connection.c:43
#define MHD_ICY_FLAG
Definition: microhttpd.h:384
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:818
size_t current_chunk_size
Definition: internal.h:850
int MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2380
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:1477
Methods for managing connections.
char * version
Definition: internal.h:660
#define INTERNAL_ERROR
Definition: connection.c:93
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:415
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:500
#define MHD_YES
Definition: microhttpd.h:134
struct MHD_Response * response
Definition: internal.h:616
char * colon
Definition: internal.h:690
#define REQUEST_LACKS_HOST
Definition: connection.c:68
char * write_buffer
Definition: internal.h:673
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:473
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1175
Header for platform missing functions.
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:318
MHD_RequestTerminationCode
Definition: microhttpd.h:1099
size_t data_size
Definition: internal.h:336
static int do_read(struct MHD_Connection *connection)
Definition: connection.c:1954
#define EXTRA_CHECK(a)
Definition: internal.h:1536
int have_chunked_upload
Definition: internal.h:842
enum MHD_ValueKind kind
Definition: internal.h:256
struct MHD_HTTP_Header * first_header
Definition: internal.h:272
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1217
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1105
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:188
size_t current_chunk_offset
Definition: internal.h:856
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:1717
#define EDLL_insert(head, tail, element)
Definition: internal.h:1637
uint64_t remaining_upload_size
Definition: internal.h:738
unsigned int responseCode
Definition: internal.h:824
int MHD_parse_arguments_(struct MHD_Connection *connection, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:186
MHD_CONNECTION_STATE
Definition: internal.h:377
char * value
Definition: internal.h:250
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:2560
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1237
struct MHD_Daemon * daemon
Definition: internal.h:601
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:871
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1183
struct MHD_Connection * cleanup_head
Definition: internal.h:1135
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:409
#define MHD_SCKT_ERR_IS_REMOTE_DISCNN_(err)
Definition: mhd_sockets.h:622
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:542
int client_aware
Definition: internal.h:775
#define XDLL_remove(head, tail, element)
Definition: internal.h:1614
size_t MHD_strx_to_sizet_n_(const char *str, size_t maxlen, size_t *out_val)
Definition: mhd_str.c:514
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
#define XDLL_insert(head, tail, element)
Definition: internal.h:1593
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3204
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:768
struct MHD_Connection * cleanup_tail
Definition: internal.h:1140
Header for platform-independent inter-thread communication.
int MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2313
size_t data_buffer_size
Definition: internal.h:341
MHD_CONNECTION_OPTION
Definition: microhttpd.h:2657
size_t write_buffer_send_offset
Definition: internal.h:726
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:233
static void get_date_string(char *date)
Definition: connection.c:814
void * mhd_panic_cls
Definition: daemon.c:124
size_t read_buffer_size
Definition: internal.h:710
void * client_context
Definition: internal.h:634
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1190
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
const char * url
Definition: internal.h:654
size_t continue_message_write_offset
Definition: internal.h:751
MHD_UpgradeHandler upgrade_handler
Definition: internal.h:303
#define REQUEST_MALFORMED
Definition: connection.c:81
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:782
char * method
Definition: internal.h:648
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:588
enum MHD_FLAG options
Definition: internal.h:1403
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:309
LogCallback uri_log_callback
Definition: internal.h:1232
static int socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:205
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:994
#define MHD_HTTP_OK
Definition: microhttpd.h:305
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3252
int shutdown
Definition: internal.h:1362
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1028
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:861
char * last
Definition: internal.h:681
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1168
MHD_ValueKind
Definition: microhttpd.h:1053
char * read_buffer
Definition: internal.h:667
ReceiveCallback recv_cls
Definition: internal.h:876
static void update_last_activity(struct MHD_Connection *connection)
Definition: connection.c:2283
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:474
size_t write_buffer_size
Definition: internal.h:721
MHD_ConnectionInfoType
Definition: microhttpd.h:1235
uint64_t data_start
Definition: internal.h:325
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:455
internal shared structures
UnescapeCallback unescape_callback
Definition: internal.h:1242
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:498
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:872
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3310
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:866
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:324
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:601
struct MHD_Connection * connections_head
Definition: internal.h:1115
size_t pool_size
Definition: internal.h:1280
char * header
Definition: internal.h:245
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2048
struct MHD_itc_ itc
Definition: internal.h:1357
time_t last_activity
Definition: internal.h:762
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2612
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:491
unsigned int connection_timeout
Definition: internal.h:768
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2120
enum MHD_ResponseFlags flags
Definition: internal.h:357
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:412
struct MemoryPool * pool
Definition: internal.h:626
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:467
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2202
#define MHD_PANIC(msg)
Definition: internal.h:59
time_t MHD_monotonic_sec_counter(void)
Header for string manipulating helpers.
size_t write_buffer_append_offset
Definition: internal.h:732
struct MHD_HTTP_Header * next
Definition: internal.h:240
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1207
static int socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:146
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:401
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3185
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:470
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:319
#define DLL_remove(head, tail, element)
Definition: internal.h:1569
void * notify_completed_cls
Definition: internal.h:1212
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:1752
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:454
TransmitCallback send_cls
Definition: internal.h:881
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:352
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:355
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:290
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:1622
void * crc_cls
Definition: internal.h:284
struct sockaddr * addr
Definition: internal.h:696
MHD_mutex_ mutex
Definition: internal.h:314
MHD_PanicCallback mhd_panic
Definition: daemon.c:119
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1130
static int socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:288
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:404
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
static int socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:128
char * data
Definition: internal.h:278
#define MHD_MIN(a, b)
Definition: internal.h:84
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:258
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
Definition: response.c:708
static int do_write(struct MHD_Connection *connection)
Definition: connection.c:2004
size_t read_buffer_offset
Definition: internal.h:716
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1418
void * default_handler_cls
Definition: internal.h:1110
#define MHD_NO
Definition: microhttpd.h:139
unsigned int connection_timeout
Definition: internal.h:1392
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:230
#define MHD_HTTP_REQUEST_URI_TOO_LONG
Definition: microhttpd.h:341
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:579
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1310
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:562
Header for platform-independent locks abstraction.
struct MHD_HTTP_Header * headers_received
Definition: internal.h:606
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:302
struct MHD_Connection * connections_tail
Definition: internal.h:1120
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:436
#define MHD_BUF_INC_SIZE
Definition: internal.h:94
#define SIZE_MAX
Definition: mhd_limits.h:83
_MHD_EXTERN int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:404
#define REQUEST_TOO_BIG
Definition: connection.c:55
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:611
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:904
size_t pool_increment
Definition: internal.h:1285
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:469
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:382
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1125
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...