]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon: unificate tls structures to avod code duplication
authorGrigorii Demidov <grigorii.demidov@nic.cz>
Wed, 7 Feb 2018 16:27:01 +0000 (17:27 +0100)
committerPetr Spacek <pspacek@knot-comcast-1.labs.office.nic.cz>
Thu, 8 Feb 2018 13:11:23 +0000 (14:11 +0100)
daemon/io.c
daemon/tls.c
daemon/tls.h
daemon/worker.c

index d0235f94809e0c8cff17b56a70f27f2218faa056..fa1ac7f4f3b4b2cbad484cfa45305e24bbdf8cee 100644 (file)
@@ -239,8 +239,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
         * so the whole message reassembly and demuxing logic is inside worker */
        int ret = 0;
        if (s->has_tls) {
-               ret = s->outgoing ? tls_client_process(worker, handle, (const uint8_t *)buf->base, nread) :
-                                   tls_process(worker, handle, (const uint8_t *)buf->base, nread);
+               ret = tls_process(worker, handle, (const uint8_t *)buf->base, nread);
        } else {
                ret = worker_process_tcp(worker, handle, (const uint8_t *)buf->base, nread);
        }
@@ -298,7 +297,8 @@ static void _tcp_accept(uv_stream_t *master, int status, bool tls)
        session->has_tls = tls;
        if (tls && !session->tls_ctx) {
                session->tls_ctx = tls_new(master->loop->data);
-               session->tls_ctx->session = session;
+               session->tls_ctx->c.session = session;
+               session->tls_ctx->c.handshake_state = TLS_HS_IN_PROGRESS;
        }
        uv_timer_t *timer = &session->timeout;
        uv_timer_start(timer, tcp_timeout_trigger, KR_CONN_RTT_MAX/2, KR_CONN_RTT_MAX/2);
index 56117a1b6e0684c236c1026cca170a0870d79ebf..79bc21de710087a5d1e04d535e1f7de959157767 100644 (file)
@@ -45,6 +45,9 @@
 #define DEBUG_MSG(fmt...)
 #endif
 
