C++程序  |  1429行  |  33.35 KB

/*
  This file is part of libmicrohttpd
  Copyright (C) 2007-2015 Daniel Pittman and Christian Grothoff

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

/**
 * @file microhttpd/internal.h
 * @brief  internal shared structures
 * @author Daniel Pittman
 * @author Christian Grothoff
 */

#ifndef INTERNAL_H
#define INTERNAL_H

#include "platform.h"
#include "microhttpd.h"
#include "platform_interface.h"
#if HTTPS_SUPPORT
#include <openssl/ssl.h>
#endif
#if EPOLL_SUPPORT
#include <sys/epoll.h>
#endif
#if HAVE_NETINET_TCP_H
/* for TCP_FASTOPEN */
#include <netinet/tcp.h>
#endif


/**
 * Should we perform additional sanity checks at runtime (on our internal
 * invariants)?  This may lead to aborts, but can be useful for debugging.
 */
#define EXTRA_CHECKS MHD_NO

#define MHD_MAX(a,b) ((a)<(b)) ? (b) : (a)
#define MHD_MIN(a,b) ((a)<(b)) ? (a) : (b)


/**
 * Minimum size by which MHD tries to increment read/write buffers.
 * We usually begin with half the available pool space for the
 * IO-buffer, but if absolutely needed we additively grow by the
 * number of bytes given here (up to -- theoretically -- the full pool
 * space).
 */
#define MHD_BUF_INC_SIZE 1024


/**
 * Handler for fatal errors.
 */
extern MHD_PanicCallback mhd_panic;

/**
 * Closure argument for "mhd_panic".
 */
extern void *mhd_panic_cls;

/* If we have Clang or gcc >= 4.5, use __buildin_unreachable() */
#if defined(__clang__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define BUILTIN_NOT_REACHED __builtin_unreachable()
#else
#define BUILTIN_NOT_REACHED
#endif


#if HAVE_MESSAGES
/**
 * Trigger 'panic' action based on fatal errors.
 *
 * @param msg error message (const char *)
 */
#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, msg); BUILTIN_NOT_REACHED; } while (0)
#else
/**
 * Trigger 'panic' action based on fatal errors.
 *
 * @param msg error message (const char *)
 */
#define MHD_PANIC(msg) do { mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); BUILTIN_NOT_REACHED; } while (0)
#endif


/**
 * State of the socket with respect to epoll (bitmask).
 */
enum MHD_EpollState
  {

    /**
     * The socket is not involved with a defined state in epoll right
     * now.
     */
    MHD_EPOLL_STATE_UNREADY = 0,

    /**
     * epoll told us that data was ready for reading, and we did
     * not consume all of it yet.
     */
    MHD_EPOLL_STATE_READ_READY = 1,

    /**
     * epoll told us that space was available for writing, and we did
     * not consume all of it yet.
     */
    MHD_EPOLL_STATE_WRITE_READY = 2,

    /**
     * Is this connection currently in the 'eready' EDLL?
     */
    MHD_EPOLL_STATE_IN_EREADY_EDLL = 4,

    /**
     * Is this connection currently in the 'epoll' set?
     */
    MHD_EPOLL_STATE_IN_EPOLL_SET = 8,

    /**
     * Is this connection currently suspended?
     */
    MHD_EPOLL_STATE_SUSPENDED = 16
  };


/**
 * What is this connection waiting for?
 */
enum MHD_ConnectionEventLoopInfo
  {
    /**
     * We are waiting to be able to read.
     */
    MHD_EVENT_LOOP_INFO_READ = 0,

    /**
     * We are waiting to be able to write.
     */
    MHD_EVENT_LOOP_INFO_WRITE = 1,

    /**
     * We are waiting for the application to provide data.
     */
    MHD_EVENT_LOOP_INFO_BLOCK = 2,

    /**
     * We are finished and are awaiting cleanup.
     */
    MHD_EVENT_LOOP_INFO_CLEANUP = 3
  };


/**
 * Maximum length of a nonce in digest authentication.  32(MD5 Hex) +
 * 8(Timestamp Hex) + 1(NULL); hence 41 should suffice, but Opera
 * (already) takes more (see Mantis #1633), so we've increased the
 * value to support something longer...
 */
#define MAX_NONCE_LENGTH 129


/**
 * A structure representing the internal holder of the
 * nonce-nc map.
 */
struct MHD_NonceNc
{

  /**
   * Nonce counter, a value that increases for each subsequent
   * request for the same nonce.
   */
  unsigned long int nc;

