123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- <?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">
- <section id="select_module" xmlns:xi="http://www.w3.org/2001/XInclude">
- <sectioninfo>
- <revhistory>
- <revision>
- <revnumber>$Revision$</revnumber>
- <date>$Date$</date>
- </revision>
- </revhistory>
- </sectioninfo>
-
- <section><title>Extend select framework with module related functions</title>
- <para>
- If you want to extend functions which select framework can call with some
- dependent on module you have to follow next steps:
- <itemizedlist>
- <listitem><para>
- define working functions
- </para>
- </listitem>
- <listitem><para>
- create module's select parsing table
- </para>
- </listitem>
- <listitem><para>
- in module's mod_init call register_select_table
- </para>
- </listitem>
- </itemizedlist>
- </para>
- </section>
- <section>
- <title>Define your working functions</title>
- <para>
- Working functions are the piece of code, which is called as when SER needs
- get result of select function (defined as @name.foo[2].bar[5]). The working copy
- has following definition:
- </para>
- <para><emphasis>
- int <function>select_function_name</function>(str* res, struct select *s, struct sip_msg *msg)
- </emphasis>
- Pointer to the string result workspace <emphasis>res</emphasis>, don't allocate
- memory for the string, but use static buffer. There is no way to free the
- allocated memory.
- Pointer to the parsed select structure <emphasis>s</emphasis>. Holds all names,
- numbers divided by the dot and square bracket notation. Use that if any of the
- part used CONSUME_NEXT_STR or CONSUME_NEXT_INT to get the value.
- Pointer to the processed message structure <emphasis>msg</emphasis>.
- </para>
- <para>
- <emphasis>FIXUP CALL:</emphasis>
- If you set FIXUP_CALL flag for the final
- function, the fixup call will be done immediatelly after function resolution.
- Such call is indicated with res==NULL && msg==NULL. Such call can convert any of
- the select's parameter into internal data (can hold one pointer), if you do
- that, set param_type to SEL_PARAM_DATA.
- </para>
- <para>
- Result code of the function declares if the call was successful and if the result is
- valid string or empty string.
- </para>
- <itemizedlist>
- <listitem><para><emphasis>-1</emphasis> error</para></listitem>
- <listitem><para><emphasis>0</emphasis> success, res contains non-empty string</para></listitem>
- <listitem><para><emphasis>1</emphasis> success, result of select call is empty string (res can be left
- unchanged)</para></listitem>
- </itemizedlist>
- </section>
- <section>
- <title>Create module's select parsing table</title>
- <para>Define static table of select_row_t type and initialize it directly.
- </para>
- <para>The table is representation of tree (or oriented graph if you want), where
- first column represents current (up-to now) resolved function (starting with NULL),
- next two columns define if next parameter is integer or particullar string, next
- column is new resolved function which will be tested in next round and the last
- column is set of flags.
- </para>
- <programlisting><![CDATA[
- static select_row_t test_sel[] = {
- { NULL, SEL_PARAM_STR, STR_STATIC_INIT("test"), select_test, 0},
- { select_test, SEL_PARAM_STR, STR_STATIC_INIT("value"), select_test_val, 0},
- { select_test, SEL_PARAM_STR, STR_STATIC_INIT("echo"), select_test_echo, CONSUME_NEXT_STR},
- { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
- };
- ]]>
- </programlisting>
- <para>
- So in the previous example, the first line will accept syntax
- <emphasis>@test</emphasis> and set the resolved function to select_test. In the
- next round, all rows with the select_test in the first column will be used to
- match, so the next two lines
- are candidates to match depending on the next part of select syntax. If it
- matches <emphasis>@test.value</emphasis>, the function is resolved to
- select_test_val, if it matches <emphasis>@test.echo.anystring</emphasis>, it is
- resolved into select_test_echo. Flag <emphasis>CONSUME_NEXT_STR</emphasis> will
- accept any string at the 3rd position. As the <emphasis>OPTIONAL</emphasis> flag
- is not present, it won't accept just the <emphasis>@test.echo</emphasis> syntax.
- </para>
- <para>
- The table ends with the <emphasis>NULL</emphasis> in the 1st and 4th column,
- other columns are not checked (the notation in the example suits well).
- </para>
- <para>
- At the resolving time all function names must be already defined. For functions which are
- not leaves, you can use macro <emphasis>ABSTRACT_F(name)</emphasis> to define empty
- function, for working function you can use advance definition using
- <emphasis>SELECT_F(name)</emphasis> macro.
- </para>
- </section>
- <!--
- TODO:
- <section>
- <title>Available flag options and their meaning</title>
- <para>
- <emphasis></emphasis>
- </para>
- </section>
- -->
- <section>
- <title>Register the created table</title>
- <para>
- In the module initialization function call <emphasis>register_select_table(table)</emphasis>
- where table is the parsing tree/table you have defined in previous step.
- This call ensures, that the table will become part of the parsing logic for
- all select framework calls defined in the script file or called by another
- module's parse_select.
- </para>
- <para>
- <emphasis>NOTE:</emphasis> The tables are inserted into the beginning of the
- list, so the core's table (and thus parseable names and definitions) can be
- overrided by module's function, if it is defined with the same name. To
- avoid such situation, the best practice is to start module's select with the
- module's name. E.g in our example code both select functions start
- with @test...
- </para>
- </section>
- <section>
- <title>Example - module defining select extension</title>
- <para>Example module <emphasis>test</emphasis>, which defines two select function.
- <itemizedlist>
- <listitem><para>
- <emphasis>@test.value</emphasis> - returns value passed as modules parameter
- "value"
- </para></listitem>
- <listitem><para>
- <emphasis>@test.echo.xxx</emphasis> - returns xxx regardless of what you put
- as xxx (shows CONSUME_NEXT_STR option)
- </para></listitem>
- </itemizedlist>
- </para>
- <example id="test.c">
- <title>test.c</title>
- <programlisting><![CDATA[
- #include <string.h>
- #include "../../sr_module.h"
- #include "../../str.h"
- #include "../../dprint.h"
- #include "../../select.h"
- MODULE_VERSION
- static cmd_export_t cmds[] = {
- {0, 0, 0, 0, 0}
- };
- static char* value=NULL;
- static param_export_t params[] = {
- {"value", STR_PARAM, &value},
- {0, 0, 0}
- };
- int select_test_val(str* res, struct select* s, struct sip_msg* msg) {
- DBG("SELECT_TEST_VAL called test_val=%s\n", value);
- res->s=value;
- res->len=strlen(value);
- return 0;
- }
- int select_test_echo(str* res, struct select* s, struct sip_msg* msg) {
- DBG("SELECT_TEST_ECHO called\n");
- if (s->params[s->n-1].type==SEL_PARAM_STR) {
- *res=s->params[s->n-1].v.s;
- return 0;
- } else
- return -1;
- }
- ABSTRACT_F(select_test)
-
- static select_row_t test_sel[] = {
- { NULL, SEL_PARAM_STR, STR_STATIC_INIT("test"), select_test, 0},
- { select_test, SEL_PARAM_STR, STR_STATIC_INIT("value"), select_test_val, 0},
- { select_test, SEL_PARAM_STR, STR_STATIC_INIT("echo"), select_test_echo, CONSUME_NEXT_STR},
- { NULL, SEL_PARAM_INT, STR_NULL, NULL, 0}
- };
-
- static int init(void) {
- register_select_table(test_sel);
- return 0;
- };
- struct module_exports exports = {
- "test",
- cmds, /* Exported commands */
- 0, /* RPC methods */
- params, /* Exported parameters */
- init, /* module initialization function */
- 0, /* response function*/
- 0, /* destroy function */
- 0, /* oncancel function */
- 0 /* per-child init function */
- };
- ]]>
- </programlisting>
- </example>
- </section>
- </section>
|