+static char const server_logstring[] = "tls";
+static char const client_logstring[] = "tls-client";
+
 static int client_verify_certificate(gnutls_session_t tls_session);
 
 /**
@@ -68,11 +71,12 @@ static int kres_gnutls_set_priority(gnutls_session_t session) {
 
 static ssize_t kres_gnutls_pull(gnutls_transport_ptr_t h, void *buf, size_t len)
 {
-       struct tls_ctx_t *t = (struct tls_ctx_t *)h;
+       struct tls_common_ctx *t = (struct tls_common_ctx *)h;
        assert(t != NULL);
 
        ssize_t avail = t->nread - t->consumed;
-       DEBUG_MSG("[tls] pull wanted: %zu available: %zu\n", len, avail);
+       DEBUG_MSG("[%s] pull wanted: %zu available: %zu\n",
+                 t->client_side ? "tls_client" : "tls", len, avail);
        if (t->nread <= t->consumed) {
                errno = EAGAIN;
                return -1;
@@ -129,33 +133,35 @@ struct tls_ctx_t *tls_new(struct worker_ctx *worker)
                return NULL;
        }
 
-       int err = gnutls_init(&tls->tls_session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
+       int err = gnutls_init(&tls->c.tls_session, GNUTLS_SERVER | GNUTLS_NONBLOCK);
        if (err != GNUTLS_E_SUCCESS) {
                kr_log_error("[tls] gnutls_init(): %s (%d)\n", gnutls_strerror_name(err), err);
                tls_free(tls);
                return NULL;
        }
        tls->credentials = tls_credentials_reserve(net->tls_credentials);
-       err = gnutls_credentials_set(tls->tls_session, GNUTLS_CRD_CERTIFICATE, tls->credentials->credentials);
+       err = gnutls_credentials_set(tls->c.tls_session, GNUTLS_CRD_CERTIFICATE,
+                                    tls->credentials->credentials);
        if (err != GNUTLS_E_SUCCESS) {
                kr_log_error("[tls] gnutls_credentials_set(): %s (%d)\n", gnutls_strerror_name(err), err);
                tls_free(tls);
                return NULL;
        }
-       if (kres_gnutls_set_priority(tls->tls_session) != GNUTLS_E_SUCCESS) {
+       if (kres_gnutls_set_priority(tls->c.tls_session) != GNUTLS_E_SUCCESS) {
                tls_free(tls);
                return NULL;
        }
 
-       tls->worker = worker;
+       tls->c.worker = worker;
+       tls->c.client_side = false;
 
-       gnutls_transport_set_pull_function(tls->tls_session, kres_gnutls_pull);
-       gnutls_transport_set_push_function(tls->tls_session, worker_gnutls_push);
-       gnutls_transport_set_ptr(tls->tls_session, tls);
+       gnutls_transport_set_pull_function(tls->c.tls_session, kres_gnutls_pull);
+       gnutls_transport_set_push_function(tls->c.tls_session, worker_gnutls_push);
+       gnutls_transport_set_ptr(tls->c.tls_session, tls);
        return tls;
 }
 
-void tls_close(struct tls_ctx_t *ctx)
+void tls_close(struct tls_common_ctx *ctx)
 {
        if (ctx == NULL || ctx->tls_session == NULL) {
                return;
@@ -163,10 +169,11 @@ void tls_close(struct tls_ctx_t *ctx)
 
        assert(ctx->session);
 
-       if (ctx->handshake_done) {
-               DEBUG_MSG("[tls] closing tls connection to `%s`\n",
-                         kr_straddr(&ctx->session->peer.ip));
-               ctx->handshake_done = false;
+       if (ctx->handshake_state == TLS_HS_DONE) {
+               kr_log_verbose("[%s] closing tls connection to `%s`\n",
+                              ctx->client_side ? "tls-client" : "tls",
+                              kr_straddr(&ctx->session->peer.ip));
+               ctx->handshake_state = TLS_HS_CLOSING;
                gnutls_bye(ctx->tls_session, GNUTLS_SHUT_RDWR);
        }
 }
@@ -177,46 +184,34 @@ void tls_free(struct tls_ctx_t *tls)
                return;
        }
 
-       if (tls->session) {
+       if (tls->c.tls_session) {
                /* Don't terminate TLS connection, just tear it down */
-               gnutls_deinit(tls->tls_session);
-               tls->tls_session = NULL;
+               gnutls_deinit(tls->c.tls_session);
+               tls->c.tls_session = NULL;
        }
 
        tls_credentials_release(tls->credentials);
        free(tls);
 }
 
