]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: explicit processing of UV_EOF within stream read callback function
authorgrid <grigorii.demidov@nic.cz>
Wed, 3 Jan 2018 10:39:03 +0000 (11:39 +0100)
committerPetr Špaček <petr.spacek@nic.cz>
Mon, 8 Jan 2018 11:01:01 +0000 (12:01 +0100)
daemon/io.c
daemon/tls.c
daemon/worker.c

index a69c187a16cdbe7cd20cd24a836850629f5ce625..0cfe5b3c5de4b2d92053fb0b93ef2700c8814fe4 100644 (file)
@@ -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 */
index 9903b291e8c31f68d5dee39afe1b4ec08a32bfae..c49f3612fc8b487a21e5f09cc5ed9268876bb1c2 100644 (file)
@@ -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;
 
index fad3b707eed8212cac6f6044a1573c714f292ec4..821eabd4cd71167aa3cb9598e07cb3b3863a5b25 100644 (file)
@@ -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;