Commit a1f3feef authored by Petr Špaček's avatar Petr Špaček

Merge branch 'tls-crash' into 'master'

improve TLS error handling

Closes #340

See merge request !555
parents 32ae4cc4 d9350443
......@@ -280,11 +280,11 @@ int tls_process(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *b
int err = gnutls_handshake(tls_p->tls_session);
if (err == GNUTLS_E_SUCCESS) {
tls_p->handshake_state = TLS_HS_DONE;
kr_log_verbose("[%s] TLS handshake with %s has completed\n",
logstring, kr_straddr(&session->peer.ip));
if (tls_p->handshake_cb) {
tls_p->handshake_cb(tls_p->session, 0);
}
kr_log_verbose("[%s] TLS handshake with %s has completed\n",
logstring, kr_straddr(&session->peer.ip));
} else if (err == GNUTLS_E_AGAIN) {
return 0;
} else if (gnutls_error_is_fatal(err)) {
......
......@@ -1080,29 +1080,31 @@ static int session_tls_hs_cb(struct session *session, int status)
kr_nsrep_update_rtt(NULL, &peer->ip, KR_NS_DEAD,
worker->engine->resolver.cache_rtt,
KR_NS_UPDATE_NORESET);
return kr_ok();
}
int ret = worker_add_tcp_connected(worker, &peer->ip, session);
if (deletion_res == kr_ok() && ret == kr_ok()) {
ret = session_next_waiting_send(session);
} else {
if (deletion_res != 0) {
/* session isn't in list of waiting queries, *
* something gone wrong */
while (session->waiting.len > 0) {
struct qr_task *task = session->waiting.at[0];
session_del_tasks(session, task);
array_del(session->waiting, 0);
qr_task_finalize(task, KR_STATE_FAIL);
qr_task_unref(task);
}
assert(session->tasks.len == 0);
session_close(session);
return kr_ok();
}
ret = kr_error(EINVAL);
}
int ret = session_next_waiting_send(session);
if (ret == kr_ok()) {
struct worker_ctx *worker = get_worker();
union inaddr *peer = &session->peer;
int ret = worker_add_tcp_connected(worker, &peer->ip, session);
assert(ret == 0);
if (ret != kr_ok()) {
/* Something went wrong.
* Session isn't in the list of waiting sessions,
* or addition to the list of connected sessions failed,
* or write to upstream failed. */
while (session->waiting.len > 0) {
struct qr_task *task = session->waiting.at[0];
session_del_tasks(session, task);
array_del(session->waiting, 0);
qr_task_finalize(task, KR_STATE_FAIL);
qr_task_unref(task);
}
worker_del_tcp_connected(worker, &peer->ip);
assert(session->tasks.len == 0);
session_close(session);
}
return kr_ok();
}
......@@ -1473,23 +1475,32 @@ static int qr_task_finalize(struct qr_task *task, int state)
struct request_ctx *ctx = task->ctx;
kr_resolve_finish(&ctx->req, state);
task->finished = true;
/* Send back answer */
if (ctx->source.session != NULL) {
uv_handle_t *handle = ctx->source.session->handle;
assert(ctx->source.session->closing == false);
assert(handle && handle->data == ctx->source.session);
assert(ctx->source.addr.ip.sa_family != AF_UNSPEC);
(void) qr_task_send(task, handle,
(struct sockaddr *)&ctx->source.addr,
ctx->req.answer);
if (handle->type == UV_TCP) {
/* Don't try to close source session at least
* retry_interval_for_timeout_timer milliseconds */
uv_timer_again(&ctx->source.session->timeout);
}
} else {
if (ctx->source.session == NULL) {
(void) qr_task_on_send(task, NULL, kr_error(EIO));
return state == KR_STATE_DONE ? 0 : kr_error(EIO);
}
/* Send back answer */
struct session *source_session = ctx->source.session;
uv_handle_t *handle = source_session->handle;
assert(source_session->closing == false);
assert(handle && handle->data == ctx->source.session);
assert(ctx->source.addr.ip.sa_family != AF_UNSPEC);
int res = qr_task_send(task, handle,
(struct sockaddr *)&ctx->source.addr,
ctx->req.answer);
if (res != kr_ok()) {
while (source_session->tasks.len > 0) {
struct qr_task *t = source_session->tasks.at[0];
(void) qr_task_on_send(t, NULL, kr_error(EIO));
}
session_close(source_session);
} else if (handle->type == UV_TCP) {
/* Don't try to close source session at least
* retry_interval_for_timeout_timer milliseconds */
uv_timer_again(&ctx->source.session->timeout);
}
return state == KR_STATE_DONE ? 0 : kr_error(EIO);
}
......@@ -1651,7 +1662,13 @@ static int qr_task_step(struct qr_task *task,
if (ret < 0) {
session_del_waiting(session, task);
session_del_tasks(session, task);
while (session->tasks.len != 0) {
struct qr_task *t = session->tasks.at[0];
qr_task_finalize(t, KR_STATE_FAIL);
session_del_tasks(session, t);
}
subreq_finalize(task, packet_source, packet);
session_close(session);
return qr_task_finalize(task, KR_STATE_FAIL);
}
ret = timer_start(session, on_tcp_watchdog_timeout,
......@@ -1659,7 +1676,13 @@ static int qr_task_step(struct qr_task *task,
if (ret < 0) {
session_del_waiting(session, task);
session_del_tasks(session, task);
while (session->tasks.len != 0) {
struct qr_task *t = session->tasks.at[0];
qr_task_finalize(t, KR_STATE_FAIL);
session_del_tasks(session, t);
}
subreq_finalize(task, packet_source, packet);
session_close(session);
return qr_task_finalize(task, KR_STATE_FAIL);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment