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 */
MHD_SCKT_ERR_IS_EAGAIN_
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:624
MHD_CONN_KEEPALIVE_UNKOWN
@ MHD_CONN_KEEPALIVE_UNKOWN
Definition: internal.h:597
get_next_header_line
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1976
MHD_Connection::recv_cls
ReceiveCallback recv_cls
Definition: internal.h:938
MHD_Connection::in_cleanup
bool in_cleanup
Definition: internal.h:887
mhd_compat.h
Header for platform missing functions.
MHD_HTTP_METHOD_PUT
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:760
MHD_EVENT_LOOP_INFO_WRITE
@ MHD_EVENT_LOOP_INFO_WRITE
Definition: internal.h:189
_
#define _(String)
Definition: mhd_options.h:42
MHD_Daemon::options
enum MHD_FLAG options
Definition: internal.h:1569
MHD_CONNECTION_BODY_SENT
@ MHD_CONNECTION_BODY_SENT
Definition: internal.h:493
MHD_CONNECTION_FOOTERS_SENT
@ MHD_CONNECTION_FOOTERS_SENT
Definition: internal.h:503
MHD_Daemon::uri_log_callback
LogCallback uri_log_callback
Definition: internal.h:1377
MHD_Daemon::manual_timeout_tail
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1335
MHD_Daemon::unescape_callback
UnescapeCallback unescape_callback
Definition: internal.h:1387
MHD_Daemon::pool_size
size_t pool_size
Definition: internal.h:1425
MHD_Connection::resuming
bool resuming
Definition: internal.h:997
MHD_HTTP_Header::header
char * header
Definition: internal.h:269
MHD_CONN_USE_KEEPALIVE
@ MHD_CONN_USE_KEEPALIVE
Definition: internal.h:602
MHD_YES
#define MHD_YES
Definition: microhttpd.h:134
MHD_CONNECTION_INFO_PROTOCOL
@ MHD_CONNECTION_INFO_PROTOCOL
Definition: microhttpd.h:1729
mhd_sockets.h
MHD_socket_last_strerr_
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
MHD_CONTENT_READER_END_WITH_ERROR
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_USE_ERROR_LOG
@ MHD_USE_ERROR_LOG
Definition: microhttpd.h:894
REQUEST_TOO_BIG
#define REQUEST_TOO_BIG
Definition: connection.c:67
data
void * data
Definition: microhttpd.h:2661
MHD_DaemonInfo::flags
enum MHD_FLAG flags
Definition: microhttpd.h:3298
call_connection_handler
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:2275
MHD_Daemon::itc
struct MHD_itc_ itc
Definition: internal.h:1505
MHD_RF_HTTP_VERSION_1_0_ONLY
@ MHD_RF_HTTP_VERSION_1_0_ONLY
Definition: microhttpd.h:2590
transmit_error_response
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1748
MHD_CONNECTION_HEADERS_SENT
@ MHD_CONNECTION_HEADERS_SENT
Definition: internal.h:467
MHD_USE_TURBO
@ MHD_USE_TURBO
Definition: microhttpd.h:1087
MHD_CONNECTION_INFO_GNUTLS_SESSION
@ MHD_CONNECTION_INFO_GNUTLS_SESSION
Definition: microhttpd.h:1744
MHD_Connection::write_buffer_size
size_t write_buffer_size
Definition: internal.h:777
MHD_CONNECTION_OPTION_TIMEOUT
@ MHD_CONNECTION_OPTION_TIMEOUT
Definition: microhttpd.h:3235
MHD_HTTP_Header::next
struct MHD_HTTP_Header * next
Definition: internal.h:264
MHD_update_last_activity_
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2784
MHD_Response::fd_off
uint64_t fd_off
Definition: internal.h:356
MHD_REQUEST_TERMINATED_READ_ERROR
@ MHD_REQUEST_TERMINATED_READ_ERROR
Definition: microhttpd.h:1607
MHD_CONNECTION_CONTINUE_SENT
@ MHD_CONNECTION_CONTINUE_SENT
Definition: internal.h:439
MHD_UNSIGNED_LONG_LONG
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
MHD_HTTP_NOT_MODIFIED
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:323
MHD_monotonic_sec_counter
time_t MHD_monotonic_sec_counter(void)
Definition: mhd_mono_clock.c:337
MHD_EPOLL_STATE_IN_EPOLL_SET
@ MHD_EPOLL_STATE_IN_EPOLL_SET
Definition: internal.h:162
parse_initial_message_line
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:2180
MHD_set_connection_option
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3868
MHD_ConnectionInfoType
MHD_ConnectionInfoType
Definition: microhttpd.h:1715
MHD_HTTP_HEADER_EXPECT
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:458
try_grow_read_buffer
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:1371
DLL_insert
#define DLL_insert(head, tail, element)
Definition: internal.h:1710
MHD_Connection::connection_timeout_dummy
unsigned int connection_timeout_dummy
Definition: internal.h:843
MHD_CONNECTION_INFO_CONNECTION_TIMEOUT
@ MHD_CONNECTION_INFO_CONNECTION_TIMEOUT
Definition: microhttpd.h:1787
XDLL_insert
#define XDLL_insert(head, tail, element)
Definition: internal.h:1755
MHD_TLS_CONN_CONNECTED
@ MHD_TLS_CONN_CONNECTED
Definition: internal.h:534
MHD_CONNECTION_CHUNKED_BODY_READY
@ MHD_CONNECTION_CHUNKED_BODY_READY
Definition: internal.h:483
recv_param_adapter
static ssize_t recv_param_adapter(struct MHD_Connection *connection, void *other, size_t i)
Definition: connection.c:178
MHD_connection_update_event_loop_info
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1805
MHD_str_to_uint64_
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:450
MHD_Connection::write_buffer_append_offset
size_t write_buffer_append_offset
Definition: internal.h:788
socket_start_no_buffering_flush
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:607
cleanup_connection
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:3169
MHD_Daemon::notify_completed_cls
void * notify_completed_cls
Definition: internal.h:1357
MHD_HTTP_HEADER_CONNECTION
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:440
MHD_HTTP_METHOD_POST
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:758
MHD_REQUEST_TERMINATED_COMPLETED_OK
@ MHD_REQUEST_TERMINATED_COMPLETED_OK
Definition: microhttpd.h:1574
MHD_run_tls_handshake_
bool MHD_run_tls_handshake_(struct MHD_Connection *connection)
Definition: connection_https.c:148
MHD_CONNECTION_CONTINUE_SENDING
@ MHD_CONNECTION_CONTINUE_SENDING
Definition: internal.h:434
MHD_Connection::last_activity
time_t last_activity
Definition: internal.h:832
MHD_str_has_token_caseless_
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:393
MHD_Daemon::suspended_connections_tail
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1263
build_header_response
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1403
MHD_get_connection_values
_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
connection_https.h
Methods for managing connections.
MHD_MIN
#define MHD_MIN(a, b)
Definition: internal.h:90
MHD_TLS_CONN_INIT
@ MHD_TLS_CONN_INIT
Definition: internal.h:532
MHD_Response::crc
MHD_ContentReaderCallback crc
Definition: internal.h:314
MHD_Daemon::connections_head
struct MHD_Connection * connections_head
Definition: internal.h:1248
MHD_CONNECTION_FOOTERS_RECEIVED
@ MHD_CONNECTION_FOOTERS_RECEIVED
Definition: internal.h:456
response.h
Methods for managing response objects.
MHD_Connection::pool
struct MemoryPool * pool
Definition: internal.h:675
MHD_INVALID_SOCKET
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_Response::data_buffer_size
size_t data_buffer_size
Definition: internal.h:367
mhd_locks.h
Header for platform-independent locks abstraction.
MHD_Response::total_size
uint64_t total_size
Definition: internal.h:345
MHD_Response::data_start
uint64_t data_start
Definition: internal.h:351
MHD_Connection::addr
struct sockaddr * addr
Definition: internal.h:752
SIZE_MAX
#define SIZE_MAX
Definition: mhd_limits.h:99
MHD_Connection::read_closed
bool read_closed
Definition: internal.h:870
MHD_Response::data_size
size_t data_size
Definition: internal.h:362
MHD_connection_finish_forward_
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:156
MHD_BUF_INC_SIZE
#define MHD_BUF_INC_SIZE
Definition: internal.h:100
MHD_HTTP_HEADER_CONTENT_LENGTH
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:446
MHD_HTTP_URI_TOO_LONG
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:349
MHD_Connection::send_cls
TransmitCallback send_cls
Definition: internal.h:943
MHD_SCKT_ECONNRESET_
#define MHD_SCKT_ECONNRESET_
Definition: mhd_sockets.h:403
MHD_CONNECTION_CLOSED
@ MHD_CONNECTION_CLOSED
Definition: internal.h:508
try_ready_normal_body
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:1071
MHD_Daemon::pool_increment
size_t pool_increment
Definition: internal.h:1430
MHD_SCKT_ERR_IS_EINTR_
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
mhd_mono_clock.h
internal monotonic clock functions implementations
MHD_CONNECTION_OPTION
MHD_CONNECTION_OPTION
Definition: microhttpd.h:3225
MHD_ERR_AGAIN_
#define MHD_ERR_AGAIN_
Definition: connection.h:36
MHD_Daemon::notify_completed
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1352
MHD_CONNECTION_INFO_CIPHER_ALGO
@ MHD_CONNECTION_INFO_CIPHER_ALGO
Definition: microhttpd.h:1722
MHD_Connection::current_chunk_size
uint64_t current_chunk_size
Definition: internal.h:927
MHD_REQUEST_TERMINATED_CLIENT_ABORT
@ MHD_REQUEST_TERMINATED_CLIENT_ABORT
Definition: microhttpd.h:1615
REQUEST_MALFORMED
#define REQUEST_MALFORMED
Definition: connection.c:93
MHD_Response::crc_cls
void * crc_cls
Definition: internal.h:308
MHD_Connection::suspended
bool suspended
Definition: internal.h:987
MHD_HTTP_HEADER_TRANSFER_ENCODING
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:502
MHD_get_connection_info
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3810
MHD_Response::fd
int fd
Definition: internal.h:378
need_100_continue
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:873
mhd_assert
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
MHD_Connection::headers_received_tail
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:660
MHD_destroy_response
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1069
MHD_HTTP_NO_CONTENT
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:311
mhd_panic_cls
void * mhd_panic_cls
Definition: daemon.c:157
MHD_connection_handle_write
void MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2929
MHD_HTTP_OK
#define MHD_HTTP_OK
Definition: microhttpd.h:307
MHD_pool_reallocate
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:248
send_param_adapter
static ssize_t send_param_adapter(struct MHD_Connection *connection, const void *other, size_t i)
Definition: connection.c:231
MHD_Connection::read_buffer_offset
size_t read_buffer_offset
Definition: internal.h:772
MHD_CONNECTION_CHUNKED_BODY_UNREADY
@ MHD_CONNECTION_CHUNKED_BODY_UNREADY
Definition: internal.h:488
socket_flush_possible
static int socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:476
MHD_Daemon::default_handler_cls
void * default_handler_cls
Definition: internal.h:1243
MHD_HTTP_HEADER_DATE
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:454
MHD_KeyValueIterator
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1996
MHD_Connection::have_chunked_upload
bool have_chunked_upload
Definition: internal.h:919
MHD_Daemon::shutdown
volatile bool shutdown
Definition: internal.h:1510
mhd_panic
MHD_PanicCallback mhd_panic
Definition: daemon.c:152
process_broken_line
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2621
MHD_connection_mark_closed_
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:898
MHD_Connection::headers_received
struct MHD_HTTP_Header * headers_received
Definition: internal.h:655
MHD_EPOLL_STATE_SUSPENDED
@ MHD_EPOLL_STATE_SUSPENDED
Definition: internal.h:167
NULL
#define NULL
Definition: reason_phrase.c:31
MHD_Connection::current_chunk_offset
uint64_t current_chunk_offset
Definition: internal.h:933
MHD_ERR_BADF_
#define MHD_ERR_BADF_
Definition: connection.h:57
MHD_ERR_CONNRESET_
#define MHD_ERR_CONNRESET_
Definition: connection.h:41
MHD_CONNECTION_INIT
@ MHD_CONNECTION_INIT
Definition: internal.h:409
MHD_strx_to_uint64_n_
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:666
MHD_response_execute_upgrade_
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
MHD_set_connection_value
_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
MHD_lookup_header_token_ci
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
MHD_Daemon::connection_timeout
time_t connection_timeout
Definition: internal.h:1558
MHD_lookup_connection_value
const _MHD_EXTERN char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:794
MHD_Connection::socket_context
void * socket_context
Definition: internal.h:692
MHD_Connection::state
enum MHD_CONNECTION_STATE state
Definition: internal.h:899
REQUEST_LACKS_HOST
#define REQUEST_LACKS_HOST
Definition: connection.c:80
MHD_USE_TLS
@ MHD_USE_TLS
Definition: microhttpd.h:905
OFF_T_MAX
#define OFF_T_MAX
Definition: mhd_limits.h:123
MHD_Daemon::cleanup_connection_mutex
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1456
MHD_Connection::keepalive
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:716
MHD_mutex_lock_chk_
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
MHD_CONNECTION_INFO_CONNECTION_SUSPENDED
@ MHD_CONNECTION_INFO_CONNECTION_SUSPENDED
Definition: microhttpd.h:1781
MHD_Daemon::suspended_connections_head
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1258
MHD_USE_SUPPRESS_DATE_NO_CLOCK
@ MHD_USE_SUPPRESS_DATE_NO_CLOCK
Definition: microhttpd.h:996
MHD_CONNECTION_FOOTERS_SENDING
@ MHD_CONNECTION_FOOTERS_SENDING
Definition: internal.h:498
MHD_HTTP_VERSION_1_1
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:735
DLL_remove
#define DLL_remove(head, tail, element)
Definition: internal.h:1731
MHD_CONNECTION_NORMAL_BODY_READY
@ MHD_CONNECTION_NORMAL_BODY_READY
Definition: internal.h:472
MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:369
MHD_Daemon::connections_tail
struct MHD_Connection * connections_tail
Definition: internal.h:1253
MHD_queue_response
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3931
MHD_CONNECTION_IN_CLEANUP
@ MHD_CONNECTION_IN_CLEANUP
Definition: internal.h:513
MHD_CONN_MUST_CLOSE
@ MHD_CONN_MUST_CLOSE
Definition: internal.h:592
MHD_USE_EPOLL
@ MHD_USE_EPOLL
Definition: microhttpd.h:1022
MHD_CONNECTION_HEADERS_SENDING
@ MHD_CONNECTION_HEADERS_SENDING
Definition: internal.h:462
MHD_Response::mutex
MHD_mutex_ mutex
Definition: internal.h:340
process_request_body
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:2310
MHD_send_
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
MHD_USE_INTERNAL_POLLING_THREAD
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:931
CONNECTION_CLOSE_ERROR
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:1054
MHD_ALLOW_UPGRADE
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1123
MHD_CONNECTION_FOOTER_PART_RECEIVED
@ MHD_CONNECTION_FOOTER_PART_RECEIVED
Definition: internal.h:450
MHD_EVENT_LOOP_INFO_BLOCK
@ MHD_EVENT_LOOP_INFO_BLOCK
Definition: internal.h:194
socket_start_no_buffering
static int socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:554
MHD_Connection::version
char * version
Definition: internal.h:709
parse_cookie_header
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:2066
MHD_SENFILE_CHUNK_THR_P_C_
#define MHD_SENFILE_CHUNK_THR_P_C_
Definition: connection.c:128
MHD_Daemon
Definition: internal.h:1232
XDLL_remove
#define XDLL_remove(head, tail, element)
Definition: internal.h:1776
MHD_COOKIE_KIND
@ MHD_COOKIE_KIND
Definition: microhttpd.h:1538
MHD_HTTP_HEADER_HOST
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:464
memorypool.h
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
MHD_Connection::colon
char * colon
Definition: internal.h:746
MHD_SIZE_UNKNOWN
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
MHD_CONTENT_READER_END_OF_STREAM
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
MHD_EVENT_LOOP_INFO_READ
@ MHD_EVENT_LOOP_INFO_READ
Definition: internal.h:184
MHD_ICY_FLAG
#define MHD_ICY_FLAG
Definition: microhttpd.h:408
MHD_Daemon::unescape_callback_cls
void * unescape_callback_cls
Definition: internal.h:1392
MHD_CONNECTION_INFO_CONNECTION_FD
@ MHD_CONNECTION_INFO_CONNECTION_FD
Definition: microhttpd.h:1765
MHD_Connection::response_write_position
uint64_t response_write_position
Definition: internal.h:807
MHD_SCKT_EBADF_
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:438
MHD_ERR_NOTCONN_
#define MHD_ERR_NOTCONN_
Definition: connection.h:47
mhd_limits.h
limits values definitions
MHD_increment_response_rc
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1103
MHD_RESPMEM_PERSISTENT
@ MHD_RESPMEM_PERSISTENT
Definition: microhttpd.h:2680
socket_start_extra_buffering
static int socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:495
MHD_SCKT_SEND_MAX_SIZE_
#define MHD_SCKT_SEND_MAX_SIZE_
Definition: mhd_sockets.h:220
MHD_Connection::event_loop_info
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:904
parse_connection_headers
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2703
keepalive_possible
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:1264
MHD_FOOTER_KIND
@ MHD_FOOTER_KIND
Definition: microhttpd.h:1558
MHD_HTTP_BAD_REQUEST
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:329
internal.h
internal shared structures
MHD_CONNECTION_HEADER_PART_RECEIVED
@ MHD_CONNECTION_HEADER_PART_RECEIVED
Definition: internal.h:419
connection.h
Methods for managing connections.
socket_start_normal_buffering
static int socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:637
MHD_Daemon::default_handler
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1238
MHD_Response::data
char * data
Definition: internal.h:302
HTTP_100_CONTINUE
#define HTTP_100_CONTINUE
Definition: connection.c:55
connection_close_error
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:1032
MHD_Connection::suspended_dummy
int suspended_dummy
Definition: internal.h:992
MHD_get_reason_phrase_for
const _MHD_EXTERN char * MHD_get_reason_phrase_for(unsigned int code)
Definition: reason_phrase.c:176
MHD_create_response_from_buffer
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:671
MHD_HTTP_METHOD_CONNECT
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:748
MHD_Daemon::manual_timeout_head
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1328
MHD_Connection::remaining_upload_size
uint64_t remaining_upload_size
Definition: internal.h:800
MHD_Connection::response
struct MHD_Response * response
Definition: internal.h:665
MHD_Daemon::cleanup_head
struct MHD_Connection * cleanup_head
Definition: internal.h:1268
MHD_Response::first_header
struct MHD_HTTP_Header * first_header
Definition: internal.h:296
MHD_connection_close_
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:936
MHD_Connection::write_buffer
char * write_buffer
Definition: internal.h:729
MHD_socket_get_error_
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
MHD_connection_handle_idle
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:3240
MHD_SENFILE_CHUNK_
#define MHD_SENFILE_CHUNK_
Definition: connection.c:123
MHD_HTTP_VERSION_1_0
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:734
MHD_HTTP_Header
Definition: internal.h:259
MHD_connection_handle_read
void MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2820
MHD_Daemon::normal_timeout_tail
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1320
MHD_Connection::in_idle
bool in_idle
Definition: internal.h:881
MHD_EPOLL_STATE_READ_READY
@ MHD_EPOLL_STATE_READ_READY
Definition: internal.h:146
mhd_str.h
Header for string manipulating helpers.
MHD_Connection::pid
MHD_thread_handle_ID_ pid
Definition: internal.h:758
MHD_EVENT_LOOP_INFO_CLEANUP
@ MHD_EVENT_LOOP_INFO_CLEANUP
Definition: internal.h:199
connection_add_header
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:2035
MHD_CONNECTION_INFO_CLIENT_ADDRESS
@ MHD_CONNECTION_INFO_CLIENT_ADDRESS
Definition: microhttpd.h:1738
process_header_line
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2562
MHD_RequestTerminationCode
MHD_RequestTerminationCode
Definition: microhttpd.h:1567
MHD_HTTP_HEADER_COOKIE
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:568
MHD_Daemon::strict_for_client
int strict_for_client
Definition: internal.h:1579
MHD_ValueKind
MHD_ValueKind
Definition: microhttpd.h:1517
MHD_REQUEST_TERMINATED_WITH_ERROR
@ MHD_REQUEST_TERMINATED_WITH_ERROR
Definition: microhttpd.h:1582
MHD_Daemon::cleanup_tail
struct MHD_Connection * cleanup_tail
Definition: internal.h:1273
MHD_TLS_CONN_HANDSHAKING
@ MHD_TLS_CONN_HANDSHAKING
Definition: internal.h:533
MHD_lookup_header_s_token_ci
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:861
MHD_HEADER_KIND
@ MHD_HEADER_KIND
Definition: microhttpd.h:1532
MHD_HTTP_PROCESSING
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:305
MHD_CONNECTION_HEADERS_RECEIVED
@ MHD_CONNECTION_HEADERS_RECEIVED
Definition: internal.h:424
MHD_CONNECTION_NORMAL_BODY_UNREADY
@ MHD_CONNECTION_NORMAL_BODY_UNREADY
Definition: internal.h:478
MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE
@ MHD_CONNECTION_INFO_REQUEST_HEADER_SIZE
Definition: microhttpd.h:1793
MHD_SCKT_ERR_IS_
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:591
MHD_USE_THREAD_PER_CONNECTION
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:920
MHD_Response
Definition: internal.h:288
MHD_CONNECTION_URL_RECEIVED
@ MHD_CONNECTION_URL_RECEIVED
Definition: internal.h:414
MHD_Connection::responseCode
unsigned int responseCode
Definition: internal.h:910
check_write_done
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2533
MHD_pool_allocate
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
MHD_Connection::write_buffer_send_offset
size_t write_buffer_send_offset
Definition: internal.h:782
mhd_itc.h
Header for platform-independent inter-thread communication.
MHD_Connection
Definition: internal.h:608
get_date_string
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:1311
MHD_Connection::header_size
size_t header_size
Definition: internal.h:794
MHD_STATICSTR_LEN_
#define MHD_STATICSTR_LEN_(macro)
Definition: internal.h:126
MHD_REQUEST_TERMINATED_TIMEOUT_REACHED
@ MHD_REQUEST_TERMINATED_TIMEOUT_REACHED
Definition: microhttpd.h:1590
MHD_CONNECTION_BODY_RECEIVED
@ MHD_CONNECTION_BODY_RECEIVED
Definition: internal.h:444
MHD_HTTP_Header::kind
enum MHD_ValueKind kind
Definition: internal.h:280
MHD_SCKT_OPT_BOOL_
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
MHD_Connection::daemon
struct MHD_Daemon * daemon
Definition: internal.h:650
MHD_Daemon::uri_log_callback_cls
void * uri_log_callback_cls
Definition: internal.h:1382
MHD_Connection::url
const char * url
Definition: internal.h:703
MHD_Connection::read_buffer_size
size_t read_buffer_size
Definition: internal.h:766
MHD_get_response_header
const _MHD_EXTERN char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:238
MHD_CONNECTION_STATE
MHD_CONNECTION_STATE
Definition: internal.h:403
offset
int off_t offset
Definition: microhttpd.h:2772
MHD_HTTP_INTERNAL_SERVER_ERROR
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:377
MHD_UNSIGNED_LONG_LONG_PRINTF
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
MHD_PANIC
#define MHD_PANIC(msg)
Definition: internal.h:65
MHD_TLS_CONN_NO_TLS
@ MHD_TLS_CONN_NO_TLS
Definition: internal.h:531
MHD_tls_connection_shutdown
bool MHD_tls_connection_shutdown(struct MHD_Connection *connection)
Definition: connection_https.c:205
EDLL_remove
#define EDLL_remove(head, tail, element)
Definition: internal.h:1818
MHD_HTTP_SWITCHING_PROTOCOLS
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:304
MHD_Connection::method
char * method
Definition: internal.h:697
MHD_HTTP_Header::value
char * value
Definition: internal.h:274
MHD_Response::flags
enum MHD_ResponseFlags flags
Definition: internal.h:383
MHD_Connection::client_aware
bool client_aware
Definition: internal.h:850
MHD_check_response_header_s_token_ci
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1910
MHD_Daemon::normal_timeout_head
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1313
try_ready_chunked_body
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:1137
MHD_CONNECTION_INFO_DAEMON
@ MHD_CONNECTION_INFO_DAEMON
Definition: microhttpd.h:1758
MHD_recv_
#define MHD_recv_(s, b, l)
Definition: mhd_sockets.h:270
MHD_ConnectionInfo
Definition: microhttpd.h:1646
MHD_NO
#define MHD_NO
Definition: microhttpd.h:139
MHD_EPOLL_STATE_WRITE_READY
@ MHD_EPOLL_STATE_WRITE_READY
Definition: internal.h:152
INTERNAL_ERROR
#define INTERNAL_ERROR
Definition: connection.c:105
MHD_Connection::connection_timeout
time_t connection_timeout
Definition: internal.h:838
MHD_set_http_callbacks_
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3792
MHD_mutex_unlock_chk_
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
MHD_Connection::client_context
void * client_context
Definition: internal.h:683
MHD_Connection::last
char * last
Definition: internal.h:737
MHD_pool_reset
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
MHD_Connection::continue_message_write_offset
size_t continue_message_write_offset
Definition: internal.h:821
MHD_Connection::socket_fd
MHD_socket socket_fd
Definition: internal.h:857
MHD_GET_ARGUMENT_KIND
@ MHD_GET_ARGUMENT_KIND
Definition: microhttpd.h:1553
MHD_str_equal_caseless_
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:329
MHD_HTTP_METHOD_HEAD
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:754
MHD_CONNECTION_INFO_SOCKET_CONTEXT
@ MHD_CONNECTION_INFO_SOCKET_CONTEXT
Definition: microhttpd.h:1775
MHD_Connection::read_buffer
char * read_buffer
Definition: internal.h:723
MHD_pool_destroy
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
MHD_parse_arguments_
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_HEADERS_PROCESSED
@ MHD_CONNECTION_HEADERS_PROCESSED
Definition: internal.h:429