commit a2f8683def34643b64a3c1afd00900fbe99f6d0f
parent e101aeb4a9e18d506bd93afc87ea55183128f2cd
Author: Christian Grothoff <christian@grothoff.org>
Date: Fri, 16 Feb 2018 07:24:27 +0100
implement recv/send adapters
Diffstat:
4 files changed, 160 insertions(+), 14 deletions(-)
diff --git a/src/lib/connection_add.c b/src/lib/connection_add.c
@@ -29,6 +29,7 @@
#include "daemon_ip_limit.h"
#include "daemon_select.h"
#include "daemon_poll.h"
+#include "mhd_sockets.h"
#ifdef UPGRADE_SUPPORT
@@ -453,6 +454,113 @@ exit:
/**
+ * Callback for receiving data from the socket.
+ *
+ * @param connection the MHD connection structure
+ * @param other where to write received data to
+ * @param i maximum size of other (in bytes)
+ * @return positive value for number of bytes actually received or
+ * negative value for error number MHD_ERR_xxx_
+ */
+static ssize_t
+recv_param_adapter (struct MHD_Connection *connection,
+ void *other,
+ size_t i)
+{
+ ssize_t ret;
+
+ if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
+ (MHD_REQUEST_CLOSED == connection->request.state) )
+ {
+ return MHD_ERR_NOTCONN_;
+ }
+ if (i > MHD_SCKT_SEND_MAX_SIZE_)
+ i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
+
+ ret = MHD_recv_ (connection->socket_fd,
+ other,
+ i);
+ if (0 > ret)
+ {
+ const int err = MHD_socket_get_error_ ();
+ if (MHD_SCKT_ERR_IS_EAGAIN_ (err))
+ {
+#ifdef EPOLL_SUPPORT
+ /* Got EAGAIN --- no longer read-ready */
+ connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
+#endif /* EPOLL_SUPPORT */
+ return MHD_ERR_AGAIN_;
+ }
+ if (MHD_SCKT_ERR_IS_EINTR_ (err))
+ return MHD_ERR_AGAIN_;
+ if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
+ return MHD_ERR_CONNRESET_;
+ /* Treat any other error as hard error. */
+ return MHD_ERR_NOTCONN_;
+ }
+#ifdef EPOLL_SUPPORT
+ else if (i > (size_t)ret)
+ connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
+#endif /* EPOLL_SUPPORT */
+ return ret;
+}
+
+
+/**
+ * Callback for writing data to the socket.
+ *
+ * @param connection the MHD connection structure
+ * @param other data to write
+ * @param i number of bytes to write
+ * @return positive value for number of bytes actually sent or
+ * negative value for error number MHD_ERR_xxx_
+ */
+static ssize_t
+send_param_adapter (struct MHD_Connection *connection,
+ const void *other,
+ size_t i)
+{
+ ssize_t ret;
+
+ if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
+ (MHD_REQUEST_CLOSED == connection->request.state) )
+ {
+ return MHD_ERR_NOTCONN_;
+ }
+ if (i > MHD_SCKT_SEND_MAX_SIZE_)
+ i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
+
+ ret = MHD_send_ (connection->socket_fd,
+ other,
+ i);
+ if (0 > ret)
+ {
+ const int err = MHD_socket_get_error_();
+
+ if (MHD_SCKT_ERR_IS_EAGAIN_(err))
+ {
+#ifdef EPOLL_SUPPORT
+ /* EAGAIN --- no longer write-ready */
+ connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
+#endif /* EPOLL_SUPPORT */
+ return MHD_ERR_AGAIN_;
+ }
+ if (MHD_SCKT_ERR_IS_EINTR_ (err))
+ return MHD_ERR_AGAIN_;
+ if (MHD_SCKT_ERR_IS_ (err, MHD_SCKT_ECONNRESET_))
+ return MHD_ERR_CONNRESET_;
+ /* Treat any other error as hard error. */
+ return MHD_ERR_NOTCONN_;
+ }
+#ifdef EPOLL_SUPPORT
+ else if (i > (size_t)ret)
+ connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
+#endif /* EPOLL_SUPPORT */
+ return ret;
+}
+
+
+/**
* Add another client connection to the set of connections
* managed by MHD. This API is usually not needed (since
* MHD will accept inbound connections on the server socket).
@@ -669,9 +777,11 @@ internal_add_connection (struct MHD_Daemon *daemon,
}
else
#endif /* ! HTTPS_SUPPORT */
- /* set default connection handlers */
- MHD_set_http_callbacks_ (connection);
-
+ {
+ /* set default connection handlers */
+ connection->recv_cls = &recv_param_adapter;
+ connection->send_cls = &send_param_adapter;
+ }
MHD_mutex_lock_chk_ (&daemon->cleanup_connection_mutex);
/* Firm check under lock. */
if (daemon->connections >= daemon->global_connection_limit)
diff --git a/src/lib/daemon_close_all_connections.c b/src/lib/daemon_close_all_connections.c
@@ -111,7 +111,7 @@ MHD_daemon_close_all_connections_ (struct MHD_Daemon *daemon)
MHD_connection_finish_forward_ (urh->connection);
urh->clean_ready = true;
/* Resuming will move connection to cleanup list. */
- MHD_resume_connection (urh->connection);
+ MHD_request_resume (&urh->connection->request);
}
#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
diff --git a/src/lib/internal.h b/src/lib/internal.h
@@ -494,16 +494,6 @@ struct MHD_Request
*/
char *colon;
- /**
- * Function used for reading HTTP request stream.
- */
- ReceiveCallback recv_cls;
-
- /**
- * Function used for writing HTTP response stream.
- */
- TransmitCallback send_cls;
-
#ifdef UPGRADE_SUPPORT
/**
* If this connection was upgraded, this points to
@@ -741,6 +731,16 @@ struct MHD_Connection
#endif
/**
+ * Function used for reading HTTP request stream.
+ */
+ ReceiveCallback recv_cls;
+
+ /**
+ * Function used for writing HTTP response stream.
+ */
+ TransmitCallback send_cls;
+
+ /**
* Information about the current request we are processing
* on this connection.
*/
@@ -1894,4 +1894,38 @@ MHD_parse_arguments_ (struct MHD_Request *request,
+/**
+ * Error code similar to EGAIN or EINTR
+ */
+#define MHD_ERR_AGAIN_ (-3073)
+
+/**
+ * Connection was hard-closed by remote peer.
+ */
+#define MHD_ERR_CONNRESET_ (-3074)
+
+/**
+ * Connection is not connected anymore due to
+ * network error or any other reason.
+ */
+#define MHD_ERR_NOTCONN_ (-3075)
+
+/**
+ * "Not enough memory" error code
+ */
+#define MHD_ERR_NOMEM_ (-3076)
+
+/**
+ * "Bad FD" error code
+ */
+#define MHD_ERR_BADF_ (-3077)
+
+/**
+ * Error code similar to EINVAL
+ */
+#define MHD_ERR_INVAL_ (-3078)
+
+
+
+
#endif
diff --git a/src/lib/request_resume.c b/src/lib/request_resume.c
@@ -66,6 +66,7 @@ MHD_request_resume (struct MHD_Request *request)
/**
* Run through the suspended connections and move any that are no
* longer suspended back to the active state.
+ *
* @remark To be called only from thread that process
* daemon's select()/poll()/etc.
*
@@ -74,6 +75,7 @@ MHD_request_resume (struct MHD_Request *request)
*/
bool
MHD_resume_suspended_connections_ (struct MHD_Daemon *daemon)
+/* FIXME: rename connections -> requests? */
{
struct MHD_Connection *pos;
struct MHD_Connection *prev = NULL;