/*
  This file is part of libmicrohttpd
  Copyright (C) 2007-2017 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 lib/internal.h
 * @brief  internal shared structures
 * @author Daniel Pittman
 * @author Christian Grothoff
 */

#ifndef INTERNAL_H
#define INTERNAL_H

#include "mhd_options.h"
#include "platform.h"
#include "microhttpd2.h"
#include "microhttpd_tls.h"
#include "mhd_assert.h"
#include "mhd_compat.h"
#include "mhd_itc.h"
#include "mhd_mono_clock.h"
#include "memorypool.h"

#ifdef HTTPS_SUPPORT
#include <gnutls/gnutls.h>
#if GNUTLS_VERSION_MAJOR >= 3
#include <gnutls/abstract.h>
#endif
#endif /* HTTPS_SUPPORT */

#ifdef HAVE_STDBOOL_H
#include <stdbool.h>
#endif
#ifdef MHD_PANIC
/* Override any defined MHD_PANIC macro with proper one */
#undef MHD_PANIC
#endif /* MHD_PANIC */

#ifdef 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

#include "mhd_threads.h"
#include "mhd_locks.h"
#include "mhd_sockets.h"
#include "mhd_str.h"
#include "mhd_itc_types.h"


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

#endif


/**
 * Close FD and abort execution if error is detected.
 * @param fd the FD to close
 */
#define MHD_fd_close_chk_(fd) do {                      \
    if ( (0 != close ((fd)) && (EBADF == errno)) )  \
      MHD_PANIC (_ ("Failed to close FD.\n"));            \
} while (0)

/**
 * 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 ()
#elif defined(_MSC_FULL_VER)
#define BUILTIN_NOT_REACHED __assume (0)
#else
#define BUILTIN_NOT_REACHED
#endif

#ifndef MHD_STATICSTR_LEN_
/**
 * Determine length of static string / macro strings at compile time.
 */
#define MHD_STATICSTR_LEN_(macro) (sizeof(macro) / sizeof(char) - 1)
#endif /* ! MHD_STATICSTR_LEN_ */


/**
 * Ability to use same connection for next request
 */
enum MHD_ConnKeepAlive
{
  /**
   * Connection must be closed after sending response.
   */
  MHD_CONN_MUST_CLOSE = -1,

  /**
   * KeelAlive state is not yet determined
   */
  MHD_CONN_KEEPALIVE_UNKOWN = 0,

  /**
   * Connection can be used for serving next request
   */
  MHD_CONN_USE_KEEPALIVE = 1
};


/**
 * 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 @a 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 *read_from,
                     size_t max_bytes);


/**
 * States in a state machine for a request.
 *
 * The main transitions are any-state to #MHD_REQUEST_CLOSED, any
 * state to state+1, #MHD_REQUEST_FOOTERS_SENT to
 * #MHD_REQUEST_INIT.  #MHD_REQUEST_CLOSED is the terminal state
 * and #MHD_REQUEST_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
 * #MHD_REQUEST_CLOSED or #MHD_REQUEST_INIT requires the write
 * to be complete.
 */
enum MHD_REQUEST_STATE // FIXME: fix capitalization!
{
  /**
   * Request just started (no headers received).
   * Waiting for the line with the request type, URL and version.
   */
  MHD_REQUEST_INIT = 0,

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  /**
   * 19: This request is to be closed.
   */
  MHD_REQUEST_CLOSED = MHD_REQUEST_FOOTERS_SENT + 1,

#ifdef UPGRADE_SUPPORT
  /**
   * Request was "upgraded" and socket is now under the
   * control of the application.
   */
  MHD_REQUEST_UPGRADE
#endif /* UPGRADE_SUPPORT */

};


