libmicrohttpd

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

commit 9914072c16b773a828709ecc61062c37c864e858
parent bca7a709f8129e856d9175ea1081abc0feec883c
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu, 15 Feb 2018 04:04:22 +0100

add explicit nonnull declarations to function arguments

Diffstat:
Msrc/include/microhttpd2.h | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
Msrc/lib/daemon_create.c | 2--
Msrc/lib/daemon_destroy.c | 2--
Msrc/lib/daemon_get_fdset.c | 166++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/lib/internal.h | 215+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/lib/request.c | 4----
Msrc/lib/response.c | 5-----
7 files changed, 525 insertions(+), 84 deletions(-)

diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h @@ -267,6 +267,16 @@ typedef SOCKET MHD_socket; #define _MHD_DEPR_FUNC(msg) #endif /* !_MHD_DEPR_FUNC */ + +/* Define MHD_NONNULL attribute */ + +/** + * Macro to indicate that certain parameters must be + * non-null. Todo: port to non-gcc platforms. + */ +#define MHD_NONNULL(...) __THROW __nonnull((__VA_ARGS__)) + + /** * Not all architectures and `printf()`'s support the `long long` type. * This gives the ability to replace `long long` with just a `long`, @@ -541,6 +551,17 @@ enum MHD_StatusCode */ MHD_SC_EPOLL_CTL_CONFIGURE_NOINHERIT_FAILED = 50035, + /** + * We failed to build the FD set because a socket was + * outside of the permitted range. + */ + MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE = 50036, + + /** + * This daemon was not configured with options that + * would allow us to build an FD set for select(). + */ + MHD_SC_CONFIGURATION_MISSMATCH_FOR_GET_FDSET = 50037, }; @@ -1148,7 +1169,8 @@ typedef struct MHD_Action * */ _MHD_EXTERN struct MHD_Daemon * MHD_daemon_create (MHD_RequestCallback cb, - void *cb_cls); + void *cb_cls) + MHD_NONNULL(1); /** @@ -1160,7 +1182,8 @@ MHD_daemon_create (MHD_RequestCallback cb, * @ingroup event */ _MHD_EXTERN enum MHD_StatusCode -MHD_daemon_start (struct MHD_Daemon *daemon); +MHD_daemon_start (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1184,7 +1207,8 @@ MHD_daemon_start (struct MHD_Daemon *daemon); * @ingroup specialized */ _MHD_EXTERN MHD_socket -MHD_daemon_quiesce (struct MHD_Daemon *daemon); +MHD_daemon_quiesce (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1194,7 +1218,8 @@ MHD_daemon_quiesce (struct MHD_Daemon *daemon); * @ingroup event */ _MHD_EXTERN void -MHD_daemon_destroy (struct MHD_Daemon *daemon); +MHD_daemon_destroy (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1226,7 +1251,8 @@ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_add_connection (struct MHD_Daemon *daemon, MHD_socket client_socket, const struct sockaddr *addr, - socklen_t addrlen); + socklen_t addrlen) + MHD_NONNULL(1); /** @@ -1258,7 +1284,8 @@ MHD_daemon_get_fdset (struct MHD_Daemon *daemon, fd_set *read_fd_set, fd_set *write_fd_set, fd_set *except_fd_set, - MHD_socket *max_fd); + MHD_socket *max_fd) + MHD_NONNULL(1,2,3,4); /** @@ -1294,7 +1321,8 @@ MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon, fd_set *write_fd_set, fd_set *except_fd_set, MHD_socket *max_fd, - unsigned int fd_setsize); + unsigned int fd_setsize) + MHD_NONNULL(1,2,3,4); /** @@ -1344,7 +1372,8 @@ MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon, */ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_get_timeout (struct MHD_Daemon *daemon, - MHD_UNSIGNED_LONG_LONG *timeout); + MHD_UNSIGNED_LONG_LONG *timeout) + MHD_NONNULL(1,2); /** @@ -1366,7 +1395,8 @@ MHD_daemon_get_timeout (struct MHD_Daemon *daemon, * @ingroup event */ _MHD_EXTERN enum MHD_StatusCode -MHD_daemon_run (struct MHD_Daemon *daemon); +MHD_daemon_run (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1395,9 +1425,8 @@ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_run_from_select (struct MHD_Daemon *daemon, const fd_set *read_fd_set, const fd_set *write_fd_set, - const fd_set *except_fd_set); - - + const fd_set *except_fd_set) + MHD_NONNULL(1,2,3,4); /* ********************* daemon options ************** */ @@ -1431,7 +1460,8 @@ typedef void _MHD_EXTERN void MHD_daemon_set_logger (struct MHD_Daemon *daemon, MHD_LoggingCallback logger, - void *logger_cls); + void *logger_cls) + MHD_NONNULL(1); /** @@ -1448,7 +1478,8 @@ MHD_daemon_set_logger (struct MHD_Daemon *daemon, * @param daemon which instance to disable clock for. */ _MHD_EXTERN void -MHD_daemon_suppress_date_no_clock (struct MHD_Daemon *daemon); +MHD_daemon_suppress_date_no_clock (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1469,7 +1500,8 @@ MHD_daemon_suppress_date_no_clock (struct MHD_Daemon *daemon); * @param daemon which instance to disable itc for */ _MHD_EXTERN void -MHD_daemon_disable_itc (struct MHD_Daemon *daemon); +MHD_daemon_disable_itc (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1481,7 +1513,8 @@ MHD_daemon_disable_itc (struct MHD_Daemon *daemon); * @param daemon which instance to enable turbo for */ _MHD_EXTERN void -MHD_daemon_enable_turbo (struct MHD_Daemon *daemon); +MHD_daemon_enable_turbo (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1494,7 +1527,8 @@ MHD_daemon_enable_turbo (struct MHD_Daemon *daemon); * @param daemon which instance to disable suspend for */ _MHD_EXTERN void -MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon); +MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1509,7 +1543,8 @@ MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon); * @param daemon which instance to enable suspend/resume for */ _MHD_EXTERN void -MHD_daemon_disallow_upgrade (struct MHD_Daemon *daemon); +MHD_daemon_disallow_upgrade (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1555,7 +1590,8 @@ enum MHD_FastOpenMethod _MHD_EXTERN enum MHD_Bool MHD_daemon_tcp_fastopen (struct MHD_Daemon *daemon, enum MHD_FastOpenMethod fom, - unsigned int queue_length); + unsigned int queue_length) + MHD_NONNULL(1); /** @@ -1608,7 +1644,8 @@ enum MHD_AddressFamily _MHD_EXTERN void MHD_daemon_bind_port (struct MHD_Daemon *daemon, enum MHD_AddressFamily af, - uint16_t port); + uint16_t port) + MHD_NONNULL(1); /** @@ -1623,7 +1660,8 @@ MHD_daemon_bind_port (struct MHD_Daemon *daemon, _MHD_EXTERN void MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon, const struct sockaddr *sa, - size_t sa_len); + size_t sa_len) + MHD_NONNULL(1); /** @@ -1635,7 +1673,8 @@ MHD_daemon_bind_socket_address (struct MHD_Daemon *daemon, */ _MHD_EXTERN void MHD_daemon_listen_backlog (struct MHD_Daemon *daemon, - int listen_backlog); + int listen_backlog) + MHD_NONNULL(1); /** @@ -1649,7 +1688,8 @@ MHD_daemon_listen_backlog (struct MHD_Daemon *daemon, * @param daemon daemon to configure address reuse for */ _MHD_EXTERN void -MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon); +MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1668,7 +1708,8 @@ MHD_daemon_listen_allow_address_reuse (struct MHD_Daemon *daemon); */ _MHD_EXTERN void MHD_daemon_listen_socket (struct MHD_Daemon *daemon, - MHD_socket listen_socket); + MHD_socket listen_socket) + MHD_NONNULL(1); /** @@ -1708,7 +1749,8 @@ enum MHD_EventLoopSyscall */ _MHD_EXTERN enum MHD_Bool MHD_daemon_event_loop (struct MHD_Daemon *daemon, - enum MHD_EventLoopSyscall els); + enum MHD_EventLoopSyscall els) + MHD_NONNULL(1); /** @@ -1752,7 +1794,8 @@ enum MHD_ProtocolStrictLevel */ _MHD_EXTERN void MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon, - enum MHD_ProtocolStrictLevel sl); + enum MHD_ProtocolStrictLevel sl) + MHD_NONNULL(1); /** @@ -1762,7 +1805,8 @@ MHD_daemon_protocol_strict_level (struct MHD_Daemon *daemon, * @param daemon daemon to set SHOUTcast option for */ _MHD_EXTERN void -MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon); +MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon) + MHD_NONNULL(1); /** @@ -1783,7 +1827,8 @@ MHD_daemon_enable_shoutcast (struct MHD_Daemon *daemon); _MHD_EXTERN enum MHD_StatusCode MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon, const char *tls_backend, - const char *ciphers); + const char *ciphers) + MHD_NONNULL(1); /** @@ -1802,7 +1847,8 @@ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon, const char *mem_key, const char *mem_cert, - const char *pass); + const char *pass) + MHD_NONNULL(1,2,3); /** @@ -1815,7 +1861,8 @@ MHD_daemon_tls_key_and_cert_from_memory (struct MHD_Daemon *daemon, */ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon, - const char *dh); + const char *dh) + MHD_NONNULL(1); /** @@ -1828,7 +1875,8 @@ MHD_daemon_tls_mem_dhparams (struct MHD_Daemon *daemon, */ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon, - const char *mem_trust); + const char *mem_trust) + MHD_NONNULL(1); /** @@ -1840,7 +1888,8 @@ MHD_daemon_tls_mem_trust (struct MHD_Daemon *daemon, */ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon, - int gnutls_credentials); + int gnutls_credentials) + MHD_NONNULL(1); /** @@ -1862,7 +1911,8 @@ MHD_daemon_gnutls_credentials (struct MHD_Daemon *daemon, */ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_gnutls_key_and_cert_from_callback (struct MHD_Daemon *daemon, - void *cb); + void *cb) + MHD_NONNULL(1); /** @@ -1920,7 +1970,8 @@ enum MHD_ThreadingModel */ _MHD_EXTERN void MHD_daemon_threading_model (struct MHD_Daemon *daemon, - enum MHD_ThreadingModel tm); + enum MHD_ThreadingModel tm) + MHD_NONNULL(1); /** @@ -1950,7 +2001,8 @@ typedef enum MHD_Bool _MHD_EXTERN void MHD_daemon_accept_policy (struct MHD_Daemon *daemon, MHD_AcceptPolicyCallback apc, - void *apc_cls); + void *apc_cls) + MHD_NONNULL(1); /** @@ -1981,7 +2033,8 @@ typedef void * _MHD_EXTERN void MHD_daemon_set_early_uri_logger (struct MHD_Daemon *daemon, MHD_EarlyUriLogCallback cb, - void *cb_cls); + void *cb_cls) + MHD_NONNULL(1); /** @@ -2043,7 +2096,8 @@ typedef void _MHD_EXTERN void MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon, MHD_NotifyConnectionCallback ncc, - void *ncc_cls); + void *ncc_cls) + MHD_NONNULL(1); /** @@ -2060,7 +2114,8 @@ MHD_daemon_set_notify_connection (struct MHD_Daemon *daemon, _MHD_EXTERN void MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon, size_t memory_limit_b, - size_t memory_increment_b); + size_t memory_increment_b) + MHD_NONNULL(1); /** @@ -2073,7 +2128,8 @@ MHD_daemon_connection_memory_limit (struct MHD_Daemon *daemon, */ _MHD_EXTERN void MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon, - size_t stack_limit_b); + size_t stack_limit_b) + MHD_NONNULL(1); /** @@ -2094,7 +2150,8 @@ MHD_daemon_thread_stack_size (struct MHD_Daemon *daemon, _MHD_EXTERN void MHD_daemon_connection_limits (struct MHD_Daemon *daemon, unsigned int global_connection_limit, - unsigned int ip_connection_limit); + unsigned int ip_connection_limit) + MHD_NONNULL(1); /** @@ -2107,7 +2164,8 @@ MHD_daemon_connection_limits (struct MHD_Daemon *daemon, */ _MHD_EXTERN void MHD_daemon_connection_default_timeout (struct MHD_Daemon *daemon, - unsigned int timeout_s); + unsigned int timeout_s) + MHD_NONNULL(1); /** @@ -2142,7 +2200,8 @@ typedef size_t _MHD_EXTERN void MHD_daemon_unescape_cb (struct MHD_Daemon *daemon, MHD_UnescapeCallback unescape_cb, - void *unescape_cb_cls); + void *unescape_cb_cls) + MHD_NONNULL(1); /** @@ -2157,7 +2216,8 @@ MHD_daemon_unescape_cb (struct MHD_Daemon *daemon, _MHD_EXTERN void MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon, size_t buf_size, - const void *buf); + const void *buf) + MHD_NONNULL(1,3); /** @@ -2169,7 +2229,8 @@ MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon, */ _MHD_EXTERN enum MHD_StatusCode MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon, - size_t nc_length); + size_t nc_length) + MHD_NONNULL(1); /* ********************* connection options ************** */ @@ -2185,7 +2246,8 @@ MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon, */ _MHD_EXTERN void MHD_connection_set_timeout (struct MHD_Connection *connection, - unsigned int timeout_s); + unsigned int timeout_s) + MHD_NONNULL(1); /* **************** Request handling functions ***************** */ @@ -2268,7 +2330,8 @@ _MHD_EXTERN unsigned int MHD_request_get_values (struct MHD_Request *request, enum MHD_ValueKind kind, MHD_KeyValueIterator iterator, - void *iterator_cls); + void *iterator_cls) + MHD_NONNULL(1); /** @@ -2300,7 +2363,8 @@ _MHD_EXTERN enum MHD_Bool MHD_request_set_value (struct MHD_Request *request, enum MHD_ValueKind kind, const char *key, - const char *value); + const char *value) + MHD_NONNULL(1,3,4); /** @@ -2316,7 +2380,8 @@ MHD_request_set_value (struct MHD_Request *request, _MHD_EXTERN const char * MHD_request_lookup_value (struct MHD_Request *request, enum MHD_ValueKind kind, - const char *key); + const char *key) + MHD_NONNULL(1); @@ -2487,7 +2552,8 @@ MHD_action_suspend (void); * @param request the request to resume */ _MHD_EXTERN void -MHD_request_resume (struct MHD_Request *request); +MHD_request_resume (struct MHD_Request *request) + MHD_NONNULL(1); /* **************** Response manipulation functions ***************** */ @@ -2520,7 +2586,8 @@ struct MHD_Response; */ _MHD_EXTERN struct MHD_Action * MHD_action_from_response (struct MHD_Response *response, - enum MHD_Bool destroy_after_use); + enum MHD_Bool destroy_after_use) + MHD_NONNULL(1); /** @@ -2531,7 +2598,8 @@ MHD_action_from_response (struct MHD_Response *response, * @param request the request for which we force HTTP 1.0 to be used */ _MHD_EXTERN void -MHD_response_option_v10_only (struct MHD_Response *response); +MHD_response_option_v10_only (struct MHD_Response *response) + MHD_NONNULL(1); /** @@ -2620,7 +2688,8 @@ typedef void _MHD_EXTERN void MHD_response_option_termination_callback (struct MHD_Response *response, MHD_RequestTerminationCallback termination_cb, - void *termination_cb_cls); + void *termination_cb_cls) + MHD_NONNULL(1); /** @@ -2837,7 +2906,8 @@ struct MHD_UpgradeResponseHandle; _MHD_EXTERN enum MHD_Bool MHD_upgrade_operation (struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeOperation operation, - ...); + ...) + MHD_NONNULL(1); /** @@ -2929,7 +2999,8 @@ typedef void */ _MHD_EXTERN struct MHD_Response * MHD_response_for_upgrade (MHD_UpgradeHandler upgrade_handler, - void *upgrade_handler_cls); + void *upgrade_handler_cls) + MHD_NONNULL(1); /** @@ -2942,7 +3013,8 @@ MHD_response_for_upgrade (MHD_UpgradeHandler upgrade_handler, * @ingroup response */ _MHD_EXTERN void -MHD_response_queue_for_destroy (struct MHD_Response *response); +MHD_response_queue_for_destroy (struct MHD_Response *response) + MHD_NONNULL(1); /** @@ -2958,7 +3030,8 @@ MHD_response_queue_for_destroy (struct MHD_Response *response); _MHD_EXTERN enum MHD_Bool MHD_response_add_header (struct MHD_Response *response, const char *header, - const char *content); + const char *content) + MHD_NONNULL(1,2,3); /** @@ -2974,7 +3047,8 @@ MHD_response_add_header (struct MHD_Response *response, _MHD_EXTERN enum MHD_Bool MHD_response_add_trailer (struct MHD_Response *response, const char *footer, - const char *content); + const char *content) + MHD_NONNULL(1,2,3); /** @@ -2989,7 +3063,8 @@ MHD_response_add_trailer (struct MHD_Response *response, _MHD_EXTERN enum MHD_Bool MHD_response_del_header (struct MHD_Response *response, const char *header, - const char *content); + const char *content) + MHD_NONNULL(1,2,3); /** @@ -3005,7 +3080,8 @@ MHD_response_del_header (struct MHD_Response *response, _MHD_EXTERN unsigned int MHD_response_get_headers (struct MHD_Response *response, MHD_KeyValueIterator iterator, - void *iterator_cls); + void *iterator_cls) + MHD_NONNULL(1); /** @@ -3018,7 +3094,8 @@ MHD_response_get_headers (struct MHD_Response *response, */ _MHD_EXTERN const char * MHD_response_get_header (struct MHD_Response *response, - const char *key); + const char *key) + MHD_NONNULL(1,2); /* ************Upload and PostProcessor functions ********************** */ @@ -3067,7 +3144,8 @@ typedef struct MHD_Action * */ _MHD_EXTERN struct MHD_Action * MHD_action_process_upload (MHD_UploadCallback uc, - void *uc_cls); + void *uc_cls) + MHD_NONNULL(1); /** @@ -3132,7 +3210,8 @@ typedef struct MHD_Action * _MHD_EXTERN struct MHD_Action * MHD_action_parse_post (size_t buffer_size, MHD_PostDataIterator iter, - void *iter_cls); + void *iter_cls) + MHD_NONNULL(2); @@ -3303,7 +3382,8 @@ _MHD_EXTERN enum MHD_Bool MHD_connection_get_information_sz (struct MHD_Connection *connection, enum MHD_ConnectionInformationType info_type, union MHD_ConnectionInformation *return_value, - size_t return_value_size); + size_t return_value_size) + MHD_NONNULL(1,3); /** @@ -3415,7 +3495,8 @@ _MHD_EXTERN enum MHD_Bool MHD_request_get_information_sz (struct MHD_Request *request, enum MHD_RequestInformationType info_type, union MHD_RequestInformation *return_value, - size_t return_value_size); + size_t return_value_size) + MHD_NONNULL(1,3); /** @@ -3521,7 +3602,8 @@ _MHD_EXTERN enum MHD_Bool MHD_daemon_get_information_sz (struct MHD_Daemon *daemon, enum MHD_DaemonInformationType info_type, union MHD_DaemonInformation *return_value, - size_t return_value_size); + size_t return_value_size) + MHD_NONNULL(1,3); /** * Obtain information about the given daemon. @@ -3588,7 +3670,8 @@ MHD_set_panic_func (MHD_PanicCallback cb, * shorter afterwards due to elimination of escape sequences) */ _MHD_EXTERN size_t -MHD_http_unescape (char *val); +MHD_http_unescape (char *val) + MHD_NONNULL(1); /** diff --git a/src/lib/daemon_create.c b/src/lib/daemon_create.c @@ -89,8 +89,6 @@ MHD_daemon_create (MHD_RequestCallback cb, struct MHD_Daemon *daemon; MHD_check_global_init_(); - if (NULL == cb) - return NULL; if (NULL == (daemon = malloc (sizeof (struct MHD_Daemon)))) return NULL; memset (daemon, diff --git a/src/lib/daemon_destroy.c b/src/lib/daemon_destroy.c @@ -93,8 +93,6 @@ MHD_daemon_destroy (struct MHD_Daemon *daemon) { MHD_socket fd; - if (NULL == daemon) - return; daemon->shutdown = true; if (daemon->was_quiesced) fd = MHD_INVALID_SOCKET; /* Do not use FD if daemon was quiesced */ diff --git a/src/lib/daemon_get_fdset.c b/src/lib/daemon_get_fdset.c @@ -62,7 +62,142 @@ MHD_daemon_get_fdset (struct MHD_Daemon *daemon, fd_set *except_fd_set, MHD_socket *max_fd) { - return -1; + return MHD_daemon_get_fdset2 (daemon, + read_fd_set, + write_fd_set, + except_fd_set, + max_fd, + _MHD_SYS_DEFAULT_FD_SETSIZE); +} + + +/** + * Internal version of #MHD_daemon_get_fdset2(). + * + * @param daemon daemon to get sets from + * @param read_fd_set read set + * @param write_fd_set write set + * @param except_fd_set except set + * @param max_fd increased to largest FD added (if larger + * than existing value); can be NULL + * @param fd_setsize value of FD_SETSIZE + * @return #MHD_SC_OK on success + * @ingroup event + */ +static enum MHD_StatusCode +internal_get_fdset2 (struct MHD_Daemon *daemon, + fd_set *read_fd_set, + fd_set *write_fd_set, + fd_set *except_fd_set, + MHD_socket *max_fd, + unsigned int fd_setsize) + +{ + struct MHD_Connection *pos; + struct MHD_Connection *posn; + int result = MHD_YES; + MHD_socket ls; + + if (daemon->shutdown) + return MHD_NO; + + ls = daemon->listen_socket; + if ( (MHD_INVALID_SOCKET != ls) && + (! daemon->was_quiesced) && + (! MHD_add_to_fd_set_ (ls, + read_fd_set, + max_fd, + fd_setsize)) ) + result = MHD_NO; + + /* Add all sockets to 'except_fd_set' as well to watch for + * out-of-band data. However, ignore errors if INFO_READ + * or INFO_WRITE sockets will not fit 'except_fd_set'. */ + /* Start from oldest connections. Make sense for W32 FDSETs. */ + for (pos = daemon->connections_tail; NULL != pos; pos = posn) + { + posn = pos->prev; + + switch (pos->request.event_loop_info) + { + case MHD_EVENT_LOOP_INFO_READ: + if (! MHD_add_to_fd_set_ (pos->socket_fd, + read_fd_set, + max_fd, + fd_setsize)) + result = MHD_NO; +#ifdef MHD_POSIX_SOCKETS + MHD_add_to_fd_set_ (pos->socket_fd, + except_fd_set, + max_fd, + fd_setsize); +#endif /* MHD_POSIX_SOCKETS */ + break; + case MHD_EVENT_LOOP_INFO_WRITE: + if (! MHD_add_to_fd_set_ (pos->socket_fd, + write_fd_set, + max_fd, + fd_setsize)) + result = MHD_NO; +#ifdef MHD_POSIX_SOCKETS + MHD_add_to_fd_set_ (pos->socket_fd, + except_fd_set, + max_fd, + fd_setsize); +#endif /* MHD_POSIX_SOCKETS */ + break; + case MHD_EVENT_LOOP_INFO_BLOCK: + if ( (NULL == except_fd_set) || + ! MHD_add_to_fd_set_ (pos->socket_fd, + except_fd_set, + max_fd, + fd_setsize)) + result = MHD_NO; + break; + case MHD_EVENT_LOOP_INFO_CLEANUP: + /* this should never happen */ + break; + } + } +#ifdef MHD_WINSOCK_SOCKETS + /* W32 use limited array for fd_set so add INFO_READ/INFO_WRITE sockets + * only after INFO_BLOCK sockets to ensure that INFO_BLOCK sockets will + * not be pushed out. */ + for (pos = daemon->connections_tail; NULL != pos; pos = posn) + { + posn = pos->prev; + MHD_add_to_fd_set_ (pos->socket_fd, + except_fd_set, + max_fd, + fd_setsize); + } +#endif /* MHD_WINSOCK_SOCKETS */ +#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) + { + struct MHD_UpgradeResponseHandle *urh; + + for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev) + { + if (MHD_NO == + urh_to_fdset (urh, + read_fd_set, + write_fd_set, + except_fd_set, + max_fd, + fd_setsize)) + result = MHD_NO; + } + } +#endif +#if DEBUG_CONNECT +#ifdef HAVE_MESSAGES + if (NULL != max_fd) + MHD_DLOG (daemon, + _("Maximum socket in select set: %d\n"), + *max_fd); +#endif +#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ + return result; } @@ -101,7 +236,34 @@ MHD_daemon_get_fdset2 (struct MHD_Daemon *daemon, MHD_socket *max_fd, unsigned int fd_setsize) { - return -1; + if ( (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_model) || + (MHD_ELS_POLL == daemon->event_loop_syscall) ) + return MHD_SC_CONFIGURATION_MISSMATCH_FOR_GET_FDSET; + +#ifdef EPOLL_SUPPORT + if (MHD_ELS_EPOLL == daemon->event_loop_syscall) + { + if (daemon->shutdown) + return MHD_SC_DAEMON_ALREADY_SHUTDOWN; + + /* we're in epoll mode, use the epoll FD as a stand-in for + the entire event set */ + + return MHD_add_to_fd_set_ (daemon->epoll_fd, + read_fd_set, + max_fd, + fd_setsize) + ? MHD_SC_OK + : MHD_SC_SOCKET_OUTSIDE_OF_FDSET_RANGE; + } +#endif + + return internal_get_fdset2 (daemon, + read_fd_set, + write_fd_set, + except_fd_set, + max_fd, + fd_setsize); } /* end of daemon_get_fdset.c */ diff --git a/src/lib/internal.h b/src/lib/internal.h @@ -826,6 +826,202 @@ struct MHD_Connection }; +#ifdef UPGRADE_SUPPORT +/** + * Buffer we use for upgrade response handling in the unlikely + * case where the memory pool was so small it had no buffer + * capacity left. Note that we don't expect to _ever_ use this + * buffer, so it's mostly wasted memory (except that it allows + * us to handle a tricky error condition nicely). So no need to + * make this one big. Applications that want to perform well + * should just pick an adequate size for the memory pools. + */ +#define RESERVE_EBUF_SIZE 8 + +/** + * Context we pass to epoll() for each of the two sockets + * of a `struct MHD_UpgradeResponseHandle`. We need to do + * this so we can distinguish the two sockets when epoll() + * gives us event notifications. + */ +struct UpgradeEpollHandle +{ + /** + * Reference to the overall response handle this struct is + * included within. + */ + struct MHD_UpgradeResponseHandle *urh; + + /** + * The socket this event is kind-of about. Note that this is NOT + * necessarily the socket we are polling on, as for when we read + * from TLS, we epoll() on the connection's socket + * (`urh->connection->socket_fd`), while this then the application's + * socket (where the application will read from). Nevertheless, for + * the application to read, we need to first read from TLS, hence + * the two are related. + * + * Similarly, for writing to TLS, this epoll() will be on the + * connection's `socket_fd`, and this will merely be the FD which + * the applicatio would write to. Hence this struct must always be + * interpreted based on which field in `struct + * MHD_UpgradeResponseHandle` it is (`app` or `mhd`). + */ + MHD_socket socket; + + /** + * IO-state of the @e socket (or the connection's `socket_fd`). + */ + enum MHD_EpollState celi; + +}; + + +/** + * Handle given to the application to manage special + * actions relating to MHD responses that "upgrade" + * the HTTP protocol (i.e. to WebSockets). + */ +struct MHD_UpgradeResponseHandle +{ + /** + * The connection for which this is an upgrade handle. Note that + * because a response may be shared over many connections, this may + * not be the only upgrade handle for the response of this connection. + */ + struct MHD_Connection *connection; + +#ifdef HTTPS_SUPPORT + /** + * Kept in a DLL per daemon. + */ + struct MHD_UpgradeResponseHandle *next; + + /** + * Kept in a DLL per daemon. + */ + struct MHD_UpgradeResponseHandle *prev; + +#ifdef EPOLL_SUPPORT + /** + * Next pointer for the EDLL listing urhs that are epoll-ready. + */ + struct MHD_UpgradeResponseHandle *nextE; + + /** + * Previous pointer for the EDLL listing urhs that are epoll-ready. + */ + struct MHD_UpgradeResponseHandle *prevE; + + /** + * Specifies whether urh already in EDLL list of ready connections. + */ + bool in_eready_list; +#endif + + /** + * The buffer for receiving data from TLS to + * be passed to the application. Contains @e in_buffer_size + * bytes (unless @e in_buffer_size is zero). Do not free! + */ + char *in_buffer; + + /** + * The buffer for receiving data from the application to + * be passed to TLS. Contains @e out_buffer_size + * bytes (unless @e out_buffer_size is zero). Do not free! + */ + char *out_buffer; + + /** + * Size of the @e in_buffer. + * Set to 0 if the TLS connection went down for reading or socketpair + * went down for writing. + */ + size_t in_buffer_size; + + /** + * Size of the @e out_buffer. + * Set to 0 if the TLS connection went down for writing or socketpair + * went down for reading. + */ + size_t out_buffer_size; + + /** + * Number of bytes actually in use in the @e in_buffer. Can be larger + * than @e in_buffer_size if and only if @a in_buffer_size is zero and + * we still have bytes that can be forwarded. + * Reset to zero if all data was forwarded to socketpair or + * if socketpair went down for writing. + */ + size_t in_buffer_used; + + /** + * Number of bytes actually in use in the @e out_buffer. Can be larger + * than @e out_buffer_size if and only if @a out_buffer_size is zero and + * we still have bytes that can be forwarded. + * Reset to zero if all data was forwarded to TLS connection or + * if TLS connection went down for writing. + */ + size_t out_buffer_used; + + /** + * The socket we gave to the application (r/w). + */ + struct UpgradeEpollHandle app; + + /** + * If @a app_sock was a socketpair, our end of it, otherwise + * #MHD_INVALID_SOCKET; (r/w). + */ + struct UpgradeEpollHandle mhd; + + /** + * Emergency IO buffer we use in case the memory pool has literally + * nothing left. + */ + char e_buf[RESERVE_EBUF_SIZE]; + +#endif /* HTTPS_SUPPORT */ + + /** + * Set to true after the application finished with the socket + * by #MHD_UPGRADE_ACTION_CLOSE. + * + * When BOTH @e was_closed (changed by command from application) + * AND @e clean_ready (changed internally by MHD) are set to + * #MHD_YES, function #MHD_resume_connection() will move this + * connection to cleanup list. + * @remark This flag could be changed from any thread. + */ + volatile bool was_closed; + + /** + * Set to true if connection is ready for cleanup. + * + * In TLS mode functions #MHD_connection_finish_forward_() must + * be called before setting this flag to true. + * + * In thread-per-connection mode, true in this flag means + * that connection's thread exited or about to exit and will + * not use MHD_Connection::urh data anymore. + * + * In any mode true in this flag also means that + * MHD_Connection::urh data will not be used for socketpair + * forwarding and forwarding itself is finished. + * + * When BOTH @e was_closed (changed by command from application) + * AND @e clean_ready (changed internally by MHD) are set to + * true, function #MHD_resume_connection() will move this + * connection to cleanup list. + * @remark This flag could be changed from thread that process + * connection's recv(), send() and response. + */ + bool clean_ready; +}; +#endif /* UPGRADE_SUPPORT */ + + /** * State kept for each MHD daemon. All connections are kept in two * doubly-linked lists. The first one reflects the state of the @@ -910,6 +1106,22 @@ struct MHD_Daemon #if HTTPS_SUPPORT +#ifdef UPGRADE_SUPPORT + /** + * Head of DLL of upgrade response handles we are processing. + * Used for upgraded TLS connections when thread-per-connection + * is not used. + */ + struct MHD_UpgradeResponseHandle *urh_head; + + /** + * Tail of DLL of upgrade response handles we are processing. + * Used for upgraded TLS connections when thread-per-connection + * is not used. + */ + struct MHD_UpgradeResponseHandle *urh_tail; +#endif /* UPGRADE_SUPPORT */ + /** * Which TLS backend should be used. NULL for no TLS. * This is merely the handle to the dlsym() object, not @@ -1012,13 +1224,10 @@ 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). diff --git a/src/lib/request.c b/src/lib/request.c @@ -47,8 +47,6 @@ MHD_request_get_values (struct MHD_Request *request, int ret; struct MHD_HTTP_Header *pos; - if (NULL == request) - return -1; ret = 0; for (pos = request->headers_received; NULL != pos; @@ -143,8 +141,6 @@ MHD_request_lookup_value (struct MHD_Request *request, { struct MHD_HTTP_Header *pos; - if (NULL == request) - return NULL; for (pos = request->headers_received; NULL != pos; pos = pos->next) diff --git a/src/lib/response.c b/src/lib/response.c @@ -172,9 +172,6 @@ MHD_response_del_header (struct MHD_Response *response, struct MHD_HTTP_Header *pos; struct MHD_HTTP_Header *prev; - if ( (NULL == header) || - (NULL == content) ) - return MHD_NO; prev = NULL; pos = response->first_header; while (NULL != pos) @@ -248,8 +245,6 @@ MHD_response_get_header (struct MHD_Response *response, { struct MHD_HTTP_Header *pos; - if (NULL == key) - return NULL; for (pos = response->first_header; NULL != pos; pos = pos->next)