File: startup.xml

package info (click to toggle)
kamailio 5.6.3-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 68,332 kB
  • sloc: ansic: 744,091; xml: 196,848; cpp: 14,471; makefile: 8,859; sh: 8,814; sql: 7,844; yacc: 3,863; perl: 2,955; python: 2,710; java: 449; javascript: 269; php: 258; ruby: 225; cs: 40; awk: 27
file content (810 lines) | stat: -rw-r--r-- 30,268 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
<?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="ser_startup" xmlns:xi="http://www.w3.org/2001/XInclude">
    <sectioninfo>
	<revhistory>
	    <revision>
		<revnumber>$Revision$</revnumber>
		<date>$Date$</date>
	    </revision>
	</revhistory>
    </sectioninfo>
    
    <title>The Server Startup</title>
    <para>
	The <function>main</function> function in file
	<filename>main.c</filename> is the first function called upon server
	startup. It's purpose is to initialize the server and enter main
	loop. The server initialization will be described in the following
	sections.
    </para>
    
    <para>
	Particular initialization steps are described in order in which they
	appear in <function>main</function> function.
    </para>
    
    <section id="signal_handlers">
	<title>Installation Of New Signal Handlers</title>
	<para>
	    The first step in the initialization process is the installation of
	    new signal handlers. We need our own signal handlers to be able to
	    do graceful shutdown, print server statistics and so on. There is
	    only one signal handler function which is function
	    <function>sig_usr</function> in file <filename>main.c</filename>.
	</para>
	<para>
	    The following signals are handled by the function: SIGINT, SIGPIPE,
	    SIGUSR1, SIGCHLD, SIGTERM, SIGHUP and SIGUSR2.
	</para>
    </section> <!-- signal-installation -->
    
    <section id="cmdline_parameters">
	<title>Processing Command Line Parameters</title>
	<para>
	    SER utilizes the <function>getopt</function>function to parse
	    command line parameters. The function is extensively described in
	    the man pages.
	</para>
    </section> <!-- cmd-line-params -->
    
    <section id="parser-init">
	<title>Parser Initialization</title>
	<para>
	    SER contains a fast 32-bit parser. The parser uses pre-calculated
	    hash table that needs to be filled in upon startup. The
	    initialization is done here, there are two functions that do the
	    job. Function <function>init_hfname_parser</function> initializes
	    hash table in header field name parser and function
	    <function>init_digest_parser</function> initializes hash table in
	    digest authentication parser. The parser's internals will be
	    described later.
	</para>
    </section> <!-- parser-init -->
    
    <section id="malloc_init">
	<title>Malloc Initialization</title>
	<para>
	    To make SER even faster we decided to re-implement memory
	    allocation routines. The new <function>malloc</function> better
	    fits our needs and speeds up the server a lot. The memory
	    management subsystem needs to be initialized upon server
	    startup. The initialization mainly creates internal data structures
	    and allocates memory region to be partitioned.
	</para>
	
	<important>
	    <para>
		The memory allocation code must be initialized
		<emphasis>BEFORE</emphasis> any of its function is called !
	    </para>
	</important>
    </section> <!-- malloc-init -->
    
    <section id="timer_init">
	<title>Timer Initialization</title>
	<para>
	    Various subsystems of the server must be called periodically
	    regardless of the incoming requests. That's what timer is
	    for. Function <function>init_timer</function> initializes the timer
	    subsystem. The function is called from <filename>main.c</filename>
	    and can be found in <filename>timer.c</filename> The timer
	    subsystem will be described later.
	</para>
	<warning>
	    <para>
		Timer subsystem must be initialized before config file is parsed !
	    </para>
	</warning>
    </section> <!-- timer-init -->

    <section id="fifo_init">
	<title>FIFO Initialization</title>
	<para>
	    SER has built-in support for FIFO control. It means that the
	    running server can accept commands over a FIFO special file (a
	    named pipe). Function <function>register_core_fifo</function>
	    initializes FIFO subsystem and registers basic commands, that are
	    processed by the core itself. The function can be found in file
	    <filename>fifo_server.c</filename>.
	</para>
	<para>
	    The FIFO server will be described in another chapter.
	</para>
    </section> <!-- fifo-init -->
    
    <section id="builtin_modules">
	<title>Built-in Module Initialization</title>
	<para>
	    Modules can be either loaded dynamically at runtime or compiled in statically. When a module
	    is loaded at runtime, it is registered
	    <footnote id="regfoot">
		<para>
		    Module registration is a process when the core tries to find what functions and
		    parameters are offered by the module.
		</para>
	    </footnote>
	    immediately with the core. When the module is compiled in
	    statically, the registration<footnoteref linkend="regfoot"/> must be
	    performed during the server startup. Function
	    <function>register_builtin_modules</function> does the job.
	</para>
    </section> <!-- builtin-mod-reg -->
    
    <section id="ser_configuration">
	<title>Server Configuration</title>
	<para>
	    The server is configured through a configuration file. The
	    configuration file is C-Shell like script which defines how
	    incoming requests should be processed. The file cannot be
	    interpreted directly because that would be very slow. Instead of
	    that the file is translated into an internal binary
	    representation. The process is called compilation and will be
	    described in the following sections.
	</para>
	<note>
	    <para>
		The following sections only describe how the internal binary
		representation is being constructed from the config file. The
		way how the binary representation is used upon a request
		arrival will be described later.
	    </para>
	</note>
	<para>The compilation can be divided in several steps:</para>
	
	<section id="lexical_analysis">
	    <title>Lexical Analysis</title>
	    <para>
		Lexical analysis is process of converting the input (the
		configuration file in this case) into a stream of tokens. A
		token is a set of characters that 'belong' together. A program
		that can turn the input into stream of tokens is called
		scanner. For example, when scanner encounters a number in the
		config file, it will produce token NUMBER.
	    </para>
	    <para>
		There is no need to implement the scanner from scratch, it can
		be done automatically.  There is a utility called flex. Flex
		accepts a configuration file and generates scanner according to
		the configuration file. The configuration file for flex
		consists of several lines - each line describing one token. The
		tokens are described using regular expressions. For more
		details, see flex manual page or info documentation.
	    </para>
	    <para>
		Flex input file for the SER config file is in file
		<filename>cfg.lex</filename>. The file is processed by flex
		when the server is being compiled and the result is written in
		file <filename>lex.yy.c</filename>. The output file contains
		the scanner implemented in the C language.
	    </para>
	</section> <!-- lex-analysis -->
	
	<section id="syntax_analysis">
	    <title>Syntactical Analysis</title>
	    <para>
		The second stage of configuration file processing is called
		syntactical analysis. Purpose of syntactical analysis is to
		check if the configuration file has been well formed, doesn't
		contain syntactical errors and perform various actions at
		various stages of the analysis.  Program performing syntactical
		analysis is called parser.
	    </para>
	    <para>
		Structure of the configuration file is described using
		grammar. Grammar is a set of rules describing valid 'order' or
		'combination' of tokens. If the file isn't conformable with
		it's grammar, it is syntactically invalid and cannot be further
		processed. In that case an error will be issued and the server
		will be aborted.
	    </para>
	    <para>
		There is a utility called yacc. Input of the utility is a file
		containing the grammar of the configuration file, in addition
		to the grammar, you can describe what action the parser should
		do at various stages of parsing. For example, you can instruct
		the parser to create a structure describing an IP address every
		time it finds an IP address in the configuration file and
		convert the address to its binary representation.
	    </para>
	    <para>For more information see yacc documentation.</para>
	    <para>
		yacc creates the parser when the server is being compiled from
		the sources.  Input file for yacc is
		<filename>cfg.y</filename>. The file contains grammar of the
		config file along with actions that create the binary
		representation of the file.  Yacc will write its result into
		file <filename>cfg.tab.c</filename>. The file contains function
		<function>yyparse</function> which will parse the whole
		configuration file and construct the binary representation. For
		more information about the bison input file syntax see bison
		documentation.
	    </para>
	</section> <!-- syntax-analysis -->
	
	<section id="config_structure">
	    <title>Config File Structure</title>
	    <para>
		The configuration file consist of three sections, each of the
		sections will be described separately.
	    </para>
	    <itemizedlist>
		<listitem>
		    <para>
			<emphasis>Route Statement</emphasis> - The statement
			describes how incoming requests will be processed.
			When a request is received, commands in one or more
			"route" sections will be executed step by step. The
			config file must always contain one main "route"
			statement and may contain several additional "route"
			statements. Request processing always starts at the
			beginning of the main "route" statement. Additional
			"route" statements can be called from the main one or
			another additional "route" statements (It it similar to
			function calling).
		    </para>
		</listitem>
		<listitem>
		    <para>
			<emphasis>Assign Statement</emphasis> - There are many
			configuration variables across the server and this
			statement makes it possible to change their
			value. Generally it is a list of assignments, each
			assignment on a separate line.
		    </para>
		</listitem>
		<listitem>
		    <para>
			<emphasis>Module Statement</emphasis> - Additional
			functionality of the server is available through
			separate modules. Each module is a shared object that
			can be loaded at runtime. Modules can export functions,
			that can be called from the configuration file and
			variables, that can be configured from the config
			file. The module statement makes it possible to load
			modules and configure them. There are two commands in
			the statement - <function>loadmodule</function> and
			<function>modparam</function>.  The first can load a
			module. The second one can configure module's internal
			variables.
		    </para>
		</listitem>
	    </itemizedlist>
	    <para>
		In the following sections we will describe in detail how the
		three sections are being processed upon server startup.
	    </para>

	    <section id="route_statement">
		<title>Route Statement</title>
		<para>The following grammar snippet describes how the route statement is constructed</para>
		<programlisting>
