Blame src/microhttpd/response.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2007, 2009, 2010, 2016, 2017 Daniel Pittman and Christian Grothoff
Packit 875988
Packit 875988
     This library is free software; you can redistribute it and/or
Packit 875988
     modify it under the terms of the GNU Lesser General Public
Packit 875988
     License as published by the Free Software Foundation; either
Packit 875988
     version 2.1 of the License, or (at your option) any later version.
Packit 875988
Packit 875988
     This library is distributed in the hope that it will be useful,
Packit 875988
     but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     Lesser General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU Lesser General Public
Packit 875988
     License along with this library; if not, write to the Free Software
Packit 875988
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit 875988
*/
Packit 875988
/**
Packit 875988
 * @file response.c
Packit 875988
 * @brief  Methods for managing response objects
Packit 875988
 * @author Daniel Pittman
Packit 875988
 * @author Christian Grothoff
Packit 875988
 * @author Karlson2k (Evgeny Grin)
Packit 875988
 */
Packit 875988
Packit 875988
#define MHD_NO_DEPRECATION 1
Packit 875988
Packit 875988
#include "mhd_options.h"
Packit 875988
#ifdef HAVE_SYS_IOCTL_H
Packit 875988
#include <sys/ioctl.h>
Packit 875988
#endif /* HAVE_SYS_IOCTL_H */
Packit 875988
#if defined(_WIN32) && ! defined(__CYGWIN__)
Packit 875988
#include <windows.h>
Packit 875988
#endif /* _WIN32 && !__CYGWIN__ */
Packit 875988
Packit 875988
#include "internal.h"
Packit 875988
#include "response.h"
Packit 875988
#include "mhd_limits.h"
Packit 875988
#include "mhd_sockets.h"
Packit 875988
#include "mhd_itc.h"
Packit 875988
#include "mhd_str.h"
Packit 875988
#include "connection.h"
Packit 875988
#include "memorypool.h"
Packit 875988
#include "mhd_compat.h"
Packit 875988
Packit 875988
Packit 875988
#if defined(MHD_W32_MUTEX_)
Packit 875988
#ifndef WIN32_LEAN_AND_MEAN
Packit 875988
#define WIN32_LEAN_AND_MEAN 1
Packit 875988
#endif /* !WIN32_LEAN_AND_MEAN */
Packit 875988
#include <windows.h>
Packit 875988
#endif /* MHD_W32_MUTEX_ */
Packit 875988
#if defined(_WIN32)
Packit 875988
#include <io.h> /* for lseek(), read() */
Packit 875988
#endif /* _WIN32 */
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Add a header or footer line to the response.
Packit 875988
 *
Packit 875988
 * @param response response to add a header to
Packit 875988
 * @param kind header or footer
Packit 875988
 * @param header the header to add
Packit 875988
 * @param content value to add
Packit 875988
 * @return #MHD_NO on error (i.e. invalid header or content format).
Packit 875988
 */
Packit 875988
static int
Packit 875988
add_response_entry (struct MHD_Response *response,
Packit 875988
		    enum MHD_ValueKind kind,
Packit 875988
		    const char *header,
Packit 875988
		    const char *content)