  /**
   * Nonce value:
   */
  char nonce[MAX_NONCE_LENGTH];

};

#if HAVE_MESSAGES
/**
 * fprintf-like helper function for logging debug
 * messages.
 */
void
MHD_DLOG (const struct MHD_Daemon *daemon,
	  const char *format, ...);
#endif


/**
 * Header or cookie in HTTP request or response.
 */
struct MHD_HTTP_Header
{
  /**
   * Headers are kept in a linked list.
   */
  struct MHD_HTTP_Header *next;

  /**
   * The name of the header (key), without
   * the colon.
   */
  char *header;

  /**
   * The value of the header.
   */
  char *value;

  /**
   * Type of the header (where in the HTTP
   * protocol is this header from).
   */
  enum MHD_ValueKind kind;

};


/**
 * Representation of a response.
 */
struct MHD_Response
{

  /**
   * Headers to send for the response.  Initially
   * the linked list is created in inverse order;
   * the order should be inverted before sending!
   */
  struct MHD_HTTP_Header *first_header;

  /**
   * Buffer pointing to data that we are supposed
   * to send as a response.
   */
  char *data;

  /**
   * Closure to give to the content reader @e crc
   * and content reader free callback @e crfc.
   */
  void *crc_cls;

  /**
   * How do we get more data?  NULL if we are
   * given all of the data up front.
   */
  MHD_ContentReaderCallback crc;

  /**
   * NULL if data must not be freed, otherwise
   * either user-specified callback or "&free".
   */
  MHD_ContentReaderFreeCallback crfc;

  /**
   * Mutex to synchronize access to @e data, @e size and
   * @e reference_count.
   */
  MHD_mutex_ mutex;

  /**
   * Set to #MHD_SIZE_UNKNOWN if size is not known.
   */
  uint64_t total_size;

  /**
   * At what offset in the stream is the
   * beginning of @e data located?
   */
  uint64_t data_start;

  /**
   * Offset to start reading from when using @e fd.
   */
  off_t fd_off;

  /**
   * Number of bytes ready in @e data (buffer may be larger
   * than what is filled with payload).
   */
  size_t data_size;

  /**
   * Size of the data buffer @e data.
   */
  size_t data_buffer_size;

  /**
   * Reference count for this response.  Free
   * once the counter hits zero.
   */
  unsigned int reference_count;

  /**
   * File-descriptor if this response is FD-backed.
   */
  int fd;

  /**
   * Flags set for the MHD response.
   */
  enum MHD_ResponseFlags flags;

};


/**
 * States in a state machine for a connection.
 *
 * Transitions are any-state to CLOSED, any state to state+1,
 * FOOTERS_SENT to INIT.  CLOSED is the terminal state and
 * INIT the initial state.
 *
 * Note that transitions for *reading* happen only after
 * the input has been processed; transitions for
 * *writing* happen after the respective data has been
 * put into the write buffer (the write does not have
 * to be completed yet).  A transition to CLOSED or INIT
 * requires the write to be complete.
 */
enum MHD_CONNECTION_STATE
{
  /**
   * Connection just started (no headers received).
   * Waiting for the line with the request type, URL and version.
   */
  MHD_CONNECTION_INIT = 0,

  /**
   * 1: We got the URL (and request type and version).  Wait for a header line.
   */
  MHD_CONNECTION_URL_RECEIVED = MHD_CONNECTION_INIT + 1,

  /**
   * 2: We got part of a multi-line request header.  Wait for the rest.
   */
  MHD_CONNECTION_HEADER_PART_RECEIVED = MHD_CONNECTION_URL_RECEIVED + 1,

  /**
   * 3: We got the request headers.  Process them.
   */
  MHD_CONNECTION_HEADERS_RECEIVED = MHD_CONNECTION_HEADER_PART_RECEIVED + 1,

  /**
   * 4: We have processed the request headers.  Send 100 continue.
   */
  MHD_CONNECTION_HEADERS_PROCESSED = MHD_CONNECTION_HEADERS_RECEIVED + 1,

  /**
   * 5: We have processed the headers and need to send 100 CONTINUE.
   */
  MHD_CONNECTION_CONTINUE_SENDING = MHD_CONNECTION_HEADERS_PROCESSED + 1,

  /**
   * 6: We have sent 100 CONTINUE (or do not need to).  Read the message body.
   */
  MHD_CONNECTION_CONTINUE_SENT = MHD_CONNECTION_CONTINUE_SENDING + 1,

  /**
   * 7: We got the request body.  Wait for a line of the footer.
   */
  MHD_CONNECTION_BODY_RECEIVED = MHD_CONNECTION_CONTINUE_SENT + 1,

