GNU libmicrohttpd  0.9.5
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  (C) 2007, 2008, 2009, 2010, 2011, 2012 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 
43 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
44 
52 #if HAVE_MESSAGES
53 #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>"
54 #else
55 #define REQUEST_TOO_BIG ""
56 #endif
57 
65 #if HAVE_MESSAGES
66 #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>"
67 #else
68 #define REQUEST_LACKS_HOST ""
69 #endif
70 
78 #if HAVE_MESSAGES
79 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
80 #else
81 #define REQUEST_MALFORMED ""
82 #endif
83 
90 #if HAVE_MESSAGES
91 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
92 #else
93 #define INTERNAL_ERROR ""
94 #endif
95 
100 #define DEBUG_CLOSE MHD_NO
101 
105 #define DEBUG_SEND_DATA MHD_NO
106 
107 
118 int
120  enum MHD_ValueKind kind,
121  MHD_KeyValueIterator iterator, void *iterator_cls)
122 {
123  int ret;
124  struct MHD_HTTP_Header *pos;
125 
126  if (NULL == connection)
127  return -1;
128  ret = 0;
129  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
130  if (0 != (pos->kind & kind))
131  {
132  ret++;
133  if ((NULL != iterator) &&
134  (MHD_YES != iterator (iterator_cls,
135  kind, pos->header, pos->value)))
136  return ret;
137  }
138  return ret;
139 }
140 
141 
171 int
173  enum MHD_ValueKind kind,
174  const char *key, const char *value)
175 {
176  struct MHD_HTTP_Header *pos;
177 
178  pos = MHD_pool_allocate (connection->pool,
179  sizeof (struct MHD_HTTP_Header), MHD_NO);
180  if (NULL == pos)
181  return MHD_NO;
182  pos->header = (char *) key;
183  pos->value = (char *) value;
184  pos->kind = kind;
185  pos->next = NULL;
186  /* append 'pos' to the linked list of headers */
187  if (NULL == connection->headers_received_tail)
188  {
189  connection->headers_received = pos;
190  connection->headers_received_tail = pos;
191  }
192  else
193  {
194  connection->headers_received_tail->next = pos;
195  connection->headers_received_tail = pos;
196  }
197  return MHD_YES;
198 }
199 
200 
210 const char *
212  enum MHD_ValueKind kind, const char *key)
213 {
214  struct MHD_HTTP_Header *pos;
215 
216  if (NULL == connection)
217  return NULL;
218  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
219  if ((0 != (pos->kind & kind)) &&
220  ( (key == pos->header) ||
221  ( (NULL != pos->header) &&
222  (NULL != key) &&
223  (0 == strcasecmp (key, pos->header))) ))
224  return pos->value;
225  return NULL;
226 }
227 
228 
239 int
240 MHD_queue_response (struct MHD_Connection *connection,
241  unsigned int status_code, struct MHD_Response *response)
242 {
243  if ( (NULL == connection) ||
244  (NULL == response) ||
245  (NULL != connection->response) ||
246  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
247  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
248  return MHD_NO;
249  MHD_increment_response_rc (response);
250  connection->response = response;
251  connection->responseCode = status_code;
252  if ( (NULL != connection->method) &&
253  (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)) )
254  {
255  /* if this is a "HEAD" request, pretend that we
256  have already sent the full message body */
257  connection->response_write_position = response->total_size;
258  }
259  if (MHD_CONNECTION_HEADERS_PROCESSED == connection->state)
260  {
261  /* response was queued "early",
262  refuse to read body / footers or further
263  requests! */
264  (void) SHUTDOWN (connection->socket_fd, SHUT_RD);
265  connection->read_closed = MHD_YES;
267  }
268  return MHD_YES;
269 }
270 
271 
279 static int
280 need_100_continue (struct MHD_Connection *connection)
281 {
282  const char *expect;
283 
284  return ( (NULL == connection->response) &&
285  (NULL != connection->version) &&
286  (0 == strcasecmp (connection->version,
288  (NULL != (expect = MHD_lookup_connection_value (connection,
291  (0 == strcasecmp (expect, "100-continue")) &&
292  (connection->continue_message_write_offset <
293  strlen (HTTP_100_CONTINUE)) );
294 }
295 
296 
304 void
306  enum MHD_RequestTerminationCode termination_code)
307 {
308  struct MHD_Daemon *daemon;
309 
310  daemon = connection->daemon;
311  SHUTDOWN (connection->socket_fd,
312  (connection->read_closed == MHD_YES) ? SHUT_WR : SHUT_RDWR);
313  connection->state = MHD_CONNECTION_CLOSED;
314  if ( (NULL != daemon->notify_completed) &&
315  (MHD_YES == connection->client_aware) )
316  daemon->notify_completed (daemon->notify_completed_cls,
317  connection,
318  &connection->client_context,
319  termination_code);
320  connection->client_aware = MHD_NO;
321 }
322 
323 
331 static void
333  const char *emsg)
334 {
335 #if HAVE_MESSAGES
336  if (NULL != emsg)
337  MHD_DLOG (connection->daemon, emsg);
338 #endif
340 }
341 
342 
347 #if HAVE_MESSAGES
348 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
349 #else
350 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
351 #endif
352 
353 
364 static int
366 {
367  int ret;
368  struct MHD_Response *response;
369 
370  response = connection->response;
371  if (NULL == response->crc)
372  return MHD_YES;
373  if ( (response->data_start <=
374  connection->response_write_position) &&
375  (response->data_size + response->data_start >
376  connection->response_write_position) )
377  return MHD_YES; /* response already ready */
378 #if LINUX
379  if ( (-1 != response->fd) &&
380  (0 == (connection->daemon->options & MHD_USE_SSL)) )
381  {
382  /* will use sendfile, no need to bother response crc */
383  return MHD_YES;
384  }
385 #endif
386 
387  ret = response->crc (response->crc_cls,
388  connection->response_write_position,
389  response->data,
390  MHD_MIN (response->data_buffer_size,
391  response->total_size -
392  connection->response_write_position));
393  if ((0 == ret) &&
394  (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY)))
395  mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
396 #if HAVE_MESSAGES
397  "API violation"
398 #else
399  NULL
400 #endif
401  );
402  if ( (MHD_CONTENT_READER_END_OF_STREAM == ret) ||
404  {
405  /* either error or http 1.0 transfer, close socket! */
406  response->total_size = connection->response_write_position;
407  CONNECTION_CLOSE_ERROR (connection,
409  ? "Closing connection (end of response)\n"
410  : "Closing connection (stream error)\n");
411  return MHD_NO;
412  }
413  response->data_start = connection->response_write_position;
414  response->data_size = ret;
415  if (0 == ret)
416  {
418  return MHD_NO;
419  }
420  return MHD_YES;
421 }
422 
423 
433 static int
435 {
436  int ret;
437  char *buf;
438  struct MHD_Response *response;
439  size_t size;
440  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
441  int cblen;
442 
443  response = connection->response;
444  if (0 == connection->write_buffer_size)
445  {
446  size = connection->daemon->pool_size;
447  do
448  {
449  size /= 2;
450  if (size < 128)
451  {
452  /* not enough memory */
453  CONNECTION_CLOSE_ERROR (connection,
454  "Closing connection (out of memory)\n");
455  return MHD_NO;
456  }
457  buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
458  }
459  while (NULL == buf);
460  connection->write_buffer_size = size;
461  connection->write_buffer = buf;
462  }
463 
464  if ( (response->data_start <=
465  connection->response_write_position) &&
466  (response->data_size + response->data_start >
467  connection->response_write_position) )
468  {
469  /* buffer already ready, use what is there for the chunk */
470  ret = response->data_size + response->data_start - connection->response_write_position;
471  if (ret > connection->write_buffer_size - sizeof (cbuf) - 2)
472  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
473  memcpy (&connection->write_buffer[sizeof (cbuf)],
474  &response->data[connection->response_write_position - response->data_start],
475  ret);
476  }
477  else
478  {
479  /* buffer not in range, try to fill it */
480  ret = response->crc (response->crc_cls,
481  connection->response_write_position,
482  &connection->write_buffer[sizeof (cbuf)],
483  connection->write_buffer_size - sizeof (cbuf) - 2);
484  }
486  {
487  /* error, close socket! */
488  response->total_size = connection->response_write_position;
489  CONNECTION_CLOSE_ERROR (connection,
490  "Closing connection (error generating response)\n");
491  return MHD_NO;
492  }
494  {
495  /* end of message, signal other side! */
496  strcpy (connection->write_buffer, "0\r\n");
497  connection->write_buffer_append_offset = 3;
498  connection->write_buffer_send_offset = 0;
499  response->total_size = connection->response_write_position;
500  return MHD_YES;
501  }
502  if (0 == ret)
503  {
505  return MHD_NO;
506  }
507  if (ret > 0xFFFFFF)
508  ret = 0xFFFFFF;
509  snprintf (cbuf,
510  sizeof (cbuf),
511  "%X\r\n", ret);
512  cblen = strlen (cbuf);
513  EXTRA_CHECK (cblen <= sizeof (cbuf));
514  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
515  memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
516  connection->response_write_position += ret;
517  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
518  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
519  return MHD_YES;
520 }
521 
522 
529 static void
530 add_extra_headers (struct MHD_Connection *connection)
531 {
532  const char *have;
533  char buf[128];
534 
535  connection->have_chunked_upload = MHD_NO;
536  if (MHD_SIZE_UNKNOWN == connection->response->total_size)
537  {
538  have = MHD_get_response_header (connection->response,
540  if ((NULL == have) || (0 != strcasecmp (have, "close")))
541  {
542  if ((NULL != connection->version) &&
543  (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
544  {
545  connection->have_chunked_upload = MHD_YES;
546  have = MHD_get_response_header (connection->response,
548  if (NULL == have)
549  MHD_add_response_header (connection->response,
551  "chunked");
552  }
553  else
554  {
555  MHD_add_response_header (connection->response,
556  MHD_HTTP_HEADER_CONNECTION, "close");
557  }
558  }
559  }
560  else if (NULL == MHD_get_response_header (connection->response,
562  {
563  SPRINTF (buf,
564  "%" MHD_LONG_LONG_PRINTF "u",
565  (unsigned MHD_LONG_LONG) connection->response->total_size);
566  MHD_add_response_header (connection->response,
568  }
569 }
570 
571 
578 static void
579 get_date_string (char *date)
580 {
581  static const char *days[] =
582  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
583  static const char *mons[] =
584  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
585  "Nov", "Dec"
586  };
587  struct tm now;
588  time_t t;
589 
590  time (&t);
591  gmtime_r (&t, &now);
592  SPRINTF (date,
593  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
594  days[now.tm_wday % 7],
595  now.tm_mday,
596  mons[now.tm_mon % 12],
597  1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
598 }
599 
600 
607 static int
609 {
610  void *buf;
611 
612  buf = MHD_pool_reallocate (connection->pool,
613  connection->read_buffer,
614  connection->read_buffer_size,
615  connection->read_buffer_size * 2 +
616  MHD_BUF_INC_SIZE + 1);
617  if (NULL == buf)
618  return MHD_NO;
619  /* we can actually grow the buffer, do it! */
620  connection->read_buffer = buf;
621  connection->read_buffer_size =
622  connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
623  return MHD_YES;
624 }
625 
626 
634 static int
636 {
637  size_t size;
638  size_t off;
639  struct MHD_HTTP_Header *pos;
640  char code[256];
641  char date[128];
642  char *data;
643  enum MHD_ValueKind kind;
644  const char *reason_phrase;
645  uint32_t rc;
646  int must_add_close;
647 
648  EXTRA_CHECK (NULL != connection->version);
649  if (0 == strlen(connection->version))
650  {
651  data = MHD_pool_allocate (connection->pool, 0, MHD_YES);
652  connection->write_buffer = data;
653  connection->write_buffer_append_offset = 0;
654  connection->write_buffer_send_offset = 0;
655  connection->write_buffer_size = 0;
656  return MHD_YES;
657  }
658  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
659  {
660  add_extra_headers (connection);
661  rc = connection->responseCode & (~MHD_ICY_FLAG);
662  reason_phrase = MHD_get_reason_phrase_for (rc);
663  SPRINTF (code,
664  "%s %u %s\r\n",
665  (0 != (connection->responseCode & MHD_ICY_FLAG))
666  ? "ICY"
667  : ( (0 == strcasecmp (MHD_HTTP_VERSION_1_0,
668  connection->version))
671  rc,
672  reason_phrase);
673  off = strlen (code);
674  /* estimate size */
675  size = off + 2; /* extra \r\n at the end */
676  kind = MHD_HEADER_KIND;
677  if ( (0 == (connection->daemon->options & MHD_SUPPRESS_DATE_NO_CLOCK)) &&
678  (NULL == MHD_get_response_header (connection->response,
680  get_date_string (date);
681  else
682  date[0] = '\0';
683  size += strlen (date);
684  }
685  else
686  {
687  size = 2;
688  kind = MHD_FOOTER_KIND;
689  off = 0;
690  }
691  must_add_close = ( (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED) &&
692  (connection->read_closed == MHD_YES) &&
693  (0 == strcasecmp (connection->version,
695  (NULL == MHD_get_response_header (connection->response,
697  if (must_add_close)
698  size += strlen ("Connection: close\r\n");
699  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
700  if (pos->kind == kind)
701  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
702  /* produce data */
703  data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
704  if (NULL == data)
705  {
706 #if HAVE_MESSAGES
707  MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
708 #endif
709  return MHD_NO;
710  }
711  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
712  {
713  memcpy (data, code, off);
714  }
715  if (must_add_close)
716  {
717  /* we must add the 'close' header because circumstances forced us to
718  stop reading from the socket; however, we are not adding the header
719  to the response as the response may be used in a different context
720  as well */
721  memcpy (&data[off], "Connection: close\r\n",
722  strlen ("Connection: close\r\n"));
723  off += strlen ("Connection: close\r\n");
724  }
725  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
726  if (pos->kind == kind)
727  off += SPRINTF (&data[off],
728  "%s: %s\r\n",
729  pos->header,
730  pos->value);
731  if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
732  {
733  strcpy (&data[off], date);
734  off += strlen (date);
735  }
736  memcpy (&data[off], "\r\n", 2);
737  off += 2;
738 
739  if (off != size)
740  mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
741  connection->write_buffer = data;
742  connection->write_buffer_append_offset = size;
743  connection->write_buffer_send_offset = 0;
744  connection->write_buffer_size = size + 1;
745  return MHD_YES;
746 }
747 
748 
758 static void
760  unsigned int status_code,
761  const char *message)
762 {
763  struct MHD_Response *response;
764 
765  if (NULL == connection->version)
766  {
767  /* we were unable to process the full header line, so we don't
768  really know what version the client speaks; assume 1.0 */
769  connection->version = MHD_HTTP_VERSION_1_0;
770  }
772  connection->read_closed = MHD_YES;
773 #if HAVE_MESSAGES
774  MHD_DLOG (connection->daemon,
775  "Error %u (`%s') processing request, closing connection.\n",
776  status_code, message);
777 #endif
778  EXTRA_CHECK (connection->response == NULL);
779  response = MHD_create_response_from_buffer (strlen (message),
780  (void *) message,
782  MHD_queue_response (connection, status_code, response);
783  EXTRA_CHECK (connection->response != NULL);
784  MHD_destroy_response (response);
785  if (MHD_NO == build_header_response (connection))
786  {
787  /* oops - close! */
788  CONNECTION_CLOSE_ERROR (connection,
789  "Closing connection (failed to create response header)\n");
790  }
791  else
792  {
794  }
795 }
796 
797 
806 static void
808  fd_set *set,
809  int *max_fd)
810 {
811  FD_SET (fd, set);
812  if ( (NULL != max_fd) &&
813  (fd > *max_fd) )
814  *max_fd = fd;
815 }
816 
817 
830 int
832  fd_set *read_fd_set,
833  fd_set *write_fd_set,
834  fd_set *except_fd_set,
835  int *max_fd)
836 {
837  int ret;
838  struct MHD_Pollfd p;
839 
840  /* we use the 'poll fd' as a convenient way to re-use code
841  when determining the select sets */
842  memset (&p, 0, sizeof(struct MHD_Pollfd));
843  ret = MHD_connection_get_pollfd (connection, &p);
844  if ( (MHD_YES == ret) && (p.fd >= 0) ) {
845  if (0 != (p.events & MHD_POLL_ACTION_IN))
846  add_to_fd_set(p.fd, read_fd_set, max_fd);
847  if (0 != (p.events & MHD_POLL_ACTION_OUT))
848  add_to_fd_set(p.fd, write_fd_set, max_fd);
849  }
850  return ret;
851 }
852 
853 
862 int
864  struct MHD_Pollfd *p)
865 {
866  int fd;
867 
868  if (NULL == connection->pool)
869  connection->pool = MHD_pool_create (connection->daemon->pool_size);
870  if (NULL == connection->pool)
871  {
872  CONNECTION_CLOSE_ERROR (connection,
873  "Failed to create memory pool!\n");
874  return MHD_YES;
875  }
876  fd = connection->socket_fd;
877  p->fd = fd;
878  if (-1 == fd)
879  return MHD_YES;
880  while (1)
881  {
882 #if DEBUG_STATES
883  MHD_DLOG (connection->daemon, "%s: state: %s\n",
884  __FUNCTION__, MHD_state_to_string (connection->state));
885 #endif
886  switch (connection->state)
887  {
888 #if HTTPS_SUPPORT
890  if (0 == gnutls_record_get_direction (connection->tls_session))
892  else
894  break;
895 #endif
896  case MHD_CONNECTION_INIT:
899  /* while reading headers, we always grow the
900  read buffer if needed, no size-check required */
901  if ((connection->read_closed) &&
902  (0 == connection->read_buffer_offset))
903  {
904  CONNECTION_CLOSE_ERROR (connection,
905  "Connection buffer to small for request\n");
906  continue;
907  }
908  if ((connection->read_buffer_offset == connection->read_buffer_size)
909  && (MHD_NO == try_grow_read_buffer (connection)))
910  {
911  transmit_error_response (connection,
912  (connection->url != NULL)
916  continue;
917  }
918  if (MHD_NO == connection->read_closed)
920  break;
922  /* we should never get here */
923  EXTRA_CHECK (0);
924  break;
926  EXTRA_CHECK (0);
927  break;
930  break;
932  if (connection->read_buffer_offset == connection->read_buffer_size)
933  {
934  if ((MHD_YES != try_grow_read_buffer (connection)) &&
935  (0 != (connection->daemon->options &
938  {
939  /* failed to grow the read buffer, and the
940  client which is supposed to handle the
941  received data in a *blocking* fashion
942  (in this mode) did not handle the data as
943  it was supposed to!
944  => we would either have to do busy-waiting
945  (on the client, which would likely fail),
946  or if we do nothing, we would just timeout
947  on the connection (if a timeout is even
948  set!).
949  Solution: we kill the connection with an error */
950  transmit_error_response (connection,
953  continue;
954  }
955  }
956  if ((connection->read_buffer_offset < connection->read_buffer_size)
957  && (MHD_NO == connection->read_closed))
959  break;
962  /* while reading footers, we always grow the
963  read buffer if needed, no size-check required */
964  if (MHD_YES == connection->read_closed)
965  {
966  CONNECTION_CLOSE_ERROR (connection,
967  NULL);
968  continue;
969  }
971  /* transition to FOOTERS_RECEIVED
972  happens in read handler */
973  break;
975  /* no socket action, wait for client
976  to provide response */
977  break;
979  /* headers in buffer, keep writing */
981  break;
983  EXTRA_CHECK (0);
984  break;
987  break;
989  /* not ready, no socket action */
990  break;
993  break;
995  /* not ready, no socket action */
996  break;
998  EXTRA_CHECK (0);
999  break;
1002  break;
1004  EXTRA_CHECK (0);
1005  break;
1006  case MHD_CONNECTION_CLOSED:
1007  return MHD_YES; /* do nothing, not even reading */
1008  default:
1009  EXTRA_CHECK (0);
1010  }
1011  break;
1012  }
1013  return MHD_YES;
1014 }
1015 
1016 
1025 static char *
1027 {
1028  char *rbuf;
1029  size_t pos;
1030 
1031  if (0 == connection->read_buffer_offset)
1032  return NULL;
1033  pos = 0;
1034  rbuf = connection->read_buffer;
1035  while ((pos < connection->read_buffer_offset - 1) &&
1036  ('\r' != rbuf[pos]) && ('\n' != rbuf[pos]))
1037  pos++;
1038  if (pos == connection->read_buffer_offset - 1)
1039  {
1040  /* not found, consider growing... */
1041  if (connection->read_buffer_offset == connection->read_buffer_size)
1042  {
1043  rbuf = MHD_pool_reallocate (connection->pool,
1044  connection->read_buffer,
1045  connection->read_buffer_size,
1046  connection->read_buffer_size * 2 +
1048  if (NULL == rbuf)
1049  {
1050  transmit_error_response (connection,
1051  (NULL != connection->url)
1054  REQUEST_TOO_BIG);
1055  }
1056  else
1057  {
1058  connection->read_buffer_size =
1059  connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
1060  connection->read_buffer = rbuf;
1061  }
1062  }
1063  return NULL;
1064  }
1065  /* found, check if we have proper CRLF */
1066  if (('\r' == rbuf[pos]) && ('\n' == rbuf[pos + 1]))
1067  rbuf[pos++] = '\0'; /* skip both r and n */
1068  rbuf[pos++] = '\0';
1069  connection->read_buffer += pos;
1070  connection->read_buffer_size -= pos;
1071  connection->read_buffer_offset -= pos;
1072  return rbuf;
1073 }
1074 
1075 
1087 static int
1089  char *key, char *value, enum MHD_ValueKind kind)
1090 {
1091  if (MHD_NO == MHD_set_connection_value (connection,
1092  kind,
1093  key, value))
1094  {
1095 #if HAVE_MESSAGES
1096  MHD_DLOG (connection->daemon,
1097  "Not enough memory to allocate header record!\n");
1098 #endif
1100  REQUEST_TOO_BIG);
1101  return MHD_NO;
1102  }
1103  return MHD_YES;
1104 }
1105 
1106 
1116 static int
1118  struct MHD_Connection *connection,
1119  char *args)
1120 {
1121  char *equals;
1122  char *amper;
1123 
1124  while (NULL != args)
1125  {
1126  equals = strchr (args, '=');
1127  amper = strchr (args, '&');
1128  if (NULL == amper)
1129  {
1130  /* last argument */
1131  if (NULL == equals)
1132  {
1133  /* got 'foo', add key 'foo' with NULL for value */
1134  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1135  connection,
1136  args);
1137  return connection_add_header (connection,
1138  args,
1139  NULL,
1140  kind);
1141  }
1142  /* got 'foo=bar' */
1143  equals[0] = '\0';
1144  equals++;
1145  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1146  connection,
1147  args);
1148  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1149  connection,
1150  equals);
1151  return connection_add_header (connection, args, equals, kind);
1152  }
1153  /* amper is non-NULL here */
1154  amper[0] = '\0';
1155  amper++;
1156  if ( (NULL == equals) ||
1157  (equals >= amper) )
1158  {
1159  /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */
1160  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1161  connection,
1162  args);
1163  if (MHD_NO ==
1164  connection_add_header (connection,
1165  args,
1166  NULL,
1167  kind))
1168  return MHD_NO;
1169  /* continue with 'bar' */
1170  args = amper;
1171  continue;
1172 
1173  }
1174  /* equals and amper are non-NULL here, and equals < amper,
1175  so we got regular 'foo=value&bar...'-kind of argument */
1176  equals[0] = '\0';
1177  equals++;
1178  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1179  connection,
1180  args);
1181  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1182  connection,
1183  equals);
1184  if (MHD_NO == connection_add_header (connection, args, equals, kind))
1185  return MHD_NO;
1186  args = amper;
1187  }
1188  return MHD_YES;
1189 }
1190 
1191 
1197 static int
1199 {
1200  const char *hdr;
1201  char *cpy;
1202  char *pos;
1203  char *sce;
1204  char *semicolon;
1205  char *equals;
1206  char *ekill;
1207  char old;
1208  int quotes;
1209 
1210  hdr = MHD_lookup_connection_value (connection,
1213  if (hdr == NULL)
1214  return MHD_YES;
1215  cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
1216  if (cpy == NULL)
1217  {
1218 #if HAVE_MESSAGES
1219  MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
1220 #endif
1222  REQUEST_TOO_BIG);
1223  return MHD_NO;
1224  }
1225  memcpy (cpy, hdr, strlen (hdr) + 1);
1226  pos = cpy;
1227  while (pos != NULL)
1228  {
1229  while (*pos == ' ')
1230  pos++; /* skip spaces */
1231 
1232  sce = pos;
1233  while (((*sce) != '\0') &&
1234  ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
1235  sce++;
1236  /* remove tailing whitespace (if any) from key */
1237  ekill = sce - 1;
1238  while ((*ekill == ' ') && (ekill >= pos))
1239  *(ekill--) = '\0';
1240  old = *sce;
1241  *sce = '\0';
1242  if (old != '=')
1243  {
1244  /* value part omitted, use empty string... */
1245  if (MHD_NO ==
1246  connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
1247  return MHD_NO;
1248  if (old == '\0')
1249  break;
1250  pos = sce + 1;
1251  continue;
1252  }
1253  equals = sce + 1;
1254  quotes = 0;
1255  semicolon = equals;
1256  while ((semicolon[0] != '\0') &&
1257  ((quotes != 0) ||
1258  ((semicolon[0] != ';') && (semicolon[0] != ','))))
1259  {
1260  if (semicolon[0] == '"')
1261  quotes = (quotes + 1) & 1;
1262  semicolon++;
1263  }
1264  if (semicolon[0] == '\0')
1265  semicolon = NULL;
1266  if (semicolon != NULL)
1267  {
1268  semicolon[0] = '\0';
1269  semicolon++;
1270  }
1271  /* remove quotes */
1272  if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
1273  {
1274  equals[strlen (equals) - 1] = '\0';
1275  equals++;
1276  }
1277  if (MHD_NO == connection_add_header (connection,
1278  pos, equals, MHD_COOKIE_KIND))
1279  return MHD_NO;
1280  pos = semicolon;
1281  }
1282  return MHD_YES;
1283 }
1284 
1285 
1293 static int
1294 parse_initial_message_line (struct MHD_Connection *connection, char *line)
1295 {
1296  char *uri;
1297  char *httpVersion;
1298  char *args;
1299 
1300  if (NULL == (uri = strchr (line, ' ')))
1301  return MHD_NO; /* serious error */
1302  uri[0] = '\0';
1303  connection->method = line;
1304  uri++;
1305  while (uri[0] == ' ')
1306  uri++;
1307  httpVersion = strchr (uri, ' ');
1308  if (httpVersion != NULL)
1309  {
1310  httpVersion[0] = '\0';
1311  httpVersion++;
1312  }
1313  if (connection->daemon->uri_log_callback != NULL)
1314  connection->client_context
1315  =
1316  connection->daemon->uri_log_callback (connection->daemon->
1317  uri_log_callback_cls, uri);
1318  args = strchr (uri, '?');
1319  if (NULL != args)
1320  {
1321  args[0] = '\0';
1322  args++;
1323  parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
1324  }
1325  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1326  connection,
1327  uri);
1328  connection->url = uri;
1329  if (NULL == httpVersion)
1330  connection->version = "";
1331  else
1332  connection->version = httpVersion;
1333  return MHD_YES;
1334 }
1335 
1336 
1342 static void
1344 {
1345  size_t processed;
1346 
1347  if (NULL != connection->response)
1348  return; /* already queued a response */
1349  processed = 0;
1350  connection->client_aware = MHD_YES;
1351  if (MHD_NO ==
1352  connection->daemon->default_handler (connection->daemon->
1353  default_handler_cls,
1354  connection, connection->url,
1355  connection->method,
1356  connection->version,
1357  NULL, &processed,
1358  &connection->client_context))
1359  {
1360  /* serious internal error, close connection */
1361  CONNECTION_CLOSE_ERROR (connection,
1362  "Internal application error, closing connection.\n");
1363  return;
1364  }
1365 }
1366 
1367 
1368 
1374 static void
1376 {
1377  size_t processed;
1378  size_t available;
1379  size_t used;
1380  size_t i;
1381  int instant_retry;
1382  int malformed;
1383  char *buffer_head;
1384  char *end;
1385 
1386  if (NULL != connection->response)
1387  return; /* already queued a response */
1388 
1389  buffer_head = connection->read_buffer;
1390  available = connection->read_buffer_offset;
1391  do
1392  {
1393  instant_retry = MHD_NO;
1394  if ((connection->have_chunked_upload == MHD_YES) &&
1395  (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
1396  {
1397  if ((connection->current_chunk_offset ==
1398  connection->current_chunk_size)
1399  && (connection->current_chunk_offset != 0) && (available >= 2))
1400  {
1401  /* skip new line at the *end* of a chunk */
1402  i = 0;
1403  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1404  i++; /* skip 1st part of line feed */
1405  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1406  i++; /* skip 2nd part of line feed */
1407  if (i == 0)
1408  {
1409  /* malformed encoding */
1410  CONNECTION_CLOSE_ERROR (connection,
1411  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1412  return;
1413  }
1414  available -= i;
1415  buffer_head += i;
1416  connection->current_chunk_offset = 0;
1417  connection->current_chunk_size = 0;
1418  }
1419  if (connection->current_chunk_offset <
1420  connection->current_chunk_size)
1421  {
1422  /* we are in the middle of a chunk, give
1423  as much as possible to the client (without
1424  crossing chunk boundaries) */
1425  processed =
1426  connection->current_chunk_size -
1427  connection->current_chunk_offset;
1428  if (processed > available)
1429  processed = available;
1430  if (available > processed)
1431  instant_retry = MHD_YES;
1432  }
1433  else
1434  {
1435  /* we need to read chunk boundaries */
1436  i = 0;
1437  while (i < available)
1438  {
1439  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1440  break;
1441  i++;
1442  if (i >= 6)
1443  break;
1444  }
1445  /* take '\n' into account; if '\n'
1446  is the unavailable character, we
1447  will need to wait until we have it
1448  before going further */
1449  if ((i + 1 >= available) &&
1450  !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
1451  break; /* need more data... */
1452  malformed = (i >= 6);
1453  if (!malformed)
1454  {
1455  buffer_head[i] = '\0';
1456  connection->current_chunk_size = strtoul (buffer_head, &end, 16);
1457  malformed = ('\0' != *end);
1458  }
1459  if (malformed)
1460  {
1461  /* malformed encoding */
1462  CONNECTION_CLOSE_ERROR (connection,
1463  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1464  return;
1465  }
1466  i++;
1467  if ((i < available) &&
1468  ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
1469  i++; /* skip 2nd part of line feed */
1470 
1471  buffer_head += i;
1472  available -= i;
1473  connection->current_chunk_offset = 0;
1474 
1475  if (available > 0)
1476  instant_retry = MHD_YES;
1477  if (connection->current_chunk_size == 0)
1478  {
1479  connection->remaining_upload_size = 0;
1480  break;
1481  }
1482  continue;
1483  }
1484  }
1485  else
1486  {
1487  /* no chunked encoding, give all to the client */
1488  if ( (0 != connection->remaining_upload_size) &&
1489  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
1490  (connection->remaining_upload_size < available) )
1491  {
1492  processed = connection->remaining_upload_size;
1493  }
1494  else
1495  {
1500  processed = available;
1501  }
1502  }
1503  used = processed;
1504  connection->client_aware = MHD_YES;
1505  if (MHD_NO ==
1506  connection->daemon->default_handler (connection->daemon->
1507  default_handler_cls,
1508  connection, connection->url,
1509  connection->method,
1510  connection->version,
1511  buffer_head, &processed,
1512  &connection->client_context))
1513  {
1514  /* serious internal error, close connection */
1515  CONNECTION_CLOSE_ERROR (connection,
1516  "Internal application error, closing connection.\n");
1517  return;
1518  }
1519  if (processed > used)
1520  mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
1521 #if HAVE_MESSAGES
1522  "API violation"
1523 #else
1524  NULL
1525 #endif
1526  );
1527  if (processed != 0)
1528  instant_retry = MHD_NO; /* client did not process everything */
1529  used -= processed;
1530  if (connection->have_chunked_upload == MHD_YES)
1531  connection->current_chunk_offset += used;
1532  /* dh left "processed" bytes in buffer for next time... */
1533  buffer_head += used;
1534  available -= used;
1535  if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
1536  connection->remaining_upload_size -= used;
1537  }
1538  while (MHD_YES == instant_retry);
1539  if (available > 0)
1540  memmove (connection->read_buffer, buffer_head, available);
1541  connection->read_buffer_offset = available;
1542 }
1543 
1552 static int
1553 do_read (struct MHD_Connection *connection)
1554 {
1555  int bytes_read;
1556 
1557  if (connection->read_buffer_size == connection->read_buffer_offset)
1558  return MHD_NO;
1559 
1560  bytes_read = connection->recv_cls (connection,
1561  &connection->read_buffer
1562  [connection->read_buffer_offset],
1563  connection->read_buffer_size -
1564  connection->read_buffer_offset);
1565  if (bytes_read < 0)
1566  {
1567  if ((EINTR == errno) || (EAGAIN == errno))
1568  return MHD_NO;
1569 #if HAVE_MESSAGES
1570 #if HTTPS_SUPPORT
1571  if (0 != (connection->daemon->options & MHD_USE_SSL))
1572  MHD_DLOG (connection->daemon,
1573  "Failed to receive data: %s\n",
1574  gnutls_strerror (bytes_read));
1575  else
1576 #endif
1577  MHD_DLOG (connection->daemon,
1578  "Failed to receive data: %s\n", STRERROR (errno));
1579 #endif
1580  CONNECTION_CLOSE_ERROR (connection, NULL);
1581  return MHD_YES;
1582  }
1583  if (0 == bytes_read)
1584  {
1585  /* other side closed connection */
1586  connection->read_closed = MHD_YES;
1587  SHUTDOWN (connection->socket_fd, SHUT_RD);
1588  return MHD_YES;
1589  }
1590  connection->read_buffer_offset += bytes_read;
1591  return MHD_YES;
1592 }
1593 
1601 static int
1602 do_write (struct MHD_Connection *connection)
1603 {
1604  int ret;
1605 
1606  ret = connection->send_cls (connection,
1607  &connection->write_buffer
1608  [connection->write_buffer_send_offset],
1609  connection->write_buffer_append_offset
1610  - connection->write_buffer_send_offset);
1611 
1612  if (ret < 0)
1613  {
1614  if ((EINTR == errno) || (EAGAIN == errno))
1615  return MHD_NO;
1616 #if HAVE_MESSAGES
1617 #if HTTPS_SUPPORT
1618  if (0 != (connection->daemon->options & MHD_USE_SSL))
1619  MHD_DLOG (connection->daemon,
1620  "Failed to send data: %s\n",
1621  gnutls_strerror (ret));
1622  else
1623 #endif
1624  MHD_DLOG (connection->daemon,
1625  "Failed to send data: %s\n", STRERROR (errno));
1626 #endif
1627  CONNECTION_CLOSE_ERROR (connection, NULL);
1628  return MHD_YES;
1629  }
1630 #if DEBUG_SEND_DATA
1631  FPRINTF (stderr,
1632  "Sent response: `%.*s'\n",
1633  ret,
1634  &connection->write_buffer[connection->write_buffer_send_offset]);
1635 #endif
1636  connection->write_buffer_send_offset += ret;
1637  return MHD_YES;
1638 }
1639 
1645 static int
1646 check_write_done (struct MHD_Connection *connection,
1647  enum MHD_CONNECTION_STATE next_state)
1648 {
1649  if (connection->write_buffer_append_offset !=
1650  connection->write_buffer_send_offset)
1651  return MHD_NO;
1652  connection->write_buffer_append_offset = 0;
1653  connection->write_buffer_send_offset = 0;
1654  connection->state = next_state;
1655  MHD_pool_reallocate (connection->pool, connection->write_buffer,
1656  connection->write_buffer_size, 0);
1657  connection->write_buffer = NULL;
1658  connection->write_buffer_size = 0;
1659  return MHD_YES;
1660 }
1661 
1667 static int
1668 process_header_line (struct MHD_Connection *connection, char *line)
1669 {
1670  char *colon;
1671 
1672  /* line should be normal header line, find colon */
1673  colon = strchr (line, ':');
1674  if (colon == NULL)
1675  {
1676  /* error in header line, die hard */
1677  CONNECTION_CLOSE_ERROR (connection,
1678  "Received malformed line (no colon), closing connection.\n");
1679  return MHD_NO;
1680  }
1681  /* zero-terminate header */
1682  colon[0] = '\0';
1683  colon++; /* advance to value */
1684  while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
1685  colon++;
1686  /* we do the actual adding of the connection
1687  header at the beginning of the while
1688  loop since we need to be able to inspect
1689  the *next* header line (in case it starts
1690  with a space...) */
1691  connection->last = line;
1692  connection->colon = colon;
1693  return MHD_YES;
1694 }
1695 
1696 
1706 static int
1708  char *line, enum MHD_ValueKind kind)
1709 {
1710  char *last;
1711  char *tmp;
1712  size_t last_len;
1713  size_t tmp_len;
1714 
1715  last = connection->last;
1716  if ((line[0] == ' ') || (line[0] == '\t'))
1717  {
1718  /* value was continued on the next line, see
1719  http://www.jmarshall.com/easy/http/ */
1720  last_len = strlen (last);
1721  /* skip whitespace at start of 2nd line */
1722  tmp = line;
1723  while ((tmp[0] == ' ') || (tmp[0] == '\t'))
1724  tmp++;
1725  tmp_len = strlen (tmp);
1726  last = MHD_pool_reallocate (connection->pool,
1727  last,
1728  last_len + 1,
1729  last_len + tmp_len + 1);
1730  if (last == NULL)
1731  {
1732  transmit_error_response (connection,
1734  REQUEST_TOO_BIG);
1735  return MHD_NO;
1736  }
1737  memcpy (&last[last_len], tmp, tmp_len + 1);
1738  connection->last = last;
1739  return MHD_YES; /* possibly more than 2 lines... */
1740  }
1741  EXTRA_CHECK ((last != NULL) && (connection->colon != NULL));
1742  if ((MHD_NO == connection_add_header (connection,
1743  last, connection->colon, kind)))
1744  {
1746  REQUEST_TOO_BIG);
1747  return MHD_NO;
1748  }
1749  /* we still have the current line to deal with... */
1750  if (strlen (line) != 0)
1751  {
1752  if (MHD_NO == process_header_line (connection, line))
1753  {
1754  transmit_error_response (connection,
1756  return MHD_NO;
1757  }
1758  }
1759  return MHD_YES;
1760 }
1761 
1762 
1768 static void
1770 {
1771  const char *clen;
1772  unsigned MHD_LONG_LONG cval;
1773  struct MHD_Response *response;
1774  const char *enc;
1775  char *end;
1776 
1777  parse_cookie_header (connection);
1778  if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
1779  && (NULL != connection->version)
1780  && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
1781  && (NULL ==
1784  {
1785  /* die, http 1.1 request without host and we are pedantic */
1786  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1787  connection->read_closed = MHD_YES;
1788 #if HAVE_MESSAGES
1789  MHD_DLOG (connection->daemon,
1790  "Received `%s' request without `%s' header.\n",
1792 #endif
1793  EXTRA_CHECK (connection->response == NULL);
1794  response =
1798  MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
1799  MHD_destroy_response (response);
1800  return;
1801  }
1802 
1803  clen = MHD_lookup_connection_value (connection,
1806  if (clen != NULL)
1807  {
1808  cval = strtoul (clen, &end, 10);
1809  if ( ('\0' != *end) ||
1810  ( (LONG_MAX == cval) && (errno == ERANGE) ) )
1811  {
1812 #if HAVE_MESSAGES
1813  MHD_DLOG (connection->daemon,
1814  "Failed to parse `%s' header `%s', closing connection.\n",
1816 #endif
1817  CONNECTION_CLOSE_ERROR (connection, NULL);
1818  return;
1819  }
1820  connection->remaining_upload_size = cval;
1821  }
1822  else
1823  {
1824  enc = MHD_lookup_connection_value (connection,
1827  if (NULL == enc)
1828  {
1829  /* this request (better) not have a body */
1830  connection->remaining_upload_size = 0;
1831  }
1832  else
1833  {
1835  if (0 == strcasecmp (enc, "chunked"))
1836  connection->have_chunked_upload = MHD_YES;
1837  }
1838  }
1839 }
1840 
1841 
1852 int
1854 {
1855  connection->last_activity = MHD_monotonic_time();
1856  if (connection->state == MHD_CONNECTION_CLOSED)
1857  return MHD_YES;
1858  /* make sure "read" has a reasonable number of bytes
1859  in buffer to use per system call (if possible) */
1860  if (connection->read_buffer_offset + MHD_BUF_INC_SIZE >
1861  connection->read_buffer_size)
1862  try_grow_read_buffer (connection);
1863  if (MHD_NO == do_read (connection))
1864  return MHD_YES;
1865  while (1)
1866  {
1867 #if DEBUG_STATES
1868  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1869  __FUNCTION__, MHD_state_to_string (connection->state));
1870 #endif
1871  switch (connection->state)
1872  {
1873  case MHD_CONNECTION_INIT:
1882  /* nothing to do but default action */
1883  if (MHD_YES == connection->read_closed)
1884  {
1885  MHD_connection_close (connection,
1887  continue;
1888  }
1889  break;
1890  case MHD_CONNECTION_CLOSED:
1891  return MHD_YES;
1892  default:
1893  /* shrink read buffer to how much is actually used */
1894  MHD_pool_reallocate (connection->pool,
1895  connection->read_buffer,
1896  connection->read_buffer_size + 1,
1897  connection->read_buffer_offset);
1898  break;
1899  }
1900  break;
1901  }
1902  return MHD_YES;
1903 }
1904 
1905 
1916 int
1918 {
1919  struct MHD_Response *response;
1920  int ret;
1921  connection->last_activity = MHD_monotonic_time();
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 (response->crc != NULL)
1982  pthread_mutex_lock (&response->mutex);
1983  if (MHD_YES != try_ready_normal_body (connection))
1984  {
1985  if (response->crc != NULL)
1986  pthread_mutex_unlock (&response->mutex);
1987  break;
1988  }
1989  ret = connection->send_cls (connection,
1990  &response->data
1991  [connection->response_write_position
1992  - response->data_start],
1993  response->data_size -
1994  (connection->response_write_position
1995  - response->data_start));
1996 #if DEBUG_SEND_DATA
1997  if (ret > 0)
1998  FPRINTF (stderr,
1999  "Sent DATA response: `%.*s'\n",
2000  ret,
2001  &response->data[connection->response_write_position -
2002  response->data_start]);
2003 #endif
2004  if (response->crc != NULL)
2005  pthread_mutex_unlock (&response->mutex);
2006  if (ret < 0)
2007  {
2008  if ((errno == EINTR) || (errno == EAGAIN))
2009  return MHD_YES;
2010 #if HAVE_MESSAGES
2011  MHD_DLOG (connection->daemon,
2012  "Failed to send data: %s\n", STRERROR (errno));
2013 #endif
2014  CONNECTION_CLOSE_ERROR (connection, NULL);
2015  return MHD_YES;
2016  }
2017  connection->response_write_position += ret;
2018  if (connection->response_write_position ==
2019  connection->response->total_size)
2020  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers... */
2021  break;
2023  EXTRA_CHECK (0);
2024  break;
2026  do_write (connection);
2027  if (connection->state != MHD_CONNECTION_CHUNKED_BODY_READY)
2028  break;
2029  check_write_done (connection,
2030  (connection->response->total_size ==
2031  connection->response_write_position) ?
2034  break;
2035  case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
2037  EXTRA_CHECK (0);
2038  break;
2040  do_write (connection);
2041  if (connection->state != MHD_CONNECTION_FOOTERS_SENDING)
2042  break;
2044  break;
2046  EXTRA_CHECK (0);
2047  break;
2048  case MHD_CONNECTION_CLOSED:
2049  return MHD_YES;
2051  EXTRA_CHECK (0);
2052  break;
2053  default:
2054  EXTRA_CHECK (0);
2055  CONNECTION_CLOSE_ERROR (connection, "Internal error\n");
2056  return MHD_YES;
2057  }
2058  break;
2059  }
2060  return MHD_YES;
2061 }
2062 
2063 
2074 int
2076 {
2077  struct MHD_Daemon *daemon;
2078  unsigned int timeout;
2079  const char *end;
2080  int rend;
2081  char *line;
2082 
2083  while (1)
2084  {
2085 #if DEBUG_STATES
2086  MHD_DLOG (connection->daemon, "%s: state: %s\n",
2087  __FUNCTION__, MHD_state_to_string (connection->state));
2088 #endif
2089  switch (connection->state)
2090  {
2091  case MHD_CONNECTION_INIT:
2092  line = get_next_header_line (connection);
2093  if (line == NULL)
2094  {
2095  if (connection->state != MHD_CONNECTION_INIT)
2096  continue;
2097  if (connection->read_closed)
2098  {
2099  CONNECTION_CLOSE_ERROR (connection,
2100  NULL);
2101  continue;
2102  }
2103  break;
2104  }
2105  if (MHD_NO == parse_initial_message_line (connection, line))
2106  CONNECTION_CLOSE_ERROR (connection, NULL);
2107  else
2108  connection->state = MHD_CONNECTION_URL_RECEIVED;
2109  continue;
2111  line = get_next_header_line (connection);
2112  if (line == NULL)
2113  {
2114  if (connection->state != MHD_CONNECTION_URL_RECEIVED)
2115  continue;
2116  if (connection->read_closed)
2117  {
2118  CONNECTION_CLOSE_ERROR (connection,
2119  NULL);
2120  continue;
2121  }
2122  break;
2123  }
2124  if (strlen (line) == 0)
2125  {
2126  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2127  continue;
2128  }
2129  if (MHD_NO == process_header_line (connection, line))
2130  {
2131  transmit_error_response (connection,
2134  break;
2135  }
2137  continue;
2139  line = get_next_header_line (connection);
2140  if (line == NULL)
2141  {
2142  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2143  continue;
2144  if (connection->read_closed)
2145  {
2146  CONNECTION_CLOSE_ERROR (connection,
2147  NULL);
2148  continue;
2149  }
2150  break;
2151  }
2152  if (MHD_NO ==
2153  process_broken_line (connection, line, MHD_HEADER_KIND))
2154  continue;
2155  if (strlen (line) == 0)
2156  {
2157  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2158  continue;
2159  }
2160  continue;
2162  parse_connection_headers (connection);
2163  if (connection->state == MHD_CONNECTION_CLOSED)
2164  continue;
2166  continue;
2168  call_connection_handler (connection); /* first call */
2169  if (connection->state == MHD_CONNECTION_CLOSED)
2170  continue;
2171  if (need_100_continue (connection))
2172  {
2173  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2174  break;
2175  }
2176  if (connection->response != NULL)
2177  {
2178  /* we refused (no upload allowed!) */
2179  connection->remaining_upload_size = 0;
2180  /* force close, in case client still tries to upload... */
2181  connection->read_closed = MHD_YES;
2182  }
2183  connection->state = (connection->remaining_upload_size == 0)
2185  continue;
2187  if (connection->continue_message_write_offset ==
2188  strlen (HTTP_100_CONTINUE))
2189  {
2190  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2191  continue;
2192  }
2193  break;
2195  if (connection->read_buffer_offset != 0)
2196  {
2197  process_request_body (connection); /* loop call */
2198  if (connection->state == MHD_CONNECTION_CLOSED)
2199  continue;
2200  }
2201  if ((connection->remaining_upload_size == 0) ||
2202  ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
2203  (connection->read_buffer_offset == 0) &&
2204  (MHD_YES == connection->read_closed)))
2205  {
2206  if ((MHD_YES == connection->have_chunked_upload) &&
2207  (MHD_NO == connection->read_closed))
2208  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2209  else
2210  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2211  continue;
2212  }
2213  break;
2215  line = get_next_header_line (connection);
2216  if (line == NULL)
2217  {
2218  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2219  continue;
2220  if (connection->read_closed)
2221  {
2222  CONNECTION_CLOSE_ERROR (connection,
2223  NULL);
2224  continue;
2225  }
2226  break;
2227  }
2228  if (strlen (line) == 0)
2229  {
2230  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2231  continue;
2232  }
2233  if (MHD_NO == process_header_line (connection, line))
2234  {
2235  transmit_error_response (connection,
2238  break;
2239  }
2241  continue;
2243  line = get_next_header_line (connection);
2244  if (line == NULL)
2245  {
2246  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2247  continue;
2248  if (connection->read_closed)
2249  {
2250  CONNECTION_CLOSE_ERROR (connection,
2251  NULL);
2252  continue;
2253  }
2254  break;
2255  }
2256  if (MHD_NO ==
2257  process_broken_line (connection, line, MHD_FOOTER_KIND))
2258  continue;
2259  if (strlen (line) == 0)
2260  {
2261  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2262  continue;
2263  }
2264  continue;
2266  call_connection_handler (connection); /* "final" call */
2267  if (connection->state == MHD_CONNECTION_CLOSED)
2268  continue;
2269  if (connection->response == NULL)
2270  break; /* try again next time */
2271  if (MHD_NO == build_header_response (connection))
2272  {
2273  /* oops - close! */
2274  CONNECTION_CLOSE_ERROR (connection,
2275  "Closing connection (failed to create response header)\n");
2276  continue;
2277  }
2278  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2279 
2280 #if HAVE_DECL_TCP_CORK
2281  /* starting header send, set TCP cork */
2282  {
2283  const int val = 1;
2284  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2285  sizeof (val));
2286  }
2287 #endif
2288  break;
2290  /* no default action */
2291  break;
2293  if (connection->have_chunked_upload)
2295  else
2297  continue;
2299  /* nothing to do here */
2300  break;
2302  if (connection->response->crc != NULL)
2303  pthread_mutex_lock (&connection->response->mutex);
2304  if (MHD_YES == try_ready_normal_body (connection))
2305  {
2306  if (connection->response->crc != NULL)
2307  pthread_mutex_unlock (&connection->response->mutex);
2309  break;
2310  }
2311  if (connection->response->crc != NULL)
2312  pthread_mutex_unlock (&connection->response->mutex);
2313  /* not ready, no socket action */
2314  break;
2316  /* nothing to do here */
2317  break;
2319  if (connection->response->crc != NULL)
2320  pthread_mutex_lock (&connection->response->mutex);
2321  if (MHD_YES == try_ready_chunked_body (connection))
2322  {
2323  if (connection->response->crc != NULL)
2324  pthread_mutex_unlock (&connection->response->mutex);
2326  continue;
2327  }
2328  if (connection->response->crc != NULL)
2329  pthread_mutex_unlock (&connection->response->mutex);
2330  break;
2332  build_header_response (connection);
2333  if (connection->write_buffer_send_offset ==
2334  connection->write_buffer_append_offset)
2335  connection->state = MHD_CONNECTION_FOOTERS_SENT;
2336  else
2337  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
2338  continue;
2340  /* no default action */
2341  break;
2343 #if HAVE_DECL_TCP_CORK
2344  /* done sending, uncork */
2345  {
2346  const int val = 0;
2347  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2348  sizeof (val));
2349  }
2350 #endif
2351  end =
2352  MHD_get_response_header (connection->response,
2354  rend = ( (end != NULL) && (0 == strcasecmp (end, "close")) );
2355  MHD_destroy_response (connection->response);
2356  connection->response = NULL;
2357  if (connection->daemon->notify_completed != NULL)
2358  connection->daemon->notify_completed (connection->daemon->
2360  connection,
2361  &connection->client_context,
2363  connection->client_aware = MHD_NO;
2364  end =
2367  connection->client_context = NULL;
2368  connection->continue_message_write_offset = 0;
2369  connection->responseCode = 0;
2370  connection->headers_received = NULL;
2371  connection->headers_received_tail = NULL;
2372  connection->response_write_position = 0;
2373  connection->have_chunked_upload = MHD_NO;
2374  connection->method = NULL;
2375  connection->url = NULL;
2376  connection->write_buffer = NULL;
2377  connection->write_buffer_size = 0;
2378  connection->write_buffer_send_offset = 0;
2379  connection->write_buffer_append_offset = 0;
2380  if ( (rend) || ((end != NULL) && (0 == strcasecmp (end, "close"))) )
2381  {
2382  connection->read_closed = MHD_YES;
2383  connection->read_buffer_offset = 0;
2384  }
2385  if (((MHD_YES == connection->read_closed) &&
2386  (0 == connection->read_buffer_offset)) ||
2387  (connection->version == NULL) ||
2388  (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
2389  {
2390  /* http 1.0, version-less requests cannot be pipelined */
2392  MHD_pool_destroy (connection->pool);
2393  connection->pool = NULL;
2394  connection->read_buffer = NULL;
2395  connection->read_buffer_size = 0;
2396  connection->read_buffer_offset = 0;
2397  }
2398  else
2399  {
2400  connection->version = NULL;
2401  connection->state = MHD_CONNECTION_INIT;
2402  connection->read_buffer
2403  = MHD_pool_reset (connection->pool,
2404  connection->read_buffer,
2405  connection->read_buffer_size);
2406  }
2407  continue;
2408  case MHD_CONNECTION_CLOSED:
2409  if (connection->response != NULL)
2410  {
2411  MHD_destroy_response (connection->response);
2412  connection->response = NULL;
2413  }
2414  daemon = connection->daemon;
2415  if (0 != pthread_mutex_lock(&daemon->cleanup_connection_mutex))
2416  {
2417  MHD_PANIC ("Failed to acquire cleanup mutex\n");
2418  }
2419  DLL_remove (daemon->connections_head,
2420  daemon->connections_tail,
2421  connection);
2422  DLL_insert (daemon->cleanup_head,
2423  daemon->cleanup_tail,
2424  connection);
2425  if (0 != pthread_mutex_unlock(&daemon->cleanup_connection_mutex))
2426  {
2427  MHD_PANIC ("Failed to release cleanup mutex\n");
2428  }
2429  return MHD_NO;
2430  default:
2431  EXTRA_CHECK (0);
2432  break;
2433  }
2434  break;
2435  }
2436  timeout = connection->connection_timeout;
2437  if ( (timeout != 0) &&
2438  (timeout <= (MHD_monotonic_time() - connection->last_activity)) )
2439  {
2441  return MHD_YES;
2442  }
2443  return MHD_YES;
2444 }
2445 
2446 
2452 void
2454 {
2458 }
2459 
2460 
2470 const union MHD_ConnectionInfo *
2472  enum MHD_ConnectionInfoType infoType, ...)
2473 {
2474  switch (infoType)
2475  {
2476 #if HTTPS_SUPPORT
2478  if (connection->tls_session == NULL)
2479  return NULL;
2480  connection->cipher = gnutls_cipher_get (connection->tls_session);
2481  return (const union MHD_ConnectionInfo *) &connection->cipher;
2483  if (connection->tls_session == NULL)
2484  return NULL;
2485  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
2486  return (const union MHD_ConnectionInfo *) &connection->protocol;
2488  if (connection->tls_session == NULL)
2489  return NULL;
2490  return (const union MHD_ConnectionInfo *) &connection->tls_session;
2491 #endif
2493  return (const union MHD_ConnectionInfo *) &connection->addr;
2495  return (const union MHD_ConnectionInfo *) &connection->daemon;
2496  default:
2497  return NULL;
2498  };
2499 }
2500 
2501 
2510 int
2512  enum MHD_CONNECTION_OPTION option,
2513  ...)
2514 {
2515  va_list ap;
2516 
2517  switch (option)
2518  {
2520  va_start (ap, option);
2521  connection->connection_timeout = va_arg (ap, unsigned int);
2522  va_end (ap);
2523  return MHD_YES;
2524  default:
2525  return MHD_NO;
2526  }
2527 }
2528 
2529 
2530 /* end of connection.c */