libmicrohttpd

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

commit 38e2c1faacaf061c5a56de537e64eb86bdb4928f
parent af6dd184d69b0d87751b6210c36c3f24370c389f
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Tue, 21 Nov 2023 17:26:27 +0300

Unified and simplified fd_set filling

Diffstat:
Msrc/microhttpd/daemon.c | 141+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
1 file changed, 81 insertions(+), 60 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c @@ -995,6 +995,7 @@ internal_get_fdset2 (struct MHD_Daemon *daemon, struct MHD_Connection *posn; enum MHD_Result result = MHD_YES; MHD_socket ls; + bool itc_added; #ifndef HAS_FD_SETSIZE_OVERRIDABLE (void) fd_setsize; /* Mute compiler warning */ @@ -1004,14 +1005,37 @@ internal_get_fdset2 (struct MHD_Daemon *daemon, if (daemon->shutdown) return MHD_YES; - ls = daemon->listen_fd; - if ( (MHD_INVALID_SOCKET != ls) && - (! daemon->was_quiesced) && - (! MHD_add_to_fd_set_ (ls, - read_fd_set, - max_fd, - fd_setsize)) ) - result = MHD_NO; + /* The order of FDs added is important for W32 sockets as W32 fd_set has + limits for number of added FDs instead of the limit for the higher + FD value. */ + + /* Add ITC FD first. The daemon must be able to respond on application + commands issued in other threads. */ + itc_added = false; + if (MHD_ITC_IS_VALID_ (daemon->itc)) + { + itc_added = MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc), + read_fd_set, + max_fd, + fd_setsize); + if (! itc_added) + result = MHD_NO; + } + + ls = daemon->was_quiesced ? MHD_INVALID_SOCKET : daemon->listen_fd; + if (! itc_added && + (MHD_INVALID_SOCKET != ls)) + { + /* Add listen FD if ITC was not added. Listen FD could be used to signal + the daemon shutdown. */ + if (MHD_add_to_fd_set_ (ls, + read_fd_set, + max_fd, + fd_setsize)) + ls = MHD_INVALID_SOCKET; /* Already added */ + else + result = MHD_NO; + } /* Add all sockets to 'except_fd_set' as well to watch for * out-of-band data. However, ignore errors if INFO_READ @@ -1082,6 +1106,7 @@ internal_get_fdset2 (struct MHD_Daemon *daemon, } #endif /* MHD_WINSOCK_SOCKETS */ #if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) + if (1) { struct MHD_UpgradeResponseHandle *urh; @@ -1098,6 +1123,21 @@ internal_get_fdset2 (struct MHD_Daemon *daemon, } } #endif + + if (MHD_INVALID_SOCKET != ls) + { + /* The listen socket is present and hasn't been added */ + if ((daemon->connections < daemon->connection_limit) && + ! daemon->at_limit) + { + if (! MHD_add_to_fd_set_ (ls, + read_fd_set, + max_fd, + fd_setsize)) + result = MHD_NO; + } + } + #if _MHD_DEBUG_CONNECT #ifdef HAVE_MESSAGES if (NULL != max_fd) @@ -4810,70 +4850,51 @@ MHD_select (struct MHD_Daemon *daemon, } else { + bool itc_added; /* accept only, have one thread per connection */ - if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) && - (! daemon->was_quiesced) && - (! MHD_add_to_fd_set_ (ls, - &rs, - &maxsock, - (int) FD_SETSIZE)) ) + itc_added = false; + if (MHD_ITC_IS_VALID_ (daemon->itc)) { + itc_added = MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc), + &rs, + &maxsock, + (int) FD_SETSIZE); + if (! itc_added) + { #ifdef HAVE_MESSAGES - MHD_DLOG (daemon, - _ ("Could not add listen socket to fdset.\n")); + MHD_DLOG (daemon, _ ("Could not add control inter-thread " \ + "communication channel FD to fdset.\n")); #endif - return MHD_NO; + err_state = MHD_YES; + } } - } - if ( (MHD_ITC_IS_VALID_ (daemon->itc)) && - (! MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc), - &rs, - &maxsock, - (int) FD_SETSIZE)) ) - { - bool retry_succeed; - - retry_succeed = false; -#if defined(MHD_WINSOCK_SOCKETS) - /* fdset limit reached, new connections - cannot be handled. Remove listen socket FD - from fdset and retry to add ITC FD. */ if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) && (! daemon->was_quiesced) ) { - FD_CLR (ls, - &rs); - if (MHD_add_to_fd_set_ (MHD_itc_r_fd_ (daemon->itc), - &rs, - &maxsock, - (int) FD_SETSIZE)) - retry_succeed = true; - } -#endif /* MHD_WINSOCK_SOCKETS */ - - if (! retry_succeed) - { + /* Stop listening if we are at the configured connection limit */ + /* If we're at the connection limit, no point in really + accepting new connections; however, make sure we do not miss + the shutdown OR the termination of an existing connection; so + only do this optimisation if we have a signaling ITC in + place. */ + if (! itc_added || + ((daemon->connections < daemon->connection_limit) && + ! daemon->at_limit)) + { + if (! MHD_add_to_fd_set_ (ls, + &rs, + &maxsock, + (int) FD_SETSIZE)) + { #ifdef HAVE_MESSAGES - MHD_DLOG (daemon, _ ("Could not add control inter-thread " \ - "communication channel FD to fdset.\n")); + MHD_DLOG (daemon, + _ ("Could not add listen socket to fdset.\n")); #endif - err_state = MHD_YES; + err_state = MHD_YES; + } + } } } - /* Stop listening if we are at the configured connection limit */ - /* If we're at the connection limit, no point in really - accepting new connections; however, make sure we do not miss - the shutdown OR the termination of an existing connection; so - only do this optimization if we have a signaling ITC in - place. */ - if ( (MHD_INVALID_SOCKET != (ls = daemon->listen_fd)) && - (MHD_ITC_IS_VALID_ (daemon->itc)) && - ( (daemon->connections == daemon->connection_limit) || - (daemon->at_limit) ) ) - { - FD_CLR (ls, - &rs); - } if (MHD_NO != err_state) millisec = 0;