GNU libmicrohttpd  0.9.65
response.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007, 2009, 2010, 2016, 2017 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
27 #define MHD_NO_DEPRECATION 1
28 
29 #include "mhd_options.h"
30 #ifdef HAVE_SYS_IOCTL_H
31 #include <sys/ioctl.h>
32 #endif /* HAVE_SYS_IOCTL_H */
33 #if defined(_WIN32) && ! defined(__CYGWIN__)
34 #include <windows.h>
35 #endif /* _WIN32 && !__CYGWIN__ */
36 
37 #include "internal.h"
38 #include "response.h"
39 #include "mhd_limits.h"
40 #include "mhd_sockets.h"
41 #include "mhd_itc.h"
42 #include "mhd_str.h"
43 #include "connection.h"
44 #include "memorypool.h"
45 #include "mhd_compat.h"
46 
47 
48 #if defined(MHD_W32_MUTEX_)
49 #ifndef WIN32_LEAN_AND_MEAN
50 #define WIN32_LEAN_AND_MEAN 1
51 #endif /* !WIN32_LEAN_AND_MEAN */
52 #include <windows.h>
53 #endif /* MHD_W32_MUTEX_ */
54 #if defined(_WIN32)
55 #include <io.h> /* for lseek(), read() */
56 #endif /* _WIN32 */
57 
58 
63 #ifndef MHD_FILE_READ_BLOCK_SIZE
64 #ifdef _WIN32
65 #define MHD_FILE_READ_BLOCK_SIZE 16384 /* 16k */
66 #else /* _WIN32 */
67 #define MHD_FILE_READ_BLOCK_SIZE 4096 /* 4k */
68 #endif /* _WIN32 */
69 #endif /* !MHD_FD_BLOCK_SIZE */
70 
71 
81 static int
82 add_response_entry (struct MHD_Response *response,
83  enum MHD_ValueKind kind,
84  const char *header,
85  const char *content)
86 {
87  struct MHD_HTTP_Header *hdr;
88 
89  if ( (NULL == response) ||
90  (NULL == header) ||
91  (NULL == content) ||
92  (0 == header[0]) ||
93  (0 == content[0]) ||
94  (NULL != strchr (header, '\t')) ||
95  (NULL != strchr (header, '\r')) ||
96  (NULL != strchr (header, '\n')) ||
97  (NULL != strchr (content, '\t')) ||
98  (NULL != strchr (content, '\r')) ||
99  (NULL != strchr (content, '\n')) )
100  return MHD_NO;
101  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
102  return MHD_NO;
103  if (NULL == (hdr->header = strdup (header)))
104  {
105  free (hdr);
106  return MHD_NO;
107  }
108  hdr->header_size = strlen (header);
109  if (NULL == (hdr->value = strdup (content)))
110  {
111  free (hdr->header);
112  free (hdr);
113  return MHD_NO;
114  }
115  hdr->value_size = strlen (content);
116  hdr->kind = kind;
117  hdr->next = response->first_header;
118  response->first_header = hdr;
119  return MHD_YES;
120 }
121 
122 
132 int
134  const char *header,
135  const char *content)
136 {
139  (! MHD_str_equal_caseless_ (content,
140  "identity")) &&
141  (! MHD_str_equal_caseless_ (content,
142  "chunked")) )
143  {
144  /* Setting transfer encodings other than "identity" or
145  "chunked" is not allowed. Note that MHD will set the
146  correct transfer encoding if required automatically. */
147  /* NOTE: for compressed bodies, use the "Content-encoding" header */
148  return MHD_NO;
149  }
152  {
153  /* MHD will set Content-length if allowed and possible,
154  reject attempt by application */
155  return MHD_NO;
156  }
157 
158  return add_response_entry (response,
160  header,
161  content);
162 }
163 
164 
174 int
176  const char *footer,
177  const char *content)
178 {
179  return add_response_entry (response,
181  footer,
182  content);
183 }
184 
185 
195 int
197  const char *header,
198  const char *content)
199 {
200  struct MHD_HTTP_Header *pos;
201  struct MHD_HTTP_Header *prev;
202  size_t header_len;
203  size_t content_len;
204 
205  if ( (NULL == header) ||
206  (NULL == content) )
207  return MHD_NO;
208  header_len = strlen (header);
209  content_len = strlen (content);
210  prev = NULL;
211  pos = response->first_header;
212  while (NULL != pos)
213  {
214  if ((header_len == pos->header_size) &&
215  (content_len == pos->value_size) &&
216  (0 == memcmp (header,
217  pos->header,
218  header_len)) &&
219  (0 == memcmp (content,
220  pos->value,
221  content_len)))
222  {
223  free (pos->header);
224  free (pos->value);
225  if (NULL == prev)
226  response->first_header = pos->next;
227  else
228  prev->next = pos->next;
229  free (pos);
230  return MHD_YES;
231  }
232  prev = pos;
233  pos = pos->next;
234  }
235  return MHD_NO;
236 }
237 
238 
249 int
251  MHD_KeyValueIterator iterator,
252  void *iterator_cls)
253 {
254  int numHeaders = 0;
255  struct MHD_HTTP_Header *pos;
256 
257  for (pos = response->first_header;
258  NULL != pos;
259  pos = pos->next)
260  {
261  numHeaders++;
262  if ((NULL != iterator) &&
263  (MHD_YES != iterator (iterator_cls,
264  pos->kind,
265  pos->header,
266  pos->value)))
267  break;
268  }
269  return numHeaders;
270 }
271 
272 
281 const char *
283  const char *key)
284 {
285  struct MHD_HTTP_Header *pos;
286  size_t key_size;
287 
288  if (NULL == key)
289  return NULL;
290 
291  key_size = strlen (key);
292  for (pos = response->first_header;
293  NULL != pos;
294  pos = pos->next)
295  {
296  if ((pos->header_size == key_size) &&
298  return pos->value;
299  }
300  return NULL;
301 }
302 
303 
320 bool
322  const char *key,
323  size_t key_len,
324  const char *token,
325  size_t token_len)
326 {
327  struct MHD_HTTP_Header *pos;
328 
329  if ( (NULL == key) ||
330  ('\0' == key[0]) ||
331  (NULL == token) ||
332  ('\0' == token[0]) )
333  return false;
334 
335  /* Token must not contain binary zero! */
336  mhd_assert(strlen(token) == token_len);
337 
338  for (pos = response->first_header;
339  NULL != pos;
340  pos = pos->next)
341  {
342  if ( (pos->kind == MHD_HEADER_KIND) &&
343  (key_len == pos->header_size) &&
345  key,
346  key_len) &&
348  token,
349  token_len) )
350  return true;
351  }
352  return false;
353 }
354 
355 
372 struct MHD_Response *
374  size_t block_size,
376  void *crc_cls,
378 {
379  struct MHD_Response *response;
380 
381  if ((NULL == crc) || (0 == block_size))
382  return NULL;
383  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response) + block_size)))
384  return NULL;
385  response->fd = -1;
386  response->data = (void *) &response[1];
387  response->data_buffer_size = block_size;
388 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
389  if (! MHD_mutex_init_ (&response->mutex))
390  {
391  free (response);
392  return NULL;
393  }
394 #endif
395  response->crc = crc;
396  response->crfc = crfc;
397  response->crc_cls = crc_cls;
398  response->reference_count = 1;
399  response->total_size = size;
400  return response;
401 }
402 
403 
412 int
415  ...)
416 {
417  va_list ap;
418  int ret;
419  enum MHD_ResponseOptions ro;
420 
421  ret = MHD_YES;
422  response->flags = flags;
423  va_start (ap, flags);
424  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
425  {
426  switch (ro)
427  {
428  default:
429  ret = MHD_NO;
430  break;
431  }
432  }
433  va_end (ap);
434  return ret;
435 }
436 
437 
448 static ssize_t
449 file_reader (void *cls,
450  uint64_t pos,
451  char *buf,
452  size_t max)
453 {
454  struct MHD_Response *response = cls;
455 #if !defined(_WIN32) || defined(__CYGWIN__)
456  ssize_t n;
457 #else /* _WIN32 && !__CYGWIN__ */
458  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
459 #endif /* _WIN32 && !__CYGWIN__ */
460  const int64_t offset64 = (int64_t)(pos + response->fd_off);
461 
462  if (offset64 < 0)
463  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
464 
465 #if !defined(_WIN32) || defined(__CYGWIN__)
466  if (max > SSIZE_MAX)
467  max = SSIZE_MAX; /* Clamp to maximum return value. */
468 
469 #if defined(HAVE_PREAD64)
470  n = pread64(response->fd, buf, max, offset64);
471 #elif defined(HAVE_PREAD)
472  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
473  (offset64 > (uint64_t)INT32_MAX) )
474  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
475 
476  n = pread(response->fd, buf, max, (off_t) offset64);
477 #else /* ! HAVE_PREAD */
478 #if defined(HAVE_LSEEK64)
479  if (lseek64 (response->fd,
480  offset64,
481  SEEK_SET) != offset64)
482  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
483 #else /* ! HAVE_LSEEK64 */
484  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
485  (offset64 > (uint64_t)INT32_MAX) )
486  return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
487 
488  if (lseek (response->fd,
489  (off_t) offset64,
490  SEEK_SET) != (off_t) offset64)
491  return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
492 #endif /* ! HAVE_LSEEK64 */
493  n = read (response->fd,
494  buf,
495  max);
496 
497 #endif /* ! HAVE_PREAD */
498  if (0 == n)
500  if (n < 0)
502  return n;
503 #else /* _WIN32 && !__CYGWIN__ */
504  if (INVALID_HANDLE_VALUE == fh)
505  return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
506  else
507  {
508  OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
509  ULARGE_INTEGER pos_uli;
510  DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
511  DWORD resRead;
512 
513  pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
514  f_ol.Offset = pos_uli.LowPart;
515  f_ol.OffsetHigh = pos_uli.HighPart;
516  if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
517  return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
518  if (0 == resRead)
520  return (ssize_t) resRead;
521  }
522 #endif /* _WIN32 && !__CYGWIN__ */
523 }
524 
525 
532 static void
533 free_callback (void *cls)
534 {
535  struct MHD_Response *response = cls;
536 
537  (void) close (response->fd);
538  response->fd = -1;
539 }
540 
541 #undef MHD_create_response_from_fd_at_offset
542 
559 struct MHD_Response *
561  int fd,
562  off_t offset)
563 {
565  fd,
566  offset);
567 }
568 
569 
586 _MHD_EXTERN struct MHD_Response *
588  int fd,
589  uint64_t offset)
590 {
591  struct MHD_Response *response;
592 
593 #if !defined(HAVE___LSEEKI64) && !defined(HAVE_LSEEK64)
594  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
595  ( (size > (uint64_t)INT32_MAX) ||
596  (offset > (uint64_t)INT32_MAX) ||
597  ((size + offset) >= (uint64_t)INT32_MAX) ) )
598  return NULL;
599 #endif
600  if ( ((int64_t)size < 0) ||
601  ((int64_t)offset < 0) ||
602  ((int64_t)(size + offset) < 0) )
603  return NULL;
604 
605  response = MHD_create_response_from_callback (size,
607  &file_reader,
608  NULL,
609  &free_callback);
610  if (NULL == response)
611  return NULL;
612  response->fd = fd;
613  response->fd_off = offset;
614  response->crc_cls = response;
615  return response;
616 }
617 
618 
628 struct MHD_Response *
630  int fd)
631 {
633  fd,
634  0);
635 }
636 
637 
651 _MHD_EXTERN struct MHD_Response *
653  int fd)
654 {
656  fd,
657  0);
658 }
659 
660 
675 struct MHD_Response *
677  void *data,
678  int must_free,
679  int must_copy)
680 {
681  struct MHD_Response *response;
682  void *tmp;
683 
684  if ((NULL == data) && (size > 0))
685  return NULL;
686  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
687  return NULL;
688  response->fd = -1;
689 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
690  if (! MHD_mutex_init_ (&response->mutex))
691  {
692  free (response);
693  return NULL;
694  }
695 #endif
696  if ((must_copy) && (size > 0))
697  {
698  if (NULL == (tmp = malloc (size)))
699  {
700 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
701  MHD_mutex_destroy_chk_ (&response->mutex);
702 #endif
703  free (response);
704  return NULL;
705  }
706  memcpy (tmp, data, size);
707  must_free = MHD_YES;
708  data = tmp;
709  }
710  if (must_free)
711  {
712  response->crfc = &free;
713  response->crc_cls = data;
714  }
715  response->reference_count = 1;
716  response->total_size = size;
717  response->data = data;
718  response->data_size = size;
719  return response;
720 }
721 
722 
733 struct MHD_Response *
735  void *buffer,
736  enum MHD_ResponseMemoryMode mode)
737 {
738  return MHD_create_response_from_data (size,
739  buffer,
740  mode == MHD_RESPMEM_MUST_FREE,
741  mode == MHD_RESPMEM_MUST_COPY);
742 }
743 
744 
755 _MHD_EXTERN struct MHD_Response *
757  void *buffer,
759 {
760  struct MHD_Response *r;
761 
763  buffer,
764  MHD_YES,
765  MHD_NO);
766  if (NULL == r)
767  return r;
768  r->crfc = crfc;
769  return r;
770 }
771 
772 
773 #ifdef UPGRADE_SUPPORT
774 
786 _MHD_EXTERN int
787 MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
789  ...)
790 {
791  struct MHD_Connection *connection;
792  struct MHD_Daemon *daemon;
793 
794  if (NULL == urh)
795  return MHD_NO;
796  connection = urh->connection;
797 
798  /* Precaution checks on external data. */
799  if (NULL == connection)
800  return MHD_NO;
801  daemon = connection->daemon;
802  if (NULL == daemon)
803  return MHD_NO;
804 
805  switch (action)
806  {
808  if (urh->was_closed)
809  return MHD_NO; /* Already closed. */
810 
811  /* transition to special 'closed' state for start of cleanup */
812 #ifdef HTTPS_SUPPORT
813  if (0 != (daemon->options & MHD_USE_TLS) )
814  {
815  /* signal that app is done by shutdown() of 'app' socket */
816  /* Application will not use anyway this socket after this command. */
817  shutdown (urh->app.socket,
818  SHUT_RDWR);
819  }
820 #endif /* HTTPS_SUPPORT */
821  mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
822  urh->was_closed = true;
823  /* As soon as connection will be marked with BOTH
824  * 'urh->was_closed' AND 'urh->clean_ready', it will
825  * be moved to cleanup list by MHD_resume_connection(). */
826  MHD_resume_connection (connection);
827  return MHD_YES;
828  default:
829  /* we don't understand this one */
830  return MHD_NO;
831  }
832 }
833 
834 
848 int
850  struct MHD_Connection *connection)
851 {
852  struct MHD_Daemon *daemon = connection->daemon;
853  struct MHD_UpgradeResponseHandle *urh;
854  size_t rbo;
855 
856  if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
857  return MHD_NO;
858 
859  if (NULL ==
860  MHD_get_response_header (response,
862  {
863 #ifdef HAVE_MESSAGES
864  MHD_DLOG (daemon,
865  _("Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
866 #endif
867  return MHD_NO;
868  }
869 
870  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
871  if (NULL == urh)
872  return MHD_NO;
873  urh->connection = connection;
874  rbo = connection->read_buffer_offset;
875  connection->read_buffer_offset = 0;
876 #ifdef HTTPS_SUPPORT
877  if (0 != (daemon->options & MHD_USE_TLS) )
878  {
879  struct MemoryPool *pool;
880  size_t avail;
881  char *buf;
882  MHD_socket sv[2];
883 #if defined(MHD_socket_nosignal_) || !defined(MHD_socket_pair_nblk_)
884  int res1;
885  int res2;
886 #endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
887 
888 #ifdef MHD_socket_pair_nblk_
889  if (! MHD_socket_pair_nblk_ (sv))
890  {
891  free (urh);
892  return MHD_NO;
893  }
894 #else /* !MHD_socket_pair_nblk_ */
895  if (! MHD_socket_pair_ (sv))
896  {
897  free (urh);
898  return MHD_NO;
899  }
900  res1 = MHD_socket_nonblocking_(sv[0]);
901  res2 = MHD_socket_nonblocking_(sv[1]);
902  if ( (! res1) || (! res2) )
903  {
904 #ifdef HAVE_MESSAGES
905  MHD_DLOG (daemon,
906  _("Failed to make loopback sockets non-blocking.\n"));
907 #endif
908  if (! res2)
909  {
910  /* Socketpair cannot be used. */
911  MHD_socket_close_chk_ (sv[0]);
912  MHD_socket_close_chk_ (sv[1]);
913  free (urh);
914  return MHD_NO;
915  }
916  }
917 #endif /* !MHD_socket_pair_nblk_ */
918 #ifdef MHD_socket_nosignal_
919  res1 = MHD_socket_nosignal_(sv[0]);
920  res2 = MHD_socket_nosignal_(sv[1]);
921  if ( (! res1) || (! res2) )
922  {
923 #ifdef HAVE_MESSAGES
924  MHD_DLOG (daemon,
925  _("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
926 #endif
927 #ifndef MSG_NOSIGNAL
928  if (!res2)
929  {
930  /* Socketpair cannot be used. */
931  MHD_socket_close_chk_ (sv[0]);
932  MHD_socket_close_chk_ (sv[1]);
933  free (urh);
934  return MHD_NO;
935  }
936 #endif /* ! MSG_NOSIGNAL */
937  }
938 #endif /* MHD_socket_nosignal_ */
939  if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
940  NULL)) &&
941  (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
942  {
943 #ifdef HAVE_MESSAGES
944  MHD_DLOG (daemon,
945  _("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
946  (int) sv[1],
947  (int) FD_SETSIZE);
948 #endif
949  MHD_socket_close_chk_ (sv[0]);
950  MHD_socket_close_chk_ (sv[1]);
951  free (urh);
952  return MHD_NO;
953  }
954  urh->app.socket = sv[0];
955  urh->app.urh = urh;
956  urh->app.celi = MHD_EPOLL_STATE_UNREADY;
957  urh->mhd.socket = sv[1];
958  urh->mhd.urh = urh;
959  urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
960  pool = connection->pool;
961  avail = MHD_pool_get_free (pool);
962  if (avail < RESERVE_EBUF_SIZE)
963  {
964  /* connection's pool is totally at the limit,
965  use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
966  avail = RESERVE_EBUF_SIZE;
967  buf = urh->e_buf;
968  }
969  else
970  {
971  /* Normal case: grab all remaining memory from the
972  connection's pool for the IO buffers; the connection
973  certainly won't need it anymore as we've upgraded
974  to another protocol. */
975  buf = MHD_pool_allocate (pool,
976  avail,
977  false);
978  }
979  /* use half the buffer for inbound, half for outbound */
980  urh->in_buffer_size = avail / 2;
981  urh->out_buffer_size = avail - urh->in_buffer_size;
982  urh->in_buffer = buf;
983  urh->out_buffer = &buf[urh->in_buffer_size];
984 #ifdef EPOLL_SUPPORT
985  /* Launch IO processing by the event loop */
986  if (0 != (daemon->options & MHD_USE_EPOLL))
987  {
988  /* We're running with epoll(), need to add the sockets
989  to the event set of the daemon's `epoll_upgrade_fd` */
990  struct epoll_event event;
991 
992  mhd_assert (-1 != daemon->epoll_upgrade_fd);
993  /* First, add network socket */
994  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
995  event.data.ptr = &urh->app;
996  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
997  EPOLL_CTL_ADD,
998  connection->socket_fd,
999  &event))
1000  {
1001 #ifdef HAVE_MESSAGES
1002  MHD_DLOG (daemon,
1003  _("Call to epoll_ctl failed: %s\n"),
1005 #endif
1006  MHD_socket_close_chk_ (sv[0]);
1007  MHD_socket_close_chk_ (sv[1]);
1008  free (urh);
1009  return MHD_NO;
1010  }
1011 
1012  /* Second, add our end of the UNIX socketpair() */
1013  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
1014  event.data.ptr = &urh->mhd;
1015  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1016  EPOLL_CTL_ADD,
1017  urh->mhd.socket,
1018  &event))
1019  {
1020  event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
1021  event.data.ptr = &urh->app;
1022  if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
1023  EPOLL_CTL_DEL,
1024  connection->socket_fd,
1025  &event))
1026  MHD_PANIC (_("Error cleaning up while handling epoll error"));
1027 #ifdef HAVE_MESSAGES
1028  MHD_DLOG (daemon,
1029  _("Call to epoll_ctl failed: %s\n"),
1031 #endif
1032  MHD_socket_close_chk_ (sv[0]);
1033  MHD_socket_close_chk_ (sv[1]);
1034  free (urh);
1035  return MHD_NO;
1036  }
1037  EDLL_insert (daemon->eready_urh_head,
1038  daemon->eready_urh_tail,
1039  urh);
1040  urh->in_eready_list = true;
1041  }
1042 #endif /* EPOLL_SUPPORT */
1043  if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
1044  {
1045  /* This takes care of further processing for most event loops:
1046  simply add to DLL for bi-direcitonal processing */
1047  DLL_insert (daemon->urh_head,
1048  daemon->urh_tail,
1049  urh);
1050  }
1051  /* In thread-per-connection mode, thread will switch to forwarding once
1052  * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
1053  */
1054  }
1055  else
1056  {
1057  urh->app.socket = MHD_INVALID_SOCKET;
1058  urh->mhd.socket = MHD_INVALID_SOCKET;
1059  /* Non-TLS connection do not hold any additional resources. */
1060  urh->clean_ready = true;
1061  }
1062 #else /* ! HTTPS_SUPPORT */
1063  urh->clean_ready = true;
1064 #endif /* ! HTTPS_SUPPORT */
1065  connection->urh = urh;
1066  /* As far as MHD's event loops are concerned, this connection is
1067  suspended; it will be resumed once application is done by the
1068  #MHD_upgrade_action() function */
1069  internal_suspend_connection_ (connection);
1070 
1071  /* hand over socket to application */
1072  response->upgrade_handler (response->upgrade_handler_cls,
1073  connection,
1074  connection->client_context,
1075  connection->read_buffer,
1076  rbo,
1077 #ifdef HTTPS_SUPPORT
1078  (0 == (daemon->options & MHD_USE_TLS) ) ?
1079  connection->socket_fd : urh->app.socket,
1080 #else /* ! HTTPS_SUPPORT */
1081  connection->socket_fd,
1082 #endif /* ! HTTPS_SUPPORT */
1083  urh);
1084  return MHD_YES;
1085 }
1086 
1087 
1117 _MHD_EXTERN struct MHD_Response *
1119  void *upgrade_handler_cls)
1120 {
1121  struct MHD_Response *response;
1122 
1123  if (NULL == upgrade_handler)
1124  return NULL; /* invalid request */
1125  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
1126  if (NULL == response)
1127  return NULL;
1128 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1129  if (! MHD_mutex_init_ (&response->mutex))
1130  {
1131  free (response);
1132  return NULL;
1133  }
1134 #endif
1135  response->upgrade_handler = upgrade_handler;
1136  response->upgrade_handler_cls = upgrade_handler_cls;
1137  response->total_size = MHD_SIZE_UNKNOWN;
1138  response->reference_count = 1;
1139  if (MHD_NO ==
1140  MHD_add_response_header (response,
1142  "Upgrade"))
1143  {
1144  MHD_destroy_response (response);
1145  return NULL;
1146  }
1147  return response;
1148 }
1149 #endif /* UPGRADE_SUPPORT */
1150 
1151 
1161 void
1163 {
1164  struct MHD_HTTP_Header *pos;
1165 
1166  if (NULL == response)
1167  return;
1168 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1169  MHD_mutex_lock_chk_ (&response->mutex);
1170 #endif
1171  if (0 != --(response->reference_count))
1172  {
1173 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1174  MHD_mutex_unlock_chk_ (&response->mutex);
1175 #endif
1176  return;
1177  }
1178 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1179  MHD_mutex_unlock_chk_ (&response->mutex);
1180  MHD_mutex_destroy_chk_ (&response->mutex);
1181 #endif
1182  if (NULL != response->crfc)
1183  response->crfc (response->crc_cls);
1184  while (NULL != response->first_header)
1185  {
1186  pos = response->first_header;
1187  response->first_header = pos->next;
1188  free (pos->header);
1189  free (pos->value);
1190  free (pos);
1191  }
1192  free (response);
1193 }
1194 
1195 
1201 void
1203 {
1204 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1205  MHD_mutex_lock_chk_ (&response->mutex);
1206 #endif
1207  (response->reference_count)++;
1208 #if defined(MHD_USE_POSIX_THREADS) || defined(MHD_USE_W32_THREADS)
1209  MHD_mutex_unlock_chk_ (&response->mutex);
1210 #endif
1211 }
1212 
1213 
1214 /* end of response.c */
#define SSIZE_MAX
Definition: mhd_limits.h:111
#define MHD_FILE_READ_BLOCK_SIZE
Definition: response.c:67
int(* MHD_KeyValueIterator)(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
Definition: microhttpd.h:2163
#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:373
uint64_t fd_off
Definition: internal.h:1650
enum MHD_CONNECTION_STATE state
Definition: internal.h:925
void * data
Definition: microhttpd.h:2948
_MHD_EXTERN int MHD_add_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:133
void int int must_copy
Definition: microhttpd.h:2948
int MHD_set_response_options(struct MHD_Response *response, enum MHD_ResponseFlags flags,...)
Definition: response.c:413
#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:2257
#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:140
char * data
Definition: internal.h:1585
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd64(uint64_t size, int fd)
Definition: response.c:652
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:603
int MHD_socket
Definition: microhttpd.h:187
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:2885
#define DLL_insert(head, tail, element)
Definition: internal.h:1742
void MHD_increment_response_rc(struct MHD_Response *response)
Definition: response.c:1202
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:3076
void * client_context
Definition: internal.h:693
#define MHD_INVALID_SOCKET
Definition: microhttpd.h:188
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:175
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset64(uint64_t size, int fd, uint64_t offset)
Definition: response.c:587
enum MHD_FLAG options
Definition: internal.h:1600
#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:2241
unsigned int reference_count
Definition: internal.h:1672
_MHD_EXTERN void MHD_destroy_response(struct MHD_Response *response)
Definition: response.c:1162
struct MHD_Action action
Definition: internal.h:1572
#define _MHD_EXTERN
Definition: mhd_options.h:51
void int must_free
Definition: microhttpd.h:2948
#define MHD_CONTENT_READER_END_OF_STREAM
Definition: microhttpd.h:166
#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:676
MHD_ValueKind
Definition: microhttpd.h:1684
Header for string manipulating helpers.
char * read_buffer
Definition: internal.h:733
size_t value_size
Definition: internal.h:286
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd(size_t size, int fd)
Definition: response.c:629
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
Definition: response.c:449
_MHD_EXTERN int MHD_upgrade_action(struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action,...)
int off_t offset
Definition: microhttpd.h:3076
void internal_suspend_connection_(struct MHD_Connection *connection)
Definition: daemon.c:2760
size_t header_size
Definition: internal.h:276
_MHD_EXTERN struct MHD_Response * MHD_create_response_from_buffer(size_t size, void *buffer, enum MHD_ResponseMemoryMode mode)
Definition: response.c:734
#define mhd_assert(CHK)
Definition: mhd_assert.h:39
enum MHD_ResponseFlags flags
Definition: internal.h:397
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:3203
#define MHD_SCKT_FD_FITS_FDSET_(fd, pset)
Definition: mhd_sockets.h:299
#define MHD_HTTP_HEADER_CONNECTION
Definition: microhttpd.h:539
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:167
MHD_ContentReaderCallback crc
Definition: internal.h:1597
MHD_UpgradeAction
Definition: microhttpd.h:3116
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:756
#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:82
#define MHD_HTTP_HEADER_CONTENT_LENGTH
Definition: microhttpd.h:545
#define MHD_SIZE_UNKNOWN
Definition: microhttpd.h:159
_MHD_EXTERN int MHD_del_response_header(struct MHD_Response *response, const char *header, const char *content)
Definition: response.c:196
size_t read_buffer_offset
Definition: internal.h:784
#define MHD_NO
Definition: microhttpd.h:145
volatile bool shutdown
Definition: internal.h:1523
MHD_ResponseFlags
Definition: microhttpd.h:2854
_MHD_EXTERN const char * MHD_get_response_header(struct MHD_Response *response, const char *key)
Definition: response.c:282
limits values definitions
#define MHD_HTTP_HEADER_TRANSFER_ENCODING
Definition: microhttpd.h:601
struct MHD_Response * MHD_create_response_from_fd_at_offset(size_t size, int fd, off_t offset)
Definition: response.c:560
bool MHD_check_response_header_token_ci(const struct MHD_Response *response, const char *key, size_t key_len, const char *token, size_t token_len)
Definition: response.c:321
_MHD_EXTERN int MHD_get_response_headers(struct MHD_Response *response, MHD_KeyValueIterator iterator, void *iterator_cls)
Definition: response.c:250
MHD_ResponseMemoryMode
Definition: microhttpd.h:2958
bool MHD_str_equal_caseless_bin_n_(const char *const str1, const char *const str2, size_t len)
Definition: mhd_str.c:389
_MHD_EXTERN void MHD_resume_connection(struct MHD_Connection *connection)
Definition: daemon.c:2884
static void free_callback(void *cls)
Definition: response.c:533