GNU libmicrohttpd  0.9.76
response.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007-2021 Daniel Pittman and Christian Grothoff
4  Copyright (C) 2015-2021 Evgeny Grin (Karlson2k)
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either
9  version 2.1 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
28 #define MHD_NO_DEPRECATION 1
29 
30 #include "mhd_options.h"
31 #ifdef HAVE_SYS_IOCTL_H
32 #include <sys/ioctl.h>
33 #endif /* HAVE_SYS_IOCTL_H */
34 #if defined(_WIN32) && ! defined(__CYGWIN__)
35 #include <windows.h>
36 #endif /* _WIN32 && !__CYGWIN__ */
37 
38 #include "internal.h"
39 #include "response.h"
40 #include "mhd_limits.h"
41 #include "mhd_sockets.h"
42 #include "mhd_itc.h"
43 #include "mhd_str.h"
44 #include "connection.h"
45 #include "memorypool.h"
46 #include "mhd_send.h"
47 #include "mhd_compat.h"
48 #include "mhd_assert.h"
49 
50 
51 #if defined(MHD_W32_MUTEX_)
52 #ifndef WIN32_LEAN_AND_MEAN
53 #define WIN32_LEAN_AND_MEAN 1
54 #endif /* !WIN32_LEAN_AND_MEAN */
55 #include <windows.h>
56 #endif /* MHD_W32_MUTEX_ */
57 #if defined(_WIN32)
58 #include <io.h> /* for lseek(), read() */
59 #endif /* _WIN32 */
60 
61 
66 #ifndef MHD_FILE_READ_BLOCK_SIZE
67 #ifdef _WIN32
68 #define MHD_FILE_READ_BLOCK_SIZE 16384 /* 16k */
69 #else /* _WIN32 */
70 #define MHD_FILE_READ_BLOCK_SIZE 4096 /* 4k */
71 #endif /* _WIN32 */
72 #endif /* !MHD_FD_BLOCK_SIZE */
73 
77 #define _MHD_insert_header_first(presponse, phdr) do { \
78  mhd_assert (NULL == phdr->next); \
79  mhd_assert (NULL == phdr->prev); \
80  if (NULL == presponse->first_header) \
81  { \
82  mhd_assert (NULL == presponse->last_header); \
83  presponse->first_header = phdr; \
84  presponse->last_header = phdr; \
85  } \
86  else \
87  { \
88  mhd_assert (NULL != presponse->last_header); \
89  presponse->first_header->prev = phdr; \
90  phdr->next = presponse->first_header; \
91  presponse->first_header = phdr; \
92  } \
93 } while (0)
94 
98 #define _MHD_insert_header_last(presponse, phdr) do { \
99  mhd_assert (NULL == phdr->next); \
100  mhd_assert (NULL == phdr->prev); \
101  if (NULL == presponse->last_header) \
102  { \
103  mhd_assert (NULL == presponse->first_header); \
104  presponse->last_header = phdr; \
105  presponse->first_header = phdr; \
106  } \
107  else \
108  { \
109  mhd_assert (NULL != presponse->first_header); \
110  presponse->last_header->next = phdr; \
111  phdr->prev = presponse->last_header; \
112  presponse->last_header = phdr; \
113  } \
114 } while (0)
115 
116 
120 #define _MHD_remove_header(presponse, phdr) do { \
121  mhd_assert (NULL != presponse->first_header); \
122  mhd_assert (NULL != presponse->last_header); \
123  if (NULL == phdr->prev) \
124  { \
125  mhd_assert (phdr == presponse->first_header); \
126  presponse->first_header = phdr->next; \
127  } \
128  else \
129  { \
130  mhd_assert (phdr != presponse->first_header); \
131  mhd_assert (phdr == phdr->prev->next); \
132  phdr->prev->next = phdr->next; \
133  } \
134  if (NULL == phdr->next) \
135  { \
136  mhd_assert (phdr == presponse->last_header); \
137  presponse->last_header = phdr->prev; \
138  } \
139  else \
140  { \
141  mhd_assert (phdr != presponse->last_header); \
142  mhd_assert (phdr == phdr->next->prev); \
143  phdr->next->prev = phdr->prev; \
144  } \
145 } while (0)
146 
156 static enum MHD_Result
157 add_response_entry (struct MHD_Response *response,
158  enum MHD_ValueKind kind,
159  const char *header,
160  const char *content)
161 {
162  struct MHD_HTTP_Header *hdr;
163 
164  if ( (NULL == response) ||
165  (NULL == header) ||
166  (NULL == content) ||
167  (0 == header[0]) ||
168  (0 == content[0]) ||
169  (NULL != strchr (header, '\t')) ||
170  (NULL != strchr (header, ' ')) ||
171  (NULL != strchr (header, '\r')) ||
172  (NULL != strchr (header, '\n')) ||
173  (NULL != strchr (content, '\r')) ||
174  (NULL != strchr (content, '\n')) )
175  return MHD_NO;
176  if (NULL == (hdr = MHD_calloc_ (1, sizeof (struct MHD_HTTP_Header))))
177  return MHD_NO;
178  if (NULL == (hdr->header = strdup (header)))
179  {
180  free (hdr);
181  return MHD_NO;
182  }
183  hdr->header_size = strlen (header);
184  if (NULL == (hdr->value = strdup (content)))
185  {
186  free (hdr->header);
187  free (hdr);
188  return MHD_NO;
189  }
190  hdr->value_size = strlen (content);
191  hdr->kind = kind;
192  _MHD_insert_header_last (response, hdr);
193  return MHD_YES;
194 }
195 
196 
208 static enum MHD_Result
210  const char *value)
211 {
212  static const char *key = MHD_HTTP_HEADER_CONNECTION;
214  static const size_t key_len =
216  size_t value_len;
217  size_t old_value_len;
218  size_t buf_size;
219  ssize_t norm_len;
220  char *buf;
221  struct MHD_HTTP_Header *hdr;
222  bool value_has_close;
223  bool already_has_close;
224  size_t pos = 0;
226  if ( (NULL != strchr (value, '\r')) ||
227  (NULL != strchr (value, '\n')) )
228  return MHD_NO;
229 
230  if (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR))
231  {
233  key, key_len);
234  already_has_close =
235  (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_CLOSE));
236  mhd_assert (already_has_close == (0 == memcmp (hdr->value, "close", 5)));
237  mhd_assert (NULL != hdr);
238  }
239  else
240  {
241  hdr = NULL;
242  already_has_close = false;
245  key, key_len));
247  }
248  if (NULL != hdr)
249  old_value_len = hdr->value_size + 2; /* additional size for ", " */
250  else
251  old_value_len = 0;
252 
253  value_len = strlen (value);
254  if (value_len >= SSIZE_MAX)
255  return MHD_NO;
256  /* Additional space for normalisation and zero-termination*/
257  norm_len = (ssize_t) (value_len + value_len / 2 + 1);
258  buf_size = old_value_len + (size_t) norm_len;
259 
260  buf = malloc (buf_size);
261  if (NULL == buf)
262  return MHD_NO;
263  /* Remove "close" token (if any), it will be moved to the front */
264  value_has_close = MHD_str_remove_token_caseless_ (value, value_len, "close",
266  "close"),
267  buf + old_value_len,
268  &norm_len);
269 #ifdef UPGRADE_SUPPORT
270  if ( (NULL != response->upgrade_handler) && value_has_close)
271  { /* The "close" token cannot be used with connection "upgrade" */
272  free (buf);
273  return MHD_NO;
274  }
275 #endif /* UPGRADE_SUPPORT */
276  mhd_assert (0 <= norm_len);
277  if (0 > norm_len)
278  norm_len = 0; /* Must never happen */
279  if (0 != norm_len)
280  {
281  size_t len = norm_len;
282  MHD_str_remove_tokens_caseless_ (buf + old_value_len, &len,
283  "keep-alive",
284  MHD_STATICSTR_LEN_ ("keep-alive"));
285  norm_len = (ssize_t) len;
286  }
287  if (0 == norm_len)
288  { /* New value is empty after normalisation */
289  if (! value_has_close)
290  { /* The new value had no tokens */
291  free (buf);
292  return MHD_NO;
293  }
294  if (already_has_close)
295  { /* The "close" token is already present, nothing to modify */
296  free (buf);
297  return MHD_YES;
298  }
299  }
300  /* Add "close" token if required */
301  if (value_has_close && ! already_has_close)
302  {
303  /* Need to insert "close" token at the first position */
304  mhd_assert (buf_size >= old_value_len + (size_t) norm_len \
305  + MHD_STATICSTR_LEN_ ("close, ") + 1);
306  if (0 != norm_len)
307  memmove (buf + MHD_STATICSTR_LEN_ ("close, ") + old_value_len,
308  buf + old_value_len, norm_len + 1);
309  memcpy (buf, "close", MHD_STATICSTR_LEN_ ("close"));
310  pos += MHD_STATICSTR_LEN_ ("close");
311  }
312  /* Add old value tokens (if any) */
313  if (0 != old_value_len)
314  {
315  if (0 != pos)
316  {
317  buf[pos++] = ',';
318  buf[pos++] = ' ';
319  }
320  memcpy (buf + pos, hdr->value,
321  hdr->value_size);
322  pos += hdr->value_size;
323  }
324  /* Add new value token (if any) */
325  if (0 != norm_len)
326  {
327  if (0 != pos)
328  {
329  buf[pos++] = ',';
330  buf[pos++] = ' ';
331  }
332  /* The new value tokens must be already at the correct position */
333  mhd_assert ((value_has_close && ! already_has_close) ? \
334  (MHD_STATICSTR_LEN_ ("close, ") + old_value_len == pos) : \
335  (old_value_len == pos));
336  pos += (size_t) norm_len;
337  }
338  mhd_assert (buf_size > pos);
339  buf[pos] = 0; /* Null terminate the result */
340 
341  if (NULL == hdr)
342  {
343  struct MHD_HTTP_Header *new_hdr;
344  /* Create new response header entry */
345  new_hdr = MHD_calloc_ (1, sizeof (struct MHD_HTTP_Header));
346  if (NULL != new_hdr)
347  {
348  new_hdr->header = malloc (key_len + 1);
349  if (NULL != new_hdr->header)
350  {
351  memcpy (new_hdr->header, key, key_len + 1);
352  new_hdr->header_size = key_len;
353  new_hdr->value = buf;
354  new_hdr->value_size = pos;
355  new_hdr->kind = MHD_HEADER_KIND;
356  if (value_has_close)
359  else
361  _MHD_insert_header_first (response, new_hdr);
362  return MHD_YES;
363  }
364  free (new_hdr);
365  }
366  free (buf);
367  return MHD_NO;
368  }
369 
370  /* Update existing header entry */
371  free (hdr->value);
372  hdr->value = buf;
373  hdr->value_size = pos;
374  if (value_has_close && ! already_has_close)
376  return MHD_YES;
377 }
378 
379 
389 static enum MHD_Result
391  const char *value)
392 {
393  struct MHD_HTTP_Header *hdr;
399  if (NULL == hdr)
400  return MHD_NO;
401 
403  strlen (value)))
404  return MHD_NO;
405  if (0 == hdr->value_size)
406  {
407  _MHD_remove_header (response, hdr);
408  free (hdr->value);
409  free (hdr->header);
410  free (hdr);
411  response->flags_auto &=
414  }
415  else
416  {
417  hdr->value[hdr->value_size] = 0; /* Null-terminate the result */
418  if (0 != (response->flags_auto
420  {
421  if (MHD_STATICSTR_LEN_ ("close") == hdr->value_size)
422  {
423  if (0 != memcmp (hdr->value, "close", MHD_STATICSTR_LEN_ ("close")))
424  response->flags_auto &=
426  }
427  else if (MHD_STATICSTR_LEN_ ("close, ") < hdr->value_size)
428  {
429  if (0 != memcmp (hdr->value, "close, ",
430  MHD_STATICSTR_LEN_ ("close, ")))
431  response->flags_auto &=
433  }
434  else
435  response->flags_auto &=
437  }
438  }
439  return MHD_YES;
440 }
441 
442 
492 enum MHD_Result
493 MHD_add_response_header (struct MHD_Response *response,
494  const char *header,
495  const char *content)
496 {
498  return add_response_header_connection (response, content);
499 
502  {
503  if (! MHD_str_equal_caseless_ (content, "chunked"))
504  return MHD_NO;
505  if (0 != (response->flags_auto & MHD_RAF_HAS_TRANS_ENC_CHUNKED))
506  return MHD_YES;
507  if (MHD_NO != add_response_entry (response,
509  header,
510  content))
511  {
513  return MHD_YES;
514  }
515  return MHD_NO;
516  }
519  {
520  if (0 != (response->flags_auto & MHD_RAF_HAS_DATE_HDR))
521  {
522  struct MHD_HTTP_Header *hdr;
527  mhd_assert (NULL != hdr);
528  _MHD_remove_header (response, hdr);
529  if (NULL != hdr->value)
530  free (hdr->value);
531  free (hdr->header);
532  free (hdr);
533  }
534  if (MHD_NO != add_response_entry (response,
536  header,
537  content))
538  {
539  response->flags_auto |= MHD_RAF_HAS_DATE_HDR;
540  return MHD_YES;
541  }
542  return MHD_NO;
543  }
545  & response->flags)) &&
548  {
549  /* MHD will set Content-length if allowed and possible,
550  reject attempt by application */
551  return MHD_NO;
552  }
553 
554  return add_response_entry (response,
556  header,
557  content);
558 }
559 
560 
570 enum MHD_Result
571 MHD_add_response_footer (struct MHD_Response *response,
572  const char *footer,
573  const char *content)
574 {
575  return add_response_entry (response,
577  footer,
578  content);
579 }
580 
581 
596 enum MHD_Result
597 MHD_del_response_header (struct MHD_Response *response,
598  const char *header,
599  const char *content)
600 {
601  struct MHD_HTTP_Header *pos;
602  size_t header_len;
603  size_t content_len;
604 
605  if ( (NULL == header) ||
606  (NULL == content) )
607  return MHD_NO;
608  header_len = strlen (header);
609 
610  if ((0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR)) &&
613  header_len))
614  return del_response_header_connection (response, content);
615 
616  content_len = strlen (content);
617  pos = response->first_header;
618  while (NULL != pos)
619  {
620  if ((header_len == pos->header_size) &&
621  (content_len == pos->value_size) &&
622  (0 == memcmp (header,
623  pos->header,
624  header_len)) &&
625  (0 == memcmp (content,
626  pos->value,
627  content_len)))
628  {
629  _MHD_remove_header (response, pos);
630  free (pos->header);
631  free (pos->value);
632  free (pos);
634  header_len) &&
637  header_len) )
638  response->flags_auto &=
641  header_len) &&
644  header_len) )
645  response->flags_auto &=
647  return MHD_YES;
648  }
649  pos = pos->next;
650  }
651  return MHD_NO;
652 }
653 
654 
665 int
667  MHD_KeyValueIterator iterator,
668  void *iterator_cls)
669 {
670  int numHeaders = 0;
671  struct MHD_HTTP_Header *pos;
672 
673  for (pos = response->first_header;
674  NULL != pos;
675  pos = pos->next)
676  {
677  numHeaders++;
678  if ((NULL != iterator) &&
679  (MHD_NO == iterator (iterator_cls,
680  pos->kind,
681  pos->header,
682  pos->value)))
683  break;
684  }
685  return numHeaders;
686 }
687 
688 
697 const char *
699  const char *key)
700 {
701  struct MHD_HTTP_Header *pos;
702  size_t key_size;
703 
704  if (NULL == key)
705  return NULL;
706 
707  key_size = strlen (key);
708  for (pos = response->first_header;
709  NULL != pos;
710  pos = pos->next)
711  {
712  if ((pos->header_size == key_size) &&
714  return pos->value;
715  }
716  return NULL;
717 }
718 
719 
731 struct MHD_HTTP_Header *
733  enum MHD_ValueKind kind,
734  const char *key,
735  size_t key_len)
736 {
737  struct MHD_HTTP_Header *pos;
738 
739  mhd_assert (NULL != key);
740  mhd_assert (0 != key[0]);
741  mhd_assert (0 != key_len);
742 
743  for (pos = response->first_header;
744  NULL != pos;
745  pos = pos->next)
746  {
747  if ((pos->header_size == key_len) &&
748  (kind == pos->kind) &&
750  return pos;
751  }
752  return NULL;
753 }
754 
755 
772 bool
774  const char *key,
775  size_t key_len,
776  const char *token,
777  size_t token_len)
778 {
779  struct MHD_HTTP_Header *pos;
780 
781  if ( (NULL == key) ||
782  ('\0' == key[0]) ||
783  (NULL == token) ||
784  ('\0' == token[0]) )
785  return false;
786 
787  /* Token must not contain binary zero! */
788  mhd_assert (strlen (token) == token_len);
789 
790  for (pos = response->first_header;
791  NULL != pos;
792  pos = pos->next)
793  {
794  if ( (pos->kind == MHD_HEADER_KIND) &&
795  (key_len == pos->header_size) &&
797  key,
798  key_len) &&
800  token,
801  token_len) )
802  return true;
803  }
804  return false;
805 }
806 
807 
824 struct MHD_Response *
826  size_t block_size,
828  void *crc_cls,
830 {
831  struct MHD_Response *response;
832 
833  if ((NULL == crc) || (0 == block_size))
834  return NULL;
835  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response)
836  + block_size)))
837  return NULL;
838  response->fd = -1;
839  response->data = (void *) &response[1];
840  response->data_buffer_size = block_size;
841 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
842  if (! MHD_mutex_init_ (&response->mutex))
843  {
844  free (response);
845  return NULL;
846  }
847 #endif
848  response->crc = crc;
849  response->crfc = crfc;
850  response->crc_cls = crc_cls;
851  response->reference_count = 1;
852  response->total_size = size;
853  return response;
854 }
855 
856 
865 enum MHD_Result
866 MHD_set_response_options (struct MHD_Response *response,
868  ...)
869 {
870  va_list ap;
871  enum MHD_Result ret;
872  enum MHD_ResponseOptions ro;
873 
874  ret = MHD_YES;
875  response->flags = flags;
876  va_start (ap, flags);
877  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
878  {
879  switch (ro)
880  {
881  default:
882  ret = MHD_NO;
883  break;
884  }
885  }
886  va_end (ap);
887  return ret;
888 }
889 
890 
901 static ssize_t
902 file_reader (void *cls,
903  uint64_t pos,
904  char *buf,
905  size_t max)
906 {
907  struct MHD_Response *response = cls;
908 #if ! defined(_WIN32) || defined(__CYGWIN__)
909  ssize_t n;
910 #else /* _WIN32 && !__CYGWIN__ */
911  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
912 #endif /* _WIN32 && !__CYGWIN__ */
913  const int64_t offset64 = (int64_t) (pos + response->fd_off);
914 
915  if (offset64 < 0)
916  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
917 
918 #if ! defined(_WIN32) || defined(__CYGWIN__)
919  if (max > SSIZE_MAX)
920  max = SSIZE_MAX; /* Clamp to maximum return value. */
921 
922 #if defined(HAVE_PREAD64)
923  n = pread64 (response->fd, buf, max, offset64);
924 #elif defined(HAVE_PREAD)
925  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
926  (offset64 > (uint64_t) INT32_MAX) )
927  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
928 
929  n = pread (response->fd, buf, max, (off_t) offset64);
930 #else /* ! HAVE_PREAD */
931 #if defined(HAVE_LSEEK64)
932  if (lseek64 (response->fd,
933  offset64,
934  SEEK_SET) != offset64)
935  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
936 #else /* ! HAVE_LSEEK64 */
937  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
938  (offset64 > (uint64_t) INT32_MAX) )
939  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
940 
941  if (lseek (response->fd,
942  (off_t) offset64,
943  SEEK_SET) != (off_t) offset64)
944  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
945 #endif /* ! HAVE_LSEEK64 */
946  n = read (response->fd,
947  buf,
948  max);
949 
950 #endif /* ! HAVE_PREAD */
951  if (0 == n)
953  if (n < 0)
955  return n;
956 #else /* _WIN32 && !__CYGWIN__ */
957  if (INVALID_HANDLE_VALUE == fh)
958  return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
959  else
960  {
961  OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
962  ULARGE_INTEGER pos_uli;
963  DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
964  DWORD resRead;
965 
966  pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
967  f_ol.Offset = pos_uli.LowPart;
968  f_ol.OffsetHigh = pos_uli.HighPart;
969  if (! ReadFile (fh, (void*) buf, toRead, &resRead, &f_ol))
970  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
971  if (0 == resRead)
973  return (ssize_t) resRead;
974  }
975 #endif /* _WIN32 && !__CYGWIN__ */
976 }
977 
978 
989 static ssize_t
990 pipe_reader (void *cls,
991  uint64_t pos,
992  char *buf,
993  size_t max)
994 {
995  struct MHD_Response *response = cls;
996  ssize_t n;
997 
998  (void) pos;
999 #ifndef _WIN32
1000  if (SSIZE_MAX < max)
1001  max = SSIZE_MAX;
1002 #else /* _WIN32 */
1003  if (UINT_MAX < max)
1004  max = UINT_MAX;
1005 #endif /* _WIN32 */
1006 
1007  n = read (response->fd,
1008  buf,
1009  (MHD_SCKT_SEND_SIZE_) max);
1010  if (0 == n)
1012  if (n < 0)
1014  return n;
1015 }
1016 
1017 
1024 static void
1025 free_callback (void *cls)
1026 {
1027  struct MHD_Response *response = cls;
1028 
1029  (void) close (response->fd);
1030  response->fd = -1;
1031 }
1032 
1033 
1034 #undef MHD_create_response_from_fd_at_offset
1035 
1059 struct MHD_Response *
1061  int fd,
1062  off_t offset)
1063 {
1065  fd,
1066  offset);
1067 }
1068 
1069 
1093 _MHD_EXTERN struct MHD_Response *
1095  int fd,
1096  uint64_t offset)
1097 {
1098  struct MHD_Response *response;
1099 
1100 #if ! defined(HAVE___LSEEKI64) && ! defined(HAVE_LSEEK64)
1101  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
1102  ( (size > (uint64_t) INT32_MAX) ||
1103  (offset > (uint64_t) INT32_MAX) ||
1104  ((size + offset) >= (uint64_t) INT32_MAX) ) )
1105  return NULL;
1106 #endif
1107  if ( ((int64_t) size < 0) ||
1108  ((int64_t) offset < 0) ||
1109  ((int64_t) (size + offset) < 0) )
1110  return NULL;
1111 
1112  response = MHD_create_response_from_callback (size,
1114  &file_reader,
1115  NULL,
1116  &free_callback);
1117  if (NULL == response)
1118  return NULL;
1119  response->fd = fd;
1120  response->is_pipe = false;
1121  response->fd_off = offset;
1122  response->crc_cls = response;
1123  return response;
1124 }
1125 
1126 
1144 _MHD_EXTERN struct MHD_Response *
1146 {
1147  struct MHD_Response *response;
1148 
1151  &pipe_reader,
1152  NULL,
1153  &free_callback);
1154  if (NULL == response)
1155  return NULL;
1156  response->fd = fd;
1157  response->is_pipe = true;
1158  response->crc_cls = response;
1159  return response;
1160 }
1161 
1162 
1179 struct MHD_Response *
1181  int fd)
1182 {
1184  fd,
1185  0);
1186 }
1187 
1188 
1209 _MHD_EXTERN struct MHD_Response *
1211  int fd)
1212 {
1214  fd,
1215  0);
1216 }
1217 
1218 
1240 struct MHD_Response *
1242  void *data,
1243  int must_free,
1244  int must_copy)
1245 {
1246  struct MHD_Response *response;
1247  void *tmp;
1248 
1249  if ((NULL == data) && (size > 0))
1250  return NULL;
1251  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
1252  return NULL;
1253  response->fd = -1;
1254 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1255  if (! MHD_mutex_init_ (&response->mutex))
1256  {
1257  free (response);
1258  return NULL;
1259  }
1260 #endif
1261  if ((must_copy) && (size > 0))
1262  {
1263  if (NULL == (tmp = malloc (size)))
1264  {
1265 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1266  MHD_mutex_destroy_chk_ (&response->mutex);
1267 #endif
1268  free (response);
1269  return NULL;
1270  }
1271  memcpy (tmp, data, size);
1272  must_free = MHD_YES;
1273  data = tmp;
1274  }
1275  if (must_free)
1276  {
1277  response->crfc = &free;
1278  response->crc_cls = data;
1279  }
1280  response->reference_count = 1;
1281  response->total_size = size;
1282  response->data = data;
1283  response->data_size = size;
1284  if (must_copy)
1285  response->data_buffer_size = size;
1286  return response;
1287 }
1288 
1289 
1307 struct MHD_Response *
1309  void *buffer,
1310  enum MHD_ResponseMemoryMode mode)
1311 {
1312  return MHD_create_response_from_data (size,
1313  buffer,
1314  mode == MHD_RESPMEM_MUST_FREE,
1315  mode == MHD_RESPMEM_MUST_COPY);
1316 }
1317 
1318 
1336 _MHD_EXTERN struct MHD_Response *
1338  void *buffer,
1340  crfc)
1341 {
1342  struct MHD_Response *r;
1343 
1345  buffer,
1346  MHD_YES,
1347  MHD_NO);
1348  if (NULL == r)
1349  return r;
1350  r->crfc = crfc;
1351  return r;
1352 }
1353 
1354 
1375 _MHD_EXTERN struct MHD_Response *
1377  void *buffer,
1379  crfc,
1380  void *crfc_cls)
1381 {
1382  struct MHD_Response *r;
1383 
1385  buffer,
1386  crfc);
1387  if (NULL != r)
1388  r->crc_cls = crfc_cls;
1389  return r;
1390 }
1391 
1392 
1412 _MHD_EXTERN struct MHD_Response *
1414  unsigned int iovcnt,
1416  void *cls)
1417 {
1418  struct MHD_Response *response;
1419  unsigned int i;
1420  int i_cp = 0;
1421  uint64_t total_size = 0;
1422  const void *last_valid_buffer = NULL;
1423 
1424  if ((NULL == iov) && (0 < iovcnt))
1425  return NULL;
1426 
1427  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1428  if (NULL == response)
1429  return NULL;
1430  if (! MHD_mutex_init_ (&response->mutex))
1431  {
1432  free (response);
1433  return NULL;
1434  }
1435  /* Calculate final size, number of valid elements, and check 'iov' */
1436  for (i = 0; i < iovcnt; ++i)
1437  {
1438  if (0 == iov[i].iov_len)
1439  continue; /* skip zero-sized elements */
1440  if (NULL == iov[i].iov_base)
1441  {
1442  i_cp = -1; /* error */
1443  break;
1444  }
1445  if ( (total_size > (total_size + iov[i].iov_len)) ||
1446  (INT_MAX == i_cp) ||
1447  (SSIZE_MAX < (total_size + iov[i].iov_len)) )
1448  {
1449  i_cp = -1; /* overflow */
1450  break;
1451  }
1452  last_valid_buffer = iov[i].iov_base;
1453  total_size += iov[i].iov_len;
1454 #if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64)
1455  i_cp++;
1456 #else /* ! MHD_POSIX_SOCKETS && _WIN64 */
1457  {
1458  int64_t i_add;
1459 
1460  i_add = iov[i].iov_len / ULONG_MAX;
1461  if (0 != iov[i].iov_len % ULONG_MAX)
1462  i_add++;
1463  if (INT_MAX < (i_add + i_cp))
1464  {
1465  i_cp = -1; /* overflow */
1466  break;
1467  }
1468  i_cp += (int) i_add;
1469  }
1470 #endif /* ! MHD_POSIX_SOCKETS && _WIN64 */
1471  }
1472  if (-1 == i_cp)
1473  {
1474  /* Some error condition */
1475  MHD_mutex_destroy_chk_ (&response->mutex);
1476  free (response);
1477  return NULL;
1478  }
1479  response->fd = -1;
1480  response->reference_count = 1;
1481  response->total_size = total_size;
1482  response->crc_cls = cls;
1483  response->crfc = free_cb;
1484  if (0 == i_cp)
1485  {
1486  mhd_assert (0 == total_size);
1487  return response;
1488  }
1489  if (1 == i_cp)
1490  {
1491  mhd_assert (NULL != last_valid_buffer);
1492  response->data = (void *) last_valid_buffer;
1493  response->data_size = (size_t) total_size;
1494  return response;
1495  }
1496  mhd_assert (1 < i_cp);
1497  {
1498  MHD_iovec_ *iov_copy;
1499  int num_copy_elements = i_cp;
1500 
1501  iov_copy = MHD_calloc_ (num_copy_elements,
1502  sizeof(MHD_iovec_));
1503  if (NULL == iov_copy)
1504  {
1505  MHD_mutex_destroy_chk_ (&response->mutex);
1506  free (response);
1507  return NULL;
1508  }
1509  i_cp = 0;
1510  for (i = 0; i < iovcnt; ++i)
1511  {
1512  size_t element_size = iov[i].iov_len;
1513  const uint8_t *buf = (const uint8_t *) iov[i].iov_base;
1514 
1515  if (0 == element_size)
1516  continue; /* skip zero-sized elements */
1517 #if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
1518  while (MHD_IOV_ELMN_MAX_SIZE < element_size)
1519  {
1520  iov_copy[i_cp].iov_base = (char *) buf;
1521  iov_copy[i_cp].iov_len = ULONG_MAX;
1522  buf += ULONG_MAX;
1523  element_size -= ULONG_MAX;
1524  i_cp++;
1525  }
1526 #endif /* MHD_WINSOCK_SOCKETS && _WIN64 */
1527  iov_copy[i_cp].iov_base = (void *) buf;
1528  iov_copy[i_cp].iov_len = (MHD_iov_size_) element_size;
1529  i_cp++;
1530  }
1531  mhd_assert (num_copy_elements == i_cp);
1532  response->data_iov = iov_copy;
1533  response->data_iovcnt = i_cp;
1534  return response;
1535  }
1536 }
1537 
1538 
1539 #ifdef UPGRADE_SUPPORT
1553 MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
1555  ...)
1556 {
1557  struct MHD_Connection *connection;
1558  struct MHD_Daemon *daemon;
1559 
1560  if (NULL == urh)
1561  return MHD_NO;
1562  connection = urh->connection;
1563 
1564  /* Precaution checks on external data. */
1565  if (NULL == connection)
1566  return MHD_NO;
1567  daemon = connection->daemon;
1568  if (NULL == daemon)
1569  return MHD_NO;
1570 
1571  switch (action)
1572  {
1574  if (urh->was_closed)
1575  return MHD_NO; /* Already closed. */
1576 
1577  /* transition to special 'closed' state for start of cleanup */
1578 #ifdef HTTPS_SUPPORT
1579  if (0 != (daemon->options & MHD_USE_TLS) )
1580  {
1581  /* signal that app is done by shutdown() of 'app' socket */
1582  /* Application will not use anyway this socket after this command. */
1583  shutdown (urh->app.socket,
1584  SHUT_RDWR);
1585  }
1586 #endif /* HTTPS_SUPPORT */
1587  mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
1588  urh->was_closed = true;
1589  /* As soon as connection will be marked with BOTH
1590  * 'urh->was_closed' AND 'urh->clean_ready', it will
1591  * be moved to cleanup list by MHD_resume_connection(). */
1592  MHD_resume_connection (connection);
1593  return MHD_YES;
1595  /* Unportable API. TODO: replace with portable action. */
1596  return MHD_connection_set_cork_state_ (connection,
1597  true) ? MHD_YES : MHD_NO;
1599  /* Unportable API. TODO: replace with portable action. */
1600  return MHD_connection_set_cork_state_ (connection,
1601  false) ? MHD_YES : MHD_NO;
1602  default:
1603  /* we don't understand this one */
1604  return MHD_NO;
1605  }
1606 }
1607 
1608 
1622 enum MHD_Result
1624  struct MHD_Connection *connection)
1625 {
1626  struct MHD_Daemon *daemon = connection->daemon;
1627  struct MHD_UpgradeResponseHandle *urh;
1628  size_t rbo;
1629 
1630 #ifdef MHD_USE_THREADS
1631  mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1632  MHD_thread_ID_match_current_ (connection->pid) );
1633 #endif /* MHD_USE_THREADS */
1634 
1635  if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
1636  return MHD_NO;
1637 
1638  if (NULL ==
1641  MHD_STATICSTR_LEN_ ( \
1643  {
1644 #ifdef HAVE_MESSAGES
1645  MHD_DLOG (daemon,
1646  _ ("Invalid response for upgrade: " \
1647  "application failed to set the 'Upgrade' header!\n"));
1648 #endif
1649  return MHD_NO;
1650  }
1651 
1652  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
1653  if (NULL == urh)
1654  return MHD_NO;
1655  urh->connection = connection;
1656  rbo = connection->read_buffer_offset;
1657  connection->read_buffer_offset = 0;
1658  MHD_connection_set_nodelay_state_ (connection, false);
1659  MHD_connection_set_cork_state_ (connection, false);
1660 #ifdef HTTPS_SUPPORT
1661  if (0 != (daemon->options & MHD_USE_TLS) )
1662  {
1663  struct MemoryPool *pool;
1664  size_t avail;
1665  char *buf;
1666  MHD_socket sv[2];
1667 #if defined(MHD_socket_nosignal_) || ! defined(MHD_socket_pair_nblk_)
1668  int res1;
1669  int res2;
1670 #endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
1671 
1672 #ifdef MHD_socket_pair_nblk_
1673  if (! MHD_socket_pair_nblk_ (sv))
1674  {
1675  free (urh);
1676  return MHD_NO;
1677  }
1678 #else /* !MHD_socket_pair_nblk_ */
1679  if (! MHD_socket_pair_ (sv))
1680  {
1681  free (urh);
1682  return MHD_NO;
1683  }
1684  res1 = MHD_socket_nonblocking_ (sv[0]);
1685  res2 = MHD_socket_nonblocking_ (sv[1]);
1686  if ( (! res1) || (! res2) )
1687  {
1688 #ifdef HAVE_MESSAGES
1689  MHD_DLOG (daemon,
1690  _ ("Failed to make loopback sockets non-blocking.\n"));
1691 #endif
1692  if (! res2)
1693  {
1694  /* Socketpair cannot be used. */
1695  MHD_socket_close_chk_ (sv[0]);
1696  MHD_socket_close_chk_ (sv[1]);
1697  free (urh);
1698  return MHD_NO;
1699  }
1700  }
1701 #endif /* !MHD_socket_pair_nblk_ */
1702 #ifdef MHD_socket_nosignal_
1703  res1 = MHD_socket_nosignal_ (sv[0]);
1704  res2 = MHD_socket_nosignal_ (sv[1]);
1705  if ( (! res1) || (! res2) )
1706  {
1707 #ifdef HAVE_MESSAGES
1708  MHD_DLOG (daemon,
1709  _ ("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
1710 #endif
1711 #ifndef MSG_NOSIGNAL
1712  if (! res2)
1713  {
1714  /* Socketpair cannot be used. */
1715  MHD_socket_close_chk_ (sv[0]);
1716  MHD_socket_close_chk_ (sv[1]);
1717  free (urh);
1718  return MHD_NO;
1719  }
1720 #endif /* ! MSG_NOSIGNAL */
1721  }
1722 #endif /* MHD_socket_nosignal_ */
1723  if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
1724  NULL)) &&
1725  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
1726  {
1727 #ifdef HAVE_MESSAGES
1728  MHD_DLOG (daemon,
1729  _ ("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
1730  (int) sv[1],
1731  (int) FD_SETSIZE);
1732 #endif
1733  MHD_socket_close_chk_ (sv[0]);
1734  MHD_socket_close_chk_ (sv[1]);
1735  free (urh);
1736  return MHD_NO;
1737  }
1738  urh->app.socket = sv[0];
1739  urh->app.urh = urh;
1740  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
1741  urh->mhd.socket = sv[1];
1742  urh->mhd.urh = urh;
1743  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
1744  pool = connection->pool;
1745  avail = MHD_pool_get_free (pool);
1746  if (avail < RESERVE_EBUF_SIZE)
1747  {
1748  /* connection's pool is totally at the limit,
1749  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
1750  avail = RESERVE_EBUF_SIZE;
1751  buf = urh->e_buf;
1752  }
1753  else
1754  {
1755  /* Normal case: grab all remaining memory from the
1756  connection's pool for the IO buffers; the connection
1757  certainly won't need it anymore as we've upgraded
1758  to another protocol. */
1759  buf = MHD_pool_allocate (pool,
1760  avail,
1761  false);
1762  }
1763  /* use half the buffer for inbound, half for outbound */
1764  urh->in_buffer_size = avail / 2;
1765  urh->out_buffer_size = avail - urh->in_buffer_size;
1766  urh->in_buffer = buf;
1767  urh->out_buffer = &buf[urh->in_buffer_size];
1768 #ifdef EPOLL_SUPPORT
1769  /* Launch IO processing by the event loop */
1770  if (0 != (daemon->options & MHD_USE_EPOLL))
1771  {
1772  /* We're running with epoll(), need to add the sockets
1773  to the event set of the daemon's `epoll_upgrade_fd` */
1774  struct epoll_event event;
1775 
1776  mhd_assert (-1 != daemon->epoll_upgrade_fd);
1777  /* First, add network socket */
1778  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1779  event.data.ptr = &urh->app;
1780  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1781  EPOLL_CTL_ADD,
1782  connection->socket_fd,
1783  &event))
1784  {
1785 #ifdef HAVE_MESSAGES
1786  MHD_DLOG (daemon,
1787  _ ("Call to epoll_ctl failed: %s\n"),
1789 #endif
1790  MHD_socket_close_chk_ (sv[0]);
1791  MHD_socket_close_chk_ (sv[1]);
1792  free (urh);
1793  return MHD_NO;
1794  }
1795 
1796  /* Second, add our end of the UNIX socketpair() */
1797  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1798  event.data.ptr = &urh->mhd;
1799  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1800  EPOLL_CTL_ADD,
1801  urh->mhd.socket,
1802  &event))
1803  {
1804  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
1805  event.data.ptr = &urh->app;
1806  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1807  EPOLL_CTL_DEL,
1808  connection->socket_fd,
1809  &event))
1810  MHD_PANIC (_ ("Error cleaning up while handling epoll error.\n"));
1811 #ifdef HAVE_MESSAGES
1812  MHD_DLOG (daemon,
1813  _ ("Call to epoll_ctl failed: %s\n"),
1815 #endif
1816  MHD_socket_close_chk_ (sv[0]);
1817  MHD_socket_close_chk_ (sv[1]);
1818  free (urh);
1819  return MHD_NO;
1820  }
1821  EDLL_insert (daemon->eready_urh_head,
1822  daemon->eready_urh_tail,
1823  urh);
1824  urh->in_eready_list = true;
1825  }
1826 #endif /* EPOLL_SUPPORT */
1827  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
1828  {
1829  /* This takes care of further processing for most event loops:
1830  simply add to DLL for bi-direcitonal processing */
1831  DLL_insert (daemon->urh_head,
1832  daemon->urh_tail,
1833  urh);
1834  }
1835  /* In thread-per-connection mode, thread will switch to forwarding once
1836  * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
1837  */
1838  }
1839  else
1840  {
1841  urh->app.socket = MHD_INVALID_SOCKET;
1842  urh->mhd.socket = MHD_INVALID_SOCKET;
1843  /* Non-TLS connection do not hold any additional resources. */
1844  urh->clean_ready = true;
1845  }
1846 #else /* ! HTTPS_SUPPORT */
1847  urh->clean_ready = true;
1848 #endif /* ! HTTPS_SUPPORT */
1849  connection->urh = urh;
1850  /* As far as MHD's event loops are concerned, this connection is
1851  suspended; it will be resumed once application is done by the
1852  #MHD_upgrade_action() function */
1853  internal_suspend_connection_ (connection);
1854 
1855  /* hand over socket to application */
1856  response->upgrade_handler (response->upgrade_handler_cls,
1857  connection,
1858  connection->client_context,
1859  connection->read_buffer,
1860  rbo,
1861 #ifdef HTTPS_SUPPORT
1862  (0 == (daemon->options & MHD_USE_TLS) ) ?
1863  connection->socket_fd : urh->app.socket,
1864 #else /* ! HTTPS_SUPPORT */
1865  connection->socket_fd,
1866 #endif /* ! HTTPS_SUPPORT */
1867  urh);
1868  return MHD_YES;
1869 }
1870 
1871 
1901 _MHD_EXTERN struct MHD_Response *
1903  void *upgrade_handler_cls)
1904 {
1905  struct MHD_Response *response;
1906 
1907  if (NULL == upgrade_handler)
1908  return NULL; /* invalid request */
1909  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1910  if (NULL == response)
1911  return NULL;
1912 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1913  if (! MHD_mutex_init_ (&response->mutex))
1914  {
1915  free (response);
1916  return NULL;
1917  }
1918 #endif
1919  response->upgrade_handler = upgrade_handler;
1920  response->upgrade_handler_cls = upgrade_handler_cls;
1921  response->total_size = MHD_SIZE_UNKNOWN;
1922  response->reference_count = 1;
1923  if (MHD_NO ==
1924  MHD_add_response_header (response,
1926  "Upgrade"))
1927  {
1928  MHD_destroy_response (response);
1929  return NULL;
1930  }
1931  return response;
1932 }
1933 
1934 
1935 #endif /* UPGRADE_SUPPORT */
1936 
1937 
1947 void
1949 {
1950  struct MHD_HTTP_Header *pos;
1951 
1952  if (NULL == response)
1953  return;
1954 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1955  MHD_mutex_lock_chk_ (&response->mutex);
1956 #endif
1957  if (0 != --(response->reference_count))
1958  {
1959 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1960  MHD_mutex_unlock_chk_ (&response->mutex);
1961 #endif
1962  return;
1963  }
1964 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1965  MHD_mutex_unlock_chk_ (&response->mutex);
1966  MHD_mutex_destroy_chk_ (&response->mutex);
1967 #endif
1968  if (NULL != response->crfc)
1969  response->crfc (response->crc_cls);
1970 
1971  if (NULL != response->data_iov)
1972  {
1973  free (response->data_iov);
1974  }
1975 
1976  while (NULL != response->first_header)
1977  {
1978  pos = response->first_header;
1979  response->first_header = pos->next;
1980  free (pos->header);
1981  free (pos->value);
1982  free (pos);
1983  }
1984  free (response);
1985 }
1986 
1987 
1993 void
1995 {
1996 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1997  MHD_mutex_lock_chk_ (&response->mutex);
1998 #endif
1999  (response->reference_count)++;
2000 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2001  MHD_mutex_unlock_chk_ (&response->mutex);
2002 #endif
2003 }
2004 
2005 
2006 /* end of response.c */
Methods for managing connections.
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:3107
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:612
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:606
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:620
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:674
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:676
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2518
_MHD_EXTERN enum MHD_Result MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:597
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_iovec(const struct MHD_IoVec *iov, unsigned int iovcnt, MHD_ContentReaderFreeCallback free_cb, void *cls)
Definition: response.c:1413
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:1337
_MHD_EXTERN enum MHD_Result MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:571
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:1180
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_pipe(int fd)
Definition: response.c:1145
struct MHD_HTTP_Header * MHD_get_response_element_n_(struct MHD_Response *response, enum MHD_ValueKind kind, const char *key, size_t key_len)
Definition: response.c:732
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:1308
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:666
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_callback(uint64_t size, size_t block_size, MHD_ContentReaderCallback crc, void *crc_cls, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:825
struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:1060
MHD_ResponseMemoryMode
Definition: microhttpd.h:3439
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:2613
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:1094
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1948
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:493
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:698
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:1210
struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:1241
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback_cls(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc, void *crfc_cls)
Definition: response.c:1376
@ MHD_RESPMEM_MUST_FREE
Definition: microhttpd.h:3455
@ MHD_RESPMEM_MUST_COPY
Definition: microhttpd.h:3464
@ MHD_EPOLL_STATE_UNREADY
Definition: internal.h:594
#define DLL_insert(head, tail, element)
Definition: internal.h:1743
#define EDLL_insert(head, tail, element)
Definition: internal.h:1829
#define MHD_PANIC(msg)
Definition: internal.h:69
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:185
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:98
#define INT32_MAX
Definition: mhd_limits.h:65
#define UINT_MAX
Definition: mhd_limits.h:45
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:180
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:121
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:154
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:407
size_t MHD_SCKT_SEND_SIZE_
Definition: mhd_sockets.h:213
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:549
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:248
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:309
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:346
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:412
#define MHD_STATICSTR_LEN_(macro)
Definition: mhd_str.h:45
#define NULL
Definition: reason_phrase.c:30
additional automatic macros for MHD_config.h
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:50
bool MHD_connection_set_cork_state_(struct MHD_Connection *connection, bool cork_state)
Definition: mhd_send.c:240
bool MHD_connection_set_nodelay_state_(struct MHD_Connection *connection, bool nodelay_state)
Definition: mhd_send.c:170
Declarations of send() wrappers.
MHD internal shared structures.
size_t MHD_iov_size_
Definition: internal.h:403
MHD_ResponseAutoFlags
Definition: internal.h:367
@ MHD_RAF_HAS_DATE_HDR
Definition: internal.h:372
@ MHD_RAF_HAS_CONNECTION_CLOSE
Definition: internal.h:370
@ MHD_RAF_HAS_TRANS_ENC_CHUNKED
Definition: internal.h:371
@ MHD_RAF_HAS_CONNECTION_HDR
Definition: internal.h:369
#define MHD_IOV_ELMN_MAX_SIZE
Definition: internal.h:402
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
macros for mhd_assert()
Header for platform missing functions.
Header for platform-independent inter-thread communication.
limits values definitions
#define SSIZE_MAX
Definition: mhd_limits.h:113
#define MHD_mutex_init_(ignore)
Definition: mhd_locks.h:191
bool MHD_str_remove_tokens_caseless_(char *str, size_t *str_len, const char *const tokens, const size_t tokens_len)
Definition: mhd_str.c:720
bool MHD_str_remove_token_caseless_(const char *str, size_t str_len, const char *const token, const size_t token_len, char *buf, ssize_t *buf_size)
Definition: mhd_str.c:553
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:445
Header for string manipulating helpers.
static void free_callback(void *cls)
Definition: response.c:1025
#define MHD_FILE_READ_BLOCK_SIZE
Definition: response.c:70
bool MHD_check_response_header_token_ci(const struct MHD_Response *response, const char *key, size_t key_len, const char *token, size_t token_len)
Definition: response.c:773
#define _MHD_insert_header_last(presponse, phdr)
Definition: response.c:98
#define _MHD_remove_header(presponse, phdr)
Definition: response.c:120
static enum MHD_Result add_response_header_connection(struct MHD_Response *response, const char *value)
Definition: response.c:209
#define _MHD_insert_header_first(presponse, phdr)
Definition: response.c:77
static enum MHD_Result add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:157
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:902
static enum MHD_Result del_response_header_connection(struct MHD_Response *response, const char *value)
Definition: response.c:390
enum MHD_Result MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:866
static ssize_t pipe_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:990
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1994
int MHD_socket
Definition: microhttpd.h:207
void(* MHD_UpgradeHandler)(void *cls, struct MHD_Connection *connection, void *con_cls, const char *extra_in, size_t extra_in_size, MHD_socket sock, struct MHD_UpgradeResponseHandle *urh)
Definition: microhttpd.h:3815
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:184
MHD_Result
Definition: microhttpd.h:158
@ MHD_YES
Definition: microhttpd.h:167
@ MHD_NO
Definition: microhttpd.h:162
int off_t offset
Definition: microhttpd.h:3643
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:187
_MHD_EXTERN struct MHD_Response * MHD_create_response_for_upgrade(MHD_UpgradeHandler upgrade_handler, void *upgrade_handler_cls)
void int int must_copy
Definition: microhttpd.h:3430
void int must_free
Definition: microhttpd.h:3429
int fd
Definition: microhttpd.h:3642
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:3245
void * data
Definition: microhttpd.h:3428
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:208
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:2597
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:188
MHD_UpgradeAction
Definition: microhttpd.h:3719
@ MHD_UPGRADE_ACTION_CORK_ON
Definition: microhttpd.h:3731
@ MHD_UPGRADE_ACTION_CLOSE
Definition: microhttpd.h:3726
@ MHD_UPGRADE_ACTION_CORK_OFF
Definition: microhttpd.h:3736
MHD_ValueKind
Definition: microhttpd.h:1978
@ MHD_FOOTER_KIND
Definition: microhttpd.h:2019
@ MHD_HEADER_KIND
Definition: microhttpd.h:1993
@ MHD_USE_EPOLL
Definition: microhttpd.h:1369
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1261
@ MHD_USE_POLL
Definition: microhttpd.h:1319
@ MHD_USE_TLS
Definition: microhttpd.h:1246
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1478
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1273
MHD_ResponseOptions
Definition: microhttpd.h:3365
@ MHD_RO_END
Definition: microhttpd.h:3369
MHD_ResponseFlags
Definition: microhttpd.h:3297
@ MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:3349
_MHD_EXTERN enum MHD_Result MHD_upgrade_action(struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action,...)
Methods for managing response objects.
enum MHD_Result MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
MHD_socket socket_fd
Definition: internal.h:752
struct MemoryPool * pool
Definition: internal.h:685
size_t read_buffer_offset
Definition: internal.h:1086
MHD_thread_handle_ID_ pid
Definition: internal.h:723
void * client_context
Definition: internal.h:986
enum MHD_CONNECTION_STATE state
Definition: internal.h:1263
char * read_buffer
Definition: internal.h:1036
struct MHD_Daemon * daemon
Definition: internal.h:675
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1619
size_t value_size
Definition: internal.h:352
char * header
Definition: internal.h:347
enum MHD_ValueKind kind
Definition: internal.h:358
size_t header_size
Definition: internal.h:342
struct MHD_HTTP_Header * next
Definition: internal.h:342
char * value
Definition: internal.h:352
const void * iov_base
Definition: microhttpd.h:2185
size_t iov_len
Definition: microhttpd.h:2190
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:1606
struct MHD_HTTP_Header * first_header
Definition: internal.h:1582
void * crc_cls
Definition: internal.h:1594
size_t data_buffer_size
Definition: internal.h:1664
MHD_iovec_ * data_iov
Definition: internal.h:549
MHD_ContentReaderCallback crc
Definition: internal.h:1600
bool is_pipe
Definition: internal.h:544
struct MHD_Action action
Definition: internal.h:1575
enum MHD_ResponseAutoFlags flags_auto
Definition: internal.h:539
unsigned int data_iovcnt
Definition: internal.h:554
size_t data_size
Definition: internal.h:1659
enum MHD_ResponseFlags flags
Definition: internal.h:534
unsigned int reference_count
Definition: internal.h:1675
char * data
Definition: internal.h:1588
MHD_mutex_ mutex
Definition: internal.h:1637
uint64_t total_size
Definition: internal.h:1642
uint64_t fd_off
Definition: internal.h:1653