  /**
   * 8: We got part of a line of the footer.  Wait for the
   * rest.
   */
  MHD_CONNECTION_FOOTER_PART_RECEIVED = MHD_CONNECTION_BODY_RECEIVED + 1,

  /**
   * 9: We received the entire footer.  Wait for a response to be queued
   * and prepare the response headers.
   */
  MHD_CONNECTION_FOOTERS_RECEIVED = MHD_CONNECTION_FOOTER_PART_RECEIVED + 1,

  /**
   * 10: We have prepared the response headers in the writ buffer.
   * Send the response headers.
   */
  MHD_CONNECTION_HEADERS_SENDING = MHD_CONNECTION_FOOTERS_RECEIVED + 1,

  /**
   * 11: We have sent the response headers.  Get ready to send the body.
   */
  MHD_CONNECTION_HEADERS_SENT = MHD_CONNECTION_HEADERS_SENDING + 1,

  /**
   * 12: We are ready to send a part of a non-chunked body.  Send it.
   */
  MHD_CONNECTION_NORMAL_BODY_READY = MHD_CONNECTION_HEADERS_SENT + 1,

  /**
   * 13: We are waiting for the client to provide more
   * data of a non-chunked body.
   */
  MHD_CONNECTION_NORMAL_BODY_UNREADY = MHD_CONNECTION_NORMAL_BODY_READY + 1,

  /**
   * 14: We are ready to send a chunk.
   */
  MHD_CONNECTION_CHUNKED_BODY_READY = MHD_CONNECTION_NORMAL_BODY_UNREADY + 1,

  /**
   * 15: We are waiting for the client to provide a chunk of the body.
   */
  MHD_CONNECTION_CHUNKED_BODY_UNREADY = MHD_CONNECTION_CHUNKED_BODY_READY + 1,

  /**
   * 16: We have sent the response body. Prepare the footers.
   */
  MHD_CONNECTION_BODY_SENT = MHD_CONNECTION_CHUNKED_BODY_UNREADY + 1,

  /**
   * 17: We have prepared the response footer.  Send it.
   */
  MHD_CONNECTION_FOOTERS_SENDING = MHD_CONNECTION_BODY_SENT + 1,

  /**
   * 18: We have sent the response footer.  Shutdown or restart.
   */
  MHD_CONNECTION_FOOTERS_SENT = MHD_CONNECTION_FOOTERS_SENDING + 1,

  /**
   * 19: This connection is to be closed.
   */
  MHD_CONNECTION_CLOSED = MHD_CONNECTION_FOOTERS_SENT + 1,

  /**
   * 20: This connection is finished (only to be freed)
   */
  MHD_CONNECTION_IN_CLEANUP = MHD_CONNECTION_CLOSED + 1,

  /*
   *  SSL/TLS connection states
   */

  /**
   * The initial connection state for all secure connectoins
   * Handshake messages will be processed in this state & while
   * in the 'MHD_TLS_HELLO_REQUEST' state
   */
  MHD_TLS_CONNECTION_INIT = MHD_CONNECTION_IN_CLEANUP + 1

};

/**
 * Should all state transitions be printed to stderr?
 */
#define DEBUG_STATES MHD_NO


#if HAVE_MESSAGES
#if DEBUG_STATES
const char *
MHD_state_to_string (enum MHD_CONNECTION_STATE state);
#endif
#endif

/**
 * Function to receive plaintext data.
 *
 * @param conn the connection struct
 * @param write_to where to write received data
 * @param max_bytes maximum number of bytes to receive
 * @return number of bytes written to write_to
 */
typedef ssize_t
(*ReceiveCallback) (struct MHD_Connection *conn,
                    void *write_to,
                    size_t max_bytes);


/**
 * Function to transmit plaintext data.
 *
 * @param conn the connection struct
 * @param read_from where to read data to transmit
 * @param max_bytes maximum number of bytes to transmit
 * @return number of bytes transmitted
 */
typedef ssize_t
(*TransmitCallback) (struct MHD_Connection *conn,
                     const void *write_to,
                     size_t max_bytes);


/**
 * State kept for each HTTP request.
 */
struct MHD_Connection
{

#if EPOLL_SUPPORT
  /**
   * Next pointer for the EDLL listing connections that are epoll-ready.
   */
  struct MHD_Connection *nextE;

  /**
   * Previous pointer for the EDLL listing connections that are epoll-ready.
   */
  struct MHD_Connection *prevE;
#endif

