GNU libmicrohttpd  1.0.1
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-2023 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 
166 bool
168  enum MHD_ValueKind kind,
169  char *header,
170  size_t header_len,
171  char *content,
172  size_t content_len)
173 {
174  struct MHD_HTTP_Res_Header *hdr;
175 
176  mhd_assert (0 != header_len);
177  mhd_assert (0 != content_len);
178  if (NULL == (hdr = MHD_calloc_ (1, sizeof (struct MHD_HTTP_Res_Header))))
179  return false;
180 
181  hdr->header = header;
182  hdr->header_size = header_len;
183  hdr->value = content;
184  hdr->value_size = content_len;
185  hdr->kind = kind;
186  _MHD_insert_header_last (response, hdr);
187 
188  return true; /* Success exit point */
189 }
190 
191 
206 bool
208  enum MHD_ValueKind kind,
209  const char *header,
210  size_t header_len,
211  const char *content,
212  size_t content_len)
213 {
214  char *header_malloced;
215  char *value_malloced;
216 
217  mhd_assert (0 != header_len);
218  mhd_assert (0 != content_len);
219  header_malloced = malloc (header_len + 1);
220  if (NULL == header_malloced)
221  return false;
222 
223  memcpy (header_malloced, header, header_len);
224  header_malloced[header_len] = 0;
225 
226  value_malloced = malloc (content_len + 1);
227  if (NULL != value_malloced)
228  {
229  memcpy (value_malloced, content, content_len);
230  value_malloced[content_len] = 0;
231 
232  if (MHD_add_response_entry_no_alloc_ (response, kind,
233  header_malloced, header_len,
234  value_malloced, content_len))
235  return true; /* Success exit point */
236 
237  free (value_malloced);
238  }
239  free (header_malloced);
240 
241  return false; /* Failure exit point */
242 }
243 
244 
255 static bool
257  enum MHD_ValueKind kind,
258  const char *header,
259  size_t header_len,
260  const char *content,
261  size_t content_len)
262 {
263  if (NULL == response)
264  return false;
265  if (0 == header_len)
266  return false;
267  if (0 == content_len)
268  return false;
269  if (NULL != memchr (header, '\t', header_len))
270  return false;
271  if (NULL != memchr (header, ' ', header_len))
272  return false;
273  if (NULL != memchr (header, '\r', header_len))
274  return false;
275  if (NULL != memchr (header, '\n', header_len))
276  return false;
277  if (NULL != memchr (content, '\r', content_len))
278  return false;
279  if (NULL != memchr (content, '\n', content_len))
280  return false;
281 
282  return MHD_add_response_entry_no_check_ (response, kind, header, header_len,
283  content, content_len);
284 }
285 
286 
296 static enum MHD_Result
297 add_response_entry (struct MHD_Response *response,
298  enum MHD_ValueKind kind,
299  const char *header,
300  const char *content)
301 {
302  size_t header_len;
303  size_t content_len;
304 
305  if (NULL == content)
306  return MHD_NO;
307 
308  header_len = strlen (header);
309  content_len = strlen (content);
310  return add_response_entry_n (response, kind, header,
311  header_len, content,
312  content_len) ? MHD_YES : MHD_NO;
313 }
314 
315 
327 static enum MHD_Result
329  const char *value)
330 {
331  static const char *key = MHD_HTTP_HEADER_CONNECTION;
333  static const size_t key_len =
335  size_t value_len;
336  size_t old_value_len;
337  size_t buf_size;
338  size_t norm_len;
339  char *buf;
340  struct MHD_HTTP_Res_Header *hdr;
341  bool value_has_close;
342  bool already_has_close;
343  size_t pos = 0;
345  if ( (NULL != strchr (value, '\r')) ||
346  (NULL != strchr (value, '\n')) )
347  return MHD_NO;
348 
349  if (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR))
350  {
352  key, key_len);
353  already_has_close =
354  (0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_CLOSE));
355  mhd_assert (already_has_close == (0 == memcmp (hdr->value, "close", 5)));
356  mhd_assert (NULL != hdr);
357  }
358  else
359  {
360  hdr = NULL;
361  already_has_close = false;
364  key, key_len));
366  }
367  if (NULL != hdr)
368  old_value_len = hdr->value_size + 2; /* additional size for ", " */
369  else
370  old_value_len = 0;
371 
372  value_len = strlen (value);
373  if (value_len >= SSIZE_MAX)
374  return MHD_NO;
375  /* Additional space for normalisation and zero-termination */
376  norm_len = value_len + value_len / 2 + 1;
377  if (norm_len >= SSIZE_MAX)
378  return MHD_NO;
379  buf_size = old_value_len + (size_t) norm_len;
380 
381  buf = malloc (buf_size);
382  if (NULL == buf)
383  return MHD_NO;
384  if (1)
385  { /* local scope */
386  ssize_t norm_len_s = (ssize_t) norm_len;
387  /* Remove "close" token (if any), it will be moved to the front */
388  value_has_close = MHD_str_remove_token_caseless_ (value, value_len, "close",
390  "close"),
391  buf + old_value_len,
392  &norm_len_s);
393  mhd_assert (0 <= norm_len_s);
394  if (0 > norm_len_s)
395  {
396  /* Must never happen with realistic sizes */
397  free (buf);
398  return MHD_NO;
399  }
400  else
401  norm_len = (size_t) norm_len_s;
402  }
403 #ifdef UPGRADE_SUPPORT
404  if ( (NULL != response->upgrade_handler) && value_has_close)
405  { /* The "close" token cannot be used with connection "upgrade" */
406  free (buf);
407  return MHD_NO;
408  }
409 #endif /* UPGRADE_SUPPORT */
410  if (0 != norm_len)
411  MHD_str_remove_tokens_caseless_ (buf + old_value_len, &norm_len,
412  "keep-alive",
413  MHD_STATICSTR_LEN_ ("keep-alive"));
414  if (0 == norm_len)
415  { /* New value is empty after normalisation */
416  if (! value_has_close)
417  { /* The new value had no tokens */
418  free (buf);
419  return MHD_NO;
420  }
421  if (already_has_close)
422  { /* The "close" token is already present, nothing to modify */
423  free (buf);
424  return MHD_YES;
425  }
426  }
427  /* Add "close" token if required */
428  if (value_has_close && ! already_has_close)
429  {
430  /* Need to insert "close" token at the first position */
431  mhd_assert (buf_size >= old_value_len + norm_len \
432  + MHD_STATICSTR_LEN_ ("close, ") + 1);
433  if (0 != norm_len)
434  memmove (buf + MHD_STATICSTR_LEN_ ("close, ") + old_value_len,
435  buf + old_value_len, norm_len + 1);
436  memcpy (buf, "close", MHD_STATICSTR_LEN_ ("close"));
437  pos += MHD_STATICSTR_LEN_ ("close");
438  }
439  /* Add old value tokens (if any) */
440  if (0 != old_value_len)
441  {
442  if (0 != pos)
443  {
444  buf[pos++] = ',';
445  buf[pos++] = ' ';
446  }
447  memcpy (buf + pos, hdr->value,
448  hdr->value_size);
449  pos += hdr->value_size;
450  }
451  /* Add new value token (if any) */
452  if (0 != norm_len)
453  {
454  if (0 != pos)
455  {
456  buf[pos++] = ',';
457  buf[pos++] = ' ';
458  }
459  /* The new value tokens must be already at the correct position */
460  mhd_assert ((value_has_close && ! already_has_close) ? \
461  (MHD_STATICSTR_LEN_ ("close, ") + old_value_len == pos) : \
462  (old_value_len == pos));
463  pos += norm_len;
464  }
465  mhd_assert (buf_size > pos);
466  buf[pos] = 0; /* Null terminate the result */
467 
468  if (NULL == hdr)
469  {
470  struct MHD_HTTP_Res_Header *new_hdr;
471  /* Create new response header entry */
472  new_hdr = MHD_calloc_ (1, sizeof (struct MHD_HTTP_Res_Header));
473  if (NULL != new_hdr)
474  {
475  new_hdr->header = malloc (key_len + 1);
476  if (NULL != new_hdr->header)
477  {
478  memcpy (new_hdr->header, key, key_len + 1);
479  new_hdr->header_size = key_len;
480  new_hdr->value = buf;
481  new_hdr->value_size = pos;
482  new_hdr->kind = MHD_HEADER_KIND;
483  if (value_has_close)
486  else
488  _MHD_insert_header_first (response, new_hdr);
489  return MHD_YES;
490  }
491  free (new_hdr);
492  }
493  free (buf);
494  return MHD_NO;
495  }
496 
497  /* Update existing header entry */
498  free (hdr->value);
499  hdr->value = buf;
500  hdr->value_size = pos;
501  if (value_has_close && ! already_has_close)
503  return MHD_YES;
504 }
505 
506 
516 static enum MHD_Result
518  const char *value)
519 {
520  struct MHD_HTTP_Res_Header *hdr;
526  if (NULL == hdr)
527  return MHD_NO;
528 
530  strlen (value)))
531  return MHD_NO;
532  if (0 == hdr->value_size)
533  {
534  _MHD_remove_header (response, hdr);
535  free (hdr->value);
536  free (hdr->header);
537  free (hdr);
538  response->flags_auto &=
541  }
542  else
543  {
544  hdr->value[hdr->value_size] = 0; /* Null-terminate the result */
545  if (0 != (response->flags_auto
547  {
548  if (MHD_STATICSTR_LEN_ ("close") == hdr->value_size)
549  {
550  if (0 != memcmp (hdr->value, "close", MHD_STATICSTR_LEN_ ("close")))
551  response->flags_auto &=
553  }
554  else if (MHD_STATICSTR_LEN_ ("close, ") < hdr->value_size)
555  {
556  if (0 != memcmp (hdr->value, "close, ",
557  MHD_STATICSTR_LEN_ ("close, ")))
558  response->flags_auto &=
560  }
561  else
562  response->flags_auto &=
564  }
565  }
566  return MHD_YES;
567 }
568 
569 
620 MHD_add_response_header (struct MHD_Response *response,
621  const char *header,
622  const char *content)
623 {
625  return add_response_header_connection (response, content);
626 
629  {
630  if (! MHD_str_equal_caseless_ (content, "chunked"))
631  return MHD_NO; /* Only "chunked" encoding is allowed */
632  if (0 != (response->flags_auto & MHD_RAF_HAS_TRANS_ENC_CHUNKED))
633  return MHD_YES; /* Already has "chunked" encoding header */
634  if ( (0 != (response->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH)) &&
635  (0 == (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags)) )
636  return MHD_NO; /* Has "Content-Length" header and no "Insanity" flag */
637  if (MHD_NO != add_response_entry (response,
639  header,
640  content))
641  {
643  return MHD_YES;
644  }
645  return MHD_NO;
646  }
649  {
650  if (0 != (response->flags_auto & MHD_RAF_HAS_DATE_HDR))
651  {
652  struct MHD_HTTP_Res_Header *hdr;
657  mhd_assert (NULL != hdr);
658  _MHD_remove_header (response, hdr);
659  if (NULL != hdr->value)
660  free (hdr->value);
661  free (hdr->header);
662  free (hdr);
663  }
664  if (MHD_NO != add_response_entry (response,
666  header,
667  content))
668  {
669  response->flags_auto |= MHD_RAF_HAS_DATE_HDR;
670  return MHD_YES;
671  }
672  return MHD_NO;
673  }
674 
677  {
678  /* Generally MHD sets automatically correct "Content-Length" always when
679  * needed.
680  * Custom "Content-Length" header is allowed only in special cases. */
681  if ( (0 != (MHD_RF_INSANITY_HEADER_CONTENT_LENGTH & response->flags)) ||
682  ((0 != (MHD_RF_HEAD_ONLY_RESPONSE & response->flags)) &&
683  (0 == (response->flags_auto & (MHD_RAF_HAS_TRANS_ENC_CHUNKED
685  {
686  if (MHD_NO != add_response_entry (response,
688  header,
689  content))
690  {
692  return MHD_YES;
693  }
694  }
695  return MHD_NO;
696  }
697 
698  return add_response_entry (response,
700  header,
701  content);
702 }
703 
704 
715 MHD_add_response_footer (struct MHD_Response *response,
716  const char *footer,
717  const char *content)
718 {
719  return add_response_entry (response,
721  footer,
722  content);
723 }
724 
725 
741 MHD_del_response_header (struct MHD_Response *response,
742  const char *header,
743  const char *content)
744 {
745  struct MHD_HTTP_Res_Header *pos;
746  size_t header_len;
747  size_t content_len;
748 
749  if ( (NULL == header) ||
750  (NULL == content) )
751  return MHD_NO;
752  header_len = strlen (header);
753 
754  if ((0 != (response->flags_auto & MHD_RAF_HAS_CONNECTION_HDR)) &&
757  header_len))
758  return del_response_header_connection (response, content);
759 
760  content_len = strlen (content);
761  pos = response->first_header;
762  while (NULL != pos)
763  {
764  if ((header_len == pos->header_size) &&
765  (content_len == pos->value_size) &&
766  (0 == memcmp (header,
767  pos->header,
768  header_len)) &&
769  (0 == memcmp (content,
770  pos->value,
771  content_len)))
772  {
773  _MHD_remove_header (response, pos);
774  free (pos->header);
775  free (pos->value);
776  free (pos);
778  header_len) &&
781  header_len) )
782  response->flags_auto &=
785  header_len) &&
788  header_len) )
789  response->flags_auto &=
792  header_len) &&
795  header_len) )
796  {
797  if (NULL == MHD_get_response_element_n_ (response,
800  header_len))
801  response->flags_auto &=
803  }
804  return MHD_YES;
805  }
806  pos = pos->next;
807  }
808  return MHD_NO;
809 }
810 
811 
822 _MHD_EXTERN int
824  MHD_KeyValueIterator iterator,
825  void *iterator_cls)
826 {
827  int numHeaders = 0;
828  struct MHD_HTTP_Res_Header *pos;
829 
830  for (pos = response->first_header;
831  NULL != pos;
832  pos = pos->next)
833  {
834  numHeaders++;
835  if ((NULL != iterator) &&
836  (MHD_NO == iterator (iterator_cls,
837  pos->kind,
838  pos->header,
839  pos->value)))
840  break;
841  }
842  return numHeaders;
843 }
844 
845 
854 _MHD_EXTERN const char *
856  const char *key)
857 {
858  struct MHD_HTTP_Res_Header *pos;
859  size_t key_size;
860 
861  if (NULL == key)
862  return NULL;
863 
864  key_size = strlen (key);
865  for (pos = response->first_header;
866  NULL != pos;
867  pos = pos->next)
868  {
869  if ((pos->header_size == key_size) &&
871  return pos->value;
872  }
873  return NULL;
874 }
875 
876 
888 struct MHD_HTTP_Res_Header *
890  enum MHD_ValueKind kind,
891  const char *key,
892  size_t key_len)
893 {
894  struct MHD_HTTP_Res_Header *pos;
895 
896  mhd_assert (NULL != key);
897  mhd_assert (0 != key[0]);
898  mhd_assert (0 != key_len);
899 
900  for (pos = response->first_header;
901  NULL != pos;
902  pos = pos->next)
903  {
904  if ((pos->header_size == key_len) &&
905  (kind == pos->kind) &&
907  return pos;
908  }
909  return NULL;
910 }
911 
912 
929 bool
931  const char *key,
932  size_t key_len,
933  const char *token,
934  size_t token_len)
935 {
936  struct MHD_HTTP_Res_Header *pos;
937 
938  if ( (NULL == key) ||
939  ('\0' == key[0]) ||
940  (NULL == token) ||
941  ('\0' == token[0]) )
942  return false;
943 
944  /* Token must not contain binary zero! */
945  mhd_assert (strlen (token) == token_len);
946 
947  for (pos = response->first_header;
948  NULL != pos;
949  pos = pos->next)
950  {
951  if ( (pos->kind == MHD_HEADER_KIND) &&
952  (key_len == pos->header_size) &&
954  key,
955  key_len) &&
957  token,
958  token_len) )
959  return true;
960  }
961  return false;
962 }
963 
964 
986 _MHD_EXTERN struct MHD_Response *
988  size_t block_size,
990  void *crc_cls,
992 {
993  struct MHD_Response *response;
994 
995  if ((NULL == crc) || (0 == block_size))
996  return NULL;
997  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response)
998  + block_size)))
999  return NULL;
1000  response->fd = -1;
1001  response->data = (void *) &response[1];
1002  response->data_buffer_size = block_size;
1003 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1004  if (! MHD_mutex_init_ (&response->mutex))
1005  {
1006  free (response);
1007  return NULL;
1008  }
1009 #endif
1010  response->crc = crc;
1011  response->crfc = crfc;
1012  response->crc_cls = crc_cls;
1013  response->reference_count = 1;
1014  response->total_size = size;
1015  return response;
1016 }
1017 
1018 
1028 MHD_set_response_options (struct MHD_Response *response,
1029  enum MHD_ResponseFlags flags,
1030  ...)
1031 {
1032  va_list ap;
1033  enum MHD_Result ret;
1034  enum MHD_ResponseOptions ro;
1035 
1036  if (0 != (response->flags_auto & MHD_RAF_HAS_CONTENT_LENGTH))
1037  { /* Response has custom "Content-Lengh" header */
1038  if ( (0 != (response->flags & MHD_RF_INSANITY_HEADER_CONTENT_LENGTH)) &&
1040  { /* Request to remove MHD_RF_INSANITY_HEADER_CONTENT_LENGTH flag */
1041  return MHD_NO;
1042  }
1043  if ( (0 != (response->flags & MHD_RF_HEAD_ONLY_RESPONSE)) &&
1044  (0 == (flags & MHD_RF_HEAD_ONLY_RESPONSE)))
1045  { /* Request to remove MHD_RF_HEAD_ONLY_RESPONSE flag */
1047  return MHD_NO;
1048  }
1049  }
1050 
1051  if ( (0 != (flags & MHD_RF_HEAD_ONLY_RESPONSE)) &&
1052  (0 != response->total_size) )
1053  return MHD_NO;
1054 
1055  ret = MHD_YES;
1056  response->flags = flags;
1057 
1058  va_start (ap, flags);
1059  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
1060  {
1061  switch (ro)
1062  {
1063  case MHD_RO_END: /* Not possible */
1064  break;
1065  default:
1066  ret = MHD_NO;
1067  break;
1068  }
1069  }
1070  va_end (ap);
1071  return ret;
1072 }
1073 
1074 
1085 static ssize_t
1086 file_reader (void *cls,
1087  uint64_t pos,
1088  char *buf,
1089  size_t max)
1090 {
1091  struct MHD_Response *response = cls;
1092 #if ! defined(_WIN32) || defined(__CYGWIN__)
1093  ssize_t n;
1094 #else /* _WIN32 && !__CYGWIN__ */
1095  const HANDLE fh = (HANDLE) (uintptr_t) _get_osfhandle (response->fd);
1096 #endif /* _WIN32 && !__CYGWIN__ */
1097  const int64_t offset64 = (int64_t) (pos + response->fd_off);
1098 
1099  if (offset64 < 0)
1100  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
1101 
1102 #if ! defined(_WIN32) || defined(__CYGWIN__)
1103  if (max > SSIZE_MAX)
1104  max = SSIZE_MAX; /* Clamp to maximum return value. */
1105 
1106 #if defined(HAVE_PREAD64)
1107  n = pread64 (response->fd, buf, max, offset64);
1108 #elif defined(HAVE_PREAD)
1109  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
1110  (offset64 > (uint64_t) INT32_MAX) )
1111  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
1112 
1113  n = pread (response->fd, buf, max, (off_t) offset64);
1114 #else /* ! HAVE_PREAD */
1115 #if defined(HAVE_LSEEK64)
1116  if (lseek64 (response->fd,
1117  offset64,
1118  SEEK_SET) != offset64)
1119  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
1120 #else /* ! HAVE_LSEEK64 */
1121  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
1122  (offset64 > (uint64_t) INT32_MAX) )
1123  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
1124 
1125  if (lseek (response->fd,
1126  (off_t) offset64,
1127  SEEK_SET) != (off_t) offset64)
1128  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
1129 #endif /* ! HAVE_LSEEK64 */
1130  n = read (response->fd,
1131  buf,
1132  max);
1133 
1134 #endif /* ! HAVE_PREAD */
1135  if (0 == n)
1137  if (n < 0)
1139  return n;
1140 #else /* _WIN32 && !__CYGWIN__ */
1141  if (INVALID_HANDLE_VALUE == fh)
1142  return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
1143  else
1144  {
1145  OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
1146  ULARGE_INTEGER pos_uli;
1147  DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
1148  DWORD resRead;
1149 
1150  pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
1151  f_ol.Offset = pos_uli.LowPart;
1152  f_ol.OffsetHigh = pos_uli.HighPart;
1153  if (! ReadFile (fh, (void *) buf, toRead, &resRead, &f_ol))
1154  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
1155  if (0 == resRead)
1157  return (ssize_t) resRead;
1158  }
1159 #endif /* _WIN32 && !__CYGWIN__ */
1160 }
1161 
1162 
1173 static ssize_t
1174 pipe_reader (void *cls,
1175  uint64_t pos,
1176  char *buf,
1177  size_t max)
1178 {
1179  struct MHD_Response *response = cls;
1180  ssize_t n;
1181 
1182  (void) pos;
1183 
1184 #ifndef _WIN32
1185  if (SSIZE_MAX < max)
1186  max = SSIZE_MAX;
1187  n = read (response->fd,
1188  buf,
1189  (MHD_SCKT_SEND_SIZE_) max);
1190 #else /* _WIN32 */
1191  if (UINT_MAX < max)
1192  max = INT_MAX;
1193  n = read (response->fd,
1194  buf,
1195  (unsigned int) max);
1196 #endif /* _WIN32 */
1197 
1198  if (0 == n)
1200  if (n < 0)
1202  return n;
1203 }
1204 
1205 
1212 static void
1213 free_callback (void *cls)
1214 {
1215  struct MHD_Response *response = cls;
1216 
1217  (void) close (response->fd);
1218  response->fd = -1;
1219 }
1220 
1221 
1222 #undef MHD_create_response_from_fd_at_offset
1223 
1247 _MHD_EXTERN struct MHD_Response *
1249  int fd,
1250  off_t offset)
1251 {
1252  if (0 > offset)
1253  return NULL;
1255  fd,
1256  (uint64_t) offset);
1257 }
1258 
1259 
1283 _MHD_EXTERN struct MHD_Response *
1285  int fd,
1286  uint64_t offset)
1287 {
1288  struct MHD_Response *response;
1289 
1290 #if ! defined(HAVE___LSEEKI64) && ! defined(HAVE_LSEEK64)
1291  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
1292  ( (size > (uint64_t) INT32_MAX) ||
1293  (offset > (uint64_t) INT32_MAX) ||
1294  ((size + offset) >= (uint64_t) INT32_MAX) ) )
1295  return NULL;
1296 #endif
1297  if ( ((int64_t) size < 0) ||
1298  ((int64_t) offset < 0) ||
1299  ((int64_t) (size + offset) < 0) )
1300  return NULL;
1301 
1302  response = MHD_create_response_from_callback (size,
1304  &file_reader,
1305  NULL,
1306  &free_callback);
1307  if (NULL == response)
1308  return NULL;
1309  response->fd = fd;
1310  response->is_pipe = false;
1311  response->fd_off = offset;
1312  response->crc_cls = response;
1313  return response;
1314 }
1315 
1316 
1334 _MHD_EXTERN struct MHD_Response *
1336 {
1337  struct MHD_Response *response;
1338 
1341  &pipe_reader,
1342  NULL,
1343  &free_callback);
1344  if (NULL == response)
1345  return NULL;
1346  response->fd = fd;
1347  response->is_pipe = true;
1348  response->crc_cls = response;
1349  return response;
1350 }
1351 
1352 
1369 _MHD_EXTERN struct MHD_Response *
1371  int fd)
1372 {
1374  fd,
1375  0);
1376 }
1377 
1378 
1399 _MHD_EXTERN struct MHD_Response *
1401  int fd)
1402 {
1404  fd,
1405  0);
1406 }
1407 
1408 
1428 _MHD_EXTERN struct MHD_Response *
1430  void *data,
1431  int must_free,
1432  int must_copy)
1433 {
1434  enum MHD_ResponseMemoryMode mode;
1435 
1436  if (0 != must_copy)
1437  mode = MHD_RESPMEM_MUST_COPY;
1438  else if (0 != must_free)
1439  mode = MHD_RESPMEM_MUST_FREE;
1440  else
1441  mode = MHD_RESPMEM_PERSISTENT;
1442 
1443  return MHD_create_response_from_buffer (size, data, mode);
1444 }
1445 
1446 
1464 _MHD_EXTERN struct MHD_Response *
1466  void *buffer,
1467  enum MHD_ResponseMemoryMode mode)
1468 {
1469  if (MHD_RESPMEM_MUST_FREE == mode)
1471  buffer,
1472  &free,
1473  buffer);
1474  if (MHD_RESPMEM_MUST_COPY == mode)
1476  buffer);
1477 
1479  buffer,
1480  NULL,
1481  NULL);
1482 }
1483 
1484 
1506 _MHD_EXTERN struct MHD_Response *
1508  const void *buffer)
1509 {
1511  buffer,
1512  NULL,
1513  NULL);
1514 }
1515 
1516 
1539 _MHD_EXTERN struct MHD_Response *
1541  const void *buffer)
1542 {
1543  struct MHD_Response *r;
1544  void *mhd_copy;
1545 
1546  if (0 == size)
1548  NULL,
1549  NULL,
1550  NULL);
1551  if (NULL == buffer)
1552  return NULL;
1553 
1554  mhd_copy = malloc (size);
1555  if (NULL == mhd_copy)
1556  return NULL;
1557  memcpy (mhd_copy, buffer, size);
1558 
1560  mhd_copy,
1561  &free,
1562  mhd_copy);
1563  if (NULL == r)
1564  free (mhd_copy);
1565  else
1566  {
1567  /* TODO: remove the next assignment, the buffer should not be modifiable */
1568  r->data_buffer_size = size;
1569  }
1570 
1571  return r;
1572 }
1573 
1574 
1592 _MHD_EXTERN struct MHD_Response *
1594  void *buffer,
1596  crfc)
1597 {
1599  buffer,
1600  crfc,
1601  buffer);
1602 }
1603 
1604 
1626 _MHD_EXTERN struct MHD_Response *
1628  const void *buffer,
1630  crfc,
1631  void *crfc_cls)
1632 {
1633  struct MHD_Response *r;
1634 
1635  if ((NULL == buffer) && (size > 0))
1636  return NULL;
1637 #if SIZEOF_SIZE_T >= SIZEOF_UINT64_T
1638  if (MHD_SIZE_UNKNOWN == size)
1639  return NULL;
1640 #endif /* SIZEOF_SIZE_T >= SIZEOF_UINT64_T */
1641  r = MHD_calloc_ (1, sizeof (struct MHD_Response));
1642  if (NULL == r)
1643  return NULL;
1644 #if defined(MHD_USE_THREADS)
1645  if (! MHD_mutex_init_ (&r->mutex))
1646  {
1647  free (r);
1648  return NULL;
1649  }
1650 #endif
1651  r->fd = -1;
1652  r->reference_count = 1;
1653  r->total_size = size;
1654  r->data = buffer;
1655  r->data_size = size;
1656  r->crfc = crfc;
1657  r->crc_cls = crfc_cls;
1658  return r;
1659 }
1660 
1661 
1681 _MHD_EXTERN struct MHD_Response *
1683  unsigned int iovcnt,
1685  void *cls)
1686 {
1687  struct MHD_Response *response;
1688  unsigned int i;
1689  int i_cp = 0;
1690  uint64_t total_size = 0;
1691  const void *last_valid_buffer = NULL;
1692 
1693  if ((NULL == iov) && (0 < iovcnt))
1694  return NULL;
1695 
1696  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1697  if (NULL == response)
1698  return NULL;
1699  if (! MHD_mutex_init_ (&response->mutex))
1700  {
1701  free (response);
1702  return NULL;
1703  }
1704  /* Calculate final size, number of valid elements, and check 'iov' */
1705  for (i = 0; i < iovcnt; ++i)
1706  {
1707  if (0 == iov[i].iov_len)
1708  continue; /* skip zero-sized elements */
1709  if (NULL == iov[i].iov_base)
1710  {
1711  i_cp = -1; /* error */
1712  break;
1713  }
1714  if ( (total_size > (total_size + iov[i].iov_len)) ||
1715  (INT_MAX == i_cp) ||
1716  (SSIZE_MAX < (total_size + iov[i].iov_len)) )
1717  {
1718  i_cp = -1; /* overflow */
1719  break;
1720  }
1721  last_valid_buffer = iov[i].iov_base;
1722  total_size += iov[i].iov_len;
1723 #if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64)
1724  i_cp++;
1725 #else /* ! MHD_POSIX_SOCKETS && _WIN64 */
1726  {
1727  int64_t i_add;
1728 
1729  i_add = (int64_t) (iov[i].iov_len / ULONG_MAX);
1730  if (0 != iov[i].iov_len % ULONG_MAX)
1731  i_add++;
1732  if (INT_MAX < (i_add + i_cp))
1733  {
1734  i_cp = -1; /* overflow */
1735  break;
1736  }
1737  i_cp += (int) i_add;
1738  }
1739 #endif /* ! MHD_POSIX_SOCKETS && _WIN64 */
1740  }
1741  if (-1 == i_cp)
1742  {
1743  /* Some error condition */
1744  MHD_mutex_destroy_chk_ (&response->mutex);
1745  free (response);
1746  return NULL;
1747  }
1748  response->fd = -1;
1749  response->reference_count = 1;
1750  response->total_size = total_size;
1751  response->crc_cls = cls;
1752  response->crfc = free_cb;
1753  if (0 == i_cp)
1754  {
1755  mhd_assert (0 == total_size);
1756  return response;
1757  }
1758  if (1 == i_cp)
1759  {
1760  mhd_assert (NULL != last_valid_buffer);
1761  response->data = last_valid_buffer;
1762  response->data_size = (size_t) total_size;
1763  return response;
1764  }
1765  mhd_assert (1 < i_cp);
1766  if (1)
1767  { /* for local variables local scope only */
1768  MHD_iovec_ *iov_copy;
1769  int num_copy_elements = i_cp;
1770 
1771  iov_copy = MHD_calloc_ ((size_t) num_copy_elements, \
1772  sizeof(MHD_iovec_));
1773  if (NULL == iov_copy)
1774  {
1775  MHD_mutex_destroy_chk_ (&response->mutex);
1776  free (response);
1777  return NULL;
1778  }
1779  i_cp = 0;
1780  for (i = 0; i < iovcnt; ++i)
1781  {
1782  size_t element_size = iov[i].iov_len;
1783  const uint8_t *buf = (const uint8_t *) iov[i].iov_base;
1784 
1785  if (0 == element_size)
1786  continue; /* skip zero-sized elements */
1787 #if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
1788  while (MHD_IOV_ELMN_MAX_SIZE < element_size)
1789  {
1790  iov_copy[i_cp].iov_base = (char *) _MHD_DROP_CONST (buf);
1791  iov_copy[i_cp].iov_len = ULONG_MAX;
1792  buf += ULONG_MAX;
1793  element_size -= ULONG_MAX;
1794  i_cp++;
1795  }
1796 #endif /* MHD_WINSOCK_SOCKETS && _WIN64 */
1797  iov_copy[i_cp].iov_base = _MHD_DROP_CONST (buf);
1798  iov_copy[i_cp].iov_len = (MHD_iov_size_) element_size;
1799  i_cp++;
1800  }
1801  mhd_assert (num_copy_elements == i_cp);
1802  mhd_assert (0 <= i_cp);
1803  response->data_iov = iov_copy;
1804  response->data_iovcnt = (unsigned int) i_cp;
1805  }
1806  return response;
1807 }
1808 
1809 
1825 _MHD_EXTERN struct MHD_Response *
1827 {
1828  struct MHD_Response *r;
1829  r = (struct MHD_Response *) MHD_calloc_ (1, sizeof (struct MHD_Response));
1830  if (NULL != r)
1831  {
1832  if (MHD_mutex_init_ (&r->mutex))
1833  {
1834  r->fd = -1;
1835  r->reference_count = 1;
1836  /* If any flags combination will be not allowed, replace the next
1837  * assignment with MHD_set_response_options() call. */
1838  r->flags = flags;
1839 
1840  return r; /* Successful result */
1841  }
1842  free (r);
1843  }
1844  return NULL; /* Something failed */
1845 }
1846 
1847 
1848 #ifdef UPGRADE_SUPPORT
1862 MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
1864  ...)
1865 {
1866  struct MHD_Connection *connection;
1867  struct MHD_Daemon *daemon;
1868 
1869  if (NULL == urh)
1870  return MHD_NO;
1871  connection = urh->connection;
1872 
1873  /* Precaution checks on external data. */
1874  if (NULL == connection)
1875  return MHD_NO;
1876  daemon = connection->daemon;
1877  if (NULL == daemon)
1878  return MHD_NO;
1879 
1880  switch (action)
1881  {
1883  if (urh->was_closed)
1884  return MHD_NO; /* Already closed. */
1885 
1886  /* transition to special 'closed' state for start of cleanup */
1887 #ifdef HTTPS_SUPPORT
1888  if (0 != (daemon->options & MHD_USE_TLS) )
1889  {
1890  /* signal that app is done by shutdown() of 'app' socket */
1891  /* Application will not use anyway this socket after this command. */
1892  shutdown (urh->app.socket,
1893  SHUT_RDWR);
1894  }
1895 #endif /* HTTPS_SUPPORT */
1896  mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
1897  /* The next function will mark the connection as closed by application
1898  * by setting 'urh->was_closed'.
1899  * As soon as connection will be marked with BOTH
1900  * 'urh->was_closed' AND 'urh->clean_ready', it will
1901  * be moved to cleanup list by MHD_resume_connection(). */
1902  MHD_upgraded_connection_mark_app_closed_ (connection);
1903  return MHD_YES;
1905  /* Unportable API. TODO: replace with portable action. */
1906  return MHD_connection_set_cork_state_ (connection,
1907  true) ? MHD_YES : MHD_NO;
1909  /* Unportable API. TODO: replace with portable action. */
1910  return MHD_connection_set_cork_state_ (connection,
1911  false) ? MHD_YES : MHD_NO;
1912  default:
1913  /* we don't understand this one */
1914  return MHD_NO;
1915  }
1916 }
1917 
1918 
1932 enum MHD_Result
1934  struct MHD_Connection *connection)
1935 {
1936 #if defined(HTTPS_SUPPORT) || defined(_DEBUG) || defined(HAVE_MESSAGES)
1937  struct MHD_Daemon *const daemon = connection->daemon;
1938 #endif /* HTTPS_SUPPORT || _DEBUG || HAVE_MESSAGES */
1939  struct MHD_UpgradeResponseHandle *urh;
1940  size_t rbo;
1941 
1942 #ifdef MHD_USE_THREADS
1943  mhd_assert ( (! MHD_D_IS_USING_THREADS_ (daemon)) || \
1944  MHD_thread_handle_ID_is_current_thread_ (connection->tid) );
1945 #endif /* MHD_USE_THREADS */
1946 
1947  /* "Upgrade" responses accepted only if MHD_ALLOW_UPGRADE is enabled */
1948  mhd_assert (0 != (daemon->options & MHD_ALLOW_UPGRADE));
1949  /* The header was checked when response queued */
1950  mhd_assert (NULL != \
1953  MHD_STATICSTR_LEN_ ( \
1955 
1956  if (! connection->sk_nonblck)
1957  {
1958 #ifdef HAVE_MESSAGES
1959  MHD_DLOG (daemon,
1960  _ ("Cannot execute \"upgrade\" as the socket is in " \
1961  "the blocking mode.\n"));
1962 #endif
1963  return MHD_NO;
1964  }
1965  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
1966  if (NULL == urh)
1967  return MHD_NO;
1968  urh->connection = connection;
1969  rbo = connection->read_buffer_offset;
1970  connection->read_buffer_offset = 0;
1971  MHD_connection_set_nodelay_state_ (connection, false);
1972  MHD_connection_set_cork_state_ (connection, false);
1973 #ifdef HTTPS_SUPPORT
1974  if (0 != (daemon->options & MHD_USE_TLS) )
1975  {
1976  MHD_socket sv[2];
1977 #if defined(MHD_socket_nosignal_) || ! defined(MHD_socket_pair_nblk_)
1978  int res1;
1979  int res2;
1980 #endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
1981 
1982 #ifdef MHD_socket_pair_nblk_
1983  if (! MHD_socket_pair_nblk_ (sv))
1984  {
1985  free (urh);
1986  return MHD_NO;
1987  }
1988 #else /* !MHD_socket_pair_nblk_ */
1989  if (! MHD_socket_pair_ (sv))
1990  {
1991  free (urh);
1992  return MHD_NO;
1993  }
1994  res1 = MHD_socket_nonblocking_ (sv[0]);
1995  res2 = MHD_socket_nonblocking_ (sv[1]);
1996  if ( (! res1) || (! res2) )
1997  {
1998 #ifdef HAVE_MESSAGES
1999  MHD_DLOG (daemon,
2000  _ ("Failed to make loopback sockets non-blocking.\n"));
2001 #endif
2002  if (! res2)
2003  {
2004  /* Socketpair cannot be used. */
2005  MHD_socket_close_chk_ (sv[0]);
2006  MHD_socket_close_chk_ (sv[1]);
2007  free (urh);
2008  return MHD_NO;
2009  }
2010  }
2011 #endif /* !MHD_socket_pair_nblk_ */
2012 #ifdef MHD_socket_nosignal_
2013  res1 = MHD_socket_nosignal_ (sv[0]);
2014  res2 = MHD_socket_nosignal_ (sv[1]);
2015  if ( (! res1) || (! res2) )
2016  {
2017 #ifdef HAVE_MESSAGES
2018  MHD_DLOG (daemon,
2019  _ ("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
2020 #endif
2021 #ifndef MSG_NOSIGNAL
2022  if (! res2)
2023  {
2024  /* Socketpair cannot be used. */
2025  MHD_socket_close_chk_ (sv[0]);
2026  MHD_socket_close_chk_ (sv[1]);
2027  free (urh);
2028  return MHD_NO;
2029  }
2030 #endif /* ! MSG_NOSIGNAL */
2031  }
2032 #endif /* MHD_socket_nosignal_ */
2033  if (MHD_D_IS_USING_SELECT_ (daemon) &&
2034  (! MHD_D_DOES_SCKT_FIT_FDSET_ (sv[1], daemon)) )
2035  {
2036 #ifdef HAVE_MESSAGES
2037  MHD_DLOG (daemon,
2038  _ ("Socketpair descriptor is not less than FD_SETSIZE: " \
2039  "%d >= %d\n"),
2040  (int) sv[1],
2041  (int) MHD_D_GET_FD_SETSIZE_ (daemon));
2042 #endif
2043  MHD_socket_close_chk_ (sv[0]);
2044  MHD_socket_close_chk_ (sv[1]);
2045  free (urh);
2046  return MHD_NO;
2047  }
2048  urh->app.socket = sv[0];
2049  urh->app.urh = urh;
2050  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
2051  urh->mhd.socket = sv[1];
2052  urh->mhd.urh = urh;
2053  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
2054 #ifdef EPOLL_SUPPORT
2055  /* Launch IO processing by the event loop */
2056  if (MHD_D_IS_USING_EPOLL_ (daemon))
2057  {
2058  /* We're running with epoll(), need to add the sockets
2059  to the event set of the daemon's `epoll_upgrade_fd` */
2060  struct epoll_event event;
2061 
2062  mhd_assert (-1 != daemon->epoll_upgrade_fd);
2063  /* First, add network socket */
2064  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2065  event.data.ptr = &urh->app;
2066  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
2067  EPOLL_CTL_ADD,
2068  connection->socket_fd,
2069  &event))
2070  {
2071 #ifdef HAVE_MESSAGES
2072  MHD_DLOG (daemon,
2073  _ ("Call to epoll_ctl failed: %s\n"),
2075 #endif
2076  MHD_socket_close_chk_ (sv[0]);
2077  MHD_socket_close_chk_ (sv[1]);
2078  free (urh);
2079  return MHD_NO;
2080  }
2081 
2082  /* Second, add our end of the UNIX socketpair() */
2083  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
2084  event.data.ptr = &urh->mhd;
2085  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
2086  EPOLL_CTL_ADD,
2087  urh->mhd.socket,
2088  &event))
2089  {
2090  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
2091  event.data.ptr = &urh->app;
2092  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
2093  EPOLL_CTL_DEL,
2094  connection->socket_fd,
2095  &event))
2096  MHD_PANIC (_ ("Error cleaning up while handling epoll error.\n"));
2097 #ifdef HAVE_MESSAGES
2098  MHD_DLOG (daemon,
2099  _ ("Call to epoll_ctl failed: %s\n"),
2101 #endif
2102  MHD_socket_close_chk_ (sv[0]);
2103  MHD_socket_close_chk_ (sv[1]);
2104  free (urh);
2105  return MHD_NO;
2106  }
2107  EDLL_insert (daemon->eready_urh_head,
2108  daemon->eready_urh_tail,
2109  urh);
2110  urh->in_eready_list = true;
2111  }
2112 #endif /* EPOLL_SUPPORT */
2113  if (! MHD_D_IS_USING_THREAD_PER_CONN_ (daemon))
2114  {
2115  /* This takes care of further processing for most event loops:
2116  simply add to DLL for bi-direcitonal processing */
2117  DLL_insert (daemon->urh_head,
2118  daemon->urh_tail,
2119  urh);
2120  }
2121  /* In thread-per-connection mode, thread will switch to forwarding once
2122  * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
2123  */
2124  }
2125  else
2126  {
2127  urh->app.socket = MHD_INVALID_SOCKET;
2128  urh->mhd.socket = MHD_INVALID_SOCKET;
2129  /* Non-TLS connection do not hold any additional resources. */
2130  urh->clean_ready = true;
2131  }
2132 #else /* ! HTTPS_SUPPORT */
2133  urh->clean_ready = true;
2134 #endif /* ! HTTPS_SUPPORT */
2135  connection->urh = urh;
2136  /* As far as MHD's event loops are concerned, this connection is
2137  suspended; it will be resumed once application is done by the
2138  #MHD_upgrade_action() function */
2139  internal_suspend_connection_ (connection);
2140 
2141  /* hand over socket to application */
2142  response->upgrade_handler (response->upgrade_handler_cls,
2143  connection,
2144  connection->rq.client_context,
2145  connection->read_buffer,
2146  rbo,
2147 #ifdef HTTPS_SUPPORT
2148  (0 == (daemon->options & MHD_USE_TLS) ) ?
2149  connection->socket_fd : urh->app.socket,
2150 #else /* ! HTTPS_SUPPORT */
2151  connection->socket_fd,
2152 #endif /* ! HTTPS_SUPPORT */
2153  urh);
2154 
2155 #ifdef HTTPS_SUPPORT
2156  if (0 != (daemon->options & MHD_USE_TLS))
2157  {
2158  struct MemoryPool *const pool = connection->pool;
2159  size_t avail;
2160  char *buf;
2161 
2162  /* All data should be sent already */
2163  mhd_assert (connection->write_buffer_send_offset == \
2164  connection->write_buffer_append_offset);
2165  MHD_pool_deallocate (pool, connection->write_buffer,
2166  connection->write_buffer_size);
2167  connection->write_buffer_append_offset = 0;
2168  connection->write_buffer_send_offset = 0;
2169  connection->write_buffer_size = 0;
2170  connection->write_buffer = NULL;
2171 
2172  /* Extra read data should be processed already by the application */
2173  MHD_pool_deallocate (pool, connection->read_buffer,
2174  connection->read_buffer_size);
2175  connection->read_buffer_offset = 0;
2176  connection->read_buffer_size = 0;
2177  connection->read_buffer = NULL;
2178 
2179  avail = MHD_pool_get_free (pool);
2180  if (avail < RESERVE_EBUF_SIZE)
2181  {
2182  /* connection's pool is totally at the limit,
2183  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
2184  avail = RESERVE_EBUF_SIZE;
2185  buf = urh->e_buf;
2186 #ifdef HAVE_MESSAGES
2187  MHD_DLOG (daemon,
2188  _ ("Memory shortage in connection's memory pool. " \
2189  "The \"upgraded\" communication will be inefficient.\n"));
2190 #endif
2191  }
2192  else
2193  {
2194  /* Normal case: grab all remaining memory from the
2195  connection's pool for the IO buffers; the connection
2196  certainly won't need it anymore as we've upgraded
2197  to another protocol. */
2198  buf = MHD_pool_allocate (pool,
2199  avail,
2200  false);
2201  }
2202  /* use half the buffer for inbound, half for outbound */
2203  urh->in_buffer_size = avail / 2;
2204  urh->out_buffer_size = avail - urh->in_buffer_size;
2205  urh->in_buffer = buf;
2206  urh->out_buffer = buf + urh->in_buffer_size;
2207  }
2208 #endif /* HTTPS_SUPPORT */
2209  return MHD_YES;
2210 }
2211 
2212 
2242 _MHD_EXTERN struct MHD_Response *
2244  void *upgrade_handler_cls)
2245 {
2246  struct MHD_Response *response;
2247 
2248  if (NULL == upgrade_handler)
2249  return NULL; /* invalid request */
2250  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
2251  if (NULL == response)
2252  return NULL;
2253 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2254  if (! MHD_mutex_init_ (&response->mutex))
2255  {
2256  free (response);
2257  return NULL;
2258  }
2259 #endif
2260  response->upgrade_handler = upgrade_handler;
2261  response->upgrade_handler_cls = upgrade_handler_cls;
2262  response->total_size = 0;
2263  response->reference_count = 1;
2264  if (MHD_NO ==
2265  MHD_add_response_header (response,
2267  "Upgrade"))
2268  {
2269  MHD_destroy_response (response);
2270  return NULL;
2271  }
2272  return response;
2273 }
2274 
2275 
2276 #endif /* UPGRADE_SUPPORT */
2277 
2278 
2288 _MHD_EXTERN void
2290 {
2291  struct MHD_HTTP_Res_Header *pos;
2292 
2293  if (NULL == response)
2294  return;
2295 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2296  MHD_mutex_lock_chk_ (&response->mutex);
2297 #endif
2298  if (0 != --(response->reference_count))
2299  {
2300 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2301  MHD_mutex_unlock_chk_ (&response->mutex);
2302 #endif
2303  return;
2304  }
2305 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2306  MHD_mutex_unlock_chk_ (&response->mutex);
2307  MHD_mutex_destroy_chk_ (&response->mutex);
2308 #endif
2309  if (NULL != response->crfc)
2310  response->crfc (response->crc_cls);
2311 
2312  if (NULL != response->data_iov)
2313  {
2314  free (response->data_iov);
2315  }
2316 
2317  while (NULL != response->first_header)
2318  {
2319  pos = response->first_header;
2320  response->first_header = pos->next;
2321  free (pos->header);
2322  free (pos->value);
2323  free (pos);
2324  }
2325  free (response);
2326 }
2327 
2328 
2334 void
2336 {
2337 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2338  MHD_mutex_lock_chk_ (&response->mutex);
2339 #endif
2340  (response->reference_count)++;
2341 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
2342  MHD_mutex_unlock_chk_ (&response->mutex);
2343 #endif
2344 }
2345 
2346 
2347 /* end of response.c */
Methods for managing connections.
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:3224
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:590
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:584
#define MHD_HTTP_HEADER_DATE
Definition: microhttpd.h:598
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:648
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:650
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2789
_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:1682
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:823
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:1593
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_copy(size_t size, const void *buffer)
Definition: response.c:1540
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:1465
_MHD_EXTERN enum MHD_Result MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:741
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_pipe(int fd)
Definition: response.c:1335
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:2289
struct MHD_HTTP_Res_Header * MHD_get_response_element_n_(struct MHD_Response *response, enum MHD_ValueKind kind, const char *key, size_t key_len)
Definition: response.c:889
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:1370
_MHD_EXTERN struct MHD_Response * MHD_create_response_empty(enum MHD_ResponseFlags flags)
Definition: response.c:1826
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:1248
MHD_ResponseMemoryMode
Definition: microhttpd.h:3979
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:855
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_static(size_t size, const void *buffer)
Definition: response.c:1507
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:2884
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:1284
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback_cls(size_t size, const void *buffer, MHD_ContentReaderFreeCallback crfc, void *crfc_cls)
Definition: response.c:1627
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:620
_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:987
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:1400
_MHD_EXTERN enum MHD_Result MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:715
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:1429
@ MHD_RESPMEM_MUST_FREE
Definition: microhttpd.h:4001
@ MHD_RESPMEM_PERSISTENT
Definition: microhttpd.h:3987
@ MHD_RESPMEM_MUST_COPY
Definition: microhttpd.h:4010
@ 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
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:53
bool MHD_connection_set_cork_state_(struct MHD_Connection *connection, bool cork_state)
Definition: mhd_send.c:244
bool MHD_connection_set_nodelay_state_(struct MHD_Connection *connection, bool nodelay_state)
Definition: mhd_send.c:174
Declarations of send() wrappers.
MHD internal shared structures.
#define MHD_D_DOES_SCKT_FIT_FDSET_(sckt, d)
Definition: internal.h:2601
#define MHD_D_IS_USING_SELECT_(d)
Definition: internal.h:2542
size_t MHD_iov_size_
Definition: internal.h:442
MHD_ResponseAutoFlags
Definition: internal.h:405
@ MHD_RAF_HAS_DATE_HDR
Definition: internal.h:411
@ MHD_RAF_HAS_CONTENT_LENGTH
Definition: internal.h:410
@ MHD_RAF_HAS_CONNECTION_CLOSE
Definition: internal.h:408
@ MHD_RAF_HAS_TRANS_ENC_CHUNKED
Definition: internal.h:409
@ MHD_RAF_HAS_CONNECTION_HDR
Definition: internal.h:407
#define _MHD_DROP_CONST(ptr)
Definition: internal.h:77
#define MHD_D_GET_FD_SETSIZE_(d)
Definition: internal.h:2595
#define MHD_D_IS_USING_THREAD_PER_CONN_(d)
Definition: internal.h:2578
#define MHD_D_IS_USING_THREADS_(d)
Definition: internal.h:2574
#define MHD_D_IS_USING_EPOLL_(d)
Definition: internal.h:2550
#define MHD_IOV_ELMN_MAX_SIZE
Definition: internal.h:441
void MHD_pool_deallocate(struct MemoryPool *pool, void *block, size_t block_size)
Definition: memorypool.c:625
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:121
#define INT_MAX
Definition: mhd_limits.h:45
#define MHD_mutex_init_(ignore)
Definition: mhd_locks.h:192
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:1033
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:857
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:749
Header for string manipulating helpers.
#define MHD_thread_handle_ID_is_current_thread_(hndl_id)
Definition: mhd_threads.h:498
static void free_callback(void *cls)
Definition: response.c:1213
#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:930
bool MHD_add_response_entry_no_check_(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, size_t header_len, const char *content, size_t content_len)
Definition: response.c:207
#define _MHD_insert_header_last(presponse, phdr)
Definition: response.c:98
static bool add_response_entry_n(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, size_t header_len, const char *content, size_t content_len)
Definition: response.c:256
#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:328
#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:297
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:1086
static enum MHD_Result del_response_header_connection(struct MHD_Response *response, const char *value)
Definition: response.c:517
bool MHD_add_response_entry_no_alloc_(struct MHD_Response *response, enum MHD_ValueKind kind, char *header, size_t header_len, char *content, size_t content_len)
Definition: response.c:167
static ssize_t pipe_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:1174
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:2335
_MHD_EXTERN enum MHD_Result MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:1028
int MHD_socket
Definition: microhttpd.h:201
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:178
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:4243
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:181
_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:3970
void int must_free
Definition: microhttpd.h:3969
int fd
Definition: microhttpd.h:4242
void * data
Definition: microhttpd.h:3968
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:202
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:2868
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:182
MHD_UpgradeAction
Definition: microhttpd.h:4338
@ MHD_UPGRADE_ACTION_CORK_ON
Definition: microhttpd.h:4350
@ MHD_UPGRADE_ACTION_CLOSE
Definition: microhttpd.h:4345
@ MHD_UPGRADE_ACTION_CORK_OFF
Definition: microhttpd.h:4355
MHD_ValueKind
Definition: microhttpd.h:2245
@ MHD_FOOTER_KIND
Definition: microhttpd.h:2286
@ MHD_HEADER_KIND
Definition: microhttpd.h:2260
void(* MHD_UpgradeHandler)(void *cls, struct MHD_Connection *connection, void *req_cls, const char *extra_in, size_t extra_in_size, MHD_socket sock, struct MHD_UpgradeResponseHandle *urh)
Definition: microhttpd.h:4434
@ MHD_USE_TLS
Definition: microhttpd.h:1265
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1501
MHD_ResponseOptions
Definition: microhttpd.h:3895
@ MHD_RO_END
Definition: microhttpd.h:3899
MHD_ResponseFlags
Definition: microhttpd.h:3808
@ MHD_RF_HEAD_ONLY_RESPONSE
Definition: microhttpd.h:3887
@ MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:3862
_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
size_t write_buffer_size
Definition: internal.h:1441
size_t write_buffer_send_offset
Definition: internal.h:1446
size_t write_buffer_append_offset
Definition: internal.h:1452
char * write_buffer
Definition: internal.h:1409
bool sk_nonblck
Definition: internal.h:784
struct MHD_Request rq
Definition: internal.h:1365
struct MemoryPool * pool
Definition: internal.h:685
size_t read_buffer_offset
Definition: internal.h:1436
enum MHD_CONNECTION_STATE state
Definition: internal.h:1565
char * read_buffer
Definition: internal.h:1403
struct MHD_Daemon * daemon
Definition: internal.h:675
size_t read_buffer_size
Definition: internal.h:1430
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1880
struct MHD_HTTP_Res_Header * next
Definition: internal.h:323
enum MHD_ValueKind kind
Definition: internal.h:353
const void * iov_base
Definition: microhttpd.h:2454
size_t iov_len
Definition: microhttpd.h:2459
void * client_context
Definition: internal.h:401
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:1606
void * crc_cls
Definition: internal.h:1594
size_t data_buffer_size
Definition: internal.h:1664
MHD_iovec_ * data_iov
Definition: internal.h:588
MHD_ContentReaderCallback crc
Definition: internal.h:1600
bool is_pipe
Definition: internal.h:583
struct MHD_Action action
Definition: internal.h:1575
enum MHD_ResponseAutoFlags flags_auto
Definition: internal.h:578
unsigned int data_iovcnt
Definition: internal.h:593
size_t data_size
Definition: internal.h:1659
enum MHD_ResponseFlags flags
Definition: internal.h:573
char * data
Definition: internal.h:1588
unsigned int reference_count
Definition: internal.h:1675
MHD_mutex_ mutex
Definition: internal.h:1637
uint64_t total_size
Definition: internal.h:1642
uint64_t fd_off
Definition: internal.h:1653
struct MHD_HTTP_Header * first_header
Definition: internal.h:1582