/**
 * 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;

};


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

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

  /**
   * Connection this request is associated with.
   */
  struct MHD_Connection *connection;

  /**
   * Response to return for this request, set once
   * it is available.
   */
  struct MHD_Response *response;

  /**
   * 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;

  /**
   * 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;

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

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

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

  /**
   * Close connection after sending response?
   * Functions may change value from "Unknown" or "KeepAlive" to "Must close",
   * but no functions reset value "Must Close" to any other value.
   */
  enum MHD_ConnKeepAlive keepalive;

  /**
   * 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_REQUEST_HEADER_PART_RECEIVED or
   * #MHD_REQUEST_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_REQUEST_HEADER_PART_RECEIVED or
   * #MHD_REQUEST_FOOTER_PART_RECEIVED.
   */
  char *colon;

#ifdef UPGRADE_SUPPORT
  /**
   * If this connection was upgraded, this points to
   * the upgrade response details such that the
   * #thread_main_connection_upgrade()-logic can perform the
   * bi-directional forwarding.
   */
  struct MHD_UpgradeResponseHandle *urh;
#endif /* UPGRADE_SUPPORT */

  /**
   * Size of @e 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
   * @e read_buffer (last valid position).
   */
  size_t read_buffer_offset;

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

  /**
   * Offset where we are with sending from @e 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;

  /**
   * Number of bytes we had in the HTTP header, set once we
   * pass #MHD_REQUEST_HEADERS_RECEIVED.
   */
  size_t header_size;

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

  /**
   * 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.
   */
  uint64_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)?
   */
  uint64_t current_chunk_offset;

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

  #if defined(_MHD_HAVE_SENDFILE)
  // FIXME: document, fix capitalization!
  enum MHD_resp_sender_
  {
    MHD_resp_sender_std = 0,
    MHD_resp_sender_sendfile
  } resp_sender;
#endif /* _MHD_HAVE_SENDFILE */

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

  /**
   * State in the FSM for this request.
   */
  enum MHD_REQUEST_STATE state;

  /**
   * HTTP method, as an enum.
   */
  enum MHD_Method method;

  /**
   * What is this request waiting for?
   */
  enum MHD_RequestEventLoopInfo event_loop_info;

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

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

  /**
   * 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).
   */
  bool have_chunked_upload;
};


/**
 * 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,

  /**
   * Is this connection in some error state?
   */
  MHD_EPOLL_STATE_ERROR = 128
};


/**
 * State kept per HTTP connection.
 */
struct MHD_Connection
{

#ifdef 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;

  /**
   * 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 request-related data except for the
   * response (which maybe shared between requests) and the IP
   * address (which persists across individual requests).
   */
  struct MemoryPool *pool;

  /**
   * 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;

#ifdef HTTPS_SUPPORT
  /**
   * State kept per TLS connection. Plugin-specific.
   */
  struct MHD_TLS_ConnectionState *tls_cs;
#endif

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

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

  /**
   * Information about the current request we are processing
   * on this connection.
   */
  struct MHD_Request request;

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

  /**
   * Foreign address (of length @e addr_len).
   */
  struct sockaddr_storage addr;

  /**
   * 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.
   */
  time_t connection_timeout;

  /**
   * 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;

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

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

  /**
   * Are we ready to read from TLS for this connection?
   */
  bool tls_read_ready;

  /**
   * Is the connection wanting to resume?
   */
  bool resuming;

  /**
   * Set to `true` if the thread has been joined.
   */
  bool thread_joined;

  /**
   * true if #socket_fd is non-blocking, false otherwise.
   */
  bool sk_nonblck;

  /**
   * 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).
   */
  bool read_closed;

};


#ifdef UPGRADE_SUPPORT
/**
 * Buffer we use for upgrade response handling in the unlikely
 * case where the memory pool was so small it had no buffer
 * capacity left.  Note that we don't expect to _ever_ use this
 * buffer, so it's mostly wasted memory (except that it allows
 * us to handle a tricky error condition nicely). So no need to
 * make this one big.  Applications that want to perform well
 * should just pick an adequate size for the memory pools.
 */
#define RESERVE_EBUF_SIZE 8

