summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_h1proto.c
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2018-09-20 15:05:37 +0300
committerIgor Sysoev <igor@sysoev.ru>2018-09-20 15:05:37 +0300
commit96cd68b34037f8b6d9a1d43f67b8fe7c1df2ef9e (patch)
tree8e648712993012fbe815cc92e6debab20449fe8f /src/nxt_h1proto.c
parente964e982fd64505fb8644f91e5c57a869038cd18 (diff)
downloadunit-96cd68b34037f8b6d9a1d43f67b8fe7c1df2ef9e.tar.gz
unit-96cd68b34037f8b6d9a1d43f67b8fe7c1df2ef9e.tar.bz2
Added SSL/TLS support on connection level.
Diffstat (limited to 'src/nxt_h1proto.c')
-rw-r--r--src/nxt_h1proto.c594
1 files changed, 401 insertions, 193 deletions
diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c
index 874dd2fd..040e8b3f 100644
--- a/src/nxt_h1proto.c
+++ b/src/nxt_h1proto.c
@@ -9,11 +9,16 @@
/*
- * nxt_h1p_conn_ prefix is used for connection handlers.
+ * nxt_http_conn_ and nxt_h1p_conn_ prefixes are used for connection handlers.
+ * nxt_h1p_idle_ prefix is used for idle connection handlers.
* nxt_h1p_request_ prefix is used for HTTP/1 protocol request methods.
*/
-static ssize_t nxt_h1p_conn_io_read_handler(nxt_conn_t *c);
+#if (NXT_TLS)
+static ssize_t nxt_http_idle_io_read_handler(nxt_conn_t *c);
+static void nxt_http_conn_test(nxt_task_t *task, void *obj, void *data);
+#endif
+static ssize_t nxt_h1p_idle_io_read_handler(nxt_conn_t *c);
static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data);
static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data);
static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj,
@@ -36,43 +41,50 @@ static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r,
nxt_buf_t *out);
static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r,
nxt_buf_t *out);
-static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data);
static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task,
nxt_http_proto_t proto);
static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
nxt_buf_t *last);
-static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
- nxt_socket_conf_joint_t *joint);
-static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p,
- nxt_conn_t *c);
-static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data);
-static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data);
-static void nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data);
-static void nxt_h1p_conn_idle_timeout(nxt_task_t *task, nxt_conn_t *c);
-static void nxt_h1p_conn_idle_close(nxt_task_t *task, void *obj, void *data);
-static void nxt_h1p_conn_send_timeout(nxt_task_t *task, void *obj, void *data);
-static nxt_msec_t nxt_h1p_conn_send_timeout_value(nxt_conn_t *c,
- uintptr_t data);
-static nxt_msec_t nxt_h1p_conn_timeout_value(nxt_conn_t *c, uintptr_t data);
-static void nxt_h1p_close(nxt_task_t *task, nxt_conn_t *c);
-static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data);
static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data);
static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj,
void *data);
static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj,
void *data);
-static nxt_msec_t nxt_h1p_conn_request_timeout_value(nxt_conn_t *c,
+static nxt_msec_t nxt_h1p_conn_request_timer_value(nxt_conn_t *c,
uintptr_t data);
nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
nxt_http_request_t *r);
+static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
+ nxt_socket_conf_joint_t *joint);
+static void nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data);
+static void nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data);
+static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data);
+static nxt_msec_t nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data);
+static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p,
+ nxt_conn_t *c);
+static void nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data);
+static void nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data);
+static void nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c);
+static void nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data);
+static void nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj,
+ void *data);
+static nxt_msec_t nxt_h1p_idle_response_timer_value(nxt_conn_t *c,
+ uintptr_t data);
+static void nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c);
+static void nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data);
+static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data);
+#if (NXT_TLS)
+static const nxt_conn_state_t nxt_http_idle_state;
+static const nxt_conn_state_t nxt_h1p_shutdown_state;
+#endif
static const nxt_conn_state_t nxt_h1p_idle_state;
static const nxt_conn_state_t nxt_h1p_idle_close_state;
static const nxt_conn_state_t nxt_h1p_header_parse_state;
static const nxt_conn_state_t nxt_h1p_read_body_state;
static const nxt_conn_state_t nxt_h1p_request_send_state;
-static const nxt_conn_state_t nxt_h1p_timeout_send_state;
+static const nxt_conn_state_t nxt_h1p_timeout_response_state;
static const nxt_conn_state_t nxt_h1p_keepalive_state;
static const nxt_conn_state_t nxt_h1p_close_state;
@@ -177,28 +189,35 @@ nxt_http_conn_init(nxt_task_t *task, void *obj, void *data)
c->read_state = &nxt_h1p_idle_state;
+#if (NXT_TLS)
+ if (skcf->tls != NULL) {
+ c->read_state = &nxt_http_idle_state;
+ }
+#endif
+
nxt_conn_read(engine, c);
}
-static const nxt_conn_state_t nxt_h1p_idle_state
+#if (NXT_TLS)
+
+static const nxt_conn_state_t nxt_http_idle_state
nxt_aligned(64) =
{
- .ready_handler = nxt_h1p_conn_proto_init,
- .close_handler = nxt_h1p_conn_error,
+ .ready_handler = nxt_http_conn_test,
+ .close_handler = nxt_h1p_conn_close,
.error_handler = nxt_h1p_conn_error,
- .io_read_handler = nxt_h1p_conn_io_read_handler,
+ .io_read_handler = nxt_http_idle_io_read_handler,
- .timer_handler = nxt_h1p_conn_timeout,
- .timer_value = nxt_h1p_conn_timeout_value,
+ .timer_handler = nxt_h1p_idle_timeout,
+ .timer_value = nxt_h1p_conn_timer_value,
.timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
- .timer_autoreset = 1,
};
static ssize_t
-nxt_h1p_conn_io_read_handler(nxt_conn_t *c)
+nxt_http_idle_io_read_handler(nxt_conn_t *c)
{
size_t size;
ssize_t n;
@@ -207,7 +226,7 @@ nxt_h1p_conn_io_read_handler(nxt_conn_t *c)
joint = c->listen->socket.data;
- if (joint == NULL) {
+ if (nxt_slow_path(joint == NULL)) {
/*
* Listening socket had been closed while
* connection was in keep-alive state.
@@ -224,12 +243,18 @@ nxt_h1p_conn_io_read_handler(nxt_conn_t *c)
return NXT_ERROR;
}
- n = c->io->recvbuf(c, b);
+ /*
+ * 1 byte is enough to distinguish between SSLv3/TLS and plain HTTP.
+ * 11 bytes are enough to log supported SSLv3/TLS version.
+ * 16 bytes are just for more optimized kernel copy-out operation.
+ */
+ n = c->io->recv(c, b->mem.pos, 16, MSG_PEEK);
if (n > 0) {
c->read = b;
} else {
+ c->read = NULL;
nxt_mp_free(c->mem_pool, b);
}
@@ -237,13 +262,139 @@ nxt_h1p_conn_io_read_handler(nxt_conn_t *c)
}
-static const nxt_conn_state_t nxt_h1p_idle_close_state
+static void
+nxt_http_conn_test(nxt_task_t *task, void *obj, void *data)
+{
+ u_char *p;
+ nxt_buf_t *b;
+ nxt_conn_t *c;
+ nxt_tls_conf_t *tls;
+ nxt_socket_conf_joint_t *joint;
+
+ c = obj;
+
+ nxt_debug(task, "h1p conn https test");
+
+ b = c->read;
+ p = b->mem.pos;
+
+ c->read_state = &nxt_h1p_idle_state;
+
+ if (p[0] != 0x16) {
+ b->mem.free = b->mem.pos;
+
+ nxt_conn_read(task->thread->engine, c);
+ return;
+ }
+
+ /* SSLv3/TLS ClientHello message. */
+
+#if (NXT_DEBUG)
+ if (nxt_buf_mem_used_size(&b->mem) >= 11) {
+ u_char major, minor;
+ const char *protocol;
+
+ major = p[9];
+ minor = p[10];
+
+ if (major == 3) {
+ if (minor == 0) {
+ protocol = "SSLv";
+
+ } else {
+ protocol = "TLSv";
+ major -= 2;
+ minor -= 1;
+ }
+
+ nxt_debug(task, "SSL/TLS: %s%ud.%ud", protocol, major, minor);
+ }
+ }
+#endif
+
+ c->read = NULL;
+ nxt_mp_free(c->mem_pool, b);
+
+ joint = c->listen->socket.data;
+
+ if (nxt_slow_path(joint == NULL)) {
+ /*
+ * Listening socket had been closed while
+ * connection was in keep-alive state.
+ */
+ nxt_h1p_shutdown(task, c);
+ return;
+ }
+
+ tls = joint->socket_conf->tls;
+
+ tls->conn_init(task, tls, c);
+}
+
+#endif
+
+
+static const nxt_conn_state_t nxt_h1p_idle_state
nxt_aligned(64) =
{
+ .ready_handler = nxt_h1p_conn_proto_init,
.close_handler = nxt_h1p_conn_close,
+ .error_handler = nxt_h1p_conn_error,
+
+ .io_read_handler = nxt_h1p_idle_io_read_handler,
+
+ .timer_handler = nxt_h1p_idle_timeout,
+ .timer_value = nxt_h1p_conn_timer_value,
+ .timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
+ .timer_autoreset = 1,
};
+static ssize_t
+nxt_h1p_idle_io_read_handler(nxt_conn_t *c)
+{
+ size_t size;
+ ssize_t n;
+ nxt_buf_t *b;
+ nxt_socket_conf_joint_t *joint;
+
+ joint = c->listen->socket.data;
+
+ if (nxt_slow_path(joint == NULL)) {
+ /*
+ * Listening socket had been closed while
+ * connection was in keep-alive state.
+ */
+ c->read_state = &nxt_h1p_idle_close_state;
+ return 0;
+ }
+
+ b = c->read;
+
+ if (b == NULL) {
+ size = joint->socket_conf->header_buffer_size;
+
+ b = nxt_buf_mem_alloc(c->mem_pool, size, 0);
+ if (nxt_slow_path(b == NULL)) {
+ c->socket.error = NXT_ENOMEM;
+ return NXT_ERROR;
+ }
+ }
+
+ n = c->io->recvbuf(c, b);
+
+ if (n > 0) {
+ c->read = b;
+
+ } else {
+ c->read = NULL;
+ nxt_mp_free(c->mem_pool, b);
+ }
+
+ return n;
+}
+
+
static void
nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data)
{
@@ -256,7 +407,7 @@ nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data)
h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t));
if (nxt_slow_path(h1p == NULL)) {
- nxt_h1p_close(task, c);
+ nxt_h1p_shutdown(task, c);
return;
}
@@ -309,7 +460,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data)
nxt_mp_release(r->mem_pool);
}
- nxt_h1p_close(task, c);
+ nxt_h1p_shutdown(task, c);
}
@@ -321,7 +472,7 @@ static const nxt_conn_state_t nxt_h1p_header_parse_state
.error_handler = nxt_h1p_conn_request_error,
.timer_handler = nxt_h1p_conn_request_timeout,
- .timer_value = nxt_h1p_conn_request_timeout_value,
+ .timer_value = nxt_h1p_conn_request_timer_value,
.timer_data = offsetof(nxt_socket_conf_t, header_read_timeout),
};
@@ -608,7 +759,7 @@ static const nxt_conn_state_t nxt_h1p_read_body_state
.error_handler = nxt_h1p_conn_request_error,
.timer_handler = nxt_h1p_conn_request_timeout,
- .timer_value = nxt_h1p_conn_request_timeout_value,
+ .timer_value = nxt_h1p_conn_request_timer_value,
.timer_data = offsetof(nxt_socket_conf_t, body_read_timeout),
.timer_autoreset = 1,
};
@@ -881,7 +1032,7 @@ static const nxt_conn_state_t nxt_h1p_request_send_state
.error_handler = nxt_h1p_conn_request_error,
.timer_handler = nxt_h1p_conn_request_send_timeout,
- .timer_value = nxt_h1p_conn_request_timeout_value,
+ .timer_value = nxt_h1p_conn_request_timer_value,
.timer_data = offsetof(nxt_socket_conf_t, send_timeout),
.timer_autoreset = 1,
};
@@ -970,26 +1121,6 @@ nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out)
}
-static void
-nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data)
-{
- nxt_conn_t *c;
- nxt_event_engine_t *engine;
-
- c = obj;
-
- nxt_debug(task, "h1p conn sent");
-
- engine = task->thread->engine;
-
- c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
-
- if (c->write != NULL) {
- nxt_conn_write(engine, c);
- }
-}
-
-
static nxt_off_t
nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto)
{
@@ -1030,6 +1161,100 @@ nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r,
static void
+nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_h1proto_t *h1p;
+ nxt_http_request_t *r;
+
+ h1p = data;
+
+ nxt_debug(task, "h1p conn request error");
+
+ r = h1p->request;
+
+ if (r->fields == NULL) {
+ (void) nxt_h1p_header_process(h1p, r);
+ }
+
+ if (r->status == 0) {
+ r->status = NXT_HTTP_BAD_REQUEST;
+ }
+
+ nxt_h1p_request_error(task, h1p, r);
+}
+
+
+static void
+nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_conn_t *c;
+ nxt_timer_t *timer;
+ nxt_h1proto_t *h1p;
+ nxt_http_request_t *r;
+
+ timer = obj;
+
+ nxt_debug(task, "h1p conn request timeout");
+
+ c = nxt_read_timer_conn(timer);
+ /*
+ * Disable SO_LINGER off during socket closing
+ * to send "408 Request Timeout" error response.
+ */
+ c->socket.timedout = 0;
+
+ h1p = c->socket.data;
+ h1p->keepalive = 0;
+ r = h1p->request;
+
+ if (r->fields == NULL) {
+ (void) nxt_h1p_header_process(h1p, r);
+ }
+
+ nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT);
+}
+
+
+static void
+nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_conn_t *c;
+ nxt_timer_t *timer;
+ nxt_h1proto_t *h1p;
+
+ timer = obj;
+
+ nxt_debug(task, "h1p conn request send timeout");
+
+ c = nxt_write_timer_conn(timer);
+ h1p = c->socket.data;
+
+ nxt_h1p_request_error(task, h1p, h1p->request);
+}
+
+
+static nxt_msec_t
+nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data)
+{
+ nxt_h1proto_t *h1p;
+
+ h1p = c->socket.data;
+
+ return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data);
+}
+
+
+nxt_inline void
+nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
+ nxt_http_request_t *r)
+{
+ h1p->keepalive = 0;
+
+ r->state->error_handler(task, r, h1p);
+}
+
+
+static void
nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
nxt_socket_conf_joint_t *joint)
{
@@ -1049,12 +1274,69 @@ nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto,
nxt_h1p_keepalive(task, h1p, c);
} else {
- nxt_h1p_close(task, c);
+ nxt_h1p_shutdown(task, c);
+ }
+}
+
+
+static void
+nxt_h1p_conn_sent(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_conn_t *c;
+ nxt_event_engine_t *engine;
+
+ c = obj;
+
+ nxt_debug(task, "h1p conn sent");
+
+ engine = task->thread->engine;
+
+ c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write);
+
+ if (c->write != NULL) {
+ nxt_conn_write(engine, c);
}
}
static void
+nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_conn_t *c;
+
+ c = obj;
+
+ nxt_debug(task, "h1p conn close");
+
+ nxt_h1p_shutdown(task, c);
+}
+
+
+static void
+nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_conn_t *c;
+
+ c = obj;
+
+ nxt_debug(task, "h1p conn error");
+
+ nxt_h1p_shutdown(task, c);
+}
+
+
+static nxt_msec_t
+nxt_h1p_conn_timer_value(nxt_conn_t *c, uintptr_t data)
+{
+ nxt_socket_conf_joint_t *joint;
+
+ joint = c->listen->socket.data;
+
+ return nxt_value_at(nxt_msec_t, joint->socket_conf, data);
+}
+
+
+static void
nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c)
{
size_t size;
@@ -1116,57 +1398,51 @@ static const nxt_conn_state_t nxt_h1p_keepalive_state
nxt_aligned(64) =
{
.ready_handler = nxt_h1p_conn_request_init,
- .close_handler = nxt_h1p_conn_error,
+ .close_handler = nxt_h1p_conn_close,
.error_handler = nxt_h1p_conn_error,
- .io_read_handler = nxt_h1p_conn_io_read_handler,
+ .io_read_handler = nxt_h1p_idle_io_read_handler,
- .timer_handler = nxt_h1p_conn_timeout,
- .timer_value = nxt_h1p_conn_timeout_value,
+ .timer_handler = nxt_h1p_idle_timeout,
+ .timer_value = nxt_h1p_conn_timer_value,
.timer_data = offsetof(nxt_socket_conf_t, idle_timeout),
.timer_autoreset = 1,
};
-static void
-nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data)
+static const nxt_conn_state_t nxt_h1p_idle_close_state
+ nxt_aligned(64) =
{
- nxt_conn_t *c;
-
- c = obj;
-
- nxt_debug(task, "h1p conn error");
-
- nxt_h1p_close(task, c);
-}
+ .close_handler = nxt_h1p_idle_close,
+};
static void
-nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data)
+nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data)
{
nxt_conn_t *c;
c = obj;
- nxt_debug(task, "h1p conn close");
+ nxt_debug(task, "h1p idle close");
- nxt_h1p_conn_idle_timeout(task, c);
+ nxt_h1p_idle_response(task, c);
}
static void
-nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data)
+nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data)
{
nxt_conn_t *c;
nxt_timer_t *timer;
timer = obj;
- nxt_debug(task, "h1p conn idle timeout");
+ nxt_debug(task, "h1p idle timeout");
c = nxt_read_timer_conn(timer);
- nxt_h1p_conn_idle_timeout(task, c);
+ nxt_h1p_idle_response(task, c);
}
@@ -1179,7 +1455,7 @@ nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data)
static void
-nxt_h1p_conn_idle_timeout(nxt_task_t *task, nxt_conn_t *c)
+nxt_h1p_idle_response(nxt_task_t *task, nxt_conn_t *c)
{
u_char *p;
size_t size;
@@ -1210,85 +1486,111 @@ nxt_h1p_conn_idle_timeout(nxt_task_t *task, nxt_conn_t *c)
nxt_buf_set_sync(last);
nxt_buf_set_last(last);
- last->completion_handler = nxt_h1p_conn_idle_close;
+ last->completion_handler = nxt_h1p_idle_response_sent;
last->parent = c;
c->write = out;
- c->write_state = &nxt_h1p_timeout_send_state;
+ c->write_state = &nxt_h1p_timeout_response_state;
nxt_conn_write(task->thread->engine, c);
return;
fail:
- nxt_h1p_close(task, c);
+ nxt_h1p_shutdown(task, c);
}
-static const nxt_conn_state_t nxt_h1p_timeout_send_state
+static const nxt_conn_state_t nxt_h1p_timeout_response_state
nxt_aligned(64) =
{
.ready_handler = nxt_h1p_conn_sent,
.error_handler = nxt_h1p_conn_error,
- .timer_handler = nxt_h1p_conn_send_timeout,
- .timer_value = nxt_h1p_conn_send_timeout_value,
+ .timer_handler = nxt_h1p_idle_response_timeout,
+ .timer_value = nxt_h1p_idle_response_timer_value,
};
static void
-nxt_h1p_conn_idle_close(nxt_task_t *task, void *obj, void *data)
+nxt_h1p_idle_response_sent(nxt_task_t *task, void *obj, void *data)
{
nxt_conn_t *c;
c = data;
- nxt_debug(task, "h1p conn idle close");
+ nxt_debug(task, "h1p idle timeout response sent");
- nxt_h1p_close(task, c);
+ nxt_h1p_shutdown(task, c);
}
static void
-nxt_h1p_conn_send_timeout(nxt_task_t *task, void *obj, void *data)
+nxt_h1p_idle_response_timeout(nxt_task_t *task, void *obj, void *data)
{
nxt_conn_t *c;
nxt_timer_t *timer;
timer = obj;
- nxt_debug(task, "h1p conn send timeout");
+ nxt_debug(task, "h1p idle timeout response timeout");
c = nxt_read_timer_conn(timer);
- nxt_h1p_close(task, c);
+ nxt_h1p_shutdown(task, c);
}
static nxt_msec_t
-nxt_h1p_conn_send_timeout_value(nxt_conn_t *c, uintptr_t data)
+nxt_h1p_idle_response_timer_value(nxt_conn_t *c, uintptr_t data)
{
return 10 * 1000;
}
-static nxt_msec_t
-nxt_h1p_conn_timeout_value(nxt_conn_t *c, uintptr_t data)
+static void
+nxt_h1p_shutdown(nxt_task_t *task, nxt_conn_t *c)
{
- nxt_socket_conf_joint_t *joint;
+ nxt_debug(task, "h1p shutdown");
- joint = c->listen->socket.data;
+ c->socket.data = NULL;
- return nxt_value_at(nxt_msec_t, joint->socket_conf, data);
+#if (NXT_TLS)
+
+ if (c->u.tls != NULL) {
+ c->write_state = &nxt_h1p_shutdown_state;
+
+ c->io->shutdown(task, c, NULL);
+ return;
+ }
+
+#endif
+
+ nxt_h1p_conn_closing(task, c, NULL);
}
+#if (NXT_TLS)
+
+static const nxt_conn_state_t nxt_h1p_shutdown_state
+ nxt_aligned(64) =
+{
+ .ready_handler = nxt_h1p_conn_closing,
+ .close_handler = nxt_h1p_conn_closing,
+ .error_handler = nxt_h1p_conn_closing,
+};
+
+#endif
+
+
static void
-nxt_h1p_close(nxt_task_t *task, nxt_conn_t *c)
+nxt_h1p_conn_closing(nxt_task_t *task, void *obj, void *data)
{
- nxt_debug(task, "h1p close");
+ nxt_conn_t *c;
- c->socket.data = NULL;
+ c = obj;
+
+ nxt_debug(task, "h1p conn closing");
c->write_state = &nxt_h1p_close_state;
@@ -1326,97 +1628,3 @@ nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data)
nxt_router_listen_event_release(&engine->task, lev, NULL);
}
-
-
-static void
-nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data)
-{
- nxt_h1proto_t *h1p;
- nxt_http_request_t *r;
-
- h1p = data;
-
- nxt_debug(task, "h1p conn request error");
-
- r = h1p->request;
-
- if (r->fields == NULL) {
- (void) nxt_h1p_header_process(h1p, r);
- }
-
- if (r->status == 0) {
- r->status = NXT_HTTP_BAD_REQUEST;
- }
-
- nxt_h1p_request_error(task, h1p, r);
-}
-
-
-static void
-nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data)
-{
- nxt_conn_t *c;
- nxt_timer_t *timer;
- nxt_h1proto_t *h1p;
- nxt_http_request_t *r;
-
- timer = obj;
-
- nxt_debug(task, "h1p conn request timeout");
-
- c = nxt_read_timer_conn(timer);
- /*
- * Disable SO_LINGER off during socket closing
- * to send "408 Request Timeout" error response.
- */
- c->socket.timedout = 0;
-
- h1p = c->socket.data;
- h1p->keepalive = 0;
- r = h1p->request;
-
- if (r->fields == NULL) {
- (void) nxt_h1p_header_process(h1p, r);
- }
-
- nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT);
-}
-
-
-static void
-nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data)
-{
- nxt_conn_t *c;
- nxt_timer_t *timer;
- nxt_h1proto_t *h1p;
-
- timer = obj;
-
- nxt_debug(task, "h1p conn request send timeout");
-
- c = nxt_write_timer_conn(timer);
- h1p = c->socket.data;
-
- nxt_h1p_request_error(task, h1p, h1p->request);
-}
-
-
-static nxt_msec_t
-nxt_h1p_conn_request_timeout_value(nxt_conn_t *c, uintptr_t data)
-{
- nxt_h1proto_t *h1p;
-
- h1p = c->socket.data;
-
- return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data);
-}
-
-
-nxt_inline void
-nxt_h1p_request_error(nxt_task_t *task, nxt_h1proto_t *h1p,
- nxt_http_request_t *r)
-{
- h1p->keepalive = 0;
-
- r->state->error_handler(task, r, h1p);
-}