|
|
@@ -430,109 +430,6 @@ MHD_ip_limit_del (struct MHD_Daemon *daemon,
|
|
|
|
|
|
|
|
|
#ifdef HTTPS_SUPPORT
|
|
|
-/**
|
|
|
- * 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 number of bytes actually received
|
|
|
- */
|
|
|
-static ssize_t
|
|
|
-recv_tls_adapter (struct MHD_Connection *connection,
|
|
|
- void *other,
|
|
|
- size_t i)
|
|
|
-{
|
|
|
- ssize_t res;
|
|
|
-
|
|
|
- if (i > SSIZE_MAX)
|
|
|
- i = SSIZE_MAX;
|
|
|
-
|
|
|
- res = gnutls_record_recv (connection->tls_session,
|
|
|
- other,
|
|
|
- i);
|
|
|
- if ( (GNUTLS_E_AGAIN == res) ||
|
|
|
- (GNUTLS_E_INTERRUPTED == res) )
|
|
|
- {
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_EINTR_);
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- if (GNUTLS_E_AGAIN == res)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
|
|
-#endif
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (res < 0)
|
|
|
- {
|
|
|
- /* Likely 'GNUTLS_E_INVALID_SESSION' (client communication
|
|
|
- disrupted); set errno to something caller will interpret
|
|
|
- correctly as a hard error */
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_);
|
|
|
- connection->tls_read_ready = false;
|
|
|
- return res;
|
|
|
- }
|
|
|
-
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- /* If data not available to fill whole buffer - socket is not read ready anymore. */
|
|
|
- if (i > (size_t)res)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
|
|
-#endif /* EPOLL_SUPPORT */
|
|
|
-
|
|
|
- /* Check whether TLS buffers still have some unread data. */
|
|
|
- connection->tls_read_ready = ( ((size_t)res == i) &&
|
|
|
- (0 != gnutls_record_check_pending (connection->tls_session)) );
|
|
|
- return res;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/**
|
|
|
- * 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 actual number of bytes written
|
|
|
- */
|
|
|
-static ssize_t
|
|
|
-send_tls_adapter (struct MHD_Connection *connection,
|
|
|
- const void *other,
|
|
|
- size_t i)
|
|
|
-{
|
|
|
- ssize_t res;
|
|
|
-
|
|
|
- if (i > SSIZE_MAX)
|
|
|
- i = SSIZE_MAX;
|
|
|
-
|
|
|
- res = gnutls_record_send (connection->tls_session,
|
|
|
- other,
|
|
|
- i);
|
|
|
- if ( (GNUTLS_E_AGAIN == res) ||
|
|
|
- (GNUTLS_E_INTERRUPTED == res) )
|
|
|
- {
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_EINTR_);
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- if (GNUTLS_E_AGAIN == res)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
|
|
-#endif
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (res < 0)
|
|
|
- {
|
|
|
- /* some other GNUTLS error, should set 'errno'; as we do not
|
|
|
- really understand the error (not listed in GnuTLS
|
|
|
- documentation explicitly), we set 'errno' to something that
|
|
|
- will cause the connection to fail. */
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_);
|
|
|
- return -1;
|
|
|
- }
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- /* If NOT all available data was sent - socket is not write ready anymore. */
|
|
|
- if (i > (size_t)res)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
|
|
-#endif /* EPOLL_SUPPORT */
|
|
|
- return res;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* Read and setup our certificate and key.
|
|
|
*
|
|
|
@@ -2139,168 +2036,6 @@ 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 number of bytes actually received
|
|
|
- */
|
|
|
-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_CONNECTION_CLOSED == connection->state) )
|
|
|
- {
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_ENOTCONN_);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (i > MHD_SCKT_SEND_MAX_SIZE_)
|
|
|
- i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
|
|
|
-
|
|
|
- ret = MHD_recv_ (connection->socket_fd,
|
|
|
- other,
|
|
|
- i);
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- if (0 > ret)
|
|
|
- {
|
|
|
- /* Got EAGAIN --- no longer read-ready */
|
|
|
- if (MHD_SCKT_ERR_IS_EAGAIN_ (MHD_socket_get_error_ ()))
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
|
|
- }
|
|
|
- else if (i > (size_t)ret)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY;
|
|
|
-#endif
|
|
|
- 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 actual number of bytes written
|
|
|
- */
|
|
|
-static ssize_t
|
|
|
-send_param_adapter (struct MHD_Connection *connection,
|
|
|
- const void *other,
|
|
|
- size_t i)
|
|
|
-{
|
|
|
- ssize_t ret;
|
|
|
- int err;
|
|
|
-
|
|
|
- if ( (MHD_INVALID_SOCKET == connection->socket_fd) ||
|
|
|
- (MHD_CONNECTION_CLOSED == connection->state) )
|
|
|
- {
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_ENOTCONN_);
|
|
|
- return -1;
|
|
|
- }
|
|
|
- if (i > MHD_SCKT_SEND_MAX_SIZE_)
|
|
|
- i = MHD_SCKT_SEND_MAX_SIZE_; /* return value limit */
|
|
|
-
|
|
|
-#if LINUX
|
|
|
- if ( (connection->write_buffer_append_offset ==
|
|
|
- connection->write_buffer_send_offset) &&
|
|
|
- (NULL != connection->response) &&
|
|
|
- (MHD_resp_sender_sendfile == connection->resp_sender) )
|
|
|
- {
|
|
|
- /* can use sendfile */
|
|
|
- int file_fd = connection->response->fd;
|
|
|
- uint64_t left;
|
|
|
- uint64_t offsetu64;
|
|
|
-#ifndef HAVE_SENDFILE64
|
|
|
- off_t offset;
|
|
|
-#else /* HAVE_SENDFILE64 */
|
|
|
- off64_t offset;
|
|
|
-#endif /* HAVE_SENDFILE64 */
|
|
|
- offsetu64 = connection->response_write_position + connection->response->fd_off;
|
|
|
- left = connection->response->total_size - connection->response_write_position;
|
|
|
- ret = 0;
|
|
|
-#ifndef HAVE_SENDFILE64
|
|
|
- if ((uint64_t)OFF_T_MAX < offsetu64)
|
|
|
- MHD_socket_set_error_to_ENOMEM ();
|
|
|
- else
|
|
|
- {
|
|
|
- offset = (off_t) offsetu64;
|
|
|
- ret = sendfile (connection->socket_fd,
|
|
|
- file_fd,
|
|
|
- &offset,
|
|
|
- left);
|
|
|
- }
|
|
|
-#else /* HAVE_SENDFILE64 */
|
|
|
- if ((uint64_t)OFF64_T_MAX < offsetu64)
|
|
|
- MHD_socket_set_error_to_ENOMEM ();
|
|
|
- else
|
|
|
- {
|
|
|
- offset = (off64_t) offsetu64;
|
|
|
- ret = sendfile64 (connection->socket_fd,
|
|
|
- file_fd,
|
|
|
- &offset,
|
|
|
- left);
|
|
|
- }
|
|
|
-#endif /* HAVE_SENDFILE64 */
|
|
|
- if (0 < ret)
|
|
|
- {
|
|
|
- /* write successful */
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- if (left > (uint64_t)ret)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
|
|
-#endif /* EPOLL_SUPPORT */
|
|
|
- return ret;
|
|
|
- }
|
|
|
- err = MHD_socket_get_error_();
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- if ( (0 > ret) && (MHD_SCKT_ERR_IS_EAGAIN_(err)) )
|
|
|
- {
|
|
|
- /* EAGAIN --- no longer write-ready */
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
|
|
- }
|
|
|
-#endif
|
|
|
- if (MHD_SCKT_ERR_IS_EINTR_ (err) ||
|
|
|
- MHD_SCKT_ERR_IS_EAGAIN_ (err))
|
|
|
- return 0;
|
|
|
- if (MHD_SCKT_ERR_IS_(err,
|
|
|
- MHD_SCKT_EBADF_))
|
|
|
- return -1;
|
|
|
- /* sendfile() failed with EINVAL if mmap()-like operations are not
|
|
|
- supported for FD or other 'unusual' errors occurred, so we should try
|
|
|
- to fall back to 'SEND'; see also this thread for info on
|
|
|
- odd libc/Linux behavior with sendfile:
|
|
|
- http://lists.gnu.org/archive/html/libmicrohttpd/2011-02/msg00015.html */
|
|
|
- connection->resp_sender = MHD_resp_sender_std;
|
|
|
- }
|
|
|
-#endif
|
|
|
- ret = MHD_send_ (connection->socket_fd,
|
|
|
- other,
|
|
|
- i);
|
|
|
- err = MHD_socket_get_error_();
|
|
|
-#ifdef EPOLL_SUPPORT
|
|
|
- if (0 > ret)
|
|
|
- {
|
|
|
- /* EAGAIN --- no longer write-ready */
|
|
|
- if (MHD_SCKT_ERR_IS_EAGAIN_(err))
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
|
|
- }
|
|
|
- else if (i > (size_t)ret)
|
|
|
- connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY;
|
|
|
-#endif
|
|
|
- /* Handle broken kernel / libc, returning -1 but not setting errno;
|
|
|
- kill connection as that should be safe; reported on mailinglist here:
|
|
|
- http://lists.gnu.org/archive/html/libmicrohttpd/2014-10/msg00023.html */
|
|
|
- if ( (0 > ret) &&
|
|
|
- (0 == err) )
|
|
|
- MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* Free resources associated with all closed connections.
|
|
|
* (destroy responses, free buffers, etc.). All closed
|
|
|
@@ -2523,14 +2258,10 @@ internal_add_connection (struct MHD_Daemon *daemon,
|
|
|
{
|
|
|
/* set default connection handlers */
|
|
|
MHD_set_http_callbacks_ (connection);
|
|
|
- connection->recv_cls = &recv_param_adapter;
|
|
|
- connection->send_cls = &send_param_adapter;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
#ifdef HTTPS_SUPPORT
|
|
|
- connection->recv_cls = &recv_tls_adapter;
|
|
|
- connection->send_cls = &send_tls_adapter;
|
|
|
connection->state = MHD_TLS_CONNECTION_INIT;
|
|
|
MHD_set_https_callbacks (connection);
|
|
|
gnutls_init (&connection->tls_session,
|