]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/session2: protocol layer refactors + docs
authorOto Šťáva <oto.stava@nic.cz>
Tue, 21 May 2024 16:38:56 +0000 (18:38 +0200)
committerOto Šťáva <oto.stava@nic.cz>
Tue, 4 Jun 2024 11:04:59 +0000 (13:04 +0200)
This makes some readability enhancements to the `protolayer_` API as
well as clarifies some of the documentation.

There is also a change where the definitions of protocol layer sequences
does not require a `_NULL` layer to be present at the end anymore, as
the number of layers in a sequence is determined at compile time. This
makes defining new sequences less error-prone.

daemon/http.c
daemon/io.c
daemon/session2.c
daemon/session2.h
daemon/tls.c
daemon/worker.c

index 411fe22218f40012e2c30ea27fc2996f2c83885c..8509f2bc45238fe1336ee1004df4b2ca85cad28f 100644 (file)
@@ -390,8 +390,8 @@ static ssize_t send_callback(nghttp2_session *h2, const uint8_t *data, size_t le
 
        kr_log_debug(DOH, "[%p] send_callback: %p\n", (void *)h2, (void *)send_ctx->data);
        session2_wrap_after(http->h.session, PROTOLAYER_TYPE_HTTP,
-                       protolayer_buffer(send_ctx->data, length, false), NULL,
-                       callback_finished_free_baton, send_ctx);
+                       protolayer_payload_buffer(send_ctx->data, length, false),
+                       NULL, callback_finished_free_baton, send_ctx);
 
        return length;
 }
@@ -506,7 +506,7 @@ static int send_data_callback(nghttp2_session *h2, nghttp2_frame *frame, const u
 
        kr_assert(cur == iovcnt);
        int ret = session2_wrap_after(http->h.session, PROTOLAYER_TYPE_HTTP,
-                       protolayer_iovec(dest_iov, cur, false),
+                       protolayer_payload_iovec(dest_iov, cur, false),
                        NULL, callback_finished_free_baton, sdctx);
 
        if (ret < 0)
@@ -733,7 +733,8 @@ static int submit_to_wirebuffer(struct pl_http_sess_data *ctx)
 
        ret = 0;
        session2_unwrap_after(ctx->h.session, PROTOLAYER_TYPE_HTTP,
-                       protolayer_wire_buf(wb, false), NULL, NULL, NULL);
+                       protolayer_payload_wire_buf(wb, false),
+                       NULL, NULL, NULL);
 cleanup:
        http_cleanup_stream(ctx);
        return ret;
@@ -938,7 +939,7 @@ static enum protolayer_iter_cb_result pl_http_unwrap(
 
        struct protolayer_payload pld = ctx->payload;
        if (pld.type == PROTOLAYER_PAYLOAD_WIRE_BUF) {
-               pld = protolayer_as_buffer(&pld);
+               pld = protolayer_payload_as_buffer(&pld);
        }
 
        if (pld.type == PROTOLAYER_PAYLOAD_BUFFER) {
index d8aee074299f0c450feb5e436917fb6b26705f6d..8333577ded448e9b2db53298697f9210b61f0df5 100644 (file)
@@ -98,7 +98,7 @@ void udp_recv(uv_udp_t *handle, ssize_t nread, const uv_buf_t *buf,
                .comm_addr = comm_addr,
                .src_addr = comm_addr
        };
-       session2_unwrap(s, protolayer_wire_buf(&s->layers->wire_buf, false),
+       session2_unwrap(s, protolayer_payload_wire_buf(&s->layers->wire_buf, false),
                        &in_comm, udp_on_unwrapped, NULL);
 }
 
@@ -146,7 +146,7 @@ struct pl_udp_iter_data {
 static enum protolayer_iter_cb_result pl_udp_unwrap(
                void *sess_data, void *iter_data, struct protolayer_iter_ctx *ctx)
 {
-       ctx->payload = protolayer_as_buffer(&ctx->payload);
+       ctx->payload = protolayer_payload_as_buffer(&ctx->payload);
        if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_BUFFER)) {
                /* unsupported payload */
                return protolayer_break(ctx, kr_error(EINVAL));
@@ -197,7 +197,7 @@ static enum protolayer_iter_cb_result pl_udp_unwrap(
                        }
                }
 
-               ctx->payload = protolayer_buffer(
+               ctx->payload = protolayer_payload_buffer(
                                data + trimmed, data_len - trimmed, false);
        }
 
@@ -278,7 +278,7 @@ static enum protolayer_iter_cb_result pl_tcp_unwrap(
 
                memcpy(wire_buf_free_space(&tcp->wire_buf), buf, len);
                wire_buf_consume(&tcp->wire_buf, ctx->payload.buffer.len);
-               ctx->payload = protolayer_wire_buf(&tcp->wire_buf, false);
+               ctx->payload = protolayer_payload_wire_buf(&tcp->wire_buf, false);
        }
 
        if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF)) {
@@ -511,7 +511,7 @@ static void tcp_recv(uv_stream_t *handle, ssize_t nread, const uv_buf_t *buf)
                return;
        }
 