/**
 * Context we pass to epoll() for each of the two sockets
 * of a `struct MHD_UpgradeResponseHandle`.  We need to do
 * this so we can distinguish the two sockets when epoll()
 * gives us event notifications.
 */
struct UpgradeEpollHandle
{
  /**
   * Reference to the overall response handle this struct is
   * included within.
   */
  struct MHD_UpgradeResponseHandle *urh;

  /**
   * The socket this event is kind-of about.  Note that this is NOT
   * necessarily the socket we are polling on, as for when we read
   * from TLS, we epoll() on the connection's socket
   * (`urh->connection->socket_fd`), while this then the application's
   * socket (where the application will read from).  Nevertheless, for
   * the application to read, we need to first read from TLS, hence
   * the two are related.
   *
   * Similarly, for writing to TLS, this epoll() will be on the
   * connection's `socket_fd`, and this will merely be the FD which
   * the application would write to.  Hence this struct must always be
   * interpreted based on which field in `struct
   * MHD_UpgradeResponseHandle` it is (`app` or `mhd`).
   */
  MHD_socket socket;

  /**
   * IO-state of the @e socket (or the connection's `socket_fd`).
   */
  enum MHD_EpollState celi;

};


/**
 * Handle given to the application to manage special
 * actions relating to MHD responses that "upgrade"
 * the HTTP protocol (i.e. to WebSockets).
 */
struct MHD_UpgradeResponseHandle
{
  /**
   * The connection for which this is an upgrade handle.  Note that
   * because a response may be shared over many connections, this may
   * not be the only upgrade handle for the response of this connection.
   */
  struct MHD_Connection *connection;

#ifdef HTTPS_SUPPORT
  /**
   * Kept in a DLL per daemon.
   */
  struct MHD_UpgradeResponseHandle *next;

  /**
   * Kept in a DLL per daemon.
   */
  struct MHD_UpgradeResponseHandle *prev;

#ifdef EPOLL_SUPPORT
  /**
   * Next pointer for the EDLL listing urhs that are epoll-ready.
   */
  struct MHD_UpgradeResponseHandle *nextE;

  /**
   * Previous pointer for the EDLL listing urhs that are epoll-ready.
   */
  struct MHD_UpgradeResponseHandle *prevE;

  /**
   * Specifies whether urh already in EDLL list of ready connections.
   */
  bool in_eready_list;
#endif

  /**
   * The buffer for receiving data from TLS to
   * be passed to the application.  Contains @e in_buffer_size
   * bytes (unless @e in_buffer_size is zero). Do not free!
   */
  char *in_buffer;

  /**
   * The buffer for receiving data from the application to
   * be passed to TLS.  Contains @e out_buffer_size
   * bytes (unless @e out_buffer_size is zero). Do not free!
   */
  char *out_buffer;

  /**
   * Size of the @e in_buffer.
   * Set to 0 if the TLS connection went down for reading or socketpair
   * went down for writing.
   */
  size_t in_buffer_size;

  /**
   * Size of the @e out_buffer.
   * Set to 0 if the TLS connection went down for writing or socketpair
   * went down for reading.
   */
  size_t out_buffer_size;

  /**
   * Number of bytes actually in use in the @e in_buffer.  Can be larger
   * than @e in_buffer_size if and only if @a in_buffer_size is zero and
   * we still have bytes that can be forwarded.
   * Reset to zero if all data was forwarded to socketpair or
   * if socketpair went down for writing.
   */
  size_t in_buffer_used;

  /**
   * Number of bytes actually in use in the @e out_buffer. Can be larger
   * than @e out_buffer_size if and only if @a out_buffer_size is zero and
   * we still have bytes that can be forwarded.
   * Reset to zero if all data was forwarded to TLS connection or
   * if TLS connection went down for writing.
   */
  size_t out_buffer_used;

  /**
   * The socket we gave to the application (r/w).
   */
  struct UpgradeEpollHandle app;

  /**
   * If @a app_sock was a socketpair, our end of it, otherwise
   * #MHD_INVALID_SOCKET; (r/w).
   */
  struct UpgradeEpollHandle mhd;

