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 ( (-1 != 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  int 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 
492 static void
493 add_extra_headers (struct MHD_Connection *connection)
494 {
495  const char *have_close;
496  const char *client_close;
497  const char *have_encoding;
498  char buf[128];
499  int add_close;
500 
501  client_close = MHD_lookup_connection_value (connection,
504  /* we only care about 'close', everything else is ignored */
505  if ( (NULL != client_close) && (0 != strcasecmp (client_close, "close")) )
506  client_close = NULL;
507  have_close = MHD_get_response_header (connection->response,
509  if ( (NULL != have_close) && (0 != strcasecmp (have_close, "close")) )
510  have_close = NULL;
511  connection->have_chunked_upload = MHD_NO;
512  add_close = MHD_NO;
513  if (MHD_SIZE_UNKNOWN == connection->response->total_size)
514  {
515  /* size is unknown, need to either to HTTP 1.1 chunked encoding or
516  close the connection */
517  if (NULL == have_close)
518  {
519  /* 'close' header doesn't exist yet, see if we need to add one;
520  if the client asked for a close, no need to start chunk'ing */
521  if ((NULL == client_close) &&
522  (NULL != connection->version) &&
523  (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
524  {
525  connection->have_chunked_upload = MHD_YES;
526  have_encoding = MHD_get_response_header (connection->response,
528  if (NULL == have_encoding)
529  MHD_add_response_header (connection->response,
531  "chunked");
532  else if (0 != strcasecmp (have_encoding, "chunked"))
533  add_close = MHD_YES; /* application already set some strange encoding, can't do 'chunked' */
534  }
535  else
536  {
537  /* HTTP not 1.1 or client asked for close => set close header */
538  add_close = MHD_YES;
539  }
540  }
541  }
542  else
543  {
544  /* check if we should add a 'close' anyway */
545  if ( (NULL != client_close) &&
546  (NULL == have_close) )
547  add_close = MHD_YES; /* client asked for it, so add it */
548 
549  /* if not present, add content length */
550  if ( (NULL == MHD_get_response_header (connection->response,
552  ( (NULL == connection->method) ||
553  (0 != strcasecmp (connection->method,
555  (0 != connection->response->total_size) ) )
556  {
557  /*
558  Here we add a content-length if one is missing; however,
559  for 'connect' methods, the responses MUST NOT include a
560  content-length header *if* the response code is 2xx (in
561  which case we expect there to be no body). Still,
562  as we don't know the response code here in some cases, we
563  simply only force adding a content-length header if this
564  is not a 'connect' or if the response is not empty
565  (which is kind of more sane, because if some crazy
566  application did return content with a 2xx status code,
567  then having a content-length might again be a good idea).
568 
569  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
570  a recent development of the HTTP 1.1 specification.
571  */
572  SPRINTF (buf,
575  MHD_add_response_header (connection->response,
577  }
578  }
579  if (MHD_YES == add_close)
580  MHD_add_response_header (connection->response,
581  MHD_HTTP_HEADER_CONNECTION, "close");
582 }
583 
584 
591 static void
592 get_date_string (char *date)
593 {
594  static const char *const days[] =
595  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
596  static const char *const mons[] =
597  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
598  "Nov", "Dec"
599  };
600  struct tm now;
601  time_t t;
602 
603  time (&t);
604  gmtime_r (&t, &now);
605  SPRINTF (date,
606  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
607  days[now.tm_wday % 7],
608  (unsigned int) now.tm_mday,
609  mons[now.tm_mon % 12],
610  (unsigned int) (1900 + now.tm_year),
611  (unsigned int) now.tm_hour,
612  (unsigned int) now.tm_min,
613  (unsigned int) now.tm_sec);
614 }
615 
616 
628 static int
630 {
631  void *buf;
632  size_t new_size;
633 
634  if (0 == connection->read_buffer_size)
635  new_size = connection->daemon->pool_size / 2;
636  else
637  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
638  buf = MHD_pool_reallocate (connection->pool,
639  connection->read_buffer,
640  connection->read_buffer_size,
641  new_size);
642  if (NULL == buf)
643  return MHD_NO;
644  /* we can actually grow the buffer, do it! */
645  connection->read_buffer = buf;
646  connection->read_buffer_size = new_size;
647  return MHD_YES;
648 }
649 
650 
659 static int
661 {
662  size_t size;
663  size_t off;
664  struct MHD_HTTP_Header *pos;
665  char code[256];
666  char date[128];
667  char *data;
668  enum MHD_ValueKind kind;
669  const char *reason_phrase;
670  uint32_t rc;
671  int must_add_close;
672 
673  EXTRA_CHECK (NULL != connection->version);
674  if (0 == strlen (connection->version))
675  {
676  data = MHD_pool_allocate (connection->pool, 0, MHD_YES);
677  connection->write_buffer = data;
678  connection->write_buffer_append_offset = 0;
679  connection->write_buffer_send_offset = 0;
680  connection->write_buffer_size = 0;
681  return MHD_YES;
682  }
683  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
684  {
685  add_extra_headers (connection);
686  rc = connection->responseCode & (~MHD_ICY_FLAG);
687  reason_phrase = MHD_get_reason_phrase_for (rc);
688  SPRINTF (code,
689  "%s %u %s\r\n",
690  (0 != (connection->responseCode & MHD_ICY_FLAG))
691  ? "ICY"
692  : ( (0 == strcasecmp (MHD_HTTP_VERSION_1_0,
693  connection->version))
696  rc,
697  reason_phrase);
698  off = strlen (code);
699  /* estimate size */
700  size = off + 2; /* extra \r\n at the end */
701  kind = MHD_HEADER_KIND;
702  if ( (0 == (connection->daemon->options & MHD_SUPPRESS_DATE_NO_CLOCK)) &&
703  (NULL == MHD_get_response_header (connection->response,
705  get_date_string (date);
706  else
707  date[0] = '\0';
708  size += strlen (date);
709  }
710  else
711  {
712  size = 2;
713  kind = MHD_FOOTER_KIND;
714  off = 0;
715  }
716  must_add_close = ( (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state) &&
717  (MHD_YES == connection->read_closed) &&
718  (0 == strcasecmp (connection->version,
720  (NULL == MHD_get_response_header (connection->response,
722  if (must_add_close)
723  size += strlen ("Connection: close\r\n");
724  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
725  if (pos->kind == kind)
726  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
727  /* produce data */
728  data = MHD_pool_allocate (connection->pool, size + 1, MHD_NO);
729  if (NULL == data)
730  {
731 #if HAVE_MESSAGES
732  MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
733 #endif
734  return MHD_NO;
735  }
736  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
737  {
738  memcpy (data, code, off);
739  }
740  if (must_add_close)
741  {
742  /* we must add the 'close' header because circumstances forced us to
743  stop reading from the socket; however, we are not adding the header
744  to the response as the response may be used in a different context
745  as well */
746  memcpy (&data[off], "Connection: close\r\n",
747  strlen ("Connection: close\r\n"));
748  off += strlen ("Connection: close\r\n");
749  }
750  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
751  if (pos->kind == kind)
752  off += SPRINTF (&data[off],
753  "%s: %s\r\n",
754  pos->header,
755  pos->value);
756  if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
757  {
758  strcpy (&data[off], date);
759  off += strlen (date);
760  }
761  memcpy (&data[off], "\r\n", 2);
762  off += 2;
763 
764  if (off != size)
765  mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
766  connection->write_buffer = data;
767  connection->write_buffer_append_offset = size;
768  connection->write_buffer_send_offset = 0;
769  connection->write_buffer_size = size + 1;
770  return MHD_YES;
771 }
772 
773 
783 static void
785  unsigned int status_code,
786  const char *message)
787 {
788  struct MHD_Response *response;
789 
790  if (NULL == connection->version)
791  {
792  /* we were unable to process the full header line, so we don't
793  really know what version the client speaks; assume 1.0 */
794  connection->version = MHD_HTTP_VERSION_1_0;
795  }
797  connection->read_closed = MHD_YES;
798 #if HAVE_MESSAGES
799  MHD_DLOG (connection->daemon,
800  "Error %u (`%s') processing request, closing connection.\n",
801  status_code, message);
802 #endif
803  EXTRA_CHECK (NULL == connection->response);
804  response = MHD_create_response_from_buffer (strlen (message),
805  (void *) message,
807  MHD_queue_response (connection, status_code, response);
808  EXTRA_CHECK (NULL != connection->response);
809  MHD_destroy_response (response);
810  if (MHD_NO == build_header_response (connection))
811  {
812  /* oops - close! */
813  CONNECTION_CLOSE_ERROR (connection,
814  "Closing connection (failed to create response header)\n");
815  }
816  else
817  {
819  }
820 }
821 
822 
831 static void
833 {
834  while (1)
835  {
836 #if DEBUG_STATES
837  MHD_DLOG (connection->daemon, "%s: state: %s\n",
838  __FUNCTION__, MHD_state_to_string (connection->state));
839 #endif
840  switch (connection->state)
841  {
842 #if HTTPS_SUPPORT
844  if (0 == gnutls_record_get_direction (connection->tls_session))
846  else
848  break;
849 #endif
850  case MHD_CONNECTION_INIT:
853  /* while reading headers, we always grow the
854  read buffer if needed, no size-check required */
855  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
856  (MHD_NO == try_grow_read_buffer (connection)) )
857  {
858  transmit_error_response (connection,
859  (connection->url != NULL)
863  continue;
864  }
865  if (MHD_NO == connection->read_closed)
867  else
869  break;
871  EXTRA_CHECK (0);
872  break;
874  EXTRA_CHECK (0);
875  break;
878  break;
880  if (connection->read_buffer_offset == connection->read_buffer_size)
881  {
882  if ((MHD_YES != try_grow_read_buffer (connection)) &&
883  (0 != (connection->daemon->options &
886  {
887  /* failed to grow the read buffer, and the
888  client which is supposed to handle the
889  received data in a *blocking* fashion
890  (in this mode) did not handle the data as
891  it was supposed to!
892  => we would either have to do busy-waiting
893  (on the client, which would likely fail),
894  or if we do nothing, we would just timeout
895  on the connection (if a timeout is even
896  set!).
897  Solution: we kill the connection with an error */
898  transmit_error_response (connection,
901  continue;
902  }
903  }
904  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
905  (MHD_NO == connection->read_closed) )
907  else
909  break;
912  /* while reading footers, we always grow the
913  read buffer if needed, no size-check required */
914  if (MHD_YES == connection->read_closed)
915  {
916  CONNECTION_CLOSE_ERROR (connection,
917  NULL);
918  continue;
919  }
921  /* transition to FOOTERS_RECEIVED
922  happens in read handler */
923  break;
926  break;
928  /* headers in buffer, keep writing */
930  break;
932  EXTRA_CHECK (0);
933  break;
936  break;
939  break;
942  break;
945  break;
947  EXTRA_CHECK (0);
948  break;
951  break;
953  EXTRA_CHECK (0);
954  break;
957  return; /* do nothing, not even reading */
958  default:
959  EXTRA_CHECK (0);
960  }
961  break;
962  }
963 }
964 
965 
977 static char *
979 {
980  char *rbuf;
981  size_t pos;
982 
983  if (0 == connection->read_buffer_offset)
984  return NULL;
985  pos = 0;
986  rbuf = connection->read_buffer;
987  while ((pos < connection->read_buffer_offset - 1) &&
988  ('\r' != rbuf[pos]) && ('\n' != rbuf[pos]))
989  pos++;
990  if ( (pos == connection->read_buffer_offset - 1) &&
991  ('\n' != rbuf[pos]) )
992  {
993  /* not found, consider growing... */
994  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
995  (MHD_NO ==
996  try_grow_read_buffer (connection)) )
997  {
998  transmit_error_response (connection,
999  (NULL != connection->url)
1002  REQUEST_TOO_BIG);
1003  }
1004  return NULL;
1005  }
1006  /* found, check if we have proper LFCR */
1007  if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1]))
1008  rbuf[pos++] = '\0'; /* skip both r and n */
1009  rbuf[pos++] = '\0';
1010  connection->read_buffer += pos;
1011  connection->read_buffer_size -= pos;
1012  connection->read_buffer_offset -= pos;
1013  return rbuf;
1014 }
1015 
1016 
1028 static int
1030  char *key, char *value, enum MHD_ValueKind kind)
1031 {
1032  if (MHD_NO == MHD_set_connection_value (connection,
1033  kind,
1034  key, value))
1035  {
1036 #if HAVE_MESSAGES
1037  MHD_DLOG (connection->daemon,
1038  "Not enough memory to allocate header record!\n");
1039 #endif
1041  REQUEST_TOO_BIG);
1042  return MHD_NO;
1043  }
1044  return MHD_YES;
1045 }
1046 
1047 
1057 static int
1059  struct MHD_Connection *connection,
1060  char *args)
1061 {
1062  char *equals;
1063  char *amper;
1064 
1065  while (NULL != args)
1066  {
1067  equals = strchr (args, '=');
1068  amper = strchr (args, '&');
1069  if (NULL == amper)
1070  {
1071  /* last argument */
1072  if (NULL == equals)
1073  {
1074  /* got 'foo', add key 'foo' with NULL for value */
1075  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1076  connection,
1077  args);
1078  return connection_add_header (connection,
1079  args,
1080  NULL,
1081  kind);
1082  }
1083  /* got 'foo=bar' */
1084  equals[0] = '\0';
1085  equals++;
1086  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1087  connection,
1088  args);
1089  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1090  connection,
1091  equals);
1092  return connection_add_header (connection, args, equals, kind);
1093  }
1094  /* amper is non-NULL here */
1095  amper[0] = '\0';
1096  amper++;
1097  if ( (NULL == equals) ||
1098  (equals >= amper) )
1099  {
1100  /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
1101  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1102  connection,
1103  args);
1104  if (MHD_NO ==
1105  connection_add_header (connection,
1106  args,
1107  NULL,
1108  kind))
1109  return MHD_NO;
1110  /* continue with 'bar' */
1111  args = amper;
1112  continue;
1113 
1114  }
1115  /* equals and amper are non-NULL here, and equals < amper,
1116  so we got regular 'foo=value&bar...'-kind of argument */
1117  equals[0] = '\0';
1118  equals++;
1119  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1120  connection,
1121  args);
1122  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1123  connection,
1124  equals);
1125  if (MHD_NO == connection_add_header (connection, args, equals, kind))
1126  return MHD_NO;
1127  args = amper;
1128  }
1129  return MHD_YES;
1130 }
1131 
1132 
1138 static int
1140 {
1141  const char *hdr;
1142  char *cpy;
1143  char *pos;
1144  char *sce;
1145  char *semicolon;
1146  char *equals;
1147  char *ekill;
1148  char old;
1149  int quotes;
1150 
1151  hdr = MHD_lookup_connection_value (connection,
1154  if (NULL == hdr)
1155  return MHD_YES;
1156  cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
1157  if (NULL == cpy)
1158  {
1159 #if HAVE_MESSAGES
1160  MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
1161 #endif
1163  REQUEST_TOO_BIG);
1164  return MHD_NO;
1165  }
1166  memcpy (cpy, hdr, strlen (hdr) + 1);
1167  pos = cpy;
1168  while (NULL != pos)
1169  {
1170  while (' ' == *pos)
1171  pos++; /* skip spaces */
1172 
1173  sce = pos;
1174  while (((*sce) != '\0') &&
1175  ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
1176  sce++;
1177  /* remove tailing whitespace (if any) from key */
1178  ekill = sce - 1;
1179  while ((*ekill == ' ') && (ekill >= pos))
1180  *(ekill--) = '\0';
1181  old = *sce;
1182  *sce = '\0';
1183  if (old != '=')
1184  {
1185  /* value part omitted, use empty string... */
1186  if (MHD_NO ==
1187  connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
1188  return MHD_NO;
1189  if (old == '\0')
1190  break;
1191  pos = sce + 1;
1192  continue;
1193  }
1194  equals = sce + 1;
1195  quotes = 0;
1196  semicolon = equals;
1197  while ((semicolon[0] != '\0') &&
1198  ((quotes != 0) ||
1199  ((semicolon[0] != ';') && (semicolon[0] != ','))))
1200  {
1201  if (semicolon[0] == '"')
1202  quotes = (quotes + 1) & 1;
1203  semicolon++;
1204  }
1205  if (semicolon[0] == '\0')
1206  semicolon = NULL;
1207  if (NULL != semicolon)
1208  {
1209  semicolon[0] = '\0';
1210  semicolon++;
1211  }
1212  /* remove quotes */
1213  if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
1214  {
1215  equals[strlen (equals) - 1] = '\0';
1216  equals++;
1217  }
1218  if (MHD_NO == connection_add_header (connection,
1219  pos, equals, MHD_COOKIE_KIND))
1220  return MHD_NO;
1221  pos = semicolon;
1222  }
1223  return MHD_YES;
1224 }
1225 
1226 
1234 static int
1235 parse_initial_message_line (struct MHD_Connection *connection, char *line)
1236 {
1237  char *uri;
1238  char *http_version;
1239  char *args;
1240 
1241  if (NULL == (uri = strchr (line, ' ')))
1242  return MHD_NO; /* serious error */
1243  uri[0] = '\0';
1244  connection->method = line;
1245  uri++;
1246  while (uri[0] == ' ')
1247  uri++;
1248  http_version = strchr (uri, ' ');
1249  if (NULL != http_version)
1250  {
1251  http_version[0] = '\0';
1252  http_version++;
1253  }
1254  if (NULL != connection->daemon->uri_log_callback)
1255  connection->client_context
1256  = connection->daemon->uri_log_callback (connection->daemon->uri_log_callback_cls,
1257  uri,
1258  connection);
1259  args = strchr (uri, '?');
1260  if (NULL != args)
1261  {
1262  args[0] = '\0';
1263  args++;
1264  parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
1265  }
1266  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1267  connection,
1268  uri);
1269  connection->url = uri;
1270  if (NULL == http_version)
1271  connection->version = "";
1272  else
1273  connection->version = http_version;
1274  return MHD_YES;
1275 }
1276 
1277 
1285 static void
1287 {
1288  size_t processed;
1289 
1290  if (NULL != connection->response)
1291  return; /* already queued a response */
1292  processed = 0;
1293  connection->client_aware = MHD_YES;
1294  if (MHD_NO ==
1295  connection->daemon->default_handler (connection->daemon->
1296  default_handler_cls,
1297  connection, connection->url,
1298  connection->method,
1299  connection->version,
1300  NULL, &processed,
1301  &connection->client_context))
1302  {
1303  /* serious internal error, close connection */
1304  CONNECTION_CLOSE_ERROR (connection,
1305  "Internal application error, closing connection.\n");
1306  return;
1307  }
1308 }
1309 
1310 
1311 
1319 static void
1321 {
1322  size_t processed;
1323  size_t available;
1324  size_t used;
1325  size_t i;
1326  int instant_retry;
1327  int malformed;
1328  char *buffer_head;
1329  char *end;
1330 
1331  if (NULL != connection->response)
1332  return; /* already queued a response */
1333 
1334  buffer_head = connection->read_buffer;
1335  available = connection->read_buffer_offset;
1336  do
1337  {
1338  instant_retry = MHD_NO;
1339  if ((connection->have_chunked_upload == MHD_YES) &&
1340  (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
1341  {
1342  if ((connection->current_chunk_offset ==
1343  connection->current_chunk_size)
1344  && (connection->current_chunk_offset != 0) && (available >= 2))
1345  {
1346  /* skip new line at the *end* of a chunk */
1347  i = 0;
1348  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1349  i++; /* skip 1st part of line feed */
1350  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1351  i++; /* skip 2nd part of line feed */
1352  if (i == 0)
1353  {
1354  /* malformed encoding */
1355  CONNECTION_CLOSE_ERROR (connection,
1356  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1357  return;
1358  }
1359  available -= i;
1360  buffer_head += i;
1361  connection->current_chunk_offset = 0;
1362  connection->current_chunk_size = 0;
1363  }
1364  if (connection->current_chunk_offset <
1365  connection->current_chunk_size)
1366  {
1367  /* we are in the middle of a chunk, give
1368  as much as possible to the client (without
1369  crossing chunk boundaries) */
1370  processed =
1371  connection->current_chunk_size -
1372  connection->current_chunk_offset;
1373  if (processed > available)
1374  processed = available;
1375  if (available > processed)
1376  instant_retry = MHD_YES;
1377  }
1378  else
1379  {
1380  /* we need to read chunk boundaries */
1381  i = 0;
1382  while (i < available)
1383  {
1384  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1385  break;
1386  i++;
1387  if (i >= 6)
1388  break;
1389  }
1390  /* take '\n' into account; if '\n'
1391  is the unavailable character, we
1392  will need to wait until we have it
1393  before going further */
1394  if ((i + 1 >= available) &&
1395  !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
1396  break; /* need more data... */
1397  malformed = (i >= 6);
1398  if (!malformed)
1399  {
1400  buffer_head[i] = '\0';
1401  connection->current_chunk_size = strtoul (buffer_head, &end, 16);
1402  malformed = ('\0' != *end);
1403  }
1404  if (malformed)
1405  {
1406  /* malformed encoding */
1407  CONNECTION_CLOSE_ERROR (connection,
1408  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1409  return;
1410  }
1411  i++;
1412  if ((i < available) &&
1413  ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
1414  i++; /* skip 2nd part of line feed */
1415 
1416  buffer_head += i;
1417  available -= i;
1418  connection->current_chunk_offset = 0;
1419 
1420  if (available > 0)
1421  instant_retry = MHD_YES;
1422  if (connection->current_chunk_size == 0)
1423  {
1424  connection->remaining_upload_size = 0;
1425  break;
1426  }
1427  continue;
1428  }
1429  }
1430  else
1431  {
1432  /* no chunked encoding, give all to the client */
1433  if ( (0 != connection->remaining_upload_size) &&
1434  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
1435  (connection->remaining_upload_size < available) )
1436  {
1437  processed = connection->remaining_upload_size;
1438  }
1439  else
1440  {
1445  processed = available;
1446  }
1447  }
1448  used = processed;
1449  connection->client_aware = MHD_YES;
1450  if (MHD_NO ==
1451  connection->daemon->default_handler (connection->daemon->
1452  default_handler_cls,
1453  connection, connection->url,
1454  connection->method,
1455  connection->version,
1456  buffer_head, &processed,
1457  &connection->client_context))
1458  {
1459  /* serious internal error, close connection */
1460  CONNECTION_CLOSE_ERROR (connection,
1461  "Internal application error, closing connection.\n");
1462  return;
1463  }
1464  if (processed > used)
1465  mhd_panic (mhd_panic_cls, __FILE__, __LINE__
1466 #if HAVE_MESSAGES
1467  , "API violation"
1468 #else
1469  , NULL
1470 #endif
1471  );
1472  if (0 != processed)
1473  instant_retry = MHD_NO; /* client did not process everything */
1474  used -= processed;
1475  if (connection->have_chunked_upload == MHD_YES)
1476  connection->current_chunk_offset += used;
1477  /* dh left "processed" bytes in buffer for next time... */
1478  buffer_head += used;
1479  available -= used;
1480  if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
1481  connection->remaining_upload_size -= used;
1482  }
1483  while (MHD_YES == instant_retry);
1484  if (available > 0)
1485  memmove (connection->read_buffer, buffer_head, available);
1486  connection->read_buffer_offset = available;
1487 }
1488 
1489 
1499 static int
1500 do_read (struct MHD_Connection *connection)
1501 {
1502  int bytes_read;
1503 
1504  if (connection->read_buffer_size == connection->read_buffer_offset)
1505  return MHD_NO;
1506  bytes_read = connection->recv_cls (connection,
1507  &connection->read_buffer
1508  [connection->read_buffer_offset],
1509  connection->read_buffer_size -
1510  connection->read_buffer_offset);
1511  if (bytes_read < 0)
1512  {
1513  if ((EINTR == errno) || (EAGAIN == errno))
1514  return MHD_NO;
1515 #if HAVE_MESSAGES
1516 #if HTTPS_SUPPORT
1517  if (0 != (connection->daemon->options & MHD_USE_SSL))
1518  MHD_DLOG (connection->daemon,
1519  "Failed to receive data: %s\n",
1520  gnutls_strerror (bytes_read));
1521  else
1522 #endif
1523  MHD_DLOG (connection->daemon,
1524  "Failed to receive data: %s\n", STRERROR (errno));
1525 #endif
1526  CONNECTION_CLOSE_ERROR (connection, NULL);
1527  return MHD_YES;
1528  }
1529  if (0 == bytes_read)
1530  {
1531  /* other side closed connection; RFC 2616, section 8.1.4 suggests
1532  we should then shutdown ourselves as well. */
1533  connection->read_closed = MHD_YES;
1534  MHD_connection_close (connection,
1536  return MHD_YES;
1537  }
1538  connection->read_buffer_offset += bytes_read;
1539  return MHD_YES;
1540 }
1541 
1550 static int
1551 do_write (struct MHD_Connection *connection)
1552 {
1553  int ret;
1554  size_t max;
1555 
1556  max = connection->write_buffer_append_offset - connection->write_buffer_send_offset;
1557  ret = connection->send_cls (connection,
1558  &connection->write_buffer
1559  [connection->write_buffer_send_offset],
1560  max);
1561 
1562  if (ret < 0)
1563  {
1564  if ((EINTR == errno) || (EAGAIN == errno))
1565  return MHD_NO;
1566 #if HAVE_MESSAGES
1567 #if HTTPS_SUPPORT
1568  if (0 != (connection->daemon->options & MHD_USE_SSL))
1569  MHD_DLOG (connection->daemon,
1570  "Failed to send data: %s\n",
1571  gnutls_strerror (ret));
1572  else
1573 #endif
1574  MHD_DLOG (connection->daemon,
1575  "Failed to send data: %s\n", STRERROR (errno));
1576 #endif
1577  CONNECTION_CLOSE_ERROR (connection, NULL);
1578  return MHD_YES;
1579  }
1580 #if DEBUG_SEND_DATA
1581  FPRINTF (stderr,
1582  "Sent response: `%.*s'\n",
1583  ret,
1584  &connection->write_buffer[connection->write_buffer_send_offset]);
1585 #endif
1586  /* only increment if this wasn't a "sendfile" transmission without
1587  buffer involvement! */
1588  if (0 != max)
1589  connection->write_buffer_send_offset += ret;
1590  return MHD_YES;
1591 }
1592 
1593 
1602 static int
1603 check_write_done (struct MHD_Connection *connection,
1604  enum MHD_CONNECTION_STATE next_state)
1605 {
1606  if (connection->write_buffer_append_offset !=
1607  connection->write_buffer_send_offset)
1608  return MHD_NO;
1609  connection->write_buffer_append_offset = 0;
1610  connection->write_buffer_send_offset = 0;
1611  connection->state = next_state;
1612  MHD_pool_reallocate (connection->pool,
1613  connection->write_buffer,
1614  connection->write_buffer_size, 0);
1615  connection->write_buffer = NULL;
1616  connection->write_buffer_size = 0;
1617  return MHD_YES;
1618 }
1619 
1620 
1630 static int
1631 process_header_line (struct MHD_Connection *connection, char *line)
1632 {
1633  char *colon;
1634 
1635  /* line should be normal header line, find colon */
1636  colon = strchr (line, ':');
1637  if (NULL == colon)
1638  {
1639  /* error in header line, die hard */
1640  CONNECTION_CLOSE_ERROR (connection,
1641  "Received malformed line (no colon), closing connection.\n");
1642  return MHD_NO;
1643  }
1644  /* zero-terminate header */
1645  colon[0] = '\0';
1646  colon++; /* advance to value */
1647  while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
1648  colon++;
1649  /* we do the actual adding of the connection
1650  header at the beginning of the while
1651  loop since we need to be able to inspect
1652  the *next* header line (in case it starts
1653  with a space...) */
1654  connection->last = line;
1655  connection->colon = colon;
1656  return MHD_YES;
1657 }
1658 
1659 
1670 static int
1672  char *line, enum MHD_ValueKind kind)
1673 {
1674  char *last;
1675  char *tmp;
1676  size_t last_len;
1677  size_t tmp_len;
1678 
1679  last = connection->last;
1680  if ((line[0] == ' ') || (line[0] == '\t'))
1681  {
1682  /* value was continued on the next line, see
1683  http://www.jmarshall.com/easy/http/ */
1684  last_len = strlen (last);
1685  /* skip whitespace at start of 2nd line */
1686  tmp = line;
1687  while ((tmp[0] == ' ') || (tmp[0] == '\t'))
1688  tmp++;
1689  tmp_len = strlen (tmp);
1690  /* FIXME: we might be able to do this better (faster!), as most
1691  likely 'last' and 'line' should already be adjacent in
1692  memory; however, doing this right gets tricky if we have a
1693  value continued over multiple lines (in which case we need to
1694  record how often we have done this so we can check for
1695  adjaency); also, in the case where these are not adjacent
1696  (not sure how it can happen!), we would want to allocate from
1697  the end of the pool, so as to not destroy the read-buffer's
1698  ability to grow nicely. */
1699  last = MHD_pool_reallocate (connection->pool,
1700  last,
1701  last_len + 1,
1702  last_len + tmp_len + 1);
1703  if (NULL == last)
1704  {
1705  transmit_error_response (connection,
1707  REQUEST_TOO_BIG);
1708  return MHD_NO;
1709  }
1710  memcpy (&last[last_len], tmp, tmp_len + 1);
1711  connection->last = last;
1712  return MHD_YES; /* possibly more than 2 lines... */
1713  }
1714  EXTRA_CHECK ((NULL != last) && (NULL != connection->colon));
1715  if ((MHD_NO == connection_add_header (connection,
1716  last, connection->colon, kind)))
1717  {
1719  REQUEST_TOO_BIG);
1720  return MHD_NO;
1721  }
1722  /* we still have the current line to deal with... */
1723  if (0 != strlen (line))
1724  {
1725  if (MHD_NO == process_header_line (connection, line))
1726  {
1727  transmit_error_response (connection,
1729  return MHD_NO;
1730  }
1731  }
1732  return MHD_YES;
1733 }
1734 
1735 
1743 static void
1745 {
1746  const char *clen;
1748  struct MHD_Response *response;
1749  const char *enc;
1750  char *end;
1751 
1752  parse_cookie_header (connection);
1753  if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
1754  && (NULL != connection->version)
1755  && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
1756  && (NULL ==
1759  {
1760  /* die, http 1.1 request without host and we are pedantic */
1761  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1762  connection->read_closed = MHD_YES;
1763 #if HAVE_MESSAGES
1764  MHD_DLOG (connection->daemon,
1765  "Received `%s' request without `%s' header.\n",
1767 #endif
1768  EXTRA_CHECK (connection->response == NULL);
1769  response =
1773  MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
1774  MHD_destroy_response (response);
1775  return;
1776  }
1777 
1778  connection->remaining_upload_size = 0;
1779  enc = MHD_lookup_connection_value (connection,
1782  if (enc != NULL)
1783  {
1785  if (0 == strcasecmp (enc, "chunked"))
1786  connection->have_chunked_upload = MHD_YES;
1787  }
1788  else
1789  {
1790  clen = MHD_lookup_connection_value (connection,
1793  if (clen != NULL)
1794  {
1795  cval = strtoul (clen, &end, 10);
1796  if ( ('\0' != *end) ||
1797  ( (LONG_MAX == cval) && (errno == ERANGE) ) )
1798  {
1799 #if HAVE_MESSAGES
1800  MHD_DLOG (connection->daemon,
1801  "Failed to parse `%s' header `%s', closing connection.\n",
1803 #endif
1804  CONNECTION_CLOSE_ERROR (connection, NULL);
1805  return;
1806  }
1807  connection->remaining_upload_size = cval;
1808  }
1809  }
1810 }
1811 
1812 
1820 static void
1822 {
1823  struct MHD_Daemon *daemon = connection->daemon;
1824 
1825  connection->last_activity = MHD_monotonic_time();
1826  if (connection->connection_timeout != daemon->connection_timeout)
1827  return; /* custom timeout, no need to move it in DLL */
1828 
1829  /* move connection to head of timeout list (by remove + add operation) */
1830  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1831  (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
1832  MHD_PANIC ("Failed to acquire cleanup mutex\n");
1834  daemon->normal_timeout_tail,
1835  connection);
1837  daemon->normal_timeout_tail,
1838  connection);
1839  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
1840  (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
1841  MHD_PANIC ("Failed to release cleanup mutex\n");
1842 }
1843 
1844 
1853 int
1855 {
1856  update_last_activity (connection);
1857  if (MHD_CONNECTION_CLOSED == connection->state)
1858  return MHD_YES;
1859  /* make sure "read" has a reasonable number of bytes
1860  in buffer to use per system call (if possible) */
1861  if (connection->read_buffer_offset + connection->daemon->pool_increment >
1862  connection->read_buffer_size)
1863  try_grow_read_buffer (connection);
1864  if (MHD_NO == do_read (connection))
1865  return MHD_YES;
1866  while (1)
1867  {
1868 #if DEBUG_STATES
1869  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1870  __FUNCTION__, MHD_state_to_string (connection->state));
1871 #endif
1872  switch (connection->state)
1873  {
1874  case MHD_CONNECTION_INIT:
1883  /* nothing to do but default action */
1884  if (MHD_YES == connection->read_closed)
1885  {
1886  MHD_connection_close (connection,
1888  continue;
1889  }
1890  break;
1891  case MHD_CONNECTION_CLOSED:
1892  return MHD_YES;
1893  default:
1894  /* shrink read buffer to how much is actually used */
1895  MHD_pool_reallocate (connection->pool,
1896  connection->read_buffer,
1897  connection->read_buffer_size + 1,
1898  connection->read_buffer_offset);
1899  break;
1900  }
1901  break;
1902  }
1903  return MHD_YES;
1904 }
1905 
1906 
1915 int
1917 {
1918  struct MHD_Response *response;
1919  int ret;
1920 
1921  update_last_activity (connection);
1922  while (1)
1923  {
1924 #if DEBUG_STATES
1925  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1926  __FUNCTION__, MHD_state_to_string (connection->state));
1927 #endif
1928  switch (connection->state)
1929  {
1930  case MHD_CONNECTION_INIT:
1934  EXTRA_CHECK (0);
1935  break;
1937  break;
1939  ret = connection->send_cls (connection,
1941  [connection->continue_message_write_offset],
1942  strlen (HTTP_100_CONTINUE) -
1943  connection->continue_message_write_offset);
1944  if (ret < 0)
1945  {
1946  if ((errno == EINTR) || (errno == EAGAIN))
1947  break;
1948 #if HAVE_MESSAGES
1949  MHD_DLOG (connection->daemon,
1950  "Failed to send data: %s\n", STRERROR (errno));
1951 #endif
1952  CONNECTION_CLOSE_ERROR (connection, NULL);
1953  return MHD_YES;
1954  }
1955 #if DEBUG_SEND_DATA
1956  FPRINTF (stderr,
1957  "Sent 100 continue response: `%.*s'\n",
1958  ret,
1960  [connection->continue_message_write_offset]);
1961 #endif
1962  connection->continue_message_write_offset += ret;
1963  break;
1968  EXTRA_CHECK (0);
1969  break;
1971  do_write (connection);
1972  if (connection->state != MHD_CONNECTION_HEADERS_SENDING)
1973  break;
1975  break;
1977  EXTRA_CHECK (0);
1978  break;
1980  response = connection->response;
1981  if (NULL != response->crc)
1982  pthread_mutex_lock (&response->mutex);
1983  if (MHD_YES != try_ready_normal_body (connection))
1984  break;
1985  ret = connection->send_cls (connection,
1986  &response->data
1987  [connection->response_write_position
1988  - response->data_start],
1989  response->data_size -
1990  (connection->response_write_position
1991  - response->data_start));
1992 #if DEBUG_SEND_DATA
1993  if (ret > 0)
1994  FPRINTF (stderr,
1995  "Sent DATA response: `%.*s'\n",
1996  ret,
1997  &response->data[connection->response_write_position -
1998  response->data_start]);
1999 #endif
2000  if (NULL != response->crc)
2001  pthread_mutex_unlock (&response->mutex);
2002  if (ret < 0)
2003  {
2004  if ((errno == EINTR) || (errno == EAGAIN))
2005  return MHD_YES;
2006 #if HAVE_MESSAGES
2007  MHD_DLOG (connection->daemon,
2008  "Failed to send data: %s\n", STRERROR (errno));
2009 #endif
2010  CONNECTION_CLOSE_ERROR (connection, NULL);
2011  return MHD_YES;
2012  }
2013  connection->response_write_position += ret;
2014  if (connection->response_write_position ==
2015  connection->response->total_size)
2016  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers... */
2017  break;
2019  EXTRA_CHECK (0);
2020  break;
2022  do_write (connection);
2023  if (connection->state != MHD_CONNECTION_CHUNKED_BODY_READY)
2024  break;
2025  check_write_done (connection,
2026  (connection->response->total_size ==
2027  connection->response_write_position) ?
2030  break;
2031  case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
2033  EXTRA_CHECK (0);
2034  break;
2036  do_write (connection);
2037  if (connection->state != MHD_CONNECTION_FOOTERS_SENDING)
2038  break;
2040  break;
2042  EXTRA_CHECK (0);
2043  break;
2044  case MHD_CONNECTION_CLOSED:
2045  return MHD_YES;
2047  EXTRA_CHECK (0);
2048  break;
2049  default:
2050  EXTRA_CHECK (0);
2051  CONNECTION_CLOSE_ERROR (connection, "Internal error\n");
2052  return MHD_YES;
2053  }
2054  break;
2055  }
2056  return MHD_YES;
2057 }
2058 
2059 
2066 static void
2068 {
2069  struct MHD_Daemon *daemon = connection->daemon;
2070 
2071  if (NULL != connection->response)
2072  {
2073  MHD_destroy_response (connection->response);
2074  connection->response = NULL;
2075  }
2076  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2077  (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
2078  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2079  if (connection->connection_timeout == daemon->connection_timeout)
2081  daemon->normal_timeout_tail,
2082  connection);
2083  else
2085  daemon->manual_timeout_tail,
2086  connection);
2087  if (MHD_YES == connection->suspended)
2090  connection);
2091  else
2092  DLL_remove (daemon->connections_head,
2093  daemon->connections_tail,
2094  connection);
2095  DLL_insert (daemon->cleanup_head,
2096  daemon->cleanup_tail,
2097  connection);
2098  connection->suspended = MHD_NO;
2099  connection->resuming = MHD_NO;
2100  connection->in_idle = MHD_NO;
2101  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2102  (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex)) )
2103  MHD_PANIC ("Failed to release cleanup mutex\n");
2104 }
2105 
2106 
2115 int
2117 {
2118  struct MHD_Daemon *daemon = connection->daemon;
2119  unsigned int timeout;
2120  const char *end;
2121  int rend;
2122  char *line;
2123 
2124  connection->in_idle = MHD_YES;
2125  while (1)
2126  {
2127 #if DEBUG_STATES
2128  MHD_DLOG (daemon, "%s: state: %s\n",
2129  __FUNCTION__, MHD_state_to_string (connection->state));
2130 #endif
2131  switch (connection->state)
2132  {
2133  case MHD_CONNECTION_INIT:
2134  line = get_next_header_line (connection);
2135  if (NULL == line)
2136  {
2137  if (MHD_CONNECTION_INIT != connection->state)
2138  continue;
2139  if (MHD_YES == connection->read_closed)
2140  {
2141  CONNECTION_CLOSE_ERROR (connection,
2142  NULL);
2143  continue;
2144  }
2145  break;
2146  }
2147  if (MHD_NO == parse_initial_message_line (connection, line))
2148  CONNECTION_CLOSE_ERROR (connection, NULL);
2149  else
2150  connection->state = MHD_CONNECTION_URL_RECEIVED;
2151  continue;
2153  line = get_next_header_line (connection);
2154  if (NULL == line)
2155  {
2156  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
2157  continue;
2158  if (MHD_YES == connection->read_closed)
2159  {
2160  CONNECTION_CLOSE_ERROR (connection,
2161  NULL);
2162  continue;
2163  }
2164  break;
2165  }
2166  if (strlen (line) == 0)
2167  {
2168  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2169  continue;
2170  }
2171  if (MHD_NO == process_header_line (connection, line))
2172  {
2173  transmit_error_response (connection,
2176  break;
2177  }
2179  continue;
2181  line = get_next_header_line (connection);
2182  if (NULL == line)
2183  {
2184  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2185  continue;
2186  if (MHD_YES == connection->read_closed)
2187  {
2188  CONNECTION_CLOSE_ERROR (connection,
2189  NULL);
2190  continue;
2191  }
2192  break;
2193  }
2194  if (MHD_NO ==
2195  process_broken_line (connection, line, MHD_HEADER_KIND))
2196  continue;
2197  if (0 == strlen (line))
2198  {
2199  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2200  continue;
2201  }
2202  continue;
2204  parse_connection_headers (connection);
2205  if (MHD_CONNECTION_CLOSED == connection->state)
2206  continue;
2208  continue;
2210  call_connection_handler (connection); /* first call */
2211  if (MHD_CONNECTION_CLOSED == connection->state)
2212  continue;
2213  if (need_100_continue (connection))
2214  {
2215  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2216  break;
2217  }
2218  if ( (NULL != connection->response) &&
2219  ( (0 == strcasecmp (connection->method,
2221  (0 == strcasecmp (connection->method,
2222  MHD_HTTP_METHOD_PUT))) )
2223  {
2224  /* we refused (no upload allowed!) */
2225  connection->remaining_upload_size = 0;
2226  /* force close, in case client still tries to upload... */
2227  connection->read_closed = MHD_YES;
2228  }
2229  connection->state = (0 == connection->remaining_upload_size)
2231  continue;
2233  if (connection->continue_message_write_offset ==
2234  strlen (HTTP_100_CONTINUE))
2235  {
2236  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2237  continue;
2238  }
2239  break;
2241  if (connection->read_buffer_offset != 0)
2242  {
2243  process_request_body (connection); /* loop call */
2244  if (MHD_CONNECTION_CLOSED == connection->state)
2245  continue;
2246  }
2247  if ((connection->remaining_upload_size == 0) ||
2248  ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
2249  (connection->read_buffer_offset == 0) &&
2250  (MHD_YES == connection->read_closed)))
2251  {
2252  if ((MHD_YES == connection->have_chunked_upload) &&
2253  (MHD_NO == connection->read_closed))
2254  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2255  else
2256  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2257  continue;
2258  }
2259  break;
2261  line = get_next_header_line (connection);
2262  if (line == NULL)
2263  {
2264  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2265  continue;
2266  if (MHD_YES == connection->read_closed)
2267  {
2268  CONNECTION_CLOSE_ERROR (connection,
2269  NULL);
2270  continue;
2271  }
2272  break;
2273  }
2274  if (strlen (line) == 0)
2275  {
2276  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2277  continue;
2278  }
2279  if (MHD_NO == process_header_line (connection, line))
2280  {
2281  transmit_error_response (connection,
2284  break;
2285  }
2287  continue;
2289  line = get_next_header_line (connection);
2290  if (line == NULL)
2291  {
2292  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2293  continue;
2294  if (MHD_YES == connection->read_closed)
2295  {
2296  CONNECTION_CLOSE_ERROR (connection,
2297  NULL);
2298  continue;
2299  }
2300  break;
2301  }
2302  if (MHD_NO ==
2303  process_broken_line (connection, line, MHD_FOOTER_KIND))
2304  continue;
2305  if (strlen (line) == 0)
2306  {
2307  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2308  continue;
2309  }
2310  continue;
2312  call_connection_handler (connection); /* "final" call */
2313  if (connection->state == MHD_CONNECTION_CLOSED)
2314  continue;
2315  if (connection->response == NULL)
2316  break; /* try again next time */
2317  if (MHD_NO == build_header_response (connection))
2318  {
2319  /* oops - close! */
2320  CONNECTION_CLOSE_ERROR (connection,
2321  "Closing connection (failed to create response header)\n");
2322  continue;
2323  }
2324  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2325 
2326 #if HAVE_DECL_TCP_CORK
2327  /* starting header send, set TCP cork */
2328  {
2329  const int val = 1;
2330  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2331  sizeof (val));
2332  }
2333 #endif
2334  break;
2336  /* no default action */
2337  break;
2339  if (connection->have_chunked_upload)
2341  else
2343  continue;
2345  /* nothing to do here */
2346  break;
2348  if (NULL != connection->response->crc)
2349  pthread_mutex_lock (&connection->response->mutex);
2350  if (0 == connection->response->total_size)
2351  {
2352  if (NULL != connection->response->crc)
2353  pthread_mutex_unlock (&connection->response->mutex);
2354  connection->state = MHD_CONNECTION_BODY_SENT;
2355  continue;
2356  }
2357  if (MHD_YES == try_ready_normal_body (connection))
2358  {
2359  if (NULL != connection->response->crc)
2360  pthread_mutex_unlock (&connection->response->mutex);
2362  break;
2363  }
2364  /* not ready, no socket action */
2365  break;
2367  /* nothing to do here */
2368  break;
2370  if (NULL != connection->response->crc)
2371  pthread_mutex_lock (&connection->response->mutex);
2372  if (0 == connection->response->total_size)
2373  {
2374  if (NULL != connection->response->crc)
2375  pthread_mutex_unlock (&connection->response->mutex);
2376  connection->state = MHD_CONNECTION_BODY_SENT;
2377  continue;
2378  }
2379  if (MHD_YES == try_ready_chunked_body (connection))
2380  {
2381  if (NULL != connection->response->crc)
2382  pthread_mutex_unlock (&connection->response->mutex);
2384  continue;
2385  }
2386  if (NULL != connection->response->crc)
2387  pthread_mutex_unlock (&connection->response->mutex);
2388  break;
2390  build_header_response (connection);
2391  if (connection->write_buffer_send_offset ==
2392  connection->write_buffer_append_offset)
2393  connection->state = MHD_CONNECTION_FOOTERS_SENT;
2394  else
2395  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
2396  continue;
2398  /* no default action */
2399  break;
2401 #if HAVE_DECL_TCP_CORK
2402  /* done sending, uncork */
2403  {
2404  const int val = 0;
2405  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2406  sizeof (val));
2407  }
2408 #endif
2409  end =
2410  MHD_get_response_header (connection->response,
2412  rend = ( (MHD_YES == connection->read_closed) ||
2413  ( (end != NULL) && (0 == strcasecmp (end, "close")) ) );
2414  MHD_destroy_response (connection->response);
2415  connection->response = NULL;
2416  if (daemon->notify_completed != NULL)
2417  daemon->notify_completed (daemon->notify_completed_cls,
2418  connection,
2419  &connection->client_context,
2421  connection->client_aware = MHD_NO;
2422  end =
2425  connection->client_context = NULL;
2426  connection->continue_message_write_offset = 0;
2427  connection->responseCode = 0;
2428  connection->headers_received = NULL;
2429  connection->headers_received_tail = NULL;
2430  connection->response_write_position = 0;
2431  connection->have_chunked_upload = MHD_NO;
2432  connection->method = NULL;
2433  connection->url = NULL;
2434  connection->write_buffer = NULL;
2435  connection->write_buffer_size = 0;
2436  connection->write_buffer_send_offset = 0;
2437  connection->write_buffer_append_offset = 0;
2438  if ( (rend) || ((end != NULL) && (0 == strcasecmp (end, "close"))) )
2439  {
2440  connection->read_closed = MHD_YES;
2441  connection->read_buffer_offset = 0;
2442  }
2443  if (((MHD_YES == connection->read_closed) &&
2444  (0 == connection->read_buffer_offset)) ||
2445  (connection->version == NULL) ||
2446  (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
2447  {
2448  /* http 1.0, version-less requests cannot be pipelined */
2450  MHD_pool_destroy (connection->pool);
2451  connection->pool = NULL;
2452  connection->read_buffer = NULL;
2453  connection->read_buffer_size = 0;
2454  connection->read_buffer_offset = 0;
2455  }
2456  else
2457  {
2458  connection->version = NULL;
2459  connection->state = MHD_CONNECTION_INIT;
2460  connection->read_buffer
2461  = MHD_pool_reset (connection->pool,
2462  connection->read_buffer,
2463  connection->read_buffer_size);
2464  }
2465  continue;
2466  case MHD_CONNECTION_CLOSED:
2467  cleanup_connection (connection);
2468  return MHD_NO;
2469  default:
2470  EXTRA_CHECK (0);
2471  break;
2472  }
2473  break;
2474  }
2475  timeout = connection->connection_timeout;
2476  if ( (timeout != 0) &&
2477  (timeout <= (MHD_monotonic_time() - connection->last_activity)) )
2478  {
2480  connection->in_idle = MHD_NO;
2481  return MHD_YES;
2482  }
2484 #if EPOLL_SUPPORT
2485  switch (connection->event_loop_info)
2486  {
2488  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2489  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2490  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2491  {
2492  EDLL_insert (daemon->eready_head,
2493  daemon->eready_tail,
2494  connection);
2495  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2496  }
2497  break;
2499  if ( (connection->read_buffer_size > connection->read_buffer_offset) &&
2500  (0 != (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2501  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2502  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2503  {
2504  EDLL_insert (daemon->eready_head,
2505  daemon->eready_tail,
2506  connection);
2507  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2508  }
2509  if ( (0 != (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) &&
2510  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2511  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL)) )
2512  {
2513  EDLL_insert (daemon->eready_head,
2514  daemon->eready_tail,
2515  connection);
2516  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2517  }
2518  break;
2520  /* we should look at this connection again in the next iteration
2521  of the event loop, as we're waiting on the application */
2522  if ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EREADY_EDLL) &&
2523  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED))) )
2524  {
2525  EDLL_insert (daemon->eready_head,
2526  daemon->eready_tail,
2527  connection);
2528  connection->epoll_state |= MHD_EPOLL_STATE_IN_EREADY_EDLL;
2529  }
2530  break;
2532  /* This connection is finished, nothing left to do */
2533  break;
2534  }
2535  return MHD_connection_epoll_update_ (connection);
2536 #else
2537  return MHD_YES;
2538 #endif
2539 }
2540 
2541 
2542 #if EPOLL_SUPPORT
2543 
2551 int
2552 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
2553 {
2554  struct MHD_Daemon *daemon = connection->daemon;
2555 
2556  if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) &&
2557  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
2558  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
2559  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY)) ||
2560  ( (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) &&
2561  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) ||
2562  (connection->read_buffer_size > connection->read_buffer_offset) ) &&
2563  (MHD_NO == connection->read_closed) ) ) )
2564  {
2565  /* add to epoll set */
2566  struct epoll_event event;
2567 
2568  event.events = EPOLLIN | EPOLLOUT | EPOLLET;
2569  event.data.ptr = connection;
2570  if (0 != epoll_ctl (daemon->epoll_fd,
2571  EPOLL_CTL_ADD,
2572  connection->socket_fd,
2573  &event))
2574  {
2575 #if HAVE_MESSAGES
2576  if (0 != (daemon->options & MHD_USE_DEBUG))
2577  MHD_DLOG (daemon,
2578  "Call to epoll_ctl failed: %s\n",
2579  STRERROR (errno));
2580 #endif
2581  connection->state = MHD_CONNECTION_CLOSED;
2582  cleanup_connection (connection);
2583  return MHD_NO;
2584  }
2585  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
2586  }
2587  connection->in_idle = MHD_NO;
2588  return MHD_YES;
2589 }
2590 #endif
2591 
2592 
2598 void
2600 {
2604 }
2605 
2606 
2617 const union MHD_ConnectionInfo *
2619  enum MHD_ConnectionInfoType info_type, ...)
2620 {
2621  switch (info_type)
2622  {
2623 #if HTTPS_SUPPORT
2625  if (connection->tls_session == NULL)
2626  return NULL;
2627  connection->cipher = gnutls_cipher_get (connection->tls_session);
2628  return (const union MHD_ConnectionInfo *) &connection->cipher;
2630  if (connection->tls_session == NULL)
2631  return NULL;
2632  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
2633  return (const union MHD_ConnectionInfo *) &connection->protocol;
2635  if (connection->tls_session == NULL)
2636  return NULL;
2637  return (const union MHD_ConnectionInfo *) &connection->tls_session;
2638 #endif
2640  return (const union MHD_ConnectionInfo *) &connection->addr;
2642  return (const union MHD_ConnectionInfo *) &connection->daemon;
2644  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
2645  default:
2646  return NULL;
2647  };
2648 }
2649 
2650 
2660 int
2662  enum MHD_CONNECTION_OPTION option,
2663  ...)
2664 {
2665  va_list ap;
2666  struct MHD_Daemon *daemon;
2667 
2668  daemon = connection->daemon;
2669  switch (option)
2670  {
2672  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2673  (0 != pthread_mutex_lock (&daemon->cleanup_connection_mutex)) )
2674  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2675  if (connection->connection_timeout == daemon->connection_timeout)
2677  daemon->normal_timeout_tail,
2678  connection);
2679  else
2681  daemon->manual_timeout_tail,
2682  connection);
2683  va_start (ap, option);
2684  connection->connection_timeout = va_arg (ap, unsigned int);
2685  va_end (ap);
2686  if (connection->connection_timeout == daemon->connection_timeout)
2688  daemon->normal_timeout_tail,
2689  connection);
2690  else
2692  daemon->manual_timeout_tail,
2693  connection);
2694  if ( (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
2695  (0 != pthread_mutex_unlock (&daemon->cleanup_connection_mutex)) )
2696  MHD_PANIC ("Failed to release cleanup mutex\n");
2697  return MHD_YES;
2698  default:
2699  return MHD_NO;
2700  }
2701 }
2702 
2703 
2715 int
2717  unsigned int status_code, struct MHD_Response *response)
2718 {
2719  if ( (NULL == connection) ||
2720  (NULL == response) ||
2721  (NULL != connection->response) ||
2722  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
2723  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
2724  return MHD_NO;
2725  MHD_increment_response_rc (response);
2726  connection->response = response;
2727  connection->responseCode = status_code;
2728  if ( (NULL != connection->method) &&
2729  (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)) )
2730  {
2731  /* if this is a "HEAD" request, pretend that we
2732  have already sent the full message body */
2733  connection->response_write_position = response->total_size;
2734  }
2735  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
2736  (NULL != connection->method) &&
2737  ( (0 == strcasecmp (connection->method,
2739  (0 == strcasecmp (connection->method,
2740  MHD_HTTP_METHOD_PUT))) )
2741  {
2742  /* response was queued "early", refuse to read body / footers or
2743  further requests! */
2744  connection->read_closed = MHD_YES;
2745  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2746  }
2747  if (MHD_NO == connection->in_idle)
2748  (void) MHD_connection_handle_idle (connection);
2749  return MHD_YES;
2750 }
2751 
2752 
2753 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:1631
#define MHD_HTTP_REQUEST_ENTITY_TOO_LARGE
Definition: microhttpd.h:224
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1172
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1139
void * unescape_callback_cls
Definition: internal.h:1017
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:284
#define XDLL_insert(head, tail, element)
Definition: internal.h:1288
uint64_t total_size
Definition: internal.h:290
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:325
pthread_mutex_t cleanup_connection_mutex
Definition: internal.h:1080
void * mhd_panic_cls
Definition: daemon.c:129
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:337
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:801
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:832
enum MHD_CONNECTION_STATE state
Definition: internal.h:748
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:806
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:392
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:681
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:130
#define HTTP_100_CONTINUE
Definition: connection.c:44
#define MHD_ICY_FLAG
Definition: microhttpd.h:258
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:753
#define MHD_BUF_INC_SIZE
Definition: internal.h:60
int MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:1916
#define EXTRA_CHECK(a)
Definition: internal.h:1235
#define DLL_remove(head, tail, element)
Definition: internal.h:1266
pthread_mutex_t mutex
Definition: internal.h:285
Methods for managing connections.
MHD_CONNECTION_STATE
Definition: internal.h:341
char * version
Definition: internal.h:597
#define INTERNAL_ERROR
Definition: connection.c:94
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:289
static int connection_add_header(struct MHD_Connection *connection, char *key, char *value, enum MHD_ValueKind kind)
Definition: connection.c:1029
#define MHD_YES
Definition: microhttpd.h:129
struct MHD_Response * response
Definition: internal.h:559
char * colon
Definition: internal.h:626
#define REQUEST_LACKS_HOST
Definition: connection.c:69
char * write_buffer
Definition: internal.h:611
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:958
MHD_RequestTerminationCode
Definition: microhttpd.h:875
size_t data_size
Definition: internal.h:306
static int do_read(struct MHD_Connection *connection)
Definition: connection.c:1500
int have_chunked_upload
Definition: internal.h:777
enum MHD_ValueKind kind
Definition: internal.h:239
struct MHD_HTTP_Header * first_header
Definition: internal.h:255
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:784
MHD_AccessHandlerCallback default_handler
Definition: internal.h:891
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:154
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:1286
uint64_t remaining_upload_size
Definition: internal.h:674
unsigned int responseCode
Definition: internal.h:759
char * value
Definition: internal.h:233
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:2067
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:169
void * uri_log_callback_cls
Definition: internal.h:1007
unsigned int current_chunk_offset
Definition: internal.h:791
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:796
struct MHD_Daemon * daemon
Definition: internal.h:544
struct MHD_Connection * manual_timeout_head
Definition: internal.h:965
struct MHD_Connection * cleanup_head
Definition: internal.h:921
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:283
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:290
int client_aware
Definition: internal.h:711
struct MHD_Connection * cleanup_tail
Definition: internal.h:926
int MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:1854
size_t data_buffer_size
Definition: internal.h:311
MHD_CONNECTION_OPTION
Definition: microhttpd.h:2172
size_t write_buffer_send_offset
Definition: internal.h:662
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:197
static void get_date_string(char *date)
Definition: connection.c:592
union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:2618
return NULL
Definition: tsearch.c:30
size_t read_buffer_size
Definition: internal.h:646
void * client_context
Definition: internal.h:579
#define MHD_MIN(a, b)
Definition: internal.h:50
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:971
size_t continue_message_write_offset
Definition: internal.h:687
#define REQUEST_MALFORMED
Definition: connection.c:82
internal shared structures
static void add_extra_headers(struct MHD_Connection *connection)
Definition: connection.c:493
char * method
Definition: internal.h:585
time_t MHD_monotonic_time(void)
Definition: internal.c:169
LogCallback uri_log_callback
Definition: internal.h:1002
void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:444
int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:2661
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:473
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:155
char * last
Definition: internal.h:618
struct MHD_Connection * normal_timeout_head
Definition: internal.h:952
MHD_ValueKind
Definition: microhttpd.h:829
char * read_buffer
Definition: internal.h:605
ReceiveCallback recv_cls
Definition: internal.h:811
static void update_last_activity(struct MHD_Connection *connection)
Definition: connection.c:1821
char * url
Definition: internal.h:591
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:236
size_t write_buffer_size
Definition: internal.h:657
static char * get_next_header_line(struct MHD_Connection *connection)
Definition: connection.c:978
const char * MHD_get_reason_phrase_for(unsigned int code)
MHD_ConnectionInfoType
Definition: microhttpd.h:977
uint64_t data_start
Definition: internal.h:296
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:328
UnescapeCallback unescape_callback
Definition: internal.h:1012
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:629
int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:2716
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t size)
Definition: memorypool.c:251
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:211
static int parse_initial_message_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:1235
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:901
size_t pool_size
Definition: internal.h:1050
char * header
Definition: internal.h:228
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:1603
time_t last_activity
Definition: internal.h:698
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2116
unsigned int connection_timeout
Definition: internal.h:704
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:1671
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:286
#define MHD_PANIC(msg)
Definition: internal.h:86
struct MemoryPool * pool
Definition: internal.h:571
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:340
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:1744
size_t write_buffer_append_offset
Definition: internal.h:668
unsigned int current_chunk_size
Definition: internal.h:785
struct MHD_HTTP_Header * next
Definition: internal.h:222
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:988
enum MHD_OPTION options
Definition: internal.h:1138
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:275
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:2599
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:343
void * notify_completed_cls
Definition: internal.h:993
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:1320
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:327
TransmitCallback send_cls
Definition: internal.h:816
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:1307
#define DLL_insert(head, tail, element)
Definition: internal.h:1247
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:239
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:156
MHD_ContentReaderCallback crc
Definition: internal.h:273
void * crc_cls
Definition: internal.h:267
struct sockaddr * addr
Definition: internal.h:632
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:916
MHD_PanicCallback mhd_panic
Definition: daemon.c:124
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:180
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:278
static int parse_arguments(enum MHD_ValueKind kind, struct MHD_Connection *connection, char *args)
Definition: connection.c:1058
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:148
char * data
Definition: internal.h:261
static int do_write(struct MHD_Connection *connection)
Definition: connection.c:1551
size_t read_buffer_offset
Definition: internal.h:652
#define MHD_NO
Definition: microhttpd.h:134
unsigned int connection_timeout
Definition: internal.h:1127
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:225
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:308
struct MHD_HTTP_Header * headers_received
Definition: internal.h:549
struct MHD_Connection * connections_tail
Definition: internal.h:906
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:310
#define EDLL_insert(head, tail, element)
Definition: internal.h:1328
void MHD_connection_close(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:261
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:554
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:660
size_t pool_increment
Definition: internal.h:1055
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:342
struct MHD_Connection * suspended_connections_head
Definition: internal.h:911
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...