GNU libmicrohttpd  0.9.29
connection.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2017 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 */
28 #include "internal.h"
29 #include "mhd_limits.h"
30 #include "connection.h"
31 #include "memorypool.h"
32 #include "response.h"
33 #include "mhd_mono_clock.h"
34 #include "mhd_str.h"
35 #include "mhd_locks.h"
36 #include "mhd_sockets.h"
37 #include "mhd_compat.h"
38 #include "mhd_itc.h"
39 #ifdef HTTPS_SUPPORT
40 #include "connection_https.h"
41 #endif /* HTTPS_SUPPORT */
42 
43 
47 #define HTTP_100_CONTINUE "HTTP/1.1 100 Continue\r\n\r\n"
48 
56 #ifdef HAVE_MESSAGES
57 #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>"
58 #else
59 #define REQUEST_TOO_BIG ""
60 #endif
61 
69 #ifdef HAVE_MESSAGES
70 #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>"
71 #else
72 #define REQUEST_LACKS_HOST ""
73 #endif
74 
82 #ifdef HAVE_MESSAGES
83 #define REQUEST_MALFORMED "<html><head><title>Request malformed</title></head><body>Your HTTP request was syntactically incorrect.</body></html>"
84 #else
85 #define REQUEST_MALFORMED ""
86 #endif
87 
94 #ifdef HAVE_MESSAGES
95 #define INTERNAL_ERROR "<html><head><title>Internal server error</title></head><body>Please ask the developer of this Web server to carefully read the GNU libmicrohttpd documentation about connection management and blocking.</body></html>"
96 #else
97 #define INTERNAL_ERROR ""
98 #endif
99 
104 #define DEBUG_CLOSE MHD_NO
105 
109 #define DEBUG_SEND_DATA MHD_NO
110 
111 
131 static int
133 {
134 #if defined(TCP_CORK) || defined(TCP_PUSH)
135  return MHD_YES;
136 #else /* !TCP_CORK && !TCP_PUSH */
137  return MHD_NO;
138 #endif /* !TCP_CORK && !TCP_PUSH */
139 }
140 
141 
149 static int
151 {
152  int res = MHD_NO;
153 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
154  const MHD_SCKT_OPT_BOOL_ on_val = 1;
155 #if defined(TCP_NODELAY)
156  const MHD_SCKT_OPT_BOOL_ off_val = 0;
157 #endif /* TCP_NODELAY */
158  if (!connection)
159  return MHD_NO;
160 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
161  /* Buffer data before sending */
162  res = (0 == setsockopt (connection->socket_fd,
163  IPPROTO_TCP,
164  TCP_NOPUSH,
165  (const void *) &on_val,
166  sizeof (on_val)))
167  ? MHD_YES : MHD_NO;
168 #if defined(TCP_NODELAY)
169  /* Enable Nagle's algorithm */
170  /* TCP_NODELAY may interfere with TCP_NOPUSH */
171  res &= (0 == setsockopt (connection->socket_fd,
172  IPPROTO_TCP,
173  TCP_NODELAY,
174  (const void *) &off_val,
175  sizeof (off_val)))
176  ? MHD_YES : MHD_NO;
177 #endif /* TCP_NODELAY */
178 #else /* TCP_CORK */
179 #if defined(TCP_NODELAY)
180  /* Enable Nagle's algorithm */
181  /* TCP_NODELAY may prevent enabling TCP_CORK. Resulting buffering mode depends
182  solely on TCP_CORK result, so ignoring return code here. */
183  (void) setsockopt (connection->socket_fd,
184  IPPROTO_TCP,
185  TCP_NODELAY,
186  (const void *) &off_val,
187  sizeof (off_val));
188 #endif /* TCP_NODELAY */
189  /* Send only full packets */
190  res = (0 == setsockopt (connection->socket_fd,
191  IPPROTO_TCP,
192  TCP_CORK,
193  (const void *) &on_val,
194  sizeof (on_val)))
195  ? MHD_YES : MHD_NO;
196 #endif /* TCP_CORK */
197 #endif /* TCP_CORK || TCP_NOPUSH */
198  return res;
199 }
200 
201 
208 static int
210 {
211 #if defined(TCP_NODELAY)
212  int res = MHD_YES;
213  const MHD_SCKT_OPT_BOOL_ on_val = 1;
214 #if defined(TCP_CORK) || defined(TCP_NOPUSH)
215  const MHD_SCKT_OPT_BOOL_ off_val = 0;
216 #endif /* TCP_CORK || TCP_NOPUSH */
217 
218  if (NULL == connection)
219  return MHD_NO;
220 #if defined(TCP_CORK)
221  /* Allow partial packets */
222  res &= (0 == setsockopt (connection->socket_fd,
223  IPPROTO_TCP,
224  TCP_CORK,
225  (const void *) &off_val,
226  sizeof (off_val)))
227  ? MHD_YES : MHD_NO;
228 #endif /* TCP_CORK */
229 #if defined(TCP_NODELAY)
230  /* Disable Nagle's algorithm for sending packets without delay */
231  res &= (0 == setsockopt (connection->socket_fd,
232  IPPROTO_TCP,
233  TCP_NODELAY,
234  (const void *) &on_val,
235  sizeof (on_val)))
236  ? MHD_YES : MHD_NO;
237 #endif /* TCP_NODELAY */
238 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
239  /* Disable extra buffering */
240  res &= (0 == setsockopt (connection->socket_fd,
241  IPPROTO_TCP,
242  TCP_NOPUSH,
243  (const void *) &off_val,
244  sizeof (off_val)))
245  ? MHD_YES : MHD_NO;
246 #endif /* TCP_NOPUSH && !TCP_CORK */
247  return res;
248 #else /* !TCP_NODELAY */
249  return MHD_NO;
250 #endif /* !TCP_NODELAY */
251 }
252 
253 
261 static int
263 {
264  int res = MHD_YES;
265 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
266  const int dummy = 0;
267 #endif /* !TCP_CORK */
268 
269  if (NULL == connection)
270  return MHD_NO;
271  res = socket_start_no_buffering (connection);
272 #if defined(TCP_NOPUSH) && !defined(TCP_CORK)
273  /* Force flush data with zero send otherwise Darwin and some BSD systems
274  will add 5 seconds delay. Not required with TCP_CORK as switching off
275  TCP_CORK always flushes socket buffer. */
276  res &= (0 <= MHD_send_ (connection->socket_fd,
277  &dummy,
278  0))
279  ? MHD_YES : MHD_NO;
280 #endif /* TCP_NOPUSH && !TCP_CORK*/
281  return res;
282 }
283 
284 
291 static int
293 {
294 #if defined(TCP_NODELAY)
295  int res = MHD_YES;
296  const MHD_SCKT_OPT_BOOL_ off_val = 0;
297 #if defined(TCP_CORK)
298  MHD_SCKT_OPT_BOOL_ cork_val = 0;
299  socklen_t param_size = sizeof (cork_val);
300 #endif /* TCP_CORK */
301  if (!connection)
302  return MHD_NO;
303 #if defined(TCP_CORK)
304  /* Allow partial packets */
305  /* Disabling TCP_CORK will flush partial packet even if TCP_CORK wasn't enabled before
306  so try to check current value of TCP_CORK to prevent unrequested flushing */
307  if ( (0 != getsockopt (connection->socket_fd,
308  IPPROTO_TCP,
309  TCP_CORK,
310  (void*)&cork_val,
311  &param_size)) ||
312  (0 != cork_val))
313  res &= (0 == setsockopt (connection->socket_fd,
314  IPPROTO_TCP,
315  TCP_CORK,
316  (const void *) &off_val,
317  sizeof (off_val)))
318  ? MHD_YES : MHD_NO;
319 #elif defined(TCP_NOPUSH)
320  /* Disable extra buffering */
321  /* No need to check current value as disabling TCP_NOPUSH will not flush partial
322  packet if TCP_NOPUSH wasn't enabled before */
323  res &= (0 == setsockopt (connection->socket_fd,
324  IPPROTO_TCP,
325  TCP_NOPUSH,
326  (const void *) &off_val,
327  sizeof (off_val)))
328  ? MHD_YES : MHD_NO;
329 #endif /* TCP_NOPUSH && !TCP_CORK */
330  /* Enable Nagle's algorithm for normal buffering */
331  res &= (0 == setsockopt (connection->socket_fd,
332  IPPROTO_TCP,
333  TCP_NODELAY,
334  (const void *) &off_val,
335  sizeof (off_val)))
336  ? MHD_YES : MHD_NO;
337  return res;
338 #else /* !TCP_NODELAY */
339  return MHD_NO;
340 #endif /* !TCP_NODELAY */
341 }
342 
343 
355 int
357  enum MHD_ValueKind kind,
358  MHD_KeyValueIterator iterator,
359  void *iterator_cls)
360 {
361  int ret;
362  struct MHD_HTTP_Header *pos;
363 
364  if (NULL == connection)
365  return -1;
366  ret = 0;
367  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
368  if (0 != (pos->kind & kind))
369  {
370  ret++;
371  if ( (NULL != iterator) &&
372  (MHD_YES != iterator (iterator_cls,
373  pos->kind,
374  pos->header,
375  pos->value)) )
376  return ret;
377  }
378  return ret;
379 }
380 
381 
407 int
409  enum MHD_ValueKind kind,
410  const char *key,
411  const char *value)
412 {
413  struct MHD_HTTP_Header *pos;
414 
415  pos = MHD_pool_allocate (connection->pool,
416  sizeof (struct MHD_HTTP_Header),
417  MHD_YES);
418  if (NULL == pos)
419  return MHD_NO;
420  pos->header = (char *) key;
421  pos->value = (char *) value;
422  pos->kind = kind;
423  pos->next = NULL;
424  /* append 'pos' to the linked list of headers */
425  if (NULL == connection->headers_received_tail)
426  {
427  connection->headers_received = pos;
428  connection->headers_received_tail = pos;
429  }
430  else
431  {
432  connection->headers_received_tail->next = pos;
433  connection->headers_received_tail = pos;
434  }
435  return MHD_YES;
436 }
437 
438 
449 const char *
451  enum MHD_ValueKind kind,
452  const char *key)
453 {
454  struct MHD_HTTP_Header *pos;
455 
456  if (NULL == connection)
457  return NULL;
458  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
459  if ((0 != (pos->kind & kind)) &&
460  ( (key == pos->header) ||
461  ( (NULL != pos->header) &&
462  (NULL != key) &&
464  pos->header)))))
465  return pos->value;
466  return NULL;
467 }
468 
469 
483 static bool
484 MHD_lookup_header_token_ci (const struct MHD_Connection *connection,
485  const char *header,
486  const char *token,
487  size_t token_len)
488 {
489  struct MHD_HTTP_Header *pos;
490 
491  if (NULL == connection || NULL == header || 0 == header[0] || NULL == token || 0 == token[0])
492  return false;
493  for (pos = connection->headers_received; NULL != pos; pos = pos->next)
494  {
495  if ((0 != (pos->kind & MHD_HEADER_KIND)) &&
496  ( (header == pos->header) ||
497  (MHD_str_equal_caseless_(header,
498  pos->header)) ) &&
499  (MHD_str_has_token_caseless_ (pos->value, token, token_len)))
500  return true;
501  }
502  return false;
503 }
504 
505 
517 #define MHD_lookup_header_s_token_ci(c,h,tkn) \
518  MHD_lookup_header_token_ci((c),(h),(tkn),MHD_STATICSTR_LEN_(tkn))
519 
520 
528 static int
529 need_100_continue (struct MHD_Connection *connection)
530 {
531  const char *expect;
532 
533  return ( (NULL == connection->response) &&
534  (NULL != connection->version) &&
535  (MHD_str_equal_caseless_(connection->version,
537  (NULL != (expect = MHD_lookup_connection_value (connection,
540  (MHD_str_equal_caseless_(expect,
541  "100-continue")) &&
542  (connection->continue_message_write_offset <
544 }
545 
546 
553 void
555 {
556  const struct MHD_Daemon *daemon = connection->daemon;
557 
558  connection->state = MHD_CONNECTION_CLOSED;
560  if (0 == (daemon->options & MHD_USE_TURBO))
561  {
562 #ifdef HTTPS_SUPPORT
563  /* For TLS connection use shutdown of TLS layer
564  * and do not shutdown TCP socket. This give more
565  * chances to send TLS closure data to remote side.
566  * Closure of TLS layer will be interpreted by
567  * remote side as end of transmission. */
568  if (0 != (daemon->options & MHD_USE_TLS))
569  {
570  if (MHD_NO == MHD_tls_connection_shutdown(connection))
571  shutdown (connection->socket_fd,
572  SHUT_WR);
573  }
574  else /* Combined with next 'shutdown()'. */
575 #endif /* HTTPS_SUPPORT */
576  shutdown (connection->socket_fd,
577  SHUT_WR);
578  }
579 }
580 
581 
591 void
593  enum MHD_RequestTerminationCode termination_code)
594 {
595  struct MHD_Daemon *daemon = connection->daemon;
596  struct MHD_Response *resp = connection->response;
597 
598  MHD_connection_mark_closed_ (connection);
599  if (NULL != resp)
600  {
601  connection->response = NULL;
602  MHD_destroy_response (resp);
603  }
604  if ( (NULL != daemon->notify_completed) &&
605  (connection->client_aware) )
606  daemon->notify_completed (daemon->notify_completed_cls,
607  connection,
608  &connection->client_context,
609  termination_code);
610  connection->client_aware = false;
611 }
612 
613 
614 #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
615 
625 void
627 {
628  struct MHD_Daemon *daemon = connection->daemon;
629  struct MHD_UpgradeResponseHandle *urh = connection->urh;
630 
631  if (0 == (daemon->options & MHD_USE_TLS))
632  return; /* Nothing to do with non-TLS connection. */
633 
634  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
635  DLL_remove (daemon->urh_head,
636  daemon->urh_tail,
637  urh);
638 #if EPOLL_SUPPORT
639  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
640  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
641  EPOLL_CTL_DEL,
642  connection->socket_fd,
643  NULL)) )
644  {
645  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
646  }
647  if (urh->in_eready_list)
648  {
649  EDLL_remove (daemon->eready_urh_head,
650  daemon->eready_urh_tail,
651  urh);
652  urh->in_eready_list = false;
653  }
654 #endif /* EPOLL_SUPPORT */
655  if (MHD_INVALID_SOCKET != urh->mhd.socket)
656  {
657 #if EPOLL_SUPPORT
658  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
659  (0 != epoll_ctl (daemon->epoll_upgrade_fd,
660  EPOLL_CTL_DEL,
661  urh->mhd.socket,
662  NULL)) )
663  {
664  MHD_PANIC (_("Failed to remove FD from epoll set\n"));
665  }
666 #endif /* EPOLL_SUPPORT */
667  /* Reflect remote disconnect to application by breaking
668  * socketpair connection. */
669  shutdown (urh->mhd.socket, SHUT_RDWR);
670  }
671  /* Socketpair sockets will remain open as they will be
672  * used with MHD_UPGRADE_ACTION_CLOSE. They will be
673  * closed by MHD_cleanup_upgraded_connection_() during
674  * connection's final cleanup.
675  */
676 }
677 #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT*/
678 
679 
687 static void
689  const char *emsg)
690 {
691 #ifdef HAVE_MESSAGES
692  if (NULL != emsg)
693  MHD_DLOG (connection->daemon,
694  emsg);
695 #endif
696  MHD_connection_close_ (connection,
698 }
699 
700 
705 #ifdef HAVE_MESSAGES
706 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, emsg)
707 #else
708 #define CONNECTION_CLOSE_ERROR(c, emsg) connection_close_error (c, NULL)
709 #endif
710 
711 
724 static int
726 {
727  ssize_t ret;
728  struct MHD_Response *response;
729 
730  response = connection->response;
731  if (NULL == response->crc)
732  return MHD_YES;
733  if ( (0 == response->total_size) ||
734  (connection->response_write_position == response->total_size) )
735  return MHD_YES; /* 0-byte response is always ready */
736  if ( (response->data_start <=
737  connection->response_write_position) &&
738  (response->data_size + response->data_start >
739  connection->response_write_position) )
740  return MHD_YES; /* response already ready */
741 #if LINUX
742  if (MHD_resp_sender_sendfile == connection->resp_sender)
743  {
744  /* will use sendfile, no need to bother response crc */
745  return MHD_YES;
746  }
747 #endif
748 
749  ret = response->crc (response->crc_cls,
750  connection->response_write_position,
751  response->data,
752  (size_t) MHD_MIN ((uint64_t)response->data_buffer_size,
753  response->total_size -
754  connection->response_write_position));
755  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
756  (((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret) )
757  {
758  /* either error or http 1.0 transfer, close socket! */
759  response->total_size = connection->response_write_position;
760  MHD_mutex_unlock_chk_ (&response->mutex);
761  if ( ((ssize_t)MHD_CONTENT_READER_END_OF_STREAM) == ret)
762  MHD_connection_close_ (connection,
764  else
765  CONNECTION_CLOSE_ERROR (connection,
766  _("Closing connection (application reported error generating data)\n"));
767  return MHD_NO;
768  }
769  response->data_start = connection->response_write_position;
770  response->data_size = ret;
771  if (0 == ret)
772  {
774  MHD_mutex_unlock_chk_ (&response->mutex);
775  return MHD_NO;
776  }
777  return MHD_YES;
778 }
779 
780 
790 static int
792 {
793  ssize_t ret;
794  char *buf;
795  struct MHD_Response *response;
796  size_t size;
797  char cbuf[10]; /* 10: max strlen of "%x\r\n" */
798  int cblen;
799 
800  response = connection->response;
801  if (0 == connection->write_buffer_size)
802  {
803  size = MHD_MIN (connection->daemon->pool_size,
804  2 * (0xFFFFFF + sizeof(cbuf) + 2));
805  do
806  {
807  size /= 2;
808  if (size < 128)
809  {
810  /* not enough memory */
811  CONNECTION_CLOSE_ERROR (connection,
812  _("Closing connection (out of memory)\n"));
813  return MHD_NO;
814  }
815  buf = MHD_pool_allocate (connection->pool,
816  size,
817  MHD_NO);
818  }
819  while (NULL == buf);
820  connection->write_buffer_size = size;
821  connection->write_buffer = buf;
822  }
823 
824  if (0 == response->total_size)
825  ret = 0; /* response must be empty, don't bother calling crc */
826  else if ( (response->data_start <=
827  connection->response_write_position) &&
828  (response->data_start + response->data_size >
829  connection->response_write_position) )
830  {
831  /* difference between response_write_position and data_start is less
832  than data_size which is size_t type, no need to check for overflow */
833  const size_t data_write_offset
834  = (size_t)(connection->response_write_position - response->data_start);
835  /* buffer already ready, use what is there for the chunk */
836  ret = response->data_size - data_write_offset;
837  if ( ((size_t) ret) > connection->write_buffer_size - sizeof (cbuf) - 2 )
838  ret = connection->write_buffer_size - sizeof (cbuf) - 2;
839  memcpy (&connection->write_buffer[sizeof (cbuf)],
840  &response->data[data_write_offset],
841  ret);
842  }
843  else
844  {
845  /* buffer not in range, try to fill it */
846  ret = response->crc (response->crc_cls,
847  connection->response_write_position,
848  &connection->write_buffer[sizeof (cbuf)],
849  connection->write_buffer_size - sizeof (cbuf) - 2);
850  }
851  if ( ((ssize_t) MHD_CONTENT_READER_END_WITH_ERROR) == ret)
852  {
853  /* error, close socket! */
854  response->total_size = connection->response_write_position;
855  CONNECTION_CLOSE_ERROR (connection,
856  _("Closing connection (application error generating response)\n"));
857  return MHD_NO;
858  }
859  if ( (((ssize_t) MHD_CONTENT_READER_END_OF_STREAM) == ret) ||
860  (0 == response->total_size) )
861  {
862  /* end of message, signal other side! */
863  strcpy (connection->write_buffer,
864  "0\r\n");
865  connection->write_buffer_append_offset = 3;
866  connection->write_buffer_send_offset = 0;
867  response->total_size = connection->response_write_position;
868  return MHD_YES;
869  }
870  if (0 == ret)
871  {
873  return MHD_NO;
874  }
875  if (ret > 0xFFFFFF)
876  ret = 0xFFFFFF;
877  cblen = MHD_snprintf_(cbuf,
878  sizeof (cbuf),
879  "%X\r\n",
880  (unsigned int) ret);
881  EXTRA_CHECK(cblen > 0);
882  EXTRA_CHECK(cblen < sizeof(cbuf));
883  memcpy (&connection->write_buffer[sizeof (cbuf) - cblen],
884  cbuf,
885  cblen);
886  memcpy (&connection->write_buffer[sizeof (cbuf) + ret],
887  "\r\n",
888  2);
889  connection->response_write_position += ret;
890  connection->write_buffer_send_offset = sizeof (cbuf) - cblen;
891  connection->write_buffer_append_offset = sizeof (cbuf) + ret + 2;
892  return MHD_YES;
893 }
894 
895 
912 static int
913 keepalive_possible (struct MHD_Connection *connection)
914 {
915  if (MHD_CONN_MUST_CLOSE == connection->keepalive)
916  return MHD_NO;
917  if (NULL == connection->version)
918  return MHD_NO;
919  if ( (NULL != connection->response) &&
920  (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
921  return MHD_NO;
922 
923  if (MHD_str_equal_caseless_(connection->version,
925  {
926  if (MHD_lookup_header_s_token_ci (connection,
928  "upgrade"))
929  {
930 #ifdef UPGRADE_SUPPORT
931  if ( (NULL == connection->response) ||
932  (NULL == connection->response->upgrade_handler) )
933 #endif /* UPGRADE_SUPPORT */
934  return MHD_NO;
935  }
936  if (MHD_lookup_header_s_token_ci (connection,
938  "close"))
939  return MHD_NO;
940 
941  return MHD_YES;
942  }
943  if (MHD_str_equal_caseless_(connection->version,
945  {
946  if (MHD_lookup_header_s_token_ci (connection,
948  "Keep-Alive"))
949  return MHD_YES;
950 
951  return MHD_NO;
952  }
953  return MHD_NO;
954 }
955 
956 
964 static void
965 get_date_string (char *date,
966  size_t date_len)
967 {
968  static const char *const days[] = {
969  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
970  };
971  static const char *const mons[] = {
972  "Jan", "Feb", "Mar", "Apr", "May", "Jun",
973  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
974  };
975  struct tm now;
976  time_t t;
977 #if !defined(HAVE_C11_GMTIME_S) && !defined(HAVE_W32_GMTIME_S) && !defined(HAVE_GMTIME_R)
978  struct tm* pNow;
979 #endif
980 
981  date[0] = 0;
982  time (&t);
983 #if defined(HAVE_C11_GMTIME_S)
984  if (NULL == gmtime_s (&t,
985  &now))
986  return;
987 #elif defined(HAVE_W32_GMTIME_S)
988  if (0 != gmtime_s (&now,
989  &t))
990  return;
991 #elif defined(HAVE_GMTIME_R)
992  if (NULL == gmtime_r(&t,
993  &now))
994  return;
995 #else
996  pNow = gmtime(&t);
997  if (NULL == pNow)
998  return;
999  now = *pNow;
1000 #endif
1001  MHD_snprintf_ (date,
1002  date_len,
1003  "Date: %3s, %02u %3s %04u %02u:%02u:%02u GMT\r\n",
1004  days[now.tm_wday % 7],
1005  (unsigned int) now.tm_mday,
1006  mons[now.tm_mon % 12],
1007  (unsigned int) (1900 + now.tm_year),
1008  (unsigned int) now.tm_hour,
1009  (unsigned int) now.tm_min,
1010  (unsigned int) now.tm_sec);
1011 }
1012 
1013 
1024 static int
1026 {
1027  void *buf;
1028  size_t new_size;
1029 
1030  if (0 == connection->read_buffer_size)
1031  new_size = connection->daemon->pool_size / 2;
1032  else
1033  new_size = connection->read_buffer_size + MHD_BUF_INC_SIZE;
1034  buf = MHD_pool_reallocate (connection->pool,
1035  connection->read_buffer,
1036  connection->read_buffer_size,
1037  new_size);
1038  if (NULL == buf)
1039  return MHD_NO;
1040  /* we can actually grow the buffer, do it! */
1041  connection->read_buffer = buf;
1042  connection->read_buffer_size = new_size;
1043  return MHD_YES;
1044 }
1045 
1046 
1056 static int
1058 {
1059  size_t size;
1060  size_t off;
1061  struct MHD_HTTP_Header *pos;
1062  char code[256];
1063  char date[128];
1064  char content_length_buf[128];
1065  size_t content_length_len;
1066  char *data;
1067  enum MHD_ValueKind kind;
1068  const char *reason_phrase;
1069  uint32_t rc;
1070  bool client_requested_close;
1071  bool response_has_close;
1072  bool response_has_keepalive;
1073  const char *have_encoding;
1074  const char *have_content_length;
1075  int must_add_close;
1076  int must_add_chunked_encoding;
1077  int must_add_keep_alive;
1078  int must_add_content_length;
1079 
1080  EXTRA_CHECK (NULL != connection->version);
1081  if (0 == connection->version[0])
1082  {
1083  data = MHD_pool_allocate (connection->pool,
1084  0,
1085  MHD_YES);
1086  connection->write_buffer = data;
1087  connection->write_buffer_append_offset = 0;
1088  connection->write_buffer_send_offset = 0;
1089  connection->write_buffer_size = 0;
1090  return MHD_YES;
1091  }
1092  rc = connection->responseCode & (~MHD_ICY_FLAG);
1093  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1094  {
1095  reason_phrase = MHD_get_reason_phrase_for (rc);
1096  MHD_snprintf_ (code,
1097  sizeof (code),
1098  "%s %u %s\r\n",
1099  (0 != (connection->responseCode & MHD_ICY_FLAG))
1100  ? "ICY"
1102  connection->version))
1105  rc,
1106  reason_phrase);
1107  off = strlen (code);
1108  /* estimate size */
1109  size = off + 2; /* +2 for extra "\r\n" at the end */
1110  kind = MHD_HEADER_KIND;
1111  if ( (0 == (connection->daemon->options & MHD_USE_SUPPRESS_DATE_NO_CLOCK)) &&
1112  (NULL == MHD_get_response_header (connection->response,
1114  get_date_string (date,
1115  sizeof (date));
1116  else
1117  date[0] = '\0';
1118  size += strlen (date);
1119  }
1120  else
1121  {
1122  /* 2 bytes for final CRLF of a Chunked-Body */
1123  size = 2;
1124  kind = MHD_FOOTER_KIND;
1125  off = 0;
1126  }
1127 
1128  /* calculate extra headers we need to add, such as 'Connection: close',
1129  first see what was explicitly requested by the application */
1130  must_add_close = MHD_NO;
1131  must_add_chunked_encoding = MHD_NO;
1132  must_add_keep_alive = MHD_NO;
1133  must_add_content_length = MHD_NO;
1134  response_has_close = false;
1135  response_has_keepalive = false;
1136  switch (connection->state)
1137  {
1139  response_has_close = MHD_check_response_header_s_token_ci (connection->response,
1141  "close");
1142  response_has_keepalive = MHD_check_response_header_s_token_ci (connection->response,
1144  "Keep-Alive");
1145  client_requested_close = MHD_lookup_header_s_token_ci (connection,
1147  "close");
1148 
1149  if (0 != (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY))
1150  connection->keepalive = MHD_CONN_MUST_CLOSE;
1151 #ifdef UPGRADE_SUPPORT
1152  else if (NULL != connection->response->upgrade_handler)
1153  /* If this connection will not be "upgraded", it must be closed. */
1154  connection->keepalive = MHD_CONN_MUST_CLOSE;
1155 #endif /* UPGRADE_SUPPORT */
1156 
1157  /* now analyze chunked encoding situation */
1158  connection->have_chunked_upload = false;
1159 
1160  if ( (MHD_SIZE_UNKNOWN == connection->response->total_size) &&
1161 #ifdef UPGRADE_SUPPORT
1162  (NULL == connection->response->upgrade_handler) &&
1163 #endif /* UPGRADE_SUPPORT */
1164  (! response_has_close) &&
1165  (! client_requested_close) )
1166  {
1167  /* size is unknown, and close was not explicitly requested;
1168  need to either to HTTP 1.1 chunked encoding or
1169  close the connection */
1170  /* 'close' header doesn't exist yet, see if we need to add one;
1171  if the client asked for a close, no need to start chunk'ing */
1172  if ( (MHD_YES == keepalive_possible (connection)) &&
1174  connection->version) ) )
1175  {
1176  have_encoding = MHD_get_response_header (connection->response,
1178  if (NULL == have_encoding)
1179  {
1180  must_add_chunked_encoding = MHD_YES;
1181  connection->have_chunked_upload = true;
1182  }
1183  else if (MHD_str_equal_caseless_ (have_encoding,
1184  "identity"))
1185  {
1186  /* application forced identity encoding, can't do 'chunked' */
1187  must_add_close = MHD_YES;
1188  }
1189  else
1190  {
1191  connection->have_chunked_upload = true;
1192  }
1193  }
1194  else
1195  {
1196  /* Keep alive or chunking not possible
1197  => set close header if not present */
1198  if (! response_has_close)
1199  must_add_close = MHD_YES;
1200  }
1201  }
1202 
1203  /* check for other reasons to add 'close' header */
1204  if ( ( (client_requested_close) ||
1205  (connection->read_closed) ||
1206  (MHD_CONN_MUST_CLOSE == connection->keepalive)) &&
1207  (! response_has_close) &&
1208 #ifdef UPGRADE_SUPPORT
1209  (NULL == connection->response->upgrade_handler) &&
1210 #endif /* UPGRADE_SUPPORT */
1211  (0 == (connection->response->flags & MHD_RF_HTTP_VERSION_1_0_ONLY) ) )
1212  must_add_close = MHD_YES;
1213 
1214  /* check if we should add a 'content length' header */
1215  have_content_length = MHD_get_response_header (connection->response,
1217 
1218  /* MHD_HTTP_NO_CONTENT, MHD_HTTP_NOT_MODIFIED and 1xx-status
1219  codes SHOULD NOT have a Content-Length according to spec;
1220  also chunked encoding / unknown length or CONNECT... */
1221  if ( (MHD_SIZE_UNKNOWN != connection->response->total_size) &&
1222  (MHD_HTTP_NO_CONTENT != rc) &&
1223  (MHD_HTTP_NOT_MODIFIED != rc) &&
1224  (MHD_HTTP_OK <= rc) &&
1225  (NULL == have_content_length) &&
1226  ( (NULL == connection->method) ||
1227  (! MHD_str_equal_caseless_ (connection->method,
1229  {
1230  /*
1231  Here we add a content-length if one is missing; however,
1232  for 'connect' methods, the responses MUST NOT include a
1233  content-length header *if* the response code is 2xx (in
1234  which case we expect there to be no body). Still,
1235  as we don't know the response code here in some cases, we
1236  simply only force adding a content-length header if this
1237  is not a 'connect' or if the response is not empty
1238  (which is kind of more sane, because if some crazy
1239  application did return content with a 2xx status code,
1240  then having a content-length might again be a good idea).
1241 
1242  Note that the change from 'SHOULD NOT' to 'MUST NOT' is
1243  a recent development of the HTTP 1.1 specification.
1244  */
1245  content_length_len
1246  = MHD_snprintf_ (content_length_buf,
1247  sizeof (content_length_buf),
1249  (MHD_UNSIGNED_LONG_LONG) connection->response->total_size);
1250  must_add_content_length = MHD_YES;
1251  }
1252 
1253  /* check for adding keep alive */
1254  if ( (! response_has_keepalive) &&
1255  (! response_has_close) &&
1256  (MHD_NO == must_add_close) &&
1257  (MHD_CONN_MUST_CLOSE != connection->keepalive) &&
1258 #ifdef UPGRADE_SUPPORT
1259  (NULL == connection->response->upgrade_handler) &&
1260 #endif /* UPGRADE_SUPPORT */
1261  (MHD_YES == keepalive_possible (connection)) )
1262  must_add_keep_alive = MHD_YES;
1263  break;
1265  response_has_keepalive = false;
1266  break;
1267  default:
1268  EXTRA_CHECK (0);
1269  }
1270 
1271  if (MHD_CONN_MUST_CLOSE != connection->keepalive)
1272  {
1273  if ( (must_add_close) || (response_has_close) )
1274  connection->keepalive = MHD_CONN_MUST_CLOSE;
1275  else if ( (must_add_keep_alive) || (response_has_keepalive) )
1276  connection->keepalive = MHD_CONN_USE_KEEPALIVE;
1277  }
1278 
1279  if (must_add_close)
1280  size += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1281  if (must_add_keep_alive)
1282  size += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1283  if (must_add_chunked_encoding)
1284  size += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1285  if (must_add_content_length)
1286  size += content_length_len;
1287  EXTRA_CHECK (! (must_add_close && must_add_keep_alive) );
1288  EXTRA_CHECK (! (must_add_chunked_encoding && must_add_content_length) );
1289 
1290  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1291  {
1292  /* TODO: add proper support for excluding "Keep-Alive" token. */
1293  if ( (pos->kind == kind) &&
1294  (! ( (MHD_YES == must_add_close) &&
1295  (response_has_keepalive) &&
1299  "Keep-Alive")) ) ) )
1300  size += strlen (pos->header) + strlen (pos->value) + 4; /* colon, space, linefeeds */
1301  }
1302  /* produce data */
1303  data = MHD_pool_allocate (connection->pool,
1304  size + 1,
1305  MHD_NO);
1306  if (NULL == data)
1307  {
1308 #ifdef HAVE_MESSAGES
1309  MHD_DLOG (connection->daemon,
1310  "Not enough memory for write!\n");
1311 #endif
1312  return MHD_NO;
1313  }
1314  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1315  {
1316  memcpy (data,
1317  code,
1318  off);
1319  }
1320  if (must_add_close)
1321  {
1322  /* we must add the 'Connection: close' header */
1323  memcpy (&data[off],
1324  "Connection: close\r\n",
1325  MHD_STATICSTR_LEN_ ("Connection: close\r\n"));
1326  off += MHD_STATICSTR_LEN_ ("Connection: close\r\n");
1327  }
1328  if (must_add_keep_alive)
1329  {
1330  /* we must add the 'Connection: Keep-Alive' header */
1331  memcpy (&data[off],
1332  "Connection: Keep-Alive\r\n",
1333  MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n"));
1334  off += MHD_STATICSTR_LEN_ ("Connection: Keep-Alive\r\n");
1335  }
1336  if (must_add_chunked_encoding)
1337  {
1338  /* we must add the 'Transfer-Encoding: chunked' header */
1339  memcpy (&data[off],
1340  "Transfer-Encoding: chunked\r\n",
1341  MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n"));
1342  off += MHD_STATICSTR_LEN_ ("Transfer-Encoding: chunked\r\n");
1343  }
1344  if (must_add_content_length)
1345  {
1346  /* we must add the 'Content-Length' header */
1347  memcpy (&data[off],
1348  content_length_buf,
1349  content_length_len);
1350  off += content_length_len;
1351  }
1352  for (pos = connection->response->first_header; NULL != pos; pos = pos->next)
1353  {
1354  /* TODO: add proper support for excluding "Keep-Alive" token. */
1355  if ( (pos->kind == kind) &&
1356  (! ( (MHD_YES == must_add_close) &&
1357  (response_has_keepalive) &&
1361  "Keep-Alive")) ) ) )
1362  off += MHD_snprintf_ (&data[off],
1363  size - off,
1364  "%s: %s\r\n",
1365  pos->header,
1366  pos->value);
1367  }
1368  if (MHD_CONNECTION_FOOTERS_RECEIVED == connection->state)
1369  {
1370  strcpy (&data[off],
1371  date);
1372  off += strlen (date);
1373  }
1374  memcpy (&data[off],
1375  "\r\n",
1376  2);
1377  off += 2;
1378 
1379  if (off != size)
1381  __FILE__,
1382  __LINE__,
1383  NULL);
1384  connection->write_buffer = data;
1385  connection->write_buffer_append_offset = size;
1386  connection->write_buffer_send_offset = 0;
1387  connection->write_buffer_size = size + 1;
1388  return MHD_YES;
1389 }
1390 
1391 
1401 static void
1403  unsigned int status_code,
1404  const char *message)
1405 {
1406  struct MHD_Response *response;
1407 
1408  if (NULL == connection->version)
1409  {
1410  /* we were unable to process the full header line, so we don't
1411  really know what version the client speaks; assume 1.0 */
1412  connection->version = MHD_HTTP_VERSION_1_0;
1413  }
1414  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
1415  connection->read_closed = true;
1416 #ifdef HAVE_MESSAGES
1417  MHD_DLOG (connection->daemon,
1418  _("Error processing request (HTTP response code is %u (`%s')). Closing connection.\n"),
1419  status_code,
1420  message);
1421 #endif
1422  if (NULL != connection->response)
1423  {
1424  MHD_destroy_response (connection->response);
1425  connection->response = NULL;
1426  }
1427  response = MHD_create_response_from_buffer (strlen (message),
1428  (void *) message,
1429  MHD_RESPMEM_PERSISTENT);
1430  MHD_queue_response (connection,
1431  status_code,
1432  response);
1433  EXTRA_CHECK (NULL != connection->response);
1434  MHD_destroy_response (response);
1435  /* Do not reuse this connection. */
1436  connection->keepalive = MHD_CONN_MUST_CLOSE;
1437  if (MHD_NO == build_header_response (connection))
1438  {
1439  /* oops - close! */
1440  CONNECTION_CLOSE_ERROR (connection,
1441  _("Closing connection (failed to create response header)\n"));
1442  }
1443  else
1444  {
1445  connection->state = MHD_CONNECTION_HEADERS_SENDING;
1446  }
1447 }
1448 
1449 
1458 static void
1460 {
1461  /* Do not update states of suspended connection */
1462  if (connection->suspended)
1463  return; /* States will be updated after resume. */
1464  while (1)
1465  {
1466 #if DEBUG_STATES
1467  MHD_DLOG (connection->daemon,
1468  _("In function %s handling connection at state: %s\n"),
1469  __FUNCTION__,
1470  MHD_state_to_string (connection->state));
1471 #endif
1472  switch (connection->state)
1473  {
1474 #ifdef HTTPS_SUPPORT
1476  if (0 == gnutls_record_get_direction (connection->tls_session))
1478  else
1480  break;
1481 #endif /* HTTPS_SUPPORT */
1482  case MHD_CONNECTION_INIT:
1485  /* while reading headers, we always grow the
1486  read buffer if needed, no size-check required */
1487  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1488  (MHD_NO == try_grow_read_buffer (connection)) )
1489  {
1490  transmit_error_response (connection,
1491  (connection->url != NULL)
1494  REQUEST_TOO_BIG);
1495  continue;
1496  }
1497  if (! connection->read_closed)
1499  else
1501  break;
1503  EXTRA_CHECK (0);
1504  break;
1506  EXTRA_CHECK (0);
1507  break;
1510  break;
1512  if (connection->read_buffer_offset == connection->read_buffer_size)
1513  {
1514  if ((MHD_YES != try_grow_read_buffer (connection)) &&
1515  (0 != (connection->daemon->options &
1517  {
1518  /* failed to grow the read buffer, and the
1519  client which is supposed to handle the
1520  received data in a *blocking* fashion
1521  (in this mode) did not handle the data as
1522  it was supposed to!
1523  => we would either have to do busy-waiting
1524  (on the client, which would likely fail),
1525  or if we do nothing, we would just timeout
1526  on the connection (if a timeout is even
1527  set!).
1528  Solution: we kill the connection with an error */
1529  transmit_error_response (connection,
1531  INTERNAL_ERROR);
1532  continue;
1533  }
1534  }
1535  if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
1536  (! connection->read_closed) )
1538  else
1540  break;
1543  /* while reading footers, we always grow the
1544  read buffer if needed, no size-check required */
1545  if (connection->read_closed)
1546  {
1547  CONNECTION_CLOSE_ERROR (connection,
1548  NULL);
1549  continue;
1550  }
1552  /* transition to FOOTERS_RECEIVED
1553  happens in read handler */
1554  break;
1557  break;
1559  /* headers in buffer, keep writing */
1561  break;
1563  EXTRA_CHECK (0);
1564  break;
1567  break;
1570  break;
1573  break;
1576  break;
1578  EXTRA_CHECK (0);
1579  break;
1582  break;
1584  EXTRA_CHECK (0);
1585  break;
1586  case MHD_CONNECTION_CLOSED:
1588  return; /* do nothing, not even reading */
1590  EXTRA_CHECK (0);
1591  break;
1592 #ifdef UPGRADE_SUPPORT
1593  case MHD_CONNECTION_UPGRADE:
1594  EXTRA_CHECK (0);
1595  break;
1596 #endif /* UPGRADE_SUPPORT */
1597  default:
1598  EXTRA_CHECK (0);
1599  }
1600  break;
1601  }
1602 }
1603 
1604 
1618 static char *
1620  size_t *line_len)
1621 {
1622  char *rbuf;
1623  size_t pos;
1624 
1625  if (0 == connection->read_buffer_offset)
1626  return NULL;
1627  pos = 0;
1628  rbuf = connection->read_buffer;
1629  while ( (pos < connection->read_buffer_offset - 1) &&
1630  ('\r' != rbuf[pos]) &&
1631  ('\n' != rbuf[pos]) )
1632  pos++;
1633  if ( (pos == connection->read_buffer_offset - 1) &&
1634  ('\n' != rbuf[pos]) )
1635  {
1636  /* not found, consider growing... */
1637  if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
1638  (MHD_NO ==
1639  try_grow_read_buffer (connection)) )
1640  {
1641  transmit_error_response (connection,
1642  (NULL != connection->url)
1645  REQUEST_TOO_BIG);
1646  }
1647  if (line_len)
1648  *line_len = 0;
1649  return NULL;
1650  }
1651 
1652  if (line_len)
1653  *line_len = pos;
1654  /* found, check if we have proper LFCR */
1655  if ( ('\r' == rbuf[pos]) &&
1656  ('\n' == rbuf[pos + 1]) )
1657  rbuf[pos++] = '\0'; /* skip both r and n */
1658  rbuf[pos++] = '\0';
1659  connection->read_buffer += pos;
1660  connection->read_buffer_size -= pos;
1661  connection->read_buffer_offset -= pos;
1662  return rbuf;
1663 }
1664 
1665 
1677 static int
1679  const char *key,
1680  const char *value,
1681  enum MHD_ValueKind kind)
1682 {
1683  if (MHD_NO ==
1684  MHD_set_connection_value (connection,
1685  kind,
1686  key,
1687  value))
1688  {
1689 #ifdef HAVE_MESSAGES
1690  MHD_DLOG (connection->daemon,
1691  _("Not enough memory in pool to allocate header record!\n"));
1692 #endif
1693  transmit_error_response (connection,
1695  REQUEST_TOO_BIG);
1696  return MHD_NO;
1697  }
1698  return MHD_YES;
1699 }
1700 
1701 
1708 static int
1710 {
1711  const char *hdr;
1712  char *cpy;
1713  char *pos;
1714  char *sce;
1715  char *semicolon;
1716  char *equals;
1717  char *ekill;
1718  char old;
1719  int quotes;
1720 
1721  hdr = MHD_lookup_connection_value (connection,
1724  if (NULL == hdr)
1725  return MHD_YES;
1726  cpy = MHD_pool_allocate (connection->pool,
1727  strlen (hdr) + 1,
1728  MHD_YES);
1729  if (NULL == cpy)
1730  {
1731 #ifdef HAVE_MESSAGES
1732  MHD_DLOG (connection->daemon,
1733  _("Not enough memory in pool to parse cookies!\n"));
1734 #endif
1735  transmit_error_response (connection,
1737  REQUEST_TOO_BIG);
1738  return MHD_NO;
1739  }
1740  memcpy (cpy,
1741  hdr,
1742  strlen (hdr) + 1);
1743  pos = cpy;
1744  while (NULL != pos)
1745  {
1746  while (' ' == *pos)
1747  pos++; /* skip spaces */
1748 
1749  sce = pos;
1750  while ( ((*sce) != '\0') &&
1751  ((*sce) != ',') &&
1752  ((*sce) != ';') &&
1753  ((*sce) != '=') )
1754  sce++;
1755  /* remove tailing whitespace (if any) from key */
1756  ekill = sce - 1;
1757  while ( (*ekill == ' ') &&
1758  (ekill >= pos) )
1759  *(ekill--) = '\0';
1760  old = *sce;
1761  *sce = '\0';
1762  if (old != '=')
1763  {
1764  /* value part omitted, use empty string... */
1765  if (MHD_NO ==
1766  connection_add_header (connection,
1767  pos,
1768  "",
1769  MHD_COOKIE_KIND))
1770  return MHD_NO;
1771  if (old == '\0')
1772  break;
1773  pos = sce + 1;
1774  continue;
1775  }
1776  equals = sce + 1;
1777  quotes = 0;
1778  semicolon = equals;
1779  while ( ('\0' != semicolon[0]) &&
1780  ( (0 != quotes) ||
1781  ( (';' != semicolon[0]) &&
1782  (',' != semicolon[0]) ) ) )
1783  {
1784  if ('"' == semicolon[0])
1785  quotes = (quotes + 1) & 1;
1786  semicolon++;
1787  }
1788  if ('\0' == semicolon[0])
1789  semicolon = NULL;
1790  if (NULL != semicolon)
1791  {
1792  semicolon[0] = '\0';
1793  semicolon++;
1794  }
1795  /* remove quotes */
1796  if ( ('"' == equals[0]) &&
1797  ('"' == equals[strlen (equals) - 1]) )
1798  {
1799  equals[strlen (equals) - 1] = '\0';
1800  equals++;
1801  }
1802  if (MHD_NO ==
1803  connection_add_header (connection,
1804  pos,
1805  equals,
1806  MHD_COOKIE_KIND))
1807  return MHD_NO;
1808  pos = semicolon;
1809  }
1810  return MHD_YES;
1811 }
1812 
1813 
1822 static int
1824  char *line,
1825  size_t line_len)
1826 {
1827  struct MHD_Daemon *daemon = connection->daemon;
1828  const char *curi;
1829  char *uri;
1830  char *http_version;
1831  char *args;
1832  unsigned int unused_num_headers;
1833 
1834  if (NULL == (uri = memchr (line,
1835  ' ',
1836  line_len)))
1837  return MHD_NO; /* serious error */
1838  uri[0] = '\0';
1839  connection->method = line;
1840  uri++;
1841  /* Skip any spaces. Not required by standard but allow
1842  to be more tolerant. */
1843  while ( (' ' == uri[0]) &&
1844  ( (size_t)(uri - line) < line_len) )
1845  uri++;
1846  if ((size_t)(uri - line) == line_len)
1847  {
1848  curi = "";
1849  uri = NULL;
1850  connection->version = "";
1851  args = NULL;
1852  }
1853  else
1854  {
1855  curi = uri;
1856  /* Search from back to accept misformed URI with space */
1857  http_version = line + line_len - 1;
1858  /* Skip any trailing spaces */
1859  while ( (' ' == http_version[0]) &&
1860  (http_version > uri) )
1861  http_version--;
1862  /* Find first space in reverse direction */
1863  while ( (' ' != http_version[0]) &&
1864  (http_version > uri) )
1865  http_version--;
1866  if (http_version > uri)
1867  {
1868  http_version[0] = '\0';
1869  connection->version = http_version + 1;
1870  args = memchr (uri,
1871  '?',
1872  http_version - uri);
1873  }
1874  else
1875  {
1876  connection->version = "";
1877  args = memchr (uri,
1878  '?',
1879  line_len - (uri - line));
1880  }
1881  }
1882  if (NULL != daemon->uri_log_callback)
1883  {
1884  connection->client_aware = true;
1885  connection->client_context
1886  = daemon->uri_log_callback (daemon->uri_log_callback_cls,
1887  curi,
1888  connection);
1889  }
1890  if (NULL != args)
1891  {
1892  args[0] = '\0';
1893  args++;
1894  /* note that this call clobbers 'args' */
1895  MHD_parse_arguments_ (connection,
1897  args,
1899  &unused_num_headers);
1900  }
1901  if (NULL != uri)
1902  daemon->unescape_callback (daemon->unescape_callback_cls,
1903  connection,
1904  uri);
1905  connection->url = curi;
1906  return MHD_YES;
1907 }
1908 
1909 
1917 static void
1919 {
1920  size_t processed;
1921 
1922  if (NULL != connection->response)
1923  return; /* already queued a response */
1924  processed = 0;
1925  connection->client_aware = true;
1926  if (MHD_NO ==
1927  connection->daemon->default_handler (connection->daemon->default_handler_cls,
1928  connection,
1929  connection->url,
1930  connection->method,
1931  connection->version,
1932  NULL,
1933  &processed,
1934  &connection->client_context))
1935  {
1936  /* serious internal error, close connection */
1937  CONNECTION_CLOSE_ERROR (connection,
1938  _("Application reported internal error, closing connection.\n"));
1939  return;
1940  }
1941 }
1942 
1943 
1944 
1952 static void
1954 {
1955  size_t available;
1956  int instant_retry;
1957  char *buffer_head;
1958 
1959  if (NULL != connection->response)
1960  return; /* already queued a response */
1961 
1962  buffer_head = connection->read_buffer;
1963  available = connection->read_buffer_offset;
1964  do
1965  {
1966  size_t to_be_processed;
1967  size_t left_unprocessed;
1968  size_t processed_size;
1969 
1970  instant_retry = MHD_NO;
1971  if ( (connection->have_chunked_upload) &&
1972  (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) )
1973  {
1974  if ( (connection->current_chunk_offset == connection->current_chunk_size) &&
1975  (0LLU != connection->current_chunk_offset) &&
1976  (available >= 2) )
1977  {
1978  size_t i;
1979  /* skip new line at the *end* of a chunk */
1980  i = 0;
1981  if ( ('\r' == buffer_head[i]) ||
1982  ('\n' == buffer_head[i]) )
1983  i++; /* skip 1st part of line feed */
1984  if ( ('\r' == buffer_head[i]) ||
1985  ('\n' == buffer_head[i]) )
1986  i++; /* skip 2nd part of line feed */
1987  if (0 == i)
1988  {
1989  /* malformed encoding */
1990  CONNECTION_CLOSE_ERROR (connection,
1991  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
1992  return;
1993  }
1994  available -= i;
1995  buffer_head += i;
1996  connection->current_chunk_offset = 0;
1997  connection->current_chunk_size = 0;
1998  }
1999  if (connection->current_chunk_offset <
2000  connection->current_chunk_size)
2001  {
2002  uint64_t cur_chunk_left;
2003  /* we are in the middle of a chunk, give
2004  as much as possible to the client (without
2005  crossing chunk boundaries) */
2006  cur_chunk_left
2007  = connection->current_chunk_size - connection->current_chunk_offset;
2008  if (cur_chunk_left > available)
2009  to_be_processed = available;
2010  else
2011  { /* cur_chunk_left <= (size_t)available */
2012  to_be_processed = (size_t)cur_chunk_left;
2013  if (available > to_be_processed)
2014  instant_retry = MHD_YES;
2015  }
2016  }
2017  else
2018  {
2019  size_t i;
2020  size_t end_size;
2021  bool malformed;
2022 
2023  /* we need to read chunk boundaries */
2024  i = 0;
2025  while (i < available)
2026  {
2027  if ( ('\r' == buffer_head[i]) ||
2028  ('\n' == buffer_head[i]) ||
2029  (';' == buffer_head[i]) )
2030  break;
2031  i++;
2032  if (i >= 16)
2033  break;
2034  }
2035  end_size = i;
2036  /* find beginning of CRLF (skip over chunk extensions) */
2037  if (';' == buffer_head[i])
2038  {
2039  while (i < available)
2040  {
2041  if ( ('\r' == buffer_head[i]) ||
2042  ('\n' == buffer_head[i]) )
2043  break;
2044  i++;
2045  }
2046  }
2047  /* take '\n' into account; if '\n' is the unavailable
2048  character, we will need to wait until we have it
2049  before going further */
2050  if ( (i + 1 >= available) &&
2051  ! ( (1 == i) &&
2052  (2 == available) &&
2053  ('0' == buffer_head[0]) ) )
2054  break; /* need more data... */
2055  i++;
2056  malformed = (end_size >= 16);
2057  if (! malformed)
2058  {
2059  size_t num_dig = MHD_strx_to_uint64_n_ (buffer_head,
2060  end_size,
2061  &connection->current_chunk_size);
2062  malformed = (end_size != num_dig);
2063  }
2064  if (malformed)
2065  {
2066  /* malformed encoding */
2067  CONNECTION_CLOSE_ERROR (connection,
2068  _("Received malformed HTTP request (bad chunked encoding). Closing connection.\n"));
2069  return;
2070  }
2071  /* skip 2nd part of line feed */
2072  if ( (i < available) &&
2073  ( ('\r' == buffer_head[i]) ||
2074  ('\n' == buffer_head[i]) ) )
2075  i++;
2076 
2077  buffer_head += i;
2078  available -= i;
2079  connection->current_chunk_offset = 0;
2080 
2081  if (available > 0)
2082  instant_retry = MHD_YES;
2083  if (0LLU == connection->current_chunk_size)
2084  {
2085  connection->remaining_upload_size = 0;
2086  break;
2087  }
2088  continue;
2089  }
2090  }
2091  else
2092  {
2093  /* no chunked encoding, give all to the client */
2094  if ( (0 != connection->remaining_upload_size) &&
2095  (MHD_SIZE_UNKNOWN != connection->remaining_upload_size) &&
2096  (connection->remaining_upload_size < available) )
2097  {
2098  to_be_processed = (size_t)connection->remaining_upload_size;
2099  }
2100  else
2101  {
2106  to_be_processed = available;
2107  }
2108  }
2109  left_unprocessed = to_be_processed;
2110  connection->client_aware = true;
2111  if (MHD_NO ==
2112  connection->daemon->default_handler (connection->daemon->default_handler_cls,
2113  connection,
2114  connection->url,
2115  connection->method,
2116  connection->version,
2117  buffer_head,
2118  &left_unprocessed,
2119  &connection->client_context))
2120  {
2121  /* serious internal error, close connection */
2122  CONNECTION_CLOSE_ERROR (connection,
2123  _("Application reported internal error, closing connection.\n"));
2124  return;
2125  }
2126  if (left_unprocessed > to_be_processed)
2128  __FILE__,
2129  __LINE__
2130 #ifdef HAVE_MESSAGES
2131  , _("libmicrohttpd API violation")
2132 #else
2133  , NULL
2134 #endif
2135  );
2136  if (0 != left_unprocessed)
2137  {
2138  instant_retry = MHD_NO; /* client did not process everything */
2139 #ifdef HAVE_MESSAGES
2140  /* client did not process all upload data, complain if
2141  the setup was incorrect, which may prevent us from
2142  handling the rest of the request */
2143  if ( (0 != (connection->daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) &&
2144  (! connection->suspended) )
2145  MHD_DLOG (connection->daemon,
2146  _("WARNING: incomplete upload processing and connection not suspended may result in hung connection.\n"));
2147 #endif
2148  }
2149  processed_size = to_be_processed - left_unprocessed;
2150  if (connection->have_chunked_upload)
2151  connection->current_chunk_offset += processed_size;
2152  /* dh left "processed" bytes in buffer for next time... */
2153  buffer_head += processed_size;
2154  available -= processed_size;
2155  if (MHD_SIZE_UNKNOWN != connection->remaining_upload_size)
2156  connection->remaining_upload_size -= processed_size;
2157  }
2158  while (MHD_YES == instant_retry);
2159  if (available > 0)
2160  memmove (connection->read_buffer,
2161  buffer_head,
2162  available);
2163  connection->read_buffer_offset = available;
2164 }
2165 
2166 
2176 static int
2177 do_read (struct MHD_Connection *connection)
2178 {
2179  ssize_t bytes_read;
2180 
2181  if (connection->read_buffer_size == connection->read_buffer_offset)
2182  return MHD_NO;
2183  bytes_read = connection->recv_cls (connection,
2184  &connection->read_buffer
2185  [connection->read_buffer_offset],
2186  connection->read_buffer_size -
2187  connection->read_buffer_offset);
2188  if (bytes_read < 0)
2189  {
2190  const int err = MHD_socket_get_error_ ();
2191  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2193  return MHD_NO;
2195  {
2196  CONNECTION_CLOSE_ERROR (connection,
2197  NULL);
2198  return MHD_NO;
2199  }
2200  CONNECTION_CLOSE_ERROR (connection,
2201  NULL);
2202  return MHD_YES;
2203  }
2204  if (0 == bytes_read)
2205  {
2206  /* other side closed connection; RFC 2616, section 8.1.4 suggests
2207  we should then shutdown ourselves as well. */
2208  connection->read_closed = true;
2209  MHD_connection_close_ (connection,
2211  return MHD_YES;
2212  }
2213  connection->read_buffer_offset += bytes_read;
2214  return MHD_YES;
2215 }
2216 
2217 
2226 static int
2227 do_write (struct MHD_Connection *connection)
2228 {
2229  ssize_t ret;
2230  size_t max;
2231 
2232  max = connection->write_buffer_append_offset - connection->write_buffer_send_offset;
2233  ret = connection->send_cls (connection,
2234  &connection->write_buffer
2235  [connection->write_buffer_send_offset],
2236  max);
2237 
2238  if (ret < 0)
2239  {
2240  const int err = MHD_socket_get_error_ ();
2241  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2243  return MHD_NO;
2244  CONNECTION_CLOSE_ERROR (connection,
2245  NULL);
2246  return MHD_YES;
2247  }
2248 #if DEBUG_SEND_DATA
2249  fprintf (stderr,
2250  _("Sent response: `%.*s'\n"),
2251  ret,
2252  &connection->write_buffer[connection->write_buffer_send_offset]);
2253 #endif
2254  /* only increment if this wasn't a "sendfile" transmission without
2255  buffer involvement! */
2256  if (0 != max)
2257  connection->write_buffer_send_offset += ret;
2258  return MHD_YES;
2259 }
2260 
2261 
2270 static int
2271 check_write_done (struct MHD_Connection *connection,
2272  enum MHD_CONNECTION_STATE next_state)
2273 {
2274  if (connection->write_buffer_append_offset !=
2275  connection->write_buffer_send_offset)
2276  return MHD_NO;
2277  connection->write_buffer_append_offset = 0;
2278  connection->write_buffer_send_offset = 0;
2279  connection->state = next_state;
2280  MHD_pool_reallocate (connection->pool,
2281  connection->write_buffer,
2282  connection->write_buffer_size,
2283  0);
2284  connection->write_buffer = NULL;
2285  connection->write_buffer_size = 0;
2286  return MHD_YES;
2287 }
2288 
2289 
2299 static int
2301  char *line)
2302 {
2303  char *colon;
2304 
2305  /* line should be normal header line, find colon */
2306  colon = strchr (line, ':');
2307  if (NULL == colon)
2308  {
2309  /* error in header line, die hard */
2310  CONNECTION_CLOSE_ERROR (connection,
2311  _("Received malformed line (no colon). Closing connection.\n"));
2312  return MHD_NO;
2313  }
2314  if (-1 >= connection->daemon->strict_for_client)
2315  {
2316  /* check for whitespace before colon, which is not allowed
2317  by RFC 7230 section 3.2.4; we count space ' ' and
2318  tab '\t', but not '\r\n' as those would have ended the line. */
2319  const char *white;
2320 
2321  white = strchr (line, ' ');
2322  if ( (NULL != white) &&
2323  (white < colon) )
2324  return MHD_NO;
2325  white = strchr (line, '\t');
2326  if ( (NULL != white) &&
2327  (white < colon) )
2328  return MHD_NO;
2329  }
2330  /* zero-terminate header */
2331  colon[0] = '\0';
2332  colon++; /* advance to value */
2333  while ( ('\0' != colon[0]) &&
2334  ( (' ' == colon[0]) ||
2335  ('\t' == colon[0]) ) )
2336  colon++;
2337  /* we do the actual adding of the connection
2338  header at the beginning of the while
2339  loop since we need to be able to inspect
2340  the *next* header line (in case it starts
2341  with a space...) */
2342  connection->last = line;
2343  connection->colon = colon;
2344  return MHD_YES;
2345 }
2346 
2347 
2358 static int
2360  char *line,
2361  enum MHD_ValueKind kind)
2362 {
2363  char *last;
2364  char *tmp;
2365  size_t last_len;
2366  size_t tmp_len;
2367 
2368  last = connection->last;
2369  if ( (' ' == line[0]) ||
2370  ('\t' == line[0]) )
2371  {
2372  /* value was continued on the next line, see
2373  http://www.jmarshall.com/easy/http/ */
2374  last_len = strlen (last);
2375  /* skip whitespace at start of 2nd line */
2376  tmp = line;
2377  while ( (' ' == tmp[0]) ||
2378  ('\t' == tmp[0]) )
2379  tmp++;
2380  tmp_len = strlen (tmp);
2381  /* FIXME: we might be able to do this better (faster!), as most
2382  likely 'last' and 'line' should already be adjacent in
2383  memory; however, doing this right gets tricky if we have a
2384  value continued over multiple lines (in which case we need to
2385  record how often we have done this so we can check for
2386  adjacency); also, in the case where these are not adjacent
2387  (not sure how it can happen!), we would want to allocate from
2388  the end of the pool, so as to not destroy the read-buffer's
2389  ability to grow nicely. */
2390  last = MHD_pool_reallocate (connection->pool,
2391  last,
2392  last_len + 1,
2393  last_len + tmp_len + 1);
2394  if (NULL == last)
2395  {
2396  transmit_error_response (connection,
2398  REQUEST_TOO_BIG);
2399  return MHD_NO;
2400  }
2401  memcpy (&last[last_len], tmp, tmp_len + 1);
2402  connection->last = last;
2403  return MHD_YES; /* possibly more than 2 lines... */
2404  }
2405  EXTRA_CHECK ( (NULL != last) &&
2406  (NULL != connection->colon) );
2407  if ((MHD_NO == connection_add_header (connection,
2408  last,
2409  connection->colon,
2410  kind)))
2411  {
2412  transmit_error_response (connection,
2414  REQUEST_TOO_BIG);
2415  return MHD_NO;
2416  }
2417  /* we still have the current line to deal with... */
2418  if (0 != line[0])
2419  {
2420  if (MHD_NO == process_header_line (connection,
2421  line))
2422  {
2423  transmit_error_response (connection,
2426  return MHD_NO;
2427  }
2428  }
2429  return MHD_YES;
2430 }
2431 
2432 
2440 static void
2442 {
2443  const char *clen;
2444  struct MHD_Response *response;
2445  const char *enc;
2446  const char *end;
2447 
2448  parse_cookie_header (connection);
2449  if ( (1 <= connection->daemon->strict_for_client) &&
2450  (NULL != connection->version) &&
2452  connection->version)) &&
2453  (NULL ==
2454  MHD_lookup_connection_value (connection,
2457  {
2458  /* die, http 1.1 request without host and we are pedantic */
2459  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
2460  connection->read_closed = true;
2461 #ifdef HAVE_MESSAGES
2462  MHD_DLOG (connection->daemon,
2463  _("Received HTTP 1.1 request without `Host' header.\n"));
2464 #endif
2465  EXTRA_CHECK (NULL == connection->response);
2466  response =
2469  MHD_RESPMEM_PERSISTENT);
2470  MHD_queue_response (connection,
2472  response);
2473  MHD_destroy_response (response);
2474  return;
2475  }
2476 
2477  connection->remaining_upload_size = 0;
2478  enc = MHD_lookup_connection_value (connection,
2481  if (NULL != enc)
2482  {
2484  if (MHD_str_equal_caseless_(enc,
2485  "chunked"))
2486  connection->have_chunked_upload = true;
2487  }
2488  else
2489  {
2490  clen = MHD_lookup_connection_value (connection,
2493  if (NULL != clen)
2494  {
2495  end = clen + MHD_str_to_uint64_ (clen,
2496  &connection->remaining_upload_size);
2497  if ( (clen == end) ||
2498  ('\0' != *end) )
2499  {
2500  connection->remaining_upload_size = 0;
2501 #ifdef HAVE_MESSAGES
2502  MHD_DLOG (connection->daemon,
2503  "Failed to parse `Content-Length' header. Closing connection.\n");
2504 #endif
2505  CONNECTION_CLOSE_ERROR (connection,
2506  NULL);
2507  return;
2508  }
2509  }
2510  }
2511 }
2512 
2513 
2521 void
2523 {
2524  struct MHD_Daemon *daemon = connection->daemon;
2525 
2526  if (0 == connection->connection_timeout)
2527  return; /* Skip update of activity for connections
2528  without timeout timer. */
2529  if (connection->suspended)
2530  return; /* no activity on suspended connections */
2531 
2532  connection->last_activity = MHD_monotonic_sec_counter();
2533  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2534  return; /* each connection has personal timeout */
2535 
2536  if (connection->connection_timeout != daemon->connection_timeout)
2537  return; /* custom timeout, no need to move it in "normal" DLL */
2538 
2540  /* move connection to head of timeout list (by remove + add operation) */
2542  daemon->normal_timeout_tail,
2543  connection);
2545  daemon->normal_timeout_tail,
2546  connection);
2548 }
2549 
2550 
2559 int
2561 {
2562  if ( (MHD_CONNECTION_CLOSED == connection->state) ||
2563  (connection->suspended) )
2564  return MHD_YES;
2565  /* make sure "read" has a reasonable number of bytes
2566  in buffer to use per system call (if possible) */
2567  if (connection->read_buffer_offset + connection->daemon->pool_increment >
2568  connection->read_buffer_size)
2569  try_grow_read_buffer (connection);
2570  if (MHD_NO == do_read (connection))
2571  return MHD_YES;
2572  MHD_update_last_activity_ (connection);
2573  while (1)
2574  {
2575 #if DEBUG_STATES
2576  MHD_DLOG (connection->daemon,
2577  _("In function %s handling connection at state: %s\n"),
2578  __FUNCTION__,
2579  MHD_state_to_string (connection->state));
2580 #endif
2581  switch (connection->state)
2582  {
2583  case MHD_CONNECTION_INIT:
2592  /* nothing to do but default action */
2593  if (connection->read_closed)
2594  {
2595  MHD_connection_close_ (connection,
2597  continue;
2598  }
2599  break;
2600  case MHD_CONNECTION_CLOSED:
2601  return MHD_YES;
2602 #ifdef UPGRADE_SUPPORT
2603  case MHD_CONNECTION_UPGRADE:
2604  EXTRA_CHECK (0);
2605  break;
2606 #endif /* UPGRADE_SUPPORT */
2607  default:
2608  /* shrink read buffer to how much is actually used */
2609  MHD_pool_reallocate (connection->pool,
2610  connection->read_buffer,
2611  connection->read_buffer_size + 1,
2612  connection->read_buffer_offset);
2613  break;
2614  }
2615  break;
2616  }
2617  return MHD_YES;
2618 }
2619 
2620 
2629 int
2631 {
2632  struct MHD_Response *response;
2633  ssize_t ret;
2634  if (connection->suspended)
2635  return MHD_YES;
2636 
2637  while (1)
2638  {
2639 #if DEBUG_STATES
2640  MHD_DLOG (connection->daemon,
2641  _("In function %s handling connection at state: %s\n"),
2642  __FUNCTION__,
2643  MHD_state_to_string (connection->state));
2644 #endif
2645  switch (connection->state)
2646  {
2647  case MHD_CONNECTION_INIT:
2651  EXTRA_CHECK (0);
2652  break;
2654  break;
2656  ret = connection->send_cls (connection,
2658  [connection->continue_message_write_offset],
2660  connection->continue_message_write_offset);
2661  if (ret < 0)
2662  {
2663  const int err = MHD_socket_get_error_ ();
2664 
2665  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2667  break;
2668 #ifdef HAVE_MESSAGES
2669  MHD_DLOG (connection->daemon,
2670  _("Failed to send data in request for %s: %s\n"),
2671  connection->url,
2672  MHD_socket_strerr_ (err));
2673 #endif
2674  CONNECTION_CLOSE_ERROR (connection,
2675  NULL);
2676  return MHD_YES;
2677  }
2678 #if DEBUG_SEND_DATA
2679  fprintf (stderr,
2680  _("Sent 100 continue response: `%.*s'\n"),
2681  (int) ret,
2683 #endif
2684  connection->continue_message_write_offset += ret;
2685  MHD_update_last_activity_ (connection);
2686  break;
2691  EXTRA_CHECK (0);
2692  break;
2694  if (MHD_NO != do_write (connection))
2695  MHD_update_last_activity_ (connection);
2696  if (MHD_CONNECTION_HEADERS_SENDING != connection->state)
2697  break;
2698  check_write_done (connection,
2700  break;
2702  break;
2704  response = connection->response;
2705  if (connection->response_write_position <
2706  connection->response->total_size)
2707  {
2708  int err;
2709  uint64_t data_write_offset;
2710 
2711  if (NULL != response->crc)
2712  MHD_mutex_lock_chk_ (&response->mutex);
2713  if (MHD_YES != try_ready_normal_body (connection))
2714  {
2715  /* mutex was already unlocked by try_ready_normal_body */
2716  break;
2717  }
2718  data_write_offset = connection->response_write_position
2719  - response->data_start;
2720  if (data_write_offset > (uint64_t)SIZE_MAX)
2721  MHD_PANIC (_("Data offset exceeds limit"));
2722  ret = connection->send_cls (connection,
2723  &response->data
2724  [(size_t)data_write_offset],
2725  response->data_size -
2726  (size_t)data_write_offset);
2727 #if DEBUG_SEND_DATA
2728  if (ret > 0)
2729  fprintf (stderr,
2730  _("Sent %d-byte DATA response: `%.*s'\n"),
2731  (int) ret,
2732  (int) ret,
2733  &response->data[connection->response_write_position -
2734  response->data_start]);
2735 #endif
2736  if (NULL != response->crc)
2737  MHD_mutex_unlock_chk_ (&response->mutex);
2738  if (ret < 0)
2739  {
2740  err = MHD_socket_get_error_ ();
2741  if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
2743  return MHD_YES;
2744 #ifdef HAVE_MESSAGES
2745  MHD_DLOG (connection->daemon,
2746  _("Failed to send data in request for `%s': %s\n"),
2747  connection->url,
2748  MHD_socket_strerr_ (err));
2749 #endif
2750  CONNECTION_CLOSE_ERROR (connection,
2751  NULL);
2752  return MHD_YES;
2753  }
2754  connection->response_write_position += ret;
2755  MHD_update_last_activity_ (connection);
2756  }
2757  if (connection->response_write_position ==
2758  connection->response->total_size)
2759  connection->state = MHD_CONNECTION_FOOTERS_SENT; /* have no footers */
2760  break;
2762  EXTRA_CHECK (0);
2763  break;
2765  if (MHD_NO != do_write (connection))
2766  MHD_update_last_activity_ (connection);
2767  if (MHD_CONNECTION_CHUNKED_BODY_READY != connection->state)
2768  break;
2769  check_write_done (connection,
2770  (connection->response->total_size ==
2771  connection->response_write_position) ?
2774  break;
2777  EXTRA_CHECK (0);
2778  break;
2780  if (MHD_NO != do_write (connection))
2781  MHD_update_last_activity_ (connection);
2782  if (MHD_CONNECTION_FOOTERS_SENDING != connection->state)
2783  break;
2784  check_write_done (connection,
2786  break;
2788  EXTRA_CHECK (0);
2789  break;
2790  case MHD_CONNECTION_CLOSED:
2791  return MHD_YES;
2793  EXTRA_CHECK (0);
2794  break;
2796  EXTRA_CHECK (0);
2797  break;
2798 #ifdef UPGRADE_SUPPORT
2799  case MHD_CONNECTION_UPGRADE:
2800  EXTRA_CHECK (0);
2801  break;
2802 #endif /* UPGRADE_SUPPORT */
2803  default:
2804  EXTRA_CHECK (0);
2805  CONNECTION_CLOSE_ERROR (connection,
2806  _("Internal error\n"));
2807  return MHD_YES;
2808  }
2809  break;
2810  }
2811  return MHD_YES;
2812 }
2813 
2814 
2823 static void
2825 {
2826  struct MHD_Daemon *daemon = connection->daemon;
2827 
2828  if (connection->in_cleanup)
2829  return; /* Prevent double cleanup. */
2830  connection->in_cleanup = true;
2831  if (NULL != connection->response)
2832  {
2833  MHD_destroy_response (connection->response);
2834  connection->response = NULL;
2835  }
2837  if (connection->suspended)
2838  {
2841  connection);
2842  connection->suspended = false;
2843  }
2844  else
2845  {
2846  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2847  {
2848  if (connection->connection_timeout == daemon->connection_timeout)
2850  daemon->normal_timeout_tail,
2851  connection);
2852  else
2854  daemon->manual_timeout_tail,
2855  connection);
2856  }
2857  DLL_remove (daemon->connections_head,
2858  daemon->connections_tail,
2859  connection);
2860  }
2861  DLL_insert (daemon->cleanup_head,
2862  daemon->cleanup_tail,
2863  connection);
2864  connection->resuming = false;
2865  connection->in_idle = false;
2867  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2868  {
2869  /* if we were at the connection limit before and are in
2870  thread-per-connection mode, signal the main thread
2871  to resume accepting connections */
2872  if ( (MHD_ITC_IS_VALID_ (daemon->itc)) &&
2873  (! MHD_itc_activate_ (daemon->itc, "c")) )
2874  {
2875 #ifdef HAVE_MESSAGES
2876  MHD_DLOG (daemon,
2877  _("Failed to signal end of connection via inter-thread communication channel"));
2878 #endif
2879  }
2880  }
2881 }
2882 
2883 
2894 int
2896 {
2897  struct MHD_Daemon *daemon = connection->daemon;
2898  char *line;
2899  size_t line_len;
2900  int ret;
2901 
2902  connection->in_idle = true;
2903  while (! connection->suspended)
2904  {
2905 #if DEBUG_STATES
2906  MHD_DLOG (daemon,
2907  _("In function %s handling connection at state: %s\n"),
2908  __FUNCTION__,
2909  MHD_state_to_string (connection->state));
2910 #endif
2911  switch (connection->state)
2912  {
2913  case MHD_CONNECTION_INIT:
2914  line = get_next_header_line (connection,
2915  &line_len);
2916  /* Check for empty string, as we might want
2917  to tolerate 'spurious' empty lines; also
2918  NULL means we didn't get a full line yet;
2919  line is not 0-terminated here. */
2920  if ( (NULL == line) ||
2921  (0 == line[0]) )
2922  {
2923  if (MHD_CONNECTION_INIT != connection->state)
2924  continue;
2925  if (connection->read_closed)
2926  {
2927  CONNECTION_CLOSE_ERROR (connection,
2928  NULL);
2929  continue;
2930  }
2931  break;
2932  }
2933  if (MHD_NO == parse_initial_message_line (connection,
2934  line,
2935  line_len))
2936  CONNECTION_CLOSE_ERROR (connection,
2937  NULL);
2938  else
2939  connection->state = MHD_CONNECTION_URL_RECEIVED;
2940  continue;
2942  line = get_next_header_line (connection,
2943  NULL);
2944  if (NULL == line)
2945  {
2946  if (MHD_CONNECTION_URL_RECEIVED != connection->state)
2947  continue;
2948  if (connection->read_closed)
2949  {
2950  CONNECTION_CLOSE_ERROR (connection,
2951  NULL);
2952  continue;
2953  }
2954  break;
2955  }
2956  if (0 == line[0])
2957  {
2958  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2959  connection->header_size = (size_t) (line - connection->read_buffer);
2960  continue;
2961  }
2962  if (MHD_NO == process_header_line (connection,
2963  line))
2964  {
2965  transmit_error_response (connection,
2968  break;
2969  }
2971  continue;
2973  line = get_next_header_line (connection,
2974  NULL);
2975  if (NULL == line)
2976  {
2977  if (connection->state != MHD_CONNECTION_HEADER_PART_RECEIVED)
2978  continue;
2979  if (connection->read_closed)
2980  {
2981  CONNECTION_CLOSE_ERROR (connection,
2982  NULL);
2983  continue;
2984  }
2985  break;
2986  }
2987  if (MHD_NO ==
2988  process_broken_line (connection,
2989  line,
2990  MHD_HEADER_KIND))
2991  continue;
2992  if (0 == line[0])
2993  {
2994  connection->state = MHD_CONNECTION_HEADERS_RECEIVED;
2995  connection->header_size = (size_t) (line - connection->read_buffer);
2996  continue;
2997  }
2998  continue;
3000  parse_connection_headers (connection);
3001  if (MHD_CONNECTION_CLOSED == connection->state)
3002  continue;
3004  if (connection->suspended)
3005  break;
3006  continue;
3008  call_connection_handler (connection); /* first call */
3009  if (MHD_CONNECTION_CLOSED == connection->state)
3010  continue;
3011  if (need_100_continue (connection))
3012  {
3013  connection->state = MHD_CONNECTION_CONTINUE_SENDING;
3014  if (MHD_NO != socket_flush_possible (connection))
3015  socket_start_extra_buffering (connection);
3016  else
3017  socket_start_no_buffering (connection);
3018 
3019  break;
3020  }
3021  if ( (NULL != connection->response) &&
3022  ( (MHD_str_equal_caseless_ (connection->method,
3024  (MHD_str_equal_caseless_ (connection->method,
3025  MHD_HTTP_METHOD_PUT))) )
3026  {
3027  /* we refused (no upload allowed!) */
3028  connection->remaining_upload_size = 0;
3029  /* force close, in case client still tries to upload... */
3030  connection->read_closed = true;
3031  }
3032  connection->state = (0 == connection->remaining_upload_size)
3034  if (connection->suspended)
3035  break;
3036  continue;
3038  if (connection->continue_message_write_offset ==
3040  {
3041  connection->state = MHD_CONNECTION_CONTINUE_SENT;
3042  if (MHD_NO != socket_flush_possible (connection))
3043  socket_start_no_buffering_flush (connection);
3044  else
3045  socket_start_normal_buffering (connection);
3046 
3047  continue;
3048  }
3049  break;
3051  if (0 != connection->read_buffer_offset)
3052  {
3053  process_request_body (connection); /* loop call */
3054  if (MHD_CONNECTION_CLOSED == connection->state)
3055  continue;
3056  }
3057  if ( (0 == connection->remaining_upload_size) ||
3058  ( (MHD_SIZE_UNKNOWN == connection->remaining_upload_size) &&
3059  (0 == connection->read_buffer_offset) &&
3060  (connection->read_closed) ) )
3061  {
3062  if ( (connection->have_chunked_upload) &&
3063  (! connection->read_closed) )
3064  connection->state = MHD_CONNECTION_BODY_RECEIVED;
3065  else
3066  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3067  if (connection->suspended)
3068  break;
3069  continue;
3070  }
3071  break;
3073  line = get_next_header_line (connection,
3074  NULL);
3075  if (NULL == line)
3076  {
3077  if (connection->state != MHD_CONNECTION_BODY_RECEIVED)
3078  continue;
3079  if (connection->read_closed)
3080  {
3081  CONNECTION_CLOSE_ERROR (connection,
3082  NULL);
3083  continue;
3084  }
3085  break;
3086  }
3087  if (0 == line[0])
3088  {
3089  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3090  if (connection->suspended)
3091  break;
3092  continue;
3093  }
3094  if (MHD_NO == process_header_line (connection,
3095  line))
3096  {
3097  transmit_error_response (connection,
3100  break;
3101  }
3103  continue;
3105  line = get_next_header_line (connection,
3106  NULL);
3107  if (NULL == line)
3108  {
3109  if (connection->state != MHD_CONNECTION_FOOTER_PART_RECEIVED)
3110  continue;
3111  if (connection->read_closed)
3112  {
3113  CONNECTION_CLOSE_ERROR (connection,
3114  NULL);
3115  continue;
3116  }
3117  break;
3118  }
3119  if (MHD_NO ==
3120  process_broken_line (connection,
3121  line,
3122  MHD_FOOTER_KIND))
3123  continue;
3124  if (0 == line[0])
3125  {
3126  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3127  if (connection->suspended)
3128  break;
3129  continue;
3130  }
3131  continue;
3133  call_connection_handler (connection); /* "final" call */
3134  if (connection->state == MHD_CONNECTION_CLOSED)
3135  continue;
3136  if (NULL == connection->response)
3137  break; /* try again next time */
3138  if (MHD_NO == build_header_response (connection))
3139  {
3140  /* oops - close! */
3141  CONNECTION_CLOSE_ERROR (connection,
3142  _("Closing connection (failed to create response header)\n"));
3143  continue;
3144  }
3145  connection->state = MHD_CONNECTION_HEADERS_SENDING;
3146  if (MHD_NO != socket_flush_possible (connection))
3147  socket_start_extra_buffering (connection);
3148  else
3149  socket_start_no_buffering (connection);
3150 
3151  break;
3153  /* no default action */
3154  break;
3156  /* Some clients may take some actions right after header receive */
3157  if (MHD_NO != socket_flush_possible (connection))
3158  socket_start_no_buffering_flush (connection);
3159 
3160 #ifdef UPGRADE_SUPPORT
3161  if (NULL != connection->response->upgrade_handler)
3162  {
3163  socket_start_normal_buffering (connection);
3164  connection->state = MHD_CONNECTION_UPGRADE;
3165  /* This connection is "upgraded". Pass socket to application. */
3166  if (MHD_YES !=
3168  connection))
3169  {
3170  /* upgrade failed, fail hard */
3171  CONNECTION_CLOSE_ERROR (connection,
3172  NULL);
3173  continue;
3174  }
3175  /* Response is not required anymore for this connection. */
3176  if (NULL != connection->response)
3177  {
3178  struct MHD_Response * const resp = connection->response;
3179  connection->response = NULL;
3180  MHD_destroy_response (resp);
3181  }
3182  continue;
3183  }
3184 #endif /* UPGRADE_SUPPORT */
3185  if (MHD_NO != socket_flush_possible (connection))
3186  socket_start_extra_buffering (connection);
3187  else
3188  socket_start_normal_buffering (connection);
3189 
3190  if (connection->have_chunked_upload)
3192  else
3194  continue;
3196  /* nothing to do here */
3197  break;
3199  if (NULL != connection->response->crc)
3200  MHD_mutex_lock_chk_ (&connection->response->mutex);
3201  if (0 == connection->response->total_size)
3202  {
3203  if (NULL != connection->response->crc)
3204  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3205  connection->state = MHD_CONNECTION_BODY_SENT;
3206  continue;
3207  }
3208  if (MHD_YES == try_ready_normal_body (connection))
3209  {
3210  if (NULL != connection->response->crc)
3211  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3213  /* Buffering for flushable socket was already enabled*/
3214  if (MHD_NO == socket_flush_possible (connection))
3215  socket_start_no_buffering (connection);
3216  break;
3217  }
3218  /* mutex was already unlocked by "try_ready_normal_body */
3219  /* not ready, no socket action */
3220  break;
3222  /* nothing to do here */
3223  break;
3225  if (NULL != connection->response->crc)
3226  MHD_mutex_lock_chk_ (&connection->response->mutex);
3227  if ( (0 == connection->response->total_size) ||
3228  (connection->response_write_position ==
3229  connection->response->total_size) )
3230  {
3231  if (NULL != connection->response->crc)
3232  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3233  connection->state = MHD_CONNECTION_BODY_SENT;
3234  continue;
3235  }
3236  if (MHD_YES == try_ready_chunked_body (connection))
3237  {
3238  if (NULL != connection->response->crc)
3239  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3241  /* Buffering for flushable socket was already enabled */
3242  if (MHD_NO == socket_flush_possible (connection))
3243  socket_start_no_buffering (connection);
3244  continue;
3245  }
3246  if (NULL != connection->response->crc)
3247  MHD_mutex_unlock_chk_ (&connection->response->mutex);
3248  break;
3250  if (MHD_NO == build_header_response (connection))
3251  {
3252  /* oops - close! */
3253  CONNECTION_CLOSE_ERROR (connection,
3254  _("Closing connection (failed to create response header)\n"));
3255  continue;
3256  }
3257  if ( (! connection->have_chunked_upload) ||
3258  (connection->write_buffer_send_offset ==
3259  connection->write_buffer_append_offset) )
3260  connection->state = MHD_CONNECTION_FOOTERS_SENT;
3261  else
3262  connection->state = MHD_CONNECTION_FOOTERS_SENDING;
3263  continue;
3265  /* no default action */
3266  break;
3268  if (MHD_HTTP_PROCESSING == connection->responseCode)
3269  {
3270  /* After this type of response, we allow sending another! */
3272  MHD_destroy_response (connection->response);
3273  connection->response = NULL;
3274  /* FIXME: maybe partially reset memory pool? */
3275  continue;
3276  }
3277  if (MHD_NO != socket_flush_possible (connection))
3278  socket_start_no_buffering_flush (connection);
3279  else
3280  socket_start_normal_buffering (connection);
3281 
3282  MHD_destroy_response (connection->response);
3283  connection->response = NULL;
3284  if ( (NULL != daemon->notify_completed) &&
3285  (connection->client_aware) )
3286  {
3287  connection->client_aware = false;
3288  daemon->notify_completed (daemon->notify_completed_cls,
3289  connection,
3290  &connection->client_context,
3292  }
3293  if ( (MHD_CONN_USE_KEEPALIVE != connection->keepalive) ||
3294  (connection->read_closed) )
3295  {
3296  /* have to close for some reason */
3297  MHD_connection_close_ (connection,
3299  MHD_pool_destroy (connection->pool);
3300  connection->pool = NULL;
3301  connection->read_buffer = NULL;
3302  connection->read_buffer_size = 0;
3303  connection->read_buffer_offset = 0;
3304  }
3305  else
3306  {
3307  /* can try to keep-alive */
3308  if (MHD_NO != socket_flush_possible (connection))
3309  socket_start_normal_buffering (connection);
3310  connection->version = NULL;
3311  connection->state = MHD_CONNECTION_INIT;
3312  connection->last = NULL;
3313  connection->colon = NULL;
3314  connection->header_size = 0;
3315  connection->keepalive = MHD_CONN_KEEPALIVE_UNKOWN;
3316  /* Reset the read buffer to the starting size,
3317  preserving the bytes we have already read. */
3318  connection->read_buffer
3319  = MHD_pool_reset (connection->pool,
3320  connection->read_buffer,
3321  connection->read_buffer_offset,
3322  connection->daemon->pool_size / 2);
3323  connection->read_buffer_size
3324  = connection->daemon->pool_size / 2;
3325  }
3326  connection->client_aware = false;
3327  connection->client_context = NULL;
3328  connection->continue_message_write_offset = 0;
3329  connection->responseCode = 0;
3330  connection->headers_received = NULL;
3331  connection->headers_received_tail = NULL;
3332  connection->response_write_position = 0;
3333  connection->have_chunked_upload = false;
3334  connection->current_chunk_size = 0;
3335  connection->current_chunk_offset = 0;
3336  connection->method = NULL;
3337  connection->url = NULL;
3338  connection->write_buffer = NULL;
3339  connection->write_buffer_size = 0;
3340  connection->write_buffer_send_offset = 0;
3341  connection->write_buffer_append_offset = 0;
3342  continue;
3343  case MHD_CONNECTION_CLOSED:
3344  cleanup_connection (connection);
3345  return MHD_NO;
3346 #ifdef UPGRADE_SUPPORT
3347  case MHD_CONNECTION_UPGRADE:
3348  connection->in_idle = false;
3349  return MHD_YES; /* keep open */
3350 #endif /* UPGRADE_SUPPORT */
3351  default:
3352  EXTRA_CHECK (0);
3353  break;
3354  }
3355  break;
3356  }
3357  if (! connection->suspended)
3358  {
3359  time_t timeout;
3360  timeout = connection->connection_timeout;
3361  if ( (0 != timeout) &&
3362  (timeout < (MHD_monotonic_sec_counter() - connection->last_activity)) )
3363  {
3364  MHD_connection_close_ (connection,
3366  connection->in_idle = false;
3367  return MHD_YES;
3368  }
3369  }
3371  ret = MHD_YES;
3372 #ifdef EPOLL_SUPPORT
3373  if ( (! connection->suspended) &&
3374  (0 != (daemon->options & MHD_USE_EPOLL)) )
3375  {
3376  ret = MHD_connection_epoll_update_ (connection);
3377  }
3378 #endif /* EPOLL_SUPPORT */
3379  connection->in_idle = false;
3380  return ret;
3381 }
3382 
3383 
3384 #ifdef EPOLL_SUPPORT
3385 
3393 int
3394 MHD_connection_epoll_update_ (struct MHD_Connection *connection)
3395 {
3396  struct MHD_Daemon *daemon = connection->daemon;
3397 
3398  if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
3399  (0 == (connection->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) &&
3400  (0 == (connection->epoll_state & MHD_EPOLL_STATE_SUSPENDED)) &&
3401  ( ( (MHD_EVENT_LOOP_INFO_WRITE == connection->event_loop_info) &&
3402  (0 == (connection->epoll_state & MHD_EPOLL_STATE_WRITE_READY))) ||
3403  ( (MHD_EVENT_LOOP_INFO_READ == connection->event_loop_info) &&
3404  (0 == (connection->epoll_state & MHD_EPOLL_STATE_READ_READY)) ) ) )
3405  {
3406  /* add to epoll set */
3407  struct epoll_event event;
3408 
3409  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
3410  event.data.ptr = connection;
3411  if (0 != epoll_ctl (daemon->epoll_fd,
3412  EPOLL_CTL_ADD,
3413  connection->socket_fd,
3414  &event))
3415  {
3416 #ifdef HAVE_MESSAGES
3417  if (0 != (daemon->options & MHD_USE_ERROR_LOG))
3418  MHD_DLOG (daemon,
3419  _("Call to epoll_ctl failed: %s\n"),
3421 #endif
3422  connection->state = MHD_CONNECTION_CLOSED;
3423  cleanup_connection (connection);
3424  return MHD_NO;
3425  }
3426  connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET;
3427  }
3428  return MHD_YES;
3429 }
3430 #endif
3431 
3432 
3438 void
3440 {
3444 }
3445 
3446 
3457 const union MHD_ConnectionInfo *
3459  enum MHD_ConnectionInfoType info_type,
3460  ...)
3461 {
3462  switch (info_type)
3463  {
3464 #ifdef HTTPS_SUPPORT
3466  if (NULL == connection->tls_session)
3467  return NULL;
3468  connection->cipher = gnutls_cipher_get (connection->tls_session);
3469  return (const union MHD_ConnectionInfo *) &connection->cipher;
3471  if (NULL == connection->tls_session)
3472  return NULL;
3473  connection->protocol = gnutls_protocol_get_version (connection->tls_session);
3474  return (const union MHD_ConnectionInfo *) &connection->protocol;
3476  if (NULL == connection->tls_session)
3477  return NULL;
3478  return (const union MHD_ConnectionInfo *) &connection->tls_session;
3479 #endif /* HTTPS_SUPPORT */
3481  return (const union MHD_ConnectionInfo *) &connection->addr;
3483  return (const union MHD_ConnectionInfo *) &connection->daemon;
3485  return (const union MHD_ConnectionInfo *) &connection->socket_fd;
3487  return (const union MHD_ConnectionInfo *) &connection->socket_context;
3489  connection->suspended_dummy = connection->suspended ? MHD_YES : MHD_NO;
3490  return (const union MHD_ConnectionInfo *) &connection->suspended_dummy;
3492  connection->connection_timeout_dummy = (unsigned int)connection->connection_timeout;
3493  return (const union MHD_ConnectionInfo *) &connection->connection_timeout_dummy;
3495  if ( (MHD_CONNECTION_HEADERS_RECEIVED > connection->state) ||
3496  (MHD_CONNECTION_CLOSED == connection->state) ||
3497  (MHD_CONNECTION_IN_CLEANUP == connection->state) )
3498  return NULL; /* invalid, too early! */
3499  return (const union MHD_ConnectionInfo *) &connection->header_size;
3500  default:
3501  return NULL;
3502  }
3503 }
3504 
3505 
3515 int
3517  enum MHD_CONNECTION_OPTION option,
3518  ...)
3519 {
3520  va_list ap;
3521  struct MHD_Daemon *daemon;
3522 
3523  daemon = connection->daemon;
3524  switch (option)
3525  {
3526  case MHD_CONNECTION_OPTION_TIMEOUT:
3527  if (0 == connection->connection_timeout)
3528  connection->last_activity = MHD_monotonic_sec_counter();
3529 
3531  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3532  (! connection->suspended) )
3533  {
3534  if (connection->connection_timeout == daemon->connection_timeout)
3536  daemon->normal_timeout_tail,
3537  connection);
3538  else
3540  daemon->manual_timeout_tail,
3541  connection);
3542  }
3543  va_start (ap, option);
3544  connection->connection_timeout = va_arg (ap,
3545  unsigned int);
3546  va_end (ap);
3547  if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3548  (! connection->suspended) )
3549  {
3550  if (connection->connection_timeout == daemon->connection_timeout)
3552  daemon->normal_timeout_tail,
3553  connection);
3554  else
3556  daemon->manual_timeout_tail,
3557  connection);
3558  }
3560  return MHD_YES;
3561  default:
3562  return MHD_NO;
3563  }
3564 }
3565 
3566 
3578 int
3580  unsigned int status_code,
3581  struct MHD_Response *response)
3582 {
3583 #ifdef UPGRADE_SUPPORT
3584  struct MHD_Daemon *daemon;
3585 #endif /* UPGRADE_SUPPORT */
3586 
3587  if ( (NULL == connection) ||
3588  (NULL == response) ||
3589  (NULL != connection->response) ||
3590  ( (MHD_CONNECTION_HEADERS_PROCESSED != connection->state) &&
3591  (MHD_CONNECTION_FOOTERS_RECEIVED != connection->state) ) )
3592  return MHD_NO;
3593 #ifdef UPGRADE_SUPPORT
3594  daemon = connection->daemon;
3595  if ( (NULL != response->upgrade_handler) &&
3596  (0 == (daemon->options & MHD_ALLOW_UPGRADE)) )
3597  {
3598 #ifdef HAVE_MESSAGES
3599  MHD_DLOG (daemon,
3600  _("Attempted 'upgrade' connection on daemon without MHD_ALLOW_UPGRADE option!\n"));
3601 #endif
3602  return MHD_NO;
3603  }
3604  if ( (MHD_HTTP_SWITCHING_PROTOCOLS != status_code) &&
3605  (NULL != response->upgrade_handler) )
3606  {
3607 #ifdef HAVE_MESSAGES
3608  MHD_DLOG (daemon,
3609  _("Application used invalid status code for 'upgrade' response!\n"));
3610 #endif
3611  return MHD_NO;
3612  }
3613 #endif /* UPGRADE_SUPPORT */
3614  MHD_increment_response_rc (response);
3615  connection->response = response;
3616  connection->responseCode = status_code;
3617 #if LINUX
3618  if ( (response->fd == -1) ||
3619  (0 != (connection->daemon->options & MHD_USE_TLS)) )
3620  connection->resp_sender = MHD_resp_sender_std;
3621  else
3622  connection->resp_sender = MHD_resp_sender_sendfile;
3623 #endif /* LINUX */
3624 
3625  if ( ( (NULL != connection->method) &&
3626  (MHD_str_equal_caseless_ (connection->method,
3627  MHD_HTTP_METHOD_HEAD)) ) ||
3628  (MHD_HTTP_OK > status_code) ||
3629  (MHD_HTTP_NO_CONTENT == status_code) ||
3630  (MHD_HTTP_NOT_MODIFIED == status_code) )
3631  {
3632  /* if this is a "HEAD" request, or a status code for
3633  which a body is not allowed, pretend that we
3634  have already sent the full message body. */
3635  connection->response_write_position = response->total_size;
3636  }
3637  if ( (MHD_CONNECTION_HEADERS_PROCESSED == connection->state) &&
3638  (NULL != connection->method) &&
3639  ( (MHD_str_equal_caseless_ (connection->method,
3641  (MHD_str_equal_caseless_ (connection->method,
3642  MHD_HTTP_METHOD_PUT))) )
3643  {
3644  /* response was queued "early", refuse to read body / footers or
3645  further requests! */
3646  connection->read_closed = true;
3647  connection->state = MHD_CONNECTION_FOOTERS_RECEIVED;
3648  }
3649  if (! connection->in_idle)
3650  (void) MHD_connection_handle_idle (connection);
3651  return MHD_YES;
3652 }
3653 
3654 
3655 /* end of connection.c */
static int process_header_line(struct MHD_Connection *connection, char *line)
Definition: connection.c:2300
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1992
static int parse_cookie_header(struct MHD_Connection *connection)
Definition: connection.c:1709
void * unescape_callback_cls
Definition: internal.h:1401
#define MHD_send_(s, b, l)
Definition: mhd_sockets.h:259
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:454
uint64_t total_size
Definition: internal.h:343
bool have_chunked_upload
Definition: internal.h:910
static int try_ready_normal_body(struct MHD_Connection *connection)
Definition: connection.c:725
uint64_t current_chunk_offset
Definition: internal.h:924
#define DLL_insert(head, tail, element)
Definition: internal.h:1726
#define MHD_HTTP_METHOD_CONNECT
Definition: microhttpd.h:748
void * socket_context
Definition: internal.h:683
static void MHD_connection_update_event_loop_info(struct MHD_Connection *connection)
Definition: connection.c:1459
enum MHD_CONNECTION_STATE state
Definition: internal.h:890
static int try_ready_chunked_body(struct MHD_Connection *connection)
Definition: connection.c:791
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:299
#define MHD_lookup_header_s_token_ci(c, h, tkn)
Definition: connection.c:517
uint64_t response_write_position
Definition: internal.h:798
enum MHD_ConnKeepAlive keepalive
Definition: internal.h:707
#define NULL
Definition: reason_phrase.c:31
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:142
#define HTTP_100_CONTINUE
Definition: connection.c:47
#define MHD_ICY_FLAG
Definition: microhttpd.h:408
enum MHD_ConnectionEventLoopInfo event_loop_info
Definition: internal.h:895
int MHD_connection_handle_write(struct MHD_Connection *connection)
Definition: connection.c:2630
time_t connection_timeout
Definition: internal.h:1567
static int connection_add_header(struct MHD_Connection *connection, const char *key, const char *value, enum MHD_ValueKind kind)
Definition: connection.c:1678
Methods for managing connections.
char * version
Definition: internal.h:700
int suspended_dummy
Definition: internal.h:1001
#define INTERNAL_ERROR
Definition: connection.c:97
#define MHD_HTTP_HEADER_HOST
Definition: microhttpd.h:464
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:592
#define MHD_YES
Definition: microhttpd.h:134
const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:236
struct MHD_Response * response
Definition: internal.h:656
char * colon
Definition: internal.h:737
#define REQUEST_LACKS_HOST
Definition: connection.c:72
char * write_buffer
Definition: internal.h:720
#define MHD_socket_get_error_()
Definition: mhd_sockets.h:507
struct MHD_Connection * normal_timeout_tail
Definition: internal.h:1329
Header for platform missing functions.
#define MHD_HTTP_NOT_MODIFIED
Definition: microhttpd.h:323
void MHD_connection_mark_closed_(struct MHD_Connection *connection)
Definition: connection.c:554
MHD_RequestTerminationCode
Definition: microhttpd.h:1574
size_t data_size
Definition: internal.h:360
static int do_read(struct MHD_Connection *connection)
Definition: connection.c:2177
#define EXTRA_CHECK(a)
Definition: internal.h:1714
enum MHD_ValueKind kind
Definition: internal.h:278
struct MHD_HTTP_Header * first_header
Definition: internal.h:294
static void transmit_error_response(struct MHD_Connection *connection, unsigned int status_code, const char *message)
Definition: connection.c:1402
MHD_AccessHandlerCallback default_handler
Definition: internal.h:1247
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:188
static void call_connection_handler(struct MHD_Connection *connection)
Definition: connection.c:1918
uint64_t remaining_upload_size
Definition: internal.h:791
unsigned int responseCode
Definition: internal.h:901
int MHD_parse_arguments_(struct MHD_Connection *connection, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers)
Definition: internal.c:186
MHD_CONNECTION_STATE
Definition: internal.h:401
char * value
Definition: internal.h:272
Methods for managing response objects.
static void cleanup_connection(struct MHD_Connection *connection)
Definition: connection.c:2824
void MHD_update_last_activity_(struct MHD_Connection *connection)
Definition: connection.c:2522
#define MHD_UNSIGNED_LONG_LONG
Definition: microhttpd.h:277
void * uri_log_callback_cls
Definition: internal.h:1391
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
size_t header_size
Definition: internal.h:785
struct MHD_Daemon * daemon
Definition: internal.h:641
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:942
struct MHD_Connection * manual_timeout_head
Definition: internal.h:1337
struct MHD_Connection * cleanup_head
Definition: internal.h:1277
#define MHD_HTTP_HEADER_COOKIE
Definition: microhttpd.h:568
static bool MHD_lookup_header_token_ci(const struct MHD_Connection *connection, const char *header, const char *token, size_t token_len)
Definition: connection.c:484
#define MHD_SCKT_ERR_IS_REMOTE_DISCNN_(err)
Definition: mhd_sockets.h:656
static void connection_close_error(struct MHD_Connection *connection, const char *emsg)
Definition: connection.c:688
#define XDLL_remove(head, tail, element)
Definition: internal.h:1792
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
bool client_aware
Definition: internal.h:841
#define XDLL_insert(head, tail, element)
Definition: internal.h:1771
static int keepalive_possible(struct MHD_Connection *connection)
Definition: connection.c:913
int strict_for_client
Definition: internal.h:1588
#define MHD_HTTP_URI_TOO_LONG
Definition: microhttpd.h:349
struct MHD_Connection * cleanup_tail
Definition: internal.h:1282
Header for platform-independent inter-thread communication.
int MHD_connection_handle_read(struct MHD_Connection *connection)
Definition: connection.c:2560
#define MHD_STATICSTR_LEN_(macro)
Definition: internal.h:124
size_t data_buffer_size
Definition: internal.h:365
size_t write_buffer_send_offset
Definition: internal.h:773
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:233
void * mhd_panic_cls
Definition: daemon.c:154
size_t read_buffer_size
Definition: internal.h:757
struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:658
void * client_context
Definition: internal.h:674
struct MHD_Connection * manual_timeout_tail
Definition: internal.h:1344
int MHD_SCKT_OPT_BOOL_
Definition: mhd_sockets.h:201
const char * url
Definition: internal.h:694
size_t continue_message_write_offset
Definition: internal.h:812
#define REQUEST_MALFORMED
Definition: connection.c:85
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:848
char * method
Definition: internal.h:688
#define MHD_SCKT_ERR_IS_EAGAIN_(err)
Definition: mhd_sockets.h:622
enum MHD_FLAG options
Definition: internal.h:1578
#define MHD_HTTP_NO_CONTENT
Definition: microhttpd.h:311
LogCallback uri_log_callback
Definition: internal.h:1386
static int socket_start_no_buffering(struct MHD_Connection *connection)
Definition: connection.c:209
bool in_cleanup
Definition: internal.h:878
void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1056
#define MHD_HTTP_OK
Definition: microhttpd.h:307
time_t connection_timeout
Definition: internal.h:829
int MHD_set_connection_option(struct MHD_Connection *connection, enum MHD_CONNECTION_OPTION option,...)
Definition: connection.c:3516
const char * MHD_lookup_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key)
Definition: connection.c:450
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1090
Methods for managing connections.
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
int(* read_handler)(struct MHD_Connection *connection)
Definition: internal.h:930
char * last
Definition: internal.h:728
struct MHD_Connection * normal_timeout_head
Definition: internal.h:1322
static void get_date_string(char *date, size_t date_len)
Definition: connection.c:965
MHD_ValueKind
Definition: microhttpd.h:1524
char * read_buffer
Definition: internal.h:714
const union MHD_ConnectionInfo * MHD_get_connection_info(struct MHD_Connection *connection, enum MHD_ConnectionInfoType info_type,...)
Definition: connection.c:3458
ReceiveCallback recv_cls
Definition: internal.h:947
static int need_100_continue(struct MHD_Connection *connection)
Definition: connection.c:529
size_t write_buffer_size
Definition: internal.h:768
limits values definitions
MHD_ConnectionInfoType
Definition: microhttpd.h:1722
uint64_t data_start
Definition: internal.h:349
#define MHD_HTTP_VERSION_1_1
Definition: microhttpd.h:735
internal shared structures
#define MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
Definition: microhttpd.h:369
UnescapeCallback unescape_callback
Definition: internal.h:1396
int MHD_tls_connection_shutdown(struct MHD_Connection *connection)
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
static int try_grow_read_buffer(struct MHD_Connection *connection)
Definition: connection.c:1025
int MHD_queue_response(struct MHD_Connection *connection, unsigned int status_code, struct MHD_Response *response)
Definition: connection.c:3579
internal monotonic clock functions implementations
int(* write_handler)(struct MHD_Connection *connection)
Definition: internal.h:936
unsigned int connection_timeout_dummy
Definition: internal.h:834
#define MHD_HTTP_BAD_REQUEST
Definition: microhttpd.h:329
struct MHD_Connection * connections_head
Definition: internal.h:1257
size_t pool_size
Definition: internal.h:1434
char * header
Definition: internal.h:267
static int check_write_done(struct MHD_Connection *connection, enum MHD_CONNECTION_STATE next_state)
Definition: connection.c:2271
struct MHD_itc_ itc
Definition: internal.h:1514
time_t last_activity
Definition: internal.h:823
int MHD_connection_handle_idle(struct MHD_Connection *connection)
Definition: connection.c:2895
#define MHD_socket_strerr_(err)
Definition: mhd_sockets.h:525
static int process_broken_line(struct MHD_Connection *connection, char *line, enum MHD_ValueKind kind)
Definition: connection.c:2359
#define MHD_check_response_header_s_token_ci(r, k, tkn)
Definition: internal.h:1926
enum MHD_ResponseFlags flags
Definition: internal.h:381
#define MHD_HTTP_HEADER_EXPECT
Definition: microhttpd.h:458
struct MemoryPool * pool
Definition: internal.h:666
#define MHD_connection_finish_forward_(conn)
Definition: connection.h:120
#define MHD_HTTP_METHOD_HEAD
Definition: microhttpd.h:754
static void parse_connection_headers(struct MHD_Connection *connection)
Definition: connection.c:2441
#define MHD_PANIC(msg)
Definition: internal.h:63
time_t MHD_monotonic_sec_counter(void)
Header for string manipulating helpers.
size_t write_buffer_append_offset
Definition: internal.h:779
struct MHD_HTTP_Header * next
Definition: internal.h:262
MHD_RequestCompletedCallback notify_completed
Definition: internal.h:1361
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:383
static int socket_start_extra_buffering(struct MHD_Connection *connection)
Definition: connection.c:150
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:440
bool read_closed
Definition: internal.h:861
void MHD_set_http_callbacks_(struct MHD_Connection *connection)
Definition: connection.c:3439
#define MHD_HTTP_METHOD_PUT
Definition: microhttpd.h:760
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:319
#define DLL_remove(head, tail, element)
Definition: internal.h:1747
void * notify_completed_cls
Definition: internal.h:1366
static void process_request_body(struct MHD_Connection *connection)
Definition: connection.c:1953
#define MHD_HTTP_VERSION_1_0
Definition: microhttpd.h:734
TransmitCallback send_cls
Definition: internal.h:952
#define EDLL_remove(head, tail, element)
Definition: internal.h:1834
int MHD_get_connection_values(struct MHD_Connection *connection, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: connection.c:356
#define MHD_HTTP_INTERNAL_SERVER_ERROR
Definition: microhttpd.h:377
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:312
static int parse_initial_message_line(struct MHD_Connection *connection, char *line, size_t line_len)
Definition: connection.c:1823
void * crc_cls
Definition: internal.h:306
struct sockaddr * addr
Definition: internal.h:743
MHD_mutex_ mutex
Definition: internal.h:338
MHD_PanicCallback mhd_panic
Definition: daemon.c:149
struct MHD_Connection * suspended_connections_tail
Definition: internal.h:1272
static int socket_start_normal_buffering(struct MHD_Connection *connection)
Definition: connection.c:292
#define _(String)
Definition: mhd_options.h:42
#define MHD_UNSIGNED_LONG_LONG_PRINTF
Definition: microhttpd.h:290
bool suspended
Definition: internal.h:996
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:446
#define MHD_HTTP_PROCESSING
Definition: microhttpd.h:305
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
static int socket_flush_possible(struct MHD_Connection *connection)
Definition: connection.c:132
char * data
Definition: internal.h:300
#define MHD_MIN(a, b)
Definition: internal.h:88
static int socket_start_no_buffering_flush(struct MHD_Connection *connection)
Definition: connection.c:262
static int do_write(struct MHD_Connection *connection)
Definition: connection.c:2227
size_t read_buffer_offset
Definition: internal.h:763
static char * get_next_header_line(struct MHD_Connection *connection, size_t *line_len)
Definition: connection.c:1619
void * default_handler_cls
Definition: internal.h:1252
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1519
size_t MHD_strx_to_uint64_n_(const char *str, size_t maxlen, uint64_t *out_val)
Definition: mhd_str.c:656
#define MHD_SCKT_ERR_IS_EINTR_(err)
Definition: mhd_sockets.h:613
MHD_mutex_ cleanup_connection_mutex
Definition: internal.h:1465
#define CONNECTION_CLOSE_ERROR(c, emsg)
Definition: connection.c:708
uint64_t current_chunk_size
Definition: internal.h:918
Header for platform-independent locks abstraction.
struct MHD_HTTP_Header * headers_received
Definition: internal.h:646
#define MHD_HTTP_SWITCHING_PROTOCOLS
Definition: microhttpd.h:304
struct MHD_Connection * connections_tail
Definition: internal.h:1262
_MHD_EXTERN const char * MHD_get_reason_phrase_for(unsigned int code)
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:502
#define MHD_BUF_INC_SIZE
Definition: internal.h:98
#define SIZE_MAX
Definition: mhd_limits.h:83
int MHD_set_connection_value(struct MHD_Connection *connection, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: connection.c:408
#define REQUEST_TOO_BIG
Definition: connection.c:59
struct MHD_HTTP_Header * headers_received_tail
Definition: internal.h:651
static int build_header_response(struct MHD_Connection *connection)
Definition: connection.c:1057
size_t pool_increment
Definition: internal.h:1439
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
#define MHD_HTTP_METHOD_POST
Definition: microhttpd.h:758
size_t MHD_str_to_uint64_(const char *str, uint64_t *out_val)
Definition: mhd_str.c:440
struct MHD_Connection * suspended_connections_head
Definition: internal.h:1267
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...