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 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 "connection.h"
30 #include "memorypool.h"
31 #include "response.h"
32 #include "reason_phrase.h"
33 
34 #if HAVE_NETINET_TCP_H
35 /* for TCP_CORK */
36 #include <netinet/tcp.h>
37 #endif
38 
42 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
43 
51 #if HAVE_MESSAGES
52 #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>"
53 #else
54 #define REQUEST_TOO_BIG ""
55 #endif
56 
64 #if HAVE_MESSAGES
65 #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>"
66 #else
67 #define REQUEST_LACKS_HOST ""
68 #endif
69 
77 #if HAVE_MESSAGES
78 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
79 #else
80 #define REQUEST_MALFORMED ""
81 #endif
82 
89 #if HAVE_MESSAGES
90 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Some programmer needs to study the manual more carefully.</body></html>"
91 #else
92 #define INTERNAL_ERROR ""
93 #endif
94 
99 #define DEBUG_CLOSE MHD_NO
100 
104 #define DEBUG_SEND_DATA MHD_NO
105 
114 int
116  enum MHD_ValueKind kind,
117  MHD_KeyValueIterator iterator, void *iterator_cls)
118 {
119  int ret;
120  struct MHD_HTTP_Header *pos;
121 
122  if (connection == NULL)
123  return -1;
124  ret = 0;
125  pos = connection->headers_received;
126  while (pos != NULL)
127  {
128  if (0 != (pos->kind & kind))
129  {
130  ret++;
131  if ((iterator != NULL) &&
132  (MHD_YES != iterator (iterator_cls,
133  kind, pos->header, pos->value)))
134  return ret;
135  }
136  pos = pos->next;
137  }
138  return ret;
139 }
140 
170 int
172  enum MHD_ValueKind kind,
173  const char *key, const char *value)
174 {
175  struct MHD_HTTP_Header *pos;
176 
177  pos = MHD_pool_allocate (connection->pool,
178  sizeof (struct MHD_HTTP_Header), MHD_NO);
179  if (pos == NULL)
180  return MHD_NO;
181  pos->header = (char *) key;
182  pos->value = (char *) value;
183  pos->kind = kind;
184  pos->next = connection->headers_received;
185  connection->headers_received = pos;
186  return MHD_YES;
187 }
188 
196 const char *
198  enum MHD_ValueKind kind, const char *key)
199 {
200  struct MHD_HTTP_Header *pos;
201 
202  if (connection == NULL)
203  return NULL;
204  pos = connection->headers_received;
205  while (pos != NULL)
206  {
207  if ((0 != (pos->kind & kind)) && (0 == strcasecmp (key, pos->header)))
208  return pos->value;
209  pos = pos->next;
210  }
211  return NULL;
212 }
213 
224 int
225 MHD_queue_response (struct MHD_Connection *connection,
226  unsigned int status_code, struct MHD_Response *response)
227 {
228  if ((connection == NULL) ||
229  (response == NULL) ||
230  (connection->response != NULL) ||
231  ((connection->state != MHD_CONNECTION_HEADERS_PROCESSED) &&
232  (connection->state != MHD_CONNECTION_FOOTERS_RECEIVED)))
233  return MHD_NO;
234  MHD_increment_response_rc (response);
235  connection->response = response;
236  connection->responseCode = status_code;
237  if ((connection->method != NULL) &&
238  (0 == strcasecmp (connection->method, MHD_HTTP_METHOD_HEAD)))
239  {
240  /* if this is a "HEAD" request, pretend that we
241  have already sent the full message body */
242  connection->response_write_position = response->total_size;
243  }
244  if ((response->total_size == MHD_SIZE_UNKNOWN) &&
245  (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
246  connection->have_chunked_response = MHD_YES;
247  else
248  connection->have_chunked_response = MHD_NO;
249  if (connection->state == MHD_CONNECTION_HEADERS_PROCESSED)
250  {
251  /* response was queued "early",
252  refuse to read body / footers or further
253  requests! */
254  SHUTDOWN (connection->socket_fd, SHUT_RD);
255  connection->read_closed = MHD_YES;
257  }
258  return MHD_YES;
259 }
260 
265 static int
266 need_100_continue (struct MHD_Connection *connection)
267 {
268  const char *expect;
269 
270  return ((connection->response == NULL) &&
271  (connection->version != NULL) &&
272  (0 == strcasecmp (connection->version,
274  (NULL != (expect = MHD_lookup_connection_value (connection,
277  && (0 == strcasecmp (expect, "100-continue"))
278  && (connection->continue_message_write_offset <
279  strlen (HTTP_100_CONTINUE)));
280 }
281 
286 void
288  enum MHD_RequestTerminationCode termination_code)
289 {
290  SHUTDOWN (connection->socket_fd, SHUT_RDWR);
291  CLOSE (connection->socket_fd);
292  connection->socket_fd = -1;
293  connection->state = MHD_CONNECTION_CLOSED;
294  if ( (NULL != connection->daemon->notify_completed) &&
295  (MHD_YES == connection->client_aware) )
296  connection->daemon->notify_completed (connection->daemon->
297  notify_completed_cls, connection,
298  &connection->client_context,
299  termination_code);
300  connection->client_aware = MHD_NO;
301 }
302 
307 static void
309 {
311 }
312 
313 
323 static int
325 {
326  int ret;
327  struct MHD_Response *response;
328 
329  response = connection->response;
330  if (response->crc == NULL)
331  return MHD_YES;
332  if ( (response->data_start <=
333  connection->response_write_position) &&
334  (response->data_size + response->data_start >
335  connection->response_write_position) )
336  return MHD_YES; /* response already ready */
337 #if LINUX
338  if ( (response->fd != -1) &&
339  (0 == (connection->daemon->options & MHD_USE_SSL)) )
340  {
341  /* will use sendfile, no need to bother response crc */
342  return MHD_YES;
343  }
344 #endif
345 
346  ret = response->crc (response->crc_cls,
347  connection->response_write_position,
348  response->data,
349  MHD_MIN (response->data_buffer_size,
350  response->total_size -
351  connection->response_write_position));
352  if ((ret == 0) &&
353  (0 != (connection->daemon->options & MHD_USE_SELECT_INTERNALLY)))
354  mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
355 #if HAVE_MESSAGES
356  "API violation"
357 #else
358  NULL
359 #endif
360  );
361  if ( (ret == MHD_CONTENT_READER_END_OF_STREAM) ||
363  {
364  /* either error or http 1.0 transfer, close
365  socket! */
366 #if DEBUG_CLOSE
367 #if HAVE_MESSAGES
368  MHD_DLOG (connection->daemon,
369  "Closing connection (end of response or error)\n");
370 #endif
371 #endif
372  response->total_size = connection->response_write_position;
373  connection_close_error (connection);
374  return MHD_NO;
375  }
376  response->data_start = connection->response_write_position;
377  response->data_size = ret;
378  if (ret == 0)
379  return MHD_NO;
380  return MHD_YES;
381 }
382 
383 
392 static int
394 {
395  int ret;
396  char *buf;
397  struct MHD_Response *response;
398  size_t size;
399  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
400  int cblen;
401 
402  response = connection->response;
403  if (connection->write_buffer_size == 0)
404  {
405  size = connection->daemon->pool_size;
406  do
407  {
408  size /= 2;
409  if (size < 128)
410  {
411  /* not enough memory */
412 #if DEBUG_CLOSE
413 #if HAVE_MESSAGES
414  MHD_DLOG (connection->daemon,
415  "Closing connection (out of memory)\n");
416 #endif
417 #endif
418  connection_close_error (connection);
419  return MHD_NO;
420  }
421  buf = MHD_pool_allocate (connection->pool, size, MHD_NO);
422  }
423  while (buf == NULL);
424  connection->write_buffer_size = size;
425  connection->write_buffer = buf;
426  }
427 
428  if ( (response->data_start <=
429  connection->response_write_position) &&
430  (response->data_size + response->data_start >
431  connection->response_write_position) )
432  {
433  /* buffer already ready, use what is there for the chunk */
434  ret = response->data_size + response->data_start - connection->response_write_position;
435  if (ret > connection->write_buffer_size - sizeof (cbuf) - 2)
436  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
437  memcpy (&connection->write_buffer[sizeof (cbuf)],
438  &response->data[connection->response_write_position - response->data_start],
439  ret);
440  }
441  else
442  {
443  /* buffer not in range, try to fill it */
444  ret = response->crc (response->crc_cls,
445  connection->response_write_position,
446  &connection->write_buffer[sizeof (cbuf)],
447  connection->write_buffer_size - sizeof (cbuf) - 2);
448  }
450  {
451  /* error, close socket! */
452 #if DEBUG_CLOSE
453 #if HAVE_MESSAGES
454  MHD_DLOG (connection->daemon,
455  "Closing connection (error generating response)\n");
456 #endif
457 #endif
458  response->total_size = connection->response_write_position;
459  connection_close_error (connection);
460  return MHD_NO;
461  }
463  {
464  /* end of message, signal other side! */
465  strcpy (connection->write_buffer, "0\r\n");
466  connection->write_buffer_append_offset = 3;
467  connection->write_buffer_send_offset = 0;
468  response->total_size = connection->response_write_position;
469  return MHD_YES;
470  }
471  if (ret == 0)
472  {
474  return MHD_NO;
475  }
476  if (ret > 0xFFFFFF)
477  ret = 0xFFFFFF;
478  snprintf (cbuf,
479  sizeof (cbuf),
480  "%X\r\n", ret);
481  cblen = strlen (cbuf);
482  EXTRA_CHECK (cblen <= sizeof (cbuf));
483  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen], cbuf, cblen);
484  memcpy (&connection->write_buffer[sizeof (cbuf) + ret], "\r\n", 2);
485  connection->response_write_position += ret;
486  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
487  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
488  return MHD_YES;
489 }
490 
495 static void
496 add_extra_headers (struct MHD_Connection *connection)
497 {
498  const char *have;
499  char buf[128];
500 
501  connection->have_chunked_upload = MHD_NO;
502  if (connection->response->total_size == MHD_SIZE_UNKNOWN)
503  {
504  have = MHD_get_response_header (connection->response,
506  if ((have == NULL) || (0 != strcasecmp (have, "close")))
507  {
508  if ((connection->version != NULL) &&
509  (0 == strcasecmp (connection->version, MHD_HTTP_VERSION_1_1)))
510  {
511  connection->have_chunked_upload = MHD_YES;
512  have = MHD_get_response_header (connection->response,
514  if (have == NULL)
515  MHD_add_response_header (connection->response,
517  "chunked");
518  }
519  else
520  {
521  MHD_add_response_header (connection->response,
522  MHD_HTTP_HEADER_CONNECTION, "close");
523  }
524  }
525  }
526  else if (NULL == MHD_get_response_header (connection->response,
528  {
529  SPRINTF (buf,
530  "%" MHD_LONG_LONG_PRINTF "u",
531  (unsigned MHD_LONG_LONG)connection->response->total_size);
532  MHD_add_response_header (connection->response,
534  }
535 }
536 
543 static void
544 get_date_string (char *date)
545 {
546  static const char *days[] =
547  { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
548  static const char *mons[] =
549  { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
550  "Nov", "Dec"
551  };
552  struct tm now;
553  time_t t;
554 
555  time (&t);
556  gmtime_r (&t, &now);
557  SPRINTF (date,
558  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
559  days[now.tm_wday % 7],
560  now.tm_mday,
561  mons[now.tm_mon % 12],
562  1900 + now.tm_year, now.tm_hour, now.tm_min, now.tm_sec);
563 }
564 
570 static int
572 {
573  void *buf;
574 
575  buf = MHD_pool_reallocate (connection->pool,
576  connection->read_buffer,
577  connection->read_buffer_size,
578  connection->read_buffer_size * 2 +
579  MHD_BUF_INC_SIZE + 1);
580  if (buf == NULL)
581  return MHD_NO;
582  /* we can actually grow the buffer, do it! */
583  connection->read_buffer = buf;
584  connection->read_buffer_size =
585  connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
586  return MHD_YES;
587 }
588 
595 static int
597 {
598  size_t size;
599  size_t off;
600  struct MHD_HTTP_Header *pos;
601  char code[256];
602  char date[128];
603  char *data;
604  enum MHD_ValueKind kind;
605  const char *reason_phrase;
606  uint32_t rc;
607 
608  EXTRA_CHECK (NULL != connection->version);
609  if (0 == strlen(connection->version))
610  {
611  data = MHD_pool_allocate (connection->pool, 0, MHD_YES);
612  connection->write_buffer = data;
613  connection->write_buffer_append_offset = 0;
614  connection->write_buffer_send_offset = 0;
615  connection->write_buffer_size = 0;
616  return MHD_YES;
617  }
618  if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
619  {
620  add_extra_headers (connection);
621  rc = connection->responseCode & (~MHD_ICY_FLAG);
622  reason_phrase = MHD_get_reason_phrase_for (rc);
623  SPRINTF (code,
624  "%s %u %s\r\n",
625  (0 != (connection->responseCode & MHD_ICY_FLAG))
626  ? "ICY"
627  : ( (0 == strcasecmp (MHD_HTTP_VERSION_1_0,
628  connection->version))
631  rc,
632  reason_phrase);
633  off = strlen (code);
634  /* estimate size */
635  size = off + 2; /* extra \r\n at the end */
636  kind = MHD_HEADER_KIND;
637  if (NULL == MHD_get_response_header (connection->response,
639  get_date_string (date);
640  else
641  date[0] = '\0';
642  size += strlen (date);
643  }
644  else
645  {
646  size = 2;
647  kind = MHD_FOOTER_KIND;
648  off = 0;
649  }
650  pos = connection->response->first_header;
651  while (pos != NULL)
652  {
653  if (pos->kind == kind)
654  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
655  pos = pos->next;
656  }
657  /* produce data */
658  data = MHD_pool_allocate (connection->pool, size + 1, MHD_YES);
659  if (data == NULL)
660  {
661 #if HAVE_MESSAGES
662  MHD_DLOG (connection->daemon, "Not enough memory for write!\n");
663 #endif
664  return MHD_NO;
665  }
666  if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
667  {
668  memcpy (data, code, off);
669  }
670  pos = connection->response->first_header;
671  while (pos != NULL)
672  {
673  if (pos->kind == kind)
674  off += SPRINTF (&data[off], "%s: %s\r\n", pos->header, pos->value);
675  pos = pos->next;
676  }
677  if (connection->state == MHD_CONNECTION_FOOTERS_RECEIVED)
678  {
679  strcpy (&data[off], date);
680  off += strlen (date);
681  }
682  memcpy (&data[off], "\r\n", 2);
683  off += 2;
684  if (off != size)
685  mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL);
686  connection->write_buffer = data;
687  connection->write_buffer_append_offset = size;
688  connection->write_buffer_send_offset = 0;
689  connection->write_buffer_size = size + 1;
690  return MHD_YES;
691 }
692 
700 static void
702  unsigned int status_code, const char *message)
703 {
704  struct MHD_Response *response;
705 
706  if (connection->version == NULL)
707  {
708  /* we were unable to process the full header line, so we don't
709  really know what version the client speaks; assume 1.0 */
710  connection->version = MHD_HTTP_VERSION_1_0;
711  }
713  connection->read_closed = MHD_YES;
714 #if HAVE_MESSAGES
715  MHD_DLOG (connection->daemon,
716  "Error %u (`%s') processing request, closing connection.\n",
717  status_code, message);
718 #endif
719  EXTRA_CHECK (connection->response == NULL);
720  response = MHD_create_response_from_buffer (strlen (message),
721  (void *) message,
723  MHD_queue_response (connection, status_code, response);
724  EXTRA_CHECK (connection->response != NULL);
725  MHD_destroy_response (response);
726  if (MHD_NO == build_header_response (connection))
727  {
728  /* oops - close! */
729 #if HAVE_MESSAGES
730  MHD_DLOG (connection->daemon,
731  "Closing connection (failed to create response header)\n");
732 #endif
733  connection->state = MHD_CONNECTION_CLOSED;
734  }
735  else
736  {
738  }
739 }
740 
745 static void
746 do_fd_set (int fd, fd_set * set, int *max_fd)
747 {
748  FD_SET (fd, set);
749  if ( (NULL != max_fd) &&
750  (fd > *max_fd) )
751  *max_fd = fd;
752 }
753 
759 int
761  fd_set * read_fd_set,
762  fd_set * write_fd_set,
763  fd_set * except_fd_set, int *max_fd)
764 {
765  int ret;
766  struct MHD_Pollfd p;
767 
768  memset(&p, 0, sizeof(struct MHD_Pollfd));
769  ret = MHD_connection_get_pollfd(connection, &p);
770  if ( (ret == MHD_YES) && (p.fd >= 0) ) {
771  if (0 != (p.events & MHD_POLL_ACTION_IN))
772  do_fd_set(p.fd, read_fd_set, max_fd);
773  if (0 != (p.events & MHD_POLL_ACTION_OUT))
774  do_fd_set(p.fd, write_fd_set, max_fd);
775  }
776  return ret;
777 }
778 
785 int
786 MHD_connection_get_pollfd (struct MHD_Connection *connection, struct MHD_Pollfd *p)
787 {
788  int fd;
789 
790  if (connection->pool == NULL)
791  connection->pool = MHD_pool_create (connection->daemon->pool_size);
792  if (connection->pool == NULL)
793  {
794 #if HAVE_MESSAGES
795  MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
796 #endif
797  connection_close_error (connection);
798  return MHD_NO;
799  }
800  fd = connection->socket_fd;
801  p->fd = fd;
802  if (fd == -1)
803  return MHD_YES;
804  while (1)
805  {
806 #if DEBUG_STATES
807  MHD_DLOG (connection->daemon, "%s: state: %s\n",
808  __FUNCTION__, MHD_state_to_string (connection->state));
809 #endif
810  switch (connection->state)
811  {
812 #if HTTPS_SUPPORT
814  if (0 == gnutls_record_get_direction (connection->tls_session))
816  else
818  break;
819 #endif
820  case MHD_CONNECTION_INIT:
823  /* while reading headers, we always grow the
824  read buffer if needed, no size-check required */
825  if ((connection->read_closed) &&
826  (connection->read_buffer_offset == 0))
827  {
828  connection->state = MHD_CONNECTION_CLOSED;
829  continue;
830  }
831  if ((connection->read_buffer_offset == connection->read_buffer_size)
832  && (MHD_NO == try_grow_read_buffer (connection)))
833  {
834  transmit_error_response (connection,
835  (connection->url != NULL)
839  continue;
840  }
841  if (MHD_NO == connection->read_closed)
843  break;
845  /* we should never get here */
846  EXTRA_CHECK (0);
847  break;
849  EXTRA_CHECK (0);
850  break;
853  break;
855  if (connection->read_buffer_offset == connection->read_buffer_size)
856  {
857  if ((MHD_YES != try_grow_read_buffer (connection)) &&
858  (0 != (connection->daemon->options &
861  {
862  /* failed to grow the read buffer, and the
863  client which is supposed to handle the
864  received data in a *blocking* fashion
865  (in this mode) did not handle the data as
866  it was supposed to!
867  => we would either have to do busy-waiting
868  (on the client, which would likely fail),
869  or if we do nothing, we would just timeout
870  on the connection (if a timeout is even
871  set!).
872  Solution: we kill the connection with an error */
873  transmit_error_response (connection,
876  continue;
877  }
878  }
879  if ((connection->read_buffer_offset < connection->read_buffer_size)
880  && (MHD_NO == connection->read_closed))
882  break;
885  /* while reading footers, we always grow the
886  read buffer if needed, no size-check required */
887  if (MHD_YES == connection->read_closed)
888  {
889  connection->state = MHD_CONNECTION_CLOSED;
890  continue;
891  }
893  /* transition to FOOTERS_RECEIVED
894  happens in read handler */
895  break;
897  /* no socket action, wait for client
898  to provide response */
899  break;
901  /* headers in buffer, keep writing */
903  break;
905  EXTRA_CHECK (0);
906  break;
909  break;
911  /* not ready, no socket action */
912  break;
915  break;
917  /* not ready, no socket action */
918  break;
920  EXTRA_CHECK (0);
921  break;
924  break;
926  EXTRA_CHECK (0);
927  break;
929  if (connection->socket_fd != -1)
930  connection_close_error (connection);
931  return MHD_YES; /* do nothing, not even reading */
932 
933  default:
934  EXTRA_CHECK (0);
935  }
936  break;
937  }
938  return MHD_YES;
939 }
940 
949 static char *
951 {
952  char *rbuf;
953  size_t pos;
954 
955  if (connection->read_buffer_offset == 0)
956  return NULL;
957  pos = 0;
958  rbuf = connection->read_buffer;
959  while ((pos < connection->read_buffer_offset - 1) &&
960  (rbuf[pos] != '\r') && (rbuf[pos] != '\n'))
961  pos++;
962  if (pos == connection->read_buffer_offset - 1)
963  {
964  /* not found, consider growing... */
965  if (connection->read_buffer_offset == connection->read_buffer_size)
966  {
967  rbuf = MHD_pool_reallocate (connection->pool,
968  connection->read_buffer,
969  connection->read_buffer_size,
970  connection->read_buffer_size * 2 +
972  if (rbuf == NULL)
973  {
974  transmit_error_response (connection,
975  (connection->url != NULL)
979  }
980  else
981  {
982  connection->read_buffer_size =
983  connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
984  connection->read_buffer = rbuf;
985  }
986  }
987  return NULL;
988  }
989  /* found, check if we have proper CRLF */
990  if ((rbuf[pos] == '\r') && (rbuf[pos + 1] == '\n'))
991  rbuf[pos++] = '\0'; /* skip both r and n */
992  rbuf[pos++] = '\0';
993  connection->read_buffer += pos;
994  connection->read_buffer_size -= pos;
995  connection->read_buffer_offset -= pos;
996  return rbuf;
997 }
998 
1002 static int
1004  char *key, char *value, enum MHD_ValueKind kind)
1005 {
1006  struct MHD_HTTP_Header *hdr;
1007 
1008  hdr = MHD_pool_allocate (connection->pool,
1009  sizeof (struct MHD_HTTP_Header), MHD_YES);
1010  if (hdr == NULL)
1011  {
1012 #if HAVE_MESSAGES
1013  MHD_DLOG (connection->daemon,
1014  "Not enough memory to allocate header record!\n");
1015 #endif
1017  REQUEST_TOO_BIG);
1018  return MHD_NO;
1019  }
1020  hdr->next = connection->headers_received;
1021  hdr->header = key;
1022  hdr->value = value;
1023  hdr->kind = kind;
1024  connection->headers_received = hdr;
1025  return MHD_YES;
1026 }
1027 
1031 static int
1033  struct MHD_Connection *connection, char *args)
1034 {
1035  char *equals;
1036  char *amper;
1037 
1038  while (args != NULL)
1039  {
1040  equals = strstr (args, "=");
1041  if (equals == NULL)
1042  return MHD_NO; /* invalid, ignore */
1043  equals[0] = '\0';
1044  equals++;
1045  amper = strstr (equals, "&");
1046  if (amper != NULL)
1047  {
1048  amper[0] = '\0';
1049  amper++;
1050  }
1051  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1052  connection,
1053  args);
1054  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1055  connection,
1056  equals);
1057  if (MHD_NO == connection_add_header (connection, args, equals, kind))
1058  return MHD_NO;
1059  args = amper;
1060  }
1061  return MHD_YES;
1062 }
1063 
1069 static int
1071 {
1072  const char *hdr;
1073  char *cpy;
1074  char *pos;
1075  char *sce;
1076  char *semicolon;
1077  char *equals;
1078  char *ekill;
1079  char old;
1080  int quotes;
1081 
1082  hdr = MHD_lookup_connection_value (connection,
1085  if (hdr == NULL)
1086  return MHD_YES;
1087  cpy = MHD_pool_allocate (connection->pool, strlen (hdr) + 1, MHD_YES);
1088  if (cpy == NULL)
1089  {
1090 #if HAVE_MESSAGES
1091  MHD_DLOG (connection->daemon, "Not enough memory to parse cookies!\n");
1092 #endif
1094  REQUEST_TOO_BIG);
1095  return MHD_NO;
1096  }
1097  memcpy (cpy, hdr, strlen (hdr) + 1);
1098  pos = cpy;
1099  while (pos != NULL)
1100  {
1101  while (*pos == ' ')
1102  pos++; /* skip spaces */
1103 
1104  sce = pos;
1105  while (((*sce) != '\0') &&
1106  ((*sce) != ',') && ((*sce) != ';') && ((*sce) != '='))
1107  sce++;
1108  /* remove tailing whitespace (if any) from key */
1109  ekill = sce - 1;
1110  while ((*ekill == ' ') && (ekill >= pos))
1111  *(ekill--) = '\0';
1112  old = *sce;
1113  *sce = '\0';
1114  if (old != '=')
1115  {
1116  /* value part omitted, use empty string... */
1117  if (MHD_NO ==
1118  connection_add_header (connection, pos, "", MHD_COOKIE_KIND))
1119  return MHD_NO;
1120  if (old == '\0')
1121  break;
1122  pos = sce + 1;
1123  continue;
1124  }
1125  equals = sce + 1;
1126  quotes = 0;
1127  semicolon = equals;
1128  while ((semicolon[0] != '\0') &&
1129  ((quotes != 0) ||
1130  ((semicolon[0] != ';') && (semicolon[0] != ','))))
1131  {
1132  if (semicolon[0] == '"')
1133  quotes = (quotes + 1) & 1;
1134  semicolon++;
1135  }
1136  if (semicolon[0] == '\0')
1137  semicolon = NULL;
1138  if (semicolon != NULL)
1139  {
1140  semicolon[0] = '\0';
1141  semicolon++;
1142  }
1143  /* remove quotes */
1144  if ((equals[0] == '"') && (equals[strlen (equals) - 1] == '"'))
1145  {
1146  equals[strlen (equals) - 1] = '\0';
1147  equals++;
1148  }
1149  if (MHD_NO == connection_add_header (connection,
1150  pos, equals, MHD_COOKIE_KIND))
1151  return MHD_NO;
1152  pos = semicolon;
1153  }
1154  return MHD_YES;
1155 }
1156 
1164 static int
1165 parse_initial_message_line (struct MHD_Connection *connection, char *line)
1166 {
1167  char *uri;
1168  char *httpVersion;
1169  char *args;
1170 
1171  uri = strstr (line, " ");
1172  if (uri == NULL)
1173  return MHD_NO; /* serious error */
1174  uri[0] = '\0';
1175  connection->method = line;
1176  uri++;
1177  while (uri[0] == ' ')
1178  uri++;
1179  httpVersion = strstr (uri, " ");
1180  if (httpVersion != NULL)
1181  {
1182  httpVersion[0] = '\0';
1183  httpVersion++;
1184  }
1185  if (connection->daemon->uri_log_callback != NULL)
1186  connection->client_context
1187  =
1188  connection->daemon->uri_log_callback (connection->daemon->
1189  uri_log_callback_cls, uri);
1190  args = strstr (uri, "?");
1191  if (args != NULL)
1192  {
1193  args[0] = '\0';
1194  args++;
1195  parse_arguments (MHD_GET_ARGUMENT_KIND, connection, args);
1196  }
1197  connection->daemon->unescape_callback (connection->daemon->unescape_callback_cls,
1198  connection,
1199  uri);
1200  connection->url = uri;
1201  if (httpVersion == NULL)
1202  connection->version = "";
1203  else
1204  connection->version = httpVersion;
1205  return MHD_YES;
1206 }
1207 
1208 
1214 static void
1216 {
1217  size_t processed;
1218 
1219  if (connection->response != NULL)
1220  return; /* already queued a response */
1221  processed = 0;
1222  connection->client_aware = MHD_YES;
1223  if (MHD_NO ==
1224  connection->daemon->default_handler (connection->daemon->
1225  default_handler_cls,
1226  connection, connection->url,
1227  connection->method,
1228  connection->version,
1229  NULL, &processed,
1230  &connection->client_context))
1231  {
1232  /* serious internal error, close connection */
1233 #if HAVE_MESSAGES
1234  MHD_DLOG (connection->daemon,
1235  "Internal application error, closing connection.\n");
1236 #endif
1237  connection_close_error (connection);
1238  return;
1239  }
1240 }
1241 
1242 
1243 
1249 static void
1251 {
1252  size_t processed;
1253  size_t available;
1254  size_t used;
1255  size_t i;
1256  int instant_retry;
1257  int malformed;
1258  char *buffer_head;
1259 
1260  if (connection->response != NULL)
1261  return; /* already queued a response */
1262 
1263  buffer_head = connection->read_buffer;
1264  available = connection->read_buffer_offset;
1265  do
1266  {
1267  instant_retry = MHD_NO;
1268  if ((connection->have_chunked_upload == MHD_YES) &&
1269  (connection->remaining_upload_size == MHD_SIZE_UNKNOWN))
1270  {
1271  if ((connection->current_chunk_offset ==
1272  connection->current_chunk_size)
1273  && (connection->current_chunk_offset != 0) && (available >= 2))
1274  {
1275  /* skip new line at the *end* of a chunk */
1276  i = 0;
1277  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1278  i++; /* skip 1st part of line feed */
1279  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1280  i++; /* skip 2nd part of line feed */
1281  if (i == 0)
1282  {
1283  /* malformed encoding */
1284 #if HAVE_MESSAGES
1285  MHD_DLOG (connection->daemon,
1286  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1287 #endif
1288  connection_close_error (connection);
1289  return;
1290  }
1291  available -= i;
1292  buffer_head += i;
1293  connection->current_chunk_offset = 0;
1294  connection->current_chunk_size = 0;
1295  }
1296  if (connection->current_chunk_offset <
1297  connection->current_chunk_size)
1298  {
1299  /* we are in the middle of a chunk, give
1300  as much as possible to the client (without
1301  crossing chunk boundaries) */
1302  processed =
1303  connection->current_chunk_size -
1304  connection->current_chunk_offset;
1305  if (processed > available)
1306  processed = available;
1307  if (available > processed)
1308  instant_retry = MHD_YES;
1309  }
1310  else
1311  {
1312  /* we need to read chunk boundaries */
1313  i = 0;
1314  while (i < available)
1315  {
1316  if ((buffer_head[i] == '\r') || (buffer_head[i] == '\n'))
1317  break;
1318  i++;
1319  if (i >= 6)
1320  break;
1321  }
1322  /* take '\n' into account; if '\n'
1323  is the unavailable character, we
1324  will need to wait until we have it
1325  before going further */
1326  if ((i + 1 >= available) &&
1327  !((i == 1) && (available == 2) && (buffer_head[0] == '0')))
1328  break; /* need more data... */
1329  malformed = (i >= 6);
1330  if (!malformed)
1331  {
1332  buffer_head[i] = '\0';
1333  malformed =
1334  (1 != SSCANF (buffer_head, "%X",
1335  &connection->current_chunk_size)) &&
1336  (1 != SSCANF (buffer_head, "%x",
1337  &connection->current_chunk_size));
1338  }
1339  if (malformed)
1340  {
1341  /* malformed encoding */
1342 #if HAVE_MESSAGES
1343  MHD_DLOG (connection->daemon,
1344  "Received malformed HTTP request (bad chunked encoding), closing connection.\n");
1345 #endif
1346  connection_close_error (connection);
1347  return;
1348  }
1349  i++;
1350  if ((i < available) &&
1351  ((buffer_head[i] == '\r') || (buffer_head[i] == '\n')))
1352  i++; /* skip 2nd part of line feed */
1353 
1354  buffer_head += i;
1355  available -= i;
1356  connection->current_chunk_offset = 0;
1357 
1358  if (available > 0)
1359  instant_retry = MHD_YES;
1360  if (connection->current_chunk_size == 0)
1361  {
1362  connection->remaining_upload_size = 0;
1363  break;
1364  }
1365  continue;
1366  }
1367  }
1368  else
1369  {
1370  /* no chunked encoding, give all to the client */
1371  processed = available;
1372  }
1373  used = processed;
1374  connection->client_aware = MHD_YES;
1375  if (MHD_NO ==
1376  connection->daemon->default_handler (connection->daemon->
1377  default_handler_cls,
1378  connection, connection->url,
1379  connection->method,
1380  connection->version,
1381  buffer_head, &processed,
1382  &connection->client_context))
1383  {
1384  /* serious internal error, close connection */
1385 #if HAVE_MESSAGES
1386  MHD_DLOG (connection->daemon,
1387  "Internal application error, closing connection.\n");
1388 #endif
1389  connection_close_error (connection);
1390  return;
1391  }
1392  if (processed > used)
1393  mhd_panic (mhd_panic_cls, __FILE__, __LINE__,
1394 #if HAVE_MESSAGES
1395  "API violation"
1396 #else
1397  NULL
1398 #endif
1399  );
1400  if (processed != 0)
1401  instant_retry = MHD_NO; /* client did not process everything */
1402  used -= processed;
1403  if (connection->have_chunked_upload == MHD_YES)
1404  connection->current_chunk_offset += used;
1405  /* dh left "processed" bytes in buffer for next time... */
1406  buffer_head += used;
1407  available -= used;
1408  if (connection->remaining_upload_size != MHD_SIZE_UNKNOWN)
1409  connection->remaining_upload_size -= used;
1410  }
1411  while (instant_retry == MHD_YES);
1412  if (available > 0)
1413  memmove (connection->read_buffer, buffer_head, available);
1414  connection->read_buffer_offset = available;
1415 }
1416 
1425 static int
1426 do_read (struct MHD_Connection *connection)
1427 {
1428  int bytes_read;
1429 
1430  if (connection->read_buffer_size == connection->read_buffer_offset)
1431  return MHD_NO;
1432 
1433  bytes_read = connection->recv_cls (connection,
1434  &connection->read_buffer
1435  [connection->read_buffer_offset],
1436  connection->read_buffer_size -
1437  connection->read_buffer_offset);
1438  if (bytes_read < 0)
1439  {
1440  if (errno == EINTR)
1441  return MHD_NO;
1442 #if HAVE_MESSAGES
1443 #if HTTPS_SUPPORT
1444  if (0 != (connection->daemon->options & MHD_USE_SSL))
1445  MHD_DLOG (connection->daemon,
1446  "Failed to receive data: %s\n",
1447  gnutls_strerror (bytes_read));
1448  else
1449 #endif
1450  MHD_DLOG (connection->daemon,
1451  "Failed to receive data: %s\n", STRERROR (errno));
1452 #endif
1453  connection_close_error (connection);
1454  return MHD_YES;
1455  }
1456  if (bytes_read == 0)
1457  {
1458  /* other side closed connection */
1459  connection->read_closed = MHD_YES;
1460  SHUTDOWN (connection->socket_fd, SHUT_RD);
1461  return MHD_YES;
1462  }
1463  connection->read_buffer_offset += bytes_read;
1464  return MHD_YES;
1465 }
1466 
1474 static int
1475 do_write (struct MHD_Connection *connection)
1476 {
1477  int ret;
1478 
1479  ret = connection->send_cls (connection,
1480  &connection->write_buffer
1481  [connection->write_buffer_send_offset],
1482  connection->write_buffer_append_offset
1483  - connection->write_buffer_send_offset);
1484 
1485  if (ret < 0)
1486  {
1487  if (errno == EINTR)
1488  return MHD_NO;
1489 #if HAVE_MESSAGES
1490 #if HTTPS_SUPPORT
1491  if (0 != (connection->daemon->options & MHD_USE_SSL))
1492  MHD_DLOG (connection->daemon,
1493  "Failed to send data: %s\n",
1494  gnutls_strerror (ret));
1495  else
1496 #endif
1497  MHD_DLOG (connection->daemon,
1498  "Failed to send data: %s\n", STRERROR (errno));
1499 #endif
1500  connection_close_error (connection);
1501  return MHD_YES;
1502  }
1503 #if DEBUG_SEND_DATA
1504  FPRINTF (stderr,
1505  "Sent response: `%.*s'\n",
1506  ret,
1507  &connection->write_buffer[connection->write_buffer_send_offset]);
1508 #endif
1509  connection->write_buffer_send_offset += ret;
1510  return MHD_YES;
1511 }
1512 
1518 static int
1519 check_write_done (struct MHD_Connection *connection,
1520  enum MHD_CONNECTION_STATE next_state)
1521 {
1522  if (connection->write_buffer_append_offset !=
1523  connection->write_buffer_send_offset)
1524  return MHD_NO;
1525  connection->write_buffer_append_offset = 0;
1526  connection->write_buffer_send_offset = 0;
1527  connection->state = next_state;
1528  MHD_pool_reallocate (connection->pool, connection->write_buffer,
1529  connection->write_buffer_size, 0);
1530  connection->write_buffer = NULL;
1531  connection->write_buffer_size = 0;
1532  return MHD_YES;
1533 }
1534 
1540 static int
1541 process_header_line (struct MHD_Connection *connection, char *line)
1542 {
1543  char *colon;
1544 
1545  /* line should be normal header line, find colon */
1546  colon = strstr (line, ":");
1547  if (colon == NULL)
1548  {
1549  /* error in header line, die hard */
1550 #if HAVE_MESSAGES
1551  MHD_DLOG (connection->daemon,
1552  "Received malformed line (no colon), closing connection.\n");
1553 #endif
1554  connection->state = MHD_CONNECTION_CLOSED;
1555  return MHD_NO;
1556  }
1557  /* zero-terminate header */
1558  colon[0] = '\0';
1559  colon++; /* advance to value */
1560  while ((colon[0] != '\0') && ((colon[0] == ' ') || (colon[0] == '\t')))
1561  colon++;
1562  /* we do the actual adding of the connection
1563  header at the beginning of the while
1564  loop since we need to be able to inspect
1565  the *next* header line (in case it starts
1566  with a space...) */
1567  connection->last = line;
1568  connection->colon = colon;
1569  return MHD_YES;
1570 }
1571 
1581 static int
1583  char *line, enum MHD_ValueKind kind)
1584 {
1585  char *last;
1586  char *tmp;
1587  size_t last_len;
1588  size_t tmp_len;
1589 
1590  last = connection->last;
1591  if ((line[0] == ' ') || (line[0] == '\t'))
1592  {
1593  /* value was continued on the next line, see
1594  http://www.jmarshall.com/easy/http/ */
1595  last_len = strlen (last);
1596  /* skip whitespace at start of 2nd line */
1597  tmp = line;
1598  while ((tmp[0] == ' ') || (tmp[0] == '\t'))
1599  tmp++;
1600  tmp_len = strlen (tmp);
1601  last = MHD_pool_reallocate (connection->pool,
1602  last,
1603  last_len + 1,
1604  last_len + tmp_len + 1);
1605  if (last == NULL)
1606  {
1607  transmit_error_response (connection,
1609  REQUEST_TOO_BIG);
1610  return MHD_NO;
1611  }
1612  memcpy (&last[last_len], tmp, tmp_len + 1);
1613  connection->last = last;
1614  return MHD_YES; /* possibly more than 2 lines... */
1615  }
1616  EXTRA_CHECK ((last != NULL) && (connection->colon != NULL));
1617  if ((MHD_NO == connection_add_header (connection,
1618  last, connection->colon, kind)))
1619  {
1621  REQUEST_TOO_BIG);
1622  return MHD_NO;
1623  }
1624  /* we still have the current line to deal with... */
1625  if (strlen (line) != 0)
1626  {
1627  if (MHD_NO == process_header_line (connection, line))
1628  {
1629  transmit_error_response (connection,
1631  return MHD_NO;
1632  }
1633  }
1634  return MHD_YES;
1635 }
1636 
1642 static void
1644 {
1645  const char *clen;
1646  unsigned MHD_LONG_LONG cval;
1647  struct MHD_Response *response;
1648  const char *enc;
1649 
1650  parse_cookie_header (connection);
1651  if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
1652  && (NULL != connection->version)
1653  && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
1654  && (NULL ==
1657  {
1658  /* die, http 1.1 request without host and we are pedantic */
1659  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1660  connection->read_closed = MHD_YES;
1661 #if HAVE_MESSAGES
1662  MHD_DLOG (connection->daemon,
1663  "Received `%s' request without `%s' header.\n",
1665 #endif
1666  EXTRA_CHECK (connection->response == NULL);
1667  response =
1671  MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
1672  MHD_destroy_response (response);
1673  return;
1674  }
1675 
1676  clen = MHD_lookup_connection_value (connection,
1679  if (clen != NULL)
1680  {
1681  if (1 != SSCANF (clen, "%" MHD_LONG_LONG_PRINTF "u", &cval))
1682  {
1683 #if HAVE_MESSAGES
1684  MHD_DLOG (connection->daemon,
1685  "Failed to parse `%s' header `%s', closing connection.\n",
1687 #endif
1688  connection->state = MHD_CONNECTION_CLOSED;
1689  return;
1690  }
1691  connection->remaining_upload_size = cval;
1692  }
1693  else
1694  {
1695  enc = MHD_lookup_connection_value (connection,
1698  if (NULL == enc)
1699  {
1700  /* this request (better) not have a body */
1701  connection->remaining_upload_size = 0;
1702  }
1703  else
1704  {
1706  if (0 == strcasecmp (enc, "chunked"))
1707  connection->have_chunked_upload = MHD_YES;
1708  }
1709  }
1710 }
1711 
1721 int
1723 {
1724  connection->last_activity = time (NULL);
1725  if (connection->state == MHD_CONNECTION_CLOSED)
1726  return MHD_NO;
1727  /* make sure "read" has a reasonable number of bytes
1728  in buffer to use per system call (if possible) */
1729  if (connection->read_buffer_offset + MHD_BUF_INC_SIZE >
1730  connection->read_buffer_size)
1731  try_grow_read_buffer (connection);
1732  if (MHD_NO == do_read (connection))
1733  return MHD_YES;
1734  while (1)
1735  {
1736 #if DEBUG_STATES
1737  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1738  __FUNCTION__, MHD_state_to_string (connection->state));
1739 #endif
1740  switch (connection->state)
1741  {
1742  case MHD_CONNECTION_INIT:
1751  /* nothing to do but default action */
1752  if (MHD_YES == connection->read_closed)
1753  {
1754  connection->state = MHD_CONNECTION_CLOSED;
1755  continue;
1756  }
1757  break;
1758  case MHD_CONNECTION_CLOSED:
1759  if (connection->socket_fd != -1)
1760  connection_close_error (connection);
1761  return MHD_NO;
1762  default:
1763  /* shrink read buffer to how much is actually used */
1764  MHD_pool_reallocate (connection->pool,
1765  connection->read_buffer,
1766  connection->read_buffer_size + 1,
1767  connection->read_buffer_offset);
1768  break;
1769  }
1770  break;
1771  }
1772  return MHD_YES;
1773 }
1774 
1784 int
1786 {
1787  struct MHD_Response *response;
1788  int ret;
1789  connection->last_activity = time (NULL);
1790  while (1)
1791  {
1792 #if DEBUG_STATES
1793  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1794  __FUNCTION__, MHD_state_to_string (connection->state));
1795 #endif
1796  switch (connection->state)
1797  {
1798  case MHD_CONNECTION_INIT:
1802  EXTRA_CHECK (0);
1803  break;
1805  break;
1807  ret = connection->send_cls (connection,
1809  [connection->continue_message_write_offset],
1810  strlen (HTTP_100_CONTINUE) -
1811  connection->continue_message_write_offset);
1812  if (ret < 0)
1813  {
1814  if (errno == EINTR)
1815  break;
1816 #if HAVE_MESSAGES
1817  MHD_DLOG (connection->daemon,
1818  "Failed to send data: %s\n", STRERROR (errno));
1819 #endif
1820  connection_close_error (connection);
1821  return MHD_NO;
1822  }
1823 #if DEBUG_SEND_DATA
1824  FPRINTF (stderr,
1825  "Sent 100 continue response: `%.*s'\n",
1826  ret,
1828  [connection->continue_message_write_offset]);
1829 #endif
1830  connection->continue_message_write_offset += ret;
1831  break;
1836  EXTRA_CHECK (0);
1837  break;
1839  do_write (connection);
1841  break;
1843  EXTRA_CHECK (0);
1844  break;
1846  response = connection->response;
1847  if (response->crc != NULL)
1848  pthread_mutex_lock (&response->mutex);
1849  if (MHD_YES != try_ready_normal_body (connection))
1850  {
1851  if (response->crc != NULL)
1852  pthread_mutex_unlock (&response->mutex);
1854  break;
1855  }
1856  ret = connection->send_cls (connection,
1857  &response->data
1858  [connection->response_write_position
1859  - response->data_start],
1860  response->data_size -
1861  (connection->response_write_position
1862  - response->data_start));
1863 #if DEBUG_SEND_DATA
1864  if (ret > 0)
1865  FPRINTF (stderr,
1866  "Sent DATA response: `%.*s'\n",
1867  ret,
1868  &response->data[connection->response_write_position -
1869  response->data_start]);
1870 #endif
1871  if (response->crc != NULL)
1872  pthread_mutex_unlock (&response->mutex);
1873  if (ret < 0)
1874  {
1875  if (errno == EINTR)
1876  return MHD_YES;
1877 #if HAVE_MESSAGES
1878  MHD_DLOG (connection->daemon,
1879  "Failed to send data: %s\n", STRERROR (errno));
1880 #endif
1881  connection_close_error (connection);
1882  return MHD_NO;
1883  }
1884  connection->response_write_position += ret;
1885  if (connection->response_write_position ==
1886  connection->response->total_size)
1887  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers... */
1888  break;
1890  EXTRA_CHECK (0);
1891  break;
1893  do_write (connection);
1894  check_write_done (connection,
1895  (connection->response->total_size ==
1896  connection->response_write_position) ?
1899  break;
1900  case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
1902  EXTRA_CHECK (0);
1903  break;
1905  do_write (connection);
1907  break;
1909  EXTRA_CHECK (0);
1910  break;
1911  case MHD_CONNECTION_CLOSED:
1912  if (connection->socket_fd != -1)
1913  connection_close_error (connection);
1914  return MHD_NO;
1916  EXTRA_CHECK (0);
1917  break;
1918  default:
1919  EXTRA_CHECK (0);
1920  connection_close_error (connection);
1921  return MHD_NO;
1922  }
1923  break;
1924  }
1925  return MHD_YES;
1926 }
1927 
1937 int
1939 {
1940  unsigned int timeout;
1941  const char *end;
1942  char *line;
1943 
1944  while (1)
1945  {
1946 #if DEBUG_STATES
1947  MHD_DLOG (connection->daemon, "%s: state: %s\n",
1948  __FUNCTION__, MHD_state_to_string (connection->state));
1949 #endif
1950  switch (connection->state)
1951  {
1952  case MHD_CONNECTION_INIT:
1953  line = get_next_header_line (connection);
1954  if (line == NULL)
1955  {
1956  if (connection->state != MHD_CONNECTION_INIT)
1957  continue;
1958  if (connection->read_closed)
1959  {
1960  connection->state = MHD_CONNECTION_CLOSED;
1961  continue;
1962  }
1963  break;
1964  }
1965  if (MHD_NO == parse_initial_message_line (connection, line))
1966  connection->state = MHD_CONNECTION_CLOSED;
1967  else
1968  connection->state = MHD_CONNECTION_URL_RECEIVED;
1969  continue;
1971  line = get_next_header_line (connection);
1972  if (line == NULL)
1973  {
1974  if (connection->state != MHD_CONNECTION_URL_RECEIVED)
1975  continue;
1976  if (connection->read_closed)
1977  {
1978  connection->state = MHD_CONNECTION_CLOSED;
1979  continue;
1980  }
1981  break;
1982  }
1983  if (strlen (line) == 0)
1984  {
1985  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
1986  continue;
1987  }
1988  if (MHD_NO == process_header_line (connection, line))
1989  {
1990  transmit_error_response (connection,
1993  break;
1994  }
1996  continue;
1998  line = get_next_header_line (connection);
1999  if (line == NULL)
2000  {
2001  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2002  continue;
2003  if (connection->read_closed)
2004  {
2005  connection->state = MHD_CONNECTION_CLOSED;
2006  continue;
2007  }
2008  break;
2009  }
2010  if (MHD_NO ==
2011  process_broken_line (connection, line, MHD_HEADER_KIND))
2012  continue;
2013  if (strlen (line) == 0)
2014  {
2015  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2016  continue;
2017  }
2018  continue;
2020  parse_connection_headers (connection);
2021  if (connection->state == MHD_CONNECTION_CLOSED)
2022  continue;
2024  continue;
2026  call_connection_handler (connection); /* first call */
2027  if (connection->state == MHD_CONNECTION_CLOSED)
2028  continue;
2029  if (need_100_continue (connection))
2030  {
2031  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
2032  break;
2033  }
2034  if (connection->response != NULL)
2035  {
2036  /* we refused (no upload allowed!) */
2037  connection->remaining_upload_size = 0;
2038  /* force close, in case client still tries to upload... */
2039  connection->read_closed = MHD_YES;
2040  }
2041  connection->state = (connection->remaining_upload_size == 0)
2043  continue;
2045  if (connection->continue_message_write_offset ==
2046  strlen (HTTP_100_CONTINUE))
2047  {
2048  connection->state = MHD_CONNECTION_CONTINUE_SENT;
2049  continue;
2050  }
2051  break;
2053  if (connection->read_buffer_offset != 0)
2054  {
2055  process_request_body (connection); /* loop call */
2056  if (connection->state == MHD_CONNECTION_CLOSED)
2057  continue;
2058  }
2059  if ((connection->remaining_upload_size == 0) ||
2060  ((connection->remaining_upload_size == MHD_SIZE_UNKNOWN) &&
2061  (connection->read_buffer_offset == 0) &&
2062  (MHD_YES == connection->read_closed)))
2063  {
2064  if ((MHD_YES == connection->have_chunked_upload) &&
2065  (MHD_NO == connection->read_closed))
2066  connection->state = MHD_CONNECTION_BODY_RECEIVED;
2067  else
2068  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2069  continue;
2070  }
2071  break;
2073  line = get_next_header_line (connection);
2074  if (line == NULL)
2075  {
2076  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
2077  continue;
2078  if (connection->read_closed)
2079  {
2080  connection->state = MHD_CONNECTION_CLOSED;
2081  continue;
2082  }
2083  break;
2084  }
2085  if (strlen (line) == 0)
2086  {
2087  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2088  continue;
2089  }
2090  if (MHD_NO == process_header_line (connection, line))
2091  {
2092  transmit_error_response (connection,
2095  break;
2096  }
2098  continue;
2100  line = get_next_header_line (connection);
2101  if (line == NULL)
2102  {
2103  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
2104  continue;
2105  if (connection->read_closed)
2106  {
2107  connection->state = MHD_CONNECTION_CLOSED;
2108  continue;
2109  }
2110  break;
2111  }
2112  if (MHD_NO ==
2113  process_broken_line (connection, line, MHD_FOOTER_KIND))
2114  continue;
2115  if (strlen (line) == 0)
2116  {
2117  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2118  continue;
2119  }
2120  continue;
2122  call_connection_handler (connection); /* "final" call */
2123  if (connection->state == MHD_CONNECTION_CLOSED)
2124  continue;
2125  if (connection->response == NULL)
2126  break; /* try again next time */
2127  if (MHD_NO == build_header_response (connection))
2128  {
2129  /* oops - close! */
2130 #if HAVE_MESSAGES
2131  MHD_DLOG (connection->daemon,
2132  "Closing connection (failed to create response header)\n");
2133 #endif
2134  connection->state = MHD_CONNECTION_CLOSED;
2135  continue;
2136  }
2137  connection->state = MHD_CONNECTION_HEADERS_SENDING;
2138 
2139 #if HAVE_DECL_TCP_CORK
2140  /* starting header send, set TCP cork */
2141  {
2142  const int val = 1;
2143  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2144  sizeof (val));
2145  }
2146 #endif
2147  break;
2149  /* no default action */
2150  break;
2152  if (connection->have_chunked_upload)
2154  else
2156  continue;
2158  /* nothing to do here */
2159  break;
2161  if (connection->response->crc != NULL)
2162  pthread_mutex_lock (&connection->response->mutex);
2163  if (MHD_YES == try_ready_normal_body (connection))
2164  {
2165  if (connection->response->crc != NULL)
2166  pthread_mutex_unlock (&connection->response->mutex);
2168  break;
2169  }
2170  if (connection->response->crc != NULL)
2171  pthread_mutex_unlock (&connection->response->mutex);
2172  /* not ready, no socket action */
2173  break;
2175  /* nothing to do here */
2176  break;
2178  if (connection->response->crc != NULL)
2179  pthread_mutex_lock (&connection->response->mutex);
2180  if (MHD_YES == try_ready_chunked_body (connection))
2181  {
2182  if (connection->response->crc != NULL)
2183  pthread_mutex_unlock (&connection->response->mutex);
2185  continue;
2186  }
2187  if (connection->response->crc != NULL)
2188  pthread_mutex_unlock (&connection->response->mutex);
2189  break;
2191  build_header_response (connection);
2192  if (connection->write_buffer_send_offset ==
2193  connection->write_buffer_append_offset)
2194  connection->state = MHD_CONNECTION_FOOTERS_SENT;
2195  else
2196  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
2197  continue;
2199  /* no default action */
2200  break;
2202 #if HAVE_DECL_TCP_CORK
2203  /* done sending, uncork */
2204  {
2205  const int val = 0;
2206  setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
2207  sizeof (val));
2208  }
2209 #endif
2210  MHD_destroy_response (connection->response);
2211  connection->response = NULL;
2212  if (connection->daemon->notify_completed != NULL)
2213  connection->daemon->notify_completed (connection->daemon->
2214  notify_completed_cls,
2215  connection,
2216  &connection->client_context,
2218  connection->client_aware = MHD_NO;
2219  end =
2222  connection->client_context = NULL;
2223  connection->continue_message_write_offset = 0;
2224  connection->responseCode = 0;
2225  connection->headers_received = NULL;
2226  connection->response_write_position = 0;
2227  connection->have_chunked_upload = MHD_NO;
2228  connection->method = NULL;
2229  connection->url = NULL;
2230  connection->write_buffer = NULL;
2231  connection->write_buffer_size = 0;
2232  connection->write_buffer_send_offset = 0;
2233  connection->write_buffer_append_offset = 0;
2234  if ((end != NULL) && (0 == strcasecmp (end, "close")))
2235  {
2236  connection->read_closed = MHD_YES;
2237  connection->read_buffer_offset = 0;
2238  }
2239  if (((MHD_YES == connection->read_closed) &&
2240  (0 == connection->read_buffer_offset)) ||
2241  (connection->version == NULL) ||
2242  (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
2243  {
2244  /* http 1.0, version-less requests cannot be pipelined */
2245  connection->state = MHD_CONNECTION_CLOSED;
2246  MHD_pool_destroy (connection->pool);
2247  connection->pool = NULL;
2248  connection->read_buffer = NULL;
2249  connection->read_buffer_size = 0;
2250  connection->read_buffer_offset = 0;
2251  }
2252  else
2253  {
2254  connection->version = NULL;
2255  connection->state = MHD_CONNECTION_INIT;
2256  connection->read_buffer
2257  = MHD_pool_reset (connection->pool,
2258  connection->read_buffer,
2259  connection->read_buffer_size);
2260  }
2261  continue;
2262  case MHD_CONNECTION_CLOSED:
2263  if (connection->socket_fd != -1)
2264  connection_close_error (connection);
2265  break;
2266  default:
2267  EXTRA_CHECK (0);
2268  break;
2269  }
2270  break;
2271  }
2272  timeout = connection->daemon->connection_timeout;
2273  if ((connection->socket_fd != -1) &&
2274  (timeout != 0) &&
2275  (timeout < (time (NULL) - connection->last_activity)) )
2276  {
2278  return MHD_NO;
2279  }
2280  return MHD_YES;
2281 }
2282 
2283 
2284 void
2286 {
2290 }
2291 
2292 
2302 const union MHD_ConnectionInfo *
2304  enum MHD_ConnectionInfoType infoType, ...)
2305 {
2306  switch (infoType)
2307  {
2308 #if HTTPS_SUPPORT
2310  if (connection->tls_session == NULL)
2311  return NULL;
2312  connection->cipher = gnutls_cipher_get (connection->tls_session);
2313  return (const union MHD_ConnectionInfo *) &connection->cipher;
2315  if (connection->tls_session == NULL)
2316  return NULL;
2317  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
2318  return (const union MHD_ConnectionInfo *) &connection->protocol;
2320  if (connection->tls_session == NULL)
2321  return NULL;
2322  return (const union MHD_ConnectionInfo *) &connection->tls_session;
2323 #endif
2325  return (const union MHD_ConnectionInfo *) &connection->addr;
2326  default:
2327  return NULL;
2328  };
2329 }
2330 
2331 
2332 /* end of connection.c */