]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
prop340: Add relay msg codec, encoder and decoder basics
authorDavid Goulet <dgoulet@torproject.org>
Thu, 5 Oct 2023 14:49:59 +0000 (10:49 -0400)
committerDavid Goulet <dgoulet@torproject.org>
Wed, 31 Jan 2024 15:16:02 +0000 (10:16 -0500)
Signed-off-by: David Goulet <dgoulet@torproject.org>
src/core/or/relay_msg.c
src/core/or/relay_msg.h
src/core/or/relay_msg_st.h [new file with mode: 0644]

index 3dad5322fd98d8f74c0c6f9a65dd29cd9caafb67..864a6066f2bdc40c9e3c5acafd78e820eda8ef48 100644 (file)
@@ -36,6 +36,73 @@ get_param_enabled(const networkstatus_t *ns)
                                  RELAY_MSG_PARAM_ENABLED_MAX) != 0;
 }
 
+/** Initialize the given encoder for the relay cell protocol version. */
+static void
+encoder_relay_msg_init(relay_msg_encoder_t *encoder, uint8_t relay_cell_proto)
+{
+  tor_assert(encoder);
+  encoder->relay_cell_proto = relay_cell_proto;
+  encoder->ready_cells = smartlist_new();
+}
+
+/** Clear a given encoder which frees its ressources. */
+static void
+encoder_relay_msg_clear(relay_msg_encoder_t *encoder)
+{
+  tor_assert(encoder);
+  SMARTLIST_FOREACH(encoder->ready_cells, cell_t *, c, tor_free(c));
+  smartlist_free(encoder->ready_cells);
+}
+
+/** Reset a given encoder that is set it back to its initial state. */
+#if 0
+static void
+encoder_relay_msg_reset(relay_msg_encoder_t *encoder)
+{
+  tor_assert(encoder);
+  uint8_t relay_cell_proto = encoder->relay_cell_proto;
+  encoder_relay_msg_clear(encoder);
+  encoder_relay_msg_init(encoder, relay_cell_proto);
+}
+#endif
+
+/** Initialize a given decoder object for the relay cell protocol version. */
+static void
+decoder_relay_msg_init(relay_msg_decoder_t *decoder, uint8_t relay_cell_proto)
+{
+  memset(decoder, 0, sizeof(relay_msg_decoder_t));
+  decoder->relay_cell_proto = relay_cell_proto;
+  decoder->ready = smartlist_new();
+}
+
+/** Clear the inside of the given decoder object as in free any ressources. */
+static void
+decoder_relay_msg_clear(relay_msg_decoder_t *decoder)
+{
+  if (!decoder) {
+    return;
+  }
+  relay_msg_free(decoder->pending);
+  SMARTLIST_FOREACH(decoder->ready, relay_msg_t *, m, relay_msg_free(m));
+  smartlist_free(decoder->ready);
+}
+
+/** Clear the given decoder as in free all its content and initialize it to
+ * factory default. */
+#if 0
+static void
+decoder_relay_msg_reset(relay_msg_decoder_t *decoder)
+{
+  uint8_t relay_cell_proto = decoder->relay_cell_proto;
+  decoder_relay_msg_clear(decoder);
+  decoder_relay_msg_init(decoder, relay_cell_proto);
+}
+#endif
+
+/*
+ * Public API
+ */
+
 /** Return true iff the ability to use relay messages is enabled. */
 bool
 relay_msg_is_enabled(void)
@@ -50,3 +117,47 @@ relay_msg_consensus_has_changed(const networkstatus_t *ns)
 {
   relay_msg_enabled = get_param_enabled(ns);
 }
+
+/** Free the given relay message. */
+void
+relay_msg_free(relay_msg_t *msg)
+{
+  if (!msg) {
+    return;
+  }
+  tor_free(msg->body);
+  tor_free(msg);
+}
+
+/** Clear a relay message as in free its content and reset all fields to 0.
+ * This is useful for stack allocated memory. */
+void
+relay_msg_clear(relay_msg_t *msg)
+{
+  tor_assert(msg);
+  tor_free(msg->body);
+  memset(msg, 0, sizeof(*msg));
+}
+
+/** Initialize a given codec pointer for the relay cell protocol version. */
+void
+relay_msg_codec_init(relay_msg_codec_t *codec, uint8_t relay_cell_proto)
+{
+  tor_assert(codec);
+  codec->relay_cell_proto = relay_cell_proto;
+  decoder_relay_msg_init(&codec->decoder, relay_cell_proto);
+  encoder_relay_msg_init(&codec->encoder, relay_cell_proto);
+  codec->pending_packable_msg = smartlist_new();
+}
+
+/** Clear the content of the given codec object as in free the ressources. */
+void
+relay_msg_codec_clear(relay_msg_codec_t *codec)
+{
+  tor_assert(codec);
+  decoder_relay_msg_clear(&codec->decoder);
+  encoder_relay_msg_clear(&codec->encoder);
+  SMARTLIST_FOREACH(codec->pending_packable_msg, relay_msg_t *, msg,
+                    relay_msg_free(msg));
+  smartlist_free(codec->pending_packable_msg);
+}
index 35b0990ba3ecb9d9a5a8b083a9977f14d086d0ff..b265b8d459c62f2f0c950664f298c572d726b1ec 100644 (file)
 
 #include "core/or/or.h"
 
