GNU libmicrohttpd  0.9.29
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 #ifdef _WIN32
34 #include <windows.h>
35 #endif /* _WIN32 */
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 "connection.h"
43 #include "memorypool.h"
44 #include "mhd_compat.h"
45 
46 
47 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
48 #ifndef WIN32_LEAN_AND_MEAN
49 #define WIN32_LEAN_AND_MEAN 1
50 #endif /* !WIN32_LEAN_AND_MEAN */
51 #include <windows.h>
52 #endif /* _WIN32 && MHD_W32_MUTEX_ */
53 #if defined(_WIN32)
54 #include <io.h> /* for lseek(), read() */
55 #endif /* _WIN32 */
56 
57 
67 static int
68 add_response_entry (struct MHD_Response *response,
69  enum MHD_ValueKind kind,
70  const char *header,
71  const char *content)
72 {
73  struct MHD_HTTP_Header *hdr;
74 
75  if ( (NULL == response) ||
76  (NULL == header) ||
77  (NULL == content) ||
78  (0 == header[0]) ||
79  (0 == content[0]) ||
80  (NULL != strchr (header, '\t')) ||
81  (NULL != strchr (header, '\r')) ||
82  (NULL != strchr (header, '\n')) ||
83  (NULL != strchr (content, '\t')) ||
84  (NULL != strchr (content, '\r')) ||
85  (NULL != strchr (content, '\n')) )
86  return MHD_NO;
87  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
88  return MHD_NO;
89  if (NULL == (hdr->header = strdup (header)))
90  {
91  free (hdr);
92  return MHD_NO;
93  }
94  if (NULL == (hdr->value = strdup (content)))
95  {
96  free (hdr->header);
97  free (hdr);
98  return MHD_NO;
99  }
100  hdr->kind = kind;
101  hdr->next = response->first_header;
102  response->first_header = hdr;
103  return MHD_YES;
104 }
105 
106 
116 int
118  const char *header,
119  const char *content)
120 {
121  return add_response_entry (response,
123  header,
124  content);
125 }
126 
127 
137 int
139  const char *footer,
140  const char *content)
141 {
142  return add_response_entry (response,
144  footer,
145  content);
146 }
147 
148 
158 int
160  const char *header,
161  const char *content)
162 {
163  struct MHD_HTTP_Header *pos;
164  struct MHD_HTTP_Header *prev;
165 
166  if ( (NULL == header) ||
167  (NULL == content) )
168  return MHD_NO;
169  prev = NULL;
170  pos = response->first_header;
171  while (pos != NULL)
172  {
173  if ((0 == strcmp (header,
174  pos->header)) &&
175  (0 == strcmp (content,
176  pos->value)))
177  {
178  free (pos->header);
179  free (pos->value);
180  if (NULL == prev)
181  response->first_header = pos->next;
182  else
183  prev->next = pos->next;
184  free (pos);
185  return MHD_YES;
186  }
187  prev = pos;
188  pos = pos->next;
189  }
190  return MHD_NO;
191 }
192 
193 
204 int
206  MHD_KeyValueIterator iterator,
207  void *iterator_cls)
208 {
209  struct MHD_HTTP_Header *pos;
210  int numHeaders = 0;
211 
212  for (pos = response->first_header; NULL != pos; pos = pos->next)
213  {
214  numHeaders++;
215  if ((NULL != iterator) &&
216  (MHD_YES != iterator (iterator_cls,
217  pos->kind,
218  pos->header,
219  pos->value)))
220  break;
221  }
222  return numHeaders;
223 }
224 
225 
234 const char *
236  const char *key)
237 {
238  struct MHD_HTTP_Header *pos;
239 
240  if (NULL == key)
241  return NULL;
242  for (pos = response->first_header; NULL != pos; pos = pos->next)
243  if (0 == strcmp (key,
244  pos->header))
245  return pos->value;
246  return NULL;
247 }
248 
249 
266 struct MHD_Response *
268  size_t block_size,
270  void *crc_cls,
272 {
273  struct MHD_Response *response;
274 
275  if ((NULL == crc) || (0 == block_size))
276  return NULL;
277  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response) + block_size)))
278  return NULL;
279  response->fd = -1;
280  response->data = (void *) &response[1];
281  response->data_buffer_size = block_size;
282  if (! MHD_mutex_init_ (&response->mutex))
283  {
284  free (response);
285  return NULL;
286  }
287  response->crc = crc;
288  response->crfc = crfc;
289  response->crc_cls = crc_cls;
290  response->reference_count = 1;
291  response->total_size = size;
292  return response;
293 }
294 
295 
304 int
306  enum MHD_ResponseFlags flags,
307  ...)
308 {
309  va_list ap;
310  int ret;
311  enum MHD_ResponseOptions ro;
312 
313  ret = MHD_YES;
314  response->flags = flags;
315  va_start (ap, flags);
316  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
317  {
318  switch (ro)
319  {
320  default:
321  ret = MHD_NO;
322  break;
323  }
324  }
325  va_end (ap);
326  return ret;
327 }
328 
329 
340 static ssize_t
341 file_reader (void *cls,
342  uint64_t pos,
343  char *buf,
344  size_t max)
345 {
346  struct MHD_Response *response = cls;
347 #ifndef _WIN32
348  ssize_t n;
349 #else /* _WIN32 */
350  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
351 #endif /* _WIN32 */
352  const int64_t offset64 = (int64_t)(pos + response->fd_off);
353 
354  if (offset64 < 0)
355  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
356 
357 #ifndef _WIN32
358  if (max > SSIZE_MAX)
359  max = SSIZE_MAX; /* Clamp to maximum return value. */
360 
361 #if defined(HAVE_PREAD64)
362  n = pread64(response->fd, buf, max, offset64);
363 #elif defined(HAVE_PREAD)
364  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
365  (offset64 > (uint64_t)INT32_MAX) )
366  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
367 
368  n = pread(response->fd, buf, max, (off_t) offset64);
369 #else /* ! HAVE_PREAD */
370 #if defined(HAVE_LSEEK64)
371  if (lseek64 (response->fd,
372  offset64,
373  SEEK_SET) != offset64)
374  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
375 #else /* ! HAVE_LSEEK64 */
376  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
377  (offset64 > (uint64_t)INT32_MAX) )
378  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
379 
380  if (lseek (response->fd,
381  (off_t) offset64,
382  SEEK_SET) != (off_t) offset64)
383  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
384 #endif /* ! HAVE_LSEEK64 */
385  n = read (response->fd,
386  buf,
387  max);
388 
389 #endif /* ! HAVE_PREAD */
390  if (0 == n)
392  if (n < 0)
394  return n;
395 #else /* _WIN32 */
396  if (INVALID_HANDLE_VALUE == fh)
397  return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
398  else
399  {
400  OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
401  ULARGE_INTEGER pos_uli;
402  DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
403  DWORD resRead;
404 
405  pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
406  f_ol.Offset = pos_uli.LowPart;
407  f_ol.OffsetHigh = pos_uli.HighPart;
408  if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
409  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
410  if (0 == resRead)
412  return (ssize_t) resRead;
413  }
414 #endif /* _WIN32 */
415 }
416 
417 
424 static void
425 free_callback (void *cls)
426 {
427  struct MHD_Response *response = cls;
428 
429  (void) close (response->fd);
430  response->fd = -1;
431 }
432 
433 #undef MHD_create_response_from_fd_at_offset
434 
451 struct MHD_Response *
453  int fd,
454  off_t offset)
455 {
457  fd,
458  offset);
459 }
460 
461 
478 _MHD_EXTERN struct MHD_Response *
480  int fd,
481  uint64_t offset)
482 {
483  struct MHD_Response *response;
484 
485 #if !defined(HAVE___LSEEKI64) && !defined(HAVE_LSEEK64)
486  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
487  ( (size > (uint64_t)INT32_MAX) ||
488  (offset > (uint64_t)INT32_MAX) ||
489  ((size + offset) >= (uint64_t)INT32_MAX) ) )
490  return NULL;
491 #endif
492  if ( ((int64_t)size < 0) ||
493  ((int64_t)offset < 0) ||
494  ((int64_t)(size + offset) < 0) )
495  return NULL;
496 
497  response = MHD_create_response_from_callback (size,
498  4 * 1024,
499  &file_reader,
500  NULL,
501  &free_callback);
502  if (NULL == response)
503  return NULL;
504  response->fd = fd;
505  response->fd_off = offset;
506  response->crc_cls = response;
507  return response;
508 }
509 
510 
520 struct MHD_Response *
522  int fd)
523 {
525  fd,
526  0);
527 }
528 
529 
543 _MHD_EXTERN struct MHD_Response *
545  int fd)
546 {
548  fd,
549  0);
550 }
551 
552 
567 struct MHD_Response *
569  void *data,
570  int must_free,
571  int must_copy)
572 {
573  struct MHD_Response *response;
574  void *tmp;
575 
576  if ((NULL == data) && (size > 0))
577  return NULL;
578  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
579  return NULL;
580  response->fd = -1;
581  if (! MHD_mutex_init_ (&response->mutex))
582  {
583  free (response);
584  return NULL;
585  }
586  if ((must_copy) && (size > 0))
587  {
588  if (NULL == (tmp = malloc (size)))
589  {
590  MHD_mutex_destroy_chk_ (&response->mutex);
591  free (response);
592  return NULL;
593  }
594  memcpy (tmp, data, size);
595  must_free = MHD_YES;
596  data = tmp;
597  }
598  if (must_free)
599  {
600  response->crfc = &free;
601  response->crc_cls = data;
602  }
603  response->reference_count = 1;
604  response->total_size = size;
605  response->data = data;
606  response->data_size = size;
607  return response;
608 }
609 
610 
621 struct MHD_Response *
623  void *buffer,
624  enum MHD_ResponseMemoryMode mode)
625 {
626  return MHD_create_response_from_data (size,
627  buffer,
628  mode == MHD_RESPMEM_MUST_FREE,
629  mode == MHD_RESPMEM_MUST_COPY);
630 }
631 
632 
633 #ifdef UPGRADE_SUPPORT
634 
646 _MHD_EXTERN int
647 MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
648  enum MHD_UpgradeAction action,
649  ...)
650 {
651  struct MHD_Connection *connection;
652  struct MHD_Daemon *daemon;
653 
654  if (NULL == urh)
655  return MHD_NO;
656  connection = urh->connection;
657 
658  /* Precaution checks on external data. */
659  if (NULL == connection)
660  return MHD_NO;
661  daemon = connection->daemon;
662  if (NULL == daemon)
663  return MHD_NO;
664 
665  switch (action)
666  {
667  case MHD_UPGRADE_ACTION_CLOSE:
668  if (urh->was_closed)
669  return MHD_NO; /* Already closed. */
670 
671  /* transition to special 'closed' state for start of cleanup */
672 #ifdef HTTPS_SUPPORT
673  if (0 != (daemon->options & MHD_USE_TLS) )
674  {
675  /* signal that app is done by shutdown() of 'app' socket */
676  /* Application will not use anyway this socket after this command. */
677  shutdown (urh->app.socket,
678  SHUT_RDWR);
679  }
680 #endif /* HTTPS_SUPPORT */
681  EXTRA_CHECK (MHD_CONNECTION_UPGRADE == connection->state);
682  urh->was_closed = true;
683  /* As soon as connection will be marked with BOTH
684  * 'urh->was_closed' AND 'urh->clean_ready', it will
685  * be moved to cleanup list by MHD_resume_connection(). */
686  MHD_resume_connection (connection);
687  return MHD_YES;
688  default:
689  /* we don't understand this one */
690  return MHD_NO;
691  }
692 }
693 
694 
708 int
710  struct MHD_Connection *connection)
711 {
712  struct MHD_Daemon *daemon = connection->daemon;
713  struct MHD_UpgradeResponseHandle *urh;
714  size_t rbo;
715 
716  if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
717  return MHD_NO;
718 
719  if (NULL ==
720  MHD_get_response_header (response,
722  {
723 #ifdef HAVE_MESSAGES
724  MHD_DLOG (daemon,
725  _("Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
726 #endif
727  return MHD_NO;
728  }
729 
730  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
731  if (NULL == urh)
732  return MHD_NO;
733  urh->connection = connection;
734  rbo = connection->read_buffer_offset;
735  connection->read_buffer_offset = 0;
736 #ifdef HTTPS_SUPPORT
737  if (0 != (daemon->options & MHD_USE_TLS) )
738  {
739  struct MemoryPool *pool;
740  size_t avail;
741  char *buf;
742  MHD_socket sv[2];
743 #if defined(MHD_socket_nosignal_) || !defined(MHD_socket_pair_nblk_)
744  int res1;
745  int res2;
746 #endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
747 
748 #ifdef MHD_socket_pair_nblk_
749  if (! MHD_socket_pair_nblk_ (sv))
750  {
751  free (urh);
752  return MHD_NO;
753  }
754 #else /* !MHD_socket_pair_nblk_ */
755  if (! MHD_socket_pair_ (sv))
756  {
757  free (urh);
758  return MHD_NO;
759  }
760  res1 = MHD_socket_nonblocking_(sv[0]);
761  res2 = MHD_socket_nonblocking_(sv[1]);
762  if ( (! res1) || (! res2) )
763  {
764 #ifdef HAVE_MESSAGES
765  MHD_DLOG (daemon,
766  _("Failed to make loopback sockets non-blocking.\n"));
767 #endif
768  if (! res2)
769  {
770  /* Socketpair cannot be used. */
771  MHD_socket_close_chk_ (sv[0]);
772  MHD_socket_close_chk_ (sv[1]);
773  free (urh);
774  return MHD_NO;
775  }
776  }
777 #endif /* !MHD_socket_pair_nblk_ */
778 #ifdef MHD_socket_nosignal_
779  res1 = MHD_socket_nosignal_(sv[0]);
780  res2 = MHD_socket_nosignal_(sv[1]);
781  if ( (! res1) || (! res2) )
782  {
783 #ifdef HAVE_MESSAGES
784  MHD_DLOG (daemon,
785  _("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
786 #endif
787 #ifndef MSG_NOSIGNAL
788  if (!res2)
789  {
790  /* Socketpair cannot be used. */
791  MHD_socket_close_chk_ (sv[0]);
792  MHD_socket_close_chk_ (sv[1]);
793  free (urh);
794  return MHD_NO;
795  }
796 #endif /* ! MSG_NOSIGNAL */
797  }
798 #endif /* MHD_socket_nosignal_ */
799  if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
800  NULL)) &&
801  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
802  {
803 #ifdef HAVE_MESSAGES
804  MHD_DLOG (daemon,
805  _("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
806  (int) sv[1],
807  (int) FD_SETSIZE);
808 #endif
809  MHD_socket_close_chk_ (sv[0]);
810  MHD_socket_close_chk_ (sv[1]);
811  free (urh);
812  return MHD_NO;
813  }
814  urh->app.socket = sv[0];
815  urh->app.urh = urh;
816  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
817  urh->mhd.socket = sv[1];
818  urh->mhd.urh = urh;
819  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
820  pool = connection->pool;
821  avail = MHD_pool_get_free (pool);
822  if (avail < RESERVE_EBUF_SIZE)
823  {
824  /* connection's pool is totally at the limit,
825  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
826  avail = RESERVE_EBUF_SIZE;
827  buf = urh->e_buf;
828  }
829  else
830  {
831  /* Normal case: grab all remaining memory from the
832  connection's pool for the IO buffers; the connection
833  certainly won't need it anymore as we've upgraded
834  to another protocol. */
835  buf = MHD_pool_allocate (pool,
836  avail,
837  MHD_NO);
838  }
839  /* use half the buffer for inbound, half for outbound */
840  urh->in_buffer_size = avail / 2;
841  urh->out_buffer_size = avail - urh->in_buffer_size;
842  urh->in_buffer = buf;
843  urh->out_buffer = &buf[urh->in_buffer_size];
844 #ifdef EPOLL_SUPPORT
845  /* Launch IO processing by the event loop */
846  if (0 != (daemon->options & MHD_USE_EPOLL))
847  {
848  /* We're running with epoll(), need to add the sockets
849  to the event set of the daemon's `epoll_upgrade_fd` */
850  struct epoll_event event;
851 
852  EXTRA_CHECK (-1 != daemon->epoll_upgrade_fd);
853  /* First, add network socket */
854  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
855  event.data.ptr = &urh->app;
856  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
857  EPOLL_CTL_ADD,
858  connection->socket_fd,
859  &event))
860  {
861 #ifdef HAVE_MESSAGES
862  MHD_DLOG (daemon,
863  _("Call to epoll_ctl failed: %s\n"),
865 #endif
866  MHD_socket_close_chk_ (sv[0]);
867  MHD_socket_close_chk_ (sv[1]);
868  free (urh);
869  return MHD_NO;
870  }
871 
872  /* Second, add our end of the UNIX socketpair() */
873  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
874  event.data.ptr = &urh->mhd;
875  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
876  EPOLL_CTL_ADD,
877  urh->mhd.socket,
878  &event))
879  {
880  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
881  event.data.ptr = &urh->app;
882  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
883  EPOLL_CTL_DEL,
884  connection->socket_fd,
885  &event))
886  MHD_PANIC (_("Error cleaning up while handling epoll error"));
887 #ifdef HAVE_MESSAGES
888  MHD_DLOG (daemon,
889  _("Call to epoll_ctl failed: %s\n"),
891 #endif
892  MHD_socket_close_chk_ (sv[0]);
893  MHD_socket_close_chk_ (sv[1]);
894  free (urh);
895  return MHD_NO;
896  }
897  EDLL_insert (daemon->eready_urh_head,
898  daemon->eready_urh_tail,
899  urh);
900  urh->in_eready_list = true;
901  }
902 #endif /* EPOLL_SUPPORT */
903  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
904  {
905  /* This takes care of further processing for most event loops:
906  simply add to DLL for bi-direcitonal processing */
907  DLL_insert (daemon->urh_head,
908  daemon->urh_tail,
909  urh);
910  }
911  /* In thread-per-connection mode, thread will switch to forwarding once
912  * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
913  */
914  }
915  else
916  {
917  urh->app.socket = MHD_INVALID_SOCKET;
918  urh->mhd.socket = MHD_INVALID_SOCKET;
919  /* Non-TLS connection do not hold any additional resources. */
920  urh->clean_ready = true;
921  }
922 #else /* ! HTTPS_SUPPORT */
923  urh->clean_ready = true;
924 #endif /* ! HTTPS_SUPPORT */
925  connection->urh = urh;
926  /* As far as MHD's event loops are concerned, this connection is
927  suspended; it will be resumed once application is done by the
928  #MHD_upgrade_action() function */
929  MHD_suspend_connection (connection);
930 
931  /* hand over socket to application */
932  response->upgrade_handler (response->upgrade_handler_cls,
933  connection,
934  connection->client_context,
935  connection->read_buffer,
936  rbo,
937 #ifdef HTTPS_SUPPORT
938  (0 == (daemon->options & MHD_USE_TLS) ) ?
939  connection->socket_fd : urh->app.socket,
940 #else /* ! HTTPS_SUPPORT */
941  connection->socket_fd,
942 #endif /* ! HTTPS_SUPPORT */
943  urh);
944  return MHD_YES;
945 }
946 
947 
977 _MHD_EXTERN struct MHD_Response *
978 MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
979  void *upgrade_handler_cls)
980 {
981  struct MHD_Response *response;
982 
983  if (NULL == upgrade_handler)
984  return NULL; /* invalid request */
985  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
986  if (NULL == response)
987  return NULL;
988  if (! MHD_mutex_init_ (&response->mutex))
989  {
990  free (response);
991  return NULL;
992  }
993  response->upgrade_handler = upgrade_handler;
994  response->upgrade_handler_cls = upgrade_handler_cls;
995  response->total_size = MHD_SIZE_UNKNOWN;
996  response->reference_count = 1;
997  if (MHD_NO ==
998  MHD_add_response_header (response,
1000  "Upgrade"))
1001  {
1002  MHD_destroy_response (response);
1003  return NULL;
1004  }
1005  return response;
1006 }
1007 #endif /* UPGRADE_SUPPORT */
1008 
1009 
1019 void
1021 {
1022  struct MHD_HTTP_Header *pos;
1023 
1024  if (NULL == response)
1025  return;
1026  MHD_mutex_lock_chk_ (&response->mutex);
1027  if (0 != --(response->reference_count))
1028  {
1029  MHD_mutex_unlock_chk_ (&response->mutex);
1030  return;
1031  }
1032  MHD_mutex_unlock_chk_ (&response->mutex);
1033  MHD_mutex_destroy_chk_ (&response->mutex);
1034  if (NULL != response->crfc)
1035  response->crfc (response->crc_cls);
1036  while (NULL != response->first_header)
1037  {
1038  pos = response->first_header;
1039  response->first_header = pos->next;
1040  free (pos->header);
1041  free (pos->value);
1042  free (pos);
1043  }
1044  free (response);
1045 }
1046 
1047 
1053 void
1055 {
1056  MHD_mutex_lock_chk_ (&response->mutex);
1057  (response->reference_count)++;
1058  MHD_mutex_unlock_chk_ (&response->mutex);
1059 }
1060 
1061 
1062 /* end of response.c */
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1988
int MHD_socket_nonblocking_(MHD_socket sock)
Definition: mhd_sockets.c:404
int MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:305
uint64_t total_size
Definition: internal.h:340
additional automatic macros for MHD_config.h
uint64_t fd_off
Definition: internal.h:351
static void free_callback(void *cls)
Definition: response.c:425
#define DLL_insert(head, tail, element)
Definition: internal.h:1690
enum MHD_CONNECTION_STATE state
Definition: internal.h:859
int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:117
#define NULL
Definition: reason_phrase.c:31
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:544
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:315
Methods for managing connections.
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:2055
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:341
#define MHD_YES
Definition: microhttpd.h:134
const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:235
Header for platform missing functions.
size_t data_size
Definition: internal.h:357
#define EXTRA_CHECK(a)
Definition: internal.h:1678
enum MHD_ValueKind kind
Definition: internal.h:275
struct MHD_HTTP_Header * first_header
Definition: internal.h:291
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:504
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:188
int MHD_socket
Definition: microhttpd.h:181
void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2731
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:109
#define EDLL_insert(head, tail, element)
Definition: internal.h:1779
char * value
Definition: internal.h:269
Methods for managing response objects.
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
struct MHD_Daemon * daemon
Definition: internal.h:617
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
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:267
Header for platform-independent inter-thread communication.
size_t data_buffer_size
Definition: internal.h:362
struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:622
void * client_context
Definition: internal.h:650
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:817
int MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:138
enum MHD_FLAG options
Definition: internal.h:1542
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:2039
unsigned int reference_count
Definition: internal.h:368
void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1020
#define _MHD_EXTERN
Definition: mhd_options.h:51
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1054
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:160
struct MHD_Response * MHD_create_response_from_data(size_t size, void *data, int must_free, int must_copy)
Definition: response.c:568
MHD_ValueKind
Definition: microhttpd.h:1524
char * read_buffer
Definition: internal.h:683
limits values definitions
internal shared structures
void * MHD_calloc_(size_t nelem, size_t elsize)
Definition: mhd_compat.c:96
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:170
#define INT32_MAX
Definition: mhd_limits.h:59
#define MHD_socket_last_strerr_()
Definition: mhd_sockets.h:532
static int add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:68
char * header
Definition: internal.h:264
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:479
enum MHD_ResponseFlags flags
Definition: internal.h:378
struct MemoryPool * pool
Definition: internal.h:642
#define MHD_PANIC(msg)
Definition: internal.h:63
struct MHD_HTTP_Header * next
Definition: internal.h:259
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:440
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:309
void * crc_cls
Definition: internal.h:303
MHD_mutex_ mutex
Definition: internal.h:335
#define _(String)
Definition: mhd_options.h:42
void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2799
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
char * data
Definition: internal.h:297
int MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:159
size_t read_buffer_offset
Definition: internal.h:732
#define MHD_NO
Definition: microhttpd.h:139
volatile bool shutdown
Definition: internal.h:1483
struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:521
struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:452
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:205
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...