libmicrohttpd

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

commit a2f8683def34643b64a3c1afd00900fbe99f6d0f
parent e101aeb4a9e18d506bd93afc87ea55183128f2cd
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri, 16 Feb 2018 07:24:27 +0100

implement recv/send adapters

Diffstat:
Msrc/lib/connection_add.c | 116++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/lib/daemon_close_all_connections.c | 2+-
Msrc/lib/internal.h | 54++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/lib/request_resume.c | 2++
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;