aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2024-02-11 14:52:20 -0700
committerJosh Rahm <rahm@google.com>2024-02-11 14:52:20 -0700
commita0f290b2e82e1331f4f932042dcdbc7d919a374f (patch)
tree66e8c90990a913fd1fc7ee791bbcda71656f5775
parenta4a3ea6b0f14cbd3f19bedf26a40c6ef45868a15 (diff)
downloadwetterhorn-a0f290b2e82e1331f4f932042dcdbc7d919a374f.tar.gz
wetterhorn-a0f290b2e82e1331f4f932042dcdbc7d919a374f.tar.bz2
wetterhorn-a0f290b2e82e1331f4f932042dcdbc7d919a374f.zip
Start making some more changes to harness and add plugin interface.
-rw-r--r--harness/include/plugin.h101
-rw-r--r--src/harness_adapter.c2
2 files changed, 103 insertions, 0 deletions
diff --git a/harness/include/plugin.h b/harness/include/plugin.h
new file mode 100644
index 0000000..70ca198
--- /dev/null
+++ b/harness/include/plugin.h
@@ -0,0 +1,101 @@
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <dlfcn.h>
+#include <stdint.h>
+#include <pthread.h>
+
+#define PRIVATE(a) a
+
+typedef void* dlhandle_t;
+
+/* Opaque state for a plugin. Not to be touched by the harness (not that it
+ * really can be.) */
+typedef void* opqst_t;
+
+/*
+ * Structure for the plugin.
+ */
+typedef struct PLUGIN {
+ /* Opaque state of this plugin. The state is usually some kind of pointer to
+ * the plugin state, but all the harness knows is the opaque state is a
+ * pointer-sized piece of data.
+ *
+ * This opaque state is used in a linear pattern where the handlers take the
+ * opaque state, maybe operate on it, and return a new opaque state, which is
+ * then passed to the next handler, etc. It is on the plugin to properly
+ * manager the memory for this state and to destroy it upon teardown.
+ *
+ * It's guaranteed that this state is used linearly, meaning the harness gives
+ * up all ownership to it once passed into a handler. */
+ PRIVATE(opqst_t state);
+
+ /* This plugin's lock. This avoids potential issues with multiple threads
+ * trying to change the opaque state at once which can lead to undesireable
+ * outcomes. */
+ PRIVATE(pthread_mutex_t lock);
+
+ /* The handle to the shared library. */
+ PRIVATE(dlhandle_t library_handle);
+
+ /* Pointer to the plugin name. This is in the shared library and a
+ * null-terminated string. If the library does not have a plugin name, this
+ * will be NULL. */
+ PRIVATE(const char* plugin_name);
+
+ /** Intializes the plugin with the given argc/argv. This is the first thing
+ * called on the plugin and is called immediately after the library is loaded.
+ */
+ void (*plugin_load)(int argc, char** argv);
+
+ /* Start the plugin with the marshalled state from the previous plugin.
+ *
+ * This should return the opaque state from the mashalled_state.
+ *
+ * This function should not fail if the state cannot be demarshalled, rather a
+ * default state should be returned. This is because changing the plugin and
+ * hot-reloading can produce incompatibilities between the old state and the
+ * new state, and this should not cause a failure.
+ */
+ opqst_t (*plugin_hot_start)(uint8_t* mashalled_state, uint32_t n);
+
+ /*
+ * Starts the plugin without a marshalled state. Happens during the first boot
+ * when there is not state.
+ */
+ opqst_t (*plugin_cold_start)();
+
+ /*
+ * Marshals the state to a bytestring. The returned pointer should be malloc'd
+ * on the heap. The harness takes ownership of the malloc'd pointer.
+ *
+ * This is usually called in preparation for a teardown followed by a
+ * hot-start.
+ */
+ uint8_t* (*plugin_marshal_state)(opqst_t st, uint32_t* szout);
+
+ /*
+ * Teardown the plugin in preperation for the library's imminent unloading.
+ */
+ void (*plugin_teardown)(opqst_t);
+
+ /* This anonymous structure contains event handlers. It is wrapped in this
+ * structure to make it distinct from the management functions above.
+ *
+ * The handlers are all optional and if any of them are NULL, the opaque state
+ * remains untouched.
+ */
+ struct {
+ /* Right now, empty */
+ } handlers;
+
+} plugin_t;
+
+/** Loads a plugin from the dynamic library handle. Returns a non-zero error
+ * code on error. */
+int load_plugin_from_dlhandle(plugin_t* out, dlhandle_t library);
+
+/* Like the above, but load the library from the given file. */
+int load_plugin_from_file(plugin_t* out, const char* dlfilename);
+
+#endif /* _PLUGIN_H_ */
diff --git a/src/harness_adapter.c b/src/harness_adapter.c
index 4d751c0..dbae57a 100644
--- a/src/harness_adapter.c
+++ b/src/harness_adapter.c
@@ -15,3 +15,5 @@ void plugin_teardown()
{
hs_exit();
}
+
+const char* plugin_name = "Wetterhorn";