/** * Base class for deriving C++ plugins from. Possibly useful if you * like this sort of thing. Otherwise just make use you extern the * appropriate functions (i.e. the plugin init function) to have C symbols. */ #ifndef _LIGHTTPD_PLUGIN_HPP_ #define _LIGHTTPD_PLUGIN_HPP_ #include #include "c++-compat/plugin.h" #include "handler_helpers.hpp" #include "datatype_helpers.hpp" /** * Abstract base class for C++ lighty plugins. Not sure if its worth it * yet, lets see how useful it is. Really there shouldn't be any * significant performance hit with these wrappers, only a small increase * in memory usage per plugin (irrelivant). Other hit due to function * calling convensions for which I do not know the details. * * Things that need encapsulating: * * Plugin house keeping: * - set which part of the request flow we handle. i.e. _plugin_init * - populate plugin config. i.e. set_defaults * - clean up allocated memory we used. i.e. cleanup * * The request flow: * - HTTP request recieved, i.e. protocol, method, uri_raw, * headers (see http_req.h) * - "Clean" uri_raw -> uri_clean i.e. mod_rewrite * - Map the clean request to an appropriate docroot. * - Get the physical path to the requested file. * - Do untold horrors to the requested file. * - More things here. * - Send a response back maybe. * * Lighty allows plugins to hook in to multiple points of this flow, * i.e. one type of plugin, but their effects at certain levels may be NULL. * Serves as an easy method of sharing data between points of flow. Perhaps * theres something in trying to abstract this shared data out, and removing * this hardcoded sharing within a plugin. Don't know, just a gut feeling. * */ /** * Absolute base for plugins. */ class plugin_base { protected: // We always have a reference to the C plugin structure // lighty handles the freeing of p plugin_base( const char* name, const std::size_t version, plugin& p ) : p( p ), srv( 0 ) // don't know srv yet, need initialize { p.name = buffer_init_string( name ); p.version = version; p.data = reinterpret_cast< void* >( this ); // We don't have enough infomation to call init. // Instead, call it from set_defaults_wrapper // p.init = &plugin_base::initialize_wrapper; p.set_defaults = &plugin_base::set_defaults_wrapper; } plugin& p; const server* srv; public: // Here we have functions that are required by (almost) all plugins // For set defaults, we just call set defaults on all config_options // in the current translation unit. handler_t set_defaults( ) { return config_option_base::set_all_defaults( ); } static handler_t set_defaults_wrapper( server* s, void* p_d ) { plugin_base& p = reinterpret_cast< plugin_base& >( p_d ); initialize_wrapper( s, p_d ); return p.set_defaults( ); } // Set srv and return this. There are quite a few inconsistencies here I know, // this should really be called directly and return a newly allocated plugin. // Its a tug of war between C and C++ ways. I choose to init the plugin in // create_plugin and set p->data in the plugin_base constructor. void* initialize( const server& s ) { srv = &s; return reinterpret_cast< void* >( this ); } static void* initialize_wrapper( server* s, void* p_d ) { plugin_base& p = reinterpret_cast< plugin_base& >( p_d ); return p.initialize( *s ); } }; /** * Abstract plugin base-class for plugins, non-constructable, hidden from C * compilers. An alternative would be to have a plugin type derived from * this for each handler type. */ template< typename MostDerived > class Plugin : public plugin_base { typedef plugin_base super_type; protected: // Private constructor for setting plugin name. // Could say this is a part of the traditional lighty init function Plugin( const char* name, const std::size_t version, plugin& p ) : plugin_base( name, version, p ) { // The handler setter to use to configure hooks in plugin p below. typedef typename handlers_setter< MostDerived >::type setter; // use for_each to set the appropriate function pointers // in the plugin structure, dependend on the type "handlers" // defined in a derived class. setter::set( p ); } public: // This is to be called after entry, i.e. from _plugin_init. // We can't really eliminate the need to implement _plugin_init in // derived modules as we have to have the correct function name. // use the DEFINE_MODULE macro to create the appropriate entry function. static int create_plugin( plugin& p ) { // Make sure exceptions do not propergate to C code try { new MostDerived( p ); return 0; } catch( ... ) { return 1; } } }; // A list of defined interfaces. // The first argument specifies a typedef handle to the handler types, // the second specifies the handle name as seen in the plugin structure. // This macro is only for handlers that take just the connection. MAKE_HANDLER( UriRawHandler, handle_uri_raw ); MAKE_HANDLER( UriCleanHandler, handle_uri_clean ); MAKE_HANDLER( DocRootHandler, handle_docroot ); MAKE_HANDLER( PhysicalHandler, handle_physical ); MAKE_HANDLER( StartBackendHandler, handle_start_backend ); // This is defined in handler_helpers.hpp . It should not be used by derived plugins. #undef MAKE_HANDLER // Given your plugin name, this will create the entry point for lighttpd to use. // To be used in your plugins cpp file. #define MAKE_PLUGIN( name ) \ extern "C" \ { \ static int name##_plugin_init( plugin* p ) \ { \ return Plugin< name >::create_plugin( *p ); \ } \ } #endif // _LIGHTTPD_PLUGIN_HPP_