]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/worker: move checkout layer before connect, catch checkout errors
authorMarek Vavruša <mvavrusa@cloudflare.com>
Fri, 27 Apr 2018 06:21:31 +0000 (23:21 -0700)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 26 Nov 2018 10:12:28 +0000 (11:12 +0100)
The checkout layer was moved to where upstream address is known, but
before outbound message is sent (or connected to upstream).
The reason is to allow checkout layer to block outbound queries
without wasting time waiting for connect.

daemon/worker.c

index 010ade52a40bc16f24f4d95099113e5e5d9e463d..d39e06105745962a6067773cfe8987c3dc2a8a4f 100644 (file)
@@ -575,7 +575,6 @@ static int qr_task_send(struct qr_task *task, struct session *session,
 
        int ret = 0;
        struct request_ctx *ctx = task->ctx;
-       struct kr_request *req = &ctx->req;
 
        uv_handle_t *handle = session_get_handle(session);
        assert(handle && handle->data == session);
@@ -605,27 +604,6 @@ static int qr_task_send(struct qr_task *task, struct session *session,
                worker_task_pkt_set_msgid(task, msg_id);
        }
 
-       if (knot_wire_get_qr(pkt->wire) == 0) {
-               /*
-                * Query must be finalised using destination address before
-                * sending.
-                *
-                * Libuv does not offer a convenient way how to obtain a source
-                * IP address from a UDP handle that has been initialised using
-                * uv_udp_init(). The uv_udp_getsockname() fails because of the
-                * lazy socket initialisation.
-                *
-                * @note -- A solution might be opening a separate socket and
-                * trying to obtain the IP address from it.
-                */
-               ret = kr_resolve_checkout(req, NULL, addr,
-                                         is_stream ? SOCK_STREAM : SOCK_DGRAM,
-                                         pkt);
-               if (ret != 0) {
-                       return ret;
-               }
-       }
-
        uv_handle_t *ioreq = malloc(is_stream ? sizeof(uv_write_t) : sizeof(uv_udp_send_t));
        if (!ioreq) {
                return qr_task_on_send(task, handle, kr_error(ENOMEM));
@@ -947,7 +925,12 @@ static uv_handle_t *retransmit(struct qr_task *task)
                if (task->pending_count >= MAX_PENDING) {
                        return ret;
                }
-               ret = ioreq_spawn(task->ctx->worker, SOCK_DGRAM, choice->sin6_family);
+               /* Checkout answer before sending it */
+               struct request_ctx *ctx = task->ctx;
+               if (kr_resolve_checkout(&ctx->req, NULL, (struct sockaddr *)choice, SOCK_DGRAM, task->pktbuf) != 0) {
+                       return ret;
+               }
+               ret = ioreq_spawn(ctx->worker, SOCK_DGRAM, choice->sin6_family);
                if (!ret) {
                        return ret;
                }
@@ -1299,7 +1282,6 @@ static int tcp_task_step(struct qr_task *task,
                         const struct sockaddr *packet_source, knot_pkt_t *packet)
 {
        assert(task->pending_count == 0);
-       struct request_ctx *ctx = task->ctx;
 
        const struct sockaddr *addr =
                packet_source ? packet_source : task->addrlist;
@@ -1310,6 +1292,13 @@ static int tcp_task_step(struct qr_task *task,
                subreq_finalize(task, packet_source, packet);
                return qr_task_finalize(task, KR_STATE_FAIL);
        }
+       /* Checkout task before connecting */
+       struct request_ctx *ctx = task->ctx;
+       if (kr_resolve_checkout(&ctx->req, NULL, (struct sockaddr *)addr,
+                               SOCK_STREAM, task->pktbuf) != 0) {
+               subreq_finalize(task, packet_source, packet);
+               return qr_task_finalize(task, KR_STATE_FAIL);
+       }
        int ret;
        struct session* session = NULL;
        if ((session = worker_find_tcp_waiting(ctx->worker, addr)) != NULL) {