Verified Commit 01c688e2 authored by Grigorii Demidov's avatar Grigorii Demidov Committed by Petr Špaček

daemon: explicit processing of UV_EOF within stream read callback function

parent 07e423fe
......@@ -237,6 +237,14 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
if (s->closing) {
return;
}
/* nread might be 0, which does not indicate an error or EOF.
* This is equivalent to EAGAIN or EWOULDBLOCK under read(2). */
if (nread == 0) {
return;
}
if (nread == UV_EOF) {
nread = 0;
}
struct worker_ctx *worker = loop->data;
/* TCP pipelining is rather complicated and requires cooperation from the worker
* so the whole message reassembly and demuxing logic is inside worker */
......
......@@ -268,7 +268,7 @@ int tls_process(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *b
}
tls_p->buf = buf;
tls_p->nread = nread;
tls_p->nread = nread >= 0 ? nread : 0;
tls_p->handle = handle;
tls_p->consumed = 0; /* TODO: doesn't handle split TLS records */
......@@ -301,6 +301,9 @@ int tls_process(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *b
if (ret < 0) {
return ret;
}
if (count == 0) {
break;
}
submitted += ret;
}
return submitted;
......@@ -851,6 +854,7 @@ int tls_client_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt)
}
ssize_t submitted = 0;
ssize_t retries = 0;
do {
count = gnutls_record_uncork(ctx->tls_session, 0);
if (count < 0) {
......@@ -859,6 +863,11 @@ int tls_client_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt)
gnutls_strerror_name(count), count);
return kr_error(EIO);
}
if (++retries > TLS_MAX_UNCORK_RETRIES) {
kr_log_error("[tls] gnutls_record_uncork: too many sequential non-fatal errors (%zd), last error is: %s (%zd)\n",
retries, gnutls_strerror_name(count), count);
return kr_error(EIO);
}
} else {
submitted += count;
if (count == 0 && submitted != sizeof(pkt_size) + pkt->size) {
......@@ -884,7 +893,7 @@ int tls_client_process(struct worker_ctx *worker, uv_stream_t *handle, const uin
ctx->handshake_state == TLS_HS_DONE);
ctx->buf = buf;
ctx->nread = nread;
ctx->nread = nread >= 0 ? nread : 0;
ctx->session = session;
ctx->consumed = 0;
......
......@@ -1374,6 +1374,9 @@ static bool subreq_enqueue(struct qr_task *task)
static int qr_task_finalize(struct qr_task *task, int state)
{
assert(task && task->leading == false);
if (task->finished) {
return 0;
}
struct request_ctx *ctx = task->ctx;
kr_resolve_finish(&ctx->req, state);
task->finished = true;
......
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