<!-- $Id: modiface.sgml,v 1.3 2003/05/06 14:11:39 janakj Exp $ -->
<!DOCTYPE Book PUBLIC "-//OASIS//DTD DocBook V4.2//EN" [
<!ENTITY ser "SIP Express Router">
<!ENTITY moddir "/usr/lib/ser/modules">
]>

<book>
    <chapter>
	<title>Module Interface</title>
	<abstract>
	    <para>
		&ser; features modular architecture which allows us to split &ser;'s functionality
		across several modules. This approach gives us greater flexibility, only required
		set of functions can be loaded upon startup which minimizes the server's memory
		footprint. Modules can be also provided by 3rd party developers and distributed
		separately from the main server. Most of the functionality that &ser; provides is
		available through modules, the core itself contains only minimum set of functions
		that is essential for proper server's behaviour or that is needed by all modules.
	    </para>
	    <para>
		This chapter provides detailed information on module interface of &ser;, which is
		used to pass information on available functions and parameters from the modules to
		the core.
	    </para>
	</abstract>
	<section>
	    <title>Shared Objects</title>
	    <abstract>
		<para>
		    First it would be good to know how &ser; loads and uses modules before we
		    describe the module interface in detail. This section gives a brief overview of
		    &ser;'s module subsystem.
		</para>
	    </abstract>
	    <para>
		&ser; modules are compiled as <quote>shared objects</quote>. A file containing a
		shared object has usually .so suffix. All modules (shared objects) will be stored in
		one directory after installation. For example <abbrev>tm</abbrev> module, which
		contains code essential for stateful processing, will be stored in file named
		<filename moreinfo="none">tm.so</filename>. By default these files are stored in
		<filename moreinfo="none">&moddir;</filename> directory.
	    </para>
	    <para>
		You can later load the modules using <command moreinfo="none">loadmodule</command>
		command in your configuration file. If you want to load previously mentioned
		<filename moreinfo="none">tm.so</filename> module, you can do it using <command
		moreinfo="none">loadmodule "&moddir;/tm.so"</command> in your configuration
		file. This command invokes dynamic linker provided by the operating system which
		opens <filename moreinfo="none">tm.so</filename> file, loads it into memory and
		resolves all symbol dependencies (a module might require symbols from the core, for
		example functions and variables).
	    </para>
	    <para>
		As the last step of the module loading the core tries to find variable named
		<varname>exports</varname>, which describes all functions and parameters provided by
		the module. These functions and parameters are later available to the server and can
		be used either in the configuration file or by other modules.
	    </para>
	</section>
	<section>
	    <title>Exporting Functions</title>
	    <abstract>
		<para>
		    Each module can provide zero or more functions, which can be used in the
		    configuration file or by other modules internally. This section gives a detailed
		    description of structure describing exported functions and passing this
		    information to the core through the module interface.
		</para>
	    </abstract>
	    <para>
		Each function exported by a module must be described by
		<structname>cmd_export_t</structname> structure. Structures describing all exported
		functions are arranged into an array and pointer to the array is then passed to the
		core. The last element of the array must contain 0 in all it's fields, this element
		serves as the mark telling the core that this is the very last element and it must
		stop scanning the array.
	    </para>
	    <para>
		Each exported function is described by the following structure:
	    </para>
	    <programlisting format="linespecific">
struct cmd_export_ {
	char* name;             /* null terminated command name */
	cmd_function function;  /* pointer to the corresponding function */
	int param_no;           /* number of parameters used by the function */
	fixup_function fixup;   /* pointer to the function called to "fix" the parameters */
	int flags;              /* Function flags */
};	   

typedef struct cmd_export_ cmd_export_t;
</programlisting>
	    <itemizedlist>
		<title>Meaning of the fileds:</title>
		<listitem>
		    <simpara><varname>char* name</varname><simpara> 
		    <simpara>
			This is the name under which the function will be visible to the
			core. Usually it is the same as the name of the corresponding function.
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>cmd_function function</varname></simpara> 
		    <para>cmd_function type is defined as follows: </para>
		    <programlisting format="linespecific">
