GNU libmicrohttpd  0.9.59
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  (void)connection; /* Mute compiler warning. */
499 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
500  const MHD_SCKT_OPT_BOOL_ on_val = 1;
501 #if defined(TCP_NODELAY)
502  const MHD_SCKT_OPT_BOOL_ off_val = 0;
503 #endif /* TCP_NODELAY */
504  mhd_assert(NULL != connection);
505 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
506  /* Buffer data before sending */
507  res = (0 == setsockopt (connection->socket_fd,
508  IPPROTO_TCP,
509  TCP_NOPUSH,
510  (const void *) &on_val,
511  sizeof (on_val)))
512  ? MHD_YES : MHD_NO;
513 #if defined(TCP_NODELAY)
514  /* Enable Nagle's algorithm */
515  /* TCP_NODELAY may interfere with TCP_NOPUSH */
516  res &= (0 == setsockopt (connection->socket_fd,
517  IPPROTO_TCP,
518  TCP_NODELAY,
519  (const void *) &off_val,
520  sizeof (off_val)))
521  ? MHD_YES : MHD_NO;
522 #endif /* TCP_NODELAY */
523 #else /* TCP_CORK */
524 #if defined(TCP_NODELAY)
525  /* Enable Nagle's algorithm */
526  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
527  solely on TCP_CORK result, so ignoring return code here. */
528  (void) setsockopt (connection->socket_fd,
529  IPPROTO_TCP,
530  TCP_NODELAY,
531  (const void *) &off_val,
532  sizeof (off_val));
533 #endif /* TCP_NODELAY */
534  /* Send only full packets */
535  res = (0 == setsockopt (connection->socket_fd,
536  IPPROTO_TCP,
537  TCP_CORK,
538  (const void *) &on_val,
539  sizeof (on_val)))
540  ? MHD_YES : MHD_NO;
541 #endif /* TCP_CORK */
542 #endif /* TCP_CORK || TCP_NOPUSH */
543  return res;
544 }
545 
546 
553 static int
555 {
556 #if defined(TCP_NODELAY)
557  int res = MHD_YES;
558  const MHD_SCKT_OPT_BOOL_ on_val = 1;
559 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
560  const MHD_SCKT_OPT_BOOL_ off_val = 0;
561 #endif /* TCP_CORK || TCP_NOPUSH */
562 
563  (void)connection; /* Mute compiler warning. */
564  mhd_assert(NULL != connection);
565 #if defined(TCP_CORK)
566  /* Allow partial packets */
567  res &= (0 == setsockopt (connection->socket_fd,
568  IPPROTO_TCP,
569  TCP_CORK,
570  (const void *) &off_val,
571  sizeof (off_val)))
572  ? MHD_YES : MHD_NO;
573 #endif /* TCP_CORK */
574 #if defined(TCP_NODELAY)
575  /* Disable Nagle's algorithm for sending packets without delay */
576  res &= (0 == setsockopt (connection->socket_fd,
577  IPPROTO_TCP,
578  TCP_NODELAY,
579  (const void *) &on_val,
580  sizeof (on_val)))
581  ? MHD_YES : MHD_NO;
582 #endif /* TCP_NODELAY */
583 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
584  /* Disable extra buffering */
585  res &= (0 == setsockopt (connection->socket_fd,
586  IPPROTO_TCP,
587  TCP_NOPUSH,
588  (const void *) &off_val,
589  sizeof (off_val)))
590  ? MHD_YES : MHD_NO;
591 #endif /* TCP_NOPUSH && !TCP_CORK */
592  return res;
593 #else /* !TCP_NODELAY */
594  return MHD_NO;
595 #endif /* !TCP_NODELAY */
596 }
597 
598 
606 static int
608 {
609  int res = MHD_YES;
610 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
611  const int dummy = 0;
612 #endif /* !TCP_CORK */
613 
614  if (NULL == connection)
615  return MHD_NO;
616  res = socket_start_no_buffering (connection);
617 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
618  /* Force flush data with zero send otherwise Darwin and some BSD systems
619  will add 5 seconds delay. Not required with TCP_CORK as switching off
620  TCP_CORK always flushes socket buffer. */
621  res &= (0 <= MHD_send_ (connection->socket_fd,
622  &dummy,
623  0))
624  ? MHD_YES : MHD_NO;
625 #endif /* TCP_NOPUSH && !TCP_CORK*/
626  return res;
627 }
628 
629 
636 static int
638 {
639 #if defined(TCP_NODELAY)
640  int res = MHD_YES;
641  const MHD_SCKT_OPT_BOOL_ off_val = 0;
642 #if defined(TCP_CORK)
643  MHD_SCKT_OPT_BOOL_ cork_val = 0;
644  socklen_t param_size = sizeof (cork_val);
645 #endif /* TCP_CORK */
646  mhd_assert(NULL != connection);
647 #if defined(TCP_CORK)
648  /* Allow partial packets */
649  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
650  so try to check current value of TCP_CORK to prevent unrequested flushing */
651  if ( (0 != getsockopt (connection->socket_fd,
652  IPPROTO_TCP,
653  TCP_CORK,
654  (void*)&cork_val,
655  &param_size)) ||
656  (0 != cork_val))
657  res &= (0 == setsockopt (connection->socket_fd,
658  IPPROTO_TCP,
659  TCP_CORK,
660  (const void *) &off_val,
661  sizeof (off_val)))
662  ? MHD_YES : MHD_NO;
663 #elif defined(TCP_NOPUSH)
664  /* Disable extra buffering */
665  /* No need to check current value as disabling TCP_NOPUSH will not flush partial
666  packet if TCP_NOPUSH wasn't enabled before */
667  res &= (0 == setsockopt (connection->socket_fd,
668  IPPROTO_TCP,
669  TCP_NOPUSH,
670  (const void *) &off_val,
671  sizeof (off_val)))
672  ? MHD_YES : MHD_NO;
673 #endif /* TCP_NOPUSH && !TCP_CORK */
674  /* Enable Nagle's algorithm for normal buffering */
675  res &= (0 == setsockopt (connection->socket_fd,
676  IPPROTO_TCP,
677  TCP_NODELAY,
678  (const void *) &off_val,
679  sizeof (off_val)))
680  ? MHD_YES : MHD_NO;
681  return res;
682 #else /* !TCP_NODELAY */
683  return MHD_NO;
684 #endif /* !TCP_NODELAY */
685 }
686 
687 
699 int
701  enum MHD_ValueKind kind,
702  MHD_KeyValueIterator iterator,
703  void *iterator_cls)
704 {
705  int ret;
706  struct MHD_HTTP_Header *pos;
707 
708  if (NULL == connection)
709  return -1;
710  ret = 0;
711  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
712  if (0 != (pos->kind & kind))
713  {
714  ret++;
715  if ( (NULL != iterator) &&
716  (MHD_YES != iterator (iterator_cls,
717  pos->kind,
718  pos->header,
719  pos->value)) )
720  return ret;
721  }
722  return ret;
723 }
724 
725 
751 int
753  enum MHD_ValueKind kind,
754  const char *key,
755  const char *value)
756 {
757  struct MHD_HTTP_Header *pos;
758 
759  pos = MHD_pool_allocate (connection->pool,
760  sizeof (struct MHD_HTTP_Header),
761  MHD_YES);
762  if (NULL == pos)
763  return MHD_NO;
764  pos->header = (char *) key;
765  pos->value = (char *) value;
766  pos->kind = kind;
767  pos->next = NULL;
768  /* append 'pos' to the linked list of headers */
769  if (NULL == connection->headers_received_tail)
770  {
771  connection->headers_received = pos;
772  connection->headers_received_tail = pos;
773  }
774  else
775  {
776  connection->headers_received_tail->next = pos;
777  connection->headers_received_tail = pos;
778  }
779  return MHD_YES;
780 }
781 
782 
793 const char *
795  enum MHD_ValueKind kind,
796  const char *key)
797 {
798  struct MHD_HTTP_Header *pos;
799 
800  if (NULL == connection)
801  return NULL;
802  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
803  if ((0 != (pos->kind & kind)) &&
804  ( (key == pos->header) ||
805  ( (NULL != pos->header) &&
806  (NULL != key) &&
808  pos->header)))))
809  return pos->value;
810  return NULL;
811 }
812 
813 
827 static bool
828 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
829  const char *header,
830  const char *token,
831  size_t token_len)
832 {
833  struct MHD_HTTP_Header *pos;
834 
835  if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0])
836  return false;
837  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
838  {
839  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
840  ( (header == pos->header) ||
842  pos->header)) ) &&
843  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
844  return true;
845  }
846  return false;
847 }
848 
849 
861 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
862  MHD_lookup_header_token_ci((c),(h),(tkn),MHD_STATICSTR_LEN_(tkn))
863 
864 
872 static int
873 need_100_continue (struct MHD_Connection *connection)
874 {
875  const char *expect;
876 
877  return ( (NULL == connection->response) &&
878  (NULL != connection->version) &&
879  (MHD_str_equal_caseless_(connection->version,
881  (NULL != (expect = MHD_lookup_connection_value (connection,
884  (MHD_str_equal_caseless_(expect,
885  "100-continue")) &&
886  (connection->continue_message_write_offset <
888 }
889 
890 
897 void
899 {
900  const struct MHD_Daemon *daemon = connection->daemon;
901 
902  connection->state = MHD_CONNECTION_CLOSED;
904  if (0 == (daemon->options & MHD_USE_TURBO))
905  {
906 #ifdef HTTPS_SUPPORT
907  /* For TLS connection use shutdown of TLS layer
908  * and do not shutdown TCP socket. This give more
909  * chances to send TLS closure data to remote side.
910  * Closure of TLS layer will be interpreted by
911  * remote side as end of transmission. */
912  if (0 != (daemon->options & MHD_USE_TLS))
913  {
914  if (! MHD_tls_connection_shutdown(connection))
915  shutdown (connection->socket_fd,
916  SHUT_WR);
917  }
918  else /* Combined with next 'shutdown()'. */
919 #endif /* HTTPS_SUPPORT */
920  shutdown (connection->socket_fd,
921  SHUT_WR);
922  }
923 }
924 
925 
935 void
937  enum MHD_RequestTerminationCode termination_code)
938 {
939  struct MHD_Daemon *daemon = connection->daemon;
940  struct MHD_Response *resp = connection->response;
941 
942  MHD_connection_mark_closed_ (connection);
943  if (NULL != resp)
944  {
945  connection->response = NULL;
946  MHD_destroy_response (resp);
947  }
948  if ( (NULL != daemon->notify_completed) &&
949  (connection->client_aware) )
950  daemon->notify_completed (daemon->notify_completed_cls,
951  connection,
952  &connection->client_context,
953  termination_code);
954  connection->client_aware = false;
955 }
956 
957 
958 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
959 
969 void
971 {
972  struct MHD_Daemon *daemon = connection->daemon;
973  struct MHD_UpgradeResponseHandle *urh = connection->urh;
974 
975  if (0 == (daemon->options & MHD_USE_TLS))
976  return; /* Nothing to do with non-TLS connection. */
977 
978  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
979  DLL_remove (daemon->urh_head,
980  daemon->urh_tail,
981  urh);
982 #if EPOLL_SUPPORT
983  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
984  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
985  EPOLL_CTL_DEL,
986  connection->socket_fd,
987  NULL)) )
988  {
989  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
990  }
991  if (urh->in_eready_list)
992  {
993  EDLL_remove (daemon->eready_urh_head,
994  daemon->eready_urh_tail,
995  urh);
996  urh->in_eready_list = false;
997  }
998 #endif /* EPOLL_SUPPORT */
999  if (MHD_INVALID_SOCKET != urh->mhd.socket)
1000  {
1001 #if EPOLL_SUPPORT
1002  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
1003  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1004  EPOLL_CTL_DEL,
1005  urh->mhd.socket,
1006  NULL)) )
1007  {
1008  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
1009  }
1010 #endif /* EPOLL_SUPPORT */
1011  /* Reflect remote disconnect to application by breaking
1012  * socketpair connection. */
1013  shutdown (urh->mhd.socket, SHUT_RDWR);
1014  }
1015  /* Socketpair sockets will remain open as they will be
1016  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
1017  * closed by MHD_cleanup_upgraded_connection_() during
1018  * connection's final cleanup.
1019  */
1020 }
1021 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
1022 
1023 
1031 static void
1033  const char *emsg)
1034 {
1035 #ifdef HAVE_MESSAGES
1036  if (NULL != emsg)
1037  MHD_DLOG (connection->daemon,
1038  emsg);
1039 #else /* ! HAVE_MESSAGES */
1040  (void)emsg; /* Mute compiler warning. */
1041 #endif /* ! HAVE_MESSAGES */
1042  MHD_connection_close_ (connection,
1044 }
1045 
1046 
1051 #ifdef HAVE_MESSAGES
1052 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
1053 #else
1054 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
1055 #endif
1056 
1057 
1070 static int
1072 {
1073  ssize_t ret;
1074  struct MHD_Response *response;
1075 
1076  response = connection->response;
1077  if (NULL == response->crc)
1078  return MHD_YES;
1079  if ( (0 == response->total_size) ||
1080  (connection->response_write_position == response->total_size) )
1081  return MHD_YES; /* 0-byte response is always ready */
1082  if ( (response->data_start <=
1083  connection->response_write_position) &&
1084  (response->data_size + response->data_start >
1085  connection->response_write_position) )
1086  return MHD_YES; /* response already ready */
1087 #if defined(_MHD_HAVE_SENDFILE)
1088  if (MHD_resp_sender_sendfile == connection->resp_sender)
1089  {
1090  /* will use sendfile, no need to bother response crc */
1091  return MHD_YES;
1092  }
1093 #endif /* _MHD_HAVE_SENDFILE */
1094 
1095  ret = response->crc (response->crc_cls,
1096  connection->response_write_position,
1097  response->data,
1098  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
1099  response->total_size -
1100  connection->response_write_position));
1101  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1102  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
1103  {
1104  /* either error or http 1.0 transfer, close socket! */
1105  response->total_size = connection->response_write_position;
1106  MHD_mutex_unlock_chk_ (&response->mutex);
1107  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
1108  MHD_connection_close_ (connection,
1110  else
1111  CONNECTION_CLOSE_ERROR (connection,
1112  _("Closing connection (application reported error generating data)\n"));
1113  return MHD_NO;
1114  }
1115  response->data_start = connection->response_write_position;
1116  response->data_size = ret;
1117  if (0 == ret)
1118  {
1120  MHD_mutex_unlock_chk_ (&response->mutex);
1121  return MHD_NO;
1122  }
1123  return MHD_YES;
1124 }
1125 
1126 
1136 static int
1138 {
1139  ssize_t ret;
1140  char *buf;
1141  struct MHD_Response *response;
1142  size_t size;
1143  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
1144  int cblen;
1145 
1146  response = connection->response;
1147  if (NULL == response->crc)
1148  return MHD_YES;
1149  if (0 == connection->write_buffer_size)
1150  {
1151  size = MHD_MIN (connection->daemon->pool_size,
1152  2 * (0xFFFFFF + sizeof(cbuf) + 2));
1153  do
1154  {
1155  size /= 2;
1156  if (size < 128)
1157  {
1158  MHD_mutex_unlock_chk_ (&response->mutex);
1159  /* not enough memory */
1160  CONNECTION_CLOSE_ERROR (connection,
1161  _("Closing connection (out of memory)\n"));
1162  return MHD_NO;
1163  }
1164  buf = MHD_pool_allocate (connection->pool,
1165  size,
1166  MHD_NO);
1167  }
1168  while (NULL == buf);
1169  connection->write_buffer_size = size;
1170  connection->write_buffer = buf;
1171  }
1172 
1173  if (0 == response->total_size)
1174  ret = 0; /* response must be empty, don't bother calling crc */
1175  else if ( (response->data_start <=
1176  connection->response_write_position) &&
1177  (response->data_start + response->data_size >
1178  connection->response_write_position) )
1179  {
1180  /* difference between response_write_position and data_start is less
1181  than data_size which is size_t type, no need to check for overflow */
1182  const size_t data_write_offset
1183  = (size_t)(connection->response_write_position - response->data_start);
1184  /* buffer already ready, use what is there for the chunk */
1185  ret = response->data_size - data_write_offset;
1186  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
1187  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
1188  memcpy (&connection->write_buffer[sizeof (cbuf)],
1189  &response->data[data_write_offset],
1190  ret);
1191  }
1192  else
1193  {
1194  /* buffer not in range, try to fill it */
1195  ret = response->crc (response->crc_cls,
1196  connection->response_write_position,
1197  &connection->write_buffer[sizeof (cbuf)],
1198  connection->write_buffer_size - sizeof (cbuf) - 2);
1199  }
1200  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
1201  {
1202  /* error, close socket! */
1203  response->total_size = connection->response_write_position;
1204  MHD_mutex_unlock_chk_ (&response->mutex);
1205  CONNECTION_CLOSE_ERROR (connection,
1206  _("Closing connection (application error generating response)\n"));
1207  return MHD_NO;
1208  }
1209  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
1210  (0 == response->total_size) )
1211  {
1212  /* end of message, signal other side! */
1213  strcpy (connection->write_buffer,
1214  "0\r\n");
1215  connection->write_buffer_append_offset = 3;
1216  connection->write_buffer_send_offset = 0;
1217  response->total_size = connection->response_write_position;
1218  return MHD_YES;
1219  }
1220  if (0 == ret)
1221  {
1223  MHD_mutex_unlock_chk_ (&response->mutex);
1224  return MHD_NO;
1225  }
1226  if (ret > 0xFFFFFF)
1227  ret = 0xFFFFFF;
1228  cblen = MHD_snprintf_(cbuf,
1229  sizeof (cbuf),
1230  "%X\r\n",
1231  (unsigned int) ret);
1232  mhd_assert(cblen > 0);
1233  mhd_assert((size_t)cblen < sizeof(cbuf));
1234  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
1235  cbuf,
1236  cblen);
1237  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
1238  "\r\n",
1239  2);
1240  connection->response_write_position += ret;
1241  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
1242  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
1243  return MHD_YES;
1244 }
1245 
1246 
1263 static int
1265 {
1266  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
1267  return MHD_NO;
1268  if (NULL == connection->version)
1269  return MHD_NO;
1270  if ( (NULL != connection->response) &&
1271  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1272  return MHD_NO;
1273 
1274  if (MHD_str_equal_caseless_(connection->version,
1276  {
1277  if (MHD_lookup_header_s_token_ci (connection,
1279  "upgrade"))
1280  return MHD_NO;
1281 
1282  if (MHD_lookup_header_s_token_ci (connection,
1284  "close"))
1285  return MHD_NO;
1286 
1287  return MHD_YES;
1288  }
1289  if (MHD_str_equal_caseless_(connection->version,
1291  {
1292  if (MHD_lookup_header_s_token_ci (connection,
1294  "Keep-Alive"))
1295  return MHD_YES;
1296 
1297  return MHD_NO;
1298  }
1299  return MHD_NO;
1300 }
1301 
1302 
1310 static void
1311 get_date_string (char *date,
1312  size_t date_len)
1313 {
1314  static const char *const days[] = {
1315  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1316  };
1317  static const char *const mons[] = {
1318  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1319  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1320  };
1321  struct tm now;
1322  time_t t;
1323 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
1324  struct tm* pNow;
1325 #endif
1326 
1327  date[0] = 0;
1328  time (&t);
1329 #if defined(HAVE_C11_GMTIME_S)
1330  if (NULL == gmtime_s (&t,
1331  &now))
1332  return;
1333 #elif defined(HAVE_W32_GMTIME_S)
1334  if (0 != gmtime_s (&now,
1335  &t))
1336  return;
1337 #elif defined(HAVE_GMTIME_R)
1338  if (NULL == gmtime_r(&t,
1339  &now))
1340  return;
1341 #else
1342  pNow = gmtime(&t);
1343  if (NULL == pNow)
1344  return;
1345  now = *pNow;
1346 #endif
1347  MHD_snprintf_ (date,
1348  date_len,
1349  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1350  days[now.tm_wday % 7],
1351  (unsigned int) now.tm_mday,
1352  mons[now.tm_mon % 12],
1353  (unsigned int) (1900 + now.tm_year),
1354  (unsigned int) now.tm_hour,
1355  (unsigned int) now.tm_min,
1356  (unsigned int) now.tm_sec);
1357 }
1358 
1359 
1370 static int
1372 {
1373  void *buf;
1374  size_t new_size;
1375 
1376  if (0 == connection->read_buffer_size)
1377  new_size = connection->daemon->pool_size / 2;
1378  else
1379  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
1380  buf = MHD_pool_reallocate (connection->pool,
1381  connection->read_buffer,
1382  connection->read_buffer_size,
1383  new_size);
1384  if (NULL == buf)
1385  return MHD_NO;
1386  /* we can actually grow the buffer, do it! */
1387  connection->read_buffer = buf;
1388  connection->read_buffer_size = new_size;
1389  return MHD_YES;
1390 }
1391 
1392 
1402 static int
1404 {
1405  size_t size;
1406  size_t off;
1407  struct MHD_HTTP_Header *pos;
1408  char code[256];
1409  char date[128];
1410  char content_length_buf[128];
1411  size_t content_length_len;
1412  char *data;
1413  enum MHD_ValueKind kind;
1414  const char *reason_phrase;
1415  uint32_t rc;
1416  bool client_requested_close;
1417  bool response_has_close;
1418  bool response_has_keepalive;
1419  const char *have_encoding;
1420  const char *have_content_length;
1421  int must_add_close;
1422  int must_add_chunked_encoding;
1423  int must_add_keep_alive;
1424  int must_add_content_length;
1425 
1426  mhd_assert (NULL != connection->version);
1427  if (0 == connection->version[0])
1428  {
1429  data = MHD_pool_allocate (connection->pool,
1430  0,
1431  MHD_YES);
1432  connection->write_buffer = data;
1433  connection->write_buffer_append_offset = 0;
1434  connection->write_buffer_send_offset = 0;
1435  connection->write_buffer_size = 0;
1436  return MHD_YES;
1437  }
1438  rc = connection->responseCode & (~MHD_ICY_FLAG);
1439  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1440  {
1441  reason_phrase = MHD_get_reason_phrase_for (rc);
1442  MHD_snprintf_ (code,
1443  sizeof (code),
1444  "%s %u %s\r\n",
1445  (0 != (connection->responseCode & MHD_ICY_FLAG))
1446  ? "ICY"
1448  connection->version))
1451  rc,
1452  reason_phrase);
1453  off = strlen (code);
1454  /* estimate size */
1455  size = off + 2; /* +2 for extra "\r\n" at the end */
1457  if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1458  (NULL == MHD_get_response_header (connection->response,
1460  get_date_string (date,
1461  sizeof (date));
1462  else
1463  date[0] = '\0';
1464  size += strlen (date);
1465  }
1466  else
1467  {
1468  /* 2 bytes for final CRLF of a Chunked-Body */
1469  size = 2;
1471  off = 0;
1472  }
1473 
1474  /* calculate extra headers we need to add, such as 'Connection: close',
1475  first see what was explicitly requested by the application */
1476  must_add_close = MHD_NO;
1477  must_add_chunked_encoding = MHD_NO;
1478  must_add_keep_alive = MHD_NO;
1479  must_add_content_length = MHD_NO;
1480  response_has_close = false;
1481  response_has_keepalive = false;
1482  switch (connection->state)
1483  {
1485  response_has_close = MHD_check_response_header_s_token_ci (connection->response,
1487  "close");
1488  response_has_keepalive = MHD_check_response_header_s_token_ci (connection->response,
1490  "Keep-Alive");
1491  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1493  "close");
1494 
1495  if (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1496  connection->keepalive = MHD_CONN_MUST_CLOSE;
1497 #ifdef UPGRADE_SUPPORT
1498  else if (NULL != connection->response->upgrade_handler)
1499  /* If this connection will not be "upgraded", it must be closed. */
1500  connection->keepalive = MHD_CONN_MUST_CLOSE;
1501 #endif /* UPGRADE_SUPPORT */
1502 
1503  /* now analyze chunked encoding situation */
1504  connection->have_chunked_upload = false;
1505 
1506  if ( (MHD_SIZE_UNKNOWN == connection->response->total_size) &&
1507 #ifdef UPGRADE_SUPPORT
1508  (NULL == connection->response->upgrade_handler) &&
1509 #endif /* UPGRADE_SUPPORT */
1510  (! response_has_close) &&
1511  (! client_requested_close) )
1512  {
1513  /* size is unknown, and close was not explicitly requested;
1514  need to either to HTTP 1.1 chunked encoding or
1515  close the connection */
1516  /* 'close' header doesn't exist yet, see if we need to add one;
1517  if the client asked for a close, no need to start chunk'ing */
1518  if ( (MHD_YES == keepalive_possible (connection)) &&
1520  connection->version) ) )
1521  {
1522  have_encoding = MHD_get_response_header (connection->response,
1524  if (NULL == have_encoding)
1525  {
1526  must_add_chunked_encoding = MHD_YES;
1527  connection->have_chunked_upload = true;
1528  }
1529  else if (MHD_str_equal_caseless_ (have_encoding,
1530  "identity"))
1531  {
1532  /* application forced identity encoding, can't do 'chunked' */
1533  must_add_close = MHD_YES;
1534  }
1535  else
1536  {
1537  connection->have_chunked_upload = true;
1538  }
1539  }
1540  else
1541  {
1542  /* Keep alive or chunking not possible
1543  => set close header if not present */
1544  if (! response_has_close)
1545  must_add_close = MHD_YES;
1546  }
1547  }
1548 
1549  /* check for other reasons to add 'close' header */
1550  if ( ( (client_requested_close) ||
1551  (connection->read_closed) ||
1552  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1553  (! response_has_close) &&
1554 #ifdef UPGRADE_SUPPORT
1555  (NULL == connection->response->upgrade_handler) &&
1556 #endif /* UPGRADE_SUPPORT */
1557  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1558  must_add_close = MHD_YES;
1559 
1560  /* check if we should add a 'content length' header */
1561  have_content_length = MHD_get_response_header (connection->response,
1563 
1564  /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1565  codes SHOULD NOT have a Content-Length according to spec;
1566  also chunked encoding / unknown length or CONNECT... */
1567  if ( (MHD_SIZE_UNKNOWN != connection->response->total_size) &&
1568  (MHD_HTTP_NO_CONTENT != rc) &&
1569  (MHD_HTTP_NOT_MODIFIED != rc) &&
1570  (MHD_HTTP_OK <= rc) &&
1571  (NULL == have_content_length) &&
1572  ( (NULL == connection->method) ||
1573  (! MHD_str_equal_caseless_ (connection->method,
1575  {
1576  /*
1577  Here we add a content-length if one is missing; however,
1578  for 'connect' methods, the responses MUST NOT include a
1579  content-length header *if* the response code is 2xx (in
1580  which case we expect there to be no body). Still,
1581  as we don't know the response code here in some cases, we
1582  simply only force adding a content-length header if this
1583  is not a 'connect' or if the response is not empty
1584  (which is kind of more sane, because if some crazy
1585  application did return content with a 2xx status code,
1586  then having a content-length might again be a good idea).
1587 
1588  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1589  a recent development of the HTTP 1.1 specification.
1590  */
1591  content_length_len
1592  = MHD_snprintf_ (content_length_buf,
1593  sizeof (content_length_buf),
1595  (MHD_UNSIGNED_LONG_LONG) connection->response->total_size);
1596  must_add_content_length = MHD_YES;
1597  }
1598 
1599  /* check for adding keep alive */
1600  if ( (! response_has_keepalive) &&
1601  (! response_has_close) &&
1602  (MHD_NO == must_add_close) &&
1603  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1604 #ifdef UPGRADE_SUPPORT
1605  (NULL == connection->response->upgrade_handler) &&
1606 #endif /* UPGRADE_SUPPORT */
1607  (MHD_YES == keepalive_possible (connection)) )
1608  must_add_keep_alive = MHD_YES;
1609  break;
1611  response_has_keepalive = false;
1612  break;
1613  default:
1614  mhd_assert (0);
1615  }
1616 
1617  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1618  {
1619  if ( (must_add_close) || (response_has_close) )
1620  connection->keepalive = MHD_CONN_MUST_CLOSE;
1621  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1622  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1623  }
1624 
1625  if (must_add_close)
1626  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1627  if (must_add_keep_alive)
1628  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1629  if (must_add_chunked_encoding)
1630  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1631  if (must_add_content_length)
1632  size += content_length_len;
1633  mhd_assert (! (must_add_close && must_add_keep_alive) );
1634  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1635 
1636  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1637  {
1638  /* TODO: add proper support for excluding "Keep-Alive" token. */
1639  if ( (pos->kind == kind) &&
1640  (! ( (MHD_YES == must_add_close) &&
1641  (response_has_keepalive) &&
1645  "Keep-Alive")) ) ) )
1646  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1647  }
1648  /* produce data */
1649  data = MHD_pool_allocate (connection->pool,
1650  size + 1,
1651  MHD_NO);
1652  if (NULL == data)
1653  {
1654 #ifdef HAVE_MESSAGES
1655  MHD_DLOG (connection->daemon,
1656  "Not enough memory for write!\n");
1657 #endif
1658  return MHD_NO;
1659  }
1660  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1661  {
1662  memcpy (data,
1663  code,
1664  off);
1665  }
1666  if (must_add_close)
1667  {
1668  /* we must add the 'Connection: close' header */
1669  memcpy (&data[off],
1670  "Connection: close\r\n",
1671  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1672  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1673  }
1674  if (must_add_keep_alive)
1675  {
1676  /* we must add the 'Connection: Keep-Alive' header */
1677  memcpy (&data[off],
1678  "Connection: Keep-Alive\r\n",
1679  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1680  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1681  }
1682  if (must_add_chunked_encoding)
1683  {
1684  /* we must add the 'Transfer-Encoding: chunked' header */
1685  memcpy (&data[off],
1686  "Transfer-Encoding: chunked\r\n",
1687  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1688  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1689  }
1690  if (must_add_content_length)
1691  {
1692  /* we must add the 'Content-Length' header */
1693  memcpy (&data[off],
1694  content_length_buf,
1695  content_length_len);
1696  off += content_length_len;
1697  }
1698  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1699  {
1700  /* TODO: add proper support for excluding "Keep-Alive" token. */
1701  if ( (pos->kind == kind) &&
1702  (! ( (MHD_YES == must_add_close) &&
1703  (response_has_keepalive) &&
1707  "Keep-Alive")) ) ) )
1708  off += MHD_snprintf_ (&data[off],
1709  size - off,
1710  "%s: %s\r\n",
1711  pos->header,
1712  pos->value);
1713  }
1714  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1715  {
1716  strcpy (&data[off],
1717  date);
1718  off += strlen (date);
1719  }
1720  memcpy (&data[off],
1721  "\r\n",
1722  2);
1723  off += 2;
1724 
1725  if (off != size)
1727  __FILE__,
1728  __LINE__,
1729  NULL);
1730  connection->write_buffer = data;
1731  connection->write_buffer_append_offset = size;
1732  connection->write_buffer_send_offset = 0;
1733  connection->write_buffer_size = size + 1;
1734  return MHD_YES;
1735 }
1736 
1737 
1747 static void
1749  unsigned int status_code,
1750  const char *message)
1751 {
1752  struct MHD_Response *response;
1753 
1754  if (NULL == connection->version)
1755  {
1756  /* we were unable to process the full header line, so we don't
1757  really know what version the client speaks; assume 1.0 */
1758  connection->version = MHD_HTTP_VERSION_1_0;
1759  }
1760  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1761  connection->read_closed = true;
1762 #ifdef HAVE_MESSAGES
1763  MHD_DLOG (connection->daemon,
1764  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1765  status_code,
1766  message);
1767 #endif
1768  if (NULL != connection->response)
1769  {
1770  MHD_destroy_response (connection->response);
1771  connection->response = NULL;
1772  }
1773  response = MHD_create_response_from_buffer (strlen (message),
1774  (void *) message,
1776  MHD_queue_response (connection,
1777  status_code,
1778  response);
1779  mhd_assert (NULL != connection->response);
1780  MHD_destroy_response (response);
1781  /* Do not reuse this connection. */
1782  connection->keepalive = MHD_CONN_MUST_CLOSE;
1783  if (MHD_NO == build_header_response (connection))
1784  {
1785  /* oops - close! */
1786  CONNECTION_CLOSE_ERROR (connection,
1787  _("Closing connection (failed to create response header)\n"));
1788  }
1789  else
1790  {
1791  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1792  }
1793 }
1794 
1795 
1804 static void
1806 {
1807  /* Do not update states of suspended connection */
1808  if (connection->suspended)
1809  return; /* States will be updated after resume. */
1810 #ifdef HTTPS_SUPPORT
1811  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
1812  { /* HTTPS connection. */
1813  switch (connection->tls_state)
1814  {
1815  case MHD_TLS_CONN_INIT:
1817  return;
1819  if (0 == gnutls_record_get_direction (connection->tls_session))
1821  else
1823  return;
1824  default:
1825  break;
1826  }
1827  }
1828 #endif /* HTTPS_SUPPORT */
1829  while (1)
1830  {
1831 #if DEBUG_STATES
1832  MHD_DLOG (connection->daemon,
1833  _("In function %s handling connection at state: %s\n"),
1834  __FUNCTION__,
1835  MHD_state_to_string (connection->state));
1836 #endif
1837  switch (connection->state)
1838  {
1839  case MHD_CONNECTION_INIT:
1842  /* while reading headers, we always grow the
1843  read buffer if needed, no size-check required */
1844  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1845  (MHD_NO == try_grow_read_buffer (connection)) )
1846  {
1847  transmit_error_response (connection,
1848  (connection->url != NULL)
1851  REQUEST_TOO_BIG);
1852  continue;
1853  }
1854  if (! connection->read_closed)
1856  else
1858  break;
1860  mhd_assert (0);
1861  break;
1863  mhd_assert (0);
1864  break;
1867  break;
1869  if (connection->read_buffer_offset == connection->read_buffer_size)
1870  {
1871  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1872  (0 != (connection->daemon->options &
1874  {
1875  /* failed to grow the read buffer, and the
1876  client which is supposed to handle the
1877  received data in a *blocking* fashion
1878  (in this mode) did not handle the data as
1879  it was supposed to!
1880  => we would either have to do busy-waiting
1881  (on the client, which would likely fail),
1882  or if we do nothing, we would just timeout
1883  on the connection (if a timeout is even
1884  set!).
1885  Solution: we kill the connection with an error */
1886  transmit_error_response (connection,
1888  INTERNAL_ERROR);
1889  continue;
1890  }
1891  }
1892  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1893  (! connection->read_closed) )
1895  else
1897  break;
1900  /* while reading footers, we always grow the
1901  read buffer if needed, no size-check required */
1902  if (connection->read_closed)
1903  {
1904  CONNECTION_CLOSE_ERROR (connection,
1905  NULL);
1906  continue;
1907  }
1909  /* transition to FOOTERS_RECEIVED
1910  happens in read handler */
1911  break;
1914  break;
1916  /* headers in buffer, keep writing */
1918  break;
1920  mhd_assert (0);
1921  break;
1924  break;
1927  break;
1930  break;
1933  break;
1935  mhd_assert (0);
1936  break;
1939  break;
1941  mhd_assert (0);
1942  break;
1943  case MHD_CONNECTION_CLOSED:
1945  return; /* do nothing, not even reading */
1947  mhd_assert (0);
1948  break;
1949 #ifdef UPGRADE_SUPPORT
1950  case MHD_CONNECTION_UPGRADE:
1951  mhd_assert (0);
1952  break;
1953 #endif /* UPGRADE_SUPPORT */
1954  default:
1955  mhd_assert (0);
1956  }
1957  break;
1958  }
1959 }
1960 
1961 
1975 static char *
1977  size_t *line_len)
1978 {
1979  char *rbuf;
1980  size_t pos;
1981 
1982  if (0 == connection->read_buffer_offset)
1983  return NULL;
1984  pos = 0;
1985  rbuf = connection->read_buffer;
1986  while ( (pos < connection->read_buffer_offset - 1) &&
1987  ('\r' != rbuf[pos]) &&
1988  ('\n' != rbuf[pos]) )
1989  pos++;
1990  if ( (pos == connection->read_buffer_offset - 1) &&
1991  ('\n' != rbuf[pos]) )
1992  {
1993  /* not found, consider growing... */
1994  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1995  (MHD_NO ==
1996  try_grow_read_buffer (connection)) )
1997  {
1998  transmit_error_response (connection,
1999  (NULL != connection->url)
2002  REQUEST_TOO_BIG);
2003  }
2004  if (line_len)
2005  *line_len = 0;
2006  return NULL;
2007  }
2008 
2009  if (line_len)
2010  *line_len = pos;
2011  /* found, check if we have proper LFCR */
2012  if ( ('\r' == rbuf[pos]) &&
2013  ('\n' == rbuf[pos + 1]) )
2014  rbuf[pos++] = '\0'; /* skip both r and n */
2015  rbuf[pos++] = '\0';
2016  connection->read_buffer += pos;
2017  connection->read_buffer_size -= pos;
2018  connection->read_buffer_offset -= pos;
2019  return rbuf;
2020 }
2021 
2022 
2034 static int
2036  const char *key,
2037  const char *value,
2038  enum MHD_ValueKind kind)
2039 {
2040  if (MHD_NO ==
2041  MHD_set_connection_value (connection,
2042  kind,
2043  key,
2044  value))
2045  {
2046 #ifdef HAVE_MESSAGES
2047  MHD_DLOG (connection->daemon,
2048  _("Not enough memory in pool to allocate header record!\n"));
2049 #endif
2050  transmit_error_response (connection,
2052  REQUEST_TOO_BIG);
2053  return MHD_NO;
2054  }
2055  return MHD_YES;
2056 }
2057 
2058 
2065 static int
2067 {
2068  const char *hdr;
2069  char *cpy;
2070  char *pos;
2071  char *sce;
2072  char *semicolon;
2073  char *equals;
2074  char *ekill;
2075  char old;
2076  int quotes;
2077 
2078  hdr = MHD_lookup_connection_value (connection,
2081  if (NULL == hdr)
2082  return MHD_YES;
2083  cpy = MHD_pool_allocate (connection->pool,
2084  strlen (hdr) + 1,
2085  MHD_YES);
2086  if (NULL == cpy)
2087  {
2088 #ifdef HAVE_MESSAGES
2089  MHD_DLOG (connection->daemon,
2090  _("Not enough memory in pool to parse cookies!\n"));
2091 #endif
2092  transmit_error_response (connection,
2094  REQUEST_TOO_BIG);
2095  return MHD_NO;
2096  }
2097  memcpy (cpy,
2098  hdr,
2099  strlen (hdr) + 1);
2100  pos = cpy;
2101  while (NULL != pos)
2102  {
2103  while (' ' == *pos)
2104  pos++; /* skip spaces */
2105 
2106  sce = pos;
2107  while ( ((*sce) != '\0') &&
2108  ((*sce) != ',') &&
2109  ((*sce) != ';') &&
2110  ((*sce) != '=') )
2111  sce++;
2112  /* remove tailing whitespace (if any) from key */
2113  ekill = sce - 1;
2114  while ( (*ekill == ' ') &&
2115  (ekill >= pos) )
2116  *(ekill--) = '\0';
2117  old = *sce;
2118  *sce = '\0';
2119  if (old != '=')
2120  {
2121  /* value part omitted, use empty string... */
2122  if (MHD_NO ==
2123  connection_add_header (connection,
2124  pos,
2125  "",
2126  MHD_COOKIE_KIND))
2127  return MHD_NO;
2128  if (old == '\0')
2129  break;
2130  pos = sce + 1;
2131  continue;
2132  }
2133  equals = sce + 1;
2134  quotes = 0;
2135  semicolon = equals;
2136  while ( ('\0' != semicolon[0]) &&
2137  ( (0 != quotes) ||
2138  ( (';' != semicolon[0]) &&
2139  (',' != semicolon[0]) ) ) )
2140  {
2141  if ('"' == semicolon[0])
2142  quotes = (quotes + 1) & 1;
2143  semicolon++;
2144  }
2145  if ('\0' == semicolon[0])
2146  semicolon = NULL;
2147  if (NULL != semicolon)
2148  {
2149  semicolon[0] = '\0';
2150  semicolon++;
2151  }
2152  /* remove quotes */
2153  if ( ('"' == equals[0]) &&
2154  ('"' == equals[strlen (equals) - 1]) )
2155  {
2156  equals[strlen (equals) - 1] = '\0';
2157  equals++;
2158  }
2159  if (MHD_NO ==
2160  connection_add_header (connection,
2161  pos,
2162  equals,
2163  MHD_COOKIE_KIND))
2164  return MHD_NO;
2165  pos = semicolon;
2166  }
2167  return MHD_YES;
2168 }
2169 
2170 
2179 static int
2181  char *line,
2182  size_t line_len)
2183 {
2184  struct MHD_Daemon *daemon = connection->daemon;
2185  const char *curi;
2186  char *uri;
2187  char *http_version;
2188  char *args;
2189  unsigned int unused_num_headers;
2190 
2191  if (NULL == (uri = memchr (line,
2192  ' ',
2193  line_len)))
2194  return MHD_NO; /* serious error */
2195  uri[0] = '\0';
2196  connection->method = line;
2197  uri++;
2198  /* Skip any spaces. Not required by standard but allow
2199  to be more tolerant. */
2200  while ( (' ' == uri[0]) &&
2201  ( (size_t)(uri - line) < line_len) )
2202  uri++;
2203  if ((size_t)(uri - line) == line_len)
2204  {
2205  curi = "";
2206  uri = NULL;
2207  connection->version = "";
2208  args = NULL;
2209  }
2210  else
2211  {
2212  curi = uri;
2213  /* Search from back to accept misformed URI with space */
2214  http_version = line + line_len - 1;
2215  /* Skip any trailing spaces */
2216  while ( (' ' == http_version[0]) &&
2217  (http_version > uri) )
2218  http_version--;
2219  /* Find first space in reverse direction */
2220  while ( (' ' != http_version[0]) &&
2221  (http_version > uri) )
2222  http_version--;
2223  if (http_version > uri)
2224  {
2225  http_version[0] = '\0';
2226  connection->version = http_version + 1;
2227  args = memchr (uri,
2228  '?',
2229  http_version - uri);
2230  }
2231  else
2232  {
2233  connection->version = "";
2234  args = memchr (uri,
2235  '?',
2236  line_len - (uri - line));
2237  }
2238  }
2239  if (NULL != daemon->uri_log_callback)
2240  {
2241  connection->client_aware = true;
2242  connection->client_context
2243  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
2244  curi,
2245  connection);
2246  }
2247  if (NULL != args)
2248  {
2249  args[0] = '\0';
2250  args++;
2251  /* note that this call clobbers 'args' */
2252  MHD_parse_arguments_ (connection,
2254  args,
2256  &unused_num_headers);
2257  }
2258  if (NULL != uri)
2259  daemon->unescape_callback (daemon->unescape_callback_cls,
2260  connection,
2261  uri);
2262  connection->url = curi;
2263  return MHD_YES;
2264 }
2265 
2266 
2274 static void
2276 {
2277  size_t processed;
2278 
2279  if (NULL != connection->response)
2280  return; /* already queued a response */
2281  processed = 0;
2282  connection->client_aware = true;
2283  if (MHD_NO ==
2284  connection->daemon->default_handler (connection->daemon->default_handler_cls,
2285  connection,
2286  connection->url,
2287  connection->method,
2288  connection->version,
2289  NULL,
2290  &processed,
2291  &connection->client_context))
2292  {
2293  /* serious internal error, close connection */
2294  CONNECTION_CLOSE_ERROR (connection,
2295  _("Application reported internal error, closing connection.\n"));
2296  return;
2297  }
2298 }
2299 
2300 
2301 
2309 static void
2311 {
2312  size_t available;
2313  int instant_retry;
2314  char *buffer_head;
2315 
2316  if (NULL != connection->response)
2317  return; /* already queued a response */
2318 
2319  buffer_head = connection->read_buffer;
2320  available = connection->read_buffer_offset;
2321  do
2322  {
2323  size_t to_be_processed;
2324  size_t left_unprocessed;
2325  size_t processed_size;
2326 
2327  instant_retry = MHD_NO;
2328  if ( (connection->have_chunked_upload) &&
2329  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
2330  {
2331  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
2332  (0LLU != connection->current_chunk_offset) &&
2333  (available >= 2) )
2334  {
2335  size_t i;
2336  /* skip new line at the *end* of a chunk */
2337  i = 0;
2338  if ( ('\r' == buffer_head[i]) ||
2339  ('\n' == buffer_head[i]) )
2340  i++; /* skip 1st part of line feed */
2341  if ( ('\r' == buffer_head[i]) ||
2342  ('\n' == buffer_head[i]) )
2343  i++; /* skip 2nd part of line feed */
2344  if (0 == i)
2345  {
2346  /* malformed encoding */
2347  CONNECTION_CLOSE_ERROR (connection,
2348  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2349  return;
2350  }
2351  available -= i;
2352  buffer_head += i;
2353  connection->current_chunk_offset = 0;
2354  connection->current_chunk_size = 0;
2355  }
2356  if (connection->current_chunk_offset <
2357  connection->current_chunk_size)
2358  {
2359  uint64_t cur_chunk_left;
2360  /* we are in the middle of a chunk, give
2361  as much as possible to the client (without
2362  crossing chunk boundaries) */
2363  cur_chunk_left
2364  = connection->current_chunk_size - connection->current_chunk_offset;
2365  if (cur_chunk_left > available)
2366  to_be_processed = available;
2367  else
2368  { /* cur_chunk_left <= (size_t)available */
2369  to_be_processed = (size_t)cur_chunk_left;
2370  if (available > to_be_processed)
2371  instant_retry = MHD_YES;
2372  }
2373  }
2374  else
2375  {
2376  size_t i;
2377  size_t end_size;
2378  bool malformed;
2379 
2380  /* we need to read chunk boundaries */
2381  i = 0;
2382  while (i < available)
2383  {
2384  if ( ('\r' == buffer_head[i]) ||
2385  ('\n' == buffer_head[i]) ||
2386  (';' == buffer_head[i]) )
2387  break;
2388  i++;
2389  if (i >= 16)
2390  break;
2391  }
2392  end_size = i;
2393  /* find beginning of CRLF (skip over chunk extensions) */
2394  if (';' == buffer_head[i])
2395  {
2396  while (i < available)
2397  {
2398  if ( ('\r' == buffer_head[i]) ||
2399  ('\n' == buffer_head[i]) )
2400  break;
2401  i++;
2402  }
2403  }
2404  /* take '\n' into account; if '\n' is the unavailable
2405  character, we will need to wait until we have it
2406  before going further */
2407  if ( (i + 1 >= available) &&
2408  ! ( (1 == i) &&
2409  (2 == available) &&
2410  ('0' == buffer_head[0]) ) )
2411  break; /* need more data... */
2412  i++;
2413  malformed = (end_size >= 16);
2414  if (! malformed)
2415  {
2416  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2417  end_size,
2418  &connection->current_chunk_size);
2419  malformed = (end_size != num_dig);
2420  }
2421  if (malformed)
2422  {
2423  /* malformed encoding */
2424  CONNECTION_CLOSE_ERROR (connection,
2425  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2426  return;
2427  }
2428  /* skip 2nd part of line feed */
2429  if ( (i < available) &&
2430  ( ('\r' == buffer_head[i]) ||
2431  ('\n' == buffer_head[i]) ) )
2432  i++;
2433 
2434  buffer_head += i;
2435  available -= i;
2436  connection->current_chunk_offset = 0;
2437 
2438  if (available > 0)
2439  instant_retry = MHD_YES;
2440  if (0LLU == connection->current_chunk_size)
2441  {
2442  connection->remaining_upload_size = 0;
2443  break;
2444  }
2445  continue;
2446  }
2447  }
2448  else
2449  {
2450  /* no chunked encoding, give all to the client */
2451  if ( (0 != connection->remaining_upload_size) &&
2452  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2453  (connection->remaining_upload_size < available) )
2454  {
2455  to_be_processed = (size_t)connection->remaining_upload_size;
2456  }
2457  else
2458  {
2463  to_be_processed = available;
2464  }
2465  }
2466  left_unprocessed = to_be_processed;
2467  connection->client_aware = true;
2468  if (MHD_NO ==
2469  connection->daemon->default_handler (connection->daemon->default_handler_cls,
2470  connection,
2471  connection->url,
2472  connection->method,
2473  connection->version,
2474  buffer_head,
2475  &left_unprocessed,
2476  &connection->client_context))
2477  {
2478  /* serious internal error, close connection */
2479  CONNECTION_CLOSE_ERROR (connection,
2480  _("Application reported internal error, closing connection.\n"));
2481  return;
2482  }
2483  if (left_unprocessed > to_be_processed)
2485  __FILE__,
2486  __LINE__
2487 #ifdef HAVE_MESSAGES
2488  , _("libmicrohttpd API violation")
2489 #else
2490  , NULL
2491 #endif
2492  );
2493  if (0 != left_unprocessed)
2494  {
2495  instant_retry = MHD_NO; /* client did not process everything */
2496 #ifdef HAVE_MESSAGES
2497  /* client did not process all upload data, complain if
2498  the setup was incorrect, which may prevent us from
2499  handling the rest of the request */
2500  if ( (0 != (connection->daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2501  (! connection->suspended) )
2502  MHD_DLOG (connection->daemon,
2503  _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2504 #endif
2505  }
2506  processed_size = to_be_processed - left_unprocessed;
2507  if (connection->have_chunked_upload)
2508  connection->current_chunk_offset += processed_size;
2509  /* dh left "processed" bytes in buffer for next time... */
2510  buffer_head += processed_size;
2511  available -= processed_size;
2512  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2513  connection->remaining_upload_size -= processed_size;
2514  }
2515  while (MHD_YES == instant_retry);
2516  if (available > 0)
2517  memmove (connection->read_buffer,
2518  buffer_head,
2519  available);
2520  connection->read_buffer_offset = available;
2521 }
2522 
2523 
2532 static int
2533 check_write_done (struct MHD_Connection *connection,
2534  enum MHD_CONNECTION_STATE next_state)
2535 {
2536  if (connection->write_buffer_append_offset !=
2537  connection->write_buffer_send_offset)
2538  return MHD_NO;
2539  connection->write_buffer_append_offset = 0;
2540  connection->write_buffer_send_offset = 0;
2541  connection->state = next_state;
2542  MHD_pool_reallocate (connection->pool,
2543  connection->write_buffer,
2544  connection->write_buffer_size,
2545  0);
2546  connection->write_buffer = NULL;
2547  connection->write_buffer_size = 0;
2548  return MHD_YES;
2549 }
2550 
2551 
2561 static int
2563  char *line)
2564 {
2565  char *colon;
2566 
2567  /* line should be normal header line, find colon */
2568  colon = strchr (line, ':');
2569  if (NULL == colon)
2570  {
2571  /* error in header line, die hard */
2572  CONNECTION_CLOSE_ERROR (connection,
2573  _("Received malformed line (no colon). Closing connection.\n"));
2574  return MHD_NO;
2575  }
2576  if (-1 >= connection->daemon->strict_for_client)
2577  {
2578  /* check for whitespace before colon, which is not allowed
2579  by RFC 7230 section 3.2.4; we count space ' ' and
2580  tab '\t', but not '\r\n' as those would have ended the line. */
2581  const char *white;
2582 
2583  white = strchr (line, ' ');
2584  if ( (NULL != white) &&
2585  (white < colon) )
2586  return MHD_NO;
2587  white = strchr (line, '\t');
2588  if ( (NULL != white) &&
2589  (white < colon) )
2590  return MHD_NO;
2591  }
2592  /* zero-terminate header */
2593  colon[0] = '\0';
2594  colon++; /* advance to value */
2595  while ( ('\0' != colon[0]) &&
2596  ( (' ' == colon[0]) ||
2597  ('\t' == colon[0]) ) )
2598  colon++;
2599  /* we do the actual adding of the connection
2600  header at the beginning of the while
2601  loop since we need to be able to inspect
2602  the *next* header line (in case it starts
2603  with a space...) */
2604  connection->last = line;
2605  connection->colon = colon;
2606  return MHD_YES;
2607 }
2608 
2609 
2620 static int
2622  char *line,
2623  enum MHD_ValueKind kind)
2624 {
2625  char *last;
2626  char *tmp;
2627  size_t last_len;
2628  size_t tmp_len;
2629 
2630  last = connection->last;
2631  if ( (' ' == line[0]) ||
2632  ('\t' == line[0]) )
2633  {
2634  /* value was continued on the next line, see
2635  http://www.jmarshall.com/easy/http/ */
2636  last_len = strlen (last);
2637  /* skip whitespace at start of 2nd line */
2638  tmp = line;
2639  while ( (' ' == tmp[0]) ||
2640  ('\t' == tmp[0]) )
2641  tmp++;
2642  tmp_len = strlen (tmp);
2643  /* FIXME: we might be able to do this better (faster!), as most
2644  likely 'last' and 'line' should already be adjacent in
2645  memory; however, doing this right gets tricky if we have a
2646  value continued over multiple lines (in which case we need to
2647  record how often we have done this so we can check for
2648  adjacency); also, in the case where these are not adjacent
2649  (not sure how it can happen!), we would want to allocate from
2650  the end of the pool, so as to not destroy the read-buffer's
2651  ability to grow nicely. */
2652  last = MHD_pool_reallocate (connection->pool,
2653  last,
2654  last_len + 1,
2655  last_len + tmp_len + 1);
2656  if (NULL == last)
2657  {
2658  transmit_error_response (connection,
2660  REQUEST_TOO_BIG);
2661  return MHD_NO;
2662  }
2663  memcpy (&last[last_len], tmp, tmp_len + 1);
2664  connection->last = last;
2665  return MHD_YES; /* possibly more than 2 lines... */
2666  }
2667  mhd_assert ( (NULL != last) &&
2668  (NULL != connection->colon) );
2669  if ((MHD_NO == connection_add_header (connection,
2670  last,
2671  connection->colon,
2672  kind)))
2673  {
2674  transmit_error_response (connection,
2676  REQUEST_TOO_BIG);
2677  return MHD_NO;
2678  }
2679  /* we still have the current line to deal with... */
2680  if (0 != line[0])
2681  {
2682  if (MHD_NO == process_header_line (connection,
2683  line))
2684  {
2685  transmit_error_response (connection,
2688  return MHD_NO;
2689  }
2690  }
2691  return MHD_YES;
2692 }
2693 
2694 
2702 static void
2704 {
2705  const char *clen;
2706  struct MHD_Response *response;
2707  const char *enc;
2708  const char *end;
2709 
2710  parse_cookie_header (connection);
2711  if ( (1 <= connection->daemon->strict_for_client) &&
2712  (NULL != connection->version) &&
2714  connection->version)) &&
2715  (NULL ==
2716  MHD_lookup_connection_value (connection,
2719  {
2720  /* die, http 1.1 request without host and we are pedantic */
2721  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2722  connection->read_closed = true;
2723 #ifdef HAVE_MESSAGES
2724  MHD_DLOG (connection->daemon,
2725  _("Received HTTP 1.1 request without `Host' header.\n"));
2726 #endif
2727  mhd_assert (NULL == connection->response);
2728  response =
2732  MHD_queue_response (connection,
2734  response);
2735  MHD_destroy_response (response);
2736  return;
2737  }
2738 
2739  connection->remaining_upload_size = 0;
2740  enc = MHD_lookup_connection_value (connection,
2743  if (NULL != enc)
2744  {
2746  if (MHD_str_equal_caseless_(enc,
2747  "chunked"))
2748  connection->have_chunked_upload = true;
2749  }
2750  else
2751  {
2752  clen = MHD_lookup_connection_value (connection,
2755  if (NULL != clen)
2756  {
2757  end = clen + MHD_str_to_uint64_ (clen,
2758  &connection->remaining_upload_size);
2759  if ( (clen == end) ||
2760  ('\0' != *end) )
2761  {
2762  connection->remaining_upload_size = 0;
2763 #ifdef HAVE_MESSAGES
2764  MHD_DLOG (connection->daemon,
2765  "Failed to parse `Content-Length' header. Closing connection.\n");
2766 #endif
2767  CONNECTION_CLOSE_ERROR (connection,
2768  NULL);
2769  return;
2770  }
2771  }
2772  }
2773 }
2774 
2775 
2783 void
2785 {
2786  struct MHD_Daemon *daemon = connection->daemon;
2787 
2788  if (0 == connection->connection_timeout)
2789  return; /* Skip update of activity for connections
2790  without timeout timer. */
2791  if (connection->suspended)
2792  return; /* no activity on suspended connections */
2793 
2794  connection->last_activity = MHD_monotonic_sec_counter();
2795  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2796  return; /* each connection has personal timeout */
2797 
2798  if (connection->connection_timeout != daemon->connection_timeout)
2799  return; /* custom timeout, no need to move it in "normal" DLL */
2800 
2802  /* move connection to head of timeout list (by remove + add operation) */
2804  daemon->normal_timeout_tail,
2805  connection);
2807  daemon->normal_timeout_tail,
2808  connection);
2810 }
2811 
2812 
2819 void
2821 {
2822  ssize_t bytes_read;
2823 
2824  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2825  (connection->suspended) )
2826  return;
2827 #ifdef HTTPS_SUPPORT
2828  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2829  { /* HTTPS connection. */
2830  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2831  {
2832  if (!MHD_run_tls_handshake_ (connection))
2833  return;
2834  }
2835  }
2836 #endif /* HTTPS_SUPPORT */
2837 
2838  /* make sure "read" has a reasonable number of bytes
2839  in buffer to use per system call (if possible) */
2840  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2841  connection->read_buffer_size)
2842  try_grow_read_buffer (connection);
2843 
2844  if (connection->read_buffer_size == connection->read_buffer_offset)
2845  return; /* No space for receiving data. */
2846  bytes_read = connection->recv_cls (connection,
2847  &connection->read_buffer
2848  [connection->read_buffer_offset],
2849  connection->read_buffer_size -
2850  connection->read_buffer_offset);
2851  if (bytes_read < 0)
2852  {
2853  if (MHD_ERR_AGAIN_ == bytes_read)
2854  return; /* No new data to process. */
2855  if (MHD_ERR_CONNRESET_ == bytes_read)
2856  {
2857  CONNECTION_CLOSE_ERROR (connection,
2858  (MHD_CONNECTION_INIT == connection->state) ?
2859  NULL :
2860  _("Socket disconnected while reading request.\n"));
2861  return;
2862  }
2863  CONNECTION_CLOSE_ERROR (connection,
2864  (MHD_CONNECTION_INIT == connection->state) ?
2865  NULL :
2866  _("Connection socket is closed due to error when reading request.\n"));
2867  return;
2868  }
2869 
2870  if (0 == bytes_read)
2871  { /* Remote side closed connection. */
2872  connection->read_closed = true;
2873  MHD_connection_close_ (connection,
2875  return;
2876  }
2877  connection->read_buffer_offset += bytes_read;
2878  MHD_update_last_activity_ (connection);
2879 #if DEBUG_STATES
2880  MHD_DLOG (connection->daemon,
2881  _("In function %s handling connection at state: %s\n"),
2882  __FUNCTION__,
2883  MHD_state_to_string (connection->state));
2884 #endif
2885  switch (connection->state)
2886  {
2887  case MHD_CONNECTION_INIT:
2896  /* nothing to do but default action */
2897  if (connection->read_closed)
2898  {
2899  MHD_connection_close_ (connection,
2901  }
2902  return;
2903  case MHD_CONNECTION_CLOSED:
2904  return;
2905 #ifdef UPGRADE_SUPPORT
2906  case MHD_CONNECTION_UPGRADE:
2907  mhd_assert (0);
2908  return;
2909 #endif /* UPGRADE_SUPPORT */
2910  default:
2911  /* shrink read buffer to how much is actually used */
2912  MHD_pool_reallocate (connection->pool,
2913  connection->read_buffer,
2914  connection->read_buffer_size + 1,
2915  connection->read_buffer_offset);
2916  break;
2917  }
2918  return;
2919 }
2920 
2921 
2928 void
2930 {
2931  struct MHD_Response *response;
2932  ssize_t ret;
2933  if (connection->suspended)
2934  return;
2935 
2936 #ifdef HTTPS_SUPPORT
2937  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
2938  { /* HTTPS connection. */
2939  if (MHD_TLS_CONN_CONNECTED > connection->tls_state)
2940  {
2941  if (!MHD_run_tls_handshake_ (connection))
2942  return;
2943  }
2944  }
2945 #endif /* HTTPS_SUPPORT */
2946 
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:
2959  mhd_assert (0);
2960  return;
2962  return;
2964  ret = connection->send_cls (connection,
2966  [connection->continue_message_write_offset],
2968  connection->continue_message_write_offset);
2969  if (ret < 0)
2970  {
2971  if (MHD_ERR_AGAIN_ == ret)
2972  return;
2973 #ifdef HAVE_MESSAGES
2974  MHD_DLOG (connection->daemon,
2975  _("Failed to send data in request for %s.\n"),
2976  connection->url);
2977 #endif
2978  CONNECTION_CLOSE_ERROR (connection,
2979  NULL);
2980  return;
2981  }
2982 #if DEBUG_SEND_DATA
2983  fprintf (stderr,
2984  _("Sent 100 continue response: `%.*s'\n"),
2985  (int) ret,
2987 #endif
2988  connection->continue_message_write_offset += ret;
2989  MHD_update_last_activity_ (connection);
2990  return;
2995  mhd_assert (0);
2996  return;
2998  ret = connection->send_cls (connection,
2999  &connection->write_buffer
3000  [connection->write_buffer_send_offset],
3001  connection->write_buffer_append_offset -
3002  connection->write_buffer_send_offset);
3003  if (ret < 0)
3004  {
3005  if (MHD_ERR_AGAIN_ == ret)
3006  return;
3007  CONNECTION_CLOSE_ERROR (connection,
3008  _("Connection was closed while sending response headers.\n"));
3009  return;
3010  }
3011  connection->write_buffer_send_offset += ret;
3012  MHD_update_last_activity_ (connection);
3013  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
3014  return;
3015  check_write_done (connection,
3017  return;
3019  return;
3021  response = connection->response;
3022  if (connection->response_write_position <
3023  connection->response->total_size)
3024  {
3025  uint64_t data_write_offset;
3026 
3027  if (NULL != response->crc)
3028  MHD_mutex_lock_chk_ (&response->mutex);
3029  if (MHD_YES != try_ready_normal_body (connection))
3030  {
3031  /* mutex was already unlocked by try_ready_normal_body */
3032  return;
3033  }
3034 #if defined(_MHD_HAVE_SENDFILE)
3035  if (MHD_resp_sender_sendfile == connection->resp_sender)
3036  {
3037  ret = sendfile_adapter (connection);
3038  }
3039  else
3040 #else /* ! _MHD_HAVE_SENDFILE */
3041  if (1)
3042 #endif /* ! _MHD_HAVE_SENDFILE */
3043  {
3044  data_write_offset = connection->response_write_position
3045  - response->data_start;
3046  if (data_write_offset > (uint64_t)SIZE_MAX)
3047  MHD_PANIC (_("Data offset exceeds limit"));
3048  ret = connection->send_cls (connection,
3049  &response->data
3050  [(size_t)data_write_offset],
3051  response->data_size -
3052  (size_t)data_write_offset);
3053 #if DEBUG_SEND_DATA
3054  if (ret > 0)
3055  fprintf (stderr,
3056  _("Sent %d-byte DATA response: `%.*s'\n"),
3057  (int) ret,
3058  (int) ret,
3059  &response->data[connection->response_write_position -
3060  response->data_start]);
3061 #endif
3062  }
3063  if (NULL != response->crc)
3064  MHD_mutex_unlock_chk_ (&response->mutex);
3065  if (ret < 0)
3066  {
3067  if (MHD_ERR_AGAIN_ == ret)
3068  return;
3069 #ifdef HAVE_MESSAGES
3070  MHD_DLOG (connection->daemon,
3071  _("Failed to send data in request for `%s'.\n"),
3072  connection->url);
3073 #endif
3074  CONNECTION_CLOSE_ERROR (connection,
3075  NULL);
3076  return;
3077  }
3078  connection->response_write_position += ret;
3079  MHD_update_last_activity_ (connection);
3080  }
3081  if (connection->response_write_position ==
3082  connection->response->total_size)
3083  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
3084  return;
3086  mhd_assert (0);
3087  return;
3089  ret = connection->send_cls (connection,
3090  &connection->write_buffer
3091  [connection->write_buffer_send_offset],
3092  connection->write_buffer_append_offset -
3093  connection->write_buffer_send_offset);
3094  if (ret < 0)
3095  {
3096  if (MHD_ERR_AGAIN_ == ret)
3097  return;
3098  CONNECTION_CLOSE_ERROR (connection,
3099  _("Connection was closed while sending response body.\n"));
3100  return;
3101  }
3102  connection->write_buffer_send_offset += ret;
3103  MHD_update_last_activity_ (connection);
3104  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
3105  return;
3106  check_write_done (connection,
3107  (connection->response->total_size ==
3108  connection->response_write_position) ?
3111  return;
3114  mhd_assert (0);
3115  return;
3117  ret = connection->send_cls (connection,
3118  &connection->write_buffer
3119  [connection->write_buffer_send_offset],
3120  connection->write_buffer_append_offset -
3121  connection->write_buffer_send_offset);
3122  if (ret < 0)
3123  {
3124  if (MHD_ERR_AGAIN_ == ret)
3125  return;
3126  CONNECTION_CLOSE_ERROR (connection,
3127  _("Connection was closed while sending response body.\n"));
3128  return;
3129  }
3130  connection->write_buffer_send_offset += ret;
3131  MHD_update_last_activity_ (connection);
3132  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
3133  return;
3134  check_write_done (connection,
3136  return;
3138  mhd_assert (0);
3139  return;
3140  case MHD_CONNECTION_CLOSED:
3141  return;
3143  mhd_assert (0);
3144  return;
3145 #ifdef UPGRADE_SUPPORT
3146  case MHD_CONNECTION_UPGRADE:
3147  mhd_assert (0);
3148  return;
3149 #endif /* UPGRADE_SUPPORT */
3150  default:
3151  mhd_assert (0);
3152  CONNECTION_CLOSE_ERROR (connection,
3153  _("Internal error\n"));
3154  break;
3155  }
3156  return;
3157 }
3158 
3159 
3168 static void
3170 {
3171  struct MHD_Daemon *daemon = connection->daemon;
3172 
3173  if (connection->in_cleanup)
3174  return; /* Prevent double cleanup. */
3175  connection->in_cleanup = true;
3176  if (NULL != connection->response)
3177  {
3178  MHD_destroy_response (connection->response);
3179  connection->response = NULL;
3180  }
3182  if (connection->suspended)
3183  {
3186  connection);
3187  connection->suspended = false;
3188  }
3189  else
3190  {
3191  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3192  {
3193  if (connection->connection_timeout == daemon->connection_timeout)
3195  daemon->normal_timeout_tail,
3196  connection);
3197  else
3199  daemon->manual_timeout_tail,
3200  connection);
3201  }
3202  DLL_remove (daemon->connections_head,
3203  daemon->connections_tail,
3204  connection);
3205  }
3206  DLL_insert (daemon->cleanup_head,
3207  daemon->cleanup_tail,
3208  connection);
3209  connection->resuming = false;
3210  connection->in_idle = false;
3212  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
3213  {
3214  /* if we were at the connection limit before and are in
3215  thread-per-connection mode, signal the main thread
3216  to resume accepting connections */
3217  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
3218  (! MHD_itc_activate_ (daemon->itc, "c")) )
3219  {
3220 #ifdef HAVE_MESSAGES
3221  MHD_DLOG (daemon,
3222  _("Failed to signal end of connection via inter-thread communication channel"));
3223 #endif
3224  }
3225  }
3226 }
3227 
3228 
3239 int
3241 {
3242  struct MHD_Daemon *daemon = connection->daemon;
3243  char *line;
3244  size_t line_len;
3245  int ret;
3246 
3247  connection->in_idle = true;
3248  while (! connection->suspended)
3249  {
3250 #ifdef HTTPS_SUPPORT
3251  if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
3252  { /* HTTPS connection. */
3253  if ((MHD_TLS_CONN_INIT <= connection->tls_state) &&
3254  (MHD_TLS_CONN_CONNECTED > connection->tls_state))
3255  break;
3256  }
3257 #endif /* HTTPS_SUPPORT */
3258 #if DEBUG_STATES
3259  MHD_DLOG (daemon,
3260  _("In function %s handling connection at state: %s\n"),
3261  __FUNCTION__,
3262  MHD_state_to_string (connection->state));
3263 #endif
3264  switch (connection->state)
3265  {
3266  case MHD_CONNECTION_INIT:
3267  line = get_next_header_line (connection,
3268  &line_len);
3269  /* Check for empty string, as we might want
3270  to tolerate 'spurious' empty lines; also
3271  NULL means we didn't get a full line yet;
3272  line is not 0-terminated here. */
3273  if ( (NULL == line) ||
3274  (0 == line[0]) )
3275  {
3276  if (MHD_CONNECTION_INIT != connection->state)
3277  continue;
3278  if (connection->read_closed)
3279  {
3280  CONNECTION_CLOSE_ERROR (connection,
3281  NULL);
3282  continue;
3283  }
3284  break;
3285  }
3286  if (MHD_NO == parse_initial_message_line (connection,
3287  line,
3288  line_len))
3289  CONNECTION_CLOSE_ERROR (connection,
3290  NULL);
3291  else
3292  connection->state = MHD_CONNECTION_URL_RECEIVED;
3293  continue;
3295  line = get_next_header_line (connection,
3296  NULL);
3297  if (NULL == line)
3298  {
3299  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
3300  continue;
3301  if (connection->read_closed)
3302  {
3303  CONNECTION_CLOSE_ERROR (connection,
3304  NULL);
3305  continue;
3306  }
3307  break;
3308  }
3309  if (0 == line[0])
3310  {
3311  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3312  connection->header_size = (size_t) (line - connection->read_buffer);
3313  continue;
3314  }
3315  if (MHD_NO == process_header_line (connection,
3316  line))
3317  {
3318  transmit_error_response (connection,
3321  break;
3322  }
3324  continue;
3326  line = get_next_header_line (connection,
3327  NULL);
3328  if (NULL == line)
3329  {
3330  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
3331  continue;
3332  if (connection->read_closed)
3333  {
3334  CONNECTION_CLOSE_ERROR (connection,
3335  NULL);
3336  continue;
3337  }
3338  break;
3339  }
3340  if (MHD_NO ==
3341  process_broken_line (connection,
3342  line,
3343  MHD_HEADER_KIND))
3344  continue;
3345  if (0 == line[0])
3346  {
3347  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
3348  connection->header_size = (size_t) (line - connection->read_buffer);
3349  continue;
3350  }
3351  continue;
3353  parse_connection_headers (connection);
3354  if (MHD_CONNECTION_CLOSED == connection->state)
3355  continue;
3357  if (connection->suspended)
3358  break;
3359  continue;
3361  call_connection_handler (connection); /* first call */
3362  if (MHD_CONNECTION_CLOSED == connection->state)
3363  continue;
3364  if (need_100_continue (connection))
3365  {
3366  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3367  if (MHD_NO != socket_flush_possible (connection))
3368  socket_start_extra_buffering (connection);
3369  else
3370  socket_start_no_buffering (connection);
3371 
3372  break;
3373  }
3374  if ( (NULL != connection->response) &&
3375  ( (MHD_str_equal_caseless_ (connection->method,
3377  (MHD_str_equal_caseless_ (connection->method,
3378  MHD_HTTP_METHOD_PUT))) )
3379  {
3380  /* we refused (no upload allowed!) */
3381  connection->remaining_upload_size = 0;
3382  /* force close, in case client still tries to upload... */
3383  connection->read_closed = true;
3384  }
3385  connection->state = (0 == connection->remaining_upload_size)
3387  if (connection->suspended)
3388  break;
3389  continue;
3391  if (connection->continue_message_write_offset ==
3393  {
3394  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3395  if (MHD_NO != socket_flush_possible (connection))
3396  socket_start_no_buffering_flush (connection);
3397  else
3398  socket_start_normal_buffering (connection);
3399 
3400  continue;
3401  }
3402  break;
3404  if (0 != connection->read_buffer_offset)
3405  {
3406  process_request_body (connection); /* loop call */
3407  if (MHD_CONNECTION_CLOSED == connection->state)
3408  continue;
3409  }
3410  if ( (0 == connection->remaining_upload_size) ||
3411  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3412  (0 == connection->read_buffer_offset) &&
3413  (connection->read_closed) ) )
3414  {
3415  if ( (connection->have_chunked_upload) &&
3416  (! connection->read_closed) )
3417  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3418  else
3419  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3420  if (connection->suspended)
3421  break;
3422  continue;
3423  }
3424  break;
3426  line = get_next_header_line (connection,
3427  NULL);
3428  if (NULL == line)
3429  {
3430  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3431  continue;
3432  if (connection->read_closed)
3433  {
3434  CONNECTION_CLOSE_ERROR (connection,
3435  NULL);
3436  continue;
3437  }
3438  break;
3439  }
3440  if (0 == line[0])
3441  {
3442  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3443  if (connection->suspended)
3444  break;
3445  continue;
3446  }
3447  if (MHD_NO == process_header_line (connection,
3448  line))
3449  {
3450  transmit_error_response (connection,
3453  break;
3454  }
3456  continue;
3458  line = get_next_header_line (connection,
3459  NULL);
3460  if (NULL == line)
3461  {
3462  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3463  continue;
3464  if (connection->read_closed)
3465  {
3466  CONNECTION_CLOSE_ERROR (connection,
3467  NULL);
3468  continue;
3469  }
3470  break;
3471  }
3472  if (MHD_NO ==
3473  process_broken_line (connection,
3474  line,
3475  MHD_FOOTER_KIND))
3476  continue;
3477  if (0 == line[0])
3478  {
3479  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3480  if (connection->suspended)
3481  break;
3482  continue;
3483  }
3484  continue;
3486  call_connection_handler (connection); /* "final" call */
3487  if (connection->state == MHD_CONNECTION_CLOSED)
3488  continue;
3489  if (NULL == connection->response)
3490  break; /* try again next time */
3491  if (MHD_NO == build_header_response (connection))
3492  {
3493  /* oops - close! */
3494  CONNECTION_CLOSE_ERROR (connection,
3495  _("Closing connection (failed to create response header)\n"));
3496  continue;
3497  }
3498  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3499  if (MHD_NO != socket_flush_possible (connection))
3500  socket_start_extra_buffering (connection);
3501  else
3502  socket_start_no_buffering (connection);
3503 
3504  break;
3506  /* no default action */
3507  break;
3509  /* Some clients may take some actions right after header receive */
3510  if (MHD_NO != socket_flush_possible (connection))
3511  socket_start_no_buffering_flush (connection);
3512 
3513 #ifdef UPGRADE_SUPPORT
3514  if (NULL != connection->response->upgrade_handler)
3515  {
3516  socket_start_normal_buffering (connection);
3517  connection->state = MHD_CONNECTION_UPGRADE;
3518  /* This connection is "upgraded". Pass socket to application. */
3519  if (MHD_YES !=
3521  connection))
3522  {
3523  /* upgrade failed, fail hard */
3524  CONNECTION_CLOSE_ERROR (connection,
3525  NULL);
3526  continue;
3527  }
3528  /* Response is not required anymore for this connection. */
3529  if (NULL != connection->response)
3530  {
3531  struct MHD_Response * const resp = connection->response;
3532  connection->response = NULL;
3533  MHD_destroy_response (resp);
3534  }
3535  continue;
3536  }
3537 #endif /* UPGRADE_SUPPORT */
3538  if (MHD_NO != socket_flush_possible (connection))
3539  socket_start_extra_buffering (connection);
3540  else
3541  socket_start_normal_buffering (connection);
3542 
3543  if (connection->have_chunked_upload)
3545  else
3547  continue;
3549  /* nothing to do here */
3550  break;
3552  if (NULL != connection->response->crc)
3553  MHD_mutex_lock_chk_ (&connection->response->mutex);
3554  if (0 == connection->response->total_size)
3555  {
3556  if (NULL != connection->response->crc)
3557  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3558  connection->state = MHD_CONNECTION_BODY_SENT;
3559  continue;
3560  }
3561  if (MHD_YES == try_ready_normal_body (connection))
3562  {
3563  if (NULL != connection->response->crc)
3564  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3566  /* Buffering for flushable socket was already enabled*/
3567  if (MHD_NO == socket_flush_possible (connection))
3568  socket_start_no_buffering (connection);
3569  break;
3570  }
3571  /* mutex was already unlocked by "try_ready_normal_body */
3572  /* not ready, no socket action */
3573  break;
3575  /* nothing to do here */
3576  break;
3578  if (NULL != connection->response->crc)
3579  MHD_mutex_lock_chk_ (&connection->response->mutex);
3580  if ( (0 == connection->response->total_size) ||
3581  (connection->response_write_position ==
3582  connection->response->total_size) )
3583  {
3584  if (NULL != connection->response->crc)
3585  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3586  connection->state = MHD_CONNECTION_BODY_SENT;
3587  continue;
3588  }
3589  if (MHD_YES == try_ready_chunked_body (connection))
3590  {
3591  if (NULL != connection->response->crc)
3592  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3594  /* Buffering for flushable socket was already enabled */
3595  if (MHD_NO == socket_flush_possible (connection))
3596  socket_start_no_buffering (connection);
3597  continue;
3598  }
3599  /* mutex was already unlocked by try_ready_chunked_body */
3600  break;
3602  if (MHD_NO == build_header_response (connection))
3603  {
3604  /* oops - close! */
3605  CONNECTION_CLOSE_ERROR (connection,
3606  _("Closing connection (failed to create response header)\n"));
3607  continue;
3608  }
3609  if ( (! connection->have_chunked_upload) ||
3610  (connection->write_buffer_send_offset ==
3611  connection->write_buffer_append_offset) )
3612  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3613  else
3614  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3615  continue;
3617  /* no default action */
3618  break;
3620  if (MHD_HTTP_PROCESSING == connection->responseCode)
3621  {
3622  /* After this type of response, we allow sending another! */
3624  MHD_destroy_response (connection->response);
3625  connection->response = NULL;
3626  /* FIXME: maybe partially reset memory pool? */
3627  continue;
3628  }
3629  if (MHD_NO != socket_flush_possible (connection))
3630  socket_start_no_buffering_flush (connection);
3631  else
3632  socket_start_normal_buffering (connection);
3633 
3634  MHD_destroy_response (connection->response);
3635  connection->response = NULL;
3636  if ( (NULL != daemon->notify_completed) &&
3637  (connection->client_aware) )
3638  {
3639  connection->client_aware = false;
3640  daemon->notify_completed (daemon->notify_completed_cls,
3641  connection,
3642  &connection->client_context,
3644  }
3645  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3646  (connection->read_closed) )
3647  {
3648  /* have to close for some reason */
3649  MHD_connection_close_ (connection,
3651  MHD_pool_destroy (connection->pool);
3652  connection->pool = NULL;
3653  connection->read_buffer = NULL;
3654  connection->read_buffer_size = 0;
3655  connection->read_buffer_offset = 0;
3656  }
3657  else
3658  {
3659  /* can try to keep-alive */
3660  if (MHD_NO != socket_flush_possible (connection))
3661  socket_start_normal_buffering (connection);
3662  connection->version = NULL;
3663  connection->state = MHD_CONNECTION_INIT;
3664  connection->last = NULL;
3665  connection->colon = NULL;
3666  connection->header_size = 0;
3667  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3668  /* Reset the read buffer to the starting size,
3669  preserving the bytes we have already read. */
3670  connection->read_buffer
3671  = MHD_pool_reset (connection->pool,
3672  connection->read_buffer,
3673  connection->read_buffer_offset,
3674  connection->daemon->pool_size / 2);
3675  connection->read_buffer_size
3676  = connection->daemon->pool_size / 2;
3677  }
3678  connection->client_aware = false;
3679  connection->client_context = NULL;
3680  connection->continue_message_write_offset = 0;
3681  connection->responseCode = 0;
3682  connection->headers_received = NULL;
3683  connection->headers_received_tail = NULL;
3684  connection->response_write_position = 0;
3685  connection->have_chunked_upload = false;
3686  connection->current_chunk_size = 0;
3687  connection->current_chunk_offset = 0;
3688  connection->method = NULL;
3689  connection->url = NULL;
3690  connection->write_buffer = NULL;
3691  connection->write_buffer_size = 0;
3692  connection->write_buffer_send_offset = 0;
3693  connection->write_buffer_append_offset = 0;
3694  continue;
3695  case MHD_CONNECTION_CLOSED:
3696  cleanup_connection (connection);
3697  connection->in_idle = false;
3698  return MHD_NO;
3699 #ifdef UPGRADE_SUPPORT
3700  case MHD_CONNECTION_UPGRADE:
3701  connection->in_idle = false;
3702  return MHD_YES; /* keep open */
3703 #endif /* UPGRADE_SUPPORT */
3704  default:
3705  mhd_assert (0);
3706  break;
3707  }
3708  break;
3709  }
3710  if (! connection->suspended)
3711  {
3712  time_t timeout;
3713  timeout = connection->connection_timeout;
3714  if ( (0 != timeout) &&
3715  (timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
3716  {
3717  MHD_connection_close_ (connection,
3719  connection->in_idle = false;
3720  return MHD_YES;
3721  }
3722  }
3724  ret = MHD_YES;
3725 #ifdef EPOLL_SUPPORT
3726  if ( (! connection->suspended) &&
3727  (0 != (daemon->options & MHD_USE_EPOLL)) )
3728  {
3729  ret = MHD_connection_epoll_update_ (connection);
3730  }
3731 #endif /* EPOLL_SUPPORT */
3732  connection->in_idle = false;
3733  return ret;
3734 }
3735 
3736 
3737 #ifdef EPOLL_SUPPORT
3738 
3746 int
3747 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3748 {
3749  struct MHD_Daemon *daemon = connection->daemon;
3750 
3751  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3752  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3753  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3754  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3755  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3756  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3757  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3758  {
3759  /* add to epoll set */
3760  struct epoll_event event;
3761 
3762  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3763  event.data.ptr = connection;
3764  if (0 != epoll_ctl (daemon->epoll_fd,
3765  EPOLL_CTL_ADD,
3766  connection->socket_fd,
3767  &event))
3768  {
3769 #ifdef HAVE_MESSAGES
3770  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3771  MHD_DLOG (daemon,
3772  _("Call to epoll_ctl failed: %s\n"),
3774 #endif
3775  connection->state = MHD_CONNECTION_CLOSED;
3776  cleanup_connection (connection);
3777  return MHD_NO;
3778  }
3779  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3780  }
3781  return MHD_YES;
3782 }
3783 #endif
3784 
3785 
3791 void
3793 {
3794  connection->recv_cls = &recv_param_adapter;
3795  connection->send_cls = &send_param_adapter;
3796 }
3797 
3798 
3809 const union MHD_ConnectionInfo *
3811  enum MHD_ConnectionInfoType info_type,
3812  ...)
3813 {
3814  switch (info_type)
3815  {
3816 #ifdef HTTPS_SUPPORT
3818  if (NULL == connection->tls_session)
3819  return NULL;
3820  connection->cipher = gnutls_cipher_get (connection->tls_session);
3821  return (const union MHD_ConnectionInfo *) &connection->cipher;
3823  if (NULL == connection->tls_session)
3824  return NULL;
3825  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3826  return (const union MHD_ConnectionInfo *) &connection->protocol;
3828  if (NULL == connection->tls_session)
3829  return NULL;
3830  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3831 #endif /* HTTPS_SUPPORT */
3833  return (const union MHD_ConnectionInfo *) &connection->addr;
3835  return (const union MHD_ConnectionInfo *) &connection->daemon;
3837  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3839  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3841  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3842  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3844  connection->connection_timeout_dummy = (unsigned int)connection->connection_timeout;
3845  return (const union MHD_ConnectionInfo *) &connection->connection_timeout_dummy;
3847  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3848  (MHD_CONNECTION_CLOSED == connection->state) ||
3849  (MHD_CONNECTION_IN_CLEANUP == connection->state) )
3850  return NULL; /* invalid, too early! */
3851  return (const union MHD_ConnectionInfo *) &connection->header_size;
3852  default:
3853  return NULL;
3854  }
3855 }
3856 
3857 
3867 int
3869  enum MHD_CONNECTION_OPTION option,
3870  ...)
3871 {
3872  va_list ap;
3873  struct MHD_Daemon *daemon;
3874 
3875  daemon = connection->daemon;
3876  switch (option)
3877  {
3879  if (0 == connection->connection_timeout)
3880  connection->last_activity = MHD_monotonic_sec_counter();
3881 
3883  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3884  (! connection->suspended) )
3885  {
3886  if (connection->connection_timeout == daemon->connection_timeout)
3888  daemon->normal_timeout_tail,
3889  connection);
3890  else
3892  daemon->manual_timeout_tail,
3893  connection);
3894  }
3895  va_start (ap, option);
3896  connection->connection_timeout = va_arg (ap,
3897  unsigned int);
3898  va_end (ap);
3899  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3900  (! connection->suspended) )
3901  {
3902  if (connection->connection_timeout == daemon->connection_timeout)
3904  daemon->normal_timeout_tail,
3905  connection);
3906  else
3908  daemon->manual_timeout_tail,
3909  connection);
3910  }
3912  return MHD_YES;
3913  default:
3914  return MHD_NO;
3915  }
3916 }
3917 
3918 
3930 int
3932  unsigned int status_code,
3933  struct MHD_Response *response)
3934 {
3935  struct MHD_Daemon *daemon;
3936 
3937  if ( (NULL == connection) ||
3938  (NULL == response) ||
3939  (NULL != connection->response) ||
3940  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3941  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3942  return MHD_NO;
3943  daemon = connection->daemon;
3944 
3945  if (daemon->shutdown)
3946  return MHD_YES; /* If daemon was shut down in parallel,
3947  * response will be aborted now or on later stage. */
3948 
3949  if ( (!connection->suspended) &&
3950  (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
3951  (!MHD_thread_ID_match_current_(connection->pid.ID)) )
3952  {
3953 #ifdef HAVE_MESSAGES
3954  MHD_DLOG (daemon,
3955  _("Attempted to queue response on wrong thread!\n"));
3956 #endif
3957  return MHD_NO;
3958  }
3959 #ifdef UPGRADE_SUPPORT
3960  if ( (NULL != response->upgrade_handler) &&
3961  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3962  {
3963 #ifdef HAVE_MESSAGES
3964  MHD_DLOG (daemon,
3965  _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
3966 #endif
3967  return MHD_NO;
3968  }
3969  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
3970  (NULL != response->upgrade_handler) )
3971  {
3972 #ifdef HAVE_MESSAGES
3973  MHD_DLOG (daemon,
3974  _("Application used invalid status code for 'upgrade' response!\n"));
3975 #endif
3976  return MHD_NO;
3977  }
3978 #endif /* UPGRADE_SUPPORT */
3979  MHD_increment_response_rc (response);
3980  connection->response = response;
3981  connection->responseCode = status_code;
3982 #if defined(_MHD_HAVE_SENDFILE)
3983  if ( (response->fd == -1) ||
3984  (0 != (connection->daemon->options & MHD_USE_TLS)) )
3985  connection->resp_sender = MHD_resp_sender_std;
3986  else
3987  connection->resp_sender = MHD_resp_sender_sendfile;
3988 #endif /* _MHD_HAVE_SENDFILE */
3989 
3990  if ( ( (NULL != connection->method) &&
3991  (MHD_str_equal_caseless_ (connection->method,
3992  MHD_HTTP_METHOD_HEAD)) ) ||
3993  (MHD_HTTP_OK > status_code) ||
3994  (MHD_HTTP_NO_CONTENT == status_code) ||
3995  (MHD_HTTP_NOT_MODIFIED == status_code) )
3996  {
3997  /* if this is a "HEAD" request, or a status code for
3998  which a body is not allowed, pretend that we
3999  have already sent the full message body. */
4000  connection->response_write_position = response->total_size;
4001  }
4002  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
4003  (NULL != connection->method) &&
4004  ( (MHD_str_equal_caseless_ (connection->method,
4006  (MHD_str_equal_caseless_ (connection->method,
4007  MHD_HTTP_METHOD_PUT))) )
4008  {
4009  /* response was queued "early", refuse to read body / footers or
4010  further requests! */
4011  connection->read_closed = true;
4012  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
4013  }
4014  if (! connection->in_idle)
4015  (void) MHD_connection_handle_idle (connection);
4016  return MHD_YES;
4017 }
4018 
4019 
4020 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2562
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: connection.c:231
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1996
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:2066
void * unescape_callback_cls
Definition: internal.h:1392
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:454
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2929
uint64_t total_size
Definition: internal.h:345
bool have_chunked_upload
Definition: internal.h:919
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:1071
uint64_t fd_off
Definition: internal.h:356
uint64_t current_chunk_offset
Definition: internal.h:933
#define DLL_insert(head, tail, element)
Definition: internal.h:1710
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:794
#define MHD_ERR_NOTCONN_
Definition: connection.h:47
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:748
void * socket_context
Definition: internal.h:692
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1805
enum MHD_CONNECTION_STATE state
Definition: internal.h:899
void * data
Definition: microhttpd.h:2661
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:1137
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:861
uint64_t response_write_position
Definition: internal.h:807
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:716
#define NULL
Definition: reason_phrase.c:31
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define HTTP_100_CONTINUE
Definition: connection.c:55
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
#define MHD_ICY_FLAG
Definition: microhttpd.h:408
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:904
time_t connection_timeout
Definition: internal.h:1558
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:2035
Methods for managing connections.
char * version
Definition: internal.h:709
int suspended_dummy
Definition: internal.h:992
#define INTERNAL_ERROR
Definition: connection.c:105
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:464
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:936
#define MHD_YES
Definition: microhttpd.h:134
struct MHD_Response * response
Definition: internal.h:665
char * colon
Definition: internal.h:746
#define REQUEST_LACKS_HOST
Definition: connection.c:80
char * write_buffer
Definition: internal.h:729
#define MHD_SENFILE_CHUNK_
Definition: connection.c:123
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:438
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1320
Header for platform missing functions.
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:323
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:898
MHD_RequestTerminationCode
Definition: microhttpd.h:1567
size_t data_size
Definition: internal.h:362
MHD_thread_handle_ID_ pid
Definition: internal.h:758
enum MHD_ValueKind kind
Definition: internal.h:280
struct MHD_HTTP_Header * first_header
Definition: internal.h:296
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1748
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1238
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2275
uint64_t remaining_upload_size
Definition: internal.h:800
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
unsigned int responseCode
Definition: internal.h:910
int MHD_parse_arguments_(struct MHD_Connection *connection, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:184
MHD_CONNECTION_STATE
Definition: internal.h:403
char * value
Definition: internal.h:274
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3169
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2784
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1382
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:178
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t header_size
Definition: internal.h:794
#define OFF_T_MAX
Definition: mhd_limits.h:123
struct MHD_Daemon * daemon
Definition: internal.h:650
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1328
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:128
#define MHD_ERR_AGAIN_
Definition: connection.h:36
struct MHD_Connection * cleanup_head
Definition: internal.h:1268
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:568
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
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:828
#define MHD_ERR_BADF_
Definition: connection.h:57
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:1032
#define XDLL_remove(head, tail, element)
Definition: internal.h:1776
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
bool client_aware
Definition: internal.h:850
#define XDLL_insert(head, tail, element)
Definition: internal.h:1755
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3810
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1264
int strict_for_client
Definition: internal.h:1579
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:349
struct MHD_Connection * cleanup_tail
Definition: internal.h:1273
Header for platform-independent inter-thread communication.
#define MHD_STATICSTR_LEN_(macro)
Definition: internal.h:126
size_t data_buffer_size
Definition: internal.h:367
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3225
size_t write_buffer_send_offset
Definition: internal.h:782
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:248
void * mhd_panic_cls
Definition: daemon.c:157
size_t read_buffer_size
Definition: internal.h:766
void * client_context
Definition: internal.h:683
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1335
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
const char * url
Definition: internal.h:703
size_t continue_message_write_offset
Definition: internal.h:821
#define REQUEST_MALFORMED
Definition: connection.c:93
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:857
char * method
Definition: internal.h:697
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
enum MHD_FLAG options
Definition: internal.h:1569
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:311
LogCallback uri_log_callback
Definition: internal.h:1377
static int socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:554
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2820
bool in_cleanup
Definition: internal.h:887
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1069
#define MHD_HTTP_OK
Definition: microhttpd.h:307
time_t connection_timeout
Definition: internal.h:838
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3868
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1103
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
char * last
Definition: internal.h:737
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1313
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1311
#define MHD_ERR_CONNRESET_
Definition: connection.h:41
MHD_ValueKind
Definition: microhttpd.h:1517
char * read_buffer
Definition: internal.h:723
ReceiveCallback recv_cls
Definition: internal.h:938
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:873
size_t write_buffer_size
Definition: internal.h:777
limits values definitions
MHD_ConnectionInfoType
Definition: microhttpd.h:1715
uint64_t data_start
Definition: internal.h:351
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:735
internal shared structures
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:369
UnescapeCallback unescape_callback
Definition: internal.h:1387
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:1371
int off_t offset
Definition: microhttpd.h:2771
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3931
internal monotonic clock functions implementations
unsigned int connection_timeout_dummy
Definition: internal.h:843
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:329
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:671
struct MHD_Connection * connections_head
Definition: internal.h:1248
size_t pool_size
Definition: internal.h:1425
char * header
Definition: internal.h:269
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2533
struct MHD_itc_ itc
Definition: internal.h:1505
time_t last_activity
Definition: internal.h:832
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3240
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2621
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1910
enum MHD_ResponseFlags flags
Definition: internal.h:383
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:458
struct MemoryPool * pool
Definition: internal.h:675
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:156
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:754
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2703
#define MHD_PANIC(msg)
Definition: internal.h:65
time_t MHD_monotonic_sec_counter(void)
Header for string manipulating helpers.
size_t write_buffer_append_offset
Definition: internal.h:788
struct MHD_HTTP_Header * next
Definition: internal.h:264
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1352
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:393
static int socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:495
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:440
bool read_closed
Definition: internal.h:870
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3792
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:760
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:329
#define DLL_remove(head, tail, element)
Definition: internal.h:1731
void * notify_completed_cls
Definition: internal.h:1357
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2310
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:734
TransmitCallback send_cls
Definition: internal.h:943
#define EDLL_remove(head, tail, element)
Definition: internal.h:1818
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:700
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:377
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
enum MHD_FLAG flags
Definition: microhttpd.h:3298
MHD_ContentReaderCallback crc
Definition: internal.h:314
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2180
void * crc_cls
Definition: internal.h:308
struct sockaddr * addr
Definition: internal.h:752
MHD_mutex_ mutex
Definition: internal.h:340
MHD_PanicCallback mhd_panic
Definition: daemon.c:152
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1263
static int socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:637
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
bool suspended
Definition: internal.h:987
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:446
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:305
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
static int socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:476
char * data
Definition: internal.h:302
#define MHD_MIN(a, b)
Definition: internal.h:90
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:607
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
size_t read_buffer_offset
Definition: internal.h:772
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1976
void * default_handler_cls
Definition: internal.h:1243
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1510
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:238
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:666
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1456
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:1054
uint64_t current_chunk_size
Definition: internal.h:927
Header for platform-independent locks abstraction.
struct MHD_HTTP_Header * headers_received
Definition: internal.h:655
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:304
struct MHD_Connection * connections_tail
Definition: internal.h:1253
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:502
#define MHD_BUF_INC_SIZE
Definition: internal.h:100
#define SIZE_MAX
Definition: mhd_limits.h:99
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:752
#define REQUEST_TOO_BIG
Definition: connection.c:67
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:660
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1403
size_t pool_increment
Definition: internal.h:1430
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:758
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:450
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1258
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...