2008-08-05 15:08:32 +00:00
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
#include "base.h"
|
2008-08-08 16:49:00 +00:00
|
|
|
#include "plugin_core.h"
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-09-09 00:22:21 +00:00
|
|
|
/* only call it from the worker context the con belongs to */
|
2008-09-24 16:59:49 +00:00
|
|
|
void worker_con_put(connection *con); /* worker.c */
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
static void parse_request_body(connection *con) {
|
2008-10-25 12:53:57 +00:00
|
|
|
if ((con->state > CON_STATE_HANDLE_MAINVR || con->mainvr->state >= VRS_READ_CONTENT) && !con->in->is_closed) {
|
|
|
|
ev_io_add_events(con->wrk->loop, &con->sock_watcher, EV_READ);
|
|
|
|
if (con->mainvr->request.content_length == -1) {
|
2008-08-06 18:46:42 +00:00
|
|
|
/* TODO: parse chunked encoded request body, filters */
|
2008-08-05 15:08:32 +00:00
|
|
|
chunkqueue_steal_all(con->in, con->raw_in);
|
2008-08-06 18:46:42 +00:00
|
|
|
} else {
|
2008-10-25 12:53:57 +00:00
|
|
|
if (con->in->bytes_in < con->mainvr->request.content_length) {
|
|
|
|
chunkqueue_steal_len(con->in, con->raw_in, con->mainvr->request.content_length - con->in->bytes_in);
|
|
|
|
}
|
|
|
|
if (con->in->bytes_in == con->mainvr->request.content_length) {
|
|
|
|
con->in->is_closed = TRUE;
|
|
|
|
ev_io_rem_events(con->wrk->loop, &con->sock_watcher, EV_READ);
|
2008-08-06 18:46:42 +00:00
|
|
|
}
|
|
|
|
}
|
2008-10-25 12:53:57 +00:00
|
|
|
} else {
|
|
|
|
ev_io_rem_events(con->wrk->loop, &con->sock_watcher, EV_READ);
|
2008-08-06 18:46:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
static void forward_response_body(connection *con) {
|
2008-10-25 12:53:57 +00:00
|
|
|
vrequest *vr = con->mainvr;
|
|
|
|
if (con->state >= CON_STATE_HANDLE_MAINVR) {
|
|
|
|
if (!con->response_headers_sent) {
|
|
|
|
con->response_headers_sent = TRUE;
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "%s", "write response headers");
|
|
|
|
}
|
|
|
|
response_send_headers(con);
|
2008-08-06 18:46:42 +00:00
|
|
|
}
|
2008-10-25 12:53:57 +00:00
|
|
|
|
|
|
|
chunkqueue_steal_all(con->raw_out, con->out);
|
|
|
|
if (con->out->is_closed) con->raw_out->is_closed = TRUE;
|
2008-08-06 18:46:42 +00:00
|
|
|
if (con->raw_out->length > 0) {
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_io_add_events(con->wrk->loop, &con->sock_watcher, EV_WRITE);
|
2008-08-06 18:46:42 +00:00
|
|
|
} else {
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_io_rem_events(con->wrk->loop, &con->sock_watcher, EV_WRITE);
|
2008-08-05 15:08:32 +00:00
|
|
|
}
|
2008-10-25 12:53:57 +00:00
|
|
|
} else {
|
|
|
|
ev_io_rem_events(con->wrk->loop, &con->sock_watcher, EV_WRITE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void connection_request_done(connection *con) {
|
|
|
|
vrequest *vr = con->mainvr;
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "response end (keep_alive = %i)", con->keep_alive);
|
|
|
|
}
|
|
|
|
|
|
|
|
plugins_handle_close(con);
|
|
|
|
|
|
|
|
if (con->keep_alive) {
|
|
|
|
connection_reset_keep_alive(con);
|
|
|
|
} else {
|
|
|
|
worker_con_put(con);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean check_response_done(connection *con) {
|
|
|
|
if (con->in->is_closed && con->raw_out->is_closed && 0 == con->raw_out->length) {
|
|
|
|
connection_request_done(con);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void connection_close(connection *con) {
|
|
|
|
vrequest *vr = con->mainvr;
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "%s", "connection closed");
|
|
|
|
}
|
|
|
|
|
|
|
|
plugins_handle_close(con);
|
|
|
|
|
|
|
|
worker_con_put(con);
|
|
|
|
}
|
|
|
|
|
|
|
|
void connection_error(connection *con) {
|
|
|
|
vrequest *vr = con->mainvr;
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "%s", "connection closed (error)");
|
|
|
|
}
|
|
|
|
|
|
|
|
plugins_handle_close(con);
|
|
|
|
|
|
|
|
worker_con_put(con);
|
|
|
|
}
|
|
|
|
|
|
|
|
void connection_internal_error(connection *con) {
|
|
|
|
vrequest *vr = con->mainvr;
|
|
|
|
if (con->response_headers_sent) {
|
|
|
|
VR_ERROR(vr, "%s", "Couldn't send '500 Internal Error': headers already sent");
|
|
|
|
connection_error(con);
|
|
|
|
} else {
|
|
|
|
vrequest_reset(con->mainvr);
|
|
|
|
http_headers_reset(con->mainvr->response.headers);
|
|
|
|
VR_ERROR(vr, "%s", "internal error");
|
|
|
|
con->mainvr->response.http_status = 500;
|
|
|
|
con->state = CON_STATE_WRITE;
|
|
|
|
forward_response_body(con);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean connection_handle_read(connection *con) {
|
|
|
|
vrequest *vr = con->mainvr;
|
|
|
|
if (con->raw_in->length == 0) return TRUE;
|
|
|
|
|
|
|
|
if (con->state == CON_STATE_KEEP_ALIVE) {
|
|
|
|
/* stop keep alive timeout watchers */
|
|
|
|
if (con->keep_alive_data.link) {
|
|
|
|
g_queue_delete_link(&con->wrk->keep_alive_queue, con->keep_alive_data.link);
|
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
}
|
|
|
|
con->keep_alive_data.timeout = 0;
|
|
|
|
ev_timer_stop(con->wrk->loop, &con->keep_alive_data.watcher);
|
|
|
|
|
|
|
|
con->state = CON_STATE_READ_REQUEST_HEADER;
|
2008-11-03 14:18:46 +00:00
|
|
|
con->ts = CUR_TS(con->wrk);
|
2008-10-25 12:53:57 +00:00
|
|
|
} else if (con->state == CON_STATE_REQUEST_START) {
|
|
|
|
con->state = CON_STATE_READ_REQUEST_HEADER;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (con->state == CON_STATE_READ_REQUEST_HEADER && con->mainvr->state == VRS_CLEAN) {
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "%s", "reading request header");
|
|
|
|
}
|
|
|
|
switch(http_request_parse(con->mainvr, &con->req_parser_ctx)) {
|
|
|
|
case HANDLER_FINISHED:
|
|
|
|
case HANDLER_GO_ON:
|
|
|
|
break; /* go on */
|
|
|
|
case HANDLER_WAIT_FOR_EVENT:
|
|
|
|
return TRUE;
|
|
|
|
case HANDLER_ERROR:
|
|
|
|
case HANDLER_COMEBACK: /* unexpected */
|
|
|
|
case HANDLER_WAIT_FOR_FD: /* unexpected */
|
|
|
|
/* unparsable header */
|
|
|
|
connection_error(con);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
con->wrk->stats.requests++;
|
|
|
|
|
|
|
|
/* headers ready */
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "%s", "validating request header");
|
|
|
|
}
|
|
|
|
if (!request_validate_header(con)) {
|
|
|
|
/* skip mainvr handling */
|
|
|
|
con->state = CON_STATE_WRITE;
|
|
|
|
con->keep_alive = FALSE;
|
|
|
|
con->in->is_closed = TRUE;
|
|
|
|
forward_response_body(con);
|
|
|
|
} else {
|
|
|
|
con->state = CON_STATE_HANDLE_MAINVR;
|
|
|
|
action_enter(con->mainvr, con->srv->mainaction);
|
|
|
|
vrequest_handle_request_headers(con->mainvr);
|
|
|
|
}
|
2008-08-05 15:08:32 +00:00
|
|
|
}
|
2008-10-25 12:53:57 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2008-08-05 15:08:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void connection_cb(struct ev_loop *loop, ev_io *w, int revents) {
|
2008-09-08 00:20:55 +00:00
|
|
|
connection *con = (connection*) w->data;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-08-06 18:46:42 +00:00
|
|
|
if (revents & EV_READ) {
|
2008-08-05 15:08:32 +00:00
|
|
|
if (con->in->is_closed) {
|
|
|
|
/* don't read the next request before current one is done */
|
2008-08-07 00:25:02 +00:00
|
|
|
ev_io_rem_events(loop, w, EV_READ);
|
2008-08-05 15:08:32 +00:00
|
|
|
} else {
|
2008-10-25 12:53:57 +00:00
|
|
|
switch (network_read(con->mainvr, w->fd, con->raw_in)) {
|
2008-08-05 15:08:32 +00:00
|
|
|
case NETWORK_STATUS_SUCCESS:
|
2008-10-25 12:53:57 +00:00
|
|
|
if (!connection_handle_read(con)) return;
|
2008-08-05 15:08:32 +00:00
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_FATAL_ERROR:
|
2008-09-08 00:20:55 +00:00
|
|
|
CON_ERROR(con, "%s", "network read fatal error");
|
2008-10-25 12:53:57 +00:00
|
|
|
connection_error(con);
|
|
|
|
return;
|
2008-08-05 15:08:32 +00:00
|
|
|
case NETWORK_STATUS_CONNECTION_CLOSE:
|
2008-08-07 14:50:36 +00:00
|
|
|
con->raw_in->is_closed = TRUE;
|
|
|
|
shutdown(w->fd, SHUT_RD);
|
2008-10-25 12:53:57 +00:00
|
|
|
connection_close(con);
|
|
|
|
return;
|
2008-08-05 15:08:32 +00:00
|
|
|
case NETWORK_STATUS_WAIT_FOR_EVENT:
|
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
|
2008-08-07 12:12:51 +00:00
|
|
|
/* TODO: aio */
|
2008-08-06 18:46:42 +00:00
|
|
|
ev_io_rem_events(loop, w, EV_READ);
|
2008-08-05 15:08:32 +00:00
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_WAIT_FOR_FD:
|
2008-08-07 12:12:51 +00:00
|
|
|
/* TODO: wait for fd */
|
2008-08-06 18:46:42 +00:00
|
|
|
ev_io_rem_events(loop, w, EV_READ);
|
2008-08-05 15:08:32 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-06 18:46:42 +00:00
|
|
|
if (revents & EV_WRITE) {
|
2008-10-25 12:53:57 +00:00
|
|
|
ev_io_rem_events(loop, w, EV_WRITE);
|
2008-08-05 15:08:32 +00:00
|
|
|
if (con->raw_out->length > 0) {
|
2008-10-25 12:53:57 +00:00
|
|
|
switch (network_write(con->mainvr, w->fd, con->raw_out)) {
|
2008-08-07 00:25:02 +00:00
|
|
|
case NETWORK_STATUS_SUCCESS:
|
2008-10-25 12:53:57 +00:00
|
|
|
vrequest_joblist_append(con->mainvr);
|
2008-08-07 00:25:02 +00:00
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_FATAL_ERROR:
|
2008-09-08 00:20:55 +00:00
|
|
|
CON_ERROR(con, "%s", "network write fatal error");
|
2008-10-25 12:53:57 +00:00
|
|
|
connection_error(con);
|
2008-08-07 00:25:02 +00:00
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_CONNECTION_CLOSE:
|
2008-10-25 12:53:57 +00:00
|
|
|
connection_close(con);
|
|
|
|
return;
|
2008-08-07 00:25:02 +00:00
|
|
|
case NETWORK_STATUS_WAIT_FOR_EVENT:
|
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_WAIT_FOR_AIO_EVENT:
|
2008-08-07 12:12:51 +00:00
|
|
|
/* TODO: aio */
|
2008-08-07 00:25:02 +00:00
|
|
|
break;
|
|
|
|
case NETWORK_STATUS_WAIT_FOR_FD:
|
2008-08-07 12:12:51 +00:00
|
|
|
/* TODO: wait for fd */
|
2008-08-07 00:25:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-08-05 15:08:32 +00:00
|
|
|
}
|
|
|
|
}
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
check_response_done(con);
|
2008-08-05 15:08:32 +00:00
|
|
|
}
|
|
|
|
|
2008-08-17 16:24:09 +00:00
|
|
|
static void connection_keepalive_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
|
|
|
connection *con = (connection*) w->data;
|
|
|
|
UNUSED(loop); UNUSED(revents);
|
2008-09-24 16:59:49 +00:00
|
|
|
worker_con_put(con);
|
2008-08-17 16:24:09 +00:00
|
|
|
}
|
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
static handler_t mainvr_handle_response_headers(vrequest *vr) {
|
|
|
|
connection *con = vr->con;
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_TRACE(vr, "%s", "read request/handle response header");
|
|
|
|
}
|
|
|
|
if (con->expect_100_cont) {
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_TRACE(vr, "%s", "send 100 Continue");
|
|
|
|
}
|
|
|
|
chunkqueue_append_mem(con->raw_out, CONST_STR_LEN("HTTP/1.1 100 Continue\r\n\r\n"));
|
|
|
|
con->expect_100_cont = FALSE;
|
|
|
|
ev_io_add_events(con->wrk->loop, &con->sock_watcher, EV_WRITE);
|
|
|
|
}
|
|
|
|
parse_request_body(con);
|
|
|
|
|
|
|
|
return HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
static handler_t mainvr_handle_response_body(vrequest *vr) {
|
|
|
|
connection *con = vr->con;
|
|
|
|
if (check_response_done(con)) return HANDLER_FINISHED;
|
|
|
|
|
|
|
|
if (CORE_OPTION(CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
CON_TRACE(con, "%s", "write response");
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_request_body(con);
|
|
|
|
forward_response_body(con);
|
|
|
|
|
|
|
|
if (check_response_done(con)) return HANDLER_FINISHED;
|
|
|
|
|
|
|
|
return HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
|
|
|
static handler_t mainvr_handle_response_error(vrequest *vr) {
|
|
|
|
connection_internal_error(vr->con);
|
|
|
|
return HANDLER_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static handler_t mainvr_handle_request_headers(vrequest *vr) {
|
|
|
|
/* start reading input */
|
|
|
|
parse_request_body(vr->con);
|
|
|
|
return HANDLER_GO_ON;
|
|
|
|
}
|
|
|
|
|
2008-09-24 16:59:49 +00:00
|
|
|
connection* connection_new(worker *wrk) {
|
|
|
|
server *srv = wrk->srv;
|
2008-08-05 15:08:32 +00:00
|
|
|
connection *con = g_slice_new0(connection);
|
2008-09-24 16:59:49 +00:00
|
|
|
con->wrk = wrk;
|
2008-09-08 00:20:55 +00:00
|
|
|
con->srv = srv;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-08-17 16:24:09 +00:00
|
|
|
con->state = CON_STATE_DEAD;
|
2008-08-06 18:46:42 +00:00
|
|
|
con->response_headers_sent = FALSE;
|
2008-08-06 23:44:09 +00:00
|
|
|
con->expect_100_cont = FALSE;
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_init(&con->sock_watcher, connection_cb);
|
|
|
|
ev_io_set(&con->sock_watcher, -1, 0);
|
|
|
|
con->sock_watcher.data = con;
|
2008-11-03 14:18:46 +00:00
|
|
|
con->remote_addr_str = g_string_sized_new(INET6_ADDRSTRLEN);
|
|
|
|
con->local_addr_str = g_string_sized_new(INET6_ADDRSTRLEN);
|
2008-08-06 18:46:42 +00:00
|
|
|
con->keep_alive = TRUE;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-08-07 14:50:36 +00:00
|
|
|
con->raw_in = chunkqueue_new();
|
|
|
|
con->raw_out = chunkqueue_new();
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-10-01 20:20:31 +00:00
|
|
|
con->options = g_slice_copy(srv->option_def_values->len * sizeof(option_value), srv->option_def_values->data);
|
2008-08-08 16:49:00 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
con->mainvr = vrequest_new(con,
|
|
|
|
mainvr_handle_response_headers,
|
|
|
|
mainvr_handle_response_body,
|
|
|
|
mainvr_handle_response_error,
|
|
|
|
mainvr_handle_request_headers);
|
|
|
|
http_request_parser_init(&con->req_parser_ctx, &con->mainvr->request, con->raw_in);
|
|
|
|
|
|
|
|
con->in = con->mainvr->vr_in;
|
|
|
|
con->out = con->mainvr->vr_out;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-08-17 16:24:09 +00:00
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
con->keep_alive_data.timeout = 0;
|
2008-08-17 19:27:09 +00:00
|
|
|
con->keep_alive_data.max_idle = 0;
|
2008-09-02 18:30:39 +00:00
|
|
|
ev_init(&con->keep_alive_data.watcher, connection_keepalive_cb);
|
2008-08-17 16:24:09 +00:00
|
|
|
con->keep_alive_data.watcher.data = con;
|
|
|
|
|
2008-08-05 15:08:32 +00:00
|
|
|
return con;
|
|
|
|
}
|
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
void connection_reset(connection *con) {
|
2008-08-17 16:24:09 +00:00
|
|
|
con->state = CON_STATE_DEAD;
|
2008-08-06 18:46:42 +00:00
|
|
|
con->response_headers_sent = FALSE;
|
2008-08-06 23:44:09 +00:00
|
|
|
con->expect_100_cont = FALSE;
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_io_stop(con->wrk->loop, &con->sock_watcher);
|
|
|
|
if (con->sock_watcher.fd != -1) {
|
2008-08-07 14:50:36 +00:00
|
|
|
if (con->raw_in->is_closed) { /* read already shutdown */
|
2008-09-08 00:20:55 +00:00
|
|
|
shutdown(con->sock_watcher.fd, SHUT_WR);
|
|
|
|
close(con->sock_watcher.fd);
|
2008-08-07 14:50:36 +00:00
|
|
|
} else {
|
2008-09-08 00:20:55 +00:00
|
|
|
worker_add_closing_socket(con->wrk, con->sock_watcher.fd);
|
2008-08-07 14:50:36 +00:00
|
|
|
}
|
2008-08-06 18:46:42 +00:00
|
|
|
}
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_io_set(&con->sock_watcher, -1, 0);
|
2008-08-05 15:08:32 +00:00
|
|
|
g_string_truncate(con->remote_addr_str, 0);
|
|
|
|
g_string_truncate(con->local_addr_str, 0);
|
2008-08-06 18:46:42 +00:00
|
|
|
con->keep_alive = TRUE;
|
|
|
|
|
2008-08-07 14:50:36 +00:00
|
|
|
chunkqueue_reset(con->raw_in);
|
|
|
|
chunkqueue_reset(con->raw_out);
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-10-01 20:20:31 +00:00
|
|
|
memcpy(con->options, con->srv->option_def_values->data, con->srv->option_def_values->len * sizeof(option_value));
|
2008-08-08 16:49:00 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
vrequest_reset(con->mainvr);
|
2008-09-29 15:07:53 +00:00
|
|
|
http_request_parser_reset(&con->req_parser_ctx);
|
2008-08-17 16:24:09 +00:00
|
|
|
|
|
|
|
if (con->keep_alive_data.link) {
|
2008-09-08 00:20:55 +00:00
|
|
|
g_queue_delete_link(&con->wrk->keep_alive_queue, con->keep_alive_data.link);
|
2008-08-17 16:24:09 +00:00
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
}
|
|
|
|
con->keep_alive_data.timeout = 0;
|
2008-08-17 19:27:09 +00:00
|
|
|
con->keep_alive_data.max_idle = 0;
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_timer_stop(con->wrk->loop, &con->keep_alive_data.watcher);
|
2008-11-03 14:18:46 +00:00
|
|
|
|
|
|
|
/* reset stats */
|
|
|
|
con->stats.bytes_in = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_in_5s = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_in_5s_diff = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_out = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_out_5s = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_out_5s_diff = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.last_avg = 0;
|
2008-08-06 18:46:42 +00:00
|
|
|
}
|
|
|
|
|
2008-08-17 16:24:09 +00:00
|
|
|
void server_check_keepalive(server *srv);
|
2008-09-08 00:20:55 +00:00
|
|
|
void connection_reset_keep_alive(connection *con) {
|
2008-10-25 12:53:57 +00:00
|
|
|
vrequest *vr = con->mainvr;
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_timer_stop(con->wrk->loop, &con->keep_alive_data.watcher);
|
2008-08-17 16:24:09 +00:00
|
|
|
{
|
2008-09-26 14:11:08 +00:00
|
|
|
con->keep_alive_data.max_idle = CORE_OPTION(CORE_OPTION_MAX_KEEP_ALIVE_IDLE).number;
|
2008-08-17 19:27:09 +00:00
|
|
|
if (con->keep_alive_data.max_idle == 0) {
|
2008-09-24 16:59:49 +00:00
|
|
|
worker_con_put(con);
|
2008-08-17 16:24:09 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-09-08 00:20:55 +00:00
|
|
|
if (con->keep_alive_data.max_idle >= con->srv->keep_alive_queue_timeout) {
|
2008-08-17 16:24:09 +00:00
|
|
|
/* queue is sorted by con->keep_alive_data.timeout */
|
2008-09-08 00:20:55 +00:00
|
|
|
gboolean need_start = (0 == con->wrk->keep_alive_queue.length);
|
|
|
|
con->keep_alive_data.timeout = ev_now(con->wrk->loop) + con->srv->keep_alive_queue_timeout;
|
|
|
|
g_queue_push_tail(&con->wrk->keep_alive_queue, con);
|
|
|
|
con->keep_alive_data.link = g_queue_peek_tail_link(&con->wrk->keep_alive_queue);
|
2008-08-17 16:24:09 +00:00
|
|
|
if (need_start)
|
2008-09-08 00:20:55 +00:00
|
|
|
worker_check_keepalive(con->wrk);
|
2008-08-17 16:24:09 +00:00
|
|
|
} else {
|
2008-08-17 19:27:09 +00:00
|
|
|
ev_timer_set(&con->keep_alive_data.watcher, con->keep_alive_data.max_idle, 0);
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_timer_start(con->wrk->loop, &con->keep_alive_data.watcher);
|
2008-08-17 16:24:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
con->state = CON_STATE_KEEP_ALIVE;
|
2008-08-06 18:46:42 +00:00
|
|
|
con->response_headers_sent = FALSE;
|
2008-08-06 23:44:09 +00:00
|
|
|
con->expect_100_cont = FALSE;
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_io_set_events(con->wrk->loop, &con->sock_watcher, EV_READ);
|
2008-08-06 18:46:42 +00:00
|
|
|
con->keep_alive = TRUE;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-08-07 14:50:36 +00:00
|
|
|
con->raw_out->is_closed = FALSE;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-10-01 20:20:31 +00:00
|
|
|
memcpy(con->options, con->srv->option_def_values->data, con->srv->option_def_values->len * sizeof(option_value));
|
2008-08-08 16:49:00 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
vrequest_reset(con->mainvr);
|
2008-09-29 15:07:53 +00:00
|
|
|
http_request_parser_reset(&con->req_parser_ctx);
|
2008-11-03 14:18:46 +00:00
|
|
|
|
|
|
|
con->ts = CUR_TS(con->wrk);
|
|
|
|
|
|
|
|
/* reset stats */
|
|
|
|
con->stats.bytes_in = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_in_5s = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_in_5s_diff = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_out = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_out_5s = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.bytes_out_5s_diff = G_GUINT64_CONSTANT(0);
|
|
|
|
con->stats.last_avg = 0;
|
2008-08-05 15:08:32 +00:00
|
|
|
}
|
|
|
|
|
2008-09-08 00:20:55 +00:00
|
|
|
void connection_free(connection *con) {
|
2008-08-17 16:24:09 +00:00
|
|
|
con->state = CON_STATE_DEAD;
|
2008-08-06 18:46:42 +00:00
|
|
|
con->response_headers_sent = FALSE;
|
2008-08-06 23:44:09 +00:00
|
|
|
con->expect_100_cont = FALSE;
|
2008-08-06 18:46:42 +00:00
|
|
|
|
2008-09-08 00:25:55 +00:00
|
|
|
if (con->wrk)
|
|
|
|
ev_io_stop(con->wrk->loop, &con->sock_watcher);
|
2008-09-08 00:20:55 +00:00
|
|
|
if (con->sock_watcher.fd != -1) {
|
2008-09-08 00:25:55 +00:00
|
|
|
/* just close it; _free should only be called on dead connections anyway */
|
|
|
|
shutdown(con->sock_watcher.fd, SHUT_WR);
|
|
|
|
close(con->sock_watcher.fd);
|
2008-08-06 18:46:42 +00:00
|
|
|
}
|
2008-09-08 00:20:55 +00:00
|
|
|
ev_io_set(&con->sock_watcher, -1, 0);
|
2008-08-05 15:08:32 +00:00
|
|
|
g_string_free(con->remote_addr_str, TRUE);
|
|
|
|
g_string_free(con->local_addr_str, TRUE);
|
2008-08-06 18:46:42 +00:00
|
|
|
con->keep_alive = TRUE;
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-08-07 14:50:36 +00:00
|
|
|
chunkqueue_free(con->raw_in);
|
|
|
|
chunkqueue_free(con->raw_out);
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-10-01 20:20:31 +00:00
|
|
|
g_slice_free1(con->srv->option_def_values->len * sizeof(option_value), con->options);
|
2008-08-08 16:49:00 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
vrequest_free(con->mainvr);
|
2008-09-29 15:07:53 +00:00
|
|
|
http_request_parser_clear(&con->req_parser_ctx);
|
2008-08-05 15:08:32 +00:00
|
|
|
|
2008-09-08 00:25:55 +00:00
|
|
|
if (con->keep_alive_data.link && con->wrk) {
|
2008-09-08 00:20:55 +00:00
|
|
|
g_queue_delete_link(&con->wrk->keep_alive_queue, con->keep_alive_data.link);
|
2008-08-17 16:24:09 +00:00
|
|
|
con->keep_alive_data.link = NULL;
|
|
|
|
}
|
|
|
|
con->keep_alive_data.timeout = 0;
|
2008-08-17 19:27:09 +00:00
|
|
|
con->keep_alive_data.max_idle = 0;
|
2008-09-08 00:25:55 +00:00
|
|
|
if (con->wrk)
|
|
|
|
ev_timer_stop(con->wrk->loop, &con->keep_alive_data.watcher);
|
2008-08-17 16:24:09 +00:00
|
|
|
|
2008-08-05 15:08:32 +00:00
|
|
|
g_slice_free(connection, con);
|
|
|
|
}
|
2008-11-03 14:18:46 +00:00
|
|
|
|
|
|
|
gchar *connection_state_str(connection_state_t state) {
|
|
|
|
static const gchar *states[] = {
|
|
|
|
"dead",
|
|
|
|
"keep-alive",
|
|
|
|
"request start",
|
|
|
|
"read request header",
|
|
|
|
"handle main vrequest",
|
|
|
|
"write"
|
|
|
|
};
|
|
|
|
|
|
|
|
return (gchar*)states[state];
|
|
|
|
}
|