Add sideband implementation.
[paraslash.git] / sideband.h
diff --git a/sideband.h b/sideband.h
new file mode 100644 (file)
index 0000000..4f4ed0a
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2012 Andre Noll <maan@systemlinux.org>
+ *
+ * Licensed under the GPL v2. For licencing details see COPYING.
+ */
+
+/** \file sideband.h exported symbols from sideband.c */
+
+/**
+ * The valid sideband designators.
+ *
+ * A sideband packet consists of a header and a body. The header is sent prior
+ * to the data and contains the length of the buffer and the sideband
+ * designator, an integer. This scheme allows receivers to never read more data
+ * than what was specified in the header.
+ *
+ * The sideband designator indicates the type of the data. The authentication
+ * handshake between the command handler (child of para_server) and the client
+ * requires to exchange several small packages. Each such package is sent as a
+ * sideband package with a dedicated designator.
+ *
+ * Other designators are employed for normal command output and for log
+ * messages, where each loglevel corresponds to a sideband designator.
+ *
+ * Note that the values of this enum are part of the ABI, so never change
+ * or remove entries. Appending is OK though.
+ */
+#define SB_DESIGNATORS \
+       /* Special value for receiving only: Accept any band. */ \
+       DESIGNATOR(ANY), \
+       /* This packet contains the authentication challenge. */ \
+       DESIGNATOR(CHALLENGE), \
+       /* I solved your challenge and here is the proof. */ \
+       DESIGNATOR(CHALLENGE_RESPONSE), \
+       /* Congratulations, you are authenticated. */ \
+       DESIGNATOR(PROCEED), \
+       /* This is the command I want you to execute. */ \
+       DESIGNATOR(COMMAND), \
+       /* Ready to receive a blob (addblob commands only). */ \
+       DESIGNATOR(AWAITING_DATA), \
+       /* Normal command output (default). */ \
+       DESIGNATOR(OUTPUT), \
+       /* LL_DEBUG. */ \
+       DESIGNATOR(DEBUG_LOG), \
+       /* LL_INFO. */ \
+       DESIGNATOR(INFO_LOG), \
+       /* LL_NOTICE. */ \
+       DESIGNATOR(NOTICE_LOG), \
+       /* LL_WARNING, */ \
+       DESIGNATOR(WARNING_LOG), \
+       /* LL_ERROR. */ \
+       DESIGNATOR(ERROR_LOG), \
+       /* LL_CRIT. */ \
+       DESIGNATOR(CRIT_LOG), \
+       /* LL_EMERG. */ \
+       DESIGNATOR(EMERG_LOG), \
+       /* Command terminated successfully. */ \
+       DESIGNATOR(EXIT__SUCCESS), \
+       /* Command failed. */ \
+       DESIGNATOR(EXIT__FAILURE), \
+
+/** Just prefix with \p SBD_. */
+#define DESIGNATOR(x) SBD_ ## x
+
+/** All valid sideband designators. */
+enum sb_designator {SB_DESIGNATORS NUM_SB_DESIGNATORS};
+#undef DESIGNATOR
+/** One stringified sideband designator. */
+#define DESIGNATOR(x) #x
+/** List of stringified sidedband designators. */
+#define SB_DESIGNATORS_ARRAY SB_DESIGNATORS
+
+/**
+ * The information contained in a sideband buffer.
+ *
+ * This structure is used for both sending and receiving data through a
+ * sideband channel. A pointer to a sideband buffer is passed to the sending
+ * side of a sideband while the receiving end yields a filled out structure
+ * once all data has been received.
+ */
+struct sb_buffer {
+       /** Data and length. */
+       struct iovec iov;
+       /** The band designator. */
+       uint8_t band;
+};
+
+/**
+ * The opaque sideband context structure.
+ *
+ * A pointer to a structure of this type is returned by the two \a sb_new_xxx
+ * functions as an opaque handle. Other public functions of the sideband API
+ * take such a handle as a parameter.
+ */
+struct sb_context;
+
+/**
+ * The type of a sideband transformation.
+ *
+ * The sideband API allows to filter all data through an arbitrary
+ * transformation, which is useful for crypto purposes. The transformation may
+ * either transform the data in place, or return a pointer to a new buffer
+ * which contains the transformed source buffer. The internal sideband
+ * functions can tell the two types of transformations apart by checking
+ * whether the destination buffer coincides with the source buffer.
+ *
+ * If the transformation allocates a new buffer, it _must_ allocate one extra
+ * byte for \p NULL termination.
+ */
+typedef void (*sb_transformation)(struct iovec *src, struct iovec *dst,
+               void *trafo_context);
+
+
+/** Initialize a sideband buffer. */
+#define SBB_INIT(_band, _buf, _numbytes) \
+       { \
+               .band = band, \
+               .iov = { \
+                       .iov_base = _buf, \
+                       .iov_len = _numbytes \
+               } \
+       };
+
+/* receiving */
+struct sb_context *sb_new_recv(size_t max_size, sb_transformation t,
+               void *trafo_context);
+void sb_get_recv_buffer(struct sb_context *c, struct iovec *iov);
+int sb_received(struct sb_context *c, size_t nbytes, struct sb_buffer *result);
+
+/* sending */
+struct sb_context *sb_new_send(struct sb_buffer *sbb, bool dont_free,
+               sb_transformation t, void *trafo_context);
+int sb_get_send_buffers(struct sb_context *c, struct iovec iov[2]);
+bool sb_sent(struct sb_context *c, size_t nbytes);
+
+void sb_free(struct sb_context *c);