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 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 */
26 #define MHD_NO_DEPRECATION 1
27 
28 #include "mhd_options.h"
29 #ifdef HAVE_SYS_IOCTL_H
30 #include <sys/ioctl.h>
31 #endif /* HAVE_SYS_IOCTL_H */
32 
33 #include "internal.h"
34 #include "response.h"
35 #include "mhd_limits.h"
36 #include "mhd_sockets.h"
37 #include "mhd_itc.h"
38 #include "connection.h"
39 #include "memorypool.h"
40 
41 
42 #if defined(_WIN32) && defined(MHD_W32_MUTEX_)
43 #ifndef WIN32_LEAN_AND_MEAN
44 #define WIN32_LEAN_AND_MEAN 1
45 #endif /* !WIN32_LEAN_AND_MEAN */
46 #include <windows.h>
47 #endif /* _WIN32 && MHD_W32_MUTEX_ */
48 #if defined(_WIN32)
49 #include <io.h> /* for lseek(), read() */
50 #endif /* _WIN32 */
51 
52 
62 static int
63 add_response_entry (struct MHD_Response *response,
64  enum MHD_ValueKind kind,
65  const char *header,
66  const char *content)
67 {
68  struct MHD_HTTP_Header *hdr;
69 
70  if ( (NULL == response) ||
71  (NULL == header) ||
72  (NULL == content) ||
73  (0 == strlen (header)) ||
74  (0 == strlen (content)) ||
75  (NULL != strchr (header, '\t')) ||
76  (NULL != strchr (header, '\r')) ||
77  (NULL != strchr (header, '\n')) ||
78  (NULL != strchr (content, '\t')) ||
79  (NULL != strchr (content, '\r')) ||
80  (NULL != strchr (content, '\n')) )
81  return MHD_NO;
82  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
83  return MHD_NO;
84  if (NULL == (hdr->header = strdup (header)))
85  {
86  free (hdr);
87  return MHD_NO;
88  }
89  if (NULL == (hdr->value = strdup (content)))
90  {
91  free (hdr->header);
92  free (hdr);
93  return MHD_NO;
94  }
95  hdr->kind = kind;
96  hdr->next = response->first_header;
97  response->first_header = hdr;
98  return MHD_YES;
99 }
100 
101 
111 int
113  const char *header,
114  const char *content)
115 {
116  return add_response_entry (response,
118  header,
119  content);
120 }
121 
122 
132 int
134  const char *footer,
135  const char *content)
136 {
137  return add_response_entry (response,
139  footer,
140  content);
141 }
142 
143 
153 int
155  const char *header,
156  const char *content)
157 {
158  struct MHD_HTTP_Header *pos;
159  struct MHD_HTTP_Header *prev;
160 
161  if ( (NULL == header) ||
162  (NULL == content) )
163  return MHD_NO;
164  prev = NULL;
165  pos = response->first_header;
166  while (pos != NULL)
167  {
168  if ((0 == strcmp (header,
169  pos->header)) &&
170  (0 == strcmp (content,
171  pos->value)))
172  {
173  free (pos->header);
174  free (pos->value);
175  if (NULL == prev)
176  response->first_header = pos->next;
177  else
178  prev->next = pos->next;
179  free (pos);
180  return MHD_YES;
181  }
182  prev = pos;
183  pos = pos->next;
184  }
185  return MHD_NO;
186 }
187 
188 
199 int
201  MHD_KeyValueIterator iterator,
202  void *iterator_cls)
203 {
204  struct MHD_HTTP_Header *pos;
205  int numHeaders = 0;
206 
207  for (pos = response->first_header; NULL != pos; pos = pos->next)
208  {
209  numHeaders++;
210  if ((NULL != iterator) &&
211  (MHD_YES != iterator (iterator_cls,
212  pos->kind,
213  pos->header,
214  pos->value)))
215  break;
216  }
217  return numHeaders;
218 }
219 
220 
229 const char *
231  const char *key)
232 {
233  struct MHD_HTTP_Header *pos;
234 
235  if (NULL == key)
236  return NULL;
237  for (pos = response->first_header; NULL != pos; pos = pos->next)
238  if (0 == strcmp (key,
239  pos->header))
240  return pos->value;
241  return NULL;
242 }
243 
244 
261 struct MHD_Response *
263  size_t block_size,
265  void *crc_cls,
267 {
268  struct MHD_Response *response;
269 
270  if ((NULL == crc) || (0 == block_size))
271  return NULL;
272  if (NULL == (response = malloc (sizeof (struct MHD_Response) + block_size)))
273  return NULL;
274  memset (response,
275  0,
276  sizeof (struct MHD_Response));
277  response->fd = -1;
278  response->data = (void *) &response[1];
279  response->data_buffer_size = block_size;
280  if (! MHD_mutex_init_ (&response->mutex))
281  {
282  free (response);
283  return NULL;
284  }
285  response->crc = crc;
286  response->crfc = crfc;
287  response->crc_cls = crc_cls;
288  response->reference_count = 1;
289  response->total_size = size;
290  return response;
291 }
292 
293 
302 int
305  ...)
306 {
307  va_list ap;
308  int ret;
309  enum MHD_ResponseOptions ro;
310 
311  ret = MHD_YES;
312  response->flags = flags;
313  va_start (ap, flags);
314  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
315  {
316  switch (ro)
317  {
318  default:
319  ret = MHD_NO;
320  break;
321  }
322  }
323  va_end (ap);
324  return ret;
325 }
326 
327 
338 static ssize_t
339 file_reader (void *cls,
340  uint64_t pos,
341  char *buf,
342  size_t max)
343 {
344  struct MHD_Response *response = cls;
345  ssize_t n;
346  const int64_t offset64 = (int64_t)(pos + response->fd_off);
347 
348  if (offset64 < 0)
349  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
350 
351 #if defined(HAVE_LSEEK64)
352  if (lseek64 (response->fd,
353  offset64,
354  SEEK_SET) != offset64)
355  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
356 #elif defined(HAVE___LSEEKI64)
357  if (_lseeki64 (response->fd,
358  offset64,
359  SEEK_SET) != offset64)
360  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
361 #else /* !HAVE___LSEEKI64 */
362  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
363  (offset64 > (uint64_t)INT32_MAX) )
364  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
365 
366  if (lseek (response->fd,
367  (off_t) offset64,
368  SEEK_SET) != (off_t) offset64)
369  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
370 #endif
371 
372 #ifndef _WIN32
373  if (max > SSIZE_MAX)
374  max = SSIZE_MAX;
375 
376  n = read (response->fd,
377  buf,
378  max);
379 #else /* _WIN32 */
380  if (max > INT32_MAX)
381  max = INT32_MAX;
382 
383  n = read (response->fd,
384  buf,
385  (unsigned int) max);
386 #endif /* _WIN32 */
387 
388  if (0 == n)
390  if (n < 0)
392  return n;
393 }
394 
395 
402 static void
403 free_callback (void *cls)
404 {
405  struct MHD_Response *response = cls;
406 
407  (void) close (response->fd);
408  response->fd = -1;
409 }
410 
411 #undef MHD_create_response_from_fd_at_offset
412 
429 struct MHD_Response *
431  int fd,
432  off_t offset)
433 {
435  fd,
436  offset);
437 }
438 
439 
456 _MHD_EXTERN struct MHD_Response *
458  int fd,
459  uint64_t offset)
460 {
461  struct MHD_Response *response;
462 
463 #if !defined(HAVE___LSEEKI64) && !defined(HAVE_LSEEK64)
464  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
465  ( (size > (uint64_t)INT32_MAX) ||
466  (offset > (uint64_t)INT32_MAX) ||
467  ((size + offset) >= (uint64_t)INT32_MAX) ) )
468  return NULL;
469 #endif
470  if ( ((int64_t)size < 0) ||
471  ((int64_t)offset < 0) ||
472  ((int64_t)(size + offset) < 0) )
473  return NULL;
474 
475  response = MHD_create_response_from_callback (size,
476  4 * 1024,
477  &file_reader,
478  NULL,
479  &free_callback);
480  if (NULL == response)
481  return NULL;
482  response->fd = fd;
483  response->fd_off = offset;
484  response->crc_cls = response;
485  return response;
486 }
487 
488 
498 struct MHD_Response *
500  int fd)
501 {
503  fd,
504  0);
505 }
506 
507 
521 _MHD_EXTERN struct MHD_Response *
523  int fd)
524 {
526  fd,
527  0);
528 }
529 
530 
545 struct MHD_Response *
547  void *data,
548  int must_free,
549  int must_copy)
550 {
551  struct MHD_Response *response;
552  void *tmp;
553 
554  if ((NULL == data) && (size > 0))
555  return NULL;
556  if (NULL == (response = malloc (sizeof (struct MHD_Response))))
557  return NULL;
558  memset (response,
559  0,
560  sizeof (struct MHD_Response));
561  response->fd = -1;
562  if (! MHD_mutex_init_ (&response->mutex))
563  {
564  free (response);
565  return NULL;
566  }
567  if ((must_copy) && (size > 0))
568  {
569  if (NULL == (tmp = malloc (size)))
570  {
571  MHD_mutex_destroy_chk_ (&response->mutex);
572  free (response);
573  return NULL;
574  }
575  memcpy (tmp, data, size);
576  must_free = MHD_YES;
577  data = tmp;
578  }
579  response->crc = NULL;
580  response->crfc = must_free ? &free : NULL;
581  response->crc_cls = must_free ? data : NULL;
582  response->reference_count = 1;
583  response->total_size = size;
584  response->data = data;
585  response->data_size = size;
586  return response;
587 }
588 
589 
600 struct MHD_Response *
602  void *buffer,
603  enum MHD_ResponseMemoryMode mode)
604 {
605  return MHD_create_response_from_data (size,
606  buffer,
607  mode == MHD_RESPMEM_MUST_FREE,
608  mode == MHD_RESPMEM_MUST_COPY);
609 }
610 
611 
624 _MHD_EXTERN int
626  enum MHD_UpgradeAction action,
627  ...)
628 {
629  struct MHD_Connection *connection = urh->connection;
630  struct MHD_Daemon *daemon = connection->daemon;
631 
632  switch (action)
633  {
635  /* transition to special 'closed' state for start of cleanup */
636  connection->state = MHD_CONNECTION_UPGRADE_CLOSED;
637 #if HTTPS_SUPPORT
638  if (0 != (daemon->options & MHD_USE_TLS) )
639  {
640  /* signal that app is done by shutdown() of 'app' socket */
641  shutdown (urh->app.socket,
642  SHUT_RDWR);
643  }
644 #endif
645 #if HTTPS_SUPPORT
646  if (0 != (daemon->options & MHD_USE_TLS) )
647  {
648  urh->was_closed = MHD_YES;
649  /* connection and urh cleanup will be done as soon as outgoing
650  * data will be sent and 'was_closed' is detected */
651  return MHD_YES;
652  }
653 #endif
654  /* Application is done with this connection, tear it down! */
655  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
656  {
657  /* need to finish connection clean up */
659  if (MHD_CONNECTION_IN_CLEANUP != connection->state)
660  {
661 #if DEBUG_CLOSE
662 #ifdef HAVE_MESSAGES
663  MHD_DLOG (connection->daemon,
664  _("Processing thread terminating. Closing connection\n"));
665 #endif
666 #endif
667  if (MHD_CONNECTION_CLOSED != connection->state)
668  MHD_connection_close_ (connection,
670  connection->idle_handler (connection);
671  }
672  if (NULL != connection->response)
673  {
674  MHD_destroy_response (connection->response);
675  connection->response = NULL;
676  }
677 
678  if (MHD_INVALID_SOCKET != connection->socket_fd)
679  {
680  shutdown (connection->socket_fd,
681  SHUT_WR);
682  MHD_socket_close_chk_ (connection->socket_fd);
683  connection->socket_fd = MHD_INVALID_SOCKET;
684  }
685  return MHD_YES;
686  }
687  /* 'upgraded' resources are not needed anymore - cleanup now */
689  return MHD_YES;
690  default:
691  /* we don't understand this one */
692  return MHD_NO;
693  }
694 }
695 
696 
707 int
709  struct MHD_Connection *connection)
710 {
711  struct MHD_Daemon *daemon = connection->daemon;
712  struct MHD_UpgradeResponseHandle *urh;
713  size_t rbo;
714 
715  if (NULL ==
716  MHD_get_response_header (response,
718  {
719 #ifdef HAVE_MESSAGES
720  MHD_DLOG (daemon,
721  _("Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
722 #endif
723  return MHD_NO;
724  }
725 
726  urh = malloc (sizeof (struct MHD_UpgradeResponseHandle));
727  if (NULL == urh)
728  return MHD_NO;
729  memset (urh,
730  0,
731  sizeof (struct MHD_UpgradeResponseHandle));
732  urh->connection = connection;
733  rbo = connection->read_buffer_offset;
734  connection->read_buffer_offset = 0;
735 #if HTTPS_SUPPORT
736  if (0 != (daemon->options & MHD_USE_TLS) )
737  {
738  struct MemoryPool *pool;
739  size_t avail;
740  char *buf;
741  MHD_socket sv[2];
742 
743 #ifdef MHD_socket_pair_nblk_
744  if (! MHD_socket_pair_nblk_ (sv))
745  {
746  free (urh);
747  return MHD_NO;
748  }
749 #else /* !MHD_socket_pair_nblk_ */
750  if (! MHD_socket_pair_ (sv))
751  {
752  free (urh);
753  return MHD_NO;
754  }
755  if ( (! MHD_socket_nonblocking_(sv[0])) ||
756  (! MHD_socket_nonblocking_(sv[1])) )
757  {
758 #ifdef HAVE_MESSAGES
759  MHD_DLOG (daemon,
760  _("Failed to make loopback sockets non-blocking: %s\n"),
762 #endif
763  }
764 #endif /* !MHD_socket_pair_nblk_ */
765  if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
766  NULL)) &&
767  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
768  {
769 #ifdef HAVE_MESSAGES
770  MHD_DLOG (daemon,
771  _("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
772  (int) sv[1],
773  (int) FD_SETSIZE);
774 #endif
775  MHD_socket_close_chk_ (sv[0]);
776  MHD_socket_close_chk_ (sv[1]);
777  free (urh);
778  return MHD_NO;
779  }
780  urh->app.socket = sv[0];
781  urh->app.urh = urh;
782  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
783  urh->mhd.socket = sv[1];
784  urh->mhd.urh = urh;
785  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
786  pool = connection->pool;
787  avail = MHD_pool_get_free (pool);
788  if (avail < 8)
789  {
790  /* connection's pool is totally at the limit,
791  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
792  avail = RESERVE_EBUF_SIZE;
793  buf = urh->e_buf;
794  }
795  else
796  {
797  /* Normal case: grab all remaining memory from the
798  connection's pool for the IO buffers; the connection
799  certainly won't need it anymore as we've upgraded
800  to another protocol. */
801  buf = MHD_pool_allocate (pool,
802  avail,
803  MHD_NO);
804  }
805  /* use half the buffer for inbound, half for outbound */
806  avail /= 2;
807  urh->in_buffer_size = avail;
808  urh->out_buffer_size = avail;
809  urh->in_buffer = buf;
810  urh->out_buffer = &buf[avail];
811  /* hand over internal socket to application */
812  response->upgrade_handler (response->upgrade_handler_cls,
813  connection,
814  connection->client_context,
815  connection->read_buffer,
816  rbo,
817  urh->app.socket,
818  urh);
819 #ifdef EPOLL_SUPPORT
820  /* Launch IO processing by the event loop */
821  if (0 != (daemon->options & MHD_USE_EPOLL))
822  {
823  /* We're running with epoll(), need to add the sockets
824  to the event set of the daemon's `epoll_upgrade_fd` */
825  struct epoll_event event;
826 
827  EXTRA_CHECK (-1 != daemon->epoll_upgrade_fd);
828  /* First, add network socket */
829  event.events = EPOLLIN | EPOLLOUT;
830  event.data.ptr = &urh->app;
831  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
832  EPOLL_CTL_ADD,
833  connection->socket_fd,
834  &event))
835  {
836 #ifdef HAVE_MESSAGES
837  MHD_DLOG (daemon,
838  _("Call to epoll_ctl failed: %s\n"),
840 #endif
841  MHD_socket_close_chk_ (sv[0]);
842  MHD_socket_close_chk_ (sv[1]);
843  free (urh);
844  return MHD_NO;
845  }
846 
847  /* Second, add our end of the UNIX socketpair() */
848  event.events = EPOLLIN | EPOLLOUT;
849  event.data.ptr = &urh->mhd;
850  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
851  EPOLL_CTL_ADD,
852  urh->mhd.socket,
853  &event))
854  {
855  event.events = EPOLLIN | EPOLLOUT;
856  event.data.ptr = &urh->app;
857  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
858  EPOLL_CTL_DEL,
859  connection->socket_fd,
860  &event))
861  MHD_PANIC (_("Error cleaning up while handling epoll error"));
862 #ifdef HAVE_MESSAGES
863  MHD_DLOG (daemon,
864  _("Call to epoll_ctl failed: %s\n"),
866 #endif
867  MHD_socket_close_chk_ (sv[0]);
868  MHD_socket_close_chk_ (sv[1]);
869  free (urh);
870  return MHD_NO;
871  }
872  }
873 #endif /* EPOLL_SUPPORT */
874  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
875  {
876  /* As far as MHD's event loops are concerned, this connection
877  is suspended; it will be resumed once we are done in the
878  #MHD_upgrade_action() function */
879  MHD_suspend_connection (connection);
880  /* This takes care of further processing for most event loops:
881  simply add to DLL for bi-direcitonal processing */
882  DLL_insert (daemon->urh_head,
883  daemon->urh_tail,
884  urh);
885  /* Keep reference for later removal from the DLL */
886  connection->urh = urh;
887  }
888  else
889  {
890  /* Our caller will set 'connection->state' to
891  MHD_CONNECTION_UPGRADE, thereby triggering the main method
892  of the thread to switch to bi-directional forwarding. */
893  connection->urh = urh;
894  }
895  return MHD_YES;
896  }
897  urh->app.socket = MHD_INVALID_SOCKET;
898  urh->mhd.socket = MHD_INVALID_SOCKET;
899 #endif
900  if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
901  {
902  connection->urh = urh;
903  }
904  else
905  {
906  /* As far as MHD's event loops are concerned, this connection is
907  suspended; it will be resumed once we are done in the
908  #MHD_upgrade_action() function */
909  MHD_suspend_connection (connection);
910  }
911  response->upgrade_handler (response->upgrade_handler_cls,
912  connection,
913  connection->client_context,
914  connection->read_buffer,
915  rbo,
916  connection->socket_fd,
917  urh);
918  return MHD_YES;
919 }
920 
921 
951 _MHD_EXTERN struct MHD_Response *
953  void *upgrade_handler_cls)
954 {
955  struct MHD_Response *response;
956 
957  if (NULL == upgrade_handler)
958  return NULL; /* invalid request */
959  response = malloc (sizeof (struct MHD_Response));
960  if (NULL == response)
961  return NULL;
962  memset (response, 0, sizeof (struct MHD_Response));
963  if (! MHD_mutex_init_ (&response->mutex))
964  {
965  free (response);
966  return NULL;
967  }
968  response->upgrade_handler = upgrade_handler;
970  response->total_size = MHD_SIZE_UNKNOWN;
971  response->reference_count = 1;
972  if (MHD_NO ==
973  MHD_add_response_header (response,
975  "Upgrade"))
976  {
977  MHD_destroy_response (response);
978  return NULL;
979  }
980  return response;
981 }
982 
983 
993 void
995 {
996  struct MHD_HTTP_Header *pos;
997 
998  if (NULL == response)
999  return;
1000  MHD_mutex_lock_chk_ (&response->mutex);
1001  if (0 != --(response->reference_count))
1002  {
1003  MHD_mutex_unlock_chk_ (&response->mutex);
1004  return;
1005  }
1006  MHD_mutex_unlock_chk_ (&response->mutex);
1007  MHD_mutex_destroy_chk_ (&response->mutex);
1008  if (NULL != response->crfc)
1009  response->crfc (response->crc_cls);
1010  while (NULL != response->first_header)
1011  {
1012  pos = response->first_header;
1013  response->first_header = pos->next;
1014  free (pos->header);
1015  free (pos->value);
1016  free (pos);
1017  }
1018  free (response);
1019 }
1020 
1021 
1027 void
1029 {
1030  MHD_mutex_lock_chk_ (&response->mutex);
1031  (response->reference_count)++;
1032  MHD_mutex_unlock_chk_ (&response->mutex);
1033 }
1034 
1035 
1036 /* end of response.c */
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:1482
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:303
uint64_t total_size
Definition: internal.h:319
void MHD_cleanup_upgraded_connection_(struct MHD_Connection *connection)
Definition: daemon.c:920
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:262
uint64_t fd_off
Definition: internal.h:330
static void free_callback(void *cls)
Definition: response.c:403
#define DLL_insert(head, tail, element)
Definition: internal.h:1548
enum MHD_CONNECTION_STATE state
Definition: internal.h:813
void * data
Definition: microhttpd.h:2108
struct MHD_UpgradeResponseHandle * urh
Definition: internal.h:890
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:112
#define NULL
Definition: reason_phrase.c:30
void int int must_copy
Definition: microhttpd.h:2108
MHD_ContentReaderFreeCallback crfc
Definition: internal.h:296
Methods for managing connections.
void(* MHD_ContentReaderFreeCallback)(void *cls)
Definition: microhttpd.h:1549
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:339
void MHD_connection_close_(struct MHD_Connection *connection, enum MHD_RequestTerminationCode termination_code)
Definition: connection.c:500
#define MHD_YES
Definition: microhttpd.h:134
struct MHD_Response * response
Definition: internal.h:616
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:522
#define RESERVE_EBUF_SIZE
Definition: internal.h:937
size_t data_size
Definition: internal.h:336
#define EXTRA_CHECK(a)
Definition: internal.h:1536
enum MHD_ValueKind kind
Definition: internal.h:256
struct MHD_HTTP_Header * first_header
Definition: internal.h:272
#define MHD_HTTP_HEADER_UPGRADE
Definition: microhttpd.h:437
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:188
int MHD_socket
Definition: microhttpd.h:181
#define MHD_mutex_destroy_chk_(pmutex)
Definition: mhd_locks.h:109
char * value
Definition: internal.h:250
Methods for managing response objects.
struct MHD_Daemon * daemon
Definition: internal.h:601
int(* idle_handler)(struct MHD_Connection *connection)
Definition: internal.h:871
MHD_ResponseOptions
Definition: microhttpd.h:2045
#define MHD_mutex_unlock_chk_(pmutex)
Definition: mhd_locks.h:168
Header for platform-independent inter-thread communication.
_MHD_EXTERN struct MHD_Response * MHD_create_response_for_upgrade(MHD_UpgradeHandler upgrade_handler, void *upgrade_handler_cls)
Definition: response.c:952
size_t data_buffer_size
Definition: internal.h:341
int fd
Definition: microhttpd.h:2218
void * client_context
Definition: internal.h:634
#define MHD_socket_close_chk_(fd)
Definition: mhd_sockets.h:246
MHD_UpgradeHandler upgrade_handler
Definition: internal.h:303
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:182
MHD_socket socket_fd
Definition: internal.h:782
_MHD_EXTERN int MHD_add_response_footer(struct MHD_Response *response, const char *footer, const char *content)
Definition: response.c:133
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:457
enum MHD_FLAG options
Definition: internal.h:1403
ssize_t(* MHD_ContentReaderCallback)(void *cls, uint64_t pos, char *buf, size_t max)
Definition: microhttpd.h:1533
unsigned int reference_count
Definition: internal.h:347
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:994
_MHD_EXTERN void MHD_suspend_connection(struct MHD_Connection *connection)
Definition: daemon.c:2158
struct MHD_Connection * connection
Definition: internal.h:990
int shutdown
Definition: internal.h:1362
#define _MHD_EXTERN
Definition: mhd_options.h:51
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1028
void int must_free
Definition: microhttpd.h:2108
#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:546
MHD_ValueKind
Definition: microhttpd.h:1053
char * read_buffer
Definition: internal.h:667
limits values definitions
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:499
internal shared structures
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:498
int off_t offset
Definition: microhttpd.h:2218
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:601
static int add_response_entry(struct MHD_Response *response, enum MHD_ValueKind kind, const char *header, const char *content)
Definition: response.c:63
char * header
Definition: internal.h:245
enum MHD_ResponseFlags flags
Definition: internal.h:357
struct MemoryPool * pool
Definition: internal.h:626
#define MHD_PANIC(msg)
Definition: internal.h:59
struct MHD_HTTP_Header * next
Definition: internal.h:240
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
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:2342
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:401
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition: microhttpd.h:161
MHD_ContentReaderCallback crc
Definition: internal.h:290
void * crc_cls
Definition: internal.h:284
MHD_UpgradeAction
Definition: microhttpd.h:2258
MHD_mutex_ mutex
Definition: internal.h:314
#define _(String)
Definition: mhd_options.h:42
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:153
char * data
Definition: internal.h:278
_MHD_EXTERN int MHD_upgrade_action(struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action,...)
Definition: response.c:625
int MHD_response_execute_upgrade_(struct MHD_Response *response, struct MHD_Connection *connection)
Definition: response.c:708
_MHD_EXTERN int MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:154
size_t read_buffer_offset
Definition: internal.h:716
#define MHD_NO
Definition: microhttpd.h:139
MHD_ResponseFlags
Definition: microhttpd.h:2025
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:230
void * upgrade_handler_cls
Definition: internal.h:308
struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:430
#define MHD_mutex_lock_chk_(pmutex)
Definition: mhd_locks.h:142
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:200
MHD_ResponseMemoryMode
Definition: microhttpd.h:2118
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...