diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-08-28 09:05:57 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-08-28 09:05:57 +0000 |
commit | 642fef8a5b2a4913bd8a97faea0fd227652c9f31 (patch) | |
tree | 4e5aa7632c9b9ae6364b6ef950a3aae73d414376 | |
parent | fd7feaf9161ae725d3dab83794b60d56d02be735 (diff) |
-fix misc issues with upgrade introduction
-rw-r--r-- | src/microhttpd/connection.c | 2 | ||||
-rw-r--r-- | src/microhttpd/daemon.c | 99 | ||||
-rw-r--r-- | src/microhttpd/internal.h | 31 | ||||
-rw-r--r-- | src/microhttpd/response.c | 42 |
4 files changed, 133 insertions, 41 deletions
diff --git a/src/microhttpd/connection.c b/src/microhttpd/connection.c index 739f3c0f..d5ae884b 100644 --- a/src/microhttpd/connection.c +++ b/src/microhttpd/connection.c @@ -1,6 +1,6 @@ /* This file is part of libmicrohttpd - Copyright (C) 2007-2015 Daniel Pittman and Christian Grothoff + Copyright (C) 2007-2016 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 diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 3afeda69..79e8ab70 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c @@ -654,14 +654,15 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, unsigned int fd_setsize) { struct MHD_Connection *pos; + struct MHD_UpgradeResponseHandle *urh; int result = MHD_YES; - if ( (NULL == daemon) - || (NULL == read_fd_set) - || (NULL == write_fd_set) - || (MHD_YES == daemon->shutdown) - || (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) - || (0 != (daemon->options & MHD_USE_POLL))) + if ( (NULL == daemon) || + (NULL == read_fd_set) || + (NULL == write_fd_set) || + (MHD_YES == daemon->shutdown) || + (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || + (0 != (daemon->options & MHD_USE_POLL))) return MHD_NO; #ifdef EPOLL_SUPPORT if (0 != (daemon->options & MHD_USE_EPOLL)) @@ -669,11 +670,17 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, /* we're in epoll mode, use the epoll FD as a stand-in for the entire event set */ - return MHD_add_to_fd_set_ (daemon->epoll_fd, read_fd_set, max_fd, fd_setsize) ? MHD_YES : MHD_NO; + return MHD_add_to_fd_set_ (daemon->epoll_fd, + read_fd_set, + max_fd, + fd_setsize) ? MHD_YES : MHD_NO; } #endif - if (MHD_INVALID_SOCKET != daemon->socket_fd && - !MHD_add_to_fd_set_ (daemon->socket_fd, read_fd_set, max_fd, fd_setsize)) + if ( (MHD_INVALID_SOCKET != daemon->socket_fd) && + (! MHD_add_to_fd_set_ (daemon->socket_fd, + read_fd_set, + max_fd, + fd_setsize)) ) result = MHD_NO; for (pos = daemon->connections_head; NULL != pos; pos = pos->next) @@ -681,19 +688,31 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, switch (pos->event_loop_info) { case MHD_EVENT_LOOP_INFO_READ: - if (!MHD_add_to_fd_set_ (pos->socket_fd, read_fd_set, max_fd, fd_setsize)) + if (! MHD_add_to_fd_set_ (pos->socket_fd, + read_fd_set, + max_fd, + fd_setsize)) result = MHD_NO; break; case MHD_EVENT_LOOP_INFO_WRITE: - if (!MHD_add_to_fd_set_ (pos->socket_fd, write_fd_set, max_fd, fd_setsize)) + if (! MHD_add_to_fd_set_ (pos->socket_fd, + write_fd_set, + max_fd, + fd_setsize)) result = MHD_NO; - if (pos->read_buffer_size > pos->read_buffer_offset && - !MHD_add_to_fd_set_ (pos->socket_fd, read_fd_set, max_fd, fd_setsize)) + if ( (pos->read_buffer_size > pos->read_buffer_offset) && + ! MHD_add_to_fd_set_ (pos->socket_fd, + read_fd_set, + max_fd, + fd_setsize)) result = MHD_NO; break; case MHD_EVENT_LOOP_INFO_BLOCK: - if (pos->read_buffer_size > pos->read_buffer_offset && - !MHD_add_to_fd_set_ (pos->socket_fd, read_fd_set, max_fd, fd_setsize)) + if ( (pos->read_buffer_size > pos->read_buffer_offset) && + ! MHD_add_to_fd_set_ (pos->socket_fd, + read_fd_set, + max_fd, + fd_setsize)) result = MHD_NO; break; case MHD_EVENT_LOOP_INFO_CLEANUP: @@ -701,6 +720,33 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, break; } } + for (urh = daemon->urh_head; NULL != urh; urh = urh->next) + { + if ( (0 == (MHD_EPOLL_STATE_READ_READY & urh->celi_mhd)) && + (! MHD_add_to_fd_set_ (urh->mhd_socket, + read_fd_set, + max_fd, + fd_setsize)) ) + result = MHD_NO; + if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_mhd)) && + (! MHD_add_to_fd_set_ (urh->mhd_socket, + write_fd_set, + max_fd, + fd_setsize)) ) + result = MHD_NO; + if ( (0 != (MHD_EPOLL_STATE_READ_READY & urh->celi_client)) && + (! MHD_add_to_fd_set_ (urh->connection->socket_fd, + read_fd_set, + max_fd, + fd_setsize)) ) + result = MHD_NO; + if ( (0 != (MHD_EPOLL_STATE_WRITE_READY & urh->celi_client)) && + (! MHD_add_to_fd_set_ (urh->connection->socket_fd, + write_fd_set, + max_fd, + fd_setsize)) ) + result = MHD_NO; + } #if DEBUG_CONNECT #ifdef HAVE_MESSAGES if (NULL != max_fd) @@ -714,9 +760,8 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon, /** - * Call the handlers for a connection in the - * appropriate order based on the readiness as - * detected by the event loop. + * Call the handlers for a connection in the appropriate order based + * on the readiness as detected by the event loop. * * @param con connection to handle * @param read_ready set if the socket is ready for reading @@ -1239,7 +1284,7 @@ internal_add_connection (struct MHD_Daemon *daemon, return MHD_NO; } - if ( (!MHD_SCKT_FD_FITS_FDSET_(client_socket, NULL)) && + if ( (! MHD_SCKT_FD_FITS_FDSET_(client_socket, NULL)) && (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) ) { #ifdef HAVE_MESSAGES @@ -1791,7 +1836,7 @@ MHD_add_connection (struct MHD_Daemon *daemon, already set in MHD_USE_EPOLL_TURBO mode */ if (0 != (daemon->options & MHD_USE_EPOLL_TURBO)) { - if (!MHD_socket_nonblocking_ (client_socket)) + if (! MHD_socket_nonblocking_ (client_socket)) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -1799,7 +1844,7 @@ MHD_add_connection (struct MHD_Daemon *daemon, MHD_socket_last_strerr_()); #endif } - if (!MHD_socket_noninheritable_ (client_socket)) + if (! MHD_socket_noninheritable_ (client_socket)) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -1858,7 +1903,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) if (MHD_SCKT_ERR_IS_DISCNN_BEFORE_ACCEPT_(err)) return MHD_NO; /* do not print error if client just disconnected early */ #ifdef HAVE_MESSAGES - if ( !MHD_SCKT_ERR_IS_EAGAIN_ (err) ) + if (! MHD_SCKT_ERR_IS_EAGAIN_ (err) ) MHD_DLOG (daemon, "Error accepting connection: %s\n", MHD_socket_strerr_(err)); @@ -1895,7 +1940,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) return MHD_NO; } #if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK) - if (!MHD_socket_nonblocking_ (s)) + if (! MHD_socket_nonblocking_ (s)) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -1905,7 +1950,7 @@ MHD_accept_connection (struct MHD_Daemon *daemon) } #endif /* !USE_ACCEPT4 || !HAVE_SOCK_NONBLOCK */ #if !defined(USE_ACCEPT4) || !defined(SOCK_CLOEXEC) - if (!MHD_socket_noninheritable_ (s)) + if (! MHD_socket_noninheritable_ (s)) { #ifdef HAVE_MESSAGES MHD_DLOG (daemon, @@ -1920,8 +1965,10 @@ MHD_accept_connection (struct MHD_Daemon *daemon) s); #endif #endif - (void) internal_add_connection (daemon, s, - addr, addrlen, + (void) internal_add_connection (daemon, + s, + addr, + addrlen, MHD_NO); return MHD_YES; } diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h index c1524330..047300b1 100644 --- a/src/microhttpd/internal.h +++ b/src/microhttpd/internal.h @@ -147,22 +147,22 @@ enum MHD_ConnectionEventLoopInfo /** * We are waiting to be able to read. */ - MHD_EVENT_LOOP_INFO_READ = 1, + MHD_EVENT_LOOP_INFO_READ = 0, /** * We are waiting to be able to write. */ - MHD_EVENT_LOOP_INFO_WRITE = 2, + MHD_EVENT_LOOP_INFO_WRITE = 1, /** * We are waiting for the application to provide data. */ - MHD_EVENT_LOOP_INFO_BLOCK = 4, + MHD_EVENT_LOOP_INFO_BLOCK = 2, /** * We are finished and are awaiting cleanup. */ - MHD_EVENT_LOOP_INFO_CLEANUP = 8 + MHD_EVENT_LOOP_INFO_CLEANUP = 3 }; @@ -918,11 +918,6 @@ struct MHD_UpgradeResponseHandle MHD_socket app_socket; /** - * IO-state of the @e app_socket. - */ - enum MHD_ConnectionEventLoopInfo celi_app; - - /** * If @a app_sock was a socketpair, our end of it, otherwise * #MHD_INVALID_SOCKET; (r/w). */ @@ -931,7 +926,13 @@ struct MHD_UpgradeResponseHandle /** * IO-state of the @e mhd_socket. */ - enum MHD_ConnectionEventLoopInfo celi_mhd; + enum MHD_EpollState celi_mhd; + + /** + * IO-state of the @e connection's socket. + */ + enum MHD_EpollState celi_client; + }; @@ -1027,6 +1028,16 @@ struct MHD_Daemon #endif /** + * Head of DLL of upgrade response handles we are processing. + */ + struct MHD_UpgradeResponseHandle *urh_head; + + /** + * Tail of DLL of upgrade response handles we are processing. + */ + struct MHD_UpgradeResponseHandle *urh_tail; + + /** * Head of the XDLL of ALL connections with a default ('normal') * timeout, sorted by timeout (earliest at the tail, most recently * used connection at the head). MHD can just look at the tail of diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c index e7049a5a..93803813 100644 --- a/src/microhttpd/response.c +++ b/src/microhttpd/response.c @@ -597,10 +597,20 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh, enum MHD_UpgradeAction action, ...) { + struct MHD_Daemon *daemon = urh->connection->daemon; + switch (action) { case MHD_UPGRADE_ACTION_CLOSE: /* Application is done with this connection, tear it down! */ + if (0 != (daemon->options & MHD_USE_SSL) ) + { + DLL_remove (daemon->urh_head, + daemon->urh_tail, + urh); + /* FIXME: if running in epoll()-mode, do we have + to remove any of the FDs from any epoll-sets here? */ + } if ( (MHD_INVALID_SOCKET != urh->app_socket) && (0 != MHD_socket_close_ (urh->app_socket)) ) MHD_PANIC ("close failed\n"); @@ -636,6 +646,7 @@ int MHD_response_execute_upgrade_ (struct MHD_Response *response, struct MHD_Connection *connection) { + struct MHD_Daemon *daemon = connection->daemon; struct MHD_UpgradeResponseHandle *urh; int sv[2]; size_t rbo; @@ -645,7 +656,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response, MHD_HTTP_HEADER_UPGRADE)) { #ifdef HAVE_MESSAGES - MHD_DLOG (connection->daemon, + MHD_DLOG (daemon, "Invalid response for upgrade: application failed to set the 'Upgrade' header!\n"); #endif return MHD_NO; @@ -655,7 +666,7 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response, if (NULL == urh) return MHD_NO; #if HTTPS_SUPPORT - if (0 != (connection->daemon->options & MHD_USE_SSL) ) + if (0 != (daemon->options & MHD_USE_SSL) ) { /* FIXME: this is non-portable for now; W32 port pending... */ if (0 != socketpair (AF_UNIX, @@ -666,6 +677,23 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response, free (urh); return MHD_NO; } + if ( (! MHD_SCKT_FD_FITS_FDSET_(sv[1], NULL)) && + (0 == (daemon->options & (MHD_USE_POLL | MHD_USE_EPOLL))) ) + { +#ifdef HAVE_MESSAGES + MHD_DLOG (daemon, + "Socketpair descriptor larger than FD_SETSIZE: %d > %d\n", + (int) sv[1], + (int) FD_SETSIZE); +#endif + if (0 != MHD_socket_close_ (sv[0])) + MHD_PANIC ("close failed\n"); + if (0 != MHD_socket_close_ (sv[1])) + MHD_PANIC ("close failed\n"); + free (urh); + return MHD_NO; + } + urh->app_socket = sv[0]; urh->mhd_socket = sv[1]; urh->connection = connection; @@ -682,8 +710,14 @@ MHD_response_execute_upgrade_ (struct MHD_Response *response, suspended; it will be resumed once we are done in the #MHD_upgrade_action() function */ MHD_suspend_connection (connection); - /* FIXME: also need to start some processing logic in _all_ MHD - event loops for the sv traffic! (NOT IMPLEMENTED!!!) */ + urh->celi_mhd = MHD_EPOLL_STATE_UNREADY; + urh->celi_client = MHD_EPOLL_STATE_UNREADY; + /* FIXME: is it possible we did not fully drain the client + socket yet and are thus read-ready already? This may + matter if we are in epoll() edge triggered mode... */ + DLL_insert (connection->daemon->urh_head, + connection->daemon->urh_tail, + urh); return MHD_YES; } #endif |