GNU libmicrohttpd  0.9.29
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2015 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 
19 */
27 #include "internal.h"
28 #include <limits.h>
29 #include "connection.h"
30 #include "memorypool.h"
31 #include "response.h"
32 #include "mhd_mono_clock.h"
33 
34 #if HAVE_NETINET_TCP_H
35 /* for TCP_CORK */
36 #include <netinet/tcp.h>
37 #endif
38 
39 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
40 #ifndef WIN32_LEAN_AND_MEAN
41 #define WIN32_LEAN_AND_MEAN 1
42 #endif /* !WIN32_LEAN_AND_MEAN */
43 #include <windows.h>
44 #endif /* _WIN32 && MHD_W32_MUTEX_ */
45 
46 
50 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
51 
59 #if HAVE_MESSAGES
60 #define REQUEST_TOO_BIG "<html><head><title>Request too big</title></head><body>Your HTTP header was too big for the memory constraints of this webserver.</body></html>"
61 #else
62 #define REQUEST_TOO_BIG ""
63 #endif
64 
72 #if HAVE_MESSAGES
73 #define REQUEST_LACKS_HOST "<html><head><title>&quot;Host:&quot; header required</title></head><body>In HTTP 1.1, requests must include a &quot;Host:&quot; header, and your HTTP 1.1 request lacked such a header.</body></html>"
74 #else
75 #define REQUEST_LACKS_HOST ""
76 #endif
77 
85 #if HAVE_MESSAGES
86 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
87 #else
88 #define REQUEST_MALFORMED ""
89 #endif
90 
97 #if HAVE_MESSAGES
98 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
99 #else
100 #define INTERNAL_ERROR ""
101 #endif
102 
107 #define DEBUG_CLOSE MHD_NO
108 
112 #define DEBUG_SEND_DATA MHD_NO
113 
114 
126 int
128  enum MHD_ValueKind kind,
129  MHD_KeyValueIterator iterator,
130  void *iterator_cls)
131 {
132  int ret;
133  struct MHD_HTTP_Header *pos;
134 
135  if (NULL == connection)
136  return -1;
137  ret = 0;
138  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
139  if (0 != (pos->kind & kind))
140  {
141  ret++;
142  if ( (NULL != iterator) &&
143  (MHD_YES != iterator (iterator_cls,
144  pos->kind,
145  pos->header,
146  pos->value)) )
147  return ret;
148  }
149  return ret;
150 }
151 
152 
178 int
180  enum MHD_ValueKind kind,
181  const char *key, const char *value)
182 {
183  struct MHD_HTTP_Header *pos;
184 
185  pos = MHD_pool_allocate (connection->pool,
186  sizeof (struct MHD_HTTP_Header), MHD_YES);
187  if (NULL == pos)
188  return MHD_NO;
189  pos->header = (char *) key;
190  pos->value = (char *) value;
191  pos->kind = kind;
192  pos->next = NULL;
193  /* append 'pos' to the linked list of headers */
194  if (NULL == connection->headers_received_tail)
195  {
196  connection->headers_received = pos;
197  connection->headers_received_tail = pos;
198  }
199  else
200  {
201  connection->headers_received_tail->next = pos;
202  connection->headers_received_tail = pos;
203  }
204  return MHD_YES;
205 }
206 
207 
218 const char *
220  enum MHD_ValueKind kind, const char *key)
221 {
222  struct MHD_HTTP_Header *pos;
223 
224  if (NULL == connection)
225  return NULL;
226  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
227  if ((0 != (pos->kind & kind)) &&
228  ( (key == pos->header) ||
229  ( (NULL != pos->header) &&
230  (NULL != key) &&
231  (MHD_str_equal_caseless_(key, pos->header)))))
232  return pos->value;
233  return NULL;
234 }
235 
236 
244 static int
245 need_100_continue (struct MHD_Connection *connection)
246 {
247  const char *expect;
248 
249  return ( (NULL == connection->response) &&
250  (NULL != connection->version) &&
251  (MHD_str_equal_caseless_(connection->version,
253  (NULL != (expect = MHD_lookup_connection_value (connection,
256  (MHD_str_equal_caseless_(expect, "100-continue")) &&
257  (connection->continue_message_write_offset <
258  strlen (HTTP_100_CONTINUE)) );
259 }
260 
261 
269 void
271  enum MHD_RequestTerminationCode termination_code)
272 {
273  struct MHD_Daemon *daemon;
274 
275  daemon = connection->daemon;
276  if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
277  shutdown (connection->socket_fd,
278  (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR);
279  connection->state = MHD_CONNECTION_CLOSED;
281  if ( (NULL != daemon->notify_completed) &&
282  (MHD_YES == connection->client_aware) )
283  daemon->notify_completed (daemon->notify_completed_cls,
284  connection,
285  &connection->client_context,
286  termination_code);
287  connection->client_aware = MHD_NO;
288 }
289 
290 
298 static void
300  const char *emsg)
301 {
302 #if HAVE_MESSAGES
303  if (NULL != emsg)
304  MHD_DLOG (connection->daemon, emsg);
305 #endif
306  MHD_connection_close_ (connection,
308 }
309 
310 
315 #if HAVE_MESSAGES
316 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
317 #else
318 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
319 #endif
320 
321 
334 static int
336 {
337  ssize_t ret;
338  struct MHD_Response *response;
339 
340  response = connection->response;
341  if (NULL == response->crc)
342  return MHD_YES;
343  if ( (0 == response->total_size) ||
344  (connection->response_write_position == response->total_size) )
345  return MHD_YES; /* 0-byte response is always ready */
346  if ( (response->data_start <=
347  connection->response_write_position) &&
348  (response->data_size + response->data_start >
349  connection->response_write_position) )
350  return MHD_YES; /* response already ready */
351 #if LINUX
352  if ( (MHD_INVALID_SOCKET != response->fd) &&
353  (0 == (connection->daemon->options & MHD_USE_SSL)) )
354  {
355  /* will use sendfile, no need to bother response crc */
356  return MHD_YES;
357  }
358 #endif
359 
360  ret = response->crc (response->crc_cls,
361  connection->response_write_position,
362  response->data,
363  (size_t)MHD_MIN ((uint64_t)response->data_buffer_size,
364  response->total_size -
365  connection->response_write_position));
366  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
367  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
368  {
369  /* either error or http 1.0 transfer, close socket! */
370  response->total_size = connection->response_write_position;
371  if (NULL != response->crc)
372  (void) MHD_mutex_unlock_ (&response->mutex);
373  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
374  MHD_connection_close_ (connection,
376  else
377  CONNECTION_CLOSE_ERROR (connection,
378  "Closing connection (stream error)\n");
379  return MHD_NO;
380  }
381  response->data_start = connection->response_write_position;
382  response->data_size = ret;
383  if (0 == ret)
384  {
386  if (NULL != response->crc)
387  (void) MHD_mutex_unlock_ (&response->mutex);
388  return MHD_NO;
389  }
390  return MHD_YES;
391 }
392 
393 
403 static int
405 {
406  ssize_t ret;
407  char *buf;
408  struct MHD_Response *response;
409  size_t size;
410  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
411  int cblen;
412 
413  response = connection->response;
414  if (0 == connection->write_buffer_size)
415  {
416  size = MHD_MIN(connection->daemon->pool_size, 2 * (0xFFFFFF + sizeof(cbuf) + 2));
417  do
418  {
419  size /= 2;
420  if (size < 128)
421  {
422  /* not enough memory */
423  CONNECTION_CLOSE_ERROR (connection,
424  "Closing connection (out of memory)\n");
425  return MHD_NO;
426  }
427  buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
428  }
429  while (NULL == buf);
430  connection->write_buffer_size = size;
431  connection->write_buffer = buf;
432  }
433 
434  if (0 == response->total_size)
435  ret = 0; /* response must be empty, don't bother calling crc */
436  else if ( (response->data_start <=
437  connection->response_write_position) &&
438  (response->data_start + response->data_size >
439  connection->response_write_position) )
440  {
441  /* difference between response_write_position and data_start is less
442  than data_size which is size_t type, no need to check for overflow */
443  const size_t data_write_offset = (size_t)(connection->response_write_position - response->data_start);
444  /* buffer already ready, use what is there for the chunk */
445  ret = response->data_size - data_write_offset;
446  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
447  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
448  memcpy (&connection->write_buffer[sizeof (cbuf)],
449  &response->data[data_write_offset], ret);
450  }
451  else
452  {
453  /* buffer not in range, try to fill it */
454  ret = response->crc (response->crc_cls,
455  connection->response_write_position,
456  &connection->write_buffer[sizeof (cbuf)],
457  connection->write_buffer_size - sizeof (cbuf) - 2);
458  }
459  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
460  {
461  /* error, close socket! */
462  response->total_size = connection->response_write_position;
463  CONNECTION_CLOSE_ERROR (connection,
464  "Closing connection (error generating response)\n");
465  return MHD_NO;
466  }
467  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
468  (0 == response->total_size) )
469  {
470  /* end of message, signal other side! */
471  strcpy (connection->write_buffer, "0\r\n");
472  connection->write_buffer_append_offset = 3;
473  connection->write_buffer_send_offset = 0;
474  response->total_size = connection->response_write_position;
475  return MHD_YES;
476  }
477  if (0 == ret)
478  {
480  return MHD_NO;
481  }
482  if (ret > 0xFFFFFF)
483  ret = 0xFFFFFF;
484  cblen = MHD_snprintf_(cbuf,
485  sizeof (cbuf),
486  "%X\r\n", (unsigned int) ret);
487  EXTRA_CHECK(cblen > 0);
488  EXTRA_CHECK(cblen < sizeof(cbuf));
489  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
490  memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
491  connection->response_write_position += ret;
492  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
493  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
494  return MHD_YES;
495 }
496 
497 
514 static int
515 keepalive_possible (struct MHD_Connection *connection)
516 {
517  const char *end;
518 
519  if (NULL == connection->version)
520  return MHD_NO;
521  if ( (NULL != connection->response) &&
522  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
523  return MHD_NO;
524  end = MHD_lookup_connection_value (connection,
527  if (MHD_str_equal_caseless_(connection->version,
529  {
530  if (NULL == end)
531  return MHD_YES;
532  if ( (MHD_str_equal_caseless_ (end, "close")) ||
533  (MHD_str_equal_caseless_ (end, "upgrade")) )
534  return MHD_NO;
535  return MHD_YES;
536  }
537  if (MHD_str_equal_caseless_(connection->version,
539  {
540  if (NULL == end)
541  return MHD_NO;
542  if (MHD_str_equal_caseless_(end, "Keep-Alive"))
543  return MHD_YES;
544  return MHD_NO;
545  }
546  return MHD_NO;
547 }
548 
549 
556 static void
557 get_date_string (char *date)
558 {
559  static const char *const days[] =
560  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
561  static const char *const mons[] =
562  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
563  "Nov", "Dec"
564  };
565  struct tm now;
566  time_t t;
567 #if defined(_WIN32) && !defined(HAVE_GMTIME_S) && !defined(__CYGWIN__)
568  struct tm* pNow;
569 #endif
570 
571  date[0] = 0;
572  time (&t);
573 #if !defined(_WIN32)
574  if (NULL != gmtime_r (&t, &now))
575  {
576 #elif defined(HAVE_GMTIME_S)
577  if (0 == gmtime_s (&now, &t))
578  {
579 #elif defined(__CYGWIN__)
580  if (NULL != gmtime_r (&t, &now))
581  {
582 #else
583  pNow = gmtime(&t);
584  if (NULL != pNow)
585  {
586  now = *pNow;
587 #endif
588  sprintf (date,
589  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
590  days[now.tm_wday % 7],
591  (unsigned int) now.tm_mday,
592  mons[now.tm_mon % 12],
593  (unsigned int) (1900 + now.tm_year),
594  (unsigned int) now.tm_hour,
595  (unsigned int) now.tm_min,
596  (unsigned int) now.tm_sec);
597  }
598 }
599 
600 
612 static int
614 {
615  void *buf;
616  size_t new_size;
617 
618  if (0 == connection->read_buffer_size)
619  new_size = connection->daemon->pool_size / 2;
620  else
621  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
622  buf = MHD_pool_reallocate (connection->pool,
623  connection->read_buffer,
624  connection->read_buffer_size,
625  new_size);
626  if (NULL == buf)
627  return MHD_NO;
628  /* we can actually grow the buffer, do it! */
629  connection->read_buffer = buf;
630  connection->read_buffer_size = new_size;
631  return MHD_YES;
632 }
633 
634 
644 static int
646 {
647  size_t size;
648  size_t off;
649  struct MHD_HTTP_Header *pos;
650  char code[256];
651  char date[128];
652  char content_length_buf[128];
653  size_t content_length_len;
654  char *data;
655  enum MHD_ValueKind kind;
656  const char *reason_phrase;
657  uint32_t rc;
658  const char *client_requested_close;
659  const char *response_has_close;
660  const char *response_has_keepalive;
661  const char *have_encoding;
662  const char *have_content_length;
663  int must_add_close;
664  int must_add_chunked_encoding;
665  int must_add_keep_alive;
666  int must_add_content_length;
667 
668  EXTRA_CHECK (NULL != connection->version);
669  if (0 == connection->version[0])
670  {
671  data = MHD_pool_allocate (connection->pool, 0, MHD_YES);
672  connection->write_buffer = data;
673  connection->write_buffer_append_offset = 0;
674  connection->write_buffer_send_offset = 0;
675  connection->write_buffer_size = 0;
676  return MHD_YES;
677  }
678  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
679  {
680  rc = connection->responseCode & (~MHD_ICY_FLAG);
681  reason_phrase = MHD_get_reason_phrase_for (rc);
682  sprintf (code,
683  "%s %u %s\r\n",
684  (0 != (connection->responseCode & MHD_ICY_FLAG))
685  ? "ICY"
687  connection->version))
690  rc,
691  reason_phrase);
692  off = strlen (code);
693  /* estimate size */
694  size = off + 2; /* +2 for extra "\r\n" at the end */
695  kind = MHD_HEADER_KIND;
696  if ( (0 == (connection->daemon->options & MHD_SUPPRESS_DATE_NO_CLOCK)) &&
697  (NULL == MHD_get_response_header (connection->response,
699  get_date_string (date);
700  else
701  date[0] = '\0';
702  size += strlen (date);
703  }
704  else
705  {
706  /* 2 bytes for final CRLF of a Chunked-Body */
707  size = 2;
708  kind = MHD_FOOTER_KIND;
709  off = 0;
710  }
711 
712  /* calculate extra headers we need to add, such as 'Connection: close',
713  first see what was explicitly requested by the application */
714  must_add_close = MHD_NO;
715  must_add_chunked_encoding = MHD_NO;
716  must_add_keep_alive = MHD_NO;
717  must_add_content_length = MHD_NO;
718  switch (connection->state)
719  {
721  response_has_close = MHD_get_response_header (connection->response,
723  response_has_keepalive = response_has_close;
724  if ( (NULL != response_has_close) &&
725  (!MHD_str_equal_caseless_ (response_has_close, "close")) )
726  response_has_close = NULL;
727  if ( (NULL != response_has_keepalive) &&
728  (!MHD_str_equal_caseless_ (response_has_keepalive, "Keep-Alive")) )
729  response_has_keepalive = NULL;
730  client_requested_close = MHD_lookup_connection_value (connection,
733  if ( (NULL != client_requested_close) &&
734  (!MHD_str_equal_caseless_ (client_requested_close, "close")) )
735  client_requested_close = NULL;
736 
737  /* now analyze chunked encoding situation */
738  connection->have_chunked_upload = MHD_NO;
739 
740  if ( (MHD_SIZE_UNKNOWN == connection->response->total_size) &&
741  (NULL == response_has_close) &&
742  (NULL == client_requested_close) )
743  {
744  /* size is unknown, and close was not explicitly requested;
745  need to either to HTTP 1.1 chunked encoding or
746  close the connection */
747  /* 'close' header doesn't exist yet, see if we need to add one;
748  if the client asked for a close, no need to start chunk'ing */
749  if ( (MHD_YES == keepalive_possible (connection)) &&
751  connection->version) ) )
752  {
753  have_encoding = MHD_get_response_header (connection->response,
755  if (NULL == have_encoding)
756  {
757  must_add_chunked_encoding = MHD_YES;
758  connection->have_chunked_upload = MHD_YES;
759  }
760  else if (MHD_str_equal_caseless_(have_encoding, "identity"))
761  {
762  /* application forced identity encoding, can't do 'chunked' */
763  must_add_close = MHD_YES;
764  }
765  else
766  {
767  connection->have_chunked_upload = MHD_YES;
768  }
769  }
770  else
771  {
772  /* Keep alive or chunking not possible
773  => set close header if not present */
774  if (NULL == response_has_close)
775  must_add_close = MHD_YES;
776  }
777  }
778 
779  /* check for other reasons to add 'close' header */
780  if ( ( (NULL != client_requested_close) ||
781  (MHD_YES == connection->read_closed) ) &&
782  (NULL == response_has_close) &&
783  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
784  must_add_close = MHD_YES;
785 
786  /* check if we should add a 'content length' header */
787  have_content_length = MHD_get_response_header (connection->response,
789 
790  if ( (MHD_SIZE_UNKNOWN != connection->response->total_size) &&
791  (NULL == have_content_length) &&
792  ( (NULL == connection->method) ||
793  (! MHD_str_equal_caseless_ (connection->method,
795  {
796  /*
797  Here we add a content-length if one is missing; however,
798  for 'connect' methods, the responses MUST NOT include a
799  content-length header *if* the response code is 2xx (in
800  which case we expect there to be no body). Still,
801  as we don't know the response code here in some cases, we
802  simply only force adding a content-length header if this
803  is not a 'connect' or if the response is not empty
804  (which is kind of more sane, because if some crazy
805  application did return content with a 2xx status code,
806  then having a content-length might again be a good idea).
807 
808  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
809  a recent development of the HTTP 1.1 specification.
810  */
811  content_length_len
812  = sprintf (content_length_buf,
815  must_add_content_length = MHD_YES;
816  }
817 
818  /* check for adding keep alive */
819  if ( (NULL == response_has_keepalive) &&
820  (NULL == response_has_close) &&
821  (MHD_NO == must_add_close) &&
822  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) &&
823  (MHD_YES == keepalive_possible (connection)) )
824  must_add_keep_alive = MHD_YES;
825  break;
827  break;
828  default:
829  EXTRA_CHECK (0);
830  }
831 
832  if (must_add_close)
833  size += strlen ("Connection: close\r\n");
834  if (must_add_keep_alive)
835  size += strlen ("Connection: Keep-Alive\r\n");
836  if (must_add_chunked_encoding)
837  size += strlen ("Transfer-Encoding: chunked\r\n");
838  if (must_add_content_length)
839  size += content_length_len;
840  EXTRA_CHECK (! (must_add_close && must_add_keep_alive) );
841  EXTRA_CHECK (! (must_add_chunked_encoding && must_add_content_length) );
842 
843  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
844  if ( (pos->kind == kind) &&
845  (! ( (MHD_YES == must_add_close) &&
846  (pos->value == response_has_keepalive) &&
849  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
850  /* produce data */
851  data = MHD_pool_allocate (connection->pool, size + 1, MHD_NO);
852  if (NULL == data)
853  {
854 #if HAVE_MESSAGES
855  MHD_DLOG (connection->daemon,
856  "Not enough memory for write!\n");
857 #endif
858  return MHD_NO;
859  }
860  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
861  {
862  memcpy (data, code, off);
863  }
864  if (must_add_close)
865  {
866  /* we must add the 'Connection: close' header */
867  memcpy (&data[off],
868  "Connection: close\r\n",
869  strlen ("Connection: close\r\n"));
870  off += strlen ("Connection: close\r\n");
871  }
872  if (must_add_keep_alive)
873  {
874  /* we must add the 'Connection: Keep-Alive' header */
875  memcpy (&data[off],
876  "Connection: Keep-Alive\r\n",
877  strlen ("Connection: Keep-Alive\r\n"));
878  off += strlen ("Connection: Keep-Alive\r\n");
879  }
880  if (must_add_chunked_encoding)
881  {
882  /* we must add the 'Transfer-Encoding: chunked' header */
883  memcpy (&data[off],
884  "Transfer-Encoding: chunked\r\n",
885  strlen ("Transfer-Encoding: chunked\r\n"));
886  off += strlen ("Transfer-Encoding: chunked\r\n");
887  }
888  if (must_add_content_length)
889  {
890  /* we must add the 'Content-Length' header */
891  memcpy (&data[off],
892  content_length_buf,
893  content_length_len);
894  off += content_length_len;
895  }
896  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
897  if ( (pos->kind == kind) &&
898  (! ( (pos->value == response_has_keepalive) &&
899  (MHD_YES == must_add_close) &&
902  off += sprintf (&data[off],
903  "%s: %s\r\n",
904  pos->header,
905  pos->value);
906  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
907  {
908  strcpy (&data[off], date);
909  off += strlen (date);
910  }
911  memcpy (&data[off], "\r\n", 2);
912  off += 2;
913 
914  if (off != size)
915  mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
916  connection->write_buffer = data;
917  connection->write_buffer_append_offset = size;
918  connection->write_buffer_send_offset = 0;
919  connection->write_buffer_size = size + 1;
920  return MHD_YES;
921 }
922 
923 
933 static void
935  unsigned int status_code,
936  const char *message)
937 {
938  struct MHD_Response *response;
939 
940  if (NULL == connection->version)
941  {
942  /* we were unable to process the full header line, so we don't
943  really know what version the client speaks; assume 1.0 */
944  connection->version = MHD_HTTP_VERSION_1_0;
945  }
947  connection->read_closed = MHD_YES;
948 #if HAVE_MESSAGES
949  MHD_DLOG (connection->daemon,
950  "Error %u (`%s') processing request, closing connection.\n",
951  status_code, message);
952 #endif
953  EXTRA_CHECK (NULL == connection->response);
954  response = MHD_create_response_from_buffer (strlen (message),
955  (void *) message,
957  MHD_queue_response (connection, status_code, response);
958  EXTRA_CHECK (NULL != connection->response);
959  MHD_destroy_response (response);
960  if (MHD_NO == build_header_response (connection))
961  {
962  /* oops - close! */
963  CONNECTION_CLOSE_ERROR (connection,
964  "Closing connection (failed to create response header)\n");
965  }
966  else
967  {
969  }
970 }
971 
972 
981 static void
983 {
984  while (1)
985  {
986 #if DEBUG_STATES
987  MHD_DLOG (connection->daemon,
988  "%s: state: %s\n",
989  __FUNCTION__,
990  MHD_state_to_string (connection->state));
991 #endif
992  switch (connection->state)
993  {
994 #if HTTPS_SUPPORT
996  if (0 == gnutls_record_get_direction (connection->tls_session))
998  else
1000  break;
1001 #endif
1002  case MHD_CONNECTION_INIT:
1005  /* while reading headers, we always grow the
1006  read buffer if needed, no size-check required */
1007  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1008  (MHD_NO == try_grow_read_buffer (connection)) )
1009  {
1010  transmit_error_response (connection,
1011  (connection->url != NULL)
1014  REQUEST_TOO_BIG);
1015  continue;
1016  }
1017  if (MHD_NO == connection->read_closed)
1019  else
1021  break;
1023  EXTRA_CHECK (0);
1024  break;
1026  EXTRA_CHECK (0);
1027  break;
1030  break;
1032  if (connection->read_buffer_offset == connection->read_buffer_size)
1033  {
1034  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1035  (0 != (connection->daemon->options &
1038  {
1039  /* failed to grow the read buffer, and the
1040  client which is supposed to handle the
1041  received data in a *blocking* fashion
1042  (in this mode) did not handle the data as
1043  it was supposed to!
1044  => we would either have to do busy-waiting
1045  (on the client, which would likely fail),
1046  or if we do nothing, we would just timeout
1047  on the connection (if a timeout is even
1048  set!).
1049  Solution: we kill the connection with an error */
1050  transmit_error_response (connection,
1052  INTERNAL_ERROR);
1053  continue;
1054  }
1055  }
1056  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1057  (MHD_NO == connection->read_closed) )
1059  else
1061  break;
1064  /* while reading footers, we always grow the
1065  read buffer if needed, no size-check required */
1066  if (MHD_YES == connection->read_closed)
1067  {
1068  CONNECTION_CLOSE_ERROR (connection,
1069  NULL);
1070  continue;
1071  }
1073  /* transition to FOOTERS_RECEIVED
1074  happens in read handler */
1075  break;
1078  break;
1080  /* headers in buffer, keep writing */
1082  break;
1084  EXTRA_CHECK (0);
1085  break;
1088  break;
1091  break;
1094  break;
1097  break;
1099  EXTRA_CHECK (0);
1100  break;
1103  break;
1105  EXTRA_CHECK (0);
1106  break;
1107  case MHD_CONNECTION_CLOSED:
1109  return; /* do nothing, not even reading */
1110  default:
1111  EXTRA_CHECK (0);
1112  }
1113  break;
1114  }
1115 }
1116 
1117 
1129 static char *
1131 {
1132  char *rbuf;
1133  size_t pos;
1134 
1135  if (0 == connection->read_buffer_offset)
1136  return NULL;
1137  pos = 0;
1138  rbuf = connection->read_buffer;
1139  while ((pos < connection->read_buffer_offset - 1) &&
1140  ('\r' != rbuf[pos]) && ('\n' != rbuf[pos]))
1141  pos++;
1142  if ( (pos == connection->read_buffer_offset - 1) &&
1143  ('\n' != rbuf[pos]) )
1144  {
1145  /* not found, consider growing... */
1146  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1147  (MHD_NO ==
1148  try_grow_read_buffer (connection)) )
1149  {
1150  transmit_error_response (connection,
1151  (NULL != connection->url)
1154  REQUEST_TOO_BIG);
1155  }
1156  return NULL;
1157  }
1158  /* found, check if we have proper LFCR */
1159  if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1]))
1160  rbuf[pos++] = '\0'; /* skip both r and n */
1161  rbuf[pos++] = '\0';
1162  connection->read_buffer += pos;
1163  connection->read_buffer_size -= pos;
1164  connection->read_buffer_offset -= pos;
1165  return rbuf;
1166 }
1167 
1168 
1180 static int
1182  const char *key,
1183  const char *value,
1184  enum MHD_ValueKind kind)
1185 {
1186  if (MHD_NO ==
1187  MHD_set_connection_value (connection,
1188  kind,
1189  key,
1190  value))
1191  {
1192 #if HAVE_MESSAGES
1193  MHD_DLOG (connection->daemon,
1194  "Not enough memory to allocate header record!\n");
1195 #endif
1196  transmit_error_response (connection,
1198  REQUEST_TOO_BIG);
1199  return MHD_NO;
1200  }
1201  return MHD_YES;
1202 }
1203 
1204 
1211 static int
1213 {
1214  const char *hdr;
1215  char *cpy;
1216  char *pos;
1217  char *sce;
1218  char *semicolon;
1219  char *equals;
1220  char *ekill;
1221  char old;
1222  int quotes;
1223 
1224  hdr = MHD_lookup_connection_value (connection,
1227  if (NULL == hdr)
1228  return MHD_YES;
1229  cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
1230  if (NULL == cpy)
1231  {
1232 #if HAVE_MESSAGES
1233  MHD_DLOG (connection->daemon,
1234  "Not enough memory to parse cookies!\n");
1235 #endif
1237  REQUEST_TOO_BIG);
1238  return MHD_NO;
1239  }
1240  memcpy (cpy, hdr, strlen (hdr) + 1);
1241  pos = cpy;
1242  while (NULL != pos)
1243  {
1244  while (' ' == *pos)
1245  pos++; /* skip spaces */
1246 
1247  sce = pos;
1248  while (((*sce) != '\0') &&
1249  ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
1250  sce++;
1251  /* remove tailing whitespace (if any) from key */
1252  ekill = sce - 1;
1253  while ((*ekill == ' ') && (ekill >= pos))
1254  *(ekill--) = '\0';
1255  old = *sce;
1256  *sce = '\0';
1257  if (old != '=')
1258  {
1259  /* value part omitted, use empty string... */
1260  if (MHD_NO ==
1261  connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
1262  return MHD_NO;
1263  if (old == '\0')
1264  break;
1265  pos = sce + 1;
1266  continue;
1267  }
1268  equals = sce + 1;
1269  quotes = 0;
1270  semicolon = equals;
1271  while ( ('\0' != semicolon[0]) &&
1272  ( (0 != quotes) ||
1273  ( (';' != semicolon[0]) &&
1274  (',' != semicolon[0]) ) ) )
1275  {
1276  if ('"' == semicolon[0])
1277  quotes = (quotes + 1) & 1;
1278  semicolon++;
1279  }
1280  if ('\0' == semicolon[0])
1281  semicolon = NULL;
1282  if (NULL != semicolon)
1283  {
1284  semicolon[0] = '\0';
1285  semicolon++;
1286  }
1287  /* remove quotes */
1288  if ( ('"' == equals[0]) &&
1289  ('"' == equals[strlen (equals) - 1]) )
1290  {
1291  equals[strlen (equals) - 1] = '\0';
1292  equals++;
1293  }
1294  if (MHD_NO ==
1295  connection_add_header (connection,
1296  pos,
1297  equals,
1298  MHD_COOKIE_KIND))
1299  return MHD_NO;
1300  pos = semicolon;
1301  }
1302  return MHD_YES;
1303 }
1304 
1305 
1313 static int
1315  char *line)
1316 {
1317  struct MHD_Daemon *daemon = connection->daemon;
1318  char *uri;
1319  char *http_version;
1320  char *args;
1321  unsigned int unused_num_headers;
1322 
1323  if (NULL == (uri = strchr (line, ' ')))
1324  return MHD_NO; /* serious error */
1325  uri[0] = '\0';
1326  connection->method = line;
1327  uri++;
1328  while (' ' == uri[0])
1329  uri++;
1330  http_version = strchr (uri, ' ');
1331  if (NULL != http_version)
1332  {
1333  http_version[0] = '\0';
1334  http_version++;
1335  }
1336  if (NULL != daemon->uri_log_callback)
1337  connection->client_context
1338  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
1339  uri,
1340  connection);
1341  args = strchr (uri, '?');
1342  if (NULL != args)
1343  {
1344  args[0] = '\0';
1345  args++;
1346  /* note that this call clobbers 'args' */
1347  MHD_parse_arguments_ (connection,
1349  args,
1351  &unused_num_headers);
1352  }
1353  daemon->unescape_callback (daemon->unescape_callback_cls,
1354  connection,
1355  uri);
1356  connection->url = uri;
1357  if (NULL == http_version)
1358  connection->version = "";
1359  else
1360  connection->version = http_version;
1361  return MHD_YES;
1362 }
1363 
1364 
1372 static void
1374 {
1375  size_t processed;
1376 
1377  if (NULL != connection->response)
1378  return; /* already queued a response */
1379  processed = 0;
1380  connection->client_aware = MHD_YES;
1381  if (MHD_NO ==
1382  connection->daemon->default_handler (connection->daemon-> default_handler_cls,
1383  connection,
1384  connection->url,
1385  connection->method,
1386  connection->version,
1387  NULL, &processed,
1388  &connection->client_context))
1389  {
1390  /* serious internal error, close connection */
1391  CONNECTION_CLOSE_ERROR (connection,
1392  "Internal application error, closing connection.\n");
1393  return;
1394  }
1395 }
1396 
1397 
1398 
1406 static void
1408 {
1409  size_t processed;
1410  size_t available;
1411  size_t used;
1412  size_t i;
1413  int instant_retry;
1414  int malformed;
1415  char *buffer_head;
1416  char *end;
1417 
1418  if (NULL != connection->response)
1419  return; /* already queued a response */
1420 
1421  buffer_head = connection->read_buffer;
1422  available = connection->read_buffer_offset;
1423  do
1424  {
1425  instant_retry = MHD_NO;
1426  if ( (MHD_YES == connection->have_chunked_upload) &&
1427  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
1428  {
1429  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
1430  (0 != connection->current_chunk_offset) &&
1431  (available >= 2) )
1432  {
1433  /* skip new line at the *end* of a chunk */
1434  i = 0;
1435  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1436  i++; /* skip 1st part of line feed */
1437  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1438  i++; /* skip 2nd part of line feed */
1439  if (i == 0)
1440  {
1441  /* malformed encoding */
1442  CONNECTION_CLOSE_ERROR (connection,
1443  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1444  return;
1445  }
1446  available -= i;
1447  buffer_head += i;
1448  connection->current_chunk_offset = 0;
1449  connection->current_chunk_size = 0;
1450  }
1451  if (connection->current_chunk_offset <
1452  connection->current_chunk_size)
1453  {
1454  /* we are in the middle of a chunk, give
1455  as much as possible to the client (without
1456  crossing chunk boundaries) */
1457  processed =
1458  connection->current_chunk_size -
1459  connection->current_chunk_offset;
1460  if (processed > available)
1461  processed = available;
1462  if (available > processed)
1463  instant_retry = MHD_YES;
1464  }
1465  else
1466  {
1467  /* we need to read chunk boundaries */
1468  i = 0;
1469  while (i < available)
1470  {
1471  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1472  break;
1473  i++;
1474  if (i >= 6)
1475  break;
1476  }
1477  /* take '\n' into account; if '\n'
1478  is the unavailable character, we
1479  will need to wait until we have it
1480  before going further */
1481  if ((i + 1 >= available) &&
1482  !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
1483  break; /* need more data... */
1484  malformed = (i >= 6);
1485  if (!malformed)
1486  {
1487  buffer_head[i] = '\0';
1488  connection->current_chunk_size = strtoul (buffer_head, &end, 16);
1489  malformed = ('\0' != *end);
1490  }
1491  if (malformed)
1492  {
1493  /* malformed encoding */
1494  CONNECTION_CLOSE_ERROR (connection,
1495  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1496  return;
1497  }
1498  i++;
1499  if ((i < available) &&
1500  ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
1501  i++; /* skip 2nd part of line feed */
1502 
1503  buffer_head += i;
1504  available -= i;
1505  connection->current_chunk_offset = 0;
1506 
1507  if (available > 0)
1508  instant_retry = MHD_YES;
1509  if (0 == connection->current_chunk_size)
1510  {
1511  connection->remaining_upload_size = 0;
1512  break;
1513  }
1514  continue;
1515  }
1516  }
1517  else
1518  {
1519  /* no chunked encoding, give all to the client */
1520  if ( (0 != connection->remaining_upload_size) &&
1521  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
1522  (connection->remaining_upload_size < available) )
1523  {
1524  processed = (size_t)connection->remaining_upload_size;
1525  }
1526  else
1527  {
1532  processed = available;
1533  }
1534  }
1535  used = processed;
1536  connection->client_aware = MHD_YES;
1537  if (MHD_NO ==
1538  connection->daemon->default_handler (connection->daemon->default_handler_cls,
1539  connection,
1540  connection->url,
1541  connection->method,
1542  connection->version,
1543  buffer_head,
1544  &processed,
1545  &connection->client_context))
1546  {
1547  /* serious internal error, close connection */
1548  CONNECTION_CLOSE_ERROR (connection,
1549  "Internal application error, closing connection.\n");
1550  return;
1551  }
1552  if (processed > used)
1553  mhd_panic (mhd_panic_cls, __FILE__, __LINE__
1554 #if HAVE_MESSAGES
1555  , "API violation"
1556 #else
1557  , NULL
1558 #endif
1559  );
1560  if (0 != processed)
1561  instant_retry = MHD_NO; /* client did not process everything */
1562  used -= processed;
1563  if (connection->have_chunked_upload == MHD_YES)
1564  connection->current_chunk_offset += used;
1565  /* dh left "processed" bytes in buffer for next time... */
1566  buffer_head += used;
1567  available -= used;
1568  if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
1569  connection->remaining_upload_size -= used;
1570  }
1571  while (MHD_YES == instant_retry);
1572  if (available > 0)
1573  memmove (connection->read_buffer, buffer_head, available);
1574  connection->read_buffer_offset = available;
1575 }
1576 
1577 
1587 static int
1588 do_read (struct MHD_Connection *connection)
1589 {
1590  ssize_t bytes_read;
1591 
1592  if (connection->read_buffer_size == connection->read_buffer_offset)
1593  return MHD_NO;
1594  bytes_read = connection->recv_cls (connection,
1595  &connection->read_buffer
1596  [connection->read_buffer_offset],
1597  connection->read_buffer_size -
1598  connection->read_buffer_offset);
1599  if (bytes_read < 0)
1600  {
1601  const int err = MHD_socket_errno_;
1602  if ((EINTR == err) || (EAGAIN == err) || (EWOULDBLOCK == err))
1603  return MHD_NO;
1604  if (ECONNRESET == err)
1605  {
1606  CONNECTION_CLOSE_ERROR (connection, NULL);
1607  return MHD_NO;
1608  }
1609  CONNECTION_CLOSE_ERROR (connection, NULL);
1610  return MHD_YES;
1611  }
1612  if (0 == bytes_read)
1613  {
1614  /* other side closed connection; RFC 2616, section 8.1.4 suggests
1615  we should then shutdown ourselves as well. */
1616  connection->read_closed = MHD_YES;
1617  MHD_connection_close_ (connection,
1619  return MHD_YES;
1620  }
1621  connection->read_buffer_offset += bytes_read;
1622  return MHD_YES;
1623 }
1624 
1625 
1634 static int
1635 do_write (struct MHD_Connection *connection)
1636 {
1637  ssize_t ret;
1638  size_t max;
1639 
1640  max = connection->write_buffer_append_offset - connection->write_buffer_send_offset;
1641  ret = connection->send_cls (connection,
1642  &connection->write_buffer
1643  [connection->write_buffer_send_offset],
1644  max);
1645 
1646  if (ret < 0)
1647  {
1648  const int err = MHD_socket_errno_;
1649  if ((EINTR == err) || (EAGAIN == err) || (EWOULDBLOCK == err))
1650  return MHD_NO;
1651  CONNECTION_CLOSE_ERROR (connection, NULL);
1652  return MHD_YES;
1653  }
1654 #if DEBUG_SEND_DATA
1655  fprintf (stderr,
1656  "Sent response: `%.*s'\n",
1657  ret,
1658  &connection->write_buffer[connection->write_buffer_send_offset]);
1659 #endif
1660  /* only increment if this wasn't a "sendfile" transmission without
1661  buffer involvement! */
1662  if (0 != max)
1663  connection->write_buffer_send_offset += ret;
1664  return MHD_YES;
1665 }
1666 
1667 
1676 static int
1677 check_write_done (struct MHD_Connection *connection,
1678  enum MHD_CONNECTION_STATE next_state)
1679 {
1680  if (connection->write_buffer_append_offset !=
1681  connection->write_buffer_send_offset)
1682  return MHD_NO;
1683  connection->write_buffer_append_offset = 0;
1684  connection->write_buffer_send_offset = 0;
1685  connection->state = next_state;
1686  MHD_pool_reallocate (connection->pool,
1687  connection->write_buffer,
1688  connection->write_buffer_size, 0);
1689  connection->write_buffer = NULL;
1690  connection->write_buffer_size = 0;
1691  return MHD_YES;
1692 }
1693 
1694 
1704 static int
1705 process_header_line (struct MHD_Connection *connection, char *line)
1706 {
1707  char *colon;
1708 
1709  /* line should be normal header line, find colon */
1710  colon = strchr (line, ':');
1711  if (NULL == colon)
1712  {
1713  /* error in header line, die hard */
1714  CONNECTION_CLOSE_ERROR (connection,
1715  "Received malformed line (no colon), closing connection.\n");
1716  return MHD_NO;
1717  }
1718  /* zero-terminate header */
1719  colon[0] = '\0';
1720  colon++; /* advance to value */
1721  while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
1722  colon++;
1723  /* we do the actual adding of the connection
1724  header at the beginning of the while
1725  loop since we need to be able to inspect
1726  the *next* header line (in case it starts
1727  with a space...) */
1728  connection->last = line;
1729  connection->colon = colon;
1730  return MHD_YES;
1731 }
1732 
1733 
1744 static int
1746  char *line, enum MHD_ValueKind kind)
1747 {
1748  char *last;
1749  char *tmp;
1750  size_t last_len;
1751  size_t tmp_len;
1752 
1753  last = connection->last;
1754  if ((line[0] == ' ') || (line[0] == '\t'))
1755  {
1756  /* value was continued on the next line, see
1757  http://www.jmarshall.com/easy/http/ */
1758  last_len = strlen (last);
1759  /* skip whitespace at start of 2nd line */
1760  tmp = line;
1761  while ((tmp[0] == ' ') || (tmp[0] == '\t'))
1762  tmp++;
1763  tmp_len = strlen (tmp);
1764  /* FIXME: we might be able to do this better (faster!), as most
1765  likely 'last' and 'line' should already be adjacent in
1766  memory; however, doing this right gets tricky if we have a
1767  value continued over multiple lines (in which case we need to
1768  record how often we have done this so we can check for
1769  adjaency); also, in the case where these are not adjacent
1770  (not sure how it can happen!), we would want to allocate from
1771  the end of the pool, so as to not destroy the read-buffer's
1772  ability to grow nicely. */
1773  last = MHD_pool_reallocate (connection->pool,
1774  last,
1775  last_len + 1,
1776  last_len + tmp_len + 1);
1777  if (NULL == last)
1778  {
1779  transmit_error_response (connection,
1781  REQUEST_TOO_BIG);
1782  return MHD_NO;
1783  }
1784  memcpy (&last[last_len], tmp, tmp_len + 1);
1785  connection->last = last;
1786  return MHD_YES; /* possibly more than 2 lines... */
1787  }
1788  EXTRA_CHECK ((NULL != last) && (NULL != connection->colon));
1789  if ((MHD_NO == connection_add_header (connection,
1790  last,
1791  connection->colon,
1792  kind)))
1793  {
1795  REQUEST_TOO_BIG);
1796  return MHD_NO;
1797  }
1798  /* we still have the current line to deal with... */
1799  if (0 != line[0])
1800  {
1801  if (MHD_NO == process_header_line (connection, line))
1802  {
1803  transmit_error_response (connection,
1805  return MHD_NO;
1806  }
1807  }
1808  return MHD_YES;
1809 }
1810 
1811 
1819 static void
1821 {
1822  const char *clen;
1824  struct MHD_Response *response;
1825  const char *enc;
1826  char *end;
1827 
1828  parse_cookie_header (connection);
1829  if ( (0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) &&
1830  (NULL != connection->version) &&
1832  (NULL ==
1833  MHD_lookup_connection_value (connection,
1836  {
1837  /* die, http 1.1 request without host and we are pedantic */
1838  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1839  connection->read_closed = MHD_YES;
1840 #if HAVE_MESSAGES
1841  MHD_DLOG (connection->daemon,
1842  "Received `%s' request without `%s' header.\n",
1844 #endif
1845  EXTRA_CHECK (NULL == connection->response);
1846  response =
1850  MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
1851  MHD_destroy_response (response);
1852  return;
1853  }
1854 
1855  connection->remaining_upload_size = 0;
1856  enc = MHD_lookup_connection_value (connection,
1859  if (NULL != enc)
1860  {
1862  if (MHD_str_equal_caseless_(enc, "chunked"))
1863  connection->have_chunked_upload = MHD_YES;
1864  }
1865  else
1866  {
1867  clen = MHD_lookup_connection_value (connection,
1870  if (NULL != clen)
1871  {
1872  cval = strtoul (clen, &end, 10);
1873  if ( ('\0' != *end) ||
1874  ( (LONG_MAX == cval) && (errno == ERANGE) ) )
1875  {
1876 #if HAVE_MESSAGES
1877  MHD_DLOG (connection->daemon,
1878  "Failed to parse `%s' header `%s', closing connection.\n",
1880  clen);
1881 #endif
1882  CONNECTION_CLOSE_ERROR (connection, NULL);
1883  return;
1884  }
1885  connection->remaining_upload_size = cval;
1886  }
1887  }
1888 }
1889 
1890 
1898 static void
1900 {
1901  struct MHD_Daemon *daemon = connection->daemon;
1902 
1903  connection->last_activity = MHD_monotonic_sec_counter();
1904  if (connection->connection_timeout != daemon->connection_timeout)
1905  return; /* custom timeout, no need to move it in "normal" DLL */
1906 
1907  /* move connection to head of timeout list (by remove + add operation) */
1908  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1909  (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) )
1910  MHD_PANIC ("Failed to acquire cleanup mutex\n");
1912  daemon->normal_timeout_tail,
1913  connection);
1915  daemon->normal_timeout_tail,
1916  connection);
1917  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1918  (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) )
1919  MHD_PANIC ("Failed to release cleanup mutex\n");
1920 }
1921 
1922 
1931 int
1933 {
1934  update_last_activity (connection);
1935  if (MHD_CONNECTION_CLOSED == connection->state)
1936  return MHD_YES;
1937  /* make sure "read" has a reasonable number of bytes
1938  in buffer to use per system call (if possible) */
1939  if (connection->read_buffer_offset + connection->daemon->pool_increment >
1940  connection->read_buffer_size)
1941  try_grow_read_buffer (connection);
1942  if (MHD_NO == do_read (connection))
1943  return MHD_YES;
1944  while (1)
1945  {
1946 #if DEBUG_STATES
1947  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1948  __FUNCTION__,
1949  MHD_state_to_string (connection->state));
1950 #endif
1951  switch (connection->state)
1952  {
1953  case MHD_CONNECTION_INIT:
1962  /* nothing to do but default action */
1963  if (MHD_YES == connection->read_closed)
1964  {
1965  MHD_connection_close_ (connection,
1967  continue;
1968  }
1969  break;
1970  case MHD_CONNECTION_CLOSED:
1971  return MHD_YES;
1972  default:
1973  /* shrink read buffer to how much is actually used */
1974  MHD_pool_reallocate (connection->pool,
1975  connection->read_buffer,
1976  connection->read_buffer_size + 1,
1977  connection->read_buffer_offset);
1978  break;
1979  }
1980  break;
1981  }
1982  return MHD_YES;
1983 }
1984 
1985 
1994 int
1996 {
1997  struct MHD_Response *response;
1998  ssize_t ret;
1999 
2000  update_last_activity (connection);
2001  while (1)
2002  {
2003 #if DEBUG_STATES
2004  MHD_DLOG (connection->daemon, "%s: state: %s\n",
2005  __FUNCTION__,
2006  MHD_state_to_string (connection->state));
2007 #endif
2008  switch (connection->state)
2009  {
2010  case MHD_CONNECTION_INIT:
2014  EXTRA_CHECK (0);
2015  break;
2017  break;
2019  ret = connection->send_cls (connection,
2021  [connection->continue_message_write_offset],
2022  strlen (HTTP_100_CONTINUE) -
2023  connection->continue_message_write_offset);
2024  if (ret < 0)
2025  {
2026  const int err = MHD_socket_errno_;
2027  if ((err == EINTR) || (err == EAGAIN) || (EWOULDBLOCK == err))
2028  break;
2029 #if HAVE_MESSAGES
2030  MHD_DLOG (connection->daemon,
2031  "Failed to send data: %s\n",
2033 #endif
2034  CONNECTION_CLOSE_ERROR (connection, NULL);
2035  return MHD_YES;
2036  }
2037 #if DEBUG_SEND_DATA
2038  fprintf (stderr,
2039  "Sent 100 continue response: `%.*s'\n",
2040  (int) ret,
2042 #endif
2043  connection->continue_message_write_offset += ret;
2044  break;
2049  EXTRA_CHECK (0);
2050  break;
2052  do_write (connection);
2053  if (connection->state != MHD_CONNECTION_HEADERS_SENDING)
2054  break;
2056  break;
2058  EXTRA_CHECK (0);
2059  break;
2061  response = connection->response;
2062  if (connection->response_write_position <
2063  connection->response->total_size)
2064  {
2065  int err;
2066  uint64_t data_write_offset;
2067  if (NULL != response->crc)
2068  (void) MHD_mutex_lock_ (&response->mutex);
2069  if (MHD_YES != try_ready_normal_body (connection))
2070  break;
2071  data_write_offset = connection->response_write_position
2072  - response->data_start;
2073  if (data_write_offset > (uint64_t)SIZE_MAX)
2074  MHD_PANIC("Data offset exceeds limit");
2075  ret = connection->send_cls (connection,
2076  &response->data
2077  [(size_t)data_write_offset],
2078  response->data_size -
2079  (size_t)data_write_offset);
2080  err = MHD_socket_errno_;
2081 #if DEBUG_SEND_DATA
2082  if (ret > 0)
2083  fprintf (stderr,
2084  "Sent %d-byte DATA response: `%.*s'\n",
2085  (int) ret,
2086  (int) ret,
2087  &response->data[connection->response_write_position -
2088  response->data_start]);
2089 #endif
2090  if (NULL != response->crc)
2091  (void) MHD_mutex_unlock_ (&response->mutex);
2092  if (ret < 0)
2093  {
2094  if ((err == EINTR) || (err == EAGAIN) || (EWOULDBLOCK == err))
2095  return MHD_YES;
2096 #if HAVE_MESSAGES
2097  MHD_DLOG (connection->daemon,
2098  "Failed to send data: %s\n",
2100 #endif
2101  CONNECTION_CLOSE_ERROR (connection, NULL);
2102  return MHD_YES;
2103  }
2104  connection->response_write_position += ret;
2105  }
2106  if (connection->response_write_position ==
2107  connection->response->total_size)
2108  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
2109  break;
2111  EXTRA_CHECK (0);
2112  break;
2114  do_write (connection);
2115  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
2116  break;
2117  check_write_done (connection,
2118  (connection->response->total_size ==
2119  connection->response_write_position) ?
2122  break;
2123  case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
2125  EXTRA_CHECK (0);
2126  break;
2128  do_write (connection);
2129  if (connection->state != MHD_CONNECTION_FOOTERS_SENDING)
2130  break;
2132  break;
2134  EXTRA_CHECK (0);
2135  break;
2136  case MHD_CONNECTION_CLOSED:
2137  return MHD_YES;
2139  EXTRA_CHECK (0);
2140  break;
2141  default:
2142  EXTRA_CHECK (0);
2143  CONNECTION_CLOSE_ERROR (connection,
2144  "Internal error\n");
2145  return MHD_YES;
2146  }
2147  break;
2148  }
2149  return MHD_YES;
2150 }
2151 
2152 
2159 static void
2161 {
2162  struct MHD_Daemon *daemon = connection->daemon;
2163 
2164  if (NULL != connection->response)
2165  {
2166  MHD_destroy_response (connection->response);
2167  connection->response = NULL;
2168  }
2169  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2170  (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) )
2171  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2172  if (connection->connection_timeout == daemon->connection_timeout)
2174  daemon->normal_timeout_tail,
2175  connection);
2176  else
2178  daemon->manual_timeout_tail,
2179  connection);
2180  if (MHD_YES == connection->suspended)
2183  connection);
2184  else
2185  DLL_remove (daemon->connections_head,
2186  daemon->connections_tail,
2187  connection);
2188  DLL_insert (daemon->cleanup_head,
2189  daemon->cleanup_tail,
2190  connection);
2191  connection->suspended = MHD_NO;
2192  connection->resuming = MHD_NO;
2193  connection->in_idle = MHD_NO;
2194  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2195  (MHD_YES != MHD_mutex_unlock_(&daemon->cleanup_connection_mutex)) )
2196  MHD_PANIC ("Failed to release cleanup mutex\n");
2197 }
2198 
2199 
2208 int
2210 {
2211  struct MHD_Daemon *daemon = connection->daemon;
2212  unsigned int timeout;
2213  const char *end;
2214  char *line;
2215  int client_close;
2216 
2217  connection->in_idle = MHD_YES;
2218  while (1)
2219  {
2220 #if DEBUG_STATES
2221  MHD_DLOG (daemon,
2222  "%s: state: %s\n",
2223  __FUNCTION__,
2224  MHD_state_to_string (connection->state));
2225 #endif
2226  switch (connection->state)
2227  {
2228  case MHD_CONNECTION_INIT:
2229  line = get_next_header_line (connection);
2230  /* Check for empty string, as we might want
2231  to tolerate 'spurious' empty lines; also
2232  NULL means we didn't get a full line yet. */
2233  if ( (NULL == line) ||
2234  (0 == line[0]) )
2235  {
2236  if (MHD_CONNECTION_INIT != connection->state)
2237  continue;
2238  if (MHD_YES == connection->read_closed)
2239  {
2240  CONNECTION_CLOSE_ERROR (connection,
2241  NULL);
2242  continue;
2243  }
2244  break;
2245  }
2246  if (MHD_NO == parse_initial_message_line (connection, line))
2247  CONNECTION_CLOSE_ERROR (connection, NULL);
2248  else
2249  connection->state = MHD_CONNECTION_URL_RECEIVED;
2250  continue;
2252  line = get_next_header_line (connection);
2253  if (NULL == line)
2254  {
2255  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
2256  continue;
2257  if (MHD_YES == connection->read_closed)
2258  {
2259  CONNECTION_CLOSE_ERROR (connection,
2260  NULL);
2261  continue;
2262  }
2263  break;
2264  }
2265  if (0 == line[0])
2266  {
2267  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2268  continue;
2269  }
2270  if (MHD_NO == process_header_line (connection, line))
2271  {
2272  transmit_error_response (connection,
2275  break;
2276  }
2278  continue;
2280  line = get_next_header_line (connection);
2281  if (NULL == line)
2282  {
2283  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2284  continue;
2285  if (MHD_YES == connection->read_closed)
2286  {
2287  CONNECTION_CLOSE_ERROR (connection,
2288  NULL);
2289  continue;
2290  }
2291  break;
2292  }
2293  if (MHD_NO ==
2294  process_broken_line (connection, line, MHD_HEADER_KIND))
2295  continue;
2296  if (0 == line[0])
2297  {
2298  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2299  continue;
2300  }
2301  continue;
2303  parse_connection_headers (connection);
2304  if (MHD_CONNECTION_CLOSED == connection->state)
2305  continue;
2307  continue;
2309  call_connection_handler (connection); /* first call */
2310  if (MHD_CONNECTION_CLOSED == connection->state)
2311  continue;
2312  if (need_100_continue (connection))
2313  {
2314  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2315  break;
2316  }
2317  if ( (NULL != connection->response) &&
2318  ( (MHD_str_equal_caseless_ (connection->method,
2320  (MHD_str_equal_caseless_ (connection->method,
2321  MHD_HTTP_METHOD_PUT))) )
2322  {
2323  /* we refused (no upload allowed!) */
2324  connection->remaining_upload_size = 0;
2325  /* force close, in case client still tries to upload... */
2326  connection->read_closed = MHD_YES;
2327  }
2328  connection->state = (0 == connection->remaining_upload_size)
2330  continue;
2332  if (connection->continue_message_write_offset ==
2333  strlen (HTTP_100_CONTINUE))
2334  {
2335  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2336  continue;
2337  }
2338  break;
2340  if (0 != connection->read_buffer_offset)
2341  {
2342  process_request_body (connection); /* loop call */
2343  if (MHD_CONNECTION_CLOSED == connection->state)
2344  continue;
2345  }
2346  if ((0 == connection->remaining_upload_size) ||
2347  ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
2348  (0 == connection->read_buffer_offset) &&
2349  (MHD_YES == connection->read_closed)))
2350  {
2351  if ((MHD_YES == connection->have_chunked_upload) &&
2352  (MHD_NO == connection->read_closed))
2353  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2354  else
2355  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2356  continue;
2357  }
2358  break;
2360  line = get_next_header_line (connection);
2361  if (NULL == line)
2362  {
2363  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2364  continue;
2365  if (MHD_YES == connection->read_closed)
2366  {
2367  CONNECTION_CLOSE_ERROR (connection,
2368  NULL);
2369  continue;
2370  }
2371  break;
2372  }
2373  if (0 == line[0])
2374  {
2375  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2376  continue;
2377  }
2378  if (MHD_NO == process_header_line (connection, line))
2379  {
2380  transmit_error_response (connection,
2383  break;
2384  }
2386  continue;
2388  line = get_next_header_line (connection);
2389  if (NULL == line)
2390  {
2391  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2392  continue;
2393  if (MHD_YES == connection->read_closed)
2394  {
2395  CONNECTION_CLOSE_ERROR (connection,
2396  NULL);
2397  continue;
2398  }
2399  break;
2400  }
2401  if (MHD_NO ==
2402  process_broken_line (connection, line, MHD_FOOTER_KIND))
2403  continue;
2404  if (0 == line[0])
2405  {
2406  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2407  continue;
2408  }
2409  continue;
2411  call_connection_handler (connection); /* "final" call */
2412  if (connection->state == MHD_CONNECTION_CLOSED)
2413  continue;
2414  if (NULL == connection->response)
2415  break; /* try again next time */
2416  if (MHD_NO == build_header_response (connection))
2417  {
2418  /* oops - close! */
2419  CONNECTION_CLOSE_ERROR (connection,
2420  "Closing connection (failed to create response header)\n");
2421  continue;
2422  }
2423  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2424 
2425 #if HAVE_DECL_TCP_CORK
2426  /* starting header send, set TCP cork */
2427  {
2428  const int val = 1;
2429  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2430  sizeof (val));
2431  }
2432 #endif
2433  break;
2435  /* no default action */
2436  break;
2438  if (connection->have_chunked_upload)
2440  else
2442  continue;
2444  /* nothing to do here */
2445  break;
2447  if (NULL != connection->response->crc)
2448  (void) MHD_mutex_lock_ (&connection->response->mutex);
2449  if (0 == connection->response->total_size)
2450  {
2451  if (NULL != connection->response->crc)
2452  (void) MHD_mutex_unlock_ (&connection->response->mutex);
2453  connection->state = MHD_CONNECTION_BODY_SENT;
2454  continue;
2455  }
2456  if (MHD_YES == try_ready_normal_body (connection))
2457  {
2458  if (NULL != connection->response->crc)
2459  (void) MHD_mutex_unlock_ (&connection->response->mutex);
2461  break;
2462  }
2463  /* not ready, no socket action */
2464  break;
2466  /* nothing to do here */
2467  break;
2469  if (NULL != connection->response->crc)
2470  (void) MHD_mutex_lock_ (&connection->response->mutex);
2471  if ( (0 == connection->response->total_size) ||
2472  (connection->response_write_position ==
2473  connection->response->total_size) )
2474  {
2475  if (NULL != connection->response->crc)
2476  (void) MHD_mutex_unlock_ (&connection->response->mutex);
2477  connection->state = MHD_CONNECTION_BODY_SENT;
2478  continue;
2479  }
2480  if (MHD_YES == try_ready_chunked_body (connection))
2481  {
2482  if (NULL != connection->response->crc)
2483  (void) MHD_mutex_unlock_ (&connection->response->mutex);
2485  continue;
2486  }
2487  if (NULL != connection->response->crc)
2488  (void) MHD_mutex_unlock_ (&connection->response->mutex);
2489  break;
2491  if (MHD_NO == build_header_response (connection))
2492  {
2493  /* oops - close! */
2494  CONNECTION_CLOSE_ERROR (connection,
2495  "Closing connection (failed to create response header)\n");
2496  continue;
2497  }
2498  if ( (MHD_NO == connection->have_chunked_upload) ||
2499  (connection->write_buffer_send_offset ==
2500  connection->write_buffer_append_offset) )
2501  connection->state = MHD_CONNECTION_FOOTERS_SENT;
2502  else
2503  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
2504  continue;
2506  /* no default action */
2507  break;
2509 #if HAVE_DECL_TCP_CORK
2510  /* done sending, uncork */
2511  {
2512  const int val = 0;
2513  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2514  sizeof (val));
2515  }
2516 #endif
2517  end =
2518  MHD_get_response_header (connection->response,
2520  client_close = ((NULL != end) && (MHD_str_equal_caseless_(end, "close")));
2521  MHD_destroy_response (connection->response);
2522  connection->response = NULL;
2523  if ( (NULL != daemon->notify_completed) &&
2524  (MHD_YES == connection->client_aware) )
2525  {
2526  daemon->notify_completed (daemon->notify_completed_cls,
2527  connection,
2528  &connection->client_context,
2530  connection->client_aware = MHD_NO;
2531  }
2532  end =
2533  MHD_lookup_connection_value (connection,
2536  if ( (MHD_YES == connection->read_closed) ||
2537  (client_close) ||
2538  ( (NULL != end) &&
2539  (MHD_str_equal_caseless_ (end, "close")) ) )
2540  {
2541  connection->read_closed = MHD_YES;
2542  connection->read_buffer_offset = 0;
2543  }
2544  if (((MHD_YES == connection->read_closed) &&
2545  (0 == connection->read_buffer_offset)) ||
2546  (MHD_NO == keepalive_possible (connection)))
2547  {
2548  /* have to close for some reason */
2549  MHD_connection_close_ (connection,
2551  MHD_pool_destroy (connection->pool);
2552  connection->pool = NULL;
2553  connection->read_buffer = NULL;
2554  connection->read_buffer_size = 0;
2555  connection->read_buffer_offset = 0;
2556  }
2557  else
2558  {
2559  /* can try to keep-alive */
2560  connection->version = NULL;
2561  connection->state = MHD_CONNECTION_INIT;
2562  /* Reset the read buffer to the starting size,
2563  preserving the bytes we have already read. */
2564  connection->read_buffer
2565  = MHD_pool_reset (connection->pool,
2566  connection->read_buffer,
2567  connection->read_buffer_offset,
2568  connection->daemon->pool_size / 2);
2569  connection->read_buffer_size
2570  = connection->daemon->pool_size / 2;
2571  }
2572  connection->client_aware = MHD_NO;
2573  connection->client_context = NULL;
2574  connection->continue_message_write_offset = 0;
2575  connection->responseCode = 0;
2576  connection->headers_received = NULL;
2577  connection->headers_received_tail = NULL;
2578  connection->response_write_position = 0;
2579  connection->have_chunked_upload = MHD_NO;
2580  connection->method = NULL;
2581  connection->url = NULL;
2582  connection->write_buffer = NULL;
2583  connection->write_buffer_size = 0;
2584  connection->write_buffer_send_offset = 0;
2585  connection->write_buffer_append_offset = 0;
2586  continue;
2587  case MHD_CONNECTION_CLOSED:
2588  cleanup_connection (connection);
2589  return MHD_NO;
2590  default:
2591  EXTRA_CHECK (0);
2592  break;
2593  }
2594  break;
2595  }
2596  timeout = connection->connection_timeout;
2597  if ( (0 != timeout) &&
2598  (timeout <= (MHD_monotonic_sec_counter() - connection->last_activity)) )
2599  {
2600  MHD_connection_close_ (connection,
2602  connection->in_idle = MHD_NO;
2603  return MHD_YES;
2604  }
2606 #if EPOLL_SUPPORT
2607  switch (connection->event_loop_info)
2608  {
2610  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2611  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2612  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2613  {
2614  EDLL_insert (daemon->eready_head,
2615  daemon->eready_tail,
2616  connection);
2617  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2618  }
2619  break;
2621  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
2622  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2623  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2624  {
2625  EDLL_insert (daemon->eready_head,
2626  daemon->eready_tail,
2627  connection);
2628  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2629  }
2630  break;
2632  /* we should look at this connection again in the next iteration
2633  of the event loop, as we're waiting on the application */
2634  if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) &&
2635  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) )
2636  {
2637  EDLL_insert (daemon->eready_head,
2638  daemon->eready_tail,
2639  connection);
2640  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2641  }
2642  break;
2644  /* This connection is finished, nothing left to do */
2645  break;
2646  }
2647  return MHD_connection_epoll_update_ (connection);
2648 #else
2649  return MHD_YES;
2650 #endif
2651 }
2652 
2653 
2654 #if EPOLL_SUPPORT
2655 
2663 int
2664 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
2665 {
2666  struct MHD_Daemon *daemon = connection->daemon;
2667 
2668  if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
2669  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2670  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2671  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
2672  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2673  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) ||
2674  (connection->read_buffer_size > connection->read_buffer_offset) ) &&
2675  (MHD_NO == connection->read_closed) ) ) )
2676  {
2677  /* add to epoll set */
2678  struct epoll_event event;
2679 
2680  event.events = EPOLLIN | EPOLLOUT | EPOLLET;
2681  event.data.ptr = connection;
2682  if (0 != epoll_ctl (daemon->epoll_fd,
2683  EPOLL_CTL_ADD,
2684  connection->socket_fd,
2685  &event))
2686  {
2687 #if HAVE_MESSAGES
2688  if (0 != (daemon->options & MHD_USE_DEBUG))
2689  MHD_DLOG (daemon,
2690  "Call to epoll_ctl failed: %s\n",
2692 #endif
2693  connection->state = MHD_CONNECTION_CLOSED;
2694  cleanup_connection (connection);
2695  return MHD_NO;
2696  }
2697  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2698  }
2699  connection->in_idle = MHD_NO;
2700  return MHD_YES;
2701 }
2702 #endif
2703 
2704 
2710 void
2712 {
2716 }
2717 
2718 
2729 const union MHD_ConnectionInfo *
2731  enum MHD_ConnectionInfoType info_type, ...)
2732 {
2733  switch (info_type)
2734  {
2735 #if HTTPS_SUPPORT
2737  if (connection->tls_session == NULL)
2738  return NULL;
2739  connection->cipher = gnutls_cipher_get (connection->tls_session);
2740  return (const union MHD_ConnectionInfo *) &connection->cipher;
2742  if (connection->tls_session == NULL)
2743  return NULL;
2744  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
2745  return (const union MHD_ConnectionInfo *) &connection->protocol;
2747  if (connection->tls_session == NULL)
2748  return NULL;
2749  return (const union MHD_ConnectionInfo *) &connection->tls_session;
2750 #endif
2752  return (const union MHD_ConnectionInfo *) &connection->addr;
2754  return (const union MHD_ConnectionInfo *) &connection->daemon;
2756  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
2758  return (const union MHD_ConnectionInfo *) &connection->socket_context;
2759  default:
2760  return NULL;
2761  };
2762 }
2763 
2764 
2774 int
2776  enum MHD_CONNECTION_OPTION option,
2777  ...)
2778 {
2779  va_list ap;
2780  struct MHD_Daemon *daemon;
2781 
2782  daemon = connection->daemon;
2783  switch (option)
2784  {
2786  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2787  (MHD_YES != MHD_mutex_lock_ (&daemon->cleanup_connection_mutex)) )
2788  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2789  if (MHD_YES != connection->suspended)
2790  {
2791  if (connection->connection_timeout == daemon->connection_timeout)
2793  daemon->normal_timeout_tail,
2794  connection);
2795  else
2797  daemon->manual_timeout_tail,
2798  connection);
2799  }
2800  va_start (ap, option);
2801  connection->connection_timeout = va_arg (ap, unsigned int);
2802  va_end (ap);
2803  if (MHD_YES != connection->suspended)
2804  {
2805  if (connection->connection_timeout == daemon->connection_timeout)
2807  daemon->normal_timeout_tail,
2808  connection);
2809  else
2811  daemon->manual_timeout_tail,
2812  connection);
2813  }
2814  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2815  (MHD_YES != MHD_mutex_unlock_ (&daemon->cleanup_connection_mutex)) )
2816  MHD_PANIC ("Failed to release cleanup mutex\n");
2817  return MHD_YES;
2818  default:
2819  return MHD_NO;
2820  }
2821 }
2822 
2823 
2835 int
2837  unsigned int status_code,
2838  struct MHD_Response *response)
2839 {
2840  if ( (NULL == connection) ||
2841  (NULL == response) ||
2842  (NULL != connection->response) ||
2843  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
2844  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
2845  return MHD_NO;
2846  MHD_increment_response_rc (response);
2847  connection->response = response;
2848  connection->responseCode = status_code;
2849  if ( (NULL != connection->method) &&
2851  {
2852  /* if this is a "HEAD" request, pretend that we
2853  have already sent the full message body */
2854  connection->response_write_position = response->total_size;
2855  }
2856  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
2857  (NULL != connection->method) &&
2858  ( (MHD_str_equal_caseless_ (connection->method,
2860  (MHD_str_equal_caseless_ (connection->method,
2861  MHD_HTTP_METHOD_PUT))) )
2862  {
2863  /* response was queued "early", refuse to read body / footers or
2864  further requests! */
2865  connection->read_closed = MHD_YES;
2866  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2867  }
2868  if (MHD_NO == connection->in_idle)
2869  (void) MHD_connection_handle_idle (connection);
2870  return MHD_YES;
2871 }
2872 
2873 
2874 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:1705
#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
Definition: microhttpd.h:326
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1415
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1212
void * unescape_callback_cls
Definition: internal.h:1056
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:396
#define XDLL_insert(head, tail, element)
Definition: internal.h:1367
uint64_t total_size
Definition: internal.h:289
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:335
void * mhd_panic_cls
Definition: daemon.c:154
#define MHD_socket_errno_
_MHD_EXTERN const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:219
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:450
void * socket_context
Definition: internal.h:602
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:982
enum MHD_CONNECTION_STATE state
Definition: internal.h:774
void * data
Definition: microhttpd.h:2035
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:404
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:267
uint64_t response_write_position
Definition: internal.h:706
#define NULL
Definition: reason_phrase.c:30
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:135
#define HTTP_100_CONTINUE
Definition: connection.c:50
#define MHD_ICY_FLAG
Definition: microhttpd.h:370
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:779
size_t current_chunk_size
Definition: internal.h:811
#define MHD_BUF_INC_SIZE
Definition: internal.h:65
int MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:1995
#define EXTRA_CHECK(a)
Definition: internal.h:1310
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:1181
#define DLL_remove(head, tail, element)
Definition: internal.h:1343
Methods for managing connections.
MHD_CONNECTION_STATE
Definition: internal.h:347
char * version
Definition: internal.h:620
#define INTERNAL_ERROR
Definition: connection.c:100
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:401
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:270
#define MHD_YES
Definition: microhttpd.h:138
struct MHD_Response * response
Definition: internal.h:573
char * colon
Definition: internal.h:651
#define REQUEST_LACKS_HOST
Definition: connection.c:75
char * write_buffer
Definition: internal.h:634
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:986
MHD_RequestTerminationCode
Definition: microhttpd.h:1043
size_t data_size
Definition: internal.h:306
static int do_read(struct MHD_Connection *connection)
Definition: connection.c:1588
int have_chunked_upload
Definition: internal.h:803
enum MHD_ValueKind kind
Definition: internal.h:238
struct MHD_HTTP_Header * first_header
Definition: internal.h:254
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:934
MHD_AccessHandlerCallback default_handler
Definition: internal.h:919
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:165
size_t current_chunk_offset
Definition: internal.h:817
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:1373
uint64_t remaining_upload_size
Definition: internal.h:699
unsigned int responseCode
Definition: internal.h:785
char * value
Definition: internal.h:232
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:2160
#define MHD_socket_last_strerr_()
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:264
void * uri_log_callback_cls
Definition: internal.h:1046
struct MHD_Daemon * daemon
Definition: internal.h:558
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:832
#define MHD_str_equal_caseless_(a, b)
struct MHD_Connection * manual_timeout_head
Definition: internal.h:993
struct MHD_Connection * cleanup_head
Definition: internal.h:949
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:395
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:299
int client_aware
Definition: internal.h:736
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:2730
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:515
struct MHD_Connection * cleanup_tail
Definition: internal.h:954
#define EWOULDBLOCK
Definition: w32functions.h:45
int MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:1932
int MHD_parse_arguments_(struct MHD_Connection *connection, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:189
size_t data_buffer_size
Definition: internal.h:311
MHD_CONNECTION_OPTION
Definition: microhttpd.h:2588
size_t write_buffer_send_offset
Definition: internal.h:687
#define ECONNRESET
Definition: w32functions.h:96
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:208
static void get_date_string(char *date)
Definition: connection.c:557
size_t read_buffer_size
Definition: internal.h:671
void * client_context
Definition: internal.h:593
#define MHD_MIN(a, b)
Definition: internal.h:55
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:999
size_t continue_message_write_offset
Definition: internal.h:712
#define REQUEST_MALFORMED
Definition: connection.c:88
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:186
MHD_socket socket_fd
Definition: internal.h:743
internal shared structures
char * method
Definition: internal.h:608
enum MHD_FLAG options
Definition: internal.h:1192
LogCallback uri_log_callback
Definition: internal.h:1041
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:574
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:2775
int shutdown
Definition: internal.h:1160
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:603
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:164
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:822
char * last
Definition: internal.h:642
struct MHD_Connection * normal_timeout_head
Definition: internal.h:980
#define MHD_snprintf_
MHD_ValueKind
Definition: microhttpd.h:997
char * read_buffer
Definition: internal.h:628
ReceiveCallback recv_cls
Definition: internal.h:837
static void update_last_activity(struct MHD_Connection *connection)
Definition: connection.c:1899
char * url
Definition: internal.h:614
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:245
size_t write_buffer_size
Definition: internal.h:682
static char * get_next_header_line(struct MHD_Connection *connection)
Definition: connection.c:1130
MHD_ConnectionInfoType
Definition: microhttpd.h:1174
uint64_t data_start
Definition: internal.h:295
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:441
UnescapeCallback unescape_callback
Definition: internal.h:1051
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:613
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:2836
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:827
#define LONG_MAX
Definition: mhd_limits.h:36
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:310
static int parse_initial_message_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:1314
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:553
struct MHD_Connection * connections_head
Definition: internal.h:929
size_t pool_size
Definition: internal.h:1089
char * header
Definition: internal.h:227
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:1677
const char * MHD_get_reason_phrase_for(unsigned int code)
time_t last_activity
Definition: internal.h:723
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2209
unsigned int connection_timeout
Definition: internal.h:729
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:1745
enum MHD_ResponseFlags flags
Definition: internal.h:327
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:398
#define MHD_PANIC(msg)
Definition: internal.h:101
struct MemoryPool * pool
Definition: internal.h:585
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:453
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:1820
time_t MHD_monotonic_sec_counter(void)
size_t write_buffer_append_offset
Definition: internal.h:693
struct MHD_HTTP_Header * next
Definition: internal.h:221
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1016
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:387
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:2711
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:456
void * notify_completed_cls
Definition: internal.h:1021
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:1407
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:440
TransmitCallback send_cls
Definition: internal.h:842
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:127
#define XDLL_remove(head, tail, element)
Definition: internal.h:1388
#define DLL_insert(head, tail, element)
Definition: internal.h:1322
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:341
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:165
MHD_ContentReaderCallback crc
Definition: internal.h:272
void * crc_cls
Definition: internal.h:266
struct sockaddr * addr
Definition: internal.h:657
MHD_mutex_ mutex
Definition: internal.h:284
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:944
MHD_PanicCallback mhd_panic
Definition: daemon.c:149
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:277
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:390
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:157
char * data
Definition: internal.h:260
static int do_write(struct MHD_Connection *connection)
Definition: connection.c:1635
size_t read_buffer_offset
Definition: internal.h:677
void * default_handler_cls
Definition: internal.h:924
#define MHD_NO
Definition: microhttpd.h:143
unsigned int connection_timeout
Definition: internal.h:1181
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:213
#define MHD_HTTP_REQUEST_URI_TOO_LONG
Definition: microhttpd.h:327
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1119
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:318
struct MHD_HTTP_Header * headers_received
Definition: internal.h:563
struct MHD_Connection * connections_tail
Definition: internal.h:934
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:422
#define EDLL_insert(head, tail, element)
Definition: internal.h:1411
#define SIZE_MAX
Definition: mhd_limits.h:48
_MHD_EXTERN int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:179
#define REQUEST_TOO_BIG
Definition: connection.c:62
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:568
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:645
size_t pool_increment
Definition: internal.h:1094
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:455
struct MHD_Connection * suspended_connections_head
Definition: internal.h:939
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...