  /**
   * Next pointer for the DLL describing our IO state.
   */
  struct MHD_Connection *next;

  /**
   * Previous pointer for the DLL describing our IO state.
   */
  struct MHD_Connection *prev;

  /**
   * Next pointer for the XDLL organizing connections by timeout.
   * This DLL can be either the
   * 'manual_timeout_head/manual_timeout_tail' or the
   * 'normal_timeout_head/normal_timeout_tail', depending on whether a
   * custom timeout is set for the connection.
   */
  struct MHD_Connection *nextX;

  /**
   * Previous pointer for the XDLL organizing connections by timeout.
   */
  struct MHD_Connection *prevX;

  /**
   * Reference to the MHD_Daemon struct.
   */
  struct MHD_Daemon *daemon;

  /**
   * Linked list of parsed headers.
   */
  struct MHD_HTTP_Header *headers_received;

  /**
   * Tail of linked list of parsed headers.
   */
  struct MHD_HTTP_Header *headers_received_tail;

  /**
   * Response to transmit (initially NULL).
   */
  struct MHD_Response *response;

  /**
   * The memory pool is created whenever we first read
   * from the TCP stream and destroyed at the end of
   * each request (and re-created for the next request).
   * In the meantime, this pointer is NULL.  The
   * pool is used for all connection-related data
   * except for the response (which maybe shared between
   * connections) and the IP address (which persists
   * across individual requests).
   */
  struct MemoryPool *pool;

  /**
   * We allow the main application to associate some pointer with the
   * HTTP request, which is passed to each #MHD_AccessHandlerCallback
   * and some other API calls.  Here is where we store it.  (MHD does
   * not know or care what it is).
   */
  void *client_context;

  /**
   * We allow the main application to associate some pointer with the
   * TCP connection (which may span multiple HTTP requests).  Here is
   * where we store it.  (MHD does not know or care what it is).
   * The location is given to the #MHD_NotifyConnectionCallback and
   * also accessible via #MHD_CONNECTION_INFO_SOCKET_CONTEXT.
   */
  void *socket_context;

  /**
   * Request method.  Should be GET/POST/etc.  Allocated
   * in pool.
   */
  char *method;

  /**
   * Requested URL (everything after "GET" only).  Allocated
   * in pool.
   */
  char *url;

  /**
   * HTTP version string (i.e. http/1.1).  Allocated
   * in pool.
   */
  char *version;

  /**
   * Buffer for reading requests.   Allocated
   * in pool.  Actually one byte larger than
   * @e read_buffer_size (if non-NULL) to allow for
   * 0-termination.
   */
  char *read_buffer;

  /**
   * Buffer for writing response (headers only).  Allocated
   * in pool.
   */
  char *write_buffer;

  /**
   * Last incomplete header line during parsing of headers.
   * Allocated in pool.  Only valid if state is
   * either #MHD_CONNECTION_HEADER_PART_RECEIVED or
   * #MHD_CONNECTION_FOOTER_PART_RECEIVED.
   */
  char *last;

  /**
   * Position after the colon on the last incomplete header
   * line during parsing of headers.
   * Allocated in pool.  Only valid if state is
   * either #MHD_CONNECTION_HEADER_PART_RECEIVED or
   * #MHD_CONNECTION_FOOTER_PART_RECEIVED.
   */
  char *colon;

  /**
   * Foreign address (of length @e addr_len).  MALLOCED (not
   * in pool!).
   */
  struct sockaddr *addr;

  /**
   * Thread handle for this connection (if we are using
   * one thread per connection).
   */
  MHD_thread_handle_ pid;

  /**
   * Size of read_buffer (in bytes).  This value indicates
   * how many bytes we're willing to read into the buffer;
   * the real buffer is one byte longer to allow for
   * adding zero-termination (when needed).
   */
  size_t read_buffer_size;

  /**
   * Position where we currently append data in
   * read_buffer (last valid position).
   */
  size_t read_buffer_offset;

  /**
   * Size of write_buffer (in bytes).
   */
  size_t write_buffer_size;

  /**
   * Offset where we are with sending from write_buffer.
   */
  size_t write_buffer_send_offset;

  /**
   * Last valid location in write_buffer (where do we
   * append and up to where is it safe to send?)
   */
  size_t write_buffer_append_offset;

  /**
   * How many more bytes of the body do we expect
   * to read? #MHD_SIZE_UNKNOWN for unknown.
   */
  uint64_t remaining_upload_size;

  /**
   * Current write position in the actual response
   * (excluding headers, content only; should be 0
   * while sending headers).
   */
  uint64_t response_write_position;

