bool has_proxy;
};
-static int pl_udp_iter_init(struct protolayer_manager *manager, void *iter_data)
-{
- 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(
- void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
+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);
if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_BUFFER)) {
bool has_proxy : 1;
};
-static int pl_tcp_sess_init(struct protolayer_manager *manager, void *sess_data, void *param)
-{
- 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, void *sess_data)
{
struct pl_tcp_sess_data *tcp = sess_data;
return 0;
}
-static enum protolayer_cb_result pl_tcp_unwrap(
- void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
+static enum protolayer_iter_cb_result pl_tcp_unwrap(
+ void *sess_data, void *iter_data, struct protolayer_iter_ctx *ctx)
{
struct session2 *s = ctx->manager->session;
struct pl_tcp_sess_data *tcp = sess_data;
{
protolayer_globals[PROTOLAYER_UDP] = (struct protolayer_globals){
.iter_size = sizeof(struct pl_udp_iter_data),
- .iter_init = pl_udp_iter_init,
.unwrap = pl_udp_unwrap,
.event_wrap = pl_udp_event_wrap,
};
protolayer_globals[PROTOLAYER_TCP] = (struct protolayer_globals){
.sess_size = sizeof(struct pl_tcp_sess_data),
- .sess_init = pl_tcp_sess_init,
.sess_deinit = pl_tcp_sess_deinit,
.unwrap = pl_tcp_unwrap,
.event_wrap = pl_tcp_event_wrap,
struct protolayer_globals protolayer_globals[PROTOLAYER_PROTOCOL_COUNT] = {0};
-enum protolayer_protocol protolayer_grp_doudp[] = {
+static enum protolayer_protocol protolayer_grp_doudp[] = {
PROTOLAYER_UDP,
PROTOLAYER_DNS_DGRAM,
PROTOLAYER_NULL
};
-enum protolayer_protocol protolayer_grp_dotcp[] = {
+static enum protolayer_protocol protolayer_grp_dotcp[] = {
PROTOLAYER_TCP,
PROTOLAYER_DNS_MSTREAM,
PROTOLAYER_NULL
};
-enum protolayer_protocol protolayer_grp_dot[] = {
+static enum protolayer_protocol protolayer_grp_dot[] = {
PROTOLAYER_TCP,
PROTOLAYER_TLS,
PROTOLAYER_DNS_MSTREAM,
PROTOLAYER_NULL
};
-enum protolayer_protocol protolayer_grp_doh[] = {
+static enum protolayer_protocol protolayer_grp_doh[] = {
PROTOLAYER_TCP,
PROTOLAYER_TLS,
PROTOLAYER_HTTP,
};
-enum protolayer_protocol *protolayer_grps[PROTOLAYER_GRP_COUNT] = {
+/** Sequences of layers, mapped by `enum protolayer_grp`.
+ *
+ * To define a new group, add a new entry in the `PROTOLAYER_GRP_MAP` macro and
+ * create a new static `protolayer_grp_*` array above, similarly to the already
+ * existing ones. Each array must end with `PROTOLAYER_GRP_NULL`, to 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 `PROTOLAYER_GRP_MAP`
+ * macro. */
+static enum protolayer_protocol *protolayer_grps[PROTOLAYER_GRP_COUNT] = {
#define XX(cid, vid, name) [PROTOLAYER_GRP_##cid] = protolayer_grp_##vid,
PROTOLAYER_GRP_MAP(XX)
#undef XX
};
+/** Human-readable names for protocol layer groups. */
char *protolayer_grp_names[PROTOLAYER_GRP_COUNT] = {
[PROTOLAYER_GRP_NULL] = "(null)",
#define XX(cid, vid, name) [PROTOLAYER_GRP_##cid] = name,
#undef XX
};
+/** Human-readable names for events. */
char *protolayer_event_names[PROTOLAYER_EVENT_COUNT] = {
[PROTOLAYER_EVENT_NULL] = "(null)",
#define XX(cid) [PROTOLAYER_EVENT_##cid] = #cid,
#undef XX
};
+/** Human-readable names for payloads. */
char *protolayer_payload_names[PROTOLAYER_PAYLOAD_COUNT] = {
[PROTOLAYER_PAYLOAD_NULL] = "(null)",
#define XX(cid, name) [PROTOLAYER_PAYLOAD_##cid] = name,
/** 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_iter_ctx *ctx, size_t layer_ix)
{
struct protolayer_manager *m = ctx->manager;
if (kr_fails_assert(layer_ix < m->num_layers))
return -1;
}
-static inline bool protolayer_cb_ctx_is_last(struct protolayer_cb_ctx *ctx)
+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
return ctx->layer_ix == last_ix;
}
-static inline void protolayer_cb_ctx_next(struct protolayer_cb_ctx *ctx)
+static inline void protolayer_iter_ctx_next(struct protolayer_iter_ctx *ctx)
{
if (ctx->direction == PROTOLAYER_UNWRAP)
ctx->layer_ix++;
ctx->layer_ix--;
}
-static int protolayer_cb_ctx_finish(struct protolayer_cb_ctx *ctx, int ret)
+static int protolayer_iter_ctx_finish(struct protolayer_iter_ctx *ctx, int ret)
{
struct session2 *session = ctx->manager->session;
static void protolayer_push_finished(int status, struct session2 *s, const void *target, void *baton)
{
- struct protolayer_cb_ctx *ctx = baton;
+ struct protolayer_iter_ctx *ctx = baton;
ctx->status = status;
- protolayer_cb_ctx_finish(ctx, PROTOLAYER_RET_NORMAL);
+ protolayer_iter_ctx_finish(ctx, PROTOLAYER_RET_NORMAL);
}
/** Pushes the specified protocol layer's payload to the session's transport. */
-static int protolayer_push(struct protolayer_cb_ctx *ctx)
+static int protolayer_push(struct protolayer_iter_ctx *ctx)
{
struct session2 *session = ctx->manager->session;
if (status < 0) {
ctx->status = status;
- return protolayer_cb_ctx_finish(ctx, status);
+ return protolayer_iter_ctx_finish(ctx, status);
}
return PROTOLAYER_RET_ASYNC;
*
* May be called multiple times on the same `ctx` to continue processing
* after an asynchronous operation. */
-static int protolayer_step(struct protolayer_cb_ctx *ctx)
+static int protolayer_step(struct protolayer_iter_ctx *ctx)
{
while (true) {
enum protolayer_protocol protocol = protolayer_grps[ctx->manager->grp][ctx->layer_ix];
ctx->async_mode = false;
ctx->status = 0;
- ctx->action = PROTOLAYER_CB_ACTION_NULL;
+ ctx->action = PROTOLAYER_ITER_ACTION_NULL;
- protolayer_cb cb = (ctx->direction == PROTOLAYER_UNWRAP)
+ protolayer_iter_cb cb = (ctx->direction == PROTOLAYER_UNWRAP)
? globals->unwrap : globals->wrap;
if (cb) {
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)) {
+ enum protolayer_iter_cb_result result = cb(sess_data, iter_data, ctx);
+ if (kr_fails_assert(result == PROTOLAYER_ITER_CB_RESULT_MAGIC)) {
/* Callback did not use a continuation function to return. */
- return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL));
+ return protolayer_iter_ctx_finish(ctx, kr_error(EINVAL));
}
} else {
- ctx->action = PROTOLAYER_CB_ACTION_CONTINUE;
+ ctx->action = PROTOLAYER_ITER_ACTION_CONTINUE;
}
return PROTOLAYER_RET_ASYNC;
}
- if (ctx->action == PROTOLAYER_CB_ACTION_BREAK) {
- return protolayer_cb_ctx_finish(
+ if (ctx->action == PROTOLAYER_ITER_ACTION_BREAK) {
+ return protolayer_iter_ctx_finish(
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));
+ return protolayer_iter_ctx_finish(ctx, kr_error(ECANCELED));
}
- if (ctx->action == PROTOLAYER_CB_ACTION_CONTINUE) {
- if (protolayer_cb_ctx_is_last(ctx)) {
+ if (ctx->action == PROTOLAYER_ITER_ACTION_CONTINUE) {
+ if (protolayer_iter_ctx_is_last(ctx)) {
if (ctx->direction == PROTOLAYER_WRAP)
return protolayer_push(ctx);
- return protolayer_cb_ctx_finish(
+ return protolayer_iter_ctx_finish(
ctx, PROTOLAYER_RET_NORMAL);
}
- protolayer_cb_ctx_next(ctx);
+ protolayer_iter_ctx_next(ctx);
continue;
}
/* Should never get here */
kr_assert(false && "Invalid layer callback action");
- return protolayer_cb_ctx_finish(ctx, kr_error(EINVAL));
+ return protolayer_iter_ctx_finish(ctx, kr_error(EINVAL));
}
}
struct protolayer_payload payload, const void *target,
protolayer_finished_cb cb, void *baton)
{
- struct protolayer_cb_ctx *ctx = malloc(manager->cb_ctx_size);
+ struct protolayer_iter_ctx *ctx = malloc(manager->cb_ctx_size);
kr_require(ctx);
if (kr_log_is_debug(PROTOLAYER, NULL)) {
layer_ix);
}
- *ctx = (struct protolayer_cb_ctx) {
+ *ctx = (struct protolayer_iter_ctx) {
.payload = payload,
.target = target,
.direction = direction,
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;
}
size_t num_layers = 0;
size_t manager_size = sizeof(struct protolayer_manager);
- size_t cb_ctx_size = sizeof(struct protolayer_cb_ctx);
+ size_t cb_ctx_size = sizeof(struct protolayer_iter_ctx);
enum protolayer_protocol *protocols = protolayer_grps[grp];
if (kr_fails_assert(protocols))
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);
free(m);
}
-enum protolayer_cb_result protolayer_continue(struct protolayer_cb_ctx *ctx)
+enum protolayer_iter_cb_result protolayer_continue(struct protolayer_iter_ctx *ctx)
{
if (ctx->async_mode) {
- protolayer_cb_ctx_next(ctx);
+ protolayer_iter_ctx_next(ctx);
protolayer_step(ctx);
} else {
- ctx->action = PROTOLAYER_CB_ACTION_CONTINUE;
+ ctx->action = PROTOLAYER_ITER_ACTION_CONTINUE;
}
- return PROTOLAYER_CB_RESULT_MAGIC;
+ return PROTOLAYER_ITER_CB_RESULT_MAGIC;
}
-enum protolayer_cb_result protolayer_break(struct protolayer_cb_ctx *ctx, int status)
+enum protolayer_iter_cb_result protolayer_break(struct protolayer_iter_ctx *ctx, int status)
{
ctx->status = status;
if (ctx->async_mode) {
- protolayer_cb_ctx_finish(ctx, PROTOLAYER_RET_NORMAL);
+ protolayer_iter_ctx_finish(ctx, PROTOLAYER_RET_NORMAL);
} else {
- ctx->action = PROTOLAYER_CB_ACTION_BREAK;
+ ctx->action = PROTOLAYER_ITER_ACTION_BREAK;
}
- return PROTOLAYER_CB_RESULT_MAGIC;
+ return PROTOLAYER_ITER_CB_RESULT_MAGIC;
}
/* HINT: If you are looking to implement a new protocol, start with the doc
* comment of `enum protolayer_protocol` and continue from there. */
+/* GLOSSARY:
+ *
+ * Iteration:
+ * - The processing of a piece of data (a.k.a. payload) using a particular
+ * sequence of Protocol layers, either in Wrap or Unwrap direction. It is
+ * also the lifetime of `struct protolayer_iter_ctx` and layer-specific data.
+ *
+ * Protocol layer:
+ * - An implementation of a particular protocol. A layer transforms data
+ * within the resolver to conform to a particular protocol, e.g. UDP, TCP,
+ * TLS, HTTP, QUIC, etc.
+ *
+ * Protolayer:
+ * - Same as 'Protocol layer'.
+ *
+ * Unwrap:
+ * - The direction of data transformation, starting with the transport (e.g.
+ * data that came from the network), ending with an internal subsystem (e.g.
+ * DNS query resolution).
+ *
+ * Wrap:
+ * - The direction of data transformation, starting with an internal
+ * subsystem (e.g. an answer to a resolved DNS query), ending with the
+ * transport (e.g. data that is going to be sent to the client). */
+
#pragma once
#include <stdalign.h>
/* Forward declarations */
struct session2;
-struct protolayer_cb_ctx;
+struct protolayer_iter_ctx;
/** Information about the transport - addresses and proxy. */
struct comm_info {
* some logical compilation unit (e.g. `daemon/worker.c`), create a function
* that will initialize the protocol's `protolayer_globals[]`, ideally at the
* start of the program. See the docs of `struct protolayer_globals` for more
- * details. */
+ * details.
+ *
+ * To use protocols within sessions, protocol layer groups also need to be
+ * defined, to indicate the order in which individual protocols are to be
+ * processed. See `PROTOLAYER_GRP_MAP` below for more details. */
enum protolayer_protocol {
PROTOLAYER_NULL = 0,
};
/** Protocol layer groups. Each of these represents a sequence of layers in the
- * unwrap direction (wrap direction being the opposite). This macro is used to
- * generate `enum protolayer_grp` and `protolayer_grp_descs[]`.
+ * unwrap direction (wrap direction being the opposite). The sequence dictates
+ * the order, in which individual layers are processed. This macro is used to
+ * generate global data about groups.
+ *
+ * For defining new groups, see the docs of `protolayer_grps[]` in
+ * `daemon/session2.h`.
*
* Parameters are:
* 1. Constant name (for e.g. PROTOLAYER_GRP_* constants)
/** Flow control indicators for protocol layer `wrap` and `unwrap` callbacks.
* Use via `protolayer_continue`, `protolayer_break`, and `protolayer_push`
* functions. */
-enum protolayer_cb_action {
- PROTOLAYER_CB_ACTION_NULL = 0,
+enum protolayer_iter_action {
+ PROTOLAYER_ITER_ACTION_NULL = 0,
- PROTOLAYER_CB_ACTION_CONTINUE,
- PROTOLAYER_CB_ACTION_BREAK,
+ PROTOLAYER_ITER_ACTION_CONTINUE,
+ PROTOLAYER_ITER_ACTION_BREAK,
};
/** Direction of layer sequence processing. */
};
};
-/** Context for protocol layer callbacks, containing buffer data and internal
- * information for protocol layer manager. */
-struct protolayer_cb_ctx {
- /* read-write */
+/** Context for protocol layer iterations, containing payload data,
+ * layer-specific data, and internal information for the protocol layer
+ * manager. */
+struct protolayer_iter_ctx {
+/* read-write: */
/** The payload */
struct protolayer_payload payload;
/** Transport information (e.g. UDP sender address). May be `NULL`. */
* Zero-initialized in the beginning. */
struct comm_info comm;
- /* callback for when the layer iteration has ended - read-only */
+/* callback for when the layer iteration has ended - read-only: */
protolayer_finished_cb finished_cb;
const void *finished_cb_target;
void *finished_cb_baton;
- /* internal information for the manager - private */
+/* internal information for the manager - private: */
enum protolayer_direction direction;
bool async_mode;
unsigned int layer_ix;
struct protolayer_manager *manager;
int status;
- enum protolayer_cb_action action;
+ enum protolayer_iter_action action;
- /** This contains variably-sized layer-specific data. See `struct
+ /** Contains variably-sized layer-specific data. See `struct
* protolayer_manager::data`. */
alignas(CPU_STRUCT_ALIGN) char data[];
};
* Supports only `_BUFFER` and `_WIRE_BUF` on the input, otherwise returns
* `_NULL` type or aborts on assertion if allowed.
*
- * If the input payload is `_WIRE_BUF`, the pointed-to wire buffer is reset
- * to indicate that all of its contents have been used and the buffer is ready
+ * 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);
/** 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. */\
}
-/** Layer-specific data - generic struct. */
+/** Layer-specific data - the generic struct. */
struct protolayer_data {
PROTOLAYER_DATA_HEADER();
};
-/** Return value of `protolayer_cb` callbacks. To be generated by continuation
- * functions, never returned directly. */
-enum protolayer_cb_result {
- PROTOLAYER_CB_RESULT_MAGIC = 0x364F392E,
+/** Return value of `protolayer_iter_cb` callbacks. To be returned by *layer
+ * sequence return functions* as a sanity check. Not to be used directly by
+ * user code. */
+enum protolayer_iter_cb_result {
+ PROTOLAYER_ITER_CB_RESULT_MAGIC = 0x364F392E,
};
-/** Function type for `wrap` and `unwrap` callbacks of layers. The function
- * processes the provided `ctx->payload` and decides on the next action for the
- * currently processed sequence.
+/** Function type for `struct protolayer_globals::wrap` and `struct
+ * protolayer_globals::unwrap`. The function processes the provided
+ * `ctx->payload` and decides the next action for the currently processed
+ * sequence.
*
* The pointed-to function (or another function, that the pointed-to function
- * causes to be called, e.g. through an asynchronous operation), must call one
- * of the *layer sequence return functions* to advance (or end) the layer
- * iteration. The pointed-to function must return the result of such a return
- * function. */
-typedef enum protolayer_cb_result (*protolayer_cb)(
+ * causes to be called, directly or through an asynchronous operation), must
+ * call one of the *layer sequence return functions* to advance (or end) the
+ * layer iteration. The pointed-to function must return the result of such a
+ * return function. */
+typedef enum protolayer_iter_cb_result (*protolayer_iter_cb)(
void *sess_data,
void *iter_data,
- struct protolayer_cb_ctx *ctx);
-
-/** Function type for `event_wrap` and `event_unwrap` callbacks of layers.
- * The `baton` parameter points to the mutable, iteration-specific baton
- * pointer, initialized by the `baton` parameter of one of the `session2_event`
- * functions. The pointed-to value of `baton` may be modified to accommodate
- * for the next layer in the sequence.
+ struct protolayer_iter_ctx *ctx);
+
+/** Function type for `struct protolayer_globals::event_wrap` and `struct
+ * protolayer_globals::event_unwrap` callbacks of layers. The `baton` parameter
+ * points to the mutable, iteration-specific baton pointer, initialized by the
+ * `baton` parameter of one of the `session2_event` functions. The pointed-to
+ * value of `baton` may be modified to accommodate for the next layer in the
+ * sequence.
*
* When `true` is returned, iteration over the sequence of layers continues.
* When `false` is returned, iteration stops. */
struct protolayer_manager *manager,
void *sess_data);
-/** Function type for initialization callbacks of layer session data. The
- * `param` value is the one associated with the currently initialized layer,
- * from the `layer_param` array of `session2_new()` - may be NULL if none is
- * provided for the current layer.
+/** Function type for initialization callbacks of layer session data.
+ *
+ * The `param` value is the one associated with the currently initialized
+ * layer, from the `layer_param` array of `session2_new()` - may be NULL if
+ * none is provided for the current layer.
*
* `data` points to the layer-specific data struct.
*
* `sess_offsets` determines data offsets in `sess_data`.
*
* `iter_offsets` determines data offsets in
- * `struct protolayer_cb_ctx::data`. */
+ * `struct protolayer_iter_ctx::data`. */
alignas(CPU_STRUCT_ALIGN) char data[];
};
* the `protolayer_globals` global array (below) during the start of the
* resolver. It contains pointers to the specific protocol's functions. */
struct protolayer_globals {
- /** Size of the layer-specific data struct, that is valid per-session.
+ /** Size of the layer-specific data struct, valid per-session.
*
* The struct MUST begin with the `PROTOLAYER_DATA_HEADER()` macro. If
* no session struct is used by the layer, the value may be zero. */
size_t sess_size;
- /** Size of the layer-specific data struct, that is valid
- * per-iteration. It gets created and destroyed together with a `struct
- * protolayer_cb_ctx`.
+ /** Size of the layer-specific data struct, valid per-iteration. It
+ * gets created and destroyed together with a `struct
+ * protolayer_iter_ctx`.
*
* The struct MUST begin with the `PROTOLAYER_DATA_HEADER()` macro. If
* no iteration struct is used by the layer, the value may be zero. */
size_t iter_size;
- /** Called during session creation to initialize layer-specific
- * session data. */
+ /** Called during session creation to initialize layer-specific session
+ * data. Optional. The data is always zero-initialized during session
+ * initialization. */
protolayer_data_sess_init_cb sess_init;
/** Called during session destruction to deinitialize layer-specific
- * session data. */
+ * session data. Optional. */
protolayer_data_cb sess_deinit;
/** Called at the beginning of a layer sequence to initialize
- * layer-specific iteration data. */
+ * layer-specific iteration data. Optional. The data is always
+ * zero-initialized during iteration context initialization. */
protolayer_data_cb iter_init;
/** Called at the end of a layer sequence to deinitialize
- * layer-specific iteration data. */
+ * layer-specific iteration data. Optional. */
protolayer_data_cb iter_deinit;
/** Strips the buffer of protocol-specific data. E.g. a HTTP layer
- * removes HTTP status and headers. */
- protolayer_cb unwrap;
+ * removes HTTP status and headers. Optional - iteration continues
+ * automatically if this is NULL. */
+ protolayer_iter_cb unwrap;
/** Wraps the buffer into protocol-specific data. E.g. a HTTP layer
- * adds HTTP status and headers. */
- protolayer_cb wrap;
+ * adds HTTP status and headers. Optional - iteration continues
+ * automatically if this is NULL. */
+ protolayer_iter_cb wrap;
- /** Processes events in the unwrap order (sent from the outside). */
+ /** Processes events in the unwrap order (sent from the outside).
+ * Optional - iteration continues automatically if this is NULL. */
protolayer_event_cb event_unwrap;
- /** Processes events in the wrap order (bounced back by the session). */
+ /** Processes events in the wrap order (bounced back by the session).
+ * Optional - iteration continues automatically if this is NULL. */
protolayer_event_cb event_wrap;
};
-/** Global data about layered protocols. Indexed by `enum protolayer_protocol`. */
+/** Global data about layered protocols. Mapped by `enum protolayer_protocol`.
+ * Individual protocols are to be initialized during resolver startup. */
extern struct protolayer_globals protolayer_globals[PROTOLAYER_PROTOCOL_COUNT];
+
/** *Layer sequence return function* - signalizes the protolayer manager to
* continue processing the next layer. */
-enum protolayer_cb_result protolayer_continue(struct protolayer_cb_ctx *ctx);
+enum protolayer_iter_cb_result protolayer_continue(struct protolayer_iter_ctx *ctx);
/** *Layer sequence return function* - signalizes that the layer wants to stop
* processing of the buffer and clean up, possibly due to an error (indicated
* by a non-zero `status`). */
-enum protolayer_cb_result protolayer_break(struct protolayer_cb_ctx *ctx, int status);
+enum protolayer_iter_cb_result protolayer_break(struct protolayer_iter_ctx *ctx, int status);
/** *Layer sequence return function* - signalizes that the current sequence
* will continue in an asynchronous manner. The layer should store the context
* Note that this return function is just a readability hint - another return
* function may be called in another stack frame before it and the sequence
* will continue correctly. */
-static inline enum protolayer_cb_result protolayer_async()
+static inline enum protolayer_iter_cb_result protolayer_async()
{
- return PROTOLAYER_CB_RESULT_MAGIC;
+ return PROTOLAYER_ITER_CB_RESULT_MAGIC;
}
* group, and the provided transport context.
*
* `layer_param` is a pointer to an array of size `layer_param_count`. The
- * parameters are passed to the layer session initializers. The parameters and
- * the pointed-to data are only required to be valid while calling this
- * function. */
+ * parameters are passed to the layer session initializers. The parameter array
+ * is only required to be valid before this function returns. It is up to the
+ * individual layer implementations to determine the lifetime of the data
+ * pointed to by the parameters. */
struct session2 *session2_new(enum session2_transport_type transport_type,
enum protolayer_grp layer_grp,
struct protolayer_data_param *layer_param,
/** Sends an event to be synchronously processed by the protocol layers of the
* specified session, starting from the specified `protocol` in the `_UNWRAP`
* direction. The layers are first iterated through in the `_UNWRAP` direction,
- * then bounced back in the `_WRAP` direction. */
+ * then bounced back in the `_WRAP` direction.
+ *
+ * NOTE: The bounced iteration does not exclude any layers - the layer
+ * specified by `protocol` and those before it are only skipped in the
+ * `_UNWRAP` direction! */
void session2_event_after(struct session2 *s, enum protolayer_protocol protocol,
enum protolayer_event_type type, void *baton);
} tls_hs_state_t;
typedef int (*tls_handshake_cb) (struct session2 *session, int status);
-typedef queue_t(struct protolayer_cb_ctx *) pl_cb_ctx_queue_t;
+typedef queue_t(struct protolayer_iter_ctx *) pl_cb_ctx_queue_t;
struct pl_tls_sess_data {
PROTOLAYER_DATA_HEADER();
return 0;
size_t avail = 0;
- queue_it_t(struct protolayer_cb_ctx *) it = queue_it_begin(*queue);
+ queue_it_t(struct protolayer_iter_ctx *) it = queue_it_begin(*queue);
for (; !queue_it_finished(it); queue_it_next(it)) {
- struct protolayer_cb_ctx *ctx = queue_it_val(it);
+ struct protolayer_iter_ctx *ctx = queue_it_val(it);
struct protolayer_payload *pld = &ctx->payload;
if (pld->type == PROTOLAYER_PAYLOAD_BUFFER) {
avail += pld->buffer.len;
char *dest = buf;
size_t transfer = 0;
while (queue_len(tls->unwrap_queue) > 0 && len > 0) {
- struct protolayer_cb_ctx *ctx = queue_head(tls->unwrap_queue);
+ struct protolayer_iter_ctx *ctx = queue_head(tls->unwrap_queue);
struct protolayer_payload *pld = &ctx->payload;
bool fully_consumed = false;
struct kres_gnutls_push_ctx *push_ctx = baton;
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);
+ struct protolayer_iter_ctx *ctx = queue_head(tls->wrap_queue);
protolayer_break(ctx, kr_ok());
queue_pop(tls->wrap_queue);
}
return pl_tls_sess_data_deinit(sess_data);
}
-static enum protolayer_cb_result pl_tls_unwrap(void *sess_data, void *iter_data,
- struct protolayer_cb_ctx *ctx)
+static enum protolayer_iter_cb_result pl_tls_unwrap(void *sess_data, void *iter_data,
+ struct protolayer_iter_ctx *ctx)
{
struct pl_tls_sess_data *tls = sess_data;
struct session2 *s = ctx->manager->session;
if (kr_fails_assert(queue_len(tls->unwrap_queue) == 1))
return protolayer_break(ctx, kr_error(EINVAL));
- struct protolayer_cb_ctx *ctx_head = queue_head(tls->unwrap_queue);
+ struct protolayer_iter_ctx *ctx_head = queue_head(tls->unwrap_queue);
if (kr_fails_assert(ctx == ctx_head)) {
protolayer_break(ctx, kr_error(EINVAL));
ctx = ctx_head;
return kr_error(EINVAL);
}
-static enum protolayer_cb_result pl_tls_wrap(void *sess_data, void *iter_data,
- struct protolayer_cb_ctx *ctx)
+static enum protolayer_iter_cb_result pl_tls_wrap(void *sess_data, void *iter_data,
+ struct protolayer_iter_ctx *ctx)
{
struct pl_tls_sess_data *tls = sess_data;
gnutls_session_t tls_session = tls->tls_session;
return true;
}
-static enum protolayer_cb_result pl_dns_dgram_unwrap(
- void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
+static enum protolayer_iter_cb_result pl_dns_dgram_unwrap(
+ void *sess_data, void *iter_data, struct protolayer_iter_ctx *ctx)
{
struct session2 *session = ctx->manager->session;
return pkt;
}
-static enum protolayer_cb_result pl_dns_stream_unwrap(
- void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
+static enum protolayer_iter_cb_result pl_dns_stream_unwrap(
+ void *sess_data, void *iter_data, struct protolayer_iter_ctx *ctx)
{
if (kr_fails_assert(ctx->payload.type == PROTOLAYER_PAYLOAD_WIRE_BUF)) {
/* DNS stream only works with a wire buffer */
struct iovec iovs[];
};
-static enum protolayer_cb_result pl_dns_stream_wrap(
- void *sess_data, void *iter_data, struct protolayer_cb_ctx *ctx)
+static enum protolayer_iter_cb_result pl_dns_stream_wrap(
+ void *sess_data, void *iter_data, struct protolayer_iter_ctx *ctx)
{
struct pl_dns_stream_iter_data *stream = iter_data;
struct session2 *s = ctx->manager->session;