aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2017-02-26 23:34:20 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2017-02-26 23:46:51 +0300
commitdd2d724c197d6fb5c3d676ae786763190ef278c5 (patch)
tree6110ca2562bb737820dc21cd29e1910a1674a9e7 /src/microhttpd/daemon.c
parent3edd4bfa7f87f5970fc701b0772eeadc2f076df9 (diff)
downloadlibmicrohttpd-dd2d724c197d6fb5c3d676ae786763190ef278c5.tar.gz
libmicrohttpd-dd2d724c197d6fb5c3d676ae786763190ef278c5.zip
Reworked handling "already ready" situations:
* busy-waiting for write if TLS connection is in MHD_EVENT_LOOP_INFO_WRITE mode and data is pending in TLS buffers * removed calculation of number of TLS read-ready connections * simplified and unified processing if any connection is in MHD_EVENT_LOOP_INFO_BLOCK mode
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c106
1 files changed, 56 insertions, 50 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index b52f05e7..b93367b8 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -428,11 +428,6 @@ recv_tls_adapter (struct MHD_Connection *connection,
428{ 428{
429 ssize_t res; 429 ssize_t res;
430 430
431 if (connection->tls_read_ready)
432 {
433 connection->daemon->num_tls_read_ready--;
434 connection->tls_read_ready = false;
435 }
436 res = gnutls_record_recv (connection->tls_session, 431 res = gnutls_record_recv (connection->tls_session,
437 other, 432 other,
438 (i > SSIZE_MAX) ? SSIZE_MAX : i); 433 (i > SSIZE_MAX) ? SSIZE_MAX : i);
@@ -451,13 +446,13 @@ recv_tls_adapter (struct MHD_Connection *connection,
451 disrupted); set errno to something caller will interpret 446 disrupted); set errno to something caller will interpret
452 correctly as a hard error */ 447 correctly as a hard error */
453 MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_); 448 MHD_socket_set_error_ (MHD_SCKT_ECONNRESET_);
449 connection->tls_read_ready = false;
454 return res; 450 return res;
455 } 451 }
456 if ((size_t)res == i) 452
457 { 453 /* Check whether TLS buffers still have some unread data. */
458 connection->tls_read_ready = true; 454 connection->tls_read_ready = ( ((size_t)res == i) &&
459 connection->daemon->num_tls_read_ready++; 455 (0 != gnutls_record_check_pending (connection->tls_session)) );
460 }
461 return res; 456 return res;
462} 457}
463 458
@@ -951,6 +946,23 @@ call_handlers (struct MHD_Connection *con,
951 ret = con->idle_handler (con); 946 ret = con->idle_handler (con);
952 } 947 }
953 } 948 }
949
950 /* All connection's data and states are processed for this turn.
951 * If connection already has more data to be processed - use
952 * zero timeout for next select()/poll(). */
953 /* Thread-per-connection do not need global zero timeout as
954 * connections are processed individually. */
955 if ( (!con->daemon->data_already_pending) &&
956 (0 == (con->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
957 {
958 if (MHD_EVENT_LOOP_INFO_BLOCK == con->event_loop_info)
959 con->daemon->data_already_pending = true;
960#ifdef HTTPS_SUPPORT
961 else if ( (con->tls_read_ready) &&
962 (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) )
963 con->daemon->data_already_pending = true;
964#endif /* HTTPS_SUPPORT */
965 }
954 return ret; 966 return ret;
955} 967}
956 968
@@ -1061,7 +1073,6 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1061 if (0 < gnutls_record_check_pending (urh->connection->tls_session)) 1073 if (0 < gnutls_record_check_pending (urh->connection->tls_session))
1062 { 1074 {
1063 urh->connection->tls_read_ready = true; 1075 urh->connection->tls_read_ready = true;
1064 urh->connection->daemon->has_tls_recv_ready = true;
1065 } 1076 }
1066 } 1077 }
1067 else if (0 >= res) 1078 else if (0 >= res)
@@ -1238,6 +1249,13 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
1238 } 1249 }
1239 } 1250 }
1240 1251
1252 /* Check whether data is present in TLS buffers
1253 * and incoming forward buffer have some space. */
1254 if ( (urh->connection->tls_read_ready) &&
1255 (urh->in_buffer_used < urh->in_buffer_size) &&
1256 (0 == (urh->connection->daemon->options & MHD_USE_THREAD_PER_CONNECTION)) )
1257 urh->connection->daemon->data_already_pending = true;
1258
1241 if ( (urh->connection->daemon->shutdown) && 1259 if ( (urh->connection->daemon->shutdown) &&
1242 ( (0 != urh->out_buffer_size) || 1260 ( (0 != urh->out_buffer_size) ||
1243 (0 != urh->out_buffer_used) ) ) 1261 (0 != urh->out_buffer_used) ) )
@@ -1312,7 +1330,8 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1312 { 1330 {
1313 struct timeval* tvp; 1331 struct timeval* tvp;
1314 struct timeval tv; 1332 struct timeval tv;
1315 if (con->tls_read_ready) 1333 if ( (con->tls_read_ready) &&
1334 (urh->in_buffer_used < urh->in_buffer_size))
1316 { /* No need to wait if incoming data is already pending in TLS buffers. */ 1335 { /* No need to wait if incoming data is already pending in TLS buffers. */
1317 tv.tv_sec = 0; 1336 tv.tv_sec = 0;
1318 tv.tv_usec = 0; 1337 tv.tv_usec = 0;
@@ -1378,7 +1397,8 @@ thread_main_connection_upgrade (struct MHD_Connection *con)
1378 if (0 != urh->in_buffer_used) 1397 if (0 != urh->in_buffer_used)
1379 p[1].events |= POLLOUT; 1398 p[1].events |= POLLOUT;
1380 1399
1381 if (con->tls_read_ready) 1400 if ( (con->tls_read_ready) &&
1401 (urh->in_buffer_used < urh->in_buffer_size))
1382 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */ 1402 timeout = 0; /* No need to wait if incoming data is already pending in TLS buffers. */
1383 else 1403 else
1384 timeout = UINT_MAX; 1404 timeout = UINT_MAX;
@@ -1548,15 +1568,20 @@ thread_main_handle_connection (void *data)
1548 } 1568 }
1549 1569
1550 tvp = NULL; 1570 tvp = NULL;
1571
1572 if ( (MHD_EVENT_LOOP_INFO_BLOCK == con->event_loop_info)
1551#ifdef HTTPS_SUPPORT 1573#ifdef HTTPS_SUPPORT
1552 if (con->tls_read_ready) 1574 || ( (con->tls_read_ready) &&
1575 (MHD_EVENT_LOOP_INFO_READ == con->event_loop_info) )
1576#endif /* HTTPS_SUPPORT */
1577 )
1553 { 1578 {
1554 /* do not block (more data may be inside of TLS buffers waiting for us) */ 1579 /* do not block: more data may be inside of TLS buffers waiting or
1580 * application must provide response data */
1555 tv.tv_sec = 0; 1581 tv.tv_sec = 0;
1556 tv.tv_usec = 0; 1582 tv.tv_usec = 0;
1557 tvp = &tv; 1583 tvp = &tv;
1558 } 1584 }
1559#endif /* HTTPS_SUPPORT */
1560 if ( (NULL == tvp) && 1585 if ( (NULL == tvp) &&
1561 (timeout > 0) ) 1586 (timeout > 0) )
1562 { 1587 {
@@ -1609,9 +1634,6 @@ thread_main_handle_connection (void *data)
1609 &maxsock, 1634 &maxsock,
1610 FD_SETSIZE)) 1635 FD_SETSIZE))
1611 err_state = true; 1636 err_state = true;
1612 tv.tv_sec = 0;
1613 tv.tv_usec = 0;
1614 tvp = &tv;
1615 break; 1637 break;
1616 case MHD_EVENT_LOOP_INFO_CLEANUP: 1638 case MHD_EVENT_LOOP_INFO_CLEANUP:
1617 /* how did we get here!? */ 1639 /* how did we get here!? */
@@ -1691,9 +1713,6 @@ thread_main_handle_connection (void *data)
1691 break; 1713 break;
1692 case MHD_EVENT_LOOP_INFO_BLOCK: 1714 case MHD_EVENT_LOOP_INFO_BLOCK:
1693 p[0].events |= MHD_POLL_EVENTS_ERR_DISC; 1715 p[0].events |= MHD_POLL_EVENTS_ERR_DISC;
1694 tv.tv_sec = 0;
1695 tv.tv_usec = 0;
1696 tvp = &tv;
1697 break; 1716 break;
1698 case MHD_EVENT_LOOP_INFO_CLEANUP: 1717 case MHD_EVENT_LOOP_INFO_CLEANUP:
1699 /* how did we get here!? */ 1718 /* how did we get here!? */
@@ -2905,15 +2924,13 @@ MHD_get_timeout (struct MHD_Daemon *daemon,
2905 return MHD_NO; 2924 return MHD_NO;
2906 } 2925 }
2907 2926
2908#ifdef HTTPS_SUPPORT 2927 if (daemon->data_already_pending)
2909 if (0 != daemon->num_tls_read_ready || daemon->has_tls_recv_ready)
2910 { 2928 {
2911 /* if there is any TLS connection with data ready for 2929 /* Some data already waiting to be processed. */
2912 reading, we must not block in the event loop */
2913 *timeout = 0; 2930 *timeout = 0;
2914 return MHD_YES; 2931 return MHD_YES;
2915 } 2932 }
2916#endif /* HTTPS_SUPPORT */ 2933
2917#ifdef EPOLL_SUPPORT 2934#ifdef EPOLL_SUPPORT
2918 if ( (0 != (daemon->options & MHD_USE_EPOLL)) && 2935 if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
2919 (NULL != daemon->eready_head) ) 2936 (NULL != daemon->eready_head) )
@@ -3009,6 +3026,10 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
3009 unsigned int mask = MHD_ALLOW_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNAL_THREAD | 3026 unsigned int mask = MHD_ALLOW_SUSPEND_RESUME | MHD_USE_EPOLL_INTERNAL_THREAD |
3010 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_POLL_INTERNAL_THREAD; 3027 MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_POLL_INTERNAL_THREAD;
3011 3028
3029 /* Reset. New value will be set when connections are processed. */
3030 /* Note: no-op for thread-per-connection as it is always false in that mode. */
3031 daemon->data_already_pending = false;
3032
3012 /* Clear ITC to avoid spinning select */ 3033 /* Clear ITC to avoid spinning select */
3013 /* Do it before any other processing so new signals 3034 /* Do it before any other processing so new signals
3014 will trigger select again and will be processed */ 3035 will trigger select again and will be processed */
@@ -3017,14 +3038,6 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
3017 read_fd_set)) ) 3038 read_fd_set)) )
3018 MHD_itc_clear_ (daemon->itc); 3039 MHD_itc_clear_ (daemon->itc);
3019 3040
3020#ifdef HTTPS_SUPPORT
3021 /* Reset TLS read-ready.
3022 * New value will be set by read handlers. */
3023 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3024 (0 != (daemon->options & MHD_USE_TLS)) )
3025 daemon->has_tls_recv_ready = 0;
3026#endif /* HTTPS_SUPPORT */
3027
3028 /* Resuming external connections when using an extern mainloop */ 3041 /* Resuming external connections when using an extern mainloop */
3029 if (MHD_ALLOW_SUSPEND_RESUME == (daemon->options & mask)) 3042 if (MHD_ALLOW_SUSPEND_RESUME == (daemon->options & mask))
3030 resume_suspended_connections (daemon); 3043 resume_suspended_connections (daemon);
@@ -3364,7 +3377,6 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3364 break; 3377 break;
3365 case MHD_EVENT_LOOP_INFO_BLOCK: 3378 case MHD_EVENT_LOOP_INFO_BLOCK:
3366 p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC; 3379 p[poll_server+i].events |= MHD_POLL_EVENTS_ERR_DISC;
3367 timeout = 0;
3368 break; 3380 break;
3369 case MHD_EVENT_LOOP_INFO_CLEANUP: 3381 case MHD_EVENT_LOOP_INFO_CLEANUP:
3370 timeout = 0; /* clean up "pos" immediately */ 3382 timeout = 0; /* clean up "pos" immediately */
@@ -3412,6 +3424,10 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3412 free(p); 3424 free(p);
3413 return MHD_NO; 3425 return MHD_NO;
3414 } 3426 }
3427
3428 /* Reset. New value will be set when connections are processed. */
3429 daemon->data_already_pending = false;
3430
3415 /* handle ITC FD */ 3431 /* handle ITC FD */
3416 /* do it before any other processing so 3432 /* do it before any other processing so
3417 new signals will be processed in next loop */ 3433 new signals will be processed in next loop */
@@ -3419,14 +3435,6 @@ MHD_poll_all (struct MHD_Daemon *daemon,
3419 (0 != (p[poll_itc_idx].revents & POLLIN)) ) 3435 (0 != (p[poll_itc_idx].revents & POLLIN)) )
3420 MHD_itc_clear_ (daemon->itc); 3436 MHD_itc_clear_ (daemon->itc);
3421 3437
3422#ifdef HTTPS_SUPPORT
3423 /* Reset TLS read-ready.
3424 * New value will be set by read handlers. */
3425 if ( (0 == (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) &&
3426 (0 != (daemon->options & MHD_USE_TLS)) )
3427 daemon->has_tls_recv_ready = 0;
3428#endif /* HTTPS_SUPPORT */
3429
3430 /* handle shutdown */ 3438 /* handle shutdown */
3431 if (daemon->shutdown) 3439 if (daemon->shutdown)
3432 { 3440 {
@@ -3816,12 +3824,10 @@ MHD_epoll (struct MHD_Daemon *daemon,
3816 else 3824 else
3817 timeout_ms = 0; 3825 timeout_ms = 0;
3818 3826
3819#ifdef HTTPS_SUPPORT 3827 /* Reset. New value will be set when connections are processed. */
3820 /* Reset TLS read-ready. 3828 /* Note: Used mostly for uniformity here as same situation is
3821 * New value will be set by read handlers. */ 3829 * signaled in epoll mode by non-empty eready DLL. */
3822 if ( 0 != (daemon->options & MHD_USE_TLS) ) 3830 daemon->data_already_pending = false;
3823 daemon->has_tls_recv_ready = false;
3824#endif /* HTTPS_SUPPORT */
3825 3831
3826 /* drain 'epoll' event queue; need to iterate as we get at most 3832 /* drain 'epoll' event queue; need to iterate as we get at most
3827 MAX_EVENTS in one system call here; in practice this should 3833 MAX_EVENTS in one system call here; in practice this should