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-2017 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
28 #include "internal.h"
29 #include <limits.h>
30 #include "connection.h"
31 #include "memorypool.h"
32 #include "response.h"
33 #include "mhd_mono_clock.h"
34 #include "mhd_str.h"
35 #include "mhd_locks.h"
36 #include "mhd_sockets.h"
37 #include "mhd_compat.h"
38 #include "mhd_itc.h"
39 #ifdef HTTPS_SUPPORT
40 #include "connection_https.h"
41 #endif /* HTTPS_SUPPORT */
42 
43 
47 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
48 
56 #ifdef HAVE_MESSAGES
57 #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>"
58 #else
59 #define REQUEST_TOO_BIG ""
60 #endif
61 
69 #ifdef HAVE_MESSAGES
70 #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>"
71 #else
72 #define REQUEST_LACKS_HOST ""
73 #endif
74 
82 #ifdef HAVE_MESSAGES
83 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
84 #else
85 #define REQUEST_MALFORMED ""
86 #endif
87 
94 #ifdef HAVE_MESSAGES
95 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
96 #else
97 #define INTERNAL_ERROR ""
98 #endif
99 
104 #define DEBUG_CLOSE MHD_NO
105 
109 #define DEBUG_SEND_DATA MHD_NO
110 
111 
131 static int
133 {
134 #if defined(TCP_CORK) || defined(TCP_PUSH)
135  return MHD_YES;
136 #else /* !TCP_CORK && !TCP_PUSH */
137  return MHD_NO;
138 #endif /* !TCP_CORK && !TCP_PUSH */
139 }
140 
141 
149 static int
151 {
152  int res = MHD_NO;
153 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
154  const MHD_SCKT_OPT_BOOL_ on_val = 1;
155 #if defined(TCP_NODELAY)
156  const MHD_SCKT_OPT_BOOL_ off_val = 0;
157 #endif /* TCP_NODELAY */
158  if (!connection)
159  return MHD_NO;
160 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
161  /* Buffer data before sending */
162  res = (0 == setsockopt (connection->socket_fd,
163  IPPROTO_TCP,
164  TCP_NOPUSH,
165  (const void *) &on_val,
166  sizeof (on_val)))
167  ? MHD_YES : MHD_NO;
168 #if defined(TCP_NODELAY)
169  /* Enable Nagle's algorithm */
170  /* TCP_NODELAY may interfere with TCP_NOPUSH */
171  res &= (0 == setsockopt (connection->socket_fd,
172  IPPROTO_TCP,
173  TCP_NODELAY,
174  (const void *) &off_val,
175  sizeof (off_val)))
176  ? MHD_YES : MHD_NO;
177 #endif /* TCP_NODELAY */
178 #else /* TCP_CORK */
179 #if defined(TCP_NODELAY)
180  /* Enable Nagle's algorithm */
181  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
182  solely on TCP_CORK result, so ignoring return code here. */
183  (void) setsockopt (connection->socket_fd,
184  IPPROTO_TCP,
185  TCP_NODELAY,
186  (const void *) &off_val,
187  sizeof (off_val));
188 #endif /* TCP_NODELAY */
189  /* Send only full packets */
190  res = (0 == setsockopt (connection->socket_fd,
191  IPPROTO_TCP,
192  TCP_CORK,
193  (const void *) &on_val,
194  sizeof (on_val)))
195  ? MHD_YES : MHD_NO;
196 #endif /* TCP_CORK */
197 #endif /* TCP_CORK || TCP_NOPUSH */
198  return res;
199 }
200 
201 
208 static int
210 {
211 #if defined(TCP_NODELAY)
212  int res = MHD_YES;
213  const MHD_SCKT_OPT_BOOL_ on_val = 1;
214 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
215  const MHD_SCKT_OPT_BOOL_ off_val = 0;
216 #endif /* TCP_CORK || TCP_NOPUSH */
217 
218  if (NULL == connection)
219  return MHD_NO;
220 #if defined(TCP_CORK)
221  /* Allow partial packets */
222  res &= (0 == setsockopt (connection->socket_fd,
223  IPPROTO_TCP,
224  TCP_CORK,
225  (const void *) &off_val,
226  sizeof (off_val)))
227  ? MHD_YES : MHD_NO;
228 #endif /* TCP_CORK */
229 #if defined(TCP_NODELAY)
230  /* Disable Nagle's algorithm for sending packets without delay */
231  res &= (0 == setsockopt (connection->socket_fd,
232  IPPROTO_TCP,
233  TCP_NODELAY,
234  (const void *) &on_val,
235  sizeof (on_val)))
236  ? MHD_YES : MHD_NO;
237 #endif /* TCP_NODELAY */
238 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
239  /* Disable extra buffering */
240  res &= (0 == setsockopt (connection->socket_fd,
241  IPPROTO_TCP,
242  TCP_NOPUSH,
243  (const void *) &off_val,
244  sizeof (off_val)))
245  ? MHD_YES : MHD_NO;
246 #endif /* TCP_NOPUSH && !TCP_CORK */
247  return res;
248 #else /* !TCP_NODELAY */
249  return MHD_NO;
250 #endif /* !TCP_NODELAY */
251 }
252 
253 
261 static int
263 {
264  int res = MHD_YES;
265 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
266  const int dummy = 0;
267 #endif /* !TCP_CORK */
268 
269  if (NULL == connection)
270  return MHD_NO;
271  res = socket_start_no_buffering (connection);
272 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
273  /* Force flush data with zero send otherwise Darwin and some BSD systems
274  will add 5 seconds delay. Not required with TCP_CORK as switching off
275  TCP_CORK always flushes socket buffer. */
276  res &= (0 <= MHD_send_ (connection->socket_fd,
277  &dummy,
278  0))
279  ? MHD_YES : MHD_NO;
280 #endif /* TCP_NOPUSH && !TCP_CORK*/
281  return res;
282 }
283 
284 
291 static int
293 {
294 #if defined(TCP_NODELAY)
295  int res = MHD_YES;
296  const MHD_SCKT_OPT_BOOL_ off_val = 0;
297 #if defined(TCP_CORK)
298  MHD_SCKT_OPT_BOOL_ cork_val = 0;
299  socklen_t param_size = sizeof (cork_val);
300 #endif /* TCP_CORK */
301  if (!connection)
302  return MHD_NO;
303 #if defined(TCP_CORK)
304  /* Allow partial packets */
305  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
306  so try to check current value of TCP_CORK to prevent unrequested flushing */
307  if ( (0 != getsockopt (connection->socket_fd,
308  IPPROTO_TCP,
309  TCP_CORK,
310  (void*)&cork_val,
311  &param_size)) ||
312  (0 != cork_val))
313  res &= (0 == setsockopt (connection->socket_fd,
314  IPPROTO_TCP,
315  TCP_CORK,
316  (const void *) &off_val,
317  sizeof (off_val)))
318  ? MHD_YES : MHD_NO;
319 #elif defined(TCP_NOPUSH)
320  /* Disable extra buffering */
321  /* No need to check current value as disabling TCP_NOPUSH will not flush partial
322  packet if TCP_NOPUSH wasn't enabled before */
323  res &= (0 == setsockopt (connection->socket_fd,
324  IPPROTO_TCP,
325  TCP_NOPUSH,
326  (const void *) &off_val,
327  sizeof (off_val)))
328  ? MHD_YES : MHD_NO;
329 #endif /* TCP_NOPUSH && !TCP_CORK */
330  /* Enable Nagle's algorithm for normal buffering */
331  res &= (0 == setsockopt (connection->socket_fd,
332  IPPROTO_TCP,
333  TCP_NODELAY,
334  (const void *) &off_val,
335  sizeof (off_val)))
336  ? MHD_YES : MHD_NO;
337  return res;
338 #else /* !TCP_NODELAY */
339  return MHD_NO;
340 #endif /* !TCP_NODELAY */
341 }
342 
343 
355 int
357  enum MHD_ValueKind kind,
358  MHD_KeyValueIterator iterator,
359  void *iterator_cls)
360 {
361  int ret;
362  struct MHD_HTTP_Header *pos;
363 
364  if (NULL == connection)
365  return -1;
366  ret = 0;
367  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
368  if (0 != (pos->kind & kind))
369  {
370  ret++;
371  if ( (NULL != iterator) &&
372  (MHD_YES != iterator (iterator_cls,
373  pos->kind,
374  pos->header,
375  pos->value)) )
376  return ret;
377  }
378  return ret;
379 }
380 
381 
407 int
409  enum MHD_ValueKind kind,
410  const char *key,
411  const char *value)
412 {
413  struct MHD_HTTP_Header *pos;
414 
415  pos = MHD_pool_allocate (connection->pool,
416  sizeof (struct MHD_HTTP_Header),
417  MHD_YES);
418  if (NULL == pos)
419  return MHD_NO;
420  pos->header = (char *) key;
421  pos->value = (char *) value;
422  pos->kind = kind;
423  pos->next = NULL;
424  /* append 'pos' to the linked list of headers */
425  if (NULL == connection->headers_received_tail)
426  {
427  connection->headers_received = pos;
428  connection->headers_received_tail = pos;
429  }
430  else
431  {
432  connection->headers_received_tail->next = pos;
433  connection->headers_received_tail = pos;
434  }
435  return MHD_YES;
436 }
437 
438 
449 const char *
451  enum MHD_ValueKind kind,
452  const char *key)
453 {
454  struct MHD_HTTP_Header *pos;
455 
456  if (NULL == connection)
457  return NULL;
458  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
459  if ((0 != (pos->kind & kind)) &&
460  ( (key == pos->header) ||
461  ( (NULL != pos->header) &&
462  (NULL != key) &&
464  pos->header)))))
465  return pos->value;
466  return NULL;
467 }
468 
469 
477 static int
478 need_100_continue (struct MHD_Connection *connection)
479 {
480  const char *expect;
481 
482  return ( (NULL == connection->response) &&
483  (NULL != connection->version) &&
484  (MHD_str_equal_caseless_(connection->version,
486  (NULL != (expect = MHD_lookup_connection_value (connection,
489  (MHD_str_equal_caseless_(expect,
490  "100-continue")) &&
491  (connection->continue_message_write_offset <
493 }
494 
495 
502 void
504 {
505  const struct MHD_Daemon *daemon = connection->daemon;
506 
507  connection->state = MHD_CONNECTION_CLOSED;
509  if (0 == (daemon->options & MHD_USE_TURBO))
510  {
511 #ifdef HTTPS_SUPPORT
512  /* For TLS connection use shutdown of TLS layer
513  * and do not shutdown TCP socket. This give more
514  * chances to send TLS closure data to remote side.
515  * Closure of TLS layer will be interpreted by
516  * remote side as end of transmission. */
517  if (0 != (daemon->options & MHD_USE_TLS))
518  {
519  if (MHD_NO == MHD_tls_connection_shutdown(connection))
520  shutdown (connection->socket_fd,
521  SHUT_WR);
522  }
523  else /* Combined with next 'shutdown()'. */
524 #endif /* HTTPS_SUPPORT */
525  shutdown (connection->socket_fd,
526  SHUT_WR);
527  }
528 }
529 
530 
540 void
542  enum MHD_RequestTerminationCode termination_code)
543 {
544  struct MHD_Daemon *daemon = connection->daemon;
545  struct MHD_Response *resp = connection->response;
546 
547  MHD_connection_mark_closed_ (connection);
548  if (NULL != resp)
549  {
550  connection->response = NULL;
551  MHD_destroy_response (resp);
552  }
553  if ( (NULL != daemon->notify_completed) &&
554  (connection->client_aware) )
555  daemon->notify_completed (daemon->notify_completed_cls,
556  connection,
557  &connection->client_context,
558  termination_code);
559  connection->client_aware = false;
560 }
561 
562 
563 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
564 
574 void
576 {
577  struct MHD_Daemon *daemon = connection->daemon;
578  struct MHD_UpgradeResponseHandle *urh = connection->urh;
579 
580  if (0 == (daemon->options & MHD_USE_TLS))
581  return; /* Nothing to do with non-TLS connection. */
582 
583  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
584  DLL_remove (daemon->urh_head,
585  daemon->urh_tail,
586  urh);
587 #if EPOLL_SUPPORT
588  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
589  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
590  EPOLL_CTL_DEL,
591  connection->socket_fd,
592  NULL)) )
593  {
594  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
595  }
596  if (urh->in_eready_list)
597  {
598  EDLL_remove (daemon->eready_urh_head,
599  daemon->eready_urh_tail,
600  urh);
601  urh->in_eready_list = false;
602  }
603 #endif /* EPOLL_SUPPORT */
604  if (MHD_INVALID_SOCKET != urh->mhd.socket)
605  {
606 #if EPOLL_SUPPORT
607  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
608  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
609  EPOLL_CTL_DEL,
610  urh->mhd.socket,
611  NULL)) )
612  {
613  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
614  }
615 #endif /* EPOLL_SUPPORT */
616  /* Reflect remote disconnect to application by breaking
617  * socketpair connection. */
618  shutdown (urh->mhd.socket, SHUT_RDWR);
619  }
620  /* Socketpair sockets will remain open as they will be
621  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
622  * closed by MHD_cleanup_upgraded_connection_() during
623  * connection's final cleanup.
624  */
625 }
626 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
627 
628 
636 static void
638  const char *emsg)
639 {
640 #ifdef HAVE_MESSAGES
641  if (NULL != emsg)
642  MHD_DLOG (connection->daemon,
643  emsg);
644 #endif
645  MHD_connection_close_ (connection,
647 }
648 
649 
654 #ifdef HAVE_MESSAGES
655 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
656 #else
657 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
658 #endif
659 
660 
673 static int
675 {
676  ssize_t ret;
677  struct MHD_Response *response;
678 
679  response = connection->response;
680  if (NULL == response->crc)
681  return MHD_YES;
682  if ( (0 == response->total_size) ||
683  (connection->response_write_position == response->total_size) )
684  return MHD_YES; /* 0-byte response is always ready */
685  if ( (response->data_start <=
686  connection->response_write_position) &&
687  (response->data_size + response->data_start >
688  connection->response_write_position) )
689  return MHD_YES; /* response already ready */
690 #if LINUX
691  if (MHD_resp_sender_sendfile == connection->resp_sender)
692  {
693  /* will use sendfile, no need to bother response crc */
694  return MHD_YES;
695  }
696 #endif
697 
698  ret = response->crc (response->crc_cls,
699  connection->response_write_position,
700  response->data,
701  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
702  response->total_size -
703  connection->response_write_position));
704  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
705  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
706  {
707  /* either error or http 1.0 transfer, close socket! */
708  response->total_size = connection->response_write_position;
709  MHD_mutex_unlock_chk_ (&response->mutex);
710  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
711  MHD_connection_close_ (connection,
713  else
714  CONNECTION_CLOSE_ERROR (connection,
715  _("Closing connection (application reported error generating data)\n"));
716  return MHD_NO;
717  }
718  response->data_start = connection->response_write_position;
719  response->data_size = ret;
720  if (0 == ret)
721  {
723  MHD_mutex_unlock_chk_ (&response->mutex);
724  return MHD_NO;
725  }
726  return MHD_YES;
727 }
728 
729 
739 static int
741 {
742  ssize_t ret;
743  char *buf;
744  struct MHD_Response *response;
745  size_t size;
746  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
747  int cblen;
748 
749  response = connection->response;
750  if (0 == connection->write_buffer_size)
751  {
752  size = MHD_MIN (connection->daemon->pool_size,
753  2 * (0xFFFFFF + sizeof(cbuf) + 2));
754  do
755  {
756  size /= 2;
757  if (size < 128)
758  {
759  /* not enough memory */
760  CONNECTION_CLOSE_ERROR (connection,
761  _("Closing connection (out of memory)\n"));
762  return MHD_NO;
763  }
764  buf = MHD_pool_allocate (connection->pool,
765  size,
766  MHD_NO);
767  }
768  while (NULL == buf);
769  connection->write_buffer_size = size;
770  connection->write_buffer = buf;
771  }
772 
773  if (0 == response->total_size)
774  ret = 0; /* response must be empty, don't bother calling crc */
775  else if ( (response->data_start <=
776  connection->response_write_position) &&
777  (response->data_start + response->data_size >
778  connection->response_write_position) )
779  {
780  /* difference between response_write_position and data_start is less
781  than data_size which is size_t type, no need to check for overflow */
782  const size_t data_write_offset
783  = (size_t)(connection->response_write_position - response->data_start);
784  /* buffer already ready, use what is there for the chunk */
785  ret = response->data_size - data_write_offset;
786  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
787  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
788  memcpy (&connection->write_buffer[sizeof (cbuf)],
789  &response->data[data_write_offset],
790  ret);
791  }
792  else
793  {
794  /* buffer not in range, try to fill it */
795  ret = response->crc (response->crc_cls,
796  connection->response_write_position,
797  &connection->write_buffer[sizeof (cbuf)],
798  connection->write_buffer_size - sizeof (cbuf) - 2);
799  }
800  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
801  {
802  /* error, close socket! */
803  response->total_size = connection->response_write_position;
804  CONNECTION_CLOSE_ERROR (connection,
805  _("Closing connection (application error generating response)\n"));
806  return MHD_NO;
807  }
808  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
809  (0 == response->total_size) )
810  {
811  /* end of message, signal other side! */
812  strcpy (connection->write_buffer,
813  "0\r\n");
814  connection->write_buffer_append_offset = 3;
815  connection->write_buffer_send_offset = 0;
816  response->total_size = connection->response_write_position;
817  return MHD_YES;
818  }
819  if (0 == ret)
820  {
822  return MHD_NO;
823  }
824  if (ret > 0xFFFFFF)
825  ret = 0xFFFFFF;
826  cblen = MHD_snprintf_(cbuf,
827  sizeof (cbuf),
828  "%X\r\n",
829  (unsigned int) ret);
830  EXTRA_CHECK(cblen > 0);
831  EXTRA_CHECK(cblen < sizeof(cbuf));
832  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
833  cbuf,
834  cblen);
835  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
836  "\r\n",
837  2);
838  connection->response_write_position += ret;
839  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
840  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
841  return MHD_YES;
842 }
843 
844 
861 static int
862 keepalive_possible (struct MHD_Connection *connection)
863 {
864  const char *end;
865 
866  if (NULL == connection->version)
867  return MHD_NO;
868  if ( (NULL != connection->response) &&
869  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
870  return MHD_NO;
871  end = MHD_lookup_connection_value (connection,
874  if (MHD_str_equal_caseless_(connection->version,
876  {
877  if (NULL == end)
878  return MHD_YES;
879  if (MHD_str_equal_caseless_ (end,
880  "close"))
881  return MHD_NO;
882 #ifdef UPGRADE_SUPPORT
883  if ( (MHD_str_equal_caseless_ (end,
884  "upgrade")) &&
885  (NULL == connection->response->upgrade_handler) )
886  return MHD_NO;
887 #endif /* UPGRADE_SUPPORT */
888 
889  return MHD_YES;
890  }
891  if (MHD_str_equal_caseless_(connection->version,
893  {
894  if (NULL == end)
895  return MHD_NO;
896  if (MHD_str_equal_caseless_(end,
897  "Keep-Alive"))
898  return MHD_YES;
899  return MHD_NO;
900  }
901  return MHD_NO;
902 }
903 
904 
912 static void
913 get_date_string (char *date,
914  size_t date_len)
915 {
916  static const char *const days[] = {
917  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
918  };
919  static const char *const mons[] = {
920  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
921  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
922  };
923  struct tm now;
924  time_t t;
925 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
926  struct tm* pNow;
927 #endif
928 
929  date[0] = 0;
930  time (&t);
931 #if defined(HAVE_C11_GMTIME_S)
932  if (NULL == gmtime_s (&t,
933  &now))
934  return;
935 #elif defined(HAVE_W32_GMTIME_S)
936  if (0 != gmtime_s (&now,
937  &t))
938  return;
939 #elif defined(HAVE_GMTIME_R)
940  if (NULL == gmtime_r(&t,
941  &now))
942  return;
943 #else
944  pNow = gmtime(&t);
945  if (NULL == pNow)
946  return;
947  now = *pNow;
948 #endif
949  MHD_snprintf_ (date,
950  date_len,
951  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
952  days[now.tm_wday % 7],
953  (unsigned int) now.tm_mday,
954  mons[now.tm_mon % 12],
955  (unsigned int) (1900 + now.tm_year),
956  (unsigned int) now.tm_hour,
957  (unsigned int) now.tm_min,
958  (unsigned int) now.tm_sec);
959 }
960 
961 
972 static int
974 {
975  void *buf;
976  size_t new_size;
977 
978  if (0 == connection->read_buffer_size)
979  new_size = connection->daemon->pool_size / 2;
980  else
981  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
982  buf = MHD_pool_reallocate (connection->pool,
983  connection->read_buffer,
984  connection->read_buffer_size,
985  new_size);
986  if (NULL == buf)
987  return MHD_NO;
988  /* we can actually grow the buffer, do it! */
989  connection->read_buffer = buf;
990  connection->read_buffer_size = new_size;
991  return MHD_YES;
992 }
993 
994 
1004 static int
1006 {
1007  size_t size;
1008  size_t off;
1009  struct MHD_HTTP_Header *pos;
1010  char code[256];
1011  char date[128];
1012  char content_length_buf[128];
1013  size_t content_length_len;
1014  char *data;
1015  enum MHD_ValueKind kind;
1016  const char *reason_phrase;
1017  uint32_t rc;
1018  const char *client_requested_close;
1019  const char *response_has_close;
1020  const char *response_has_keepalive;
1021  const char *have_encoding;
1022  const char *have_content_length;
1023  int must_add_close;
1024  int must_add_chunked_encoding;
1025  int must_add_keep_alive;
1026  int must_add_content_length;
1027 
1028  EXTRA_CHECK (NULL != connection->version);
1029  if (0 == connection->version[0])
1030  {
1031  data = MHD_pool_allocate (connection->pool,
1032  0,
1033  MHD_YES);
1034  connection->write_buffer = data;
1035  connection->write_buffer_append_offset = 0;
1036  connection->write_buffer_send_offset = 0;
1037  connection->write_buffer_size = 0;
1038  return MHD_YES;
1039  }
1040  rc = connection->responseCode & (~MHD_ICY_FLAG);
1041  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1042  {
1043  reason_phrase = MHD_get_reason_phrase_for (rc);
1044  MHD_snprintf_ (code,
1045  sizeof (code),
1046  "%s %u %s\r\n",
1047  (0 != (connection->responseCode & MHD_ICY_FLAG))
1048  ? "ICY"
1050  connection->version))
1053  rc,
1054  reason_phrase);
1055  off = strlen (code);
1056  /* estimate size */
1057  size = off + 2; /* +2 for extra "\r\n" at the end */
1058  kind = MHD_HEADER_KIND;
1059  if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1060  (NULL == MHD_get_response_header (connection->response,
1062  get_date_string (date,
1063  sizeof (date));
1064  else
1065  date[0] = '\0';
1066  size += strlen (date);
1067  }
1068  else
1069  {
1070  /* 2 bytes for final CRLF of a Chunked-Body */
1071  size = 2;
1072  kind = MHD_FOOTER_KIND;
1073  off = 0;
1074  }
1075 
1076  /* calculate extra headers we need to add, such as 'Connection: close',
1077  first see what was explicitly requested by the application */
1078  must_add_close = MHD_NO;
1079  must_add_chunked_encoding = MHD_NO;
1080  must_add_keep_alive = MHD_NO;
1081  must_add_content_length = MHD_NO;
1082  response_has_keepalive = NULL;
1083  switch (connection->state)
1084  {
1086  response_has_close = MHD_get_response_header (connection->response,
1088  response_has_keepalive = response_has_close;
1089  if ( (NULL != response_has_close) &&
1090  (! MHD_str_equal_caseless_ (response_has_close,
1091  "close")) )
1092  response_has_close = NULL;
1093  if ( (NULL != response_has_keepalive) &&
1094  (! MHD_str_equal_caseless_ (response_has_keepalive,
1095  "Keep-Alive")) )
1096  response_has_keepalive = NULL;
1097  client_requested_close = MHD_lookup_connection_value (connection,
1100  if ( (NULL != client_requested_close) &&
1101  (! MHD_str_equal_caseless_ (client_requested_close,
1102  "close")) )
1103  client_requested_close = NULL;
1104 
1105  /* now analyze chunked encoding situation */
1106  connection->have_chunked_upload = false;
1107 
1108  if ( (MHD_SIZE_UNKNOWN == connection->response->total_size) &&
1109  (NULL == response_has_close) &&
1110  (NULL == client_requested_close) )
1111  {
1112  /* size is unknown, and close was not explicitly requested;
1113  need to either to HTTP 1.1 chunked encoding or
1114  close the connection */
1115  /* 'close' header doesn't exist yet, see if we need to add one;
1116  if the client asked for a close, no need to start chunk'ing */
1117  if ( (MHD_YES == keepalive_possible (connection)) &&
1119  connection->version) ) )
1120  {
1121  have_encoding = MHD_get_response_header (connection->response,
1123  if (NULL == have_encoding)
1124  {
1125  must_add_chunked_encoding = MHD_YES;
1126  connection->have_chunked_upload = true;
1127  }
1128  else if (MHD_str_equal_caseless_ (have_encoding,
1129  "identity"))
1130  {
1131  /* application forced identity encoding, can't do 'chunked' */
1132  must_add_close = MHD_YES;
1133  }
1134  else
1135  {
1136  connection->have_chunked_upload = true;
1137  }
1138  }
1139  else
1140  {
1141  /* Keep alive or chunking not possible
1142  => set close header if not present */
1143  if (NULL == response_has_close)
1144  must_add_close = MHD_YES;
1145  }
1146  }
1147 
1148  /* check for other reasons to add 'close' header */
1149  if ( ( (NULL != client_requested_close) ||
1150  (connection->read_closed) ) &&
1151  (NULL == response_has_close) &&
1152  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1153  must_add_close = MHD_YES;
1154 
1155  /* check if we should add a 'content length' header */
1156  have_content_length = MHD_get_response_header (connection->response,
1158 
1159  /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1160  codes SHOULD NOT have a Content-Length according to spec;
1161  also chunked encoding / unknown length or CONNECT... */
1162  if ( (MHD_SIZE_UNKNOWN != connection->response->total_size) &&
1163  (MHD_HTTP_NO_CONTENT != rc) &&
1164  (MHD_HTTP_NOT_MODIFIED != rc) &&
1165  (MHD_HTTP_OK <= rc) &&
1166  (NULL == have_content_length) &&
1167  ( (NULL == connection->method) ||
1168  (! MHD_str_equal_caseless_ (connection->method,
1170  {
1171  /*
1172  Here we add a content-length if one is missing; however,
1173  for 'connect' methods, the responses MUST NOT include a
1174  content-length header *if* the response code is 2xx (in
1175  which case we expect there to be no body). Still,
1176  as we don't know the response code here in some cases, we
1177  simply only force adding a content-length header if this
1178  is not a 'connect' or if the response is not empty
1179  (which is kind of more sane, because if some crazy
1180  application did return content with a 2xx status code,
1181  then having a content-length might again be a good idea).
1182 
1183  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1184  a recent development of the HTTP 1.1 specification.
1185  */
1186  content_length_len
1187  = MHD_snprintf_ (content_length_buf,
1188  sizeof (content_length_buf),
1190  (MHD_UNSIGNED_LONG_LONG) connection->response->total_size);
1191  must_add_content_length = MHD_YES;
1192  }
1193 
1194  /* check for adding keep alive */
1195  if ( (NULL == response_has_keepalive) &&
1196  (NULL == response_has_close) &&
1197  (MHD_NO == must_add_close) &&
1198  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) &&
1199  (MHD_YES == keepalive_possible (connection)) )
1200  must_add_keep_alive = MHD_YES;
1201  break;
1203  response_has_keepalive = NULL;
1204  break;
1205  default:
1206  EXTRA_CHECK (0);
1207  }
1208 
1209  if (must_add_close)
1210  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1211  if (must_add_keep_alive)
1212  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1213  if (must_add_chunked_encoding)
1214  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1215  if (must_add_content_length)
1216  size += content_length_len;
1217  EXTRA_CHECK (! (must_add_close && must_add_keep_alive) );
1218  EXTRA_CHECK (! (must_add_chunked_encoding && must_add_content_length) );
1219 
1220  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1221  if ( (pos->kind == kind) &&
1222  (! ( (MHD_YES == must_add_close) &&
1223  (pos->value == response_has_keepalive) &&
1226  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1227  /* produce data */
1228  data = MHD_pool_allocate (connection->pool,
1229  size + 1,
1230  MHD_NO);
1231  if (NULL == data)
1232  {
1233 #ifdef HAVE_MESSAGES
1234  MHD_DLOG (connection->daemon,
1235  "Not enough memory for write!\n");
1236 #endif
1237  return MHD_NO;
1238  }
1239  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1240  {
1241  memcpy (data,
1242  code,
1243  off);
1244  }
1245  if (must_add_close)
1246  {
1247  /* we must add the 'Connection: close' header */
1248  memcpy (&data[off],
1249  "Connection: close\r\n",
1250  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1251  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1252  }
1253  if (must_add_keep_alive)
1254  {
1255  /* we must add the 'Connection: Keep-Alive' header */
1256  memcpy (&data[off],
1257  "Connection: Keep-Alive\r\n",
1258  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1259  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1260  }
1261  if (must_add_chunked_encoding)
1262  {
1263  /* we must add the 'Transfer-Encoding: chunked' header */
1264  memcpy (&data[off],
1265  "Transfer-Encoding: chunked\r\n",
1266  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1267  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1268  }
1269  if (must_add_content_length)
1270  {
1271  /* we must add the 'Content-Length' header */
1272  memcpy (&data[off],
1273  content_length_buf,
1274  content_length_len);
1275  off += content_length_len;
1276  }
1277  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1278  if ( (pos->kind == kind) &&
1279  (! ( (pos->value == response_has_keepalive) &&
1280  (MHD_YES == must_add_close) &&
1283  off += MHD_snprintf_ (&data[off],
1284  size - off,
1285  "%s: %s\r\n",
1286  pos->header,
1287  pos->value);
1288  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1289  {
1290  strcpy (&data[off],
1291  date);
1292  off += strlen (date);
1293  }
1294  memcpy (&data[off],
1295  "\r\n",
1296  2);
1297  off += 2;
1298 
1299  if (off != size)
1301  __FILE__,
1302  __LINE__,
1303  NULL);
1304  connection->write_buffer = data;
1305  connection->write_buffer_append_offset = size;
1306  connection->write_buffer_send_offset = 0;
1307  connection->write_buffer_size = size + 1;
1308  return MHD_YES;
1309 }
1310 
1311 
1321 static void
1323  unsigned int status_code,
1324  const char *message)
1325 {
1326  struct MHD_Response *response;
1327 
1328  if (NULL == connection->version)
1329  {
1330  /* we were unable to process the full header line, so we don't
1331  really know what version the client speaks; assume 1.0 */
1332  connection->version = MHD_HTTP_VERSION_1_0;
1333  }
1334  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1335  connection->read_closed = true;
1336 #ifdef HAVE_MESSAGES
1337  MHD_DLOG (connection->daemon,
1338  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1339  status_code,
1340  message);
1341 #endif
1342  EXTRA_CHECK (NULL == connection->response);
1343  response = MHD_create_response_from_buffer (strlen (message),
1344  (void *) message,
1345  MHD_RESPMEM_PERSISTENT);
1346  MHD_queue_response (connection,
1347  status_code,
1348  response);
1349  EXTRA_CHECK (NULL != connection->response);
1350  MHD_destroy_response (response);
1351  if (MHD_NO == build_header_response (connection))
1352  {
1353  /* oops - close! */
1354  CONNECTION_CLOSE_ERROR (connection,
1355  _("Closing connection (failed to create response header)\n"));
1356  }
1357  else
1358  {
1359  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1360  }
1361 }
1362 
1363 
1372 static void
1374 {
1375  while (1)
1376  {
1377 #if DEBUG_STATES
1378  MHD_DLOG (connection->daemon,
1379  _("In function %s handling connection at state: %s\n"),
1380  __FUNCTION__,
1381  MHD_state_to_string (connection->state));
1382 #endif
1383  switch (connection->state)
1384  {
1385 #ifdef HTTPS_SUPPORT
1387  if (0 == gnutls_record_get_direction (connection->tls_session))
1389  else
1391  break;
1392 #endif /* HTTPS_SUPPORT */
1393  case MHD_CONNECTION_INIT:
1396  /* while reading headers, we always grow the
1397  read buffer if needed, no size-check required */
1398  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1399  (MHD_NO == try_grow_read_buffer (connection)) )
1400  {
1401  transmit_error_response (connection,
1402  (connection->url != NULL)
1405  REQUEST_TOO_BIG);
1406  continue;
1407  }
1408  if (! connection->read_closed)
1410  else
1412  break;
1414  EXTRA_CHECK (0);
1415  break;
1417  EXTRA_CHECK (0);
1418  break;
1421  break;
1423  if (connection->read_buffer_offset == connection->read_buffer_size)
1424  {
1425  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1426  (0 != (connection->daemon->options &
1428  (! connection->suspended) &&
1429  (! connection->resuming))
1430  {
1431  /* failed to grow the read buffer, and the
1432  client which is supposed to handle the
1433  received data in a *blocking* fashion
1434  (in this mode) did not handle the data as
1435  it was supposed to!
1436  => we would either have to do busy-waiting
1437  (on the client, which would likely fail),
1438  or if we do nothing, we would just timeout
1439  on the connection (if a timeout is even
1440  set!).
1441  Solution: we kill the connection with an error */
1442  /* If connection is suspended, give application one
1443  * more chance to read data once connection is resumed. */
1444  transmit_error_response (connection,
1446  INTERNAL_ERROR);
1447  continue;
1448  }
1449  }
1450  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1451  (! connection->read_closed) )
1453  else
1455  break;
1458  /* while reading footers, we always grow the
1459  read buffer if needed, no size-check required */
1460  if (connection->read_closed)
1461  {
1462  CONNECTION_CLOSE_ERROR (connection,
1463  NULL);
1464  continue;
1465  }
1467  /* transition to FOOTERS_RECEIVED
1468  happens in read handler */
1469  break;
1472  break;
1474  /* headers in buffer, keep writing */
1476  break;
1478  EXTRA_CHECK (0);
1479  break;
1482  break;
1485  break;
1488  break;
1491  break;
1493  EXTRA_CHECK (0);
1494  break;
1497  break;
1499  EXTRA_CHECK (0);
1500  break;
1501  case MHD_CONNECTION_CLOSED:
1503  return; /* do nothing, not even reading */
1504  default:
1505  EXTRA_CHECK (0);
1506  }
1507  break;
1508  }
1509 }
1510 
1511 
1525 static char *
1527  size_t *line_len)
1528 {
1529  char *rbuf;
1530  size_t pos;
1531 
1532  if (0 == connection->read_buffer_offset)
1533  return NULL;
1534  pos = 0;
1535  rbuf = connection->read_buffer;
1536  while ( (pos < connection->read_buffer_offset - 1) &&
1537  ('\r' != rbuf[pos]) &&
1538  ('\n' != rbuf[pos]) )
1539  pos++;
1540  if ( (pos == connection->read_buffer_offset - 1) &&
1541  ('\n' != rbuf[pos]) )
1542  {
1543  /* not found, consider growing... */
1544  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1545  (MHD_NO ==
1546  try_grow_read_buffer (connection)) )
1547  {
1548  transmit_error_response (connection,
1549  (NULL != connection->url)
1552  REQUEST_TOO_BIG);
1553  }
1554  if (line_len)
1555  *line_len = 0;
1556  return NULL;
1557  }
1558 
1559  if (line_len)
1560  *line_len = pos;
1561  /* found, check if we have proper LFCR */
1562  if ( ('\r' == rbuf[pos]) &&
1563  ('\n' == rbuf[pos + 1]) )
1564  rbuf[pos++] = '\0'; /* skip both r and n */
1565  rbuf[pos++] = '\0';
1566  connection->read_buffer += pos;
1567  connection->read_buffer_size -= pos;
1568  connection->read_buffer_offset -= pos;
1569  return rbuf;
1570 }
1571 
1572 
1584 static int
1586  const char *key,
1587  const char *value,
1588  enum MHD_ValueKind kind)
1589 {
1590  if (MHD_NO ==
1591  MHD_set_connection_value (connection,
1592  kind,
1593  key,
1594  value))
1595  {
1596 #ifdef HAVE_MESSAGES
1597  MHD_DLOG (connection->daemon,
1598  _("Not enough memory in pool to allocate header record!\n"));
1599 #endif
1600  transmit_error_response (connection,
1602  REQUEST_TOO_BIG);
1603  return MHD_NO;
1604  }
1605  return MHD_YES;
1606 }
1607 
1608 
1615 static int
1617 {
1618  const char *hdr;
1619  char *cpy;
1620  char *pos;
1621  char *sce;
1622  char *semicolon;
1623  char *equals;
1624  char *ekill;
1625  char old;
1626  int quotes;
1627 
1628  hdr = MHD_lookup_connection_value (connection,
1631  if (NULL == hdr)
1632  return MHD_YES;
1633  cpy = MHD_pool_allocate (connection->pool,
1634  strlen (hdr) + 1,
1635  MHD_YES);
1636  if (NULL == cpy)
1637  {
1638 #ifdef HAVE_MESSAGES
1639  MHD_DLOG (connection->daemon,
1640  _("Not enough memory in pool to parse cookies!\n"));
1641 #endif
1642  transmit_error_response (connection,
1644  REQUEST_TOO_BIG);
1645  return MHD_NO;
1646  }
1647  memcpy (cpy,
1648  hdr,
1649  strlen (hdr) + 1);
1650  pos = cpy;
1651  while (NULL != pos)
1652  {
1653  while (' ' == *pos)
1654  pos++; /* skip spaces */
1655 
1656  sce = pos;
1657  while ( ((*sce) != '\0') &&
1658  ((*sce) != ',') &&
1659  ((*sce) != ';') &&
1660  ((*sce) != '=') )
1661  sce++;
1662  /* remove tailing whitespace (if any) from key */
1663  ekill = sce - 1;
1664  while ( (*ekill == ' ') &&
1665  (ekill >= pos) )
1666  *(ekill--) = '\0';
1667  old = *sce;
1668  *sce = '\0';
1669  if (old != '=')
1670  {
1671  /* value part omitted, use empty string... */
1672  if (MHD_NO ==
1673  connection_add_header (connection,
1674  pos,
1675  "",
1676  MHD_COOKIE_KIND))
1677  return MHD_NO;
1678  if (old == '\0')
1679  break;
1680  pos = sce + 1;
1681  continue;
1682  }
1683  equals = sce + 1;
1684  quotes = 0;
1685  semicolon = equals;
1686  while ( ('\0' != semicolon[0]) &&
1687  ( (0 != quotes) ||
1688  ( (';' != semicolon[0]) &&
1689  (',' != semicolon[0]) ) ) )
1690  {
1691  if ('"' == semicolon[0])
1692  quotes = (quotes + 1) & 1;
1693  semicolon++;
1694  }
1695  if ('\0' == semicolon[0])
1696  semicolon = NULL;
1697  if (NULL != semicolon)
1698  {
1699  semicolon[0] = '\0';
1700  semicolon++;
1701  }
1702  /* remove quotes */
1703  if ( ('"' == equals[0]) &&
1704  ('"' == equals[strlen (equals) - 1]) )
1705  {
1706  equals[strlen (equals) - 1] = '\0';
1707  equals++;
1708  }
1709  if (MHD_NO ==
1710  connection_add_header (connection,
1711  pos,
1712  equals,
1713  MHD_COOKIE_KIND))
1714  return MHD_NO;
1715  pos = semicolon;
1716  }
1717  return MHD_YES;
1718 }
1719 
1720 
1729 static int
1731  char *line,
1732  size_t line_len)
1733 {
1734  struct MHD_Daemon *daemon = connection->daemon;
1735  const char *curi;
1736  char *uri;
1737  char *http_version;
1738  char *args;
1739  unsigned int unused_num_headers;
1740 
1741  if (NULL == (uri = memchr (line,
1742  ' ',
1743  line_len)))
1744  return MHD_NO; /* serious error */
1745  uri[0] = '\0';
1746  connection->method = line;
1747  uri++;
1748  /* Skip any spaces. Not required by standard but allow
1749  to be more tolerant. */
1750  while ( (' ' == uri[0]) &&
1751  ( (size_t)(uri - line) < line_len) )
1752  uri++;
1753  if ((size_t)(uri - line) == line_len)
1754  {
1755  curi = "";
1756  uri = NULL;
1757  connection->version = "";
1758  args = NULL;
1759  }
1760  else
1761  {
1762  curi = uri;
1763  /* Search from back to accept misformed URI with space */
1764  http_version = line + line_len - 1;
1765  /* Skip any trailing spaces */
1766  while ( (' ' == http_version[0]) &&
1767  (http_version > uri) )
1768  http_version--;
1769  /* Find first space in reverse direction */
1770  while ( (' ' != http_version[0]) &&
1771  (http_version > uri) )
1772  http_version--;
1773  if (http_version > uri)
1774  {
1775  http_version[0] = '\0';
1776  connection->version = http_version + 1;
1777  args = memchr (uri,
1778  '?',
1779  http_version - uri);
1780  }
1781  else
1782  {
1783  connection->version = "";
1784  args = memchr (uri,
1785  '?',
1786  line_len - (uri - line));
1787  }
1788  }
1789  if (NULL != daemon->uri_log_callback)
1790  {
1791  connection->client_aware = true;
1792  connection->client_context
1793  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
1794  curi,
1795  connection);
1796  }
1797  if (NULL != args)
1798  {
1799  args[0] = '\0';
1800  args++;
1801  /* note that this call clobbers 'args' */
1802  MHD_parse_arguments_ (connection,
1804  args,
1806  &unused_num_headers);
1807  }
1808  if (NULL != uri)
1809  daemon->unescape_callback (daemon->unescape_callback_cls,
1810  connection,
1811  uri);
1812  connection->url = curi;
1813  return MHD_YES;
1814 }
1815 
1816 
1824 static void
1826 {
1827  size_t processed;
1828 
1829  if (NULL != connection->response)
1830  return; /* already queued a response */
1831  processed = 0;
1832  connection->client_aware = true;
1833  if (MHD_NO ==
1834  connection->daemon->default_handler (connection->daemon->default_handler_cls,
1835  connection,
1836  connection->url,
1837  connection->method,
1838  connection->version,
1839  NULL,
1840  &processed,
1841  &connection->client_context))
1842  {
1843  /* serious internal error, close connection */
1844  CONNECTION_CLOSE_ERROR (connection,
1845  _("Application reported internal error, closing connection.\n"));
1846  return;
1847  }
1848 }
1849 
1850 
1851 
1859 static void
1861 {
1862  uint64_t processed;
1863  size_t available;
1864  size_t used;
1865  size_t i;
1866  size_t end_size;
1867  int instant_retry;
1868  int malformed;
1869  char *buffer_head;
1870 
1871  if (NULL != connection->response)
1872  return; /* already queued a response */
1873 
1874  buffer_head = connection->read_buffer;
1875  available = connection->read_buffer_offset;
1876  do
1877  {
1878  instant_retry = MHD_NO;
1879  if ( (connection->have_chunked_upload) &&
1880  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
1881  {
1882  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
1883  (0LLU != connection->current_chunk_offset) &&
1884  (available >= 2) )
1885  {
1886  /* skip new line at the *end* of a chunk */
1887  i = 0;
1888  if ( ('\r' == buffer_head[i]) ||
1889  ('\n' == buffer_head[i]) )
1890  i++; /* skip 1st part of line feed */
1891  if ( ('\r' == buffer_head[i]) ||
1892  ('\n' == buffer_head[i]) )
1893  i++; /* skip 2nd part of line feed */
1894  if (0 == i)
1895  {
1896  /* malformed encoding */
1897  CONNECTION_CLOSE_ERROR (connection,
1898  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
1899  return;
1900  }
1901  available -= i;
1902  buffer_head += i;
1903  connection->current_chunk_offset = 0;
1904  connection->current_chunk_size = 0;
1905  }
1906  if (connection->current_chunk_offset <
1907  connection->current_chunk_size)
1908  {
1909  /* we are in the middle of a chunk, give
1910  as much as possible to the client (without
1911  crossing chunk boundaries) */
1912  processed
1913  = connection->current_chunk_size - connection->current_chunk_offset;
1914  if (processed > available)
1915  processed = available;
1916  if (available > processed)
1917  instant_retry = MHD_YES;
1918  }
1919  else
1920  {
1921  /* we need to read chunk boundaries */
1922  i = 0;
1923  while (i < available)
1924  {
1925  if ( ('\r' == buffer_head[i]) ||
1926  ('\n' == buffer_head[i]) ||
1927  (';' == buffer_head[i]) )
1928  break;
1929  i++;
1930  if (i >= 16)
1931  break;
1932  }
1933  end_size = i;
1934  /* find beginning of CRLF (skip over chunk extensions) */
1935  if (';' == buffer_head[i])
1936  {
1937  while (i < available)
1938  {
1939  if ( ('\r' == buffer_head[i]) ||
1940  ('\n' == buffer_head[i]) )
1941  break;
1942  i++;
1943  }
1944  }
1945  /* take '\n' into account; if '\n' is the unavailable
1946  character, we will need to wait until we have it
1947  before going further */
1948  if ( (i + 1 >= available) &&
1949  ! ( (1 == i) &&
1950  (2 == available) &&
1951  ('0' == buffer_head[0]) ) )
1952  break; /* need more data... */
1953  i++;
1954  malformed = (end_size >= 16);
1955  if (! malformed)
1956  {
1957  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
1958  end_size,
1959  &connection->current_chunk_size);
1960  malformed = (end_size != num_dig);
1961  }
1962  if (malformed)
1963  {
1964  /* malformed encoding */
1965  CONNECTION_CLOSE_ERROR (connection,
1966  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
1967  return;
1968  }
1969  /* skip 2nd part of line feed */
1970  if ( (i < available) &&
1971  ( ('\r' == buffer_head[i]) ||
1972  ('\n' == buffer_head[i]) ) )
1973  i++;
1974 
1975  buffer_head += i;
1976  available -= i;
1977  connection->current_chunk_offset = 0;
1978 
1979  if (available > 0)
1980  instant_retry = MHD_YES;
1981  if (0LLU == connection->current_chunk_size)
1982  {
1983  connection->remaining_upload_size = 0;
1984  break;
1985  }
1986  continue;
1987  }
1988  }
1989  else
1990  {
1991  /* no chunked encoding, give all to the client */
1992  if ( (0 != connection->remaining_upload_size) &&
1993  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
1994  (connection->remaining_upload_size < available) )
1995  {
1996  processed = (size_t)connection->remaining_upload_size;
1997  }
1998  else
1999  {
2004  processed = available;
2005  }
2006  }
2007  used = processed;
2008  connection->client_aware = true;
2009  {
2010  size_t processed_st = (size_t) processed;
2011  if (MHD_NO ==
2012  connection->daemon->default_handler (connection->daemon->default_handler_cls,
2013  connection,
2014  connection->url,
2015  connection->method,
2016  connection->version,
2017  buffer_head,
2018  &processed_st,
2019  &connection->client_context))
2020  {
2021  /* serious internal error, close connection */
2022  CONNECTION_CLOSE_ERROR (connection,
2023  _("Application reported internal error, closing connection.\n"));
2024  return;
2025  }
2026  processed = (uint64_t) processed_st;
2027  }
2028  if (processed > used)
2030  __FILE__,
2031  __LINE__
2032 #ifdef HAVE_MESSAGES
2033  , _("libmicrohttpd API violation")
2034 #else
2035  , NULL
2036 #endif
2037  );
2038  if (0 != processed)
2039  {
2040  instant_retry = MHD_NO; /* client did not process everything */
2041 #ifdef HAVE_MESSAGES
2042  /* client did not process all POST data, complain if
2043  the setup was incorrect, which may prevent us from
2044  handling the rest of the request */
2045  if ( (0 != (connection->daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2046  (! connection->suspended) )
2047  MHD_DLOG (connection->daemon,
2048  _("WARNING: incomplete POST processing and connection not suspended will result in hung connection.\n"));
2049 #endif
2050  }
2051  used -= processed;
2052  if (connection->have_chunked_upload)
2053  connection->current_chunk_offset += used;
2054  /* dh left "processed" bytes in buffer for next time... */
2055  buffer_head += used;
2056  available -= used;
2057  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2058  connection->remaining_upload_size -= used;
2059  }
2060  while (MHD_YES == instant_retry);
2061  if (available > 0)
2062  memmove (connection->read_buffer,
2063  buffer_head,
2064  available);
2065  connection->read_buffer_offset = available;
2066 }
2067 
2068 
2078 static int
2079 do_read (struct MHD_Connection *connection)
2080 {
2081  ssize_t bytes_read;
2082 
2083  if (connection->read_buffer_size == connection->read_buffer_offset)
2084  return MHD_NO;
2085  bytes_read = connection->recv_cls (connection,
2086  &connection->read_buffer
2087  [connection->read_buffer_offset],
2088  connection->read_buffer_size -
2089  connection->read_buffer_offset);
2090  if (bytes_read < 0)
2091  {
2092  const int err = MHD_socket_get_error_ ();
2093  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2095  return MHD_NO;
2097  {
2098  CONNECTION_CLOSE_ERROR (connection,
2099  NULL);
2100  return MHD_NO;
2101  }
2102  CONNECTION_CLOSE_ERROR (connection,
2103  NULL);
2104  return MHD_YES;
2105  }
2106  if (0 == bytes_read)
2107  {
2108  /* other side closed connection; RFC 2616, section 8.1.4 suggests
2109  we should then shutdown ourselves as well. */
2110  connection->read_closed = true;
2111  MHD_connection_close_ (connection,
2113  return MHD_YES;
2114  }
2115  connection->read_buffer_offset += bytes_read;
2116  return MHD_YES;
2117 }
2118 
2119 
2128 static int
2129 do_write (struct MHD_Connection *connection)
2130 {
2131  ssize_t ret;
2132  size_t max;
2133 
2134  max = connection->write_buffer_append_offset - connection->write_buffer_send_offset;
2135  ret = connection->send_cls (connection,
2136  &connection->write_buffer
2137  [connection->write_buffer_send_offset],
2138  max);
2139 
2140  if (ret < 0)
2141  {
2142  const int err = MHD_socket_get_error_ ();
2143  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2145  return MHD_NO;
2146  CONNECTION_CLOSE_ERROR (connection,
2147  NULL);
2148  return MHD_YES;
2149  }
2150 #if DEBUG_SEND_DATA
2151  fprintf (stderr,
2152  _("Sent response: `%.*s'\n"),
2153  ret,
2154  &connection->write_buffer[connection->write_buffer_send_offset]);
2155 #endif
2156  /* only increment if this wasn't a "sendfile" transmission without
2157  buffer involvement! */
2158  if (0 != max)
2159  connection->write_buffer_send_offset += ret;
2160  return MHD_YES;
2161 }
2162 
2163 
2172 static int
2173 check_write_done (struct MHD_Connection *connection,
2174  enum MHD_CONNECTION_STATE next_state)
2175 {
2176  if (connection->write_buffer_append_offset !=
2177  connection->write_buffer_send_offset)
2178  return MHD_NO;
2179  connection->write_buffer_append_offset = 0;
2180  connection->write_buffer_send_offset = 0;
2181  connection->state = next_state;
2182  MHD_pool_reallocate (connection->pool,
2183  connection->write_buffer,
2184  connection->write_buffer_size,
2185  0);
2186  connection->write_buffer = NULL;
2187  connection->write_buffer_size = 0;
2188  return MHD_YES;
2189 }
2190 
2191 
2201 static int
2203  char *line)
2204 {
2205  char *colon;
2206 
2207  /* line should be normal header line, find colon */
2208  colon = strchr (line, ':');
2209  if (NULL == colon)
2210  {
2211  /* error in header line, die hard */
2212  CONNECTION_CLOSE_ERROR (connection,
2213  _("Received malformed line (no colon). Closing connection.\n"));
2214  return MHD_NO;
2215  }
2216  if (-1 >= connection->daemon->strict_for_client)
2217  {
2218  /* check for whitespace before colon, which is not allowed
2219  by RFC 7230 section 3.2.4; we count space ' ' and
2220  tab '\t', but not '\r\n' as those would have ended the line. */
2221  const char *white;
2222 
2223  white = strchr (line, ' ');
2224  if ( (NULL != white) &&
2225  (white < colon) )
2226  return MHD_NO;
2227  white = strchr (line, '\t');
2228  if ( (NULL != white) &&
2229  (white < colon) )
2230  return MHD_NO;
2231  }
2232  /* zero-terminate header */
2233  colon[0] = '\0';
2234  colon++; /* advance to value */
2235  while ( ('\0' != colon[0]) &&
2236  ( (' ' == colon[0]) ||
2237  ('\t' == colon[0]) ) )
2238  colon++;
2239  /* we do the actual adding of the connection
2240  header at the beginning of the while
2241  loop since we need to be able to inspect
2242  the *next* header line (in case it starts
2243  with a space...) */
2244  connection->last = line;
2245  connection->colon = colon;
2246  return MHD_YES;
2247 }
2248 
2249 
2260 static int
2262  char *line,
2263  enum MHD_ValueKind kind)
2264 {
2265  char *last;
2266  char *tmp;
2267  size_t last_len;
2268  size_t tmp_len;
2269 
2270  last = connection->last;
2271  if ( (' ' == line[0]) ||
2272  ('\t' == line[0]) )
2273  {
2274  /* value was continued on the next line, see
2275  http://www.jmarshall.com/easy/http/ */
2276  last_len = strlen (last);
2277  /* skip whitespace at start of 2nd line */
2278  tmp = line;
2279  while ( (' ' == tmp[0]) ||
2280  ('\t' == tmp[0]) )
2281  tmp++;
2282  tmp_len = strlen (tmp);
2283  /* FIXME: we might be able to do this better (faster!), as most
2284  likely 'last' and 'line' should already be adjacent in
2285  memory; however, doing this right gets tricky if we have a
2286  value continued over multiple lines (in which case we need to
2287  record how often we have done this so we can check for
2288  adjacency); also, in the case where these are not adjacent
2289  (not sure how it can happen!), we would want to allocate from
2290  the end of the pool, so as to not destroy the read-buffer's
2291  ability to grow nicely. */
2292  last = MHD_pool_reallocate (connection->pool,
2293  last,
2294  last_len + 1,
2295  last_len + tmp_len + 1);
2296  if (NULL == last)
2297  {
2298  transmit_error_response (connection,
2300  REQUEST_TOO_BIG);
2301  return MHD_NO;
2302  }
2303  memcpy (&last[last_len], tmp, tmp_len + 1);
2304  connection->last = last;
2305  return MHD_YES; /* possibly more than 2 lines... */
2306  }
2307  EXTRA_CHECK ( (NULL != last) &&
2308  (NULL != connection->colon) );
2309  if ((MHD_NO == connection_add_header (connection,
2310  last,
2311  connection->colon,
2312  kind)))
2313  {
2314  transmit_error_response (connection,
2316  REQUEST_TOO_BIG);
2317  return MHD_NO;
2318  }
2319  /* we still have the current line to deal with... */
2320  if (0 != line[0])
2321  {
2322  if (MHD_NO == process_header_line (connection,
2323  line))
2324  {
2325  transmit_error_response (connection,
2328  return MHD_NO;
2329  }
2330  }
2331  return MHD_YES;
2332 }
2333 
2334 
2342 static void
2344 {
2345  const char *clen;
2346  struct MHD_Response *response;
2347  const char *enc;
2348  const char *end;
2349 
2350  parse_cookie_header (connection);
2351  if ( (1 <= connection->daemon->strict_for_client) &&
2352  (NULL != connection->version) &&
2354  connection->version)) &&
2355  (NULL ==
2356  MHD_lookup_connection_value (connection,
2359  {
2360  /* die, http 1.1 request without host and we are pedantic */
2361  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2362  connection->read_closed = true;
2363 #ifdef HAVE_MESSAGES
2364  MHD_DLOG (connection->daemon,
2365  _("Received HTTP 1.1 request without `Host' header.\n"));
2366 #endif
2367  EXTRA_CHECK (NULL == connection->response);
2368  response =
2371  MHD_RESPMEM_PERSISTENT);
2372  MHD_queue_response (connection,
2374  response);
2375  MHD_destroy_response (response);
2376  return;
2377  }
2378 
2379  connection->remaining_upload_size = 0;
2380  enc = MHD_lookup_connection_value (connection,
2383  if (NULL != enc)
2384  {
2386  if (MHD_str_equal_caseless_(enc,
2387  "chunked"))
2388  connection->have_chunked_upload = true;
2389  }
2390  else
2391  {
2392  clen = MHD_lookup_connection_value (connection,
2395  if (NULL != clen)
2396  {
2397  end = clen + MHD_str_to_uint64_ (clen,
2398  &connection->remaining_upload_size);
2399  if ( (clen == end) ||
2400  ('\0' != *end) )
2401  {
2402  connection->remaining_upload_size = 0;
2403 #ifdef HAVE_MESSAGES
2404  MHD_DLOG (connection->daemon,
2405  "Failed to parse `Content-Length' header. Closing connection.\n");
2406 #endif
2407  CONNECTION_CLOSE_ERROR (connection,
2408  NULL);
2409  return;
2410  }
2411  }
2412  }
2413 }
2414 
2415 
2423 void
2425 {
2426  struct MHD_Daemon *daemon = connection->daemon;
2427 
2428  if (0 == connection->connection_timeout)
2429  return; /* Skip update of activity for connections
2430  without timeout timer. */
2431  if (connection->suspended)
2432  return; /* no activity on suspended connections */
2433 
2434  connection->last_activity = MHD_monotonic_sec_counter();
2435  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2436  return; /* each connection has personal timeout */
2437 
2438  if (connection->connection_timeout != daemon->connection_timeout)
2439  return; /* custom timeout, no need to move it in "normal" DLL */
2440 
2442  /* move connection to head of timeout list (by remove + add operation) */
2444  daemon->normal_timeout_tail,
2445  connection);
2447  daemon->normal_timeout_tail,
2448  connection);
2450 }
2451 
2452 
2461 int
2463 {
2464  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2465  (connection->suspended) )
2466  return MHD_YES;
2467  /* make sure "read" has a reasonable number of bytes
2468  in buffer to use per system call (if possible) */
2469  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2470  connection->read_buffer_size)
2471  try_grow_read_buffer (connection);
2472  if (MHD_NO == do_read (connection))
2473  return MHD_YES;
2474  MHD_update_last_activity_ (connection);
2475  while (1)
2476  {
2477 #if DEBUG_STATES
2478  MHD_DLOG (connection->daemon,
2479  _("In function %s handling connection at state: %s\n"),
2480  __FUNCTION__,
2481  MHD_state_to_string (connection->state));
2482 #endif
2483  switch (connection->state)
2484  {
2485  case MHD_CONNECTION_INIT:
2494  /* nothing to do but default action */
2495  if (connection->read_closed)
2496  {
2497  MHD_connection_close_ (connection,
2499  continue;
2500  }
2501  break;
2502  case MHD_CONNECTION_CLOSED:
2503  return MHD_YES;
2504 #ifdef UPGRADE_SUPPORT
2505  case MHD_CONNECTION_UPGRADE:
2506  EXTRA_CHECK (0);
2507  break;
2508 #endif /* UPGRADE_SUPPORT */
2509  default:
2510  /* shrink read buffer to how much is actually used */
2511  MHD_pool_reallocate (connection->pool,
2512  connection->read_buffer,
2513  connection->read_buffer_size + 1,
2514  connection->read_buffer_offset);
2515  break;
2516  }
2517  break;
2518  }
2519  return MHD_YES;
2520 }
2521 
2522 
2531 int
2533 {
2534  struct MHD_Response *response;
2535  ssize_t ret;
2536  if (connection->suspended)
2537  return MHD_YES;
2538 
2539  while (1)
2540  {
2541 #if DEBUG_STATES
2542  MHD_DLOG (connection->daemon,
2543  _("In function %s handling connection at state: %s\n"),
2544  __FUNCTION__,
2545  MHD_state_to_string (connection->state));
2546 #endif
2547  switch (connection->state)
2548  {
2549  case MHD_CONNECTION_INIT:
2553  EXTRA_CHECK (0);
2554  break;
2556  break;
2558  ret = connection->send_cls (connection,
2560  [connection->continue_message_write_offset],
2562  connection->continue_message_write_offset);
2563  if (ret < 0)
2564  {
2565  const int err = MHD_socket_get_error_ ();
2566 
2567  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2569  break;
2570 #ifdef HAVE_MESSAGES
2571  MHD_DLOG (connection->daemon,
2572  _("Failed to send data in request for %s: %s\n"),
2573  connection->url,
2574  MHD_socket_strerr_ (err));
2575 #endif
2576  CONNECTION_CLOSE_ERROR (connection,
2577  NULL);
2578  return MHD_YES;
2579  }
2580 #if DEBUG_SEND_DATA
2581  fprintf (stderr,
2582  _("Sent 100 continue response: `%.*s'\n"),
2583  (int) ret,
2585 #endif
2586  connection->continue_message_write_offset += ret;
2587  MHD_update_last_activity_ (connection);
2588  break;
2593  EXTRA_CHECK (0);
2594  break;
2596  if (MHD_NO != do_write (connection))
2597  MHD_update_last_activity_ (connection);
2598  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
2599  break;
2600  check_write_done (connection,
2602  break;
2604  break;
2606  response = connection->response;
2607  if (connection->response_write_position <
2608  connection->response->total_size)
2609  {
2610  int err;
2611  uint64_t data_write_offset;
2612 
2613  if (NULL != response->crc)
2614  MHD_mutex_lock_chk_ (&response->mutex);
2615  if (MHD_YES != try_ready_normal_body (connection))
2616  {
2617  /* mutex was already unlocked by try_ready_normal_body */
2618  break;
2619  }
2620  data_write_offset = connection->response_write_position
2621  - response->data_start;
2622  if (data_write_offset > (uint64_t)SIZE_MAX)
2623  MHD_PANIC (_("Data offset exceeds limit"));
2624  ret = connection->send_cls (connection,
2625  &response->data
2626  [(size_t)data_write_offset],
2627  response->data_size -
2628  (size_t)data_write_offset);
2629 #if DEBUG_SEND_DATA
2630  if (ret > 0)
2631  fprintf (stderr,
2632  _("Sent %d-byte DATA response: `%.*s'\n"),
2633  (int) ret,
2634  (int) ret,
2635  &response->data[connection->response_write_position -
2636  response->data_start]);
2637 #endif
2638  if (NULL != response->crc)
2639  MHD_mutex_unlock_chk_ (&response->mutex);
2640  if (ret < 0)
2641  {
2642  err = MHD_socket_get_error_ ();
2643  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2645  return MHD_YES;
2646 #ifdef HAVE_MESSAGES
2647  MHD_DLOG (connection->daemon,
2648  _("Failed to send data in request for `%s': %s\n"),
2649  connection->url,
2650  MHD_socket_strerr_ (err));
2651 #endif
2652  CONNECTION_CLOSE_ERROR (connection,
2653  NULL);
2654  return MHD_YES;
2655  }
2656  connection->response_write_position += ret;
2657  MHD_update_last_activity_ (connection);
2658  }
2659  if (connection->response_write_position ==
2660  connection->response->total_size)
2661  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
2662  break;
2664  EXTRA_CHECK (0);
2665  break;
2667  if (MHD_NO != do_write (connection))
2668  MHD_update_last_activity_ (connection);
2669  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
2670  break;
2671  check_write_done (connection,
2672  (connection->response->total_size ==
2673  connection->response_write_position) ?
2676  break;
2679  EXTRA_CHECK (0);
2680  break;
2682  if (MHD_NO != do_write (connection))
2683  MHD_update_last_activity_ (connection);
2684  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
2685  break;
2686  check_write_done (connection,
2688  break;
2690  EXTRA_CHECK (0);
2691  break;
2692  case MHD_CONNECTION_CLOSED:
2693  return MHD_YES;
2695  EXTRA_CHECK (0);
2696  break;
2697 #ifdef UPGRADE_SUPPORT
2698  case MHD_CONNECTION_UPGRADE:
2699  EXTRA_CHECK (0);
2700  break;
2701 #endif /* UPGRADE_SUPPORT */
2702  default:
2703  EXTRA_CHECK (0);
2704  CONNECTION_CLOSE_ERROR (connection,
2705  _("Internal error\n"));
2706  return MHD_YES;
2707  }
2708  break;
2709  }
2710  return MHD_YES;
2711 }
2712 
2713 
2722 static void
2724 {
2725  struct MHD_Daemon *daemon = connection->daemon;
2726 
2727  if (connection->in_cleanup)
2728  return; /* Prevent double cleanup. */
2729  connection->in_cleanup = true;
2730  if (NULL != connection->response)
2731  {
2732  MHD_destroy_response (connection->response);
2733  connection->response = NULL;
2734  }
2736  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2737  {
2738  if (connection->connection_timeout == daemon->connection_timeout)
2740  daemon->normal_timeout_tail,
2741  connection);
2742  else
2744  daemon->manual_timeout_tail,
2745  connection);
2746  }
2747  if (connection->suspended)
2748  {
2751  connection);
2752  connection->suspended = false;
2753  }
2754  else
2755  {
2756  DLL_remove (daemon->connections_head,
2757  daemon->connections_tail,
2758  connection);
2759  }
2760  DLL_insert (daemon->cleanup_head,
2761  daemon->cleanup_tail,
2762  connection);
2763  connection->resuming = false;
2764  connection->in_idle = false;
2766  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2767  {
2768  /* if we were at the connection limit before and are in
2769  thread-per-connection mode, signal the main thread
2770  to resume accepting connections */
2771  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2772  (! MHD_itc_activate_ (daemon->itc, "c")) )
2773  {
2774 #ifdef HAVE_MESSAGES
2775  MHD_DLOG (daemon,
2776  _("Failed to signal end of connection via inter-thread communication channel"));
2777 #endif
2778  }
2779  }
2780 }
2781 
2782 
2793 int
2795 {
2796  struct MHD_Daemon *daemon = connection->daemon;
2797  const char *end;
2798  char *line;
2799  size_t line_len;
2800  int client_close;
2801  int ret;
2802 
2803  connection->in_idle = true;
2804  while (! connection->suspended)
2805  {
2806 #if DEBUG_STATES
2807  MHD_DLOG (daemon,
2808  _("In function %s handling connection at state: %s\n"),
2809  __FUNCTION__,
2810  MHD_state_to_string (connection->state));
2811 #endif
2812  switch (connection->state)
2813  {
2814  case MHD_CONNECTION_INIT:
2815  line = get_next_header_line (connection,
2816  &line_len);
2817  /* Check for empty string, as we might want
2818  to tolerate 'spurious' empty lines; also
2819  NULL means we didn't get a full line yet;
2820  line is not 0-terminated here. */
2821  if ( (NULL == line) ||
2822  (0 == line[0]) )
2823  {
2824  if (MHD_CONNECTION_INIT != connection->state)
2825  continue;
2826  if (connection->read_closed)
2827  {
2828  CONNECTION_CLOSE_ERROR (connection,
2829  NULL);
2830  continue;
2831  }
2832  break;
2833  }
2834  if (MHD_NO == parse_initial_message_line (connection,
2835  line,
2836  line_len))
2837  CONNECTION_CLOSE_ERROR (connection,
2838  NULL);
2839  else
2840  connection->state = MHD_CONNECTION_URL_RECEIVED;
2841  continue;
2843  line = get_next_header_line (connection,
2844  NULL);
2845  if (NULL == line)
2846  {
2847  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
2848  continue;
2849  if (connection->read_closed)
2850  {
2851  CONNECTION_CLOSE_ERROR (connection,
2852  NULL);
2853  continue;
2854  }
2855  break;
2856  }
2857  if (0 == line[0])
2858  {
2859  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2860  connection->header_size = (size_t) (line - connection->read_buffer);
2861  continue;
2862  }
2863  if (MHD_NO == process_header_line (connection,
2864  line))
2865  {
2866  transmit_error_response (connection,
2869  break;
2870  }
2872  continue;
2874  line = get_next_header_line (connection,
2875  NULL);
2876  if (NULL == line)
2877  {
2878  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2879  continue;
2880  if (connection->read_closed)
2881  {
2882  CONNECTION_CLOSE_ERROR (connection,
2883  NULL);
2884  continue;
2885  }
2886  break;
2887  }
2888  if (MHD_NO ==
2889  process_broken_line (connection,
2890  line,
2891  MHD_HEADER_KIND))
2892  continue;
2893  if (0 == line[0])
2894  {
2895  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2896  connection->header_size = (size_t) (line - connection->read_buffer);
2897  continue;
2898  }
2899  continue;
2901  parse_connection_headers (connection);
2902  if (MHD_CONNECTION_CLOSED == connection->state)
2903  continue;
2905  if (connection->suspended)
2906  break;
2907  continue;
2909  call_connection_handler (connection); /* first call */
2910  if (MHD_CONNECTION_CLOSED == connection->state)
2911  continue;
2912  if (need_100_continue (connection))
2913  {
2914  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2915  if (MHD_NO != socket_flush_possible (connection))
2916  socket_start_extra_buffering (connection);
2917  else
2918  socket_start_no_buffering (connection);
2919 
2920  break;
2921  }
2922  if ( (NULL != connection->response) &&
2923  ( (MHD_str_equal_caseless_ (connection->method,
2925  (MHD_str_equal_caseless_ (connection->method,
2926  MHD_HTTP_METHOD_PUT))) )
2927  {
2928  /* we refused (no upload allowed!) */
2929  connection->remaining_upload_size = 0;
2930  /* force close, in case client still tries to upload... */
2931  connection->read_closed = true;
2932  }
2933  connection->state = (0 == connection->remaining_upload_size)
2935  if (connection->suspended)
2936  break;
2937  continue;
2939  if (connection->continue_message_write_offset ==
2941  {
2942  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2943  if (MHD_NO != socket_flush_possible (connection))
2944  socket_start_no_buffering_flush (connection);
2945  else
2946  socket_start_normal_buffering (connection);
2947 
2948  continue;
2949  }
2950  break;
2952  if (0 != connection->read_buffer_offset)
2953  {
2954  process_request_body (connection); /* loop call */
2955  if (MHD_CONNECTION_CLOSED == connection->state)
2956  continue;
2957  }
2958  if ( (0 == connection->remaining_upload_size) ||
2959  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
2960  (0 == connection->read_buffer_offset) &&
2961  (connection->read_closed) ) )
2962  {
2963  if ( (connection->have_chunked_upload) &&
2964  (! connection->read_closed) )
2965  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2966  else
2967  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2968  if (connection->suspended)
2969  break;
2970  continue;
2971  }
2972  break;
2974  line = get_next_header_line (connection,
2975  NULL);
2976  if (NULL == line)
2977  {
2978  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2979  continue;
2980  if (connection->read_closed)
2981  {
2982  CONNECTION_CLOSE_ERROR (connection,
2983  NULL);
2984  continue;
2985  }
2986  break;
2987  }
2988  if (0 == line[0])
2989  {
2990  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2991  if (connection->suspended)
2992  break;
2993  continue;
2994  }
2995  if (MHD_NO == process_header_line (connection,
2996  line))
2997  {
2998  transmit_error_response (connection,
3001  break;
3002  }
3004  continue;
3006  line = get_next_header_line (connection,
3007  NULL);
3008  if (NULL == line)
3009  {
3010  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3011  continue;
3012  if (connection->read_closed)
3013  {
3014  CONNECTION_CLOSE_ERROR (connection,
3015  NULL);
3016  continue;
3017  }
3018  break;
3019  }
3020  if (MHD_NO ==
3021  process_broken_line (connection,
3022  line,
3023  MHD_FOOTER_KIND))
3024  continue;
3025  if (0 == line[0])
3026  {
3027  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3028  if (connection->suspended)
3029  break;
3030  continue;
3031  }
3032  continue;
3034  call_connection_handler (connection); /* "final" call */
3035  if (connection->state == MHD_CONNECTION_CLOSED)
3036  continue;
3037  if (NULL == connection->response)
3038  break; /* try again next time */
3039  if (MHD_NO == build_header_response (connection))
3040  {
3041  /* oops - close! */
3042  CONNECTION_CLOSE_ERROR (connection,
3043  _("Closing connection (failed to create response header)\n"));
3044  continue;
3045  }
3046  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3047  if (MHD_NO != socket_flush_possible (connection))
3048  socket_start_extra_buffering (connection);
3049  else
3050  socket_start_no_buffering (connection);
3051 
3052  break;
3054  /* no default action */
3055  break;
3057  /* Some clients may take some actions right after header receive */
3058  if (MHD_NO != socket_flush_possible (connection))
3059  socket_start_no_buffering_flush (connection);
3060 
3061 #ifdef UPGRADE_SUPPORT
3062  if (NULL != connection->response->upgrade_handler)
3063  {
3064  struct MHD_Response *resp_clr = connection->response;
3065 
3066  socket_start_normal_buffering (connection);
3067  connection->state = MHD_CONNECTION_UPGRADE;
3068  connection->response = NULL;
3069  /* This connection is "upgraded". Pass socket to application. */
3070  if (MHD_YES !=
3072  connection))
3073  {
3074  /* upgrade failed, fail hard */
3075  CONNECTION_CLOSE_ERROR (connection,
3076  NULL);
3077  continue;
3078  }
3079  /* Response is not required anymore for this connection. */
3080  if (NULL != resp_clr)
3081  MHD_destroy_response (resp_clr);
3082  continue;
3083  }
3084 #endif /* UPGRADE_SUPPORT */
3085  if (MHD_NO != socket_flush_possible (connection))
3086  socket_start_extra_buffering (connection);
3087  else
3088  socket_start_normal_buffering (connection);
3089 
3090  if (connection->have_chunked_upload)
3092  else
3094  continue;
3096  /* nothing to do here */
3097  break;
3099  if (NULL != connection->response->crc)
3100  MHD_mutex_lock_chk_ (&connection->response->mutex);
3101  if (0 == connection->response->total_size)
3102  {
3103  if (NULL != connection->response->crc)
3104  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3105  connection->state = MHD_CONNECTION_BODY_SENT;
3106  continue;
3107  }
3108  if (MHD_YES == try_ready_normal_body (connection))
3109  {
3110  if (NULL != connection->response->crc)
3111  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3113  /* Buffering for flushable socket was already enabled*/
3114  if (MHD_NO == socket_flush_possible (connection))
3115  socket_start_no_buffering (connection);
3116  break;
3117  }
3118  /* mutex was already unlocked by "try_ready_normal_body */
3119  /* not ready, no socket action */
3120  break;
3122  /* nothing to do here */
3123  break;
3125  if (NULL != connection->response->crc)
3126  MHD_mutex_lock_chk_ (&connection->response->mutex);
3127  if ( (0 == connection->response->total_size) ||
3128  (connection->response_write_position ==
3129  connection->response->total_size) )
3130  {
3131  if (NULL != connection->response->crc)
3132  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3133  connection->state = MHD_CONNECTION_BODY_SENT;
3134  continue;
3135  }
3136  if (MHD_YES == try_ready_chunked_body (connection))
3137  {
3138  if (NULL != connection->response->crc)
3139  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3141  /* Buffering for flushable socket was already enabled */
3142  if (MHD_NO == socket_flush_possible (connection))
3143  socket_start_no_buffering (connection);
3144  continue;
3145  }
3146  if (NULL != connection->response->crc)
3147  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3148  break;
3150  if (MHD_NO == build_header_response (connection))
3151  {
3152  /* oops - close! */
3153  CONNECTION_CLOSE_ERROR (connection,
3154  _("Closing connection (failed to create response header)\n"));
3155  continue;
3156  }
3157  if ( (! connection->have_chunked_upload) ||
3158  (connection->write_buffer_send_offset ==
3159  connection->write_buffer_append_offset) )
3160  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3161  else
3162  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3163  continue;
3165  /* no default action */
3166  break;
3168  if (MHD_HTTP_PROCESSING == connection->responseCode)
3169  {
3170  /* After this type of response, we allow sending another! */
3172  MHD_destroy_response (connection->response);
3173  connection->response = NULL;
3174  /* FIXME: maybe partially reset memory pool? */
3175  continue;
3176  }
3177  if (MHD_NO != socket_flush_possible (connection))
3178  socket_start_no_buffering_flush (connection);
3179  else
3180  socket_start_normal_buffering (connection);
3181 
3182  end =
3183  MHD_get_response_header (connection->response,
3185  client_close = ( (NULL != end) &&
3187  "close")));
3188  MHD_destroy_response (connection->response);
3189  connection->response = NULL;
3190  if ( (NULL != daemon->notify_completed) &&
3191  (connection->client_aware) )
3192  {
3193  connection->client_aware = false;
3194  daemon->notify_completed (daemon->notify_completed_cls,
3195  connection,
3196  &connection->client_context,
3198  }
3199  end =
3200  MHD_lookup_connection_value (connection,
3203  if ( (connection->read_closed) ||
3204  (client_close) ||
3205  ( (NULL != end) &&
3207  "close")) ) )
3208  {
3209  connection->read_closed = true;
3210  connection->read_buffer_offset = 0;
3211  }
3212  if ( ( (connection->read_closed) &&
3213  (0 == connection->read_buffer_offset) ) ||
3214  (MHD_NO == keepalive_possible (connection) ) )
3215  {
3216  /* have to close for some reason */
3217  MHD_connection_close_ (connection,
3219  MHD_pool_destroy (connection->pool);
3220  connection->pool = NULL;
3221  connection->read_buffer = NULL;
3222  connection->read_buffer_size = 0;
3223  connection->read_buffer_offset = 0;
3224  }
3225  else
3226  {
3227  /* can try to keep-alive */
3228  if (MHD_NO != socket_flush_possible (connection))
3229  socket_start_normal_buffering (connection);
3230  connection->version = NULL;
3231  connection->state = MHD_CONNECTION_INIT;
3232  /* Reset the read buffer to the starting size,
3233  preserving the bytes we have already read. */
3234  connection->read_buffer
3235  = MHD_pool_reset (connection->pool,
3236  connection->read_buffer,
3237  connection->read_buffer_offset,
3238  connection->daemon->pool_size / 2);
3239  connection->read_buffer_size
3240  = connection->daemon->pool_size / 2;
3241  }
3242  connection->client_aware = false;
3243  connection->client_context = NULL;
3244  connection->continue_message_write_offset = 0;
3245  connection->responseCode = 0;
3246  connection->headers_received = NULL;
3247  connection->headers_received_tail = NULL;
3248  connection->response_write_position = 0;
3249  connection->have_chunked_upload = false;
3250  connection->method = NULL;
3251  connection->url = NULL;
3252  connection->write_buffer = NULL;
3253  connection->write_buffer_size = 0;
3254  connection->write_buffer_send_offset = 0;
3255  connection->write_buffer_append_offset = 0;
3256  continue;
3257  case MHD_CONNECTION_CLOSED:
3258  cleanup_connection (connection);
3259  return MHD_NO;
3260 #ifdef UPGRADE_SUPPORT
3261  case MHD_CONNECTION_UPGRADE:
3262  connection->in_idle = false;
3263  return MHD_YES; /* keep open */
3264 #endif /* UPGRADE_SUPPORT */
3265  default:
3266  EXTRA_CHECK (0);
3267  break;
3268  }
3269  break;
3270  }
3271  if (! connection->suspended)
3272  {
3273  time_t timeout;
3274  timeout = connection->connection_timeout;
3275  if ( (0 != timeout) &&
3276  (timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
3277  {
3278  MHD_connection_close_ (connection,
3280  connection->in_idle = false;
3281  return MHD_YES;
3282  }
3283  }
3285  ret = MHD_YES;
3286 #ifdef EPOLL_SUPPORT
3287  if ( (! connection->suspended) &&
3288  (0 != (daemon->options & MHD_USE_EPOLL)) )
3289  {
3290  ret = MHD_connection_epoll_update_ (connection);
3291  }
3292 #endif /* EPOLL_SUPPORT */
3293  connection->in_idle = false;
3294  return ret;
3295 }
3296 
3297 
3298 #ifdef EPOLL_SUPPORT
3299 
3307 int
3308 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3309 {
3310  struct MHD_Daemon *daemon = connection->daemon;
3311 
3312  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3313  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3314  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3315  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3316  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3317  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3318  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3319  {
3320  /* add to epoll set */
3321  struct epoll_event event;
3322 
3323  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3324  event.data.ptr = connection;
3325  if (0 != epoll_ctl (daemon->epoll_fd,
3326  EPOLL_CTL_ADD,
3327  connection->socket_fd,
3328  &event))
3329  {
3330 #ifdef HAVE_MESSAGES
3331  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3332  MHD_DLOG (daemon,
3333  _("Call to epoll_ctl failed: %s\n"),
3335 #endif
3336  connection->state = MHD_CONNECTION_CLOSED;
3337  cleanup_connection (connection);
3338  return MHD_NO;
3339  }
3340  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3341  }
3342  return MHD_YES;
3343 }
3344 #endif
3345 
3346 
3352 void
3354 {
3358 }
3359 
3360 
3371 const union MHD_ConnectionInfo *
3373  enum MHD_ConnectionInfoType info_type,
3374  ...)
3375 {
3376  switch (info_type)
3377  {
3378 #ifdef HTTPS_SUPPORT
3380  if (NULL == connection->tls_session)
3381  return NULL;
3382  connection->cipher = gnutls_cipher_get (connection->tls_session);
3383  return (const union MHD_ConnectionInfo *) &connection->cipher;
3385  if (NULL == connection->tls_session)
3386  return NULL;
3387  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3388  return (const union MHD_ConnectionInfo *) &connection->protocol;
3390  if (NULL == connection->tls_session)
3391  return NULL;
3392  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3393 #endif /* HTTPS_SUPPORT */
3395  return (const union MHD_ConnectionInfo *) &connection->addr;
3397  return (const union MHD_ConnectionInfo *) &connection->daemon;
3399  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3401  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3403  return (const union MHD_ConnectionInfo *) &connection->suspended;
3405  connection->connection_timeout_dummy = (unsigned int)connection->connection_timeout;
3406  return (const union MHD_ConnectionInfo *) &connection->connection_timeout_dummy;
3408  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3409  (MHD_CONNECTION_CLOSED == connection->state) ||
3410  (MHD_CONNECTION_IN_CLEANUP == connection->state) )
3411  return NULL; /* invalid, too early! */
3412  return (const union MHD_ConnectionInfo *) &connection->header_size;
3413  default:
3414  return NULL;
3415  }
3416 }
3417 
3418 
3428 int
3430  enum MHD_CONNECTION_OPTION option,
3431  ...)
3432 {
3433  va_list ap;
3434  struct MHD_Daemon *daemon;
3435 
3436  daemon = connection->daemon;
3437  switch (option)
3438  {
3439  case MHD_CONNECTION_OPTION_TIMEOUT:
3440  if (0 == connection->connection_timeout)
3441  connection->last_activity = MHD_monotonic_sec_counter();
3442 
3444  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3445  (! connection->suspended) )
3446  {
3447  if (connection->connection_timeout == daemon->connection_timeout)
3449  daemon->normal_timeout_tail,
3450  connection);
3451  else
3453  daemon->manual_timeout_tail,
3454  connection);
3455  }
3456  va_start (ap, option);
3457  connection->connection_timeout = va_arg (ap,
3458  unsigned int);
3459  va_end (ap);
3460  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3461  (! connection->suspended) )
3462  {
3463  if (connection->connection_timeout == daemon->connection_timeout)
3465  daemon->normal_timeout_tail,
3466  connection);
3467  else
3469  daemon->manual_timeout_tail,
3470  connection);
3471  }
3473  return MHD_YES;
3474  default:
3475  return MHD_NO;
3476  }
3477 }
3478 
3479 
3491 int
3493  unsigned int status_code,
3494  struct MHD_Response *response)
3495 {
3496 #ifdef UPGRADE_SUPPORT
3497  struct MHD_Daemon *daemon;
3498 #endif /* UPGRADE_SUPPORT */
3499 
3500  if ( (NULL == connection) ||
3501  (NULL == response) ||
3502  (NULL != connection->response) ||
3503  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3504  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3505  return MHD_NO;
3506 #ifdef UPGRADE_SUPPORT
3507  daemon = connection->daemon;
3508  if ( (NULL != response->upgrade_handler) &&
3509  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3510  {
3511 #ifdef HAVE_MESSAGES
3512  MHD_DLOG (daemon,
3513  _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
3514 #endif
3515  return MHD_NO;
3516  }
3517  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
3518  (NULL != response->upgrade_handler) )
3519  {
3520 #ifdef HAVE_MESSAGES
3521  MHD_DLOG (daemon,
3522  _("Application used invalid status code for 'upgrade' response!\n"));
3523 #endif
3524  return MHD_NO;
3525  }
3526 #endif /* UPGRADE_SUPPORT */
3527  MHD_increment_response_rc (response);
3528  connection->response = response;
3529  connection->responseCode = status_code;
3530 #if LINUX
3531  if ( (response->fd == -1) ||
3532  (0 != (connection->daemon->options & MHD_USE_TLS)) )
3533  connection->resp_sender = MHD_resp_sender_std;
3534  else
3535  connection->resp_sender = MHD_resp_sender_sendfile;
3536 #endif /* LINUX */
3537 
3538  if ( ( (NULL != connection->method) &&
3539  (MHD_str_equal_caseless_ (connection->method,
3540  MHD_HTTP_METHOD_HEAD)) ) ||
3541  (MHD_HTTP_OK > status_code) ||
3542  (MHD_HTTP_NO_CONTENT == status_code) ||
3543  (MHD_HTTP_NOT_MODIFIED == status_code) )
3544  {
3545  /* if this is a "HEAD" request, or a status code for
3546  which a body is not allowed, pretend that we
3547  have already sent the full message body. */
3548  connection->response_write_position = response->total_size;
3549  }
3550  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
3551  (NULL != connection->method) &&
3552  ( (MHD_str_equal_caseless_ (connection->method,
3554  (MHD_str_equal_caseless_ (connection->method,
3555  MHD_HTTP_METHOD_PUT))) )
3556  {
3557  /* response was queued "early", refuse to read body / footers or
3558  further requests! */
3559  connection->read_closed = true;
3560  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3561  }
3562  if (! connection->in_idle)
3563  (void) MHD_connection_handle_idle (connection);
3564  return MHD_YES;
3565 }
3566 
3567 
3568 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2202
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1988
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1616
void * unescape_callback_cls
Definition: internal.h:1365
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:454
uint64_t total_size
Definition: internal.h:340
bool have_chunked_upload
Definition: internal.h:879
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:674
uint64_t current_chunk_offset
Definition: internal.h:893
#define DLL_insert(head, tail, element)
Definition: internal.h:1690
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:748
void * socket_context
Definition: internal.h:659
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1373
enum MHD_CONNECTION_STATE state
Definition: internal.h:859
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:740
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:767
#define NULL
Definition: reason_phrase.c:31
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:142
#define HTTP_100_CONTINUE
Definition: connection.c:47
#define MHD_ICY_FLAG
Definition: microhttpd.h:408
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:864
int MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2532
time_t connection_timeout
Definition: internal.h:1531
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:1585
Methods for managing connections.
char * version
Definition: internal.h:676
#define INTERNAL_ERROR
Definition: connection.c:97
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:464
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:541
#define MHD_YES
Definition: microhttpd.h:134
const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:235
struct MHD_Response * response
Definition: internal.h:632
char * colon
Definition: internal.h:706
#define REQUEST_LACKS_HOST
Definition: connection.c:72
char * write_buffer
Definition: internal.h:689
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1293
Header for platform missing functions.
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:323
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:503
MHD_RequestTerminationCode
Definition: microhttpd.h:1570
size_t data_size
Definition: internal.h:357
static int do_read(struct MHD_Connection *connection)
Definition: connection.c:2079
#define EXTRA_CHECK(a)
Definition: internal.h:1678
enum MHD_ValueKind kind
Definition: internal.h:275
struct MHD_HTTP_Header * first_header
Definition: internal.h:291
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1322
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1211
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:188
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:1825
uint64_t remaining_upload_size
Definition: internal.h:760
unsigned int responseCode
Definition: internal.h:870
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:398
char * value
Definition: internal.h:269
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:2723
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2424
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1355
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t header_size
Definition: internal.h:754
struct MHD_Daemon * daemon
Definition: internal.h:617
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:911
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1301
struct MHD_Connection * cleanup_head
Definition: internal.h:1241
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:568
#define MHD_SCKT_ERR_IS_REMOTE_DISCNN_(err)
Definition: mhd_sockets.h:656
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:637
#define XDLL_remove(head, tail, element)
Definition: internal.h:1756
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
bool client_aware
Definition: internal.h:810
#define XDLL_insert(head, tail, element)
Definition: internal.h:1735
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:862
int strict_for_client
Definition: internal.h:1552
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:349
struct MHD_Connection * cleanup_tail
Definition: internal.h:1246
Header for platform-independent inter-thread communication.
int MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2462
#define MHD_STATICSTR_LEN_(macro)
Definition: internal.h:123
size_t data_buffer_size
Definition: internal.h:362
size_t write_buffer_send_offset
Definition: internal.h:742
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:233
void * mhd_panic_cls
Definition: daemon.c:154
size_t read_buffer_size
Definition: internal.h:726
struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:622
void * client_context
Definition: internal.h:650
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1308
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
const char * url
Definition: internal.h:670
size_t continue_message_write_offset
Definition: internal.h:781
#define REQUEST_MALFORMED
Definition: connection.c:85
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:817
char * method
Definition: internal.h:664
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
enum MHD_FLAG options
Definition: internal.h:1542
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:311
LogCallback uri_log_callback
Definition: internal.h:1350
static int socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:209
bool in_cleanup
Definition: internal.h:847
void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1020
#define MHD_HTTP_OK
Definition: microhttpd.h:307
time_t connection_timeout
Definition: internal.h:798
int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3429
const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:450
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1054
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:899
char * last
Definition: internal.h:697
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1286
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:913
MHD_ValueKind
Definition: microhttpd.h:1524
char * read_buffer
Definition: internal.h:683
const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3372
ReceiveCallback recv_cls
Definition: internal.h:916
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:478
size_t write_buffer_size
Definition: internal.h:737
MHD_ConnectionInfoType
Definition: microhttpd.h:1718
uint64_t data_start
Definition: internal.h:346
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:735
internal shared structures
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:369
UnescapeCallback unescape_callback
Definition: internal.h:1360
int MHD_tls_connection_shutdown(struct MHD_Connection *connection)
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:973
int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3492
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:905
unsigned int connection_timeout_dummy
Definition: internal.h:803
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:329
struct MHD_Connection * connections_head
Definition: internal.h:1221
size_t pool_size
Definition: internal.h:1398
char * header
Definition: internal.h:264
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2173
struct MHD_itc_ itc
Definition: internal.h:1478
time_t last_activity
Definition: internal.h:792
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2794
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:525
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2261
enum MHD_ResponseFlags flags
Definition: internal.h:378
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:458
struct MemoryPool * pool
Definition: internal.h:642
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:120
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:754
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2343
#define MHD_PANIC(msg)
Definition: internal.h:63
time_t MHD_monotonic_sec_counter(void)
Header for string manipulating helpers.
size_t write_buffer_append_offset
Definition: internal.h:748
struct MHD_HTTP_Header * next
Definition: internal.h:259
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1325
static int socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:150
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:440
bool read_closed
Definition: internal.h:830
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3353
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:760
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:1711
void * notify_completed_cls
Definition: internal.h:1330
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:1860
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:734
TransmitCallback send_cls
Definition: internal.h:921
#define EDLL_remove(head, tail, element)
Definition: internal.h:1798
int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:356
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:377
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:309
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:1730
void * crc_cls
Definition: internal.h:303
struct sockaddr * addr
Definition: internal.h:712
MHD_mutex_ mutex
Definition: internal.h:335
MHD_PanicCallback mhd_panic
Definition: daemon.c:149
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1236
static int socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:292
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
bool suspended
Definition: internal.h:965
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:446
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:305
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
static int socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:132
char * data
Definition: internal.h:297
#define MHD_MIN(a, b)
Definition: internal.h:88
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:262
static int do_write(struct MHD_Connection *connection)
Definition: connection.c:2129
size_t read_buffer_offset
Definition: internal.h:732
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1526
void * default_handler_cls
Definition: internal.h:1216
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1483
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:598
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1429
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:657
uint64_t current_chunk_size
Definition: internal.h:887
Header for platform-independent locks abstraction.
struct MHD_HTTP_Header * headers_received
Definition: internal.h:622
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:304
struct MHD_Connection * connections_tail
Definition: internal.h:1226
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:502
#define MHD_BUF_INC_SIZE
Definition: internal.h:98
#define SIZE_MAX
Definition: mhd_limits.h:83
int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:408
#define REQUEST_TOO_BIG
Definition: connection.c:59
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:627
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1005
size_t pool_increment
Definition: internal.h:1403
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:758
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:1231
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...