Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

How to add a Medium Plugin

$Id: plugins.txt,v 1.8 2003/05/11 17:21:57 aquamaniac Exp $

This file describes how to add a Medium-Plugin to OpenHBCI.


What Is A Medium Plugin ?
=========================

A medium is something used to store the user's cryptographic keys.
They can be stored in a key file with some file format, or on a
chipcard, or on whatever type of medium you want to implement.

A medium plugin is a mechanism which provides support for a medium.
E.g., the plugin "DDVCard" provides support for DDV chipcards, so with
this plugin installed you are able to use such a card.

A plugin is either loaded on demand at run-time or statically linked into
OpenHBCI.


Rules For Creating a Medium Plugin
==================================

A plugin must follow these rules in order to be useable with OpenHBCI.

Medium Type String
------------------

A plugin for a specifc medium is identified by a unique medium type
string, e.g. "DDVCard", "RSACard", or "RDHFile". This string is the
identification by which an application may query whether this plugin
can be loaded.

Filename
--------
When OpenHBCI is asked to create a medium of the type "DDVCard" it performs
these actions:
- check whether a plugin is already loaded which provides this type
- if it is not:
  - take the name of the medium type (in this case "DDVCard") 
  - change it to lower cases (->"ddvcard") 
  - append the extension used on the running system (on Linux: ".so") 
    (-> "ddvcard.so") 
  - look for a file of that name in the system wide OpenHBCI plugin folder.
    You can get this folder with the command "openhbci-config --plugins"

So the name of the file must be the lower cased medium type string
plus the shared object file extension used on the current operating system.

Exported Symbols
----------------
The following symbols (see nm(1)) must be defined in any new plugin:

int @PLUGINNAME@_openhbci_plugin_interface_version;
  /* This is the plugin interface version of OpenHBCI, which is
  necessary so that old plugins can be handled as well. For new
  plugins, it has to be set to the current value of
  OPENHBCI_PLUGIN_INTERFACE_VERSION */

int @PLUGINNAME@_openhbci_module_current; 
int @PLUGINNAME@_openhbci_module_revision;
int @PLUGINNAME@_openhbci_module_age; 
/* The above three numbers are the version
number of the given plugin implementation. The three version numbers
are handled in the same way as libtool's versioning system. See the
info pages of libtool. */

HBCI::Error @PLUGINNAME@_registerYourSelf(HBCI::API *api);
  /* This is the initialization function for the plugin. See below. */

If any of these symbols cannot be found, the plugin loader interface
will return an error message and refuse to load the plugin.

Please note that @PLUGINNAME@ stands for the name of your plugin (no
capitals). Each exported symbol must have this prefix to avoid namespace
collisions when linking a plugin statically to OpenHBCI.

RegisterYourSelf
----------------
This is the function OpenHBCI uses to initialize the plugin. It may
perform whatever actions it needs to perform. 
However, the first thing this function should do is to check the version
of OpenHBCI used and compare it against that version which was used when
the plugin has been compiled.

RULE 1: A plugin should refuse to work if the currently running
        version of OpenHBCI is older than that one used to compile the
        plugin!  In that case, the plugin's function
        registerYourSelf() should return an HBCI::Error with error
        code [FIXME: Give error code here]. [FIXME: Isn't this a bit
        too strict? Shouldn't it be allowed if only the patchlevel
        and/or minor changed?]

RULE 2: If the major version number of the running OpenHBCI library differs
        from the one used to compile the plugin, then the plugin
        should refuse to work, too, and return a HBCI::Error with erro
        code [FIXME: give error code here.]

If the version check succeeds, then this function should instantiate
an object of a class that inherits HBCI::MediumPlugin (in our example
this is HBCI::DDVCardPlugin) and call api->registerMediumPlugin() with
this object, thus registering the new plugin.



Important Classes
=================
When writing your own MediumPlugin you will find the following classes
helpful: 
- HBCI::Medium -- Abstract base class for any security medium
- HBCI::Plugin -- Abstract base class for any plugin
- HBCI::MediumPlugin -- Abstract base class for medium plugin