  /**
   * Emergency IO buffer we use in case the memory pool has literally
   * nothing left.
   */
  char e_buf[RESERVE_EBUF_SIZE];

#endif /* HTTPS_SUPPORT */

  /**
   * Set to true after the application finished with the socket
   * by #MHD_UPGRADE_ACTION_CLOSE.
   *
   * When BOTH @e was_closed (changed by command from application)
   * AND @e clean_ready (changed internally by MHD) are set to
   * #MHD_YES, function #MHD_resume_connection() will move this
   * connection to cleanup list.
   * @remark This flag could be changed from any thread.
   */
  volatile bool was_closed;

  /**
   * Set to true if connection is ready for cleanup.
   *
   * In TLS mode functions #MHD_connection_finish_forward_() must
   * be called before setting this flag to true.
   *
   * In thread-per-connection mode, true in this flag means
   * that connection's thread exited or about to exit and will
   * not use MHD_Connection::urh data anymore.
   *
   * In any mode true in this flag also means that
   * MHD_Connection::urh data will not be used for socketpair
   * forwarding and forwarding itself is finished.
   *
   * When BOTH @e was_closed (changed by command from application)
   * AND @e clean_ready (changed internally by MHD) are set to
   * true, function #MHD_resume_connection() will move this
   * connection to cleanup list.
   * @remark This flag could be changed from thread that process
   * connection's recv(), send() and response.
   */
  bool clean_ready;
};
#endif /* UPGRADE_SUPPORT */


/**
 * 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
{
  /**
   * Function to call to handle incoming requests.
   */
  MHD_RequestCallback rc;

  /**
   * Closure for @e rc.
   */
  void *rc_cls;

  /**
   * Function to call for logging.
   */
  MHD_LoggingCallback logger;

  /**
   * Closure for @e logger.
   */
  void *logger_cls;

  /**
   * Function to call to accept/reject connections based on
   * the client's IP address.
   */
  MHD_AcceptPolicyCallback accept_policy_cb;

  /**
   * Closure for @e accept_policy_cb.
   */
  void *accept_policy_cb_cls;

  /**
   * Function to call on the full URL early for logging.
   */
  MHD_EarlyUriLogCallback early_uri_logger_cb;

  /**
   * Closure for @e early_uri_logger_cb.
   */
  void *early_uri_logger_cb_cls;

  /**
   * Function to call whenever a connection is started or
   * closed.
   */
  MHD_NotifyConnectionCallback notify_connection_cb;

  /**
   * Closure for @e notify_connection_cb.
   */
  void *notify_connection_cb_cls;

  /**
   * Function to call to unescape sequences in URIs and URI arguments.
   * See #MHD_daemon_unescape_cb().
   */
  MHD_UnescapeCallback unescape_cb;

  /**
   * Closure for @e unescape_cb.
   */
  void *unescape_cb_cls;

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

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


#if HTTPS_SUPPORT
#ifdef UPGRADE_SUPPORT
  /**
   * Head of DLL of upgrade response handles we are processing.
   * Used for upgraded TLS connections when thread-per-connection
   * is not used.
   */
  struct MHD_UpgradeResponseHandle *urh_head;

  /**
   * Tail of DLL of upgrade response handles we are processing.
   * Used for upgraded TLS connections when thread-per-connection
   * is not used.
   */
  struct MHD_UpgradeResponseHandle *urh_tail;
#endif /* UPGRADE_SUPPORT */

  /**
   * Which TLS backend should be used. NULL for no TLS.
   * This is merely the handle to the dlsym() object, not
   * the API.
   */
  void *tls_backend_lib;

  /**
   * Callback functions to use for TLS operations.
   */
  struct MHD_TLS_Plugin *tls_api;
#endif
#if ENABLE_DAUTH

  /**
   * Random values to be used by digest authentication module.
   * Size given in @e digest_auth_random_buf_size.
   */
  const void *digest_auth_random_buf;
