diff options
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r-- | src/microhttpd/daemon.c | 189 |
1 files changed, 130 insertions, 59 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c index 2f88b2d3..cd7a75c6 100644 --- a/src/microhttpd/daemon.c +++ b/src/microhttpd/daemon.c | |||
@@ -981,16 +981,19 @@ create_thread (pthread_t *thread, | |||
981 | * to receive an HTTP request from this socket next). | 981 | * to receive an HTTP request from this socket next). |
982 | * @param addr IP address of the client | 982 | * @param addr IP address of the client |
983 | * @param addrlen number of bytes in addr | 983 | * @param addrlen number of bytes in addr |
984 | * @param external_add perform additional operations needed due | ||
985 | * to the application calling us directly | ||
984 | * @return MHD_YES on success, MHD_NO if this daemon could | 986 | * @return MHD_YES on success, MHD_NO if this daemon could |
985 | * not handle the connection (i.e. malloc failed, etc). | 987 | * not handle the connection (i.e. malloc failed, etc). |
986 | * The socket will be closed in any case; 'errno' is | 988 | * The socket will be closed in any case; 'errno' is |
987 | * set to indicate further details about the error. | 989 | * set to indicate further details about the error. |
988 | */ | 990 | */ |
989 | int | 991 | static int |
990 | MHD_add_connection (struct MHD_Daemon *daemon, | 992 | internal_add_connection (struct MHD_Daemon *daemon, |
991 | int client_socket, | 993 | int client_socket, |
992 | const struct sockaddr *addr, | 994 | const struct sockaddr *addr, |
993 | socklen_t addrlen) | 995 | socklen_t addrlen, |
996 | int external_add) | ||
994 | { | 997 | { |
995 | struct MHD_Connection *connection; | 998 | struct MHD_Connection *connection; |
996 | int res_thread_create; | 999 | int res_thread_create; |
@@ -1007,9 +1010,10 @@ MHD_add_connection (struct MHD_Daemon *daemon, | |||
1007 | balancing */ | 1010 | balancing */ |
1008 | for (i=0;i<daemon->worker_pool_size;i++) | 1011 | for (i=0;i<daemon->worker_pool_size;i++) |
1009 | if (0 < daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size].max_connections) | 1012 | if (0 < daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size].max_connections) |
1010 | return MHD_add_connection (&daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size], | 1013 | return internal_add_connection (&daemon->worker_pool[(i + client_socket) % daemon->worker_pool_size], |
1011 | client_socket, | 1014 | client_socket, |
1012 | addr, addrlen); | 1015 | addr, addrlen, |
1016 | external_add); | ||
1013 | /* all pools are at their connection limit, must refuse */ | 1017 | /* all pools are at their connection limit, must refuse */ |
1014 | if (0 != CLOSE (client_socket)) | 1018 | if (0 != CLOSE (client_socket)) |
1015 | MHD_PANIC ("close failed\n"); | 1019 | MHD_PANIC ("close failed\n"); |
@@ -1263,6 +1267,13 @@ MHD_add_connection (struct MHD_Daemon *daemon, | |||
1263 | goto cleanup; | 1267 | goto cleanup; |
1264 | } | 1268 | } |
1265 | } | 1269 | } |
1270 | else | ||
1271 | if ( (MHD_YES == external_add) && | ||
1272 | (-1 != daemon->wpipe[1]) && | ||
1273 | (1 != WRITE (daemon->wpipe[1], "n", 1)) ) | ||
1274 | MHD_DLOG (daemon, | ||
1275 | "failed to signal new connection via pipe"); | ||
1276 | |||
1266 | #if EPOLL_SUPPORT | 1277 | #if EPOLL_SUPPORT |
1267 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) | 1278 | if (0 != (daemon->options & MHD_USE_EPOLL_LINUX_ONLY)) |
1268 | { | 1279 | { |
@@ -1329,6 +1340,113 @@ MHD_add_connection (struct MHD_Daemon *daemon, | |||
1329 | 1340 | ||
1330 | 1341 | ||
1331 | /** | 1342 | /** |
1343 | * Change socket options to be non-blocking, non-inheritable. | ||
1344 | * | ||
1345 | * @param daemon daemon context | ||
1346 | * @param sock socket to manipulate | ||
1347 | */ | ||
1348 | static void | ||
1349 | make_nonblocking_noninheritable (struct MHD_Daemon *daemon, | ||
1350 | int sock) | ||
1351 | { | ||
1352 | int nonblock; | ||
1353 | |||
1354 | #ifdef HAVE_SOCK_NONBLOCK | ||
1355 | nonblock = SOCK_NONBLOCK; | ||
1356 | #else | ||
1357 | nonblock = 0; | ||
1358 | #endif | ||
1359 | #ifdef CYGWIN | ||
1360 | if (0 == (daemon->options & MHD_USE_SSL)) | ||
1361 | nonblock = 0; | ||
1362 | #endif | ||
1363 | |||
1364 | #ifdef WINDOWS | ||
1365 | DWORD dwFlags; | ||
1366 | unsigned long flags = 1; | ||
1367 | |||
1368 | if (0 != ioctlsocket (sock, FIONBIO, &flags)) | ||
1369 | { | ||
1370 | #if HAVE_MESSAGES | ||
1371 | MHD_DLOG (daemon, | ||
1372 | "Failed to make socket non-blocking: %s\n", | ||
1373 | STRERROR (errno)); | ||
1374 | #endif | ||
1375 | } | ||
1376 | if (!GetHandleInformation ((HANDLE) sock, &dwFlags) || | ||
1377 | ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) && | ||
1378 | !SetHandleInformation ((HANDLE) sock, HANDLE_FLAG_INHERIT, 0))) | ||
1379 | { | ||
1380 | #if HAVE_MESSAGES | ||
1381 | SetErrnoFromWinError (GetLastError ()); | ||
1382 | MHD_DLOG (daemon, | ||
1383 | "Failed to make socket non-inheritable: %s\n", | ||
1384 | STRERROR (errno)); | ||
1385 | #endif | ||
1386 | } | ||
1387 | #else | ||
1388 | int flags; | ||
1389 | |||
1390 | nonblock = O_NONBLOCK; | ||
1391 | #ifdef CYGWIN | ||
1392 | if (0 == (daemon->options & MHD_USE_SSL)) | ||
1393 | nonblock = 0; | ||
1394 | #endif | ||
1395 | flags = fcntl (sock, F_GETFD); | ||
1396 | if ( ( (-1 == flags) || | ||
1397 | ( (flags != (flags | FD_CLOEXEC)) && | ||
1398 | (0 != fcntl (sock, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) ) | ||
1399 | { | ||
1400 | #if HAVE_MESSAGES | ||
1401 | MHD_DLOG (daemon, | ||
1402 | "Failed to make socket non-inheritable: %s\n", | ||
1403 | STRERROR (errno)); | ||
1404 | #endif | ||
1405 | } | ||
1406 | #endif | ||
1407 | } | ||
1408 | |||
1409 | |||
1410 | /** | ||
1411 | * Add another client connection to the set of connections | ||
1412 | * managed by MHD. This API is usually not needed (since | ||
1413 | * MHD will accept inbound connections on the server socket). | ||
1414 | * Use this API in special cases, for example if your HTTP | ||
1415 | * server is behind NAT and needs to connect out to the | ||
1416 | * HTTP client. | ||
1417 | * | ||
1418 | * The given client socket will be managed (and closed!) by MHD after | ||
1419 | * this call and must no longer be used directly by the application | ||
1420 | * afterwards. | ||
1421 | * | ||
1422 | * Per-IP connection limits are ignored when using this API. | ||
1423 | * | ||
1424 | * @param daemon daemon that manages the connection | ||
1425 | * @param client_socket socket to manage (MHD will expect | ||
1426 | * to receive an HTTP request from this socket next). | ||
1427 | * @param addr IP address of the client | ||
1428 | * @param addrlen number of bytes in addr | ||
1429 | * @return MHD_YES on success, MHD_NO if this daemon could | ||
1430 | * not handle the connection (i.e. malloc failed, etc). | ||
1431 | * The socket will be closed in any case; 'errno' is | ||
1432 | * set to indicate further details about the error. | ||
1433 | */ | ||
1434 | int | ||
1435 | MHD_add_connection (struct MHD_Daemon *daemon, | ||
1436 | int client_socket, | ||
1437 | const struct sockaddr *addr, | ||
1438 | socklen_t addrlen) | ||
1439 | { | ||
1440 | make_nonblocking_noninheritable (daemon, | ||
1441 | client_socket); | ||
1442 | return internal_add_connection (daemon, | ||
1443 | client_socket, | ||
1444 | addr, addrlen, | ||
1445 | MHD_YES); | ||
1446 | } | ||
1447 | |||
1448 | |||
1449 | /** | ||
1332 | * Accept an incoming connection and create the MHD_Connection object for | 1450 | * Accept an incoming connection and create the MHD_Connection object for |
1333 | * it. This function also enforces policy by way of checking with the | 1451 | * it. This function also enforces policy by way of checking with the |
1334 | * accept policy callback. | 1452 | * accept policy callback. |
@@ -1390,63 +1508,16 @@ MHD_accept_connection (struct MHD_Daemon *daemon) | |||
1390 | return MHD_NO; | 1508 | return MHD_NO; |
1391 | } | 1509 | } |
1392 | #if !HAVE_ACCEPT4 | 1510 | #if !HAVE_ACCEPT4 |
1393 | { | 1511 | make_nonblocking_noninheritable (daemon, s); |
1394 | /* make socket non-inheritable and non-blocking */ | ||
1395 | #ifdef WINDOWS | ||
1396 | DWORD dwFlags; | ||
1397 | unsigned long flags = 1; | ||
1398 | |||
1399 | if (0 != ioctlsocket (s, FIONBIO, &flags)) | ||
1400 | { | ||
1401 | #if HAVE_MESSAGES | ||
1402 | MHD_DLOG (daemon, | ||
1403 | "Failed to make socket non-blocking: %s\n", | ||
1404 | STRERROR (errno)); | ||
1405 | #endif | ||
1406 | } | ||
1407 | if (!GetHandleInformation ((HANDLE) s, &dwFlags) || | ||
1408 | ((dwFlags != dwFlags & ~HANDLE_FLAG_INHERIT) && | ||
1409 | !SetHandleInformation ((HANDLE) s, HANDLE_FLAG_INHERIT, 0))) | ||
1410 | { | ||
1411 | #if HAVE_MESSAGES | ||
1412 | SetErrnoFromWinError (GetLastError ()); | ||
1413 | MHD_DLOG (daemon, | ||
1414 | "Failed to make socket non-inheritable: %s\n", | ||
1415 | STRERROR (errno)); | ||
1416 | #endif | ||
1417 | } | ||
1418 | #else | ||
1419 | int flags; | ||
1420 | |||
1421 | nonblock = O_NONBLOCK; | ||
1422 | #ifdef CYGWIN | ||
1423 | if (0 == (daemon->options & MHD_USE_SSL)) | ||
1424 | nonblock = 0; | ||
1425 | #endif | ||
1426 | flags = fcntl (s, F_GETFD); | ||
1427 | if ( ( (-1 == flags) || | ||
1428 | ( (flags != (flags | FD_CLOEXEC)) && | ||
1429 | (0 != fcntl (s, F_SETFD, flags | nonblock | FD_CLOEXEC)) ) ) ) | ||
1430 | { | ||
1431 | #if HAVE_MESSAGES | ||
1432 | MHD_DLOG (daemon, | ||
1433 | "Failed to make socket non-inheritable: %s\n", | ||
1434 | STRERROR (errno)); | ||
1435 | #endif | ||
1436 | } | ||
1437 | #endif | ||
1438 | /* make socket non-blocking */ | ||
1439 | |||
1440 | } | ||
1441 | |||
1442 | #endif | 1512 | #endif |
1443 | #if HAVE_MESSAGES | 1513 | #if HAVE_MESSAGES |
1444 | #if DEBUG_CONNECT | 1514 | #if DEBUG_CONNECT |
1445 | MHD_DLOG (daemon, "Accepted connection on socket %d\n", s); | 1515 | MHD_DLOG (daemon, "Accepted connection on socket %d\n", s); |
1446 | #endif | 1516 | #endif |
1447 | #endif | 1517 | #endif |
1448 | (void) MHD_add_connection (daemon, s, | 1518 | (void) internal_add_connection (daemon, s, |
1449 | addr, addrlen); | 1519 | addr, addrlen, |
1520 | MHD_NO); | ||
1450 | return MHD_YES; | 1521 | return MHD_YES; |
1451 | } | 1522 | } |
1452 | 1523 | ||