libmicrohttpd

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

commit b7dd331e440f36db9c362731afed803148a08fe9
parent b14541751ff614f00867ceaf4c0fa21f7c484c58
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 14 Feb 2018 05:35:48 +0100

more lib/ work

Diffstat:
Msrc/include/microhttpd2.h | 46+++++++++++++++++++++++++++-------------------
Msrc/include/microhttpd_tls.h | 20+++++++++++++++++++-
Msrc/lib/connection_info.c | 60+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/lib/daemon_info.c | 63++++++++++++++++++++++++++++++++++++---------------------------
Msrc/lib/daemon_options.c | 18++++++++++++------
Msrc/lib/internal.c | 2+-
Msrc/lib/internal.h | 52++++++++++++++++++++++++++++++++++++++++++++--------
Msrc/lib/request_info.c | 36+++++++++++++++++++++++++++++++++++-
8 files changed, 233 insertions(+), 64 deletions(-)

diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h @@ -2608,7 +2608,14 @@ enum MHD_ConnectionInformationType * Get connection timeout * @ingroup request */ - MHD_CONNECTION_INFORMATION_CONNECTION_TIMEOUT + MHD_CONNECTION_INFORMATION_CONNECTION_TIMEOUT, + + /** + * Check whether the connection is suspended. + * @ingroup request + */ + MHD_CONNECTION_INFORMATION_CONNECTION_SUSPENDED + }; @@ -2654,7 +2661,7 @@ union MHD_ConnectionInformation /** * Address information for the client. */ - struct sockaddr *client_addr; + const struct sockaddr *client_addr; /** * Which daemon manages this connection (useful in case there are many @@ -2663,10 +2670,16 @@ union MHD_ConnectionInformation struct MHD_Daemon *daemon; /** - * Socket-specific client context. Points to the same address as - * the "socket_context" of the #MHD_NotifyConnectionCallback. + * Pointer to connection-specific client context. Points to the + * same address as the "socket_context" of the + * #MHD_NotifyConnectionCallback. + */ + void **socket_context; + + /** + * Is this connection right now suspended? */ - void *socket_context; + enum MHD_Bool suspended; }; @@ -2721,15 +2734,10 @@ union MHD_RequestInformation struct MHD_Connection *connection; /** - * Socket-specific client context. Will also be given to + * Pointer to client context. Will also be given to * the application in a #MHD_RequestTerminationCallback. */ - void *request_context; - - /** - * The suspended status of a request. - */ - enum MHD_Bool suspended; + void **request_context; /** * HTTP version requested by the client. @@ -2762,11 +2770,11 @@ enum MHD_RequestInformationType MHD_REQUEST_INFORMATION_CONNECTION, /** - * Check whether the connection is suspended. - * @ingroup request + * Returns the client-specific pointer to a `void *` that + * is specific to this request. */ - MHD_REQUEST_INFORMATION_SUSPENDED, - + MHD_REQUEST_INFORMATION_CLIENT_CONTEXT, + /** * Return the HTTP version string given by the client. * @ingroup request @@ -2837,7 +2845,7 @@ enum MHD_DaemonInformationType * Request the file descriptor for the listening socket. * No extra arguments should be passed. */ - MHD_DAEMON_INFORMATION_LISTEN_FD, + MHD_DAEMON_INFORMATION_LISTEN_SOCKET, /** * Request the file descriptor for the external epoll. @@ -2871,9 +2879,9 @@ union MHD_DaemonInformation { /** - * Socket, returned for #MHD_DAEMON_INFORMATION_LISTEN_FD. + * Socket, returned for #MHD_DAEMON_INFORMATION_LISTEN_SOCKET. */ - MHD_socket listen_fd; + MHD_socket listen_socket; /** * Bind port number, returned for #MHD_DAEMON_INFORMATION_BIND_PORT. diff --git a/src/include/microhttpd_tls.h b/src/include/microhttpd_tls.h @@ -14,6 +14,12 @@ /** + * Data structure kept per TLS client by the plugin. + */ +struct MHD_TLS_ConnectionState; + + +/** * Callback functions to use for TLS operations. */ struct MHD_TLS_Plugin @@ -70,7 +76,19 @@ struct MHD_TLS_Plugin enum MHD_StatusCode (*init_mem_trust)(void *cls, const char *mem_trust); - + + + /** + * Function called when we receive a connection and need + * to initialize our TLS state for it. + * + * @param cls the @e cls of this struct + * @param ... TBD + * @return NULL on error + */ + struct MHD_TLS_ConnectionState * + (*setup_connection)(void *cls, + ...); /** * TODO: More functions here.... diff --git a/src/lib/connection_info.c b/src/lib/connection_info.c @@ -46,7 +46,65 @@ MHD_connection_get_information_sz (struct MHD_Connection *connection, union MHD_ConnectionInformation *return_value, size_t return_value_size) { - return MHD_NO; /* FIXME: not yet implemented */ +#define CHECK_SIZE(type) if (sizeof(type) < return_value_size) \ + return MHD_NO + + switch (info_type) + { +#ifdef HTTPS_SUPPORT + case MHD_CONNECTION_INFORMATION_CIPHER_ALGO: + CHECK_SIZE (int); + if (NULL == connection->tls_cs) + return MHD_NO; + // return_value->cipher_algorithm + // = gnutls_cipher_get (connection->tls_session); + return MHD_NO; // FIXME: to be implemented + case MHD_CONNECTION_INFORMATION_PROTOCOL: + CHECK_SIZE (int); + if (NULL == connection->tls_cs) + return MHD_NO; + //return_value->protocol + // = gnutls_protocol_get_version (connection->tls_session); + return MHD_NO; // FIXME: to be implemented + case MHD_CONNECTION_INFORMATION_GNUTLS_SESSION: + CHECK_SIZE (void *); + if (NULL == connection->tls_cs) + return MHD_NO; + // return_value->tls_session = connection->tls_session; + return MHD_NO; // FIXME: to be implemented +#endif /* HTTPS_SUPPORT */ + case MHD_CONNECTION_INFORMATION_CLIENT_ADDRESS: + CHECK_SIZE (struct sockaddr *); + return_value->client_addr + = (const struct sockaddr *) &connection->addr; + return MHD_YES; + case MHD_CONNECTION_INFORMATION_DAEMON: + CHECK_SIZE (struct MHD_Daemon *); + return_value->daemon = connection->daemon; + return MHD_YES; + case MHD_CONNECTION_INFORMATION_CONNECTION_FD: + CHECK_SIZE (MHD_socket); + return_value->connect_fd = connection->socket_fd; + return MHD_YES; + case MHD_CONNECTION_INFORMATION_SOCKET_CONTEXT: + CHECK_SIZE (void **); + return_value->socket_context = &connection->socket_context; + return MHD_YES; + case MHD_CONNECTION_INFORMATION_CONNECTION_SUSPENDED: + CHECK_SIZE (enum MHD_Bool); + return_value->suspended + = connection->suspended ? MHD_YES : MHD_NO; + return MHD_YES; + case MHD_CONNECTION_INFORMATION_CONNECTION_TIMEOUT: + CHECK_SIZE (unsigned int); + return_value->connection_timeout + = (unsigned int) connection->connection_timeout; + return MHD_YES; + default: + return MHD_NO; + } + +#undef CHECK_SIZE } /* end of connection_info.c */ diff --git a/src/lib/daemon_info.c b/src/lib/daemon_info.c @@ -46,50 +46,59 @@ MHD_daemon_get_information_sz (struct MHD_Daemon *daemon, union MHD_DaemonInformation *return_value, size_t return_value_size) { -#if OLD - if (NULL == daemon) - return NULL; +#define CHECK_SIZE(type) if (sizeof(type) < return_value_size) \ + return MHD_NO + switch (info_type) { - case MHD_DAEMON_INFO_KEY_SIZE: - return NULL; /* no longer supported */ - case MHD_DAEMON_INFO_MAC_KEY_SIZE: - return NULL; /* no longer supported */ - case MHD_DAEMON_INFO_LISTEN_FD: - return (const union MHD_DaemonInfo *) &daemon->listen_fd; + case MHD_DAEMON_INFORMATION_LISTEN_SOCKET: + CHECK_SIZE (MHD_socket); + return_value->listen_socket + = daemon->listen_socket; + return MHD_YES; #ifdef EPOLL_SUPPORT - case MHD_DAEMON_INFO_EPOLL_FD: - return (const union MHD_DaemonInfo *) &daemon->epoll_fd; + case MHD_DAEMON_INFORMATION_EPOLL_FD: + CHECK_SIZE (int); + // FIXME: maybe return MHD_NO if we are not using EPOLL? + return_value->epoll_fd = daemon->epoll_fd; + return MHD_YES; #endif - case MHD_DAEMON_INFO_CURRENT_CONNECTIONS: - if (0 == (daemon->options & MHD_USE_INTERNAL_POLLING_THREAD)) + case MHD_DAEMON_INFORMATION_CURRENT_CONNECTIONS: + CHECK_SIZE (unsigned int); + if (MHD_TM_EXTERNAL_EVENT_LOOP == daemon->threading_model) { - /* Assume that MHD_run() in not called in other thread - * at the same time. */ + /* Assumes that MHD_run() in not called in other thread + (of the application) at the same time. */ MHD_cleanup_connections (daemon); + return_value->num_connections + = daemon->connections; } else if (daemon->worker_pool) { unsigned int i; /* Collect the connection information stored in the workers. */ - daemon->connections = 0; - for (i = 0; i < daemon->worker_pool_size; i++) + return_value->num_connections = 0; + for (i = 0; i < daemon->worker_pool_size; i++) { /* FIXME: next line is thread-safe only if read is atomic. */ - daemon->connections += daemon->worker_pool[i].connections; + return_value->num_connections + += daemon->worker_pool[i].connections; } } - return (const union MHD_DaemonInfo *) &daemon->connections; - case MHD_DAEMON_INFO_FLAGS: - return (const union MHD_DaemonInfo *) &daemon->options; - case MHD_DAEMON_INFO_BIND_PORT: - return (const union MHD_DaemonInfo *) &daemon->port; + else + return_value->num_connections + = daemon->connections; + return MHD_YES; + case MHD_DAEMON_INFORMATION_BIND_PORT: + CHECK_SIZE (uint16_t); + // FIXME: return MHD_NO if port is not known/UNIX? + return_value->port = daemon->listen_port; + return MHD_YES; default: - return NULL; + return MHD_NO; } -#else - return MHD_NO; -#endif + +#undef CHECK_SIZE } /* end of daemon_info.c */ diff --git a/src/lib/daemon_options.c b/src/lib/daemon_options.c @@ -126,7 +126,7 @@ MHD_daemon_disallow_suspend_resume (struct MHD_Daemon *daemon) void MHD_daemon_disallow_upgrade (struct MHD_Daemon *daemon) { - daemon->disallow_upgrade; + daemon->disallow_upgrade = true; } @@ -165,6 +165,7 @@ MHD_daemon_tcp_fastopen (struct MHD_Daemon *daemon, return MHD_NO; #endif } + return MHD_NO; } @@ -355,20 +356,20 @@ MHD_daemon_set_tls_backend (struct MHD_Daemon *daemon, if (NULL == (daemon->tls_backend_lib = dlopen (filename, RTLD_NOW | RTLD_LOCAL))) - return MHD_SC_BACKEND_UNSUPPORTED; /* plugin not found */ + return MHD_SC_TLS_BACKEND_UNSUPPORTED; /* plugin not found */ if (NULL == (init = dlsym (daemon->tls_backend_lib, "MHD_TLS_init_" MHD_TLS_ABI_VERSION_STR))) { dlclose (daemon->tls_backend_lib); daemon->tls_backend_lib = NULL; - return MHD_SC_BACKEND_UNSUPPORTED; /* possibly wrong version installed */ + return MHD_SC_TLS_BACKEND_UNSUPPORTED; /* possibly wrong version installed */ } if (NULL == (daemon->tls_api = init (ciphers))) { dlclose (daemon->tls_backend_lib); daemon->tls_backend_lib = NULL; - return MHD_SC_CIPHERS_INVALID; /* possibly wrong version installed */ + return MHD_SC_TLS_CIPHERS_INVALID; /* possibly wrong version installed */ } return MHD_SC_OK; #endif @@ -545,8 +546,8 @@ MHD_daemon_set_early_uri_logger (struct MHD_Daemon *daemon, MHD_EarlyUriLogCallback cb, void *cb_cls) { - daemon->early_uri_logger = cb; - daemon->early_uri_logger_cls = cb_cls; + daemon->early_uri_logger_cb = cb; + daemon->early_uri_logger_cb_cls = cb_cls; } @@ -687,6 +688,9 @@ MHD_daemon_digest_auth_random (struct MHD_Daemon *daemon, daemon->digest_auth_random_buf = buf; daemon->digest_auth_random_buf_size = buf_size; #else + (void) daemon; + (void) buf_size; + (void) buf; MHD_PANIC ("digest authentication not supported by this build"); #endif } @@ -732,6 +736,8 @@ MHD_daemon_digest_auth_nc_length (struct MHD_Daemon *daemon, daemon->digest_nc_length = nc_length; return MHD_SC_OK; #else + (void) daemon; + (void) nc_length; return MHD_SC_DIGEST_AUTH_NOT_SUPPORTED_BY_BUILD; #endif } diff --git a/src/lib/internal.c b/src/lib/internal.c @@ -238,7 +238,7 @@ MHD_parse_arguments_ (struct MHD_Connection *connection, break; } /* amper is non-NULL here */ - amper[0] = '\0';d + amper[0] = '\0'; amper++; if ( (NULL == equals) || (equals >= amper) ) diff --git a/src/lib/internal.h b/src/lib/internal.h @@ -454,7 +454,7 @@ struct MHD_Request * HTTP version string (i.e. http/1.1). Allocated * in pool. */ - char *version; + char *version_s; /** * Close connection after sending response? @@ -493,7 +493,6 @@ struct MHD_Request */ char *colon; - /** * Function used for reading HTTP request stream. */ @@ -515,11 +514,6 @@ struct MHD_Request #endif /* UPGRADE_SUPPORT */ /** - * Foreign address (of length @e addr_len). - */ - struct sockaddr_storage addr; - - /** * Thread handle for this connection (if we are using * one thread per connection). */ @@ -741,7 +735,23 @@ struct MHD_Connection * Reference to the MHD_Daemon struct. */ struct MHD_Daemon *daemon; + + /** + * We allow the main application to associate some pointer with the + * TCP connection (which may span multiple HTTP requests). Here is + * where we store it. (MHD does not know or care what it is). + * The location is given to the #MHD_NotifyConnectionCallback and + * also accessible via #MHD_CONNECTION_INFO_SOCKET_CONTEXT. + */ + void *socket_context; +#ifdef HTTPS_SUPPORT + /** + * State kept per TLS connection. Plugin-specific. + */ + struct MHD_TLS_ConnectionState *tls_cs; +#endif + /** * Information about the current request we are processing * on this connection. @@ -749,6 +759,11 @@ struct MHD_Connection struct MHD_Request request; /** + * Foreign address (of length @e addr_len). + */ + struct sockaddr_storage addr; + + /** * Length of the foreign address. */ socklen_t addr_len; @@ -858,7 +873,7 @@ struct MHD_Daemon /** * Closure for @e early_uri_logger_cb. */ - void *early_uri_logger_cls; + void *early_uri_logger_cb_cls; /** * Function to call whenever a connection is started or @@ -881,6 +896,17 @@ struct MHD_Daemon * Closure for @e unescape_cb. */ void *unescape_cb_cls; + + /** + * Pointer to master daemon (NULL if this is the master) + */ + struct MHD_Daemon *master; + + /** + * Worker daemons (one per thread) + */ + struct MHD_Daemon *worker_pool; + #if HTTPS_SUPPORT /** @@ -1135,6 +1161,16 @@ struct MHD_Daemon unsigned int ip_connection_limit; /** + * Number of active parallel connections. + */ + unsigned int connections; + + /** + * Number of worker daemons + */ + unsigned int worker_pool_size; + + /** * Default timeout in seconds for idle connections. */ time_t connection_default_timeout; diff --git a/src/lib/request_info.c b/src/lib/request_info.c @@ -46,7 +46,41 @@ MHD_request_get_information_sz (struct MHD_Request *request, union MHD_RequestInformation *return_value, size_t return_value_size) { - return MHD_NO; /* not implemented */ +#define CHECK_SIZE(type) if (sizeof(type) < return_value_size) \ + return MHD_NO + + switch (info_type) + { + case MHD_REQUEST_INFORMATION_CONNECTION: + CHECK_SIZE (struct MHD_Connection *); + return_value->connection = request->connection; + return MHD_YES; + case MHD_REQUEST_INFORMATION_CLIENT_CONTEXT: + CHECK_SIZE (void **); + return_value->request_context = &request->client_context; + return MHD_YES; + case MHD_REQUEST_INFORMATION_HTTP_VERSION: + CHECK_SIZE (const char *); + return_value->http_version = request->version_s; + return MHD_YES; + case MHD_REQUEST_INFORMATION_HTTP_METHOD: + CHECK_SIZE (const char *); + return_value->http_method = request->method_s; + return MHD_YES; + case MHD_REQUEST_INFORMATION_HEADER_SIZE: + CHECK_SIZE (size_t); + if ( (MHD_REQUEST_HEADERS_RECEIVED > request->state) || + (MHD_REQUEST_CLOSED == request->state) || + (MHD_REQUEST_IN_CLEANUP == request->state) ) + return MHD_NO; /* invalid, too early! */ + return_value->header_size = request->header_size; + return MHD_YES; + + default: + return MHD_NO; + } + +#undef CHECK_SIZE }