#ifndef _PLUGIN_H_ #define _PLUGIN_H_ #include #include #include #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_ */