123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965 |
- <?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 writing a RPC
- transport module. The most used transport modules are
- <ulink url='https://www.kamailio.org/docs/modules/devel/modules/ctl/ctl.html'>
- <emphasis>ctl</emphasis>
- </ulink>,
- <ulink url='https://www.kamailio.org/docs/modules/devel/modules/xmlrpc/xmlrpc.html'>
- <emphasis>xmlrpc</emphasis>
- </ulink>
- and
- <ulink url='https://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.
- <emphasis>It is now completely obselete.</emphasis>
- The correct way is 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>Unsigned Integer</entry>
- <entry>u</entry>
- <entry>int</entry>
- </row>
- <row>
- <entry>Boolean</entry>
- <entry>b</entry>
- <entry>int</entry>
- </row>
- <row>
- <entry>Long</entry>
- <entry>l</entry>
- <entry>long</entry>
- </row>
- <row>
- <entry>Unsigned Long</entry>
- <entry>j</entry>
- <entry>unsigned long</entry>
- </row>
- <row>
- <entry>Long Long</entry>
- <entry>L</entry>
- <entry>long long</entry>
- </row>
- <row>
- <entry>Unsigned Long Long</entry>
- <entry>J</entry>
- <entry>unsigned long long</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>time</entry>
- <entry>t</entry>
- <entry>int</entry>
- </row>
- <row>
- <entry>Struct</entry>
- <entry>{</entry>
- <entry>struct rpc_struct_l </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>
- <note>
- <para>
- The <emphasis>time</emphasis> parameter is of type <emphasis>int</emphasis>. Recent OS use 64-bit time_t (typedef long), so if you are using a 64-bit OS, you should use <emphasis>l</emphasis> or <emphasis>LL</emphasis> instead of <emphasis>t</emphasis> when trying to add/read a time_t value to avoid overflowing.
- </para>
- </note>
- </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>siremis</emphasis> (php application that can use
- the <emphasis>XML-RPC</emphasis> interface to call &kamailioname;
- 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='https://www.kamailio.org/docs/modules/devel/modules/xmlrpc.html'>modules/xmlrpc/README</ulink>.
- </para>
- </section>
- </section>
|