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