GNU libmicrohttpd 0.9.73
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
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
27#define MHD_NO_DEPRECATION 1
28
29#include "mhd_options.h"
30#ifdef HAVE_SYS_IOCTL_H
31#include <sys/ioctl.h>
32#endif /* HAVE_SYS_IOCTL_H */
33#if defined(_WIN32) && ! defined(__CYGWIN__)
34#include <windows.h>
35#endif /* _WIN32 && !__CYGWIN__ */
36
37#include "internal.h"
38#include "response.h"
39#include "mhd_limits.h"
40#include "mhd_sockets.h"
41#include "mhd_itc.h"
42#include "mhd_str.h"
43#include "connection.h"
44#include "memorypool.h"
45#include "mhd_send.h"
46#include "mhd_compat.h"
47
48
49#if defined(MHD_W32_MUTEX_)
50#ifndef WIN32_LEAN_AND_MEAN
51#define WIN32_LEAN_AND_MEAN 1
52#endif /* !WIN32_LEAN_AND_MEAN */
53#include <windows.h>
54#endif /* MHD_W32_MUTEX_ */
55#if defined(_WIN32)
56#include <io.h> /* for lseek(), read() */
57#endif /* _WIN32 */
58
59
64#ifndef MHD_FILE_READ_BLOCK_SIZE
65#ifdef _WIN32
66#define MHD_FILE_READ_BLOCK_SIZE 16384 /* 16k */
67#else /* _WIN32 */
68#define MHD_FILE_READ_BLOCK_SIZE 4096 /* 4k */
69#endif /* _WIN32 */
70#endif /* !MHD_FD_BLOCK_SIZE */
71
72
82static enum MHD_Result
84 enum MHD_ValueKind kind,
85 const char *header,
86 const char *content)
87{
88 struct MHD_HTTP_Header *hdr;
89
90 if ( (NULL == response) ||
91 (NULL == header) ||
92 (NULL == content) ||
93 (0 == header[0]) ||
94 (0 == content[0]) ||
95 (NULL != strchr (header, '\t')) ||
96 (NULL != strchr (header, '\r')) ||
97 (NULL != strchr (header, '\n')) ||
98 (NULL != strchr (content, '\t')) ||
99 (NULL != strchr (content, '\r')) ||
100 (NULL != strchr (content, '\n')) )
101 return MHD_NO;
102 if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
103 return MHD_NO;
104 if (NULL == (hdr->header = strdup (header)))
105 {
106 free (hdr);
107 return MHD_NO;
108 }
109 hdr->header_size = strlen (header);
110 if (NULL == (hdr->value = strdup (content)))
111 {
112 free (hdr->header);
113 free (hdr);
114 return MHD_NO;
115 }
116 hdr->value_size = strlen (content);
117 hdr->kind = kind;
118 hdr->next = response->first_header;
119 response->first_header = hdr;
120 return MHD_YES;
121}
122
123
133enum MHD_Result
135 const char *header,
136 const char *content)
137{
140 (! MHD_str_equal_caseless_ (content,
141 "identity")) &&
142 (! MHD_str_equal_caseless_ (content,
143 "chunked")) )
144 {
145 /* Setting transfer encodings other than "identity" or
146 "chunked" is not allowed. Note that MHD will set the
147 correct transfer encoding if required automatically. */
148 /* NOTE: for compressed bodies, use the "Content-encoding" header */
149 return MHD_NO;
150 }
152 & response->flags)) &&
155 {
156 /* MHD will set Content-length if allowed and possible,
157 reject attempt by application */
158 return MHD_NO;
159 }
160
161 return add_response_entry (response,
163 header,
164 content);
165}
166
167
177enum MHD_Result
179 const char *footer,
180 const char *content)
181{
182 return add_response_entry (response,
184 footer,
185 content);
186}
187
188
198enum MHD_Result
200 const char *header,
201 const char *content)
202{
203 struct MHD_HTTP_Header *pos;
204 struct MHD_HTTP_Header *prev;
205 size_t header_len;
206 size_t content_len;
207
208 if ( (NULL == header) ||
209 (NULL == content) )
210 return MHD_NO;
211 header_len = strlen (header);
212 content_len = strlen (content);
213 prev = NULL;
214 pos = response->first_header;
215 while (NULL != pos)
216 {
217 if ((header_len == pos->header_size) &&
218 (content_len == pos->value_size) &&
219 (0 == memcmp (header,
220 pos->header,
221 header_len)) &&
222 (0 == memcmp (content,
223 pos->value,
224 content_len)))
225 {
226 free (pos->header);
227 free (pos->value);
228 if (NULL == prev)
229 response->first_header = pos->next;
230 else
231 prev->next = pos->next;
232 free (pos);
233 return MHD_YES;
234 }
235 prev = pos;
236 pos = pos->next;
237 }
238 return MHD_NO;
239}
240
241
252int
254 MHD_KeyValueIterator iterator,
255 void *iterator_cls)
256{
257 int numHeaders = 0;
258 struct MHD_HTTP_Header *pos;
259
260 for (pos = response->first_header;
261 NULL != pos;
262 pos = pos->next)
263 {
264 numHeaders++;
265 if ((NULL != iterator) &&
266 (MHD_NO == iterator (iterator_cls,
267 pos->kind,
268 pos->header,
269 pos->value)))
270 break;
271 }
272 return numHeaders;
273}
274
275
284const char *
286 const char *key)
287{
288 struct MHD_HTTP_Header *pos;
289 size_t key_size;
290
291 if (NULL == key)
292 return NULL;
293
294 key_size = strlen (key);
295 for (pos = response->first_header;
296 NULL != pos;
297 pos = pos->next)
298 {
299 if ((pos->header_size == key_size) &&
301 return pos->value;
302 }
303 return NULL;
304}
305
306
323bool
325 const char *key,
326 size_t key_len,
327 const char *token,
328 size_t token_len)
329{
330 struct MHD_HTTP_Header *pos;
331
332 if ( (NULL == key) ||
333 ('\0' == key[0]) ||
334 (NULL == token) ||
335 ('\0' == token[0]) )
336 return false;
337
338 /* Token must not contain binary zero! */
339 mhd_assert (strlen (token) == token_len);
340
341 for (pos = response->first_header;
342 NULL != pos;
343 pos = pos->next)
344 {
345 if ( (pos->kind == MHD_HEADER_KIND) &&
346 (key_len == pos->header_size) &&
348 key,
349 key_len) &&
351 token,
352 token_len) )
353 return true;
354 }
355 return false;
356}
357
358
375struct MHD_Response *
377 size_t block_size,
379 void *crc_cls,
381{
382 struct MHD_Response *response;
383
384 if ((NULL == crc) || (0 == block_size))
385 return NULL;
386 if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response)
387 + block_size)))
388 return NULL;
389 response->fd = -1;
390 response->data = (void *) &response[1];
391 response->data_buffer_size = block_size;
392#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
393 if (! MHD_mutex_init_ (&response->mutex))
394 {
395 free (response);
396 return NULL;
397 }
398#endif
399 response->crc = crc;
400 response->crfc = crfc;
401 response->crc_cls = crc_cls;
402 response->reference_count = 1;
403 response->total_size = size;
404 return response;
405}
406
407
416enum MHD_Result
419 ...)
420{
421 va_list ap;
422 enum MHD_Result ret;
423 enum MHD_ResponseOptions ro;
424
425 ret = MHD_YES;
426 response->flags = flags;
427 va_start (ap, flags);
428 while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
429 {
430 switch (ro)
431 {
432 default:
433 ret = MHD_NO;
434 break;
435 }
436 }
437 va_end (ap);
438 return ret;
439}
440
441
452static ssize_t
453file_reader (void *cls,
454 uint64_t pos,
455 char *buf,
456 size_t max)
457{
458 struct MHD_Response *response = cls;
459#if ! defined(_WIN32) || defined(__CYGWIN__)
460 ssize_t n;
461#else /* _WIN32 && !__CYGWIN__ */
462 const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
463#endif /* _WIN32 && !__CYGWIN__ */
464 const int64_t offset64 = (int64_t) (pos + response->fd_off);
465
466 if (offset64 < 0)
467 return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
468
469#if ! defined(_WIN32) || defined(__CYGWIN__)
470 if (max > SSIZE_MAX)
471 max = SSIZE_MAX; /* Clamp to maximum return value. */
472
473#if defined(HAVE_PREAD64)
474 n = pread64 (response->fd, buf, max, offset64);
475#elif defined(HAVE_PREAD)
476 if ( (sizeof(off_t) < sizeof (uint64_t)) &&
477 (offset64 > (uint64_t) INT32_MAX) )
478 return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
479
480 n = pread (response->fd, buf, max, (off_t) offset64);
481#else /* ! HAVE_PREAD */
482#if defined(HAVE_LSEEK64)
483 if (lseek64 (response->fd,
484 offset64,
485 SEEK_SET) != offset64)
486 return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
487#else /* ! HAVE_LSEEK64 */
488 if ( (sizeof(off_t) < sizeof (uint64_t)) &&
489 (offset64 > (uint64_t) INT32_MAX) )
490 return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
491
492 if (lseek (response->fd,
493 (off_t) offset64,
494 SEEK_SET) != (off_t) offset64)
495 return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
496#endif /* ! HAVE_LSEEK64 */
497 n = read (response->fd,
498 buf,
499 max);
500
501#endif /* ! HAVE_PREAD */
502 if (0 == n)
504 if (n < 0)
506 return n;
507#else /* _WIN32 && !__CYGWIN__ */
508 if (INVALID_HANDLE_VALUE == fh)
509 return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
510 else
511 {
512 OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
513 ULARGE_INTEGER pos_uli;
514 DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
515 DWORD resRead;
516
517 pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
518 f_ol.Offset = pos_uli.LowPart;
519 f_ol.OffsetHigh = pos_uli.HighPart;
520 if (! ReadFile (fh, (void*) buf, toRead, &resRead, &f_ol))
521 return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
522 if (0 == resRead)
524 return (ssize_t) resRead;
525 }
526#endif /* _WIN32 && !__CYGWIN__ */
527}
528
529
540static ssize_t
541pipe_reader (void *cls,
542 uint64_t pos,
543 char *buf,
544 size_t max)
545{
546 struct MHD_Response *response = cls;
547 ssize_t n;
548
549 (void) pos;
550#ifndef _WIN32
551 if (SSIZE_MAX < max)
552 max = SSIZE_MAX;
553#else /* _WIN32 */
554 if (UINT_MAX < max)
555 max = UINT_MAX;
556#endif /* _WIN32 */
557
558 n = read (response->fd,
559 buf,
560 (MHD_SCKT_SEND_SIZE_) max);
561 if (0 == n)
563 if (n < 0)
565 return n;
566}
567
568
575static void
576free_callback (void *cls)
577{
578 struct MHD_Response *response = cls;
579
580 (void) close (response->fd);
581 response->fd = -1;
582}
583
584
585#undef MHD_create_response_from_fd_at_offset
586
603struct MHD_Response *
605 int fd,
606 off_t offset)
607{
609 fd,
610 offset);
611}
612
613
632 int fd,
633 uint64_t offset)
634{
635 struct MHD_Response *response;
636
637#if ! defined(HAVE___LSEEKI64) && ! defined(HAVE_LSEEK64)
638 if ( (sizeof(uint64_t) > sizeof(off_t)) &&
639 ( (size > (uint64_t) INT32_MAX) ||
640 (offset > (uint64_t) INT32_MAX) ||
641 ((size + offset) >= (uint64_t) INT32_MAX) ) )
642 return NULL;
643#endif
644 if ( ((int64_t) size < 0) ||
645 ((int64_t) offset < 0) ||
646 ((int64_t) (size + offset) < 0) )
647 return NULL;
648
649 response = MHD_create_response_from_callback (size,
652 NULL,
654 if (NULL == response)
655 return NULL;
656 response->fd = fd;
657 response->is_pipe = false;
658 response->fd_off = offset;
659 response->crc_cls = response;
660 return response;
661}
662
663
676{
677 struct MHD_Response *response;
678
682 NULL,
684 if (NULL == response)
685 return NULL;
686 response->fd = fd;
687 response->is_pipe = true;
688 response->crc_cls = response;
689 return response;
690}
691
692
702struct MHD_Response *
704 int fd)
705{
707 fd,
708 0);
709}
710
711
727 int fd)
728{
730 fd,
731 0);
732}
733
734
749struct MHD_Response *
751 void *data,
752 int must_free,
753 int must_copy)
754{
755 struct MHD_Response *response;
756 void *tmp;
757
758 if ((NULL == data) && (size > 0))
759 return NULL;
760 if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
761 return NULL;
762 response->fd = -1;
763#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
764 if (! MHD_mutex_init_ (&response->mutex))
765 {
766 free (response);
767 return NULL;
768 }
769#endif
770 if ((must_copy) && (size > 0))
771 {
772 if (NULL == (tmp = malloc (size)))
773 {
774#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
775 MHD_mutex_destroy_chk_ (&response->mutex);
776#endif
777 free (response);
778 return NULL;
779 }
780 memcpy (tmp, data, size);
782 data = tmp;
783 }
784 if (must_free)
785 {
786 response->crfc = &free;
787 response->crc_cls = data;
788 }
789 response->reference_count = 1;
790 response->total_size = size;
791 response->data = data;
792 response->data_size = size;
793 if (must_copy)
794 response->data_buffer_size = size;
795 return response;
796}
797
798
809struct MHD_Response *
811 void *buffer,
812 enum MHD_ResponseMemoryMode mode)
813{
815 buffer,
816 mode == MHD_RESPMEM_MUST_FREE,
817 mode == MHD_RESPMEM_MUST_COPY);
818}
819
820
833 void *buffer,
835 crfc)
836{
837 struct MHD_Response *r;
838
840 buffer,
841 MHD_YES,
842 MHD_NO);
843 if (NULL == r)
844 return r;
845 r->crfc = crfc;
846 return r;
847}
848
849
865 unsigned int iovcnt,
867 void *cls)
868{
869 struct MHD_Response *response;
870 unsigned int i;
871 int i_cp = 0;
872 uint64_t total_size = 0;
873 const void *last_valid_buffer = NULL;
874
875 if ((NULL == iov) && (0 < iovcnt))
876 return NULL;
877
878 response = MHD_calloc_ (1, sizeof (struct MHD_Response));
879 if (NULL == response)
880 return NULL;
881 if (! MHD_mutex_init_ (&response->mutex))
882 {
883 free (response);
884 return NULL;
885 }
886 /* Calculate final size, number of valid elements, and check 'iov' */
887 for (i = 0; i < iovcnt; ++i)
888 {
889 if (0 == iov[i].iov_len)
890 continue; /* skip zero-sized elements */
891 if (NULL == iov[i].iov_base)
892 {
893 i_cp = -1; /* error */
894 break;
895 }
896 if ( (total_size > (total_size + iov[i].iov_len)) ||
897 (INT_MAX == i_cp) ||
898 (SSIZE_MAX < (total_size + iov[i].iov_len)) )
899 {
900 i_cp = -1; /* overflow */
901 break;
902 }
903 last_valid_buffer = iov[i].iov_base;
904 total_size += iov[i].iov_len;
905#if defined(MHD_POSIX_SOCKETS) || ! defined(_WIN64)
906 i_cp++;
907#else /* ! MHD_POSIX_SOCKETS && _WIN64 */
908 {
909 int64_t i_add;
910
911 i_add = iov[i].iov_len / ULONG_MAX;
912 if (0 != iov[i].iov_len % ULONG_MAX)
913 i_add++;
914 if (INT_MAX < (i_add + i_cp))
915 {
916 i_cp = -1; /* overflow */
917 break;
918 }
919 i_cp += (int) i_add;
920 }
921#endif /* ! MHD_POSIX_SOCKETS && _WIN64 */
922 }
923 if (-1 == i_cp)
924 {
925 /* Some error condition */
926 MHD_mutex_destroy_chk_ (&response->mutex);
927 free (response);
928 return NULL;
929 }
930 response->fd = -1;
931 response->reference_count = 1;
932 response->total_size = total_size;
933 response->crc_cls = cls;
934 response->crfc = free_cb;
935 if (0 == i_cp)
936 {
937 mhd_assert (0 == total_size);
938 return response;
939 }
940 if (1 == i_cp)
941 {
942 mhd_assert (NULL != last_valid_buffer);
943 response->data = (void *) last_valid_buffer;
944 response->data_size = (size_t) total_size;
945 return response;
946 }
947 mhd_assert (1 < i_cp);
948 {
949 MHD_iovec_ *iov_copy;
950 int num_copy_elements = i_cp;
951
952 iov_copy = MHD_calloc_ (num_copy_elements,
953 sizeof(MHD_iovec_));
954 if (NULL == iov_copy)
955 {
956 MHD_mutex_destroy_chk_ (&response->mutex);
957 free (response);
958 return NULL;
959 }
960 i_cp = 0;
961 for (i = 0; i < iovcnt; ++i)
962 {
963 size_t element_size = iov[i].iov_len;
964 const uint8_t *buf = (const uint8_t *) iov[i].iov_base;
965
966 if (0 == element_size)
967 continue; /* skip zero-sized elements */
968#if defined(MHD_WINSOCK_SOCKETS) && defined(_WIN64)
969 while (MHD_IOV_ELMN_MAX_SIZE < element_size)
970 {
971 iov_copy[i_cp].iov_base = (char *) buf;
972 iov_copy[i_cp].iov_len = ULONG_MAX;
973 buf += ULONG_MAX;
974 element_size -= ULONG_MAX;
975 i_cp++;
976 }
977#endif /* MHD_WINSOCK_SOCKETS && _WIN64 */
978 iov_copy[i_cp].iov_base = (void *) buf;
979 iov_copy[i_cp].iov_len = (MHD_iov_size_) element_size;
980 i_cp++;
981 }
982 mhd_assert (num_copy_elements == i_cp);
983 response->data_iov = iov_copy;
984 response->data_iovcnt = i_cp;
985 return response;
986 }
987}
988
989
990#ifdef UPGRADE_SUPPORT
1004MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
1006 ...)
1007{
1008 struct MHD_Connection *connection;
1009 struct MHD_Daemon *daemon;
1010
1011 if (NULL == urh)
1012 return MHD_NO;
1013 connection = urh->connection;
1014
1015 /* Precaution checks on external data. */
1016 if (NULL == connection)
1017 return MHD_NO;
1018 daemon = connection->daemon;
1019 if (NULL == daemon)
1020 return MHD_NO;
1021
1022 switch (action)
1023 {
1025 if (urh->was_closed)
1026 return MHD_NO; /* Already closed. */
1027
1028 /* transition to special 'closed' state for start of cleanup */
1029#ifdef HTTPS_SUPPORT
1030 if (0 != (daemon->options & MHD_USE_TLS) )
1031 {
1032 /* signal that app is done by shutdown() of 'app' socket */
1033 /* Application will not use anyway this socket after this command. */
1034 shutdown (urh->app.socket,
1035 SHUT_RDWR);
1036 }
1037#endif /* HTTPS_SUPPORT */
1038 mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
1039 urh->was_closed = true;
1040 /* As soon as connection will be marked with BOTH
1041 * 'urh->was_closed' AND 'urh->clean_ready', it will
1042 * be moved to cleanup list by MHD_resume_connection(). */
1043 MHD_resume_connection (connection);
1044 return MHD_YES;
1046 /* Unportable API. TODO: replace with portable action. */
1047 return MHD_connection_set_cork_state_ (connection,
1048 true) ? MHD_YES : MHD_NO;
1050 /* Unportable API. TODO: replace with portable action. */
1051 return MHD_connection_set_cork_state_ (connection,
1052 false) ? MHD_YES : MHD_NO;
1053 default:
1054 /* we don't understand this one */
1055 return MHD_NO;
1056 }
1057}
1058
1059
1073enum MHD_Result
1075 struct MHD_Connection *connection)
1076{
1077 struct MHD_Daemon *daemon = connection->daemon;
1078 struct MHD_UpgradeResponseHandle *urh;
1079 size_t rbo;
1080
1081#ifdef MHD_USE_THREADS
1082 mhd_assert ( (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) || \
1083 MHD_thread_ID_match_current_ (connection->pid) );
1084#endif /* MHD_USE_THREADS */
1085
1086 if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
1087 return MHD_NO;
1088
1089 if (NULL ==
1090 MHD_get_response_header (response,
1092 {
1093#ifdef HAVE_MESSAGES
1094 MHD_DLOG (daemon,
1095 _ (
1096 "Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
1097#endif
1098 return MHD_NO;
1099 }
1100
1101 urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
1102 if (NULL == urh)
1103 return MHD_NO;
1104 urh->connection = connection;
1105 rbo = connection->read_buffer_offset;
1106 connection->read_buffer_offset = 0;
1107 MHD_connection_set_nodelay_state_ (connection, false);
1108 MHD_connection_set_cork_state_ (connection, false);
1109#ifdef HTTPS_SUPPORT
1110 if (0 != (daemon->options & MHD_USE_TLS) )
1111 {
1112 struct MemoryPool *pool;
1113 size_t avail;
1114 char *buf;
1115 MHD_socket sv[2];
1116#if defined(MHD_socket_nosignal_) || ! defined(MHD_socket_pair_nblk_)
1117 int res1;
1118 int res2;
1119#endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
1120
1121#ifdef MHD_socket_pair_nblk_
1122 if (! MHD_socket_pair_nblk_ (sv))
1123 {
1124 free (urh);
1125 return MHD_NO;
1126 }
1127#else /* !MHD_socket_pair_nblk_ */
1128 if (! MHD_socket_pair_ (sv))
1129 {
1130 free (urh);
1131 return MHD_NO;
1132 }
1133 res1 = MHD_socket_nonblocking_ (sv[0]);
1134 res2 = MHD_socket_nonblocking_ (sv[1]);
1135 if ( (! res1) || (! res2) )
1136 {
1137#ifdef HAVE_MESSAGES
1138 MHD_DLOG (daemon,
1139 _ ("Failed to make loopback sockets non-blocking.\n"));
1140#endif
1141 if (! res2)
1142 {
1143 /* Socketpair cannot be used. */
1144 MHD_socket_close_chk_ (sv[0]);
1145 MHD_socket_close_chk_ (sv[1]);
1146 free (urh);
1147 return MHD_NO;
1148 }
1149 }
1150#endif /* !MHD_socket_pair_nblk_ */
1151#ifdef MHD_socket_nosignal_
1152 res1 = MHD_socket_nosignal_ (sv[0]);
1153 res2 = MHD_socket_nosignal_ (sv[1]);
1154 if ( (! res1) || (! res2) )
1155 {
1156#ifdef HAVE_MESSAGES
1157 MHD_DLOG (daemon,
1158 _ ("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
1159#endif
1160#ifndef MSG_NOSIGNAL
1161 if (! res2)
1162 {
1163 /* Socketpair cannot be used. */
1164 MHD_socket_close_chk_ (sv[0]);
1165 MHD_socket_close_chk_ (sv[1]);
1166 free (urh);
1167 return MHD_NO;
1168 }
1169#endif /* ! MSG_NOSIGNAL */
1170 }
1171#endif /* MHD_socket_nosignal_ */
1172 if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
1173 NULL)) &&
1174 (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
1175 {
1176#ifdef HAVE_MESSAGES
1177 MHD_DLOG (daemon,
1178 _ ("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
1179 (int) sv[1],
1180 (int) FD_SETSIZE);
1181#endif
1182 MHD_socket_close_chk_ (sv[0]);
1183 MHD_socket_close_chk_ (sv[1]);
1184 free (urh);
1185 return MHD_NO;
1186 }
1187 urh->app.socket = sv[0];
1188 urh->app.urh = urh;
1189 urh->app.celi = MHD_EPOLL_STATE_UNREADY;
1190 urh->mhd.socket = sv[1];
1191 urh->mhd.urh = urh;
1192 urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
1193 pool = connection->pool;
1194 avail = MHD_pool_get_free (pool);
1195 if (avail < RESERVE_EBUF_SIZE)
1196 {
1197 /* connection's pool is totally at the limit,
1198 use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
1199 avail = RESERVE_EBUF_SIZE;
1200 buf = urh->e_buf;
1201 }
1202 else
1203 {
1204 /* Normal case: grab all remaining memory from the
1205 connection's pool for the IO buffers; the connection
1206 certainly won't need it anymore as we've upgraded
1207 to another protocol. */
1208 buf = MHD_pool_allocate (pool,
1209 avail,
1210 false);
1211 }
1212 /* use half the buffer for inbound, half for outbound */
1213 urh->in_buffer_size = avail / 2;
1214 urh->out_buffer_size = avail - urh->in_buffer_size;
1215 urh->in_buffer = buf;
1216 urh->out_buffer = &buf[urh->in_buffer_size];
1217#ifdef EPOLL_SUPPORT
1218 /* Launch IO processing by the event loop */
1219 if (0 != (daemon->options & MHD_USE_EPOLL))
1220 {
1221 /* We're running with epoll(), need to add the sockets
1222 to the event set of the daemon's `epoll_upgrade_fd` */
1223 struct epoll_event event;
1224
1225 mhd_assert (-1 != daemon->epoll_upgrade_fd);
1226 /* First, add network socket */
1227 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1228 event.data.ptr = &urh->app;
1229 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1230 EPOLL_CTL_ADD,
1231 connection->socket_fd,
1232 &event))
1233 {
1234#ifdef HAVE_MESSAGES
1235 MHD_DLOG (daemon,
1236 _ ("Call to epoll_ctl failed: %s\n"),
1238#endif
1239 MHD_socket_close_chk_ (sv[0]);
1240 MHD_socket_close_chk_ (sv[1]);
1241 free (urh);
1242 return MHD_NO;
1243 }
1244
1245 /* Second, add our end of the UNIX socketpair() */
1246 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1247 event.data.ptr = &urh->mhd;
1248 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1249 EPOLL_CTL_ADD,
1250 urh->mhd.socket,
1251 &event))
1252 {
1253 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
1254 event.data.ptr = &urh->app;
1255 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1256 EPOLL_CTL_DEL,
1257 connection->socket_fd,
1258 &event))
1259 MHD_PANIC (_ ("Error cleaning up while handling epoll error.\n"));
1260#ifdef HAVE_MESSAGES
1261 MHD_DLOG (daemon,
1262 _ ("Call to epoll_ctl failed: %s\n"),
1264#endif
1265 MHD_socket_close_chk_ (sv[0]);
1266 MHD_socket_close_chk_ (sv[1]);
1267 free (urh);
1268 return MHD_NO;
1269 }
1270 EDLL_insert (daemon->eready_urh_head,
1271 daemon->eready_urh_tail,
1272 urh);
1273 urh->in_eready_list = true;
1274 }
1275#endif /* EPOLL_SUPPORT */
1276 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
1277 {
1278 /* This takes care of further processing for most event loops:
1279 simply add to DLL for bi-direcitonal processing */
1280 DLL_insert (daemon->urh_head,
1281 daemon->urh_tail,
1282 urh);
1283 }
1284 /* In thread-per-connection mode, thread will switch to forwarding once
1285 * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
1286 */
1287 }
1288 else
1289 {
1290 urh->app.socket = MHD_INVALID_SOCKET;
1291 urh->mhd.socket = MHD_INVALID_SOCKET;
1292 /* Non-TLS connection do not hold any additional resources. */
1293 urh->clean_ready = true;
1294 }
1295#else /* ! HTTPS_SUPPORT */
1296 urh->clean_ready = true;
1297#endif /* ! HTTPS_SUPPORT */
1298 connection->urh = urh;
1299 /* As far as MHD's event loops are concerned, this connection is
1300 suspended; it will be resumed once application is done by the
1301 #MHD_upgrade_action() function */
1302 internal_suspend_connection_ (connection);
1303
1304 /* hand over socket to application */
1305 response->upgrade_handler (response->upgrade_handler_cls,
1306 connection,
1307 connection->client_context,
1308 connection->read_buffer,
1309 rbo,
1310#ifdef HTTPS_SUPPORT
1311 (0 == (daemon->options & MHD_USE_TLS) ) ?
1312 connection->socket_fd : urh->app.socket,
1313#else /* ! HTTPS_SUPPORT */
1314 connection->socket_fd,
1315#endif /* ! HTTPS_SUPPORT */
1316 urh);
1317 return MHD_YES;
1318}
1319
1320
1352 void *upgrade_handler_cls)
1353{
1354 struct MHD_Response *response;
1355
1356 if (NULL == upgrade_handler)
1357 return NULL; /* invalid request */
1358 response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1359 if (NULL == response)
1360 return NULL;
1361#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1362 if (! MHD_mutex_init_ (&response->mutex))
1363 {
1364 free (response);
1365 return NULL;
1366 }
1367#endif
1368 response->upgrade_handler = upgrade_handler;
1369 response->upgrade_handler_cls = upgrade_handler_cls;
1370 response->total_size = MHD_SIZE_UNKNOWN;
1371 response->reference_count = 1;
1372 if (MHD_NO ==
1373 MHD_add_response_header (response,
1375 "Upgrade"))
1376 {
1377 MHD_destroy_response (response);
1378 return NULL;
1379 }
1380 return response;
1381}
1382
1383
1384#endif /* UPGRADE_SUPPORT */
1385
1386
1396void
1398{
1399 struct MHD_HTTP_Header *pos;
1400
1401 if (NULL == response)
1402 return;
1403#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1404 MHD_mutex_lock_chk_ (&response->mutex);
1405#endif
1406 if (0 != --(response->reference_count))
1407 {
1408#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1409 MHD_mutex_unlock_chk_ (&response->mutex);
1410#endif
1411 return;
1412 }
1413#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1414 MHD_mutex_unlock_chk_ (&response->mutex);
1415 MHD_mutex_destroy_chk_ (&response->mutex);
1416#endif
1417 if (NULL != response->crfc)
1418 response->crfc (response->crc_cls);
1419
1420 if (NULL != response->data_iov)
1421 {
1422 free (response->data_iov);
1423 }
1424
1425 while (NULL != response->first_header)
1426 {
1427 pos = response->first_header;
1428 response->first_header = pos->next;
1429 free (pos->header);
1430 free (pos->value);
1431 free (pos);
1432 }
1433 free (response);
1434}
1435
1436
1442void
1444{
1445#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1446 MHD_mutex_lock_chk_ (&response->mutex);
1447#endif
1448 (response->reference_count)++;
1449#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1450 MHD_mutex_unlock_chk_ (&response->mutex);
1451#endif
1452}
1453
1454
1455/* end of response.c */
Methods for managing connections.
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:3038
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:572
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:566
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:628
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:630
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2298
_MHD_EXTERN enum MHD_Result MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:199
struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:750
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:832
_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:864
_MHD_EXTERN enum MHD_Result MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:178
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:703
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_pipe(int fd)
Definition: response.c:675
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:810
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:253
_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:376
MHD_ResponseMemoryMode
Definition: microhttpd.h:3136
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:2392
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:631
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1397
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:134
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:285
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:726
@ MHD_RESPMEM_MUST_FREE
Definition: microhttpd.h:3152
@ MHD_RESPMEM_MUST_COPY
Definition: microhttpd.h:3161
@ 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 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.
internal shared structures
size_t MHD_iov_size_
Definition: internal.h:376
#define MHD_IOV_ELMN_MAX_SIZE
Definition: internal.h:375
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
Header for platform missing functions.
Header for platform-independent inter-thread communication.
limits values definitions
#define SSIZE_MAX
Definition: mhd_limits.h:111
#define MHD_mutex_init_(ignore)
Definition: mhd_locks.h:189
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:408
Header for string manipulating helpers.
static void free_callback(void *cls)
Definition: response.c:576
#define MHD_FILE_READ_BLOCK_SIZE
Definition: response.c:68
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:324
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:453
enum MHD_Result MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:417
static ssize_t pipe_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:541
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1443
int MHD_socket
Definition: microhttpd.h:193
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:3429
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:165
MHD_Result
Definition: microhttpd.h:139
@ MHD_YES
Definition: microhttpd.h:148
@ MHD_NO
Definition: microhttpd.h:143
int off_t offset
Definition: microhttpd.h:3270
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:172
void int int must_copy
Definition: microhttpd.h:3127
#define MHD_create_response_from_fd_at_offset(size, fd, offset)
Definition: microhttpd.h:3275
_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:3126
int fd
Definition: microhttpd.h:3269
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:3173
void * data
Definition: microhttpd.h:3125
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:194
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:2376
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:173
MHD_UpgradeAction
Definition: microhttpd.h:3333
@ MHD_UPGRADE_ACTION_CORK_ON
Definition: microhttpd.h:3345
@ MHD_UPGRADE_ACTION_CLOSE
Definition: microhttpd.h:3340
@ MHD_UPGRADE_ACTION_CORK_OFF
Definition: microhttpd.h:3350
MHD_ValueKind
Definition: microhttpd.h:1800
@ MHD_FOOTER_KIND
Definition: microhttpd.h:1841
@ MHD_HEADER_KIND
Definition: microhttpd.h:1815
@ MHD_USE_EPOLL
Definition: microhttpd.h:1193
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1087
@ MHD_USE_POLL
Definition: microhttpd.h:1143
@ MHD_USE_TLS
Definition: microhttpd.h:1072
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1302
@ MHD_USE_INTERNAL_POLLING_THREAD
Definition: microhttpd.h:1098
MHD_ResponseOptions
Definition: microhttpd.h:3062
@ MHD_RO_END
Definition: microhttpd.h:3066
MHD_ResponseFlags
Definition: microhttpd.h:3024
@ MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:3052
_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:905
MHD_thread_handle_ID_ pid
Definition: internal.h:723
void * client_context
Definition: internal.h:814
enum MHD_CONNECTION_STATE state
Definition: internal.h:1064
char * read_buffer
Definition: internal.h:854
struct MHD_Daemon * daemon
Definition: internal.h:675
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1411
size_t value_size
Definition: internal.h:338
char * header
Definition: internal.h:347
enum MHD_ValueKind kind
Definition: internal.h:358
size_t header_size
Definition: internal.h:328
struct MHD_HTTP_Header * next
Definition: internal.h:342
char * value
Definition: internal.h:352
const void * iov_base
Definition: microhttpd.h:2002
size_t iov_len
Definition: microhttpd.h:2007
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:513
MHD_ContentReaderCallback crc
Definition: internal.h:1600
bool is_pipe
Definition: internal.h:508
struct MHD_Action action
Definition: internal.h:1575
unsigned int data_iovcnt
Definition: internal.h:518
size_t data_size
Definition: internal.h:1659
enum MHD_ResponseFlags flags
Definition: internal.h:503
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