  /**
   * Position in the 100 CONTINUE message that
   * we need to send when receiving http 1.1 requests.
   */
  size_t continue_message_write_offset;

  /**
   * Length of the foreign address.
   */
  socklen_t addr_len;

  /**
   * Last time this connection had any activity
   * (reading or writing).
   */
  time_t last_activity;

  /**
   * After how many seconds of inactivity should
   * this connection time out?  Zero for no timeout.
   */
  unsigned int connection_timeout;

  /**
   * Did we ever call the "default_handler" on this connection?
   * (this flag will determine if we call the 'notify_completed'
   * handler when the connection closes down).
   */
  int client_aware;

  /**
   * Socket for this connection.  Set to #MHD_INVALID_SOCKET if
   * this connection has died (daemon should clean
   * up in that case).
   */
  MHD_socket socket_fd;

  /**
   * Has this socket been closed for reading (i.e.  other side closed
   * the connection)?  If so, we must completely close the connection
   * once we are done sending our response (and stop trying to read
   * from this socket).
   */
  int read_closed;

  /**
   * Set to #MHD_YES if the thread has been joined.
   */
  int thread_joined;

  /**
   * Are we currently inside the "idle" handler (to avoid recursively invoking it).
   */
  int in_idle;

#if EPOLL_SUPPORT
  /**
   * What is the state of this socket in relation to epoll?
   */
  enum MHD_EpollState epoll_state;
#endif

  /**
   * State in the FSM for this connection.
   */
  enum MHD_CONNECTION_STATE state;

  /**
   * What is this connection waiting for?
   */
  enum MHD_ConnectionEventLoopInfo event_loop_info;

  /**
   * HTTP response code.  Only valid if response object
   * is already set.
   */
  unsigned int responseCode;

  /**
   * Set to MHD_YES if the response's content reader
   * callback failed to provide data the last time
   * we tried to read from it.  In that case, the
   * write socket should be marked as unready until
   * the CRC call succeeds.
   */
  int response_unready;

  /**
   * Are we receiving with chunked encoding?  This will be set to
   * MHD_YES after we parse the headers and are processing the body
   * with chunks.  After we are done with the body and we are
   * processing the footers; once the footers are also done, this will
   * be set to MHD_NO again (before the final call to the handler).
   */
  int have_chunked_upload;

  /**
   * If we are receiving with chunked encoding, where are we right
   * now?  Set to 0 if we are waiting to receive the chunk size;
   * otherwise, this is the size of the current chunk.  A value of
   * zero is also used when we're at the end of the chunks.
   */
  size_t current_chunk_size;

  /**
   * If we are receiving with chunked encoding, where are we currently
   * with respect to the current chunk (at what offset / position)?
   */
  size_t current_chunk_offset;

  /**
   * Handler used for processing read connection operations
   */
  int (*read_handler) (struct MHD_Connection *connection);

  /**
   * Handler used for processing write connection operations
   */
  int (*write_handler) (struct MHD_Connection *connection);

  /**
   * Handler used for processing idle connection operations
   */
  int (*idle_handler) (struct MHD_Connection *connection);

  /**
   * Function used for reading HTTP request stream.
   */
  ReceiveCallback recv_cls;

  /**
   * Function used for writing HTTP response stream.
   */
  TransmitCallback send_cls;

#if HTTPS_SUPPORT
  /**
   * State required for HTTPS/SSL/TLS support.
   */
  SSL* tls_session;

  /**
   * Memory location to return for protocol session info.
   */
  const char* protocol;

  /**
   * Memory location to return for protocol session info.
   */
  const char* cipher;

  /**
   * Could it be that we are ready to read due to TLS buffers
   * even though the socket is not?
   */
  int tls_read_ready;
#endif

  /**
   * Is the connection suspended?
   */
  int suspended;

  /**
   * Is the connection wanting to resume?
   */
  int resuming;
};

/**
 * Signature of function called to log URI accesses.
 *
 * @param cls closure
 * @param uri uri being accessed
 * @param con connection handle
 * @return new closure
 */
typedef void *
(*LogCallback)(void * cls,
               const char * uri,
               struct MHD_Connection *con);

/**
 * Signature of function called to unescape URIs.  See also
 * #MHD_http_unescape().
 *
 * @param cls closure
 * @param conn connection handle
 * @param uri 0-terminated string to unescape (should be updated)
 * @return length of the resulting string
 */
typedef size_t
(*UnescapeCallback)(void *cls,
                    struct MHD_Connection *conn,
                    char *uri);


