|
|
|
@ -130,11 +130,17 @@ static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) {
|
|
|
|
|
joblist_append(srv, con);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void connection_keepalive_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
|
|
|
connection *con = (connection*) w->data;
|
|
|
|
|
UNUSED(loop); UNUSED(revents);
|
|
|
|
|
con_put(con->sock.srv, con);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connection* connection_new(server *srv) {
|
|
|
|
|
connection *con = g_slice_new0(connection);
|
|
|
|
|
UNUSED(srv);
|
|
|
|
|
|
|
|
|
|
con->state = CON_STATE_REQUEST_START;
|
|
|
|
|
con->state = CON_STATE_DEAD;
|
|
|
|
|
con->response_headers_sent = FALSE;
|
|
|
|
|
con->expect_100_cont = FALSE;
|
|
|
|
|
|
|
|
|
@ -158,11 +164,16 @@ connection* connection_new(server *srv) {
|
|
|
|
|
physical_init(&con->physical);
|
|
|
|
|
response_init(&con->response);
|
|
|
|
|
|
|
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
|
con->keep_alive_data.timeout = 0;
|
|
|
|
|
my_ev_init(&con->keep_alive_data.watcher, connection_keepalive_cb);
|
|
|
|
|
con->keep_alive_data.watcher.data = con;
|
|
|
|
|
|
|
|
|
|
return con;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void connection_reset(server *srv, connection *con) {
|
|
|
|
|
con->state = CON_STATE_REQUEST_START;
|
|
|
|
|
con->state = CON_STATE_DEAD;
|
|
|
|
|
con->response_headers_sent = FALSE;
|
|
|
|
|
con->expect_100_cont = FALSE;
|
|
|
|
|
|
|
|
|
@ -192,10 +203,39 @@ void connection_reset(server *srv, connection *con) {
|
|
|
|
|
request_reset(&con->request);
|
|
|
|
|
physical_reset(&con->physical);
|
|
|
|
|
response_reset(&con->response);
|
|
|
|
|
|
|
|
|
|
if (con->keep_alive_data.link) {
|
|
|
|
|
g_queue_delete_link(&srv->keep_alive_queue, con->keep_alive_data.link);
|
|
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
|
}
|
|
|
|
|
con->keep_alive_data.timeout = 0;
|
|
|
|
|
ev_timer_stop(srv->loop, &con->keep_alive_data.watcher);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void server_check_keepalive(server *srv);
|
|
|
|
|
void connection_reset_keep_alive(server *srv, connection *con) {
|
|
|
|
|
con->state = CON_STATE_REQUEST_START;
|
|
|
|
|
ev_timer_stop(srv->loop, &con->keep_alive_data.watcher);
|
|
|
|
|
{
|
|
|
|
|
guint timeout = GPOINTER_TO_INT(CORE_OPTION(CORE_OPTION_MAX_KEEP_ALIVE_IDLE));
|
|
|
|
|
if (timeout == 0) {
|
|
|
|
|
con_put(srv, con);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (timeout >= srv->keep_alive_queue_timeout) {
|
|
|
|
|
/* queue is sorted by con->keep_alive_data.timeout */
|
|
|
|
|
gboolean need_start = (0 == srv->keep_alive_queue.length);
|
|
|
|
|
con->keep_alive_data.timeout = ev_now((srv)->loop) + srv->keep_alive_queue_timeout;
|
|
|
|
|
g_queue_push_tail(&srv->keep_alive_queue, con);
|
|
|
|
|
con->keep_alive_data.link = g_queue_peek_tail_link(&srv->keep_alive_queue);
|
|
|
|
|
if (need_start)
|
|
|
|
|
server_check_keepalive(srv);
|
|
|
|
|
} else {
|
|
|
|
|
ev_timer_set(&con->keep_alive_data.watcher, timeout, 0);
|
|
|
|
|
ev_timer_start(srv->loop, &con->keep_alive_data.watcher);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
con->state = CON_STATE_KEEP_ALIVE;
|
|
|
|
|
con->response_headers_sent = FALSE;
|
|
|
|
|
con->expect_100_cont = FALSE;
|
|
|
|
|
|
|
|
|
@ -218,7 +258,7 @@ void connection_reset_keep_alive(server *srv, connection *con) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void connection_free(server *srv, connection *con) {
|
|
|
|
|
con->state = CON_STATE_REQUEST_START;
|
|
|
|
|
con->state = CON_STATE_DEAD;
|
|
|
|
|
con->response_headers_sent = FALSE;
|
|
|
|
|
con->expect_100_cont = FALSE;
|
|
|
|
|
|
|
|
|
@ -249,6 +289,13 @@ void connection_free(server *srv, connection *con) {
|
|
|
|
|
physical_clear(&con->physical);
|
|
|
|
|
response_clear(&con->response);
|
|
|
|
|
|
|
|
|
|
if (con->keep_alive_data.link) {
|
|
|
|
|
g_queue_delete_link(&srv->keep_alive_queue, con->keep_alive_data.link);
|
|
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
|
}
|
|
|
|
|
con->keep_alive_data.timeout = 0;
|
|
|
|
|
ev_timer_stop(srv->loop, &con->keep_alive_data.watcher);
|
|
|
|
|
|
|
|
|
|
g_slice_free(connection, con);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -264,6 +311,26 @@ void connection_state_machine(server *srv, connection *con) {
|
|
|
|
|
gboolean done = FALSE;
|
|
|
|
|
do {
|
|
|
|
|
switch (con->state) {
|
|
|
|
|
case CON_STATE_DEAD:
|
|
|
|
|
done = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case CON_STATE_KEEP_ALIVE:
|
|
|
|
|
if (con->raw_in->length > 0) {
|
|
|
|
|
/* stop keep alive timeout watchers */
|
|
|
|
|
if (con->keep_alive_data.link) {
|
|
|
|
|
g_queue_delete_link(&srv->keep_alive_queue, con->keep_alive_data.link);
|
|
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
|
}
|
|
|
|
|
con->keep_alive_data.timeout = 0;
|
|
|
|
|
ev_timer_stop(srv->loop, &con->keep_alive_data.watcher);
|
|
|
|
|
|
|
|
|
|
connection_set_state(srv, con, CON_STATE_REQUEST_START);
|
|
|
|
|
} else
|
|
|
|
|
done = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case CON_STATE_REQUEST_START:
|
|
|
|
|
connection_set_state(srv, con, CON_STATE_READ_REQUEST_HEADER);
|
|
|
|
|
action_enter(con, srv->mainaction);
|
|
|
|
|