-       session2_unwrap(s, protolayer_wire_buf(&s->layers->wire_buf, false),
+       session2_unwrap(s, protolayer_payload_wire_buf(&s->layers->wire_buf, false),
                        NULL, NULL, NULL);
 }
 
@@ -950,7 +950,7 @@ static void xdp_rx(uv_poll_t* handle, int status, int events)
                memcpy(comm.eth_from, msg->eth_from, sizeof(comm.eth_from));
                memcpy(comm.eth_to, msg->eth_to, sizeof(comm.eth_to));
                session2_unwrap(xhd->session,
-                               protolayer_buffer(
+                               protolayer_payload_buffer(
                                        msg->payload.iov_base,
                                        msg->payload.iov_len, false),
                                &comm, NULL, NULL);
index dc9911a0b1688e3c289453ff9afeac9c58b822ee..fa3feb9c4bb91a4cd362632dd8eb8ff5b9549489 100644 (file)
@@ -36,20 +36,17 @@ struct protolayer_globals protolayer_globals[PROTOLAYER_TYPE_COUNT] = {{0}};
 static const enum protolayer_type protolayer_grp_udp53[] = {
        PROTOLAYER_TYPE_UDP,
        PROTOLAYER_TYPE_DNS_DGRAM,
-       PROTOLAYER_TYPE_NULL
 };
 
 static const enum protolayer_type protolayer_grp_tcp53[] = {
        PROTOLAYER_TYPE_TCP,
        PROTOLAYER_TYPE_DNS_MULTI_STREAM,
-       PROTOLAYER_TYPE_NULL
 };
 
 static const enum protolayer_type protolayer_grp_dot[] = {
        PROTOLAYER_TYPE_TCP,
        PROTOLAYER_TYPE_TLS,
        PROTOLAYER_TYPE_DNS_MULTI_STREAM,
-       PROTOLAYER_TYPE_NULL
 };
 
 static const enum protolayer_type protolayer_grp_doh[] = {
@@ -57,14 +54,23 @@ static const enum protolayer_type protolayer_grp_doh[] = {
        PROTOLAYER_TYPE_TLS,
        PROTOLAYER_TYPE_HTTP,
        PROTOLAYER_TYPE_DNS_UNSIZED_STREAM,
-       PROTOLAYER_TYPE_NULL
 };
 
 static const enum protolayer_type protolayer_grp_doq[] = {
        // not yet used
-       PROTOLAYER_TYPE_NULL
+       PROTOLAYER_TYPE_NULL,
 };
 
+struct protolayer_grp {
+       const enum protolayer_type *layers;
+       size_t num_layers;
+};
+
+#define PROTOLAYER_GRP(p_array) { \
+       .layers = (p_array), \
+       .num_layers = sizeof((p_array)) / sizeof((p_array)[0]), \
+}
+
 /** Sequences of layers, or groups, mapped by `enum kr_proto`.
  *
  * Each group represents a sequence of layers in the unwrap direction (wrap
@@ -78,8 +84,8 @@ static const enum protolayer_type protolayer_grp_doq[] = {
  * indicate the end of the list of protocol layers. The array name's suffix must
  * be the one defined as *Variable name* (2nd parameter) in the
  * `KR_PROTO_MAP` macro. */
-static const enum protolayer_type *protolayer_grps[KR_PROTO_COUNT] = {
-#define XX(cid, vid, name) [KR_PROTO_##cid] = protolayer_grp_##vid,
+static const struct protolayer_grp protolayer_grps[KR_PROTO_COUNT] = {
+#define XX(cid, vid, name) [KR_PROTO_##cid] = PROTOLAYER_GRP(protolayer_grp_##vid),
        KR_PROTO_MAP(XX)
 #undef XX
 };
@@ -222,7 +228,8 @@ size_t protolayer_payload_copy(void *dest,
        }
 }
 
-struct protolayer_payload protolayer_as_buffer(const struct protolayer_payload *payload)
+struct protolayer_payload protolayer_payload_as_buffer(
+               const struct protolayer_payload *payload)
 {
        if (payload->type == PROTOLAYER_PAYLOAD_BUFFER)
                return *payload;
@@ -296,12 +303,13 @@ bool protolayer_queue_has_payload(const protolayer_iter_ctx_queue_t *queue)
 static inline struct protolayer_data *protolayer_sess_data_get(
                struct protolayer_manager *m, size_t layer_ix)
 {
-       if (kr_fails_assert(layer_ix < m->num_layers))
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       if (kr_fails_assert(layer_ix < grp->num_layers))
                return NULL;
 
        /* See doc comment of `struct protolayer_manager::data` */
        const ssize_t *offsets = (ssize_t *)m->data;
-       char *pl_data_beg = &m->data[2 * m->num_layers * sizeof(*offsets)];
+       char *pl_data_beg = &m->data[2 * grp->num_layers * sizeof(*offsets)];
        ssize_t offset = offsets[layer_ix];
 
        if (offset < 0) /* No session data for this layer */
@@ -316,11 +324,12 @@ static inline struct protolayer_data *protolayer_iter_data_get(
                struct protolayer_iter_ctx *ctx, size_t layer_ix)
 {
        struct protolayer_manager *m = ctx->manager;
-       if (kr_fails_assert(layer_ix < m->num_layers))
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       if (kr_fails_assert(layer_ix < grp->num_layers))
                return NULL;
 
        /* See doc comment of `struct protolayer_manager::data` */
-       const ssize_t *offsets = (ssize_t *)&m->data[m->num_layers * sizeof(*offsets)];
+       const ssize_t *offsets = (ssize_t *)&m->data[grp->num_layers * sizeof(*offsets)];
        ssize_t offset = offsets[layer_ix];
 
        if (offset < 0) /* No iteration data for this layer */
@@ -332,8 +341,9 @@ static inline struct protolayer_data *protolayer_iter_data_get(
 static inline ssize_t protolayer_manager_get_protocol(
                struct protolayer_manager *m, enum protolayer_type protocol)
 {
-       for (ssize_t i = 0; i < m->num_layers; i++) {
-               enum protolayer_type found = protolayer_grps[m->grp][i];
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       for (ssize_t i = 0; i < grp->num_layers; i++) {
+               enum protolayer_type found = grp->layers[i];
                if (protocol == found)
                        return i;
        }
@@ -344,7 +354,7 @@ static inline ssize_t protolayer_manager_get_protocol(
 static inline bool protolayer_iter_ctx_is_last(struct protolayer_iter_ctx *ctx)
 {
        unsigned int last_ix = (ctx->direction == PROTOLAYER_UNWRAP)
-               ? ctx->manager->num_layers - 1
+               ? protolayer_grps[ctx->manager->proto].num_layers - 1
                : 0;
        return ctx->layer_ix == last_ix;
 }
@@ -361,13 +371,13 @@ static inline const char *layer_name(enum kr_proto grp, ssize_t layer_ix)
 {
        if (grp >= KR_PROTO_COUNT)
                return "(invalid)";
-       enum protolayer_type p = protolayer_grps[grp][layer_ix];
+       enum protolayer_type p = protolayer_grps[grp].layers[layer_ix];
        return protolayer_layer_name(p);
 }
 
 static inline const char *layer_name_ctx(struct protolayer_iter_ctx *ctx)
 {
-       return layer_name(ctx->manager->grp, ctx->layer_ix);
+       return layer_name(ctx->manager->proto, ctx->layer_ix);
 }
 
 static int protolayer_iter_ctx_finish(struct protolayer_iter_ctx *ctx, int ret)
@@ -375,8 +385,9 @@ static int protolayer_iter_ctx_finish(struct protolayer_iter_ctx *ctx, int ret)
        struct session2 *session = ctx->manager->session;
 
        struct protolayer_manager *m = ctx->manager;
-       struct protolayer_globals *globals = &protolayer_globals[m->grp];
-       for (size_t i = 0; i < m->num_layers; i++) {
+       const struct protolayer_globals *globals = &protolayer_globals[m->proto];
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       for (size_t i = 0; i < grp->num_layers; i++) {
                struct protolayer_data *d = protolayer_iter_data_get(ctx, i);
                if (globals->iter_deinit)
                        globals->iter_deinit(m, ctx, d);
@@ -384,12 +395,12 @@ static int protolayer_iter_ctx_finish(struct protolayer_iter_ctx *ctx, int ret)
 
        if (ret)
                VERBOSE_LOG(session, "layer context of group '%s' (on %u: %s) ended with return code %d\n",
-                               kr_proto_name(ctx->manager->grp),
+                               kr_proto_name(ctx->manager->proto),
                                ctx->layer_ix, layer_name_ctx(ctx), ret);
 
        if (ctx->status)
                VERBOSE_LOG(session, "iteration of group '%s' (on %u: %s) ended with status %d\n",
-                               kr_proto_name(ctx->manager->grp),
+                               kr_proto_name(ctx->manager->proto),
                                ctx->layer_ix, layer_name_ctx(ctx), ctx->status);
 
        if (ctx->finished_cb)
@@ -415,7 +426,7 @@ static int protolayer_push(struct protolayer_iter_ctx *ctx)
        struct session2 *session = ctx->manager->session;
 
        if (ctx->payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF) {
-               ctx->payload = protolayer_as_buffer(&ctx->payload);
+               ctx->payload = protolayer_payload_as_buffer(&ctx->payload);
        }
 
        if (kr_log_is_debug(PROTOLAYER, NULL)) {
@@ -441,7 +452,7 @@ static int protolayer_push(struct protolayer_iter_ctx *ctx)
        return PROTOLAYER_RET_ASYNC;
 }
 
-static void protolayer_ensure_long_lived(struct protolayer_iter_ctx *ctx)
+static void protolayer_payload_ensure_long_lived(struct protolayer_iter_ctx *ctx)
 {
        if (!ctx->payload.short_lived)
                return;
@@ -455,7 +466,7 @@ static void protolayer_ensure_long_lived(struct protolayer_iter_ctx *ctx)
        protolayer_payload_copy(buf, &ctx->payload, buf_len);
 
        ctx->async_buffer = buf;
-       ctx->payload = protolayer_buffer(buf, buf_len, false);
+       ctx->payload = protolayer_payload_buffer(buf, buf_len, false);
 }
 
 /** Processes as many layers as possible synchronously, returning when either
@@ -466,10 +477,10 @@ static void protolayer_ensure_long_lived(struct protolayer_iter_ctx *ctx)
 static int protolayer_step(struct protolayer_iter_ctx *ctx)
 {
        while (true) {
-               if (kr_fails_assert(ctx->manager->grp < KR_PROTO_COUNT))
+               if (kr_fails_assert(ctx->manager->proto < KR_PROTO_COUNT))
                        return kr_error(EFAULT);
 
-               enum protolayer_type protocol = protolayer_grps[ctx->manager->grp][ctx->layer_ix];
+               enum protolayer_type protocol = protolayer_grps[ctx->manager->proto].layers[ctx->layer_ix];
                struct protolayer_globals *globals = &protolayer_globals[protocol];
 
                ctx->async_mode = false;
@@ -502,7 +513,7 @@ static int protolayer_step(struct protolayer_iter_ctx *ctx)
                if (!ctx->action) {
                        /* Next step is from a callback */
                        ctx->async_mode = true;
-                       protolayer_ensure_long_lived(ctx);
+                       protolayer_payload_ensure_long_lived(ctx);
                        return PROTOLAYER_RET_ASYNC;
                }
 
@@ -551,15 +562,18 @@ static int protolayer_manager_submit(
        if (manager->session->closing)
                return kr_error(ECANCELED);
 
+       if (kr_fails_assert(manager->proto < KR_PROTO_COUNT))
+               return kr_error(EFAULT);
+
        struct protolayer_iter_ctx *ctx = malloc(manager->cb_ctx_size);
        kr_require(ctx);
 
        VERBOSE_LOG(manager->session,
                        "%s submitted to grp '%s' in %s direction (%zu: %s)\n",
                        protolayer_payload_name(payload.type),
-                       kr_proto_name(manager->grp),
+                       kr_proto_name(manager->proto),
                        (direction == PROTOLAYER_UNWRAP) ? "unwrap" : "wrap",
-                       layer_ix, layer_name(manager->grp, layer_ix));
+                       layer_ix, layer_name(manager->proto, layer_ix));
 
        *ctx = (struct protolayer_iter_ctx) {
                .payload = payload,
@@ -571,12 +585,9 @@ static int protolayer_manager_submit(
                .finished_cb_baton = baton
        };
 
-       for (size_t i = 0; i < manager->num_layers; i++) {
-               if (kr_fails_assert(ctx->manager->grp < KR_PROTO_COUNT))
-                       return kr_error(EFAULT);
-
-               enum protolayer_type p = protolayer_grps[manager->grp][i];
-               struct protolayer_globals *globals = &protolayer_globals[p];
+       const struct protolayer_grp *grp = &protolayer_grps[manager->proto];
+       for (size_t i = 0; i < grp->num_layers; i++) {
+               struct protolayer_globals *globals = &protolayer_globals[grp->layers[i]];
                struct protolayer_data *iter_data = protolayer_iter_data_get(ctx, i);
                if (iter_data) {
                        memset(iter_data, 0, globals->iter_size);
@@ -606,41 +617,33 @@ static void *get_init_param(enum protolayer_type p,
 /** Allocates and initializes a new manager. */
 static struct protolayer_manager *protolayer_manager_new(
                struct session2 *s,
-               enum kr_proto grp,
+               enum kr_proto proto,
                struct protolayer_data_param *layer_param,
                size_t layer_param_count)
 {
-       if (kr_fails_assert(s && grp))
+       if (kr_fails_assert(s && proto))
                return NULL;
 
-       size_t num_layers = 0;
        size_t manager_size = sizeof(struct protolayer_manager);
        size_t cb_ctx_size = sizeof(struct protolayer_iter_ctx);
 
-       const enum protolayer_type *protocols = protolayer_grps[grp];
-       if (kr_fails_assert(protocols))
-               return NULL;
-       const enum protolayer_type *p = protocols;
-
-       /* Space for offset index */
-       for (; *p; p++)
-               num_layers++;
-       if (kr_fails_assert(num_layers))
+       const struct protolayer_grp *grp = &protolayer_grps[proto];
+       if (kr_fails_assert(grp->num_layers))
                return NULL;
 
        size_t wire_buf_length = 0;
        size_t wire_buf_max_length = 0;
-       ssize_t offsets[2 * num_layers];
+       ssize_t offsets[2 * grp->num_layers];
        manager_size += sizeof(offsets);
 
        ssize_t *sess_offsets = offsets;
-       ssize_t *iter_offsets = &offsets[num_layers];
+       ssize_t *iter_offsets = &offsets[grp->num_layers];
 
        /* Space for layer-specific data, guaranteeing alignment */
        size_t total_sess_data_size = 0;
        size_t total_iter_data_size = 0;
-       for (size_t i = 0; i < num_layers; i++) {
-               const struct protolayer_globals *g = &protolayer_globals[protocols[i]];
+       for (size_t i = 0; i < grp->num_layers; i++) {
+               const struct protolayer_globals *g = &protolayer_globals[grp->layers[i]];
 
                sess_offsets[i] = g->sess_size ? total_sess_data_size : -1;
                total_sess_data_size += ALIGN_TO(g->sess_size, CPU_STRUCT_ALIGN);
@@ -660,9 +663,8 @@ static struct protolayer_manager *protolayer_manager_new(
        /* Allocate and initialize manager */
        struct protolayer_manager *m = calloc(1, manager_size);
        kr_require(m);
-       m->grp = grp;
+       m->proto = proto;
        m->session = s;
-       m->num_layers = num_layers;
        m->cb_ctx_size = cb_ctx_size;
        memcpy(m->data, offsets, sizeof(offsets));
 
@@ -671,15 +673,15 @@ static struct protolayer_manager *protolayer_manager_new(
        kr_require(!ret);
 
        /* Initialize the layer's session data */
-       for (size_t i = 0; i < num_layers; i++) {
-               struct protolayer_globals *globals = &protolayer_globals[protocols[i]];
+       for (size_t i = 0; i < grp->num_layers; i++) {
+               struct protolayer_globals *globals = &protolayer_globals[grp->layers[i]];
                struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
                if (sess_data) {
                        memset(sess_data, 0, globals->sess_size);
                        sess_data->session = s;
                }
 
-               void *param = get_init_param(protocols[i], layer_param, layer_param_count);
+               void *param = get_init_param(grp->layers[i], layer_param, layer_param_count);
                if (globals->sess_init)
                        globals->sess_init(m, sess_data, param);
        }
@@ -692,9 +694,9 @@ static void protolayer_manager_free(struct protolayer_manager *m)
 {
        if (!m) return;
 
-       for (size_t i = 0; i < m->num_layers; i++) {
-               enum protolayer_type p = protolayer_grps[m->grp][i];
-               struct protolayer_globals *globals = &protolayer_globals[p];
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       for (size_t i = 0; i < grp->num_layers; i++) {
+               struct protolayer_globals *globals = &protolayer_globals[grp->layers[i]];
                if (globals->sess_deinit) {
                        struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
                        globals->sess_deinit(m, sess_data);
@@ -751,8 +753,9 @@ int wire_buf_reserve(struct wire_buf *wb, size_t size)
        if (wb->buf && wb->size >= size)
                return kr_ok();
 
-       wb->buf = realloc(wb->buf, size);
-       kr_require(wb->buf);
+       char *newbuf = realloc(wb->buf, size);
+       kr_require(newbuf);
+       wb->buf = newbuf;
        wb->size = size;
        return kr_ok();
 }
@@ -1194,7 +1197,7 @@ int session2_wrap(struct session2 *s, struct protolayer_payload payload,
                   void *baton)
 {
        return protolayer_manager_submit(s->layers, PROTOLAYER_WRAP,
-                       s->layers->num_layers - 1,
+                       protolayer_grps[s->layers->proto].num_layers - 1,
                        payload, comm, cb, baton);
 }
 
@@ -1214,9 +1217,9 @@ static void session2_event_wrap(struct session2 *s, enum protolayer_event_type e
 {
        bool cont;
        struct protolayer_manager *m = s->layers;
-       for (ssize_t i = m->num_layers - 1; i >= 0; i--) {
-               enum protolayer_type p = protolayer_grps[s->layers->grp][i];
-               struct protolayer_globals *globals = &protolayer_globals[p];
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       for (ssize_t i = grp->num_layers - 1; i >= 0; i--) {
+               struct protolayer_globals *globals = &protolayer_globals[grp->layers[i]];
                if (globals->event_wrap) {
                        struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
                        cont = globals->event_wrap(event, &baton, m, sess_data);
@@ -1235,9 +1238,9 @@ void session2_event_unwrap(struct session2 *s, ssize_t start_ix, enum protolayer
 {
        bool cont;
        struct protolayer_manager *m = s->layers;
-       for (ssize_t i = start_ix; i < m->num_layers; i++) {
-               enum protolayer_type p = protolayer_grps[s->layers->grp][i];
-               struct protolayer_globals *globals = &protolayer_globals[p];
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       for (ssize_t i = start_ix; i < grp->num_layers; i++) {
+               struct protolayer_globals *globals = &protolayer_globals[grp->layers[i]];
                if (globals->event_unwrap) {
                        struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
                        cont = globals->event_unwrap(event, &baton, m, sess_data);
@@ -1275,9 +1278,9 @@ void session2_event_after(struct session2 *s, enum protolayer_type protocol,
 void session2_init_request(struct session2 *s, struct kr_request *req)
 {
        struct protolayer_manager *m = s->layers;
-       for (ssize_t i = 0; i < m->num_layers; i++) {
-               enum protolayer_type p = protolayer_grps[s->layers->grp][i];
-               struct protolayer_globals *globals = &protolayer_globals[p];
+       const struct protolayer_grp *grp = &protolayer_grps[m->proto];
+       for (ssize_t i = 0; i < grp->num_layers; i++) {
+               struct protolayer_globals *globals = &protolayer_globals[grp->layers[i]];
                if (globals->request_init) {
                        struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
                        globals->request_init(m, req, sess_data);
@@ -1519,7 +1522,7 @@ static int session2_transport_pushv(struct session2 *s,
                        goto exit_err;
                }
                int ret = session2_wrap(parent,
-                               protolayer_iovec(iov, iovcnt, iov_short_lived),
+                               protolayer_payload_iovec(iov, iovcnt, iov_short_lived),
                                comm, session2_transport_parent_pushv_finished,
                                ctx);
                return (ret < 0) ? ret : kr_ok();
index cda0bd5a16e7586adf9263dfb6dbfcc96b9487ef..f65cf5d6ba1dbb7e907244486908e8fbef8164c3 100644 (file)
@@ -338,7 +338,7 @@ const char *protolayer_event_name(enum protolayer_event_type e);
  * valid. */
 enum protolayer_payload_type {
        PROTOLAYER_PAYLOAD_NULL = 0,
-#define XX(cid, name) PROTOLAYER_PAYLOAD_ ## cid,
+#define XX(cid, name) PROTOLAYER_PAYLOAD_##cid,
        PROTOLAYER_PAYLOAD_MAP(XX)
 #undef XX
        PROTOLAYER_PAYLOAD_COUNT
@@ -357,9 +357,17 @@ struct protolayer_payload {
        /** Time-to-live hint (e.g. for HTTP Cache-Control) */
        unsigned int ttl;
 
-       /** If `true`, the payload's memory may be freed early as kresd does not
-        * completely control its lifetime. When going asynchronous, it needs to
-        * be copied. */
+       /** If `true`, signifies that the memory this payload points to may
+        * become invalid when we return from one of the functions in the
+        * current stack. That is fine as long as all the protocol layer
+        * processing for this payload takes place in a single `session2_wrap()`
+        * or `session2_unwrap()` call, but may become a problem, when a layer
+        * goes asynchronous (via `protolayer_async()`).
+        *
+        * Setting this to `true` will ensure that the payload will get copied
+        * into a separate memory buffer if and only if a layer goes
+        * asynchronous. It makes sure that if all processing for the payload is
+        * synchronous, no copies or reallocations for the payload are done. */
        bool short_lived;
 
        union {
@@ -421,8 +429,8 @@ size_t protolayer_payload_copy(void *dest,
                                size_t max_len);
 
 /** Convenience function to get a buffer-type payload. */
-static inline struct protolayer_payload protolayer_buffer(void *buf, size_t len,
-                                                          bool short_lived)
+static inline struct protolayer_payload protolayer_payload_buffer(
+               void *buf, size_t len, bool short_lived)
 {
        return (struct protolayer_payload){
                .type = PROTOLAYER_PAYLOAD_BUFFER,
@@ -435,7 +443,7 @@ static inline struct protolayer_payload protolayer_buffer(void *buf, size_t len,
 }
 
 /** Convenience function to get an iovec-type payload. */
-static inline struct protolayer_payload protolayer_iovec(
+static inline struct protolayer_payload protolayer_payload_iovec(
                struct iovec *iov, int iovcnt, bool short_lived)
 {
        return (struct protolayer_payload){
@@ -449,7 +457,7 @@ static inline struct protolayer_payload protolayer_iovec(
 }
 
 /** Convenience function to get a wire-buf-type payload. */
-static inline struct protolayer_payload protolayer_wire_buf(
+static inline struct protolayer_payload protolayer_payload_wire_buf(
                struct wire_buf *wire_buf, bool short_lived)
 {
        return (struct protolayer_payload){
@@ -466,7 +474,8 @@ static inline struct protolayer_payload protolayer_wire_buf(
  * If the input payload is `_WIRE_BUF`, the pointed-to wire buffer is reset to
  * indicate that all of its contents have been used up, and the buffer is ready
  * to be reused. */
-struct protolayer_payload protolayer_as_buffer(const struct protolayer_payload *payload);
+struct protolayer_payload protolayer_payload_as_buffer(
+               const struct protolayer_payload *payload);
 
 /** A predefined queue type for iteration context. */
 typedef queue_t(struct protolayer_iter_ctx *) protolayer_iter_ctx_queue_t;
@@ -580,11 +589,10 @@ typedef void (*protolayer_request_cb)(struct protolayer_manager *manager,
  * `grp`), which define how the data processed by the session is to be
  * interpreted. */
 struct protolayer_manager {
-       enum kr_proto grp;
+       enum kr_proto proto;
        struct wire_buf wire_buf;
        size_t wire_buf_max_length;
        struct session2 *session;
-       size_t num_layers;
        size_t cb_ctx_size; /**< Size of a single callback context, including
                             * layer-specific per-iteration data. */
 
index 377355f7a4eb97142ae812b2bb97643117a139ee..fd684518145ac8255607195e806647ef4cfc4d24 100644 (file)
@@ -229,8 +229,8 @@ static ssize_t kres_gnutls_vec_push(gnutls_transport_ptr_t h, const giovec_t * i
        memcpy(push_ctx->iov, iov, sizeof(struct iovec[iovcnt]));
 
        session2_wrap_after(tls->h.session, PROTOLAYER_TYPE_TLS,
-                       protolayer_iovec(push_ctx->iov, iovcnt, true), NULL,
-                       kres_gnutls_push_finished, push_ctx);
+                       protolayer_payload_iovec(push_ctx->iov, iovcnt, true),
+                       NULL, kres_gnutls_push_finished, push_ctx);
 
        return total_len;
 }
@@ -967,7 +967,7 @@ static int pl_tls_sess_server_init(struct protolayer_manager *manager,
                                          tls->tls_session);
        }
 
-       const gnutls_datum_t *alpn = &tls_grp_alpn[manager->grp];
+       const gnutls_datum_t *alpn = &tls_grp_alpn[manager->proto];
        if (alpn->size) { /* ALPN is a non-empty string */
                flags = 0;
 #if GNUTLS_VERSION_NUMBER >= 0x030500
@@ -1160,7 +1160,7 @@ static enum protolayer_iter_cb_result pl_tls_unwrap(void *sess_data, void *iter_
        struct protolayer_iter_ctx *ctx_head = queue_head(tls->unwrap_queue);
        if (!kr_fails_assert(ctx == ctx_head))
                queue_pop(tls->unwrap_queue);
-       ctx->payload = protolayer_wire_buf(&tls->unwrap_buf, false);
+       ctx->payload = protolayer_payload_wire_buf(&tls->unwrap_buf, false);
        return protolayer_continue(ctx);
 
 exit_break:
@@ -1174,7 +1174,7 @@ static ssize_t pl_tls_submit(gnutls_session_t tls_session,
                              struct protolayer_payload payload)
 {
        if (payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF)
-               payload = protolayer_as_buffer(&payload);
+               payload = protolayer_payload_as_buffer(&payload);
 
        if (payload.type == PROTOLAYER_PAYLOAD_BUFFER) {
                ssize_t count = gnutls_record_send(tls_session,
index 1ac52266184da04762635908ca89a7ac092d7e2e..31070f0da86088aa9f424c581b0f67b223441f3b 100644 (file)
@@ -662,7 +662,7 @@ static int qr_task_send(struct qr_task *task, struct session2 *session,
 
        /* Pending '_finished' callback on current task */
        qr_task_ref(task);
-       struct protolayer_payload payload = protolayer_buffer(
+       struct protolayer_payload payload = protolayer_payload_buffer(
                        (char *)pkt->wire, pkt->size, false);
        payload.ttl = packet_ttl(pkt);
        ret = session2_wrap(session, payload, comm, qr_task_wrap_finished, task);
@@ -2262,7 +2262,7 @@ static enum protolayer_iter_cb_result pl_dns_stream_wrap(
                stream->sent.mem = siov;
                stream->sent.pool = &s->pool;
 
-               ctx->payload = protolayer_iovec(siov->iovs, iovcnt, false);
+               ctx->payload = protolayer_payload_iovec(siov->iovs, iovcnt, false);
                return protolayer_continue(ctx);
        } else if (ctx->payload.type == PROTOLAYER_PAYLOAD_IOVEC) {
                const int iovcnt = 1 + ctx->payload.iovec.cnt;
@@ -2288,7 +2288,7 @@ static enum protolayer_iter_cb_result pl_dns_stream_wrap(
                stream->sent.mem = siov;
                stream->sent.pool = &s->pool;
 
-               ctx->payload = protolayer_iovec(siov->iovs, iovcnt, false);
+               ctx->payload = protolayer_payload_iovec(siov->iovs, iovcnt, false);
                return protolayer_continue(ctx);
        } else {
                kr_assert(false && "Invalid payload");