aboutsummaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
authorEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-11-09 23:14:01 +0300
committerEvgeny Grin (Karlson2k) <k2k@narod.ru>2016-11-10 17:11:35 +0300
commit51c1f5e65bff0eee79d87874ee5b8f1514c38032 (patch)
tree58305e8749e7051492b99dbe0b41de198dd57b0a /src/microhttpd/daemon.c
parente05239e5c7c6d073fcc2500c59d3b1c39e44169d (diff)
downloadlibmicrohttpd-51c1f5e65bff0eee79d87874ee5b8f1514c38032.tar.gz
libmicrohttpd-51c1f5e65bff0eee79d87874ee5b8f1514c38032.zip
Use non-blocking sockets for fast responses
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c74
1 files changed, 39 insertions, 35 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index ae6aaeed..fda82836 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -889,8 +889,9 @@ call_handlers (struct MHD_Connection *con,
889 int force_close) 889 int force_close)
890{ 890{
891 struct MHD_Daemon *daemon = con->daemon; 891 struct MHD_Daemon *daemon = con->daemon;
892 int had_response_before_idle;
893 int ret; 892 int ret;
893 /* Initial state of connection. */
894 bool was_initing = (con->state == MHD_CONNECTION_INIT);
894 895
895#ifdef HTTPS_SUPPORT 896#ifdef HTTPS_SUPPORT
896 if (MHD_YES == con->tls_read_ready) 897 if (MHD_YES == con->tls_read_ready)
@@ -900,25 +901,37 @@ call_handlers (struct MHD_Connection *con,
900 con->read_handler (con); 901 con->read_handler (con);
901 if (write_ready) 902 if (write_ready)
902 con->write_handler (con); 903 con->write_handler (con);
903 had_response_before_idle = (NULL != con->response);
904 if (force_close) 904 if (force_close)
905 MHD_connection_close_ (con, 905 MHD_connection_close_ (con,
906 MHD_REQUEST_TERMINATED_WITH_ERROR); 906 MHD_REQUEST_TERMINATED_WITH_ERROR);
907 ret = con->idle_handler (con); 907 ret = con->idle_handler (con);
908 /* If we're in TURBO mode, and got a response object, 908
909 try opportunistically to just call write immediately. */ 909 /* Fast track for fast connections. */
910 if ( (! force_close) && 910 /* If full request was read by single read_handler() invocation
911 (MHD_YES == ret) && 911 and headers were completely prepared by single idle_handler()
912 (0 != (daemon->options & MHD_USE_EPOLL_TURBO)) && 912 then try not to wait for next sockets polling and send response
913 (NULL != con->response) && 913 immediately.
914 (MHD_NO == had_response_before_idle) ) 914 As writeability of socket was not checked and it may have
915 { 915 some data pending in system buffers, use this optimization
916 /* first 'write' gets the header, then 'idle' 916 only for non-blocking sockets. */
917 readies the body, then 2nd 'write' may send 917 if ( (MHD_NO != ret) &&
918 the body. */ 918 (was_initing) &&
919 (MHD_CONNECTION_HEADERS_SENDING == con->state) &&
920 (con->sk_nonblck) )
921 {
919 con->write_handler (con); 922 con->write_handler (con);
920 if (MHD_YES == (ret = con->idle_handler (con))) 923 /* If all headers were sent by single write_handler() - continue. */
921 con->write_handler (con); 924 if (MHD_CONNECTION_HEADERS_SENT == con->state)
925 {
926 ret = con->idle_handler (con);
927 if ( (MHD_NO != ret) &&
928 ( (MHD_CONNECTION_NORMAL_BODY_READY == con->state) ||
929 (MHD_CONNECTION_CHUNKED_BODY_READY == con->state) ) )
930 {
931 con->write_handler (con);
932 ret = con->idle_handler (con);
933 }
934 }
922 } 935 }
923 return ret; 936 return ret;
924} 937}
@@ -2126,28 +2139,16 @@ internal_add_connection (struct MHD_Daemon *daemon,
2126 connection->daemon = daemon; 2139 connection->daemon = daemon;
2127 connection->last_activity = MHD_monotonic_sec_counter(); 2140 connection->last_activity = MHD_monotonic_sec_counter();
2128 2141
2129 /* set default connection handlers */ 2142 if (0 == (daemon->options & MHD_USE_TLS))
2130 MHD_set_http_callbacks_ (connection);
2131 connection->recv_cls = &recv_param_adapter;
2132 connection->send_cls = &send_param_adapter;
2133
2134 if (0 == (connection->daemon->options & MHD_USE_EPOLL_TURBO))
2135 { 2143 {
2136 /* in turbo mode, we assume that non-blocking was already set 2144 /* set default connection handlers */
2137 by 'accept4' or whoever calls 'MHD_add_connection' */ 2145 MHD_set_http_callbacks_ (connection);
2138 if (! MHD_socket_nonblocking_ (connection->socket_fd)) 2146 connection->recv_cls = &recv_param_adapter;
2139 { 2147 connection->send_cls = &send_param_adapter;
2140#ifdef HAVE_MESSAGES
2141 MHD_DLOG (connection->daemon,
2142 _("Failed to set nonblocking mode on connection socket: %s\n"),
2143 MHD_socket_last_strerr_());
2144#endif
2145 }
2146 } 2148 }
2147 2149 else
2148#ifdef HTTPS_SUPPORT
2149 if (0 != (daemon->options & MHD_USE_TLS))
2150 { 2150 {
2151#ifdef HTTPS_SUPPORT
2151 connection->recv_cls = &recv_tls_adapter; 2152 connection->recv_cls = &recv_tls_adapter;
2152 connection->send_cls = &send_tls_adapter; 2153 connection->send_cls = &send_tls_adapter;
2153 connection->state = MHD_TLS_CONNECTION_INIT; 2154 connection->state = MHD_TLS_CONNECTION_INIT;
@@ -2192,8 +2193,11 @@ internal_add_connection (struct MHD_Daemon *daemon,
2192 if (daemon->https_mem_trust) 2193 if (daemon->https_mem_trust)
2193 gnutls_certificate_server_set_request (connection->tls_session, 2194 gnutls_certificate_server_set_request (connection->tls_session,
2194 GNUTLS_CERT_REQUEST); 2195 GNUTLS_CERT_REQUEST);
2196#else /* ! HTTPS_SUPPORT */
2197 goto cleanup;
2198#endif /* ! HTTPS_SUPPORT */
2195 } 2199 }
2196#endif /* HTTPS_SUPPORT */ 2200
2197 2201
2198 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION)) 2202 if (0 != (daemon->options & MHD_USE_THREAD_PER_CONNECTION))
2199 { 2203 {