From b926a975e6633e9d4d1c2ec21f459e55a5ceb5de Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 15 Feb 2018 02:52:09 +0100 Subject: get src/lib/ to build -- with plenty of warnings --- src/include/microhttpd2.h | 398 +++++++++++++++++++++++++++++++++++++++++ src/lib/Makefile.am | 16 +- src/lib/daemon_create.c | 4 + src/lib/daemon_destroy.c | 179 ++++++++++-------- src/lib/daemon_options.c | 13 ++ src/lib/daemon_quiesce.c | 2 +- src/lib/daemon_start.c | 237 +++++++++++++----------- src/lib/init.c | 31 ++++ src/lib/internal.c | 26 +-- src/lib/internal.h | 31 +++- src/lib/reason_phrase.c | 182 +++++++++++++++++++ src/lib/response_for_upgrade.c | 4 +- 12 files changed, 912 insertions(+), 211 deletions(-) create mode 100644 src/lib/reason_phrase.c diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h index f4b39fbe..bb65f534 100644 --- a/src/include/microhttpd2.h +++ b/src/include/microhttpd2.h @@ -520,7 +520,28 @@ enum MHD_StatusCode */ MHD_SC_THREAD_POOL_LAUNCH_FAILURE = 50031, + /** + * We failed to add a socket to the epoll() set. + */ + MHD_SC_EPOLL_CTL_ADD_FAILED = 50032, + + /** + * We failed to start a thread. + */ + MHD_SC_THREAD_LAUNCH_FAILURE = 50033, + /** + * We failed to create control socket for the epoll(). + */ + MHD_SC_EPOLL_CTL_CREATE_FAILED = 50034, + + /** + * We failed to configure control socket for the epoll() + * to be non-inheritable. + */ + MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED = 50035, + + }; @@ -542,6 +563,12 @@ struct MHD_Action; * add additional methods (as per IANA registry), thus even if the API * returns "unknown" today, it may return a method-specific header in * the future! + * + * @defgroup methods HTTP methods + * HTTP methods (as strings). + * See: http://www.iana.org/assignments/http-methods/http-methods.xml + * Registry Version 2015-05-19 + * @{ */ enum MHD_Method { @@ -553,31 +580,37 @@ enum MHD_Method /** * "OPTIONS" method. + * Safe. Idempotent. RFC7231, Section 4.3.7. */ MHD_METHOD_OPTIONS = 1, /** * "GET" method. + * Safe. Idempotent. RFC7231, Section 4.3.1. */ MHD_METHOD_GET = 2, /** * "HEAD" method. + * Safe. Idempotent. RFC7231, Section 4.3.2. */ MHD_METHOD_HEAD = 3, /** * "POST" method. + * Not safe. Not idempotent. RFC7231, Section 4.3.3. */ MHD_METHOD_POST = 4, /** * "PUT" method. + * Not safe. Idempotent. RFC7231, Section 4.3.4. */ MHD_METHOD_PUT = 5, /** * "DELETE" method. + * Not safe. Idempotent. RFC7231, Section 4.3.5. */ MHD_METHOD_DELETE = 6, @@ -746,6 +779,339 @@ enum MHD_Method }; +/** @} */ /* end of group methods */ + + +/** + * @defgroup postenc HTTP POST encodings + * See also: http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 + * @{ + */ +#define MHD_HTTP_POST_ENCODING_FORM_URLENCODED "application/x-www-form-urlencoded" +#define MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA "multipart/form-data" + +/** @} */ /* end of group postenc */ + + + +/** + * @defgroup headers HTTP headers + * These are the standard headers found in HTTP requests and responses. + * See: http://www.iana.org/assignments/message-headers/message-headers.xml + * Registry Version 2017-01-27 + * @{ + */ + +/* Main HTTP headers. */ +/* Standard. RFC7231, Section 5.3.2 */ +#define MHD_HTTP_HEADER_ACCEPT "Accept" +/* Standard. RFC7231, Section 5.3.3 */ +#define MHD_HTTP_HEADER_ACCEPT_CHARSET "Accept-Charset" +/* Standard. RFC7231, Section 5.3.4; RFC7694, Section 3 */ +#define MHD_HTTP_HEADER_ACCEPT_ENCODING "Accept-Encoding" +/* Standard. RFC7231, Section 5.3.5 */ +#define MHD_HTTP_HEADER_ACCEPT_LANGUAGE "Accept-Language" +/* Standard. RFC7233, Section 2.3 */ +#define MHD_HTTP_HEADER_ACCEPT_RANGES "Accept-Ranges" +/* Standard. RFC7234, Section 5.1 */ +#define MHD_HTTP_HEADER_AGE "Age" +/* Standard. RFC7231, Section 7.4.1 */ +#define MHD_HTTP_HEADER_ALLOW "Allow" +/* Standard. RFC7235, Section 4.2 */ +#define MHD_HTTP_HEADER_AUTHORIZATION "Authorization" +/* Standard. RFC7234, Section 5.2 */ +#define MHD_HTTP_HEADER_CACHE_CONTROL "Cache-Control" +/* Reserved. RFC7230, Section 8.1 */ +#define MHD_HTTP_HEADER_CLOSE "Close" +/* Standard. RFC7230, Section 6.1 */ +#define MHD_HTTP_HEADER_CONNECTION "Connection" +/* Standard. RFC7231, Section 3.1.2.2 */ +#define MHD_HTTP_HEADER_CONTENT_ENCODING "Content-Encoding" +/* Standard. RFC7231, Section 3.1.3.2 */ +#define MHD_HTTP_HEADER_CONTENT_LANGUAGE "Content-Language" +/* Standard. RFC7230, Section 3.3.2 */ +#define MHD_HTTP_HEADER_CONTENT_LENGTH "Content-Length" +/* Standard. RFC7231, Section 3.1.4.2 */ +#define MHD_HTTP_HEADER_CONTENT_LOCATION "Content-Location" +/* Standard. RFC7233, Section 4.2 */ +#define MHD_HTTP_HEADER_CONTENT_RANGE "Content-Range" +/* Standard. RFC7231, Section 3.1.1.5 */ +#define MHD_HTTP_HEADER_CONTENT_TYPE "Content-Type" +/* Standard. RFC7231, Section 7.1.1.2 */ +#define MHD_HTTP_HEADER_DATE "Date" +/* Standard. RFC7232, Section 2.3 */ +#define MHD_HTTP_HEADER_ETAG "ETag" +/* Standard. RFC7231, Section 5.1.1 */ +#define MHD_HTTP_HEADER_EXPECT "Expect" +/* Standard. RFC7234, Section 5.3 */ +#define MHD_HTTP_HEADER_EXPIRES "Expires" +/* Standard. RFC7231, Section 5.5.1 */ +#define MHD_HTTP_HEADER_FROM "From" +/* Standard. RFC7230, Section 5.4 */ +#define MHD_HTTP_HEADER_HOST "Host" +/* Standard. RFC7232, Section 3.1 */ +#define MHD_HTTP_HEADER_IF_MATCH "If-Match" +/* Standard. RFC7232, Section 3.3 */ +#define MHD_HTTP_HEADER_IF_MODIFIED_SINCE "If-Modified-Since" +/* Standard. RFC7232, Section 3.2 */ +#define MHD_HTTP_HEADER_IF_NONE_MATCH "If-None-Match" +/* Standard. RFC7233, Section 3.2 */ +#define MHD_HTTP_HEADER_IF_RANGE "If-Range" +/* Standard. RFC7232, Section 3.4 */ +#define MHD_HTTP_HEADER_IF_UNMODIFIED_SINCE "If-Unmodified-Since" +/* Standard. RFC7232, Section 2.2 */ +#define MHD_HTTP_HEADER_LAST_MODIFIED "Last-Modified" +/* Standard. RFC7231, Section 7.1.2 */ +#define MHD_HTTP_HEADER_LOCATION "Location" +/* Standard. RFC7231, Section 5.1.2 */ +#define MHD_HTTP_HEADER_MAX_FORWARDS "Max-Forwards" +/* Standard. RFC7231, Appendix A.1 */ +#define MHD_HTTP_HEADER_MIME_VERSION "MIME-Version" +/* Standard. RFC7234, Section 5.4 */ +#define MHD_HTTP_HEADER_PRAGMA "Pragma" +/* Standard. RFC7235, Section 4.3 */ +#define MHD_HTTP_HEADER_PROXY_AUTHENTICATE "Proxy-Authenticate" +/* Standard. RFC7235, Section 4.4 */ +#define MHD_HTTP_HEADER_PROXY_AUTHORIZATION "Proxy-Authorization" +/* Standard. RFC7233, Section 3.1 */ +#define MHD_HTTP_HEADER_RANGE "Range" +/* Standard. RFC7231, Section 5.5.2 */ +#define MHD_HTTP_HEADER_REFERER "Referer" +/* Standard. RFC7231, Section 7.1.3 */ +#define MHD_HTTP_HEADER_RETRY_AFTER "Retry-After" +/* Standard. RFC7231, Section 7.4.2 */ +#define MHD_HTTP_HEADER_SERVER "Server" +/* Standard. RFC7230, Section 4.3 */ +#define MHD_HTTP_HEADER_TE "TE" +/* Standard. RFC7230, Section 4.4 */ +#define MHD_HTTP_HEADER_TRAILER "Trailer" +/* Standard. RFC7230, Section 3.3.1 */ +#define MHD_HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding" +/* Standard. RFC7230, Section 6.7 */ +#define MHD_HTTP_HEADER_UPGRADE "Upgrade" +/* Standard. RFC7231, Section 5.5.3 */ +#define MHD_HTTP_HEADER_USER_AGENT "User-Agent" +/* Standard. RFC7231, Section 7.1.4 */ +#define MHD_HTTP_HEADER_VARY "Vary" +/* Standard. RFC7230, Section 5.7.1 */ +#define MHD_HTTP_HEADER_VIA "Via" +/* Standard. RFC7235, Section 4.1 */ +#define MHD_HTTP_HEADER_WWW_AUTHENTICATE "WWW-Authenticate" +/* Standard. RFC7234, Section 5.5 */ +#define MHD_HTTP_HEADER_WARNING "Warning" + +/* Additional HTTP headers. */ +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_A_IM "A-IM" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_ACCEPT_ADDITIONS "Accept-Additions" +/* Informational. RFC7089 */ +#define MHD_HTTP_HEADER_ACCEPT_DATETIME "Accept-Datetime" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_ACCEPT_FEATURES "Accept-Features" +/* No category. RFC5789 */ +#define MHD_HTTP_HEADER_ACCEPT_PATCH "Accept-Patch" +/* Standard. RFC7639, Section 2 */ +#define MHD_HTTP_HEADER_ALPN "ALPN" +/* Standard. RFC7838 */ +#define MHD_HTTP_HEADER_ALT_SVC "Alt-Svc" +/* Standard. RFC7838 */ +#define MHD_HTTP_HEADER_ALT_USED "Alt-Used" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_ALTERNATES "Alternates" +/* No category. RFC4437 */ +#define MHD_HTTP_HEADER_APPLY_TO_REDIRECT_REF "Apply-To-Redirect-Ref" +/* Experimental. RFC8053, Section 4 */ +#define MHD_HTTP_HEADER_AUTHENTICATION_CONTROL "Authentication-Control" +/* Standard. RFC7615, Section 3 */ +#define MHD_HTTP_HEADER_AUTHENTICATION_INFO "Authentication-Info" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_C_EXT "C-Ext" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_C_MAN "C-Man" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_C_OPT "C-Opt" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_C_PEP "C-PEP" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_C_PEP_INFO "C-PEP-Info" +/* Standard. RFC7809, Section 7.1 */ +#define MHD_HTTP_HEADER_CALDAV_TIMEZONES "CalDAV-Timezones" +/* Obsoleted. RFC2068; RFC2616 */ +#define MHD_HTTP_HEADER_CONTENT_BASE "Content-Base" +/* Standard. RFC6266 */ +#define MHD_HTTP_HEADER_CONTENT_DISPOSITION "Content-Disposition" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_CONTENT_ID "Content-ID" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_CONTENT_MD5 "Content-MD5" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_CONTENT_SCRIPT_TYPE "Content-Script-Type" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_CONTENT_STYLE_TYPE "Content-Style-Type" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_CONTENT_VERSION "Content-Version" +/* Standard. RFC6265 */ +#define MHD_HTTP_HEADER_COOKIE "Cookie" +/* Obsoleted. RFC2965; RFC6265 */ +#define MHD_HTTP_HEADER_COOKIE2 "Cookie2" +/* Standard. RFC5323 */ +#define MHD_HTTP_HEADER_DASL "DASL" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_DAV "DAV" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_DEFAULT_STYLE "Default-Style" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_DELTA_BASE "Delta-Base" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_DEPTH "Depth" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_DERIVED_FROM "Derived-From" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_DESTINATION "Destination" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_DIFFERENTIAL_ID "Differential-ID" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_DIGEST "Digest" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_EXT "Ext" +/* Standard. RFC7239 */ +#define MHD_HTTP_HEADER_FORWARDED "Forwarded" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_GETPROFILE "GetProfile" +/* Experimental. RFC7486, Section 6.1.1 */ +#define MHD_HTTP_HEADER_HOBAREG "Hobareg" +/* Standard. RFC7540, Section 3.2.1 */ +#define MHD_HTTP_HEADER_HTTP2_SETTINGS "HTTP2-Settings" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_IM "IM" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_IF "If" +/* Standard. RFC6638 */ +#define MHD_HTTP_HEADER_IF_SCHEDULE_TAG_MATCH "If-Schedule-Tag-Match" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_KEEP_ALIVE "Keep-Alive" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_LABEL "Label" +/* No category. RFC5988 */ +#define MHD_HTTP_HEADER_LINK "Link" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_LOCK_TOKEN "Lock-Token" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_MAN "Man" +/* Informational. RFC7089 */ +#define MHD_HTTP_HEADER_MEMENTO_DATETIME "Memento-Datetime" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_METER "Meter" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_NEGOTIATE "Negotiate" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_OPT "Opt" +/* Experimental. RFC8053, Section 3 */ +#define MHD_HTTP_HEADER_OPTIONAL_WWW_AUTHENTICATE "Optional-WWW-Authenticate" +/* Standard. RFC4229 */ +#define MHD_HTTP_HEADER_ORDERING_TYPE "Ordering-Type" +/* Standard. RFC6454 */ +#define MHD_HTTP_HEADER_ORIGIN "Origin" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_OVERWRITE "Overwrite" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_P3P "P3P" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PEP "PEP" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PICS_LABEL "PICS-Label" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PEP_INFO "Pep-Info" +/* Standard. RFC4229 */ +#define MHD_HTTP_HEADER_POSITION "Position" +/* Standard. RFC7240 */ +#define MHD_HTTP_HEADER_PREFER "Prefer" +/* Standard. RFC7240 */ +#define MHD_HTTP_HEADER_PREFERENCE_APPLIED "Preference-Applied" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROFILEOBJECT "ProfileObject" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROTOCOL "Protocol" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROTOCOL_INFO "Protocol-Info" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROTOCOL_QUERY "Protocol-Query" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROTOCOL_REQUEST "Protocol-Request" +/* Standard. RFC7615, Section 4 */ +#define MHD_HTTP_HEADER_PROXY_AUTHENTICATION_INFO "Proxy-Authentication-Info" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROXY_FEATURES "Proxy-Features" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PROXY_INSTRUCTION "Proxy-Instruction" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_PUBLIC "Public" +/* Standard. RFC7469 */ +#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS "Public-Key-Pins" +/* Standard. RFC7469 */ +#define MHD_HTTP_HEADER_PUBLIC_KEY_PINS_REPORT_ONLY "Public-Key-Pins-Report-Only" +/* No category. RFC4437 */ +#define MHD_HTTP_HEADER_REDIRECT_REF "Redirect-Ref" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_SAFE "Safe" +/* Standard. RFC6638 */ +#define MHD_HTTP_HEADER_SCHEDULE_REPLY "Schedule-Reply" +/* Standard. RFC6638 */ +#define MHD_HTTP_HEADER_SCHEDULE_TAG "Schedule-Tag" +/* Standard. RFC6455 */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_ACCEPT "Sec-WebSocket-Accept" +/* Standard. RFC6455 */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_EXTENSIONS "Sec-WebSocket-Extensions" +/* Standard. RFC6455 */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_KEY "Sec-WebSocket-Key" +/* Standard. RFC6455 */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_PROTOCOL "Sec-WebSocket-Protocol" +/* Standard. RFC6455 */ +#define MHD_HTTP_HEADER_SEC_WEBSOCKET_VERSION "Sec-WebSocket-Version" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_SECURITY_SCHEME "Security-Scheme" +/* Standard. RFC6265 */ +#define MHD_HTTP_HEADER_SET_COOKIE "Set-Cookie" +/* Obsoleted. RFC2965; RFC6265 */ +#define MHD_HTTP_HEADER_SET_COOKIE2 "Set-Cookie2" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_SETPROFILE "SetProfile" +/* Standard. RFC5023 */ +#define MHD_HTTP_HEADER_SLUG "SLUG" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_SOAPACTION "SoapAction" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_STATUS_URI "Status-URI" +/* Standard. RFC6797 */ +#define MHD_HTTP_HEADER_STRICT_TRANSPORT_SECURITY "Strict-Transport-Security" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_SURROGATE_CAPABILITY "Surrogate-Capability" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_SURROGATE_CONTROL "Surrogate-Control" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_TCN "TCN" +/* Standard. RFC4918 */ +#define MHD_HTTP_HEADER_TIMEOUT "Timeout" +/* Standard. RFC8030, Section 5.4 */ +#define MHD_HTTP_HEADER_TOPIC "Topic" +/* Standard. RFC8030, Section 5.2 */ +#define MHD_HTTP_HEADER_TTL "TTL" +/* Standard. RFC8030, Section 5.3 */ +#define MHD_HTTP_HEADER_URGENCY "Urgency" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_URI "URI" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_VARIANT_VARY "Variant-Vary" +/* No category. RFC4229 */ +#define MHD_HTTP_HEADER_WANT_DIGEST "Want-Digest" +/* Informational. RFC7034 */ +#define MHD_HTTP_HEADER_X_FRAME_OPTIONS "X-Frame-Options" + +/* Some provisional headers. */ +#define MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN "Access-Control-Allow-Origin" +/** @} */ /* end of group headers */ + /** * A client has requested the given url using the given method @@ -1186,6 +1552,16 @@ MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon, enum MHD_ProtocolStrictLevel sl); +/** + * Use SHOUTcast. This will cause the response to begin + * with the SHOUTcast "ICY" line instad of "HTTP". + * + * @param daemon daemon to set SHOUTcast option for + */ +_MHD_EXTERN void +MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon); + + /** * Enable and configure TLS. * @@ -1836,9 +2212,31 @@ enum MHD_HTTP_StatusCode { MHD_HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511 }; + + +/** + * Returns the string reason phrase for a response code. + * + * If we don't have a string for a status code, we give the first + * message in that status code class. + */ +_MHD_EXTERN const char * +MHD_get_reason_phrase_for (enum MHD_HTTP_StatusCode code); + /** @} */ /* end of group httpcode */ +/** + * @defgroup versions HTTP versions + * These strings should be used to match against the first line of the + * HTTP header. + * @{ + */ +#define MHD_HTTP_VERSION_1_0 "HTTP/1.0" +#define MHD_HTTP_VERSION_1_1 "HTTP/1.1" + +/** @} */ /* end of group versions */ + /** * Suspend handling of network data for a given request. This can diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index bba6b620..f982c70a 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -143,22 +143,22 @@ endif # TBD! if HAVE_POSTPROCESSOR -libmicrohttpd_la_SOURCES += \ - postprocessor.c +#libmicrohttpd_la_SOURCES += \ +# postprocessor.c endif # TBD! if ENABLE_DAUTH -libmicrohttpd_la_SOURCES += \ - digestauth.c \ - md5.c md5.h +#libmicrohttpd_la_SOURCES += \ +# digestauth.c \ +# md5.c md5.h endif # TBD! if ENABLE_BAUTH -libmicrohttpd_la_SOURCES += \ - basicauth.c \ - base64.c base64.h +#libmicrohttpd_la_SOURCES += \ +# basicauth.c \ +# base64.c base64.h endif diff --git a/src/lib/daemon_create.c b/src/lib/daemon_create.c index f1042789..e124b745 100644 --- a/src/lib/daemon_create.c +++ b/src/lib/daemon_create.c @@ -23,6 +23,7 @@ * @author Christian Grothoff */ #include "internal.h" +#include "init.h" /** @@ -95,6 +96,9 @@ MHD_daemon_create (MHD_RequestCallback cb, memset (daemon, 0, sizeof (struct MHD_Daemon)); +#ifdef EPOLL_SUPPORT + daemon->epoll_itc_marker = "itc_marker"; +#endif daemon->rc = cb; daemon->rc_cls = cb_cls; daemon->logger = &file_logger; diff --git a/src/lib/daemon_destroy.c b/src/lib/daemon_destroy.c index b1743088..1a8f7094 100644 --- a/src/lib/daemon_destroy.c +++ b/src/lib/daemon_destroy.c @@ -24,7 +24,63 @@ */ #include "internal.h" -/* TODO: migrate logic below! */ + +/** + * Stop all worker threads from the worker pool. + * + * @param daemon master daemon controling the workers + */ +static void +stop_workers (struct MHD_Daemon *daemon) +{ + MHD_socket fd; + unsigned int i; + + mhd_assert (1 < daemon->worker_pool_size); + mhd_assert (1 < daemon->threading_model); + if (daemon->was_quiesced) + fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */ + else + fd = daemon->listen_socket; + /* Let workers shutdown in parallel. */ + for (i = 0; i < daemon->worker_pool_size; i++) + { + daemon->worker_pool[i].shutdown = true; + if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc)) + { + if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, + "e")) + MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel.")); + } + else + { + /* Better hope shutdown() works... */ + mhd_assert (MHD_INVALID_SOCKET != fd); + } + } +#ifdef HAVE_LISTEN_SHUTDOWN + if (MHD_INVALID_SOCKET != fd) + { + (void) shutdown (fd, + SHUT_RDWR); + } +#endif /* HAVE_LISTEN_SHUTDOWN */ + for (i = 0; i < daemon->worker_pool_size; ++i) + { + MHD_daemon_destroy (&daemon->worker_pool[i]); + } + free (daemon->worker_pool); + daemon->worker_pool = NULL; + /* FIXME: does this still hold? */ + mhd_assert (MHD_ITC_IS_INVALID_(daemon->itc)); +#ifdef EPOLL_SUPPORT + mhd_assert (-1 == daemon->epoll_fd); +#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) + mhd_assert (-1 == daemon->epoll_upgrade_fd); +#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ +#endif /* EPOLL_SUPPORT */ +} + /** * Shutdown and destroy an HTTP daemon. @@ -36,7 +92,6 @@ void MHD_daemon_destroy (struct MHD_Daemon *daemon) { MHD_socket fd; - unsigned int i; if (NULL == daemon) return; @@ -50,92 +105,60 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon) if (NULL != daemon->worker_pool) { /* Master daemon with worker pool. */ - mhd_assert (1 < daemon->worker_pool_size); - mhd_assert (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)); - - /* Let workers shutdown in parallel. */ - for (i = 0; i < daemon->worker_pool_size; ++i) - { - daemon->worker_pool[i].shutdown = true; - if (MHD_ITC_IS_VALID_(daemon->worker_pool[i].itc)) - { - if (! MHD_itc_activate_ (daemon->worker_pool[i].itc, "e")) - MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel.")); - } - else - mhd_assert (MHD_INVALID_SOCKET != fd); - } -#ifdef HAVE_LISTEN_SHUTDOWN - if (MHD_INVALID_SOCKET != fd) - { - (void) shutdown (fd, - SHUT_RDWR); - } -#endif /* HAVE_LISTEN_SHUTDOWN */ - for (i = 0; i < daemon->worker_pool_size; ++i) - { - MHD_stop_daemon (&daemon->worker_pool[i]); - } - free (daemon->worker_pool); - mhd_assert (MHD_ITC_IS_INVALID_(daemon->itc)); -#ifdef EPOLL_SUPPORT - mhd_assert (-1 == daemon->epoll_fd); -#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) - mhd_assert (-1 == daemon->epoll_upgrade_fd); -#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ -#endif /* EPOLL_SUPPORT */ + stop_workers (daemon); } else - { /* Worker daemon or single daemon. */ - if (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) - { /* Worker daemon or single daemon with internal thread(s). */ - mhd_assert (0 == daemon->worker_pool_size); - if (0 != (MHD_TEST_ALLOW_SUSPEND_RESUME & daemon->options)) + { + mhd_assert (0 == daemon->worker_pool_size); + /* Worker daemon or single-thread daemon. */ + if (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_model) + { + /* Worker daemon or single daemon with internal thread(s). */ + if (! daemon->disallow_suspend_resume) resume_suspended_connections (daemon); - if (0 != (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) - { - /* Separate thread(s) is used for polling sockets. */ - if (MHD_ITC_IS_VALID_(daemon->itc)) - { - if (! MHD_itc_activate_ (daemon->itc, "e")) - MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel")); - } - else - { + /* Separate thread(s) is used for polling sockets. */ + if (MHD_ITC_IS_VALID_(daemon->itc)) + { + if (! MHD_itc_activate_ (daemon->itc, + "e")) + MHD_PANIC (_("Failed to signal shutdown via inter-thread communication channel")); + } + else + { #ifdef HAVE_LISTEN_SHUTDOWN - if (MHD_INVALID_SOCKET != fd) - { - if (NULL == daemon->master) - (void) shutdown (fd, - SHUT_RDWR); - } - else + if (MHD_INVALID_SOCKET != fd) + { + if (NULL == daemon->master) + (void) shutdown (fd, + SHUT_RDWR); + } + else #endif /* HAVE_LISTEN_SHUTDOWN */ - mhd_assert (false); /* Should never happen */ - } - - if (! MHD_join_thread_ (daemon->pid.handle)) - { - MHD_PANIC (_("Failed to join a thread\n")); - } - /* close_all_connections() was called in daemon thread. */ - } - } + mhd_assert (false); /* Should never happen */ + } + + if (! MHD_join_thread_ (daemon->pid.handle)) + { + MHD_PANIC (_("Failed to join a thread\n")); + } + /* close_all_connections() was called in daemon thread. */ + } else { - /* No internal threads are used for polling sockets. */ + /* No internal threads are used for polling sockets + (external event loop) */ close_all_connections (daemon); } if (MHD_ITC_IS_VALID_ (daemon->itc)) MHD_itc_destroy_chk_ (daemon->itc); #ifdef EPOLL_SUPPORT - if ( (0 != (daemon->options & MHD_USE_EPOLL)) && + if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && (-1 != daemon->epoll_fd) ) MHD_socket_close_chk_ (daemon->epoll_fd); #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) - if ( (0 != (daemon->options & MHD_USE_EPOLL)) && + if ( (MHD_ELS_EPOLL == daemon->event_loop_syscall) && (-1 != daemon->epoll_upgrade_fd) ) MHD_socket_close_chk_ (daemon->epoll_upgrade_fd); #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ @@ -154,16 +177,18 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon) /* TLS clean up */ #ifdef HTTPS_SUPPORT - if (daemon->have_dhparams) - { - gnutls_dh_params_deinit (daemon->https_mem_dhparams); - daemon->have_dhparams = false; - } - if (0 != (daemon->options & MHD_USE_TLS)) + if (NULL != daemon->tls_api) { +#if FIXME_TLS_API + if (daemon->have_dhparams) + { + gnutls_dh_params_deinit (daemon->https_mem_dhparams); + daemon->have_dhparams = false; + } gnutls_priority_deinit (daemon->priority_cache); if (daemon->x509_cred) gnutls_certificate_free_credentials (daemon->x509_cred); +#endif } #endif /* HTTPS_SUPPORT */ diff --git a/src/lib/daemon_options.c b/src/lib/daemon_options.c index 4693b692..991b9898 100644 --- a/src/lib/daemon_options.c +++ b/src/lib/daemon_options.c @@ -245,6 +245,19 @@ MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon) } +/** + * Use SHOUTcast. This will cause the response to begin + * with the SHOUTcast "ICY" line instad of "HTTP". + * + * @param daemon daemon to set SHOUTcast option for + */ +_MHD_EXTERN void +MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon) +{ + daemon->enable_shoutcast = true; +} + + /** * Accept connections from the given socket. Socket * must be a TCP or UNIX domain (stream) socket. diff --git a/src/lib/daemon_quiesce.c b/src/lib/daemon_quiesce.c index 31104a7d..caad0a25 100644 --- a/src/lib/daemon_quiesce.c +++ b/src/lib/daemon_quiesce.c @@ -67,7 +67,7 @@ MHD_daemon_quiesce (struct MHD_Daemon *daemon) { unsigned int i; - for (i = 0; i < daemon->threading_model; i++) + for (i = 0; i < daemon->worker_pool_size; i++) { struct MHD_Daemon *worker = &daemon->worker_pool[i]; diff --git a/src/lib/daemon_start.c b/src/lib/daemon_start.c index 98126c68..ab4a6dd9 100644 --- a/src/lib/daemon_start.c +++ b/src/lib/daemon_start.c @@ -48,40 +48,17 @@ configure_listen_reuse (struct MHD_Daemon *daemon) /* Apply the socket options according to listening_address_reuse. */ - /* FIXME: used to be -1/0/1, now defined as a bool! - MISMATCH! */ - if (0 == daemon->listening_address_reuse) - { -#ifndef MHD_WINSOCK_SOCKETS - /* No user requirement, use "traditional" default SO_REUSEADDR - * on non-W32 platforms, and do not fail if it doesn't work. - * Don't use it on W32, because on W32 it will allow multiple - * bind to the same address:port, like SO_REUSEPORT on others. */ - if (0 > setsockopt (listen_fd, - SOL_SOCKET, - SO_REUSEADDR, - (void*) &on, sizeof (on))) - { -#ifdef HAVE_MESSAGES - MHD_DLOG (daemon, - MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED, - _("setsockopt failed: %s\n"), - MHD_socket_last_strerr_ ()); -#endif - } -#endif /* ! MHD_WINSOCK_SOCKETS */ - return MHD_SC_OK; - } - if (daemon->listening_address_reuse > 0) + if (daemon->allow_address_reuse) { /* User requested to allow reusing listening address:port. */ #ifndef MHD_WINSOCK_SOCKETS /* Use SO_REUSEADDR on non-W32 platforms, and do not fail if * it doesn't work. */ - if (0 > setsockopt (listen_fd, + if (0 > setsockopt (daemon->listen_socket, SOL_SOCKET, SO_REUSEADDR, - (void*)&on, sizeof (on))) + (void *) &on, + sizeof (on))) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -91,6 +68,7 @@ configure_listen_reuse (struct MHD_Daemon *daemon) #endif return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED; } + return MHD_SC_OK; #endif /* ! MHD_WINSOCK_SOCKETS */ /* Use SO_REUSEADDR on Windows and SO_REUSEPORT on most platforms. * Fail if SO_REUSEPORT is not defined or setsockopt fails. @@ -98,7 +76,7 @@ configure_listen_reuse (struct MHD_Daemon *daemon) /* SO_REUSEADDR on W32 has the same semantics as SO_REUSEPORT on BSD/Linux */ #if defined(MHD_WINSOCK_SOCKETS) || defined(SO_REUSEPORT) - if (0 > setsockopt (listen_fd, + if (0 > setsockopt (daemon->listen_socket, SOL_SOCKET, #ifndef MHD_WINSOCK_SOCKETS SO_REUSEPORT, @@ -116,6 +94,7 @@ configure_listen_reuse (struct MHD_Daemon *daemon) #endif return MHD_SC_LISTEN_ADDRESS_REUSE_ENABLE_FAILED; } + return MHD_SC_OK; #else /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */ /* we're supposed to allow address:port re-use, but on this platform we cannot; fail hard */ @@ -128,7 +107,7 @@ configure_listen_reuse (struct MHD_Daemon *daemon) #endif /* !MHD_WINSOCK_SOCKETS && !SO_REUSEPORT */ } - /* if (daemon->listening_address_reuse < 0) */ + /* if (! daemon->allow_address_reuse) */ /* User requested to disallow reusing listening address:port. * Do nothing except for Windows where SO_EXCLUSIVEADDRUSE * is used and Solaris with SO_EXCLBIND. @@ -155,6 +134,7 @@ configure_listen_reuse (struct MHD_Daemon *daemon) #endif return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_FAILED; } + return MHD_SC_OK; #elif defined(MHD_WINSOCK_SOCKETS) /* SO_EXCLUSIVEADDRUSE not defined on W32? */ #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -163,6 +143,7 @@ configure_listen_reuse (struct MHD_Daemon *daemon) #endif return MHD_SC_LISTEN_ADDRESS_REUSE_DISABLE_NOT_SUPPORTED; #endif /* MHD_WINSOCK_SOCKETS */ + /* Not on WINSOCK, simply doing nothing will do */ return MHD_SC_OK; } @@ -183,81 +164,75 @@ open_listen_socket (struct MHD_Daemon *daemon) int pf; bool use_v6; - if (MHD_INVALID_SOCKET != daemon->listen_fd) + if (MHD_INVALID_SOCKET != daemon->listen_socket) return MHD_SC_OK; /* application opened it for us! */ /* Determine address family */ - if (MHD_AF_NONE != daemon->address_family) + switch (daemon->listen_af) { - switch (daemon->address_family) + case MHD_AF_NONE: + if (0 == daemon->listen_sa_len) { - case MHD_AF_NONE: - abort (); - case MHD_AF_AUTO: -#if HAVE_INET6 - pf = PF_INET6; - use_v6 = true; -#else + /* no listening desired, that's OK */ + return MHD_SC_OK; + } + /* we have a listen address, get AF from there! */ + switch (daemon->listen_sa.ss_family) + { + case AF_INET: pf = PF_INET; use_v6 = false; -#endif - break; - case MHD_AF_INET: - use_v6 = false; - pf = PF_INET; break; - case MHD_AF_INET6: - case MHD_AF_DUAL: -#if HAVE_INET6 +#ifdef AF_INET6 + case AF_INET6: pf = PF_INET6; use_v6 = true; break; -#else -#ifdef HAVE_MESSAGES - MHD_DLOG (daemon, - MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD, - _("IPv6 not supported by this build\n")); #endif - return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD; +#ifdef AF_UNIX + case AF_UNIX: + pf = PF_UNIX; + use_v6 = false; + break; #endif - } - } - else if (0 != daemon->listen_sa_len) - { - - /* we have a listen address, get AF from there! */ - switch (daemon->listen_sa.ss_family) - { - case AF_INET: - pf = PF_INET; - use_v6 = false; - break; -#ifdef AF_INET6 - case AF_INET6: - pf = PF_INET6; - use_v6 = true; - break; + default: + return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD; + } /* switch on ss_family */ + break; /* MHD_AF_NONE */ + case MHD_AF_AUTO: +#if HAVE_INET6 + pf = PF_INET6; + use_v6 = true; +#else + pf = PF_INET; + use_v6 = false; #endif -#ifdef AF_UNIX - case AF_UNIX: - pf = PF_UNIX; - use_v6 = false; + break; + case MHD_AF_INET4: + use_v6 = false; + pf = PF_INET; + break; + case MHD_AF_INET6: + case MHD_AF_DUAL: +#if HAVE_INET6 + pf = PF_INET6; + use_v6 = true; + break; +#else +#ifdef HAVE_MESSAGES + MHD_DLOG (daemon, + MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD, + _("IPv6 not supported by this build\n")); +#endif + return MHD_SC_IPV6_NOT_SUPPORTED_BY_BUILD; #endif - default: - return MHD_SC_AF_NOT_SUPPORTED_BY_BUILD; - } - } - else - { - /* no listening desired, that's OK */ - return MHD_SC_OK; } /* try to open listen socket */ try_open_listen_socket: daemon->listen_socket = MHD_socket_create_listen_(pf); if ( (MHD_INVALID_SOCKET == daemon->listen_socket) && - (MHD_AF_AUTO == daemon->address_family) && + (MHD_AF_AUTO == daemon->listen_af) && (use_v6) ) { use_v6 = false; @@ -288,8 +263,8 @@ open_listen_socket (struct MHD_Daemon *daemon) and may also be missing on older POSIX systems; good luck if you have any of those, your IPv6 socket may then also bind against IPv4 anyway... */ const MHD_SCKT_OPT_BOOL_ v6_only = - (MHD_AF_INET6 == daemon->address_family); - if (0 > setsockopt (listen_fd, + (MHD_AF_INET6 == daemon->listen_af); + if (0 > setsockopt (daemon->listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &v6_only, @@ -315,7 +290,7 @@ open_listen_socket (struct MHD_Daemon *daemon) if (0 != daemon->listen_sa_len) { /* Bind address explicitly given */ - sa = daemon->listen_sa; + sa = (const struct sockaddr *) &daemon->listen_sa; addrlen = daemon->listen_sa_len; } else @@ -359,7 +334,7 @@ open_listen_socket (struct MHD_Daemon *daemon) sin4->sin_len = sizeof (struct sockaddr_in); #endif } - sa = (const struct sockaddr *) ss; + sa = (const struct sockaddr *) &ss; } /* actually do the bind() */ @@ -374,13 +349,13 @@ open_listen_socket (struct MHD_Daemon *daemon) { case AF_INET: if (addrlen == sizeof (struct sockaddr_in)) - port = ntohs (((const struct sockaddr_in*)sa)->sin_port); + port = ntohs (((const struct sockaddr_in *) sa)->sin_port); else port = UINT16_MAX + 1; /* indicate size error */ break; case AF_INET6: if (addrlen == sizeof (struct sockaddr_in6)) - port = ntohs (((const struct sockaddr_in6*)sa)->sin_port); + port = ntohs (((const struct sockaddr_in6 *) sa)->sin6_port); else port = UINT16_MAX + 1; /* indicate size error */ break; @@ -404,8 +379,8 @@ open_listen_socket (struct MHD_Daemon *daemon) if (0 != setsockopt (daemon->listen_socket, IPPROTO_TCP, TCP_FASTOPEN, - &daemon->fastopen_queue_size, - sizeof (daemon->fastopen_queue_size))) + &daemon->fo_queue_length, + sizeof (daemon->fo_queue_length))) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -421,7 +396,7 @@ open_listen_socket (struct MHD_Daemon *daemon) /* setup listening */ if (0 > listen (daemon->listen_socket, - daemon->listen_backlog_size)) + daemon->listen_backlog)) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -449,7 +424,7 @@ get_listen_port_number (struct MHD_Daemon *daemon) struct sockaddr_storage servaddr; socklen_t addrlen; - if ( (0 != daemon->port) || + if ( (0 != daemon->listen_port) || (MHD_INVALID_SOCKET == daemon->listen_socket) ) return; /* nothing to be done */ @@ -487,7 +462,7 @@ get_listen_port_number (struct MHD_Daemon *daemon) { struct sockaddr_in *s4 = (struct sockaddr_in *) &servaddr; - daemon->port = ntohs (s4->sin_port); + daemon->listen_port = ntohs (s4->sin_port); break; } #ifdef HAVE_INET6 @@ -495,13 +470,13 @@ get_listen_port_number (struct MHD_Daemon *daemon) { struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &servaddr; - daemon->port = ntohs(s6->sin6_port); + daemon->listen_port = ntohs(s6->sin6_port); break; } #endif /* HAVE_INET6 */ #ifdef AF_UNIX case AF_UNIX: - daemon->port = 0; /* special value for UNIX domain sockets */ + daemon->listen_port = 0; /* special value for UNIX domain sockets */ break; #endif default: @@ -510,12 +485,57 @@ get_listen_port_number (struct MHD_Daemon *daemon) MHD_SC_LISTEN_PORT_INTROSPECTION_UNKNOWN_AF, _("Unknown address family!\n")); #endif - daemon->port = 0; /* ugh */ + daemon->listen_port = 0; /* ugh */ break; } } +#ifdef EPOLL_SUPPORT +/** + * Setup file descriptor to be used for epoll() control. + * + * @param daemon the daemon to setup epoll FD for + * @return the epoll() fd to use + */ +static int +setup_epoll_fd (struct MHD_Daemon *daemon) +{ + int fd; + +#ifndef HAVE_MESSAGES + (void)daemon; /* Mute compiler warning. */ +#endif /* ! HAVE_MESSAGES */ + +#ifdef USE_EPOLL_CREATE1 + fd = epoll_create1 (EPOLL_CLOEXEC); +#else /* ! USE_EPOLL_CREATE1 */ + fd = epoll_create (MAX_EVENTS); +#endif /* ! USE_EPOLL_CREATE1 */ + if (MHD_INVALID_SOCKET == fd) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (daemon, + MHD_SC_EPOLL_CTL_CREATE_FAILED, + _("Call to epoll_create1 failed: %s\n"), + MHD_socket_last_strerr_ ()); +#endif + return MHD_INVALID_SOCKET; + } +#if !defined(USE_EPOLL_CREATE1) + if (! MHD_socket_noninheritable_ (fd)) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (daemon, + MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED, + _("Failed to set noninheritable mode on epoll FD.\n")); +#endif + } +#endif /* ! USE_EPOLL_CREATE1 */ + return fd; +} + + /** * Setup epoll() FD for the daemon and initialize it to listen * on the listen FD. @@ -536,14 +556,14 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) if (-1 == daemon->epoll_fd) return MHD_NO; #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) - if (0 != (MHD_ALLOW_UPGRADE & daemon->options)) + if (! daemon->disallow_upgrade) { daemon->epoll_upgrade_fd = setup_epoll_fd (daemon); if (MHD_INVALID_SOCKET == daemon->epoll_upgrade_fd) return MHD_NO; } #endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ - if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_fd)) || + if ( (MHD_INVALID_SOCKET == (ls = daemon->listen_socket)) || (daemon->was_quiesced) ) return MHD_YES; /* non-listening daemon */ event.events = EPOLLIN; @@ -555,6 +575,7 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, + MHD_SC_EPOLL_CTL_ADD_FAILED, _("Call to epoll_ctl failed: %s\n"), MHD_socket_last_strerr_ ()); #endif @@ -564,7 +585,7 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) if (MHD_ITC_IS_VALID_(daemon->itc)) { event.events = EPOLLIN; - event.data.ptr = (void *) epoll_itc_marker; + event.data.ptr = (void *) daemon->epoll_itc_marker; if (0 != epoll_ctl (daemon->epoll_fd, EPOLL_CTL_ADD, MHD_itc_r_fd_ (daemon->itc), @@ -572,6 +593,7 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, + MHD_SC_EPOLL_CTL_ADD_FAILED, _("Call to epoll_ctl failed: %s\n"), MHD_socket_last_strerr_ ()); #endif @@ -647,7 +669,7 @@ setup_thread_pool (struct MHD_Daemon *daemon) / daemon->threading_model; unsigned int leftover_conns = daemon->global_connection_limit % daemon->threading_model; - unsigned int i; + int i; enum MHD_StatusCode sc; /* Allocate memory for pooled objects */ @@ -675,7 +697,7 @@ setup_thread_pool (struct MHD_Daemon *daemon) * Thread indexes in [0, leftover_conns) each get one of the * leftover connections. */ d->global_connection_limit = conns_per_thread; - if (i < leftover_conns) + if (((unsigned int) i) < leftover_conns) ++d->global_connection_limit; if (! daemon->disable_itc) @@ -733,7 +755,7 @@ setup_thread_pool (struct MHD_Daemon *daemon) /* Spawn the worker thread */ if (! MHD_create_named_thread_ (&d->pid, "MHD-worker", - daemon->thread_stack_size, + daemon->thread_stack_limit_b, &MHD_polling_thread, d)) { @@ -909,9 +931,9 @@ MHD_daemon_start (struct MHD_Daemon *daemon) (MHD_TM_THREAD_PER_CONNECTION == daemon->threading_model) ? "MHD-listen" : "MHD-single", - daemon->thread_stack_size, + daemon->thread_stack_limit_b, &MHD_polling_thread, - daemon) ) + daemon) ) ) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -928,7 +950,10 @@ MHD_daemon_start (struct MHD_Daemon *daemon) (MHD_INVALID_SOCKET != daemon->listen_socket) && (MHD_SC_OK != (sc = setup_thread_pool (daemon))) ) return sc; - + + /* make sure we know our listen port (if any) */ + get_listen_port_number (daemon); + return MHD_SC_OK; } diff --git a/src/lib/init.c b/src/lib/init.c index 96b0cbec..cea006e8 100644 --- a/src/lib/init.c +++ b/src/lib/init.c @@ -118,6 +118,37 @@ MHD_check_global_init_ (void) } +/** + * Default implementation of the panic function, + * prints an error message and aborts. + * + * @param cls unused + * @param file name of the file with the problem + * @param line line number with the problem + * @param reason error message with details + */ +static void +mhd_panic_std (void *cls, + const char *file, + unsigned int line, + const char *reason) +{ + (void)cls; /* Mute compiler warning. */ +#ifdef HAVE_MESSAGES + fprintf (stderr, + _("Fatal error in GNU libmicrohttpd %s:%u: %s\n"), + file, + line, + reason); +#else /* ! HAVE_MESSAGES */ + (void)file; /* Mute compiler warning. */ + (void)line; /* Mute compiler warning. */ + (void)reason; /* Mute compiler warning. */ +#endif + abort (); +} + + /** * Initialize do setup work. */ diff --git a/src/lib/internal.c b/src/lib/internal.c index 4422d9ed..4ea0503d 100644 --- a/src/lib/internal.c +++ b/src/lib/internal.c @@ -173,8 +173,8 @@ MHD_http_unescape (char *val) * 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 connection connection to add headers to * @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 @@ -184,13 +184,13 @@ MHD_http_unescape (char *val) * returned #MHD_YES) */ int -MHD_parse_arguments_ (struct MHD_Connection *connection, +MHD_parse_arguments_ (struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, unsigned int *num_headers) { - struct MHD_Daemon *daemon = connection->daemon; + struct MHD_Daemon *daemon = request->daemon; char *equals; char *amper; @@ -208,9 +208,9 @@ MHD_parse_arguments_ (struct MHD_Connection *connection, /* last argument, without '=' */ MHD_unescape_plus (args); daemon->unescape_cb (daemon->unescape_cb_cls, - connection, + request, args); - if (MHD_YES != cb (connection, + if (MHD_YES != cb (request, args, NULL, kind)) @@ -223,13 +223,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection, equals++; MHD_unescape_plus (args); daemon->unescape_cb (daemon->unescape_cb_cls, - connection, + request, args); MHD_unescape_plus (equals); daemon->unescape_cb (daemon->unescape_cb_cls, - connection, + request, equals); - if (MHD_YES != cb (connection, + if (MHD_YES != cb (request, args, equals, kind)) @@ -246,9 +246,9 @@ MHD_parse_arguments_ (struct MHD_Connection *connection, /* got 'foo&bar' or 'foo&bar=val', add key 'foo' with NULL for value */ MHD_unescape_plus (args); daemon->unescape_cb (daemon->unescape_cb_cls, - connection, + request, args); - if (MHD_YES != cb (connection, + if (MHD_YES != cb (request, args, NULL, kind)) @@ -264,13 +264,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection, equals++; MHD_unescape_plus (args); daemon->unescape_cb (daemon->unescape_cb_cls, - connection, + request, args); MHD_unescape_plus (equals); daemon->unescape_cb (daemon->unescape_cb_cls, - connection, + request, equals); - if (MHD_YES != cb (connection, + if (MHD_YES != cb (request, args, equals, kind)) diff --git a/src/lib/internal.h b/src/lib/internal.h index 4ea6528a..5b147df8 100644 --- a/src/lib/internal.h +++ b/src/lib/internal.h @@ -33,6 +33,7 @@ #include "microhttpd_tls.h" #include "mhd_assert.h" #include "mhd_compat.h" +#include "mhd_itc.h" #include "mhd_mono_clock.h" #include "memorypool.h" @@ -1011,6 +1012,13 @@ struct MHD_Daemon */ struct MHD_Connection *eready_tail; +#ifdef EPOLL_SUPPORT + /** + * Pointer to marker used to indicate ITC slot in epoll sets. + */ + const char *epoll_itc_marker; +#endif + #ifdef UPGRADE_SUPPORT /** * Head of EDLL of upgraded connections ready for processing (in epoll mode). @@ -1052,6 +1060,11 @@ struct MHD_Daemon 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. @@ -1285,12 +1298,22 @@ struct MHD_Daemon */ bool enable_turbo; + /** + * MHD_daemon_quiesce() was run against this daemon. + */ + bool was_quiesced; + /** * 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? */ @@ -1463,7 +1486,7 @@ struct MHD_Response * Callback invoked when iterating over @a key / @a value * argument pairs during parsing. * - * @param connection context of the iteration + * @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 @@ -1471,7 +1494,7 @@ struct MHD_Response * #MHD_NO to signal failure (and abort iteration) */ typedef int -(*MHD_ArgumentIterator_)(struct MHD_Connection *connection, +(*MHD_ArgumentIterator_)(struct MHD_Request *request, const char *key, const char *value, enum MHD_ValueKind kind); @@ -1481,8 +1504,8 @@ typedef int * 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 connection connection to add headers to * @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 @@ -1492,7 +1515,7 @@ typedef int * returned #MHD_YES) */ int -MHD_parse_arguments_ (struct MHD_Connection *connection, +MHD_parse_arguments_ (struct MHD_Request *request, enum MHD_ValueKind kind, char *args, MHD_ArgumentIterator_ cb, diff --git a/src/lib/reason_phrase.c b/src/lib/reason_phrase.c new file mode 100644 index 00000000..97ace0a3 --- /dev/null +++ b/src/lib/reason_phrase.c @@ -0,0 +1,182 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2007, 2011, 2017 Christian Grothoff, Karlson2k (Evgeny Grin) + + 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 reason_phrase.c + * @brief Tables of the string response phrases + * @author Elliot Glaysher + * @author Christian Grothoff (minor code clean up) + * @author Karlson2k (Evgeny Grin) + */ +#include "internal.h" + +#ifndef NULL +#define NULL ((void*)0) +#endif + +static const char *const invalid_hundred[] = { + NULL +}; + +static const char *const one_hundred[] = { + "Continue", + "Switching Protocols", + "Processing" +}; + +static const char *const two_hundred[] = { + "OK", + "Created", + "Accepted", + "Non-Authoritative Information", + "No Content", + "Reset Content", + "Partial Content", + "Multi-Status", + "Already Reported", + "Unknown", + "Unknown", /* 210 */ + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", /* 215 */ + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", /* 220 */ + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", /* 225 */ + "IM Used" +}; + +static const char *const three_hundred[] = { + "Multiple Choices", + "Moved Permanently", + "Found", + "See Other", + "Not Modified", + "Use Proxy", + "Switch Proxy", + "Temporary Redirect", + "Permanent Redirect" +}; + +static const char *const four_hundred[] = { + "Bad Request", + "Unauthorized", + "Payment Required", + "Forbidden", + "Not Found", + "Method Not Allowed", + "Not Acceptable", + "Proxy Authentication Required", + "Request Timeout", + "Conflict", + "Gone", + "Length Required", + "Precondition Failed", + "Payload Too Large", + "URI Too Long", + "Unsupported Media Type", + "Range Not Satisfiable", + "Expectation Failed", + "Unknown", + "Unknown", + "Unknown", /* 420 */ + "Misdirected Request", + "Unprocessable Entity", + "Locked", + "Failed Dependency", + "Unordered Collection", + "Upgrade Required", + "Unknown", + "Precondition Required", + "Too Many Requests", + "Unknown", /* 430 */ + "Request Header Fields Too Large", + "Unknown", + "Unknown", + "Unknown", + "Unknown", /* 435 */ + "Unknown", + "Unknown", + "Unknown", + "Unknown", + "Unknown", /* 440 */ + "Unknown", + "Unknown", + "Unknown", + "No Response", + "Unknown", /* 445 */ + "Unknown", + "Unknown", + "Unknown", + "Retry With", + "Blocked by Windows Parental Controls", /* 450 */ + "Unavailable For Legal Reasons" +}; + +static const char *const five_hundred[] = { + "Internal Server Error", + "Not Implemented", + "Bad Gateway", + "Service Unavailable", + "Gateway Timeout", + "HTTP Version Not Supported", + "Variant Also Negotiates", + "Insufficient Storage", + "Loop Detected", + "Bandwidth Limit Exceeded", + "Not Extended", + "Network Authentication Required" +}; + + +struct MHD_Reason_Block +{ + size_t max; + const char *const*data; +}; + +#define BLOCK(m) { (sizeof(m) / sizeof(char*)), m } + +static const struct MHD_Reason_Block reasons[] = { + BLOCK (invalid_hundred), + BLOCK (one_hundred), + BLOCK (two_hundred), + BLOCK (three_hundred), + BLOCK (four_hundred), + BLOCK (five_hundred), +}; + + +const char * +MHD_get_reason_phrase_for (enum MHD_HTTP_StatusCode code) +{ + if ( (code >= 100) && + (code < 600) && + (reasons[code / 100].max > (code % 100)) ) + return reasons[code / 100].data[code % 100]; + return "Unknown"; +} diff --git a/src/lib/response_for_upgrade.c b/src/lib/response_for_upgrade.c index 90e361b6..5de6518b 100644 --- a/src/lib/response_for_upgrade.c +++ b/src/lib/response_for_upgrade.c @@ -77,11 +77,11 @@ MHD_response_for_upgrade (MHD_UpgradeHandler upgrade_handler, response->total_size = MHD_SIZE_UNKNOWN; response->reference_count = 1; if (MHD_NO == - MHD_add_response_header (response, + MHD_response_add_header (response, MHD_HTTP_HEADER_CONNECTION, "Upgrade")) { - MHD_destroy_response (response); + MHD_response_queue_for_destroy (response); return NULL; } return response; -- cgit v1.2.3