/**
 * State kept for each MHD daemon.  All connections are kept in two
 * doubly-linked lists.  The first one reflects the state of the
 * connection in terms of what operations we are waiting for (read,
 * write, locally blocked, cleanup) whereas the second is about its
 * timeout state (default or custom).
 */
struct MHD_Daemon
{

  /**
   * Callback function for all requests.
   */
  MHD_AccessHandlerCallback default_handler;

  /**
   * Closure argument to default_handler.
   */
  void *default_handler_cls;

  /**
   * Head of doubly-linked list of our current, active connections.
   */
  struct MHD_Connection *connections_head;

  /**
   * Tail of doubly-linked list of our current, active connections.
   */
  struct MHD_Connection *connections_tail;

  /**
   * Head of doubly-linked list of our current but suspended connections.
   */
  struct MHD_Connection *suspended_connections_head;

  /**
   * Tail of doubly-linked list of our current but suspended connections.
   */
  struct MHD_Connection *suspended_connections_tail;

  /**
   * Head of doubly-linked list of connections to clean up.
   */
  struct MHD_Connection *cleanup_head;

  /**
   * Tail of doubly-linked list of connections to clean up.
   */
  struct MHD_Connection *cleanup_tail;

#if EPOLL_SUPPORT
  /**
   * Head of EDLL of connections ready for processing (in epoll mode).
   */
  struct MHD_Connection *eready_head;

  /**
   * Tail of EDLL of connections ready for processing (in epoll mode)
   */
  struct MHD_Connection *eready_tail;
#endif

  /**
   * Head of the XDLL of ALL connections with a default ('normal')
   * timeout, sorted by timeout (earliest at the tail, most recently
   * used connection at the head).  MHD can just look at the tail of
   * this list to determine the timeout for all of its elements;
   * whenever there is an event of a connection, the connection is
   * moved back to the tail of the list.
   *
   * All connections by default start in this list; if a custom
   * timeout that does not match 'connection_timeout' is set, they
   * are moved to the 'manual_timeout_head'-XDLL.
   */
  struct MHD_Connection *normal_timeout_head;

  /**
   * Tail of the XDLL of ALL connections with a default timeout,
   * sorted by timeout (earliest timeout at the tail).
   */
  struct MHD_Connection *normal_timeout_tail;

  /**
   * Head of the XDLL of ALL connections with a non-default/custom
   * timeout, unsorted.  MHD will do a O(n) scan over this list to
   * determine the current timeout.
   */
  struct MHD_Connection *manual_timeout_head;

  /**
   * Tail of the XDLL of ALL connections with a non-default/custom
   * timeout, unsorted.
   */
  struct MHD_Connection *manual_timeout_tail;

  /**
   * Function to call to check if we should accept or reject an
   * incoming request.  May be NULL.
   */
  MHD_AcceptPolicyCallback apc;

  /**
   * Closure argument to apc.
   */
  void *apc_cls;

  /**
   * Function to call when we are done processing
   * a particular request.  May be NULL.
   */
  MHD_RequestCompletedCallback notify_completed;

  /**
   * Closure argument to notify_completed.
   */
  void *notify_completed_cls;

  /**
   * Function to call when we are starting/stopping
   * a connection.  May be NULL.
   */
  MHD_NotifyConnectionCallback notify_connection;

  /**
   * Closure argument to notify_connection.
   */
  void *notify_connection_cls;

  /**
   * Function to call with the full URI at the
   * beginning of request processing.  May be NULL.
   * <p>
   * Returns the initial pointer to internal state
   * kept by the client for the request.
   */
  LogCallback uri_log_callback;

  /**
   * Closure argument to @e uri_log_callback.
   */
  void *uri_log_callback_cls;

  /**
   * Function to call when we unescape escape sequences.
   */
  UnescapeCallback unescape_callback;

  /**
   * Closure for @e unescape_callback.
   */
  void *unescape_callback_cls;

#if HAVE_MESSAGES
  /**
   * Function for logging error messages (if we
   * support error reporting).
   */
  void (*custom_error_log) (void *cls, const char *fmt, va_list va);

  /**
   * Closure argument to custom_error_log.
   */
  void *custom_error_log_cls;
#endif

  /**
   * Pointer to master daemon (NULL if this is the master)
   */
  struct MHD_Daemon *master;

  /**
   * Worker daemons (one per thread)
   */
  struct MHD_Daemon *worker_pool;

  /**
   * Table storing number of connections per IP
   */
  void *per_ip_connection_count;

  /**
   * Size of the per-connection memory pools.
   */
  size_t pool_size;

