]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
daemon/session2: move iteration data into struct protolayer_cb_ctx
authorOto Šťáva <oto.stava@nic.cz>
Tue, 13 Sep 2022 10:12:30 +0000 (12:12 +0200)
committerOto Šťáva <oto.stava@nic.cz>
Thu, 26 Jan 2023 11:56:08 +0000 (12:56 +0100)
daemon/io.c
daemon/session2.c
daemon/session2.h
daemon/tls.c
daemon/worker.c

index 6d1d069e70ec44ed3da634e0f607b762b383cbac..daac2ffc93216b158543ce2f1042093a8eb38ec6 100644 (file)
@@ -132,18 +132,20 @@ static int family_to_freebind_option(sa_family_t sa_family, int *level, int *nam
 
 
 struct pl_udp_iter_data {
+       PROTOLAYER_DATA_HEADER();
        struct proxy_result proxy;
        bool has_proxy;
 };
 
-static int pl_udp_iter_init(struct protolayer_manager *manager, struct protolayer_data *layer)
+static int pl_udp_iter_init(struct protolayer_manager *manager, void *iter_data)
 {
-       struct pl_udp_iter_data *udp = protolayer_iter_data(layer);
+       struct pl_udp_iter_data *udp = iter_data;
        *udp = (struct pl_udp_iter_data){0};
        return 0;
 }
 
-static enum protolayer_cb_result pl_udp_unwrap(struct protolayer_data *layer, struct protolayer_cb_ctx *ctx)
+static enum protolayer_cb_result pl_udp_unwrap(
+               void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
 {
        ctx->payload = protolayer_as_buffer(&ctx->payload);
        if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_BUFFER)) {
@@ -152,7 +154,7 @@ static enum protolayer_cb_result pl_udp_unwrap(struct protolayer_data *layer, st
        }
 
        struct session2 *s = ctx->manager->session;
-       struct pl_udp_iter_data *udp = protolayer_iter_data(layer);
+       struct pl_udp_iter_data *udp = iter_data;
 
        char *data = ctx->payload.buffer.buf;
        ssize_t data_len = ctx->payload.buffer.len;
@@ -207,7 +209,7 @@ static enum protolayer_cb_result pl_udp_unwrap(struct protolayer_data *layer, st
 static bool pl_udp_event_wrap(enum protolayer_event_type event,
                               void **baton,
                               struct protolayer_manager *manager,
-                              struct protolayer_data *layer)
+                              void *sess_data)
 {
        if (event == PROTOLAYER_EVENT_STATS_SEND_ERR) {
                the_worker->stats.err_udp += 1;
@@ -222,30 +224,32 @@ static bool pl_udp_event_wrap(enum protolayer_event_type event,
 
 
 struct pl_tcp_sess_data {
+       PROTOLAYER_DATA_HEADER();
        struct proxy_result proxy;
        struct wire_buf wire_buf;
        bool had_data : 1;
        bool has_proxy : 1;
 };
 
-static int pl_tcp_sess_init(struct protolayer_manager *manager, struct protolayer_data *layer, void *param)
+static int pl_tcp_sess_init(struct protolayer_manager *manager, void *sess_data, void *param)
 {
-       struct pl_tcp_sess_data *tcp = protolayer_sess_data(layer);
+       struct pl_tcp_sess_data *tcp = sess_data;
        *tcp = (struct pl_tcp_sess_data){0};
        return 0;
 }
 
-static int pl_tcp_sess_deinit(struct protolayer_manager *manager, struct protolayer_data *layer)
+static int pl_tcp_sess_deinit(struct protolayer_manager *manager, void *sess_data)
 {
-       struct pl_tcp_sess_data *tcp = protolayer_sess_data(layer);
+       struct pl_tcp_sess_data *tcp = sess_data;
        wire_buf_deinit(&tcp->wire_buf);
        return 0;
 }
 
-static enum protolayer_cb_result pl_tcp_unwrap(struct protolayer_data *layer, struct protolayer_cb_ctx *ctx)
+static enum protolayer_cb_result pl_tcp_unwrap(
+               void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
 {
        struct session2 *s = ctx->manager->session;
-       struct pl_tcp_sess_data *tcp = protolayer_sess_data(layer);
+       struct pl_tcp_sess_data *tcp = sess_data;
        struct sockaddr *peer = session2_get_peer(s);
 
        if (ctx->payload.type == PROTOLAYER_PAYLOAD_BUFFER) {
@@ -342,7 +346,7 @@ static enum protolayer_cb_result pl_tcp_unwrap(struct protolayer_data *layer, st
 static bool pl_tcp_event_wrap(enum protolayer_event_type event,
                               void **baton,
                               struct protolayer_manager *manager,
-                              struct protolayer_data *layer)
+                              void *sess_data)
 {
        if (event == PROTOLAYER_EVENT_STATS_SEND_ERR) {
                the_worker->stats.err_tcp += 1;
index 474772898390ce665cd0fde1d3451d79a53ba7f6..68363c6bb5a1e611cd8f21d69bb5c0aa06edfe4d 100644 (file)
@@ -109,24 +109,50 @@ struct protolayer_payload protolayer_as_buffer(const struct protolayer_payload *
 }
 
 
-/** Gets context for the layer with the specified index from the manager. */
-static inline struct protolayer_data *protolayer_manager_get(
+/** Gets layer-specific session data for the layer with the specified index
+ * from the manager. */
+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))
                return NULL;
 
-       const size_t *offsets = (size_t *)m->data;
-       char *pl_data_beg = m->data + (m->num_layers * sizeof(*offsets));
-       return (struct protolayer_data *)(pl_data_beg + offsets[layer_ix]);
+       /* 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)];
+       ssize_t offset = offsets[layer_ix];
+
+       if (offset < 0) /* No session data for this layer */
+               return NULL;
+
+       return (struct protolayer_data *)(pl_data_beg + offset);
+}
+
+/** Gets layer-specific iteration data for the layer with the specified index
+ * from the context. */
+static inline struct protolayer_data *protolayer_iter_data_get(
+               struct protolayer_cb_ctx *ctx, size_t layer_ix)
+{
+       struct protolayer_manager *m = ctx->manager;
+       if (kr_fails_assert(layer_ix < m->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)];
+       ssize_t offset = offsets[layer_ix];
+
+       if (offset < 0) /* No iteration data for this layer */
+               return NULL;
+
+       return (struct protolayer_data *)(ctx->data + offset);
 }
 
 static inline ssize_t protolayer_manager_get_protocol(
                struct protolayer_manager *m, enum protolayer_protocol protocol)
 {
        for (ssize_t i = 0; i < m->num_layers; i++) {
-               struct protolayer_data *d = protolayer_manager_get(m, i);
-               if (d->protocol == protocol)
+               enum protolayer_protocol found = protolayer_grps[m->grp][i];
+               if (protocol == found)
                        return i;
        }
 
@@ -149,20 +175,16 @@ static inline void protolayer_cb_ctx_next(struct protolayer_cb_ctx *ctx)
                ctx->layer_ix--;
 }
 
-static int protolayer_cb_ctx_finish(struct protolayer_cb_ctx *ctx, int ret,
-                                    bool deinit_iter_data)
+static int protolayer_cb_ctx_finish(struct protolayer_cb_ctx *ctx, int ret)
 {
        struct session2 *session = ctx->manager->session;
 
-       if (deinit_iter_data) {
-               struct protolayer_manager *m = ctx->manager;
-               struct protolayer_globals *globals = &protolayer_globals[m->grp];
-               for (size_t i = 0; i < m->num_layers; i++) {
-                       struct protolayer_data *d = protolayer_manager_get(m, i);
-                       if (globals->iter_deinit)
-                               globals->iter_deinit(m, d);
-               }
-               m->iter_data_inited = false;
+       struct protolayer_manager *m = ctx->manager;
+       struct protolayer_globals *globals = &protolayer_globals[m->grp];
+       for (size_t i = 0; i < m->num_layers; i++) {
+               struct protolayer_data *d = protolayer_iter_data_get(ctx, i);
+               if (globals->iter_deinit)
+                       globals->iter_deinit(m, d);
        }
 
        if (ret)
@@ -186,7 +208,7 @@ static void protolayer_push_finished(int status, struct session2 *s, const void
 {
        struct protolayer_cb_ctx *ctx = baton;
        ctx->status = status;
-       protolayer_cb_ctx_finish(ctx, PROTOLAYER_RET_NORMAL, true);
+       protolayer_cb_ctx_finish(ctx, PROTOLAYER_RET_NORMAL);
 }
 
 /** Pushes the specified protocol layer's payload to the session's transport. */
@@ -219,7 +241,7 @@ static int protolayer_push(struct protolayer_cb_ctx *ctx)
 
        if (status < 0) {
                ctx->status = status;
-               return protolayer_cb_ctx_finish(ctx, status, true);
+               return protolayer_cb_ctx_finish(ctx, status);
        }
 
        return PROTOLAYER_RET_ASYNC;
@@ -233,40 +255,30 @@ static int protolayer_push(struct protolayer_cb_ctx *ctx)
 static int protolayer_step(struct protolayer_cb_ctx *ctx)
 {
        while (true) {
-               struct protolayer_data *ldata = protolayer_manager_get(
-                               ctx->manager, ctx->layer_ix);
-               if (kr_fails_assert(ldata)) {
-                       /* Probably layer index or data corruption */
-                       return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL), true);
-               }
-
-               enum protolayer_protocol protocol = ldata->protocol;
+               enum protolayer_protocol protocol = protolayer_grps[ctx->manager->grp][ctx->layer_ix];
                struct protolayer_globals *globals = &protolayer_globals[protocol];
 
-               enum protolayer_cb_result result = PROTOLAYER_CB_RESULT_MAGIC;
-               if (!ldata->processed) { /* Avoid repetition */
-                       ctx->async_mode = false;
-                       ctx->status = 0;
-                       ctx->action = PROTOLAYER_CB_ACTION_NULL;
-
-                       protolayer_cb cb = (ctx->direction == PROTOLAYER_UNWRAP)
-                               ? globals->unwrap : globals->wrap;
-
-                       if (cb)
-                               result = cb(ldata, ctx);
-                       else
-                               ctx->action = PROTOLAYER_CB_ACTION_CONTINUE;
-
-                       ldata->processed = true;
+               ctx->async_mode = false;
+               ctx->status = 0;
+               ctx->action = PROTOLAYER_CB_ACTION_NULL;
+
+               protolayer_cb cb = (ctx->direction == PROTOLAYER_UNWRAP)
+                       ? globals->unwrap : globals->wrap;
+
+               if (cb) {
+                       struct protolayer_data *sess_data = protolayer_sess_data_get(
+                                       ctx->manager, ctx->layer_ix);
+                       struct protolayer_data *iter_data = protolayer_iter_data_get(
+                                       ctx, ctx->layer_ix);
+                       enum protolayer_cb_result result = cb(sess_data, iter_data, ctx);
+                       if (kr_fails_assert(result == PROTOLAYER_CB_RESULT_MAGIC)) {
+                               /* Callback did not use a continuation function to return. */
+                               return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL));
+                       }
                } else {
-                       kr_assert(false && "Repeated protocol layer step");
-                       //kr_log_debug(PROTOLAYER, "Repeated protocol layer step\n");
+                       ctx->action = PROTOLAYER_CB_ACTION_CONTINUE;
                }
 
-               if (kr_fails_assert(result == PROTOLAYER_CB_RESULT_MAGIC)) {
-                       /* Callback did not use a continuation function to return. */
-                       return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL), true);
-               }
 
                if (!ctx->action) {
                        /* Next step is from a callback */
@@ -276,13 +288,12 @@ static int protolayer_step(struct protolayer_cb_ctx *ctx)
 
                if (ctx->action == PROTOLAYER_CB_ACTION_BREAK) {
                        return protolayer_cb_ctx_finish(
-                                       ctx, PROTOLAYER_RET_NORMAL, true);
+                                       ctx, PROTOLAYER_RET_NORMAL);
                }
 
                if (kr_fails_assert(ctx->status == 0)) {
                        /* Status should be zero without a BREAK. */
-                       return protolayer_cb_ctx_finish(
-                                       ctx, kr_error(ECANCELED), true);
+                       return protolayer_cb_ctx_finish(ctx, kr_error(ECANCELED));
                }
 
                if (ctx->action == PROTOLAYER_CB_ACTION_CONTINUE) {
@@ -291,7 +302,7 @@ static int protolayer_step(struct protolayer_cb_ctx *ctx)
                                        return protolayer_push(ctx);
 
                                return protolayer_cb_ctx_finish(
-                                               ctx, PROTOLAYER_RET_NORMAL, true);
+                                               ctx, PROTOLAYER_RET_NORMAL);
                        }
 
                        protolayer_cb_ctx_next(ctx);
@@ -300,7 +311,7 @@ static int protolayer_step(struct protolayer_cb_ctx *ctx)
 
                /* Should never get here */
                kr_assert(false && "Invalid layer callback action");
-               return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL), true);
+               return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL));
        }
 }
 
@@ -317,7 +328,7 @@ static int protolayer_manager_submit(
                struct protolayer_payload payload, const void *target,
                protolayer_finished_cb cb, void *baton)
 {
-       struct protolayer_cb_ctx *ctx = malloc(sizeof(*ctx)); // TODO - mempool?
+       struct protolayer_cb_ctx *ctx = malloc(manager->cb_ctx_size);
        kr_require(ctx);
 
        if (kr_log_is_debug(PROTOLAYER, NULL)) {
@@ -330,14 +341,6 @@ static int protolayer_manager_submit(
                                layer_ix);
        }
 
-       for (size_t i = 0; i < manager->num_layers; i++) {
-               struct protolayer_data *data = protolayer_manager_get(manager, i);
-               data->processed = false;
-               struct protolayer_globals *globals = &protolayer_globals[data->protocol];
-               if (globals->iter_init)
-                       globals->iter_init(manager, data);
-       }
-
        *ctx = (struct protolayer_cb_ctx) {
                .payload = payload,
                .target = target,
@@ -349,6 +352,20 @@ static int protolayer_manager_submit(
                .finished_cb_baton = baton
        };
 
+       for (size_t i = 0; i < manager->num_layers; i++) {
+               enum protolayer_protocol p = protolayer_grps[manager->grp][i];
+               struct protolayer_globals *globals = &protolayer_globals[p];
+               struct protolayer_data *iter_data = protolayer_iter_data_get(ctx, i);
+               if (iter_data) {
+                       bzero(iter_data, globals->iter_size);
+                       iter_data->protocol = p;
+                       iter_data->session = manager->session;
+               }
+
+               if (globals->iter_init)
+                       globals->iter_init(manager, iter_data);
+       }
+
        return protolayer_step(ctx);
 }
 
@@ -372,11 +389,13 @@ static struct protolayer_manager *protolayer_manager_new(
                struct protolayer_data_param *layer_param,
                size_t layer_param_count)
 {
-       if (kr_fails_assert(grp))
+       if (kr_fails_assert(s && grp))
                return NULL;
 
        size_t num_layers = 0;
-       size_t size = sizeof(struct protolayer_manager);
+       size_t manager_size = sizeof(struct protolayer_manager);
+       size_t cb_ctx_size = sizeof(struct protolayer_cb_ctx);
+
        enum protolayer_protocol *protocols = protolayer_grps[grp];
        if (kr_fails_assert(protocols))
                return NULL;
@@ -387,40 +406,52 @@ static struct protolayer_manager *protolayer_manager_new(
                num_layers++;
        if (kr_fails_assert(num_layers))
                return NULL;
-       size_t offsets[num_layers];
-       size += sizeof(offsets);
+
+       ssize_t offsets[2 * num_layers];
+       manager_size += sizeof(offsets);
+
+       ssize_t *sess_offsets = offsets;
+       ssize_t *iter_offsets = &offsets[num_layers];
 
        /* Space for layer-specific data, guaranteeing alignment */
-       size_t total_data_size = 0;
+       size_t total_sess_data_size = 0;
+       size_t total_iter_data_size = 0;
        for (size_t i = 0; i < num_layers; i++) {
-               offsets[i] = total_data_size;
-               total_data_size += ALIGN_TO(sizeof(struct protolayer_data),
-                               CPU_STRUCT_ALIGN);
-               total_data_size += ALIGN_TO(protolayer_globals[protocols[i]].sess_size,
+               sess_offsets[i] = protolayer_globals[protocols[i]].sess_size
+                       ? total_sess_data_size : -1;
+               total_sess_data_size += ALIGN_TO(protolayer_globals[protocols[i]].sess_size,
                                CPU_STRUCT_ALIGN);
-               total_data_size += ALIGN_TO(protolayer_globals[protocols[i]].iter_size,
+
+               iter_offsets[i] = protolayer_globals[protocols[i]].iter_size
+                       ? total_iter_data_size : -1;
+               total_iter_data_size += ALIGN_TO(protolayer_globals[protocols[i]].iter_size,
                                CPU_STRUCT_ALIGN);
        }
-       size += total_data_size;
+       manager_size += total_sess_data_size;
+       cb_ctx_size += total_iter_data_size;
 
        /* Allocate and initialize manager */
-       struct protolayer_manager *m = calloc(1, size);
+       struct protolayer_manager *m = calloc(1, manager_size);
        kr_require(m);
        m->grp = grp;
        m->session = s;
        m->num_layers = num_layers;
+       m->cb_ctx_size = cb_ctx_size;
        memcpy(m->data, offsets, sizeof(offsets));
 
-       /* Initialize layer data */
+       /* Initialize the layer's session data */
        for (size_t i = 0; i < num_layers; i++) {
                struct protolayer_globals *globals = &protolayer_globals[protocols[i]];
-               struct protolayer_data *data = protolayer_manager_get(m, i);
-               data->manager = m;
-               data->protocol = protocols[i];
-               data->sess_size = ALIGN_TO(globals->sess_size, CPU_STRUCT_ALIGN);
+               struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
+               if (sess_data) {
+                       bzero(sess_data, globals->sess_size);
+                       sess_data->session = s;
+                       sess_data->protocol = protocols[i];
+               }
+
                void *param = get_init_param(protocols[i], layer_param, layer_param_count);
                if (globals->sess_init)
-                       globals->sess_init(m, data, param);
+                       globals->sess_init(m, sess_data, param);
        }
 
        return m;
@@ -432,10 +463,12 @@ static void protolayer_manager_free(struct protolayer_manager *m)
        if (!m) return;
 
        for (size_t i = 0; i < m->num_layers; i++) {
-               struct protolayer_data *data = protolayer_manager_get(m, i);
-               struct protolayer_globals *globals = &protolayer_globals[data->protocol];
-               if (globals->sess_deinit)
-                       globals->sess_deinit(m, data);
+               enum protolayer_protocol p = protolayer_grps[m->grp][i];
+               struct protolayer_globals *globals = &protolayer_globals[p];
+               if (globals->sess_deinit) {
+                       struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
+                       globals->sess_deinit(m, sess_data);
+               }
        }
 
        free(m);
@@ -456,7 +489,7 @@ enum protolayer_cb_result protolayer_break(struct protolayer_cb_ctx *ctx, int st
 {
        ctx->status = status;
        if (ctx->async_mode) {
-               protolayer_cb_ctx_finish(ctx, PROTOLAYER_RET_NORMAL, true);
+               protolayer_cb_ctx_finish(ctx, PROTOLAYER_RET_NORMAL);
        } else {
                ctx->action = PROTOLAYER_CB_ACTION_BREAK;
        }
@@ -917,12 +950,14 @@ 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--) {
-               struct protolayer_data *data = protolayer_manager_get(m, i);
-               struct protolayer_globals *globals = &protolayer_globals[data->protocol];
-               if (globals->event_wrap)
-                       cont = globals->event_wrap(event, &baton, m, data);
-               else
+               enum protolayer_protocol p = protolayer_grps[s->layers->grp][i];
+               struct protolayer_globals *globals = &protolayer_globals[p];
+               if (globals->event_wrap) {
+                       struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
+                       cont = globals->event_wrap(event, &baton, m, sess_data);
+               } else {
                        cont = true;
+               }
 
                if (!cont)
                        return;
@@ -936,12 +971,14 @@ 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++) {
-               struct protolayer_data *data = protolayer_manager_get(m, i);
-               struct protolayer_globals *globals = &protolayer_globals[data->protocol];
-               if (globals->event_unwrap)
-                       cont = globals->event_unwrap(event, &baton, m, data);
-               else
+               enum protolayer_protocol p = protolayer_grps[s->layers->grp][i];
+               struct protolayer_globals *globals = &protolayer_globals[p];
+               if (globals->event_unwrap) {
+                       struct protolayer_data *sess_data = protolayer_sess_data_get(m, i);
+                       cont = globals->event_unwrap(event, &baton, m, sess_data);
+               } else {
                        cont = true;
+               }
 
                if (!cont)
                        return;
index a7b496f02dc7b29347fe4e5bfed3a568cf39df8c..50f18cb93012af420b7574cd2c5eb08062a84f2e 100644 (file)
@@ -240,6 +240,10 @@ struct protolayer_cb_ctx {
        struct protolayer_manager *manager;
        int status;
        enum protolayer_cb_action action;
+
+       /** This contains variably-sized layer-specific data. See `struct
+        * protolayer_manager::data`. */
+       alignas(CPU_STRUCT_ALIGN) char data[];
 };
 
 /** Convenience function to get a buffer-type payload. */
@@ -285,33 +289,17 @@ static inline struct protolayer_payload protolayer_wire_buf(struct wire_buf *wir
  * to be reused. */
 struct protolayer_payload protolayer_as_buffer(const struct protolayer_payload *payload);
 
+/** Mandatory header members for any layer-specific data. */
+#define PROTOLAYER_DATA_HEADER() struct {\
+       enum protolayer_protocol protocol;\
+       struct session2 *session; /**< Pointer to the owner session. */\
+}
 
-/** Per-session layer-specific data - generic struct. */
+/** Layer-specific data - generic struct. */
 struct protolayer_data {
-       enum protolayer_protocol protocol;
-       size_t sess_size; /**< Size of the session data (aligned). */
-       size_t iter_size; /**< Size of the iteration data (aligned). */
-       struct protolayer_manager *manager; /**< Pointer to the owner manager. */
-       bool processed : 1; /**< Internal safeguard so that the layer does not
-                            * get executed multiple times on the same buffer. */
-       alignas(CPU_STRUCT_ALIGN) uint8_t data[]; /**< Memory for the layer-specific structs. */
+       PROTOLAYER_DATA_HEADER();
 };
 
-/** Get a pointer to the session data of the layer. This data shares
- * its lifetime with a session. */
-static inline void *protolayer_sess_data(struct protolayer_data *d)
-{
-       return d->data;
-}
-
-/** Gets a pointer to the iteration data of the layer. This data shares its
- * lifetime with an iteration through layers; it is also kept intact when
- * an iteration ends with a `_WAIT` action. */
-static inline void *protolayer_iter_data(struct protolayer_data *d)
-{
-       return d->data + d->sess_size;
-}
-
 /** Return value of `protolayer_cb` callbacks. To be generated by continuation
  * functions, never returned directly. */
 enum protolayer_cb_result {
@@ -324,7 +312,9 @@ enum protolayer_cb_result {
  * call one of the *layer sequence return functions*. The pointed-to function
  * must return the result of such a return function. */
 typedef enum protolayer_cb_result (*protolayer_cb)(
-               struct protolayer_data *layer, struct protolayer_cb_ctx *ctx);
+               void *sess_data,
+               void *iter_data,
+               struct protolayer_cb_ctx *ctx);
 
 /** Function type for `event_wrap` and `event_unwrap` callbacks of layers.
  * `baton` always points to some memory; it may be modified accommodate for
@@ -335,7 +325,7 @@ typedef enum protolayer_cb_result (*protolayer_cb)(
 typedef bool (*protolayer_event_cb)(enum protolayer_event_type event,
                                     void **baton,
                                     struct protolayer_manager *manager,
-                                    struct protolayer_data *layer);
+                                    void *sess_data);
 
 /** Function type for initialization callbacks of layer session data, with
  * `param`, if any is passed to the layer.
@@ -343,7 +333,7 @@ typedef bool (*protolayer_event_cb)(enum protolayer_event_type event,
  * Returning 0 means success, other return values mean error and halt the
  * initialization. */
 typedef int (*protolayer_data_sess_init_cb)(struct protolayer_manager *manager,
-                                            struct protolayer_data *layer,
+                                            void *data,
                                             void *param);
 
 /** Function type for (de)initialization callbacks of layers.
@@ -351,18 +341,33 @@ typedef int (*protolayer_data_sess_init_cb)(struct protolayer_manager *manager,
  * Returning 0 means success, other return values mean error and halt the
  * initialization. */
 typedef int (*protolayer_data_cb)(struct protolayer_manager *manager,
-                                  struct protolayer_data *layer);
+                                  void *data);
 
 /** A collection of protocol layers and their layer-specific data. */
 struct protolayer_manager {
        enum protolayer_grp grp;
-       /* TODO: move iter data to `struct protolayer_cb_ctx` */
-       bool iter_data_inited : 1; /**< True: layers' iteration data is
-                                   * initialized (e.g. from a previous
-                                   * iteration). */
        struct session2 *session;
        size_t num_layers;
-       char data[];
+       size_t cb_ctx_size;
+
+       /** The following flexible array has basically this structure:
+        *
+        * struct {
+        *      size_t sess_offsets[num_layers];
+        *      size_t iter_offsets[num_layers];
+        *      variably-sized-data sess_data[num_layers];
+        * }
+        *
+        * It is done this way, because different layer groups will have
+        * different numbers of layers and differently-sized layer-specific
+        * data. C does not have a convenient way to define this in structs, so
+        * we do it via this flexible array.
+        *
+        * `sess_offsets` determines data offsets in `sess_data`.
+        *
+        * `iter_offsets` determines data offsets in
+        * `struct protolayer_cb_ctx::data`. */
+       alignas(CPU_STRUCT_ALIGN) char data[];
 };
 
 /** Initialization parameters for protocol layer session data. */
index 0ec2d4e739a1faaaba7d38c2f55d77130ae3892b..e6def676d84fe8a41c49afa842b5cadb16c56be8 100644 (file)
@@ -54,6 +54,7 @@ typedef int (*tls_handshake_cb) (struct session2 *session, int status);
 typedef queue_t(struct protolayer_cb_ctx *) pl_cb_ctx_queue_t;
 
 struct pl_tls_sess_data {
+       PROTOLAYER_DATA_HEADER();
        bool client_side;
        gnutls_session_t tls_session;
        tls_hs_state_t handshake_state;
@@ -125,8 +126,7 @@ static size_t count_avail_payload(pl_cb_ctx_queue_t *queue)
 
 static ssize_t kres_gnutls_pull(gnutls_transport_ptr_t h, void *buf, size_t len)
 {
-       struct protolayer_data *layer = h;
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
+       struct pl_tls_sess_data *tls = h;
        if (kr_fails_assert(tls)) {
                errno = EFAULT;
                return -1;
@@ -223,7 +223,7 @@ static ssize_t kres_gnutls_pull(gnutls_transport_ptr_t h, void *buf, size_t len)
 }
 
 struct kres_gnutls_push_ctx {
-       struct protolayer_data *layer;
+       void *sess_data;
        struct iovec iov[];
 };
 
@@ -231,7 +231,7 @@ static void kres_gnutls_push_finished(int status, struct session2 *session,
                                       const void *target, void *baton)
 {
        struct kres_gnutls_push_ctx *push_ctx = baton;
-       struct pl_tls_sess_data *tls = protolayer_sess_data(push_ctx->layer);
+       struct pl_tls_sess_data *tls = push_ctx->sess_data;
        while (queue_len(tls->wrap_queue)) {
                struct protolayer_cb_ctx *ctx = queue_head(tls->wrap_queue);
                protolayer_break(ctx, kr_ok());
@@ -242,8 +242,7 @@ static void kres_gnutls_push_finished(int status, struct session2 *session,
 
 static ssize_t kres_gnutls_vec_push(gnutls_transport_ptr_t h, const giovec_t * iov, int iovcnt)
 {
-       struct protolayer_data *layer = h;
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
+       struct pl_tls_sess_data *tls = h;
        if (kr_fails_assert(tls)) {
                errno = EFAULT;
                return -1;
@@ -260,10 +259,10 @@ static ssize_t kres_gnutls_vec_push(gnutls_transport_ptr_t h, const giovec_t * i
        struct kres_gnutls_push_ctx *push_ctx =
                malloc(sizeof(*push_ctx) + sizeof(struct iovec[iovcnt]));
        kr_require(push_ctx);
-       push_ctx->layer = layer;
+       push_ctx->sess_data = tls;
        memcpy(push_ctx->iov, iov, sizeof(struct iovec[iovcnt]));
 
-       session2_wrap_after(layer->manager->session, PROTOLAYER_TLS,
+       session2_wrap_after(tls->session, PROTOLAYER_TLS,
                        protolayer_iovec(push_ctx->iov, iovcnt), NULL,
                        kres_gnutls_push_finished, push_ctx);
 
@@ -883,8 +882,7 @@ static int client_verify_certificate(gnutls_session_t tls_session)
 
 static int tls_pull_timeout_func(gnutls_transport_ptr_t h, unsigned int ms)
 {
-       struct protolayer_data *layer = h;
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
+       struct pl_tls_sess_data *tls = h;
        if (kr_fails_assert(tls)) {
                errno = EFAULT;
                return -1;
@@ -919,9 +917,8 @@ static int pl_tls_sess_data_deinit(struct pl_tls_sess_data *tls)
 }
 
 static int pl_tls_sess_server_init(struct protolayer_manager *manager,
-                                   struct protolayer_data *layer)
+                                   struct pl_tls_sess_data *tls)
 {
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
        if (kr_fails_assert(the_worker && the_engine))
                return kr_error(EINVAL);
 
@@ -990,7 +987,7 @@ static int pl_tls_sess_server_init(struct protolayer_manager *manager,
 
        gnutls_transport_set_pull_function(tls->tls_session, kres_gnutls_pull);
        gnutls_transport_set_vec_push_function(tls->tls_session, kres_gnutls_vec_push);
-       gnutls_transport_set_ptr(tls->tls_session, layer);
+       gnutls_transport_set_ptr(tls->tls_session, tls);
 
        if (the_network->tls_session_ticket_ctx) {
                tls_session_ticket_enable(the_network->tls_session_ticket_ctx,
@@ -1001,10 +998,9 @@ static int pl_tls_sess_server_init(struct protolayer_manager *manager,
 }
 
 static int pl_tls_sess_client_init(struct protolayer_manager *manager,
-                                   struct protolayer_data *layer,
+                                   struct pl_tls_sess_data *tls,
                                    tls_client_param_t *param)
 {
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
        unsigned int flags = GNUTLS_CLIENT | GNUTLS_NONBLOCK
 #ifdef GNUTLS_ENABLE_FALSE_START
                             | GNUTLS_ENABLE_FALSE_START
@@ -1051,37 +1047,35 @@ static int pl_tls_sess_client_init(struct protolayer_manager *manager,
 
        gnutls_transport_set_pull_function(tls->tls_session, kres_gnutls_pull);
        gnutls_transport_set_vec_push_function(tls->tls_session, kres_gnutls_vec_push);
-       gnutls_transport_set_ptr(tls->tls_session, layer);
+       gnutls_transport_set_ptr(tls->tls_session, tls);
 
        return kr_ok();
 }
 
 static int pl_tls_sess_init(struct protolayer_manager *manager,
-                            struct protolayer_data *layer,
+                            void *sess_data,
                             void *param)
 {
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
-       *tls = (struct pl_tls_sess_data){0};
+       struct pl_tls_sess_data *tls = sess_data;
        manager->session->secure = true;
        queue_init(tls->unwrap_queue);
        queue_init(tls->wrap_queue);
        if (manager->session->outgoing)
-               return pl_tls_sess_client_init(manager, layer, param);
+               return pl_tls_sess_client_init(manager, tls, param);
        else
-               return pl_tls_sess_server_init(manager, layer);
+               return pl_tls_sess_server_init(manager, tls);
 }
 
 static int pl_tls_sess_deinit(struct protolayer_manager *manager,
-                              struct protolayer_data *layer)
+                              void *sess_data)
 {
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
-       return pl_tls_sess_data_deinit(tls);
+       return pl_tls_sess_data_deinit(sess_data);
 }
 
-static enum protolayer_cb_result pl_tls_unwrap(struct protolayer_data *layer,
+static enum protolayer_cb_result pl_tls_unwrap(void *sess_data, void *iter_data,
                                                struct protolayer_cb_ctx *ctx)
 {
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
+       struct pl_tls_sess_data *tls = sess_data;
        struct session2 *s = ctx->manager->session;
 
        queue_push(tls->unwrap_queue, ctx);
@@ -1172,8 +1166,7 @@ static enum protolayer_cb_result pl_tls_unwrap(struct protolayer_data *layer,
        return protolayer_continue(ctx);
 }
 
-static ssize_t pl_tls_submit(struct protolayer_data *layer,
-                             gnutls_session_t tls_session,
+static ssize_t pl_tls_submit(gnutls_session_t tls_session,
                              struct protolayer_payload payload)
 {
        if (payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF)
@@ -1204,15 +1197,15 @@ static ssize_t pl_tls_submit(struct protolayer_data *layer,
        return kr_error(EINVAL);
 }
 
-static enum protolayer_cb_result pl_tls_wrap(struct protolayer_data *layer,
+static enum protolayer_cb_result pl_tls_wrap(void *sess_data, void *iter_data,
                                              struct protolayer_cb_ctx *ctx)
 {
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
+       struct pl_tls_sess_data *tls = sess_data;
        gnutls_session_t tls_session = tls->tls_session;
 
        gnutls_record_cork(tls_session);
 
-       ssize_t submitted = pl_tls_submit(layer, tls_session, ctx->payload);
+       ssize_t submitted = pl_tls_submit(tls_session, ctx->payload);
        if (submitted < 0) {
                VERBOSE_MSG(tls->client_side, "pl_tls_submit failed: %s (%zd)\n",
                                gnutls_strerror_name(submitted), submitted);
@@ -1275,10 +1268,10 @@ static bool pl_tls_client_connect_start(struct pl_tls_sess_data *tls,
 static bool pl_tls_event_unwrap(enum protolayer_event_type event,
                                 void **baton,
                                 struct protolayer_manager *manager,
-                                struct protolayer_data *layer)
+                                void *sess_data)
 {
        struct session2 *s = manager->session;
-       struct pl_tls_sess_data *tls = protolayer_sess_data(layer);
+       struct pl_tls_sess_data *tls = sess_data;
 
        if (event == PROTOLAYER_EVENT_CLOSE) {
                tls_close(tls, s, true); /* WITH gnutls_bye */
@@ -1306,7 +1299,7 @@ static bool pl_tls_event_unwrap(enum protolayer_event_type event,
 static bool pl_tls_event_wrap(enum protolayer_event_type event,
                               void **baton,
                               struct protolayer_manager *manager,
-                              struct protolayer_data *layer)
+                              void *sess_data)
 {
        if (event == PROTOLAYER_EVENT_STATS_SEND_ERR) {
                the_worker->stats.err_tls += 1;
index b348f22014c57ebe007c9a5a1d24ead816b4b563..b1ba883e38129249caa3cb9f2f8d6b776e6b7719 100644 (file)
@@ -1881,7 +1881,7 @@ static inline knot_pkt_t *produce_packet(char *buf, size_t buf_len)
 static bool pl_dns_dgram_event_unwrap(enum protolayer_event_type event,
                                       void **baton,
                                       struct protolayer_manager *manager,
-                                      struct protolayer_data *layer)
+                                      void *sess_data)
 {
        if (event != PROTOLAYER_EVENT_TIMEOUT)
                return true;
@@ -1910,7 +1910,7 @@ static bool pl_dns_dgram_event_unwrap(enum protolayer_event_type event,
 }
 
 static enum protolayer_cb_result pl_dns_dgram_unwrap(
-               struct protolayer_data *layer, struct protolayer_cb_ctx *ctx)
+               void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
 {
        struct session2 *session = ctx->manager->session;
 
@@ -1960,11 +1960,13 @@ static enum protolayer_cb_result pl_dns_dgram_unwrap(
 }
 
 struct pl_dns_stream_sess_data {
+       PROTOLAYER_DATA_HEADER();
        bool single : 1; /**< True: Stream only allows a single packet */
        bool produced : 1; /**< True: At least one packet has been produced */
 };
 
 struct pl_dns_stream_iter_data {
+       PROTOLAYER_DATA_HEADER();
        struct {
                knot_mm_t *pool;
                void *mem;
@@ -1982,35 +1984,35 @@ static void pl_dns_stream_sess_init_common(struct session2 *session,
 }
 
 static int pl_dns_mstream_sess_init(struct protolayer_manager *manager,
-                                    struct protolayer_data *layer,
+                                    void *sess_data,
                                     void *param)
 {
-       struct pl_dns_stream_sess_data *stream = protolayer_sess_data(layer);
+       struct pl_dns_stream_sess_data *stream = sess_data;
        pl_dns_stream_sess_init_common(manager->session, stream, false);
        return kr_ok();
 }
 
 static int pl_dns_sstream_sess_init(struct protolayer_manager *manager,
-                                    struct protolayer_data *layer,
+                                    void *sess_data,
                                     void *param)
 {
-       struct pl_dns_stream_sess_data *stream = protolayer_sess_data(layer);
+       struct pl_dns_stream_sess_data *stream = sess_data;
        pl_dns_stream_sess_init_common(manager->session, stream, true);
        return kr_ok();
 }
 
 static int pl_dns_stream_iter_init(struct protolayer_manager *manager,
-                                   struct protolayer_data *layer)
+                                   void *iter_data)
 {
-       struct pl_dns_stream_iter_data *stream = protolayer_iter_data(layer);
+       struct pl_dns_stream_iter_data *stream = iter_data;
        *stream = (struct pl_dns_stream_iter_data){0};
        return kr_ok();
 }
 
 static int pl_dns_stream_iter_deinit(struct protolayer_manager *manager,
-                                     struct protolayer_data *layer)
+                                     void *iter_data)
 {
-       struct pl_dns_stream_iter_data *stream = protolayer_iter_data(layer);
+       struct pl_dns_stream_iter_data *stream = iter_data;
        mm_free(stream->sent.pool, stream->sent.mem);
        return kr_ok();
 }
@@ -2190,7 +2192,7 @@ static bool pl_dns_stream_disconnected(struct session2 *session)
 static bool pl_dns_stream_event_unwrap(enum protolayer_event_type event,
                                        void **baton,
                                        struct protolayer_manager *manager,
-                                       struct protolayer_data *layer)
+                                       void *sess_data)
 {
        struct session2 *session = manager->session;
        if (session->closing)
@@ -2231,7 +2233,7 @@ static knot_pkt_t *produce_stream_packet(struct wire_buf *wb)
 }
 
 static enum protolayer_cb_result pl_dns_stream_unwrap(
-               struct protolayer_data *layer, struct protolayer_cb_ctx *ctx)
+               void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
 {
        if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF)) {
                /* DNS stream only works with a wire buffer */
@@ -2239,12 +2241,12 @@ static enum protolayer_cb_result pl_dns_stream_unwrap(
        }
 
        struct session2 *session = ctx->manager->session;
-       struct pl_dns_stream_sess_data *stream = protolayer_sess_data(layer);
+       struct pl_dns_stream_sess_data *stream_sess = sess_data;
        struct wire_buf *wb = ctx->payload.wire_buf;
 
        knot_pkt_t *pkt;
        while ((pkt = produce_stream_packet(wb))) {
-               if (stream->single && stream->produced) {
+               if (stream_sess->single && stream_sess->produced) {
                        if (kr_log_is_debug(WORKER, NULL)) {
                                kr_log_debug(WORKER, "Unexpected extra data from %s\n",
                                                kr_straddr(ctx->comm.src_addr));
@@ -2254,7 +2256,7 @@ static enum protolayer_cb_result pl_dns_stream_unwrap(
                        return protolayer_break(ctx, KNOT_EMALF);
                }
 
-               stream->produced = true;
+               stream_sess->produced = true;
                if (!pkt)
                        return protolayer_break(ctx, KNOT_EMALF);
 
@@ -2276,9 +2278,9 @@ struct sized_iovs {
 };
 
 static enum protolayer_cb_result pl_dns_stream_wrap(
-               struct protolayer_data *layer, struct protolayer_cb_ctx *ctx)
+               void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
 {
-       struct pl_dns_stream_iter_data *stream = protolayer_iter_data(layer);
+       struct pl_dns_stream_iter_data *stream = iter_data;
        struct session2 *s = ctx->manager->session;
 
        if (kr_fails_assert(!stream->sent.mem))