GNU libmicrohttpd  0.9.61
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 
68 static int
69 add_response_entry (struct MHD_Response *response,
70  enum MHD_ValueKind kind,
71  const char *header,
72  const char *content)
73 {
74  struct MHD_HTTP_Header *hdr;
75 
76  if ( (NULL == response) ||
77  (NULL == header) ||
78  (NULL == content) ||
79  (0 == header[0]) ||
80  (0 == content[0]) ||
81  (NULL != strchr (header, '\t')) ||
82  (NULL != strchr (header, '\r')) ||
83  (NULL != strchr (header, '\n')) ||
84  (NULL != strchr (content, '\t')) ||
85  (NULL != strchr (content, '\r')) ||
86  (NULL != strchr (content, '\n')) )
87  return MHD_NO;
88  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
89  return MHD_NO;
90  if (NULL == (hdr->header = strdup (header)))
91  {
92  free (hdr);
93  return MHD_NO;
94  }
95  if (NULL == (hdr->value = strdup (content)))
96  {
97  free (hdr->header);
98  free (hdr);
99  return MHD_NO;
100  }
101  hdr->kind = kind;
102  hdr->next = response->first_header;
103  response->first_header = hdr;
104  return MHD_YES;
105 }
106 
107 
117 int
119  const char *header,
120  const char *content)
121 {
124  (! MHD_str_equal_caseless_ (content,
125  "identity")) &&
126  (! MHD_str_equal_caseless_ (content,
127  "chunked")) )
128  {
129  /* Setting transfer encodings other than "identity" or
130  "chunked" is not allowed. Note that MHD will set the
131  correct transfer encoding if required automatically. */
132  /* NOTE: for compressed bodies, use the "Content-encoding" header */
133  return MHD_NO;
134  }
137  {
138  /* MHD will set Content-length if allowed and possible,
139  reject attempt by application */
140  return MHD_NO;
141  }
142 
143  return add_response_entry (response,
145  header,
146  content);
147 }
148 
149 
159 int
161  const char *footer,
162  const char *content)
163 {
164  return add_response_entry (response,
166  footer,
167  content);
168 }
169 
170 
180 int
182  const char *header,
183  const char *content)
184 {
185  struct MHD_HTTP_Header *pos;
186  struct MHD_HTTP_Header *prev;
187 
188  if ( (NULL == header) ||
189  (NULL == content) )
190  return MHD_NO;
191  prev = NULL;
192  pos = response->first_header;
193  while (NULL != pos)
194  {
195  if ((0 == strcmp (header,
196  pos->header)) &&
197  (0 == strcmp (content,
198  pos->value)))
199  {
200  free (pos->header);
201  free (pos->value);
202  if (NULL == prev)
203  response->first_header = pos->next;
204  else
205  prev->next = pos->next;
206  free (pos);
207  return MHD_YES;
208  }
209  prev = pos;
210  pos = pos->next;
211  }
212  return MHD_NO;
213 }
214 
215 
226 int
228  MHD_KeyValueIterator iterator,
229  void *iterator_cls)
230 {
231  int numHeaders = 0;
232  struct MHD_HTTP_Header *pos;
233 
234  for (pos = response->first_header;
235  NULL != pos;
236  pos = pos->next)
237  {
238  numHeaders++;
239  if ((NULL != iterator) &&
240  (MHD_YES != iterator (iterator_cls,
241  pos->kind,
242  pos->header,
243  pos->value)))
244  break;
245  }
246  return numHeaders;
247 }
248 
249 
258 const char *
260  const char *key)
261 {
262  struct MHD_HTTP_Header *pos;
263 
264  if (NULL == key)
265  return NULL;
266  for (pos = response->first_header;
267  NULL != pos;
268  pos = pos->next)
269  {
270  if (MHD_str_equal_caseless_ (pos->header, key))
271  return pos->value;
272  }
273  return NULL;
274 }
275 
276 
291 bool
293  const char *key,
294  const char *token,
295  size_t token_len)
296 {
297  struct MHD_HTTP_Header *pos;
298 
299  if ( (NULL == key) ||
300  ('\0' == key[0]) ||
301  (NULL == token) ||
302  ('\0' == token[0]) )
303  return false;
304 
305  for (pos = response->first_header;
306  NULL != pos;
307  pos = pos->next)
308  {
309  if ( (pos->kind == MHD_HEADER_KIND) &&
311  key) &&
313  token,
314  token_len) )
315  return true;
316  }
317  return false;
318 }
319 
320 
337 struct MHD_Response *
339  size_t block_size,
341  void *crc_cls,
343 {
344  struct MHD_Response *response;
345 
346  if ((NULL == crc) || (0 == block_size))
347  return NULL;
348  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response) + block_size)))
349  return NULL;
350  response->fd = -1;
351  response->data = (void *) &response[1];
352  response->data_buffer_size = block_size;
353  if (! MHD_mutex_init_ (&response->mutex))
354  {
355  free (response);
356  return NULL;
357  }
358  response->crc = crc;
359  response->crfc = crfc;
360  response->crc_cls = crc_cls;
361  response->reference_count = 1;
362  response->total_size = size;
363  return response;
364 }
365 
366 
375 int
378  ...)
379 {
380  va_list ap;
381  int ret;
382  enum MHD_ResponseOptions ro;
383 
384  ret = MHD_YES;
385  response->flags = flags;
386  va_start (ap, flags);
387  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
388  {
389  switch (ro)
390  {
391  default:
392  ret = MHD_NO;
393  break;
394  }
395  }
396  va_end (ap);
397  return ret;
398 }
399 
400 
411 static ssize_t
412 file_reader (void *cls,
413  uint64_t pos,
414  char *buf,
415  size_t max)
416 {
417  struct MHD_Response *response = cls;
418 #if !defined(_WIN32) || defined(__CYGWIN__)
419  ssize_t n;
420 #else /* _WIN32 && !__CYGWIN__ */
421  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
422 #endif /* _WIN32 && !__CYGWIN__ */
423  const int64_t offset64 = (int64_t)(pos + response->fd_off);
424 
425  if (offset64 < 0)
426  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
427 
428 #if !defined(_WIN32) || defined(__CYGWIN__)
429  if (max > SSIZE_MAX)
430  max = SSIZE_MAX; /* Clamp to maximum return value. */
431 
432 #if defined(HAVE_PREAD64)
433  n = pread64(response->fd, buf, max, offset64);
434 #elif defined(HAVE_PREAD)
435  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
436  (offset64 > (uint64_t)INT32_MAX) )
437  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
438 
439  n = pread(response->fd, buf, max, (off_t) offset64);
440 #else /* ! HAVE_PREAD */
441 #if defined(HAVE_LSEEK64)
442  if (lseek64 (response->fd,
443  offset64,
444  SEEK_SET) != offset64)
445  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
446 #else /* ! HAVE_LSEEK64 */
447  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
448  (offset64 > (uint64_t)INT32_MAX) )
449  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
450 
451  if (lseek (response->fd,
452  (off_t) offset64,
453  SEEK_SET) != (off_t) offset64)
454  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
455 #endif /* ! HAVE_LSEEK64 */
456  n = read (response->fd,
457  buf,
458  max);
459 
460 #endif /* ! HAVE_PREAD */
461  if (0 == n)
463  if (n < 0)
465  return n;
466 #else /* _WIN32 && !__CYGWIN__ */
467  if (INVALID_HANDLE_VALUE == fh)
468  return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
469  else
470  {
471  OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
472  ULARGE_INTEGER pos_uli;
473  DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
474  DWORD resRead;
475 
476  pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
477  f_ol.Offset = pos_uli.LowPart;
478  f_ol.OffsetHigh = pos_uli.HighPart;
479  if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
480  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
481  if (0 == resRead)
483  return (ssize_t) resRead;
484  }
485 #endif /* _WIN32 && !__CYGWIN__ */
486 }
487 
488 
495 static void
496 free_callback (void *cls)
497 {
498  struct MHD_Response *response = cls;
499 
500  (void) close (response->fd);
501  response->fd = -1;
502 }
503 
504 #undef MHD_create_response_from_fd_at_offset
505 
522 struct MHD_Response *
524  int fd,
525  off_t offset)
526 {
528  fd,
529  offset);
530 }
531 
532 
549 _MHD_EXTERN struct MHD_Response *
551  int fd,
552  uint64_t offset)
553 {
554  struct MHD_Response *response;
555 
556 #if !defined(HAVE___LSEEKI64) && !defined(HAVE_LSEEK64)
557  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
558  ( (size > (uint64_t)INT32_MAX) ||
559  (offset > (uint64_t)INT32_MAX) ||
560  ((size + offset) >= (uint64_t)INT32_MAX) ) )
561  return NULL;
562 #endif
563  if ( ((int64_t)size < 0) ||
564  ((int64_t)offset < 0) ||
565  ((int64_t)(size + offset) < 0) )
566  return NULL;
567 
568  response = MHD_create_response_from_callback (size,
569  4 * 1024,
570  &file_reader,
571  NULL,
572  &free_callback);
573  if (NULL == response)
574  return NULL;
575  response->fd = fd;
576  response->fd_off = offset;
577  response->crc_cls = response;
578  return response;
579 }
580 
581 
591 struct MHD_Response *
593  int fd)
594 {
596  fd,
597  0);
598 }
599 
600 
614 _MHD_EXTERN struct MHD_Response *
616  int fd)
617 {
619  fd,
620  0);
621 }
622 
623 
638 struct MHD_Response *
640  void *data,
641  int must_free,
642  int must_copy)
643 {
644  struct MHD_Response *response;
645  void *tmp;
646 
647  if ((NULL == data) && (size > 0))
648  return NULL;
649  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
650  return NULL;
651  response->fd = -1;
652  if (! MHD_mutex_init_ (&response->mutex))
653  {
654  free (response);
655  return NULL;
656  }
657  if ((must_copy) && (size > 0))
658  {
659  if (NULL == (tmp = malloc (size)))
660  {
661  MHD_mutex_destroy_chk_ (&response->mutex);
662  free (response);
663  return NULL;
664  }
665  memcpy (tmp, data, size);
666  must_free = MHD_YES;
667  data = tmp;
668  }
669  if (must_free)
670  {
671  response->crfc = &free;
672  response->crc_cls = data;
673  }
674  response->reference_count = 1;
675  response->total_size = size;
676  response->data = data;
677  response->data_size = size;
678  return response;
679 }
680 
681 
692 struct MHD_Response *
694  void *buffer,
695  enum MHD_ResponseMemoryMode mode)
696 {
697  return MHD_create_response_from_data (size,
698  buffer,
699  mode == MHD_RESPMEM_MUST_FREE,
700  mode == MHD_RESPMEM_MUST_COPY);
701 }
702 
703 
714 _MHD_EXTERN struct MHD_Response *
716  void *buffer,
718 {
719  struct MHD_Response *r;
720 
722  buffer,
723  MHD_YES,
724  MHD_NO);
725  if (NULL == r)
726  return r;
727  r->crfc = crfc;
728  return r;
729 }
730 
731 
732 #ifdef UPGRADE_SUPPORT
733 
745 _MHD_EXTERN int
746 MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
748  ...)
749 {
750  struct MHD_Connection *connection;
751  struct MHD_Daemon *daemon;
752 
753  if (NULL == urh)
754  return MHD_NO;
755  connection = urh->connection;
756 
757  /* Precaution checks on external data. */
758  if (NULL == connection)
759  return MHD_NO;
760  daemon = connection->daemon;
761  if (NULL == daemon)
762  return MHD_NO;
763 
764  switch (action)
765  {
767  if (urh->was_closed)
768  return MHD_NO; /* Already closed. */
769 
770  /* transition to special 'closed' state for start of cleanup */
771 #ifdef HTTPS_SUPPORT
772  if (0 != (daemon->options & MHD_USE_TLS) )
773  {
774  /* signal that app is done by shutdown() of 'app' socket */
775  /* Application will not use anyway this socket after this command. */
776  shutdown (urh->app.socket,
777  SHUT_RDWR);
778  }
779 #endif /* HTTPS_SUPPORT */
780  mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
781  urh->was_closed = true;
782  /* As soon as connection will be marked with BOTH
783  * 'urh->was_closed' AND 'urh->clean_ready', it will
784  * be moved to cleanup list by MHD_resume_connection(). */
785  MHD_resume_connection (connection);
786  return MHD_YES;
787  default:
788  /* we don't understand this one */
789  return MHD_NO;
790  }
791 }
792 
793 
807 int
809  struct MHD_Connection *connection)
810 {
811  struct MHD_Daemon *daemon = connection->daemon;
812  struct MHD_UpgradeResponseHandle *urh;
813  size_t rbo;
814 
815  if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
816  return MHD_NO;
817 
818  if (NULL ==
819  MHD_get_response_header (response,
821  {
822 #ifdef HAVE_MESSAGES
823  MHD_DLOG (daemon,
824  _("Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
825 #endif
826  return MHD_NO;
827  }
828 
829  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
830  if (NULL == urh)
831  return MHD_NO;
832  urh->connection = connection;
833  rbo = connection->read_buffer_offset;
834  connection->read_buffer_offset = 0;
835 #ifdef HTTPS_SUPPORT
836  if (0 != (daemon->options & MHD_USE_TLS) )
837  {
838  struct MemoryPool *pool;
839  size_t avail;
840  char *buf;
841  MHD_socket sv[2];
842 #if defined(MHD_socket_nosignal_) || !defined(MHD_socket_pair_nblk_)
843  int res1;
844  int res2;
845 #endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
846 
847 #ifdef MHD_socket_pair_nblk_
848  if (! MHD_socket_pair_nblk_ (sv))
849  {
850  free (urh);
851  return MHD_NO;
852  }
853 #else /* !MHD_socket_pair_nblk_ */
854  if (! MHD_socket_pair_ (sv))
855  {
856  free (urh);
857  return MHD_NO;
858  }
859  res1 = MHD_socket_nonblocking_(sv[0]);
860  res2 = MHD_socket_nonblocking_(sv[1]);
861  if ( (! res1) || (! res2) )
862  {
863 #ifdef HAVE_MESSAGES
864  MHD_DLOG (daemon,
865  _("Failed to make loopback sockets non-blocking.\n"));
866 #endif
867  if (! res2)
868  {
869  /* Socketpair cannot be used. */
870  MHD_socket_close_chk_ (sv[0]);
871  MHD_socket_close_chk_ (sv[1]);
872  free (urh);
873  return MHD_NO;
874  }
875  }
876 #endif /* !MHD_socket_pair_nblk_ */
877 #ifdef MHD_socket_nosignal_
878  res1 = MHD_socket_nosignal_(sv[0]);
879  res2 = MHD_socket_nosignal_(sv[1]);
880  if ( (! res1) || (! res2) )
881  {
882 #ifdef HAVE_MESSAGES
883  MHD_DLOG (daemon,
884  _("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
885 #endif
886 #ifndef MSG_NOSIGNAL
887  if (!res2)
888  {
889  /* Socketpair cannot be used. */
890  MHD_socket_close_chk_ (sv[0]);
891  MHD_socket_close_chk_ (sv[1]);
892  free (urh);
893  return MHD_NO;
894  }
895 #endif /* ! MSG_NOSIGNAL */
896  }
897 #endif /* MHD_socket_nosignal_ */
898  if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
899  NULL)) &&
900  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
901  {
902 #ifdef HAVE_MESSAGES
903  MHD_DLOG (daemon,
904  _("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
905  (int) sv[1],
906  (int) FD_SETSIZE);
907 #endif
908  MHD_socket_close_chk_ (sv[0]);
909  MHD_socket_close_chk_ (sv[1]);
910  free (urh);
911  return MHD_NO;
912  }
913  urh->app.socket = sv[0];
914  urh->app.urh = urh;
915  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
916  urh->mhd.socket = sv[1];
917  urh->mhd.urh = urh;
918  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
919  pool = connection->pool;
920  avail = MHD_pool_get_free (pool);
921  if (avail < RESERVE_EBUF_SIZE)
922  {
923  /* connection's pool is totally at the limit,
924  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
925  avail = RESERVE_EBUF_SIZE;
926  buf = urh->e_buf;
927  }
928  else
929  {
930  /* Normal case: grab all remaining memory from the
931  connection's pool for the IO buffers; the connection
932  certainly won't need it anymore as we've upgraded
933  to another protocol. */
934  buf = MHD_pool_allocate (pool,
935  avail,
936  MHD_NO);
937  }
938  /* use half the buffer for inbound, half for outbound */
939  urh->in_buffer_size = avail / 2;
940  urh->out_buffer_size = avail - urh->in_buffer_size;
941  urh->in_buffer = buf;
942  urh->out_buffer = &buf[urh->in_buffer_size];
943 #ifdef EPOLL_SUPPORT
944  /* Launch IO processing by the event loop */
945  if (0 != (daemon->options & MHD_USE_EPOLL))
946  {
947  /* We're running with epoll(), need to add the sockets
948  to the event set of the daemon's `epoll_upgrade_fd` */
949  struct epoll_event event;
950 
951  mhd_assert (-1 != daemon->epoll_upgrade_fd);
952  /* First, add network socket */
953  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
954  event.data.ptr = &urh->app;
955  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
956  EPOLL_CTL_ADD,
957  connection->socket_fd,
958  &event))
959  {
960 #ifdef HAVE_MESSAGES
961  MHD_DLOG (daemon,
962  _("Call to epoll_ctl failed: %s\n"),
964 #endif
965  MHD_socket_close_chk_ (sv[0]);
966  MHD_socket_close_chk_ (sv[1]);
967  free (urh);
968  return MHD_NO;
969  }
970 
971  /* Second, add our end of the UNIX socketpair() */
972  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
973  event.data.ptr = &urh->mhd;
974  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
975  EPOLL_CTL_ADD,
976  urh->mhd.socket,
977  &event))
978  {
979  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
980  event.data.ptr = &urh->app;
981  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
982  EPOLL_CTL_DEL,
983  connection->socket_fd,
984  &event))
985  MHD_PANIC (_("Error cleaning up while handling epoll error"));
986 #ifdef HAVE_MESSAGES
987  MHD_DLOG (daemon,
988  _("Call to epoll_ctl failed: %s\n"),
990 #endif
991  MHD_socket_close_chk_ (sv[0]);
992  MHD_socket_close_chk_ (sv[1]);
993  free (urh);
994  return MHD_NO;
995  }
996  EDLL_insert (daemon->eready_urh_head,
997  daemon->eready_urh_tail,
998  urh);
999  urh->in_eready_list = true;
1000  }
1001 #endif /* EPOLL_SUPPORT */
1002  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
1003  {
1004  /* This takes care of further processing for most event loops:
1005  simply add to DLL for bi-direcitonal processing */
1006  DLL_insert (daemon->urh_head,
1007  daemon->urh_tail,
1008  urh);
1009  }
1010  /* In thread-per-connection mode, thread will switch to forwarding once
1011  * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
1012  */
1013  }
1014  else
1015  {
1016  urh->app.socket = MHD_INVALID_SOCKET;
1017  urh->mhd.socket = MHD_INVALID_SOCKET;
1018  /* Non-TLS connection do not hold any additional resources. */
1019  urh->clean_ready = true;
1020  }
1021 #else /* ! HTTPS_SUPPORT */
1022  urh->clean_ready = true;
1023 #endif /* ! HTTPS_SUPPORT */
1024  connection->urh = urh;
1025  /* As far as MHD's event loops are concerned, this connection is
1026  suspended; it will be resumed once application is done by the
1027  #MHD_upgrade_action() function */
1028  internal_suspend_connection_ (connection);
1029 
1030  /* hand over socket to application */
1031  response->upgrade_handler (response->upgrade_handler_cls,
1032  connection,
1033  connection->client_context,
1034  connection->read_buffer,
1035  rbo,
1036 #ifdef HTTPS_SUPPORT
1037  (0 == (daemon->options & MHD_USE_TLS) ) ?
1038  connection->socket_fd : urh->app.socket,
1039 #else /* ! HTTPS_SUPPORT */
1040  connection->socket_fd,
1041 #endif /* ! HTTPS_SUPPORT */
1042  urh);
1043  return MHD_YES;
1044 }
1045 
1046 
1076 _MHD_EXTERN struct MHD_Response *
1078  void *upgrade_handler_cls)
1079 {
1080  struct MHD_Response *response;
1081 
1082  if (NULL == upgrade_handler)
1083  return NULL; /* invalid request */
1084  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1085  if (NULL == response)
1086  return NULL;
1087  if (! MHD_mutex_init_ (&response->mutex))
1088  {
1089  free (response);
1090  return NULL;
1091  }
1092  response->upgrade_handler = upgrade_handler;
1093  response->upgrade_handler_cls = upgrade_handler_cls;
1094  response->total_size = MHD_SIZE_UNKNOWN;
1095  response->reference_count = 1;
1096  if (MHD_NO ==
1097  MHD_add_response_header (response,
1099  "Upgrade"))
1100  {
1101  MHD_destroy_response (response);
1102  return NULL;
1103  }
1104  return response;
1105 }
1106 #endif /* UPGRADE_SUPPORT */
1107 
1108 
1118 void
1120 {
1121  struct MHD_HTTP_Header *pos;
1122 
1123  if (NULL == response)
1124  return;
1125  MHD_mutex_lock_chk_ (&response->mutex);
1126  if (0 != --(response->reference_count))
1127  {
1128  MHD_mutex_unlock_chk_ (&response->mutex);
1129  return;
1130  }
1131  MHD_mutex_unlock_chk_ (&response->mutex);
1132  MHD_mutex_destroy_chk_ (&response->mutex);
1133  if (NULL != response->crfc)
1134  response->crfc (response->crc_cls);
1135  while (NULL != response->first_header)
1136  {
1137  pos = response->first_header;
1138  response->first_header = pos->next;
1139  free (pos->header);
1140  free (pos->value);
1141  free (pos);
1142  }
1143  free (response);
1144 }
1145 
1146 
1152 void
1154 {
1155  MHD_mutex_lock_chk_ (&response->mutex);
1156  (response->reference_count)++;
1157  MHD_mutex_unlock_chk_ (&response->mutex);
1158 }
1159 
1160 
1161 /* end of response.c */
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2033
#define MHD_PANIC(msg)
Definition: internal.h:68
uint64_t total_size
Definition: internal.h:1639
Header for platform missing functions.
additional automatic macros for MHD_config.h
_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:338
uint64_t fd_off
Definition: internal.h:1650
enum MHD_CONNECTION_STATE state
Definition: internal.h:894
void * data
Definition: microhttpd.h:2709
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:118
void int int must_copy
Definition: microhttpd.h:2709
int MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:376
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:177
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:185
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:1603
Methods for managing connections.
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:2100
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:118
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
#define EDLL_insert(head, tail, element)
Definition: internal.h:1829
#define MHD_YES
Definition: microhttpd.h:134
char * data
Definition: internal.h:1585
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:615
bool MHD_str_has_token_caseless_(const char *str, const char *const token, size_t token_len)
Definition: mhd_str.c:393
size_t data_size
Definition: internal.h:1656
int MHD_str_equal_caseless_(const char *str1, const char *str2)
Definition: mhd_str.c:329
char * value
Definition: internal.h:349
enum MHD_ValueKind kind
Definition: internal.h:355
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:510
int MHD_socket
Definition: microhttpd.h:181
Methods for managing response objects.
char * header
Definition: internal.h:344
struct MHD_Daemon * daemon
Definition: internal.h:672
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
Header for platform-independent inter-thread communication.
MHD_ResponseOptions
Definition: microhttpd.h:2646
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1153
struct MHD_HTTP_Header * first_header
Definition: internal.h:1579
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
size_t data_buffer_size
Definition: internal.h:1661
void * crc_cls
Definition: internal.h:1591
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
int fd
Definition: microhttpd.h:2837
void * client_context
Definition: internal.h:678
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:749
internal shared structures
_MHD_EXTERN int MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:160
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:550
enum MHD_FLAG options
Definition: internal.h:1564
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:2084
unsigned int reference_count
Definition: internal.h:1672
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1119
struct MHD_Action action
Definition: internal.h:1572
#define _MHD_EXTERN
Definition: mhd_options.h:51
void int must_free
Definition: microhttpd.h:2709
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
#define NULL
Definition: reason_phrase.c:30
#define INT32_MAX
Definition: mhd_limits.h:65
struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:639
MHD_ValueKind
Definition: microhttpd.h:1554
Header for string manipulating helpers.
char * read_buffer
Definition: internal.h:718
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:592
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:412
_MHD_EXTERN int MHD_upgrade_action(struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action,...)
int off_t offset
Definition: microhttpd.h:2837
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2650
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:693
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
enum MHD_ResponseFlags flags
Definition: internal.h:383
struct MHD_HTTP_Header * next
Definition: internal.h:339
_MHD_EXTERN struct MHD_Response * MHD_create_response_for_upgrade(MHD_UpgradeHandler upgrade_handler, void *upgrade_handler_cls)
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:151
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:2964
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:446
struct MemoryPool * pool
Definition: internal.h:682
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
bool MHD_check_response_header_token_ci(const struct MHD_Response *response, const char *key, const char *token, size_t token_len)
Definition: response.c:292
MHD_ContentReaderCallback crc
Definition: internal.h:1597
MHD_UpgradeAction
Definition: microhttpd.h:2877
MHD_mutex_ mutex
Definition: internal.h:1634
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer_with_free_callback(size_t size, void *buffer, MHD_ContentReaderFreeCallback crfc)
Definition: response.c:715
#define _(String)
Definition: mhd_options.h:42
static int add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:69
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:452
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
_MHD_EXTERN int MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:181
size_t read_buffer_offset
Definition: internal.h:767
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1523
MHD_ResponseFlags
Definition: microhttpd.h:2615
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:259
limits values definitions
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:508
struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:523
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:227
MHD_ResponseMemoryMode
Definition: microhttpd.h:2719
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2768
static void free_callback(void *cls)
Definition: response.c:496