  /**
   * Increment for growth of the per-connection memory pools.
   */
  size_t pool_increment;

  /**
   * Size of threads created by MHD.
   */
  size_t thread_stack_size;

  /**
   * Number of worker daemons
   */
  unsigned int worker_pool_size;

  /**
   * The select thread handle (if we have internal select)
   */
  MHD_thread_handle_ pid;

  /**
   * Mutex for per-IP connection counts.
   */
  MHD_mutex_ per_ip_connection_mutex;

  /**
   * Mutex for (modifying) access to the "cleanup" connection DLL.
   */
  MHD_mutex_ cleanup_connection_mutex;

  /**
   * Listen socket.
   */
  MHD_socket socket_fd;

  /**
   * Whether to allow/disallow/ignore reuse of listening address.
   * The semantics is the following:
   * 0: ignore (user did not ask for neither allow/disallow, use SO_REUSEADDR)
   * >0: allow (use SO_REUSEPORT on most platforms, SO_REUSEADDR on Windows)
   * <0: disallow (mostly no action, SO_EXCLUSIVEADDRUSE on Windows)
   */
  int listening_address_reuse;

#if EPOLL_SUPPORT
  /**
   * File descriptor associated with our epoll loop.
   */
  int epoll_fd;

  /**
   * MHD_YES if the listen socket is in the 'epoll' set,
   * MHD_NO if not.
   */
  int listen_socket_in_epoll;
#endif

  /**
   * Pipe we use to signal shutdown, unless
   * 'HAVE_LISTEN_SHUTDOWN' is defined AND we have a listen
   * socket (which we can then 'shutdown' to stop listening).
   * MHD can be build with usage of socketpair instead of
   * pipe (forced on W32).
   */
  MHD_pipe wpipe[2];

  /**
   * Are we shutting down?
   */
  int shutdown;

  /*
   * Do we need to process resuming connections?
   */
  int resuming;

  /**
   * Number of active parallel connections.
   */
  unsigned int connections;

  /**
   * Limit on the number of parallel connections.
   */
  unsigned int connection_limit;

  /**
   * After how many seconds of inactivity should
   * connections time out?  Zero for no timeout.
   */
  unsigned int connection_timeout;

  /**
   * Maximum number of connections per IP, or 0 for
   * unlimited.
   */
  unsigned int per_ip_connection_limit;

  /**
   * Daemon's flags (bitfield).
   */
  enum MHD_FLAG options;

  /**
   * Listen port.
   */
  uint16_t port;

#if HTTPS_SUPPORT
  SSL_CTX* tls_context;
  /**
   * Pointer to our SSL/TLS key (in PEM) in memory.
   */
  const char *https_mem_key;

  /**
   * Pointer to our SSL/TLS certificate (in PEM) in memory.
   */
  const char *https_mem_cert;

  /**
   * Pointer to 0-terminated HTTPS passphrase in memory.
   */
  const char *https_key_password;

  /**
   * Pointer to our SSL/TLS certificate authority (in PEM) in memory.
   */
  const char *https_mem_trust;

  /**
   * Our Diffie-Hellman parameters (in PEM) in memory.
   */
  const char *https_mem_dhparams;

  /**
   * Pointer to SSL/TLS cipher string in memory.
   */
  const char *https_mem_cipher;

  /**
   * For how many connections do we have 'tls_read_ready' set to MHD_YES?
   * Used to avoid O(n) traversal over all connections when determining
   * event-loop timeout (as it needs to be zero if there is any connection
   * which might have ready data within TLS).
   */
  unsigned int num_tls_read_ready;

#endif

#ifdef DAUTH_SUPPORT

  /**
   * Character array of random values.
   */
  const char *digest_auth_random;

  /**
   * An array that contains the map nonce-nc.
   */
  struct MHD_NonceNc *nnc;

  /**
   * A rw-lock for synchronizing access to `nnc'.
   */
  MHD_mutex_ nnc_lock;

  /**
   * Size of `digest_auth_random.
   */
  size_t digest_auth_rand_size;

  /**
   * Size of the nonce-nc array.
   */
  unsigned int nonce_nc_size;

#endif

#ifdef TCP_FASTOPEN
  /**
   * The queue size for incoming SYN + DATA packets.
   */
  unsigned int fastopen_queue_size;
#endif
};


#if EXTRA_CHECKS
#define EXTRA_CHECK(a) do { if (!(a)) abort(); } while (0)
#else
#define EXTRA_CHECK(a)
#endif


