GNU libmicrohttpd 0.9.71
response.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007, 2009, 2010, 2016, 2017 Daniel Pittman and Christian Grothoff
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*/
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_compat.h"
46
47
48#if defined(MHD_W32_MUTEX_)
49#ifndef WIN32_LEAN_AND_MEAN
50#define WIN32_LEAN_AND_MEAN 1
51#endif /* !WIN32_LEAN_AND_MEAN */
52#include <windows.h>
53#endif /* MHD_W32_MUTEX_ */
54#if defined(_WIN32)
55#include <io.h> /* for lseek(), read() */
56#endif /* _WIN32 */
57
58
63#ifndef MHD_FILE_READ_BLOCK_SIZE
64#ifdef _WIN32
65#define MHD_FILE_READ_BLOCK_SIZE 16384 /* 16k */
66#else /* _WIN32 */
67#define MHD_FILE_READ_BLOCK_SIZE 4096 /* 4k */
68#endif /* _WIN32 */
69#endif /* !MHD_FD_BLOCK_SIZE */
70
71
81static enum MHD_Result
83 enum MHD_ValueKind kind,
84 const char *header,
85 const char *content)
86{
87 struct MHD_HTTP_Header *hdr;
88
89 if ( (NULL == response) ||
90 (NULL == header) ||
91 (NULL == content) ||
92 (0 == header[0]) ||
93 (0 == content[0]) ||
94 (NULL != strchr (header, '\t')) ||
95 (NULL != strchr (header, '\r')) ||
96 (NULL != strchr (header, '\n')) ||
97 (NULL != strchr (content, '\t')) ||
98 (NULL != strchr (content, '\r')) ||
99 (NULL != strchr (content, '\n')) )
100 return MHD_NO;
101 if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
102 return MHD_NO;
103 if (NULL == (hdr->header = strdup (header)))
104 {
105 free (hdr);
106 return MHD_NO;
107 }
108 hdr->header_size = strlen (header);
109 if (NULL == (hdr->value = strdup (content)))
110 {
111 free (hdr->header);
112 free (hdr);
113 return MHD_NO;
114 }
115 hdr->value_size = strlen (content);
116 hdr->kind = kind;
117 hdr->next = response->first_header;
118 response->first_header = hdr;
119 return MHD_YES;
120}
121
122
132enum MHD_Result
134 const char *header,
135 const char *content)
136{
139 (! MHD_str_equal_caseless_ (content,
140 "identity")) &&
141 (! MHD_str_equal_caseless_ (content,
142 "chunked")) )
143 {
144 /* Setting transfer encodings other than "identity" or
145 "chunked" is not allowed. Note that MHD will set the
146 correct transfer encoding if required automatically. */
147 /* NOTE: for compressed bodies, use the "Content-encoding" header */
148 return MHD_NO;
149 }
151 & response->flags)) &&
154 {
155 /* MHD will set Content-length if allowed and possible,
156 reject attempt by application */
157 return MHD_NO;
158 }
159
160 return add_response_entry (response,
162 header,
163 content);
164}
165
166
176enum MHD_Result
178 const char *footer,
179 const char *content)
180{
181 return add_response_entry (response,
183 footer,
184 content);
185}
186
187
197enum MHD_Result
199 const char *header,
200 const char *content)
201{
202 struct MHD_HTTP_Header *pos;
203 struct MHD_HTTP_Header *prev;
204 size_t header_len;
205 size_t content_len;
206
207 if ( (NULL == header) ||
208 (NULL == content) )
209 return MHD_NO;
210 header_len = strlen (header);
211 content_len = strlen (content);
212 prev = NULL;
213 pos = response->first_header;
214 while (NULL != pos)
215 {
216 if ((header_len == pos->header_size) &&
217 (content_len == pos->value_size) &&
218 (0 == memcmp (header,
219 pos->header,
220 header_len)) &&
221 (0 == memcmp (content,
222 pos->value,
223 content_len)))
224 {
225 free (pos->header);
226 free (pos->value);
227 if (NULL == prev)
228 response->first_header = pos->next;
229 else
230 prev->next = pos->next;
231 free (pos);
232 return MHD_YES;
233 }
234 prev = pos;
235 pos = pos->next;
236 }
237 return MHD_NO;
238}
239
240
251int
253 MHD_KeyValueIterator iterator,
254 void *iterator_cls)
255{
256 int numHeaders = 0;
257 struct MHD_HTTP_Header *pos;
258
259 for (pos = response->first_header;
260 NULL != pos;
261 pos = pos->next)
262 {
263 numHeaders++;
264 if ((NULL != iterator) &&
265 (MHD_YES != iterator (iterator_cls,
266 pos->kind,
267 pos->header,
268 pos->value)))
269 break;
270 }
271 return numHeaders;
272}
273
274
283const char *
285 const char *key)
286{
287 struct MHD_HTTP_Header *pos;
288 size_t key_size;
289
290 if (NULL == key)
291 return NULL;
292
293 key_size = strlen (key);
294 for (pos = response->first_header;
295 NULL != pos;
296 pos = pos->next)
297 {
298 if ((pos->header_size == key_size) &&
300 return pos->value;
301 }
302 return NULL;
303}
304
305
322bool
324 const char *key,
325 size_t key_len,
326 const char *token,
327 size_t token_len)
328{
329 struct MHD_HTTP_Header *pos;
330
331 if ( (NULL == key) ||
332 ('\0' == key[0]) ||
333 (NULL == token) ||
334 ('\0' == token[0]) )
335 return false;
336
337 /* Token must not contain binary zero! */
338 mhd_assert (strlen (token) == token_len);
339
340 for (pos = response->first_header;
341 NULL != pos;
342 pos = pos->next)
343 {
344 if ( (pos->kind == MHD_HEADER_KIND) &&
345 (key_len == pos->header_size) &&
347 key,
348 key_len) &&
350 token,
351 token_len) )
352 return true;
353 }
354 return false;
355}
356
357
374struct MHD_Response *
376 size_t block_size,
378 void *crc_cls,
380{
381 struct MHD_Response *response;
382
383 if ((NULL == crc) || (0 == block_size))
384 return NULL;
385 if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response)
386 + block_size)))
387 return NULL;
388 response->fd = -1;
389 response->data = (void *) &response[1];
390 response->data_buffer_size = block_size;
391#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
392 if (! MHD_mutex_init_ (&response->mutex))
393 {
394 free (response);
395 return NULL;
396 }
397#endif
398 response->crc = crc;
399 response->crfc = crfc;
400 response->crc_cls = crc_cls;
401 response->reference_count = 1;
402 response->total_size = size;
403 return response;
404}
405
406
415enum MHD_Result
418 ...)
419{
420 va_list ap;
421 enum MHD_Result ret;
422 enum MHD_ResponseOptions ro;
423
424 ret = MHD_YES;
425 response->flags = flags;
426 va_start (ap, flags);
427 while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
428 {
429 switch (ro)
430 {
431 default:
432 ret = MHD_NO;
433 break;
434 }
435 }
436 va_end (ap);
437 return ret;
438}
439
440
451static ssize_t
452file_reader (void *cls,
453 uint64_t pos,
454 char *buf,
455 size_t max)
456{
457 struct MHD_Response *response = cls;
458#if ! defined(_WIN32) || defined(__CYGWIN__)
459 ssize_t n;
460#else /* _WIN32 && !__CYGWIN__ */
461 const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
462#endif /* _WIN32 && !__CYGWIN__ */
463 const int64_t offset64 = (int64_t) (pos + response->fd_off);
464
465 if (offset64 < 0)
466 return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
467
468#if ! defined(_WIN32) || defined(__CYGWIN__)
469 if (max > SSIZE_MAX)
470 max = SSIZE_MAX; /* Clamp to maximum return value. */
471
472#if defined(HAVE_PREAD64)
473 n = pread64 (response->fd, buf, max, offset64);
474#elif defined(HAVE_PREAD)
475 if ( (sizeof(off_t) < sizeof (uint64_t)) &&
476 (offset64 > (uint64_t) INT32_MAX) )
477 return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
478
479 n = pread (response->fd, buf, max, (off_t) offset64);
480#else /* ! HAVE_PREAD */
481#if defined(HAVE_LSEEK64)
482 if (lseek64 (response->fd,
483 offset64,
484 SEEK_SET) != offset64)
485 return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
486#else /* ! HAVE_LSEEK64 */
487 if ( (sizeof(off_t) < sizeof (uint64_t)) &&
488 (offset64 > (uint64_t) INT32_MAX) )
489 return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
490
491 if (lseek (response->fd,
492 (off_t) offset64,
493 SEEK_SET) != (off_t) offset64)
494 return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
495#endif /* ! HAVE_LSEEK64 */
496 n = read (response->fd,
497 buf,
498 max);
499
500#endif /* ! HAVE_PREAD */
501 if (0 == n)
503 if (n < 0)
505 return n;
506#else /* _WIN32 && !__CYGWIN__ */
507 if (INVALID_HANDLE_VALUE == fh)
508 return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
509 else
510 {
511 OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
512 ULARGE_INTEGER pos_uli;
513 DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
514 DWORD resRead;
515
516 pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
517 f_ol.Offset = pos_uli.LowPart;
518 f_ol.OffsetHigh = pos_uli.HighPart;
519 if (! ReadFile (fh, (void*) buf, toRead, &resRead, &f_ol))
520 return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
521 if (0 == resRead)
523 return (ssize_t) resRead;
524 }
525#endif /* _WIN32 && !__CYGWIN__ */
526}
527
528
535static void
536free_callback (void *cls)
537{
538 struct MHD_Response *response = cls;
539
540 (void) close (response->fd);
541 response->fd = -1;
542}
543
544
545#undef MHD_create_response_from_fd_at_offset
546
563struct MHD_Response *
565 int fd,
566 off_t offset)
567{
569 fd,
570 offset);
571}
572
573
592 int fd,
593 uint64_t offset)
594{
595 struct MHD_Response *response;
596
597#if ! defined(HAVE___LSEEKI64) && ! defined(HAVE_LSEEK64)
598 if ( (sizeof(uint64_t) > sizeof(off_t)) &&
599 ( (size > (uint64_t) INT32_MAX) ||
600 (offset > (uint64_t) INT32_MAX) ||
601 ((size + offset) >= (uint64_t) INT32_MAX) ) )
602 return NULL;
603#endif
604 if ( ((int64_t) size < 0) ||
605 ((int64_t) offset < 0) ||
606 ((int64_t) (size + offset) < 0) )
607 return NULL;
608
609 response = MHD_create_response_from_callback (size,
612 NULL,
614 if (NULL == response)
615 return NULL;
616 response->fd = fd;
617 response->fd_off = offset;
618 response->crc_cls = response;
619 return response;
620}
621
622
632struct MHD_Response *
634 int fd)
635{
637 fd,
638 0);
639}
640
641
657 int fd)
658{
660 fd,
661 0);
662}
663
664
679struct MHD_Response *
681 void *data,
682 int must_free,
683 int must_copy)
684{
685 struct MHD_Response *response;
686 void *tmp;
687
688 if ((NULL == data) && (size > 0))
689 return NULL;
690 if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
691 return NULL;
692 response->fd = -1;
693#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
694 if (! MHD_mutex_init_ (&response->mutex))
695 {
696 free (response);
697 return NULL;
698 }
699#endif
700 if ((must_copy) && (size > 0))
701 {
702 if (NULL == (tmp = malloc (size)))
703 {
704#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
705 MHD_mutex_destroy_chk_ (&response->mutex);
706#endif
707 free (response);
708 return NULL;
709 }
710 memcpy (tmp, data, size);
712 data = tmp;
713 }
714 if (must_free)
715 {
716 response->crfc = &free;
717 response->crc_cls = data;
718 }
719 response->reference_count = 1;
720 response->total_size = size;
721 response->data = data;
722 response->data_size = size;
723 return response;
724}
725
726
737struct MHD_Response *
739 void *buffer,
740 enum MHD_ResponseMemoryMode mode)
741{
743 buffer,
744 mode == MHD_RESPMEM_MUST_FREE,
745 mode == MHD_RESPMEM_MUST_COPY);
746}
747
748
761 void *buffer,
763 crfc)
764{
765 struct MHD_Response *r;
766
768 buffer,
769 MHD_YES,
770 MHD_NO);
771 if (NULL == r)
772 return r;
773 r->crfc = crfc;
774 return r;
775}
776
777
778#ifdef UPGRADE_SUPPORT
792MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
794 ...)
795{
796 struct MHD_Connection *connection;
797 struct MHD_Daemon *daemon;
798
799 if (NULL == urh)
800 return MHD_NO;
801 connection = urh->connection;
802
803 /* Precaution checks on external data. */
804 if (NULL == connection)
805 return MHD_NO;
806 daemon = connection->daemon;
807 if (NULL == daemon)
808 return MHD_NO;
809
810 switch (action)
811 {
813 if (urh->was_closed)
814 return MHD_NO; /* Already closed. */
815
816 /* transition to special 'closed' state for start of cleanup */
817#ifdef HTTPS_SUPPORT
818 if (0 != (daemon->options & MHD_USE_TLS) )
819 {
820 /* signal that app is done by shutdown() of 'app' socket */
821 /* Application will not use anyway this socket after this command. */
822 shutdown (urh->app.socket,
823 SHUT_RDWR);
824 }
825#endif /* HTTPS_SUPPORT */
826 mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
827 urh->was_closed = true;
828 /* As soon as connection will be marked with BOTH
829 * 'urh->was_closed' AND 'urh->clean_ready', it will
830 * be moved to cleanup list by MHD_resume_connection(). */
831 MHD_resume_connection (connection);
832 return MHD_YES;
834 if (connection->sk_cork_on)
835 return MHD_YES;
836#ifdef HTTPS_SUPPORT
837 if (0 != (daemon->options & MHD_USE_TLS) )
838 {
839 gnutls_record_cork (connection->tls_session);
840 connection->sk_cork_on = true;
841 return MHD_YES;
842 }
843 else
844#endif
845 {
846 if (0 ==
847 MHD_socket_cork_ (connection->socket_fd,
848 true))
849 {
850 connection->sk_cork_on = true;
851 return MHD_YES;
852 }
853 return MHD_NO;
854 }
856 if (! connection->sk_cork_on)
857 return MHD_YES;
858#ifdef HTTPS_SUPPORT
859 if (0 != (daemon->options & MHD_USE_TLS) )
860 {
861 gnutls_record_uncork (connection->tls_session, 0);
862 connection->sk_cork_on = false;
863 return MHD_YES;
864 }
865 else
866#endif
867 {
868 if (0 ==
869 MHD_socket_cork_ (connection->socket_fd,
870 false))
871 {
872 connection->sk_cork_on = false;
873 return MHD_YES;
874 }
875 return MHD_NO;
876 }
877 default:
878 /* we don't understand this one */
879 return MHD_NO;
880 }
881}
882
883
897enum MHD_Result
899 struct MHD_Connection *connection)
900{
901 struct MHD_Daemon *daemon = connection->daemon;
902 struct MHD_UpgradeResponseHandle *urh;
903 size_t rbo;
904
905 if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
906 return MHD_NO;
907
908 if (NULL ==
909 MHD_get_response_header (response,
911 {
912#ifdef HAVE_MESSAGES
913 MHD_DLOG (daemon,
914 _ (
915 "Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
916#endif
917 return MHD_NO;
918 }
919
920 urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
921 if (NULL == urh)
922 return MHD_NO;
923 urh->connection = connection;
924 rbo = connection->read_buffer_offset;
925 connection->read_buffer_offset = 0;
926#ifdef HTTPS_SUPPORT
927 if (0 != (daemon->options & MHD_USE_TLS) )
928 {
929 struct MemoryPool *pool;
930 size_t avail;
931 char *buf;
932 MHD_socket sv[2];
933#if defined(MHD_socket_nosignal_) || ! defined(MHD_socket_pair_nblk_)
934 int res1;
935 int res2;
936#endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
937
938#ifdef MHD_socket_pair_nblk_
939 if (! MHD_socket_pair_nblk_ (sv))
940 {
941 free (urh);
942 return MHD_NO;
943 }
944#else /* !MHD_socket_pair_nblk_ */
945 if (! MHD_socket_pair_ (sv))
946 {
947 free (urh);
948 return MHD_NO;
949 }
950 res1 = MHD_socket_nonblocking_ (sv[0]);
951 res2 = MHD_socket_nonblocking_ (sv[1]);
952 if ( (! res1) || (! res2) )
953 {
954#ifdef HAVE_MESSAGES
955 MHD_DLOG (daemon,
956 _ ("Failed to make loopback sockets non-blocking.\n"));
957#endif
958 if (! res2)
959 {
960 /* Socketpair cannot be used. */
961 MHD_socket_close_chk_ (sv[0]);
962 MHD_socket_close_chk_ (sv[1]);
963 free (urh);
964 return MHD_NO;
965 }
966 }
967#endif /* !MHD_socket_pair_nblk_ */
968#ifdef MHD_socket_nosignal_
969 res1 = MHD_socket_nosignal_ (sv[0]);
970 res2 = MHD_socket_nosignal_ (sv[1]);
971 if ( (! res1) || (! res2) )
972 {
973#ifdef HAVE_MESSAGES
974 MHD_DLOG (daemon,
975 _ ("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
976#endif
977#ifndef MSG_NOSIGNAL
978 if (! res2)
979 {
980 /* Socketpair cannot be used. */
981 MHD_socket_close_chk_ (sv[0]);
982 MHD_socket_close_chk_ (sv[1]);
983 free (urh);
984 return MHD_NO;
985 }
986#endif /* ! MSG_NOSIGNAL */
987 }
988#endif /* MHD_socket_nosignal_ */
989 if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
990 NULL)) &&
991 (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
992 {
993#ifdef HAVE_MESSAGES
994 MHD_DLOG (daemon,
995 _ ("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
996 (int) sv[1],
997 (int) FD_SETSIZE);
998#endif
999 MHD_socket_close_chk_ (sv[0]);
1000 MHD_socket_close_chk_ (sv[1]);
1001 free (urh);
1002 return MHD_NO;
1003 }
1004 urh->app.socket = sv[0];
1005 urh->app.urh = urh;
1006 urh->app.celi = MHD_EPOLL_STATE_UNREADY;
1007 urh->mhd.socket = sv[1];
1008 urh->mhd.urh = urh;
1009 urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
1010 pool = connection->pool;
1011 avail = MHD_pool_get_free (pool);
1012 if (avail < RESERVE_EBUF_SIZE)
1013 {
1014 /* connection's pool is totally at the limit,
1015 use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
1016 avail = RESERVE_EBUF_SIZE;
1017 buf = urh->e_buf;
1018 }
1019 else
1020 {
1021 /* Normal case: grab all remaining memory from the
1022 connection's pool for the IO buffers; the connection
1023 certainly won't need it anymore as we've upgraded
1024 to another protocol. */
1025 buf = MHD_pool_allocate (pool,
1026 avail,
1027 false);
1028 }
1029 /* use half the buffer for inbound, half for outbound */
1030 urh->in_buffer_size = avail / 2;
1031 urh->out_buffer_size = avail - urh->in_buffer_size;
1032 urh->in_buffer = buf;
1033 urh->out_buffer = &buf[urh->in_buffer_size];
1034#ifdef EPOLL_SUPPORT
1035 /* Launch IO processing by the event loop */
1036 if (0 != (daemon->options & MHD_USE_EPOLL))
1037 {
1038 /* We're running with epoll(), need to add the sockets
1039 to the event set of the daemon's `epoll_upgrade_fd` */
1040 struct epoll_event event;
1041
1042 mhd_assert (-1 != daemon->epoll_upgrade_fd);
1043 /* First, add network socket */
1044 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1045 event.data.ptr = &urh->app;
1046 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1047 EPOLL_CTL_ADD,
1048 connection->socket_fd,
1049 &event))
1050 {
1051#ifdef HAVE_MESSAGES
1052 MHD_DLOG (daemon,
1053 _ ("Call to epoll_ctl failed: %s\n"),
1055#endif
1056 MHD_socket_close_chk_ (sv[0]);
1057 MHD_socket_close_chk_ (sv[1]);
1058 free (urh);
1059 return MHD_NO;
1060 }
1061
1062 /* Second, add our end of the UNIX socketpair() */
1063 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1064 event.data.ptr = &urh->mhd;
1065 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1066 EPOLL_CTL_ADD,
1067 urh->mhd.socket,
1068 &event))
1069 {
1070 event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
1071 event.data.ptr = &urh->app;
1072 if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1073 EPOLL_CTL_DEL,
1074 connection->socket_fd,
1075 &event))
1076 MHD_PANIC (_ ("Error cleaning up while handling epoll error.\n"));
1077#ifdef HAVE_MESSAGES
1078 MHD_DLOG (daemon,
1079 _ ("Call to epoll_ctl failed: %s\n"),
1081#endif
1082 MHD_socket_close_chk_ (sv[0]);
1083 MHD_socket_close_chk_ (sv[1]);
1084 free (urh);
1085 return MHD_NO;
1086 }
1087 EDLL_insert (daemon->eready_urh_head,
1088 daemon->eready_urh_tail,
1089 urh);
1090 urh->in_eready_list = true;
1091 }
1092#endif /* EPOLL_SUPPORT */
1093 if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
1094 {
1095 /* This takes care of further processing for most event loops:
1096 simply add to DLL for bi-direcitonal processing */
1097 DLL_insert (daemon->urh_head,
1098 daemon->urh_tail,
1099 urh);
1100 }
1101 /* In thread-per-connection mode, thread will switch to forwarding once
1102 * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
1103 */
1104 }
1105 else
1106 {
1107 urh->app.socket = MHD_INVALID_SOCKET;
1108 urh->mhd.socket = MHD_INVALID_SOCKET;
1109 /* Non-TLS connection do not hold any additional resources. */
1110 urh->clean_ready = true;
1111 }
1112#else /* ! HTTPS_SUPPORT */
1113 urh->clean_ready = true;
1114#endif /* ! HTTPS_SUPPORT */
1115 connection->urh = urh;
1116 /* As far as MHD's event loops are concerned, this connection is
1117 suspended; it will be resumed once application is done by the
1118 #MHD_upgrade_action() function */
1119 internal_suspend_connection_ (connection);
1120
1121 /* hand over socket to application */
1122 response->upgrade_handler (response->upgrade_handler_cls,
1123 connection,
1124 connection->client_context,
1125 connection->read_buffer,
1126 rbo,
1127#ifdef HTTPS_SUPPORT
1128 (0 == (daemon->options & MHD_USE_TLS) ) ?
1129 connection->socket_fd : urh->app.socket,
1130#else /* ! HTTPS_SUPPORT */
1131 connection->socket_fd,
1132#endif /* ! HTTPS_SUPPORT */
1133 urh);
1134 return MHD_YES;
1135}
1136
1137
1169 void *upgrade_handler_cls)
1170{
1171 struct MHD_Response *response;
1172
1173 if (NULL == upgrade_handler)
1174 return NULL; /* invalid request */
1175 response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1176 if (NULL == response)
1177 return NULL;
1178#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1179 if (! MHD_mutex_init_ (&response->mutex))
1180 {
1181 free (response);
1182 return NULL;
1183 }
1184#endif
1185 response->upgrade_handler = upgrade_handler;
1186 response->upgrade_handler_cls = upgrade_handler_cls;
1187 response->total_size = MHD_SIZE_UNKNOWN;
1188 response->reference_count = 1;
1189 if (MHD_NO ==
1190 MHD_add_response_header (response,
1192 "Upgrade"))
1193 {
1194 MHD_destroy_response (response);
1195 return NULL;
1196 }
1197 return response;
1198}
1199
1200
1201#endif /* UPGRADE_SUPPORT */
1202
1203
1213void
1215{
1216 struct MHD_HTTP_Header *pos;
1217
1218 if (NULL == response)
1219 return;
1220#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1221 MHD_mutex_lock_chk_ (&response->mutex);
1222#endif
1223 if (0 != --(response->reference_count))
1224 {
1225#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1226 MHD_mutex_unlock_chk_ (&response->mutex);
1227#endif
1228 return;
1229 }
1230#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1231 MHD_mutex_unlock_chk_ (&response->mutex);
1232 MHD_mutex_destroy_chk_ (&response->mutex);
1233#endif
1234 if (NULL != response->crfc)
1235 response->crfc (response->crc_cls);
1236 while (NULL != response->first_header)
1237 {
1238 pos = response->first_header;
1239 response->first_header = pos->next;
1240 free (pos->header);
1241 free (pos->value);
1242 free (pos);
1243 }
1244 free (response);
1245}
1246
1247
1253void
1255{
1256#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1257 MHD_mutex_lock_chk_ (&response->mutex);
1258#endif
1259 (response->reference_count)++;
1260#if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1261 MHD_mutex_unlock_chk_ (&response->mutex);
1262#endif
1263}
1264
1265
1266/* end of response.c */
Methods for managing connections.
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2810
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:574
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:568
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:630
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:632
enum MHD_Result(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2246
_MHD_EXTERN enum MHD_Result MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:198
struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:680
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:760
_MHD_EXTERN enum MHD_Result MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:177
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:633
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:738
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:252
struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:564
_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:375
MHD_ResponseMemoryMode
Definition: microhttpd.h:3049
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:2340
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:591
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1214
_MHD_EXTERN enum MHD_Result MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:133
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:284
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:656
@ MHD_RESPMEM_MUST_FREE
Definition: microhttpd.h:3065
@ MHD_RESPMEM_MUST_COPY
Definition: microhttpd.h:3074
@ 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 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
#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
additional automatic macros for MHD_config.h
#define _(String)
Definition: mhd_options.h:42
#define _MHD_EXTERN
Definition: mhd_options.h:50
internal shared structures
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
int MHD_socket_cork_(MHD_socket sock, bool on)
Definition: mhd_sockets.c:500
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:536
#define MHD_FILE_READ_BLOCK_SIZE
Definition: response.c:67
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:323
static enum MHD_Result add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:82
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:452
enum MHD_Result MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:416
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1254
int MHD_socket
Definition: microhttpd.h:195
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:3304
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:167
MHD_Result
Definition: microhttpd.h:141
@ MHD_YES
Definition: microhttpd.h:150
@ MHD_NO
Definition: microhttpd.h:145
int off_t offset
Definition: microhttpd.h:3167
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:174
void int int must_copy
Definition: microhttpd.h:3040
_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:3039
int fd
Definition: microhttpd.h:3166
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2936
void * data
Definition: microhttpd.h:3038
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:196
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:2324
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:175
MHD_UpgradeAction
Definition: microhttpd.h:3208
@ MHD_UPGRADE_ACTION_CORK_ON
Definition: microhttpd.h:3220
@ MHD_UPGRADE_ACTION_CLOSE
Definition: microhttpd.h:3215
@ MHD_UPGRADE_ACTION_CORK_OFF
Definition: microhttpd.h:3225
MHD_ValueKind
Definition: microhttpd.h:1766
@ MHD_FOOTER_KIND
Definition: microhttpd.h:1807
@ MHD_HEADER_KIND
Definition: microhttpd.h:1781
@ MHD_USE_EPOLL
Definition: microhttpd.h:1181
@ MHD_USE_THREAD_PER_CONNECTION
Definition: microhttpd.h:1075
@ MHD_USE_POLL
Definition: microhttpd.h:1131
@ MHD_USE_TLS
Definition: microhttpd.h:1060
@ MHD_ALLOW_UPGRADE
Definition: microhttpd.h:1290
MHD_ResponseOptions
Definition: microhttpd.h:2975
@ MHD_RO_END
Definition: microhttpd.h:2979
MHD_ResponseFlags
Definition: microhttpd.h:2937
@ MHD_RF_INSANITY_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:2965
_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
bool sk_cork_on
Definition: internal.h:885
struct MemoryPool * pool
Definition: internal.h:685
size_t read_buffer_offset
Definition: internal.h:789
void * client_context
Definition: internal.h:698
enum MHD_CONNECTION_STATE state
Definition: internal.h:924
char * read_buffer
Definition: internal.h:738
struct MHD_Daemon * daemon
Definition: internal.h:675
volatile bool shutdown
Definition: internal.h:1526
enum MHD_FLAG options
Definition: internal.h:1600
size_t value_size
Definition: internal.h:290
char * header
Definition: internal.h:347
enum MHD_ValueKind kind
Definition: internal.h:358
size_t header_size
Definition: internal.h:280
struct MHD_HTTP_Header * next
Definition: internal.h:342
char * value
Definition: internal.h:352
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_ContentReaderCallback crc
Definition: internal.h:1600
struct MHD_Action action
Definition: internal.h:1575
size_t data_size
Definition: internal.h:1659
enum MHD_ResponseFlags flags
Definition: internal.h:401
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