typedef int (*cmd_function)(struct sip_msg*, char*, char*); 
</programlisting>
		    <simpara>
			The first parameter is a <acronym>SIP</acronym> message being processed, the
			other 2 parameters are given from the configuration file.
		    </simpara>
		    <note>
			<simpara>
			    From time to time you might need to export a function that has different
			    synopsis. This can happen if you export functions that are supposed to
			    be called by other modules only and must not be called from the
			    configuration script. In this case you will have to do type-casting
			    otherwise the compiler will complain and will not compile your module.
			</simpara>
			<simpara>
			    Simply put (cmd_function) just before the function name, for example
			    <function moreinfo="none">(cmd_function)my_function</function>.  Don't
			    use this unless you know what are you doing ! The server might crash if
			    you pass wrong parameters to the function later !
			</simpara>
		    </note>
		</listitem>
		<listitem>
		    <simpara><varname>int param_no</varname></simpara>
		    <simpara>
			Number of parameters of the function. It can be 0, 1 or 2. The function will
			be not visible from the configuration script if you use another value.
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>fixup_function fixup</varname></simpara>
		    <simpara>
			This is the function that will be used to <quote>fixup</quote> function
			parameters. Set this field to 0 if you don't need this.
		    </simpara>
		    <simpara>
			If you provide pointer to a fixup function in this field, the fixup function
			will be called for each occurence of the exported function in the
			configuration script.
		    </simpara>
		    <simpara>
			The fixup function can be used to perform some operation on the function
			parameters. For example, if one of the parameters is a regular expression,
			you can use the fixup to compile the regular expression. The fixup functions
			are called only once - upon the server startup and so the regular expression
			will be compiled before the server starts processing messages. When the
			server calls the exported function to process a <acronym>SIP</acronym>
			message, the function will be given the already compiled regular expression
			and doesn't have to compile it again. This is a significant performance
			improvement.
		    </simpara>
		    <simpara>
			Fixup functions can also be used to convert string to integer. As you have
			might noticed, the exported functions accept up to 2 parameters of type
			char*. Because of that it is not possible to pass integer parameters from
			the script files directly. If you want to pass an integer as a parameter,
			you must pass it as string (i.e. enclosed in quotes).
		    </simpara>
		    <simpara>
			Fixup function can be used to convert the string back to integer. Such a
			conversion should happend only once because the string parameter doesn't
			change when the server is running. Fixup is therefore ideal place for the
			conversion, it will be converted upon the server startup before the server
			starts processing <acronym>SIP</acronym> messages. After the conversion the
			function will get directly the converted value. See existing modules for
			example of such a fixup function.
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>int flags</varname></simpara>
		    <simpara>
			Usage of each function can be restricted. You may want to write a function
			that can be used by other modules but cannot be called from the script. If
			you write a function that is supposed to process <acronym>SIP</acronym>
			requests only, you may want to restrict it so it will be never called for
			<acronym>SIP</acronym> replies and vice versa. That's what is flags field
			for.
		    </simpara>
		    <simpara>
			This field is OR value of different flags. Currently only REQUEST_ROUTE and
			REPLY_ROUTE flags are defined and used by the core. If you use REQUEST_ROUTE
			flag, then the function can be called from the main route block. If you use
			REPLY_ROUTE flag, then the function can be called from reply route blocks
			(More on this in the SER User's Guide). If this field is set to 0, then the
			function can be called internally (i.e. from other modules) only. If you
			want to make your function callable anywhere in the script, you can use
			REQUEST_ROUTE | REPLY_ROUTE.
		    </simpara>
		</listitem>
	    </itemizedlist>
	</section>
	<section>
	    <title>Exporting Parameters</title>
	    <abstract>
		<simpara>
		    Each module can provide zero or more parameters, which can affect the module's
		    behaviour. This section gives a detailed description of structures describing
		    exported parameters and passing this information to the core through the module
		    interface.
		</simpara>
	    </abstract>
	    <simpara>
		Each parameter exported by a module must be described by
		<structname>param_export_t</structname> structure. Structures describing all
		exported parameters are arranged into an array and pointer to the array is then
		passed to the core. The last element of the array must contain 0 in all it's fields,
		this element serves as the mark telling the core that this is the very last element
		and it must stop scanning the array (This is same as in array of exported
		functions).
	    </simpara>
	    <simpara>
		Each exported parameter is described by the following structure:
	    </simpara>
	    <programlisting format="linespecific">
		
struct param_export_ {
	char* name;             /* null terminated param. name */
	modparam_t type;        /* param. type */
	void* param_pointer;    /* pointer to the param. memory location */
};

typedef struct param_export_ param_export_t;
</programlisting>
	    <itemizedlist>
		<title>Meaning of the fields:</title>
		<listitem>
		    <simpara><varname>char* name</varname></simpara>
		    <simpara>
			This is null-terminated name of the parametes as it will be used in the
			scripts. Usually this is the same as the name of the variable holding the
			value.
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>modparam_t type</varname></simpara>
		    <simpara>
			Type of the parameter. Currently only two types are defined. INT_PARAM for
			integer parameters (corresponding variable must be of type int) and
			STR_PARAM for string parameters (corresponding variable must be of type
			char*).
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>void* param_pointer</varname></simpara>
		    <simpara>
			Pointer to the corresponding variable (stored as void* pointer, make sure
			that the variable has appropriate type depending on the type of the
			parameter !).
		    </simpara>
		</listitem>
	    </itemizedlist>
	</section>
	<section>
	    <title>Module Initialization</title>
	    <simpara>
		If you need to initialize your module before the server starts processing
		<acronym>SIP</acronym> messages, you should provide initialization function. Each
		module can provide two initialization functions, main initialization function and
		child-specific initialization function.  Fields holding pointers to both
		initialization functions are in main export structure (will be described
		later). Simply pass 0 instead of function pointer if you don't need one or both
		initialization functions.
	    </simpara>
	    <simpara>
		The main initialization function will be called before any other function exported
		by the module. The function will be called only once, before the main process
		forks. This function is good for initialization that is common for all the children
		(processes). The function should return 0 if everything went OK and a negative error
		code otherwise. Server will abort if the function returns a negative value.
	    </simpara>
	    <simpara>
		Per-child initialization function will be called <emphasis>after</emphasis> the main
		process forks. The function will be called for each child separately. The function
		should perform initialization that is specific for each child. For example each
		child process might open it's own database connection to avoid locking of a single
		connection shared by many processes. Such connections can be opened in the per-child
		initialization function. The function accepts one parameter which is rank (integer)
		of child for which the function is being executed. This allows developers to
		distinguish different children and perform different initialization for each
		child. The meaning of return value is same as in the main initialization function.
	    </simpara>
	</section>
	<section>
	    <title>Module Clean-up</title>
	    <simpara>
		A module can also export a clean-up function that will be called by the main process
		when the server shuts down. The function accepts no parameters and return no value.
	    </simpara>
	</section>
	<section>
	    <title>Module Callbacks</title>
	    <para>
		TBD.
	    </para>
	</section>
	<section>
	    <title><structname>exports</structname> Structure - Assembling the Pieces Together</title>
	    <simpara>
		We have already described how a module can export functions and parameters, but we
		haven't yet described how to pass this information to the core. Each module must
		have variable named <varname>exports</varname> which is structure
		module_exports. The variable will be looked up by the core immediately after it
		loads the module. The structure contains pointers to both arrays (functions,
		parameters), pointers to both initialization functions, destroy function and the
		callbacks. So the structure contains everything the core will need.
	    </simpara>
	    <simpara>The structure looks like the follows:</simpara>
	    <programlisting format="linespecific">
struct module_exports{
    char* name;                     /* null terminated module name */
    cmd_export_t* cmds;             /* null terminated array of the exported commands */
    param_export_t* params;         /* null terminated array of the exported module parameters */
    init_function init_f;           /* Initilization function */
    response_function response_f;   /* function used for responses, returns yes or no; can be null */
    destroy_function destroy_f;     /* function called when the module should be "destroyed", e.g: on ser exit; can be null */
    onbreak_function onbreak_f;
    child_init_function init_child_f;  /* function called by all processes after the fork */
};
</programlisting>
	    <itemizedlist>
		<title>Field description:</title>
		<listitem>
		    <simpara><varname>char* name</varname></simpara>
		    <simpara>Null terminated name of the module</simpara>
		</listitem>
		<listitem>
		    <simpara><varname>cmd_exports* cmds</varname></simpara>
		    <simpara>
			Pointer to the array of exported functions
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>param_export_t* params</varname></simpara>
		    <simpara>
			Pointer to the array of exported parameters
		    </simpara>
		</listitem>
		<listitem>
		    <simpara><varname>init_function init_f</varname></simpara>
		    <simpara>Pointer to the module initialization function</simpara>
		</listitem>
		<listitem>
		    <simpara><varname>response_function response_f</varname></simpara>
		    <simpara>Pointer to function processing responses</simpara>
		</listitem>
		<listitem>
		    <simpara><varname>destroy_function destroy_f</varname></simpara>
		    <simpara>Pointer to the module clean-up function</simpara>
		</listitem>
		<listitem>
		    <simpara><varname>onbreak_function onbreak_f</varname></simpara>
		    <simpara>TBD</simpara>
		</listitem>
		<listitem>
		    <simpara><varname>child_init_function init_child_f</varname></simpara>
		    <simpara>Pointer to the per-child initialization function</simpara>
		</listitem>
	    </itemizedlist>
	</section>
	<section>
	    <title>Example - Simple Module Interface</title>
	    <para>
		Let's suppose that we are going to write a simple module. The module will export two functions - 
		<function moreinfo="none">foo_req</function> which will be processing <acronym>SIP</acronym> requests and 
		<function moreinfo="none">foo_int</function> which is an internal function that can be called by other modules only.
		Both functions will take 2 parameters.
	    </para>
	    <programlisting format="linespecific">
/* Prototypes */
int foo_req(struct sip_msg* msg, char* param1, char* param2);
int foo_res(struct sip_msg* msg, char* param1, char* param2);

static cmd_export cmds[] = {
    {"foo_req", foo_req, 2, 0, ROUTE_REQUEST},
    {"foo_int", foo_int, 2, 0, 0            },
    {0, 0, 0, 0}
};
</programlisting>
	    <para>
		The module will also have two parameters, foo_bar of type integer and bar_foo of type string.
	    </para>
	    <programlisting format="linespecific">
int foo_bar = 0;
char* bar_foo = "default value";

static param_export params[] = {
    {"foo_bar", INT_PARAM, &amp;foo_bar},
    {"bar_foo", STR_PARAM, bar_foo     },
    {0, 0, 0}
}; 
</programlisting>
	    <para>
		We will also create both initialization functions and a clean-up function:
	    </para>
	    <programlisting format="linespecific">
static int mod_init(void)
{
    printf("foo module initializing\n");
}

static int child_init(int rank)
{
    printf("child nr. %d initializing\n", rank);
    return 0;
}

static void destroy(void)
{
    printf("foo module cleaning up\n");
}
</programlisting>
	    <para>
		And finally we put everything into the exports structure:
	    </para>
	    <programlisting format="linespecific">
struct module_exports exports = {
    "foobar",   /* Module name */
    cmds,       /* Exported functions */
    params,     /* Exported parameters */
    mod_init,   /* Module initialization function */
    0,          /* Response function */
    destroy,    /* Clean-up function */
    0,          /* On Cancel function */
    child_init  /* Per-child init function */
};
</programlisting>
	    <simpara>And that's it.</simpara>
	</section>
    </chapter>
</book>