/**
 * Insert an element at the head of a DLL. Assumes that head, tail and
 * element are structs with prev and next fields.
 *
 * @param head pointer to the head of the DLL
 * @param tail pointer to the tail of the DLL
 * @param element element to insert
 */
#define DLL_insert(head,tail,element) do { \
  EXTRA_CHECK (NULL == (element)->next); \
  EXTRA_CHECK (NULL == (element)->prev); \
  (element)->next = (head); \
  (element)->prev = NULL; \
  if ((tail) == NULL) \
    (tail) = element; \
  else \
    (head)->prev = element; \
  (head) = (element); } while (0)


/**
 * Remove an element from a DLL. Assumes
 * that head, tail and element are structs
 * with prev and next fields.
 *
 * @param head pointer to the head of the DLL
 * @param tail pointer to the tail of the DLL
 * @param element element to remove
 */
#define DLL_remove(head,tail,element) do { \
  EXTRA_CHECK ( (NULL != (element)->next) || ((element) == (tail)));  \
  EXTRA_CHECK ( (NULL != (element)->prev) || ((element) == (head)));  \
  if ((element)->prev == NULL) \
    (head) = (element)->next;  \
  else \
    (element)->prev->next = (element)->next; \
  if ((element)->next == NULL) \
    (tail) = (element)->prev;  \
  else \
    (element)->next->prev = (element)->prev; \
  (element)->next = NULL; \
  (element)->prev = NULL; } while (0)



/**
 * Insert an element at the head of a XDLL. Assumes that head, tail and
 * element are structs with prevX and nextX fields.
 *
 * @param head pointer to the head of the XDLL
 * @param tail pointer to the tail of the XDLL
 * @param element element to insert
 */
#define XDLL_insert(head,tail,element) do { \
  EXTRA_CHECK (NULL == (element)->nextX); \
  EXTRA_CHECK (NULL == (element)->prevX); \
  (element)->nextX = (head); \
  (element)->prevX = NULL; \
  if (NULL == (tail)) \
    (tail) = element; \
  else \
    (head)->prevX = element; \
  (head) = (element); } while (0)


/**
 * Remove an element from a XDLL. Assumes
 * that head, tail and element are structs
 * with prevX and nextX fields.
 *
 * @param head pointer to the head of the XDLL
 * @param tail pointer to the tail of the XDLL
 * @param element element to remove
 */
#define XDLL_remove(head,tail,element) do { \
  EXTRA_CHECK ( (NULL != (element)->nextX) || ((element) == (tail)));  \
  EXTRA_CHECK ( (NULL != (element)->prevX) || ((element) == (head)));  \
  if (NULL == (element)->prevX) \
    (head) = (element)->nextX;  \
  else \
    (element)->prevX->nextX = (element)->nextX; \
  if (NULL == (element)->nextX) \
    (tail) = (element)->prevX;  \
  else \
    (element)->nextX->prevX = (element)->prevX; \
  (element)->nextX = NULL; \
  (element)->prevX = NULL; } while (0)


/**
 * Insert an element at the head of a EDLL. Assumes that head, tail and
 * element are structs with prevE and nextE fields.
 *
 * @param head pointer to the head of the EDLL
 * @param tail pointer to the tail of the EDLL
 * @param element element to insert
 */
#define EDLL_insert(head,tail,element) do { \
  (element)->nextE = (head); \
  (element)->prevE = NULL; \
  if ((tail) == NULL) \
    (tail) = element; \
  else \
    (head)->prevE = element; \
  (head) = (element); } while (0)


/**
 * Remove an element from a EDLL. Assumes
 * that head, tail and element are structs
 * with prevE and nextE fields.
 *
 * @param head pointer to the head of the EDLL
 * @param tail pointer to the tail of the EDLL
 * @param element element to remove
 */
#define EDLL_remove(head,tail,element) do { \
  if ((element)->prevE == NULL) \
    (head) = (element)->nextE;  \
  else \
    (element)->prevE->nextE = (element)->nextE; \
  if ((element)->nextE == NULL) \
    (tail) = (element)->prevE;  \
  else \
    (element)->nextE->prevE = (element)->prevE; \
  (element)->nextE = NULL; \
  (element)->prevE = NULL; } while (0)


/**
 * Equivalent to `time(NULL)` but tries to use some sort of monotonic
 * clock that isn't affected by someone setting the system real time
 * clock.
 *
 * @return 'current' time
 */
time_t
MHD_monotonic_time(void);


/**
 * Convert all occurences of '+' to ' '.
 *
 * @param arg string that is modified (in place), must be 0-terminated
 */
void
MHD_unescape_plus (char *arg);


#endif