diff options
Diffstat (limited to 'src/daemon/daemon.c')
-rw-r--r-- | src/daemon/daemon.c | 372 |
1 files changed, 212 insertions, 160 deletions
diff --git a/src/daemon/daemon.c b/src/daemon/daemon.c index d85ed92a..2f367f25 100644 --- a/src/daemon/daemon.c +++ b/src/daemon/daemon.c | |||
@@ -121,6 +121,7 @@ MHD_get_master (struct MHD_Daemon *daemon) | |||
121 | return daemon; | 121 | return daemon; |
122 | } | 122 | } |
123 | 123 | ||
124 | |||
124 | /** | 125 | /** |
125 | * Maintain connection count for single address. | 126 | * Maintain connection count for single address. |
126 | */ | 127 | */ |
@@ -154,6 +155,7 @@ struct MHD_IPCount | |||
154 | unsigned int count; | 155 | unsigned int count; |
155 | }; | 156 | }; |
156 | 157 | ||
158 | |||
157 | /** | 159 | /** |
158 | * Lock shared structure for IP connection counts and connection DLLs. | 160 | * Lock shared structure for IP connection counts and connection DLLs. |
159 | * | 161 | * |
@@ -171,6 +173,7 @@ MHD_ip_count_lock(struct MHD_Daemon *daemon) | |||
171 | } | 173 | } |
172 | } | 174 | } |
173 | 175 | ||
176 | |||
174 | /** | 177 | /** |
175 | * Unlock shared structure for IP connection counts and connection DLLs. | 178 | * Unlock shared structure for IP connection counts and connection DLLs. |
176 | * | 179 | * |
@@ -203,6 +206,7 @@ MHD_ip_addr_compare(const void *a1, const void *a2) | |||
203 | return memcmp (a1, a2, offsetof(struct MHD_IPCount, count)); | 206 | return memcmp (a1, a2, offsetof(struct MHD_IPCount, count)); |
204 | } | 207 | } |
205 | 208 | ||
209 | |||
206 | /** | 210 | /** |
207 | * Parse address and initialize 'key' using the address. | 211 | * Parse address and initialize 'key' using the address. |
208 | * | 212 | * |
@@ -241,6 +245,7 @@ MHD_ip_addr_to_key(const struct sockaddr *addr, socklen_t addrlen, | |||
241 | return MHD_NO; | 245 | return MHD_NO; |
242 | } | 246 | } |
243 | 247 | ||
248 | |||
244 | /** | 249 | /** |
245 | * Check if IP address is over its limit. | 250 | * Check if IP address is over its limit. |
246 | * | 251 | * |
@@ -308,6 +313,7 @@ MHD_ip_limit_add(struct MHD_Daemon *daemon, | |||
308 | return result; | 313 | return result; |
309 | } | 314 | } |
310 | 315 | ||
316 | |||
311 | /** | 317 | /** |
312 | * Decrement connection count for IP address, removing from table | 318 | * Decrement connection count for IP address, removing from table |
313 | * count reaches 0 | 319 | * count reaches 0 |
@@ -372,9 +378,11 @@ MHD_ip_limit_del(struct MHD_Daemon *daemon, | |||
372 | MHD_ip_count_unlock (daemon); | 378 | MHD_ip_count_unlock (daemon); |
373 | } | 379 | } |
374 | 380 | ||
381 | |||
375 | #if HTTPS_SUPPORT | 382 | #if HTTPS_SUPPORT |
376 | static pthread_mutex_t MHD_gnutls_init_mutex; | 383 | static pthread_mutex_t MHD_gnutls_init_mutex; |
377 | 384 | ||
385 | |||
378 | /** | 386 | /** |
379 | * Callback for receiving data from the socket. | 387 | * Callback for receiving data from the socket. |
380 | * | 388 | * |
@@ -442,19 +450,21 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) | |||
442 | gnutls_datum_t key; | 450 | gnutls_datum_t key; |
443 | gnutls_datum_t cert; | 451 | gnutls_datum_t cert; |
444 | 452 | ||
445 | if (daemon->https_mem_trust) { | 453 | if (daemon->https_mem_trust) |
446 | cert.data = (unsigned char *) daemon->https_mem_trust; | 454 | { |
447 | cert.size = strlen(daemon->https_mem_trust); | 455 | cert.data = (unsigned char *) daemon->https_mem_trust; |
448 | if (gnutls_certificate_set_x509_trust_mem(daemon->x509_cred, &cert, | 456 | cert.size = strlen (daemon->https_mem_trust); |
449 | GNUTLS_X509_FMT_PEM) < 0) { | 457 | if (gnutls_certificate_set_x509_trust_mem (daemon->x509_cred, &cert, |
458 | GNUTLS_X509_FMT_PEM) < 0) | ||
459 | { | ||
450 | #if HAVE_MESSAGES | 460 | #if HAVE_MESSAGES |
451 | MHD_DLOG(daemon, | 461 | MHD_DLOG(daemon, |
452 | "Bad trust certificate format\n"); | 462 | "Bad trust certificate format\n"); |
453 | #endif | 463 | #endif |
454 | return -1; | 464 | return -1; |
455 | } | ||
456 | } | 465 | } |
457 | 466 | } | |
467 | |||
458 | /* certificate & key loaded from memory */ | 468 | /* certificate & key loaded from memory */ |
459 | if (daemon->https_mem_cert && daemon->https_mem_key) | 469 | if (daemon->https_mem_cert && daemon->https_mem_key) |
460 | { | 470 | { |
@@ -473,6 +483,7 @@ MHD_init_daemon_certificate (struct MHD_Daemon *daemon) | |||
473 | return -1; | 483 | return -1; |
474 | } | 484 | } |
475 | 485 | ||
486 | |||
476 | /** | 487 | /** |
477 | * Initialize security aspects of the HTTPS daemon | 488 | * Initialize security aspects of the HTTPS daemon |
478 | * | 489 | * |
@@ -516,41 +527,44 @@ MHD_TLS_init (struct MHD_Daemon *daemon) | |||
516 | */ | 527 | */ |
517 | int | 528 | int |
518 | MHD_get_fdset (struct MHD_Daemon *daemon, | 529 | MHD_get_fdset (struct MHD_Daemon *daemon, |
519 | fd_set * read_fd_set, | 530 | fd_set *read_fd_set, |
520 | fd_set * write_fd_set, fd_set * except_fd_set, int *max_fd) | 531 | fd_set *write_fd_set, |
532 | fd_set *except_fd_set, | ||
533 | int *max_fd) | ||
521 | { | 534 | { |
522 | struct MHD_Connection *pos; | 535 | struct MHD_Connection *pos; |
523 | struct MHD_Connection *next; | ||
524 | int fd; | 536 | int fd; |
525 | 537 | ||
526 | if ((daemon == NULL) || (read_fd_set == NULL) || (write_fd_set == NULL) | 538 | if ( (NULL == daemon) |
527 | || (except_fd_set == NULL) || (max_fd == NULL) | 539 | || (NULL == read_fd_set) |
528 | || (-1 == (fd = daemon->socket_fd)) || (daemon->shutdown == MHD_YES) | 540 | || (NULL == write_fd_set) |
529 | || ((daemon->options & MHD_USE_THREAD_PER_CONNECTION) != 0) | 541 | || (NULL == except_fd_set) |
530 | || ((daemon->options & MHD_USE_POLL) != 0)) | 542 | || (NULL == max_fd) |
543 | || (MHD_YES == daemon->shutdown) | ||
544 | || (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | ||
545 | || (0 != (daemon->options & MHD_USE_POLL))) | ||
531 | return MHD_NO; | 546 | return MHD_NO; |
532 | 547 | fd = daemon->socket_fd; | |
533 | FD_SET (fd, read_fd_set); | 548 | if (-1 != fd) |
534 | /* update max file descriptor */ | 549 | { |
535 | if ((*max_fd) < fd) | 550 | FD_SET (fd, read_fd_set); |
536 | *max_fd = fd; | 551 | /* update max file descriptor */ |
537 | 552 | if ((*max_fd) < fd) | |
538 | next = daemon->connections_head; | 553 | *max_fd = fd; |
539 | while (NULL != (pos = next)) | 554 | } |
540 | { | 555 | for (pos = daemon->connections_head; NULL != pos; pos = pos->next) |
541 | next = pos->next; | 556 | if (MHD_YES != MHD_connection_get_fdset (pos, |
542 | if (MHD_YES != MHD_connection_get_fdset (pos, | 557 | read_fd_set, |
543 | read_fd_set, | 558 | write_fd_set, |
544 | write_fd_set, | 559 | except_fd_set, max_fd)) |
545 | except_fd_set, max_fd)) | 560 | return MHD_NO; |
546 | return MHD_NO; | ||
547 | } | ||
548 | #if DEBUG_CONNECT | 561 | #if DEBUG_CONNECT |
549 | MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd); | 562 | MHD_DLOG (daemon, "Maximum socket in select set: %d\n", *max_fd); |
550 | #endif | 563 | #endif |
551 | return MHD_YES; | 564 | return MHD_YES; |
552 | } | 565 | } |
553 | 566 | ||
567 | |||
554 | /** | 568 | /** |
555 | * Main function of the thread that handles an individual | 569 | * Main function of the thread that handles an individual |
556 | * connection when MHD_USE_THREAD_PER_CONNECTION is set. | 570 | * connection when MHD_USE_THREAD_PER_CONNECTION is set. |
@@ -577,7 +591,8 @@ MHD_handle_connection (void *data) | |||
577 | #endif | 591 | #endif |
578 | 592 | ||
579 | timeout = con->daemon->connection_timeout; | 593 | timeout = con->daemon->connection_timeout; |
580 | while ( (!con->daemon->shutdown) && (con->state != MHD_CONNECTION_CLOSED) ) | 594 | while ( (MHD_YES != con->daemon->shutdown) && |
595 | (MHD_CONNECTION_CLOSED != con->state) ) | ||
581 | { | 596 | { |
582 | tvp = NULL; | 597 | tvp = NULL; |
583 | if (timeout > 0) | 598 | if (timeout > 0) |
@@ -687,6 +702,7 @@ exit: | |||
687 | return NULL; | 702 | return NULL; |
688 | } | 703 | } |
689 | 704 | ||
705 | |||
690 | /** | 706 | /** |
691 | * Callback for receiving data from the socket. | 707 | * Callback for receiving data from the socket. |
692 | * | 708 | * |
@@ -700,8 +716,8 @@ recv_param_adapter (struct MHD_Connection *connection, | |||
700 | void *other, | 716 | void *other, |
701 | size_t i) | 717 | size_t i) |
702 | { | 718 | { |
703 | if ( (connection->socket_fd == -1) || | 719 | if ( (-1 == connection->socket_fd) || |
704 | (connection->state == MHD_CONNECTION_CLOSED) ) | 720 | (MHD_CONNECTION_CLOSED == connection->state) ) |
705 | { | 721 | { |
706 | errno = ENOTCONN; | 722 | errno = ENOTCONN; |
707 | return -1; | 723 | return -1; |
@@ -711,6 +727,7 @@ recv_param_adapter (struct MHD_Connection *connection, | |||
711 | return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); | 727 | return RECV (connection->socket_fd, other, i, MSG_NOSIGNAL); |
712 | } | 728 | } |
713 | 729 | ||
730 | |||
714 | /** | 731 | /** |
715 | * Callback for writing data to the socket. | 732 | * Callback for writing data to the socket. |
716 | * | 733 | * |
@@ -1342,8 +1359,9 @@ MHD_select (struct MHD_Daemon *daemon, | |||
1342 | 1359 | ||
1343 | /* If we're at the connection limit, no need to | 1360 | /* If we're at the connection limit, no need to |
1344 | accept new connections. */ | 1361 | accept new connections. */ |
1345 | if ( (daemon->max_connections == 0) && (daemon->socket_fd != -1) ) | 1362 | if ( (0 == daemon->max_connections) && |
1346 | FD_CLR(daemon->socket_fd, &rs); | 1363 | (-1 != daemon->socket_fd) ) |
1364 | FD_CLR (daemon->socket_fd, &rs); | ||
1347 | } | 1365 | } |
1348 | else | 1366 | else |
1349 | { | 1367 | { |
@@ -1354,14 +1372,13 @@ MHD_select (struct MHD_Daemon *daemon, | |||
1354 | FD_SET (max, &rs); | 1372 | FD_SET (max, &rs); |
1355 | } | 1373 | } |
1356 | 1374 | ||
1357 | #ifndef HAVE_LISTEN_SHUTDOWN | 1375 | if (-1 != daemon->wpipe[0]) |
1358 | if (-1 == daemon->wpipe[0]) | 1376 | { |
1359 | return MHD_NO; | 1377 | FD_SET (daemon->wpipe[0], &rs); |
1360 | FD_SET (daemon->wpipe[0], &rs); | 1378 | /* update max file descriptor */ |
1361 | /* update max file descriptor */ | 1379 | if (max < daemon->wpipe[0]) |
1362 | if (max < daemon->wpipe[0]) | 1380 | max = daemon->wpipe[0]; |
1363 | max = daemon->wpipe[0]; | 1381 | } |
1364 | #endif | ||
1365 | 1382 | ||
1366 | tv = NULL; | 1383 | tv = NULL; |
1367 | if (may_block == MHD_NO) | 1384 | if (may_block == MHD_NO) |
@@ -1391,12 +1408,12 @@ MHD_select (struct MHD_Daemon *daemon, | |||
1391 | #endif | 1408 | #endif |
1392 | return MHD_NO; | 1409 | return MHD_NO; |
1393 | } | 1410 | } |
1394 | ds = daemon->socket_fd; | 1411 | if (MHD_YES == daemon->shutdown) |
1395 | if (ds == -1) | ||
1396 | return MHD_YES; | 1412 | return MHD_YES; |
1397 | 1413 | ||
1398 | /* select connection thread handling type */ | 1414 | /* select connection thread handling type */ |
1399 | if (FD_ISSET (ds, &rs)) | 1415 | if ( (-1 != (ds = daemon->socket_fd)) && |
1416 | (FD_ISSET (ds, &rs)) ) | ||
1400 | MHD_accept_connection (daemon); | 1417 | MHD_accept_connection (daemon); |
1401 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) | 1418 | if (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) |
1402 | { | 1419 | { |
@@ -1445,35 +1462,33 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
1445 | pos = pos->next; | 1462 | pos = pos->next; |
1446 | } | 1463 | } |
1447 | { | 1464 | { |
1448 | #ifdef HAVE_LISTEN_SHUTDOWN | ||
1449 | struct pollfd p[1 + num_connections]; | ||
1450 | #else | ||
1451 | struct pollfd p[2 + num_connections]; | 1465 | struct pollfd p[2 + num_connections]; |
1452 | #endif | ||
1453 | struct MHD_Pollfd mp; | 1466 | struct MHD_Pollfd mp; |
1454 | unsigned MHD_LONG_LONG ltimeout; | 1467 | unsigned MHD_LONG_LONG ltimeout; |
1455 | unsigned int i; | 1468 | unsigned int i; |
1456 | int timeout; | 1469 | int timeout; |
1457 | unsigned int poll_server; | 1470 | unsigned int poll_server; |
1471 | int poll_listen; | ||
1458 | 1472 | ||
1459 | memset (p, 0, sizeof (p)); | 1473 | memset (p, 0, sizeof (p)); |
1460 | if ( (daemon->max_connections > 0) && (daemon->socket_fd != -1) ) | 1474 | poll_server = 0; |
1475 | poll_listen = -1; | ||
1476 | if ( (-1 != daemon->socket_fd) && | ||
1477 | (0 != daemon->max_connections) ) | ||
1461 | { | 1478 | { |
1462 | p[0].fd = daemon->socket_fd; | 1479 | /* only listen if we are not at the connection limit */ |
1463 | p[0].events = POLLIN; | 1480 | p[poll_server].fd = daemon->socket_fd; |
1464 | p[0].revents = 0; | 1481 | p[poll_server].events = POLLIN; |
1465 | #ifdef HAVE_LISTEN_SHUTDOWN | 1482 | p[poll_server].revents = 0; |
1466 | poll_server = 1; | 1483 | poll_listen = (int) poll_server; |
1467 | #else | 1484 | poll_server++; |
1468 | p[1].fd = daemon->wpipe[0]; | ||
1469 | p[1].events = POLLIN; | ||
1470 | p[1].revents = 0; | ||
1471 | poll_server = 2; | ||
1472 | #endif | ||
1473 | } | 1485 | } |
1474 | else | 1486 | if (-1 != daemon->wpipe[0]) |
1475 | { | 1487 | { |
1476 | poll_server = 0; | 1488 | p[poll_server].fd = daemon->wpipe[0]; |
1489 | p[poll_server].events = POLLIN; | ||
1490 | p[poll_server].revents = 0; | ||
1491 | poll_server++; | ||
1477 | } | 1492 | } |
1478 | if (may_block == MHD_NO) | 1493 | if (may_block == MHD_NO) |
1479 | timeout = 0; | 1494 | timeout = 0; |
@@ -1484,8 +1499,7 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
1484 | timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout; | 1499 | timeout = (ltimeout > INT_MAX) ? INT_MAX : (int) ltimeout; |
1485 | 1500 | ||
1486 | i = 0; | 1501 | i = 0; |
1487 | pos = daemon->connections_head; | 1502 | for (pos = daemon->connections_head; NULL != pos; pos = pos->next) |
1488 | while (pos != NULL) | ||
1489 | { | 1503 | { |
1490 | memset(&mp, 0, sizeof (struct MHD_Pollfd)); | 1504 | memset(&mp, 0, sizeof (struct MHD_Pollfd)); |
1491 | MHD_connection_get_pollfd (pos, &mp); | 1505 | MHD_connection_get_pollfd (pos, &mp); |
@@ -1495,22 +1509,19 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
1495 | if (mp.events & MHD_POLL_ACTION_OUT) | 1509 | if (mp.events & MHD_POLL_ACTION_OUT) |
1496 | p[poll_server+i].events |= POLLOUT; | 1510 | p[poll_server+i].events |= POLLOUT; |
1497 | i++; | 1511 | i++; |
1498 | pos = pos->next; | ||
1499 | } | 1512 | } |
1500 | if (poll (p, poll_server + num_connections, timeout) < 0) | 1513 | if (poll (p, poll_server + num_connections, timeout) < 0) |
1501 | { | 1514 | { |
1502 | if (errno == EINTR) | 1515 | if (EINTR == errno) |
1503 | return MHD_YES; | 1516 | return MHD_YES; |
1504 | #if HAVE_MESSAGES | 1517 | #if HAVE_MESSAGES |
1505 | MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno)); | 1518 | MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno)); |
1506 | #endif | 1519 | #endif |
1507 | return MHD_NO; | 1520 | return MHD_NO; |
1508 | } | 1521 | } |
1509 | /* handle shutdown cases */ | 1522 | /* handle shutdown */ |
1510 | if (daemon->shutdown == MHD_YES) | 1523 | if (MHD_YES == daemon->shutdown) |
1511 | return MHD_NO; | 1524 | return MHD_NO; |
1512 | if (daemon->socket_fd < 0) | ||
1513 | return MHD_YES; | ||
1514 | i = 0; | 1525 | i = 0; |
1515 | next = daemon->connections_head; | 1526 | next = daemon->connections_head; |
1516 | while (NULL != (pos = next)) | 1527 | while (NULL != (pos = next)) |
@@ -1531,8 +1542,8 @@ MHD_poll_all (struct MHD_Daemon *daemon, | |||
1531 | pos->idle_handler (pos); | 1542 | pos->idle_handler (pos); |
1532 | i++; | 1543 | i++; |
1533 | } | 1544 | } |
1534 | if ( (0 != poll_server) && | 1545 | if ( (-1 != poll_listen) && |
1535 | (0 != (p[0].revents & POLLIN)) ) | 1546 | (0 != (p[poll_listen].revents & POLLIN)) ) |
1536 | MHD_accept_connection (daemon); | 1547 | MHD_accept_connection (daemon); |
1537 | } | 1548 | } |
1538 | return MHD_YES; | 1549 | return MHD_YES; |
@@ -1550,41 +1561,47 @@ static int | |||
1550 | MHD_poll_listen_socket (struct MHD_Daemon *daemon, | 1561 | MHD_poll_listen_socket (struct MHD_Daemon *daemon, |
1551 | int may_block) | 1562 | int may_block) |
1552 | { | 1563 | { |
1553 | #ifdef HAVE_LISTEN_SHUTDOWN | ||
1554 | struct pollfd p[1]; | ||
1555 | #else | ||
1556 | struct pollfd p[2]; | 1564 | struct pollfd p[2]; |
1557 | #endif | ||
1558 | int timeout; | 1565 | int timeout; |
1559 | 1566 | unsigned int poll_count; | |
1567 | int poll_listen; | ||
1568 | |||
1560 | memset (&p, 0, sizeof (p)); | 1569 | memset (&p, 0, sizeof (p)); |
1561 | p[0].fd = daemon->socket_fd; | 1570 | poll_count = 0; |
1562 | p[0].events = POLLIN; | 1571 | poll_listen = -1; |
1563 | p[0].revents = 0; | 1572 | if (-1 != daemon->socket_fd) |
1564 | #ifndef HAVE_LISTEN_SHUTDOWN | 1573 | { |
1565 | p[1].fd = daemon->wpipe[0]; | 1574 | p[poll_count].fd = daemon->socket_fd; |
1566 | p[1].events = POLLIN; | 1575 | p[poll_count].events = POLLIN; |
1567 | p[1].revents = 0; | 1576 | p[poll_count].revents = 0; |
1568 | #endif | 1577 | poll_listen = poll_count; |
1569 | if (may_block == MHD_NO) | 1578 | poll_count++; |
1579 | } | ||
1580 | if (-1 != daemon->wpipe[0]) | ||
1581 | { | ||
1582 | p[poll_count].fd = daemon->wpipe[0]; | ||
1583 | p[poll_count].events = POLLIN; | ||
1584 | p[poll_count].revents = 0; | ||
1585 | poll_count++; | ||
1586 | } | ||
1587 | if (MHD_NO == may_block) | ||
1570 | timeout = 0; | 1588 | timeout = 0; |
1571 | else | 1589 | else |
1572 | timeout = -1; | 1590 | timeout = -1; |
1573 | if (poll (p, (sizeof(p)/sizeof(struct pollfd)), timeout) < 0) | 1591 | if (poll (p, poll_count, timeout) < 0) |
1574 | { | 1592 | { |
1575 | if (errno == EINTR) | 1593 | if (EINTR == errno) |
1576 | return MHD_YES; | 1594 | return MHD_YES; |
1577 | #if HAVE_MESSAGES | 1595 | #if HAVE_MESSAGES |
1578 | MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno)); | 1596 | MHD_DLOG (daemon, "poll failed: %s\n", STRERROR (errno)); |
1579 | #endif | 1597 | #endif |
1580 | return MHD_NO; | 1598 | return MHD_NO; |
1581 | } | 1599 | } |
1582 | /* handle shutdown cases */ | 1600 | /* handle shutdown */ |
1583 | if (daemon->shutdown == MHD_YES) | 1601 | if (MHD_YES == daemon->shutdown) |
1584 | return MHD_NO; | 1602 | return MHD_NO; |
1585 | if (daemon->socket_fd < 0) | 1603 | if ( (-1 != poll_listen) && |
1586 | return MHD_YES; | 1604 | (0 != (p[poll_listen].revents & POLLIN)) ) |
1587 | if (0 != (p[0].revents & POLLIN)) | ||
1588 | MHD_accept_connection (daemon); | 1605 | MHD_accept_connection (daemon); |
1589 | return MHD_YES; | 1606 | return MHD_YES; |
1590 | } | 1607 | } |
@@ -1628,18 +1645,14 @@ MHD_poll (struct MHD_Daemon *daemon, | |||
1628 | int | 1645 | int |
1629 | MHD_run (struct MHD_Daemon *daemon) | 1646 | MHD_run (struct MHD_Daemon *daemon) |
1630 | { | 1647 | { |
1631 | if ((daemon->shutdown != MHD_NO) || (0 != (daemon->options | 1648 | if ( (MHD_YES == daemon->shutdown) || |
1632 | & MHD_USE_THREAD_PER_CONNECTION)) | 1649 | (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || |
1633 | || (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY))) | 1650 | (0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) ) |
1634 | return MHD_NO; | 1651 | return MHD_NO; |
1635 | if ((daemon->options & MHD_USE_POLL) == 0) | 1652 | if (0 == (daemon->options & MHD_USE_POLL)) |
1636 | { | 1653 | MHD_select (daemon, MHD_NO); |
1637 | MHD_select (daemon, MHD_NO); | 1654 | else |
1638 | } | 1655 | MHD_poll (daemon, MHD_NO); |
1639 | else | ||
1640 | { | ||
1641 | MHD_poll (daemon, MHD_NO); | ||
1642 | } | ||
1643 | MHD_cleanup_connections (daemon); | 1656 | MHD_cleanup_connections (daemon); |
1644 | return MHD_YES; | 1657 | return MHD_YES; |
1645 | } | 1658 | } |
@@ -1656,9 +1669,10 @@ static void * | |||
1656 | MHD_select_thread (void *cls) | 1669 | MHD_select_thread (void *cls) |
1657 | { | 1670 | { |
1658 | struct MHD_Daemon *daemon = cls; | 1671 | struct MHD_Daemon *daemon = cls; |
1659 | while (daemon->shutdown == MHD_NO) | 1672 | |
1673 | while (MHD_YES != daemon->shutdown) | ||
1660 | { | 1674 | { |
1661 | if ((daemon->options & MHD_USE_POLL) == 0) | 1675 | if (0 == (daemon->options & MHD_USE_POLL)) |
1662 | MHD_select (daemon, MHD_YES); | 1676 | MHD_select (daemon, MHD_YES); |
1663 | else | 1677 | else |
1664 | MHD_poll (daemon, MHD_YES); | 1678 | MHD_poll (daemon, MHD_YES); |
@@ -1686,17 +1700,26 @@ MHD_start_daemon (unsigned int options, | |||
1686 | void *apc_cls, | 1700 | void *apc_cls, |
1687 | MHD_AccessHandlerCallback dh, void *dh_cls, ...) | 1701 | MHD_AccessHandlerCallback dh, void *dh_cls, ...) |
1688 | { | 1702 | { |
1689 | struct MHD_Daemon *ret; | 1703 | struct MHD_Daemon *daemon; |
1690 | va_list ap; | 1704 | va_list ap; |
1691 | 1705 | ||
1692 | va_start (ap, dh_cls); | 1706 | va_start (ap, dh_cls); |
1693 | ret = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap); | 1707 | daemon = MHD_start_daemon_va (options, port, apc, apc_cls, dh, dh_cls, ap); |
1694 | va_end (ap); | 1708 | va_end (ap); |
1695 | return ret; | 1709 | return daemon; |
1696 | } | 1710 | } |
1697 | 1711 | ||
1698 | 1712 | ||
1699 | typedef void (*VfprintfFunctionPointerType)(void *, const char *, va_list); | 1713 | /** |
1714 | * Signature of the MHD custom logger function. | ||
1715 | * | ||
1716 | * @param cls closure | ||
1717 | * @param format format string | ||
1718 | * @param va arguments to the format string (fprintf-style) | ||
1719 | */ | ||
1720 | typedef void (*VfprintfFunctionPointerType)(void *cls, | ||
1721 | const char *format, | ||
1722 | va_list va); | ||
1700 | 1723 | ||
1701 | 1724 | ||
1702 | /** | 1725 | /** |
@@ -2009,7 +2032,7 @@ create_socket (int domain, int type, int protocol) | |||
2009 | 2032 | ||
2010 | /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo | 2033 | /* use SOCK_STREAM rather than ai_socktype: some getaddrinfo |
2011 | * implementations do not set ai_socktype, e.g. RHL6.2. */ | 2034 | * implementations do not set ai_socktype, e.g. RHL6.2. */ |
2012 | fd = SOCKET(domain, ctype, protocol); | 2035 | fd = SOCKET (domain, ctype, protocol); |
2013 | if ( (-1 == fd) && (EINVAL == errno) && (0 != sock_cloexec) ) | 2036 | if ( (-1 == fd) && (EINVAL == errno) && (0 != sock_cloexec) ) |
2014 | { | 2037 | { |
2015 | sock_cloexec = 0; | 2038 | sock_cloexec = 0; |
@@ -2090,6 +2113,7 @@ MHD_start_daemon_va (unsigned int options, | |||
2090 | socklen_t addrlen; | 2113 | socklen_t addrlen; |
2091 | unsigned int i; | 2114 | unsigned int i; |
2092 | int res_thread_create; | 2115 | int res_thread_create; |
2116 | int use_pipe; | ||
2093 | 2117 | ||
2094 | if ((port == 0) || (dh == NULL)) | 2118 | if ((port == 0) || (dh == NULL)) |
2095 | return NULL; | 2119 | return NULL; |
@@ -2116,10 +2140,15 @@ MHD_start_daemon_va (unsigned int options, | |||
2116 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; | 2140 | retVal->pool_size = MHD_POOL_SIZE_DEFAULT; |
2117 | retVal->unescape_callback = &MHD_http_unescape; | 2141 | retVal->unescape_callback = &MHD_http_unescape; |
2118 | retVal->connection_timeout = 0; /* no timeout */ | 2142 | retVal->connection_timeout = 0; /* no timeout */ |
2119 | #ifndef HAVE_LISTEN_SHUTDOWN | ||
2120 | retVal->wpipe[0] = -1; | 2143 | retVal->wpipe[0] = -1; |
2121 | retVal->wpipe[1] = -1; | 2144 | retVal->wpipe[1] = -1; |
2122 | if (0 != PIPE (retVal->wpipe)) | 2145 | #ifdef HAVE_LISTEN_SHUTDOWN |
2146 | use_pipe = (0 != (retVal->options & MHD_USE_NO_LISTEN_SOCKET)); | ||
2147 | #else | ||
2148 | use_pipe = 1; /* yes, must use pipe to signal shutdown */ | ||
2149 | #endif | ||
2150 | if ( (use_pipe) && | ||
2151 | (0 != PIPE (retVal->wpipe)) ) | ||
2123 | { | 2152 | { |
2124 | #if HAVE_MESSAGES | 2153 | #if HAVE_MESSAGES |
2125 | FPRINTF(stderr, | 2154 | FPRINTF(stderr, |
@@ -2143,7 +2172,6 @@ MHD_start_daemon_va (unsigned int options, | |||
2143 | return NULL; | 2172 | return NULL; |
2144 | } | 2173 | } |
2145 | #endif | 2174 | #endif |
2146 | #endif | ||
2147 | #ifdef DAUTH_SUPPORT | 2175 | #ifdef DAUTH_SUPPORT |
2148 | retVal->digest_auth_rand_size = 0; | 2176 | retVal->digest_auth_rand_size = 0; |
2149 | retVal->digest_auth_random = NULL; | 2177 | retVal->digest_auth_random = NULL; |
@@ -2155,13 +2183,13 @@ MHD_start_daemon_va (unsigned int options, | |||
2155 | retVal->custom_error_log_cls = stderr; | 2183 | retVal->custom_error_log_cls = stderr; |
2156 | #endif | 2184 | #endif |
2157 | #if HTTPS_SUPPORT | 2185 | #if HTTPS_SUPPORT |
2158 | if (options & MHD_USE_SSL) | 2186 | if (0 != (options & MHD_USE_SSL)) |
2159 | { | 2187 | { |
2160 | /* lock MHD_gnutls_global mutex since it uses reference counting */ | 2188 | /* lock MHD_gnutls_global mutex since it uses reference counting */ |
2161 | if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex)) | 2189 | if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex)) |
2162 | { | 2190 | { |
2163 | #if HAVE_MESSAGES | 2191 | #if HAVE_MESSAGES |
2164 | MHD_DLOG (retVal, "Failed to aquire gnutls mutex\n"); | 2192 | MHD_DLOG (retVal, "Failed to acquire gnutls mutex\n"); |
2165 | #endif | 2193 | #endif |
2166 | mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); | 2194 | mhd_panic (mhd_panic_cls, __FILE__, __LINE__, NULL); |
2167 | } | 2195 | } |
@@ -2258,8 +2286,10 @@ MHD_start_daemon_va (unsigned int options, | |||
2258 | goto free_and_fail; | 2286 | goto free_and_fail; |
2259 | } | 2287 | } |
2260 | #endif | 2288 | #endif |
2261 | if (retVal->socket_fd == -1) | 2289 | if ( (-1 == retVal->socket_fd) && |
2290 | (0 == (retVal->options & MHD_USE_NO_LISTEN_SOCKET)) ) | ||
2262 | { | 2291 | { |
2292 | /* try to open listen socket */ | ||
2263 | if ((options & MHD_USE_IPv6) != 0) | 2293 | if ((options & MHD_USE_IPv6) != 0) |
2264 | #if HAVE_INET6 | 2294 | #if HAVE_INET6 |
2265 | socket_fd = create_socket (PF_INET6, SOCK_STREAM, 0); | 2295 | socket_fd = create_socket (PF_INET6, SOCK_STREAM, 0); |
@@ -2403,7 +2433,8 @@ MHD_start_daemon_va (unsigned int options, | |||
2403 | MHD_DLOG (retVal, | 2433 | MHD_DLOG (retVal, |
2404 | "MHD failed to initialize IP connection limit mutex\n"); | 2434 | "MHD failed to initialize IP connection limit mutex\n"); |
2405 | #endif | 2435 | #endif |
2406 | CLOSE (socket_fd); | 2436 | if (-1 != socket_fd) |
2437 | CLOSE (socket_fd); | ||
2407 | goto free_and_fail; | 2438 | goto free_and_fail; |
2408 | } | 2439 | } |
2409 | if (0 != pthread_mutex_init (&retVal->cleanup_connection_mutex, NULL)) | 2440 | if (0 != pthread_mutex_init (&retVal->cleanup_connection_mutex, NULL)) |
@@ -2413,7 +2444,8 @@ MHD_start_daemon_va (unsigned int options, | |||
2413 | "MHD failed to initialize IP connection limit mutex\n"); | 2444 | "MHD failed to initialize IP connection limit mutex\n"); |
2414 | #endif | 2445 | #endif |
2415 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); | 2446 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); |
2416 | CLOSE (socket_fd); | 2447 | if (-1 != socket_fd) |
2448 | CLOSE (socket_fd); | ||
2417 | goto free_and_fail; | 2449 | goto free_and_fail; |
2418 | } | 2450 | } |
2419 | 2451 | ||
@@ -2425,7 +2457,8 @@ MHD_start_daemon_va (unsigned int options, | |||
2425 | MHD_DLOG (retVal, | 2457 | MHD_DLOG (retVal, |
2426 | "Failed to initialize TLS support\n"); | 2458 | "Failed to initialize TLS support\n"); |
2427 | #endif | 2459 | #endif |
2428 | CLOSE (socket_fd); | 2460 | if (-1 != socket_fd) |
2461 | CLOSE (socket_fd); | ||
2429 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); | 2462 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); |
2430 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); | 2463 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); |
2431 | goto free_and_fail; | 2464 | goto free_and_fail; |
@@ -2434,6 +2467,7 @@ MHD_start_daemon_va (unsigned int options, | |||
2434 | if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || | 2467 | if ( ( (0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || |
2435 | ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) && | 2468 | ( (0 != (options & MHD_USE_SELECT_INTERNALLY)) && |
2436 | (0 == retVal->worker_pool_size)) ) && | 2469 | (0 == retVal->worker_pool_size)) ) && |
2470 | (0 == (retVal->options & MHD_USE_NO_LISTEN_SOCKET)) && | ||
2437 | (0 != (res_thread_create = | 2471 | (0 != (res_thread_create = |
2438 | create_thread (&retVal->pid, retVal, &MHD_select_thread, retVal)))) | 2472 | create_thread (&retVal->pid, retVal, &MHD_select_thread, retVal)))) |
2439 | { | 2473 | { |
@@ -2444,10 +2478,12 @@ MHD_start_daemon_va (unsigned int options, | |||
2444 | #endif | 2478 | #endif |
2445 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); | 2479 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); |
2446 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); | 2480 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); |
2447 | CLOSE (socket_fd); | 2481 | if (-1 != socket_fd) |
2482 | CLOSE (socket_fd); | ||
2448 | goto free_and_fail; | 2483 | goto free_and_fail; |
2449 | } | 2484 | } |
2450 | if (retVal->worker_pool_size > 0) | 2485 | if ( (retVal->worker_pool_size > 0) && |
2486 | (0 == (retVal->options & MHD_USE_NO_LISTEN_SOCKET)) ) | ||
2451 | { | 2487 | { |
2452 | #ifndef MINGW | 2488 | #ifndef MINGW |
2453 | int sk_flags; | 2489 | int sk_flags; |
@@ -2535,7 +2571,8 @@ thread_failed: | |||
2535 | MHD_USE_SELECT_INTERNALLY mode. */ | 2571 | MHD_USE_SELECT_INTERNALLY mode. */ |
2536 | if (i == 0) | 2572 | if (i == 0) |
2537 | { | 2573 | { |
2538 | CLOSE (socket_fd); | 2574 | if (-1 != socket_fd) |
2575 | CLOSE (socket_fd); | ||
2539 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); | 2576 | pthread_mutex_destroy (&retVal->cleanup_connection_mutex); |
2540 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); | 2577 | pthread_mutex_destroy (&retVal->per_ip_connection_mutex); |
2541 | if (NULL != retVal->worker_pool) | 2578 | if (NULL != retVal->worker_pool) |
@@ -2653,16 +2690,25 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
2653 | fd = daemon->socket_fd; | 2690 | fd = daemon->socket_fd; |
2654 | daemon->socket_fd = -1; | 2691 | daemon->socket_fd = -1; |
2655 | /* Prepare workers for shutdown */ | 2692 | /* Prepare workers for shutdown */ |
2656 | for (i = 0; i < daemon->worker_pool_size; ++i) | 2693 | if (NULL != daemon->worker_pool) |
2657 | { | 2694 | { |
2658 | daemon->worker_pool[i].shutdown = MHD_YES; | 2695 | /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */ |
2659 | daemon->worker_pool[i].socket_fd = -1; | 2696 | for (i = 0; i < daemon->worker_pool_size; ++i) |
2697 | { | ||
2698 | daemon->worker_pool[i].shutdown = MHD_YES; | ||
2699 | daemon->worker_pool[i].socket_fd = -1; | ||
2700 | } | ||
2660 | } | 2701 | } |
2661 | #ifdef HAVE_LISTEN_SHUTDOWN | ||
2662 | SHUTDOWN (fd, SHUT_RDWR); | ||
2663 | #else | ||
2664 | if (daemon->wpipe[1] != -1) | 2702 | if (daemon->wpipe[1] != -1) |
2665 | WRITE (daemon->wpipe[1], "e", 1); | 2703 | { |
2704 | WRITE (daemon->wpipe[1], "e", 1); | ||
2705 | } | ||
2706 | #ifdef HAVE_LISTEN_SHUTDOWN | ||
2707 | else | ||
2708 | { | ||
2709 | /* fd must not be -1 here, otherwise we'd have used the wpipe */ | ||
2710 | SHUTDOWN (fd, SHUT_RDWR); | ||
2711 | } | ||
2666 | #endif | 2712 | #endif |
2667 | #if DEBUG_CLOSE | 2713 | #if DEBUG_CLOSE |
2668 | #if HAVE_MESSAGES | 2714 | #if HAVE_MESSAGES |
@@ -2672,40 +2718,47 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
2672 | 2718 | ||
2673 | 2719 | ||
2674 | /* Signal workers to stop and clean them up */ | 2720 | /* Signal workers to stop and clean them up */ |
2675 | for (i = 0; i < daemon->worker_pool_size; ++i) | 2721 | if (NULL != daemon->worker_pool) |
2676 | { | 2722 | { |
2677 | if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused))) | 2723 | /* MHD_USE_NO_LISTEN_SOCKET disables thread pools, hence we need to check */ |
2724 | for (i = 0; i < daemon->worker_pool_size; ++i) | ||
2678 | { | 2725 | { |
2726 | if (0 != (rc = pthread_join (daemon->worker_pool[i].pid, &unused))) | ||
2727 | { | ||
2679 | #if HAVE_MESSAGES | 2728 | #if HAVE_MESSAGES |
2680 | MHD_DLOG (daemon, "Failed to join a thread: %s\n", | 2729 | MHD_DLOG (daemon, "Failed to join a thread: %s\n", |
2681 | STRERROR (rc)); | 2730 | STRERROR (rc)); |
2682 | #endif | 2731 | #endif |
2683 | abort(); | 2732 | abort(); |
2733 | } | ||
2734 | close_all_connections (&daemon->worker_pool[i]); | ||
2684 | } | 2735 | } |
2685 | close_all_connections (&daemon->worker_pool[i]); | 2736 | free (daemon->worker_pool); |
2686 | } | 2737 | } |
2687 | free (daemon->worker_pool); | 2738 | else |
2688 | |||
2689 | /* clean up master threads */ | ||
2690 | if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || | ||
2691 | ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) | ||
2692 | && (0 == daemon->worker_pool_size))) | ||
2693 | { | 2739 | { |
2694 | if (0 != (rc = pthread_join (daemon->pid, &unused))) | 2740 | /* clean up master threads */ |
2741 | if ((0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) || | ||
2742 | ((0 != (daemon->options & MHD_USE_SELECT_INTERNALLY)) | ||
2743 | && (0 == daemon->worker_pool_size))) | ||
2695 | { | 2744 | { |
2745 | if (0 != (rc = pthread_join (daemon->pid, &unused))) | ||
2746 | { | ||
2696 | #if HAVE_MESSAGES | 2747 | #if HAVE_MESSAGES |
2697 | MHD_DLOG (daemon, "Failed to join a thread: %s\n", | 2748 | MHD_DLOG (daemon, "Failed to join a thread: %s\n", |
2698 | STRERROR (rc)); | 2749 | STRERROR (rc)); |
2699 | #endif | 2750 | #endif |
2700 | abort(); | 2751 | abort(); |
2752 | } | ||
2701 | } | 2753 | } |
2702 | } | 2754 | } |
2703 | close_all_connections (daemon); | 2755 | close_all_connections (daemon); |
2704 | CLOSE (fd); | 2756 | if (-1 != fd) |
2757 | CLOSE (fd); | ||
2705 | 2758 | ||
2706 | /* TLS clean up */ | 2759 | /* TLS clean up */ |
2707 | #if HTTPS_SUPPORT | 2760 | #if HTTPS_SUPPORT |
2708 | if (daemon->options & MHD_USE_SSL) | 2761 | if (0 != (daemon->options & MHD_USE_SSL)) |
2709 | { | 2762 | { |
2710 | gnutls_priority_deinit (daemon->priority_cache); | 2763 | gnutls_priority_deinit (daemon->priority_cache); |
2711 | if (daemon->x509_cred) | 2764 | if (daemon->x509_cred) |
@@ -2714,7 +2767,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
2714 | if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex)) | 2767 | if (0 != pthread_mutex_lock (&MHD_gnutls_init_mutex)) |
2715 | { | 2768 | { |
2716 | #if HAVE_MESSAGES | 2769 | #if HAVE_MESSAGES |
2717 | MHD_DLOG (daemon, "Failed to aquire gnutls mutex\n"); | 2770 | MHD_DLOG (daemon, "Failed to acquire gnutls mutex\n"); |
2718 | #endif | 2771 | #endif |
2719 | abort(); | 2772 | abort(); |
2720 | } | 2773 | } |
@@ -2735,8 +2788,7 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
2735 | pthread_mutex_destroy (&daemon->per_ip_connection_mutex); | 2788 | pthread_mutex_destroy (&daemon->per_ip_connection_mutex); |
2736 | pthread_mutex_destroy (&daemon->cleanup_connection_mutex); | 2789 | pthread_mutex_destroy (&daemon->cleanup_connection_mutex); |
2737 | 2790 | ||
2738 | #ifndef HAVE_LISTEN_SHUTDOWN | 2791 | if (-1 != daemon->wpipe[1]) |
2739 | if (daemon->wpipe[1] != -1) | ||
2740 | { | 2792 | { |
2741 | char c; | 2793 | char c; |
2742 | 2794 | ||
@@ -2746,7 +2798,6 @@ MHD_stop_daemon (struct MHD_Daemon *daemon) | |||
2746 | CLOSE (daemon->wpipe[0]); | 2798 | CLOSE (daemon->wpipe[0]); |
2747 | CLOSE (daemon->wpipe[1]); | 2799 | CLOSE (daemon->wpipe[1]); |
2748 | } | 2800 | } |
2749 | #endif | ||
2750 | 2801 | ||
2751 | free (daemon); | 2802 | free (daemon); |
2752 | } | 2803 | } |
@@ -2770,7 +2821,7 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon, | |||
2770 | { | 2821 | { |
2771 | case MHD_DAEMON_INFO_LISTEN_FD: | 2822 | case MHD_DAEMON_INFO_LISTEN_FD: |
2772 | return (const union MHD_DaemonInfo *) &daemon->socket_fd; | 2823 | return (const union MHD_DaemonInfo *) &daemon->socket_fd; |
2773 | default: | 2824 | default: |
2774 | return NULL; | 2825 | return NULL; |
2775 | }; | 2826 | }; |
2776 | } | 2827 | } |
@@ -2791,7 +2842,8 @@ MHD_get_daemon_info (struct MHD_Daemon *daemon, | |||
2791 | * @param cb new error handler | 2842 | * @param cb new error handler |
2792 | * @param cls passed to error handler | 2843 | * @param cls passed to error handler |
2793 | */ | 2844 | */ |
2794 | void MHD_set_panic_func (MHD_PanicCallback cb, void *cls) | 2845 | void |
2846 | MHD_set_panic_func (MHD_PanicCallback cb, void *cls) | ||
2795 | { | 2847 | { |
2796 | mhd_panic = cb; | 2848 | mhd_panic = cb; |
2797 | mhd_panic_cls = cls; | 2849 | mhd_panic_cls = cls; |