root/trunk/licq/doc/PLUGINS.HOWTO

Revision 4526, 3.6 kB (checked in by erijo, 2 years ago)

Removed svn:keywords from all files that don't need it. May make your
checkout a tiny bit faster :)

  • Property svn:eol-style set to native
Line 
1---------------------------------------
2Licq Plugins Howto v0.2
3Graham Roff
4---------------------------------------
5
6This document is not nearly complete and is only intended to give a
7bried introduction to the main ideas behind the licq plugin system.
8Careful perusal of the licq and qt-gui plugin source code is a good
9place to find out more.
10
111.0  Introduction (IPC and Initialization)
12
13Writing a plugin for licq is not too complicated.  There are two main
14ways for inter-system communication, signals and events. 
15
16Signals are asynchronous and indicate some general change or occurance
17which the plugin might be interested in being aware of.  Signals include
18when your status changes, when a new message arrives, and when you log
19on successfully.
20
21Events are synchronous to the extent that they are a response to
22something which the particular plugin started.  For example the plugin
23might call icqSendUrl() to send a url, and will receive a notification
24event in response indicating the success of failure of this call.
25
26The arrival of a signal or event is indicated by activity on a pipe,
27specific to each plugin.  Each character read from the pipe can be any
28of PLUGIN_SIGNAL, PLUGIN_EVENT, or PLUGIN_SHUTDOWN.  A signal or event
29is read from the daemon simply by calling PopPluginSignal() or
30PopPluginEvent().
31
32There are three main things each plugin must do:
33
341.  Each plugin must include plugin.h and implement the functions
35    prototyped within.  These functions are described inside this header
36    file.  The main ones are:
37    LP_Init(int, char **): This function is called to initialize the
38    plugin, and is passed any command line arguments applicable.  The
39    function should return whether or not it was successful in
40    initializing the plugin.
41    LP_Main(CICQDaemon *): This function is called within its own thread
42    and should actually run the plugin.  It can exit by calling
43    LP_Exit(int) or by returning an integer return code.
44
452.  Each plugin must register with the licq daemon it gets passed in
46    LP_Main().  This is done simply by calling CICQDaemon::Register().
47    This function returns the descriptor of the pipe to listen on for
48    notification of signals and events.  If a plugin exits without either
49    calling CICQDaemon::Shutdown() or receiving a shutdown signal then it
50    must call CICQDaemon::Unregister() to unregister itself.
51
523.  Each plugin must exit properly when it receives a PLUGIN_SHUTDOWN
53    character on the notification pipe.  This simply involves calling
54    LP_Exit() or returning from LP_Main().
55
56
572.0  Multi-threading Issues
58
59Licq is a fully multi-threaded program and as such there are some important
60issues to be dealt with when writing plugins.  First, any requests to get
61user information have been made thread safe (henceforth refered to as mt-safe)
62through a simple database type checkout system.  Given a uin, a pointer to
63the relevant user is obtained by calling gUserManager.FetchUser(<uin>, <lock type>)
64where the <lock type> is either LOCK_R or LOCK_W depending on whether one wants
65read or read/write access to the user (note that many threads may have a user
66locked for reading at the same time, but only one thread may have a user locked
67for writing, so avoid doing so if possible).
68The same idea applies to groups: gUserManager.FetchGroup(<group id>, <lock type>).
69
70Certain system calls should also be avoided or their mt-safe counterparts used.  These
71include:
72strerror (on some systems this call is mt-safe, use strerror_r to be sure)
73gethostbyname (use gethostbyname_r, see socket.cpp for an example)
74and any other call that uses an internal static buffer.
Note: See TracBrowser for help on using the browser.