route_stm = "route" "{" actions "}"  
{ 
    $$ = push($3, &amp;rlist[DEFAULT_RT]); 
}
		   
actions = actions action { $$ = append_action($1, $2}; }
| action { $$ = $1; }

action = cmd SEMICOLON { $$ = $1; }
| SEMICOLON { $$ = 0; }

cmd = "forward" "(" host ")" { $$ = mk_action(FORWARD_T, STRING_ST, NUMBER_ST, $3, 0)
| ...
		</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>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>forward</function> command,
		    <function>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>action</function>
		    rule to <function>actions</function>
		    rule. <function>Actions</function> rule will create linked
		    list of all commands. The linked list will be then inserted
		    into <structfield>rlist</structfield> table.  (Function
		    <function>push</function> in rule
		    <function>route_stm</function>).  Each element of the table
		    represents one "route" 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 SIP
				<emphasis>REPLY</emphasis> comes (not ,SIP
				<emphasis>REQUEST</emphasis>).
			    </para>
			</listitem>
			<listitem>
			    <para>
				Only subset of commands is allowed in the
				reply-route statement.  (See file
				<filename>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_statement">
		<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>
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_statement">
		<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>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>
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, PARAM_STR|PARAM_STRING, $7) != 0) {
        yyerror("Can't set module parameter");
    }
}

