GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  (C) 2007-2013 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 */
20 
28 #include "internal.h"
29 #include <limits.h>
30 #include "connection.h"
31 #include "memorypool.h"
32 #include "response.h"
33 #include "reason_phrase.h"
34 
35 #if HAVE_NETINET_TCP_H
36 /* for TCP_CORK */
37 #include <netinet/tcp.h>
38 #endif
39 
40 
44 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
45 
53 #if HAVE_MESSAGES
54 #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>"
55 #else
56 #define REQUEST_TOO_BIG ""
57 #endif
58 
66 #if HAVE_MESSAGES
67 #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>"
68 #else
69 #define REQUEST_LACKS_HOST ""
70 #endif
71 
79 #if HAVE_MESSAGES
80 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
81 #else
82 #define REQUEST_MALFORMED ""
83 #endif
84 
91 #if HAVE_MESSAGES
92 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
93 #else
94 #define INTERNAL_ERROR ""
95 #endif
96 
101 #define DEBUG_CLOSE MHD_NO
102 
106 #define DEBUG_SEND_DATA MHD_NO
107 
108 
120 int
122  enum MHD_ValueKind kind,
123  MHD_KeyValueIterator iterator, void *iterator_cls)
124 {
125  int ret;
126  struct MHD_HTTP_Header *pos;
127 
128  if (NULL == connection)
129  return -1;
130  ret = 0;
131  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
132  if (0 != (pos->kind & kind))
133  {
134  ret++;
135  if ((NULL != iterator) &&
136  (MHD_YES != iterator (iterator_cls,
137  kind, pos->header, pos->value)))
138  return ret;
139  }
140  return ret;
141 }
142 
143 
169 int
171  enum MHD_ValueKind kind,
172  const char *key, const char *value)
173 {
174  struct MHD_HTTP_Header *pos;
175 
176  pos = MHD_pool_allocate (connection->pool,
177  sizeof (struct MHD_HTTP_Header), MHD_YES);
178  if (NULL == pos)
179  return MHD_NO;
180  pos->header = (char *) key;
181  pos->value = (char *) value;
182  pos->kind = kind;
183  pos->next = NULL;
184  /* append 'pos' to the linked list of headers */
185  if (NULL == connection->headers_received_tail)
186  {
187  connection->headers_received = pos;
188  connection->headers_received_tail = pos;
189  }
190  else
191  {
192  connection->headers_received_tail->next = pos;
193  connection->headers_received_tail = pos;
194  }
195  return MHD_YES;
196 }
197 
198 
209 const char *
211  enum MHD_ValueKind kind, const char *key)
212 {
213  struct MHD_HTTP_Header *pos;
214 
215  if (NULL == connection)
216  return NULL;
217  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
218  if ((0 != (pos->kind & kind)) &&
219  ( (key == pos->header) ||
220  ( (NULL != pos->header) &&
221  (NULL != key) &&
222  (0 == strcasecmp (key, pos->header))) ))
223  return pos->value;
224  return NULL;
225 }
226 
227 
235 static int
236 need_100_continue (struct MHD_Connection *connection)
237 {
238  const char *expect;
239 
240  return ( (NULL == connection->response) &&
241  (NULL != connection->version) &&
242  (0 == strcasecmp (connection->version,
244  (NULL != (expect = MHD_lookup_connection_value (connection,
247  (0 == strcasecmp (expect, "100-continue")) &&
248  (connection->continue_message_write_offset <
249  strlen (HTTP_100_CONTINUE)) );
250 }
251 
252 
260 void
262  enum MHD_RequestTerminationCode termination_code)
263 {
264  struct MHD_Daemon *daemon;
265 
266  daemon = connection->daemon;
267  if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
268  shutdown (connection->socket_fd,
269  (MHD_YES == connection->read_closed) ? SHUT_WR : SHUT_RDWR);
270  connection->state = MHD_CONNECTION_CLOSED;
272  if ( (NULL != daemon->notify_completed) &&
273  (MHD_YES == connection->client_aware) )
274  daemon->notify_completed (daemon->notify_completed_cls,
275  connection,
276  &connection->client_context,
277  termination_code);
278  connection->client_aware = MHD_NO;
279 }
280 
281 
289 static void
291  const char *emsg)
292 {
293 #if HAVE_MESSAGES
294  if (NULL != emsg)
295  MHD_DLOG (connection->daemon, emsg);
296 #endif
298 }
299 
300 
305 #if HAVE_MESSAGES
306 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
307 #else
308 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
309 #endif
310 
311 
324 static int
326 {
327  ssize_t ret;
328  struct MHD_Response *response;
329 
330  response = connection->response;
331  if (NULL == response->crc)
332  return MHD_YES;
333  if (0 == response->total_size)
334  return MHD_YES; /* 0-byte response is always ready */
335  if ( (response->data_start <=
336  connection->response_write_position) &&
337  (response->data_size + response->data_start >
338  connection->response_write_position) )
339  return MHD_YES; /* response already ready */
340 #if LINUX
341  if ( (MHD_INVALID_SOCKET != response->fd) &&
342  (0 == (connection->daemon->options & MHD_USE_SSL)) )
343  {
344  /* will use sendfile, no need to bother response crc */
345  return MHD_YES;
346  }
347 #endif
348 
349  ret = response->crc (response->crc_cls,
350  connection->response_write_position,
351  response->data,
352  MHD_MIN (response->data_buffer_size,
353  response->total_size -
354  connection->response_write_position));
355  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
356  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
357  {
358  /* either error or http 1.0 transfer, close socket! */
359  response->total_size = connection->response_write_position;
360  if (NULL != response->crc)
361  pthread_mutex_unlock (&response->mutex);
362  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
364  else
365  CONNECTION_CLOSE_ERROR (connection,
366  "Closing connection (stream error)\n");
367  return MHD_NO;
368  }
369  response->data_start = connection->response_write_position;
370  response->data_size = ret;
371  if (0 == ret)
372  {
374  if (NULL != response->crc)
375  pthread_mutex_unlock (&response->mutex);
376  return MHD_NO;
377  }
378  return MHD_YES;
379 }
380 
381 
391 static int
393 {
394  ssize_t ret;
395  char *buf;
396  struct MHD_Response *response;
397  size_t size;
398  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
399  size_t cblen;
400 
401  response = connection->response;
402  if (0 == connection->write_buffer_size)
403  {
404  size = connection->daemon->pool_size;
405  do
406  {
407  size /= 2;
408  if (size < 128)
409  {
410  /* not enough memory */
411  CONNECTION_CLOSE_ERROR (connection,
412  "Closing connection (out of memory)\n");
413  return MHD_NO;
414  }
415  buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
416  }
417  while (NULL == buf);
418  connection->write_buffer_size = size;
419  connection->write_buffer = buf;
420  }
421 
422  if ( (response->data_start <=
423  connection->response_write_position) &&
424  (response->data_size + response->data_start >
425  connection->response_write_position) )
426  {
427  /* buffer already ready, use what is there for the chunk */
428  ret = response->data_size + response->data_start - connection->response_write_position;
429  if ( (ret > 0) &&
430  (((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2) )
431  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
432  memcpy (&connection->write_buffer[sizeof (cbuf)],
433  &response->data[connection->response_write_position - response->data_start],
434  ret);
435  }
436  else
437  {
438  /* buffer not in range, try to fill it */
439  if (0 == response->total_size)
440  ret = 0; /* response must be empty, don't bother calling crc */
441  else
442  ret = response->crc (response->crc_cls,
443  connection->response_write_position,
444  &connection->write_buffer[sizeof (cbuf)],
445  connection->write_buffer_size - sizeof (cbuf) - 2);
446  }
447  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
448  {
449  /* error, close socket! */
450  response->total_size = connection->response_write_position;
451  CONNECTION_CLOSE_ERROR (connection,
452  "Closing connection (error generating response)\n");
453  return MHD_NO;
454  }
455  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
456  (0 == response->total_size) )
457  {
458  /* end of message, signal other side! */
459  strcpy (connection->write_buffer, "0\r\n");
460  connection->write_buffer_append_offset = 3;
461  connection->write_buffer_send_offset = 0;
462  response->total_size = connection->response_write_position;
463  return MHD_YES;
464  }
465  if (0 == ret)
466  {
468  return MHD_NO;
469  }
470  if (ret > 0xFFFFFF)
471  ret = 0xFFFFFF;
472  snprintf (cbuf,
473  sizeof (cbuf),
474  "%X\r\n", (unsigned int) ret);
475  cblen = strlen (cbuf);
476  EXTRA_CHECK (cblen <= sizeof (cbuf));
477  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
478  memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
479  connection->response_write_position += ret;
480  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
481  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
482  return MHD_YES;
483 }
484 
485 
502 static int
503 keepalive_possible (struct MHD_Connection *connection)
504 {
505  const char *end;
506 
507  if (NULL == connection->version)
508  return MHD_NO;
509  end = MHD_lookup_connection_value (connection,
512  if (0 == strcasecmp (connection->version,
514  {
515  if (NULL == end)
516  return MHD_YES;
517  if (0 == strcasecmp (end, "close"))
518  return MHD_NO;
519  return MHD_YES;
520  }
521  if (0 == strcasecmp (connection->version,
523  {
524  if (NULL == end)
525  return MHD_NO;
526  if (0 == strcasecmp (end, "Keep-Alive"))
527  return MHD_YES;
528  return MHD_NO;
529  }
530  return MHD_NO;
531 }
532 
533 
540 static void
541 add_extra_headers (struct MHD_Connection *connection)
542 {
543  const char *have_close;
544  const char *have_keepalive;
545  const char *client_close;
546  const char *have_encoding;
547  char buf[128];
548  int add_close;
549 
550  client_close = MHD_lookup_connection_value (connection,
553  /* we only care about 'close', everything else is ignored */
554  if ( (NULL != client_close) &&
555  (0 != strcasecmp (client_close, "close")) )
556  client_close = NULL;
557  have_close = MHD_get_response_header (connection->response,
559  have_keepalive = have_close;
560  if ( (NULL != have_close) &&
561  (0 != strcasecmp (have_close, "close")) )
562  have_close = NULL;
563  if ( (NULL != have_keepalive) &&
564  (0 != strcasecmp (have_keepalive, "keep-alive")) )
565  have_keepalive = NULL;
566  connection->have_chunked_upload = MHD_NO;
567  add_close = MHD_NO;
568  if (MHD_SIZE_UNKNOWN == connection->response->total_size)
569  {
570  /* size is unknown, need to either to HTTP 1.1 chunked encoding or
571  close the connection */
572  if (NULL == have_close)
573  {
574  /* 'close' header doesn't exist yet, see if we need to add one;
575  if the client asked for a close, no need to start chunk'ing */
576  if ( (NULL == client_close) &&
577  (MHD_YES == keepalive_possible (connection)) &&
578  (0 == strcasecmp (connection->version,
580  {
581  connection->have_chunked_upload = MHD_YES;
582  have_encoding = MHD_get_response_header (connection->response,
584  if (NULL == have_encoding)
585  MHD_add_response_header (connection->response,
587  "chunked");
588  else if (0 != strcasecmp (have_encoding, "chunked"))
589  add_close = MHD_YES; /* application already set some strange encoding, can't do 'chunked' */
590  }
591  else
592  {
593  /* HTTP not 1.1 or client asked for close => set close header */
594  add_close = MHD_YES;
595  }
596  }
597  }
598  else
599  {
600  /* check if we should add a 'close' anyway */
601  if ( (NULL != client_close) &&
602  (NULL == have_close) )
603  add_close = MHD_YES; /* client asked for it, so add it */
604 
605  /* if not present, add content length */
606  if ( (NULL == MHD_get_response_header (connection->response,
608  ( (NULL == connection->method) ||
609  (0 != strcasecmp (connection->method,
611  (0 != connection->response->total_size) ) )
612  {
613  /*
614  Here we add a content-length if one is missing; however,
615  for 'connect' methods, the responses MUST NOT include a
616  content-length header *if* the response code is 2xx (in
617  which case we expect there to be no body). Still,
618  as we don't know the response code here in some cases, we
619  simply only force adding a content-length header if this
620  is not a 'connect' or if the response is not empty
621  (which is kind of more sane, because if some crazy
622  application did return content with a 2xx status code,
623  then having a content-length might again be a good idea).
624 
625  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
626  a recent development of the HTTP 1.1 specification.
627  */
628  sprintf (buf,
631  MHD_add_response_header (connection->response,
633  }
634  }
635  if (MHD_YES == add_close)
636  MHD_add_response_header (connection->response,
638  "close");
639  if ( (NULL == have_keepalive) &&
640  (NULL == have_close) &&
641  (MHD_NO == add_close) &&
642  (MHD_YES == keepalive_possible (connection)) )
643  MHD_add_response_header (connection->response,
645  "Keep-Alive");
646 }
647 
648 
655 static void
656 get_date_string (char *date)
657 {
658  static const char *const days[] =
659  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
660  static const char *const mons[] =
661  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
662  "Nov", "Dec"
663  };
664  struct tm now;
665  time_t t;
666 #if defined(_WIN32) && !defined(HAVE_GMTIME_S) && !defined(__CYGWIN__)
667  struct tm* pNow;
668 #endif
669 
670  date[0] = 0;
671  time (&t);
672 #if !defined(_WIN32)
673  if (NULL != gmtime_r (&t, &now))
674  {
675 #elif defined(HAVE_GMTIME_S)
676  if (0 == gmtime_s (&now, &t))
677  {
678 #elif defined(__CYGWIN__)
679  if (NULL != gmtime_r (&t, &now))
680  {
681 #else
682  pNow = gmtime(&t);
683  if (NULL != pNow)
684  {
685  now = *pNow;
686 #endif
687  sprintf (date,
688  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
689  days[now.tm_wday % 7],
690  (unsigned int) now.tm_mday,
691  mons[now.tm_mon % 12],
692  (unsigned int) (1900 + now.tm_year),
693  (unsigned int) now.tm_hour,
694  (unsigned int) now.tm_min,
695  (unsigned int) now.tm_sec);
696  }
697 }
698 
699 
711 static int
713 {
714  void *buf;
715  size_t new_size;
716 
717  if (0 == connection->read_buffer_size)
718  new_size = connection->daemon->pool_size / 2;
719  else
720  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
721  buf = MHD_pool_reallocate (connection->pool,
722  connection->read_buffer,
723  connection->read_buffer_size,
724  new_size);
725  if (NULL == buf)
726  return MHD_NO;
727  /* we can actually grow the buffer, do it! */
728  connection->read_buffer = buf;
729  connection->read_buffer_size = new_size;
730  return MHD_YES;
731 }
732 
733 
742 static int
744 {
745  size_t size;
746  size_t off;
747  struct MHD_HTTP_Header *pos;
748  char code[256];
749  char date[128];
750  char *data;
751  enum MHD_ValueKind kind;
752  const char *reason_phrase;
753  uint32_t rc;
754  int must_add_close;
755  const char *end;
756 
757  EXTRA_CHECK (NULL != connection->version);
758  if (0 == strlen (connection->version))
759  {
760  data = MHD_pool_allocate (connection->pool, 0, MHD_YES);
761  connection->write_buffer = data;
762  connection->write_buffer_append_offset = 0;
763  connection->write_buffer_send_offset = 0;
764  connection->write_buffer_size = 0;
765  return MHD_YES;
766  }
767  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
768  {
769  add_extra_headers (connection);
770  rc = connection->responseCode & (~MHD_ICY_FLAG);
771  reason_phrase = MHD_get_reason_phrase_for (rc);
772  sprintf (code,
773  "%s %u %s\r\n",
774  (0 != (connection->responseCode & MHD_ICY_FLAG))
775  ? "ICY"
776  : ( (0 == strcasecmp (MHD_HTTP_VERSION_1_0,
777  connection->version))
780  rc,
781  reason_phrase);
782  off = strlen (code);
783  /* estimate size */
784  size = off + 2; /* extra \r\n at the end */
785  kind = MHD_HEADER_KIND;
786  if ( (0 == (connection->daemon->options & MHD_SUPPRESS_DATE_NO_CLOCK)) &&
787  (NULL == MHD_get_response_header (connection->response,
789  get_date_string (date);
790  else
791  date[0] = '\0';
792  size += strlen (date);
793  }
794  else
795  {
796  /* 2 bytes for final CRLF of a Chunked-Body */
797  size = 2;
798  kind = MHD_FOOTER_KIND;
799  off = 0;
800  }
801  end = MHD_get_response_header (connection->response,
803  must_add_close = ( (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) &&
804  (MHD_YES == connection->read_closed) &&
805  (MHD_YES == keepalive_possible (connection)) &&
806  (NULL == end) );
807  if (must_add_close)
808  size += strlen ("Connection: close\r\n");
809  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
810  if (pos->kind == kind)
811  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
812  /* produce data */
813  data = MHD_pool_allocate (connection->pool, size + 1, MHD_NO);
814  if (NULL == data)
815  {
816 #if HAVE_MESSAGES
817  MHD_DLOG (connection->daemon,
818  "Not enough memory for write!\n");
819 #endif
820  return MHD_NO;
821  }
822  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
823  {
824  memcpy (data, code, off);
825  }
826  if (must_add_close)
827  {
828  /* we must add the 'close' header because circumstances forced us to
829  stop reading from the socket; however, we are not adding the header
830  to the response as the response may be used in a different context
831  as well */
832  memcpy (&data[off], "Connection: close\r\n",
833  strlen ("Connection: close\r\n"));
834  off += strlen ("Connection: close\r\n");
835  }
836  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
837  if (pos->kind == kind)
838  off += sprintf (&data[off],
839  "%s: %s\r\n",
840  pos->header,
841  pos->value);
842  if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
843  {
844  strcpy (&data[off], date);
845  off += strlen (date);
846  }
847  memcpy (&data[off], "\r\n", 2);
848  off += 2;
849 
850  if (off != size)
851  mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
852  connection->write_buffer = data;
853  connection->write_buffer_append_offset = size;
854  connection->write_buffer_send_offset = 0;
855  connection->write_buffer_size = size + 1;
856  return MHD_YES;
857 }
858 
859 
869 static void
871  unsigned int status_code,
872  const char *message)
873 {
874  struct MHD_Response *response;
875 
876  if (NULL == connection->version)
877  {
878  /* we were unable to process the full header line, so we don't
879  really know what version the client speaks; assume 1.0 */
880  connection->version = MHD_HTTP_VERSION_1_0;
881  }
883  connection->read_closed = MHD_YES;
884 #if HAVE_MESSAGES
885  MHD_DLOG (connection->daemon,
886  "Error %u (`%s') processing request, closing connection.\n",
887  status_code, message);
888 #endif
889  EXTRA_CHECK (NULL == connection->response);
890  response = MHD_create_response_from_buffer (strlen (message),
891  (void *) message,
893  MHD_queue_response (connection, status_code, response);
894  EXTRA_CHECK (NULL != connection->response);
895  MHD_destroy_response (response);
896  if (MHD_NO == build_header_response (connection))
897  {
898  /* oops - close! */
899  CONNECTION_CLOSE_ERROR (connection,
900  "Closing connection (failed to create response header)\n");
901  }
902  else
903  {
905  }
906 }
907 
908 
917 static void
919 {
920  while (1)
921  {
922 #if DEBUG_STATES
923  MHD_DLOG (connection->daemon,
924  "%s: state: %s\n",
925  __FUNCTION__,
926  MHD_state_to_string (connection->state));
927 #endif
928  switch (connection->state)
929  {
930 #if HTTPS_SUPPORT
932  if (0 == gnutls_record_get_direction (connection->tls_session))
934  else
936  break;
937 #endif
938  case MHD_CONNECTION_INIT:
941  /* while reading headers, we always grow the
942  read buffer if needed, no size-check required */
943  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
944  (MHD_NO == try_grow_read_buffer (connection)) )
945  {
946  transmit_error_response (connection,
947  (connection->url != NULL)
951  continue;
952  }
953  if (MHD_NO == connection->read_closed)
955  else
957  break;
959  EXTRA_CHECK (0);
960  break;
962  EXTRA_CHECK (0);
963  break;
966  break;
968  if (connection->read_buffer_offset == connection->read_buffer_size)
969  {
970  if ((MHD_YES != try_grow_read_buffer (connection)) &&
971  (0 != (connection->daemon->options &
974  {
975  /* failed to grow the read buffer, and the
976  client which is supposed to handle the
977  received data in a *blocking* fashion
978  (in this mode) did not handle the data as
979  it was supposed to!
980  => we would either have to do busy-waiting
981  (on the client, which would likely fail),
982  or if we do nothing, we would just timeout
983  on the connection (if a timeout is even
984  set!).
985  Solution: we kill the connection with an error */
986  transmit_error_response (connection,
989  continue;
990  }
991  }
992  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
993  (MHD_NO == connection->read_closed) )
995  else
997  break;
1000  /* while reading footers, we always grow the
1001  read buffer if needed, no size-check required */
1002  if (MHD_YES == connection->read_closed)
1003  {
1004  CONNECTION_CLOSE_ERROR (connection,
1005  NULL);
1006  continue;
1007  }
1009  /* transition to FOOTERS_RECEIVED
1010  happens in read handler */
1011  break;
1014  break;
1016  /* headers in buffer, keep writing */
1018  break;
1020  EXTRA_CHECK (0);
1021  break;
1024  break;
1027  break;
1030  break;
1033  break;
1035  EXTRA_CHECK (0);
1036  break;
1039  break;
1041  EXTRA_CHECK (0);
1042  break;
1043  case MHD_CONNECTION_CLOSED:
1045  return; /* do nothing, not even reading */
1046  default:
1047  EXTRA_CHECK (0);
1048  }
1049  break;
1050  }
1051 }
1052 
1053 
1065 static char *
1067 {
1068  char *rbuf;
1069  size_t pos;
1070 
1071  if (0 == connection->read_buffer_offset)
1072  return NULL;
1073  pos = 0;
1074  rbuf = connection->read_buffer;
1075  while ((pos < connection->read_buffer_offset - 1) &&
1076  ('\r' != rbuf[pos]) && ('\n' != rbuf[pos]))
1077  pos++;
1078  if ( (pos == connection->read_buffer_offset - 1) &&
1079  ('\n' != rbuf[pos]) )
1080  {
1081  /* not found, consider growing... */
1082  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1083  (MHD_NO ==
1084  try_grow_read_buffer (connection)) )
1085  {
1086  transmit_error_response (connection,
1087  (NULL != connection->url)
1090  REQUEST_TOO_BIG);
1091  }
1092  return NULL;
1093  }
1094  /* found, check if we have proper LFCR */
1095  if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1]))
1096  rbuf[pos++] = '\0'; /* skip both r and n */
1097  rbuf[pos++] = '\0';
1098  connection->read_buffer += pos;
1099  connection->read_buffer_size -= pos;
1100  connection->read_buffer_offset -= pos;
1101  return rbuf;
1102 }
1103 
1104 
1116 static int
1118  char *key, char *value, enum MHD_ValueKind kind)
1119 {
1120  if (MHD_NO == MHD_set_connection_value (connection,
1121  kind,
1122  key, value))
1123  {
1124 #if HAVE_MESSAGES
1125  MHD_DLOG (connection->daemon,
1126  "Not enough memory to allocate header record!\n");
1127 #endif
1129  REQUEST_TOO_BIG);
1130  return MHD_NO;
1131  }
1132  return MHD_YES;
1133 }
1134 
1135 
1145 static int
1147  struct MHD_Connection *connection,
1148  char *args)
1149 {
1150  char *equals;
1151  char *amper;
1152 
1153  while (NULL != args)
1154  {
1155  equals = strchr (args, '=');
1156  amper = strchr (args, '&');
1157  if (NULL == amper)
1158  {
1159  /* last argument */
1160  if (NULL == equals)
1161  {
1162  /* got 'foo', add key 'foo' with NULL for value */
1163  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1164  connection,
1165  args);
1166  return connection_add_header (connection,
1167  args,
1168  NULL,
1169  kind);
1170  }
1171  /* got 'foo=bar' */
1172  equals[0] = '\0';
1173  equals++;
1174  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1175  connection,
1176  args);
1177  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1178  connection,
1179  equals);
1180  return connection_add_header (connection, args, equals, kind);
1181  }
1182  /* amper is non-NULL here */
1183  amper[0] = '\0';
1184  amper++;
1185  if ( (NULL == equals) ||
1186  (equals >= amper) )
1187  {
1188  /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
1189  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1190  connection,
1191  args);
1192  if (MHD_NO ==
1193  connection_add_header (connection,
1194  args,
1195  NULL,
1196  kind))
1197  return MHD_NO;
1198  /* continue with 'bar' */
1199  args = amper;
1200  continue;
1201 
1202  }
1203  /* equals and amper are non-NULL here, and equals < amper,
1204  so we got regular 'foo=value&bar...'-kind of argument */
1205  equals[0] = '\0';
1206  equals++;
1207  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1208  connection,
1209  args);
1210  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1211  connection,
1212  equals);
1213  if (MHD_NO == connection_add_header (connection, args, equals, kind))
1214  return MHD_NO;
1215  args = amper;
1216  }
1217  return MHD_YES;
1218 }
1219 
1220 
1226 static int
1228 {
1229  const char *hdr;
1230  char *cpy;
1231  char *pos;
1232  char *sce;
1233  char *semicolon;
1234  char *equals;
1235  char *ekill;
1236  char old;
1237  int quotes;
1238 
1239  hdr = MHD_lookup_connection_value (connection,
1242  if (NULL == hdr)
1243  return MHD_YES;
1244  cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
1245  if (NULL == cpy)
1246  {
1247 #if HAVE_MESSAGES
1248  MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
1249 #endif
1251  REQUEST_TOO_BIG);
1252  return MHD_NO;
1253  }
1254  memcpy (cpy, hdr, strlen (hdr) + 1);
1255  pos = cpy;
1256  while (NULL != pos)
1257  {
1258  while (' ' == *pos)
1259  pos++; /* skip spaces */
1260 
1261  sce = pos;
1262  while (((*sce) != '\0') &&
1263  ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
1264  sce++;
1265  /* remove tailing whitespace (if any) from key */
1266  ekill = sce - 1;
1267  while ((*ekill == ' ') && (ekill >= pos))
1268  *(ekill--) = '\0';
1269  old = *sce;
1270  *sce = '\0';
1271  if (old != '=')
1272  {
1273  /* value part omitted, use empty string... */
1274  if (MHD_NO ==
1275  connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
1276  return MHD_NO;
1277  if (old == '\0')
1278  break;
1279  pos = sce + 1;
1280  continue;
1281  }
1282  equals = sce + 1;
1283  quotes = 0;
1284  semicolon = equals;
1285  while ( ('\0' != semicolon[0]) &&
1286  ( (0 != quotes) ||
1287  ( (';' != semicolon[0]) &&
1288  (',' != semicolon[0]) ) ) )
1289  {
1290  if ('"' == semicolon[0])
1291  quotes = (quotes + 1) & 1;
1292  semicolon++;
1293  }
1294  if ('\0' == semicolon[0])
1295  semicolon = NULL;
1296  if (NULL != semicolon)
1297  {
1298  semicolon[0] = '\0';
1299  semicolon++;
1300  }
1301  /* remove quotes */
1302  if ( ('"' == equals[0]) &&
1303  ('"' == equals[strlen (equals) - 1]) )
1304  {
1305  equals[strlen (equals) - 1] = '\0';
1306  equals++;
1307  }
1308  if (MHD_NO == connection_add_header (connection,
1309  pos, equals, MHD_COOKIE_KIND))
1310  return MHD_NO;
1311  pos = semicolon;
1312  }
1313  return MHD_YES;
1314 }
1315 
1316 
1324 static int
1326  char *line)
1327 {
1328  char *uri;
1329  char *http_version;
1330  char *args;
1331 
1332  if (NULL == (uri = strchr (line, ' ')))
1333  return MHD_NO; /* serious error */
1334  uri[0] = '\0';
1335  connection->method = line;
1336  uri++;
1337  while (' ' == uri[0])
1338  uri++;
1339  http_version = strchr (uri, ' ');
1340  if (NULL != http_version)
1341  {
1342  http_version[0] = '\0';
1343  http_version++;
1344  }
1345  if (NULL != connection->daemon->uri_log_callback)
1346  connection->client_context
1347  = connection->daemon->uri_log_callback (connection->daemon->uri_log_callback_cls,
1348  uri,
1349  connection);
1350  args = strchr (uri, '?');
1351  if (NULL != args)
1352  {
1353  args[0] = '\0';
1354  args++;
1355  parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
1356  }
1357  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1358  connection,
1359  uri);
1360  connection->url = uri;
1361  if (NULL == http_version)
1362  connection->version = "";
1363  else
1364  connection->version = http_version;
1365  return MHD_YES;
1366 }
1367 
1368 
1376 static void
1378 {
1379  size_t processed;
1380 
1381  if (NULL != connection->response)
1382  return; /* already queued a response */
1383  processed = 0;
1384  connection->client_aware = MHD_YES;
1385  if (MHD_NO ==
1386  connection->daemon->default_handler (connection->daemon-> default_handler_cls,
1387  connection,
1388  connection->url,
1389  connection->method,
1390  connection->version,
1391  NULL, &processed,
1392  &connection->client_context))
1393  {
1394  /* serious internal error, close connection */
1395  CONNECTION_CLOSE_ERROR (connection,
1396  "Internal application error, closing connection.\n");
1397  return;
1398  }
1399 }
1400 
1401 
1402 
1410 static void
1412 {
1413  size_t processed;
1414  size_t available;
1415  size_t used;
1416  size_t i;
1417  int instant_retry;
1418  int malformed;
1419  char *buffer_head;
1420  char *end;
1421 
1422  if (NULL != connection->response)
1423  return; /* already queued a response */
1424 
1425  buffer_head = connection->read_buffer;
1426  available = connection->read_buffer_offset;
1427  do
1428  {
1429  instant_retry = MHD_NO;
1430  if ( (MHD_YES == connection->have_chunked_upload) &&
1431  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
1432  {
1433  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
1434  (0 != connection->current_chunk_offset) &&
1435  (available >= 2) )
1436  {
1437  /* skip new line at the *end* of a chunk */
1438  i = 0;
1439  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1440  i++; /* skip 1st part of line feed */
1441  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1442  i++; /* skip 2nd part of line feed */
1443  if (i == 0)
1444  {
1445  /* malformed encoding */
1446  CONNECTION_CLOSE_ERROR (connection,
1447  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1448  return;
1449  }
1450  available -= i;
1451  buffer_head += i;
1452  connection->current_chunk_offset = 0;
1453  connection->current_chunk_size = 0;
1454  }
1455  if (connection->current_chunk_offset <
1456  connection->current_chunk_size)
1457  {
1458  /* we are in the middle of a chunk, give
1459  as much as possible to the client (without
1460  crossing chunk boundaries) */
1461  processed =
1462  connection->current_chunk_size -
1463  connection->current_chunk_offset;
1464  if (processed > available)
1465  processed = available;
1466  if (available > processed)
1467  instant_retry = MHD_YES;
1468  }
1469  else
1470  {
1471  /* we need to read chunk boundaries */
1472  i = 0;
1473  while (i < available)
1474  {
1475  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1476  break;
1477  i++;
1478  if (i >= 6)
1479  break;
1480  }
1481  /* take '\n' into account; if '\n'
1482  is the unavailable character, we
1483  will need to wait until we have it
1484  before going further */
1485  if ((i + 1 >= available) &&
1486  !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
1487  break; /* need more data... */
1488  malformed = (i >= 6);
1489  if (!malformed)
1490  {
1491  buffer_head[i] = '\0';
1492  connection->current_chunk_size = strtoul (buffer_head, &end, 16);
1493  malformed = ('\0' != *end);
1494  }
1495  if (malformed)
1496  {
1497  /* malformed encoding */
1498  CONNECTION_CLOSE_ERROR (connection,
1499  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1500  return;
1501  }
1502  i++;
1503  if ((i < available) &&
1504  ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
1505  i++; /* skip 2nd part of line feed */
1506 
1507  buffer_head += i;
1508  available -= i;
1509  connection->current_chunk_offset = 0;
1510 
1511  if (available > 0)
1512  instant_retry = MHD_YES;
1513  if (0 == connection->current_chunk_size)
1514  {
1515  connection->remaining_upload_size = 0;
1516  break;
1517  }
1518  continue;
1519  }
1520  }
1521  else
1522  {
1523  /* no chunked encoding, give all to the client */
1524  if ( (0 != connection->remaining_upload_size) &&
1525  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
1526  (connection->remaining_upload_size < available) )
1527  {
1528  processed = connection->remaining_upload_size;
1529  }
1530  else
1531  {
1536  processed = available;
1537  }
1538  }
1539  used = processed;
1540  connection->client_aware = MHD_YES;
1541  if (MHD_NO ==
1542  connection->daemon->default_handler (connection->daemon->default_handler_cls,
1543  connection,
1544  connection->url,
1545  connection->method,
1546  connection->version,
1547  buffer_head,
1548  &processed,
1549  &connection->client_context))
1550  {
1551  /* serious internal error, close connection */
1552  CONNECTION_CLOSE_ERROR (connection,
1553  "Internal application error, closing connection.\n");
1554  return;
1555  }
1556  if (processed > used)
1557  mhd_panic (mhd_panic_cls, __FILE__, __LINE__
1558 #if HAVE_MESSAGES
1559  , "API violation"
1560 #else
1561  , NULL
1562 #endif
1563  );
1564  if (0 != processed)
1565  instant_retry = MHD_NO; /* client did not process everything */
1566  used -= processed;
1567  if (connection->have_chunked_upload == MHD_YES)
1568  connection->current_chunk_offset += used;
1569  /* dh left "processed" bytes in buffer for next time... */
1570  buffer_head += used;
1571  available -= used;
1572  if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
1573  connection->remaining_upload_size -= used;
1574  }
1575  while (MHD_YES == instant_retry);
1576  if (available > 0)
1577  memmove (connection->read_buffer, buffer_head, available);
1578  connection->read_buffer_offset = available;
1579 }
1580 
1581 
1591 static int
1592 do_read (struct MHD_Connection *connection)
1593 {
1594  int bytes_read;
1595 
1596  if (connection->read_buffer_size == connection->read_buffer_offset)
1597  return MHD_NO;
1598  bytes_read = connection->recv_cls (connection,
1599  &connection->read_buffer
1600  [connection->read_buffer_offset],
1601  connection->read_buffer_size -
1602  connection->read_buffer_offset);
1603  if (bytes_read < 0)
1604  {
1605  const int err = MHD_socket_errno_;
1606  if ((EINTR == err) || (EAGAIN == err) || (ECONNRESET == err)
1607  || (EWOULDBLOCK == err))
1608  return MHD_NO;
1609 #if HAVE_MESSAGES
1610 #if HTTPS_SUPPORT
1611  if (0 != (connection->daemon->options & MHD_USE_SSL))
1612  MHD_DLOG (connection->daemon,
1613  "Failed to receive data: %s\n",
1614  gnutls_strerror (bytes_read));
1615  else
1616 #endif
1617  MHD_DLOG (connection->daemon,
1618  "Failed to receive data: %s\n",
1620 #endif
1621  CONNECTION_CLOSE_ERROR (connection, NULL);
1622  return MHD_YES;
1623  }
1624  if (0 == bytes_read)
1625  {
1626  /* other side closed connection; RFC 2616, section 8.1.4 suggests
1627  we should then shutdown ourselves as well. */
1628  connection->read_closed = MHD_YES;
1629  MHD_connection_close (connection,
1631  return MHD_YES;
1632  }
1633  connection->read_buffer_offset += bytes_read;
1634  return MHD_YES;
1635 }
1636 
1637 
1646 static int
1647 do_write (struct MHD_Connection *connection)
1648 {
1649  ssize_t ret;
1650  size_t max;
1651 
1652  max = connection->write_buffer_append_offset - connection->write_buffer_send_offset;
1653  ret = connection->send_cls (connection,
1654  &connection->write_buffer
1655  [connection->write_buffer_send_offset],
1656  max);
1657 
1658  if (ret < 0)
1659  {
1660  const int err = MHD_socket_errno_;
1661  if ((EINTR == err) || (EAGAIN == err) || (EWOULDBLOCK == err))
1662  return MHD_NO;
1663 #if HAVE_MESSAGES
1664 #if HTTPS_SUPPORT
1665  if (0 != (connection->daemon->options & MHD_USE_SSL))
1666  MHD_DLOG (connection->daemon,
1667  "Failed to send data: %s\n",
1668  gnutls_strerror ((int) ret));
1669  else
1670 #endif
1671  MHD_DLOG (connection->daemon,
1672  "Failed to send data: %s\n", MHD_socket_last_strerr_ ());
1673 #endif
1674  CONNECTION_CLOSE_ERROR (connection, NULL);
1675  return MHD_YES;
1676  }
1677 #if DEBUG_SEND_DATA
1678  fprintf (stderr,
1679  "Sent response: `%.*s'\n",
1680  ret,
1681  &connection->write_buffer[connection->write_buffer_send_offset]);
1682 #endif
1683  /* only increment if this wasn't a "sendfile" transmission without
1684  buffer involvement! */
1685  if (0 != max)
1686  connection->write_buffer_send_offset += ret;
1687  return MHD_YES;
1688 }
1689 
1690 
1699 static int
1700 check_write_done (struct MHD_Connection *connection,
1701  enum MHD_CONNECTION_STATE next_state)
1702 {
1703  if (connection->write_buffer_append_offset !=
1704  connection->write_buffer_send_offset)
1705  return MHD_NO;
1706  connection->write_buffer_append_offset = 0;
1707  connection->write_buffer_send_offset = 0;
1708  connection->state = next_state;
1709  MHD_pool_reallocate (connection->pool,
1710  connection->write_buffer,
1711  connection->write_buffer_size, 0);
1712  connection->write_buffer = NULL;
1713  connection->write_buffer_size = 0;
1714  return MHD_YES;
1715 }
1716 
1717 
1727 static int
1728 process_header_line (struct MHD_Connection *connection, char *line)
1729 {
1730  char *colon;
1731 
1732  /* line should be normal header line, find colon */
1733  colon = strchr (line, ':');
1734  if (NULL == colon)
1735  {
1736  /* error in header line, die hard */
1737  CONNECTION_CLOSE_ERROR (connection,
1738  "Received malformed line (no colon), closing connection.\n");
1739  return MHD_NO;
1740  }
1741  /* zero-terminate header */
1742  colon[0] = '\0';
1743  colon++; /* advance to value */
1744  while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
1745  colon++;
1746  /* we do the actual adding of the connection
1747  header at the beginning of the while
1748  loop since we need to be able to inspect
1749  the *next* header line (in case it starts
1750  with a space...) */
1751  connection->last = line;
1752  connection->colon = colon;
1753  return MHD_YES;
1754 }
1755 
1756 
1767 static int
1769  char *line, enum MHD_ValueKind kind)
1770 {
1771  char *last;
1772  char *tmp;
1773  size_t last_len;
1774  size_t tmp_len;
1775 
1776  last = connection->last;
1777  if ((line[0] == ' ') || (line[0] == '\t'))
1778  {
1779  /* value was continued on the next line, see
1780  http://www.jmarshall.com/easy/http/ */
1781  last_len = strlen (last);
1782  /* skip whitespace at start of 2nd line */
1783  tmp = line;
1784  while ((tmp[0] == ' ') || (tmp[0] == '\t'))
1785  tmp++;
1786  tmp_len = strlen (tmp);
1787  /* FIXME: we might be able to do this better (faster!), as most
1788  likely 'last' and 'line' should already be adjacent in
1789  memory; however, doing this right gets tricky if we have a
1790  value continued over multiple lines (in which case we need to
1791  record how often we have done this so we can check for
1792  adjaency); also, in the case where these are not adjacent
1793  (not sure how it can happen!), we would want to allocate from
1794  the end of the pool, so as to not destroy the read-buffer's
1795  ability to grow nicely. */
1796  last = MHD_pool_reallocate (connection->pool,
1797  last,
1798  last_len + 1,
1799  last_len + tmp_len + 1);
1800  if (NULL == last)
1801  {
1802  transmit_error_response (connection,
1804  REQUEST_TOO_BIG);
1805  return MHD_NO;
1806  }
1807  memcpy (&last[last_len], tmp, tmp_len + 1);
1808  connection->last = last;
1809  return MHD_YES; /* possibly more than 2 lines... */
1810  }
1811  EXTRA_CHECK ((NULL != last) && (NULL != connection->colon));
1812  if ((MHD_NO == connection_add_header (connection,
1813  last, connection->colon, kind)))
1814  {
1816  REQUEST_TOO_BIG);
1817  return MHD_NO;
1818  }
1819  /* we still have the current line to deal with... */
1820  if (0 != strlen (line))
1821  {
1822  if (MHD_NO == process_header_line (connection, line))
1823  {
1824  transmit_error_response (connection,
1826  return MHD_NO;
1827  }
1828  }
1829  return MHD_YES;
1830 }
1831 
1832 
1840 static void
1842 {
1843  const char *clen;
1845  struct MHD_Response *response;
1846  const char *enc;
1847  char *end;
1848 
1849  parse_cookie_header (connection);
1850  if ( (0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) &&
1851  (NULL != connection->version) &&
1852  (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)) &&
1853  (NULL ==
1854  MHD_lookup_connection_value (connection,
1857  {
1858  /* die, http 1.1 request without host and we are pedantic */
1859  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1860  connection->read_closed = MHD_YES;
1861 #if HAVE_MESSAGES
1862  MHD_DLOG (connection->daemon,
1863  "Received `%s' request without `%s' header.\n",
1865 #endif
1866  EXTRA_CHECK (NULL == connection->response);
1867  response =
1871  MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
1872  MHD_destroy_response (response);
1873  return;
1874  }
1875 
1876  connection->remaining_upload_size = 0;
1877  enc = MHD_lookup_connection_value (connection,
1880  if (enc != NULL)
1881  {
1883  if (0 == strcasecmp (enc, "chunked"))
1884  connection->have_chunked_upload = MHD_YES;
1885  }
1886  else
1887  {
1888  clen = MHD_lookup_connection_value (connection,
1891  if (clen != NULL)
1892  {
1893  cval = strtoul (clen, &end, 10);
1894  if ( ('\0' != *end) ||
1895  ( (LONG_MAX == cval) && (errno == ERANGE) ) )
1896  {
1897 #if HAVE_MESSAGES
1898  MHD_DLOG (connection->daemon,
1899  "Failed to parse `%s' header `%s', closing connection.\n",
1901  clen);
1902 #endif
1903  CONNECTION_CLOSE_ERROR (connection, NULL);
1904  return;
1905  }
1906  connection->remaining_upload_size = cval;
1907  }
1908  }
1909 }
1910 
1911 
1919 static void
1921 {
1922  struct MHD_Daemon *daemon = connection->daemon;
1923 
1924  connection->last_activity = MHD_monotonic_time();
1925  if (connection->connection_timeout != daemon->connection_timeout)
1926  return; /* custom timeout, no need to move it in DLL */
1927 
1928  /* move connection to head of timeout list (by remove + add operation) */
1929  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1930  (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
1931  MHD_PANIC ("Failed to acquire cleanup mutex\n");
1933  daemon->normal_timeout_tail,
1934  connection);
1936  daemon->normal_timeout_tail,
1937  connection);
1938  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1939  (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
1940  MHD_PANIC ("Failed to release cleanup mutex\n");
1941 }
1942 
1943 
1952 int
1954 {
1955  update_last_activity (connection);
1956  if (MHD_CONNECTION_CLOSED == connection->state)
1957  return MHD_YES;
1958  /* make sure "read" has a reasonable number of bytes
1959  in buffer to use per system call (if possible) */
1960  if (connection->read_buffer_offset + connection->daemon->pool_increment >
1961  connection->read_buffer_size)
1962  try_grow_read_buffer (connection);
1963  if (MHD_NO == do_read (connection))
1964  return MHD_YES;
1965  while (1)
1966  {
1967 #if DEBUG_STATES
1968  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1969  __FUNCTION__,
1970  MHD_state_to_string (connection->state));
1971 #endif
1972  switch (connection->state)
1973  {
1974  case MHD_CONNECTION_INIT:
1983  /* nothing to do but default action */
1984  if (MHD_YES == connection->read_closed)
1985  {
1986  MHD_connection_close (connection,
1988  continue;
1989  }
1990  break;
1991  case MHD_CONNECTION_CLOSED:
1992  return MHD_YES;
1993  default:
1994  /* shrink read buffer to how much is actually used */
1995  MHD_pool_reallocate (connection->pool,
1996  connection->read_buffer,
1997  connection->read_buffer_size + 1,
1998  connection->read_buffer_offset);
1999  break;
2000  }
2001  break;
2002  }
2003  return MHD_YES;
2004 }
2005 
2006 
2015 int
2017 {
2018  struct MHD_Response *response;
2019  ssize_t ret;
2020 
2021  update_last_activity (connection);
2022  while (1)
2023  {
2024 #if DEBUG_STATES
2025  MHD_DLOG (connection->daemon, "%s: state: %s\n",
2026  __FUNCTION__,
2027  MHD_state_to_string (connection->state));
2028 #endif
2029  switch (connection->state)
2030  {
2031  case MHD_CONNECTION_INIT:
2035  EXTRA_CHECK (0);
2036  break;
2038  break;
2040  ret = connection->send_cls (connection,
2042  [connection->continue_message_write_offset],
2043  strlen (HTTP_100_CONTINUE) -
2044  connection->continue_message_write_offset);
2045  if (ret < 0)
2046  {
2047  const int err = MHD_socket_errno_;
2048  if ((err == EINTR) || (err == EAGAIN) || (EWOULDBLOCK == err))
2049  break;
2050 #if HAVE_MESSAGES
2051  MHD_DLOG (connection->daemon,
2052  "Failed to send data: %s\n",
2054 #endif
2055  CONNECTION_CLOSE_ERROR (connection, NULL);
2056  return MHD_YES;
2057  }
2058 #if DEBUG_SEND_DATA
2059  fprintf (stderr,
2060  "Sent 100 continue response: `%.*s'\n",
2061  (int) ret,
2063 #endif
2064  connection->continue_message_write_offset += ret;
2065  break;
2070  EXTRA_CHECK (0);
2071  break;
2073  do_write (connection);
2074  if (connection->state != MHD_CONNECTION_HEADERS_SENDING)
2075  break;
2077  break;
2079  EXTRA_CHECK (0);
2080  break;
2082  response = connection->response;
2083  if (NULL != response->crc)
2084  pthread_mutex_lock (&response->mutex);
2085  if (MHD_YES != try_ready_normal_body (connection))
2086  break;
2087  ret = connection->send_cls (connection,
2088  &response->data
2089  [connection->response_write_position
2090  - response->data_start],
2091  response->data_size -
2092  (connection->response_write_position
2093  - response->data_start));
2094  const int err = MHD_socket_errno_;
2095 #if DEBUG_SEND_DATA
2096  if (ret > 0)
2097  fprintf (stderr,
2098  "Sent DATA response: `%.*s'\n",
2099  (int) ret,
2100  &response->data[connection->response_write_position -
2101  response->data_start]);
2102 #endif
2103  if (NULL != response->crc)
2104  pthread_mutex_unlock (&response->mutex);
2105  if (ret < 0)
2106  {
2107  if ((err == EINTR) || (err == EAGAIN) || (EWOULDBLOCK == err))
2108  return MHD_YES;
2109 #if HAVE_MESSAGES
2110  MHD_DLOG (connection->daemon,
2111  "Failed to send data: %s\n",
2113 #endif
2114  CONNECTION_CLOSE_ERROR (connection, NULL);
2115  return MHD_YES;
2116  }
2117  connection->response_write_position += ret;
2118  if (connection->response_write_position ==
2119  connection->response->total_size)
2120  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
2121  break;
2123  EXTRA_CHECK (0);
2124  break;
2126  do_write (connection);
2127  if (connection->state != MHD_CONNECTION_CHUNKED_BODY_READY)
2128  break;
2129  check_write_done (connection,
2130  (connection->response->total_size ==
2131  connection->response_write_position) ?
2134  break;
2135  case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
2137  EXTRA_CHECK (0);
2138  break;
2140  do_write (connection);
2141  if (connection->state != MHD_CONNECTION_FOOTERS_SENDING)
2142  break;
2144  break;
2146  EXTRA_CHECK (0);
2147  break;
2148  case MHD_CONNECTION_CLOSED:
2149  return MHD_YES;
2151  EXTRA_CHECK (0);
2152  break;
2153  default:
2154  EXTRA_CHECK (0);
2155  CONNECTION_CLOSE_ERROR (connection,
2156  "Internal error\n");
2157  return MHD_YES;
2158  }
2159  break;
2160  }
2161  return MHD_YES;
2162 }
2163 
2164 
2171 static void
2173 {
2174  struct MHD_Daemon *daemon = connection->daemon;
2175 
2176  if (NULL != connection->response)
2177  {
2178  MHD_destroy_response (connection->response);
2179  connection->response = NULL;
2180  }
2181  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2182  (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
2183  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2184  if (connection->connection_timeout == daemon->connection_timeout)
2186  daemon->normal_timeout_tail,
2187  connection);
2188  else
2190  daemon->manual_timeout_tail,
2191  connection);
2192  if (MHD_YES == connection->suspended)
2195  connection);
2196  else
2197  DLL_remove (daemon->connections_head,
2198  daemon->connections_tail,
2199  connection);
2200  DLL_insert (daemon->cleanup_head,
2201  daemon->cleanup_tail,
2202  connection);
2203  connection->suspended = MHD_NO;
2204  connection->resuming = MHD_NO;
2205  connection->in_idle = MHD_NO;
2206  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2207  (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) )
2208  MHD_PANIC ("Failed to release cleanup mutex\n");
2209 }
2210 
2211 
2220 int
2222 {
2223  struct MHD_Daemon *daemon = connection->daemon;
2224  unsigned int timeout;
2225  const char *end;
2226  char *line;
2227 
2228  connection->in_idle = MHD_YES;
2229  while (1)
2230  {
2231 #if DEBUG_STATES
2232  MHD_DLOG (daemon,
2233  "%s: state: %s\n",
2234  __FUNCTION__,
2235  MHD_state_to_string (connection->state));
2236 #endif
2237  switch (connection->state)
2238  {
2239  case MHD_CONNECTION_INIT:
2240  line = get_next_header_line (connection);
2241  if (NULL == line)
2242  {
2243  if (MHD_CONNECTION_INIT != connection->state)
2244  continue;
2245  if (MHD_YES == connection->read_closed)
2246  {
2247  CONNECTION_CLOSE_ERROR (connection,
2248  NULL);
2249  continue;
2250  }
2251  break;
2252  }
2253  if (MHD_NO == parse_initial_message_line (connection, line))
2254  CONNECTION_CLOSE_ERROR (connection, NULL);
2255  else
2256  connection->state = MHD_CONNECTION_URL_RECEIVED;
2257  continue;
2259  line = get_next_header_line (connection);
2260  if (NULL == line)
2261  {
2262  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
2263  continue;
2264  if (MHD_YES == connection->read_closed)
2265  {
2266  CONNECTION_CLOSE_ERROR (connection,
2267  NULL);
2268  continue;
2269  }
2270  break;
2271  }
2272  if (strlen (line) == 0)
2273  {
2274  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2275  continue;
2276  }
2277  if (MHD_NO == process_header_line (connection, line))
2278  {
2279  transmit_error_response (connection,
2282  break;
2283  }
2285  continue;
2287  line = get_next_header_line (connection);
2288  if (NULL == line)
2289  {
2290  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2291  continue;
2292  if (MHD_YES == connection->read_closed)
2293  {
2294  CONNECTION_CLOSE_ERROR (connection,
2295  NULL);
2296  continue;
2297  }
2298  break;
2299  }
2300  if (MHD_NO ==
2301  process_broken_line (connection, line, MHD_HEADER_KIND))
2302  continue;
2303  if (0 == strlen (line))
2304  {
2305  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2306  continue;
2307  }
2308  continue;
2310  parse_connection_headers (connection);
2311  if (MHD_CONNECTION_CLOSED == connection->state)
2312  continue;
2314  continue;
2316  call_connection_handler (connection); /* first call */
2317  if (MHD_CONNECTION_CLOSED == connection->state)
2318  continue;
2319  if (need_100_continue (connection))
2320  {
2321  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2322  break;
2323  }
2324  if ( (NULL != connection->response) &&
2325  ( (0 == strcasecmp (connection->method,
2327  (0 == strcasecmp (connection->method,
2328  MHD_HTTP_METHOD_PUT))) )
2329  {
2330  /* we refused (no upload allowed!) */
2331  connection->remaining_upload_size = 0;
2332  /* force close, in case client still tries to upload... */
2333  connection->read_closed = MHD_YES;
2334  }
2335  connection->state = (0 == connection->remaining_upload_size)
2337  continue;
2339  if (connection->continue_message_write_offset ==
2340  strlen (HTTP_100_CONTINUE))
2341  {
2342  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2343  continue;
2344  }
2345  break;
2347  if (0 != connection->read_buffer_offset)
2348  {
2349  process_request_body (connection); /* loop call */
2350  if (MHD_CONNECTION_CLOSED == connection->state)
2351  continue;
2352  }
2353  if ((0 == connection->remaining_upload_size) ||
2354  ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
2355  (0 == connection->read_buffer_offset) &&
2356  (MHD_YES == connection->read_closed)))
2357  {
2358  if ((MHD_YES == connection->have_chunked_upload) &&
2359  (MHD_NO == connection->read_closed))
2360  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2361  else
2362  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2363  continue;
2364  }
2365  break;
2367  line = get_next_header_line (connection);
2368  if (NULL == line)
2369  {
2370  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2371  continue;
2372  if (MHD_YES == connection->read_closed)
2373  {
2374  CONNECTION_CLOSE_ERROR (connection,
2375  NULL);
2376  continue;
2377  }
2378  break;
2379  }
2380  if (0 == strlen (line))
2381  {
2382  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2383  continue;
2384  }
2385  if (MHD_NO == process_header_line (connection, line))
2386  {
2387  transmit_error_response (connection,
2390  break;
2391  }
2393  continue;
2395  line = get_next_header_line (connection);
2396  if (NULL == line)
2397  {
2398  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2399  continue;
2400  if (MHD_YES == connection->read_closed)
2401  {
2402  CONNECTION_CLOSE_ERROR (connection,
2403  NULL);
2404  continue;
2405  }
2406  break;
2407  }
2408  if (MHD_NO ==
2409  process_broken_line (connection, line, MHD_FOOTER_KIND))
2410  continue;
2411  if (0 == strlen (line))
2412  {
2413  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2414  continue;
2415  }
2416  continue;
2418  call_connection_handler (connection); /* "final" call */
2419  if (connection->state == MHD_CONNECTION_CLOSED)
2420  continue;
2421  if (NULL == connection->response)
2422  break; /* try again next time */
2423  if (MHD_NO == build_header_response (connection))
2424  {
2425  /* oops - close! */
2426  CONNECTION_CLOSE_ERROR (connection,
2427  "Closing connection (failed to create response header)\n");
2428  continue;
2429  }
2430  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2431 
2432 #if HAVE_DECL_TCP_CORK
2433  /* starting header send, set TCP cork */
2434  {
2435  const int val = 1;
2436  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2437  sizeof (val));
2438  }
2439 #endif
2440  break;
2442  /* no default action */
2443  break;
2445  if (connection->have_chunked_upload)
2447  else
2449  continue;
2451  /* nothing to do here */
2452  break;
2454  if (NULL != connection->response->crc)
2455  pthread_mutex_lock (&connection->response->mutex);
2456  if (0 == connection->response->total_size)
2457  {
2458  if (NULL != connection->response->crc)
2459  pthread_mutex_unlock (&connection->response->mutex);
2460  connection->state = MHD_CONNECTION_BODY_SENT;
2461  continue;
2462  }
2463  if (MHD_YES == try_ready_normal_body (connection))
2464  {
2465  if (NULL != connection->response->crc)
2466  pthread_mutex_unlock (&connection->response->mutex);
2468  break;
2469  }
2470  /* not ready, no socket action */
2471  break;
2473  /* nothing to do here */
2474  break;
2476  if (NULL != connection->response->crc)
2477  pthread_mutex_lock (&connection->response->mutex);
2478  if (0 == connection->response->total_size)
2479  {
2480  if (NULL != connection->response->crc)
2481  pthread_mutex_unlock (&connection->response->mutex);
2482  connection->state = MHD_CONNECTION_BODY_SENT;
2483  continue;
2484  }
2485  if (MHD_YES == try_ready_chunked_body (connection))
2486  {
2487  if (NULL != connection->response->crc)
2488  pthread_mutex_unlock (&connection->response->mutex);
2490  continue;
2491  }
2492  if (NULL != connection->response->crc)
2493  pthread_mutex_unlock (&connection->response->mutex);
2494  break;
2496  build_header_response (connection);
2497  if (connection->write_buffer_send_offset ==
2498  connection->write_buffer_append_offset)
2499  connection->state = MHD_CONNECTION_FOOTERS_SENT;
2500  else
2501  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
2502  continue;
2504  /* no default action */
2505  break;
2507 #if HAVE_DECL_TCP_CORK
2508  /* done sending, uncork */
2509  {
2510  const int val = 0;
2511  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2512  sizeof (val));
2513  }
2514 #endif
2515  end =
2516  MHD_get_response_header (connection->response,
2518  MHD_destroy_response (connection->response);
2519  connection->response = NULL;
2520  if (NULL != daemon->notify_completed)
2521  daemon->notify_completed (daemon->notify_completed_cls,
2522  connection,
2523  &connection->client_context,
2525  end =
2528  if ( (MHD_YES == connection->read_closed) ||
2529  ((NULL != end) && (0 == strcasecmp (end, "close"))) )
2530  {
2531  connection->read_closed = MHD_YES;
2532  connection->read_buffer_offset = 0;
2533  }
2534  if (((MHD_YES == connection->read_closed) &&
2535  (0 == connection->read_buffer_offset)) ||
2536  (MHD_NO == keepalive_possible (connection)))
2537  {
2538  /* have to close for some reason */
2539  MHD_connection_close (connection,
2541  MHD_pool_destroy (connection->pool);
2542  connection->pool = NULL;
2543  connection->read_buffer = NULL;
2544  connection->read_buffer_size = 0;
2545  connection->read_buffer_offset = 0;
2546  }
2547  else
2548  {
2549  /* can try to keep-alive */
2550  connection->version = NULL;
2551  connection->state = MHD_CONNECTION_INIT;
2552  connection->read_buffer
2553  = MHD_pool_reset (connection->pool,
2554  connection->read_buffer,
2555  connection->read_buffer_size);
2556  }
2557  connection->client_aware = MHD_NO;
2558  connection->client_context = NULL;
2559  connection->continue_message_write_offset = 0;
2560  connection->responseCode = 0;
2561  connection->headers_received = NULL;
2562  connection->headers_received_tail = NULL;
2563  connection->response_write_position = 0;
2564  connection->have_chunked_upload = MHD_NO;
2565  connection->method = NULL;
2566  connection->url = NULL;
2567  connection->write_buffer = NULL;
2568  connection->write_buffer_size = 0;
2569  connection->write_buffer_send_offset = 0;
2570  connection->write_buffer_append_offset = 0;
2571  continue;
2572  case MHD_CONNECTION_CLOSED:
2573  cleanup_connection (connection);
2574  return MHD_NO;
2575  default:
2576  EXTRA_CHECK (0);
2577  break;
2578  }
2579  break;
2580  }
2581  timeout = connection->connection_timeout;
2582  if ( (0 != timeout) &&
2583  (timeout <= (MHD_monotonic_time() - connection->last_activity)) )
2584  {
2586  connection->in_idle = MHD_NO;
2587  return MHD_YES;
2588  }
2590 #if EPOLL_SUPPORT
2591  switch (connection->event_loop_info)
2592  {
2594  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2595  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2596  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2597  {
2598  EDLL_insert (daemon->eready_head,
2599  daemon->eready_tail,
2600  connection);
2601  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2602  }
2603  break;
2605  if ( (connection->read_buffer_size > connection->read_buffer_offset) &&
2606  (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2607  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2608  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2609  {
2610  EDLL_insert (daemon->eready_head,
2611  daemon->eready_tail,
2612  connection);
2613  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2614  }
2615  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
2616  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2617  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2618  {
2619  EDLL_insert (daemon->eready_head,
2620  daemon->eready_tail,
2621  connection);
2622  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2623  }
2624  break;
2626  /* we should look at this connection again in the next iteration
2627  of the event loop, as we're waiting on the application */
2628  if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) &&
2629  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) )
2630  {
2631  EDLL_insert (daemon->eready_head,
2632  daemon->eready_tail,
2633  connection);
2634  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2635  }
2636  break;
2638  /* This connection is finished, nothing left to do */
2639  break;
2640  }
2641  return MHD_connection_epoll_update_ (connection);
2642 #else
2643  return MHD_YES;
2644 #endif
2645 }
2646 
2647 
2648 #if EPOLL_SUPPORT
2649 
2657 int
2658 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
2659 {
2660  struct MHD_Daemon *daemon = connection->daemon;
2661 
2662  if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
2663  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2664  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2665  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
2666  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2667  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) ||
2668  (connection->read_buffer_size > connection->read_buffer_offset) ) &&
2669  (MHD_NO == connection->read_closed) ) ) )
2670  {
2671  /* add to epoll set */
2672  struct epoll_event event;
2673 
2674  event.events = EPOLLIN | EPOLLOUT | EPOLLET;
2675  event.data.ptr = connection;
2676  if (0 != epoll_ctl (daemon->epoll_fd,
2677  EPOLL_CTL_ADD,
2678  connection->socket_fd,
2679  &event))
2680  {
2681 #if HAVE_MESSAGES
2682  if (0 != (daemon->options & MHD_USE_DEBUG))
2683  MHD_DLOG (daemon,
2684  "Call to epoll_ctl failed: %s\n",
2686 #endif
2687  connection->state = MHD_CONNECTION_CLOSED;
2688  cleanup_connection (connection);
2689  return MHD_NO;
2690  }
2691  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2692  }
2693  connection->in_idle = MHD_NO;
2694  return MHD_YES;
2695 }
2696 #endif
2697 
2698 
2704 void
2706 {
2710 }
2711 
2712 
2723 const union MHD_ConnectionInfo *
2725  enum MHD_ConnectionInfoType info_type, ...)
2726 {
2727  switch (info_type)
2728  {
2729 #if HTTPS_SUPPORT
2731  if (connection->tls_session == NULL)
2732  return NULL;
2733  connection->cipher = gnutls_cipher_get (connection->tls_session);
2734  return (const union MHD_ConnectionInfo *) &connection->cipher;
2736  if (connection->tls_session == NULL)
2737  return NULL;
2738  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
2739  return (const union MHD_ConnectionInfo *) &connection->protocol;
2741  if (connection->tls_session == NULL)
2742  return NULL;
2743  return (const union MHD_ConnectionInfo *) &connection->tls_session;
2744 #endif
2746  return (const union MHD_ConnectionInfo *) &connection->addr;
2748  return (const union MHD_ConnectionInfo *) &connection->daemon;
2750  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
2751  default:
2752  return NULL;
2753  };
2754 }
2755 
2756 
2766 int
2768  enum MHD_CONNECTION_OPTION option,
2769  ...)
2770 {
2771  va_list ap;
2772  struct MHD_Daemon *daemon;
2773 
2774  daemon = connection->daemon;
2775  switch (option)
2776  {
2778  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2779  (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
2780  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2781  if (connection->connection_timeout == daemon->connection_timeout)
2783  daemon->normal_timeout_tail,
2784  connection);
2785  else
2787  daemon->manual_timeout_tail,
2788  connection);
2789  va_start (ap, option);
2790  connection->connection_timeout = va_arg (ap, unsigned int);
2791  va_end (ap);
2792  if (connection->connection_timeout == daemon->connection_timeout)
2794  daemon->normal_timeout_tail,
2795  connection);
2796  else
2798  daemon->manual_timeout_tail,
2799  connection);
2800  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2801  (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
2802  MHD_PANIC ("Failed to release cleanup mutex\n");
2803  return MHD_YES;
2804  default:
2805  return MHD_NO;
2806  }
2807 }
2808 
2809 
2821 int
2823  unsigned int status_code, struct MHD_Response *response)
2824 {
2825  if ( (NULL == connection) ||
2826  (NULL == response) ||
2827  (NULL != connection->response) ||
2828  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
2829  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
2830  return MHD_NO;
2831  MHD_increment_response_rc (response);
2832  connection->response = response;
2833  connection->responseCode = status_code;
2834  if ( (NULL != connection->method) &&
2835  (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)) )
2836  {
2837  /* if this is a "HEAD" request, pretend that we
2838  have already sent the full message body */
2839  connection->response_write_position = response->total_size;
2840  }
2841  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
2842  (NULL != connection->method) &&
2843  ( (0 == strcasecmp (connection->method,
2845  (0 == strcasecmp (connection->method,
2846  MHD_HTTP_METHOD_PUT))) )
2847  {
2848  /* response was queued "early", refuse to read body / footers or
2849  further requests! */
2850  connection->read_closed = MHD_YES;
2851  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2852  }
2853  if (MHD_NO == connection->in_idle)
2854  (void) MHD_connection_handle_idle (connection);
2855  return MHD_YES;
2856 }
2857 
2858 
2859 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:1728
#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
Definition: microhttpd.h:250
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1215
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1227
void * unescape_callback_cls
Definition: internal.h:1022
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:310
#define XDLL_insert(head, tail, element)
Definition: internal.h:1300
uint64_t total_size
Definition: internal.h:295
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:325
pthread_mutex_t cleanup_connection_mutex
Definition: internal.h:1085
void * mhd_panic_cls
Definition: daemon.c:143
#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:210
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:363
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:806
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:918
enum MHD_CONNECTION_STATE state
Definition: internal.h:753
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:811
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:392
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:90
uint64_t response_write_position
Definition: internal.h:686
#define NULL
Definition: reason_phrase.c:31
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:135
#define HTTP_100_CONTINUE
Definition: connection.c:44
#define MHD_ICY_FLAG
Definition: microhttpd.h:284
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:758
size_t current_chunk_size
Definition: internal.h:790
#define MHD_BUF_INC_SIZE
Definition: internal.h:65
int MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2016
#define EXTRA_CHECK(a)
Definition: internal.h:1247
#define DLL_remove(head, tail, element)
Definition: internal.h:1278
pthread_mutex_t mutex
Definition: internal.h:290
Methods for managing connections.
MHD_CONNECTION_STATE
Definition: internal.h:346
char * version
Definition: internal.h:602
#define INTERNAL_ERROR
Definition: connection.c:94
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:315
static int connection_add_header(struct MHD_Connection *connection, char *key, char *value, enum MHD_ValueKind kind)
Definition: connection.c:1117
#define MHD_YES
Definition: microhttpd.h:134
struct MHD_Response * response
Definition: internal.h:564
char * colon
Definition: internal.h:631
#define REQUEST_LACKS_HOST
Definition: connection.c:69
char * write_buffer
Definition: internal.h:616
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:963
MHD_RequestTerminationCode
Definition: microhttpd.h:918
size_t data_size
Definition: internal.h:311
static int do_read(struct MHD_Connection *connection)
Definition: connection.c:1592
int have_chunked_upload
Definition: internal.h:782
enum MHD_ValueKind kind
Definition: internal.h:244
struct MHD_HTTP_Header * first_header
Definition: internal.h:260
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:870
MHD_AccessHandlerCallback default_handler
Definition: internal.h:896
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:796
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:1377
uint64_t remaining_upload_size
Definition: internal.h:679
unsigned int responseCode
Definition: internal.h:764
char * value
Definition: internal.h:238
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:2172
#define MHD_socket_last_strerr_()
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:195
void * uri_log_callback_cls
Definition: internal.h:1012
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:801
struct MHD_Daemon * daemon
Definition: internal.h:549
struct MHD_Connection * manual_timeout_head
Definition: internal.h:970
struct MHD_Connection * cleanup_head
Definition: internal.h:926
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:309
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:290
int client_aware
Definition: internal.h:716
_MHD_EXTERN const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:2724
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:503
struct MHD_Connection * cleanup_tail
Definition: internal.h:931
#define EWOULDBLOCK
Definition: w32functions.h:45
int MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:1953
size_t data_buffer_size
Definition: internal.h:316
MHD_CONNECTION_OPTION
Definition: microhttpd.h:2218
size_t write_buffer_send_offset
Definition: internal.h:667
#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:656
size_t read_buffer_size
Definition: internal.h:651
void * client_context
Definition: internal.h:584
#define MHD_MIN(a, b)
Definition: internal.h:55
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:976
size_t continue_message_write_offset
Definition: internal.h:692
#define REQUEST_MALFORMED
Definition: connection.c:82
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:175
MHD_socket socket_fd
Definition: internal.h:723
internal shared structures
static void add_extra_headers(struct MHD_Connection *connection)
Definition: connection.c:541
char * method
Definition: internal.h:590
time_t MHD_monotonic_time(void)
Definition: internal.c:169
LogCallback uri_log_callback
Definition: internal.h:1007
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:444
_MHD_EXTERN int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:2767
int shutdown
Definition: internal.h:1117
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:473
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
char * last
Definition: internal.h:623
struct MHD_Connection * normal_timeout_head
Definition: internal.h:957
MHD_ValueKind
Definition: microhttpd.h:872
char * read_buffer
Definition: internal.h:610
ReceiveCallback recv_cls
Definition: internal.h:816
static void update_last_activity(struct MHD_Connection *connection)
Definition: connection.c:1920
char * url
Definition: internal.h:596
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:236
size_t write_buffer_size
Definition: internal.h:662
static char * get_next_header_line(struct MHD_Connection *connection)
Definition: connection.c:1066
const char * MHD_get_reason_phrase_for(unsigned int code)
MHD_ConnectionInfoType
Definition: microhttpd.h:1020
uint64_t data_start
Definition: internal.h:301
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:354
UnescapeCallback unescape_callback
Definition: internal.h:1017
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:712
_MHD_EXTERN int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:2822
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t size)
Definition: memorypool.c:262
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:237
static int parse_initial_message_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:1325
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:423
struct MHD_Connection * connections_head
Definition: internal.h:906
size_t pool_size
Definition: internal.h:1055
char * header
Definition: internal.h:233
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:1700
time_t last_activity
Definition: internal.h:703
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2221
unsigned int connection_timeout
Definition: internal.h:709
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:1768
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:312
#define MHD_PANIC(msg)
Definition: internal.h:91
struct MemoryPool * pool
Definition: internal.h:576
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:366
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:1841
size_t write_buffer_append_offset
Definition: internal.h:673
struct MHD_HTTP_Header * next
Definition: internal.h:227
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:993
enum MHD_OPTION options
Definition: internal.h:1144
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:301
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:2705
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:369
void * notify_completed_cls
Definition: internal.h:998
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:1411
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:353
TransmitCallback send_cls
Definition: internal.h:821
_MHD_EXTERN int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:121
#define XDLL_remove(head, tail, element)
Definition: internal.h:1319
#define DLL_insert(head, tail, element)
Definition: internal.h:1259
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:265
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:278
void * crc_cls
Definition: internal.h:272
struct sockaddr * addr
Definition: internal.h:637
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:921
MHD_PanicCallback mhd_panic
Definition: daemon.c:138
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:206
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:304
static int parse_arguments(enum MHD_ValueKind kind, struct MHD_Connection *connection, char *args)
Definition: connection.c:1146
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
char * data
Definition: internal.h:266
static int do_write(struct MHD_Connection *connection)
Definition: connection.c:1647
size_t read_buffer_offset
Definition: internal.h:657
void * default_handler_cls
Definition: internal.h:901
#define MHD_NO
Definition: microhttpd.h:139
unsigned int connection_timeout
Definition: internal.h:1133
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:200
#define MHD_HTTP_REQUEST_URI_TOO_LONG
Definition: microhttpd.h:251
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:308
struct MHD_HTTP_Header * headers_received
Definition: internal.h:554
struct MHD_Connection * connections_tail
Definition: internal.h:911
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:336
#define EDLL_insert(head, tail, element)
Definition: internal.h:1340
void MHD_connection_close(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:261
_MHD_EXTERN int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:170
#define REQUEST_TOO_BIG
Definition: connection.c:56
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:559
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:743
size_t pool_increment
Definition: internal.h:1060
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:368
struct MHD_Connection * suspended_connections_head
Definition: internal.h:916
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...