#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 @e connection_timeout is set, they
   * are moved to the @e manual_timeout_head-XDLL.
   * Not used in MHD_USE_THREAD_PER_CONNECTION mode as each thread
   * needs only one connection-specific timeout.
   */
  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).
   * Not used in MHD_USE_THREAD_PER_CONNECTION mode.
   */
  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.
   * Not used in MHD_USE_THREAD_PER_CONNECTION mode.
   */
  struct MHD_Connection *manual_timeout_head;

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

  /**
   * 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;

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

#ifdef 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;

  /**
   * Pointer to marker used to indicate ITC slot in epoll sets.
   */
  const char *epoll_itc_marker;
#ifdef UPGRADE_SUPPORT
  /**
   * Head of EDLL of upgraded connections ready for processing (in epoll mode).
   */
  struct MHD_UpgradeResponseHandle *eready_urh_head;

  /**
   * Tail of EDLL of upgraded connections ready for processing (in epoll mode)
   */
  struct MHD_UpgradeResponseHandle *eready_urh_tail;
#endif /* UPGRADE_SUPPORT */
#endif /* EPOLL_SUPPORT */

#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 @e 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

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

  /**
   * Socket address to bind to for the listen socket.
   */
  struct sockaddr_storage listen_sa;

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

  /**
   * Mutex for (modifying) access to the "cleanup", "normal_timeout" and
   * "manual_timeout" DLLs.
   */
  MHD_mutex_ cleanup_connection_mutex;

  /**
   * Number of (valid) bytes in @e listen_sa.  Zero
   * if @e listen_sa is not initialized.
   */
  size_t listen_sa_len;

/**
 * Default size of the per-connection memory pool.
 */
#define POOL_SIZE_DEFAULT (32 * 1024)
  /**
   * Buffer size to use for each connection. Default
   * is #POOL_SIZE_DEFAULT.
   */
  size_t connection_memory_limit_b;

/**
 * Default 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 BUF_INC_SIZE_DEFAULT 1024

  /**
   * Increment to use when growing the read buffer. Smaller
   * than @e connection_memory_limit_b.
   */
  size_t connection_memory_increment_b;

  /**
   * Desired size of the stack for threads created by MHD,
   * 0 for system default.
   */
  size_t thread_stack_limit_b;

#if ENABLE_DAUTH

  /**
   * Size of @e digest_auth_random_buf.
   */
  size_t digest_auth_random_buf_size;

  /**
   * Default value for @e digest_nc_length.
   */
#define DIGEST_NC_LENGTH_DEFAULT 4

  /**
   * Desired length of the internal array with the nonce and
   * nonce counters for digest authentication.
   */
  size_t digest_nc_length;
#endif

  /**
   * Default value we use for the listen backlog.
   */
#ifdef SOMAXCONN
#define LISTEN_BACKLOG_DEFAULT SOMAXCONN
#else  /* !SOMAXCONN */
#define LISTEN_BACKLOG_DEFAULT 511
#endif

  /**
   * Backlog argument to use for listen.  See
   * #MHD_daemon_listen_backlog().
   */
  int listen_backlog;

  /**
   * Default queue length to use with fast open.
   */
#define FO_QUEUE_LENGTH_DEFAULT 50

  /**
   * Queue length to use with fast open.
   */
  unsigned int fo_queue_length;

  /**
   * Maximum number of connections MHD accepts. 0 for unlimited.
   */
  unsigned int global_connection_limit;

  /**
   * Maximum number of connections we accept per IP, 0 for unlimited.
   */
  unsigned int ip_connection_limit;

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

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

  /**
   * Default timeout in seconds for idle connections.
   */
  time_t connection_default_timeout;

  /**
   * Listen socket we should use, MHD_INVALID_SOCKET means
   * we are to initialize the socket from the other options given.
   */
  MHD_socket listen_socket;

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

  /**
   * true if the listen socket is in the 'epoll' set,
   * false if not.
   */
  bool listen_socket_in_epoll;