-int tls_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt,
-            bool server_side)
+int tls_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt)
 {
        if (!pkt || !handle || !handle->data) {
                return kr_error(EINVAL);
        }
 
        struct session *session = handle->data;
+       struct tls_common_ctx *tls_ctx = session->outgoing ? &session->tls_client_ctx->c :
+                                                            &session->tls_ctx->c;
+
+       assert (tls_ctx);
+       assert (session->outgoing == tls_ctx->client_side);
+
        const uint16_t pkt_size = htons(pkt->size);
-       static char const server_logstring[] = "tls";
-       static char const client_logstring[] = "tls-client";
-       const char *logstring = client_logstring;
-       gnutls_session_t tls_session = NULL;
-
-       if (server_side) {
-               logstring = server_logstring;
-               if (!session->tls_ctx) {
-                       kr_log_error("[%s] no tls context on push\n", logstring);
-                       return kr_error(ENOENT);
-               }
-               session->tls_ctx->task = task;
-               tls_session = session->tls_ctx->tls_session;
-       } else {
-               if (!session->tls_client_ctx) {
-                       kr_log_error("[%s] no tls context on push\n", logstring);
-                       return kr_error(ENOENT);
-               }
-               session->tls_client_ctx->task = task;
-               tls_session = session->tls_client_ctx->tls_session;
-       }
+       const char *logstring = tls_ctx->client_side ? client_logstring : server_logstring;
+       gnutls_session_t tls_session = tls_ctx->tls_session;
+
+       tls_ctx->task = task;
 
        assert(gnutls_record_check_corked(tls_session) == 0);
 
@@ -266,27 +261,39 @@ int tls_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt,
 int tls_process(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *buf, ssize_t nread)
 {
        struct session *session = handle->data;
-       struct tls_ctx_t *tls_p = session->tls_ctx;
+       struct tls_common_ctx *tls_p = session->outgoing ? &session->tls_client_ctx->c :
+                                                          &session->tls_ctx->c;
        if (!tls_p) {
                return kr_error(ENOSYS);
        }
 
        assert(tls_p->session == session);
 
+       const char *logstring = tls_p->client_side ? client_logstring : server_logstring;
+
        tls_p->buf = buf;
        tls_p->nread = nread >= 0 ? nread : 0;
-       tls_p->consumed = 0;    /* TODO: doesn't handle split TLS records */
+       tls_p->consumed = 0;
 
        /* Ensure TLS handshake is performed before receiving data. */
-       while (!tls_p->handshake_done) {
+       while (tls_p->handshake_state == TLS_HS_IN_PROGRESS) {
                int err = gnutls_handshake(tls_p->tls_session);
                if (err == GNUTLS_E_SUCCESS) {
-                       DEBUG_MSG("[tls] TLS handshake with %s has completed\n",
-                                 kr_straddr(&session->peer.ip));
-                       tls_p->handshake_done = true;
+                       tls_p->handshake_state = TLS_HS_DONE;
+                       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; /* No data, bail out */
+                       return 0;
                } else if (gnutls_error_is_fatal(err)) {
+                       kr_log_error("[%s] gnutls_handshake failed: %s (%d)\n",
+                                    logstring,
+                                    gnutls_strerror_name(err), err);
+                       if (tls_p->handshake_cb) {
+                               tls_p->handshake_cb(tls_p->session, -1);
+                       }
                        return kr_error(err);
                }
        }
@@ -299,11 +306,11 @@ int tls_process(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *b
                } else if (count == GNUTLS_E_INTERRUPTED) {
                        continue; /* Try reading again */
                } else if (count < 0) {
-                       kr_log_error("[tls] gnutls_record_recv failed: %s (%zd)\n",
-                                    gnutls_strerror_name(count), count);
+                       kr_log_error("[%s] gnutls_record_recv failed: %s (%zd)\n",
+                                    logstring, gnutls_strerror_name(count), count);
                        return kr_error(EIO);
                }
-               DEBUG_MSG("[tls] submitting %zd data to worker\n", count);
+               DEBUG_MSG("[%s] submitting %zd data to worker\n", logstring, count);
                int ret = worker_process_tcp(worker, handle, tls_p->recv_buf, count);
                if (ret < 0) {
                        return ret;
@@ -792,7 +799,8 @@ skip_pins:
                };
                size_t data_count = 2;
                unsigned int status;
-               int ret = gnutls_certificate_verify_peers(ctx->tls_session, data, data_count, &status);
+               int ret = gnutls_certificate_verify_peers(ctx->c.tls_session, data,
+                                                         data_count, &status);
                if ((ret == GNUTLS_E_SUCCESS) && (status == 0)) {
                        return GNUTLS_E_SUCCESS;
                }
@@ -802,137 +810,6 @@ skip_pins:
        return GNUTLS_E_CERTIFICATE_ERROR;
 }
 
-static ssize_t kres_gnutls_client_pull(gnutls_transport_ptr_t h, void *buf, size_t len)
-{
-       struct tls_client_ctx_t *t = (struct tls_client_ctx_t *)h;
-       assert(t != NULL);
-
-       ssize_t avail = t->nread - t->consumed;
-       DEBUG_MSG("[tls_client] pull wanted: %zu available: %zu\n", len, avail);
-       if (t->nread <= t->consumed) {
-               errno = EAGAIN;
-               return -1;
-       }
-
-       ssize_t transfer = MIN(avail, len);
-       memcpy(buf, t->buf + t->consumed, transfer);
-       t->consumed += transfer;
-       return transfer;
-}
-
-int tls_client_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt)
-{
-       if (!pkt || !handle || !handle->data) {
-               return kr_error(EINVAL);
-       }
-
-       struct session *session = handle->data;
-       const uint16_t pkt_size = htons(pkt->size);
-       struct tls_client_ctx_t *ctx = session->tls_client_ctx;
-       if (!ctx) {
-               kr_log_error("[tls_client] no tls context on push\n");
-               return kr_error(ENOENT);
-       }
-
-       gnutls_record_cork(ctx->tls_session);
-       ssize_t count = 0;
-       if ((count = gnutls_record_send(ctx->tls_session, &pkt_size, sizeof(pkt_size)) < 0) ||
-           (count = gnutls_record_send(ctx->tls_session, pkt->wire, pkt->size) < 0)) {
-               kr_log_error("[tls_client] gnutls_record_send failed: %s (%zd)\n", gnutls_strerror_name(count), count);
-               return kr_error(EIO);
-       }
-
-       ssize_t submitted = 0;
-       ssize_t retries = 0;
-       do {
-               count = gnutls_record_uncork(ctx->tls_session, 0);
-               if (count < 0) {
-                       if (gnutls_error_is_fatal(count)) {
-                               kr_log_error("[tls_client] gnutls_record_uncork failed: %s (%zd)\n",
-                                            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 {
-                       retries = 0;
-                       submitted += count;
-                       if (count == 0 && submitted != sizeof(pkt_size) + pkt->size) {
-                               kr_log_error("[tls_client] gnutls_record_uncork didn't send all data: %s (%zd)\n",
-                                            gnutls_strerror_name(count), count);
-                               return kr_error(EIO);
-                       }
-               }
-       } while (submitted != sizeof(pkt_size) + pkt->size);
-
-       return kr_ok();
-}
-
-int tls_client_process(struct worker_ctx *worker, uv_stream_t *handle, const uint8_t *buf, ssize_t nread)
-{
-       struct session *session = handle->data;
-       struct tls_client_ctx_t *ctx = session->tls_client_ctx;
-       if (!ctx) {
-               return kr_error(ENOSYS);
-       }
-
-       assert(ctx->handshake_state == TLS_HS_IN_PROGRESS ||
-              ctx->handshake_state == TLS_HS_DONE);
-
-       ctx->buf = buf;
-       ctx->nread = nread >= 0 ? nread : 0;
-       ctx->session = session;
-       ctx->consumed = 0;
-
-       if (ctx->handshake_state == TLS_HS_IN_PROGRESS) {
-               int err = gnutls_handshake(ctx->tls_session);
-               if (err == GNUTLS_E_SUCCESS) {
-                       ctx->handshake_state = TLS_HS_DONE;
-               } else if (err == GNUTLS_E_AGAIN) {
-                       return 0;
-               } else if (gnutls_error_is_fatal(err)) {
-                       kr_log_error("[tls_client] gnutls_handshake failed: %s (%d)\n",
-                                    gnutls_strerror_name(err), err);
-                       if (ctx->handshake_cb) {
-                               ctx->handshake_cb(ctx->session, -1);
-                       }
-                       return kr_error(err);
-               }
-               if (ctx->handshake_cb) {
-                       ctx->handshake_cb(ctx->session, 0);
-               }
-               DEBUG_MSG("[tls_client] TLS handshake with %s has completed.\n",
-                         kr_straddr(&session->peer.ip));
-       }
-
-       int submitted = 0;
-       while (true) {
-               ssize_t count = gnutls_record_recv(ctx->tls_session, ctx->recv_buf, sizeof(ctx->recv_buf));
-               if (count == GNUTLS_E_AGAIN) {
-                       break;    /* No data available */
-               } else if (count == GNUTLS_E_INTERRUPTED) {
-                       continue; /* Try reading again */
-               } else if (count < 0) {
-                       kr_log_error("[tls_client] gnutls_record_recv failed: %s (%zd)\n",
-                                    gnutls_strerror_name(count), count);
-                       return kr_error(EIO);
-               }
-               DEBUG_MSG("[tls_client] submitting %zd data to worker\n", count);
-               int ret = worker_process_tcp(worker, handle, ctx->recv_buf, count);
-               if (ret < 0) {
-                       return ret;
-               }
-               if (count == 0) {
-                       break;
-               }
-               submitted += ret;
-       }
-       return submitted;
-}
-
 struct tls_client_ctx_t *tls_client_ctx_new(const struct tls_client_paramlist_entry *entry,
                                            struct worker_ctx *worker)
 {
@@ -941,30 +818,31 @@ struct tls_client_ctx_t *tls_client_ctx_new(const struct tls_client_paramlist_en
                return NULL;
        }
 
-       int ret = gnutls_init(&ctx->tls_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK);
+       int ret = gnutls_init(&ctx->c.tls_session, GNUTLS_CLIENT | GNUTLS_NONBLOCK);
        if (ret != GNUTLS_E_SUCCESS) {
                tls_client_ctx_free(ctx);
                return NULL;
        }
 
-       ret = kres_gnutls_set_priority(ctx->tls_session);
+       ret = kres_gnutls_set_priority(ctx->c.tls_session);
        if (ret != GNUTLS_E_SUCCESS) {
                tls_client_ctx_free(ctx);
                return NULL;
        }
 
-       ret = gnutls_credentials_set(ctx->tls_session, GNUTLS_CRD_CERTIFICATE,
+       ret = gnutls_credentials_set(ctx->c.tls_session, GNUTLS_CRD_CERTIFICATE,
                                     entry->credentials);
        if (ret != GNUTLS_E_SUCCESS) {
                tls_client_ctx_free(ctx);
                return NULL;
        }
 
-       ctx->worker = worker;
+       ctx->c.worker = worker;
+       ctx->c.client_side = true;
 
-       gnutls_transport_set_pull_function(ctx->tls_session, kres_gnutls_client_pull);
-       gnutls_transport_set_push_function(ctx->tls_session, worker_gnutls_client_push);
-       gnutls_transport_set_ptr(ctx->tls_session, ctx);
+       gnutls_transport_set_pull_function(ctx->c.tls_session, kres_gnutls_pull);
+       gnutls_transport_set_push_function(ctx->c.tls_session, worker_gnutls_push);
+       gnutls_transport_set_ptr(ctx->c.tls_session, ctx);
        return ctx;
 }
 
@@ -974,27 +852,29 @@ void tls_client_ctx_free(struct tls_client_ctx_t *ctx)
                return;
        }
 
-       if (ctx->tls_session != NULL) {
-               gnutls_deinit(ctx->tls_session);
-               ctx->tls_session = NULL;
+       if (ctx->c.tls_session != NULL) {
+               gnutls_deinit(ctx->c.tls_session);
+               ctx->c.tls_session = NULL;
        }
 
        free (ctx);
 }
 
-int tls_client_connect_start(struct tls_client_ctx_t *ctx,
+int tls_client_connect_start(struct tls_client_ctx_t *client_ctx,
                             struct session *session,
                             tls_handshake_cb handshake_cb)
 {
-       if (session == NULL || ctx == NULL) {
+       if (session == NULL || client_ctx == NULL) {
                return kr_error(EINVAL);
        }
 
        assert(session->outgoing && session->handle->type == UV_TCP);
 
-       gnutls_session_set_ptr(ctx->tls_session, ctx);
+       struct tls_common_ctx *ctx = &client_ctx->c;
+
+       gnutls_session_set_ptr(ctx->tls_session, client_ctx);
        gnutls_handshake_set_timeout(ctx->tls_session, 5000);
-       session->tls_client_ctx = ctx;
+       session->tls_client_ctx = client_ctx;
        ctx->handshake_cb = handshake_cb;
        ctx->handshake_state = TLS_HS_IN_PROGRESS;
        ctx->session = session;
@@ -1009,28 +889,12 @@ int tls_client_connect_start(struct tls_client_ctx_t *ctx,
        return kr_error(EAGAIN);
 }
 
-void tls_client_close(struct tls_client_ctx_t *ctx)
-{
-       if (ctx == NULL || ctx->tls_session == NULL) {
-               return;
-       }
-
-       assert(ctx->session);
-
-       if (ctx->handshake_state == TLS_HS_DONE) {
-               DEBUG_MSG("[tls client] closing tls connection to `%s`\n",
-                         kr_straddr(&ctx->session->peer.ip));
-               ctx->handshake_state = TLS_HS_CLOSING;
-               gnutls_bye(ctx->tls_session, GNUTLS_SHUT_RDWR);
-       }
-}
-
-tls_client_hs_state_t tls_client_get_hs_state(const struct tls_client_ctx_t *ctx)
+tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx)
 {
        return ctx->handshake_state;
 }
 
-int tls_client_set_hs_state(struct tls_client_ctx_t *ctx, tls_client_hs_state_t state)
+int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state)
 {
        if (state >= TLS_HS_LAST) {
                return kr_error(EINVAL);
@@ -1047,7 +911,7 @@ int tls_client_ctx_set_params(struct tls_client_ctx_t *ctx,
                return kr_error(EINVAL);
        }
        ctx->params = entry;
-       ctx->session = session;
+       ctx->c.session = session;
        return kr_ok();
 }
 
index 60a040198853dda1dcf022aaf6bccd3fb704a7be..c638fb76497742e26355f8e9fd7cbf8681931607 100644 (file)
@@ -47,60 +47,62 @@ struct tls_client_paramlist_entry {
 struct worker_ctx;
 struct qr_task;
 
-/* gnutls_record_recv and gnutls_record_send */
-struct tls_ctx_t {
-       gnutls_session_t tls_session;
-       bool handshake_done;
-
-       struct session *session;
-
-       /* for reading from the network */
-       const uint8_t *buf;
-       ssize_t nread;
-       ssize_t consumed;
-       uint8_t recv_buf[4096];
-       struct tls_credentials *credentials;
-       struct worker_ctx *worker;
-       struct qr_task *task;
-};
-
 typedef enum tls_client_hs_state {
        TLS_HS_NOT_STARTED = 0,
        TLS_HS_IN_PROGRESS,
        TLS_HS_DONE,
        TLS_HS_CLOSING,
        TLS_HS_LAST
-} tls_client_hs_state_t;
+} tls_hs_state_t;
 
 typedef int (*tls_handshake_cb) (struct session *session, int status);
 
-struct tls_client_ctx_t {
+struct tls_common_ctx {
+       bool client_side;
        gnutls_session_t tls_session;
-       tls_client_hs_state_t handshake_state;
-
+       tls_hs_state_t handshake_state;
        struct session *session;
-       tls_handshake_cb handshake_cb;
+       /* for reading from the network */
        const uint8_t *buf;
        ssize_t nread;
        ssize_t consumed;
        uint8_t recv_buf[4096];
-       const struct tls_client_paramlist_entry *params;
+       tls_handshake_cb handshake_cb;
        struct worker_ctx *worker;
        struct qr_task *task;
 };
 
+struct tls_ctx_t {
+       /*
+        * Since pointer to tls_ctx_t needs to be casted
+        * to  tls_ctx_common in some functions,
+        * this field must be always at first position
+        */
+       struct tls_common_ctx c;
+       struct tls_credentials *credentials;
+};
+
+struct tls_client_ctx_t {
+       /*
+        * Since pointer to tls_client_ctx_t needs to be casted
+        * to  tls_ctx_common in some functions,
+        * this field must be always at first position
+        */
+       struct tls_common_ctx c;
+       const struct tls_client_paramlist_entry *params;
+};
+
 /*! Create an empty TLS context in query context */
 struct tls_ctx_t* tls_new(struct worker_ctx *worker);
 
 /*! Close a TLS context (call gnutls_bye()) */
-void tls_close(struct tls_ctx_t *ctx);
+void tls_close(struct tls_common_ctx *ctx);
 
 /*! Release a TLS context */
 void tls_free(struct tls_ctx_t* tls);
 
 /*! Push new data to TLS context for sending */
-int tls_push(struct qr_task *task, uv_handle_t* handle, knot_pkt_t * pkt,
-            bool server_side);
+int tls_push(struct qr_task *task, uv_handle_t* handle, knot_pkt_t * pkt);
 
 /*! Unwrap incoming data from a TLS stream and pass them to TCP session.
  * @return the number of newly-completed requests (>=0) or an error code
@@ -126,6 +128,12 @@ void tls_credentials_log_pins(struct tls_credentials *tls_credentials);
 /*! Generate new ephemeral TLS credentials. */
 struct tls_credentials * tls_get_ephemeral_credentials(struct engine *engine);
 
+/*! Get TLS handshake state. */
+tls_hs_state_t tls_get_hs_state(const struct tls_common_ctx *ctx);
+
+/*! Set TLS handshake state. */
+int tls_set_hs_state(struct tls_common_ctx *ctx, tls_hs_state_t state);
+
 /*! Set TLS authentication parameters for given address. */
 int tls_client_params_set(map_t *tls_client_paramlist,
                          const char *addr, uint16_t port,
@@ -138,23 +146,13 @@ int tls_client_params_free(map_t *tls_client_paramlist);
 struct tls_client_ctx_t *tls_client_ctx_new(const struct tls_client_paramlist_entry *entry,
                                            struct worker_ctx *worker);
 
-int tls_client_process(struct worker_ctx *worker, uv_stream_t *handle,
-                      const uint8_t *buf, ssize_t nread);
-
 /*! Free client TLS context */
 void tls_client_ctx_free(struct tls_client_ctx_t *ctx);
 
-int tls_client_connect_start(struct tls_client_ctx_t *ctx, struct session *session,
+int tls_client_connect_start(struct tls_client_ctx_t *client_ctx,
+                            struct session *session,
                             tls_handshake_cb handshake_cb);
 
-void tls_client_close(struct tls_client_ctx_t *ctx);
-
-int tls_client_push(struct qr_task *task, uv_handle_t *handle, knot_pkt_t *pkt);
-
-tls_client_hs_state_t tls_client_get_hs_state(const struct tls_client_ctx_t *ctx);
-
-int tls_client_set_hs_state(struct tls_client_ctx_t *ctx, tls_client_hs_state_t state);
-
 int tls_client_ctx_set_params(struct tls_client_ctx_t *ctx,
                              const struct tls_client_paramlist_entry *entry,
                              struct session *session);
index df73a5babe5e680523488a309ddb29d853d167a4..fff8c55d43bfb877fd7ed29f6e64cc939d1b30c9 100644 (file)
@@ -367,10 +367,10 @@ static void session_close(struct session *session)
        if (!uv_is_closing((uv_handle_t *)&session->timeout)) {
                uv_timer_stop(&session->timeout);
                if (session->tls_client_ctx) {
-                       tls_client_close(session->tls_client_ctx);
+                       tls_close(&session->tls_client_ctx->c);
                }
                if (session->tls_ctx) {
-                       tls_close(session->tls_ctx);
+                       tls_close(&session->tls_ctx->c);
                }
 
                session->timeout.data = session;
@@ -897,12 +897,11 @@ static void on_nontask_write(uv_write_t *req, int status)
 
 ssize_t worker_gnutls_push(gnutls_transport_ptr_t h, const void *buf, size_t len)
 {
-       struct tls_ctx_t *t = (struct tls_ctx_t *)h;
+       struct tls_common_ctx *t = (struct tls_common_ctx *)h;
        const uv_buf_t uv_buf[1] = {
                { (char *)buf, len }
        };
 
-       VERBOSE_MSG(NULL,"[tls] push %zu <%p>\n", len, h);
        if (t == NULL) {
                errno = EFAULT;
                return -1;
@@ -911,63 +910,8 @@ ssize_t worker_gnutls_push(gnutls_transport_ptr_t h, const void *buf, size_t len
        assert(t->session && t->session->handle &&
               t->session->handle->type == UV_TCP);
 
-       struct worker_ctx *worker = t->worker;
-       assert(worker);
-
-       void *ioreq = worker_iohandle_borrow(worker);
-       if (!ioreq) {
-               errno = EFAULT;
-               return -1;
-       }
-
-       uv_write_t *write_req = (uv_write_t *)ioreq;
-
-       struct qr_task *task = t->task;
-       uv_write_cb write_cb = on_task_write;
-       if (t->handshake_done) {
-               assert(task);
-       } else {
-               task = NULL;
-               write_cb = on_nontask_write;
-       }
-
-       write_req->data = task;
-
-       ssize_t ret = -1;
-       int res = uv_write(write_req, (uv_stream_t *)t->session->handle, uv_buf, 1, write_cb);
-       if (res == 0) {
-               if (task) {
-                       qr_task_ref(task); /* Pending ioreq on current task */
-               }
-               if (worker->too_many_open &&
-                   worker->stats.rconcurrent <
-                       worker->rconcurrent_highwatermark - 10) {
-                       worker->too_many_open = false;
-               }
-               ret = len;
-       } else {
-               VERBOSE_MSG(NULL,"[tls] uv_write: %s\n", uv_strerror(res));
-               iorequest_release(worker, ioreq);
-               errno = EIO;
-               /* TODO ret == UV_EMFILE */
-       }
-       return ret;
-}
-
-ssize_t worker_gnutls_client_push(gnutls_transport_ptr_t h, const void *buf, size_t len)
-{
-       struct tls_client_ctx_t *t = (struct tls_client_ctx_t *)h;
-       const uv_buf_t uv_buf[1] = {
-               { (char *)buf, len }
-       };
-
-       VERBOSE_MSG(NULL,"[tls client] push %zu <%p>\n", len, h);
-       if (t == NULL) {
-               errno = EFAULT;
-               return -1;
-       }
-       assert(t->session && t->session->handle &&
-              t->session->handle->type == UV_TCP);
+       VERBOSE_MSG(NULL,"[%s] push %zu <%p>\n",
+                   t->client_side ? "tls-client" : "tls", len, h);
 
        struct worker_ctx *worker = t->worker;
        assert(worker);
@@ -1004,7 +948,8 @@ ssize_t worker_gnutls_client_push(gnutls_transport_ptr_t h, const void *buf, siz
                }
                ret = len;
        } else {
-               VERBOSE_MSG(NULL,"[tls_client] uv_write: %s\n", uv_strerror(res));
+               VERBOSE_MSG(NULL,"[%s] uv_write: %s\n",
+                           t->client_side ? "tls-client" : "tls", uv_strerror(res));
                iorequest_release(worker, ioreq);
                errno = EIO;
                /* TODO ret == UV_EMFILE */
@@ -1012,7 +957,8 @@ ssize_t worker_gnutls_client_push(gnutls_transport_ptr_t h, const void *buf, siz
        return ret;
 }
 
-static int qr_task_send(struct qr_task *task, uv_handle_t *handle, struct sockaddr *addr, knot_pkt_t *pkt)
+static int qr_task_send(struct qr_task *task, uv_handle_t *handle,
+                       struct sockaddr *addr, knot_pkt_t *pkt)
 {
        if (!handle) {
                return qr_task_on_send(task, handle, kr_error(EIO));
@@ -1030,7 +976,7 @@ static int qr_task_send(struct qr_task *task, uv_handle_t *handle, struct sockad
                                return ret;
                        }
                }
-               return tls_push(task, handle, pkt, !session->outgoing);
+               return tls_push(task, handle, pkt);
        }
 
        int ret = 0;
@@ -1127,9 +1073,6 @@ static int session_next_waiting_send(struct session *session)
 
 static int session_tls_hs_cb(struct session *session, int status)
 {
-       VERBOSE_MSG(NULL, "=> server: '%s' TLS handshake has %s\n",
-                   kr_straddr(&session->peer.ip), status ? "failed" : "completed");
-
        struct worker_ctx *worker = get_worker();
        union inaddr *peer = &session->peer;
        int deletion_res = worker_del_tcp_waiting(worker, &peer->ip);
@@ -2050,8 +1993,14 @@ int worker_process_tcp(struct worker_ctx *worker, uv_stream_t *handle,
 
                if (session->tls_client_ctx) {
                        /* Avoid gnutls_bye() call */
-                       tls_client_set_hs_state(session->tls_client_ctx,
-                                               TLS_HS_NOT_STARTED);
+                       tls_set_hs_state(&session->tls_client_ctx->c,
+                                        TLS_HS_NOT_STARTED);
+               }
+
+               if (session->tls_ctx) {
+                       /* Avoid gnutls_bye() call */
+                       tls_set_hs_state(&session->tls_ctx->c,
+                                        TLS_HS_NOT_STARTED);
                }
 
                if (session->outgoing && session->buffering) {