GNU libmicrohttpd  0.9.68
connection_call_handlers.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2018 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 */
24 #include "internal.h"
27 #include "connection_close.h"
28 
29 
30 #ifdef MHD_LINUX_SOLARIS_SENDFILE
31 #include <sys/sendfile.h>
32 #endif /* MHD_LINUX_SOLARIS_SENDFILE */
33 #if defined(HAVE_FREEBSD_SENDFILE) || defined(HAVE_DARWIN_SENDFILE)
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <sys/uio.h>
37 #endif /* HAVE_FREEBSD_SENDFILE || HAVE_DARWIN_SENDFILE */
38 
39 
43 #define MHD_SENFILE_CHUNK_ (0x20000)
44 
48 #define MHD_SENFILE_CHUNK_THR_P_C_ (0x200000)
49 
50 
58 #ifdef HAVE_MESSAGES
59 #define REQUEST_TOO_BIG \
60  "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
61 #else
62 #define REQUEST_TOO_BIG ""
63 #endif
64 
72 #ifdef HAVE_MESSAGES
73 #define REQUEST_LACKS_HOST \
74  "<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>"
75 #else
76 #define REQUEST_LACKS_HOST ""
77 #endif
78 
86 #ifdef HAVE_MESSAGES
87 #define REQUEST_MALFORMED \
88  "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
89 #else
90 #define REQUEST_MALFORMED ""
91 #endif
92 
99 #ifdef HAVE_MESSAGES
100 #define INTERNAL_ERROR \
101  "<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>"
102 #else
103 #define INTERNAL_ERROR ""
104 #endif
105 
106 
107 #ifdef HAVE_FREEBSD_SENDFILE
108 #ifdef SF_FLAGS
109 
112 static int freebsd_sendfile_flags_;
113 
117 static int freebsd_sendfile_flags_thd_p_c_;
118 #endif /* SF_FLAGS */
119 
120 
126 void
127 MHD_conn_init_static_ (void)
128 {
129 /* FreeBSD 11 and later allow to specify read-ahead size
130  * and handles SF_NODISKIO differently.
131  * SF_FLAGS defined only on FreeBSD 11 and later. */
132 #ifdef SF_FLAGS
133  long sys_page_size = sysconf (_SC_PAGESIZE);
134  if (0 > sys_page_size)
135  { /* Failed to get page size. */
136  freebsd_sendfile_flags_ = SF_NODISKIO;
137  freebsd_sendfile_flags_thd_p_c_ = SF_NODISKIO;
138  }
139  else
140  {
141  freebsd_sendfile_flags_ =
142  SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_ / sys_page_size), SF_NODISKIO);
143  freebsd_sendfile_flags_thd_p_c_ =
144  SF_FLAGS ((uint16_t) (MHD_SENFILE_CHUNK_THR_P_C_ / sys_page_size),
145  SF_NODISKIO);
146  }
147 #endif /* SF_FLAGS */
148 }
149 #endif /* HAVE_FREEBSD_SENDFILE */
150 
151 
152 
156 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
157 
158 
167 static void
169  enum MHD_StatusCode sc,
170  const char *emsg)
171 {
172 #ifdef HAVE_MESSAGES
173  if (NULL != emsg)
174  MHD_DLOG (connection->daemon,
175  sc,
176  emsg);
177 #else /* ! HAVE_MESSAGES */
178  (void) emsg; /* Mute compiler warning. */
179  (void) sc;
180 #endif /* ! HAVE_MESSAGES */
181  MHD_connection_close_ (connection,
183 }
184 
185 
190 #ifdef HAVE_MESSAGES
191 #define CONNECTION_CLOSE_ERROR(c, sc, emsg) connection_close_error (c, sc, emsg)
192 #else
193 #define CONNECTION_CLOSE_ERROR(c, sc, emsg) connection_close_error (c, sc, NULL)
194 #endif
195 
196 
207 static bool
209 {
210  struct MHD_Daemon *daemon = request->daemon;
211  void *buf;
212  size_t new_size;
213 
214  if (0 == request->read_buffer_size)
215  new_size = daemon->connection_memory_limit_b / 2;
216  else
217  new_size = request->read_buffer_size
219  buf = MHD_pool_reallocate (request->connection->pool,
220  request->read_buffer,
221  request->read_buffer_size,
222  new_size);
223  if (NULL == buf)
224  return false;
225  /* we can actually grow the buffer, do it! */
226  request->read_buffer = buf;
227  request->read_buffer_size = new_size;
228  return true;
229 }
230 
231 
238 static void
240 {
241  struct MHD_Daemon *daemon = request->daemon;
242  struct MHD_Connection *connection = request->connection;
243  ssize_t bytes_read;
244 
245  if ( (MHD_REQUEST_CLOSED == request->state) ||
246  (connection->suspended) )
247  return;
248 #ifdef HTTPS_SUPPORT
249  {
250  struct MHD_TLS_Plugin *tls;
251 
252  if ( (NULL != (tls = daemon->tls_api)) &&
253  (! tls->handshake (tls->cls,
254  connection->tls_cs)) )
255  return;
256  }
257 #endif /* HTTPS_SUPPORT */
258 
259  /* make sure "read" has a reasonable number of bytes
260  in buffer to use per system call (if possible) */
261  if (request->read_buffer_offset
263  request->read_buffer_size)
264  try_grow_read_buffer (request);
265 
266  if (request->read_buffer_size == request->read_buffer_offset)
267  return; /* No space for receiving data. */
268  bytes_read = connection->recv_cls (connection,
269  &request->read_buffer
270  [request->read_buffer_offset],
271  request->read_buffer_size
272  - request->read_buffer_offset);
273  if (bytes_read < 0)
274  {
275  if (MHD_ERR_AGAIN_ == bytes_read)
276  return; /* No new data to process. */
277  if (MHD_ERR_CONNRESET_ == bytes_read)
278  {
279  CONNECTION_CLOSE_ERROR (connection,
280  (MHD_REQUEST_INIT == request->state)
281  ? MHD_SC_CONNECTION_CLOSED
282  : MHD_SC_CONNECTION_RESET_CLOSED,
283  (MHD_REQUEST_INIT == request->state)
284  ? NULL
285  : _ (
286  "Socket disconnected while reading request.\n"));
287  return;
288  }
289  CONNECTION_CLOSE_ERROR (connection,
290  (MHD_REQUEST_INIT == request->state)
291  ? MHD_SC_CONNECTION_CLOSED
292  : MHD_SC_CONNECTION_READ_FAIL_CLOSED,
293  (MHD_REQUEST_INIT == request->state)
294  ? NULL
295  : _ (
296  "Connection socket is closed due to error when reading request.\n"));
297  return;
298  }
299 
300  if (0 == bytes_read)
301  { /* Remote side closed connection. */
302  connection->read_closed = true;
303  MHD_connection_close_ (connection,
305  return;
306  }
307  request->read_buffer_offset += bytes_read;
309 #if DEBUG_STATES
310  MHD_DLOG (daemon,
311  MHD_SC_STATE_MACHINE_STATUS_REPORT,
312  _ ("In function %s handling connection at state: %s\n"),
313  __FUNCTION__,
314  MHD_state_to_string (request->state));
315 #endif
316  switch (request->state)
317  {
318  case MHD_REQUEST_INIT:
327  /* nothing to do but default action */
328  if (connection->read_closed)
329  {
330  MHD_connection_close_ (connection,
332  }
333  return;
334  case MHD_REQUEST_CLOSED:
335  return;
336 #ifdef UPGRADE_SUPPORT
337  case MHD_REQUEST_UPGRADE:
338  mhd_assert (0);
339  return;
340 #endif /* UPGRADE_SUPPORT */
341  default:
342  /* shrink read buffer to how much is actually used */
343  MHD_pool_reallocate (connection->pool,
344  request->read_buffer,
345  request->read_buffer_size + 1,
346  request->read_buffer_offset);
347  break;
348  }
349  return;
350 }
351 
352 
353 #if defined(_MHD_HAVE_SENDFILE)
354 
360 static ssize_t
361 sendfile_adapter (struct MHD_Connection *connection)
362 {
363  struct MHD_Daemon *daemon = connection->daemon;
364  struct MHD_Request *request = &connection->request;
365  struct MHD_Response *response = request->response;
366  ssize_t ret;
367  const int file_fd = response->fd;
368  uint64_t left;
369  uint64_t offsetu64;
370 #ifndef HAVE_SENDFILE64
371  const uint64_t max_off_t = (uint64_t) OFF_T_MAX;
372 #else /* HAVE_SENDFILE64 */
373  const uint64_t max_off_t = (uint64_t) OFF64_T_MAX;
374 #endif /* HAVE_SENDFILE64 */
375 #ifdef MHD_LINUX_SOLARIS_SENDFILE
376 #ifndef HAVE_SENDFILE64
377  off_t offset;
378 #else /* HAVE_SENDFILE64 */
379  off64_t offset;
380 #endif /* HAVE_SENDFILE64 */
381 #endif /* MHD_LINUX_SOLARIS_SENDFILE */
382 #ifdef HAVE_FREEBSD_SENDFILE
383  off_t sent_bytes;
384  int flags = 0;
385 #endif
386 #ifdef HAVE_DARWIN_SENDFILE
387  off_t len;
388 #endif /* HAVE_DARWIN_SENDFILE */
389  const bool used_thr_p_c = (MHD_TM_THREAD_PER_CONNECTION ==
390  daemon->threading_mode);
391  const size_t chunk_size = used_thr_p_c ? MHD_SENFILE_CHUNK_THR_P_C_ :
393  size_t send_size = 0;
394 
395  mhd_assert (MHD_resp_sender_sendfile == request->resp_sender);
396  offsetu64 = request->response_write_position + response->fd_off;
397  left = response->total_size - request->response_write_position;
398  /* Do not allow system to stick sending on single fast connection:
399  * use 128KiB chunks (2MiB for thread-per-connection). */
400  send_size = (left > chunk_size) ? chunk_size : (size_t) left;
401  if (max_off_t < offsetu64)
402  { /* Retry to send with standard 'send()'. */
403  request->resp_sender = MHD_resp_sender_std;
404  return MHD_ERR_AGAIN_;
405  }
406 #ifdef MHD_LINUX_SOLARIS_SENDFILE
407 #ifndef HAVE_SENDFILE64
408  offset = (off_t) offsetu64;
409  ret = sendfile (connection->socket_fd,
410  file_fd,
411  &offset,
412  send_size);
413 #else /* HAVE_SENDFILE64 */
414  offset = (off64_t) offsetu64;
415  ret = sendfile64 (connection->socket_fd,
416  file_fd,
417  &offset,
418  send_size);
419 #endif /* HAVE_SENDFILE64 */
420  if (0 > ret)
421  {
422  const int err = MHD_socket_get_error_ ();
423 
424  if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
425  {
426 #ifdef EPOLL_SUPPORT
427  /* EAGAIN --- no longer write-ready */
428  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
429 #endif /* EPOLL_SUPPORT */
430  return MHD_ERR_AGAIN_;
431  }
432  if (MHD_SCKT_ERR_IS_EINTR_ (err))
433  return MHD_ERR_AGAIN_;
434 #ifdef HAVE_LINUX_SENDFILE
435  if (MHD_SCKT_ERR_IS_ (err,
437  return MHD_ERR_BADF_;
438  /* sendfile() failed with EINVAL if mmap()-like operations are not
439  supported for FD or other 'unusual' errors occurred, so we should try
440  to fall back to 'SEND'; see also this thread for info on
441  odd libc/Linux behavior with sendfile:
442  http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
443  request->resp_sender = MHD_resp_sender_std;
444  return MHD_ERR_AGAIN_;
445 #else /* HAVE_SOLARIS_SENDFILE */
446  if ( (EAFNOSUPPORT == err) ||
447  (EINVAL == err) ||
448  (EOPNOTSUPP == err) )
449  { /* Retry with standard file reader. */
450  request->resp_sender = MHD_resp_sender_std;
451  return MHD_ERR_AGAIN_;
452  }
453  if ( (ENOTCONN == err) ||
454  (EPIPE == err) )
455  {
456  return MHD_ERR_CONNRESET_;
457  }
458  return MHD_ERR_BADF_; /* Fail hard */
459 #endif /* HAVE_SOLARIS_SENDFILE */
460  }
461 #ifdef EPOLL_SUPPORT
462  else if (send_size > (size_t) ret)
463  connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
464 #endif /* EPOLL_SUPPORT */
465 #elif defined(HAVE_FREEBSD_SENDFILE)
466 #ifdef SF_FLAGS
467  flags = used_thr_p_c ?
468  freebsd_sendfile_flags_thd_p_c_ : freebsd_sendfile_flags_;
469 #endif /* SF_FLAGS */
470  if (0 != sendfile (file_fd,
471  connection->socket_fd,
472  (off_t) offsetu64,
473  send_size,
474  NULL,
475  &sent_bytes,
476  flags))
477  {
478  const int err = MHD_socket_get_error_ ();
479  if (MHD_SCKT_ERR_IS_EAGAIN_ (err) ||
480  MHD_SCKT_ERR_IS_EINTR_ (err) ||
481  (EBUSY == err) )
482  {
483  mhd_assert (SSIZE_MAX >= sent_bytes);
484  if (0 != sent_bytes)
485  return (ssize_t) sent_bytes;
486 
487  return MHD_ERR_AGAIN_;
488  }
489  /* Some unrecoverable error. Possibly file FD is not suitable
490  * for sendfile(). Retry with standard send(). */
491  request->resp_sender = MHD_resp_sender_std;
492  return MHD_ERR_AGAIN_;
493  }
494  mhd_assert (0 < sent_bytes);
495  mhd_assert (SSIZE_MAX >= sent_bytes);
496  ret = (ssize_t) sent_bytes;
497 #elif defined(HAVE_DARWIN_SENDFILE)
498  len = (off_t) send_size; /* chunk always fit */
499  if (0 != sendfile (file_fd,
500  connection->socket_fd,
501  (off_t) offsetu64,
502  &len,
503  NULL,
504  0))
505  {
506  const int err = MHD_socket_get_error_ ();
507  if (MHD_SCKT_ERR_IS_EAGAIN_ (err) ||
509  {
510  mhd_assert (0 <= len);
511  mhd_assert (SSIZE_MAX >= len);
512  mhd_assert (send_size >= (size_t) len);
513  if (0 != len)
514  return (ssize_t) len;
515 
516  return MHD_ERR_AGAIN_;
517  }
518  if ((ENOTCONN == err) ||
519  (EPIPE == err) )
520  return MHD_ERR_CONNRESET_;
521  if ((ENOTSUP == err) ||
522  (EOPNOTSUPP == err) )
523  { /* This file FD is not suitable for sendfile().
524  * Retry with standard send(). */
525  request->resp_sender = MHD_resp_sender_std;
526  return MHD_ERR_AGAIN_;
527  }
528  return MHD_ERR_BADF_; /* Return hard error. */
529  }
530  mhd_assert (0 <= len);
531  mhd_assert (SSIZE_MAX >= len);
532  mhd_assert (send_size >= (size_t) len);
533  ret = (ssize_t) len;
534 #endif /* HAVE_FREEBSD_SENDFILE */
535  return ret;
536 }
537 #endif /* _MHD_HAVE_SENDFILE */
538 
539 
548 static bool
549 check_write_done (struct MHD_Request *request,
550  enum MHD_REQUEST_STATE next_state)
551 {
552  if (request->write_buffer_append_offset !=
553  request->write_buffer_send_offset)
554  return false;
555  request->write_buffer_append_offset = 0;
556  request->write_buffer_send_offset = 0;
557  request->state = next_state;
559  request->write_buffer,
560  request->write_buffer_size,
561  0);
562  request->write_buffer = NULL;
563  request->write_buffer_size = 0;
564  return true;
565 }
566 
567 
578 static bool
580 {
581  struct MHD_Response *response = request->response;
582  struct MHD_Connection *connection = request->connection;
583  ssize_t ret;
584 
585  if (NULL == response->crc)
586  return true;
587  if ( (0 == response->total_size) ||
589  return true; /* 0-byte response is always ready */
590  if ( (response->data_start <=
594  return true; /* response already ready */
595 #if defined(_MHD_HAVE_SENDFILE)
596  if (MHD_resp_sender_sendfile == request->resp_sender)
597  {
598  /* will use sendfile, no need to bother response crc */
599  return true;
600  }
601 #endif /* _MHD_HAVE_SENDFILE */
602 
603  ret = response->crc (response->crc_cls,
605  response->data,
606  (size_t) MHD_MIN ((uint64_t) response->data_buffer_size,
609  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
610  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
611  {
612  /* either error or http 1.0 transfer, close socket! */
615  if ( ((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret)
616  MHD_connection_close_ (connection,
618  else
619  CONNECTION_CLOSE_ERROR (connection,
620  MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
621  _ (
622  "Closing connection (application reported error generating data)\n"));
623  return false;
624  }
626  response->data_size = ret;
627  if (0 == ret)
628  {
631  return false;
632  }
633  return true;
634 }
635 
636 
645 static bool
647 {
648  struct MHD_Connection *connection = request->connection;
649  struct MHD_Response *response = request->response;
650  struct MHD_Daemon *daemon = request->daemon;
651  ssize_t ret;
652  char *buf;
653  size_t size;
654  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
655  int cblen;
656 
657  if (NULL == response->crc)
658  return true;
659  if (0 == request->write_buffer_size)
660  {
661  size = MHD_MIN (daemon->connection_memory_limit_b,
662  2 * (0xFFFFFF + sizeof(cbuf) + 2));
663  do
664  {
665  size /= 2;
666  if (size < 128)
667  {
668  MHD_mutex_unlock_chk_ (&response->mutex);
669  /* not enough memory */
670  CONNECTION_CLOSE_ERROR (connection,
671  MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
672  _ ("Closing connection (out of memory)\n"));
673  return false;
674  }
675  buf = MHD_pool_allocate (connection->pool,
676  size,
677  MHD_NO);
678  }
679  while (NULL == buf);
680  request->write_buffer_size = size;
681  request->write_buffer = buf;
682  }
683 
684  if (0 == response->total_size)
685  ret = 0; /* response must be empty, don't bother calling crc */
686  else if ( (response->data_start <=
687  request->response_write_position) &&
688  (response->data_start + response->data_size >
689  request->response_write_position) )
690  {
691  /* difference between response_write_position and data_start is less
692  than data_size which is size_t type, no need to check for overflow */
693  const size_t data_write_offset
694  = (size_t) (request->response_write_position - response->data_start);
695  /* buffer already ready, use what is there for the chunk */
696  ret = response->data_size - data_write_offset;
697  if ( ((size_t) ret) > request->write_buffer_size - sizeof (cbuf) - 2 )
698  ret = request->write_buffer_size - sizeof (cbuf) - 2;
699  memcpy (&request->write_buffer[sizeof (cbuf)],
700  &response->data[data_write_offset],
701  ret);
702  }
703  else
704  {
705  /* buffer not in range, try to fill it */
706  ret = response->crc (response->crc_cls,
707  request->response_write_position,
708  &request->write_buffer[sizeof (cbuf)],
709  request->write_buffer_size - sizeof (cbuf) - 2);
710  }
711  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
712  {
713  /* error, close socket! */
714  response->total_size = request->response_write_position;
715  MHD_mutex_unlock_chk_ (&response->mutex);
716  CONNECTION_CLOSE_ERROR (connection,
717  MHD_SC_APPLICATION_DATA_GENERATION_FAILURE_CLOSED,
718  _ (
719  "Closing connection (application error generating response)\n"));
720  return false;
721  }
722  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
723  (0 == response->total_size) )
724  {
725  /* end of message, signal other side! */
726  memcpy (request->write_buffer,
727  "0\r\n",
728  3);
729  request->write_buffer_append_offset = 3;
730  request->write_buffer_send_offset = 0;
731  response->total_size = request->response_write_position;
732  return true;
733  }
734  if (0 == ret)
735  {
737  MHD_mutex_unlock_chk_ (&response->mutex);
738  return false;
739  }
740  if (ret > 0xFFFFFF)
741  ret = 0xFFFFFF;
742  cblen = MHD_snprintf_ (cbuf,
743  sizeof (cbuf),
744  "%X\r\n",
745  (unsigned int) ret);
746  mhd_assert (cblen > 0);
747  mhd_assert ((size_t) cblen < sizeof(cbuf));
748  memcpy (&request->write_buffer[sizeof (cbuf) - cblen],
749  cbuf,
750  cblen);
751  memcpy (&request->write_buffer[sizeof (cbuf) + ret],
752  "\r\n",
753  2);
754  request->response_write_position += ret;
755  request->write_buffer_send_offset = sizeof (cbuf) - cblen;
756  request->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
757  return true;
758 }
759 
760 
767 static void
769 {
770  struct MHD_Daemon *daemon = request->daemon;
771  struct MHD_Connection *connection = request->connection;
772  struct MHD_Response *response;
773  ssize_t ret;
774 
775  if (connection->suspended)
776  return;
777 #ifdef HTTPS_SUPPORT
778  {
779  struct MHD_TLS_Plugin *tls;
780 
781  if ( (NULL != (tls = daemon->tls_api)) &&
782  (! tls->handshake (tls->cls,
783  connection->tls_cs)) )
784  return;
785  }
786 #endif /* HTTPS_SUPPORT */
787 
788 #if DEBUG_STATES
789  MHD_DLOG (daemon,
790  MHD_SC_STATE_MACHINE_STATUS_REPORT,
791  _ ("In function %s handling connection at state: %s\n"),
792  __FUNCTION__,
793  MHD_state_to_string (request->state));
794 #endif
795  switch (request->state)
796  {
797  case MHD_REQUEST_INIT:
801  mhd_assert (0);
802  return;
804  return;
806  ret = connection->send_cls (connection,
810  - request->continue_message_write_offset);
811  if (ret < 0)
812  {
813  if (MHD_ERR_AGAIN_ == ret)
814  return;
815 #ifdef HAVE_MESSAGES
816  MHD_DLOG (daemon,
817  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
818  _ ("Failed to send data in request for %s.\n"),
819  request->url);
820 #endif
821  CONNECTION_CLOSE_ERROR (connection,
822  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
823  NULL);
824  return;
825  }
826  request->continue_message_write_offset += ret;
828  return;
833  mhd_assert (0);
834  return;
836  ret = connection->send_cls (connection,
837  &request->write_buffer
838  [request->write_buffer_send_offset],
840  - request->write_buffer_send_offset);
841  if (ret < 0)
842  {
843  if (MHD_ERR_AGAIN_ == ret)
844  return;
845  CONNECTION_CLOSE_ERROR (connection,
846  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
847  _ (
848  "Connection was closed while sending response headers.\n"));
849  return;
850  }
851  request->write_buffer_send_offset += ret;
853  if (MHD_REQUEST_HEADERS_SENDING != request->state)
854  return;
855  check_write_done (request,
857  return;
859  return;
861  response = request->response;
862  if (request->response_write_position <
863  request->response->total_size)
864  {
865  uint64_t data_write_offset;
866 
867  if (NULL != response->crc)
868  MHD_mutex_lock_chk_ (&response->mutex);
869  if (! try_ready_normal_body (request))
870  {
871  /* mutex was already unlocked by try_ready_normal_body */
872  return;
873  }
874 #if defined(_MHD_HAVE_SENDFILE)
875  if (MHD_resp_sender_sendfile == request->resp_sender)
876  {
877  ret = sendfile_adapter (connection);
878  }
879  else
880 #else /* ! _MHD_HAVE_SENDFILE */
881  if (1)
882 #endif /* ! _MHD_HAVE_SENDFILE */
883  {
884  data_write_offset = request->response_write_position
885  - response->data_start;
886  if (data_write_offset > (uint64_t) SIZE_MAX)
887  MHD_PANIC (_ ("Data offset exceeds limit"));
888  ret = connection->send_cls (connection,
889  &response->data
890  [(size_t) data_write_offset],
891  response->data_size
892  - (size_t) data_write_offset);
893 #if DEBUG_SEND_DATA
894  if (ret > 0)
895  fprintf (stderr,
896  _ ("Sent %d-byte DATA response: `%.*s'\n"),
897  (int) ret,
898  (int) ret,
899  &response->data[request->response_write_position
900  - response->data_start]);
901 #endif
902  }
903  if (NULL != response->crc)
904  MHD_mutex_unlock_chk_ (&response->mutex);
905  if (ret < 0)
906  {
907  if (MHD_ERR_AGAIN_ == ret)
908  return;
909 #ifdef HAVE_MESSAGES
910  MHD_DLOG (daemon,
911  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
912  _ ("Failed to send data in request for `%s'.\n"),
913  request->url);
914 #endif
915  CONNECTION_CLOSE_ERROR (connection,
916  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
917  NULL);
918  return;
919  }
920  request->response_write_position += ret;
922  }
923  if (request->response_write_position ==
924  request->response->total_size)
925  request->state = MHD_REQUEST_FOOTERS_SENT; /* have no footers */
926  return;
928  mhd_assert (0);
929  return;
931  ret = connection->send_cls (connection,
932  &request->write_buffer
933  [request->write_buffer_send_offset],
935  - request->write_buffer_send_offset);
936  if (ret < 0)
937  {
938  if (MHD_ERR_AGAIN_ == ret)
939  return;
940  CONNECTION_CLOSE_ERROR (connection,
941  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
942  _ (
943  "Connection was closed while sending response body.\n"));
944  return;
945  }
946  request->write_buffer_send_offset += ret;
948  if (MHD_REQUEST_CHUNKED_BODY_READY != request->state)
949  return;
950  check_write_done (request,
951  (request->response->total_size ==
952  request->response_write_position) ?
955  return;
958  mhd_assert (0);
959  return;
961  ret = connection->send_cls (connection,
962  &request->write_buffer
963  [request->write_buffer_send_offset],
965  - request->write_buffer_send_offset);
966  if (ret < 0)
967  {
968  if (MHD_ERR_AGAIN_ == ret)
969  return;
970  CONNECTION_CLOSE_ERROR (connection,
971  MHD_SC_CONNECTION_WRITE_FAIL_CLOSED,
972  _ (
973  "Connection was closed while sending response body.\n"));
974  return;
975  }
976  request->write_buffer_send_offset += ret;
978  if (MHD_REQUEST_FOOTERS_SENDING != request->state)
979  return;
980  check_write_done (request,
982  return;
984  mhd_assert (0);
985  return;
986  case MHD_REQUEST_CLOSED:
987  return;
988 #ifdef UPGRADE_SUPPORT
989  case MHD_REQUEST_UPGRADE:
990  mhd_assert (0);
991  return;
992 #endif /* UPGRADE_SUPPORT */
993  default:
994  mhd_assert (0);
995  CONNECTION_CLOSE_ERROR (connection,
996  MHD_SC_STATEMACHINE_FAILURE_CONNECTION_CLOSED,
997  _ ("Internal error\n"));
998  break;
999  }
1000 }
1001 
1002 
1016 static bool
1018  const char *header,
1019  const char *token,
1020  size_t token_len)
1021 {
1022  struct MHD_HTTP_Header *pos;
1023 
1024  if ( (NULL == request) || /* FIXME: require non-null? */
1025  (NULL == header) || /* FIXME: require non-null? */
1026  (0 == header[0]) ||
1027  (NULL == token) ||
1028  (0 == token[0]) )
1029  return false;
1030  for (pos = request->headers_received; NULL != pos; pos = pos->next)
1031  {
1032  if ( (0 != (pos->kind & MHD_HEADER_KIND)) &&
1033  ( (header == pos->header) ||
1035  pos->header)) ) &&
1037  token,
1038  token_len)) )
1039  return true;
1040  }
1041  return false;
1042 }
1043 
1044 
1056 #define MHD_lookup_header_s_token_ci(r,h,tkn) \
1057  MHD_lookup_header_token_ci ((r),(h),(tkn),MHD_STATICSTR_LEN_ (tkn))
1058 
1059 
1076 static bool
1078 {
1079  if (MHD_CONN_MUST_CLOSE == request->keepalive)
1080  return false;
1081  if (NULL == request->version_s)
1082  return false;
1083  if ( (NULL != request->response) &&
1084  (request->response->v10_only) )
1085  return false;
1086 
1087  if (MHD_str_equal_caseless_ (request->version_s,
1089  {
1090  if (MHD_lookup_header_s_token_ci (request,
1092  "upgrade"))
1093  return false;
1094  if (MHD_lookup_header_s_token_ci (request,
1096  "close"))
1097  return false;
1098  return true;
1099  }
1100  if (MHD_str_equal_caseless_ (request->version_s,
1102  {
1103  if (MHD_lookup_header_s_token_ci (request,
1105  "Keep-Alive"))
1106  return true;
1107  return false;
1108  }
1109  return false;
1110 }
1111 
1112 
1120 static void
1121 get_date_string (char *date,
1122  size_t date_len)
1123 {
1124  static const char *const days[] = {
1125  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1126  };
1127  static const char *const mons[] = {
1128  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1129  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1130  };
1131  struct tm now;
1132  time_t t;
1133 #if ! defined(HAVE_C11_GMTIME_S) && ! defined(HAVE_W32_GMTIME_S) && \
1134  ! defined(HAVE_GMTIME_R)
1135  struct tm*pNow;
1136 #endif
1137 
1138  date[0] = 0;
1139  time (&t);
1140 #if defined(HAVE_C11_GMTIME_S)
1141  if (NULL == gmtime_s (&t,
1142  &now))
1143  return;
1144 #elif defined(HAVE_W32_GMTIME_S)
1145  if (0 != gmtime_s (&now,
1146  &t))
1147  return;
1148 #elif defined(HAVE_GMTIME_R)
1149  if (NULL == gmtime_r (&t,
1150  &now))
1151  return;
1152 #else
1153  pNow = gmtime (&t);
1154  if (NULL == pNow)
1155  return;
1156  now = *pNow;
1157 #endif
1158  MHD_snprintf_ (date,
1159  date_len,
1160  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1161  days[now.tm_wday % 7],
1162  (unsigned int) now.tm_mday,
1163  mons[now.tm_mon % 12],
1164  (unsigned int) (1900 + now.tm_year),
1165  (unsigned int) now.tm_hour,
1166  (unsigned int) now.tm_min,
1167  (unsigned int) now.tm_sec);
1168 }
1169 
1170 
1184 static bool
1186  const char *key,
1187  const char *token,
1188  size_t token_len)
1189 {
1190  struct MHD_HTTP_Header *pos;
1191 
1192  if ( (NULL == key) ||
1193  ('\0' == key[0]) ||
1194  (NULL == token) ||
1195  ('\0' == token[0]) )
1196  return false;
1197 
1198  for (pos = response->first_header;
1199  NULL != pos;
1200  pos = pos->next)
1201  {
1202  if ( (pos->kind == MHD_HEADER_KIND) &&
1204  key) &&
1206  token,
1207  token_len) )
1208  return true;
1209  }
1210  return false;
1211 }
1212 
1213 
1225 #define check_response_header_s_token_ci(r,k,tkn) \
1226  check_response_header_token_ci ((r),(k),(tkn),MHD_STATICSTR_LEN_ (tkn))
1227 
1228 
1238 static bool
1240 {
1241  struct MHD_Connection *connection = request->connection;
1242  struct MHD_Daemon *daemon = request->daemon;
1243  struct MHD_Response *response = request->response;
1244  size_t size;
1245  size_t off;
1246  struct MHD_HTTP_Header *pos;
1247  char code[256];
1248  char date[128];
1249  size_t datelen;
1250  char content_length_buf[128];
1251  size_t content_length_len;
1252  char *data;
1253  enum MHD_ValueKind kind;
1254  bool client_requested_close;
1255  bool response_has_close;
1256  bool response_has_keepalive;
1257  const char *have_encoding;
1258  const char *have_content_length;
1259  bool must_add_close;
1260  bool must_add_chunked_encoding;
1261  bool must_add_keep_alive;
1262  bool must_add_content_length;
1263 
1264  mhd_assert (NULL != request->version_s);
1265  if (0 == request->version_s[0])
1266  {
1267  data = MHD_pool_allocate (connection->pool,
1268  0,
1269  MHD_YES);
1270  request->write_buffer = data;
1271  request->write_buffer_append_offset = 0;
1272  request->write_buffer_send_offset = 0;
1273  request->write_buffer_size = 0;
1274  return true;
1275  }
1276  if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
1277  {
1278  const char *reason_phrase;
1279  const char *version;
1280 
1281  reason_phrase
1282  = MHD_get_reason_phrase_for (response->status_code);
1283  version
1284  = (response->icy)
1285  ? "ICY"
1287  request->version_s))
1290  MHD_snprintf_ (code,
1291  sizeof (code),
1292  "%s %u %s\r\n",
1293  version,
1294  response->status_code,
1295  reason_phrase);
1296  off = strlen (code);
1297  /* estimate size */
1298  size = off + 2; /* +2 for extra "\r\n" at the end */
1300  if ( (! daemon->suppress_date) &&
1301  (NULL == MHD_response_get_header (response,
1303  get_date_string (date,
1304  sizeof (date));
1305  else
1306  date[0] = '\0';
1307  datelen = strlen (date);
1308  size += datelen;
1309  }
1310  else
1311  {
1312  /* 2 bytes for final CRLF of a Chunked-Body */
1313  size = 2;
1315  off = 0;
1316  datelen = 0;
1317  }
1318 
1319  /* calculate extra headers we need to add, such as 'Connection: close',
1320  first see what was explicitly requested by the application */
1321  must_add_close = false;
1322  must_add_chunked_encoding = false;
1323  must_add_keep_alive = false;
1324  must_add_content_length = false;
1325  response_has_close = false;
1326  switch (request->state)
1327  {
1329  response_has_close
1332  "close");
1333  response_has_keepalive
1336  "Keep-Alive");
1337  client_requested_close
1338  = MHD_lookup_header_s_token_ci (request,
1340  "close");
1341 
1342  if (response->v10_only)
1343  request->keepalive = MHD_CONN_MUST_CLOSE;
1344 #ifdef UPGRADE_SUPPORT
1345  else if (NULL != response->upgrade_handler)
1346  /* If this connection will not be "upgraded", it must be closed. */
1347  request->keepalive = MHD_CONN_MUST_CLOSE;
1348 #endif /* UPGRADE_SUPPORT */
1349 
1350  /* now analyze chunked encoding situation */
1351  request->have_chunked_upload = false;
1352 
1353  if ( (MHD_SIZE_UNKNOWN == response->total_size) &&
1354 #ifdef UPGRADE_SUPPORT
1355  (NULL == response->upgrade_handler) &&
1356 #endif /* UPGRADE_SUPPORT */
1357  (! response_has_close) &&
1358  (! client_requested_close) )
1359  {
1360  /* size is unknown, and close was not explicitly requested;
1361  need to either to HTTP 1.1 chunked encoding or
1362  close the connection */
1363  /* 'close' header doesn't exist yet, see if we need to add one;
1364  if the client asked for a close, no need to start chunk'ing */
1365  if ( (keepalive_possible (request)) &&
1367  request->version_s)) )
1368  {
1369  have_encoding
1370  = MHD_response_get_header (response,
1372  if (NULL == have_encoding)
1373  {
1374  must_add_chunked_encoding = true;
1375  request->have_chunked_upload = true;
1376  }
1377  else if (MHD_str_equal_caseless_ (have_encoding,
1378  "identity"))
1379  {
1380  /* application forced identity encoding, can't do 'chunked' */
1381  must_add_close = true;
1382  }
1383  else
1384  {
1385  request->have_chunked_upload = true;
1386  }
1387  }
1388  else
1389  {
1390  /* Keep alive or chunking not possible
1391  => set close header if not present */
1392  if (! response_has_close)
1393  must_add_close = true;
1394  }
1395  }
1396 
1397  /* check for other reasons to add 'close' header */
1398  if ( ( (client_requested_close) ||
1399  (connection->read_closed) ||
1400  (MHD_CONN_MUST_CLOSE == request->keepalive)) &&
1401  (! response_has_close) &&
1402 #ifdef UPGRADE_SUPPORT
1403  (NULL == response->upgrade_handler) &&
1404 #endif /* UPGRADE_SUPPORT */
1405  (! response->v10_only) )
1406  must_add_close = true;
1407 
1408  /* check if we should add a 'content length' header */
1409  have_content_length
1410  = MHD_response_get_header (response,
1412 
1413  /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1414  codes SHOULD NOT have a Content-Length according to spec;
1415  also chunked encoding / unknown length or CONNECT... */
1416  if ( (MHD_SIZE_UNKNOWN != response->total_size) &&
1417  (MHD_HTTP_NO_CONTENT != response->status_code) &&
1418  (MHD_HTTP_NOT_MODIFIED != response->status_code) &&
1419  (MHD_HTTP_OK <= response->status_code) &&
1420  (NULL == have_content_length) &&
1421  (request->method != MHD_METHOD_CONNECT) )
1422  {
1423  /*
1424  Here we add a content-length if one is missing; however,
1425  for 'connect' methods, the responses MUST NOT include a
1426  content-length header *if* the response code is 2xx (in
1427  which case we expect there to be no body). Still,
1428  as we don't know the response code here in some cases, we
1429  simply only force adding a content-length header if this
1430  is not a 'connect' or if the response is not empty
1431  (which is kind of more sane, because if some crazy
1432  application did return content with a 2xx status code,
1433  then having a content-length might again be a good idea).
1434 
1435  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1436  a recent development of the HTTP 1.1 specification.
1437  */
1438  content_length_len
1439  = MHD_snprintf_ (content_length_buf,
1440  sizeof (content_length_buf),
1443  (MHD_UNSIGNED_LONG_LONG) response->total_size);
1444  must_add_content_length = true;
1445  }
1446 
1447  /* check for adding keep alive */
1448  if ( (! response_has_keepalive) &&
1449  (! response_has_close) &&
1450  (! must_add_close) &&
1451  (MHD_CONN_MUST_CLOSE != request->keepalive) &&
1452 #ifdef UPGRADE_SUPPORT
1453  (NULL == response->upgrade_handler) &&
1454 #endif /* UPGRADE_SUPPORT */
1455  (keepalive_possible (request)) )
1456  must_add_keep_alive = true;
1457  break;
1458  case MHD_REQUEST_BODY_SENT:
1459  response_has_keepalive = false;
1460  break;
1461  default:
1462  mhd_assert (0);
1463  return MHD_NO;
1464  }
1465 
1466  if (MHD_CONN_MUST_CLOSE != request->keepalive)
1467  {
1468  if ( (must_add_close) ||
1469  (response_has_close) )
1470  request->keepalive = MHD_CONN_MUST_CLOSE;
1471  else if ( (must_add_keep_alive) ||
1472  (response_has_keepalive) )
1473  request->keepalive = MHD_CONN_USE_KEEPALIVE;
1474  }
1475 
1476  if (must_add_close)
1477  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1478  if (must_add_keep_alive)
1479  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1480  if (must_add_chunked_encoding)
1481  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1482  if (must_add_content_length)
1483  size += content_length_len;
1484  mhd_assert (! (must_add_close && must_add_keep_alive) );
1485  mhd_assert (! (must_add_chunked_encoding && must_add_content_length) );
1486 
1487  for (pos = response->first_header; NULL != pos; pos = pos->next)
1488  {
1489  /* TODO: add proper support for excluding "Keep-Alive" token. */
1490  if ( (pos->kind == kind) &&
1491  (! ( (must_add_close) &&
1492  (response_has_keepalive) &&
1496  "Keep-Alive")) ) ) )
1497  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1498  }
1499  /* produce data */
1500  data = MHD_pool_allocate (connection->pool,
1501  size + 1,
1502  MHD_NO);
1503  if (NULL == data)
1504  {
1505 #ifdef HAVE_MESSAGES
1506  MHD_DLOG (daemon,
1507  MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
1508  "Not enough memory for write!\n");
1509 #endif
1510  return false;
1511  }
1512  if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
1513  {
1514  memcpy (data,
1515  code,
1516  off);
1517  }
1518  if (must_add_close)
1519  {
1520  /* we must add the 'Connection: close' header */
1521  memcpy (&data[off],
1522  "Connection: close\r\n",
1523  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1524  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1525  }
1526  if (must_add_keep_alive)
1527  {
1528  /* we must add the 'Connection: Keep-Alive' header */
1529  memcpy (&data[off],
1530  "Connection: Keep-Alive\r\n",
1531  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1532  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1533  }
1534  if (must_add_chunked_encoding)
1535  {
1536  /* we must add the 'Transfer-Encoding: chunked' header */
1537  memcpy (&data[off],
1538  "Transfer-Encoding: chunked\r\n",
1539  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1540  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1541  }
1542  if (must_add_content_length)
1543  {
1544  /* we must add the 'Content-Length' header */
1545  memcpy (&data[off],
1546  content_length_buf,
1547  content_length_len);
1548  off += content_length_len;
1549  }
1550  for (pos = response->first_header; NULL != pos; pos = pos->next)
1551  {
1552  /* TODO: add proper support for excluding "Keep-Alive" token. */
1553  if ( (pos->kind == kind) &&
1554  (! ( (must_add_close) &&
1555  (response_has_keepalive) &&
1559  "Keep-Alive")) ) ) )
1560  off += MHD_snprintf_ (&data[off],
1561  size - off,
1562  "%s: %s\r\n",
1563  pos->header,
1564  pos->value);
1565  }
1566  if (MHD_REQUEST_FOOTERS_RECEIVED == request->state)
1567  {
1568  memcpy (&data[off],
1569  date,
1570  datelen);
1571  off += datelen;
1572  }
1573  memcpy (&data[off],
1574  "\r\n",
1575  2);
1576  off += 2;
1577 
1578  if (off != size)
1580  __FILE__,
1581  __LINE__,
1582  NULL);
1583  request->write_buffer = data;
1584  request->write_buffer_append_offset = size;
1585  request->write_buffer_send_offset = 0;
1586  request->write_buffer_size = size + 1;
1587  return true;
1588 }
1589 
1590 
1601 static void
1603  enum MHD_StatusCode ec,
1604  enum MHD_HTTP_StatusCode status_code,
1605  const char *message)
1606 {
1607  struct MHD_Response *response;
1608 
1609  if (NULL == request->version_s)
1610  {
1611  /* we were unable to process the full header line, so we don't
1612  really know what version the client speaks; assume 1.0 */
1613  request->version_s = MHD_HTTP_VERSION_1_0;
1614  }
1616  request->connection->read_closed = true;
1617 #ifdef HAVE_MESSAGES
1618  MHD_DLOG (request->daemon,
1619  ec,
1620  _ (
1621  "Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1622  status_code,
1623  message);
1624 #endif
1625  if (NULL != request->response)
1626  {
1628  request->response = NULL;
1629  }
1631  strlen (message),
1632  (void *) message,
1634  request->response = response;
1635  /* Do not reuse this connection. */
1636  request->keepalive = MHD_CONN_MUST_CLOSE;
1637  if (! build_header_response (request))
1638  {
1639  /* oops - close! */
1641  ec,
1642  _ (
1643  "Closing connection (failed to create response header)\n"));
1644  }
1645  else
1646  {
1648  }
1649 }
1650 
1651 
1658 static enum MHD_Method
1659 method_string_to_enum (const char *method)
1660 {
1661  static const struct
1662  {
1663  const char *key;
1664  enum MHD_Method value;
1665  } methods[] = {
1666  { "OPTIONS", MHD_METHOD_OPTIONS },
1667  { "GET", MHD_METHOD_GET },
1668  { "HEAD", MHD_METHOD_HEAD },
1669  { "POST", MHD_METHOD_POST },
1670  { "PUT", MHD_METHOD_PUT },
1671  { "DELETE", MHD_METHOD_DELETE },
1672  { "TRACE", MHD_METHOD_TRACE },
1673  { "CONNECT", MHD_METHOD_CONNECT },
1674  { "ACL", MHD_METHOD_ACL },
1675  { "BASELINE_CONTROL", MHD_METHOD_BASELINE_CONTROL },
1676  { "BIND", MHD_METHOD_BIND },
1677  { "CHECKIN", MHD_METHOD_CHECKIN },
1678  { "CHECKOUT", MHD_METHOD_CHECKOUT },
1679  { "COPY", MHD_METHOD_COPY },
1680  { "LABEL", MHD_METHOD_LABEL },
1681  { "LINK", MHD_METHOD_LINK },
1682  { "LOCK", MHD_METHOD_LOCK },
1683  { "MERGE", MHD_METHOD_MERGE },
1684  { "MKACTIVITY", MHD_METHOD_MKACTIVITY },
1685  { "MKCOL", MHD_METHOD_MKCOL },
1686  { "MKREDIRECTREF", MHD_METHOD_MKREDIRECTREF },
1687  { "MKWORKSPACE", MHD_METHOD_MKWORKSPACE },
1688  { "MOVE", MHD_METHOD_MOVE },
1689  { "ORDERPATCH", MHD_METHOD_ORDERPATCH },
1690  { "PRI", MHD_METHOD_PRI },
1691  { "PROPFIND", MHD_METHOD_PROPFIND },
1692  { "PROPPATCH", MHD_METHOD_PROPPATCH },
1693  { "REBIND", MHD_METHOD_REBIND },
1694  { "REPORT", MHD_METHOD_REPORT },
1695  { "SEARCH", MHD_METHOD_SEARCH },
1696  { "UNBIND", MHD_METHOD_UNBIND },
1697  { "UNCHECKOUT", MHD_METHOD_UNCHECKOUT },
1698  { "UNLINK", MHD_METHOD_UNLINK },
1699  { "UNLOCK", MHD_METHOD_UNLOCK },
1700  { "UPDATE", MHD_METHOD_UPDATE },
1701  { "UPDATEDIRECTREF", MHD_METHOD_UPDATEDIRECTREF },
1702  { "VERSION-CONTROL", MHD_METHOD_VERSION_CONTROL },
1703  { NULL, MHD_METHOD_UNKNOWN } /* must be last! */
1704  };
1705  unsigned int i;
1706 
1707  for (i = 0; NULL != methods[i].key; i++)
1708  if (0 ==
1709  MHD_str_equal_caseless_ (method,
1710  methods[i].key))
1711  return methods[i].value;
1712  return MHD_METHOD_UNKNOWN;
1713 }
1714 
1715 
1726 static bool
1728  const char *key,
1729  const char *value,
1730  enum MHD_ValueKind kind)
1731 {
1732  if (MHD_NO ==
1733  MHD_request_set_value (request,
1734  kind,
1735  key,
1736  value))
1737  {
1738 #ifdef HAVE_MESSAGES
1739  MHD_DLOG (request->daemon,
1740  MHD_SC_CONNECTION_POOL_MALLOC_FAILURE,
1741  _ ("Not enough memory in pool to allocate header record!\n"));
1742 #endif
1743  transmit_error_response (request,
1744  MHD_SC_CLIENT_HEADER_TOO_BIG,
1746  REQUEST_TOO_BIG);
1747  return false;
1748  }
1749  return true;
1750 }
1751 
1752 
1761 static bool
1763  char *line,
1764  size_t line_len)
1765 {
1766  struct MHD_Daemon *daemon = request->daemon;
1767  const char *curi;
1768  char *uri;
1769  char *http_version;
1770  char *args;
1771  unsigned int unused_num_headers;
1772  size_t url_end;
1773 
1774  if (NULL == (uri = memchr (line,
1775  ' ',
1776  line_len)))
1777  return false; /* serious error */
1778  uri[0] = '\0';
1779  request->method_s = line;
1780  request->method = method_string_to_enum (line);
1781  uri++;
1782  /* Skip any spaces. Not required by standard but allow
1783  to be more tolerant. */
1784  while ( (' ' == uri[0]) &&
1785  ( (size_t) (uri - line) < line_len) )
1786  uri++;
1787  if ((size_t) (uri - line) == line_len)
1788  {
1789  curi = "";
1790  uri = NULL;
1791  request->version_s = "";
1792  args = NULL;
1793  url_end = line_len - (line - uri); // EH, this is garbage. FIXME!
1794  }
1795  else
1796  {
1797  curi = uri;
1798  /* Search from back to accept misformed URI with space */
1799  http_version = line + line_len - 1;
1800  /* Skip any trailing spaces */
1801  while ( (' ' == http_version[0]) &&
1802  (http_version > uri) )
1803  http_version--;
1804  /* Find first space in reverse direction */
1805  while ( (' ' != http_version[0]) &&
1806  (http_version > uri) )
1807  http_version--;
1808  if (http_version > uri)
1809  {
1810  http_version[0] = '\0';
1811  request->version_s = http_version + 1;
1812  args = memchr (uri,
1813  '?',
1814  http_version - uri);
1815  }
1816  else
1817  {
1818  request->version_s = "";
1819  args = memchr (uri,
1820  '?',
1821  line_len - (uri - line));
1822  }
1823  url_end = http_version - uri;
1824  }
1825  if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) &&
1826  (NULL != memchr (curi,
1827  ' ',
1828  url_end)) )
1829  {
1830  /* space exists in URI and we are supposed to be strict, reject */
1831  return MHD_NO;
1832  }
1833  if (NULL != daemon->early_uri_logger_cb)
1834  {
1835  request->client_context
1836  = daemon->early_uri_logger_cb (daemon->early_uri_logger_cb_cls,
1837  curi,
1838  request);
1839  }
1840  if (NULL != args)
1841  {
1842  args[0] = '\0';
1843  args++;
1844  /* note that this call clobbers 'args' */
1845  MHD_parse_arguments_ (request,
1847  args,
1849  &unused_num_headers);
1850  }
1851  if (NULL != uri)
1852  daemon->unescape_cb (daemon->unescape_cb_cls,
1853  request,
1854  uri);
1855  request->url = curi;
1856  return true;
1857 }
1858 
1859 
1869 static bool
1871  char *line)
1872 {
1873  struct MHD_Connection *connection = request->connection;
1874  char *colon;
1875 
1876  /* line should be normal header line, find colon */
1877  colon = strchr (line,
1878  ':');
1879  if (NULL == colon)
1880  {
1881  /* error in header line, die hard */
1882  CONNECTION_CLOSE_ERROR (connection,
1883  MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1884  _ (
1885  "Received malformed line (no colon). Closing connection.\n"));
1886  return false;
1887  }
1888  if (MHD_PSL_PERMISSIVE != request->daemon->protocol_strict_level)
1889  {
1890  /* check for whitespace before colon, which is not allowed
1891  by RFC 7230 section 3.2.4; we count space ' ' and
1892  tab '\t', but not '\r\n' as those would have ended the line. */
1893  const char *white;
1894 
1895  white = strchr (line,
1896  (unsigned char) ' ');
1897  if ( (NULL != white) &&
1898  (white < colon) )
1899  {
1900  CONNECTION_CLOSE_ERROR (connection,
1901  MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1902  _ (
1903  "Whitespace before colon forbidden by RFC 7230. Closing connection.\n"));
1904  return false;
1905  }
1906  white = strchr (line,
1907  (unsigned char) '\t');
1908  if ( (NULL != white) &&
1909  (white < colon) )
1910  {
1911  CONNECTION_CLOSE_ERROR (connection,
1912  MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
1913  _ (
1914  "Tab before colon forbidden by RFC 7230. Closing connection.\n"));
1915  return false;
1916  }
1917  }
1918  /* zero-terminate header */
1919  colon[0] = '\0';
1920  colon++; /* advance to value */
1921  while ( ('\0' != colon[0]) &&
1922  ( (' ' == colon[0]) ||
1923  ('\t' == colon[0]) ) )
1924  colon++;
1925  /* we do the actual adding of the connection
1926  header at the beginning of the while
1927  loop since we need to be able to inspect
1928  the *next* header line (in case it starts
1929  with a space...) */
1930  request->last = line;
1931  request->colon = colon;
1932  return true;
1933 }
1934 
1935 
1946 static bool
1948  char *line,
1949  enum MHD_ValueKind kind)
1950 {
1951  struct MHD_Connection *connection = request->connection;
1952  char *last;
1953  char *tmp;
1954  size_t last_len;
1955  size_t tmp_len;
1956 
1957  last = request->last;
1958  if ( (' ' == line[0]) ||
1959  ('\t' == line[0]) )
1960  {
1961  /* value was continued on the next line, see
1962  http://www.jmarshall.com/easy/http/ */
1963  last_len = strlen (last);
1964  /* skip whitespace at start of 2nd line */
1965  tmp = line;
1966  while ( (' ' == tmp[0]) ||
1967  ('\t' == tmp[0]) )
1968  tmp++;
1969  tmp_len = strlen (tmp);
1970  /* FIXME: we might be able to do this better (faster!), as most
1971  likely 'last' and 'line' should already be adjacent in
1972  memory; however, doing this right gets tricky if we have a
1973  value continued over multiple lines (in which case we need to
1974  record how often we have done this so we can check for
1975  adjacency); also, in the case where these are not adjacent
1976  (not sure how it can happen!), we would want to allocate from
1977  the end of the pool, so as to not destroy the read-buffer's
1978  ability to grow nicely. */
1979  last = MHD_pool_reallocate (connection->pool,
1980  last,
1981  last_len + 1,
1982  last_len + tmp_len + 1);
1983  if (NULL == last)
1984  {
1986  MHD_SC_CLIENT_HEADER_TOO_BIG,
1988  REQUEST_TOO_BIG);
1989  return MHD_NO;
1990  }
1991  memcpy (&last[last_len],
1992  tmp,
1993  tmp_len + 1);
1994  request->last = last;
1995  return MHD_YES; /* possibly more than 2 lines... */
1996  }
1997  mhd_assert ( (NULL != last) &&
1998  (NULL != request->colon) );
1999  if (! request_add_header (request,
2000  last,
2001  request->colon,
2002  kind))
2003  {
2005  MHD_SC_CLIENT_HEADER_TOO_BIG,
2007  REQUEST_TOO_BIG);
2008  return false;
2009  }
2010  /* we still have the current line to deal with... */
2011  if ('\0' != line[0])
2012  {
2014  line))
2015  {
2017  MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
2020  return false;
2021  }
2022  }
2023  return true;
2024 }
2025 
2026 
2040 static char *
2042  size_t *line_len)
2043 {
2044  char *rbuf;
2045  size_t pos;
2046 
2047  if (0 == request->read_buffer_offset)
2048  return NULL;
2049  pos = 0;
2050  rbuf = request->read_buffer;
2051  while ( (pos < request->read_buffer_offset - 1) &&
2052  ('\r' != rbuf[pos]) &&
2053  ('\n' != rbuf[pos]) )
2054  pos++;
2055  if ( (pos == request->read_buffer_offset - 1) &&
2056  ('\n' != rbuf[pos]) )
2057  {
2058  /* not found, consider growing... */
2061  {
2063  MHD_SC_CLIENT_HEADER_TOO_BIG,
2064  (NULL != request->url)
2067  REQUEST_TOO_BIG);
2068  }
2069  if (line_len)
2070  *line_len = 0;
2071  return NULL;
2072  }
2073 
2074  if (line_len)
2075  *line_len = pos;
2076  /* found, check if we have proper LFCR */
2077  if ( ('\r' == rbuf[pos]) &&
2078  ('\n' == rbuf[pos + 1]) )
2079  rbuf[pos++] = '\0'; /* skip both r and n */
2080  rbuf[pos++] = '\0';
2081  request->read_buffer += pos;
2082  request->read_buffer_size -= pos;
2083  request->read_buffer_offset -= pos;
2084  return rbuf;
2085 }
2086 
2087 
2107 static bool
2109 {
2110  (void) connection; /* Mute compiler warning. */
2111 #if defined(TCP_CORK) || defined(TCP_PUSH)
2112  return true;
2113 #else /* !TCP_CORK && !TCP_PUSH */
2114  return false;
2115 #endif /* !TCP_CORK && !TCP_PUSH */
2116 }
2117 
2118 
2126 static bool
2128 {
2129  bool res = false;
2130  (void) connection; /* Mute compiler warning. */
2131 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
2132  const MHD_SCKT_OPT_BOOL_ on_val = 1;
2133 #if defined(TCP_NODELAY)
2134  const MHD_SCKT_OPT_BOOL_ off_val = 0;
2135 #endif /* TCP_NODELAY */
2136  mhd_assert (NULL != connection);
2137 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2138  /* Buffer data before sending */
2139  res = (0 == setsockopt (connection->socket_fd,
2140  IPPROTO_TCP,
2141  TCP_NOPUSH,
2142  (const void *) &on_val,
2143  sizeof (on_val)))
2144  ? true : false;
2145 #if defined(TCP_NODELAY)
2146  /* Enable Nagle's algorithm */
2147  /* TCP_NODELAY may interfere with TCP_NOPUSH */
2148  res &= (0 == setsockopt (connection->socket_fd,
2149  IPPROTO_TCP,
2150  TCP_NODELAY,
2151  (const void *) &off_val,
2152  sizeof (off_val)))
2153  ? true : false;
2154 #endif /* TCP_NODELAY */
2155 #else /* TCP_CORK */
2156 #if defined(TCP_NODELAY)
2157  /* Enable Nagle's algorithm */
2158  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
2159  solely on TCP_CORK result, so ignoring return code here. */
2160  (void) setsockopt (connection->socket_fd,
2161  IPPROTO_TCP,
2162  TCP_NODELAY,
2163  (const void *) &off_val,
2164  sizeof (off_val));
2165 #endif /* TCP_NODELAY */
2166  /* Send only full packets */
2167  res = (0 == setsockopt (connection->socket_fd,
2168  IPPROTO_TCP,
2169  TCP_CORK,
2170  (const void *) &on_val,
2171  sizeof (on_val)))
2172  ? true : false;
2173 #endif /* TCP_CORK */
2174 #endif /* TCP_CORK || TCP_NOPUSH */
2175  return res;
2176 }
2177 
2178 
2185 static bool
2187 {
2188 #if defined(TCP_NODELAY)
2189  bool res = true;
2190  const MHD_SCKT_OPT_BOOL_ on_val = 1;
2191 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
2192  const MHD_SCKT_OPT_BOOL_ off_val = 0;
2193 #endif /* TCP_CORK || TCP_NOPUSH */
2194 
2195  (void) connection; /* Mute compiler warning. */
2196  mhd_assert (NULL != connection);
2197 #if defined(TCP_CORK)
2198  /* Allow partial packets */
2199  res &= (0 == setsockopt (connection->socket_fd,
2200  IPPROTO_TCP,
2201  TCP_CORK,
2202  (const void *) &off_val,
2203  sizeof (off_val)))
2204  ? true : false;
2205 #endif /* TCP_CORK */
2206 #if defined(TCP_NODELAY)
2207  /* Disable Nagle's algorithm for sending packets without delay */
2208  res &= (0 == setsockopt (connection->socket_fd,
2209  IPPROTO_TCP,
2210  TCP_NODELAY,
2211  (const void *) &on_val,
2212  sizeof (on_val)))
2213  ? true : false;
2214 #endif /* TCP_NODELAY */
2215 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2216  /* Disable extra buffering */
2217  res &= (0 == setsockopt (connection->socket_fd,
2218  IPPROTO_TCP,
2219  TCP_NOPUSH,
2220  (const void *) &off_val,
2221  sizeof (off_val)))
2222  ? true : false;
2223 #endif /* TCP_NOPUSH && !TCP_CORK */
2224  return res;
2225 #else /* !TCP_NODELAY */
2226  return false;
2227 #endif /* !TCP_NODELAY */
2228 }
2229 
2230 
2238 static bool
2240 {
2241  bool res = true;
2242 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2243  const int dummy = 0;
2244 #endif /* !TCP_CORK */
2245 
2246  if (NULL == connection)
2247  return false; /* FIXME: use MHD_NONNULL? */
2248  res = socket_start_no_buffering (connection);
2249 #if defined(TCP_NOPUSH) && ! defined(TCP_CORK)
2250  /* Force flush data with zero send otherwise Darwin and some BSD systems
2251  will add 5 seconds delay. Not required with TCP_CORK as switching off
2252  TCP_CORK always flushes socket buffer. */
2253  res &= (0 <= MHD_send_ (connection->socket_fd,
2254  &dummy,
2255  0))
2256  ? true : false;
2257 #endif /* TCP_NOPUSH && !TCP_CORK*/
2258  return res;
2259 }
2260 
2261 
2268 static bool
2270 {
2271 #if defined(TCP_NODELAY)
2272  bool res = true;
2273  const MHD_SCKT_OPT_BOOL_ off_val = 0;
2274 #if defined(TCP_CORK)
2275  MHD_SCKT_OPT_BOOL_ cork_val = 0;
2276  socklen_t param_size = sizeof (cork_val);
2277 #endif /* TCP_CORK */
2278 
2279  mhd_assert (NULL != connection);
2280 #if defined(TCP_CORK)
2281  /* Allow partial packets */
2282  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
2283  so try to check current value of TCP_CORK to prevent unrequested flushing */
2284  if ( (0 != getsockopt (connection->socket_fd,
2285  IPPROTO_TCP,
2286  TCP_CORK,
2287  (void*) &cork_val,
2288  &param_size)) ||
2289  (0 != cork_val))
2290  res &= (0 == setsockopt (connection->socket_fd,
2291  IPPROTO_TCP,
2292  TCP_CORK,
2293  (const void *) &off_val,
2294  sizeof (off_val)))
2295  ? true : false;
2296 #elif defined(TCP_NOPUSH)
2297  /* Disable extra buffering */
2298  /* No need to check current value as disabling TCP_NOPUSH will not flush partial
2299  packet if TCP_NOPUSH wasn't enabled before */
2300  res &= (0 == setsockopt (connection->socket_fd,
2301  IPPROTO_TCP,
2302  TCP_NOPUSH,
2303  (const void *) &off_val,
2304  sizeof (off_val)))
2305  ? true : false;
2306 #endif /* TCP_NOPUSH && !TCP_CORK */
2307  /* Enable Nagle's algorithm for normal buffering */
2308  res &= (0 == setsockopt (connection->socket_fd,
2309  IPPROTO_TCP,
2310  TCP_NODELAY,
2311  (const void *) &off_val,
2312  sizeof (off_val)))
2313  ? true : false;
2314  return res;
2315 #else /* !TCP_NODELAY */
2316  return false;
2317 #endif /* !TCP_NODELAY */
2318 }
2319 
2320 
2328 static bool
2330 {
2331  const char *expect;
2332 
2333  return ( (NULL == request->response) &&
2334  (NULL != request->version_s) &&
2337  (NULL != (expect = MHD_request_lookup_value (request,
2340  &&
2341  (MHD_str_equal_caseless_ (expect,
2342  "100-continue")) &&
2345 }
2346 
2347 
2354 static int
2356 {
2357  const char *hdr;
2358  char *cpy;
2359  char *pos;
2360  char *sce;
2361  char *semicolon;
2362  char *equals;
2363  char *ekill;
2364  char old;
2365  int quotes;
2366 
2370  if (NULL == hdr)
2371  return true;
2373  strlen (hdr) + 1,
2374  MHD_YES);
2375  if (NULL == cpy)
2376  {
2377 #ifdef HAVE_MESSAGES
2378  MHD_DLOG (request->daemon,
2379  MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
2380  _ ("Not enough memory in pool to parse cookies!\n"));
2381 #endif
2383  MHD_SC_COOKIE_POOL_ALLOCATION_FAILURE,
2385  REQUEST_TOO_BIG);
2386  return false;
2387  }
2388  memcpy (cpy,
2389  hdr,
2390  strlen (hdr) + 1);
2391  pos = cpy;
2392  while (NULL != pos)
2393  {
2394  while (' ' == *pos)
2395  pos++; /* skip spaces */
2396 
2397  sce = pos;
2398  while ( ((*sce) != '\0') &&
2399  ((*sce) != ',') &&
2400  ((*sce) != ';') &&
2401  ((*sce) != '=') )
2402  sce++;
2403  /* remove tailing whitespace (if any) from key */
2404  ekill = sce - 1;
2405  while ( (*ekill == ' ') &&
2406  (ekill >= pos) )
2407  *(ekill--) = '\0';
2408  old = *sce;
2409  *sce = '\0';
2410  if (old != '=')
2411  {
2412  /* value part omitted, use empty string... */
2413  if (! request_add_header (request,
2414  pos,
2415  "",
2416  MHD_COOKIE_KIND))
2417  return false;
2418  if (old == '\0')
2419  break;
2420  pos = sce + 1;
2421  continue;
2422  }
2423  equals = sce + 1;
2424  quotes = 0;
2425  semicolon = equals;
2426  while ( ('\0' != semicolon[0]) &&
2427  ( (0 != quotes) ||
2428  ( (';' != semicolon[0]) &&
2429  (',' != semicolon[0]) ) ) )
2430  {
2431  if ('"' == semicolon[0])
2432  quotes = (quotes + 1) & 1;
2433  semicolon++;
2434  }
2435  if ('\0' == semicolon[0])
2436  semicolon = NULL;
2437  if (NULL != semicolon)
2438  {
2439  semicolon[0] = '\0';
2440  semicolon++;
2441  }
2442  /* remove quotes */
2443  if ( ('"' == equals[0]) &&
2444  ('"' == equals[strlen (equals) - 1]) )
2445  {
2446  equals[strlen (equals) - 1] = '\0';
2447  equals++;
2448  }
2449  if (! request_add_header (request,
2450  pos,
2451  equals,
2452  MHD_COOKIE_KIND))
2453  return false;
2454  pos = semicolon;
2455  }
2456  return true;
2457 }
2458 
2459 
2467 static void
2469 {
2470  struct MHD_Daemon *daemon = request->daemon;
2471  struct MHD_Connection *connection = request->connection;
2472  const char *clen;
2473  struct MHD_Response *response;
2474  const char *enc;
2475  const char *end;
2476 
2477  parse_cookie_header (request); /* FIXME: return value ignored! */
2478  if ( (MHD_PSL_STRICT == daemon->protocol_strict_level) &&
2479  (NULL != request->version_s) &&
2481  request->version_s)) &&
2482  (NULL ==
2483  MHD_request_lookup_value (request,
2486  {
2487  /* die, http 1.1 request without host and we are pedantic */
2489  connection->read_closed = true;
2490 #ifdef HAVE_MESSAGES
2491  MHD_DLOG (daemon,
2492  MHD_SC_HOST_HEADER_MISSING,
2493  _ ("Received HTTP 1.1 request without `Host' header.\n"));
2494 #endif
2495  mhd_assert (NULL == request->response);
2496  response =
2501  request->response = response;
2502  // FIXME: state machine advance?
2503  return;
2504  }
2505 
2506  request->remaining_upload_size = 0;
2507  enc = MHD_request_lookup_value (request,
2510  if (NULL != enc)
2511  {
2513  if (MHD_str_equal_caseless_ (enc,
2514  "chunked"))
2515  request->have_chunked_upload = true;
2516  return;
2517  }
2518  clen = MHD_request_lookup_value (request,
2521  if (NULL == clen)
2522  return;
2523  end = clen + MHD_str_to_uint64_ (clen,
2524  &request->remaining_upload_size);
2525  if ( (clen == end) ||
2526  ('\0' != *end) )
2527  {
2528  request->remaining_upload_size = 0;
2529 #ifdef HAVE_MESSAGES
2530  MHD_DLOG (request->daemon,
2531  MHD_SC_CONTENT_LENGTH_MALFORMED,
2532  "Failed to parse `Content-Length' header. Closing connection.\n");
2533 #endif
2534  CONNECTION_CLOSE_ERROR (connection,
2535  MHD_SC_CONTENT_LENGTH_MALFORMED,
2536  NULL);
2537  }
2538 }
2539 
2540 
2547 static void
2549 {
2550  struct MHD_Daemon *daemon = request->daemon;
2551  struct MHD_Connection *connection = request->connection;
2552  const struct MHD_Action *action;
2553 
2554  if (NULL != request->response)
2555  return; /* already queued a response */
2556  if (NULL == (action =
2557  daemon->rc (daemon->rc_cls,
2558  request,
2559  request->url,
2560  request->method)))
2561  {
2562  /* serious internal error, close connection */
2563  CONNECTION_CLOSE_ERROR (connection,
2564  MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
2565  _ (
2566  "Application reported internal error, closing connection.\n"));
2567  return;
2568  }
2569  action->action (action->action_cls,
2570  request);
2571 }
2572 
2573 
2580 static void
2582 {
2583  struct MHD_Daemon *daemon = request->daemon;
2584  struct MHD_Connection *connection = request->connection;
2585  size_t available;
2586  bool instant_retry;
2587  char *buffer_head;
2588 
2589  if (NULL != request->response)
2590  return; /* already queued a response */
2591 
2592  buffer_head = request->read_buffer;
2593  available = request->read_buffer_offset;
2594  do
2595  {
2596  size_t to_be_processed;
2597  size_t left_unprocessed;
2598  size_t processed_size;
2599 
2600  instant_retry = false;
2601  if ( (request->have_chunked_upload) &&
2603  {
2605  (0LLU != request->current_chunk_offset) &&
2606  (available >= 2) )
2607  {
2608  size_t i;
2609 
2610  /* skip new line at the *end* of a chunk */
2611  i = 0;
2612  if ( ('\r' == buffer_head[i]) ||
2613  ('\n' == buffer_head[i]) )
2614  i++; /* skip 1st part of line feed */
2615  if ( ('\r' == buffer_head[i]) ||
2616  ('\n' == buffer_head[i]) )
2617  i++; /* skip 2nd part of line feed */
2618  if (0 == i)
2619  {
2620  /* malformed encoding */
2621  CONNECTION_CLOSE_ERROR (connection,
2622  MHD_SC_CHUNKED_ENCODING_MALFORMED,
2623  _ (
2624  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2625  return;
2626  }
2627  available -= i;
2628  buffer_head += i;
2631  }
2634  {
2635  uint64_t cur_chunk_left;
2636 
2637  /* we are in the middle of a chunk, give
2638  as much as possible to the client (without
2639  crossing chunk boundaries) */
2640  cur_chunk_left
2642  if (cur_chunk_left > available)
2643  {
2644  to_be_processed = available;
2645  }
2646  else
2647  { /* cur_chunk_left <= (size_t)available */
2648  to_be_processed = (size_t) cur_chunk_left;
2649  if (available > to_be_processed)
2650  instant_retry = true;
2651  }
2652  }
2653  else
2654  {
2655  size_t i;
2656  size_t end_size;
2657  bool malformed;
2658 
2659  /* we need to read chunk boundaries */
2660  i = 0;
2661  while (i < available)
2662  {
2663  if ( ('\r' == buffer_head[i]) ||
2664  ('\n' == buffer_head[i]) ||
2665  (';' == buffer_head[i]) )
2666  break;
2667  i++;
2668  if (i >= 16)
2669  break;
2670  }
2671  end_size = i;
2672  /* find beginning of CRLF (skip over chunk extensions) */
2673  if (';' == buffer_head[i])
2674  {
2675  while (i < available)
2676  {
2677  if ( ('\r' == buffer_head[i]) ||
2678  ('\n' == buffer_head[i]) )
2679  break;
2680  i++;
2681  }
2682  }
2683  /* take '\n' into account; if '\n' is the unavailable
2684  character, we will need to wait until we have it
2685  before going further */
2686  if ( (i + 1 >= available) &&
2687  ! ( (1 == i) &&
2688  (2 == available) &&
2689  ('0' == buffer_head[0]) ) )
2690  break; /* need more data... */
2691  i++;
2692  malformed = (end_size >= 16);
2693  if (! malformed)
2694  {
2695  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2696  end_size,
2698  malformed = (end_size != num_dig);
2699  }
2700  if (malformed)
2701  {
2702  /* malformed encoding */
2703  CONNECTION_CLOSE_ERROR (connection,
2704  MHD_SC_CHUNKED_ENCODING_MALFORMED,
2705  _ (
2706  "Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2707  return;
2708  }
2709  /* skip 2nd part of line feed */
2710  if ( (i < available) &&
2711  ( ('\r' == buffer_head[i]) ||
2712  ('\n' == buffer_head[i]) ) )
2713  i++;
2714 
2715  buffer_head += i;
2716  available -= i;
2718 
2719  if (available > 0)
2720  instant_retry = true;
2721  if (0LLU == request->current_chunk_size)
2722  {
2724  break;
2725  }
2726  continue;
2727  }
2728  }
2729  else
2730  {
2731  /* no chunked encoding, give all to the client */
2732  if ( (0 != request->remaining_upload_size) &&
2734  (request->remaining_upload_size < available) )
2735  {
2736  to_be_processed = (size_t) request->remaining_upload_size;
2737  }
2738  else
2739  {
2744  to_be_processed = available;
2745  }
2746  }
2747  left_unprocessed = to_be_processed;
2748 #if FIXME_OLD_STYLE
2749  if (MHD_NO ==
2750  daemon->rc (daemon->rc_cls,
2751  request,
2752  request->url,
2753  request->method,
2754  request->version,
2755  buffer_head,
2756  &left_unprocessed,
2758  {
2759  /* serious internal error, close connection */
2760  CONNECTION_CLOSE_ERROR (connection,
2761  MHD_SC_APPLICATION_CALLBACK_FAILURE_CLOSED,
2762  _ (
2763  "Application reported internal error, closing connection.\n"));
2764  return;
2765  }
2766 #endif
2767  if (left_unprocessed > to_be_processed)
2769  __FILE__,
2770  __LINE__
2771 #ifdef HAVE_MESSAGES
2772  , _ ("libmicrohttpd API violation")
2773 #else
2774  , NULL
2775 #endif
2776  );
2777  if (0 != left_unprocessed)
2778  {
2779  instant_retry = false; /* client did not process everything */
2780 #ifdef HAVE_MESSAGES
2781  /* client did not process all upload data, complain if
2782  the setup was incorrect, which may prevent us from
2783  handling the rest of the request */
2784  if ( (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_mode) &&
2785  (! connection->suspended) )
2786  MHD_DLOG (daemon,
2787  MHD_SC_APPLICATION_HUNG_CONNECTION,
2788  _ (
2789  "WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2790 #endif
2791  }
2792  processed_size = to_be_processed - left_unprocessed;
2794  request->current_chunk_offset += processed_size;
2795  /* dh left "processed" bytes in buffer for next time... */
2796  buffer_head += processed_size;
2797  available -= processed_size;
2799  request->remaining_upload_size -= processed_size;
2800  }
2801  while (instant_retry);
2802  if (available > 0)
2803  memmove (request->read_buffer,
2804  buffer_head,
2805  available);
2806  request->read_buffer_offset = available;
2807 }
2808 
2809 
2818 static void
2820 {
2821  struct MHD_Daemon *daemon = connection->daemon;
2822 
2823  if (connection->request.in_cleanup)
2824  return; /* Prevent double cleanup. */
2825  connection->request.in_cleanup = true;
2826  if (NULL != connection->request.response)
2827  {
2829  connection->request.response = NULL;
2830  }
2832  if (connection->suspended)
2833  {
2836  connection);
2837  connection->suspended = false;
2838  }
2839  else
2840  {
2841  if (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode)
2842  {
2843  if (connection->connection_timeout ==
2846  daemon->normal_timeout_tail,
2847  connection);
2848  else
2850  daemon->manual_timeout_tail,
2851  connection);
2852  }
2853  DLL_remove (daemon->connections_head,
2854  daemon->connections_tail,
2855  connection);
2856  }
2857  DLL_insert (daemon->cleanup_head,
2858  daemon->cleanup_tail,
2859  connection);
2860  connection->resuming = false;
2861  connection->request.in_idle = false;
2863  if (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_mode)
2864  {
2865  /* if we were at the connection limit before and are in
2866  thread-per-connection mode, signal the main thread
2867  to resume accepting connections */
2868  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2869  (! MHD_itc_activate_ (daemon->itc,
2870  "c")) )
2871  {
2872 #ifdef HAVE_MESSAGES
2873  MHD_DLOG (daemon,
2874  MHD_SC_ITC_USE_FAILED,
2875  _ (
2876  "Failed to signal end of connection via inter-thread communication channel"));
2877 #endif
2878  }
2879  }
2880 }
2881 
2882 
2883 #ifdef EPOLL_SUPPORT
2884 
2892 static bool
2893 connection_epoll_update_ (struct MHD_Connection *connection)
2894 {
2895  struct MHD_Daemon *daemon = connection->daemon;
2896 
2897  if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) &&
2898  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2899  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2900  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->request.event_loop_info) &&
2901  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
2902  ( (MHD_EVENT_LOOP_INFO_READ == connection->request.event_loop_info) &&
2903  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
2904  {
2905  /* add to epoll set */
2906  struct epoll_event event;
2907 
2908  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2909  event.data.ptr = connection;
2910  if (0 != epoll_ctl (daemon->epoll_fd,
2911  EPOLL_CTL_ADD,
2912  connection->socket_fd,
2913  &event))
2914  {
2915 #ifdef HAVE_MESSAGES
2916  MHD_DLOG (daemon,
2917  MHD_SC_EPOLL_CTL_ADD_FAILED,
2918  _ ("Call to epoll_ctl failed: %s\n"),
2920 #endif
2921  connection->request.state = MHD_REQUEST_CLOSED;
2922  cleanup_connection (connection);
2923  return false;
2924  }
2925  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2926  }
2927  return true;
2928 }
2929 #endif
2930 
2931 
2940 static void
2942 {
2943  struct MHD_Daemon *daemon = connection->daemon;
2944  struct MHD_Request *request = &connection->request;
2945 
2946  /* Do not update states of suspended connection */
2947  if (connection->suspended)
2948  return; /* States will be updated after resume. */
2949 #ifdef HTTPS_SUPPORT
2950  {
2951  struct MHD_TLS_Plugin *tls;
2952 
2953  if ( (NULL != (tls = daemon->tls_api)) &&
2954  (tls->update_event_loop_info (tls->cls,
2955  connection->tls_cs,
2956  &request->event_loop_info)) )
2957  return; /* TLS has decided what to do */
2958  }
2959 #endif /* HTTPS_SUPPORT */
2960  while (1)
2961  {
2962 #if DEBUG_STATES
2963  MHD_DLOG (daemon,
2964  MHD_SC_STATE_MACHINE_STATUS_REPORT,
2965  _ ("In function %s handling connection at state: %s\n"),
2966  __FUNCTION__,
2967  MHD_state_to_string (request->state));
2968 #endif
2969  switch (request->state)
2970  {
2971  case MHD_REQUEST_INIT:
2974  /* while reading headers, we always grow the
2975  read buffer if needed, no size-check required */
2976  if ( (request->read_buffer_offset == request->read_buffer_size) &&
2977  (! try_grow_read_buffer (request)) )
2978  {
2979  transmit_error_response (request,
2980  MHD_SC_CLIENT_HEADER_TOO_BIG,
2981  (NULL != request->url)
2984  REQUEST_TOO_BIG);
2985  continue;
2986  }
2987  if (! connection->read_closed)
2989  else
2991  break;
2993  mhd_assert (0);
2994  break;
2996  mhd_assert (0);
2997  break;
3000  break;
3002  if (request->read_buffer_offset == request->read_buffer_size)
3003  {
3004  if ( (! try_grow_read_buffer (request)) &&
3005  (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_mode) )
3006  {
3007  /* failed to grow the read buffer, and the client
3008  which is supposed to handle the received data in
3009  a *blocking* fashion (in this mode) did not
3010  handle the data as it was supposed to!
3011 
3012  => we would either have to do busy-waiting
3013  (on the client, which would likely fail),
3014  or if we do nothing, we would just timeout
3015  on the connection (if a timeout is even set!).
3016 
3017  Solution: we kill the connection with an error */
3018  transmit_error_response (request,
3019  MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
3021  INTERNAL_ERROR);
3022  continue;
3023  }
3024  }
3025  if ( (request->read_buffer_offset < request->read_buffer_size) &&
3026  (! connection->read_closed) )
3028  else
3030  break;
3033  /* while reading footers, we always grow the
3034  read buffer if needed, no size-check required */
3035  if (connection->read_closed)
3036  {
3037  CONNECTION_CLOSE_ERROR (connection,
3038  MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3039  NULL);
3040  continue;
3041  }
3043  /* transition to FOOTERS_RECEIVED
3044  happens in read handler */
3045  break;
3048  break;
3050  /* headers in buffer, keep writing */
3052  break;
3054  mhd_assert (0);
3055  break;
3058  break;
3061  break;
3064  break;
3067  break;
3068  case MHD_REQUEST_BODY_SENT:
3069  mhd_assert (0);
3070  break;
3073  break;
3075  mhd_assert (0);
3076  break;
3077  case MHD_REQUEST_CLOSED:
3079  return; /* do nothing, not even reading */
3080 #ifdef UPGRADE_SUPPORT
3081  case MHD_REQUEST_UPGRADE:
3082  mhd_assert (0);
3083  break;
3084 #endif /* UPGRADE_SUPPORT */
3085  default:
3086  mhd_assert (0);
3087  }
3088  break;
3089  }
3090 }
3091 
3092 
3103 bool
3105 {
3106  struct MHD_Daemon *daemon = request->daemon;
3107  struct MHD_Connection *connection = request->connection;
3108  char *line;
3109  size_t line_len;
3110  bool ret;
3111 
3112  request->in_idle = true;
3113  while (! connection->suspended)
3114  {
3115 #ifdef HTTPS_SUPPORT
3116  struct MHD_TLS_Plugin *tls;
3117 
3118  if ( (NULL != (tls = daemon->tls_api)) &&
3119  (! tls->idle_ready (tls->cls,
3120  connection->tls_cs)) )
3121  break;
3122 #endif /* HTTPS_SUPPORT */
3123 #if DEBUG_STATES
3124  MHD_DLOG (daemon,
3125  MHD_SC_STATE_MACHINE_STATUS_REPORT,
3126  _ ("In function %s handling connection at state: %s\n"),
3127  __FUNCTION__,
3128  MHD_state_to_string (request->state));
3129 #endif
3130  switch (request->state)
3131  {
3132  case MHD_REQUEST_INIT:
3133  line = get_next_header_line (request,
3134  &line_len);
3135  /* Check for empty string, as we might want
3136  to tolerate 'spurious' empty lines; also
3137  NULL means we didn't get a full line yet;
3138  line is not 0-terminated here. */
3139  if ( (NULL == line) ||
3140  (0 == line[0]) )
3141  {
3142  if (MHD_REQUEST_INIT != request->state)
3143  continue;
3144  if (connection->read_closed)
3145  {
3146  CONNECTION_CLOSE_ERROR (connection,
3147  MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3148  NULL);
3149  continue;
3150  }
3151  break;
3152  }
3153  if (MHD_NO ==
3154  parse_initial_message_line (request,
3155  line,
3156  line_len))
3157  CONNECTION_CLOSE_ERROR (connection,
3158  MHD_SC_CONNECTION_CLOSED,
3159  NULL);
3160  else
3161  request->state = MHD_REQUEST_URL_RECEIVED;
3162  continue;
3164  line = get_next_header_line (request,
3165  NULL);
3166  if (NULL == line)
3167  {
3168  if (MHD_REQUEST_URL_RECEIVED != request->state)
3169  continue;
3170  if (connection->read_closed)
3171  {
3172  CONNECTION_CLOSE_ERROR (connection,
3173  MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3174  NULL);
3175  continue;
3176  }
3177  break;
3178  }
3179  if (0 == line[0])
3180  {
3182  request->header_size = (size_t) (line - request->read_buffer);
3183  continue;
3184  }
3185  if (! process_header_line (request,
3186  line))
3187  {
3188  transmit_error_response (request,
3189  MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
3192  break;
3193  }
3195  continue;
3197  line = get_next_header_line (request,
3198  NULL);
3199  if (NULL == line)
3200  {
3201  if (request->state != MHD_REQUEST_HEADER_PART_RECEIVED)
3202  continue;
3203  if (connection->read_closed)
3204  {
3205  CONNECTION_CLOSE_ERROR (connection,
3206  MHD_SC_CONNECTION_READ_FAIL_CLOSED,
3207  NULL);
3208  continue;
3209  }
3210  break;
3211  }
3212  if (MHD_NO ==
3213  process_broken_line (request,
3214  line,
3215  MHD_HEADER_KIND))
3216  continue;
3217  if (0 == line[0])
3218  {
3220  request->header_size = (size_t) (line - request->read_buffer);
3221  continue;
3222  }
3223  continue;
3225  parse_request_headers (request);
3226  if (MHD_REQUEST_CLOSED == request->state)
3227  continue;
3229  if (connection->suspended)
3230  break;
3231  continue;
3233  call_request_handler (request); /* first call */
3234  if (MHD_REQUEST_CLOSED == request->state)
3235  continue;
3236  if (need_100_continue (request))
3237  {
3239  if (socket_flush_possible (connection))
3240  socket_start_extra_buffering (connection);
3241  else
3242  socket_start_no_buffering (connection);
3243  break;
3244  }
3245  if ( (NULL != request->response) &&
3246  ( (MHD_METHOD_POST == request->method) ||
3247  (MHD_METHOD_PUT == request->method) ) )
3248  {
3249  /* we refused (no upload allowed!) */
3250  request->remaining_upload_size = 0;
3251  /* force close, in case client still tries to upload... */
3252  connection->read_closed = true;
3253  }
3254  request->state = (0 == request->remaining_upload_size)
3257  if (connection->suspended)
3258  break;
3259  continue;
3261  if (request->continue_message_write_offset ==
3263  {
3264  request->state = MHD_REQUEST_CONTINUE_SENT;
3265  if (! socket_flush_possible (connection))
3266  socket_start_no_buffering_flush (connection);
3267  else
3268  socket_start_normal_buffering (connection);
3269  continue;
3270  }
3271  break;
3273  if (0 != request->read_buffer_offset)
3274  {
3275  process_request_body (request); /* loop call */
3276  if (MHD_REQUEST_CLOSED == request->state)
3277  continue;
3278  }
3279  if ( (0 == request->remaining_upload_size) ||
3280  ( (MHD_SIZE_UNKNOWN == request->remaining_upload_size) &&
3281  (0 == request->read_buffer_offset) &&
3282  (connection->read_closed) ) )
3283  {
3284  if ( (request->have_chunked_upload) &&
3285  (! connection->read_closed) )
3286  request->state = MHD_REQUEST_BODY_RECEIVED;
3287  else
3289  if (connection->suspended)
3290  break;
3291  continue;
3292  }
3293  break;
3295  line = get_next_header_line (request,
3296  NULL);
3297  if (NULL == line)
3298  {
3299  if (request->state != MHD_REQUEST_BODY_RECEIVED)
3300  continue;
3301  if (connection->read_closed)
3302  {
3303  CONNECTION_CLOSE_ERROR (connection,
3304  MHD_SC_CONNECTION_CLOSED,
3305  NULL);
3306  continue;
3307  }
3308  break;
3309  }
3310  if (0 == line[0])
3311  {
3313  if (connection->suspended)
3314  break;
3315  continue;
3316  }
3317  if (MHD_NO == process_header_line (request,
3318  line))
3319  {
3320  transmit_error_response (request,
3321  MHD_SC_CONNECTION_PARSE_FAIL_CLOSED,
3324  break;
3325  }
3327  continue;
3329  line = get_next_header_line (request,
3330  NULL);
3331  if (NULL == line)
3332  {
3333  if (request->state != MHD_REQUEST_FOOTER_PART_RECEIVED)
3334  continue;
3335  if (connection->read_closed)
3336  {
3337  CONNECTION_CLOSE_ERROR (connection,
3338  MHD_SC_CONNECTION_CLOSED,
3339  NULL);
3340  continue;
3341  }
3342  break;
3343  }
3344  if (MHD_NO ==
3345  process_broken_line (request,
3346  line,
3347  MHD_FOOTER_KIND))
3348  continue;
3349  if (0 == line[0])
3350  {
3352  if (connection->suspended)
3353  break;
3354  continue;
3355  }
3356  continue;
3358  call_request_handler (request); /* "final" call */
3359  if (request->state == MHD_REQUEST_CLOSED)
3360  continue;
3361  if (NULL == request->response)
3362  break; /* try again next time */
3363  if (! build_header_response (request))
3364  {
3365  /* oops - close! */
3366  CONNECTION_CLOSE_ERROR (connection,
3367  MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
3368  _ (
3369  "Closing connection (failed to create response header)\n"));
3370  continue;
3371  }
3373  if (MHD_NO != socket_flush_possible (connection))
3374  socket_start_extra_buffering (connection);
3375  else
3376  socket_start_no_buffering (connection);
3377 
3378  break;
3380  /* no default action */
3381  break;
3383  /* Some clients may take some actions right after header receive */
3384  if (MHD_NO != socket_flush_possible (connection))
3385  socket_start_no_buffering_flush (connection);
3386 
3387 #ifdef UPGRADE_SUPPORT
3388  if (NULL != request->response->upgrade_handler)
3389  {
3390  socket_start_normal_buffering (connection);
3391  request->state = MHD_REQUEST_UPGRADE;
3392 #if FIXME_LEGACY_STYLE
3393  /* This request is "upgraded". Pass socket to application. */
3394  if (! MHD_response_execute_upgrade_ (request->response,
3395  request))
3396  {
3397  /* upgrade failed, fail hard */
3398  CONNECTION_CLOSE_ERROR (connection,
3399  MHD_SC_CONNECTION_CLOSED,
3400  NULL);
3401  continue;
3402  }
3403 #endif
3404  /* Response is not required anymore for this request. */
3405  {
3406  struct MHD_Response *const resp = request->response;
3407 
3408  request->response = NULL;
3410  }
3411  continue;
3412  }
3413 #endif /* UPGRADE_SUPPORT */
3414  if (MHD_NO != socket_flush_possible (connection))
3415  socket_start_extra_buffering (connection);
3416  else
3417  socket_start_normal_buffering (connection);
3418 
3419  if (request->have_chunked_upload)
3421  else
3423  continue;
3425  /* nothing to do here */
3426  break;
3428  if (NULL != request->response->crc)
3429  MHD_mutex_lock_chk_ (&request->response->mutex);
3430  if (0 == request->response->total_size)
3431  {
3432  if (NULL != request->response->crc)
3433  MHD_mutex_unlock_chk_ (&request->response->mutex);
3434  request->state = MHD_REQUEST_BODY_SENT;
3435  continue;
3436  }
3437  if (try_ready_normal_body (request))
3438  {
3439  if (NULL != request->response->crc)
3440  MHD_mutex_unlock_chk_ (&request->response->mutex);
3442  /* Buffering for flushable socket was already enabled*/
3443  if (MHD_NO == socket_flush_possible (connection))
3444  socket_start_no_buffering (connection);
3445  break;
3446  }
3447  /* mutex was already unlocked by "try_ready_normal_body */
3448  /* not ready, no socket action */
3449  break;
3451  /* nothing to do here */
3452  break;
3454  if (NULL != request->response->crc)
3455  MHD_mutex_lock_chk_ (&request->response->mutex);
3456  if ( (0 == request->response->total_size) ||
3457  (request->response_write_position ==
3458  request->response->total_size) )
3459  {
3460  if (NULL != request->response->crc)
3461  MHD_mutex_unlock_chk_ (&request->response->mutex);
3462  request->state = MHD_REQUEST_BODY_SENT;
3463  continue;
3464  }
3465  if (try_ready_chunked_body (request))
3466  {
3467  if (NULL != request->response->crc)
3468  MHD_mutex_unlock_chk_ (&request->response->mutex);
3470  /* Buffering for flushable socket was already enabled */
3471  if (MHD_NO == socket_flush_possible (connection))
3472  socket_start_no_buffering (connection);
3473  continue;
3474  }
3475  /* mutex was already unlocked by try_ready_chunked_body */
3476  break;
3477  case MHD_REQUEST_BODY_SENT:
3478  if (! build_header_response (request))
3479  {
3480  /* oops - close! */
3481  CONNECTION_CLOSE_ERROR (connection,
3482  MHD_SC_FAILED_RESPONSE_HEADER_GENERATION,
3483  _ (
3484  "Closing connection (failed to create response header)\n"));
3485  continue;
3486  }
3487  if ( (! request->have_chunked_upload) ||
3488  (request->write_buffer_send_offset ==
3489  request->write_buffer_append_offset) )
3490  request->state = MHD_REQUEST_FOOTERS_SENT;
3491  else
3493  continue;
3495  /* no default action */
3496  break;
3498  {
3499  struct MHD_Response *response = request->response;
3500 
3501  if (MHD_HTTP_PROCESSING == response->status_code)
3502  {
3503  /* After this type of response, we allow sending another! */
3505  MHD_response_queue_for_destroy (response);
3506  request->response = NULL;
3507  /* FIXME: maybe partially reset memory pool? */
3508  continue;
3509  }
3510  if (socket_flush_possible (connection))
3511  socket_start_no_buffering_flush (connection);
3512  else
3513  socket_start_normal_buffering (connection);
3514 
3515  if (NULL != response->termination_cb)
3516  {
3517  response->termination_cb (response->termination_cb_cls,
3519  request->client_context);
3520  }
3521  MHD_response_queue_for_destroy (response);
3522  request->response = NULL;
3523  }
3524  if ( (MHD_CONN_USE_KEEPALIVE != request->keepalive) ||
3525  (connection->read_closed) )
3526  {
3527  /* have to close for some reason */
3528  MHD_connection_close_ (connection,
3530  MHD_pool_destroy (connection->pool);
3531  connection->pool = NULL;
3532  request->read_buffer = NULL;
3533  request->read_buffer_size = 0;
3534  request->read_buffer_offset = 0;
3535  }
3536  else
3537  {
3538  /* can try to keep-alive */
3539  if (socket_flush_possible (connection))
3540  socket_start_normal_buffering (connection);
3541  request->version_s = NULL;
3542  request->state = MHD_REQUEST_INIT;
3543  request->last = NULL;
3544  request->colon = NULL;
3545  request->header_size = 0;
3547  /* Reset the read buffer to the starting size,
3548  preserving the bytes we have already read. */
3549  request->read_buffer
3550  = MHD_pool_reset (connection->pool,
3551  request->read_buffer,
3552  request->read_buffer_offset,
3553  daemon->connection_memory_limit_b / 2);
3554  request->read_buffer_size
3555  = daemon->connection_memory_limit_b / 2;
3556  }
3557  // FIXME: this is too much, NULLs out some of the things
3558  // initialized above...
3559  memset (request,
3560  0,
3561  sizeof (struct MHD_Request));
3562  request->daemon = daemon;
3563  request->connection = connection;
3564  continue;
3565  case MHD_REQUEST_CLOSED:
3566  cleanup_connection (connection);
3567  request->in_idle = false;
3568  return false;
3569 #ifdef UPGRADE_SUPPORT
3570  case MHD_REQUEST_UPGRADE:
3571  request->in_idle = false;
3572  return true; /* keep open */
3573 #endif /* UPGRADE_SUPPORT */
3574  default:
3575  mhd_assert (0);
3576  break;
3577  }
3578  break;
3579  }
3580  if (! connection->suspended)
3581  {
3582  time_t timeout;
3583  timeout = connection->connection_timeout;
3584  if ( (0 != timeout) &&
3585  (timeout < (MHD_monotonic_sec_counter ()
3586  - connection->last_activity)) )
3587  {
3588  MHD_connection_close_ (connection,
3590  request->in_idle = false;
3591  return true;
3592  }
3593  }
3594  connection_update_event_loop_info (connection);
3595  ret = true;
3596 #ifdef EPOLL_SUPPORT
3597  if ( (! connection->suspended) &&
3598  (MHD_ELS_EPOLL == daemon->event_loop_syscall) )
3599  {
3600  ret = connection_epoll_update_ (connection);
3601  }
3602 #endif /* EPOLL_SUPPORT */
3603  request->in_idle = false;
3604  return ret;
3605 }
3606 
3607 
3621 // FIXME: rename connection->request?
3622 int
3624  bool read_ready,
3625  bool write_ready,
3626  bool force_close)
3627 {
3628  struct MHD_Daemon *daemon = con->daemon;
3629  int ret;
3630  bool states_info_processed = false;
3631  /* Fast track flag */
3632  bool on_fasttrack = (con->request.state == MHD_REQUEST_INIT);
3633 
3634 #ifdef HTTPS_SUPPORT
3635  if (con->tls_read_ready)
3636  read_ready = true;
3637 #endif /* HTTPS_SUPPORT */
3638  if (! force_close)
3639  {
3640  if ( (MHD_EVENT_LOOP_INFO_READ ==
3641  con->request.event_loop_info) &&
3642  read_ready)
3643  {
3645  ret = MHD_request_handle_idle_ (&con->request);
3646  states_info_processed = true;
3647  }
3648  /* No need to check value of 'ret' here as closed connection
3649  * cannot be in MHD_EVENT_LOOP_INFO_WRITE state. */
3650  if ( (MHD_EVENT_LOOP_INFO_WRITE ==
3651  con->request.event_loop_info) &&
3652  write_ready)
3653  {
3655  ret = MHD_request_handle_idle_ (&con->request);
3656  states_info_processed = true;
3657  }
3658  }
3659  else
3660  {
3661  MHD_connection_close_ (con,
3663  return MHD_request_handle_idle_ (&con->request);
3664  }
3665 
3666  if (! states_info_processed)
3667  { /* Connection is not read or write ready, but external conditions
3668  * may be changed and need to be processed. */
3669  ret = MHD_request_handle_idle_ (&con->request);
3670  }
3671  /* Fast track for fast connections. */
3672  /* If full request was read by single read_handler() invocation
3673  and headers were completely prepared by single MHD_request_handle_idle_()
3674  then try not to wait for next sockets polling and send response
3675  immediately.
3676  As writeability of socket was not checked and it may have
3677  some data pending in system buffers, use this optimization
3678  only for non-blocking sockets. */
3679  /* No need to check 'ret' as connection is always in
3680  * MHD_CONNECTION_CLOSED state if 'ret' is equal 'MHD_NO'. */
3681  else if (on_fasttrack &&
3682  con->sk_nonblck)
3683  {
3685  {
3687  /* Always call 'MHD_request_handle_idle_()' after each read/write. */
3688  ret = MHD_request_handle_idle_ (&con->request);
3689  }
3690  /* If all headers were sent by single write_handler() and
3691  * response body is prepared by single MHD_request_handle_idle_()
3692  * call - continue. */
3695  {
3697  ret = MHD_request_handle_idle_ (&con->request);
3698  }
3699  }
3700 
3701  /* All connection's data and states are processed for this turn.
3702  * If connection already has more data to be processed - use
3703  * zero timeout for next select()/poll(). */
3704  /* Thread-per-connection do not need global zero timeout as
3705  * connections are processed individually. */
3706  /* Note: no need to check for read buffer availability for
3707  * TLS read-ready connection in 'read info' state as connection
3708  * without space in read buffer will be market as 'info block'. */
3709  if ( (! daemon->data_already_pending) &&
3710  (MHD_TM_THREAD_PER_CONNECTION != daemon->threading_mode) )
3711  {
3713  con->request.event_loop_info)
3714  daemon->data_already_pending = true;
3715 #ifdef HTTPS_SUPPORT
3716  else if ( (con->tls_read_ready) &&
3718  con->request.event_loop_info) )
3719  daemon->data_already_pending = true;
3720 #endif /* HTTPS_SUPPORT */
3721  }
3722  return ret;
3723 }
3724 
3725 /* end of connection_call_handlers.c */
#define check_response_header_s_token_ci(r, k, tkn)
#define SSIZE_MAX
Definition: mhd_limits.h:111
static void parse_request_headers(struct MHD_Request *request)
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:261
size_t continue_message_write_offset
Definition: internal.h:544
struct MHD_Request request
Definition: internal.h:717
enum MHD_EventLoopSyscall event_loop_syscall
Definition: internal.h:1436
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:574
#define MHD_PANIC(msg)
Definition: internal.h:69
#define REQUEST_LACKS_HOST
uint64_t total_size
Definition: internal.h:1642
#define HTTP_100_CONTINUE
uint64_t fd_off
Definition: internal.h:1653
bool data_already_pending
Definition: internal.h:1500
size_t connection_memory_limit_b
Definition: internal.h:1281
static void get_date_string(char *date, size_t date_len)
MHD_EarlyUriLogCallback early_uri_logger_cb
Definition: internal.h:1036
bool in_cleanup
Definition: internal.h:571
struct MHD_Connection * cleanup_head
Definition: internal.h:1177
void * data
Definition: microhttpd.h:3031
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:457
void * mhd_panic_cls
Definition: panic.c:36
#define OFF_T_MAX
Definition: mhd_limits.h:123
size_t header_size
Definition: internal.h:502
size_t read_buffer_offset
Definition: internal.h:480
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:180
MHD_PanicCallback mhd_panic
Definition: panic.c:31
void * termination_cb_cls
Definition: internal.h:1617
#define INTERNAL_ERROR
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:523
uint64_t current_chunk_size
Definition: internal.h:516
enum MHD_ProtocolStrictLevel protocol_strict_level
Definition: internal.h:1442
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:584
static bool check_response_header_token_ci(const struct MHD_Response *response, const char *key, const char *token, size_t token_len)
#define MHD_YES
Definition: microhttpd.h:140
#define SIZE_MAX
Definition: mhd_limits.h:99
enum MHD_Bool MHD_request_set_value(struct MHD_Request *request, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: request.c:96
struct MHD_Response * response
Definition: internal.h:678
char * data
Definition: internal.h:1588
char * colon
Definition: internal.h:759
MHD_RequestTerminationCallback termination_cb
Definition: internal.h:1612
#define REQUEST_MALFORMED
char * read_buffer
Definition: internal.h:433
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:365
char * colon
Definition: internal.h:456
const char * MHD_request_lookup_value(struct MHD_Request *request, enum MHD_ValueKind kind, const char *key)
Definition: request.c:138
static bool build_header_response(struct MHD_Request *request)
#define MHD_ERR_AGAIN_
Definition: internal.h:1867
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:397
bool MHD_parse_arguments_(struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:186
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1143
MHD_REQUEST_STATE
Definition: internal.h:216
size_t data_size
Definition: internal.h:1659
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:333
time_t MHD_monotonic_sec_counter(void)
char * value
Definition: internal.h:352
static bool check_write_done(struct MHD_Request *request, enum MHD_REQUEST_STATE next_state)
enum MHD_ValueKind kind
Definition: internal.h:358
bool in_idle
Definition: internal.h:565
static void cleanup_connection(struct MHD_Connection *connection)
size_t write_buffer_size
Definition: internal.h:485
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:642
static bool try_ready_chunked_body(struct MHD_Request *request)
#define MHD_lookup_header_s_token_ci(r, h, tkn)
uint64_t current_chunk_offset
Definition: internal.h:522
internal shared structures
static void transmit_error_response(struct MHD_Request *request, enum MHD_StatusCode ec, enum MHD_HTTP_StatusCode status_code, const char *message)
static enum MHD_Method method_string_to_enum(const char *method)
#define MHD_ERR_CONNRESET_
Definition: internal.h:1872
char * header
Definition: internal.h:347
static bool socket_start_extra_buffering(struct MHD_Connection *connection)
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:290
struct MHD_Daemon * daemon
Definition: internal.h:675
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
static bool socket_start_normal_buffering(struct MHD_Connection *connection)
function to update last activity of a connection
time_t connection_default_timeout
Definition: internal.h:1371
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:694
enum MHD_REQUEST_STATE state
Definition: internal.h:549
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:426
static bool MHD_lookup_header_token_ci(const struct MHD_Request *request, const char *header, const char *token, size_t token_len)
struct MHD_Daemon * daemon
Definition: internal.h:372
bool v10_only
Definition: internal.h:1685
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
#define DLL_insert(head, tail, element)
Definition: internal.h:1745
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:404
static bool process_header_line(struct MHD_Request *request, char *line)
static void MHD_request_handle_read_(struct MHD_Request *request)
struct MHD_HTTP_Header * first_header
Definition: internal.h:1582
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:548
size_t data_buffer_size
Definition: internal.h:1664
void * unescape_cb_cls
Definition: internal.h:1063
void * crc_cls
Definition: internal.h:1594
struct MHD_Connection * connections_tail
Definition: internal.h:1160
#define MHD_SENFILE_CHUNK_THR_P_C_
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
#define REQUEST_TOO_BIG
char * write_buffer
Definition: internal.h:439
#define MHD_SCKT_EBADF_
Definition: mhd_sockets.h:454
functions to close connection
struct MHD_Response * MHD_response_from_buffer(enum MHD_HTTP_StatusCode sc, size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
ActionCallback action
Definition: internal.h:1554
static bool socket_start_no_buffering(struct MHD_Connection *connection)
size_t read_buffer_size
Definition: internal.h:474
MHD_UnescapeCallback unescape_cb
Definition: internal.h:1058
static bool process_broken_line(struct MHD_Request *request, char *line, enum MHD_ValueKind kind)
MHD_socket socket_fd
Definition: internal.h:752
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:676
enum MHD_HTTP_StatusCode status_code
Definition: internal.h:1669
size_t connection_memory_increment_b
Definition: internal.h:1296
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:248
struct MHD_Connection * connections_head
Definition: internal.h:1155
static bool socket_start_no_buffering_flush(struct MHD_Connection *connection)
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:343
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode rtc)
uint64_t remaining_upload_size
Definition: internal.h:508
time_t connection_timeout
Definition: internal.h:745
#define MHD_SCKT_ERR_IS_(err, code)
Definition: mhd_sockets.h:610
enum MHD_RequestEventLoopInfo event_loop_info
Definition: internal.h:559
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:166
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1150
function to call event handlers based on event mask
static bool need_100_continue(struct MHD_Request *request)
#define NULL
Definition: reason_phrase.c:30
char * last
Definition: internal.h:750
static bool socket_flush_possible(struct MHD_Connection *connection)
static int parse_cookie_header(struct MHD_Request *request)
MHD_RequestCallback rc
Definition: internal.h:1005
MHD_ValueKind
Definition: microhttpd.h:1757
char * version_s
Definition: internal.h:419
#define DLL_remove(head, tail, element)
Definition: internal.h:1765
static bool try_grow_read_buffer(struct MHD_Request *request)
ReceiveCallback recv_cls
Definition: internal.h:706
enum MHD_Method method
Definition: internal.h:554
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
uint64_t data_start
Definition: internal.h:1648
bool have_chunked_upload
Definition: internal.h:580
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:880
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1128
int MHD_connection_call_handlers_(struct MHD_Connection *con, bool read_ready, bool write_ready, bool force_close)
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:431
int off_t offset
Definition: microhttpd.h:3161
static void call_request_handler(struct MHD_Request *request)
#define XDLL_remove(head, tail, element)
Definition: internal.h:1809
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:376
#define MHD_ERR_BADF_
Definition: internal.h:1888
static void connection_close_error(struct MHD_Connection *connection, enum MHD_StatusCode sc, const char *emsg)
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1172
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:203
bool tls_read_ready
Definition: internal.h:769
struct MHD_itc_ itc
Definition: internal.h:1410
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
time_t last_activity
Definition: internal.h:739
struct MHD_Connection * cleanup_tail
Definition: internal.h:1182
struct MHD_HTTP_Header * headers_received
Definition: internal.h:388
static void process_request_body(struct MHD_Request *request)
char * method_s
Definition: internal.h:407
static bool try_ready_normal_body(struct MHD_Request *request)
bool sk_nonblck
Definition: internal.h:784
#define CONNECTION_CLOSE_ERROR(c, sc, emsg)
enum MHD_ResponseFlags flags
Definition: internal.h:400
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:578
size_t write_buffer_send_offset
Definition: internal.h:490
struct MHD_HTTP_Header * next
Definition: internal.h:342
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1135
struct MHD_Response * response
Definition: internal.h:383
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
void * early_uri_logger_cb_cls
Definition: internal.h:1041
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:560
bool read_closed
Definition: internal.h:792
bool suppress_date
Definition: internal.h:1456
static bool request_add_header(struct MHD_Request *request, const char *key, const char *value, enum MHD_ValueKind kind)
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:879
struct MemoryPool * pool
Definition: internal.h:685
TransmitCallback send_cls
Definition: internal.h:711
void * rc_cls
Definition: internal.h:1010
static bool keepalive_possible(struct MHD_Request *request)
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:437
uint64_t response_write_position
Definition: internal.h:529
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:167
MHD_ContentReaderCallback crc
Definition: internal.h:1600
enum MHD_Bool(* handshake)(void *cls, struct MHD_TLS_ConnectionState *cs)
MHD_mutex_ mutex
Definition: internal.h:1637
static char * get_next_header_line(struct MHD_Request *request, size_t *line_len)
size_t write_buffer_append_offset
Definition: internal.h:496
static void MHD_request_handle_write_(struct MHD_Request *request)
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:304
struct MHD_Connection * connection
Definition: internal.h:377
bool suspended
Definition: internal.h:764
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:566
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:330
const char * url
Definition: internal.h:413
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:159
#define MHD_MIN(a, b)
Definition: internal.h:109
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1166
size_t read_buffer_offset
Definition: internal.h:787
static void connection_update_event_loop_info(struct MHD_Connection *connection)
#define MHD_NO
Definition: microhttpd.h:145
enum MHD_ThreadingMode threading_mode
Definition: internal.h:1417
void * client_context
Definition: internal.h:401
char * last
Definition: internal.h:447
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:633
#define MHD_SENFILE_CHUNK_
void MHD_connection_update_last_activity_(struct MHD_Connection *connection)
bool MHD_request_handle_idle_(struct MHD_Request *request)
enum MHD_Bool(* idle_ready)(void *cls, struct MHD_TLS_ConnectionState *cs)
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1265
static bool parse_initial_message_line(struct MHD_Request *request, char *line, size_t line_len)
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:622
const char * MHD_response_get_header(struct MHD_Response *response, const char *key)
Definition: response.c:243
enum MHD_Bool(* update_event_loop_info)(void *cls, struct MHD_TLS_ConnectionState *cs, enum MHD_RequestEventLoopInfo *eli)
void MHD_response_queue_for_destroy(struct MHD_Response *response)
Definition: response.c:88