#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
  /**
   * File descriptor associated with the #run_epoll_for_upgrade() loop.
   * Only available if #MHD_USE_HTTPS_EPOLL_UPGRADE is set.
   */
  int epoll_upgrade_fd;

  /**
   * true if @e epoll_upgrade_fd is in the 'epoll' set,
   * false if not.
   */
  bool upgrade_fd_in_epoll;
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */

#endif

  /**
   * Inter-thread communication channel.
   */
  struct MHD_itc_ itc;

  /**
   * Which threading mode do we use? Positive
   * numbers indicate the number of worker threads to be used.
   * Values larger than 1 imply a thread pool.
   */
  enum MHD_ThreadingMode threading_mode;

  /**
   * When should we use TCP_FASTOPEN?
   * See #MHD_daemon_tcp_fastopen().
   */
  enum MHD_FastOpenMethod fast_open_method;

  /**
   * Address family to use when listening.
   * Default is #MHD_AF_NONE (do not listen).
   */
  enum MHD_AddressFamily listen_af;

  /**
   * Sets active/desired style of the event loop.
   * (Auto only possible during initialization, later set to
   * the actual style we use.)
   */
  enum MHD_EventLoopSyscall event_loop_syscall;

  /**
   * How strictly do we enforce the HTTP protocol?
   * See #MHD_daemon_protocol_strict_level().
   */
  enum MHD_ProtocolStrictLevel protocol_strict_level;

  /**
   * On which port should we listen on? Only effective if we were not
   * given a listen socket or a full address via
   * #MHD_daemon_bind_sa().  0 means to bind to random free port.
   */
  uint16_t listen_port;

  /**
   * Suppress generating the "Date:" header, this system
   * lacks an RTC (or developer is hyper-optimizing).  See
   * #MHD_daemon_suppress_date_no_clock().
   */
  bool suppress_date;

  /**
   * The use of the inter-thread communication channel is disabled.
   * See #MHD_daemon_disable_itc().
   */
  bool disable_itc;

  /**
   * Disable #MHD_action_suspend() functionality.  See
   * #MHD_daemon_disallow_suspend_resume().
   */
  bool disallow_suspend_resume;

  /**
   * Disable #MHD_action_upgrade() functionality.  See
   * #MHD_daemon_disallow_upgrade().
   */
  bool disallow_upgrade;

  /**
   * Did we hit some system or process-wide resource limit while
   * trying to accept() the last time? If so, we don't accept new
   * connections until we close an existing one.  This effectively
   * temporarily lowers the "connection_limit" to the current
   * number of connections.
   */
  bool at_limit;

  /**
   * Disables optional calls to `shutdown()` and enables aggressive
   * non-blocking optimistic reads and other potentially unsafe
   * optimizations.  See #MHD_daemon_enable_turbo().
   */
  bool enable_turbo;

  /**
   * 'True' if some data is already waiting to be processed.  If set
   * to 'true' - zero timeout for select()/poll*() is used.  Should be
   * reset each time before processing connections and raised by any
   * connection which require additional immediately processing
   * (application does not provide data for response, data waiting in
   * TLS buffers etc.)
   */
  bool data_already_pending;

  /**
   * MHD_daemon_quiesce() was run against this daemon.
   */
  bool was_quiesced;

  /**
   * Is some connection wanting to resume?
   */
  bool resuming;

  /**
   * Allow reusing the address:port combination when binding.
   * See #MHD_daemon_listen_allow_address_reuse().
   */
  bool allow_address_reuse;

  /**
   * MHD should speak SHOUTcast instead of HTTP.
   */
  bool enable_shoutcast;

  /**
   * Are we shutting down?
   */
  volatile bool shutdown;

};


/**
 * Action function implementing some action to be
 * performed on a request.
 *
 * @param cls action-specfic closure
 * @param request the request on which the action is to be performed
 * @return #MHD_SC_OK on success, otherwise an error code
 */
