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.c189
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 */
989int 991static int
990MHD_add_connection (struct MHD_Daemon *daemon, 992internal_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 */
1348static void
1349make_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 */
1434int
1435MHD_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