|
|
|
@ -1436,6 +1436,57 @@ connection_state_machine_loop (request_st * const r, connection * const con)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
connection_set_fdevent_interest (request_st * const r, connection * const con)
|
|
|
|
|
{
|
|
|
|
|
if (con->fd < 0) return;
|
|
|
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
|
switch(r->state) {
|
|
|
|
|
case CON_STATE_READ:
|
|
|
|
|
n = FDEVENT_IN | FDEVENT_RDHUP;
|
|
|
|
|
break;
|
|
|
|
|
case CON_STATE_WRITE:
|
|
|
|
|
if (!chunkqueue_is_empty(con->write_queue)
|
|
|
|
|
&& 0 == con->is_writable && 0 == con->traffic_limit_reached)
|
|
|
|
|
n |= FDEVENT_OUT;
|
|
|
|
|
__attribute_fallthrough__
|
|
|
|
|
case CON_STATE_READ_POST:
|
|
|
|
|
if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN)
|
|
|
|
|
n |= FDEVENT_IN;
|
|
|
|
|
if (!(r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLRDHUP))
|
|
|
|
|
n |= FDEVENT_RDHUP;
|
|
|
|
|
break;
|
|
|
|
|
case CON_STATE_CLOSE:
|
|
|
|
|
n = FDEVENT_IN;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const int events = fdevent_fdnode_interest(con->fdn);
|
|
|
|
|
if (con->is_readable < 0) {
|
|
|
|
|
con->is_readable = 0;
|
|
|
|
|
n |= FDEVENT_IN;
|
|
|
|
|
}
|
|
|
|
|
if (con->is_writable < 0) {
|
|
|
|
|
con->is_writable = 0;
|
|
|
|
|
n |= FDEVENT_OUT;
|
|
|
|
|
}
|
|
|
|
|
if (events & FDEVENT_RDHUP)
|
|
|
|
|
n |= FDEVENT_RDHUP;
|
|
|
|
|
|
|
|
|
|
if (n == events) return;
|
|
|
|
|
|
|
|
|
|
/* update timestamps when enabling interest in events */
|
|
|
|
|
if ((n & FDEVENT_IN) && !(events & FDEVENT_IN))
|
|
|
|
|
con->read_idle_ts = log_epoch_secs;
|
|
|
|
|
if ((n & FDEVENT_OUT) && !(events & FDEVENT_OUT))
|
|
|
|
|
con->write_request_ts = log_epoch_secs;
|
|
|
|
|
fdevent_fdnode_event_set(con->srv->ev, con->fdn, n);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void connection_state_machine(connection *con) {
|
|
|
|
|
request_st * const r = &con->request;
|
|
|
|
|
const int log_state_handling = r->conf.log_state_handling;
|
|
|
|
@ -1452,57 +1503,7 @@ void connection_state_machine(connection *con) {
|
|
|
|
|
"state at exit: %d %s", con->fd, connection_get_state(r->state));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rc = 0;
|
|
|
|
|
switch(r->state) {
|
|
|
|
|
case CON_STATE_READ:
|
|
|
|
|
rc = FDEVENT_IN | FDEVENT_RDHUP;
|
|
|
|
|
break;
|
|
|
|
|
case CON_STATE_WRITE:
|
|
|
|
|
/* request write-fdevent only if we really need it
|
|
|
|
|
* - if we have data to write
|
|
|
|
|
* - if the socket is not writable yet
|
|
|
|
|
*/
|
|
|
|
|
if (!chunkqueue_is_empty(con->write_queue) &&
|
|
|
|
|
(con->is_writable == 0) &&
|
|
|
|
|
(con->traffic_limit_reached == 0)) {
|
|
|
|
|
rc |= FDEVENT_OUT;
|
|
|
|
|
}
|
|
|
|
|
/* fall through */
|
|
|
|
|
case CON_STATE_READ_POST:
|
|
|
|
|
if (r->conf.stream_request_body & FDEVENT_STREAM_REQUEST_POLLIN) {
|
|
|
|
|
rc |= FDEVENT_IN | FDEVENT_RDHUP;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case CON_STATE_CLOSE:
|
|
|
|
|
rc = FDEVENT_IN;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (con->fd >= 0) {
|
|
|
|
|
const int events = fdevent_fdnode_interest(con->fdn);
|
|
|
|
|
if (con->is_readable < 0) {
|
|
|
|
|
con->is_readable = 0;
|
|
|
|
|
rc |= FDEVENT_IN;
|
|
|
|
|
}
|
|
|
|
|
if (con->is_writable < 0) {
|
|
|
|
|
con->is_writable = 0;
|
|
|
|
|
rc |= FDEVENT_OUT;
|
|
|
|
|
}
|
|
|
|
|
if (events & FDEVENT_RDHUP) {
|
|
|
|
|
rc |= FDEVENT_RDHUP;
|
|
|
|
|
}
|
|
|
|
|
if (rc != events) {
|
|
|
|
|
/* update timestamps when enabling interest in events */
|
|
|
|
|
if ((rc & FDEVENT_IN) && !(events & FDEVENT_IN)) {
|
|
|
|
|
con->read_idle_ts = log_epoch_secs;
|
|
|
|
|
}
|
|
|
|
|
if ((rc & FDEVENT_OUT) && !(events & FDEVENT_OUT)) {
|
|
|
|
|
con->write_request_ts = log_epoch_secs;
|
|
|
|
|
}
|
|
|
|
|
fdevent_fdnode_event_set(con->srv->ev, con->fdn, rc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
connection_set_fdevent_interest(r, con);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void connection_check_timeout (connection * const con, const time_t cur_ts) {
|
|
|
|
|