GNU libmicrohttpd  0.9.63
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 defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
354  if (! MHD_mutex_init_ (&response->mutex))
355  {
356  free (response);
357  return NULL;
358  }
359 #endif
360  response->crc = crc;
361  response->crfc = crfc;
362  response->crc_cls = crc_cls;
363  response->reference_count = 1;
364  response->total_size = size;
365  return response;
366 }
367 
368 
377 int
380  ...)
381 {
382  va_list ap;
383  int ret;
384  enum MHD_ResponseOptions ro;
385 
386  ret = MHD_YES;
387  response->flags = flags;
388  va_start (ap, flags);
389  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
390  {
391  switch (ro)
392  {
393  default:
394  ret = MHD_NO;
395  break;
396  }
397  }
398  va_end (ap);
399  return ret;
400 }
401 
402 
413 static ssize_t
414 file_reader (void *cls,
415  uint64_t pos,
416  char *buf,
417  size_t max)
418 {
419  struct MHD_Response *response = cls;
420 #if !defined(_WIN32) || defined(__CYGWIN__)
421  ssize_t n;
422 #else /* _WIN32 && !__CYGWIN__ */
423  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
424 #endif /* _WIN32 && !__CYGWIN__ */
425  const int64_t offset64 = (int64_t)(pos + response->fd_off);
426 
427  if (offset64 < 0)
428  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
429 
430 #if !defined(_WIN32) || defined(__CYGWIN__)
431  if (max > SSIZE_MAX)
432  max = SSIZE_MAX; /* Clamp to maximum return value. */
433 
434 #if defined(HAVE_PREAD64)
435  n = pread64(response->fd, buf, max, offset64);
436 #elif defined(HAVE_PREAD)
437  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
438  (offset64 > (uint64_t)INT32_MAX) )
439  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
440 
441  n = pread(response->fd, buf, max, (off_t) offset64);
442 #else /* ! HAVE_PREAD */
443 #if defined(HAVE_LSEEK64)
444  if (lseek64 (response->fd,
445  offset64,
446  SEEK_SET) != offset64)
447  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
448 #else /* ! HAVE_LSEEK64 */
449  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
450  (offset64 > (uint64_t)INT32_MAX) )
451  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
452 
453  if (lseek (response->fd,
454  (off_t) offset64,
455  SEEK_SET) != (off_t) offset64)
456  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
457 #endif /* ! HAVE_LSEEK64 */
458  n = read (response->fd,
459  buf,
460  max);
461 
462 #endif /* ! HAVE_PREAD */
463  if (0 == n)
465  if (n < 0)
467  return n;
468 #else /* _WIN32 && !__CYGWIN__ */
469  if (INVALID_HANDLE_VALUE == fh)
470  return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
471  else
472  {
473  OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
474  ULARGE_INTEGER pos_uli;
475  DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
476  DWORD resRead;
477 
478  pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
479  f_ol.Offset = pos_uli.LowPart;
480  f_ol.OffsetHigh = pos_uli.HighPart;
481  if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
482  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
483  if (0 == resRead)
485  return (ssize_t) resRead;
486  }
487 #endif /* _WIN32 && !__CYGWIN__ */
488 }
489 
490 
497 static void
498 free_callback (void *cls)
499 {
500  struct MHD_Response *response = cls;
501 
502  (void) close (response->fd);
503  response->fd = -1;
504 }
505 
506 #undef MHD_create_response_from_fd_at_offset
507 
524 struct MHD_Response *
526  int fd,
527  off_t offset)
528 {
530  fd,
531  offset);
532 }
533 
534 
551 _MHD_EXTERN struct MHD_Response *
553  int fd,
554  uint64_t offset)
555 {
556  struct MHD_Response *response;
557 
558 #if !defined(HAVE___LSEEKI64) && !defined(HAVE_LSEEK64)
559  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
560  ( (size > (uint64_t)INT32_MAX) ||
561  (offset > (uint64_t)INT32_MAX) ||
562  ((size + offset) >= (uint64_t)INT32_MAX) ) )
563  return NULL;
564 #endif
565  if ( ((int64_t)size < 0) ||
566  ((int64_t)offset < 0) ||
567  ((int64_t)(size + offset) < 0) )
568  return NULL;
569 
570  response = MHD_create_response_from_callback (size,
572  &file_reader,
573  NULL,
574  &free_callback);
575  if (NULL == response)
576  return NULL;
577  response->fd = fd;
578  response->fd_off = offset;
579  response->crc_cls = response;
580  return response;
581 }
582 
583 
593 struct MHD_Response *
595  int fd)
596 {
598  fd,
599  0);
600 }
601 
602 
616 _MHD_EXTERN struct MHD_Response *
618  int fd)
619 {
621  fd,
622  0);
623 }
624 
625 
640 struct MHD_Response *
642  void *data,
643  int must_free,
644  int must_copy)
645 {
646  struct MHD_Response *response;
647  void *tmp;
648 
649  if ((NULL == data) && (size > 0))
650  return NULL;
651  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
652  return NULL;
653  response->fd = -1;
654 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
655  if (! MHD_mutex_init_ (&response->mutex))
656  {
657  free (response);
658  return NULL;
659  }
660 #endif
661  if ((must_copy) && (size > 0))
662  {
663  if (NULL == (tmp = malloc (size)))
664  {
665 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
666  MHD_mutex_destroy_chk_ (&response->mutex);
667 #endif
668  free (response);
669  return NULL;
670  }
671  memcpy (tmp, data, size);
672  must_free = MHD_YES;
673  data = tmp;
674  }
675  if (must_free)
676  {
677  response->crfc = &free;
678  response->crc_cls = data;
679  }
680  response->reference_count = 1;
681  response->total_size = size;
682  response->data = data;
683  response->data_size = size;
684  return response;
685 }
686 
687 
698 struct MHD_Response *
700  void *buffer,
701  enum MHD_ResponseMemoryMode mode)
702 {
703  return MHD_create_response_from_data (size,
704  buffer,
705  mode == MHD_RESPMEM_MUST_FREE,
706  mode == MHD_RESPMEM_MUST_COPY);
707 }
708 
709 
720 _MHD_EXTERN struct MHD_Response *
722  void *buffer,
724 {
725  struct MHD_Response *r;
726 
728  buffer,
729  MHD_YES,
730  MHD_NO);
731  if (NULL == r)
732  return r;
733  r->crfc = crfc;
734  return r;
735 }
736 
737 
738 #ifdef UPGRADE_SUPPORT
739 
751 _MHD_EXTERN int
752 MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
754  ...)
755 {
756  struct MHD_Connection *connection;
757  struct MHD_Daemon *daemon;
758 
759  if (NULL == urh)
760  return MHD_NO;
761  connection = urh->connection;
762 
763  /* Precaution checks on external data. */
764  if (NULL == connection)
765  return MHD_NO;
766  daemon = connection->daemon;
767  if (NULL == daemon)
768  return MHD_NO;
769 
770  switch (action)
771  {
773  if (urh->was_closed)
774  return MHD_NO; /* Already closed. */
775 
776  /* transition to special 'closed' state for start of cleanup */
777 #ifdef HTTPS_SUPPORT
778  if (0 != (daemon->options & MHD_USE_TLS) )
779  {
780  /* signal that app is done by shutdown() of 'app' socket */
781  /* Application will not use anyway this socket after this command. */
782  shutdown (urh->app.socket,
783  SHUT_RDWR);
784  }
785 #endif /* HTTPS_SUPPORT */
786  mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
787  urh->was_closed = true;
788  /* As soon as connection will be marked with BOTH
789  * 'urh->was_closed' AND 'urh->clean_ready', it will
790  * be moved to cleanup list by MHD_resume_connection(). */
791  MHD_resume_connection (connection);
792  return MHD_YES;
793  default:
794  /* we don't understand this one */
795  return MHD_NO;
796  }
797 }
798 
799 
813 int
815  struct MHD_Connection *connection)
816 {
817  struct MHD_Daemon *daemon = connection->daemon;
818  struct MHD_UpgradeResponseHandle *urh;
819  size_t rbo;
820 
821  if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
822  return MHD_NO;
823 
824  if (NULL ==
825  MHD_get_response_header (response,
827  {
828 #ifdef HAVE_MESSAGES
829  MHD_DLOG (daemon,
830  _("Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
831 #endif
832  return MHD_NO;
833  }
834 
835  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
836  if (NULL == urh)
837  return MHD_NO;
838  urh->connection = connection;
839  rbo = connection->read_buffer_offset;
840  connection->read_buffer_offset = 0;
841 #ifdef HTTPS_SUPPORT
842  if (0 != (daemon->options & MHD_USE_TLS) )
843  {
844  struct MemoryPool *pool;
845  size_t avail;
846  char *buf;
847  MHD_socket sv[2];
848 #if defined(MHD_socket_nosignal_) || !defined(MHD_socket_pair_nblk_)
849  int res1;
850  int res2;
851 #endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
852 
853 #ifdef MHD_socket_pair_nblk_
854  if (! MHD_socket_pair_nblk_ (sv))
855  {
856  free (urh);
857  return MHD_NO;
858  }
859 #else /* !MHD_socket_pair_nblk_ */
860  if (! MHD_socket_pair_ (sv))
861  {
862  free (urh);
863  return MHD_NO;
864  }
865  res1 = MHD_socket_nonblocking_(sv[0]);
866  res2 = MHD_socket_nonblocking_(sv[1]);
867  if ( (! res1) || (! res2) )
868  {
869 #ifdef HAVE_MESSAGES
870  MHD_DLOG (daemon,
871  _("Failed to make loopback sockets non-blocking.\n"));
872 #endif
873  if (! res2)
874  {
875  /* Socketpair cannot be used. */
876  MHD_socket_close_chk_ (sv[0]);
877  MHD_socket_close_chk_ (sv[1]);
878  free (urh);
879  return MHD_NO;
880  }
881  }
882 #endif /* !MHD_socket_pair_nblk_ */
883 #ifdef MHD_socket_nosignal_
884  res1 = MHD_socket_nosignal_(sv[0]);
885  res2 = MHD_socket_nosignal_(sv[1]);
886  if ( (! res1) || (! res2) )
887  {
888 #ifdef HAVE_MESSAGES
889  MHD_DLOG (daemon,
890  _("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
891 #endif
892 #ifndef MSG_NOSIGNAL
893  if (!res2)
894  {
895  /* Socketpair cannot be used. */
896  MHD_socket_close_chk_ (sv[0]);
897  MHD_socket_close_chk_ (sv[1]);
898  free (urh);
899  return MHD_NO;
900  }
901 #endif /* ! MSG_NOSIGNAL */
902  }
903 #endif /* MHD_socket_nosignal_ */
904  if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
905  NULL)) &&
906  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
907  {
908 #ifdef HAVE_MESSAGES
909  MHD_DLOG (daemon,
910  _("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
911  (int) sv[1],
912  (int) FD_SETSIZE);
913 #endif
914  MHD_socket_close_chk_ (sv[0]);
915  MHD_socket_close_chk_ (sv[1]);
916  free (urh);
917  return MHD_NO;
918  }
919  urh->app.socket = sv[0];
920  urh->app.urh = urh;
921  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
922  urh->mhd.socket = sv[1];
923  urh->mhd.urh = urh;
924  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
925  pool = connection->pool;
926  avail = MHD_pool_get_free (pool);
927  if (avail < RESERVE_EBUF_SIZE)
928  {
929  /* connection's pool is totally at the limit,
930  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
931  avail = RESERVE_EBUF_SIZE;
932  buf = urh->e_buf;
933  }
934  else
935  {
936  /* Normal case: grab all remaining memory from the
937  connection's pool for the IO buffers; the connection
938  certainly won't need it anymore as we've upgraded
939  to another protocol. */
940  buf = MHD_pool_allocate (pool,
941  avail,
942  MHD_NO);
943  }
944  /* use half the buffer for inbound, half for outbound */
945  urh->in_buffer_size = avail / 2;
946  urh->out_buffer_size = avail - urh->in_buffer_size;
947  urh->in_buffer = buf;
948  urh->out_buffer = &buf[urh->in_buffer_size];
949 #ifdef EPOLL_SUPPORT
950  /* Launch IO processing by the event loop */
951  if (0 != (daemon->options & MHD_USE_EPOLL))
952  {
953  /* We're running with epoll(), need to add the sockets
954  to the event set of the daemon's `epoll_upgrade_fd` */
955  struct epoll_event event;
956 
957  mhd_assert (-1 != daemon->epoll_upgrade_fd);
958  /* First, add network socket */
959  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
960  event.data.ptr = &urh->app;
961  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
962  EPOLL_CTL_ADD,
963  connection->socket_fd,
964  &event))
965  {
966 #ifdef HAVE_MESSAGES
967  MHD_DLOG (daemon,
968  _("Call to epoll_ctl failed: %s\n"),
970 #endif
971  MHD_socket_close_chk_ (sv[0]);
972  MHD_socket_close_chk_ (sv[1]);
973  free (urh);
974  return MHD_NO;
975  }
976 
977  /* Second, add our end of the UNIX socketpair() */
978  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
979  event.data.ptr = &urh->mhd;
980  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
981  EPOLL_CTL_ADD,
982  urh->mhd.socket,
983  &event))
984  {
985  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
986  event.data.ptr = &urh->app;
987  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
988  EPOLL_CTL_DEL,
989  connection->socket_fd,
990  &event))
991  MHD_PANIC (_("Error cleaning up while handling epoll error"));
992 #ifdef HAVE_MESSAGES
993  MHD_DLOG (daemon,
994  _("Call to epoll_ctl failed: %s\n"),
996 #endif
997  MHD_socket_close_chk_ (sv[0]);
998  MHD_socket_close_chk_ (sv[1]);
999  free (urh);
1000  return MHD_NO;
1001  }
1002  EDLL_insert (daemon->eready_urh_head,
1003  daemon->eready_urh_tail,
1004  urh);
1005  urh->in_eready_list = true;
1006  }
1007 #endif /* EPOLL_SUPPORT */
1008  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
1009  {
1010  /* This takes care of further processing for most event loops:
1011  simply add to DLL for bi-direcitonal processing */
1012  DLL_insert (daemon->urh_head,
1013  daemon->urh_tail,
1014  urh);
1015  }
1016  /* In thread-per-connection mode, thread will switch to forwarding once
1017  * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
1018  */
1019  }
1020  else
1021  {
1022  urh->app.socket = MHD_INVALID_SOCKET;
1023  urh->mhd.socket = MHD_INVALID_SOCKET;
1024  /* Non-TLS connection do not hold any additional resources. */
1025  urh->clean_ready = true;
1026  }
1027 #else /* ! HTTPS_SUPPORT */
1028  urh->clean_ready = true;
1029 #endif /* ! HTTPS_SUPPORT */
1030  connection->urh = urh;
1031  /* As far as MHD's event loops are concerned, this connection is
1032  suspended; it will be resumed once application is done by the
1033  #MHD_upgrade_action() function */
1034  internal_suspend_connection_ (connection);
1035 
1036  /* hand over socket to application */
1037  response->upgrade_handler (response->upgrade_handler_cls,
1038  connection,
1039  connection->client_context,
1040  connection->read_buffer,
1041  rbo,
1042 #ifdef HTTPS_SUPPORT
1043  (0 == (daemon->options & MHD_USE_TLS) ) ?
1044  connection->socket_fd : urh->app.socket,
1045 #else /* ! HTTPS_SUPPORT */
1046  connection->socket_fd,
1047 #endif /* ! HTTPS_SUPPORT */
1048  urh);
1049  return MHD_YES;
1050 }
1051 
1052 
1082 _MHD_EXTERN struct MHD_Response *
1084  void *upgrade_handler_cls)
1085 {
1086  struct MHD_Response *response;
1087 
1088  if (NULL == upgrade_handler)
1089  return NULL; /* invalid request */
1090  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1091  if (NULL == response)
1092  return NULL;
1093 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1094  if (! MHD_mutex_init_ (&response->mutex))
1095  {
1096  free (response);
1097  return NULL;
1098  }
1099 #endif
1100  response->upgrade_handler = upgrade_handler;
1101  response->upgrade_handler_cls = upgrade_handler_cls;
1102  response->total_size = MHD_SIZE_UNKNOWN;
1103  response->reference_count = 1;
1104  if (MHD_NO ==
1105  MHD_add_response_header (response,
1107  "Upgrade"))
1108  {
1109  MHD_destroy_response (response);
1110  return NULL;
1111  }
1112  return response;
1113 }
1114 #endif /* UPGRADE_SUPPORT */
1115 
1116 
1126 void
1128 {
1129  struct MHD_HTTP_Header *pos;
1130 
1131  if (NULL == response)
1132  return;
1133 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1134  MHD_mutex_lock_chk_ (&response->mutex);
1135 #endif
1136  if (0 != --(response->reference_count))
1137  {
1138 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1139  MHD_mutex_unlock_chk_ (&response->mutex);
1140 #endif
1141  return;
1142  }
1143 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1144  MHD_mutex_unlock_chk_ (&response->mutex);
1145  MHD_mutex_destroy_chk_ (&response->mutex);
1146 #endif
1147  if (NULL != response->crfc)
1148  response->crfc (response->crc_cls);
1149  while (NULL != response->first_header)
1150  {
1151  pos = response->first_header;
1152  response->first_header = pos->next;
1153  free (pos->header);
1154  free (pos->value);
1155  free (pos);
1156  }
1157  free (response);
1158 }
1159 
1160 
1166 void
1168 {
1169 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1170  MHD_mutex_lock_chk_ (&response->mutex);
1171 #endif
1172  (response->reference_count)++;
1173 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1174  MHD_mutex_unlock_chk_ (&response->mutex);
1175 #endif
1176 }
1177 
1178 
1179 /* 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:915
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:378
#define MHD_FD_BLOCK_SIZE
Definition: mhd_limits.h:150
#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:617
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:1167
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:683
#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:552
enum MHD_FLAG options
Definition: internal.h:1590
#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:1127
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:641
MHD_ValueKind
Definition: microhttpd.h:1554
Header for string manipulating helpers.
char * read_buffer
Definition: internal.h:723
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:594
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:414
_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:2686
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:699
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
enum MHD_ResponseFlags flags
Definition: internal.h:387
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:721
#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:774
#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:525
_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:2810
static void free_callback(void *cls)
Definition: response.c:498