| "modparam" "(" STRING "," STRING "," NUMBER ")" 
{
    if (set_mod_param($3, $5, PARAM_INT, (void*)$7) != 0) {
        yyerror("Can't set module parameter");
    }
}

| MODPARAM error { yyerror("Invalid arguments"); }
		</programlisting>
		<para>
		    When the parser finds <function>loadmodule</function>
		    command, it will execute statement in curly braces.  The
		    statement will call <function>load_module</function>
		    function.  The function will load the specified filename
		    using <function>dlopen</function>.  If
		    <function>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>modparam</function> command,
		    it will try to configure the specified variable in the
		    specified module. The module must be loaded using
		    <function>loadmodule</function> before
		    <function>modparam</function> for the module can be used !
		    Function <function>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 IP address and will use interface with the IP address
	    only.
	</para>
	<para>
	    Function <function>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, SER becomes a daemon during startup. A process
	    is called daemon when it hasn't associated controlling
	    terminal. See function <function>daemonize</function> in file
	    <filename>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>mod_init</function>
	    function. <function>mod_init</function> function of all loaded
	    modules will be called now.
	</para>
    </section> <!-- module-init -->
    
    <section id="routing_list_fixing">
	<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>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>strlen</function> every time it is called, but that
	    is not a very good idea because <function>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>append_hf</function> doesn't need to call
	    <function>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>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>udp_init</function> in file
	    <filename>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>main.c</filename>.  We will describe both variants
	    separately.
	</para>

	<section id="dont_fork">
	    <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>
			FIFO server will spawn another child if enabled. The
			child will be processing all commands coming through
			the fifo interface.
		    </para>
		</listitem>
		<listitem>
		    <para>If SNMP support was enabled, another child will be created.</para>
		</listitem>
	    </itemizedlist>
	    
	    <para>
		The following initialization will be performed in dont fork
		mode.  (look into function <function>main_loop</function> in
		file <filename>main.c</filename>.
	    </para>

	    <itemizedlist>
		<listitem>
		    <para>Another child will be forked for the timer subsystem.</para>
		</listitem>
		<listitem>
		    <para>
			Initialize the FIFO server if enabled, this will fork
			another child.  For more info about the FIFO server,
			see section The FIFO server.
		    </para>
		</listitem>
		<listitem>
		    <para>
			Call <function>init_child(0).</function> The function
			performs per-child specific initialization of all
			loaded modules.  A module can be initialized though
			<function>mod_init</function> function.  The function
			is called <emphasis>BEFORE</emphasis> the server forks
			and thus is common for all children.
		    </para>
		    <para>
			If there is anything, that needs to be initialized in
			every child separately (for example if each child needs
			to open its own file descriptor), it cannot be done in
			<function>mod_init</function>.  To make such
			initialization possible, a module can export another
			initialization function called
			<function>init_child</function>. The function will be
			called in all children <emphasis>AFTER</emphasis> fork
			of the server.
		    </para>
		    <para>
			And since we are in "dont fork" mode and there will no
			children processing requests (remember the main process
			will be processing all requests), the
			<function>init_child</function> wouldn't be called.
		    </para>
		    <para>
			That would be bad, because
			<function>child_init</function> might do some
			initialization that must be done otherwise modules
			might not work properly.
		    </para>
		    <para>
			To make sure that module initialization is complete we
			will call <function>init_child</function> here for the
			main process even if we are not going to fork.
		    </para>
		</listitem>
	    </itemizedlist>
	    <para>
		That's it. Everything has been initialized properly and as the
		last step we will call <function>udp_rcv_loop</function> which
		is the main loop function. The function will be described
		later.
	    </para>
	</section> <!-- dont-fork-set -->

	<section id="dont_fork_not_set">
	    <title><varname>dont_fork</varname> is not set (zero)</title>
	    <para>
		<varname>dont_fork</varname> is not set. That means that the
		server will fork children and the children will be processing
		incoming requests. How many children will be created depends on
		the configuration (<varname>children</varname> variable). The
		main process will be sleeping and handling signals only.
	    </para>

	    <para>
		The main process will then initialize the FIFO server. The FIFO
		server needs another child to handle communication over FIFO
		and thus another child will be created. The FIFO server will be
		described in more detail later.
	    </para>

	    <para>
		Then the main process will perform another fork for the timer
		attendant. The child will take care of timer lists and execute
		specified function when a timer hits.
	    </para>
	    <para>
		The main process is now completely initialized, it will sleep
		in <function>pause</function> function until a signal comes and
		call <function>handle_sigs</function> when such condition
		occurs.
	    </para>
	    
	    <para>
		The following initialization will be performed by each child
		separately:
	    </para>
	    <para>
		Each child executes <function>init_child</function>
		function. The function will sequentially call
		<function>child_init</function> functions of all loaded
		modules.
	    </para>
	    <para>
		Because the function is called in each child separately, it can
		initialize per-child specific data. For example if a module
		needs to communicate with database, it must open a database
		connection. If the connection would be opened in
		<function>mod_init</function> function, all the children would
		share the same connection and locking would be necessary to
		avoid conflicts. On the other hand if the connection was opened
		in <function>child_init</function> function, each child will
		have its own connection and concurrency conflicts will be
		handled by the database server.
	    </para>
	    <para>
		And last, but not least, each child executes
		<function>udp_rcv_loop</function> function which contains the
		main loop logic.
	    </para>
	    
	</section> <!-- dont-fork-not-set -->
    </section> <!-- forking -->
</section>