summaryrefslogtreecommitdiff
path: root/src/microhttpd/daemon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/microhttpd/daemon.c')
-rw-r--r--src/microhttpd/daemon.c180
1 files changed, 86 insertions, 94 deletions
diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 5476f956..2c0e0a82 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -826,6 +826,62 @@ MHD_get_fdset2 (struct MHD_Daemon *daemon,
/**
+ * Call the handlers for a connection in the
+ * appropriate order based on the readiness as
+ * detected by the event loop.
+ *
+ * @param con connection to handle
+ * @param read_ready set if the socket is ready for reading
+ * @param write_ready set if the socket is ready for writing
+ * @param force_close set if a hard error was detected on the socket;
+ * if this information is not available, simply pass #MHD_NO
+ * @return #MHD_YES to continue normally,
+ * #MHD_NO if a serious error was encountered and the
+ * connection is to be closed.
+ */
+static int
+call_handlers (struct MHD_Connection *con,
+ int read_ready,
+ int write_ready,
+ int force_close)
+{
+ struct MHD_Daemon *daemon = con->daemon;
+ int had_response_before_idle;
+ int ret;
+
+#if HTTPS_SUPPORT
+ if (MHD_YES == con->tls_read_ready)
+ read_ready = MHD_YES;
+#endif
+ if (read_ready)
+ con->read_handler (con);
+ if (write_ready)
+ con->write_handler (con);
+ had_response_before_idle = (NULL != con->response);
+ if (force_close)
+ MHD_connection_close_ (con,
+ MHD_REQUEST_TERMINATED_WITH_ERROR);
+ ret = con->idle_handler (con);
+ /* If we're in TURBO mode, and got a response object,
+ try opportunistically to just call write immediately. */
+ if ( (! force_close) &&
+ (MHD_YES == ret) &&
+ (0 != (daemon->options & MHD_USE_EPOLL_TURBO)) &&
+ (NULL != con->response) &&
+ (MHD_NO == had_response_before_idle) )
+ {
+ /* first 'write' gets the header, then 'idle'
+ readies the body, then 2nd 'write' may send
+ the body. */
+ con->write_handler (con);
+ if (MHD_YES == (ret = con->idle_handler (con)))
+ con->write_handler (con);
+ }
+ return ret;
+}
+
+
+/**
* Main function of the thread that handles an individual
* connection when #MHD_USE_THREAD_PER_CONNECTION is set.
*
@@ -962,17 +1018,12 @@ MHD_handle_connection (void *data)
(FD_ISSET (spipe, &rs)) )
MHD_pipe_drain_ (spipe);
#endif
- /* call appropriate connection handler if necessary */
- if ( (FD_ISSET (con->socket_fd, &rs))
-#if HTTPS_SUPPORT
- || (MHD_YES == con->tls_read_ready)
-#endif
- )
- con->read_handler (con);
- if (FD_ISSET (con->socket_fd, &ws))
- con->write_handler (con);
- if (MHD_NO == con->idle_handler (con))
- goto exit;
+ if (MHD_NO ==
+ call_handlers (con,
+ FD_ISSET (con->socket_fd, &rs),
+ FD_ISSET (con->socket_fd, &ws),
+ MHD_NO))
+ goto exit;
}
#ifdef HAVE_POLL
else
@@ -1034,19 +1085,12 @@ MHD_handle_connection (void *data)
(0 != (p[1].revents & (POLLERR | POLLHUP))) )
MHD_pipe_drain_ (spipe);
#endif
- if ( (0 != (p[0].revents & POLLIN))
-#if HTTPS_SUPPORT
- || (MHD_YES == con->tls_read_ready)
-#endif
- )
- con->read_handler (con);
- if (0 != (p[0].revents & POLLOUT))
- con->write_handler (con);
- if (0 != (p[0].revents & (POLLERR | POLLHUP)))
- MHD_connection_close_ (con,
- MHD_REQUEST_TERMINATED_WITH_ERROR);
- if (MHD_NO == con->idle_handler (con))
- goto exit;
+ if (MHD_NO ==
+ call_handlers (con,
+ 0 != (p[0].revents & POLLIN),
+ 0 != (p[0].revents & POLLOUT),
+ 0 != (p[0].revents & (POLLERR | POLLHUP))))
+ goto exit;
}
#endif
}
@@ -1823,7 +1867,7 @@ resume_suspended_connections (struct MHD_Daemon *daemon)
MHD_PANIC ("Failed to acquire cleanup mutex\n");
if (MHD_NO != daemon->resuming)
next = daemon->suspended_connections_head;
-
+
/* Clear the flag *only* if connections will be resumed otherwise
it may accidentally clear flag that was set at the same time in
other thread (just after 'if (MHD_NO != daemon->resuming)' in
@@ -2310,33 +2354,10 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
ds = pos->socket_fd;
if (MHD_INVALID_SOCKET == ds)
continue;
- switch (pos->event_loop_info)
- {
- case MHD_EVENT_LOOP_INFO_READ:
- if ( (FD_ISSET (ds, read_fd_set))
-#if HTTPS_SUPPORT
- || (MHD_YES == pos->tls_read_ready)
-#endif
- )
- pos->read_handler (pos);
- break;
- case MHD_EVENT_LOOP_INFO_WRITE:
- if ( (FD_ISSET (ds, read_fd_set)) &&
- (pos->read_buffer_size > pos->read_buffer_offset) )
- pos->read_handler (pos);
- if (FD_ISSET (ds, write_fd_set))
- pos->write_handler (pos);
- break;
- case MHD_EVENT_LOOP_INFO_BLOCK:
- if ( (FD_ISSET (ds, read_fd_set)) &&
- (pos->read_buffer_size > pos->read_buffer_offset) )
- pos->read_handler (pos);
- break;
- case MHD_EVENT_LOOP_INFO_CLEANUP:
- /* should never happen */
- break;
- }
- pos->idle_handler (pos);
+ call_handlers (pos,
+ FD_ISSET (ds, read_fd_set),
+ FD_ISSET (ds, write_fd_set),
+ MHD_NO);
}
}
MHD_cleanup_connections (daemon);
@@ -2621,43 +2642,15 @@ MHD_poll_all (struct MHD_Daemon *daemon,
while (NULL != (pos = next))
{
next = pos->next;
- switch (pos->event_loop_info)
- {
- case MHD_EVENT_LOOP_INFO_READ:
- /* first, sanity checks */
- if (i >= num_connections)
- break; /* connection list changed somehow, retry later ... */
- if (p[poll_server+i].fd != pos->socket_fd)
- break; /* fd mismatch, something else happened, retry later ... */
- /* normal handling */
- if (0 != (p[poll_server+i].revents & POLLIN))
- pos->read_handler (pos);
- pos->idle_handler (pos);
- i++;
- break;
- case MHD_EVENT_LOOP_INFO_WRITE:
- /* first, sanity checks */
- if (i >= num_connections)
- break; /* connection list changed somehow, retry later ... */
- if (p[poll_server+i].fd != pos->socket_fd)
- break; /* fd mismatch, something else happened, retry later ... */
- /* normal handling */
- if (0 != (p[poll_server+i].revents & POLLIN))
- pos->read_handler (pos);
- if (0 != (p[poll_server+i].revents & POLLOUT))
- pos->write_handler (pos);
- pos->idle_handler (pos);
- i++;
- break;
- case MHD_EVENT_LOOP_INFO_BLOCK:
- if (0 != (p[poll_server+i].revents & POLLIN))
- pos->read_handler (pos);
- pos->idle_handler (pos);
- break;
- case MHD_EVENT_LOOP_INFO_CLEANUP:
- pos->idle_handler (pos);
- break;
- }
+ /* first, sanity checks */
+ if (i >= num_connections)
+ continue; /* connection list changed somehow, retry later ... */
+ if (p[poll_server+i].fd != pos->socket_fd)
+ continue; /* fd mismatch, something else happened, retry later ... */
+ call_handlers (pos,
+ 0 != (p[poll_server+i].revents & POLLIN),
+ 0 != (p[poll_server+i].revents & POLLOUT),
+ MHD_NO);
}
/* handle 'listen' FD */
if ( (-1 != poll_listen) &&
@@ -2934,11 +2927,10 @@ MHD_epoll (struct MHD_Daemon *daemon,
daemon->eready_tail,
pos);
pos->epoll_state &= ~MHD_EPOLL_STATE_IN_EREADY_EDLL;
- if (MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info)
- pos->read_handler (pos);
- if (MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info)
- pos->write_handler (pos);
- pos->idle_handler (pos);
+ call_handlers (pos,
+ MHD_EVENT_LOOP_INFO_READ == pos->event_loop_info,
+ MHD_EVENT_LOOP_INFO_WRITE == pos->event_loop_info,
+ MHD_NO);
}
/* Finally, handle timed-out connections; we need to do this here