GNU libmicrohttpd  0.9.62
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 "mhd_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 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
36 #include "mhd_locks.h"
37 #endif
38 #include "mhd_sockets.h"
39 #include "mhd_compat.h"
40 #include "mhd_itc.h"
41 #ifdef MHD_LINUX_SOLARIS_SENDFILE
42 #include <sys/sendfile.h>
43 #endif /* MHD_LINUX_SOLARIS_SENDFILE */
44 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <sys/uio.h>
48 #endif /* HAVE_FREEBSD_SENDFILE || HAVE_DARWIN_SENDFILE */
49 #ifdef HTTPS_SUPPORT
50 #include "connection_https.h"
51 #endif /* HTTPS_SUPPORT */
52 
53 
57 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
58 
66 #ifdef HAVE_MESSAGES
67 #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>"
68 #else
69 #define REQUEST_TOO_BIG ""
70 #endif
71 
79 #ifdef HAVE_MESSAGES
80 #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>"
81 #else
82 #define REQUEST_LACKS_HOST ""
83 #endif
84 
92 #ifdef HAVE_MESSAGES
93 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
94 #else
95 #define REQUEST_MALFORMED ""
96 #endif
97 
104 #ifdef HAVE_MESSAGES
105 #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>"
106 #else
107 #define INTERNAL_ERROR ""
108 #endif
109 
114 #define DEBUG_CLOSE MHD_NO
115 
119 #define DEBUG_SEND_DATA MHD_NO
120 
121 
125 #define MHD_SENFILE_CHUNK_ (0x20000)
126 
130 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
131 
132 #ifdef HAVE_FREEBSD_SENDFILE
133 #ifdef SF_FLAGS
134 
137 static int freebsd_sendfile_flags_;
138 
142 static int freebsd_sendfile_flags_thd_p_c_;
143 #endif /* SF_FLAGS */
144 
147 void
148 MHD_conn_init_static_ (void)
149 {
150 /* FreeBSD 11 and later allow to specify read-ahead size
151  * and handles SF_NODISKIO differently.
152  * SF_FLAGS defined only on FreeBSD 11 and later. */
153 #ifdef SF_FLAGS
154  long sys_page_size = sysconf (_SC_PAGESIZE);
155  if (0 > sys_page_size)
156  { /* Failed to get page size. */
157  freebsd_sendfile_flags_ = SF_NODISKIO;
158  freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
159  }
160  else
161  {
162  freebsd_sendfile_flags_ =
163  SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
164  freebsd_sendfile_flags_thd_p_c_ =
165  SF_FLAGS((uint16_t)(MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size), SF_NODISKIO);
166  }
167 #endif /* SF_FLAGS */
168 }
169 #endif /* HAVE_FREEBSD_SENDFILE */
170 
179 static ssize_t
180 recv_param_adapter (struct MHD_Connection *connection,
181  void *other,
182  size_t i)
183 {
184  ssize_t ret;
185 
186  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
187  (MHD_CONNECTION_CLOSED == connection->state) )
188  {
189  return MHD_ERR_NOTCONN_;
190  }
191  if (i > MHD_SCKT_SEND_MAX_SIZE_)
192  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
193 
194  ret = MHD_recv_ (connection->socket_fd,
195  other,
196  i);
197  if (0 > ret)
198  {
199  const int err = MHD_socket_get_error_ ();
200  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
201  {
202 #ifdef EPOLL_SUPPORT
203  /* Got EAGAIN --- no longer read-ready */
204  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
205 #endif /* EPOLL_SUPPORT */
206  return MHD_ERR_AGAIN_;
207  }
208  if (MHD_SCKT_ERR_IS_EINTR_ (err))
209  return MHD_ERR_AGAIN_;
211  return MHD_ERR_CONNRESET_;
212  /* Treat any other error as hard error. */
213  return MHD_ERR_NOTCONN_;
214  }
215 #ifdef EPOLL_SUPPORT
216  else if (i > (size_t)ret)
217  connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
218 #endif /* EPOLL_SUPPORT */
219  return ret;
220 }
221 
222 
232 static ssize_t
233 send_param_adapter (struct MHD_Connection *connection,
234  const void *other,
235  size_t i)
236 {
237  ssize_t ret;
238 
239  if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
240  (MHD_CONNECTION_CLOSED == connection->state) )
241  {
242  return MHD_ERR_NOTCONN_;
243  }
244  if (i > MHD_SCKT_SEND_MAX_SIZE_)
245  i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
246 
247  ret = MHD_send_ (connection->socket_fd,
248  other,
249  i);
250  if (0 > ret)
251  {
252  const int err = MHD_socket_get_error_();
253 
254  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
255  {
256 #ifdef EPOLL_SUPPORT
257  /* EAGAIN --- no longer write-ready */
258  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
259 #endif /* EPOLL_SUPPORT */
260  return MHD_ERR_AGAIN_;
261  }
262  if (MHD_SCKT_ERR_IS_EINTR_ (err))
263  return MHD_ERR_AGAIN_;
265  return MHD_ERR_CONNRESET_;
266  /* Treat any other error as hard error. */
267  return MHD_ERR_NOTCONN_;
268  }
269 #ifdef EPOLL_SUPPORT
270  else if (i > (size_t)ret)
271  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
272 #endif /* EPOLL_SUPPORT */
273  return ret;
274 }
275 
276 
277 #if defined(_MHD_HAVE_SENDFILE)
278 
284 static ssize_t
285 sendfile_adapter (struct MHD_Connection *connection)
286 {
287  ssize_t ret;
288  const int file_fd = connection->response->fd;
289  uint64_t left;
290  uint64_t offsetu64;
291 #ifndef HAVE_SENDFILE64
292  const uint64_t max_off_t = (uint64_t)OFF_T_MAX;
293 #else /* HAVE_SENDFILE64 */
294  const uint64_t max_off_t = (uint64_t)OFF64_T_MAX;
295 #endif /* HAVE_SENDFILE64 */
296 #ifdef MHD_LINUX_SOLARIS_SENDFILE
297 #ifndef HAVE_SENDFILE64
298  off_t offset;
299 #else /* HAVE_SENDFILE64 */
300  off64_t offset;
301 #endif /* HAVE_SENDFILE64 */
302 #endif /* MHD_LINUX_SOLARIS_SENDFILE */
303 #ifdef HAVE_FREEBSD_SENDFILE
304  off_t sent_bytes;
305  int flags = 0;
306 #endif
307 #ifdef HAVE_DARWIN_SENDFILE
308  off_t len;
309 #endif /* HAVE_DARWIN_SENDFILE */
310  const bool used_thr_p_c = (0 != (connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION));
311  const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ : MHD_SENFILE_CHUNK_;
312  size_t send_size = 0;
313  mhd_assert (MHD_resp_sender_sendfile == connection->resp_sender);
314 
315  offsetu64 = connection->response_write_position + connection->response->fd_off;
316  left = connection->response->total_size - connection->response_write_position;
317  /* Do not allow system to stick sending on single fast connection:
318  * use 128KiB chunks (2MiB for thread-per-connection). */
319  send_size = (left > chunk_size) ? chunk_size : (size_t) left;
320  if (max_off_t < offsetu64)
321  { /* Retry to send with standard 'send()'. */
322  connection->resp_sender = MHD_resp_sender_std;
323  return MHD_ERR_AGAIN_;
324  }
325 #ifdef MHD_LINUX_SOLARIS_SENDFILE
326 #ifndef HAVE_SENDFILE64
327  offset = (off_t) offsetu64;
328  ret = sendfile (connection->socket_fd,
329  file_fd,
330  &offset,
331  send_size);
332 #else /* HAVE_SENDFILE64 */
333  offset = (off64_t) offsetu64;
334  ret = sendfile64 (connection->socket_fd,
335  file_fd,
336  &offset,
337  send_size);
338 #endif /* HAVE_SENDFILE64 */
339  if (0 > ret)
340  {
341  const int err = MHD_socket_get_error_();
342  if (MHD_SCKT_ERR_IS_EAGAIN_(err))
343  {
344 #ifdef EPOLL_SUPPORT
345  /* EAGAIN --- no longer write-ready */
346  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
347 #endif /* EPOLL_SUPPORT */
348  return MHD_ERR_AGAIN_;
349  }
350  if (MHD_SCKT_ERR_IS_EINTR_ (err))
351  return MHD_ERR_AGAIN_;
352 #ifdef HAVE_LINUX_SENDFILE
353  if (MHD_SCKT_ERR_IS_(err,
355  return MHD_ERR_BADF_;
356  /* sendfile() failed with EINVAL if mmap()-like operations are not
357  supported for FD or other 'unusual' errors occurred, so we should try
358  to fall back to 'SEND'; see also this thread for info on
359  odd libc/Linux behavior with sendfile:
360  http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
361  connection->resp_sender = MHD_resp_sender_std;
362  return MHD_ERR_AGAIN_;
363 #else /* HAVE_SOLARIS_SENDFILE */
364  if ( (EAFNOSUPPORT == err) ||
365  (EINVAL == err) ||
366  (EOPNOTSUPP == err) )
367  { /* Retry with standard file reader. */
368  connection->resp_sender = MHD_resp_sender_std;
369  return MHD_ERR_AGAIN_;
370  }
371  if ( (ENOTCONN == err) ||
372  (EPIPE == err) )
373  {
374  return MHD_ERR_CONNRESET_;
375  }
376  return MHD_ERR_BADF_; /* Fail hard */
377 #endif /* HAVE_SOLARIS_SENDFILE */
378  }
379 #ifdef EPOLL_SUPPORT
380  else if (send_size > (size_t)ret)
381  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
382 #endif /* EPOLL_SUPPORT */
383 #elif defined(HAVE_FREEBSD_SENDFILE)
384 #ifdef SF_FLAGS
385  flags = used_thr_p_c ?
386  freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
387 #endif /* SF_FLAGS */
388  if (0 != sendfile (file_fd,
389  connection->socket_fd,
390  (off_t) offsetu64,
391  send_size,
392  NULL,
393  &sent_bytes,
394  flags))
395  {
396  const int err = MHD_socket_get_error_();
397  if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
398  MHD_SCKT_ERR_IS_EINTR_(err) ||
399  EBUSY == err)
400  {
401  mhd_assert (SSIZE_MAX >= sent_bytes);
402  if (0 != sent_bytes)
403  return (ssize_t)sent_bytes;
404 
405  return MHD_ERR_AGAIN_;
406  }
407  /* Some unrecoverable error. Possibly file FD is not suitable
408  * for sendfile(). Retry with standard send(). */
409  connection->resp_sender = MHD_resp_sender_std;
410  return MHD_ERR_AGAIN_;
411  }
412  mhd_assert (0 < sent_bytes);
413  mhd_assert (SSIZE_MAX >= sent_bytes);
414  ret = (ssize_t)sent_bytes;
415 #elif defined(HAVE_DARWIN_SENDFILE)
416  len = (off_t)send_size; /* chunk always fit */
417  if (0 != sendfile (file_fd,
418  connection->socket_fd,
419  (off_t) offsetu64,
420  &len,
421  NULL,
422  0))
423  {
424  const int err = MHD_socket_get_error_();
425  if (MHD_SCKT_ERR_IS_EAGAIN_(err) ||
427  {
428  mhd_assert (0 <= len);
429  mhd_assert (SSIZE_MAX >= len);
430  mhd_assert (send_size >= (size_t)len);
431  if (0 != len)
432  return (ssize_t)len;
433 
434  return MHD_ERR_AGAIN_;
435  }
436  if (ENOTCONN == err ||
437  EPIPE == err)
438  return MHD_ERR_CONNRESET_;
439  if (ENOTSUP == err ||
440  EOPNOTSUPP == err)
441  { /* This file FD is not suitable for sendfile().
442  * Retry with standard send(). */
443  connection->resp_sender = MHD_resp_sender_std;
444  return MHD_ERR_AGAIN_;
445  }
446  return MHD_ERR_BADF_; /* Return hard error. */
447  }
448  mhd_assert (0 <= len);
449  mhd_assert (SSIZE_MAX >= len);
450  mhd_assert (send_size >= (size_t)len);
451  ret = (ssize_t)len;
452 #endif /* HAVE_FREEBSD_SENDFILE */
453  return ret;
454 }
455 #endif /* _MHD_HAVE_SENDFILE */
456 
457 
477 static int
479 {
480  (void)connection; /* Mute compiler warning. */
481 #if defined(TCP_CORK) || defined(TCP_PUSH)
482  return MHD_YES;
483 #else /* !TCP_CORK && !TCP_PUSH */
484  return MHD_NO;
485 #endif /* !TCP_CORK && !TCP_PUSH */
486 }
487 
488 
496 static int
498 {
499  int res = MHD_NO;
500 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
501  const MHD_SCKT_OPT_BOOL_ on_val = 1;
502 #if defined(TCP_NODELAY)
503  const MHD_SCKT_OPT_BOOL_ off_val = 0;
504 #endif /* TCP_NODELAY */
505  (void) connection; /* mute compiler warning, assertion below
506  may be compiled out! */
507  mhd_assert(NULL != connection);
508 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
509  /* Buffer data before sending */
510  res = (0 == setsockopt (connection->socket_fd,
511  IPPROTO_TCP,
512  TCP_NOPUSH,
513  (const void *) &on_val,
514  sizeof (on_val)))
515  ? MHD_YES : MHD_NO;
516 #if defined(TCP_NODELAY)
517  /* Enable Nagle's algorithm */
518  /* TCP_NODELAY may interfere with TCP_NOPUSH */
519  res &= (0 == setsockopt (connection->socket_fd,
520  IPPROTO_TCP,
521  TCP_NODELAY,
522  (const void *) &off_val,
523  sizeof (off_val)))
524  ? MHD_YES : MHD_NO;
525 #endif /* TCP_NODELAY */
526 #else /* TCP_CORK */
527 #if defined(TCP_NODELAY)
528  /* Enable Nagle's algorithm */
529  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
530  solely on TCP_CORK result, so ignoring return code here. */
531  (void) setsockopt (connection->socket_fd,
532  IPPROTO_TCP,
533  TCP_NODELAY,
534  (const void *) &off_val,
535  sizeof (off_val));
536 #endif /* TCP_NODELAY */
537  /* Send only full packets */
538  res = (0 == setsockopt (connection->socket_fd,
539  IPPROTO_TCP,
540  TCP_CORK,
541  (const void *) &on_val,
542  sizeof (on_val)))
543  ? MHD_YES : MHD_NO;
544 #endif /* TCP_CORK */
545 #endif /* TCP_CORK || TCP_NOPUSH */
546  return res;
547 }
548 
549 
556 static int
558 {
559 #if defined(TCP_NODELAY)
560  int res = MHD_YES;
561  const MHD_SCKT_OPT_BOOL_ on_val = 1;
562 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
563  const MHD_SCKT_OPT_BOOL_ off_val = 0;
564 #endif /* TCP_CORK || TCP_NOPUSH */
565 
566  (void)connection; /* Mute compiler warning. */
567  mhd_assert(NULL != connection);
568 #if defined(TCP_CORK)
569  /* Allow partial packets */
570  res &= (0 == setsockopt (connection->socket_fd,
571  IPPROTO_TCP,
572  TCP_CORK,
573  (const void *) &off_val,
574  sizeof (off_val)))
575  ? MHD_YES : MHD_NO;
576 #endif /* TCP_CORK */
577 #if defined(TCP_NODELAY)
578  /* Disable Nagle's algorithm for sending packets without delay */
579  res &= (0 == setsockopt (connection->socket_fd,
580  IPPROTO_TCP,
581  TCP_NODELAY,
582  (const void *) &on_val,
583  sizeof (on_val)))
584  ? MHD_YES : MHD_NO;
585 #endif /* TCP_NODELAY */
586 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
587  /* Disable extra buffering */
588  res &= (0 == setsockopt (connection->socket_fd,
589  IPPROTO_TCP,
590  TCP_NOPUSH,
591  (const void *) &off_val,
592  sizeof (off_val)))
593  ? MHD_YES : MHD_NO;
594 #endif /* TCP_NOPUSH && !TCP_CORK */
595  return res;
596 #else /* !TCP_NODELAY */
597  return MHD_NO;
598 #endif /* !TCP_NODELAY */
599 }
600 
601 
609 static int
611 {
612  int res = MHD_YES;
613 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
614  const int dummy = 0;
615 #endif /* !TCP_CORK */
616 
617  if (NULL == connection)
618  return MHD_NO;
619  res = socket_start_no_buffering (connection);
620 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
621  /* Force flush data with zero send otherwise Darwin and some BSD systems
622  will add 5 seconds delay. Not required with TCP_CORK as switching off
623  TCP_CORK always flushes socket buffer. */
624  res &= (0 <= MHD_send_ (connection->socket_fd,
625  &dummy,
626  0))
627  ? MHD_YES : MHD_NO;
628 #endif /* TCP_NOPUSH && !TCP_CORK*/
629  return res;
630 }
631 
632 
639 static int
641 {
642 #if defined(TCP_NODELAY)
643  int res = MHD_YES;
644  const MHD_SCKT_OPT_BOOL_ off_val = 0;
645 #if defined(TCP_CORK)
646  MHD_SCKT_OPT_BOOL_ cork_val = 0;
647  socklen_t param_size = sizeof (cork_val);
648 #endif /* TCP_CORK */
649  mhd_assert(NULL != connection);
650 #if defined(TCP_CORK)
651  /* Allow partial packets */
652  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
653  so try to check current value of TCP_CORK to prevent unrequested flushing */
654  if ( (0 != getsockopt (connection->socket_fd,
655  IPPROTO_TCP,
656  TCP_CORK,
657  (void*)&cork_val,
658  &param_size)) ||
659  (0 != cork_val))
660  res &= (0 == setsockopt (connection->socket_fd,
661  IPPROTO_TCP,
662  TCP_CORK,
663  (const void *) &off_val,
664  sizeof (off_val)))
665  ? MHD_YES : MHD_NO;
666 #elif defined(TCP_NOPUSH)
667  /* Disable extra buffering */
668  /* No need to check current value as disabling TCP_NOPUSH will not flush partial
669  packet if TCP_NOPUSH wasn't enabled before */
670  res &= (0 == setsockopt (connection->socket_fd,
671  IPPROTO_TCP,
672  TCP_NOPUSH,
673  (const void *) &off_val,
674  sizeof (off_val)))
675  ? MHD_YES : MHD_NO;
676 #endif /* TCP_NOPUSH && !TCP_CORK */
677  /* Enable Nagle's algorithm for normal buffering */
678  res &= (0 == setsockopt (connection->socket_fd,
679  IPPROTO_TCP,
680  TCP_NODELAY,
681  (const void *) &off_val,
682  sizeof (off_val)))
683  ? MHD_YES : MHD_NO;
684  return res;
685 #else /* !TCP_NODELAY */
686  return MHD_NO;
687 #endif /* !TCP_NODELAY */
688 }
689 
690 
702 int
704  enum MHD_ValueKind kind,
705  MHD_KeyValueIterator iterator,
706  void *iterator_cls)
707 {
708  int ret;
709  struct MHD_HTTP_Header *pos;
710 
711  if (NULL == connection)
712  return -1;
713  ret = 0;
714  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
715  if (0 != (pos->kind & kind))
716  {
717  ret++;
718  if ( (NULL != iterator) &&
719  (MHD_YES != iterator (iterator_cls,
720  pos->kind,
721  pos->header,
722  pos->value)) )
723  return ret;
724  }
725  return ret;
726 }
727 
728 
754 int
756  enum MHD_ValueKind kind,
757  const char *key,
758  const char *value)
759 {
760  struct MHD_HTTP_Header *pos;
761 
762  pos = MHD_pool_allocate (connection->pool,
763  sizeof (struct MHD_HTTP_Header),
764  MHD_YES);
765  if (NULL == pos)
766  return MHD_NO;
767  pos->header = (char *) key;
768  pos->value = (char *) value;
769  pos->kind = kind;
770  pos->next = NULL;
771  /* append 'pos' to the linked list of headers */
772  if (NULL == connection->headers_received_tail)
773  {
774  connection->headers_received = pos;
775  connection->headers_received_tail = pos;
776  }
777  else
778  {
779  connection->headers_received_tail->next = pos;
780  connection->headers_received_tail = pos;
781  }
782  return MHD_YES;
783 }
784 
785 
796 const char *
798  enum MHD_ValueKind kind,
799  const char *key)
800 {
801  struct MHD_HTTP_Header *pos;
802 
803  if (NULL == connection)
804  return NULL;
805  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
806  if ((0 != (pos->kind & kind)) &&
807  ( (key == pos->header) ||
808  ( (NULL != pos->header) &&
809  (NULL != key) &&
811  pos->header)))))
812  return pos->value;
813  return NULL;
814 }
815 
816 
830 static bool
831 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
832  const char *header,
833  const char *token,
834  size_t token_len)
835 {
836  struct MHD_HTTP_Header *pos;
837 
838  if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0])
839  return false;
840  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
841  {
842  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
843  ( (header == pos->header) ||
844  (MHD_str_equal_caseless_(header,
845  pos->header)) ) &&
846  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
847  return true;
848  }
849  return false;
850 }
851 
852 
864 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
865  MHD_lookup_header_token_ci((c),(h),(tkn),MHD_STATICSTR_LEN_(tkn))
866 
867 
875 static int
876 need_100_continue (struct MHD_Connection *connection)
877 {
878  const char *expect;
879 
880  return ( (NULL == connection->response) &&
881  (NULL != connection->version) &&
882  (MHD_str_equal_caseless_(connection->version,
884  (NULL != (expect = MHD_lookup_connection_value (connection,
887  (MHD_str_equal_caseless_(expect,
888  "100-continue")) &&
889  (connection->continue_message_write_offset <
891 }
892 
893 
900 void
902 {
903  const struct MHD_Daemon *daemon = connection->daemon;
904 
905  connection->state = MHD_CONNECTION_CLOSED;
907  if (0 == (daemon->options & MHD_USE_TURBO))
908  {
909 #ifdef HTTPS_SUPPORT
910  /* For TLS connection use shutdown of TLS layer
911  * and do not shutdown TCP socket. This give more
912  * chances to send TLS closure data to remote side.
913  * Closure of TLS layer will be interpreted by
914  * remote side as end of transmission. */
915  if (0 != (daemon->options & MHD_USE_TLS))
916  {
917  if (! MHD_tls_connection_shutdown(connection))
918  shutdown (connection->socket_fd,
919  SHUT_WR);
920  }
921  else /* Combined with next 'shutdown()'. */
922 #endif /* HTTPS_SUPPORT */
923  shutdown (connection->socket_fd,
924  SHUT_WR);
925  }
926 }
927 
928 
938 void
940  enum MHD_RequestTerminationCode termination_code)
941 {
942  struct MHD_Daemon *daemon = connection->daemon;
943  struct MHD_Response *resp = connection->response;
944 
945  MHD_connection_mark_closed_ (connection);
946  if (NULL != resp)
947  {
948  connection->response = NULL;
949  MHD_destroy_response (resp);
950  }
951  if ( (NULL != daemon->notify_completed) &&
952  (connection->client_aware) )
953  daemon->notify_completed (daemon->notify_completed_cls,
954  connection,
955  &connection->client_context,
956  termination_code);
957  connection->client_aware = false;
958 }
959 
960 
961 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
962 
972 void
974 {
975  struct MHD_Daemon *daemon = connection->daemon;
976  struct MHD_UpgradeResponseHandle *urh = connection->urh;
977 
978  if (0 == (daemon->options & MHD_USE_TLS))
979  return; /* Nothing to do with non-TLS connection. */
980 
981  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
982  DLL_remove (daemon->urh_head,
983  daemon->urh_tail,
984  urh);
985 #if EPOLL_SUPPORT
986  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
987  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
988  EPOLL_CTL_DEL,
989  connection->socket_fd,
990  NULL)) )
991  {
992  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
993  }
994  if (urh->in_eready_list)
995  {
996  EDLL_remove (daemon->eready_urh_head,
997  daemon->eready_urh_tail,
998  urh);
999  urh->in_eready_list = false;
1000  }
1001 #endif /* EPOLL_SUPPORT */
1002  if (MHD_INVALID_SOCKET != urh->mhd.socket)
1003  {
1004 #if EPOLL_SUPPORT
1005  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
1006  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1007  EPOLL_CTL_DEL,
1008  urh->mhd.socket,
1009  NULL)) )
1010  {
1011  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
1012  }
1013 #endif /* EPOLL_SUPPORT */
1014  /* Reflect remote disconnect to application by breaking
1015  * socketpair connection. */
1016  shutdown (urh->mhd.socket, SHUT_RDWR);
1017  }
1018  /* Socketpair sockets will remain open as they will be
1019  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
1020  * closed by MHD_cleanup_upgraded_connection_() during
1021  * connection's final cleanup.
1022  */
1023 }
1024 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
1025 
1026 
1034 static void
1036  const char *emsg)
1037 {
1038 #ifdef HAVE_MESSAGES
1039  if (NULL != emsg)
1040  MHD_DLOG (connection->daemon,
1041  emsg);
1042 #else /* ! HAVE_MESSAGES */
1043  (void)emsg; /* Mute compiler warning. */
1044 #endif /* ! HAVE_MESSAGES */
1045  MHD_connection_close_ (connection,
1047 }
1048 
1049 
1054 #ifdef HAVE_MESSAGES
1055 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
1056 #else
1057 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
1058 #endif
1059 
1060 
1073 static int
1075 {
1076  ssize_t ret;
1077  struct MHD_Response *response;
1078 
1079  response = connection->response;
1080  if (NULL == response->crc)
1081  return MHD_YES;
1082  if ( (0 == response->total_size) ||
1083  (connection->response_write_position == response->total_size) )
1084  return MHD_YES; /* 0-byte response is always ready */
1085  if ( (response->data_start <=
1086  connection->response_write_position) &&
1087  (response->data_size + response->data_start >
1088  connection->response_write_position) )
1089  return MHD_YES; /* response already ready */
1090 #if defined(_MHD_HAVE_SENDFILE)
1091  if (MHD_resp_sender_sendfile == connection->resp_sender)
1092  {
1093  /* will use sendfile, no need to bother response crc */
1094  return MHD_YES;
1095  }
1096 #endif /* _MHD_HAVE_SENDFILE */
1097 
1098  ret = response->crc (response->crc_cls,
1099  connection->response_write_position,
1100  response->data,
1101  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
1102  response->total_size -
1103  connection->response_write_position));
1104  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1105  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
1106  {
1107  /* either error or http 1.0 transfer, close socket! */
1108  response->total_size = connection->response_write_position;
1109 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1110  MHD_mutex_unlock_chk_ (&response->mutex);
1111 #endif
1112  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
1113  MHD_connection_close_ (connection,
1115  else
1116  CONNECTION_CLOSE_ERROR (connection,
1117  _("Closing connection (application reported error generating data)\n"));
1118  return MHD_NO;
1119  }
1120  response->data_start = connection->response_write_position;
1121  response->data_size = ret;
1122  if (0 == ret)
1123  {
1125 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1126  MHD_mutex_unlock_chk_ (&response->mutex);
1127 #endif
1128  return MHD_NO;
1129  }
1130  return MHD_YES;
1131 }
1132 
1133 
1143 static int
1145 {
1146  ssize_t ret;
1147  char *buf;
1148  struct MHD_Response *response;
1149  size_t size;
1150  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
1151  int cblen;
1152 
1153  response = connection->response;
1154  if (NULL == response->crc)
1155  return MHD_YES;
1156  if (0 == connection->write_buffer_size)
1157  {
1158  size = MHD_MIN (connection->daemon->pool_size,
1159  2 * (0xFFFFFF + sizeof(cbuf) + 2));
1160  do
1161  {
1162  size /= 2;
1163  if (size < 128)
1164  {
1165 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1166  MHD_mutex_unlock_chk_ (&response->mutex);
1167 #endif
1168  /* not enough memory */
1169  CONNECTION_CLOSE_ERROR (connection,
1170  _("Closing connection (out of memory)\n"));
1171  return MHD_NO;
1172  }
1173  buf = MHD_pool_allocate (connection->pool,
1174  size,
1175  MHD_NO);
1176  }
1177  while (NULL == buf);
1178  connection->write_buffer_size = size;
1179  connection->write_buffer = buf;
1180  }
1181 
1182  if (0 == response->total_size)
1183  ret = 0; /* response must be empty, don't bother calling crc */
1184  else if ( (response->data_start <=
1185  connection->response_write_position) &&
1186  (response->data_start + response->data_size >
1187  connection->response_write_position) )
1188  {
1189  /* difference between response_write_position and data_start is less
1190  than data_size which is size_t type, no need to check for overflow */
1191  const size_t data_write_offset
1192  = (size_t)(connection->response_write_position - response->data_start);
1193  /* buffer already ready, use what is there for the chunk */
1194  ret = response->data_size - data_write_offset;
1195  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
1196  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1197  memcpy (&connection->write_buffer[sizeof (cbuf)],
1198  &response->data[data_write_offset],
1199  ret);
1200  }
1201  else
1202  {
1203  /* buffer not in range, try to fill it */
1204  ret = response->crc (response->crc_cls,
1205  connection->response_write_position,
1206  &connection->write_buffer[sizeof (cbuf)],
1207  connection->write_buffer_size - sizeof (cbuf) - 2);
1208  }
1209  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1210  {
1211  /* error, close socket! */
1212  response->total_size = connection->response_write_position;
1213 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1214  MHD_mutex_unlock_chk_ (&response->mutex);
1215 #endif
1216  CONNECTION_CLOSE_ERROR (connection,
1217  _("Closing connection (application error generating response)\n"));
1218  return MHD_NO;
1219  }
1220  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1221  (0 == response->total_size) )
1222  {
1223  /* end of message, signal other side! */
1224  memcpy (connection->write_buffer,
1225  "0\r\n",
1226  3);
1227  connection->write_buffer_append_offset = 3;
1228  connection->write_buffer_send_offset = 0;
1229  response->total_size = connection->response_write_position;
1230  return MHD_YES;
1231  }
1232  if (0 == ret)
1233  {
1235 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1236  MHD_mutex_unlock_chk_ (&response->mutex);
1237 #endif
1238  return MHD_NO;
1239  }
1240  if (ret > 0xFFFFFF)
1241  ret = 0xFFFFFF;
1242  cblen = MHD_snprintf_(cbuf,
1243  sizeof (cbuf),
1244  "%X\r\n",
1245  (unsigned int) ret);
1246  mhd_assert(cblen > 0);
1247  mhd_assert((size_t)cblen < sizeof(cbuf));
1248  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1249  cbuf,
1250  cblen);
1251  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1252  "\r\n",
1253  2);
1254  connection->response_write_position += ret;
1255  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1256  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1257  return MHD_YES;
1258 }
1259 
1260 
1277 static int
1279 {
1280  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1281  return MHD_NO;
1282  if (NULL == connection->version)
1283  return MHD_NO;
1284  if ( (NULL != connection->response) &&
1285  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1286  return MHD_NO;
1287 
1288  if (MHD_str_equal_caseless_(connection->version,
1290  ( (NULL == connection->response) ||
1291  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE) ) ) )
1292  {
1293  if (MHD_lookup_header_s_token_ci (connection,
1295  "upgrade"))
1296  return MHD_NO;
1297 
1298  if (MHD_lookup_header_s_token_ci (connection,
1300  "close"))
1301  return MHD_NO;
1302 
1303  return MHD_YES;
1304  }
1305  if (MHD_str_equal_caseless_(connection->version,
1307  {
1308  if (MHD_lookup_header_s_token_ci (connection,
1310  "Keep-Alive"))
1311  return MHD_YES;
1312 
1313  return MHD_NO;
1314  }
1315  return MHD_NO;
1316 }
1317 
1318 
1326 static void
1327 get_date_string (char *date,
1328  size_t date_len)
1329 {
1330  static const char *const days[] = {
1331  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1332  };
1333  static const char *const mons[] = {
1334  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1335  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1336  };
1337  struct tm now;
1338  time_t t;
1339 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
1340  struct tm* pNow;
1341 #endif
1342 
1343  date[0] = 0;
1344  time (&t);
1345 #if defined(HAVE_C11_GMTIME_S)
1346  if (NULL == gmtime_s (&t,
1347  &now))
1348  return;
1349 #elif defined(HAVE_W32_GMTIME_S)
1350  if (0 != gmtime_s (&now,
1351  &t))
1352  return;
1353 #elif defined(HAVE_GMTIME_R)
1354  if (NULL == gmtime_r(&t,
1355  &now))
1356  return;
1357 #else
1358  pNow = gmtime(&t);
1359  if (NULL == pNow)
1360  return;
1361  now = *pNow;
1362 #endif
1363  MHD_snprintf_ (date,
1364  date_len,
1365  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1366  days[now.tm_wday % 7],
1367  (unsigned int) now.tm_mday,
1368  mons[now.tm_mon % 12],
1369  (unsigned int) (1900 + now.tm_year),
1370  (unsigned int) now.tm_hour,
1371  (unsigned int) now.tm_min,
1372  (unsigned int) now.tm_sec);
1373 }
1374 
1375 
1386 static int
1388 {
1389  void *buf;
1390  size_t new_size;
1391 
1392  if (0 == connection->read_buffer_size)
1393  new_size = connection->daemon->pool_size / 2;
1394  else
1395  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
1396  buf = MHD_pool_reallocate (connection->pool,
1397  connection->read_buffer,
1398  connection->read_buffer_size,
1399  new_size);
1400  if (NULL == buf)
1401  return MHD_NO;
1402  /* we can actually grow the buffer, do it! */
1403  connection->read_buffer = buf;
1404  connection->read_buffer_size = new_size;
1405  return MHD_YES;
1406 }
1407 
1408 
1418 static int
1420 {
1421  struct MHD_Response *response = connection->response;
1422  size_t size;
1423  size_t off;
1424  struct MHD_HTTP_Header *pos;
1425  char code[256];
1426  char date[128];
1427  size_t datelen;
1428  char content_length_buf[128];
1429  size_t content_length_len;
1430  char *data;
1431  enum MHD_ValueKind kind;
1432  const char *reason_phrase;
1433  uint32_t rc;
1434  bool client_requested_close;
1435  bool response_has_close;
1436  bool response_has_keepalive;
1437  const char *have_encoding;
1438  int must_add_close;
1439  int must_add_chunked_encoding;
1440  int must_add_keep_alive;
1441  int must_add_content_length;
1442  int may_add_content_length;
1443 
1444  mhd_assert (NULL != connection->version);
1445  if (0 == connection->version[0])
1446  {
1447  data = MHD_pool_allocate (connection->pool,
1448  0,
1449  MHD_YES);
1450  connection->write_buffer = data;
1451  connection->write_buffer_append_offset = 0;
1452  connection->write_buffer_send_offset = 0;
1453  connection->write_buffer_size = 0;
1454  return MHD_YES;
1455  }
1456  rc = connection->responseCode & (~MHD_ICY_FLAG);
1457  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1458  {
1459  reason_phrase = MHD_get_reason_phrase_for (rc);
1460  MHD_snprintf_ (code,
1461  sizeof (code),
1462  "%s %u %s\r\n",
1463  (0 != (connection->responseCode & MHD_ICY_FLAG))
1464  ? "ICY"
1466  connection->version) ||
1467  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_RESPONSE)) )
1470  rc,
1471  reason_phrase);
1472  off = strlen (code);
1473  /* estimate size */
1474  size = off + 2; /* +2 for extra "\r\n" at the end */
1475  kind = MHD_HEADER_KIND;
1476  if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1477  (NULL == MHD_get_response_header (response,
1479  get_date_string (date,
1480  sizeof (date));
1481  else
1482  date[0] = '\0';
1483  datelen = strlen (date);
1484  size += datelen;
1485  }
1486  else
1487  {
1488  /* 2 bytes for final CRLF of a Chunked-Body */
1489  size = 2;
1490  kind = MHD_FOOTER_KIND;
1491  off = 0;
1492  datelen = 0;
1493  }
1494 
1495  /* calculate extra headers we need to add, such as 'Connection: close',
1496  first see what was explicitly requested by the application */
1497  must_add_close = MHD_NO;
1498  must_add_chunked_encoding = MHD_NO;
1499  must_add_keep_alive = MHD_NO;
1500  must_add_content_length = MHD_NO;
1501  response_has_close = false;
1502  switch (connection->state)
1503  {
1505  response_has_close = MHD_check_response_header_s_token_ci (response,
1507  "close");
1508  response_has_keepalive = MHD_check_response_header_s_token_ci (response,
1510  "Keep-Alive");
1511  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1513  "close");
1514 
1515  if (0 != (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1516  connection->keepalive = MHD_CONN_MUST_CLOSE;
1517 #ifdef UPGRADE_SUPPORT
1518  else if (NULL != response->upgrade_handler)
1519  /* If this connection will not be "upgraded", it must be closed. */
1520  connection->keepalive = MHD_CONN_MUST_CLOSE;
1521 #endif /* UPGRADE_SUPPORT */
1522 
1523  /* now analyze chunked encoding situation */
1524  connection->have_chunked_upload = false;
1525  have_encoding = MHD_get_response_header (response,
1527  if (NULL == have_encoding)
1528  may_add_content_length = MHD_YES;
1529  else
1530  may_add_content_length = MHD_NO; /* RFC 7230, Section 3.3.2 forbids header */
1531  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1532 #ifdef UPGRADE_SUPPORT
1533  (NULL == response->upgrade_handler) &&
1534 #endif /* UPGRADE_SUPPORT */
1535  (! response_has_close) &&
1536  (! client_requested_close) )
1537  {
1538  /* size is unknown, and close was not explicitly requested;
1539  need to either to HTTP 1.1 chunked encoding or
1540  close the connection */
1541  /* 'close' header doesn't exist yet, see if we need to add one;
1542  if the client asked for a close, no need to start chunk'ing */
1543  if ( (MHD_YES == keepalive_possible (connection)) &&
1545  connection->version) ) )
1546  {
1547  if (NULL == have_encoding)
1548  {
1549  must_add_chunked_encoding = MHD_YES;
1550  connection->have_chunked_upload = true;
1551  }
1552  else
1553  {
1554  if (MHD_str_equal_caseless_ (have_encoding,
1555  "identity"))
1556  {
1557  /* application forced identity encoding, can't do 'chunked' */
1558  must_add_close = MHD_YES;
1559  }
1560  else
1561  {
1562  connection->have_chunked_upload = true;
1563  }
1564  }
1565  }
1566  else
1567  {
1568  /* Keep alive or chunking not possible
1569  => set close header if not present */
1570  if (! response_has_close)
1571  must_add_close = MHD_YES;
1572  }
1573  }
1574 
1575  /* check for other reasons to add 'close' header */
1576  if ( ( (client_requested_close) ||
1577  (connection->read_closed) ||
1578  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1579  (! response_has_close) &&
1580 #ifdef UPGRADE_SUPPORT
1581  (NULL == response->upgrade_handler) &&
1582 #endif /* UPGRADE_SUPPORT */
1583  (0 == (response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1584  must_add_close = MHD_YES;
1585 
1586  /* check if we must add 'close' header because we cannot add content-length
1587  because it is forbidden AND we don't have a 'chunked' encoding */
1588  if ( (! may_add_content_length) &&
1589  (! connection->have_chunked_upload) &&
1590  (! response_has_close) )
1591  must_add_close = MHD_YES;
1592  /* #MHD_HTTP_NO_CONTENT, #MHD_HTTP_NOT_MODIFIED and 1xx-status
1593  codes SHOULD NOT have a Content-Length according to spec;
1594  also chunked encoding / unknown length or CONNECT... */
1595  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1596  (MHD_HTTP_NO_CONTENT != rc) &&
1597  (MHD_HTTP_NOT_MODIFIED != rc) &&
1598  (MHD_HTTP_OK <= rc) &&
1599  (NULL == /* this should always succeed due to check in
1600  MHD_add_response_header() */
1601  MHD_get_response_header (response,
1603  (may_add_content_length) &&
1604  ( (NULL == connection->method) ||
1605  (! MHD_str_equal_caseless_ (connection->method,
1607  {
1608  /*
1609  Here we add a content-length if one is missing; however,
1610  for 'connect' methods, the responses MUST NOT include a
1611  content-length header *if* the response code is 2xx (in
1612  which case we expect there to be no body). Still,
1613  as we don't know the response code here in some cases, we
1614  simply only force adding a content-length header if this
1615  is not a 'connect' or if the response is not empty
1616  (which is kind of more sane, because if some crazy
1617  application did return content with a 2xx status code,
1618  then having a content-length might again be a good idea).
1619 
1620  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1621  a recent development of the HTTP 1.1 specification.
1622  */
1623  content_length_len
1624  = MHD_snprintf_ (content_length_buf,
1625  sizeof (content_length_buf),
1627  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1628  must_add_content_length = MHD_YES;
1629  }
1630 
1631  /* check for adding keep alive */
1632  if ( (! response_has_keepalive) &&
1633  (! response_has_close) &&
1634  (MHD_NO == must_add_close) &&
1635  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1636 #ifdef UPGRADE_SUPPORT
1637  (NULL == response->upgrade_handler) &&
1638 #endif /* UPGRADE_SUPPORT */
1639  (MHD_YES == keepalive_possible (connection)) )
1640  must_add_keep_alive = MHD_YES;
1641  break;
1643  response_has_keepalive = false;
1644  break;
1645  default:
1646  mhd_assert (0);
1647  return MHD_NO;
1648  }
1649 
1650  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1651  {
1652  if ( (must_add_close) || (response_has_close) )
1653  connection->keepalive = MHD_CONN_MUST_CLOSE;
1654  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1655  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1656  }
1657 
1658  if (must_add_close)
1659  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1660  if (must_add_keep_alive)
1661  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1662  if (must_add_chunked_encoding)
1663  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1664  if (must_add_content_length)
1665  size += content_length_len;
1666  mhd_assert (! (must_add_close && must_add_keep_alive) );
1667  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1668 
1669  for (pos = response->first_header; NULL != pos; pos = pos->next)
1670  {
1671  /* TODO: add proper support for excluding "Keep-Alive" token. */
1672  if ( (pos->kind == kind) &&
1673  (! ( (MHD_YES == must_add_close) &&
1674  (response_has_keepalive) &&
1678  "Keep-Alive")) ) ) )
1679  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1680  }
1681  /* produce data */
1682  data = MHD_pool_allocate (connection->pool,
1683  size + 1,
1684  MHD_NO);
1685  if (NULL == data)
1686  {
1687 #ifdef HAVE_MESSAGES
1688  MHD_DLOG (connection->daemon,
1689  "Not enough memory for write!\n");
1690 #endif
1691  return MHD_NO;
1692  }
1693  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1694  {
1695  memcpy (data,
1696  code,
1697  off);
1698  }
1699  if (must_add_close)
1700  {
1701  /* we must add the 'Connection: close' header */
1702  memcpy (&data[off],
1703  "Connection: close\r\n",
1704  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1705  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1706  }
1707  if (must_add_keep_alive)
1708  {
1709  /* we must add the 'Connection: Keep-Alive' header */
1710  memcpy (&data[off],
1711  "Connection: Keep-Alive\r\n",
1712  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1713  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1714  }
1715  if (must_add_chunked_encoding)
1716  {
1717  /* we must add the 'Transfer-Encoding: chunked' header */
1718  memcpy (&data[off],
1719  "Transfer-Encoding: chunked\r\n",
1720  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1721  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1722  }
1723  if (must_add_content_length)
1724  {
1725  /* we must add the 'Content-Length' header */
1726  memcpy (&data[off],
1727  content_length_buf,
1728  content_length_len);
1729  off += content_length_len;
1730  }
1731  for (pos = response->first_header; NULL != pos; pos = pos->next)
1732  {
1733  /* TODO: add proper support for excluding "Keep-Alive" token. */
1734  if ( (pos->kind == kind) &&
1735  (! ( (MHD_YES == must_add_close) &&
1736  (response_has_keepalive) &&
1740  "Keep-Alive")) ) ) )
1741  off += MHD_snprintf_ (&data[off],
1742  size - off,
1743  "%s: %s\r\n",
1744  pos->header,
1745  pos->value);
1746  }
1747  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1748  {
1749  memcpy (&data[off],
1750  date,
1751  datelen);
1752  off += datelen;
1753  }
1754  memcpy (&data[off],
1755  "\r\n",
1756  2);
1757  off += 2;
1758 
1759  if (off != size)
1761  __FILE__,
1762  __LINE__,
1763  NULL);
1764  connection->write_buffer = data;
1765  connection->write_buffer_append_offset = size;
1766  connection->write_buffer_send_offset = 0;
1767  connection->write_buffer_size = size + 1;
1768  return MHD_YES;
1769 }
1770 
1771 
1781 static void
1783  unsigned int status_code,
1784  const char *message)
1785 {
1786  struct MHD_Response *response;
1787  int iret;
1788 
1789  if (NULL == connection->version)
1790  {
1791  /* we were unable to process the full header line, so we don't
1792  really know what version the client speaks; assume 1.0 */
1793  connection->version = MHD_HTTP_VERSION_1_0;
1794  }
1795  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1796  connection->read_closed = true;
1797 #ifdef HAVE_MESSAGES
1798  MHD_DLOG (connection->daemon,
1799  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1800  status_code,
1801  message);
1802 #endif
1803  if (NULL != connection->response)
1804  {
1805  MHD_destroy_response (connection->response);
1806  connection->response = NULL;
1807  }
1808  response = MHD_create_response_from_buffer (strlen (message),
1809  (void *) message,
1811  if (NULL == response)
1812  {
1813  /* can't even send a reply, at least close the connection */
1814  connection->state = MHD_CONNECTION_CLOSED;
1815  return;
1816  }
1817  iret = MHD_queue_response (connection,
1818  status_code,
1819  response);
1820  MHD_destroy_response (response);
1821  if (MHD_YES != iret)
1822  {
1823  /* can't even send a reply, at least close the connection */
1824  CONNECTION_CLOSE_ERROR (connection,
1825  _("Closing connection (failed to queue response)\n"));
1826  return;
1827  }
1828  mhd_assert (NULL != connection->response);
1829  /* Do not reuse this connection. */
1830  connection->keepalive = MHD_CONN_MUST_CLOSE;
1831  if (MHD_NO == build_header_response (connection))
1832  {
1833  /* oops - close! */
1834  CONNECTION_CLOSE_ERROR (connection,
1835  _("Closing connection (failed to create response header)\n"));
1836  }
1837  else
1838  {
1839  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1840  }
1841 }
1842 
1843 
1852 static void
1854 {
1855  /* Do not update states of suspended connection */
1856  if (connection->suspended)
1857  return; /* States will be updated after resume. */
1858 #ifdef HTTPS_SUPPORT
1859  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1860  { /* HTTPS connection. */
1861  switch (connection->tls_state)
1862  {
1863  case MHD_TLS_CONN_INIT:
1865  return;
1867  if (0 == gnutls_record_get_direction (connection->tls_session))
1869  else
1871  return;
1872  default:
1873  break;
1874  }
1875  }
1876 #endif /* HTTPS_SUPPORT */
1877  while (1)
1878  {
1879 #if DEBUG_STATES
1880  MHD_DLOG (connection->daemon,
1881  _("In function %s handling connection at state: %s\n"),
1882  __FUNCTION__,
1883  MHD_state_to_string (connection->state));
1884 #endif
1885  switch (connection->state)
1886  {
1887  case MHD_CONNECTION_INIT:
1890  /* while reading headers, we always grow the
1891  read buffer if needed, no size-check required */
1892  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1893  (MHD_NO == try_grow_read_buffer (connection)) )
1894  {
1895  transmit_error_response (connection,
1896  (connection->url != NULL)
1899  REQUEST_TOO_BIG);
1900  continue;
1901  }
1902  if (! connection->read_closed)
1904  else
1906  break;
1908  mhd_assert (0);
1909  break;
1911  mhd_assert (0);
1912  break;
1915  break;
1917  if (connection->read_buffer_offset == connection->read_buffer_size)
1918  {
1919  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1920  (0 != (connection->daemon->options &
1922  {
1923  /* failed to grow the read buffer, and the
1924  client which is supposed to handle the
1925  received data in a *blocking* fashion
1926  (in this mode) did not handle the data as
1927  it was supposed to!
1928  => we would either have to do busy-waiting
1929  (on the client, which would likely fail),
1930  or if we do nothing, we would just timeout
1931  on the connection (if a timeout is even
1932  set!).
1933  Solution: we kill the connection with an error */
1934  transmit_error_response (connection,
1936  INTERNAL_ERROR);
1937  continue;
1938  }
1939  }
1940  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1941  (! connection->read_closed) )
1943  else
1945  break;
1948  /* while reading footers, we always grow the
1949  read buffer if needed, no size-check required */
1950  if (connection->read_closed)
1951  {
1952  CONNECTION_CLOSE_ERROR (connection,
1953  NULL);
1954  continue;
1955  }
1957  /* transition to FOOTERS_RECEIVED
1958  happens in read handler */
1959  break;
1962  break;
1964  /* headers in buffer, keep writing */
1966  break;
1968  mhd_assert (0);
1969  break;
1972  break;
1975  break;
1978  break;
1981  break;
1983  mhd_assert (0);
1984  break;
1987  break;
1989  mhd_assert (0);
1990  break;
1991  case MHD_CONNECTION_CLOSED:
1993  return; /* do nothing, not even reading */
1994 #ifdef UPGRADE_SUPPORT
1995  case MHD_CONNECTION_UPGRADE:
1996  mhd_assert (0);
1997  break;
1998 #endif /* UPGRADE_SUPPORT */
1999  default:
2000  mhd_assert (0);
2001  }
2002  break;
2003  }
2004 }
2005 
2006 
2020 static char *
2022  size_t *line_len)
2023 {
2024  char *rbuf;
2025  size_t pos;
2026 
2027  if (0 == connection->read_buffer_offset)
2028  return NULL;
2029  pos = 0;
2030  rbuf = connection->read_buffer;
2031  while ( (pos < connection->read_buffer_offset - 1) &&
2032  ('\r' != rbuf[pos]) &&
2033  ('\n' != rbuf[pos]) )
2034  pos++;
2035  if ( (pos == connection->read_buffer_offset - 1) &&
2036  ('\n' != rbuf[pos]) )
2037  {
2038  /* not found, consider growing... */
2039  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
2040  (MHD_NO ==
2041  try_grow_read_buffer (connection)) )
2042  {
2043  transmit_error_response (connection,
2044  (NULL != connection->url)
2047  REQUEST_TOO_BIG);
2048  }
2049  if (line_len)
2050  *line_len = 0;
2051  return NULL;
2052  }
2053 
2054  if (line_len)
2055  *line_len = pos;
2056  /* found, check if we have proper LFCR */
2057  if ( ('\r' == rbuf[pos]) &&
2058  ('\n' == rbuf[pos + 1]) )
2059  rbuf[pos++] = '\0'; /* skip both r and n */
2060  rbuf[pos++] = '\0';
2061  connection->read_buffer += pos;
2062  connection->read_buffer_size -= pos;
2063  connection->read_buffer_offset -= pos;
2064  return rbuf;
2065 }
2066 
2067 
2079 static int
2081  const char *key,
2082  const char *value,
2083  enum MHD_ValueKind kind)
2084 {
2085  if (MHD_NO ==
2086  MHD_set_connection_value (connection,
2087  kind,
2088  key,
2089  value))
2090  {
2091 #ifdef HAVE_MESSAGES
2092  MHD_DLOG (connection->daemon,
2093  _("Not enough memory in pool to allocate header record!\n"));
2094 #endif
2095  transmit_error_response (connection,
2097  REQUEST_TOO_BIG);
2098  return MHD_NO;
2099  }
2100  return MHD_YES;
2101 }
2102 
2103 
2110 static int
2112 {
2113  const char *hdr;
2114  char *cpy;
2115  char *pos;
2116  char *sce;
2117  char *semicolon;
2118  char *equals;
2119  char *ekill;
2120  char old;
2121  int quotes;
2122 
2123  hdr = MHD_lookup_connection_value (connection,
2126  if (NULL == hdr)
2127  return MHD_YES;
2128  cpy = MHD_pool_allocate (connection->pool,
2129  strlen (hdr) + 1,
2130  MHD_YES);
2131  if (NULL == cpy)
2132  {
2133 #ifdef HAVE_MESSAGES
2134  MHD_DLOG (connection->daemon,
2135  _("Not enough memory in pool to parse cookies!\n"));
2136 #endif
2137  transmit_error_response (connection,
2139  REQUEST_TOO_BIG);
2140  return MHD_NO;
2141  }
2142  memcpy (cpy,
2143  hdr,
2144  strlen (hdr) + 1);
2145  pos = cpy;
2146  while (NULL != pos)
2147  {
2148  while (' ' == *pos)
2149  pos++; /* skip spaces */
2150 
2151  sce = pos;
2152  while ( ((*sce) != '\0') &&
2153  ((*sce) != ',') &&
2154  ((*sce) != ';') &&
2155  ((*sce) != '=') )
2156  sce++;
2157  /* remove tailing whitespace (if any) from key */
2158  ekill = sce - 1;
2159  while ( (*ekill == ' ') &&
2160  (ekill >= pos) )
2161  *(ekill--) = '\0';
2162  old = *sce;
2163  *sce = '\0';
2164  if (old != '=')
2165  {
2166  /* value part omitted, use empty string... */
2167  if (MHD_NO ==
2168  connection_add_header (connection,
2169  pos,
2170  "",
2171  MHD_COOKIE_KIND))
2172  return MHD_NO;
2173  if (old == '\0')
2174  break;
2175  pos = sce + 1;
2176  continue;
2177  }
2178  equals = sce + 1;
2179  quotes = 0;
2180  semicolon = equals;
2181  while ( ('\0' != semicolon[0]) &&
2182  ( (0 != quotes) ||
2183  ( (';' != semicolon[0]) &&
2184  (',' != semicolon[0]) ) ) )
2185  {
2186  if ('"' == semicolon[0])
2187  quotes = (quotes + 1) & 1;
2188  semicolon++;
2189  }
2190  if ('\0' == semicolon[0])
2191  semicolon = NULL;
2192  if (NULL != semicolon)
2193  {
2194  semicolon[0] = '\0';
2195  semicolon++;
2196  }
2197  /* remove quotes */
2198  if ( ('"' == equals[0]) &&
2199  ('"' == equals[strlen (equals) - 1]) )
2200  {
2201  equals[strlen (equals) - 1] = '\0';
2202  equals++;
2203  }
2204  if (MHD_NO ==
2205  connection_add_header (connection,
2206  pos,
2207  equals,
2208  MHD_COOKIE_KIND))
2209  return MHD_NO;
2210  pos = semicolon;
2211  }
2212  return MHD_YES;
2213 }
2214 
2215 
2224 static int
2226  char *line,
2227  size_t line_len)
2228 {
2229  struct MHD_Daemon *daemon = connection->daemon;
2230  const char *curi;
2231  char *uri;
2232  char *http_version;
2233  char *args;
2234  unsigned int unused_num_headers;
2235  size_t uri_len;
2236 
2237  if (NULL == (uri = memchr (line,
2238  ' ',
2239  line_len)))
2240  return MHD_NO; /* serious error */
2241  uri[0] = '\0';
2242  connection->method = line;
2243  uri++;
2244  /* Skip any spaces. Not required by standard but allow
2245  to be more tolerant. */
2246  while ( (' ' == uri[0]) &&
2247  ( (size_t)(uri - line) < line_len) )
2248  uri++;
2249  if ((size_t)(uri - line) == line_len)
2250  {
2251  /* No URI and no http version given */
2252  curi = "";
2253  uri_len = 0;
2254  uri = NULL;
2255  connection->version = "";
2256  args = NULL;
2257  }
2258  else
2259  {
2260  curi = uri;
2261  /* Search from back to accept misformed URI with space */
2262  http_version = line + line_len - 1;
2263  /* Skip any trailing spaces */
2264  while ( (' ' == http_version[0]) &&
2265  (http_version > uri) )
2266  http_version--;
2267  /* Find first space in reverse direction */
2268  while ( (' ' != http_version[0]) &&
2269  (http_version > uri) )
2270  http_version--;
2271  if (http_version > uri)
2272  {
2273  /* http_version points to string before HTTP version string */
2274  http_version[0] = '\0';
2275  connection->version = http_version + 1;
2276  uri_len = http_version - uri;
2277  }
2278  else
2279  {
2280  connection->version = "";
2281  uri_len = line_len - (uri - line);
2282  }
2283  /* check for spaces in URI if we are "strict" */
2284  if ( (1 <= daemon->strict_for_client) &&
2285  (NULL != memchr (uri,
2286  ' ',
2287  uri_len)) )
2288  {
2289  /* space exists in URI and we are supposed to be strict, reject */
2290  return MHD_NO;
2291  }
2292 
2293  /* unescape URI before searching for arguments */
2294  daemon->unescape_callback (daemon->unescape_callback_cls,
2295  connection,
2296  uri);
2297  uri_len = strlen (uri); /* recalculate: may have changed! */
2298  args = memchr (uri,
2299  '?',
2300  uri_len);
2301  }
2302 
2303  if (NULL != daemon->uri_log_callback)
2304  {
2305  connection->client_aware = true;
2306  connection->client_context
2307  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2308  curi,
2309  connection);
2310  }
2311  if (NULL != args)
2312  {
2313  args[0] = '\0';
2314  args++;
2315  /* note that this call clobbers 'args' */
2316  MHD_parse_arguments_ (connection,
2318  args,
2320  &unused_num_headers);
2321  }
2322  connection->url = curi;
2323  return MHD_YES;
2324 }
2325 
2326 
2334 static void
2336 {
2337  struct MHD_Daemon *daemon = connection->daemon;
2338  size_t processed;
2339 
2340  if (NULL != connection->response)
2341  return; /* already queued a response */
2342  processed = 0;
2343  connection->client_aware = true;
2344  if (MHD_NO ==
2345  daemon->default_handler (daemon->default_handler_cls,
2346  connection,
2347  connection->url,
2348  connection->method,
2349  connection->version,
2350  NULL,
2351  &processed,
2352  &connection->client_context))
2353  {
2354  /* serious internal error, close connection */
2355  CONNECTION_CLOSE_ERROR (connection,
2356  _("Application reported internal error, closing connection.\n"));
2357  return;
2358  }
2359 }
2360 
2361 
2369 static void
2371 {
2372  struct MHD_Daemon *daemon = connection->daemon;
2373  size_t available;
2374  int instant_retry;
2375  char *buffer_head;
2376 
2377  if (NULL != connection->response)
2378  return; /* already queued a response */
2379 
2380  buffer_head = connection->read_buffer;
2381  available = connection->read_buffer_offset;
2382  do
2383  {
2384  size_t to_be_processed;
2385  size_t left_unprocessed;
2386  size_t processed_size;
2387 
2388  instant_retry = MHD_NO;
2389  if ( (connection->have_chunked_upload) &&
2390  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2391  {
2392  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
2393  (0LLU != connection->current_chunk_offset) &&
2394  (available >= 2) )
2395  {
2396  size_t i;
2397  /* skip new line at the *end* of a chunk */
2398  i = 0;
2399  if ( ('\r' == buffer_head[i]) ||
2400  ('\n' == buffer_head[i]) )
2401  i++; /* skip 1st part of line feed */
2402  if ( ('\r' == buffer_head[i]) ||
2403  ('\n' == buffer_head[i]) )
2404  i++; /* skip 2nd part of line feed */
2405  if (0 == i)
2406  {
2407  /* malformed encoding */
2408  CONNECTION_CLOSE_ERROR (connection,
2409  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2410  return;
2411  }
2412  available -= i;
2413  buffer_head += i;
2414  connection->current_chunk_offset = 0;
2415  connection->current_chunk_size = 0;
2416  }
2417  if (connection->current_chunk_offset <
2418  connection->current_chunk_size)
2419  {
2420  uint64_t cur_chunk_left;
2421  /* we are in the middle of a chunk, give
2422  as much as possible to the client (without
2423  crossing chunk boundaries) */
2424  cur_chunk_left
2425  = connection->current_chunk_size - connection->current_chunk_offset;
2426  if (cur_chunk_left > available)
2427  to_be_processed = available;
2428  else
2429  { /* cur_chunk_left <= (size_t)available */
2430  to_be_processed = (size_t)cur_chunk_left;
2431  if (available > to_be_processed)
2432  instant_retry = MHD_YES;
2433  }
2434  }
2435  else
2436  {
2437  size_t i;
2438  size_t end_size;
2439  bool malformed;
2440 
2441  /* we need to read chunk boundaries */
2442  i = 0;
2443  while (i < available)
2444  {
2445  if ( ('\r' == buffer_head[i]) ||
2446  ('\n' == buffer_head[i]) ||
2447  (';' == buffer_head[i]) )
2448  break;
2449  i++;
2450  if (i >= 16)
2451  break;
2452  }
2453  end_size = i;
2454  /* find beginning of CRLF (skip over chunk extensions) */
2455  if (';' == buffer_head[i])
2456  {
2457  while (i < available)
2458  {
2459  if ( ('\r' == buffer_head[i]) ||
2460  ('\n' == buffer_head[i]) )
2461  break;
2462  i++;
2463  }
2464  }
2465  /* take '\n' into account; if '\n' is the unavailable
2466  character, we will need to wait until we have it
2467  before going further */
2468  if ( (i + 1 >= available) &&
2469  ! ( (1 == i) &&
2470  (2 == available) &&
2471  ('0' == buffer_head[0]) ) )
2472  break; /* need more data... */
2473  i++;
2474  malformed = (end_size >= 16);
2475  if (! malformed)
2476  {
2477  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2478  end_size,
2479  &connection->current_chunk_size);
2480  malformed = (end_size != num_dig);
2481  }
2482  if (malformed)
2483  {
2484  /* malformed encoding */
2485  CONNECTION_CLOSE_ERROR (connection,
2486  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2487  return;
2488  }
2489  /* skip 2nd part of line feed */
2490  if ( (i < available) &&
2491  ( ('\r' == buffer_head[i]) ||
2492  ('\n' == buffer_head[i]) ) )
2493  i++;
2494 
2495  buffer_head += i;
2496  available -= i;
2497  connection->current_chunk_offset = 0;
2498 
2499  if (available > 0)
2500  instant_retry = MHD_YES;
2501  if (0LLU == connection->current_chunk_size)
2502  {
2503  connection->remaining_upload_size = 0;
2504  break;
2505  }
2506  continue;
2507  }
2508  }
2509  else
2510  {
2511  /* no chunked encoding, give all to the client */
2512  if ( (0 != connection->remaining_upload_size) &&
2513  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2514  (connection->remaining_upload_size < available) )
2515  {
2516  to_be_processed = (size_t)connection->remaining_upload_size;
2517  }
2518  else
2519  {
2524  to_be_processed = available;
2525  }
2526  }
2527  left_unprocessed = to_be_processed;
2528  connection->client_aware = true;
2529  if (MHD_NO ==
2530  daemon->default_handler (daemon->default_handler_cls,
2531  connection,
2532  connection->url,
2533  connection->method,
2534  connection->version,
2535  buffer_head,
2536  &left_unprocessed,
2537  &connection->client_context))
2538  {
2539  /* serious internal error, close connection */
2540  CONNECTION_CLOSE_ERROR (connection,
2541  _("Application reported internal error, closing connection.\n"));
2542  return;
2543  }
2544  if (left_unprocessed > to_be_processed)
2546  __FILE__,
2547  __LINE__
2548 #ifdef HAVE_MESSAGES
2549  , _("libmicrohttpd API violation")
2550 #else
2551  , NULL
2552 #endif
2553  );
2554  if (0 != left_unprocessed)
2555  {
2556  instant_retry = MHD_NO; /* client did not process everything */
2557 #ifdef HAVE_MESSAGES
2558  /* client did not process all upload data, complain if
2559  the setup was incorrect, which may prevent us from
2560  handling the rest of the request */
2561  if ( (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2562  (! connection->suspended) )
2563  MHD_DLOG (daemon,
2564  _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2565 #endif
2566  }
2567  processed_size = to_be_processed - left_unprocessed;
2568  if (connection->have_chunked_upload)
2569  connection->current_chunk_offset += processed_size;
2570  /* dh left "processed" bytes in buffer for next time... */
2571  buffer_head += processed_size;
2572  available -= processed_size;
2573  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2574  connection->remaining_upload_size -= processed_size;
2575  }
2576  while (MHD_YES == instant_retry);
2577  if (available > 0)
2578  memmove (connection->read_buffer,
2579  buffer_head,
2580  available);
2581  connection->read_buffer_offset = available;
2582 }
2583 
2584 
2593 static int
2594 check_write_done (struct MHD_Connection *connection,
2595  enum MHD_CONNECTION_STATE next_state)
2596 {
2597  if (connection->write_buffer_append_offset !=
2598  connection->write_buffer_send_offset)
2599  return MHD_NO;
2600  connection->write_buffer_append_offset = 0;
2601  connection->write_buffer_send_offset = 0;
2602  connection->state = next_state;
2603  MHD_pool_reallocate (connection->pool,
2604  connection->write_buffer,
2605  connection->write_buffer_size,
2606  0);
2607  connection->write_buffer = NULL;
2608  connection->write_buffer_size = 0;
2609  return MHD_YES;
2610 }
2611 
2612 
2622 static int
2624  char *line)
2625 {
2626  char *colon;
2627 
2628  /* line should be normal header line, find colon */
2629  colon = strchr (line, ':');
2630  if (NULL == colon)
2631  {
2632  /* error in header line, die hard */
2633  CONNECTION_CLOSE_ERROR (connection,
2634  _("Received malformed line (no colon). Closing connection.\n"));
2635  return MHD_NO;
2636  }
2637  if (-1 >= connection->daemon->strict_for_client)
2638  {
2639  /* check for whitespace before colon, which is not allowed
2640  by RFC 7230 section 3.2.4; we count space ' ' and
2641  tab '\t', but not '\r\n' as those would have ended the line. */
2642  const char *white;
2643 
2644  white = strchr (line, ' ');
2645  if ( (NULL != white) &&
2646  (white < colon) )
2647  return MHD_NO;
2648  white = strchr (line, '\t');
2649  if ( (NULL != white) &&
2650  (white < colon) )
2651  return MHD_NO;
2652  }
2653  /* zero-terminate header */
2654  colon[0] = '\0';
2655  colon++; /* advance to value */
2656  while ( ('\0' != colon[0]) &&
2657  ( (' ' == colon[0]) ||
2658  ('\t' == colon[0]) ) )
2659  colon++;
2660  /* we do the actual adding of the connection
2661  header at the beginning of the while
2662  loop since we need to be able to inspect
2663  the *next* header line (in case it starts
2664  with a space...) */
2665  connection->last = line;
2666  connection->colon = colon;
2667  return MHD_YES;
2668 }
2669 
2670 
2681 static int
2683  char *line,
2684  enum MHD_ValueKind kind)
2685 {
2686  char *last;
2687  char *tmp;
2688  size_t last_len;
2689  size_t tmp_len;
2690 
2691  last = connection->last;
2692  if ( (' ' == line[0]) ||
2693  ('\t' == line[0]) )
2694  {
2695  /* value was continued on the next line, see
2696  http://www.jmarshall.com/easy/http/ */
2697  last_len = strlen (last);
2698  /* skip whitespace at start of 2nd line */
2699  tmp = line;
2700  while ( (' ' == tmp[0]) ||
2701  ('\t' == tmp[0]) )
2702  tmp++;
2703  tmp_len = strlen (tmp);
2704  /* FIXME: we might be able to do this better (faster!), as most
2705  likely 'last' and 'line' should already be adjacent in
2706  memory; however, doing this right gets tricky if we have a
2707  value continued over multiple lines (in which case we need to
2708  record how often we have done this so we can check for
2709  adjacency); also, in the case where these are not adjacent
2710  (not sure how it can happen!), we would want to allocate from
2711  the end of the pool, so as to not destroy the read-buffer's
2712  ability to grow nicely. */
2713  last = MHD_pool_reallocate (connection->pool,
2714  last,
2715  last_len + 1,
2716  last_len + tmp_len + 1);
2717  if (NULL == last)
2718  {
2719  transmit_error_response (connection,
2721  REQUEST_TOO_BIG);
2722  return MHD_NO;
2723  }
2724  memcpy (&last[last_len], tmp, tmp_len + 1);
2725  connection->last = last;
2726  return MHD_YES; /* possibly more than 2 lines... */
2727  }
2728  mhd_assert ( (NULL != last) &&
2729  (NULL != connection->colon) );
2730  if ((MHD_NO == connection_add_header (connection,
2731  last,
2732  connection->colon,
2733  kind)))
2734  {
2735  transmit_error_response (connection,
2737  REQUEST_TOO_BIG);
2738  return MHD_NO;
2739  }
2740  /* we still have the current line to deal with... */
2741  if (0 != line[0])
2742  {
2743  if (MHD_NO == process_header_line (connection,
2744  line))
2745  {
2746  transmit_error_response (connection,
2749  return MHD_NO;
2750  }
2751  }
2752  return MHD_YES;
2753 }
2754 
2755 
2763 static void
2765 {
2766  const char *clen;
2767  struct MHD_Response *response;
2768  const char *enc;
2769  const char *end;
2770 
2771  parse_cookie_header (connection);
2772  if ( (1 <= connection->daemon->strict_for_client) &&
2773  (NULL != connection->version) &&
2775  connection->version)) &&
2776  (NULL ==
2777  MHD_lookup_connection_value (connection,
2780  {
2781  int iret;
2782 
2783  /* die, http 1.1 request without host and we are pedantic */
2784  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2785  connection->read_closed = true;
2786 #ifdef HAVE_MESSAGES
2787  MHD_DLOG (connection->daemon,
2788  _("Received HTTP 1.1 request without `Host' header.\n"));
2789 #endif
2790  mhd_assert (NULL == connection->response);
2791  response =
2795  if (NULL == response)
2796  {
2797  /* can't even send a reply, at least close the connection */
2798  CONNECTION_CLOSE_ERROR (connection,
2799  _("Closing connection (failed to create response)\n"));
2800  return;
2801  }
2802  iret = MHD_queue_response (connection,
2804  response);
2805  MHD_destroy_response (response);
2806  if (MHD_YES != iret)
2807  {
2808  /* can't even send a reply, at least close the connection */
2809  CONNECTION_CLOSE_ERROR (connection,
2810  _("Closing connection (failed to queue response)\n"));
2811  }
2812  return;
2813  }
2814 
2815  connection->remaining_upload_size = 0;
2816  enc = MHD_lookup_connection_value (connection,
2819  if (NULL != enc)
2820  {
2822  if (MHD_str_equal_caseless_(enc,
2823  "chunked"))
2824  connection->have_chunked_upload = true;
2825  }
2826  else
2827  {
2828  clen = MHD_lookup_connection_value (connection,
2831  if (NULL != clen)
2832  {
2833  end = clen + MHD_str_to_uint64_ (clen,
2834  &connection->remaining_upload_size);
2835  if ( (clen == end) ||
2836  ('\0' != *end) )
2837  {
2838  connection->remaining_upload_size = 0;
2839 #ifdef HAVE_MESSAGES
2840  MHD_DLOG (connection->daemon,
2841  "Failed to parse `Content-Length' header. Closing connection.\n");
2842 #endif
2843  CONNECTION_CLOSE_ERROR (connection,
2844  NULL);
2845  return;
2846  }
2847  }
2848  }
2849 }
2850 
2851 
2859 void
2861 {
2862  struct MHD_Daemon *daemon = connection->daemon;
2863 
2864  if (0 == connection->connection_timeout)
2865  return; /* Skip update of activity for connections
2866  without timeout timer. */
2867  if (connection->suspended)
2868  return; /* no activity on suspended connections */
2869 
2870  connection->last_activity = MHD_monotonic_sec_counter();
2871  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2872  return; /* each connection has personal timeout */
2873 
2874  if (connection->connection_timeout != daemon->connection_timeout)
2875  return; /* custom timeout, no need to move it in "normal" DLL */
2876 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2878 #endif
2879  /* move connection to head of timeout list (by remove + add operation) */
2881  daemon->normal_timeout_tail,
2882  connection);
2884  daemon->normal_timeout_tail,
2885  connection);
2886 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2888 #endif
2889 }
2890 
2891 
2898 void
2900 {
2901  ssize_t bytes_read;
2902 
2903  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2904  (connection->suspended) )
2905  return;
2906 #ifdef HTTPS_SUPPORT
2907  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2908  { /* HTTPS connection. */
2909  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2910  {
2911  if (!MHD_run_tls_handshake_ (connection))
2912  return;
2913  }
2914  }
2915 #endif /* HTTPS_SUPPORT */
2916 
2917  /* make sure "read" has a reasonable number of bytes
2918  in buffer to use per system call (if possible) */
2919  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2920  connection->read_buffer_size)
2921  try_grow_read_buffer (connection);
2922 
2923  if (connection->read_buffer_size == connection->read_buffer_offset)
2924  return; /* No space for receiving data. */
2925  bytes_read = connection->recv_cls (connection,
2926  &connection->read_buffer
2927  [connection->read_buffer_offset],
2928  connection->read_buffer_size -
2929  connection->read_buffer_offset);
2930  if (bytes_read < 0)
2931  {
2932  if (MHD_ERR_AGAIN_ == bytes_read)
2933  return; /* No new data to process. */
2934  if (MHD_ERR_CONNRESET_ == bytes_read)
2935  {
2936  CONNECTION_CLOSE_ERROR (connection,
2937  (MHD_CONNECTION_INIT == connection->state) ?
2938  NULL :
2939  _("Socket disconnected while reading request.\n"));
2940  return;
2941  }
2942  CONNECTION_CLOSE_ERROR (connection,
2943  (MHD_CONNECTION_INIT == connection->state) ?
2944  NULL :
2945  _("Connection socket is closed due to error when reading request.\n"));
2946  return;
2947  }
2948 
2949  if (0 == bytes_read)
2950  { /* Remote side closed connection. */
2951  connection->read_closed = true;
2952  MHD_connection_close_ (connection,
2954  return;
2955  }
2956  connection->read_buffer_offset += bytes_read;
2957  MHD_update_last_activity_ (connection);
2958 #if DEBUG_STATES
2959  MHD_DLOG (connection->daemon,
2960  _("In function %s handling connection at state: %s\n"),
2961  __FUNCTION__,
2962  MHD_state_to_string (connection->state));
2963 #endif
2964  switch (connection->state)
2965  {
2966  case MHD_CONNECTION_INIT:
2975  /* nothing to do but default action */
2976  if (connection->read_closed)
2977  {
2978  MHD_connection_close_ (connection,
2980  }
2981  return;
2982  case MHD_CONNECTION_CLOSED:
2983  return;
2984 #ifdef UPGRADE_SUPPORT
2985  case MHD_CONNECTION_UPGRADE:
2986  mhd_assert (0);
2987  return;
2988 #endif /* UPGRADE_SUPPORT */
2989  default:
2990  /* shrink read buffer to how much is actually used */
2991  MHD_pool_reallocate (connection->pool,
2992  connection->read_buffer,
2993  connection->read_buffer_size + 1,
2994  connection->read_buffer_offset);
2995  break;
2996  }
2997  return;
2998 }
2999 
3000 
3007 void
3009 {
3010  struct MHD_Response *response;
3011  ssize_t ret;
3012  if (connection->suspended)
3013  return;
3014 
3015 #ifdef HTTPS_SUPPORT
3016  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3017  { /* HTTPS connection. */
3018  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
3019  {
3020  if (!MHD_run_tls_handshake_ (connection))
3021  return;
3022  }
3023  }
3024 #endif /* HTTPS_SUPPORT */
3025 
3026 #if DEBUG_STATES
3027  MHD_DLOG (connection->daemon,
3028  _("In function %s handling connection at state: %s\n"),
3029  __FUNCTION__,
3030  MHD_state_to_string (connection->state));
3031 #endif
3032  switch (connection->state)
3033  {
3034  case MHD_CONNECTION_INIT:
3038  mhd_assert (0);
3039  return;
3041  return;
3043  ret = connection->send_cls (connection,
3045  [connection->continue_message_write_offset],
3047  connection->continue_message_write_offset);
3048  if (ret < 0)
3049  {
3050  if (MHD_ERR_AGAIN_ == ret)
3051  return;
3052 #ifdef HAVE_MESSAGES
3053  MHD_DLOG (connection->daemon,
3054  _("Failed to send data in request for %s.\n"),
3055  connection->url);
3056 #endif
3057  CONNECTION_CLOSE_ERROR (connection,
3058  NULL);
3059  return;
3060  }
3061 #if DEBUG_SEND_DATA
3062  fprintf (stderr,
3063  _("Sent 100 continue response: `%.*s'\n"),
3064  (int) ret,
3066 #endif
3067  connection->continue_message_write_offset += ret;
3068  MHD_update_last_activity_ (connection);
3069  return;
3074  mhd_assert (0);
3075  return;
3077  ret = connection->send_cls (connection,
3078  &connection->write_buffer
3079  [connection->write_buffer_send_offset],
3080  connection->write_buffer_append_offset -
3081  connection->write_buffer_send_offset);
3082  if (ret < 0)
3083  {
3084  if (MHD_ERR_AGAIN_ == ret)
3085  return;
3086  CONNECTION_CLOSE_ERROR (connection,
3087  _("Connection was closed while sending response headers.\n"));
3088  return;
3089  }
3090  connection->write_buffer_send_offset += ret;
3091  MHD_update_last_activity_ (connection);
3092  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3093  return;
3094  check_write_done (connection,
3096  return;
3098  return;
3100  response = connection->response;
3101  if (connection->response_write_position <
3102  connection->response->total_size)
3103  {
3104  uint64_t data_write_offset;
3105 
3106 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3107  if (NULL != response->crc)
3108  MHD_mutex_lock_chk_ (&response->mutex);
3109 #endif
3110  if (MHD_YES != try_ready_normal_body (connection))
3111  {
3112  /* mutex was already unlocked by try_ready_normal_body */
3113  return;
3114  }
3115 #if defined(_MHD_HAVE_SENDFILE)
3116  if (MHD_resp_sender_sendfile == connection->resp_sender)
3117  {
3118  ret = sendfile_adapter (connection);
3119  }
3120  else
3121 #else /* ! _MHD_HAVE_SENDFILE */
3122  if (1)
3123 #endif /* ! _MHD_HAVE_SENDFILE */
3124  {
3125  data_write_offset = connection->response_write_position
3126  - response->data_start;
3127  if (data_write_offset > (uint64_t)SIZE_MAX)
3128  MHD_PANIC (_("Data offset exceeds limit"));
3129  ret = connection->send_cls (connection,
3130  &response->data
3131  [(size_t)data_write_offset],
3132  response->data_size -
3133  (size_t)data_write_offset);
3134 #if DEBUG_SEND_DATA
3135  if (ret > 0)
3136  fprintf (stderr,
3137  _("Sent %d-byte DATA response: `%.*s'\n"),
3138  (int) ret,
3139  (int) ret,
3140  &response->data[connection->response_write_position -
3141  response->data_start]);
3142 #endif
3143  }
3144 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3145  if (NULL != response->crc)
3146  MHD_mutex_unlock_chk_ (&response->mutex);
3147 #endif
3148  if (ret < 0)
3149  {
3150  if (MHD_ERR_AGAIN_ == ret)
3151  return;
3152 #ifdef HAVE_MESSAGES
3153  MHD_DLOG (connection->daemon,
3154  _("Failed to send data in request for `%s'.\n"),
3155  connection->url);
3156 #endif
3157  CONNECTION_CLOSE_ERROR (connection,
3158  NULL);
3159  return;
3160  }
3161  connection->response_write_position += ret;
3162  MHD_update_last_activity_ (connection);
3163  }
3164  if (connection->response_write_position ==
3165  connection->response->total_size)
3166  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3167  return;
3169  mhd_assert (0);
3170  return;
3172  ret = connection->send_cls (connection,
3173  &connection->write_buffer
3174  [connection->write_buffer_send_offset],
3175  connection->write_buffer_append_offset -
3176  connection->write_buffer_send_offset);
3177  if (ret < 0)
3178  {
3179  if (MHD_ERR_AGAIN_ == ret)
3180  return;
3181  CONNECTION_CLOSE_ERROR (connection,
3182  _("Connection was closed while sending response body.\n"));
3183  return;
3184  }
3185  connection->write_buffer_send_offset += ret;
3186  MHD_update_last_activity_ (connection);
3187  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3188  return;
3189  check_write_done (connection,
3190  (connection->response->total_size ==
3191  connection->response_write_position) ?
3194  return;
3195  case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
3197  mhd_assert (0);
3198  return;
3200  ret = connection->send_cls (connection,
3201  &connection->write_buffer
3202  [connection->write_buffer_send_offset],
3203  connection->write_buffer_append_offset -
3204  connection->write_buffer_send_offset);
3205  if (ret < 0)
3206  {
3207  if (MHD_ERR_AGAIN_ == ret)
3208  return;
3209  CONNECTION_CLOSE_ERROR (connection,
3210  _("Connection was closed while sending response body.\n"));
3211  return;
3212  }
3213  connection->write_buffer_send_offset += ret;
3214  MHD_update_last_activity_ (connection);
3215  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3216  return;
3217  check_write_done (connection,
3219  return;
3221  mhd_assert (0);
3222  return;
3223  case MHD_CONNECTION_CLOSED:
3224  return;
3225 #ifdef UPGRADE_SUPPORT
3226  case MHD_CONNECTION_UPGRADE:
3227  mhd_assert (0);
3228  return;
3229 #endif /* UPGRADE_SUPPORT */
3230  default:
3231  mhd_assert (0);
3232  CONNECTION_CLOSE_ERROR (connection,
3233  _("Internal error\n"));
3234  break;
3235  }
3236  return;
3237 }
3238 
3239 
3248 static void
3250 {
3251  struct MHD_Daemon *daemon = connection->daemon;
3252 
3253  if (connection->in_cleanup)
3254  return; /* Prevent double cleanup. */
3255  connection->in_cleanup = true;
3256  if (NULL != connection->response)
3257  {
3258  MHD_destroy_response (connection->response);
3259  connection->response = NULL;
3260  }
3261 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3263 #endif
3264  if (connection->suspended)
3265  {
3268  connection);
3269  connection->suspended = false;
3270  }
3271  else
3272  {
3273  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3274  {
3275  if (connection->connection_timeout == daemon->connection_timeout)
3277  daemon->normal_timeout_tail,
3278  connection);
3279  else
3281  daemon->manual_timeout_tail,
3282  connection);
3283  }
3284  DLL_remove (daemon->connections_head,
3285  daemon->connections_tail,
3286  connection);
3287  }
3288  DLL_insert (daemon->cleanup_head,
3289  daemon->cleanup_tail,
3290  connection);
3291  connection->resuming = false;
3292  connection->in_idle = false;
3293 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3295 #endif
3296  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3297  {
3298  /* if we were at the connection limit before and are in
3299  thread-per-connection mode, signal the main thread
3300  to resume accepting connections */
3301  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3302  (! MHD_itc_activate_ (daemon->itc, "c")) )
3303  {
3304 #ifdef HAVE_MESSAGES
3305  MHD_DLOG (daemon,
3306  _("Failed to signal end of connection via inter-thread communication channel"));
3307 #endif
3308  }
3309  }
3310 }
3311 
3312 
3323 int
3325 {
3326  struct MHD_Daemon *daemon = connection->daemon;
3327  char *line;
3328  size_t line_len;
3329  int ret;
3330 
3331  connection->in_idle = true;
3332  while (! connection->suspended)
3333  {
3334 #ifdef HTTPS_SUPPORT
3335  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3336  { /* HTTPS connection. */
3337  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3338  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3339  break;
3340  }
3341 #endif /* HTTPS_SUPPORT */
3342 #if DEBUG_STATES
3343  MHD_DLOG (daemon,
3344  _("In function %s handling connection at state: %s\n"),
3345  __FUNCTION__,
3346  MHD_state_to_string (connection->state));
3347 #endif
3348  switch (connection->state)
3349  {
3350  case MHD_CONNECTION_INIT:
3351  line = get_next_header_line (connection,
3352  &line_len);
3353  /* Check for empty string, as we might want
3354  to tolerate 'spurious' empty lines; also
3355  NULL means we didn't get a full line yet;
3356  line is not 0-terminated here. */
3357  if ( (NULL == line) ||
3358  (0 == line[0]) )
3359  {
3360  if (MHD_CONNECTION_INIT != connection->state)
3361  continue;
3362  if (connection->read_closed)
3363  {
3364  CONNECTION_CLOSE_ERROR (connection,
3365  NULL);
3366  continue;
3367  }
3368  break;
3369  }
3370  if (MHD_NO == parse_initial_message_line (connection,
3371  line,
3372  line_len))
3373  CONNECTION_CLOSE_ERROR (connection,
3374  NULL);
3375  else
3376  connection->state = MHD_CONNECTION_URL_RECEIVED;
3377  continue;
3379  line = get_next_header_line (connection,
3380  NULL);
3381  if (NULL == line)
3382  {
3383  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3384  continue;
3385  if (connection->read_closed)
3386  {
3387  CONNECTION_CLOSE_ERROR (connection,
3388  NULL);
3389  continue;
3390  }
3391  break;
3392  }
3393  if (0 == line[0])
3394  {
3395  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3396  connection->header_size = (size_t) (line - connection->read_buffer);
3397  continue;
3398  }
3399  if (MHD_NO == process_header_line (connection,
3400  line))
3401  {
3402  transmit_error_response (connection,
3405  break;
3406  }
3408  continue;
3410  line = get_next_header_line (connection,
3411  NULL);
3412  if (NULL == line)
3413  {
3414  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
3415  continue;
3416  if (connection->read_closed)
3417  {
3418  CONNECTION_CLOSE_ERROR (connection,
3419  NULL);
3420  continue;
3421  }
3422  break;
3423  }
3424  if (MHD_NO ==
3425  process_broken_line (connection,
3426  line,
3427  MHD_HEADER_KIND))
3428  continue;
3429  if (0 == line[0])
3430  {
3431  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3432  connection->header_size = (size_t) (line - connection->read_buffer);
3433  continue;
3434  }
3435  continue;
3437  parse_connection_headers (connection);
3438  if (MHD_CONNECTION_CLOSED == connection->state)
3439  continue;
3441  if (connection->suspended)
3442  break;
3443  continue;
3445  call_connection_handler (connection); /* first call */
3446  if (MHD_CONNECTION_CLOSED == connection->state)
3447  continue;
3448  if (need_100_continue (connection))
3449  {
3450  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3451  if (MHD_NO != socket_flush_possible (connection))
3452  socket_start_extra_buffering (connection);
3453  else
3454  socket_start_no_buffering (connection);
3455 
3456  break;
3457  }
3458  if ( (NULL != connection->response) &&
3459  ( (MHD_str_equal_caseless_ (connection->method,
3461  (MHD_str_equal_caseless_ (connection->method,
3462  MHD_HTTP_METHOD_PUT))) )
3463  {
3464  /* we refused (no upload allowed!) */
3465  connection->remaining_upload_size = 0;
3466  /* force close, in case client still tries to upload... */
3467  connection->read_closed = true;
3468  }
3469  connection->state = (0 == connection->remaining_upload_size)
3471  if (connection->suspended)
3472  break;
3473  continue;
3475  if (connection->continue_message_write_offset ==
3477  {
3478  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3479  if (MHD_NO != socket_flush_possible (connection))
3480  socket_start_no_buffering_flush (connection);
3481  else
3482  socket_start_normal_buffering (connection);
3483 
3484  continue;
3485  }
3486  break;
3488  if (0 != connection->read_buffer_offset)
3489  {
3490  process_request_body (connection); /* loop call */
3491  if (MHD_CONNECTION_CLOSED == connection->state)
3492  continue;
3493  }
3494  if ( (0 == connection->remaining_upload_size) ||
3495  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3496  (0 == connection->read_buffer_offset) &&
3497  (connection->read_closed) ) )
3498  {
3499  if ( (connection->have_chunked_upload) &&
3500  (! connection->read_closed) )
3501  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3502  else
3503  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3504  if (connection->suspended)
3505  break;
3506  continue;
3507  }
3508  break;
3510  line = get_next_header_line (connection,
3511  NULL);
3512  if (NULL == line)
3513  {
3514  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3515  continue;
3516  if (connection->read_closed)
3517  {
3518  CONNECTION_CLOSE_ERROR (connection,
3519  NULL);
3520  continue;
3521  }
3522  break;
3523  }
3524  if (0 == line[0])
3525  {
3526  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3527  if (connection->suspended)
3528  break;
3529  continue;
3530  }
3531  if (MHD_NO == process_header_line (connection,
3532  line))
3533  {
3534  transmit_error_response (connection,
3537  break;
3538  }
3540  continue;
3542  line = get_next_header_line (connection,
3543  NULL);
3544  if (NULL == line)
3545  {
3546  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3547  continue;
3548  if (connection->read_closed)
3549  {
3550  CONNECTION_CLOSE_ERROR (connection,
3551  NULL);
3552  continue;
3553  }
3554  break;
3555  }
3556  if (MHD_NO ==
3557  process_broken_line (connection,
3558  line,
3559  MHD_FOOTER_KIND))
3560  continue;
3561  if (0 == line[0])
3562  {
3563  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3564  if (connection->suspended)
3565  break;
3566  continue;
3567  }
3568  continue;
3570  call_connection_handler (connection); /* "final" call */
3571  if (connection->state == MHD_CONNECTION_CLOSED)
3572  continue;
3573  if (NULL == connection->response)
3574  break; /* try again next time */
3575  if (MHD_NO == build_header_response (connection))
3576  {
3577  /* oops - close! */
3578  CONNECTION_CLOSE_ERROR (connection,
3579  _("Closing connection (failed to create response header)\n"));
3580  continue;
3581  }
3582  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3583  if (MHD_NO != socket_flush_possible (connection))
3584  socket_start_extra_buffering (connection);
3585  else
3586  socket_start_no_buffering (connection);
3587 
3588  break;
3590  /* no default action */
3591  break;
3593  /* Some clients may take some actions right after header receive */
3594  if (MHD_NO != socket_flush_possible (connection))
3595  socket_start_no_buffering_flush (connection);
3596 
3597 #ifdef UPGRADE_SUPPORT
3598  if (NULL != connection->response->upgrade_handler)
3599  {
3600  socket_start_normal_buffering (connection);
3601  connection->state = MHD_CONNECTION_UPGRADE;
3602  /* This connection is "upgraded". Pass socket to application. */
3603  if (MHD_YES !=
3605  connection))
3606  {
3607  /* upgrade failed, fail hard */
3608  CONNECTION_CLOSE_ERROR (connection,
3609  NULL);
3610  continue;
3611  }
3612  /* Response is not required anymore for this connection. */
3613  {
3614  struct MHD_Response * const resp = connection->response;
3615 
3616  connection->response = NULL;
3617  MHD_destroy_response (resp);
3618  }
3619  continue;
3620  }
3621 #endif /* UPGRADE_SUPPORT */
3622  if (MHD_NO != socket_flush_possible (connection))
3623  socket_start_extra_buffering (connection);
3624  else
3625  socket_start_normal_buffering (connection);
3626 
3627  if (connection->have_chunked_upload)
3629  else
3631  continue;
3633  /* nothing to do here */
3634  break;
3636 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3637  if (NULL != connection->response->crc)
3638  MHD_mutex_lock_chk_ (&connection->response->mutex);
3639 #endif
3640  if (0 == connection->response->total_size)
3641  {
3642 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3643  if (NULL != connection->response->crc)
3644  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3645 #endif
3646  connection->state = MHD_CONNECTION_BODY_SENT;
3647  continue;
3648  }
3649  if (MHD_YES == try_ready_normal_body (connection))
3650  {
3651 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3652  if (NULL != connection->response->crc)
3653  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3654 #endif
3656  /* Buffering for flushable socket was already enabled*/
3657  if (MHD_NO == socket_flush_possible (connection))
3658  socket_start_no_buffering (connection);
3659  break;
3660  }
3661  /* mutex was already unlocked by "try_ready_normal_body */
3662  /* not ready, no socket action */
3663  break;
3665  /* nothing to do here */
3666  break;
3668 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3669  if (NULL != connection->response->crc)
3670  MHD_mutex_lock_chk_ (&connection->response->mutex);
3671 #endif
3672  if ( (0 == connection->response->total_size) ||
3673  (connection->response_write_position ==
3674  connection->response->total_size) )
3675  {
3676 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3677  if (NULL != connection->response->crc)
3678  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3679 #endif
3680  connection->state = MHD_CONNECTION_BODY_SENT;
3681  continue;
3682  }
3683  if (MHD_YES == try_ready_chunked_body (connection))
3684  {
3685 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3686  if (NULL != connection->response->crc)
3687  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3688 #endif
3690  /* Buffering for flushable socket was already enabled */
3691  if (MHD_NO == socket_flush_possible (connection))
3692  socket_start_no_buffering (connection);
3693  continue;
3694  }
3695  /* mutex was already unlocked by try_ready_chunked_body */
3696  break;
3698  if (MHD_NO == build_header_response (connection))
3699  {
3700  /* oops - close! */
3701  CONNECTION_CLOSE_ERROR (connection,
3702  _("Closing connection (failed to create response header)\n"));
3703  continue;
3704  }
3705  if ( (! connection->have_chunked_upload) ||
3706  (connection->write_buffer_send_offset ==
3707  connection->write_buffer_append_offset) )
3708  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3709  else
3710  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3711  continue;
3713  /* no default action */
3714  break;
3716  if (MHD_HTTP_PROCESSING == connection->responseCode)
3717  {
3718  /* After this type of response, we allow sending another! */
3720  MHD_destroy_response (connection->response);
3721  connection->response = NULL;
3722  /* FIXME: maybe partially reset memory pool? */
3723  continue;
3724  }
3725  if (MHD_NO != socket_flush_possible (connection))
3726  socket_start_no_buffering_flush (connection);
3727  else
3728  socket_start_normal_buffering (connection);
3729 
3730  MHD_destroy_response (connection->response);
3731  connection->response = NULL;
3732  if ( (NULL != daemon->notify_completed) &&
3733  (connection->client_aware) )
3734  {
3735  daemon->notify_completed (daemon->notify_completed_cls,
3736  connection,
3737  &connection->client_context,
3739  }
3740  connection->client_aware = false;
3741  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3742  (connection->read_closed) )
3743  {
3744  /* have to close for some reason */
3745  MHD_connection_close_ (connection,
3747  MHD_pool_destroy (connection->pool);
3748  connection->pool = NULL;
3749  connection->read_buffer = NULL;
3750  connection->read_buffer_size = 0;
3751  connection->read_buffer_offset = 0;
3752  }
3753  else
3754  {
3755  /* can try to keep-alive */
3756  if (MHD_NO != socket_flush_possible (connection))
3757  socket_start_normal_buffering (connection);
3758  connection->version = NULL;
3759  connection->state = MHD_CONNECTION_INIT;
3760  connection->last = NULL;
3761  connection->colon = NULL;
3762  connection->header_size = 0;
3763  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3764  /* Reset the read buffer to the starting size,
3765  preserving the bytes we have already read. */
3766  connection->read_buffer
3767  = MHD_pool_reset (connection->pool,
3768  connection->read_buffer,
3769  connection->read_buffer_offset,
3770  connection->daemon->pool_size / 2);
3771  connection->read_buffer_size
3772  = connection->daemon->pool_size / 2;
3773  }
3774  connection->client_context = NULL;
3775  connection->continue_message_write_offset = 0;
3776  connection->responseCode = 0;
3777  connection->headers_received = NULL;
3778  connection->headers_received_tail = NULL;
3779  connection->response_write_position = 0;
3780  connection->have_chunked_upload = false;
3781  connection->current_chunk_size = 0;
3782  connection->current_chunk_offset = 0;
3783  connection->method = NULL;
3784  connection->url = NULL;
3785  connection->write_buffer = NULL;
3786  connection->write_buffer_size = 0;
3787  connection->write_buffer_send_offset = 0;
3788  connection->write_buffer_append_offset = 0;
3789  continue;
3790  case MHD_CONNECTION_CLOSED:
3791  cleanup_connection (connection);
3792  connection->in_idle = false;
3793  return MHD_NO;
3794 #ifdef UPGRADE_SUPPORT
3795  case MHD_CONNECTION_UPGRADE:
3796  connection->in_idle = false;
3797  return MHD_YES; /* keep open */
3798 #endif /* UPGRADE_SUPPORT */
3799  default:
3800  mhd_assert (0);
3801  break;
3802  }
3803  break;
3804  }
3805  if (! connection->suspended)
3806  {
3807  time_t timeout;
3808  timeout = connection->connection_timeout;
3809  if ( (0 != timeout) &&
3810  (timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
3811  {
3812  MHD_connection_close_ (connection,
3814  connection->in_idle = false;
3815  return MHD_YES;
3816  }
3817  }
3819  ret = MHD_YES;
3820 #ifdef EPOLL_SUPPORT
3821  if ( (! connection->suspended) &&
3822  (0 != (daemon->options & MHD_USE_EPOLL)) )
3823  {
3824  ret = MHD_connection_epoll_update_ (connection);
3825  }
3826 #endif /* EPOLL_SUPPORT */
3827  connection->in_idle = false;
3828  return ret;
3829 }
3830 
3831 
3832 #ifdef EPOLL_SUPPORT
3833 
3841 int
3842 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3843 {
3844  struct MHD_Daemon *daemon = connection->daemon;
3845 
3846  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3847  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3848  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3849  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3850  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3851  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3852  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3853  {
3854  /* add to epoll set */
3855  struct epoll_event event;
3856 
3857  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3858  event.data.ptr = connection;
3859  if (0 != epoll_ctl (daemon->epoll_fd,
3860  EPOLL_CTL_ADD,
3861  connection->socket_fd,
3862  &event))
3863  {
3864 #ifdef HAVE_MESSAGES
3865  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3866  MHD_DLOG (daemon,
3867  _("Call to epoll_ctl failed: %s\n"),
3869 #endif
3870  connection->state = MHD_CONNECTION_CLOSED;
3871  cleanup_connection (connection);
3872  return MHD_NO;
3873  }
3874  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3875  }
3876  return MHD_YES;
3877 }
3878 #endif
3879 
3880 
3886 void
3888 {
3889  connection->recv_cls = &recv_param_adapter;
3890  connection->send_cls = &send_param_adapter;
3891 }
3892 
3893 
3904 const union MHD_ConnectionInfo *
3906  enum MHD_ConnectionInfoType info_type,
3907  ...)
3908 {
3909  switch (info_type)
3910  {
3911 #ifdef HTTPS_SUPPORT
3913  if (NULL == connection->tls_session)
3914  return NULL;
3915  connection->cipher = gnutls_cipher_get (connection->tls_session);
3916  return (const union MHD_ConnectionInfo *) &connection->cipher;
3918  if (NULL == connection->tls_session)
3919  return NULL;
3920  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3921  return (const union MHD_ConnectionInfo *) &connection->protocol;
3923  if (NULL == connection->tls_session)
3924  return NULL;
3925  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3926 #endif /* HTTPS_SUPPORT */
3928  return (const union MHD_ConnectionInfo *) &connection->addr;
3930  return (const union MHD_ConnectionInfo *) &connection->daemon;
3932  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3934  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3936  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3937  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3939  connection->connection_timeout_dummy = (unsigned int)connection->connection_timeout;
3940  return (const union MHD_ConnectionInfo *) &connection->connection_timeout_dummy;
3942  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3943  (MHD_CONNECTION_CLOSED == connection->state) )
3944  return NULL; /* invalid, too early! */
3945  return (const union MHD_ConnectionInfo *) &connection->header_size;
3946  default:
3947  return NULL;
3948  }
3949 }
3950 
3951 
3961 int
3963  enum MHD_CONNECTION_OPTION option,
3964  ...)
3965 {
3966  va_list ap;
3967  struct MHD_Daemon *daemon;
3968 
3969  daemon = connection->daemon;
3970  switch (option)
3971  {
3973  if (0 == connection->connection_timeout)
3974  connection->last_activity = MHD_monotonic_sec_counter();
3975 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
3977 #endif
3978  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3979  (! connection->suspended) )
3980  {
3981  if (connection->connection_timeout == daemon->connection_timeout)
3983  daemon->normal_timeout_tail,
3984  connection);
3985  else
3987  daemon->manual_timeout_tail,
3988  connection);
3989  }
3990  va_start (ap, option);
3991  connection->connection_timeout = va_arg (ap,
3992  unsigned int);
3993  va_end (ap);
3994  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3995  (! connection->suspended) )
3996  {
3997  if (connection->connection_timeout == daemon->connection_timeout)
3999  daemon->normal_timeout_tail,
4000  connection);
4001  else
4003  daemon->manual_timeout_tail,
4004  connection);
4005  }
4006 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4008 #endif
4009  return MHD_YES;
4010  default:
4011  return MHD_NO;
4012  }
4013 }
4014 
4015 
4027 int
4029  unsigned int status_code,
4030  struct MHD_Response *response)
4031 {
4032  struct MHD_Daemon *daemon;
4033 
4034  if ( (NULL == connection) ||
4035  (NULL == response) ||
4036  (NULL != connection->response) ||
4037  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
4038  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
4039  return MHD_NO;
4040  daemon = connection->daemon;
4041 
4042  if (daemon->shutdown)
4043  return MHD_YES; /* If daemon was shut down in parallel,
4044  * response will be aborted now or on later stage. */
4045 
4046 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
4047  if ( (!connection->suspended) &&
4048  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
4049  (!MHD_thread_ID_match_current_(connection->pid.ID)) )
4050  {
4051 #ifdef HAVE_MESSAGES
4052  MHD_DLOG (daemon,
4053  _("Attempted to queue response on wrong thread!\n"));
4054 #endif
4055  return MHD_NO;
4056  }
4057 #endif
4058 #ifdef UPGRADE_SUPPORT
4059  if ( (NULL != response->upgrade_handler) &&
4060  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
4061  {
4062 #ifdef HAVE_MESSAGES
4063  MHD_DLOG (daemon,
4064  _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
4065 #endif
4066  return MHD_NO;
4067  }
4068  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
4069  (NULL != response->upgrade_handler) )
4070  {
4071 #ifdef HAVE_MESSAGES
4072  MHD_DLOG (daemon,
4073  _("Application used invalid status code for 'upgrade' response!\n"));
4074 #endif
4075  return MHD_NO;
4076  }
4077 #endif /* UPGRADE_SUPPORT */
4078  MHD_increment_response_rc (response);
4079  connection->response = response;
4080  connection->responseCode = status_code;
4081 #if defined(_MHD_HAVE_SENDFILE)
4082  if ( (response->fd == -1) ||
4083  (0 != (connection->daemon->options & MHD_USE_TLS)) )
4084  connection->resp_sender = MHD_resp_sender_std;
4085  else
4086  connection->resp_sender = MHD_resp_sender_sendfile;
4087 #endif /* _MHD_HAVE_SENDFILE */
4088 
4089  if ( ( (NULL != connection->method) &&
4090  (MHD_str_equal_caseless_ (connection->method,
4091  MHD_HTTP_METHOD_HEAD)) ) ||
4092  (MHD_HTTP_OK > status_code) ||
4093  (MHD_HTTP_NO_CONTENT == status_code) ||
4094  (MHD_HTTP_NOT_MODIFIED == status_code) )
4095  {
4096  /* if this is a "HEAD" request, or a status code for
4097  which a body is not allowed, pretend that we
4098  have already sent the full message body. */
4099  connection->response_write_position = response->total_size;
4100  }
4101  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
4102  (NULL != connection->method) &&
4103  ( (MHD_str_equal_caseless_ (connection->method,
4105  (MHD_str_equal_caseless_ (connection->method,
4106  MHD_HTTP_METHOD_PUT))) )
4107  {
4108  /* response was queued "early", refuse to read body / footers or
4109  further requests! */
4110  connection->read_closed = true;
4111  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4112  }
4113  if (! connection->in_idle)
4114  (void) MHD_connection_handle_idle (connection);
4115  return MHD_YES;
4116 }
4117 
4118 
4119 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2623
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: connection.c:233
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2033
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:2111
void * unescape_callback_cls
Definition: internal.h:1395
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:460
#define MHD_PANIC(msg)
Definition: internal.h:68
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:3008
uint64_t total_size
Definition: internal.h:1639
bool have_chunked_upload
Definition: internal.h:922
Header for platform missing functions.
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:1074
uint64_t fd_off
Definition: internal.h:1650
uint64_t current_chunk_offset
Definition: internal.h:936
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:797
DLL_remove(daemon->suspended_connections_head, daemon->suspended_connections_tail, pos)
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:754
void MHD_update_last_activity_(struct MHD_Connection *connection)
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1853
struct sockaddr_storage addr
Definition: internal.h:725
struct MHD_Connection * cleanup_head
Definition: internal.h:1174
enum MHD_CONNECTION_STATE state
Definition: internal.h:902
void * data
Definition: microhttpd.h:2709
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:1144
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:864
uint64_t response_write_position
Definition: internal.h:808
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:715
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:450
void * mhd_panic_cls
Definition: panic.c:36
#define HTTP_100_CONTINUE
Definition: connection.c:57
#define MHD_ICY_FLAG
Definition: microhttpd.h:414
MHD_mutex_lock_chk_ & daemon
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:907
#define OFF_T_MAX
Definition: mhd_limits.h:123
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
time_t connection_timeout
Definition: internal.h:1566
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:2080
Methods for managing connections.
MHD_PanicCallback mhd_panic
Definition: panic.c:31
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
internal monotonic clock functions implementations
MHD_CONNECTION_STATE
Definition: internal.h:407
char * version
Definition: internal.h:708
int suspended_dummy
Definition: internal.h:995
#define INTERNAL_ERROR
Definition: connection.c:107
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:470
#define MHD_YES
Definition: microhttpd.h:134
#define SIZE_MAX
Definition: mhd_limits.h:99
struct MHD_Response * response
Definition: internal.h:664
char * data
Definition: internal.h:1585
char * colon
Definition: internal.h:745
#define REQUEST_LACKS_HOST
Definition: connection.c:82
char * write_buffer
Definition: internal.h:728
#define MHD_SENFILE_CHUNK_
Definition: connection.c:125
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:329
#define MHD_ERR_AGAIN_
Definition: internal.h:1864
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:393
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:186
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1140
MHD_RequestTerminationCode
Definition: microhttpd.h:1604
size_t data_size
Definition: internal.h:1656
MHD_thread_handle_ID_ pid
Definition: internal.h:720
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:329
time_t MHD_monotonic_sec_counter(void)
char * value
Definition: internal.h:349
enum MHD_ValueKind kind
Definition: internal.h:355
bool ret
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1782
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1241
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2335
uint64_t remaining_upload_size
Definition: internal.h:801
unsigned int responseCode
Definition: internal.h:913
#define MHD_ERR_CONNRESET_
Definition: internal.h:1869
const bool used_thr_p_c
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3249
char * header
Definition: internal.h:344
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1385
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:180
struct MHD_Daemon * daemon
Definition: internal.h:672
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t header_size
Definition: internal.h:795
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1935
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:130
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:574
static bool MHD_lookup_header_token_ci(const struct MHD_Connection *connection, const char *header, const char *token, size_t token_len)
Definition: connection.c:831
Header for platform-independent inter-thread communication.
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:1035
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
bool client_aware
Definition: internal.h:851
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1278
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
int strict_for_client
Definition: internal.h:1587
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1167
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:355
void * socket_context
Definition: internal.h:691
struct MHD_HTTP_Header * first_header
Definition: internal.h:1579
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
size_t data_buffer_size
Definition: internal.h:1661
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3422
size_t write_buffer_send_offset
Definition: internal.h:783
void * crc_cls
Definition: internal.h:1591
struct MHD_Connection * connections_tail
Definition: internal.h:1157
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
_MHD_EXTERN union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3905
size_t read_buffer_size
Definition: internal.h:767
void * client_context
Definition: internal.h:682
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:438
const char * url
Definition: internal.h:702
size_t continue_message_write_offset
Definition: internal.h:822
#define REQUEST_MALFORMED
Definition: connection.c:95
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:749
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:666
internal shared structures
char * method
Definition: internal.h:696
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
enum MHD_FLAG options
Definition: internal.h:1577
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:248
struct MHD_Connection * connections_head
Definition: internal.h:1152
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:317
LogCallback uri_log_callback
Definition: internal.h:1380
static int socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:557
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2899
bool in_cleanup
Definition: internal.h:890
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1127
#define MHD_HTTP_OK
Definition: microhttpd.h:313
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
time_t connection_timeout
Definition: internal.h:742
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3962
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
#define EDLL_remove(head, tail, element)
Definition: internal.h:1847
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1147
#define NULL
Definition: reason_phrase.c:30
char * last
Definition: internal.h:736
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1327
MHD_ValueKind
Definition: microhttpd.h:1554
Header for string manipulating helpers.
char * read_buffer
Definition: internal.h:722
ReceiveCallback recv_cls
Definition: internal.h:703
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:876
size_t write_buffer_size
Definition: internal.h:778
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
MHD_ConnectionInfoType
Definition: microhttpd.h:1752
uint64_t data_start
Definition: internal.h:1645
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:741
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1125
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:375
UnescapeCallback unescape_callback
Definition: internal.h:1390
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:1387
int off_t offset
Definition: microhttpd.h:2837
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:4028
#define XDLL_remove(head, tail, element)
Definition: internal.h:1806
unsigned int connection_timeout_dummy
Definition: internal.h:844
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:335
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:699
#define MHD_ERR_BADF_
Definition: internal.h:1885
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1169
size_t pool_size
Definition: internal.h:1430
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2594
struct MHD_itc_ itc
Definition: internal.h:1407
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:736
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
struct MHD_Connection * cleanup_tail
Definition: internal.h:1179
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3324
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2682
enum MHD_ResponseFlags flags
Definition: internal.h:387
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:464
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
struct MHD_HTTP_Header * next
Definition: internal.h:339
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:156
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:760
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2764
size_t write_buffer_append_offset
Definition: internal.h:789
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1132
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1355
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
#define MHD_BUF_INC_SIZE
Definition: internal.h:117
static int socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:497
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:446
bool read_closed
Definition: internal.h:789
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3887
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:766
void * notify_completed_cls
Definition: internal.h:1360
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2370
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:740
#define MHD_ERR_NOTCONN_
Definition: internal.h:1875
struct MemoryPool * pool
Definition: internal.h:682
TransmitCallback send_cls
Definition: internal.h:708
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:703
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:383
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:1597
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2225
MHD_mutex_ mutex
Definition: internal.h:1634
#define XDLL_insert(head, tail, element)
Definition: internal.h:1786
static int socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:640
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
bool suspended
Definition: internal.h:761
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:452
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:311
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
#define MHD_MIN(a, b)
Definition: internal.h:107
static int socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:478
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1163
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:610
size_t read_buffer_offset
Definition: internal.h:773
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:2021
void * default_handler_cls
Definition: internal.h:1246
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1523
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:259
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1262
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:1057
uint64_t current_chunk_size
Definition: internal.h:930
struct MHD_HTTP_Header * headers_received
Definition: internal.h:654
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:310
limits values definitions
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:508
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
_MHD_EXTERN int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:755
#define REQUEST_TOO_BIG
Definition: connection.c:69
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:659
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1419
size_t pool_increment
Definition: internal.h:1435
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:764