aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c249
1 files changed, 139 insertions, 110 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 0c2c4d3c..1c86057f 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -64,10 +64,6 @@
64#include <process.h> 64#include <process.h>
65#endif 65#endif
66 66
67#if HAVE_ACCEPT4+0 != 0 && (defined(HAVE_SOCK_NONBLOCK) || (SOCK_CLOEXEC+0 != 0))
68#define USE_ACCEPT4 1
69#endif
70
71/** 67/**
72 * Default connection limit. 68 * Default connection limit.
73 */ 69 */
@@ -115,6 +111,10 @@
115#define EPOLL_CLOEXEC 0 111#define EPOLL_CLOEXEC 0
116#endif 112#endif
117 113
114#if HAVE_ACCEPT4+0 != 0 && (defined(HAVE_SOCK_NONBLOCK) || (SOCK_CLOEXEC+0 != 0))
115#define USE_ACCEPT4 1
116#endif
117
118 118
119/** 119/**
120 * Default implementation of the panic function, 120 * Default implementation of the panic function,
@@ -157,6 +157,50 @@ void *mhd_panic_cls;
157static int mhd_winsock_inited_ = 0; 157static int mhd_winsock_inited_ = 0;
158#endif 158#endif
159 159
160
161/**
162 * Change socket options to be non-blocking.
163 *
164 * @param daemon daemon context
165 * @param sock socket to manipulate
166 * @return #MHD_YES if succeeded, #MHD_NO otherwise
167 */
168static int
169make_nonblocking (struct MHD_Daemon *daemon,
170 MHD_socket sock)
171{
172#ifdef MHD_WINSOCK_SOCKETS
173 unsigned long flags = 1;
174
175 if (0 != ioctlsocket (sock, FIONBIO, &flags))
176 {
177 #ifdef HAVE_MESSAGES
178 MHD_DLOG (daemon,
179 "Failed to make socket non-blocking: %s\n",
180 MHD_socket_last_strerr_ ());
181 #endif
182 return MHD_NO;
183 }
184#else /* MHD_POSIX_SOCKETS */
185 int flags;
186
187 flags = fcntl (sock, F_GETFD);
188 if ( ( (-1 == flags) ||
189 ( (flags != (flags | O_NONBLOCK)) &&
190 (0 != fcntl (sock, F_SETFD, flags | O_NONBLOCK)) ) ) )
191 {
192#ifdef HAVE_MESSAGES
193 MHD_DLOG (daemon,
194 "Failed to make socket non-blocking: %s\n",
195 MHD_socket_last_strerr_ ());
196#endif
197 return MHD_NO;
198 }
199#endif /* MHD_POSIX_SOCKETS */
200 return MHD_YES;
201}
202
203
160/** 204/**
161 * Trace up to and return master daemon. If the supplied daemon 205 * Trace up to and return master daemon. If the supplied daemon
162 * is a master, then return the daemon itself. 206 * is a master, then return the daemon itself.
@@ -1462,30 +1506,7 @@ internal_add_connection (struct MHD_Daemon *daemon,
1462 { 1506 {
1463 /* in turbo mode, we assume that non-blocking was already set 1507 /* in turbo mode, we assume that non-blocking was already set
1464 by 'accept4' or whoever calls 'MHD_add_connection' */ 1508 by 'accept4' or whoever calls 'MHD_add_connection' */
1465 1509 make_nonblocking (daemon, connection->socket_fd);
1466 /* make socket non-blocking */
1467#if !defined(MHD_WINSOCK_SOCKETS)
1468 int flags = fcntl (connection->socket_fd, F_GETFL);
1469 if ( (-1 == flags) ||
1470 (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) )
1471 {
1472#ifdef HAVE_MESSAGES
1473 MHD_DLOG (daemon,
1474 "Failed to make socket non-blocking: %s\n",
1475 MHD_socket_last_strerr_ ());
1476#endif
1477 }
1478#else
1479 unsigned long flags = 1;
1480 if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags))
1481 {
1482#ifdef HAVE_MESSAGES
1483 MHD_DLOG (daemon,
1484 "Failed to make socket non-blocking: %s\n",
1485 MHD_socket_last_strerr_ ());
1486#endif
1487 }
1488#endif
1489 } 1510 }
1490 1511
1491#if HTTPS_SUPPORT 1512#if HTTPS_SUPPORT
@@ -1833,34 +1854,59 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
1833 1854
1834 1855
1835/** 1856/**
1836 * Change socket options to be non-blocking, non-inheritable. 1857 * Change socket options to be non-inheritable.
1837 * 1858 *
1838 * @param daemon daemon context 1859 * @param daemon daemon context
1839 * @param sock socket to manipulate 1860 * @param sock socket to manipulate
1861 * @return #MHD_YES if succeeded, #MHD_NO otherwise
1840 */ 1862 */
1841static void 1863static int
1842make_nonblocking_noninheritable (struct MHD_Daemon *daemon, 1864make_noninheritable (struct MHD_Daemon *daemon,
1843 MHD_socket sock) 1865 MHD_socket sock)
1844{ 1866{
1845#ifdef MHD_WINSOCK_SOCKETS 1867#ifdef MHD_WINSOCK_SOCKETS
1846 unsigned long flags = 1; 1868 if (!SetHandleInformation ((HANDLE)sock, HANDLE_FLAG_INHERIT, 0))
1847
1848 if (0 != ioctlsocket (sock, FIONBIO, &flags))
1849 { 1869 {
1850#ifdef HAVE_MESSAGES 1870#ifdef HAVE_MESSAGES
1851 MHD_DLOG (daemon, 1871 MHD_DLOG (daemon,
1852 "Failed to make socket non-blocking: %s\n", 1872 "Failed to make socket non-inheritable: %u\n",
1853 MHD_socket_last_strerr_ ()); 1873 (unsigned int)GetLastError ());
1854#endif 1874#endif
1875 return MHD_NO;
1855 } 1876 }
1856 if (!SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) 1877#else /* MHD_POSIX_SOCKETS */
1878 int flags;
1879
1880 flags = fcntl (sock, F_GETFD);
1881 if ( ( (-1 == flags) ||
1882 ( (flags != (flags | FD_CLOEXEC)) &&
1883 (0 != fcntl (sock, F_SETFD, flags | FD_CLOEXEC)) ) ) )
1857 { 1884 {
1858#ifdef HAVE_MESSAGES 1885#ifdef HAVE_MESSAGES
1859 MHD_DLOG (daemon, 1886 MHD_DLOG (daemon,
1860 "Failed to make socket non-inheritable: %u\n", 1887 "Failed to make socket non-inheritable: %s\n",
1861 (unsigned int) GetLastError ()); 1888 MHD_socket_last_strerr_ ());
1862#endif 1889#endif
1890 return MHD_NO;
1863 } 1891 }
1892#endif /* MHD_POSIX_SOCKETS */
1893 return MHD_YES;
1894}
1895
1896
1897/**
1898 * Change socket options to be non-blocking, non-inheritable.
1899 *
1900 * @param daemon daemon context
1901 * @param sock socket to manipulate
1902 */
1903static void
1904make_nonblocking_noninheritable (struct MHD_Daemon *daemon,
1905 MHD_socket sock)
1906{
1907#ifdef MHD_WINSOCK_SOCKETS
1908 (void)make_nonblocking (daemon, sock);
1909 (void)make_noninheritable (daemon, sock);
1864#else 1910#else
1865 int flags; 1911 int flags;
1866 1912
@@ -1914,8 +1960,11 @@ MHD_add_connection (struct MHD_Daemon *daemon,
1914 const struct sockaddr *addr, 1960 const struct sockaddr *addr,
1915 socklen_t addrlen) 1961 socklen_t addrlen)
1916{ 1962{
1917 make_nonblocking_noninheritable (daemon, 1963 /* internal_add_connection() assume that non-blocking is
1918 client_socket); 1964 already set in MHD_USE_EPOLL_TURBO mode */
1965 if (0 != (daemon->options & MHD_USE_EPOLL_TURBO))
1966 make_nonblocking_noninheritable (daemon,
1967 client_socket);
1919 return internal_add_connection (daemon, 1968 return internal_add_connection (daemon,
1920 client_socket, 1969 client_socket,
1921 addr, addrlen, 1970 addr, addrlen,
@@ -1985,8 +2034,12 @@ MHD_accept_connection (struct MHD_Daemon *daemon)
1985 } 2034 }
1986 return MHD_NO; 2035 return MHD_NO;
1987 } 2036 }
1988#if !defined(USE_ACCEPT4) || !defined(HAVE_SOCK_NONBLOCK) || SOCK_CLOEXEC+0 == 0 2037#if !defined(USE_ACCEPT4)
1989 make_nonblocking_noninheritable (daemon, s); 2038 make_nonblocking_noninheritable (daemon, s);
2039#elif !defined(HAVE_SOCK_NONBLOCK)
2040 make_nonblocking (daemon, s);
2041#elif SOCK_CLOEXEC+0 == 0
2042 make_noninheritable (daemon, s);
1990#endif 2043#endif
1991#ifdef HAVE_MESSAGES 2044#ifdef HAVE_MESSAGES
1992#if DEBUG_CONNECT 2045#if DEBUG_CONNECT
@@ -3519,24 +3572,33 @@ parse_options_va (struct MHD_Daemon *daemon,
3519 * @param protocol desired protocol, 0 for default 3572 * @param protocol desired protocol, 0 for default
3520 */ 3573 */
3521static MHD_socket 3574static MHD_socket
3522create_socket (struct MHD_Daemon *daemon, 3575create_listen_socket (struct MHD_Daemon *daemon,
3523 int domain, int type, int protocol) 3576 int domain, int type, int protocol)
3524{ 3577{
3525 int ctype = type | SOCK_CLOEXEC;
3526 MHD_socket fd; 3578 MHD_socket fd;
3579 int cloexec_set;
3527 3580
3528 /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo 3581 /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo
3529 * implementations do not set ai_socktype, e.g. RHL6.2. */ 3582 * implementations do not set ai_socktype, e.g. RHL6.2. */
3530 fd = socket (domain, ctype, protocol); 3583#if defined(MHD_POSIX_SOCKETS) && SOCK_CLOEXEC+0 != 0
3531 if ( (MHD_INVALID_SOCKET == fd) && (EINVAL == MHD_socket_errno_) && (0 != SOCK_CLOEXEC) ) 3584 fd = socket (domain, type | SOCK_CLOEXEC, protocol);
3532 { 3585 cloexec_set = MHD_YES;
3533 ctype = type; 3586#elif defined(MHD_WINSOCK_SOCKETS) && defined (WSA_FLAG_NO_HANDLE_INHERIT)
3534 fd = socket(domain, type, protocol); 3587 fd = WSASocketW (domain, type, protocol, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT);
3535 } 3588 cloexec_set = MHD_YES;
3589#else /* !SOCK_CLOEXEC */
3590 fd = socket (domain, type, protocol);
3591 cloexec_set = MHD_NO;
3592#endif /* !SOCK_CLOEXEC */
3593 if ( (MHD_INVALID_SOCKET == fd) && (MHD_NO != cloexec_set) )
3594 {
3595 fd = socket (domain, type, protocol);
3596 cloexec_set = MHD_NO;
3597 }
3536 if (MHD_INVALID_SOCKET == fd) 3598 if (MHD_INVALID_SOCKET == fd)
3537 return MHD_INVALID_SOCKET; 3599 return MHD_INVALID_SOCKET;
3538 if (type == ctype) 3600 if (MHD_NO == cloexec_set)
3539 make_nonblocking_noninheritable (daemon, fd); 3601 make_noninheritable (daemon, fd);
3540 return fd; 3602 return fd;
3541} 3603}
3542 3604
@@ -3568,23 +3630,10 @@ setup_epoll_to_listen (struct MHD_Daemon *daemon)
3568#endif 3630#endif
3569 return MHD_NO; 3631 return MHD_NO;
3570 } 3632 }
3571#ifndef HAVE_EPOLL_CREATE1 3633#if !defined(HAVE_EPOLL_CREATE1) || EPOLL_CLOEXEC+0 == 0
3572 else 3634 make_noninheritable (daemon,
3573 { 3635 daemon->epoll_fd);
3574 int fdflags = fcntl (daemon->epoll_fd, F_GETFD); 3636#endif /* !HAVE_EPOLL_CREATE1 || !EPOLL_CLOEXEC */
3575 if (0 > fdflags || 0 > fcntl (daemon->epoll_fd, F_SETFD, fdflags | FD_CLOEXEC))
3576 {
3577#ifdef HAVE_MESSAGES
3578 MHD_DLOG (daemon,
3579 "Failed to change flags on epoll fd: %s\n",
3580 MHD_socket_last_strerr_ ());
3581#endif /* HAVE_MESSAGES */
3582 }
3583 }
3584#endif /* !HAVE_EPOLL_CREATE1 */
3585 if (0 == EPOLL_CLOEXEC)
3586 make_nonblocking_noninheritable (daemon,
3587 daemon->epoll_fd);
3588 if (MHD_INVALID_SOCKET == daemon->socket_fd) 3637 if (MHD_INVALID_SOCKET == daemon->socket_fd)
3589 return MHD_YES; /* non-listening daemon */ 3638 return MHD_YES; /* non-listening daemon */
3590 event.events = EPOLLIN; 3639 event.events = EPOLLIN;
@@ -3870,10 +3919,10 @@ MHD_start_daemon_va (unsigned int flags,
3870 { 3919 {
3871 /* try to open listen socket */ 3920 /* try to open listen socket */
3872 if (0 != (flags & MHD_USE_IPv6)) 3921 if (0 != (flags & MHD_USE_IPv6))
3873 socket_fd = create_socket (daemon, 3922 socket_fd = create_listen_socket (daemon,
3874 PF_INET6, SOCK_STREAM, 0); 3923 PF_INET6, SOCK_STREAM, 0);
3875 else 3924 else
3876 socket_fd = create_socket (daemon, 3925 socket_fd = create_listen_socket (daemon,
3877 PF_INET, SOCK_STREAM, 0); 3926 PF_INET, SOCK_STREAM, 0);
3878 if (MHD_INVALID_SOCKET == socket_fd) 3927 if (MHD_INVALID_SOCKET == socket_fd)
3879 { 3928 {
@@ -4073,23 +4122,24 @@ MHD_start_daemon_va (unsigned int flags,
4073 } 4122 }
4074 } 4123 }
4075#endif 4124#endif
4076#if EPOLL_SUPPORT 4125 if (MHD_NO == make_nonblocking (daemon, socket_fd))
4077 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY)) 4126 {
4078 {
4079 int sk_flags = fcntl (socket_fd, F_GETFL);
4080 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
4081 {
4082#ifdef HAVE_MESSAGES 4127#ifdef HAVE_MESSAGES
4083 MHD_DLOG (daemon, 4128 MHD_DLOG (daemon,
4084 "Failed to make listen socket non-blocking: %s\n", 4129 "Failed to make listen socket non-blocking: %s\n",
4085 MHD_socket_last_strerr_ ()); 4130 MHD_socket_last_strerr_ ());
4086#endif 4131#endif /* HAVE_MESSAGES */
4087 if (0 != MHD_socket_close_ (socket_fd)) 4132 if (0 != (flags & MHD_USE_EPOLL_LINUX_ONLY) ||
4088 MHD_PANIC ("close failed\n"); 4133 daemon->worker_pool_size > 0)
4089 goto free_and_fail; 4134 {
4090 } 4135 /* Accept must be non-blocking. Multiple children may wake up
4091 } 4136 * to handle a new connection, but only one will win the race.
4092#endif 4137 * The others must immediately return. */
4138 if (0 != MHD_socket_close_ (socket_fd))
4139 MHD_PANIC ("close failed\n");
4140 goto free_and_fail;
4141 }
4142 }
4093 if (listen (socket_fd, daemon->listen_backlog_size) < 0) 4143 if (listen (socket_fd, daemon->listen_backlog_size) < 0)
4094 { 4144 {
4095#ifdef HAVE_MESSAGES 4145#ifdef HAVE_MESSAGES
@@ -4211,12 +4261,6 @@ MHD_start_daemon_va (unsigned int flags,
4211 if ( (daemon->worker_pool_size > 0) && 4261 if ( (daemon->worker_pool_size > 0) &&
4212 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) ) 4262 (0 == (daemon->options & MHD_USE_NO_LISTEN_SOCKET)) )
4213 { 4263 {
4214#if !defined(MHD_WINSOCK_SOCKETS)
4215 int sk_flags;
4216#else
4217 unsigned long sk_flags;
4218#endif
4219
4220 /* Coarse-grained count of connections per thread (note error 4264 /* Coarse-grained count of connections per thread (note error
4221 * due to integer division). Also keep track of how many 4265 * due to integer division). Also keep track of how many
4222 * connections are leftover after an equal split. */ 4266 * connections are leftover after an equal split. */
@@ -4227,21 +4271,6 @@ MHD_start_daemon_va (unsigned int flags,
4227 4271
4228 i = 0; /* we need this in case fcntl or malloc fails */ 4272 i = 0; /* we need this in case fcntl or malloc fails */
4229 4273
4230 /* Accept must be non-blocking. Multiple children may wake up
4231 * to handle a new connection, but only one will win the race.
4232 * The others must immediately return. */
4233#if !defined(MHD_WINSOCK_SOCKETS)
4234 sk_flags = fcntl (socket_fd, F_GETFL);
4235 if (sk_flags < 0)
4236 goto thread_failed;
4237 if (0 != fcntl (socket_fd, F_SETFL, sk_flags | O_NONBLOCK))
4238 goto thread_failed;
4239#else
4240 sk_flags = 1;
4241 if (SOCKET_ERROR == ioctlsocket (socket_fd, FIONBIO, &sk_flags))
4242 goto thread_failed;
4243#endif /* MHD_WINSOCK_SOCKETS */
4244
4245 /* Allocate memory for pooled objects */ 4274 /* Allocate memory for pooled objects */
4246 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon) 4275 daemon->worker_pool = malloc (sizeof (struct MHD_Daemon)
4247 * daemon->worker_pool_size); 4276 * daemon->worker_pool_size);