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.c281
1 files changed, 173 insertions, 108 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 5646fcfb..e0d0b522 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -681,82 +681,179 @@ MHD_get_fdset (struct MHD_Daemon *daemon,
681 * @param urh upgrade handle to wait for 681 * @param urh upgrade handle to wait for
682 * @param[out] rs read set to initialize 682 * @param[out] rs read set to initialize
683 * @param[out] ws write set to initialize 683 * @param[out] ws write set to initialize
684 * @param[out] es except set to initialize
684 * @param[out] max_fd maximum FD to update 685 * @param[out] max_fd maximum FD to update
685 * @param fd_setsize value of FD_SETSIZE 686 * @param fd_setsize value of FD_SETSIZE
686 * @return #MHD_YES on success, #MHD_NO on error 687 * @return true on success, false on error
687 */ 688 */
688static int 689static bool
689urh_to_fdset (struct MHD_UpgradeResponseHandle *urh, 690urh_to_fdset (struct MHD_UpgradeResponseHandle *urh,
690 fd_set *rs, 691 fd_set *rs,
691 fd_set *ws, 692 fd_set *ws,
693 fd_set *es,
692 MHD_socket *max_fd, 694 MHD_socket *max_fd,
693 unsigned int fd_setsize) 695 unsigned int fd_setsize)
694{ 696{
695 if ( (urh->out_buffer_used < urh->out_buffer_size) && 697 const MHD_socket conn_sckt = urh->connection->socket_fd;
696 (MHD_INVALID_SOCKET != urh->mhd.socket) && 698 const MHD_socket mhd_sckt = urh->mhd.socket;
697 (! MHD_add_to_fd_set_ (urh->mhd.socket, 699 bool res = true;
698 rs, 700
699 max_fd, 701 if (MHD_INVALID_SOCKET != conn_sckt)
700 fd_setsize)) ) 702 {
701 return MHD_NO; 703 if ( (urh->in_buffer_used < urh->in_buffer_size) &&
702 if ( (0 != urh->in_buffer_used) && 704 (! MHD_add_to_fd_set_ (conn_sckt,
703 (! urh->was_closed) && 705 rs,
704 (MHD_INVALID_SOCKET != urh->mhd.socket) && 706 max_fd,
705 (! MHD_add_to_fd_set_ (urh->mhd.socket, 707 fd_setsize)) )
706 ws, 708 res = false;
707 max_fd, 709 if ( (0 != urh->out_buffer_used) &&
708 fd_setsize)) ) 710 (! MHD_add_to_fd_set_ (conn_sckt,
709 return MHD_NO; 711 ws,
710 if ( (urh->in_buffer_used < urh->in_buffer_size) && 712 max_fd,
711 (! urh->was_closed) && 713 fd_setsize)) )
712 (MHD_INVALID_SOCKET != urh->connection->socket_fd) && 714 res = false;
713 (! MHD_add_to_fd_set_ (urh->connection->socket_fd, 715 if (0 != urh->in_buffer_size)
714 rs, 716 MHD_add_to_fd_set_ (conn_sckt,
715 max_fd, 717 es,
716 fd_setsize)) ) 718 max_fd,
717 return MHD_NO; 719 fd_setsize);
718 if ( (0 != urh->out_buffer_used) && 720 }
719 (MHD_INVALID_SOCKET != urh->connection->socket_fd) && 721 if (MHD_INVALID_SOCKET != mhd_sckt)
720 (! MHD_add_to_fd_set_ (urh->connection->socket_fd, 722 {
721 ws, 723 if ( (urh->out_buffer_used < urh->out_buffer_size) &&
722 max_fd, 724 (! MHD_add_to_fd_set_ (mhd_sckt,
723 fd_setsize)) ) 725 rs,
724 return MHD_NO; 726 max_fd,
725 return MHD_YES; 727 fd_setsize)) )
728 res = false;
729 if ( (0 != urh->in_buffer_used) &&
730 (! MHD_add_to_fd_set_ (mhd_sckt,
731 ws,
732 max_fd,
733 fd_setsize)) )
734 res = false;
735 if (0 != urh->out_buffer_size)
736 MHD_add_to_fd_set_ (mhd_sckt,
737 es,
738 max_fd,
739 fd_setsize);
740 }
741
742 return res;
726} 743}
727 744
728 745
729/** 746/**
730 * Update the @a urh based on the ready FDs in the @a rs and @a ws. 747 * Update the @a urh based on the ready FDs in
748 * the @a rs, @a ws, and @a es.
731 * 749 *
732 * @param urh upgrade handle to update 750 * @param urh upgrade handle to update
733 * @param rs read result from select() 751 * @param rs read result from select()
734 * @param ws write result from select() 752 * @param ws write result from select()
753 * @param ws except result from select()
735 */ 754 */
736static void 755static void
737urh_from_fdset (struct MHD_UpgradeResponseHandle *urh, 756urh_from_fdset (struct MHD_UpgradeResponseHandle *urh,
738 const fd_set *rs, 757 const fd_set *rs,
739 const fd_set *ws) 758 const fd_set *ws,
759 const fd_set *es,)
740{ 760{
741 const MHD_socket mhd_sckt = urh->mhd.socket;
742 const MHD_socket conn_sckt = urh->connection->socket_fd; 761 const MHD_socket conn_sckt = urh->connection->socket_fd;
762 const MHD_socket mhd_sckt = urh->mhd.socket;
763
764 urh->app.celi = MHD_EPOLL_STATE_UNREADY;
765 urh->mhd.celi = MHD_EPOLL_STATE_UNREADY;
766
767 if (MHD_INVALID_SOCKET != conn_sckt)
768 {
769 if (FD_ISSET (conn_sckt, rs))
770 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
771 if (FD_ISSET (conn_sckt, ws))
772 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
773 if (FD_ISSET (conn_sckt, es))
774 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
775 }
776 if ((MHD_INVALID_SOCKET != mhd_sckt))
777 {
778 if (FD_ISSET (mhd_sckt, rs))
779 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
780 if (FD_ISSET (mhd_sckt, ws))
781 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
782 if (FD_ISSET (mhd_sckt, es))
783 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
784 }
785}
786
787
788/**
789 * Set required 'event' members in 'pollfd' elements,
790 * assuming that @a p[0].fd is MHD side of socketpair
791 * and @a p[1].fd is TLS connected socket.
792 *
793 * @param urh upgrade handle to watch for
794 * @param p pollfd array to update
795 */
796static void
797urh_update_pollfd(struct MHD_UpgradeResponseHandle *urh,
798 struct pollfd p[2])
799{
800 p[0].events = 0;
801 p[1].events = 0;
802 if (urh->in_buffer_used < urh->in_buffer_size)
803 p[0].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
804 if (0 != urh->out_buffer_used)
805 p[0].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
806 if (0 != urh->in_buffer_size)
807 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
808 if (urh->out_buffer_used < urh->out_buffer_size)
809 p[1].events |= POLLIN | MHD_POLL_EVENTS_ERR_DISC;
810 if (0 != urh->in_buffer_used)
811 p[1].events |= POLLOUT | MHD_POLL_EVENTS_ERR_DISC;
812 if (0 != urh->out_buffer_size)
813 p[1].events |= MHD_POLL_EVENTS_ERR_DISC;
814}
815
743 816
744 if ((MHD_INVALID_SOCKET != conn_sckt) && 817/**
745 FD_ISSET (conn_sckt, rs)) 818 * Set @a p to watch for @a urh.
819 *
820 * @param urh upgrade handle to watch for
821 * @param p pollfd array to set
822 */
823static void
824urh_to_pollfd(struct MHD_UpgradeResponseHandle *urh,
825 struct pollfd p[2])
826{
827 p[0].fd = urh->connection->socket_fd;
828 p[1].fd = urh->mhd.socket;
829 urh_update_pollfd(urh, p);
830}
831
832
833/**
834 * Update ready state in @a urh based on pollfd.
835 * @param urh upgrade handle to update
836 * @param p 'poll()' processed pollfd.
837 */
838static void
839urh_from_pollfd(struct MHD_UpgradeResponseHandle *urh,
840 struct pollfd p[2])
841{
842 if (0 != (p[0].revents & POLLIN))
746 urh->app.celi |= MHD_EPOLL_STATE_READ_READY; 843 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
747 if ((MHD_INVALID_SOCKET != conn_sckt) && 844 if (0 != (p[0].revents & POLLOUT))
748 FD_ISSET (conn_sckt, ws))
749 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY; 845 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
750 if ((MHD_INVALID_SOCKET != mhd_sckt) && 846 if (0 != (p[0].revents & MHD_POLL_REVENTS_ERR_DISC))
751 FD_ISSET (mhd_sckt, rs)) 847 urh->app.celi |= MHD_EPOLL_STATE_ERROR;
848 if (0 != (p[1].revents & POLLIN))
752 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY; 849 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
753 if ((MHD_INVALID_SOCKET != mhd_sckt) && 850 if (0 != (p[1].revents & POLLOUT))
754 FD_ISSET (mhd_sckt, ws))
755 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY; 851 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
852 if (0 != (p[1].revents & MHD_POLL_REVENTS_ERR_DISC))
853 urh->mhd.celi |= MHD_EPOLL_STATE_ERROR;
756} 854}
757#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 855#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
758 856
759
760/** 857/**
761 * Obtain the `select()` sets for this daemon. 858 * Obtain the `select()` sets for this daemon.
762 * Daemon's FDs will be added to fd_sets. To get only 859 * Daemon's FDs will be added to fd_sets. To get only
@@ -891,6 +988,7 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
891 urh_to_fdset (urh, 988 urh_to_fdset (urh,
892 read_fd_set, 989 read_fd_set,
893 write_fd_set, 990 write_fd_set,
991 except_fd_set,
894 max_fd, 992 max_fd,
895 fd_setsize)) 993 fd_setsize))
896 result = MHD_NO; 994 result = MHD_NO;
@@ -1362,19 +1460,22 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1362 /* use select */ 1460 /* use select */
1363 fd_set rs; 1461 fd_set rs;
1364 fd_set ws; 1462 fd_set ws;
1463 fd_set es;
1365 MHD_socket max_fd; 1464 MHD_socket max_fd;
1366 int num_ready; 1465 int num_ready;
1367 int result; 1466 bool result;
1368 1467
1369 FD_ZERO (&rs); 1468 FD_ZERO (&rs);
1370 FD_ZERO (&ws); 1469 FD_ZERO (&ws);
1470 FD_ZERO (&es);
1371 max_fd = MHD_INVALID_SOCKET; 1471 max_fd = MHD_INVALID_SOCKET;
1372 result = urh_to_fdset (urh, 1472 result = urh_to_fdset (urh,
1373 &rs, 1473 &rs,
1374 &ws, 1474 &ws,
1475 &es,
1375 &max_fd, 1476 &max_fd,
1376 FD_SETSIZE); 1477 FD_SETSIZE);
1377 if (MHD_NO == result) 1478 if (! result)
1378 { 1479 {
1379#ifdef HAVE_MESSAGES 1480#ifdef HAVE_MESSAGES
1380 MHD_DLOG (con->daemon, 1481 MHD_DLOG (con->daemon,
@@ -1399,7 +1500,7 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1399 num_ready = MHD_SYS_select_ (max_fd + 1, 1500 num_ready = MHD_SYS_select_ (max_fd + 1,
1400 &rs, 1501 &rs,
1401 &ws, 1502 &ws,
1402 NULL, 1503 &es,
1403 tvp); 1504 tvp);
1404 } 1505 }
1405 else 1506 else
@@ -1420,7 +1521,8 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1420 } 1521 }
1421 urh_from_fdset (urh, 1522 urh_from_fdset (urh,
1422 &rs, 1523 &rs,
1423 &ws); 1524 &ws
1525 &es);
1424 process_urh (urh); 1526 process_urh (urh);
1425 if ( (0 == urh->in_buffer_size) && 1527 if ( (0 == urh->in_buffer_size) &&
1426 (0 == urh->out_buffer_size) && 1528 (0 == urh->out_buffer_size) &&
@@ -1433,38 +1535,29 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1433 else if (0 != (daemon->options & MHD_USE_TLS)) 1535 else if (0 != (daemon->options & MHD_USE_TLS))
1434 { 1536 {
1435 /* use poll() */ 1537 /* use poll() */
1538 struct pollfd p[2];
1539 memset (p,
1540 0,
1541 sizeof (p));
1542 p[0].fd = urh->connection->socket_fd;
1543 p[1].fd = urh->mhd.socket;
1436 1544
1437 while ( (MHD_CONNECTION_UPGRADE == con->state) || 1545 while ( (MHD_CONNECTION_UPGRADE == con->state) ||
1438 (0 != urh->out_buffer_used) ) 1546 (0 != urh->out_buffer_used) )
1439 { 1547 {
1440 struct pollfd p[2]; 1548 int timeout;
1441 unsigned int timeout;
1442 1549
1443 memset (p, 1550 urh_update_pollfd(urh, p);
1444 0,
1445 sizeof (struct pollfd) * 2);
1446 p[0].fd = urh->connection->socket_fd;
1447 p[1].fd = urh->mhd.socket;
1448 if (urh->in_buffer_used < urh->in_buffer_size)
1449 p[0].events |= POLLIN;
1450 if (0 != urh->out_buffer_used)
1451 p[0].events |= POLLOUT;
1452 if (urh->out_buffer_used < urh->out_buffer_size)
1453 p[1].events |= POLLIN;
1454 if (0 != urh->in_buffer_used)
1455 p[1].events |= POLLOUT;
1456 1551
1457 if ( (con->tls_read_ready) && 1552 if ( (con->tls_read_ready) &&
1458 (urh->in_buffer_used < urh->in_buffer_size)) 1553 (urh->in_buffer_used < urh->in_buffer_size))
1459 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */ 1554 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1460 else 1555 else
1461 timeout = UINT_MAX; 1556 timeout = -1;
1462 1557
1463 /* FIXME: does this check really needed? */ 1558 if (MHD_sys_poll_ (p,
1464 if ( (0 != (p[0].events | p[1].events)) && 1559 2,
1465 (MHD_sys_poll_ (p, 1560 timeout) < 0)
1466 2,
1467 timeout) < 0) )
1468 { 1561 {
1469 const int err = MHD_socket_get_error_ (); 1562 const int err = MHD_socket_get_error_ ();
1470 1563
@@ -1477,14 +1570,7 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1477#endif 1570#endif
1478 break; 1571 break;
1479 } 1572 }
1480 if (0 != (p[0].revents & POLLIN)) 1573 urh_from_pollfd(urh, p);
1481 urh->app.celi |= MHD_EPOLL_STATE_READ_READY;
1482 if (0 != (p[0].revents & POLLOUT))
1483 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
1484 if (0 != (p[1].revents & POLLIN))
1485 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
1486 if (0 != (p[1].revents & POLLOUT))
1487 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
1488 process_urh (urh); 1574 process_urh (urh);
1489 if ( (0 == urh->in_buffer_size) && 1575 if ( (0 == urh->in_buffer_size) &&
1490 (0 == urh->out_buffer_size) && 1576 (0 == urh->out_buffer_size) &&
@@ -3153,7 +3239,8 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
3153 /* update urh state based on select() output */ 3239 /* update urh state based on select() output */
3154 urh_from_fdset (urh, 3240 urh_from_fdset (urh,
3155 read_fd_set, 3241 read_fd_set,
3156 write_fd_set); 3242 write_fd_set,
3243 except_fd_set);
3157 /* call generic forwarding function for passing data */ 3244 /* call generic forwarding function for passing data */
3158 process_urh (urh); 3245 process_urh (urh);
3159 /* Finished forwarding? */ 3246 /* Finished forwarding? */
@@ -3448,18 +3535,8 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3448#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT) 3535#if defined(HTTPS_SUPPORT) && defined(UPGRADE_SUPPORT)
3449 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev) 3536 for (urh = daemon->urh_tail; NULL != urh; urh = urh->prev)
3450 { 3537 {
3451 p[poll_server+i].fd = urh->connection->socket_fd; 3538 urh_to_pollfd(urh, &(p[poll_server+i]));
3452 if (urh->in_buffer_used < urh->in_buffer_size) 3539 i += 2;
3453 p[poll_server+i].events |= POLLIN;
3454 if (0 != urh->out_buffer_used)
3455 p[poll_server+i].events |= POLLOUT;
3456 i++;
3457 p[poll_server+i].fd = urh->mhd.socket;
3458 if (urh->out_buffer_used < urh->out_buffer_size)
3459 p[poll_server+i].events |= POLLIN;
3460 if (0 != urh->in_buffer_used)
3461 p[poll_server+i].events |= POLLOUT;
3462 i++;
3463 } 3540 }
3464#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */ 3541#endif /* HTTPS_SUPPORT && UPGRADE_SUPPORT */
3465 if (0 == poll_server + num_connections) 3542 if (0 == poll_server + num_connections)
@@ -3528,23 +3605,11 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3528 * from 'daemon->urh_head' list. */ 3605 * from 'daemon->urh_head' list. */
3529 urhn = urh->prev; 3606 urhn = urh->prev;
3530 /* Check for fd mismatch. FIXME: required for safety? */ 3607 /* Check for fd mismatch. FIXME: required for safety? */
3531 if (p[poll_server+i].fd == urh->connection->socket_fd) 3608 if ((p[poll_server+i].fd != urh->connection->socket_fd) ||
3532 { 3609 (p[poll_server+i+1].fd != urh->mhd.socket))
3533 if (0 != (p[poll_server+i].revents & POLLIN)) 3610 break;
3534 urh->app.celi |= MHD_EPOLL_STATE_READ_READY; 3611 urh_from_pollfd(urh, &(p[poll_server+i]));
3535 if (0 != (p[poll_server+i].revents & POLLOUT)) 3612 i += 2;
3536 urh->app.celi |= MHD_EPOLL_STATE_WRITE_READY;
3537 }
3538 i++;
3539 /* Check for fd mismatch. FIXME: required for safety? */
3540 if (p[poll_server+i].fd == urh->mhd.socket)
3541 {
3542 if (0 != (p[poll_server+i].revents & POLLIN))
3543 urh->mhd.celi |= MHD_EPOLL_STATE_READ_READY;
3544 if (0 != (p[poll_server+i].revents & POLLOUT))
3545 urh->mhd.celi |= MHD_EPOLL_STATE_WRITE_READY;
3546 }
3547 i++;
3548 process_urh (urh); 3613 process_urh (urh);
3549 /* Finished forwarding? */ 3614 /* Finished forwarding? */
3550 if ( (0 == urh->in_buffer_size) && 3615 if ( (0 == urh->in_buffer_size) &&