mirror of https://github.com/sipwise/kamailio.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
919 lines
33 KiB
919 lines
33 KiB
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
|
[ <!ENTITY % local.common.attrib
|
|
"xmlns:xi CDATA #FIXED 'http://www.w3.org/2001/XInclude'">
|
|
<!ENTITY % docentities SYSTEM "../../docbook/entities.xml">
|
|
%docentities;
|
|
|
|
]>
|
|
<!-- Include general documentation entities -->
|
|
|
|
<section id="rpc.main" xmlns:xi="http://www.w3.org/2001/XInclude">
|
|
<!--
|
|
<sectioninfo>
|
|
<releaseinfo role="cvs">$Revision$</releaseinfo>
|
|
<pubdate role="cvs">$Date$</pubdate>
|
|
</sectioninfo>
|
|
-->
|
|
|
|
<title>
|
|
The Kamailio RPC Control Interface
|
|
</title>
|
|
|
|
<section id="rpc.overview">
|
|
<title>Overview of Operation</title>
|
|
<para>
|
|
The RPC (Remote Procedure Call) interface is an interface for
|
|
communicating with external applications. Using it an external
|
|
application can call a function or procedure that will be executed
|
|
inside Kamailio. Function parameters are supported as well as returning
|
|
multiple values as results.
|
|
</para>
|
|
<para>
|
|
By itself RPC consists of two APIs, one for defining RPC functions
|
|
in a transport independent way (called the rpc module api) and one
|
|
for implementing RPC transports.
|
|
</para>
|
|
<para>
|
|
The RPC transports are implemented by writting a RPC
|
|
transport module. The most used transport modules are
|
|
<ulink url='http://www.kamailio.org/docs/modules/devel/modules/ctl/ctl.html'>
|
|
<emphasis>ctl</emphasis>
|
|
</ulink>,
|
|
<ulink url='http://www.kamailio.org/docs/modules/devel/modules/xmlrpc/xmlrpc.html'>
|
|
<emphasis>xmlrpc</emphasis>
|
|
</ulink>
|
|
and
|
|
<ulink url='http://www.kamailio.org/docs/modules/devel/modules/jsonrpc-s/jsonrpc-s.html'>
|
|
<emphasis>jsonrpc-s</emphasis>
|
|
</ulink>.
|
|
</para>
|
|
<para>
|
|
ctl implements a proprietary fast and space efficient
|
|
RPC encoding over different protocols (unix sockets, UDP, TCP, fifo).
|
|
</para>
|
|
<para>
|
|
xmlrpc uses the de-facto XML-RPC standard encoding
|
|
(over HTTP TCP or TLS).
|
|
</para>
|
|
<para>
|
|
jsonrpc-s uses the de-facto JSON-RPC standard encoding
|
|
(over HTTP TCP or TLS).
|
|
</para>
|
|
<para>
|
|
For more information about the existing transport modules, please
|
|
refer to their documentation.
|
|
</para>
|
|
<para>
|
|
When writing a RPC procedure or function, one needs only use the
|
|
RPC API and it will work automatically with all the transports and
|
|
encodings. One needs only to load the desired RPC transport module
|
|
(e.g. xmlrpc).
|
|
</para>
|
|
<para>
|
|
The RPC interface (or API) was created in such a way that would allow
|
|
supporting XML-RPC (because XML-RPC is a de-facto standard), while in
|
|
the same time being very easy to use.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="rpc.module_api">
|
|
<title>Module API</title>
|
|
<para>
|
|
Each module can export RPC functions just like it can export
|
|
parameters and functions to be called from the script. Whenever &kamailio;
|
|
receives an RPC request, it will search through the list of
|
|
exported RPC functions and the function with matching name will be
|
|
executed. A couple of essential RPC functions are also embedded into
|
|
the SIP server core.
|
|
</para>
|
|
<para>
|
|
This section gives a detailed overview of the whole RPC API. <xref
|
|
linkend="rpc.rpc_functions"/> describes the prototype and
|
|
conventions used in RPC functions. <xref linkend="rpc.data_types"/>
|
|
gives a detailed overview of available data types that can be used
|
|
in function parameters and return value. <xref
|
|
linkend="rpc.getting_parameters"/> describes functions of the RPC
|
|
API that can be used to retrieve parameters of the function, and
|
|
finally <xref linkend="rpc.creating_result"/> describes functions of
|
|
the API that can be used to build the result value that will be
|
|
sent in the reply to the caller.
|
|
</para>
|
|
<para>
|
|
The whole RPC API is described in header file
|
|
<filename>kamailio/rpc.h</filename>. This file defines the set
|
|
of functions that must be implemented by RPC transport modules, as
|
|
described in <xref linkend="rpc.new_transport"/>, prototypes of RPC
|
|
functions and structures used for the communication between RPC
|
|
transport modules and ordinary modules exporting RPC functions.
|
|
</para>
|
|
<section id="rpc.rpc_functions">
|
|
<title>RPC Functions</title>
|
|
<para>
|
|
RPC functions are standard C functions with the following
|
|
prototype:
|
|
<programlisting>
|
|
typedef void (*rpc_function_t)(rpc_t* rpc, void* ctx);
|
|
</programlisting>
|
|
RPC functions take two parameters, first parameter is a pointer
|
|
to rpc_t structure and the context. The rpc_t structure
|
|
contains references to all API functions available to the RPC
|
|
function as well as all data necessary to create the
|
|
response. RPC functions do not return any value, instead the
|
|
return value is created using functions from the context. The
|
|
motivation for this decision is the fact that RPC functions
|
|
should always return a response and even the API functions
|
|
called from RPC functions should have the possibility to
|
|
indicate an error (and should not rely on RPC functions doing so).
|
|
</para>
|
|
<para>
|
|
If no reply is sent explicitely, the RPC transport module will
|
|
automatically send a "success" reply (e.g. 200 OK for XML-RPC)
|
|
when the RPC function finishes.
|
|
If no values are added to the response, the reponse will be an
|
|
empty "success" reply (e.g. a 200 OK with empty body for
|
|
XML-RPC).
|
|
RPC API functions will automatically send an error reply upon a
|
|
failure.
|
|
</para>
|
|
<para>
|
|
Each RPC function has associated an array of documentation
|
|
strings. The purpose of the documentation strings is to give a
|
|
short overview of the function, accepted parameters, and format
|
|
of the reply. By convention the name of the documentation string
|
|
array is same as the name of the function with "_doc" suffix.
|
|
</para>
|
|
<para>
|
|
Each module containing RPC functions has to export all the
|
|
RPC functions to the &kamailio; core in order to make them visible to the RPC
|
|
transport modules.
|
|
The export process involves a <emphasis>rpc_export_t</emphasis>
|
|
structure (either by itself or in an array):
|
|
<programlisting>
|
|
<emphasis>
|
|
typedef struct rpc_export {
|
|
const char* name; /* Name of the RPC function (null terminated) */
|
|
rpc_function_t function; /* Pointer to the function */
|
|
const char** doc_str; /* Documentation strings, method signature and description */
|
|
unsigned int flags; /* Various flags, reserved for future use */
|
|
} rpc_export_t;
|
|
</emphasis>
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
The <varname>flags</varname> attribute of the
|
|
<varname>rpc_export</varname> structure is reserved for future
|
|
use and is currently unused.
|
|
</para>
|
|
<para>
|
|
There are several ways of exporting the RPC functions to the &kamailio; core:
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
register a null terminated array of rpc_export_t structures
|
|
using the <function>rpc_register_array()</function> function
|
|
(defined in rpc_lookup.h), from the module init function
|
|
(mod_init()). This is the <emphasis>recommended</emphasis>
|
|
method for all the new modules.
|
|
<example><title>usrloc RPC Exports Declaration</title>
|
|
<para>
|
|
The <varname>rpc_export_t</varname> array for the modules_s/usrloc
|
|
module looks like:
|
|
</para>
|
|
<programlisting>
|
|
<emphasis>
|
|
rpc_export_t ul_rpc[] = {
|
|
{"usrloc.statistics", rpc_stats, rpc_stats_doc, 0},
|
|
{"usrloc.delete_aor", rpc_delete_aor, rpc_delete_aor_doc, 0},
|
|
{"usrloc.delete_contact", rpc_delete_contact, rpc_delete_contact_doc, 0},
|
|
{"usrloc.dump", rpc_dump, rpc_dump_doc, 0},
|
|
{"usrloc.flush", rpc_flush, rpc_flush_doc, 0},
|
|
{"usrloc.add_contact", rpc_add_contact, rpc_add_contact_doc, 0},
|
|
{"usrloc.show_contacts", rpc_show_contacts, rpc_show_contacts_doc, 0},
|
|
{0, 0, 0, 0}
|
|
};
|
|
</emphasis>
|
|
</programlisting>
|
|
<para>
|
|
To register it from the module init function one would use
|
|
something similar to:
|
|
</para>
|
|
<programlisting>
|
|
if (rpc_register_array(ul_rpc) != 0) {
|
|
ERR("failed to register RPC commands\n");
|
|
return -1;
|
|
}
|
|
</programlisting>
|
|
</example>
|
|
</para></listitem>
|
|
<listitem><para>
|
|
register RPCs one by one using the
|
|
<function>rpc_register_function()</function>
|
|
(defined in rpc_lookup.h), from the module init function.
|
|
</para></listitem>
|
|
<listitem><para>
|
|
register a null terminated array of rpc_export_t structures
|
|
using the &kamailio; module interface SER_MOD_INTERFACE
|
|
For this purpose, the
|
|
<varname>module_exports</varname> structure of the &kamailio; module API
|
|
contains a new attribute called <varname>rpc_methods</varname>:
|
|
<programlisting>
|
|
struct module_exports {
|
|
char* name; /* null terminated module name */
|
|
cmd_export_t* cmds; /* null terminated array of the exported commands */
|
|
<emphasis>rpc_export_t* rpc_methods;</emphasis> /* null terminated array of exported rpc methods */
|
|
param_export_t* params; /* null terminated array of the exported module parameters */
|
|
|
|
init_function init_f; /* Initialization function */
|
|
response_function response_f; /* function used for responses */
|
|
destroy_function destroy_f; /* function called upon shutdown */
|
|
onbreak_function onbreak_f;
|
|
child_init_function init_child_f; /* function called by all processes after the fork */
|
|
};
|
|
</programlisting>
|
|
<varname>rpc_methods</varname> is a pointer to an array of
|
|
rpc_export_t structures. The last element of the array is a
|
|
bumper containing zeroes in all the attributes of the
|
|
structure. The following program listing shows the exported RPC
|
|
functions of the modules_s/usrloc module, using the rpc_export_t array
|
|
<emphasis>ul_rpc</emphasis> defined above, in the
|
|
rpc_register_array() example:
|
|
<example><title>usrloc Module Exports Declaration</title>
|
|
<programlisting>
|
|
struct module_exports exports = {
|
|
"usrloc",
|
|
cmds, /* Exported functions */
|
|
<emphasis>ul_rpc</emphasis>, /* RPC methods */
|
|
params, /* Export parameters */
|
|
mod_init, /* Module initialization function */
|
|
0, /* Response function */
|
|
destroy, /* Destroy function */
|
|
0, /* OnCancel function */
|
|
child_init /* Child initialization function */ };
|
|
|
|
</programlisting>
|
|
</example>
|
|
<note><para>
|
|
This mode works only with modules using the SER flavour module
|
|
interface. It does not work for &kamailio; modules and it
|
|
will probably not work for future sip-router modules. It is
|
|
safer and recommended to use instead the
|
|
<function>rpc_register_array()</function> function.
|
|
</para></note>
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
<para>
|
|
By convention the name of every exported function consists of
|
|
two parts delimited by a dot. The first part is the name of the
|
|
module or &kamailio; subsystem this function belongs to. The second
|
|
part is the name of the function.
|
|
</para>
|
|
</section>
|
|
|
|
<section id="rpc.data_types">
|
|
<title>Data Types</title>
|
|
<para>
|
|
The RPC API defines several basic and one compound data type
|
|
that can be used in communication with the caller of RPC
|
|
functions. The RPC API uses formating strings to describe data
|
|
types. Each data type is described by exactly one character in
|
|
the formating string. For example, if an RPC function calls
|
|
function <function>add</function> of the RPC API and it passes
|
|
two parameters to it, the first one of type string and the
|
|
second one of type integer, the function parameters will look
|
|
like:
|
|
<programlisting>
|
|
add("sd", string_param, int_param);
|
|
</programlisting>
|
|
Character "s" in the formating string tells to the function
|
|
that the 2nd parameter should be interpreted as string,
|
|
character "d" in the formating string tells to the function
|
|
that the 3rd parameter should be interpreted as signed integer.
|
|
</para>
|
|
<formalpara>
|
|
<title>Integer</title>
|
|
<para>
|
|
Integer type represents a signed 32-bit
|
|
integer. Corresponding character in the formating string is
|
|
"d". This parameter can be stored in C-style variable with
|
|
type <varname>int</varname>.
|
|
</para>
|
|
</formalpara>
|
|
<formalpara>
|
|
<title>Float</title>
|
|
<para>
|
|
Float type represents a signed floating point
|
|
number. Corresponding character in the formating string is
|
|
"f". Data of this type can be stored in C-style variables
|
|
of type <varname>double</varname>.
|
|
</para>
|
|
</formalpara>
|
|
<formalpara>
|
|
<title>String</title>
|
|
<para>
|
|
String type represents a string of characters. The string
|
|
may contain zeroes. This data type is represented by two
|
|
characters in the formatting string, either "s" or "S". "s"
|
|
indicates to the conversion function that the result should
|
|
be stored in a variable of type <varname>char*</varname>
|
|
and it should be zero terminated. "S" indicates to the
|
|
conversion function that the result will be stored in
|
|
a variable of type <varname>str</varname> which contains
|
|
both the pointer to the beginning of the string and its
|
|
length.
|
|
</para>
|
|
</formalpara>
|
|
<formalpara>
|
|
<title>Structure</title>
|
|
<para>
|
|
Structure is the only compound data type currently defined
|
|
in the API. A structure is a collection of attributes. Each
|
|
attribute is identified using name (string) and each
|
|
attribute can be one of the basic data types, that
|
|
is integer, float, or string. Nesting of structures is not
|
|
allowed (in other words, structure attributes cannot be of
|
|
type struct again). Corresponding character in the
|
|
formatting string is "{".
|
|
</para>
|
|
</formalpara>
|
|
<formalpara>
|
|
<title>Optional parameters</title>
|
|
<para>
|
|
Optional parameters can be used, but only in the
|
|
<function>scan</function> function. For optional parameters the
|
|
<function>scan</function> function will not automatically generate
|
|
a rpc fault if the input ends. Note that in this case the
|
|
<function>scan</function> will still return a negative value
|
|
(minus the number of parameters successfully read).
|
|
Optional parameters can be marked in the format string by
|
|
preceding the first optional parameter type with a "*".
|
|
All the parameters following a "*" are considered to be optional.
|
|
For example for the format string "ds*dds", the last 3 parameters
|
|
(2 ints and a string) are optional.
|
|
</para>
|
|
</formalpara>
|
|
<table>
|
|
<title>Data Type Overview</title>
|
|
<tgroup cols="3">
|
|
<tbody>
|
|
<row rowsep="1">
|
|
<entry>Name</entry>
|
|
<entry>Formating String Char</entry>
|
|
<entry>C-Style Variable</entry>
|
|
</row>
|
|
<row>
|
|
<entry>Integer</entry>
|
|
<entry>d</entry>
|
|
<entry>int</entry>
|
|
</row>
|
|
<row>
|
|
<entry>Float</entry>
|
|
<entry>f</entry>
|
|
<entry>double</entry>
|
|
</row>
|
|
<row>
|
|
<entry>String</entry>
|
|
<entry>s</entry>
|
|
<entry>char*</entry>
|
|
</row>
|
|
<row>
|
|
<entry>String</entry>
|
|
<entry>S</entry>
|
|
<entry>str*</entry>
|
|
</row>
|
|
<row>
|
|
<entry>Optional modifier</entry>
|
|
<entry>*</entry>
|
|
<entry>marks all further parameters as optional</entry>
|
|
</row>
|
|
<row>
|
|
<entry>Autoconvert modifier</entry>
|
|
<entry>.</entry>
|
|
<entry>requires auto-conversion for the next parameter</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</section>
|
|
|
|
<section id="rpc.getting_parameters">
|
|
<title>Getting Parameters</title>
|
|
<para>
|
|
Each RPC function call can contain parameters. Parameters have
|
|
no name, their meaning is determined by their position in the
|
|
parameter set.
|
|
<note>
|
|
<para>
|
|
You can pass all parameters to a function within a
|
|
structure if you want to make them position
|
|
independent. Then each parameter can be retrieved by
|
|
its name regardless of its position.
|
|
</para>
|
|
</note>
|
|
There are two functions in the RPC API that can be used to
|
|
obtain function call parameters: <function>scan</function> and
|
|
<function>struct_scan</function>.
|
|
</para>
|
|
<section id="rpc.scan">
|
|
<title><function>scan</function></title>
|
|
<para>
|
|
Function <function>scan</function> can be used to retrieve
|
|
parameters from the parameter set. The function accepts
|
|
variable number of parameters. The first parameter is the
|
|
formatting string that determines the type of the
|
|
parameters to be retrieved. Each parameter is represented by
|
|
exactly one parameter type character in the string.
|
|
The variable part of parameters must contain as many pointers to C
|
|
variables as there are formatting non-modifiers characters in the
|
|
formatting string.
|
|
<warning>
|
|
<para>
|
|
The function will crash if you fail to provide
|
|
enough parameters.
|
|
</para>
|
|
</warning>
|
|
</para>
|
|
<para>
|
|
Besides characters representing parameter types, the formatting
|
|
string can contain two special modifiers: "*" and ".". The
|
|
modifiers do not have a correspondent in the variable part of the
|
|
parameters.
|
|
</para>
|
|
<para>
|
|
The meaning of "*" modifier is that any further parameters
|
|
(defined by other type characters in the formatting string) are
|
|
optional (they can be missing in the input and no rpc fault will
|
|
automatically be generated).
|
|
</para>
|
|
<para>
|
|
The '.' modifiers turns on type autoconversion for the next
|
|
parameter. This means that if the type of the next parameter
|
|
differs from the type specified in the formatting string, the
|
|
parameter will be automatically converted to the formatting string
|
|
type (if possible) and if the automatic conversion succeeds, no
|
|
fault will be generated.
|
|
</para>
|
|
<para>
|
|
The function returns the number of parameters read on success
|
|
(a number greater or equal 0) and - (minus) the number of
|
|
parameters read on error (for example for an error after
|
|
reading 2 parameters it will return -2).
|
|
When a failure occurs (incorrect parameter type or no more
|
|
parameters in the parameter set) the function will
|
|
return a negative number (- number of parameters read so far)
|
|
and it will also automatically change the reply that will be
|
|
sent to the caller to indicate that a failure has occurred on
|
|
the server (unless the "*" is used and the error is lack
|
|
of more parameters).
|
|
</para>
|
|
<para>
|
|
The prototype of the function is:
|
|
<programlisting>
|
|
int scan((void* ctx, char* fmt, ...)
|
|
</programlisting>
|
|
It is possible to either call the function once to scan all
|
|
the parameters:
|
|
<programlisting>
|
|
rpc->scan(ctx, "sdf", &string_val, &int_val, &double_val);
|
|
</programlisting>
|
|
Or you can call the same function several times and it will
|
|
continue where it left off previously:
|
|
<programlisting>
|
|
rpc->scan(ctx, "s", &string_val);
|
|
rpc->scan(ctx, "d", &int_val);
|
|
rpc->scan(ctx, "f", &double_val);
|
|
</programlisting>
|
|
</para>
|
|
<para>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title><function>struct_scan</function></title>
|
|
<para>
|
|
Function <function>struct_scan</function> can be used to
|
|
retrieve named attributes from a parameter of type
|
|
structure.
|
|
<note><para>
|
|
This function is obsolete and not implemented by all the
|
|
rpc transports (e.g.: ctl / binrpc). Consider using the normal
|
|
<function>scan</function> instead.
|
|
</para></note>
|
|
When retrieving a structure parameter from the
|
|
parameter set:
|
|
<programlisting>
|
|
rpc->scan(ctx, "{", &handle);
|
|
</programlisting>
|
|
The corresponding variable (named
|
|
<varname>handle</varname> in the example above) will contain
|
|
the index of the structure parameter within the parameter
|
|
set, but the index cannot be used to retrieve the contents
|
|
of the structure. To retrieve the contents of the structure
|
|
you can use function <function>struct_scan</function>. The
|
|
function gets the handle as the first parameter:
|
|
<programlisting>
|
|
rpc->struct_scan(handle, "sd", "str_attr", &str_val, "int_attr", &int_val);
|
|
</programlisting>
|
|
The second parameter is the formatting string followed by
|
|
pairs of parameters. First parameter in each pair is the
|
|
name of the attribute to retrieve (string) and the second
|
|
parameter in each pair is the pointer to the variable to
|
|
store the value of the parameter. The function returns the
|
|
number of parameters (name value pairs) read on
|
|
success and - number of parameters read so far on an error
|
|
(just like the <function>scan</function> function). The function
|
|
also indicates an error if a requested attribute is missing in
|
|
the structure.
|
|
</para>
|
|
</section>
|
|
|
|
<section><title>Retrieving Parameters Example</title>
|
|
<example>
|
|
<title>Retrieving Parameters</title>
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_delete_contact(rpc_t* rpc, void* ctx)
|
|
{
|
|
str aor, contact;
|
|
char* table;
|
|
void *handle;
|
|
int expires;
|
|
double q;
|
|
|
|
if (rpc->scan(ctx, "sS{", &table, &aor, &handle) < 0) {
|
|
/* Reply is set automatically by scan upon failure,
|
|
* no need to do anything here
|
|
*/
|
|
return;
|
|
}
|
|
|
|
if (rpc->struct_scan(handle, "Sdf", "Contact", &contact,
|
|
"Expires", &expires,
|
|
"Q", &q ) < 0) {
|
|
/* Reply is set automatically by struct_scan upon failure,
|
|
* no need to do anything here
|
|
*/
|
|
return;
|
|
}
|
|
|
|
/* Process retrieved parameters here */
|
|
}
|
|
|
|
/* variable number of parameters:
|
|
echo back all the parameters, string type required */
|
|
static void core_prints(rpc_t* rpc, void* c)
|
|
{
|
|
char* string = 0;
|
|
while((rpc->scan(c, "*s", &string)>0))
|
|
rpc->add(c, "s", string);
|
|
}
|
|
|
|
/* variable number of parameters and auto conversion:
|
|
echo back all the parameters, works with any type (everything is
|
|
internally converted to string, notice the '.' modifier) */
|
|
static void core_echo(rpc_t* rpc, void* c)
|
|
{
|
|
char* string = 0;
|
|
while((rpc->scan(c, "*.s", &string)>0))
|
|
rpc->add(c, "s", string);
|
|
}
|
|
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="rpc.creating_result">
|
|
<title>Building Reply</title>
|
|
<para>
|
|
The RPC API contains several functions that can be used to
|
|
modify and/or send a reply. The functions use formatting
|
|
strings and parameter lists just like functions described in
|
|
<xref linkend="rpc.getting_parameters"/>.
|
|
</para>
|
|
<para>
|
|
Each RPC function call must return a reply. The reply can be
|
|
either a failure reply or success reply. Failure replies
|
|
contain only the status code and reason phrase. Success
|
|
replies can have arbitrary amount of data attached to
|
|
them. Status codes 3xx, 4xx, 5xx, and 6xx indicate
|
|
failures. Status code 2xx indicates success.
|
|
</para>
|
|
<para>
|
|
The default reply is 200 OK with no data attached to it. This
|
|
is what will be returned by the RPC transport module if you do
|
|
not call any of the reply-related functions described in this
|
|
section.
|
|
<example>
|
|
<title>Sending default reply</title>
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_dummy(rpc_t* rpc, void *ctx)
|
|
{
|
|
/* 200 OK with no data will be returned */
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</para>
|
|
<section>
|
|
<title>fault</title>
|
|
<para>
|
|
You can use <function>fault</function> function to indicate
|
|
that an error has occurred on the server to the caller. The
|
|
function accepts two parameters. The first parameter is the
|
|
status code and the second parameter is the reason phrase.
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_my_function(rpc_t* rpc, void *ctx)
|
|
{
|
|
rpc->fault(ctx, 600, "Not Yet Implemented");
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
If your function first creates some result using
|
|
<function>add</function>, or <function>printf</function>
|
|
functions then all the data will be lost once you call
|
|
<function>fault</function> function. Failure replies must
|
|
not contain any data:
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_my_function(rpc_t* rpc, void *ctx)
|
|
{
|
|
rpc->add(ctx, "s", "result1");
|
|
rpc->add(ctx, "d", variable);
|
|
|
|
/* Reply created by previous functions will be
|
|
* deleted and a failure reply 600 Not Yet Implemented
|
|
* will be created instead
|
|
*/
|
|
rpc->fault(ctx, 600, "Not Yet Implemented");
|
|
|
|
/* You can also add data here, but that will have no
|
|
* effect
|
|
*/
|
|
rpc->add(ctx, "s", "result2");
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
Similarly you can also call <function>add</function> or
|
|
<function>printf</function> functions after calling
|
|
<function>fault</function>, in this case they will have no
|
|
effect:
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_my_function(rpc_t* rpc, void *ctx)
|
|
{
|
|
rpc->fault(ctx, 600, "Not Yet Implemented");
|
|
|
|
/* You can also add data here, but that will have no
|
|
* effect and only 600 Not Yet Implemented will be returned
|
|
*/
|
|
rpc->add(ctx, "s", "result2");
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>send</title>
|
|
<para>
|
|
RPC functions can use function <function>send</function> to
|
|
explicitly send the reply. Each RPC function call generates
|
|
exactly one reply. No reply will be sent after the function
|
|
finishes if it already sent the reply using
|
|
<function>send</function> function explicitly. This
|
|
function is especially useful if the RPC function needs to
|
|
perform some (potentially destructive) actions after the
|
|
reply has been sent.
|
|
</para>
|
|
<example>
|
|
<title>Kill the server</title>
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void core_kill(rpc_t* rpc, void *ctx)
|
|
{
|
|
int sig_no;
|
|
|
|
if (rpc->scan(ctx, "d", &sig_no) < 0) return;
|
|
rpc->send(ctx, ); /* First send a reply */
|
|
kill(0, sig_no); /* Then kill the server */
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
|
|
</section>
|
|
<section>
|
|
<title>add</title>
|
|
<para>
|
|
Function <function>add</function> can be used to add
|
|
arbitrary data to the result set. Its parameters and use
|
|
are analogical to <function>scan</function> function
|
|
described in <xref linkend="rpc.scan"/>. The first
|
|
parameter of the function is the formatting string that
|
|
determines the types of additional parameters:
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_func(rpc_t* rpc, void *ctx)
|
|
{
|
|
str str_result;
|
|
int int_result;
|
|
void *handle;
|
|
double float_result;
|
|
|
|
if (rpc->add(ctx, "Sdf{", &str_result, int_result, float_result, &handle) < 0) return;
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
Naturally you can call this function several times, adding
|
|
only one piece of data at a time. The function returns 0 on
|
|
success and -1 on an error. In case of an error the reply
|
|
is set automatically with corresponding error code and
|
|
reason phrase.
|
|
</para>
|
|
<para>
|
|
The last character in the formatting string of the function
|
|
above indicates that the last data to be added will be a
|
|
structure. This deserves some clarification. In this case,
|
|
the function will create an empty structure and the handle
|
|
to the newly created structure will be stored in
|
|
<varname>handle</varname> variable (hence the last
|
|
parameter is pointer to an integer). In this particular
|
|
example parameters <varname>str_result</varname>,
|
|
<varname>int_result</varname>, and
|
|
<varname>float_result</varname> will be used for reading
|
|
while parameter <varname>handle</varname> will be used for
|
|
writing by the function.
|
|
</para>
|
|
<para>
|
|
You can set the attributes of the newly created structure
|
|
using <function>struct_add</function> function described in
|
|
<xref linkend="rpc.struct_add"/>.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>rpl_printf</title>
|
|
<para>
|
|
<varname>rpl_printf</varname> is a convenience function. The
|
|
function adds data of type string to the result set. The
|
|
first parameter of the function is again a formatting
|
|
string, but this time it is standard
|
|
<function>printf</function>-like formatting string:
|
|
<programlisting>
|
|
<![CDATA[
|
|
if (rpc->rpl_printf(ctx, "Unable to delete %d entries from table %s", num_entries, table_name) < 0) return;
|
|
]]>
|
|
</programlisting>
|
|
The return value of the function is the same as of
|
|
<function>add</function> function.
|
|
</para>
|
|
</section>
|
|
<section id="rpc.struct_add">
|
|
<title>struct_add</title>
|
|
<para>
|
|
Function <function>struct_add</function> can be used to add
|
|
attributes to a structure (created previously by
|
|
<function>add</function> function). The first parameter of
|
|
the function is handle obtained through
|
|
<function>add</function> function, the second parameters is
|
|
formatting string that determines the types of attributes
|
|
to be added. There must be two parameters per each
|
|
character in the formatting string, the first one is the
|
|
name of the attribute, the second parameter is the value
|
|
of the attribute. If a parameter with such a name already
|
|
exist in the structure then it will be overwritten with the
|
|
new value.
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_func(rpc_t* rpc, void *ctx)
|
|
{
|
|
void *handle;
|
|
|
|
/* Create empty structure and obtain its handle */
|
|
if (rpc->add(ctx, "{", &handle) < 0) return;
|
|
/* Fill-in the structure */
|
|
if (rpc->struct_add(handle, "sd", "attr1", str_val,
|
|
"attr2", int_val ) < 0)
|
|
return;
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
The function returns -1 on an error (and sets the status
|
|
code and reason phrase of the reply accordingly) and 0 on success.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Real World Example</title>
|
|
<para>
|
|
The following example illustrates the use of most of the
|
|
functions from the API together:
|
|
</para>
|
|
<example>
|
|
<title>Real World Example RPC Function</title>
|
|
<programlisting>
|
|
<![CDATA[
|
|
static void rpc_register(rpc_t* rpc, void *ctx)
|
|
{
|
|
char* domain;
|
|
str aor;
|
|
contact_t contact, new_contact;
|
|
void *handle;
|
|
|
|
/* Extract the domain, address of record from the request */
|
|
if (rpc->scan(ctx, "sS{", &domain, &aor, &handle) < 0) return;
|
|
/* Extract the structure describing the contact to be processed */
|
|
if (rpc->struct_scan(handle, "Sdf", "Contact", &contact.c,
|
|
"Expires", &contact.expires,
|
|
"Q", &contact.q ) < 0)
|
|
return;
|
|
|
|
/* Process the contact, new_contact will contain updated value after processing */
|
|
if (process_contact(domain, &aor, &new_contact, &contact) < 0) {
|
|
/* Processing failed, indicate the failure to the caller */
|
|
rpc->fault(ctx, 500, "Error While Processing Contact");
|
|
return;
|
|
}
|
|
|
|
/* Return the domain and the address of record */
|
|
rpc->add(ctx, "sS{", &domain, &aor, &handle) < 0) return;
|
|
/* And also add the new values for contact, q, and expires parameters */
|
|
rpc->struct_add(handle, "Sdf", "Contact", &new_contact.c,
|
|
"Expires", &new_contact.expires,
|
|
"Q", &new_contact.q );
|
|
}
|
|
]]>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="rpc.client_examples">
|
|
<title>Client Examples</title>
|
|
<para>
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>sercmd</emphasis> (C application that uses the
|
|
<emphasis>binrpc</emphasis> interface implemented by the
|
|
<emphasis>ctl</emphasis> module).
|
|
</para></listitem>
|
|
<listitem><para>
|
|
<emphasis>ser_ctl</emphasis> (python application that uses the
|
|
<emphasis>XML-RPC</emphasis> interface implemented by the
|
|
<emphasis>xmlrpc</emphasis>
|
|
module).
|
|
</para></listitem>
|
|
<listitem><para>
|
|
<emphasis>serweb</emphasis> (php application that can use
|
|
the <emphasis>XML-RPC</emphasis> interface to call ser
|
|
functions).
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="rpc.new_transport">
|
|
<title>Implementing New Transports</title>
|
|
<remark>
|
|
To be done.
|
|
</remark>
|
|
<!-- TODO:
|
|
- create a new module
|
|
- take a look at sip_router/rpc.h
|
|
- implement all functions in that header field
|
|
- no garbage collection in rpc functions, the module needs to keep
|
|
track of all allocated data
|
|
- return value default to true
|
|
- parameter type conflict is an error
|
|
- missing struct attribute is an error
|
|
- always send a reply, prepare replies so that you do not have to
|
|
allocate memory at runtime
|
|
- str strings do not have to be zero terminated
|
|
- no structure/array nesting allowed
|
|
- printf creates string attribute
|
|
-->
|
|
<para>
|
|
Examples:
|
|
<itemizedlist>
|
|
<listitem><para>
|
|
<emphasis>ctl</emphasis>
|
|
</para></listitem>
|
|
<listitem><para>
|
|
<emphasis>xmlrpc</emphasis>
|
|
</para></listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</section>
|
|
|
|
<section id="rpc.xmlrpc_examples">
|
|
<title>Examples using xmlrpc</title>
|
|
<para>See the <varname>xmlrpc</varname> module documentation:
|
|
<ulink url='http://www.kamailio.org/docs/modules/devel/modules/xmlrpc.html'>modules/xmlrpc/README</ulink>.
|
|
</para>
|
|
</section>
|
|
|
|
</section>
|