Packit 875988
{
Packit 875988
  struct MHD_HTTP_Header *hdr;
Packit 875988
Packit 875988
  if ( (NULL == response) ||
Packit 875988
       (NULL == header) ||
Packit 875988
       (NULL == content) ||
Packit 875988
       (0 == header[0]) ||
Packit 875988
       (0 == content[0]) ||
Packit 875988
       (NULL != strchr (header, '\t')) ||
Packit 875988
       (NULL != strchr (header, '\r')) ||
Packit 875988
       (NULL != strchr (header, '\n')) ||
Packit 875988
       (NULL != strchr (content, '\t')) ||
Packit 875988
       (NULL != strchr (content, '\r')) ||
Packit 875988
       (NULL != strchr (content, '\n')) )
Packit 875988
    return MHD_NO;
Packit 875988
  if (NULL == (hdr = malloc (sizeof (struct MHD_HTTP_Header))))
Packit 875988
    return MHD_NO;
Packit 875988
  if (NULL == (hdr->header = strdup (header)))
Packit 875988
    {
Packit 875988
      free (hdr);
Packit 875988
      return MHD_NO;
Packit 875988
    }
Packit 875988
  if (NULL == (hdr->value = strdup (content)))
Packit 875988
    {
Packit 875988
      free (hdr->header);
Packit 875988
      free (hdr);
Packit 875988
      return MHD_NO;
Packit 875988
    }
Packit 875988
  hdr->kind = kind;
Packit 875988
  hdr->next = response->first_header;
Packit 875988
  response->first_header = hdr;
Packit 875988
  return MHD_YES;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Add a header line to the response.
Packit 875988
 *
Packit 875988
 * @param response response to add a header to
Packit 875988
 * @param header the header to add
Packit 875988
 * @param content value to add
Packit 875988
 * @return #MHD_NO on error (i.e. invalid header or content format).
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
int
Packit 875988
MHD_add_response_header (struct MHD_Response *response,
Packit 875988
                         const char *header,
Packit 875988
                         const char *content)
Packit 875988
{
Packit 875988
  return add_response_entry (response,
Packit 875988
			     MHD_HEADER_KIND,
Packit 875988
			     header,
Packit 875988
			     content);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Add a footer line to the response.
Packit 875988
 *
Packit 875988
 * @param response response to remove a header from
Packit 875988
 * @param footer the footer to delete
Packit 875988
 * @param content value to delete
Packit 875988
 * @return #MHD_NO on error (i.e. invalid footer or content format).
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
int
Packit 875988
MHD_add_response_footer (struct MHD_Response *response,
Packit 875988
                         const char *footer,
Packit 875988
                         const char *content)
Packit 875988
{
Packit 875988
  return add_response_entry (response,
Packit 875988
			     MHD_FOOTER_KIND,
Packit 875988
			     footer,
Packit 875988
			     content);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Delete a header (or footer) line from the response.
Packit 875988
 *
Packit 875988
 * @param response response to remove a header from
Packit 875988
 * @param header the header to delete
Packit 875988
 * @param content value to delete
Packit 875988
 * @return #MHD_NO on error (no such header known)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
int
Packit 875988
MHD_del_response_header (struct MHD_Response *response,
Packit 875988
                         const char *header,
Packit 875988
			 const char *content)
Packit 875988
{
Packit 875988
  struct MHD_HTTP_Header *pos;
Packit 875988
  struct MHD_HTTP_Header *prev;
Packit 875988
Packit 875988
  if ( (NULL == header) ||
Packit 875988
  (NULL == content) )
Packit 875988
    return MHD_NO;
Packit 875988
  prev = NULL;
Packit 875988
  pos = response->first_header;
Packit 875988
  while (NULL != pos)
Packit 875988
    {
Packit 875988
      if ((0 == strcmp (header,
Packit 875988
                        pos->header)) &&
Packit 875988
          (0 == strcmp (content,
Packit 875988
                        pos->value)))
Packit 875988
        {
Packit 875988
          free (pos->header);
Packit 875988
          free (pos->value);
Packit 875988
          if (NULL == prev)
Packit 875988
            response->first_header = pos->next;
Packit 875988
          else
Packit 875988
            prev->next = pos->next;
Packit 875988
          free (pos);
Packit 875988
          return MHD_YES;
Packit 875988
        }
Packit 875988
      prev = pos;
Packit 875988
      pos = pos->next;
Packit 875988
    }
Packit 875988
  return MHD_NO;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Get all of the headers (and footers) added to a response.
Packit 875988
 *
Packit 875988
 * @param response response to query
Packit 875988
 * @param iterator callback to call on each header;
Packit 875988
 *        maybe NULL (then just count headers)
Packit 875988
 * @param iterator_cls extra argument to @a iterator
Packit 875988
 * @return number of entries iterated over
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
int
Packit 875988
MHD_get_response_headers (struct MHD_Response *response,
Packit 875988
                          MHD_KeyValueIterator iterator,
Packit 875988
                          void *iterator_cls)
Packit 875988
{
Packit 875988
  int numHeaders = 0;
Packit 875988
  struct MHD_HTTP_Header *pos;
Packit 875988
Packit 875988
  for (pos = response->first_header;
Packit 875988
       NULL != pos;
Packit 875988
       pos = pos->next)
Packit 875988
    {
Packit 875988
      numHeaders++;
Packit 875988
      if ((NULL != iterator) &&
Packit 875988
          (MHD_YES != iterator (iterator_cls,
Packit 875988
                                pos->kind,
Packit 875988
                                pos->header,
Packit 875988
                                pos->value)))
Packit 875988
        break;
Packit 875988
    }
Packit 875988
  return numHeaders;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Get a particular header (or footer) from the response.
Packit 875988
 *
Packit 875988
 * @param response response to query
Packit 875988
 * @param key which header to get
Packit 875988
 * @return NULL if header does not exist
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
const char *
Packit 875988
MHD_get_response_header (struct MHD_Response *response,
Packit 875988
			 const char *key)
Packit 875988
{
Packit 875988
  struct MHD_HTTP_Header *pos;
Packit 875988
Packit 875988
  if (NULL == key)
Packit 875988
    return NULL;
Packit 875988
  for (pos = response->first_header;
Packit 875988
       NULL != pos;
Packit 875988
       pos = pos->next)
Packit 875988
    {
Packit 875988
      if ( MHD_str_equal_caseless_ (pos->header, key) )
Packit 875988
        return pos->value;
Packit 875988
    }
Packit 875988
  return NULL;
Packit 875988
}
Packit 875988
Packit 875988
/**
Packit 875988
 * Check whether response header contains particular token.
Packit 875988
 *
Packit 875988
 * Token could be surrounded by spaces and tabs and delimited by comma.
Packit 875988
 * Case-insensitive match used for header names and tokens.
Packit 875988
 *
Packit 875988
 * @param response  the response to query
Packit 875988
 * @param key       header name
Packit 875988
 * @param token     the token to find
Packit 875988
 * @param token_len the length of token, not including optional
Packit 875988
 *                  terminating null-character.
Packit 875988
 * @return true if token is found in specified header,
Packit 875988
 *         false otherwise
Packit 875988
 */
Packit 875988
bool
Packit 875988
MHD_check_response_header_token_ci (const struct MHD_Response *response,
Packit 875988
                                    const char *key,
Packit 875988
                                    const char *token,
Packit 875988
                                    size_t token_len)
Packit 875988
{
Packit 875988
  struct MHD_HTTP_Header *pos;
Packit 875988
Packit 875988
  if ( (NULL == key) ||
Packit 875988
       ('\0' == key[0]) ||
Packit 875988
       (NULL == token) ||
Packit 875988
       ('\0' == token[0]) )
Packit 875988
    return false;
Packit 875988
Packit 875988
  for (pos = response->first_header;
Packit 875988
       NULL != pos;
Packit 875988
       pos = pos->next)
Packit 875988
    {
Packit 875988
      if ( (pos->kind == MHD_HEADER_KIND) &&
Packit 875988
           MHD_str_equal_caseless_ (pos->header,
Packit 875988
                                    key) &&
Packit 875988
           MHD_str_has_token_caseless_ (pos->value,
Packit 875988
                                        token,
Packit 875988
                                        token_len) )
Packit 875988
        return true;
Packit 875988
    }
Packit 875988
  return false;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown
Packit 875988
 * @param block_size preferred block size for querying crc (advisory only,
Packit 875988
 *                   MHD may still call @a crc using smaller chunks); this
Packit 875988
 *                   is essentially the buffer size used for IO, clients
Packit 875988
 *                   should pick a value that is appropriate for IO and
Packit 875988
 *                   memory performance requirements
Packit 875988
 * @param crc callback to use to obtain response data
Packit 875988
 * @param crc_cls extra argument to @a crc
Packit 875988
 * @param crfc callback to call to free @a crc_cls resources
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
struct MHD_Response *
Packit 875988
MHD_create_response_from_callback (uint64_t size,
Packit 875988
                                   size_t block_size,
Packit 875988
                                   MHD_ContentReaderCallback crc,
Packit 875988
                                   void *crc_cls,
Packit 875988
                                   MHD_ContentReaderFreeCallback crfc)
Packit 875988
{
Packit 875988
  struct MHD_Response *response;
Packit 875988
Packit 875988
  if ((NULL == crc) || (0 == block_size))
Packit 875988
    return NULL;
Packit 875988
  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response) + block_size)))
Packit 875988
    return NULL;
Packit 875988
  response->fd = -1;
Packit 875988
  response->data = (void *) &response[1];
Packit 875988
  response->data_buffer_size = block_size;
Packit 875988
  if (! MHD_mutex_init_ (&response->mutex))
Packit 875988
  {
Packit 875988
    free (response);
Packit 875988
    return NULL;
Packit 875988
  }
Packit 875988
  response->crc = crc;
Packit 875988
  response->crfc = crfc;
Packit 875988
  response->crc_cls = crc_cls;
Packit 875988
  response->reference_count = 1;
Packit 875988
  response->total_size = size;
Packit 875988
  return response;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Set special flags and options for a response.
Packit 875988
 *
Packit 875988
 * @param response the response to modify
Packit 875988
 * @param flags to set for the response
Packit 875988
 * @param ... #MHD_RO_END terminated list of options
Packit 875988
 * @return #MHD_YES on success, #MHD_NO on error
Packit 875988
 */
Packit 875988
int
Packit 875988
MHD_set_response_options (struct MHD_Response *response,
Packit 875988
                          enum MHD_ResponseFlags flags,
Packit 875988
                          ...)
Packit 875988
{
Packit 875988
  va_list ap;
Packit 875988
  int ret;
Packit 875988
  enum MHD_ResponseOptions ro;
Packit 875988
Packit 875988
  ret = MHD_YES;
Packit 875988
  response->flags = flags;
Packit 875988
  va_start (ap, flags);
Packit 875988
  while (MHD_RO_END != (ro = va_arg (ap, enum MHD_ResponseOptions)))
Packit 875988
  {
Packit 875988
    switch (ro)
Packit 875988
    {
Packit 875988
    default:
Packit 875988
      ret = MHD_NO;
Packit 875988
      break;
Packit 875988
    }
Packit 875988
  }
Packit 875988
  va_end (ap);
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Given a file descriptor, read data from the file
Packit 875988
 * to generate the response.
Packit 875988
 *
Packit 875988
 * @param cls pointer to the response
Packit 875988
 * @param pos offset in the file to access
Packit 875988
 * @param buf where to write the data
Packit 875988
 * @param max number of bytes to write at most
Packit 875988
 * @return number of bytes written
Packit 875988
 */
Packit 875988
static ssize_t
Packit 875988
file_reader (void *cls,
Packit 875988
             uint64_t pos,
Packit 875988
             char *buf,
Packit 875988
             size_t max)
Packit 875988
{
Packit 875988
  struct MHD_Response *response = cls;
Packit 875988
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 875988
  ssize_t n;
Packit 875988
#else  /* _WIN32 && !__CYGWIN__ */
Packit 875988
  const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
Packit 875988
#endif /* _WIN32 && !__CYGWIN__ */
Packit 875988
  const int64_t offset64 = (int64_t)(pos + response->fd_off);
Packit 875988
Packit 875988
  if (offset64 < 0)
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
Packit 875988
Packit 875988
#if !defined(_WIN32) || defined(__CYGWIN__)
Packit 875988
  if (max > SSIZE_MAX)
Packit 875988
    max = SSIZE_MAX; /* Clamp to maximum return value. */
Packit 875988
Packit 875988
#if defined(HAVE_PREAD64)
Packit 875988
  n = pread64(response->fd, buf, max, offset64);
Packit 875988
#elif defined(HAVE_PREAD)
Packit 875988
  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
Packit 875988
       (offset64 > (uint64_t)INT32_MAX) )
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
Packit 875988
Packit 875988
  n = pread(response->fd, buf, max, (off_t) offset64);
Packit 875988
#else  /* ! HAVE_PREAD */
Packit 875988
#if defined(HAVE_LSEEK64)
Packit 875988
  if (lseek64 (response->fd,
Packit 875988
               offset64,
Packit 875988
               SEEK_SET) != offset64)
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
Packit 875988
#else  /* ! HAVE_LSEEK64 */
Packit 875988
  if ( (sizeof(off_t) < sizeof (uint64_t)) &&
Packit 875988
       (offset64 > (uint64_t)INT32_MAX) )
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
Packit 875988
Packit 875988
  if (lseek (response->fd,
Packit 875988
             (off_t) offset64,
Packit 875988
             SEEK_SET) != (off_t) offset64)
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
Packit 875988
#endif /* ! HAVE_LSEEK64 */
Packit 875988
  n = read (response->fd,
Packit 875988
            buf,
Packit 875988
            max);
Packit 875988
Packit 875988
#endif /* ! HAVE_PREAD */
Packit 875988
  if (0 == n)
Packit 875988
    return MHD_CONTENT_READER_END_OF_STREAM;
Packit 875988
  if (n < 0)
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR;
Packit 875988
  return n;
Packit 875988
#else /* _WIN32 && !__CYGWIN__ */
Packit 875988
  if (INVALID_HANDLE_VALUE == fh)
Packit 875988
    return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
Packit 875988
  else
Packit 875988
    {
Packit 875988
      OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
Packit 875988
      ULARGE_INTEGER pos_uli;
Packit 875988
      DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
Packit 875988
      DWORD resRead;
Packit 875988
Packit 875988
      pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
Packit 875988
      f_ol.Offset = pos_uli.LowPart;
Packit 875988
      f_ol.OffsetHigh = pos_uli.HighPart;
Packit 875988
      if (! ReadFile(fh, (void*)buf, toRead, &resRead, &f_ol))
Packit 875988
        return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
Packit 875988
      if (0 == resRead)
Packit 875988
        return MHD_CONTENT_READER_END_OF_STREAM;
Packit 875988
      return (ssize_t) resRead;
Packit 875988
    }
Packit 875988
#endif /* _WIN32 && !__CYGWIN__ */
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Destroy file reader context.  Closes the file
Packit 875988
 * descriptor.
Packit 875988
 *
Packit 875988
 * @param cls pointer to file descriptor
Packit 875988
 */
Packit 875988
static void
Packit 875988
free_callback (void *cls)
Packit 875988
{
Packit 875988
  struct MHD_Response *response = cls;
Packit 875988
Packit 875988
  (void) close (response->fd);
Packit 875988
  response->fd = -1;
Packit 875988
}
Packit 875988
Packit 875988
#undef MHD_create_response_from_fd_at_offset
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the data portion of the response
Packit 875988
 * @param fd file descriptor referring to a file on disk with the
Packit 875988
 *        data; will be closed when response is destroyed;
Packit 875988
 *        fd should be in 'blocking' mode
Packit 875988
 * @param offset offset to start reading from in the file;
Packit 875988
 *        Be careful! `off_t` may have been compiled to be a
Packit 875988
 *        64-bit variable for MHD, in which case your application
Packit 875988
 *        also has to be compiled using the same options! Read
Packit 875988
 *        the MHD manual for more details.
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
struct MHD_Response *
Packit 875988
MHD_create_response_from_fd_at_offset (size_t size,
Packit 875988
				       int fd,
Packit 875988
				       off_t offset)
Packit 875988
{
Packit 875988
  return MHD_create_response_from_fd_at_offset64 (size,
Packit 875988
                                                  fd,
Packit 875988
                                                  offset);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the data portion of the response;
Packit 875988
 *        sizes larger than 2 GiB may be not supported by OS or
Packit 875988
 *        MHD build; see ::MHD_FEATURE_LARGE_FILE
Packit 875988
 * @param fd file descriptor referring to a file on disk with the
Packit 875988
 *        data; will be closed when response is destroyed;
Packit 875988
 *        fd should be in 'blocking' mode
Packit 875988
 * @param offset offset to start reading from in the file;
Packit 875988
 *        reading file beyond 2 GiB may be not supported by OS or
Packit 875988
 *        MHD build; see ::MHD_FEATURE_LARGE_FILE
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
_MHD_EXTERN struct MHD_Response *
Packit 875988
MHD_create_response_from_fd_at_offset64 (uint64_t size,
Packit 875988
                                         int fd,
Packit 875988
                                         uint64_t offset)
Packit 875988
{
Packit 875988
  struct MHD_Response *response;
Packit 875988
Packit 875988
#if !defined(HAVE___LSEEKI64) && !defined(HAVE_LSEEK64)
Packit 875988
  if ( (sizeof(uint64_t) > sizeof(off_t)) &&
Packit 875988
       ( (size > (uint64_t)INT32_MAX) ||
Packit 875988
         (offset > (uint64_t)INT32_MAX) ||
Packit 875988
         ((size + offset) >= (uint64_t)INT32_MAX) ) )
Packit 875988
    return NULL;
Packit 875988
#endif
Packit 875988
  if ( ((int64_t)size < 0) ||
Packit 875988
       ((int64_t)offset < 0) ||
Packit 875988
       ((int64_t)(size + offset) < 0) )
Packit 875988
    return NULL;
Packit 875988
Packit 875988
  response = MHD_create_response_from_callback (size,
Packit 875988
						4 * 1024,
Packit 875988
						&file_reader,
Packit 875988
						NULL,
Packit 875988
						&free_callback);
Packit 875988
  if (NULL == response)
Packit 875988
    return NULL;
Packit 875988
  response->fd = fd;
Packit 875988
  response->fd_off = offset;
Packit 875988
  response->crc_cls = response;
Packit 875988
  return response;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the data portion of the response
Packit 875988
 * @param fd file descriptor referring to a file on disk with the data
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
struct MHD_Response *
Packit 875988
MHD_create_response_from_fd (size_t size,
Packit 875988
			     int fd)
Packit 875988
{
Packit 875988
  return MHD_create_response_from_fd_at_offset64 (size,
Packit 875988
                                                  fd,
Packit 875988
                                                  0);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the data portion of the response;
Packit 875988
 *        sizes larger than 2 GiB may be not supported by OS or
Packit 875988
 *        MHD build; see ::MHD_FEATURE_LARGE_FILE
Packit 875988
 * @param fd file descriptor referring to a file on disk with the
Packit 875988
 *        data; will be closed when response is destroyed;
Packit 875988
 *        fd should be in 'blocking' mode
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
_MHD_EXTERN struct MHD_Response *
Packit 875988
MHD_create_response_from_fd64 (uint64_t size,
Packit 875988
                               int fd)
Packit 875988
{
Packit 875988
  return MHD_create_response_from_fd_at_offset64 (size,
Packit 875988
                                                  fd,
Packit 875988
                                                  0);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the @a data portion of the response
Packit 875988
 * @param data the data itself
Packit 875988
 * @param must_free libmicrohttpd should free data when done
Packit 875988
 * @param must_copy libmicrohttpd must make a copy of @a data
Packit 875988
 *        right away, the data maybe released anytime after
Packit 875988
 *        this call returns
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @deprecated use #MHD_create_response_from_buffer instead
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
struct MHD_Response *
Packit 875988
MHD_create_response_from_data (size_t size,
Packit 875988
                               void *data,
Packit 875988
                               int must_free,
Packit 875988
                               int must_copy)
Packit 875988
{
Packit 875988
  struct MHD_Response *response;
Packit 875988
  void *tmp;
Packit 875988
Packit 875988
  if ((NULL == data) && (size > 0))
Packit 875988
    return NULL;
Packit 875988
  if (NULL == (response = MHD_calloc_ (1, sizeof (struct MHD_Response))))
Packit 875988
    return NULL;
Packit 875988
  response->fd = -1;
Packit 875988
  if (! MHD_mutex_init_ (&response->mutex))
Packit 875988
    {
Packit 875988
      free (response);
Packit 875988
      return NULL;
Packit 875988
    }
Packit 875988
  if ((must_copy) && (size > 0))
Packit 875988
    {
Packit 875988
      if (NULL == (tmp = malloc (size)))
Packit 875988
        {
Packit 875988
          MHD_mutex_destroy_chk_ (&response->mutex);
Packit 875988
          free (response);
Packit 875988
          return NULL;
Packit 875988
        }
Packit 875988
      memcpy (tmp, data, size);
Packit 875988
      must_free = MHD_YES;
Packit 875988
      data = tmp;
Packit 875988
    }
Packit 875988
  if (must_free)
Packit 875988
    {
Packit 875988
      response->crfc = &fre;;
Packit 875988
      response->crc_cls = data;
Packit 875988
    }
Packit 875988
  response->reference_count = 1;
Packit 875988
  response->total_size = size;
Packit 875988
  response->data = data;
Packit 875988
  response->data_size = size;
Packit 875988
  return response;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object.  The response object can be extended with
Packit 875988
 * header information and then be used any number of times.
Packit 875988
 *
Packit 875988
 * @param size size of the data portion of the response
Packit 875988
 * @param buffer size bytes containing the response's data portion
Packit 875988
 * @param mode flags for buffer management
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
struct MHD_Response *
Packit 875988
MHD_create_response_from_buffer (size_t size,
Packit 875988
				 void *buffer,
Packit 875988
				 enum MHD_ResponseMemoryMode mode)
Packit 875988
{
Packit 875988
  return MHD_create_response_from_data (size,
Packit 875988
					buffer,
Packit 875988
					mode == MHD_RESPMEM_MUST_FREE,
Packit 875988
					mode == MHD_RESPMEM_MUST_COPY);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
#ifdef UPGRADE_SUPPORT
Packit 875988
/**
Packit 875988
 * This connection-specific callback is provided by MHD to
Packit 875988
 * applications (unusual) during the #MHD_UpgradeHandler.
Packit 875988
 * It allows applications to perform 'special' actions on
Packit 875988
 * the underlying socket from the upgrade.
Packit 875988
 *
Packit 875988
 * @param urh the handle identifying the connection to perform
Packit 875988
 *            the upgrade @a action on.
Packit 875988
 * @param action which action should be performed
Packit 875988
 * @param ... arguments to the action (depends on the action)
Packit 875988
 * @return #MHD_NO on error, #MHD_YES on success
Packit 875988
 */
Packit 875988
_MHD_EXTERN int
Packit 875988
MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
Packit 875988
                    enum MHD_UpgradeAction action,
Packit 875988
                    ...)
Packit 875988
{
Packit 875988
  struct MHD_Connection *connection;
Packit 875988
  struct MHD_Daemon *daemon;
Packit 875988
Packit 875988
  if (NULL == urh)
Packit 875988
    return MHD_NO;
Packit 875988
  connection = urh->connection;
Packit 875988
Packit 875988
  /* Precaution checks on external data. */
Packit 875988
  if (NULL == connection)
Packit 875988
    return MHD_NO;
Packit 875988
  daemon = connection->daemon;
Packit 875988
  if (NULL == daemon)
Packit 875988
    return MHD_NO;
Packit 875988
Packit 875988
  switch (action)
Packit 875988
  {
Packit 875988
  case MHD_UPGRADE_ACTION_CLOSE:
Packit 875988
    if (urh->was_closed)
Packit 875988
      return MHD_NO; /* Already closed. */
Packit 875988
Packit 875988
    /* transition to special 'closed' state for start of cleanup */
Packit 875988
#ifdef HTTPS_SUPPORT
Packit 875988
    if (0 != (daemon->options & MHD_USE_TLS) )
Packit 875988
      {
Packit 875988
        /* signal that app is done by shutdown() of 'app' socket */
Packit 875988
        /* Application will not use anyway this socket after this command. */
Packit 875988
        shutdown (urh->app.socket,
Packit 875988
                  SHUT_RDWR);
Packit 875988
      }
Packit 875988
#endif /* HTTPS_SUPPORT */
Packit 875988
    mhd_assert (MHD_CONNECTION_UPGRADE == connection->state);
Packit 875988
    urh->was_closed = true;
Packit 875988
    /* As soon as connection will be marked with BOTH
Packit 875988
     * 'urh->was_closed' AND 'urh->clean_ready', it will
Packit 875988
     * be moved to cleanup list by MHD_resume_connection(). */
Packit 875988
    MHD_resume_connection (connection);
Packit 875988
    return MHD_YES;
Packit 875988
  default:
Packit 875988
    /* we don't understand this one */
Packit 875988
    return MHD_NO;
Packit 875988
  }
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * We are done sending the header of a given response to the client.
Packit 875988
 * Now it is time to perform the upgrade and hand over the connection
Packit 875988
 * to the application.
Packit 875988
 * @remark To be called only from thread that process connection's
Packit 875988
 * recv(), send() and response. Must be called right after sending
Packit 875988
 * response headers.
Packit 875988
 *
Packit 875988
 * @param response the response that was created for an upgrade
Packit 875988
 * @param connection the specific connection we are upgrading
Packit 875988
 * @return #MHD_YES on success, #MHD_NO on failure (will cause
Packit 875988
 *        connection to be closed)
Packit 875988
 */
Packit 875988
int
Packit 875988
MHD_response_execute_upgrade_ (struct MHD_Response *response,
Packit 875988
                               struct MHD_Connection *connection)
Packit 875988
{
Packit 875988
  struct MHD_Daemon *daemon = connection->daemon;
Packit 875988
  struct MHD_UpgradeResponseHandle *urh;
Packit 875988
  size_t rbo;
Packit 875988
Packit 875988
  if (0 == (daemon->options & MHD_ALLOW_UPGRADE))
Packit 875988
    return MHD_NO;
Packit 875988
Packit 875988
  if (NULL ==
Packit 875988
      MHD_get_response_header (response,
Packit 875988
                               MHD_HTTP_HEADER_UPGRADE))
Packit 875988
    {
Packit 875988
#ifdef HAVE_MESSAGES
Packit 875988
      MHD_DLOG (daemon,
Packit 875988
                _("Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"));
Packit 875988
#endif
Packit 875988
      return MHD_NO;
Packit 875988
    }
Packit 875988
Packit 875988
  urh = MHD_calloc_ (1, sizeof (struct MHD_UpgradeResponseHandle));
Packit 875988
  if (NULL == urh)
Packit 875988
    return MHD_NO;
Packit 875988
  urh->connection = connection;
Packit 875988
  rbo = connection->read_buffer_offset;
Packit 875988
  connection->read_buffer_offset = 0;
Packit 875988
#ifdef HTTPS_SUPPORT
Packit 875988
  if (0 != (daemon->options & MHD_USE_TLS) )
Packit 875988
  {
Packit 875988
    struct MemoryPool *pool;
Packit 875988
    size_t avail;
Packit 875988
    char *buf;
Packit 875988
    MHD_socket sv[2];
Packit 875988
#if defined(MHD_socket_nosignal_) || !defined(MHD_socket_pair_nblk_)
Packit 875988
    int res1;
Packit 875988
    int res2;
Packit 875988
#endif /* MHD_socket_nosignal_ || !MHD_socket_pair_nblk_ */
Packit 875988
Packit 875988
#ifdef MHD_socket_pair_nblk_
Packit 875988
    if (! MHD_socket_pair_nblk_ (sv))
Packit 875988
      {
Packit 875988
        free (urh);
Packit 875988
        return MHD_NO;
Packit 875988
      }
Packit 875988
#else  /* !MHD_socket_pair_nblk_ */
Packit 875988
    if (! MHD_socket_pair_ (sv))
Packit 875988
      {
Packit 875988
        free (urh);
Packit 875988
        return MHD_NO;
Packit 875988
      }
Packit 875988
    res1 = MHD_socket_nonblocking_(sv[0]);
Packit 875988
    res2 = MHD_socket_nonblocking_(sv[1]);
Packit 875988
    if ( (! res1) || (! res2) )
Packit 875988
      {
Packit 875988
#ifdef HAVE_MESSAGES
Packit 875988
        MHD_DLOG (daemon,
Packit 875988
		  _("Failed to make loopback sockets non-blocking.\n"));
Packit 875988
#endif
Packit 875988
        if (! res2)
Packit 875988
          {
Packit 875988
            /* Socketpair cannot be used. */
Packit 875988
            MHD_socket_close_chk_ (sv[0]);
Packit 875988
            MHD_socket_close_chk_ (sv[1]);
Packit 875988
            free (urh);
Packit 875988
            return MHD_NO;
Packit 875988
          }
Packit 875988
      }
Packit 875988
#endif /* !MHD_socket_pair_nblk_ */
Packit 875988
#ifdef MHD_socket_nosignal_
Packit 875988
    res1 = MHD_socket_nosignal_(sv[0]);
Packit 875988
    res2 = MHD_socket_nosignal_(sv[1]);
Packit 875988
    if ( (! res1) || (! res2) )
Packit 875988
      {
Packit 875988
#ifdef HAVE_MESSAGES
Packit 875988
        MHD_DLOG (daemon,
Packit 875988
                  _("Failed to set SO_NOSIGPIPE on loopback sockets.\n"));
Packit 875988
#endif
Packit 875988
#ifndef MSG_NOSIGNAL
Packit 875988
        if (!res2)
Packit 875988
          {
Packit 875988
            /* Socketpair cannot be used. */
Packit 875988
            MHD_socket_close_chk_ (sv[0]);
Packit 875988
            MHD_socket_close_chk_ (sv[1]);
Packit 875988
            free (urh);
Packit 875988
            return MHD_NO;
Packit 875988
          }
Packit 875988
#endif /* ! MSG_NOSIGNAL */
Packit 875988
      }
Packit 875988
#endif /* MHD_socket_nosignal_ */
Packit 875988
    if ( (! MHD_SCKT_FD_FITS_FDSET_ (sv[1],
Packit 875988
                                     NULL)) &&
Packit 875988
         (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) )
Packit 875988
      {
Packit 875988
#ifdef HAVE_MESSAGES
Packit 875988
        MHD_DLOG (daemon,
Packit 875988
                  _("Socketpair descriptor larger than FD_SETSIZE: %d > %d\n"),
Packit 875988
                  (int) sv[1],
Packit 875988
                  (int) FD_SETSIZE);
Packit 875988
#endif
Packit 875988
        MHD_socket_close_chk_ (sv[0]);
Packit 875988
        MHD_socket_close_chk_ (sv[1]);
Packit 875988
        free (urh);
Packit 875988
        return MHD_NO;
Packit 875988
      }
Packit 875988
    urh->app.socket = sv[0];
Packit 875988
    urh->app.urh = urh;
Packit 875988
    urh->app.celi = MHD_EPOLL_STATE_UNREADY;
Packit 875988
    urh->mhd.socket = sv[1];
Packit 875988
    urh->mhd.urh = urh;
Packit 875988
    urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
Packit 875988
    pool = connection->pool;
Packit 875988
    avail = MHD_pool_get_free (pool);
Packit 875988
    if (avail < RESERVE_EBUF_SIZE)
Packit 875988
      {
Packit 875988
        /* connection's pool is totally at the limit,
Packit 875988
           use our 'emergency' buffer of #RESERVE_EBUF_SIZE bytes. */
Packit 875988
        avail = RESERVE_EBUF_SIZE;
Packit 875988
        buf = urh->e_buf;
Packit 875988
      }
Packit 875988
    else
Packit 875988
      {
Packit 875988
        /* Normal case: grab all remaining memory from the
Packit 875988
           connection's pool for the IO buffers; the connection
Packit 875988
           certainly won't need it anymore as we've upgraded
Packit 875988
           to another protocol. */
Packit 875988
        buf = MHD_pool_allocate (pool,
Packit 875988
                                 avail,
Packit 875988
                                 MHD_NO);
Packit 875988
      }
Packit 875988
    /* use half the buffer for inbound, half for outbound */
Packit 875988
    urh->in_buffer_size = avail / 2;
Packit 875988
    urh->out_buffer_size = avail - urh->in_buffer_size;
Packit 875988
    urh->in_buffer = buf;
Packit 875988
    urh->out_buffer = &buf[urh->in_buffer_size];
Packit 875988
#ifdef EPOLL_SUPPORT
Packit 875988
    /* Launch IO processing by the event loop */
Packit 875988
    if (0 != (daemon->options & MHD_USE_EPOLL))
Packit 875988
      {
Packit 875988
        /* We're running with epoll(), need to add the sockets
Packit 875988
           to the event set of the daemon's `epoll_upgrade_fd` */
Packit 875988
        struct epoll_event event;
Packit 875988
Packit 875988
        mhd_assert (-1 != daemon->epoll_upgrade_fd);
Packit 875988
        /* First, add network socket */
Packit 875988
        event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
Packit 875988
        event.data.ptr = &urh->app;
Packit 875988
        if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
Packit 875988
                            EPOLL_CTL_ADD,
Packit 875988
                            connection->socket_fd,
Packit 875988
                            &event))
Packit 875988
	{
Packit 875988
#ifdef HAVE_MESSAGES
Packit 875988
          MHD_DLOG (daemon,
Packit 875988
                    _("Call to epoll_ctl failed: %s\n"),
Packit 875988
                    MHD_socket_last_strerr_ ());
Packit 875988
#endif
Packit 875988
          MHD_socket_close_chk_ (sv[0]);
Packit 875988
          MHD_socket_close_chk_ (sv[1]);
Packit 875988
          free (urh);
Packit 875988
          return MHD_NO;
Packit 875988
	}
Packit 875988
Packit 875988
        /* Second, add our end of the UNIX socketpair() */
Packit 875988
        event.events = EPOLLIN | EPOLLOUT | EPOLLPRI | EPOLLET;
Packit 875988
        event.data.ptr = &urh->mhd;
Packit 875988
        if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
Packit 875988
                            EPOLL_CTL_ADD,
Packit 875988
                            urh->mhd.socket,
Packit 875988
                            &event))
Packit 875988
	{
Packit 875988
          event.events = EPOLLIN | EPOLLOUT | EPOLLPRI;
Packit 875988
          event.data.ptr = &urh->app;
Packit 875988
          if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
Packit 875988
                              EPOLL_CTL_DEL,
Packit 875988
                              connection->socket_fd,
Packit 875988
                              &event))
Packit 875988
            MHD_PANIC (_("Error cleaning up while handling epoll error"));
Packit 875988
#ifdef HAVE_MESSAGES
Packit 875988
          MHD_DLOG (daemon,
Packit 875988
                    _("Call to epoll_ctl failed: %s\n"),
Packit 875988
                    MHD_socket_last_strerr_ ());
Packit 875988
#endif
Packit 875988
          MHD_socket_close_chk_ (sv[0]);
Packit 875988
          MHD_socket_close_chk_ (sv[1]);
Packit 875988
          free (urh);
Packit 875988
          return MHD_NO;
Packit 875988
	}
Packit 875988
	EDLL_insert (daemon->eready_urh_head,
Packit 875988
		     daemon->eready_urh_tail,
Packit 875988
		     urh);
Packit 875988
	urh->in_eready_list = true;
Packit 875988
      }
Packit 875988
#endif /* EPOLL_SUPPORT */
Packit 875988
    if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION) )
Packit 875988
      {
Packit 875988
        /* This takes care of further processing for most event loops:
Packit 875988
           simply add to DLL for bi-direcitonal processing */
Packit 875988
        DLL_insert (daemon->urh_head,
Packit 875988
                    daemon->urh_tail,
Packit 875988
                    urh);
Packit 875988
      }
Packit 875988
    /* In thread-per-connection mode, thread will switch to forwarding once
Packit 875988
     * connection.urh is not NULL and connection.state == MHD_CONNECTION_UPGRADE.
Packit 875988
     */
Packit 875988
  }
Packit 875988
  else
Packit 875988
    {
Packit 875988
      urh->app.socket = MHD_INVALID_SOCKET;
Packit 875988
      urh->mhd.socket = MHD_INVALID_SOCKET;
Packit 875988
      /* Non-TLS connection do not hold any additional resources. */
Packit 875988
      urh->clean_ready = true;
Packit 875988
    }
Packit 875988
#else  /* ! HTTPS_SUPPORT */
Packit 875988
  urh->clean_ready = true;
Packit 875988
#endif /* ! HTTPS_SUPPORT */
Packit 875988
  connection->urh = urh;
Packit 875988
  /* As far as MHD's event loops are concerned, this connection is
Packit 875988
     suspended; it will be resumed once application is done by the
Packit 875988
     #MHD_upgrade_action() function */
Packit 875988
  internal_suspend_connection_ (connection);
Packit 875988
Packit 875988
  /* hand over socket to application */
Packit 875988
  response->upgrade_handler (response->upgrade_handler_cls,
Packit 875988
                             connection,
Packit 875988
                             connection->client_context,
Packit 875988
                             connection->read_buffer,
Packit 875988
                             rbo,
Packit 875988
#ifdef HTTPS_SUPPORT
Packit 875988
                             (0 == (daemon->options & MHD_USE_TLS) ) ?
Packit 875988
                             connection->socket_fd : urh->app.socket,
Packit 875988
#else  /* ! HTTPS_SUPPORT */
Packit 875988
                             connection->socket_fd,
Packit 875988
#endif /* ! HTTPS_SUPPORT */
Packit 875988
                             urh);
Packit 875988
  return MHD_YES;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Create a response object that can be used for 101 UPGRADE
Packit 875988
 * responses, for example to implement WebSockets.  After sending the
Packit 875988
 * response, control over the data stream is given to the callback (which
Packit 875988
 * can then, for example, start some bi-directional communication).
Packit 875988
 * If the response is queued for multiple connections, the callback
Packit 875988
 * will be called for each connection.  The callback
Packit 875988
 * will ONLY be called after the response header was successfully passed
Packit 875988
 * to the OS; if there are communication errors before, the usual MHD
Packit 875988
 * connection error handling code will be performed.
Packit 875988
 *
Packit 875988
 * Setting the correct HTTP code (i.e. MHD_HTTP_SWITCHING_PROTOCOLS)
Packit 875988
 * and setting correct HTTP headers for the upgrade must be done
Packit 875988
 * manually (this way, it is possible to implement most existing
Packit 875988
 * WebSocket versions using this API; in fact, this API might be useful
Packit 875988
 * for any protocol switch, not just WebSockets).  Note that
Packit 875988
 * draft-ietf-hybi-thewebsocketprotocol-00 cannot be implemented this
Packit 875988
 * way as the header "HTTP/1.1 101 WebSocket Protocol Handshake"
Packit 875988
 * cannot be generated; instead, MHD will always produce "HTTP/1.1 101
Packit 875988
 * Switching Protocols" (if the response code 101 is used).
Packit 875988
 *
Packit 875988
 * As usual, the response object can be extended with header
Packit 875988
 * information and then be used any number of times (as long as the
Packit 875988
 * header information is not connection-specific).
Packit 875988
 *
Packit 875988
 * @param upgrade_handler function to call with the 'upgraded' socket
Packit 875988
 * @param upgrade_handler_cls closure for @a upgrade_handler
Packit 875988
 * @return NULL on error (i.e. invalid arguments, out of memory)
Packit 875988
 */
Packit 875988
_MHD_EXTERN struct MHD_Response *
Packit 875988
MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler,
Packit 875988
				 void *upgrade_handler_cls)
Packit 875988
{
Packit 875988
  struct MHD_Response *response;
Packit 875988
Packit 875988
  if (NULL == upgrade_handler)
Packit 875988
    return NULL; /* invalid request */
Packit 875988
  response = MHD_calloc_ (1, sizeof (struct MHD_Response));
Packit 875988
  if (NULL == response)
Packit 875988
    return NULL;
Packit 875988
  if (! MHD_mutex_init_ (&response->mutex))
Packit 875988
    {
Packit 875988
      free (response);
Packit 875988
      return NULL;
Packit 875988
    }
Packit 875988
  response->upgrade_handler = upgrade_handler;
Packit 875988
  response->upgrade_handler_cls = upgrade_handler_cls;
Packit 875988
  response->total_size = MHD_SIZE_UNKNOWN;
Packit 875988
  response->reference_count = 1;
Packit 875988
  if (MHD_NO ==
Packit 875988
      MHD_add_response_header (response,
Packit 875988
                               MHD_HTTP_HEADER_CONNECTION,
Packit 875988
                               "Upgrade"))
Packit 875988
    {
Packit 875988
      MHD_destroy_response (response);
Packit 875988
      return NULL;
Packit 875988
    }
Packit 875988
  return response;
Packit 875988
}
Packit 875988
#endif /* UPGRADE_SUPPORT */
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Destroy a response object and associated resources.  Note that
Packit 875988
 * libmicrohttpd may keep some of the resources around if the response
Packit 875988
 * is still in the queue for some clients, so the memory may not
Packit 875988
 * necessarily be freed immediately.
Packit 875988
 *
Packit 875988
 * @param response response to destroy
Packit 875988
 * @ingroup response
Packit 875988
 */
Packit 875988
void
Packit 875988
MHD_destroy_response (struct MHD_Response *response)
Packit 875988
{
Packit 875988
  struct MHD_HTTP_Header *pos;
Packit 875988
Packit 875988
  if (NULL == response)
Packit 875988
    return;
Packit 875988
  MHD_mutex_lock_chk_ (&response->mutex);
Packit 875988
  if (0 != --(response->reference_count))
Packit 875988
    {
Packit 875988
      MHD_mutex_unlock_chk_ (&response->mutex);
Packit 875988
      return;
Packit 875988
    }
Packit 875988
  MHD_mutex_unlock_chk_ (&response->mutex);
Packit 875988
  MHD_mutex_destroy_chk_ (&response->mutex);
Packit 875988
  if (NULL != response->crfc)
Packit 875988
    response->crfc (response->crc_cls);
Packit 875988
  while (NULL != response->first_header)
Packit 875988
    {
Packit 875988
      pos = response->first_header;
Packit 875988
      response->first_header = pos->next;
Packit 875988
      free (pos->header);
Packit 875988
      free (pos->value);
Packit 875988
      free (pos);
Packit 875988
    }
Packit 875988
  free (response);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/**
Packit 875988
 * Increments the reference counter for the @a response.
Packit 875988
 *
Packit 875988
 * @param response object to modify
Packit 875988
 */
Packit 875988
void
Packit 875988
MHD_increment_response_rc (struct MHD_Response *response)
Packit 875988
{
Packit 875988
  MHD_mutex_lock_chk_ (&response->mutex);
Packit 875988
  (response->reference_count)++;
Packit 875988
  MHD_mutex_unlock_chk_ (&response->mutex);
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
/* end of response.c */