A nice example of how to create a plugin is the RDHFile plugin located
in "src/plugins/keyfile".

Note: The class PluginFile is not intended to be inherited by a
plugin, despite its name. Instead, that class is used internally by
OpenHBCI's plugin loader interface to manage the known plugins. You
probably do not need to inherit that class.



Caveats
=======

Most likely your new medium plugin is written in C++.  However, to be
able to lookup the exported symbols through dlsym(3), the exported
symbols must be declared with the 'extern "C"' binding
prefix. Otherwise, due to each C++ compiler's name mangling, it would
not be possible to lookup the symbols by dlsym(). So you need to use
the binding prefix `extern "C"`.  The following example will work:

-------------------------------------------------X8
extern "C" {

  int @PLUGINNAME@_openhbci_plugin_interface_version = OPENHBCI_PLUGIN_INTERFACE_VERSION;

  int @PLUGINNAME@_openhbci_module_current=DDVCARD_MODULE_CURRENT;
  int @PLUGINNAME@_openhbci_module_revision=DDVCARD_MODULE_REVISION;
  int @PLUGINNAME@_openhbci_module_age=DDVCARD_MODULE_AGE;

  HBCI::Error @PLUGINNAME@_registerYourSelf(HBCI::API *api) {
    // do initialization here
  }
}; // extern "C"
-------------------------------------------------X8

Please note that ONLY these symbols (functions, variables) MUST be
declared within the 'extern "C"' statement. All other symbols MUST
NOT!


More Usefull Rules
==================

Unfortunately old GCC compilers (before 3.0) have very big problems with code
that loads C++-libraries via dlopen(3). These problems make the new plugin
system of OpenHBCI useles on those systems. 
However, in such a case OpenHBCI is able to statically link against your 
plugin, if you respect the following additional rules:

RULE 1: Your makefiles must include rules that additionally allow building of
        a conveniance library. Normally your Makefile.am looks like this:

          -------------------------------------------------X8
          plugindir=@PLUGIN_PATH@/media
          plugin_LTLIBRARIES=ddvcard.la
          ddvcard_la_SOURCES=ddvcard.cpp mediumddv.cpp
          ddvcard_la_LDFLAGS=-module -version-info 0:0:0
          ddvcard_la_LIBADD=@libchipcard_libs@
          -------------------------------------------------X8

        This builds the plugin module.
        Now you should add the following to your Makefile.am:

          -------------------------------------------------X8
          noinst_LTLIBRARIES=libddvcard.la
          libddvcard_la_SOURCES=ddvcard.cpp mediumddv.cpp
          libddvcard_la_LIBADD=@libchipcard_libs@
          -------------------------------------------------X8
        
        As you can see these rules are the same as those for building the
        module, except that the options "-module" and "-version-info" are
        missing. These rules create a standard library against which OpenHBCI
        can be linked.

RULE 2: The main folder of your package should contain a file named
        "LIBRARY". This should contain the relative path and name of the
        library for statical linking (e.g. "src/libddvcard.la").
        If this file is missing then the name of the folder containing the
        plugin plus ".la" is used.
        
RULE 3: The main folder of your package should contain a file named
        "PLUGINNAME" which holds the name of the plugin in lower cased 
        (e.g. "ddvcard").
        If this file is missing then the name of the folder containing the
        plugin is used.


Examples
========
Please have a look at the plugin "openhbci-ddvcard". 
You can get it
- via CVS:
  "cvs -d:anonymous@cvs.openhbci.sf.net:/cvsroot/openhbci login"
  <Leave Password empty>
  "cvs -d:anonymous@cvs.openhbci.sf.net:/cvsroot/openhbci co plugins"
  <THIS DOWNLOADS THE PLUGINS>
- later from the OpenHBCI site (http://www.openhbci.de)



Generated on Mon Jun 23 13:41:08 2003 for openhbci by doxygen1.2.17