+#include "core/or/relay_msg_st.h"
+
 bool relay_msg_is_enabled(void);
 
 void relay_msg_consensus_has_changed(const networkstatus_t *ns);
 
+/* Relay message */
+void relay_msg_free(relay_msg_t *msg);
+void relay_msg_clear(relay_msg_t *msg);
+
+/* Codec. */
+void relay_msg_codec_init(relay_msg_codec_t *codec, uint8_t relay_cell_proto);
+void relay_msg_codec_clear(relay_msg_codec_t *codec);
+
 #ifdef RELAY_MSG_PRIVATE
 
 #endif /* RELAY_MSG_PRIVATE */
diff --git a/src/core/or/relay_msg_st.h b/src/core/or/relay_msg_st.h
new file mode 100644 (file)
index 0000000..0da0673
--- /dev/null
@@ -0,0 +1,75 @@
+/* Copyright (c) 2023, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * @file relay_msg_st.h
+ * @brief A relay message which contains a relay command and parameters,
+ *        if any, that is from a relay cell.
+ **/
+
+#ifndef TOR_RELAY_MSG_ST_H
+#define TOR_RELAY_MSG_ST_H
+
+#include "core/or/or.h"
+
+/** A relay message object which contains pointers to the header and payload.
+ *
+ * One acquires a relay message through the use of an iterator. Once you get a
+ * reference, the getters MUST be used to access data.
+ *
+ * This CAN NOT be made opaque so to avoid heap allocation in the fast path. */
+typedef struct relay_msg_t {
+  /* Relay cell protocol version of this message. */
+  uint8_t relay_cell_proto;
+  /* Relay command of a message. */
+  uint8_t command;
+  /* Length of payload. */
+  uint16_t length;
+  /* Optional routing header: stream ID of a message or 0. */
+  streamid_t stream_id;
+  /* Indicate if this is a message from a relay early cell. */
+  bool is_relay_early;
+  /* Message body of a relay message. */
+  uint8_t *body;
+} relay_msg_t;
+
+/** Decoder object for which cells (cell_t) are given and then unframed into
+ * relay message(s) kept in this object. */
+typedef struct relay_msg_decoder_t {
+  /* Version of the relay cell protocol to use for this decoder. */
+  uint8_t relay_cell_proto;
+  /* The pending relay message meaning that it needs more cell to be completed.
+   * This happens when messages are fragmented over many cells. */
+  relay_msg_t *pending;
+  /* The length of the pending data we are waiting for. In other words, how
+   * many bytes do we need more in more cells to complete the message body. */
+  size_t pending_len;
+  /* The list of messages that are ready. Multiple messages can be in one
+   * single cell and so this list will have them once unframed. */
+  smartlist_t *ready;
+} relay_msg_decoder_t;
+
+/** Encoder object for which relay messages are given and then packed or/and
+ * fragmented yielding cell(s) to be sent on the wire. */
+typedef struct relay_msg_encoder_t {
+  /* Version of the relay cell protocol of this encoded. */
+  uint8_t relay_cell_proto;
+  /* Cells that are ready to be sent on the wire. */
+  smartlist_t *ready_cells;
+} relay_msg_encoder_t;
+
+/** Codec object for relay message. This contains the decoder to be used for
+ * relay message. */
+typedef struct relay_msg_codec_t {
+  /* Version of the relay cell protocol of this codec. */
+  uint8_t relay_cell_proto;
+  /* The decoder. */
+  relay_msg_decoder_t decoder;
+  /* The encoded . */
+  relay_msg_encoder_t encoder;
+  /* A list of relay message that are awaiting to be packed. A message is
+   * popped everytime a cell goes through the encoder. */
+  smartlist_t *pending_packable_msg;
+} relay_msg_codec_t;
+
+#endif /* !defined(TOR_RELAY_MSG_ST_H) */