typedef enum MHD_StatusCode
(*ActionCallback)(void *cls,
                  struct MHD_Request *request);


/**
 * Actions are returned by the application to drive the request
 * handling of MHD.
 */
struct MHD_Action
{

  /**
   * Function to call for the action.
   */
  ActionCallback action;

  /**
   * Closure for @a action
   */
  void *action_cls;

};


/**
 * Representation of an HTTP response.
 */
struct MHD_Response
{

  /**
   * A response *is* an action. See also
   * #MHD_action_from_response().   Hence this field
   * must be the first field in a response!
   */
  struct MHD_Action action;

  /**
   * 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;

  /**
   * Function to call once MHD is finished with
   * the request, may be NULL.
   */
  MHD_RequestTerminationCallback termination_cb;

  /**
   * Closure for @e termination_cb.
   */
  void *termination_cb_cls;

#ifdef UPGRADE_SUPPORT
  /**
   * Application function to call once we are done sending the headers
   * of the response; NULL unless this is a response created with
   * #MHD_create_response_for_upgrade().
   */
  MHD_UpgradeHandler upgrade_handler;

  /**
   * Closure for @e uh.
   */
  void *upgrade_handler_cls;
#endif /* UPGRADE_SUPPORT */

  /**
   * 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.
   */
  uint64_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;

  /**
   * HTTP status code of the response.
   */
  enum MHD_HTTP_StatusCode status_code;

  /**
   * 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;

  /**
   * Only respond in HTTP 1.0 mode.
   */
  bool v10_only;

  /**
   * Use ShoutCAST format.
   */
  bool icy;

};


/**
 * Callback invoked when iterating over @a key / @a value
 * argument pairs during parsing.
 *
 * @param request context of the iteration
 * @param key 0-terminated key string, never NULL
 * @param value 0-terminated value string, may be NULL
 * @param kind origin of the key-value pair
 * @return true on success (continue to iterate)
 *         false to signal failure (and abort iteration)
 */
typedef bool
(*MHD_ArgumentIterator_)(struct MHD_Request *request,
                         const char *key,
                         const char *value,
                         enum MHD_ValueKind kind);


/**
 * Parse and unescape the arguments given by the client
 * as part of the HTTP request URI.
 *
 * @param request request to add headers to
 * @param kind header kind to pass to @a cb
 * @param[in,out] args argument URI string (after "?" in URI),
 *        clobbered in the process!
 * @param cb function to call on each key-value pair found
 * @param[out] num_headers set to the number of headers found
 * @return false on failure (@a cb returned false),
 *         true for success (parsing succeeded, @a cb always
 *                               returned true)
 */
bool
MHD_parse_arguments_ (struct MHD_Request *request,
                      enum MHD_ValueKind kind,
                      char *args,
                      MHD_ArgumentIterator_ cb,
                      unsigned int *num_headers);


/**
 * 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 { \
    mhd_assert (NULL == (element)->next); \
    mhd_assert (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 { \
    mhd_assert ( (NULL != (element)->next) || ((element) == (tail)));  \
    mhd_assert ( (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 { \
    mhd_assert (NULL == (element)->nextX); \
    mhd_assert (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 { \
    mhd_assert ( (NULL != (element)->nextX) || ((element) == (tail)));  \
    mhd_assert ( (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)


/**
 * Error code similar to EGAIN or EINTR
 */
#define MHD_ERR_AGAIN_ (-3073)

/**
 * Connection was hard-closed by remote peer.
 */
#define MHD_ERR_CONNRESET_ (-3074)

/**
 * Connection is not connected anymore due to
 * network error or any other reason.
 */
#define MHD_ERR_NOTCONN_ (-3075)

/**
 * "Not enough memory" error code
 */
#define MHD_ERR_NOMEM_ (-3076)

/**
 * "Bad FD" error code
 */
#define MHD_ERR_BADF_ (-3077)

/**
 * Error code similar to EINVAL
 */
#define MHD_ERR_INVAL_ (-3078)


#endif
