commit e5c2f9a339845bd040f3b326d2f976d4ea4d1ac2
parent dcaf43e3230f725a6ec0b406c205b7a87b7e3368
Author: Christian Grothoff <christian@grothoff.org>
Date: Sun, 18 Feb 2018 12:31:35 +0100
add remaining missing symbols for library to fully link
Diffstat:
10 files changed, 259 insertions(+), 273 deletions(-)
diff --git a/src/gnutls/update_event_loop_info.c b/src/gnutls/update_event_loop_info.c
@@ -0,0 +1,20 @@
+ enum MHD_Bool
+ (*update_event_loop_info)(void *cls,
+ struct MHD_TLS_ConnectionState *cs,
+ enum MHD_RequestEventLoopInfo *eli);
+
+
+ switch (connection->tls_state)
+ {
+ case MHD_TLS_CONN_INIT:
+ *eli = MHD_EVENT_LOOP_INFO_READ;
+ return true;
+ case MHD_TLS_CONN_HANDSHAKING:
+ if (0 == gnutls_record_get_direction (connection->tls_session))
+ *eli = MHD_EVENT_LOOP_INFO_READ;
+ else
+ *eli = MHD_EVENT_LOOP_INFO_WRITE;
+ return true;
+ default:
+ return false;
+ }
diff --git a/src/include/microhttpd2.h b/src/include/microhttpd2.h
@@ -323,12 +323,13 @@ struct MHD_Connection;
* for logging.
*
* A value of 0 indicates success (as a return value).
- * Values between 1 and 10000 must not be used.
+ * Values between 0 and 10000 must be handled explicitly by the app.
* Values from 10000-19999 are informational.
* Values from 20000-29999 indicate successful operations.
* Values from 30000-39999 indicate unsuccessful (normal) operations.
* Values from 40000-49999 indicate client errors.
- * Values from 50000-59999 indicate server errors.
+ * Values from 50000-59999 indicate MHD server errors.
+ * Values from 60000-69999 indicate application errors.
*/
enum MHD_StatusCode
{
@@ -866,6 +867,13 @@ enum MHD_StatusCode
*/
MHD_SC_APPLICATION_HUNG_CONNECTION = 60007,
+ /**
+ * Application only partially processed upload and did
+ * not suspend connection and the read buffer was maxxed
+ * out, so MHD closed the connection.
+ */
+ MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED = 60008,
+
};
@@ -4154,4 +4162,31 @@ _MHD_EXTERN enum MHD_Bool
MHD_is_feature_supported (enum MHD_Feature feature);
+/**
+ * What is this request waiting for?
+ */
+enum MHD_RequestEventLoopInfo
+{
+ /**
+ * We are waiting to be able to read.
+ */
+ MHD_EVENT_LOOP_INFO_READ = 0,
+
+ /**
+ * We are waiting to be able to write.
+ */
+ MHD_EVENT_LOOP_INFO_WRITE = 1,
+
+ /**
+ * We are waiting for the application to provide data.
+ */
+ MHD_EVENT_LOOP_INFO_BLOCK = 2,
+
+ /**
+ * We are finished and are awaiting cleanup.
+ */
+ MHD_EVENT_LOOP_INFO_CLEANUP = 3
+};
+
+
#endif
diff --git a/src/include/microhttpd_tls.h b/src/include/microhttpd_tls.h
@@ -1,6 +1,33 @@
+/*
+ This file is part of libmicrohttpd
+ Copyright (C) 2018 Christian Grothoff (and other contributing authors)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/**
+ * @file microhttpd_tls.h
+ * @brief interface for TLS plugins of libmicrohttpd
+ * @author Christian Grothoff
+ */
+
#ifndef MICROHTTPD_TLS_H
#define MICROHTTPD_TLS_H
+#include <microhttpd2.h>
+
/**
* Version of the TLS ABI.
*/
@@ -100,6 +127,12 @@ struct MHD_TLS_Plugin
enum MHD_Bool
(*idle_ready)(void *cls,
struct MHD_TLS_ConnectionState *cs);
+
+
+ enum MHD_Bool
+ (*update_event_loop_info)(void *cls,
+ struct MHD_TLS_ConnectionState *cs,
+ enum MHD_RequestEventLoopInfo *eli);
ssize_t
(*send)(void *cls,
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
@@ -65,7 +65,6 @@ libmicrohttpd_la_SOURCES = \
connection_finish_forward.c connection_finish_forward.h \
connection_info.c \
connection_options.c \
- connection_update_event_loop_info.c connection_update_event_loop_info.h \
connection_update_last_activity.c connection_update_last_activity.h \
daemon_close_all_connections.c daemon_close_all_connections.h \
daemon_create.c \
diff --git a/src/lib/action_from_response.c b/src/lib/action_from_response.c
@@ -89,7 +89,7 @@ response_action (void *cls,
request->state = MHD_REQUEST_FOOTERS_RECEIVED;
}
if (! request->in_idle)
- (void) MHD_connection_handle_idle (request->connection);
+ (void) MHD_request_handle_idle_ (request);
return MHD_SC_OK;
}
diff --git a/src/lib/connection_call_handlers.c b/src/lib/connection_call_handlers.c
@@ -23,7 +23,6 @@
*/
#include "internal.h"
#include "connection_call_handlers.h"
-#include "connection_update_event_loop_info.h"
#include "connection_update_last_activity.h"
#include "connection_close.h"
@@ -2889,6 +2888,170 @@ connection_epoll_update_ (struct MHD_Connection *connection)
/**
+ * Update the 'event_loop_info' field of this connection based on the
+ * state that the connection is now in. May also close the connection
+ * or perform other updates to the connection if needed to prepare for
+ * the next round of the event loop.
+ *
+ * @param connection connection to get poll set for
+ */
+static void
+connection_update_event_loop_info (struct MHD_Connection *connection)
+{
+ struct MHD_Daemon *daemon = connection->daemon;
+ struct MHD_Request *request = &connection->request;
+
+ /* Do not update states of suspended connection */
+ if (connection->suspended)
+ return; /* States will be updated after resume. */
+#ifdef HTTPS_SUPPORT
+ {
+ struct MHD_TLS_Plugin *tls;
+
+ if ( (NULL != (tls = daemon->tls_api)) &&
+ (tls->update_event_loop_info (tls->cls,
+ connection->tls_cs,
+ &request->event_loop_info)) )
+ return; /* TLS has decided what to do */
+ }
+#endif /* HTTPS_SUPPORT */
+ while (1)
+ {
+#if DEBUG_STATES
+ MHD_DLOG (daemon,
+ MHD_SC_STATE_MACHINE_STATUS_REPORT,
+ _("In function %s handling connection at state: %s\n"),
+ __FUNCTION__,
+ MHD_state_to_string (request->state));
+#endif
+ switch (request->state)
+ {
+ case MHD_REQUEST_INIT:
+ case MHD_REQUEST_URL_RECEIVED:
+ case MHD_REQUEST_HEADER_PART_RECEIVED:
+ /* while reading headers, we always grow the
+ read buffer if needed, no size-check required */
+ if ( (request->read_buffer_offset == request->read_buffer_size) &&
+ (! try_grow_read_buffer (request)) )
+ {
+ transmit_error_response (request,
+ MHD_SC_CLIENT_HEADER_TOO_BIG,
+ (NULL != request->url)
+ ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
+ : MHD_HTTP_URI_TOO_LONG,
+ REQUEST_TOO_BIG);
+ continue;
+ }
+ if (! connection->read_closed)
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
+ else
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
+ break;
+ case MHD_REQUEST_HEADERS_RECEIVED:
+ mhd_assert (0);
+ break;
+ case MHD_REQUEST_HEADERS_PROCESSED:
+ mhd_assert (0);
+ break;
+ case MHD_REQUEST_CONTINUE_SENDING:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
+ break;
+ case MHD_REQUEST_CONTINUE_SENT:
+ if (request->read_buffer_offset == request->read_buffer_size)
+ {
+ if ( (! try_grow_read_buffer (request)) &&
+ (MHD_TM_EXTERNAL_EVENT_LOOP != daemon->threading_model) )
+ {
+ /* failed to grow the read buffer, and the client
+ which is supposed to handle the received data in
+ a *blocking* fashion (in this mode) did not
+ handle the data as it was supposed to!
+
+ => we would either have to do busy-waiting
+ (on the client, which would likely fail),
+ or if we do nothing, we would just timeout
+ on the connection (if a timeout is even set!).
+
+ Solution: we kill the connection with an error */
+ transmit_error_response (request,
+ MHD_SC_APPLICATION_HUNG_CONNECTION_CLOSED,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ INTERNAL_ERROR);
+ continue;
+ }
+ }
+ if ( (request->read_buffer_offset < request->read_buffer_size) &&
+ (! connection->read_closed) )
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
+ else
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
+ break;
+ case MHD_REQUEST_BODY_RECEIVED:
+ case MHD_REQUEST_FOOTER_PART_RECEIVED:
+ /* while reading footers, we always grow the
+ read buffer if needed, no size-check required */
+ if (connection->read_closed)
+ {
+ CONNECTION_CLOSE_ERROR (connection,
+ MHD_SC_CONNECTION_READ_FAIL_CLOSED,
+ NULL);
+ continue;
+ }
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
+ /* transition to FOOTERS_RECEIVED
+ happens in read handler */
+ break;
+ case MHD_REQUEST_FOOTERS_RECEIVED:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
+ break;
+ case MHD_REQUEST_HEADERS_SENDING:
+ /* headers in buffer, keep writing */
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
+ break;
+ case MHD_REQUEST_HEADERS_SENT:
+ mhd_assert (0);
+ break;
+ case MHD_REQUEST_NORMAL_BODY_READY:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
+ break;
+ case MHD_REQUEST_NORMAL_BODY_UNREADY:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
+ break;
+ case MHD_REQUEST_CHUNKED_BODY_READY:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
+ break;
+ case MHD_REQUEST_CHUNKED_BODY_UNREADY:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
+ break;
+ case MHD_REQUEST_BODY_SENT:
+ mhd_assert (0);
+ break;
+ case MHD_REQUEST_FOOTERS_SENDING:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
+ break;
+ case MHD_REQUEST_FOOTERS_SENT:
+ mhd_assert (0);
+ break;
+ case MHD_REQUEST_CLOSED:
+ request->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
+ return; /* do nothing, not even reading */
+ case MHD_REQUEST_IN_CLEANUP:
+ mhd_assert (0);
+ break;
+#ifdef UPGRADE_SUPPORT
+ case MHD_REQUEST_UPGRADE:
+ mhd_assert (0);
+ break;
+#endif /* UPGRADE_SUPPORT */
+ default:
+ mhd_assert (0);
+ }
+ break;
+ }
+}
+
+
+/**
* This function was created to handle per-request processing that
* has to happen even if the socket cannot be read or written to.
* @remark To be called only from thread that process request's
@@ -3386,7 +3549,7 @@ MHD_request_handle_idle_ (struct MHD_Request *request)
return true;
}
}
- MHD_connection_update_event_loop_info_ (connection);
+ connection_update_event_loop_info (connection);
ret = true;
#ifdef EPOLL_SUPPORT
if ( (! connection->suspended) &&
diff --git a/src/lib/connection_update_event_loop_info.c b/src/lib/connection_update_event_loop_info.c
@@ -1,195 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-/**
- * @file lib/connection_update_event_loop_info.c
- * @brief update the set of network events this connection is waiting for
- * @author Christian Grothoff
- */
-#include "internal.h"
-#include "connection_update_event_loop_info.h"
-
-
-/**
- * Update the 'event_loop_info' field of this connection based on the
- * state that the connection is now in. May also close the connection
- * or perform other updates to the connection if needed to prepare for
- * the next round of the event loop.
- *
- * @param connection connection to get poll set for
- */
-void
-MHD_connection_update_event_loop_info_ (struct MHD_Connection *connection)
-{
- /* Do not update states of suspended connection */
- if (connection->suspended)
- return; /* States will be updated after resume. */
-#ifdef HTTPS_SUPPORT
- if (MHD_TLS_CONN_NO_TLS != connection->tls_state)
- { /* HTTPS connection. */
- switch (connection->tls_state)
- {
- case MHD_TLS_CONN_INIT:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
- return;
- case MHD_TLS_CONN_HANDSHAKING:
- if (0 == gnutls_record_get_direction (connection->tls_session))
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
- else
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
- return;
- default:
- break;
- }
- }
-#endif /* HTTPS_SUPPORT */
- while (1)
- {
-#if DEBUG_STATES
- MHD_DLOG (connection->daemon,
- _("In function %s handling connection at state: %s\n"),
- __FUNCTION__,
- MHD_state_to_string (connection->state));
-#endif
- switch (connection->state)
- {
- case MHD_CONNECTION_INIT:
- case MHD_CONNECTION_URL_RECEIVED:
- case MHD_CONNECTION_HEADER_PART_RECEIVED:
- /* while reading headers, we always grow the
- read buffer if needed, no size-check required */
- if ( (connection->read_buffer_offset == connection->read_buffer_size) &&
- (MHD_NO == try_grow_read_buffer (connection)) )
- {
- transmit_error_response (connection,
- (connection->url != NULL)
- ? MHD_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE
- : MHD_HTTP_URI_TOO_LONG,
- REQUEST_TOO_BIG);
- continue;
- }
- if (! connection->read_closed)
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
- else
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
- break;
- case MHD_CONNECTION_HEADERS_RECEIVED:
- mhd_assert (0);
- break;
- case MHD_CONNECTION_HEADERS_PROCESSED:
- mhd_assert (0);
- break;
- case MHD_CONNECTION_CONTINUE_SENDING:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
- break;
- case MHD_CONNECTION_CONTINUE_SENT:
- if (connection->read_buffer_offset == connection->read_buffer_size)
- {
- if ((MHD_YES != try_grow_read_buffer (connection)) &&
- (0 != (connection->daemon->options &
- MHD_USE_INTERNAL_POLLING_THREAD)))
- {
- /* failed to grow the read buffer, and the
- client which is supposed to handle the
- received data in a *blocking* fashion
- (in this mode) did not handle the data as
- it was supposed to!
- => we would either have to do busy-waiting
- (on the client, which would likely fail),
- or if we do nothing, we would just timeout
- on the connection (if a timeout is even
- set!).
- Solution: we kill the connection with an error */
- transmit_error_response (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- INTERNAL_ERROR);
- continue;
- }
- }
- if ( (connection->read_buffer_offset < connection->read_buffer_size) &&
- (! connection->read_closed) )
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
- else
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
- break;
- case MHD_CONNECTION_BODY_RECEIVED:
- case MHD_CONNECTION_FOOTER_PART_RECEIVED:
- /* while reading footers, we always grow the
- read buffer if needed, no size-check required */
- if (connection->read_closed)
- {
- CONNECTION_CLOSE_ERROR (connection,
- NULL);
- continue;
- }
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_READ;
- /* transition to FOOTERS_RECEIVED
- happens in read handler */
- break;
- case MHD_CONNECTION_FOOTERS_RECEIVED:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
- break;
- case MHD_CONNECTION_HEADERS_SENDING:
- /* headers in buffer, keep writing */
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
- break;
- case MHD_CONNECTION_HEADERS_SENT:
- mhd_assert (0);
- break;
- case MHD_CONNECTION_NORMAL_BODY_READY:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
- break;
- case MHD_CONNECTION_NORMAL_BODY_UNREADY:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
- break;
- case MHD_CONNECTION_CHUNKED_BODY_READY:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
- break;
- case MHD_CONNECTION_CHUNKED_BODY_UNREADY:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_BLOCK;
- break;
- case MHD_CONNECTION_BODY_SENT:
- mhd_assert (0);
- break;
- case MHD_CONNECTION_FOOTERS_SENDING:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_WRITE;
- break;
- case MHD_CONNECTION_FOOTERS_SENT:
- mhd_assert (0);
- break;
- case MHD_CONNECTION_CLOSED:
- connection->event_loop_info = MHD_EVENT_LOOP_INFO_CLEANUP;
- return; /* do nothing, not even reading */
- case MHD_CONNECTION_IN_CLEANUP:
- mhd_assert (0);
- break;
-#ifdef UPGRADE_SUPPORT
- case MHD_CONNECTION_UPGRADE:
- mhd_assert (0);
- break;
-#endif /* UPGRADE_SUPPORT */
- default:
- mhd_assert (0);
- }
- break;
- }
-}
-
-
-/* end of connection_update_event_loop_info.c */
-
diff --git a/src/lib/connection_update_event_loop_info.h b/src/lib/connection_update_event_loop_info.h
@@ -1,42 +0,0 @@
-/*
- This file is part of libmicrohttpd
- Copyright (C) 2007-2018 Daniel Pittman and Christian Grothoff
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-/**
- * @file lib/connection_update_event_loop_info.h
- * @brief function to update last activity of a connection
- * @author Christian Grothoff
- */
-
-#ifndef CONNECTION_UPDATE_EVENT_LOOP_INFO_H
-#define CONNECTION_UPDATE_EVENT_LOOP_INFO_H
-
-
-/**
- * Update the 'event_loop_info' field of this connection based on the
- * state that the connection is now in. May also close the connection
- * or perform other updates to the connection if needed to prepare for
- * the next round of the event loop.
- *
- * @param connection connection to get poll set for
- */
-void
-MHD_connection_update_event_loop_info_ (struct MHD_Connection *connection)
- MHD_NONNULL (1);
-
-
-#endif
diff --git a/src/lib/daemon_epoll.c b/src/lib/daemon_epoll.c
@@ -477,7 +477,7 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
}
/* Finally, handle timed-out connections; we need to do this here
- as the epoll mechanism won't call the 'MHD_connection_handle_idle()' on everything,
+ as the epoll mechanism won't call the 'MHD_request_handle_idle_()' on everything,
as the other event loops do. As timeouts do not get an explicit
event, we need to find those connections that might have timed out
here.
@@ -488,7 +488,7 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
while (NULL != (pos = prev))
{
prev = pos->prevX;
- MHD_connection_handle_idle (pos);
+ MHD_request_handle_idle_ (&pos->request);
}
/* Connections with the default timeout are sorted by prepending
them to the head of the list whenever we touch the connection;
@@ -498,7 +498,7 @@ MHD_daemon_epoll_ (struct MHD_Daemon *daemon,
while (NULL != (pos = prev))
{
prev = pos->prevX;
- MHD_connection_handle_idle (pos);
+ MHD_request_handle_idle_ (&pos->request);
if (MHD_REQUEST_CLOSED != pos->request.state)
break; /* sorted by timeout, no need to visit the rest! */
}
diff --git a/src/lib/internal.h b/src/lib/internal.h
@@ -363,33 +363,6 @@ struct MHD_HTTP_Header
/**
- * What is this request waiting for?
- */
-enum MHD_RequestEventLoopInfo
-{
- /**
- * We are waiting to be able to read.
- */
- MHD_EVENT_LOOP_INFO_READ = 0,
-
- /**
- * We are waiting to be able to write.
- */
- MHD_EVENT_LOOP_INFO_WRITE = 1,
-
- /**
- * We are waiting for the application to provide data.
- */
- MHD_EVENT_LOOP_INFO_BLOCK = 2,
-
- /**
- * We are finished and are awaiting cleanup.
- */
- MHD_EVENT_LOOP_INFO_CLEANUP = 3
-};
-
-
-/**
* State kept for each HTTP request.
*/
struct MHD_Request