diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 148 |
1 files changed, 98 insertions, 50 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 1625078d..d111d9cd 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -809,7 +809,7 @@ recv_param_adapter (struct MHD_Connection *connection, | |||
809 | } | 809 | } |
810 | ret = RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); | 810 | ret = RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); |
811 | #if EPOLL_SUPPORT | 811 | #if EPOLL_SUPPORT |
812 | if (ret < i) | 812 | if (ret < (ssize_t) i) |
813 | { | 813 | { |
814 | /* partial read --- no longer read-ready */ | 814 | /* partial read --- no longer read-ready */ |
815 | connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; | 815 | connection->epoll_state &= ~MHD_EPOLL_STATE_READ_READY; |
@@ -884,7 +884,7 @@ send_param_adapter (struct MHD_Connection *connection, | |||
884 | #endif | 884 | #endif |
885 | ret = SEND (connection->socket_fd, other, i, MSG_NOSIGNAL); | 885 | ret = SEND (connection->socket_fd, other, i, MSG_NOSIGNAL); |
886 | #if EPOLL_SUPPORT | 886 | #if EPOLL_SUPPORT |
887 | if (ret < i) | 887 | if (ret < (ssize_t) i) |
888 | { | 888 | { |
889 | /* partial write --- no longer write-ready */ | 889 | /* partial write --- no longer write-ready */ |
890 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; | 890 | connection->epoll_state &= ~MHD_EPOLL_STATE_WRITE_READY; |
@@ -1121,37 +1121,43 @@ MHD_add_connection (struct MHD_Daemon *daemon, | |||
1121 | MHD_set_http_callbacks_ (connection); | 1121 | MHD_set_http_callbacks_ (connection); |
1122 | connection->recv_cls = &recv_param_adapter; | 1122 | connection->recv_cls = &recv_param_adapter; |
1123 | connection->send_cls = &send_param_adapter; | 1123 | connection->send_cls = &send_param_adapter; |
1124 | /* non-blocking sockets are required on most systems and for GNUtls; | 1124 | |
1125 | however, they somehow cause serious problems on CYGWIN (#1824) */ | 1125 | if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO)) |
1126 | { | ||
1127 | /* non-blocking sockets are required on most systems and for GNUtls; | ||
1128 | however, they somehow cause serious problems on CYGWIN (#1824); | ||
1129 | in turbo mode, we assume that non-blocking was already set | ||
1130 | by 'accept4' or whoever calls 'MHD_add_connection' */ | ||
1126 | #ifdef CYGWIN | 1131 | #ifdef CYGWIN |
1127 | if (0 != (daemon->options & MHD_USE_SSL)) | 1132 | if (0 != (daemon->options & MHD_USE_SSL)) |
1128 | #endif | 1133 | #endif |
1129 | { | 1134 | { |
1130 | /* make socket non-blocking */ | 1135 | /* make socket non-blocking */ |
1131 | #ifndef MINGW | 1136 | #ifndef MINGW |
1132 | int flags = fcntl (connection->socket_fd, F_GETFL); | 1137 | int flags = fcntl (connection->socket_fd, F_GETFL); |
1133 | if ( (-1 == flags) || | 1138 | if ( (-1 == flags) || |
1134 | (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) ) | 1139 | (0 != fcntl (connection->socket_fd, F_SETFL, flags | O_NONBLOCK)) ) |
1135 | { | 1140 | { |
1136 | #if HAVE_MESSAGES | 1141 | #if HAVE_MESSAGES |
1137 | MHD_DLOG (daemon, | 1142 | MHD_DLOG (daemon, |
1138 | "Failed to make socket %d non-blocking: %s\n", | 1143 | "Failed to make socket %d non-blocking: %s\n", |
1139 | connection->socket_fd, | 1144 | connection->socket_fd, |
1140 | STRERROR (errno)); | 1145 | STRERROR (errno)); |
1141 | #endif | 1146 | #endif |
1142 | } | 1147 | } |
1143 | #else | 1148 | #else |
1144 | unsigned long flags = 1; | 1149 | unsigned long flags = 1; |
1145 | if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags)) | 1150 | if (0 != ioctlsocket (connection->socket_fd, FIONBIO, &flags)) |
1146 | { | 1151 | { |
1147 | #if HAVE_MESSAGES | 1152 | #if HAVE_MESSAGES |
1148 | MHD_DLOG (daemon, | 1153 | MHD_DLOG (daemon, |
1149 | "Failed to make socket non-blocking: %s\n", | 1154 | "Failed to make socket non-blocking: %s\n", |
1150 | STRERROR (errno)); | 1155 | STRERROR (errno)); |
1151 | #endif | 1156 | #endif |
1152 | } | 1157 | } |
1153 | #endif | 1158 | #endif |
1154 | } | 1159 | } |
1160 | } | ||
1155 | 1161 | ||
1156 | #if HTTPS_SUPPORT | 1162 | #if HTTPS_SUPPORT |
1157 | if (0 != (daemon->options & MHD_USE_SSL)) | 1163 | if (0 != (daemon->options & MHD_USE_SSL)) |
@@ -1228,25 +1234,35 @@ MHD_add_connection (struct MHD_Daemon *daemon, | |||
1228 | #if EPOLL_SUPPORT | 1234 | #if EPOLL_SUPPORT |
1229 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) | 1235 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) |
1230 | { | 1236 | { |
1231 | struct epoll_event event; | 1237 | if (0 == (daemon->options & MHD_USE_EPOLL_TURBO)) |
1232 | |||
1233 | event.events = EPOLLIN | EPOLLOUT | EPOLLET; | ||
1234 | event.data.ptr = connection; | ||
1235 | if (0 != epoll_ctl (daemon->epoll_fd, | ||
1236 | EPOLL_CTL_ADD, | ||
1237 | client_socket, | ||
1238 | &event)) | ||
1239 | { | 1238 | { |
1239 | struct epoll_event event; | ||
1240 | |||
1241 | event.events = EPOLLIN | EPOLLOUT | EPOLLET; | ||
1242 | event.data.ptr = connection; | ||
1243 | if (0 != epoll_ctl (daemon->epoll_fd, | ||
1244 | EPOLL_CTL_ADD, | ||
1245 | client_socket, | ||
1246 | &event)) | ||
1247 | { | ||
1240 | #if HAVE_MESSAGES | 1248 | #if HAVE_MESSAGES |
1241 | if (0 != (daemon->options & MHD_USE_DEBUG)) | 1249 | if (0 != (daemon->options & MHD_USE_DEBUG)) |
1242 | MHD_DLOG (daemon, | 1250 | MHD_DLOG (daemon, |
1243 | "Call to epoll_ctl failed: %s\n", | 1251 | "Call to epoll_ctl failed: %s\n", |
1244 | STRERROR (errno)); | 1252 | STRERROR (errno)); |
1245 | #endif | 1253 | #endif |
1246 | goto cleanup; | 1254 | goto cleanup; |
1255 | } | ||
1256 | connection->epoll_state |= MHD_EPOLL_STATE_IN_EPOLL_SET; | ||
1257 | } | ||
1258 | else | ||
1259 | { | ||
1260 | connection->epoll_state |= MHD_EPOLL_STATE_READ_READY | MHD_EPOLL_STATE_WRITE_READY | ||
1261 | | MHD_EPOLL_STATE_IN_EREADY_EDLL; | ||
1262 | EDLL_insert (daemon->eready_head, | ||
1263 | daemon->eready_tail, | ||
1264 | connection); | ||
1247 | } | 1265 | } |
1248 | daemon->listen_socket_in_epoll = MHD_YES; | ||
1249 | |||
1250 | } | 1266 | } |
1251 | #endif | 1267 | #endif |
1252 | daemon->max_connections--; | 1268 | daemon->max_connections--; |
@@ -1300,13 +1316,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1300 | socklen_t addrlen; | 1316 | socklen_t addrlen; |
1301 | int s; | 1317 | int s; |
1302 | int fd; | 1318 | int fd; |
1319 | int nonblock; | ||
1303 | 1320 | ||
1304 | addrlen = sizeof (addrstorage); | 1321 | addrlen = sizeof (addrstorage); |
1305 | memset (addr, 0, sizeof (addrstorage)); | 1322 | memset (addr, 0, sizeof (addrstorage)); |
1306 | if (-1 == (fd = daemon->socket_fd)) | 1323 | if (-1 == (fd = daemon->socket_fd)) |
1307 | return MHD_NO; | 1324 | return MHD_NO; |
1325 | nonblock = SOCK_NONBLOCK; | ||
1326 | #ifdef CYGWIN | ||
1327 | if (0 == (daemon->options & MHD_USE_SSL)) | ||
1328 | nonblock = 0; | ||
1329 | #endif | ||
1308 | #if HAVE_ACCEPT4 | 1330 | #if HAVE_ACCEPT4 |
1309 | s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC); | 1331 | s = accept4 (fd, addr, &addrlen, SOCK_CLOEXEC | nonblock); |
1310 | #else | 1332 | #else |
1311 | s = ACCEPT (fd, addr, &addrlen); | 1333 | s = ACCEPT (fd, addr, &addrlen); |
1312 | #endif | 1334 | #endif |
@@ -1329,9 +1351,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1329 | } | 1351 | } |
1330 | #if !HAVE_ACCEPT4 | 1352 | #if !HAVE_ACCEPT4 |
1331 | { | 1353 | { |
1332 | /* make socket non-inheritable */ | 1354 | /* make socket non-inheritable and non-blocking */ |
1333 | #ifdef WINDOWS | 1355 | #ifdef WINDOWS |
1334 | DWORD dwFlags; | 1356 | DWORD dwFlags; |
1357 | unsigned long flags = 1; | ||
1358 | |||
1359 | if (0 != ioctlsocket (s, FIONBIO, &flags)) | ||
1360 | { | ||
1361 | #if HAVE_MESSAGES | ||
1362 | MHD_DLOG (daemon, | ||
1363 | "Failed to make socket non-blocking: %s\n", | ||
1364 | STRERROR (errno)); | ||
1365 | #endif | ||
1366 | } | ||
1335 | if (!GetHandleInformation ((HANDLE) s, &dwFlags) || | 1367 | if (!GetHandleInformation ((HANDLE) s, &dwFlags) || |
1336 | ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) && | 1368 | ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) && |
1337 | !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0))) | 1369 | !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0))) |
@@ -1342,14 +1374,19 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1342 | "Failed to make socket non-inheritable: %s\n", | 1374 | "Failed to make socket non-inheritable: %s\n", |
1343 | STRERROR (errno)); | 1375 | STRERROR (errno)); |
1344 | #endif | 1376 | #endif |
1345 | } | 1377 | } |
1346 | #else | 1378 | #else |
1347 | int flags; | 1379 | int flags; |
1348 | 1380 | ||
1381 | nonblock = O_NONBLOCK; | ||
1382 | #ifdef CYGWIN | ||
1383 | if (0 == (daemon->options & MHD_USE_SSL)) | ||
1384 | nonblock = 0; | ||
1385 | #endif | ||
1349 | flags = fcntl (s, F_GETFD); | 1386 | flags = fcntl (s, F_GETFD); |
1350 | if ( ( (-1 == flags) || | 1387 | if ( ( (-1 == flags) || |
1351 | ( (flags != (flags | FD_CLOEXEC)) && | 1388 | ( (flags != (flags | FD_CLOEXEC)) && |
1352 | (0 != fcntl (s, F_SETFD, flags | FD_CLOEXEC)) ) ) ) | 1389 | (0 != fcntl (s, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) ) |
1353 | { | 1390 | { |
1354 | #if HAVE_MESSAGES | 1391 | #if HAVE_MESSAGES |
1355 | MHD_DLOG (daemon, | 1392 | MHD_DLOG (daemon, |
@@ -1358,7 +1395,10 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1358 | #endif | 1395 | #endif |
1359 | } | 1396 | } |
1360 | #endif | 1397 | #endif |
1398 | /* make socket non-blocking */ | ||
1399 | |||
1361 | } | 1400 | } |
1401 | |||
1362 | #endif | 1402 | #endif |
1363 | #if HAVE_MESSAGES | 1403 | #if HAVE_MESSAGES |
1364 | #if DEBUG_CONNECT | 1404 | #if DEBUG_CONNECT |
@@ -1406,10 +1446,13 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
1406 | if (pos->tls_session != NULL) | 1446 | if (pos->tls_session != NULL) |
1407 | gnutls_deinit (pos->tls_session); | 1447 | gnutls_deinit (pos->tls_session); |
1408 | #endif | 1448 | #endif |
1409 | MHD_ip_limit_del (daemon, (struct sockaddr*)pos->addr, pos->addr_len); | 1449 | MHD_ip_limit_del (daemon, |
1450 | (struct sockaddr *) pos->addr, | ||
1451 | pos->addr_len); | ||
1410 | #if EPOLL_SUPPORT | 1452 | #if EPOLL_SUPPORT |
1411 | if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) && | 1453 | if ( (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) && |
1412 | (-1 != daemon->epoll_fd) ) | 1454 | (-1 != daemon->epoll_fd) && |
1455 | (0 != (pos->epoll_state & MHD_EPOLL_STATE_IN_EPOLL_SET)) ) | ||
1413 | { | 1456 | { |
1414 | /* epoll documentation suggests that closing a FD | 1457 | /* epoll documentation suggests that closing a FD |
1415 | automatically removes it from the epoll set; however, | 1458 | automatically removes it from the epoll set; however, |
@@ -1422,6 +1465,7 @@ MHD_cleanup_connections (struct MHD_Daemon *daemon) | |||
1422 | pos->socket_fd, | 1465 | pos->socket_fd, |
1423 | NULL)) | 1466 | NULL)) |
1424 | MHD_PANIC ("Failed to remove FD from epoll set\n"); | 1467 | MHD_PANIC ("Failed to remove FD from epoll set\n"); |
1468 | pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EPOLL_SET; | ||
1425 | } | 1469 | } |
1426 | #endif | 1470 | #endif |
1427 | if (NULL != pos->response) | 1471 | if (NULL != pos->response) |
@@ -1949,10 +1993,10 @@ MHD_poll (struct MHD_Daemon *daemon, | |||
1949 | 1993 | ||
1950 | /** | 1994 | /** |
1951 | * Do 'epoll'-based processing (this function is allowed to | 1995 | * Do 'epoll'-based processing (this function is allowed to |
1952 | * block). | 1996 | * block if 'may_block' is set to MHD_YES). |
1953 | * | 1997 | * |
1954 | * @param daemon daemon to run poll loop for | 1998 | * @param daemon daemon to run poll loop for |
1955 | * @param may_block YES if blocking, NO if non-blocking | 1999 | * @param may_block MHD_YES if blocking, MHD_NO if non-blocking |
1956 | * @return MHD_NO on serious errors, MHD_YES on success | 2000 | * @return MHD_NO on serious errors, MHD_YES on success |
1957 | */ | 2001 | */ |
1958 | static int | 2002 | static int |
@@ -1966,7 +2010,8 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
1966 | int timeout_ms; | 2010 | int timeout_ms; |
1967 | MHD_UNSIGNED_LONG_LONG timeout_ll; | 2011 | MHD_UNSIGNED_LONG_LONG timeout_ll; |
1968 | int num_events; | 2012 | int num_events; |
1969 | unsigned int i; | 2013 | unsigned int i; |
2014 | unsigned int series_length; | ||
1970 | 2015 | ||
1971 | if (-1 == daemon->epoll_fd) | 2016 | if (-1 == daemon->epoll_fd) |
1972 | return MHD_NO; /* we're down! */ | 2017 | return MHD_NO; /* we're down! */ |
@@ -2082,8 +2127,11 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2082 | { | 2127 | { |
2083 | /* run 'accept' until it fails or we are not allowed to take | 2128 | /* run 'accept' until it fails or we are not allowed to take |
2084 | on more connections */ | 2129 | on more connections */ |
2130 | series_length = 0; | ||
2085 | while ( (MHD_YES == MHD_accept_connection (daemon)) && | 2131 | while ( (MHD_YES == MHD_accept_connection (daemon)) && |
2086 | (0 != daemon->max_connections) ) ; | 2132 | (0 != daemon->max_connections) && |
2133 | (series_length < 128) ) | ||
2134 | series_length++; | ||
2087 | } | 2135 | } |
2088 | } | 2136 | } |
2089 | } | 2137 | } |
@@ -2094,7 +2142,7 @@ MHD_epoll (struct MHD_Daemon *daemon, | |||
2094 | EDLL_remove (daemon->eready_head, | 2142 | EDLL_remove (daemon->eready_head, |
2095 | daemon->eready_tail, | 2143 | daemon->eready_tail, |
2096 | pos); | 2144 | pos); |
2097 | pos->epoll_state -= MHD_EPOLL_STATE_IN_EREADY_EDLL; | 2145 | pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL; |
2098 | if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) | 2146 | if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info) |
2099 | pos->read_handler (pos); | 2147 | pos->read_handler (pos); |
2100 | if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) | 2148 | if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info) |