memcpy(send_ctx->data, data, length);
kr_log_debug(DOH, "[%p] send_callback: %p\n", (void *)h2, (void *)send_ctx->data);
- session2_wrap_after(http->session, PROTOLAYER_HTTP,
+ session2_wrap_after(http->session, PROTOLAYER_PROTOCOL_HTTP,
protolayer_buffer(send_ctx->data, length), NULL,
callback_finished_free_baton, send_ctx);
dest_iov[cur++] = (struct iovec){ (void *)padding, padlen - 1 };
kr_assert(cur == iovcnt);
- int ret = session2_wrap_after(http->session, PROTOLAYER_HTTP,
+ int ret = session2_wrap_after(http->session, PROTOLAYER_PROTOCOL_HTTP,
protolayer_iovec(dest_iov, cur),
NULL, callback_finished_free_baton, sdctx);
}
ret = 0;
- session2_unwrap_after(ctx->session, PROTOLAYER_HTTP,
+ session2_unwrap_after(ctx->session, PROTOLAYER_PROTOCOL_HTTP,
protolayer_wire_buf(wb), NULL, NULL, NULL);
cleanup:
http_cleanup_stream(ctx);
void http_protolayers_init(void)
{
- protolayer_globals[PROTOLAYER_HTTP] = (struct protolayer_globals) {
+ protolayer_globals[PROTOLAYER_PROTOCOL_HTTP] = (struct protolayer_globals) {
.sess_size = sizeof(struct pl_http_sess_data),
.sess_deinit = pl_http_sess_deinit,
.wire_buf_overhead = HTTP_MAX_FRAME_SIZE,
void io_protolayers_init(void)
{
- protolayer_globals[PROTOLAYER_UDP] = (struct protolayer_globals){
+ protolayer_globals[PROTOLAYER_PROTOCOL_UDP] = (struct protolayer_globals){
.iter_size = sizeof(struct pl_udp_iter_data),
.unwrap = pl_udp_unwrap,
.event_wrap = pl_udp_event_wrap,
};
- protolayer_globals[PROTOLAYER_TCP] = (struct protolayer_globals){
+ protolayer_globals[PROTOLAYER_PROTOCOL_TCP] = (struct protolayer_globals){
.sess_size = sizeof(struct pl_tcp_sess_data),
.sess_init = pl_tcp_sess_init,
.sess_deinit = pl_tcp_sess_deinit,
struct protolayer_globals protolayer_globals[PROTOLAYER_PROTOCOL_COUNT] = {{0}};
static const enum protolayer_protocol protolayer_grp_doudp[] = {
- PROTOLAYER_UDP,
- PROTOLAYER_DNS_DGRAM,
- PROTOLAYER_NULL
+ PROTOLAYER_PROTOCOL_UDP,
+ PROTOLAYER_PROTOCOL_DNS_DGRAM,
+ PROTOLAYER_PROTOCOL_NULL
};
static const enum protolayer_protocol protolayer_grp_dotcp[] = {
- PROTOLAYER_TCP,
- PROTOLAYER_DNS_MULTI_STREAM,
- PROTOLAYER_NULL
+ PROTOLAYER_PROTOCOL_TCP,
+ PROTOLAYER_PROTOCOL_DNS_MULTI_STREAM,
+ PROTOLAYER_PROTOCOL_NULL
};
static const enum protolayer_protocol protolayer_grp_dot[] = {
- PROTOLAYER_TCP,
- PROTOLAYER_TLS,
- PROTOLAYER_DNS_MULTI_STREAM,
- PROTOLAYER_NULL
+ PROTOLAYER_PROTOCOL_TCP,
+ PROTOLAYER_PROTOCOL_TLS,
+ PROTOLAYER_PROTOCOL_DNS_MULTI_STREAM,
+ PROTOLAYER_PROTOCOL_NULL
};
static const enum protolayer_protocol protolayer_grp_doh[] = {
- PROTOLAYER_TCP,
- PROTOLAYER_TLS,
- PROTOLAYER_HTTP,
- PROTOLAYER_DNS_UNSIZED_STREAM,
- PROTOLAYER_NULL
+ PROTOLAYER_PROTOCOL_TCP,
+ PROTOLAYER_PROTOCOL_TLS,
+ PROTOLAYER_PROTOCOL_HTTP,
+ PROTOLAYER_PROTOCOL_DNS_UNSIZED_STREAM,
+ PROTOLAYER_PROTOCOL_NULL
};
-const char *protolayer_protocol_names[PROTOLAYER_PROTOCOL_COUNT] = {
- [PROTOLAYER_NULL] = "(null)",
-#define XX(cid) [PROTOLAYER_##cid] = #cid,
+const char *protolayer_protocol_name(enum protolayer_protocol p)
+{
+ switch (p) {
+ case PROTOLAYER_PROTOCOL_NULL:
+ return "(null)";
+#define XX(cid) case PROTOLAYER_PROTOCOL_ ## cid: \
+ return #cid;
PROTOLAYER_PROTOCOL_MAP(XX)
#undef XX
-};
+ default:
+ return "(invalid)";
+ }
+}
/** Sequences of layers, mapped by `enum protolayer_grp`.
*
* one defined as *Variable name* (2nd parameter) in the `PROTOLAYER_GRP_MAP`
* macro. */
static const enum protolayer_protocol *protolayer_grps[PROTOLAYER_GRP_COUNT] = {
-#define XX(cid, vid, name) [PROTOLAYER_GRP_##cid] = protolayer_grp_##vid,
+#define XX(cid, vid, name) [PROTOLAYER_GRP_ ## cid] = protolayer_grp_ ## vid,
PROTOLAYER_GRP_MAP(XX)
#undef XX
};
-/** Human-readable names for protocol layer groups. */
-const char *protolayer_grp_names[PROTOLAYER_GRP_COUNT] = {
- [PROTOLAYER_GRP_NULL] = "(null)",
-#define XX(cid, vid, name) [PROTOLAYER_GRP_##cid] = (name),
+const char *protolayer_grp_name(enum protolayer_grp g)
+{
+ switch (g) {
+ case PROTOLAYER_GRP_NULL:
+ return "(null)";
+#define XX(cid, vid, name) case PROTOLAYER_GRP_ ## cid: \
+ return (name);
PROTOLAYER_GRP_MAP(XX)
#undef XX
-};
+ default:
+ return "(invalid)";
+ }
+}
-/** Human-readable names for events. */
-const char *protolayer_event_names[PROTOLAYER_EVENT_COUNT] = {
- [PROTOLAYER_EVENT_NULL] = "(null)",
-#define XX(cid) [PROTOLAYER_EVENT_##cid] = #cid,
+const char *protolayer_event_name(enum protolayer_event_type e)
+{
+ switch (e) {
+ case PROTOLAYER_EVENT_NULL:
+ return "(null)";
+#define XX(cid) case PROTOLAYER_EVENT_ ## cid: \
+ return #cid;
PROTOLAYER_EVENT_MAP(XX)
#undef XX
-};
+ default:
+ return "(invalid)";
+ }
+}
-/** Human-readable names for payloads. */
-const char *protolayer_payload_names[PROTOLAYER_PAYLOAD_COUNT] = {
- [PROTOLAYER_PAYLOAD_NULL] = "(null)",
-#define XX(cid, name) [PROTOLAYER_PAYLOAD_##cid] = (name),
+const char *protolayer_payload_name(enum protolayer_payload_type p)
+{
+ switch (p) {
+ case PROTOLAYER_PAYLOAD_NULL:
+ return "(null)";
+#define XX(cid, name) case PROTOLAYER_PAYLOAD_ ## cid: \
+ return (name);
PROTOLAYER_PAYLOAD_MAP(XX)
#undef XX
-};
+ default:
+ return "(invalid)";
+ }
+}
/* Forward decls. */
static inline const char *layer_name(enum protolayer_grp grp, ssize_t layer_ix)
{
+ if (grp >= PROTOLAYER_GRP_COUNT)
+ return "(invalid)";
enum protolayer_protocol p = protolayer_grps[grp][layer_ix];
- return protolayer_protocol_names[p];
+ return protolayer_protocol_name(p);
}
static inline const char *layer_name_ctx(struct protolayer_iter_ctx *ctx)
if (ret)
VERBOSE_LOG(session, "layer context of group '%s' (on %u: %s) ended with return code %d\n",
- protolayer_grp_names[ctx->manager->grp],
+ protolayer_grp_name(ctx->manager->grp),
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",
- protolayer_grp_names[ctx->manager->grp],
+ protolayer_grp_name(ctx->manager->grp),
ctx->layer_ix, layer_name_ctx(ctx), ctx->status);
if (ctx->finished_cb)
if (kr_log_is_debug(PROTOLAYER, NULL)) {
VERBOSE_LOG(session, "Pushing %s\n",
- protolayer_payload_names[ctx->payload.type]);
+ protolayer_payload_name(ctx->payload.type));
}
if (ctx->payload.type == PROTOLAYER_PAYLOAD_BUFFER) {
static int protolayer_step(struct protolayer_iter_ctx *ctx)
{
while (true) {
+ if (kr_fails_assert(ctx->manager->grp < PROTOLAYER_GRP_COUNT))
+ return kr_error(EFAULT);
+
enum protolayer_protocol protocol = protolayer_grps[ctx->manager->grp][ctx->layer_ix];
struct protolayer_globals *globals = &protolayer_globals[protocol];
VERBOSE_LOG(manager->session,
"%s submitted to grp '%s' in %s direction (%zu: %s)\n",
- protolayer_payload_names[payload.type],
- protolayer_grp_names[manager->grp],
+ protolayer_payload_name(payload.type),
+ protolayer_grp_name(manager->grp),
(direction == PROTOLAYER_UNWRAP) ? "unwrap" : "wrap",
layer_ix, layer_name(manager->grp, layer_ix));
};
for (size_t i = 0; i < manager->num_layers; i++) {
+ if (kr_fails_assert(ctx->manager->grp < PROTOLAYER_GRP_COUNT))
+ return kr_error(EFAULT);
+
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);
};
-/** A buffer, with indices marking the chunk containing valid data.
+/** A buffer, with indices marking the chunk containing as of yet unprocessed
+ * data - this chunk is called "valid". The contents may be manipulated using
+ * `wire_buf_` functions, which ensure the struct's validity.
+ *
+ * The struct may be used to retrieve data piecewise, e.g. from a stream-based
+ * transport like TCP, by writing data to the buffer's free space, then
+ * "consuming" that space with `wire_buf_consume`. It can also be handy for
+ * processing message headers, then trimming the beginning of the buffer (using
+ * `wire_buf_trim`) so that the next part of the data may be processed by a
+ * next part of a common pipeline.
*
* May be initialized in two possible ways:
* - via `wire_buf_init`
* intact). */
void wire_buf_deinit(struct wire_buf *wb);
-/** Ensures that the wire buffer's size is at least `size`. `*wb` must be
- * initialized, either to zero or via `wire_buf_init`. */
+/** Ensures that the wire buffer's size is at least `size`. The memory at `wb`
+ * must be initialized, either to zero or via `wire_buf_init`. */
int wire_buf_reserve(struct wire_buf *wb, size_t size);
/** Adds `length` to the end index of the valid data, marking `length` more
* bytes as valid.
*
* Returns 0 on success.
- * Returns `kr_error(EINVAL)` if the end index would exceed the
- * buffer size. */
+ * Assert-fails and/or returns `kr_error(EINVAL)` if the end index would exceed
+ * the buffer size. */
int wire_buf_consume(struct wire_buf *wb, size_t length);
/** Adds `length` to the start index of the valid data, marking `length` less
* bytes as valid.
*
* Returns 0 on success.
- * Returns `kr_error(EINVAL)` if the start index would exceed
- * the end index. */
+ * Assert-fails and/or returns `kr_error(EINVAL)` if the start index would
+ * exceed the end index. */
int wire_buf_trim(struct wire_buf *wb, size_t length);
/** Moves the valid bytes of the buffer to the buffer's beginning. */
int wire_buf_movestart(struct wire_buf *wb);
-/** Resets the valid bytes of the buffer to zero, as well as the error flag. */
+/** Resets the valid bytes of the buffer to zero. */
int wire_buf_reset(struct wire_buf *wb);
/** Gets a pointer to the data marked as valid in the wire buffer. */
/** The identifiers of protocol layer types. */
enum protolayer_protocol {
- PROTOLAYER_NULL = 0,
-#define XX(cid) PROTOLAYER_##cid,
+ PROTOLAYER_PROTOCOL_NULL = 0,
+#define XX(cid) PROTOLAYER_PROTOCOL_ ## cid,
PROTOLAYER_PROTOCOL_MAP(XX)
#undef XX
PROTOLAYER_PROTOCOL_COUNT /* must be the last! */
};
-/** Maps protocol layer type IDs to string names.
- * E.g. PROTOLAYER_HTTP has name 'HTTP'. */
-extern const char *protolayer_protocol_names[];
+/** Gets the constant string name of the specified protocol. */
+const char *protolayer_protocol_name(enum protolayer_protocol p);
/** Protocol layer group map
*
/** The identifiers of pre-defined protocol layer sequences. */
enum protolayer_grp {
PROTOLAYER_GRP_NULL = 0,
-#define XX(cid, vid, name) PROTOLAYER_GRP_##cid,
+#define XX(cid, vid, name) PROTOLAYER_GRP_ ## cid,
PROTOLAYER_GRP_MAP(XX)
#undef XX
PROTOLAYER_GRP_COUNT
};
-/** Maps protocol layer group IDs to human-readable descriptions.
- * E.g. PROTOLAYER_GRP_DOH has description 'DNS-over-HTTPS'. */
-extern const char *protolayer_grp_names[];
+/** Gets the constant string name of the specified protocol layer group. */
+const char *protolayer_grp_name(enum protolayer_grp g);
/** Flow control indicators for protocol layer `wrap` and `unwrap` callbacks.
* Use via `protolayer_continue`, `protolayer_break`, and `protolayer_push`
/** Event type, to be interpreted by a layer. */
enum protolayer_event_type {
PROTOLAYER_EVENT_NULL = 0,
-#define XX(cid) PROTOLAYER_EVENT_##cid,
+#define XX(cid) PROTOLAYER_EVENT_ ## cid,
PROTOLAYER_EVENT_MAP(XX)
#undef XX
PROTOLAYER_EVENT_COUNT
};
-/** Maps event types to their names. */
-extern const char *protolayer_event_names[];
+/** Gets the constant string name of the specified event. */
+const char *protolayer_event_name(enum protolayer_event_type e);
/** Payload types.
* 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
};
-/** Maps payload type IDs to human-readable names. */
-extern const char *protolayer_payload_names[];
+/** Gets the constant string name of the specified payload type. */
+const char *protolayer_payload_name(enum protolayer_payload_type p);
/** Data processed by the sequence of layers. All pointed-to memory is always
* owned by its creator. It is also the layer (group) implementor's
push_ctx->sess_data = tls;
memcpy(push_ctx->iov, iov, sizeof(struct iovec[iovcnt]));
- session2_wrap_after(tls->session, PROTOLAYER_TLS,
+ session2_wrap_after(tls->session, PROTOLAYER_PROTOCOL_TLS,
protolayer_iovec(push_ctx->iov, iovcnt), NULL,
kres_gnutls_push_finished, push_ctx);
}
}
if (!tls->first_handshake_done) {
- session2_event_after(session, PROTOLAYER_TLS,
+ session2_event_after(session, PROTOLAYER_PROTOCOL_TLS,
PROTOLAYER_EVENT_CONNECT, NULL);
tls->first_handshake_done = true;
}
void tls_protolayers_init(void)
{
- protolayer_globals[PROTOLAYER_TLS] = (struct protolayer_globals){
+ protolayer_globals[PROTOLAYER_PROTOCOL_TLS] = (struct protolayer_globals){
.sess_size = sizeof(struct pl_tls_sess_data),
.sess_deinit = pl_tls_sess_deinit,
.wire_buf_overhead = TLS_CHUNK_SIZE,
bool has_tls = tls_entry;
if (has_tls) {
struct protolayer_data_param param = {
- .protocol = PROTOLAYER_TLS,
+ .protocol = PROTOLAYER_PROTOCOL_TLS,
.param = tls_entry
};
session = ioreq_spawn(SOCK_STREAM, addr->sa_family,
kr_bindings_register(the_engine->L); // TODO move
/* DNS protocol layers */
- protolayer_globals[PROTOLAYER_DNS_DGRAM] = (struct protolayer_globals){
+ protolayer_globals[PROTOLAYER_PROTOCOL_DNS_DGRAM] = (struct protolayer_globals){
.wire_buf_overhead = KNOT_WIRE_MAX_PKTSIZE,
.unwrap = pl_dns_dgram_unwrap,
.event_unwrap = pl_dns_dgram_event_unwrap
};
- protolayer_globals[PROTOLAYER_DNS_UNSIZED_STREAM] = (struct protolayer_globals){
+ protolayer_globals[PROTOLAYER_PROTOCOL_DNS_UNSIZED_STREAM] = (struct protolayer_globals){
.wire_buf_overhead = KNOT_WIRE_MAX_PKTSIZE,
.sess_init = pl_dns_stream_sess_init,
.unwrap = pl_dns_dgram_unwrap,
.event_unwrap = pl_dns_stream_event_unwrap,
.request_init = pl_dns_stream_request_init
};
- protolayer_globals[PROTOLAYER_DNS_MULTI_STREAM] = stream_common;
- protolayer_globals[PROTOLAYER_DNS_MULTI_STREAM].sess_init = pl_dns_stream_sess_init;
- protolayer_globals[PROTOLAYER_DNS_SINGLE_STREAM] = stream_common;
- protolayer_globals[PROTOLAYER_DNS_SINGLE_STREAM].sess_init = pl_dns_single_stream_sess_init;
+ protolayer_globals[PROTOLAYER_PROTOCOL_DNS_MULTI_STREAM] = stream_common;
+ protolayer_globals[PROTOLAYER_PROTOCOL_DNS_MULTI_STREAM].sess_init = pl_dns_stream_sess_init;
+ protolayer_globals[PROTOLAYER_PROTOCOL_DNS_SINGLE_STREAM] = stream_common;
+ protolayer_globals[PROTOLAYER_PROTOCOL_DNS_SINGLE_STREAM].sess_init = pl_dns_single_stream_sess_init;
/* Create main worker. */
the_worker = &the_worker_value;