GNU libmicrohttpd 0.9.75
Loading...
Searching...
No Matches
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
156static enum MHD_Result
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
208static 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
389static 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
492enum MHD_Result
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
570enum MHD_Result
572 const char *footer,
573 const char *content)
574{
575 return add_response_entry (response,
577 footer,
578 content);
579}
580
581
596enum MHD_Result
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
665int
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
697const 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
731struct 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
772bool
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
824struct 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
865enum MHD_Result
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
901static ssize_t
902file_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
989static ssize_t
990pipe_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
1024static void
1025free_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
1059struct MHD_Response *
1061 int fd,
1062 off_t offset)
1063{
1065 fd,
1066 offset);
1067}
1068
1069
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
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
1179struct MHD_Response *
1181 int fd)
1182{
1184 fd,
1185 0);
1186}
1187
1188
1211 int fd)
1212{
1214 fd,
1215 0);
1216}
1217
1218
1240struct 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);
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
1307struct 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
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
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
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
1553MHD_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
1622enum 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 ==
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
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
1947void
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
1993void
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
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(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:1337
_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 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
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
_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
static bool add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:40
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 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
void int int must_copy
Definition: microhttpd.h:3430
#define MHD_create_response_from_fd_at_offset(size, fd, offset)
Definition: microhttpd.h:3648
_MHD_EXTERN struct MHD_Response * MHD_create_response_for_upgrade(MHD_UpgradeHandler upgrade_handler, void *upgrade_handler_cls)
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