libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 66066283bd3733b168db454dd9297ba4262e407d
parent 17a75e59233b8af60b4135f297a187fdad7929b2
Author: Christian Grothoff <christian@grothoff.org>
Date:   Tue, 18 Jul 2017 11:43:25 +0200

propsing NG API for MHD

Diffstat:
Msrc/include/microhttpd.h | 7-------
Asrc/include/microhttpd2.h | 1960+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1960 insertions(+), 7 deletions(-)

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -1477,13 +1477,6 @@ enum MHD_OPTION * the "be as liberal as possible in what you accept" norm. It is * recommended to set this to 1 if you are testing clients against * MHD, and 0 in production. - * if set to -1 - be opposite to strict and be permissive about the - * protocol, allowing slight deviations that are technically not - * allowed by the RFC. Specifically, at the moment, this flag - * causes MHD to allow spaces in header field names. This is - * disallowed by the standard. - * It is not recommended to set it to -1 on publicly available - * servers as it may potentially lower level of protection. * This option should be followed by an `int` argument. */ MHD_OPTION_STRICT_FOR_CLIENT = 29 diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h @@ -0,0 +1,1960 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2006-2017 Christian Grothoff (and other contributing authors) + + 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 +*/ + +/** + * Just includes the NEW definitions for the NG-API. + * Note that we do not indicate which of the OLD APIs + * simply need to be kept vs. deprecated. + * + * The goal is to provide a basis for discussion! + * None of this is implemented yet. + * + * Main goals: + * - simplify application callbacks by splitting header/upload/post + * functionality currently provided by calling the same + * MHD_AccessHandlerCallback 3+ times into separate callbacks. + * - avoid repeated scans for URL matches via the new + * struct MHD_RequestHandlerCallbacks construction + * - provide default logarithmic implementation of URL scan + * => reduce strcmp(url) from >= 3n operations to "log n" + * per request. + * - better types, in particular avoid varargs for options + * - make it harder to pass inconsistent options + * - combine options and flags into more uniform API (at least + * exterally!) + * - simplify API use by using sane defaults (benefiting from + * breaking backwards compatibility) and making all options + * really optional, and where applicable avoid having options + * where the default works if nothing is specified + * - simplify API by moving rarely used http_version into + * MHD_request_get_information() + * - avoid 'int' for MHD_YES/MHD_NO by introducing `enum MHD_Bool` + * - improve terminology by eliminating confusion between + * 'request' and 'connection' + * - prepare API for having multiple TLS backends + * - use more consistent prefixes for related functions + * by using MHD_subject_verb_object naming convention, also + * at the same time avoid symbol conflict with legacy names + * (so we can have one binary implementing old and new + * library API at the same time via compatibility layer). + */ + + +/** + * Representation of 'bool' in the public API as stdbool.h may not + * always be available. + */ +enum MHD_Bool +{ + + /** + * MHD-internal return code for "NO". + */ + MHD_NO = 0, + + /** + * MHD-internal return code for "YES". + */ + MHD_YES = 1 +}; + + +/** + * @brief Handle for a connection / HTTP request. + * + * With HTTP/1.1, multiple requests can be run over the same + * connection. However, MHD will only show one request per TCP + * connection to the client at any given time. + * + * Replaces `struct MHD_Connection`, renamed to better reflect + * what this object truly represents to the application using + * MHD. + * + * @ingroup request + */ +struct MHD_Request; + + +/** + * Enumeration used to define options in + * `struct MHD_Option`. Opaque to the application. + */ +enum MHD_OptionValue; + + +/** + * Option configuring the service. + */ +struct MHD_Option +{ + /** + * Which option is being given. #MHD_OPTION_VALUE_END + * terminates the array. + */ + enum MHD_OptionValue option; + + /** + * Option value. + */ + intptr_t value1; + + /** + * Option value. + */ + intptr_t value2; + + /** + * Option value. + */ + intptr_t value3; + +}; + + +/** + * Returns terminating element of an option array. + * + * @return MHD option array terminator + */ +_MHD_EXTERN struct MHD_Option +MHD_option_end (void); + + +/** + * Set logging method. Specify NULL to disable logging entirely. By + * default (if this option is not given), we log error messages to + * stderr. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_log (MHD_LogCallback logger, + void *cls logger_cls); + + +/** + * Convenience macro used to disable logging. + * + * @return MHD option that disables logging + */ +#define MHD_option_disable_logging() MHD_option_log (NULL, NULL) + + +/** + * Suppress use of "Date" header as this system has no RTC. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_suppress_date_no_clock (void); + + +/** + * Use inter-thread communication channel. #MHD_option_enable_itc() + * can be used with #MHD_option_thread_internal() and is ignored with + * any "external" mode. It's required for use of + * #MHD_daemon_quiesce() or #MHD_connection_add(). This option is + * enforced by #MHD_option_allow_suspend_resume() and if there is no + * listen socket. #MHD_option_enable_itc() is always used + * automatically on platforms where select()/poll()/other ignore + * shutdown of listen socket. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_enable_itc (void); + + +/** + * Enable `turbo`. Disables certain calls to `shutdown()`, + * enables aggressive non-blocking optimistic reads and + * other potentially unsafe optimizations. + * Most effects only happen with #MHD_ELS_EPOLL. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_enable_turbo (void); + + +/** + * Enable suspend/resume functions, which also implies setting up + * #MHD_option_enable_itc() to signal resume. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_allow_suspend_resume (void); + + +/** + * You need to set this option if you want to use HTTP "Upgrade". + * "Upgrade" may require usage of additional internal resources, + * which we do not want to use unless necessary. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_allow_upgrade (void); + + +/** + * Possible levels of enforcement for TCP_FASTOPEN. + */ +enum MHD_FastOpenMethod +{ + /** + * Disable use of TCP_FASTOPEN. + */ + MHD_FOM_DISABLE = -1, + + /** + * Enable TCP_FASTOPEN where supported (Linux with a kernel >= 3.6). + * This is the default. + */ + MHD_FOM_AUTO = 0, + + /** + * If TCP_FASTOPEN is not available, cause #MHD_daemon_start() to +fail. + */ + MHD_FOM_REQUIRE = 1 +}; + + +/** + * Configure TCP_FASTOPEN option, including setting a + * custom @a queue_length. + * + * Note that having a larger queue size can cause resource exhaustion + * attack as the TCP stack has to now allocate resources for the SYN + * packet along with its DATA. + * + * @param fom under which conditions should we use TCP_FASTOPEN? + * @param queue_length queue length to use, default is 50 if this + * option is never given. + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tcp_fastopen (enum MHD_FastOpenMethod fom, + unsigned int queue_length); + + +/** + * Bind to the given TCP port. + * Ineffective in conjunction with #MHD_option_listen_socket(). + * Ineffective in conjunction with #MHD_option_bind_sa(). + * + * If neither this option nor the other two mentioned above + * is specified, MHD will simply not listen on any socket! + * + * @param port port to use, 0 to bind to a random (free) port + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_bind_port (uint16_t port); + + +/** + * Bind to the given socket address. + * Ineffective in conjunction with #MHD_option_listen_socket(). + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_bind_socket_address (const struct sockaddr *sa); + + +/** + * Use the given backlog for the listen() call. + * Ineffective in conjunction with #MHD_option_listen_socket(). + * + * @param listen_backlog backlog to use + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_listen_queue (int listen_backlog); + + +/** + * If present true, allow reusing address:port socket (by using + * SO_REUSEPORT on most platform, or platform-specific ways). If + * present and set to false, disallow reusing address:port socket + * (does nothing on most plaform, but uses SO_EXCLUSIVEADDRUSE on + * Windows). + * Ineffective in conjunction with #MHD_option_listen_socket(). + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_listen_allow_address_reuse (void); + + +/** + * Accept connections from the given socket. Socket + * must be a TCP or UNIX domain (stream) socket. + * + * Disables other listen options, including + * #MHD_option_bind_sa(), #MHD_option_bind_port(), + * #MHD_option_listen_queue() and + * #MHD_option_listen_allow_address_reuse(). + * + * @param listen_socket listen socket to use + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_listen_socket (int listen_socket); + + +/** + * Event loop syscalls supported by MHD. + */ +enum MHD_EventLoopSyscall +{ + /** + * Automatic selection of best-available method. This is also the + * default. + */ + MHD_ELS_AUTO = 0, + + /** + * Use select(). + */ + MHD_ELS_SELECT = 1, + + /** + * Use poll(). + */ + MHD_ELS_POLL = 2, + + /** + * Use epoll(). + */ + MHD_ELS_EPOLL = 3 +}; + + +/** + * Force use of a particular event loop system call. + * + * @param els event loop syscall to use + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_event_loop (enum MHD_EventLoopSyscall els); + + +/** + * Protocol strictness enforced by MHD on clients. + */ +enum MHD_ProtocolStrictLevel +{ + /** + * Be particularly permissive about the protocol, allowing slight + * deviations that are technically not allowed by the + * RFC. Specifically, at the moment, this flag causes MHD to allow + * spaces in header field names. This is disallowed by the standard. + * It is not recommended to set this value on publicly available + * servers as it may potentially lower level of protection. + */ + MHD_SL_PERMISSIVE = -1, + + /** + * Sane level of protocol enforcement for production use. + */ + MHD_SL_DEFAULT = 0, + + /** + * Be strict about the protocol (as opposed to as tolerant as + * possible). Specifically, at the moment, this flag causes MHD to + * reject HTTP 1.1 connections without a "Host" header. This is + * required by the standard, but of course in violation of the "be + * as liberal as possible in what you accept" norm. It is + * recommended to set this if you are testing clients against + * MHD, and to use default in production. + */ + MHD_SL_STRICT = 1 +}; + + +/** + * Set how strictly MHD will enforce the HTTP protocol. + * + * @param sl how strict should we be + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_protocol_strict_level (enum MHD_ProtocolStrictLevel sl); + + +/** + * Enable TLS. + * + * @param tls_backend which TLS backend should be used, + * currently only "gnutls" is supported. You can + * also specify "NULL" for best-available (which is the default). + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tls (const char *tls_backend); + + +/** + * Provide TLS key and certificate data in-memory. + * + * @param mem_key private key (key.pem) to be used by the + * HTTPS daemon. Must be the actual data in-memory, not a filename. + * @param mem_cert certificate (cert.pem) to be used by the + * HTTPS daemon. Must be the actual data in-memory, not a filename. + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tls_key_and_cert_from_memory (const char *mem_key, + const char *mem_cert); + + +/** + * Provide passphrase to decrypt 'key.pem' (if required). + * + * @param pass passphrase phrase to decrypt 'key.pem' + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tls_key_passphrase (const char *pass); + + +/** + * Configure TLS ciphers to use. Default is "NORMAL". + * + * @param ciphers which ciphers should be used by TLS + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tls_ciphers (const char *ciphers); + + +/** + * Configure DH parameters (dh.pem) to use for the TLS key + * exchange. + * + * @param dh parameters to use + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tls_mem_dhparams (const char *dh); + + +/** + * Memory pointer for the certificate (ca.pem) to be used by the + * HTTPS daemon for client authentification. + * + * @param mem_trust memory pointer to the certificate + */ +_MHD_EXTERN struct MHD_Option +MHD_option_tls_mem_trust (const char *mem_trust); + + +/** + * Configure daemon credentials type for GnuTLS. + * + * @param gnutls_credentials must be a value of + * type `gnutls_credentials_type_t` + */ +_MHD_EXTERN struct MHD_Option +MHD_option_gnutls_credentials (int gnutls_credentials); + + +/** + * Provide TLS key and certificate data via callback. + * + * Use a callback to determine which X.509 certificate should be used + * for a given HTTPS connection. This option provides an alternative + * to #MHD_option_tls_key_and_cert_from_memory(). You must use this + * version if multiple domains are to be hosted at the same IP address + * using TLS's Server Name Indication (SNI) extension. In this case, + * the callback is expected to select the correct certificate based on + * the SNI information provided. The callback is expected to access + * the SNI data using `gnutls_server_name_get()`. Using this option + * requires GnuTLS 3.0 or higher. + * + * @param cb must be of type `gnutls_certificate_retrieve_function2 *`. + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_gnutls_key_and_cert_from_callback (void *cb); + + +/** + * Run using a specific address family (by default, MHD will support + * dual stack if supported by the operating system). + * + * @param af address family to use, i.e. #AF_INET or #AF_INET6, + * or #AF_UNSPEC for dual stack + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_address_family (int af); + + +/** + * Enable use of one thread per connection. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_thread_per_connection (void); + + +/** + * Enable use of MHD-internal worker thread. + * + * Run using an internal thread (or thread pool) for sockets sending + * and receiving and data processing. Without this flag MHD will not + * run automatically in background thread(s). If this option is set, + * #MHD_run() and #MHD_run_from_select() cannot be used. + * + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_thread_iternal (void); + + +/** + * Enable use of a thread pool of the given size. + * + * @param num_threads number of threads to run in the pool + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_thread_pool_size (unsigned int num_threads); + + +/** + * Allow or deny a client to connect. + * + * @param cls closure + * @param addr address information from the client + * @param addrlen length of @a addr + * @see #MHD_option_accept_policy() + * @return #MHD_YES if connection is allowed, #MHD_NO if not + */ +typedef enum MHD_Bool +(*MHD_AcceptPolicyCallback) (void *cls, + const struct sockaddr *addr, + socklen_t addrlen); + + +/** + * Return option setting a policy that accepts/rejects connections + * based on the client's IP address. This function will be called + * before a connection object is created. + * + * @param apc function to call to check the policy + * @param apc_cls closure for @a apc + */ +_MHD_EXTERN struct MHD_Option +MHD_option_accept_policy (MHD_AcceptPolicyCallback apc, + void *apc_cls); + + +/** + * Signature of the callback used by MHD to notify the + * application about started/stopped connections + * + * @param cls client-defined closure + * @param connection connection handle + * @param socket_context socket-specific pointer where the + * client can associate some state specific + * to the TCP connection; note that this is + * different from the "con_cls" which is per + * HTTP request. The client can initialize + * during #MHD_CONNECTION_NOTIFY_STARTED and + * cleanup during #MHD_CONNECTION_NOTIFY_CLOSED + * and access in the meantime using + * #MHD_CONNECTION_INFO_SOCKET_CONTEXT. + * @param toe reason for connection notification + * @see #MHD_OPTION_NOTIFY_CONNECTION + * @ingroup request + */ +typedef void +(*MHD_ConnectionCompletedCallback) (void *cls, + struct MHD_Connection *connection, + enum MHD_ConnectionNotificationCode toe); + + +/** + * Register a function that should be called whenever a connection is + * started or closed. + * + * @param ncc function to call to check the policy + * @param ncc_cls closure for @a apc + */ +_MHD_EXTERN struct MHD_Option +MHD_option_set_notify_connection (MHD_NotifyConnectionCallback ncc, + void *ncc_cls); + + +/** + * Maximum memory size per connection (followed by a `size_t`). + * Default is 32 kb (#MHD_POOL_SIZE_DEFAULT). + * Values above 128k are unlikely to result in much benefit, as half + * of the memory will be typically used for IO, and TCP buffers are + * unlikely to support window sizes above 64k on most systems. + * + * @param memory_limit_b connection memory limit to use in bytes + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_connection_memory_limit (size_t memory_limit_b); + + +/** + * Increment to use for growing the read buffer (followed by a + * `size_t`). Must fit within #MHD_option_connection_memory_limit()). + * + * @param memory_limit_b connection memory limit to use in bytes + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_connection_memory_increment (size_t memory_increment_b); + + +/** + * Desired size of the stack for threads created by MHD. Use 0 for + * system default. + * + * @param stack_limit_b stack size to use in bytes + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_thread_stack_size (size_t stack_limit_b); + + +/** + * Set maximum number of concurrent connections to accept. If not + * given, MHD will not enforce any global limit (modulo running into + * OS limits). + * + * @param connection_limit maximum number of concurrent connections + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_connection_global_limit (unsigned int connection_limit); + + +/** + * Limit on the number of (concurrent) connections made to the + * server from the same IP address. Can be used to prevent one + * IP from taking over all of the allowed connections. If the + * same IP tries to establish more than the specified number of + * connections, they will be immediately rejected. The default is + * zero, which means no limit on the number of connections + * from the same IP address. + * + * @param connection_limit maximum number of concurrent connections + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_connection_ip_limit (unsigned int connection_limit); + + +/** + * After how many seconds of inactivity should a + * connection automatically be timed out? + * Use zero for no timeout, which is also the (unsafe!) default. + * + * @param timeout_s number of seconds of timeout to use + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_connection_default_timeout (unsigned int timeout_s); + + +/** + * Signature of functions performing unescaping of strings. + * The return value must be "strlen(s)" and @a s should be + * updated. Note that the unescape function must not lengthen @a s + * (the result must be shorter than the input and still be + * 0-terminated). + * + * @param cls closure + * @param req the request for which unescaping is performed + * @param[in,out] s string to unescape + * @return number of characters in @a s (excluding 0-terminator) + */ +typedef size_t +MHD_UnescapeCallback (void *cls, + struct MHD_Request *req, + char *s); + + +/** + * Specify a function that should be called for unescaping escape + * sequences in URIs and URI arguments. Note that this function + * will NOT be used by the `struct MHD_PostProcessor`. If this + * option is not specified, the default method will be used which + * decodes escape sequences of the form "%HH". + * + * @param unescape_cb function to use, NULL for default + * @param unescape_cb_cls closure for @a unescape_cb + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_unescape_cb (MHD_UnescapeCallback unescape_cb, + void *unescape_cb_cls); + + +/** + * Set random values to be used by the Digest Auth module. Note that + * the application must ensure that @a buf remains allocated and + * unmodified while the deamon is running. + * + * @param buf_size number of bytes in @a buf + * @param buf entropy buffer + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_digest_auth_random (size_t buf_size, + const void *buf); + + +/** + * Size of the internal array holding the map of the nonce and + * the nonce counter. + * + * @param nc_length desired array length + * @return MHD option + */ +_MHD_EXTERN struct MHD_Option +MHD_option_digest_auth_nc_size (size_t stack_limit_b); + + +/** + * Return option setting a callback to call upon connection + * completion. + * + * @param ccc function to call + * @param ccc_cls closure for @a ccc + */ +_MHD_EXTERN struct MHD_Option +MHD_option_connection_completion (MHD_ConnectionCompledCallback ccc, + void *ccc_cls;) + + +/** + * Signature of the callback used by MHD to notify the application + * that we have received the full header of a request. Can be used to + * send error responses to a "Expect: 100-continue" request. + * Note that regular responses should be set in the + * #MHD_RequestCompletedCallback. + * + * @param cls client-defined closure + * @ingroup request + * @return #MHD_YES if the upload was handled successfully, + * #MHD_NO if the socket must be closed due to a serios + * error while handling the request + */ +typedef enum MHD_Bool +(*MHD_RequestHeaderCallback) (void *cls); + + +/** + * A client has uploaded data. + * + * @param cls argument given together with the function + * pointer when the handler was registered with MHD + * @param upload_data the data being uploaded (excluding HEADERS, + * for a POST that fits into memory and that is encoded + * with a supported encoding, the POST data will NOT be + * given in upload_data and is instead available as + * part of #MHD_get_connection_values; very large POST + * data *will* be made available incrementally in + * @a upload_data) + * @param[in,out] upload_data_size set initially to the size of the + * @a upload_data provided; the method must update this + * value to the number of bytes NOT processed; + * @return #MHD_YES if the upload was handled successfully, + * #MHD_NO if the socket must be closed due to a serios + * error while handling the request + */ +typedef enum MHD_Bool +(*MHD_UploadCallback) (void *cls, + const char *upload_data, + size_t *upload_data_size); + + +/** + * Signature of the callback used by MHD to notify the application + * that we now expect a response. The application can either + * call #MHD_response_queue() or suspend the request or return + * #MHD_NO. + * + * @param cls client-defined closure + * @ingroup request + * @return #MHD_YES if the upload was handled successfully, + * #MHD_NO if the socket must be closed due to a serios + * error while handling the request + */ +typedef enum MHD_Bool +(*MHD_RequestFetchResponseCallback) (void *cls); + + +/** + * Signature of the callback used by MHD to notify the + * application about completed requests. + * + * @param cls client-defined closure + * @param toe reason for request termination + * @see #MHD_option_request_completion() + * @ingroup request + */ +typedef void +(*MHD_RequestCompletedCallback) (void *cls, + enum MHD_RequestTerminationCode toe); + + +/** + * Functions called for an MHD request to process it. + * Not all functions must be implemented for each request. + */ +struct MHD_RequestHandlerCallbacks +{ + /** + * Closure argument passed to all callbacks in this struct. + */ + void *cls; + + /** + * Function called after we have received the full HTTP header. + */ + MHD_RequestHeaderCallback header_cb; + + /** + * Function called if we receive uploaded data. + */ + MHD_UploadCallback upload_cb; + + /** + * Function called when we expect the application to + * generate a response (mandatory to be set; if not + * set and #MHD_NO is not returned, MHD will generate + * 500 internal error and log an error). + */ + MHD_RequestFetchResponseCallback fetch_response_cb; + + /** + * Function called last to clean up. Gives the + * application a chance to check on the final status of + * the request (and to clean up @e cls). + */ + MHD_RequestCompletedCallback completed_cb; + +}; + + +/** + * A client has requested the given url using the given method + * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, + * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback + * must initialize @a rhp to provide further callbacks which will + * process the request further and ultimately to provide the response + * to give back to the client. + * + * @param cls argument given together with the function + * pointer when the handler was registered with MHD + * @param url the requested url (without arguments after "?") + * @param method the HTTP method used (#MHD_HTTP_METHOD_GET, + * #MHD_HTTP_METHOD_PUT, etc.) + * @param[out] must be set to function pointers to be used to + * handle the request further; can be assumed to have + * been initialized to all-NULL values already. + * @return #MHD_YES if the request was handled successfully, + * #MHD_NO if the socket must be closed due to a serios + * error while handling the request + */ +typedef enum MHD_Bool +(*MHD_RequestCallback) (void *cls, + struct MHD_Request *request, + const char *url, + const char *method, + struct MHD_RequestHandlerCallbacks *rhp); + + +/** + * Generic option to set a global URL handler which + * will be called for all requests. You may prefer the + * more convenient, but less generic #MHD_option_url_table(). + * + * @param rc function to call for requests + * @param rc_cls closure to give to @a rc + */ +_MHD_EXTERN struct MHD_Option +MHD_option_url_handler (MHD_RequestCallback rc, + void *rc_cls); + + +/** + * A client has requested the given url using the given method + * (#MHD_HTTP_METHOD_GET, #MHD_HTTP_METHOD_PUT, + * #MHD_HTTP_METHOD_DELETE, #MHD_HTTP_METHOD_POST, etc). The callback + * must initialize @a rhp to provide further callbacks which will + * process the request further and ultimately to provide the response + * to give back to the client. + * + * @param cls argument given together with the function + * pointer when the handler was registered with MHD + * @param request HTTP request handle + * @param[out] must be set to function pointers to be used to + * handle the request further; can be assumed to have + * been initialized to all-NULL values already. + * @return #MHD_YES if the request was handled successfully, + * #MHD_NO if the socket must be closed due to a serious + * error while handling the request + */ +typedef enum MHD_Bool +(*MHD_RequestStartCallback) (void *cls, + struct MHD_Request *request, + struct MHD_RequestHandlerCallbacks *rhp); + + +/** + * Definition of a request handler for a URL and method. + */ +struct MHD_UrlHandler; + + +/** + * Create URL handler array terminator. + */ +_MHD_EXTERN struct MHD_UrlHandler +MHD_url_handler_end (void); + + +/** + * Create a generic URL handler array entry. + * + * @param method HTTP method to which this handler + * matches. Case-insensitive, i.e. "GET". + * @param url Which URL does this handler match. Case-sensitive, + * i.e. "/favicon.ico". + * @param start_cb function to call for matching requests + * @param start_cb_cls closure for @a start_cb + * @return url handler array entry + */ +_MHD_EXTERN struct MHD_UrlHandler +MHD_url_handler_generic (const char *method, + const char *url, + MHD_RequestStartCallback start_cb, + void *start_cb_cls); + + +/** + * Create a simple URL handler array entry for requests + * where the application simply returns a response and + * has no state to initialize or clean up and where there + * is no upload. + * + * @param method HTTP method to which this handler + * matches. Case-insensitive, i.e. "GET". + * @param url Which URL does this handler match. Case-sensitive, + * i.e. "/favicon.ico". + * @param fetch_cb function to call for matching requests + * @param fetch_cb_cls closure for @a fetch_cb + * @return url handler array entry + */ +_MHD_EXTERN struct MHD_UrlHandler +MHD_url_handler_simple (const char *method, + const char *url, + MHD_RequestFetchResponseCallback fetch_cb, + void *fetch_cb_cls); + + +/** + * Set a table of @a handlers to process requests of matching methods + * and URLs. Requests that do not match any entry will yield a 404 + * NOT FOUND response. Note that this function may sort the @a + * handlers array in-place for faster (logarithmic) lookups later, + * hence the argument must be muteable. The @a handlers array must + * remain allocated by the application throughout the lifetime of the + * daemon! + * + * @param[in,out] handlers url handler table, terminated + * by #MHD_url_handler_end() + * @return option array entry + */ +_MHD_EXTERN struct MHD_Option +MHD_option_url_table (struct MHD_UrlHandler handlers[]); + + +/* **************** Daemon handling functions ***************** */ + +/** + * Start a webserver on the given port. + * + * @param options array of options, does NOT have to + * persist in memory past this call (note that individual + * arguments passed to the functions may need to + * be preserved) + * @return NULL on error, handle to daemon on success + * @ingroup event + */ +_MHD_EXTERN struct MHD_Daemon * +MHD_daemon_start (const struct MHD_Option options[]); + + +/** + * Stop accepting connections from the listening socket. Allows + * clients to continue processing, but stops accepting new + * connections. Note that the caller is responsible for closing the + * returned socket; however, if MHD is run using threads (anything but + * external select mode), it must not be closed until AFTER + * #MHD_stop_daemon has been called (as it is theoretically possible + * that an existing thread is still using it). + * + * Note that some thread modes require the caller to have passed + * #MHD_USE_ITC when using this API. If this daemon is + * in one of those modes and this option was not given to + * #MHD_start_daemon, this function will return #MHD_INVALID_SOCKET. + * + * @param daemon daemon to stop accepting new connections for + * @return old listen socket on success, #MHD_INVALID_SOCKET if + * the daemon was already not listening anymore + * @ingroup specialized + */ +_MHD_EXTERN MHD_socket +MHD_daemon_quiesce (struct MHD_Daemon *daemon); + + +/** + * Shutdown an HTTP daemon. + * + * @param daemon daemon to stop + * @ingroup event + */ +_MHD_EXTERN void +MHD_daemon_stop (struct MHD_Daemon *daemon); + + +/* ********************* connection options ************** */ + +/** + * MHD connection options. Given to #MHD_set_connection_option() to + * set custom options for a particular connection. + */ +struct MHD_ConnectionOption; + + +/** + * Generate array terminator for connection options. + */ +struct MHD_ConnectionOption +MHD_connection_option_end (void); + + +/** + * Generate option to set a custom timeout for the given connection. + * Specified as the number of seconds. Use zero for no timeout. If + * timeout was set to zero (or unset) before, setting of a new value + * by MHD_connection_set_option() will reset timeout timer. + * + * @param timeout_s new timeout in seconds + */ +struct MHD_ConnectionOption +MHD_connection_option_timeout (unsigned int timeout_s); + + +/** + * Set a custom option for the given connection, overriding defaults. + * + * @param connection connection to modify + * @param options array of options to set, does NOT have to + * persist past this call + * @ingroup specialized + * @return #MHD_YES on success + */ +_MHD_EXTERN enum MHD_Bool +MHD_connection_set_options (struct MHD_Connection *connection, + struct MHD_ConnectionOption options[]); + + +/* **************** Request handling functions ***************** */ + +/** + * Get all of the headers from the request. + * + * @param request request to get values from + * @param kind types of values to iterate over, can be a bitmask + * @param iterator callback to call on each header; + * maybe NULL (then just count headers) + * @param iterator_cls extra argument to @a iterator + * @return number of entries iterated over + * @ingroup request + */ +_MHD_EXTERN unsigned int +MHD_request_get_values (struct MHD_Request *request, + enum MHD_ValueKind kind, + MHD_KeyValueIterator iterator, + void *iterator_cls); + + +/** + * This function can be used to add an entry to the HTTP headers of a + * request (so that the #MHD_request_get_values function will + * return them -- and the `struct MHD_PostProcessor` will also see + * them). This maybe required in certain situations (see Mantis + * #1399) where (broken) HTTP implementations fail to supply values + * needed by the post processor (or other parts of the application). + * + * This function MUST only be called from within the + * request callbacks (otherwise, access maybe improperly + * synchronized). Furthermore, the client must guarantee that the key + * and value arguments are 0-terminated strings that are NOT freed + * until the connection is closed. (The easiest way to do this is by + * passing only arguments to permanently allocated strings.). + * + * @param request the request for which a + * value should be set + * @param kind kind of the value + * @param key key for the value + * @param value the value itself + * @return #MHD_NO if the operation could not be + * performed due to insufficient memory; + * #MHD_YES on success + * @ingroup request + */ +_MHD_EXTERN enum MHD_Bool +MHD_request_set_value (struct MHD_Request *request, + enum MHD_ValueKind kind, + const char *key, + const char *value); + + +/** + * Get a particular header value. If multiple + * values match the kind, return any one of them. + * + * @param request request to get values from + * @param kind what kind of value are we looking for + * @param key the header to look for, NULL to lookup 'trailing' value without a key + * @return NULL if no such item was found + * @ingroup request + */ +_MHD_EXTERN const char * +MHD_request_lookup_value (struct MHD_Request *request, + enum MHD_ValueKind kind, + const char *key); + + +/** + * Queue a response to be transmitted to the client (as soon as + * possible but after the current callback returns). + * + * @param request the request identifying the client + * @param status_code HTTP status code (i.e. #MHD_HTTP_OK) + * @param response response to transmit + * @return #MHD_NO on error (i.e. reply already sent), + * #MHD_YES on success or if message has been queued + * @ingroup response + */ +_MHD_EXTERN int +MHD_request_queue_response (struct MHD_Request *request, + unsigned int status_code, + struct MHD_Response *response); + + +/** + * Suspend handling of network data for a given request. This can + * be used to dequeue a request from MHD's event loop for a while. + * + * If you use this API in conjunction with a internal select or a + * thread pool, you must set the option #MHD_USE_ITC to + * ensure that a resumed request is immediately processed by MHD. + * + * Suspended requests continue to count against the total number of + * requests allowed (per daemon, as well as per IP, if such limits + * are set). Suspended requests will NOT time out; timeouts will + * restart when the request handling is resumed. While a + * request is suspended, MHD will not detect disconnects by the + * client. + * + * The only safe time to suspend a request is from the + * #MHD_AccessHandlerCallback. + * + * Finally, it is an API violation to call #MHD_stop_daemon while + * having suspended requests (this will at least create memory and + * socket leaks or lead to undefined behavior). You must explicitly + * resume all requests before stopping the daemon. + * + * @param request the request to suspend + */ +_MHD_EXTERN void +MHD_request_suspend (struct MHD_Request *request); + + +/** + * Resume handling of network data for suspended request. It is + * safe to resume a suspended request at any time. Calling this + * function on a request that was not previously suspended will + * result in undefined behavior. + * + * If you are using this function in ``external'' select mode, you must + * make sure to run #MHD_run() afterwards (before again calling + * #MHD_get_fdset(), as otherwise the change may not be reflected in + * the set returned by #MHD_get_fdset() and you may end up with a + * request that is stuck until the next network activity. + * + * @param request the request to resume + */ +_MHD_EXTERN void +MHD_request_resume (struct MHD_Request *request); + + +/* **************** Response manipulation functions ***************** */ + + +/** + * MHD response option. + */ +struct MHD_ResponseOption; + + +/** + * End of options array. + */ +struct MHD_ResponseOption +MHD_response_option_end (void); + + +/** + * Only respond in conservative HTTP 1.0-mode. In particular, + * do not (automatically) sent "Connection" headers and always + * close the connection after generating the response. + */ +struct MHD_ResponseOption +MHD_response_option_v10_only (void); + + +/** + * Set special @a options for a @a response. + * + * @param response the response to modify + * @param options options to set for the response + * @return #MHD_YES on success, #MHD_NO on error + */ +_MHD_EXTERN enum MHD_Bool +MHD_response_set_options (struct MHD_Response *response, + enum MHD_ResponseOption options[]); + + +/** + * Create a response object. The response object can be extended with + * header information and then be used any number of times. + * + * @param size size of the data portion of the response, #MHD_SIZE_UNKNOWN for unknown + * @param block_size preferred block size for querying crc (advisory only, + * MHD may still call @a crc using smaller chunks); this + * is essentially the buffer size used for IO, clients + * should pick a value that is appropriate for IO and + * memory performance requirements + * @param crc callback to use to obtain response data + * @param crc_cls extra argument to @a crc + * @param crfc callback to call to free @a crc_cls resources + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_response_from_callback (uint64_t size, + size_t block_size, + MHD_ContentReaderCallback crc, + void *crc_cls, + MHD_ContentReaderFreeCallback crfc); + + +/** + * Specification for how MHD should treat the memory buffer + * given for the response. + * @ingroup response + */ +enum MHD_ResponseMemoryMode +{ + + /** + * Buffer is a persistent (static/global) buffer that won't change + * for at least the lifetime of the response, MHD should just use + * it, not free it, not copy it, just keep an alias to it. + * @ingroup response + */ + MHD_RESPMEM_PERSISTENT, + + /** + * Buffer is heap-allocated with `malloc()` (or equivalent) and + * should be freed by MHD after processing the response has + * concluded (response reference counter reaches zero). + * @ingroup response + */ + MHD_RESPMEM_MUST_FREE, + + /** + * Buffer is in transient memory, but not on the heap (for example, + * on the stack or non-`malloc()` allocated) and only valid during the + * call to #MHD_create_response_from_buffer. MHD must make its + * own private copy of the data for processing. + * @ingroup response + */ + MHD_RESPMEM_MUST_COPY + +}; + + +/** + * Create a response object. The response object can be extended with + * header information and then be used any number of times. + * + * @param size size of the data portion of the response + * @param buffer size bytes containing the response's data portion + * @param mode flags for buffer management + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_response_from_buffer (size_t size, + void *buffer, + enum MHD_ResponseMemoryMode mode); + + +/** + * Create a response object based on an @a fd from which + * data is read. The response object can be extended with + * header information and then be used any number of times. + * + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @param offset offset to start reading from in the file; + * reading file beyond 2 GiB may be not supported by OS or + * MHD build; see ::MHD_FEATURE_LARGE_FILE + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build; see ::MHD_FEATURE_LARGE_FILE + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_response_from_fd (int fd, + uint64_t offset, + uint64_t size); + + +/** + * Enumeration for actions MHD should perform on the underlying socket + * of the upgrade. This API is not finalized, and in particular + * the final set of actions is yet to be decided. This is just an + * idea for what we might want. + */ +enum MHD_UpgradeAction +{ + + /** + * Close the socket, the application is done with it. + * + * Takes no extra arguments. + */ + MHD_UPGRADE_ACTION_CLOSE = 0 + +}; + + +/** + * 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; + + +/** + * This connection-specific callback is provided by MHD to + * applications (unusual) during the #MHD_UpgradeHandler. + * It allows applications to perform 'special' actions on + * the underlying socket from the upgrade. + * + * @param urh the handle identifying the connection to perform + * the upgrade @a action on. + * @param action which action should be performed + * @param ... arguments to the action (depends on the action) + * @return #MHD_NO on error, #MHD_YES on success + */ +_MHD_EXTERN enum MHD_Bool +MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh, + enum MHD_UpgradeAction action, + ...); + + +/** + * Function called after a protocol "upgrade" response was sent + * successfully and the socket should now be controlled by some + * protocol other than HTTP. + * + * Any data already received on the socket will be made available in + * @e extra_in. This can happen if the application sent extra data + * before MHD send the upgrade response. The application should + * treat data from @a extra_in as if it had read it from the socket. + * + * Note that the application must not close() @a sock directly, + * but instead use #MHD_upgrade_action() for special operations + * on @a sock. + * + * Data forwarding to "upgraded" @a sock will be started as soon + * as this function return. + * + * Except when in 'thread-per-connection' mode, implementations + * of this function should never block (as it will still be called + * from within the main event loop). + * + * @param cls closure, whatever was given to #MHD_create_response_for_upgrade(). + * @param connection original HTTP connection handle, + * giving the function a last chance + * to inspect the original HTTP request + * @param con_cls last value left in `con_cls` of the `MHD_AccessHandlerCallback` + * @param extra_in if we happened to have read bytes after the + * HTTP header already (because the client sent + * more than the HTTP header of the request before + * we sent the upgrade response), + * these are the extra bytes already read from @a sock + * by MHD. The application should treat these as if + * it had read them from @a sock. + * @param extra_in_size number of bytes in @a extra_in + * @param sock socket to use for bi-directional communication + * with the client. For HTTPS, this may not be a socket + * that is directly connected to the client and thus certain + * operations (TCP-specific setsockopt(), getsockopt(), etc.) + * may not work as expected (as the socket could be from a + * socketpair() or a TCP-loopback). The application is expected + * to perform read()/recv() and write()/send() calls on the socket. + * The application may also call shutdown(), but must not call + * close() directly. + * @param urh argument for #MHD_upgrade_action()s on this @a connection. + * Applications must eventually use this callback to (indirectly) + * perform the close() action on the @a sock. + */ +typedef void +(*MHD_UpgradeHandler)(void *cls, + struct MHD_Connection *connection, + void *con_cls, + const char *extra_in, + size_t extra_in_size, + MHD_socket sock, + struct MHD_UpgradeResponseHandle *urh); + + +/** + * Create a response object that can be used for 101 UPGRADE + * responses, for example to implement WebSockets. After sending the + * response, control over the data stream is given to the callback (which + * can then, for example, start some bi-directional communication). + * If the response is queued for multiple connections, the callback + * will be called for each connection. The callback + * will ONLY be called after the response header was successfully passed + * to the OS; if there are communication errors before, the usual MHD + * connection error handling code will be performed. + * + * Setting the correct HTTP code (i.e. MHD_HTTP_SWITCHING_PROTOCOLS) + * and setting correct HTTP headers for the upgrade must be done + * manually (this way, it is possible to implement most existing + * WebSocket versions using this API; in fact, this API might be useful + * for any protocol switch, not just WebSockets). Note that + * draft-ietf-hybi-thewebsocketprotocol-00 cannot be implemented this + * way as the header "HTTP/1.1 101 WebSocket Protocol Handshake" + * cannot be generated; instead, MHD will always produce "HTTP/1.1 101 + * Switching Protocols" (if the response code 101 is used). + * + * As usual, the response object can be extended with header + * information and then be used any number of times (as long as the + * header information is not connection-specific). + * + * @param upgrade_handler function to call with the "upgraded" socket + * @param upgrade_handler_cls closure for @a upgrade_handler + * @return NULL on error (i.e. invalid arguments, out of memory) + */ +_MHD_EXTERN struct MHD_Response * +MHD_response_for_upgrade (MHD_UpgradeHandler upgrade_handler, + void *upgrade_handler_cls); + + +/** + * Destroy a response object and associated resources. Note that + * libmicrohttpd may keep some of the resources around if the response + * is still in the queue for some clients, so the memory may not + * necessarily be freed immediatley. + * + * @param response response to destroy + * @ingroup response + */ +_MHD_EXTERN void +MHD_response_destroy (struct MHD_Response *response); + + +/** + * Add a header line to the response. + * + * @param response response to add a header to + * @param header the header to add + * @param content value to add + * @return #MHD_NO on error (i.e. invalid header or content format), + * or out of memory + * @ingroup response + */ +_MHD_EXTERN enum MHD_Bool +MHD_response_add_header (struct MHD_Response *response, + const char *header, + const char *content); + + +/** + * Add a footer line to the response. + * + * @param response response to remove a header from + * @param footer the footer to delete + * @param content value to delete + * @return #MHD_NO on error (i.e. invalid footer or content format). + * @ingroup response + */ +_MHD_EXTERN enum MHD_Bool +MHD_response_add_footer (struct MHD_Response *response, + const char *footer, + const char *content); + + +/** + * Delete a header (or footer) line from the response. + * + * @param response response to remove a header from + * @param header the header to delete + * @param content value to delete + * @return #MHD_NO on error (no such header known) + * @ingroup response + */ +_MHD_EXTERN enum MHD_Bool +MHD_response_del_header (struct MHD_Response *response, + const char *header, + const char *content); + + +/** + * Get all of the headers (and footers) added to a response. + * + * @param response response to query + * @param iterator callback to call on each header; + * maybe NULL (then just count headers) + * @param iterator_cls extra argument to @a iterator + * @return number of entries iterated over + * @ingroup response + */ +_MHD_EXTERN unsigned int +MHD_response_get_headers (struct MHD_Response *response, + MHD_KeyValueIterator iterator, + void *iterator_cls); + + +/** + * Get a particular header (or footer) from the response. + * + * @param response response to query + * @param key which header to get + * @return NULL if header does not exist + * @ingroup response + */ +_MHD_EXTERN const char * +MHD_response_get_header (struct MHD_Response *response, + const char *key); + + +/* ********************** PostProcessor functions ********************** */ + +/** + * Create a `struct MHD_PostProcessor`. + * + * A `struct MHD_PostProcessor` can be used to (incrementally) parse + * the data portion of a POST request. Note that some buggy browsers + * fail to set the encoding type. If you want to support those, you + * may have to call #MHD_set_connection_value with the proper encoding + * type before creating a post processor (if no supported encoding + * type is set, this function will fail). + * + * @param connection the connection on which the POST is + * happening (used to determine the POST format) + * @param buffer_size maximum number of bytes to use for + * internal buffering (used only for the parsing, + * specifically the parsing of the keys). A + * tiny value (256-1024) should be sufficient. + * Do NOT use a value smaller than 256. For good + * performance, use 32 or 64k (i.e. 65536). + * @param iter iterator to be called with the parsed data, + * Must NOT be NULL. + * @param iter_cls first argument to @a iter + * @return NULL on error (out of memory, unsupported encoding), + * otherwise a PP handle + * @ingroup request + */ +_MHD_EXTERN struct MHD_PostProcessor * +MHD_post_processor_create (struct MHD_Connection *connection, + size_t buffer_size, + MHD_PostDataIterator iter, + void *iter_cls); + + +/** + * Parse and process POST data. Call this function when POST data is + * available (usually during an #MHD_AccessHandlerCallback) with the + * "upload_data" and "upload_data_size". Whenever possible, this will + * then cause calls to the #MHD_PostDataIterator. + * + * @param pp the post processor + * @param post_data @a post_data_len bytes of POST data + * @param post_data_len length of @a post_data + * @return #MHD_YES on success, #MHD_NO on error + * (out-of-memory, iterator aborted, parse error) + * @ingroup request + */ +_MHD_EXTERN enum MHD_Bool +MHD_post_processor_run (struct MHD_PostProcessor *pp, + const char *post_data, + size_t post_data_len); + + +/** + * Release PostProcessor resources. + * + * @param pp the PostProcessor to destroy + * @return #MHD_YES if processing completed nicely, + * #MHD_NO if there were spurious characters / formatting + * problems; it is common to ignore the return + * value of this function + * @ingroup request + */ +_MHD_EXTERN enum MHD_Bool +MHD_post_processor_destroy (struct MHD_PostProcessor *pp); + + +/* ********************** generic query functions ********************** */ + + +/** + * Select which member of the `struct ConnectionInformation` + * union is desired to be returned by #MHD_connection_get_info(). + */ +enum MHD_ConnectionInformationType +{ + /** + * What cipher algorithm is being used. + * Takes no extra arguments. + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_CIPHER_ALGO, + + /** + * + * Takes no extra arguments. + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_PROTOCOL, + + /** + * Obtain IP address of the client. Takes no extra arguments. + * Returns essentially a `struct sockaddr **` (since the API returns + * a `union MHD_ConnectionInfo *` and that union contains a `struct + * sockaddr *`). + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_CLIENT_ADDRESS, + + /** + * Get the gnuTLS session handle. + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_GNUTLS_SESSION, + + /** + * Get the gnuTLS client certificate handle. Dysfunctional (never + * implemented, deprecated). Use #MHD_CONNECTION_INFORMATION_GNUTLS_SESSION + * to get the `gnutls_session_t` and then call + * gnutls_certificate_get_peers(). + */ + MHD_CONNECTION_INFORMATION_GNUTLS_CLIENT_CERT, + + /** + * Get the `struct MHD_Daemon *` responsible for managing this connection. + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_DAEMON, + + /** + * Request the file descriptor for the connection socket. + * No extra arguments should be passed. + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_CONNECTION_FD, + + /** + * Returns the client-specific pointer to a `void *` that was (possibly) + * set during a #MHD_NotifyConnectionCallback when the socket was + * first accepted. Note that this is NOT the same as the "con_cls" + * argument of the #MHD_AccessHandlerCallback. The "con_cls" is + * fresh for each HTTP request, while the "socket_context" is fresh + * for each socket. + */ + MHD_CONNECTION_INFORMATION_SOCKET_CONTEXT, + + /** + * Get connection timeout + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_CONNECTION_TIMEOUT + +}; + + +/** + * Information about a connection. + */ +union MHD_ConnectionInformation +{ + + /** + * Cipher algorithm used, of type "enum gnutls_cipher_algorithm". + */ + int /* enum gnutls_cipher_algorithm */ cipher_algorithm; + + /** + * Protocol used, of type "enum gnutls_protocol". + */ + int /* enum gnutls_protocol */ protocol; + + /** + * Amount of second that connection could spend in idle state + * before automatically disconnected. + * Zero for no timeout (unlimited idle time). + */ + unsigned int connection_timeout; + + /** + * Connect socket + */ + MHD_socket connect_fd; + + /** + * GNUtls session handle, of type "gnutls_session_t". + */ + void * /* gnutls_session_t */ tls_session; + + /** + * GNUtls client certificate handle, of type "gnutls_x509_crt_t". + */ + void * /* gnutls_x509_crt_t */ client_cert; + + /** + * Address information for the client. + */ + struct sockaddr *client_addr; + + /** + * Which daemon manages this connection (useful in case there are many + * daemons running). + */ + struct MHD_Daemon *daemon; + + /** + * Socket-specific client context. Points to the same address as + * the "socket_context" of the #MHD_NotifyConnectionCallback. + */ + void *socket_context; +}; + + +/** + * Obtain information about the given connection. + * + * @param connection what connection to get information about + * @param info_type what information is desired? + * @param ... depends on @a info_type + * @return NULL if this information is not available + * (or if the @a info_type is unknown) + * @ingroup specialized + */ +_MHD_EXTERN const union MHD_ConnectionInformation * +MHD_connection_get_information (struct MHD_Connection *connection, + enum MHD_ConnectionInformationType info_type, + ...); + + +/** + * Information we return about a request. + */ +union MHD_RequestInformation +{ + + /** + * Connection via which we received the request. + */ + struct MHD_Connection *connection; + + /** + * The suspended status of a request. + */ + enum MHD_Bool suspended; + + /** + * HTTP version requested by the client. + */ + const char *http_version; + + /** + * Size of the client's HTTP header. + */ + size_t header_size; + +}; + + +/** + * Select which member of the `struct RequestInformation` + * union is desired to be returned by #MHD_request_get_info(). + */ +enum MHD_RequestInformationType +{ + /** + * Return which connection the request is associated with. + */ + MHD_REQUEST_INFORMATION_CONNECTION, + + /** + * Check whether the connection is suspended. + * @ingroup request + */ + MHD_REQUEST_INFORMATION_SUSPENDED, + + /** + * Return the HTTP version string given by the client. + * @ingroup request + */ + MHD_REQUEST_INFORMATION_HTTP_VERSION, + + /** + * Return length of the client's HTTP request header. + * @ingroup request + */ + MHD_REQUEST_INFORMATION_HEADER_SIZE +}; + + +/** + * Obtain information about the given connection. + * + * @param connection what connection to get information about + * @param info_type what information is desired? + * @param ... depends on @a info_type + * @return NULL if this information is not available + * (or if the @a info_type is unknown) + * @ingroup specialized + */ +_MHD_EXTERN const union MHD_RequestInformation * +MHD_request_get_information (struct MHD_Request *request, + enum MHD_RequestInformationType info_type, + ...); + + +/** + * Values of this enum are used to specify what + * information about a deamon is desired. + */ +enum MHD_DaemonInformationType +{ + + /** + * Request the file descriptor for the listening socket. + * No extra arguments should be passed. + */ + MHD_DAEMON_INFORMATION_LISTEN_FD, + + /** + * Request the file descriptor for the external epoll. + * No extra arguments should be passed. + */ + MHD_DAEMON_INFORMATION_EPOLL_FD, + + /** + * Request the number of current connections handled by the daemon. + * No extra arguments should be passed. + * Note: when using MHD in external polling mode, this type of request + * could be used only when #MHD_run()/#MHD_run_from_select is not + * working in other thread at the same time. + */ + MHD_DAEMON_INFORMATION_CURRENT_CONNECTIONS, + + /** + * Request the port number of daemon's listen socket. + * No extra arguments should be passed. + * Note: if port '0' was specified for #MHD_option_port(), returned + * value will be real port number. + */ + MHD_DAEMON_INFORMATION_BIND_PORT +}; + + +/** + * Information about an MHD daemon. + */ +union MHD_DaemonInformation +{ + + /** + * Socket, returned for #MHD_DAEMON_INFORMATION_LISTEN_FD. + */ + MHD_socket listen_fd; + + /** + * Bind port number, returned for #MHD_DAEMON_INFORMATION_BIND_PORT. + */ + uint16_t port; + + /** + * epoll FD, returned for #MHD_DAEMON_INFORMATION_EPOLL_FD. + */ + int epoll_fd; + + /** + * Number of active connections, for #MHD_DAEMON_INFORMATION_CURRENT_CONNECTIONS. + */ + unsigned int num_connections; + +}; + + +/** + * Obtain information about the given daemon + * (not fully implemented!). + * + * @param daemon what daemon to get information about + * @param info_type what information is desired? + * @param ... depends on @a info_type + * @return NULL if this information is not available + * (or if the @a info_type is unknown) + * @ingroup specialized + */ +_MHD_EXTERN const union MHD_DaemonInformation * +MHD_daemon_get_information (struct MHD_Daemon *daemon, + enum MHD_DaemonInformationType info_type, + ...); +