📄 serdev.sgml
字号:
| ...</programlisting> <para> A config file can contain one or more "route" statements. "route" statement without number will be executed first and is called the main route statement. There can be additional route statements identified by number, these additional route statements can be called from the main route statement or another additional route statements. </para> <para> Each route statement consists of a set of actions. Actions in the route statement are executed step by step in the same order in which they appear in the config file. Actions in the route statement are delimited by semicolon. </para> <para> Each action consists of one and only one command (cmd in the grammar). There are many types of commands defined. We don't list all of them here because the list would be too long and all the commands are processed in the same way. Therefore we show only one example (forward) and interested readers might look in <filename moreinfo="none">cfg.y</filename> file for full list of available commands. </para> <para> Each rule in the grammar contains a section enclosed in curly braces. The section is the C code snippet that will be executed every time the parser recognizes that rule in the config file. </para> <para> For example, when the parser finds <function moreinfo="none">forward</function> command, <function moreinfo="none">mk_action</function> function (as specified in the grammar snippet above) will be called. The function creates a new structure with <structfield>type</structfield> field set to FORWARD_T representing the command. Pointer to the structure will be returned as the return value of the rule. </para> <para> The pointer propagates through <function moreinfo="none">action</function> rule to <function moreinfo="none">actions</function> rule. <function moreinfo="none">Actions</function> rule will create linked list of all commands. The linked list will be then inserted into <structfield>rlist</structfield> table. (Function <function moreinfo="none">push</function> in rule <function moreinfo="none">route_stm</function>). Each element of the table represents one <quote>route</quote> statement of the config file. </para> <para> Each route statement of the configuration file will be represented by a linked list of all actions in the statement. Pointers to all the lists will be stored in rlist array. Additional route statements are identified by number. The number also serves as index to the array. </para> <para> When the core is about to execute route statement with number n, it will look in the array at position n. If the element at position n is not null then there is a linked list of commands and the commands will be executed step by step. </para> <para> Reply-Route statement is compiled in the same way. Main differences are: <itemizedlist> <listitem> <para> Reply-Route statement is executed when a <acronym>SIP</acronym> <emphasis>REPLY</emphasis> comes (not ,<acronym>SIP</acronym> <emphasis>REQUEST</emphasis>). </para> </listitem> <listitem> <para> Only subset of commands is allowed in the reply-route statement. (See file <filename moreinfo="none">cfg.y</filename> for more details). </para> </listitem> <listitem> <para>Reply-route statement has it's own array of linked-lists.</para> </listitem> </itemizedlist> </para> </section> <!-- route-stm --> <section id="assign-stm"> <title>Assign Statement</title> <para> The server contains many configuration variables. There is a section of the config file in which the variables can be assigned new value. The section is called The Assign Statement. The following grammar snippet describes how the section is constructed (only one example will be shown): </para> <programlisting format="linespecific">assign_stm = "children" '=' NUMBER { children_no=$3; } | "children" '=' error { yyerror("number expected"); } ...</programlisting> <para> The number in the config file is assigned to <varname>children_no</varname> variable. The second statement will be executed if the parameter is not number or is in invalid format and will issue an error and abort the server. </para> </section> <!-- assign-stm --> <section id="module-stm"> <title>Module Statement</title> <para> The module statement allows module loading and configuration. There are two commands: </para> <itemizedlist> <listitem> <para> <emphasis>loadmodule</emphasis> - Load the specified module in form of a shared object. The shared object will be loaded using <function moreinfo="none">dlopen</function>. </para> </listitem> <listitem> <para> <emphasis>modparam</emphasis> - It is possible to configure a module using this command. The command accepts 3 parameters: <emphasis>module name</emphasis>, <emphasis>variable name</emphasis> and <emphasis>variable value</emphasis>. </para> </listitem> </itemizedlist> <para>The following grammar snippet describes the module statement:</para> <programlisting format="linespecific">module_stm = "loadmodule" STRING { DBG("loading module %s\n", $2); if (load_module($2)!=0) { yyerror("failed to load module"); }} | "loadmodule" error { yyerror("string expected"); } | "modparam" "(" STRING "," STRING "," STRING ")" { if (set_mod_param($3, $5, STR_PARAM, $7) != 0) { yyerror("Can't set module parameter"); } } | "modparam" "(" STRING "," STRING "," NUMBER ")" { if (set_mod_param($3, $5, INT_PARAM, (void*)$7) != 0) { yyerror("Can't set module parameter"); } } | MODPARAM error { yyerror("Invalid arguments"); }</programlisting> <para> When the parser finds <function moreinfo="none">loadmodule</function> command, it will execute statement in curly braces. The statement will call <function moreinfo="none">load_module</function> function. The function will load the specified filename using <function moreinfo="none">dlopen</function>. If <function moreinfo="none">dlopen</function> was successful, the server will look for <structname>exports</structname> structure describing the module's interface and register the module. For more details see <link linkend="module-interface">module section</link>. </para> <para> If the parser finds <function moreinfo="none">modparam</function> command, it will try to configure the specified variable in the specified module. The module must be loaded using <function moreinfo="none">loadmodule</function> before <function moreinfo="none">modparam</function> for the module can be used ! Function <function moreinfo="none">set_mod_param</function> will be called and will configure the variable in the specified module. </para> </section> <!-- module-stm --> </section> <!-- config-file-struct --> </section> <!-- ser-config --> <section id="iface-config"> <title>Interface Configuration</title> <para> The server will try to obtain list of all configured interfaces of the host it is running on. If it fails the server tries to convert hostname to <acronym>IP</acronym> address and will use interface with the <acronym>IP</acronym> address only. </para> <para> Function <function moreinfo="none">add_interfaces</function> will add all configured interfaces to the array. </para> <para> Try to convert all interface names to IP addresses, remove duplicates... </para> </section> <!-- iface-config --> <section id="daemon"> <title>Turning into a Daemon</title> <para> When configured so, <acronym>SER</acronym> becomes a daemon during startup. A process is called daemon when it hasn't associated controlling terminal. See function <function moreinfo="none">daemonize</function> in file <filename moreinfo="none">main.c</filename> for more details. The function does the following: </para> <itemizedlist> <listitem> <para> <emphasis>chroot</emphasis> is performed if necessary. That ensures that the server will have access to a particular directory and its subdirectories only. </para> </listitem> <listitem> <para> Server's working directory is changed if the new working directory was specified (usually it is /). </para> </listitem> <listitem> <para> If command line parameter -g was used, the server's group ID is changed to that value. </para> </listitem> <listitem> <para> If command line parameter -u was used, the server's user ID is changed to that value. </para> </listitem> <listitem> <para> Perform <emphasis>fork</emphasis>, let the parent process exit. This ensures that we are not a group leader. </para> </listitem> <listitem> <para> Perform <emphasis>setsid</emphasis> to become a session leader and drop the controlling terminal. </para> </listitem> <listitem> <para> Fork again to drop group leadership. </para> </listitem> <listitem> <para>Create a pid file.</para> </listitem> <listitem> <para>Close all opened file descriptors.</para> </listitem> </itemizedlist> </section> <!-- daemon --> <section id="module-init"> <title>Module Initialization</title> <para> The whole config file was parsed, all modules were loaded already and can be initialized now. A module can tell the core that it needs to be initialized by exporting <function moreinfo="none">mod_init</function> function. <function moreinfo="none">mod_init</function> function of all loaded modules will be called now. </para> </section> <!-- module-init --> <section id="rt-list-fix"> <title>Routing List Fixing</title> <para> After the whole routing list was parsed, there might be still places that can be further processed to speed-up the server. For example, several commands accept regular expression as one of their parameters. The regular expression can be compiled too and processing of compiled expression will be much faster. </para> <para> Another example might be string as parameter of a function. For example if you call <function moreinfo="none">append_hf("Server: SIP Express Router\r\n")</function> from the routing script, the function will append a new header field after the last one. In this case, the function needs to know length of the string parameter. It could call <function moreinfo="none">strlen</function> every time it is called, but that is not a very good idea because <function moreinfo="none">strlen</function> would be called every time a message is processed and that is not necessary. </para> <para> Instead of that the length of the string parameter could be pre-calculated upon server startup, saved and reused later. The processing of the request will be faster because <function moreinfo="none">append_hf</function> doesn't need to call <function moreinfo="none">strlen</function> every time, I can just reuse the saved value. </para> <para> This can be used also for string to int conversions, hostname lookups, expression evaluation and so on. </para> <para> This process is called Routing List Fixing and will be done as one of last steps of the server startup. </para> <para> Every loaded module can export one or more functions. Each such function can have associated a fixup function, which should do fixing as described in this section. All such fixups of all loaded modules will be called here. That makes it possible for module functions to fix their parameters too if necessary. </para> </section> <!-- rt-list-fix --> <section id="stat-init"> <title>Statistics Initialization</title> <para> If compiled-in, the core can produce some statistics about itself and traffic processed. The statistics subsystem gets initialized here, see function <function moreinfo="none">init_stats</function>. </para> </section> <!-- stat-init --> <section id="socket-init"> <title>Socket Initialization</title> <para> UDP socket initialization depends on <varname>dont_fork</varname> variable. If this variable is set (only one process will be processing incoming requests) and there are multiple listen interfaces, only the first one will be used. This mode is mainly for debugging. </para> <para> If the variable is not set, then sockets for all configured interfaces will be created and initialized. See function <function moreinfo="none">udp_init</function> in file <filename moreinfo="none">udp_server.c</filename> for more details. </para> </section> <!-- socke-init --> <section id="forking"> <title>Forking</title> <para> The rest of the initialization process depends on value of <varname>dont_fork</varname> variable. <varname>dont_fork</varname> is a global variable defined in <filename moreinfo="none">main.c</filename>. We will describe both variants separately. </para> <section id="dont-fork-set"> <title><varname>dont_fork</varname> variable is set (not zero)</title> <para> If <varname>dont_fork</varname> variable is set, the server will be operating in special mode. There will be only one process processing incoming requests. This is very slow and was intended mainly for debugging purposes. The main process will be processing all incoming requests itself. </para> <para> The server still needs additional children: </para> <itemizedlist> <listitem> <para> One child is for the timer subsystem, the child will be processing timers independently of the main process. </para> </listitem> <listitem> <para> <acronym>FIFO</acronym> server will spawn another child if enabled. The child will be processing all commands coming through the fifo interface. </para> </listitem> <listitem>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -