libserver(8) FreeBSD System Manager's Manual libserver(8)
NAME
libserver -- Multi-process TCP/UNIX Server-in-a-Library
SYNOPSIS
#include<server.h>
-I/usr/local/include -L/usr/local/lib -lserver
DESCRIPTION
libserver implements a generic multi-process TCP or UNIX-domain server
which is incapable of servicing connections on its own. The programmer
writes initialization functions, and a function to service connections,
then compiles and links his or her code against the library to create a
complete multi-process server.
USAGE
An example echo server is included in the libserver distribution, named
echo.c. It is built automatically when libserver.so is built, but not
installed by the Makefile.
The programmer must not define any global symbol beginning with the five
characters 'serv_', other than the names of the three programmer supplied
functions, because the library reserves that namespace for its own use.
The prototypes for the three functions the programmer must supply are
declared in server.h. You must define the functions to match the proto-
types:
void serv_init_func();
void serv_child_init_func();
void serv_service_connection();
Libserver uses a multi-process model. One master process forks and kills
child processes, as needed, according to demand, once per second. The
child processes accept and service client connections. The master
process does not.
In serv_init_func(), or in functions which it calls, the programmer must
perform the initialization tasks his or her server needs to do, once at
server start-up, before any child processes are forked. serv_init_func()
is called precisely once by libserver before the server attempts to
change user and group to "nobody" or to the values specified by the -u
and/or -g command-line options. Therefore, if the server starts as root,
serv_init_func() will execute as root. serv_init_func() is executed
before the server becomes a daemon, which means the standard streams will
still be connected to the terminal it was started from, and error and
informative messages may be sent there. serv_init_func() is called
before any of the command-line options are processed, except for the -f
option. Therefore, if the server has been started with the -r option,
the server will not yet have set the current working directory when
serv_init_func() is executed.
In serv_child_init_func(), or in functions which it calls, the programmer
may perform any other initialization tasks each child process needs to
perform independently of its parent before it can begin servicing connec-
tions. For example, one may open unique database connections for each
server child in serv_child_init_func(). serv_child_init_func() is called
every time a new server child process is forked(), in the child process.
serv_child_init_func() is executed after the server has changed user and
group to "nobody" or to the values specified by the -u and/or -g command-
line options. When serv_child_init_func() is executed the standard
streams will be connected to /dev/null. Therefore errors must be
reported using syslog(3). When serv_child_init_func() is executed, the
-r command-line option will have been processed to change the current
working directory.
Libserver recognizes several command-line options to configure itself,
but does not allow user code direct access to the command line arguments.
Instead, it recognizes an -f option, and assigns the value of this option
to the global character pointer serv_config_file. The code in
serv_init_func() and/or serv_child_init_func() may then access the speci-
fied configuration file. Libserver does nothing with the value of
serv_config_file. If the -f option was not present on the command line,
this variable will be NULL.
If the programmer has shut-down tasks to perform when the master or child
processes exit, he or she can register functions via atexit(3) in either
serv_init_func() or serv_child_init_func(). Functions registered in
serv_init_func() will be called by the master and all child processes
when they exit. Functions registered in serv_child_init_func() will only
be called by the registering process when it exits. If the programmer
needs to perform a shut-down task only in the master process, then he or
she is advised to use a global int to indicate whether a process is the
master or a child.
In scgi_init_func(), the programmer may install a function to be called
periodically by the master process to perform maintenance tasks with:
void serv_periodic( void (*)(), int );
The function pointed to by first argument will be called periodically by
the master process, the period being specified in seconds by the second
argument. This function may only be called from scgi_int_func() or from
functions which that function calls. Calling serv_periodic() from any
other place in your code will have no effect, because only
scgi_init_func() is invoked in the master process. Setting the interval
to a value <= 0, or setting the function to NULL, disables the periodic
function. Note that the server will be running as the user and group
defined by the -u and -g options when the periodic function is invoked.
One libserver library function which should be called from inside
serv_init_func() to set the server's name:
void serv_set_name( char * );
If not set, or set to NULL, the server's name defaults to "server". The
server's name is used in two ways:
o When the server is running, stderr is connected to /dev/null.
Errors, therefore, must be reported using syslog(3). The library
calls openlog() with the server's name as argument, to ensure log
entries are identified by the server's name.
o The server's pidfile will be written to /var/run/, if the server is
started as root. The filename will be the server's name with ".pid"
appended to it. This file can be used by /usr/local/etc/rc.d/
scripts to stop the server. A sample script is included in the lib-
server distribution.
The third programmer-supplied function, serv_service_connection() is
called once for every connection accepted by the server. The programmer
may use the buffered IO functions to communicate with the client via
stdin and stdout. If the programmer wishes to communicate with the non-
buffered UNIX IO functions, he or she must use the fileno() function to
determine the descriptors associated with stdout and stdin. They will
never be 0 or 1. serv_request_handler() should return only when the
server has finished servicing the current connection.
Please examine the echo.c source for the example echo server. It demon-
strates the use of libserver concisely.
CONFIGURATION
A server linked against libserver writes its pidfile into /var/run/, if
it can (ie., it is started as root), and may be stopped with a SIGTERM.
A sample rc.d script is provided in the libserver distribution. To use
the script, all occurrences of "server" must be replaced with the value
you passed to serv_set_name(), and the script installed in
/usr/local/etc/rc.d, renamed as the value you passed to serv_set_name().
Two variables must be added to /etc/rc.conf. For example (substituting
"server" for your server's name):
server_enable="YES"
server_flags="-u www -g www -r /usr/local/server"
If the "enable" variable is set to "YES", the server will be started at
system start. The following rc commands will be available:
/usr/local/etc/rc.d/server start
/usr/local/etc/rc.d/server stop
/usr/local/etc/rc.d/server restart
/usr/local/etc/rc.d/server status
If you do not want the server started on system start, then set
server_enable="NO"
and use the following commands:
/usr/local/etc/rc.d/server forcestart
/usr/local/etc/rc.d/server forcestop
/usr/local/etc/rc.d/server forcerestart
/usr/local/etc/rc.d/server forcestatus
COMMAND-LINE OPTIONS
The following command-line options are recognized by libserver servers.
All of these are optional.
-r The -r option specifies the server root directory, which libserver
will make its current working directory.
-l By default, libserver listens on all TCP interfaces it can find capa-
ble of IPv4 or IPv6. The -l option instructs the library to listen
on a UNIX-domain socket instead. The path to the socket must be
specified as this option's argument. The server will create the
socket when it starts, unlinking it first, if it already exists in
the filesystem. The owner and group of the socket will be changed to
the values of the -u and -g options, or their defaults. The permiss-
sions of the socket will be set to srwxrwx---. If this option is
present on the command-line, then the -p and -i options may not be
present. The server will refuse to run if they are.
-p The -p option specifies the port to listen on. This defaults to 1966
if not specified. Note that to bind to a port lower than 1024, the
server must be started as root.
-i By default, libserver accepts connections on all interfaces it can
find capable of IPv4 or IPv6. The -i option, when present, overrides
this behavior, by limiting libserver to accepting connections from a
specified interface only. The option accepts the IP address of the
desired interface as an argument. The address must be expressed in
the presentation format for either IPv4 or IPv6.
-m
-n libserver uses a multi-process model, with one master process forking
or killing slave processes in response to client activity. Only the
slave processes service client requests. The -n options specifies
the number of idle slaves the master will attempt to keep ready at
all times. The -m option specifies the maximum number of slaves
which may be running at any time. The value specified must be equal
to or greater than the value specified for -n. The default value for
-n is 3 and the default value for -m is 25.
-u
-g The -u and the -g options may be used to specify the user and group
for the server to change to after it has bound to the listening
socket. If not specified, both values default to "nobody". Note
that in order for a libserver server to change user the server must
be started as root. If not started as root, two error messages will
be syslog()ed at start-up, complaining about the inability of the
server to change user and group. You can suppress them by providing
values to -u and -g to override the default "nobody" with the actual
user and group under which the server runs.
-x The -x option, if present, prevents libserver from becoming a daemon.
It will then run in the foreground of the terminal where it was
started, and may be stopped with signals (ie., Control-C). Stderr
will be connected to the terminal, so diagnostic output may be sent
there when this option is present on the command-line. The server
also will not write its pidfile to /var/run/ when the -x option is
used.
-f The -f option requires a filename as argument. Libserver does noth-
ing with this value, but assigns it to the global character pointer
named serv_config_file. This allows the code in serv_init_func()
and/or serv_child_init_func() to read a configuration file, specified
by the user, upon process start-up.
AUTHORS
James Bailie <jimmy@mammothcheese.ca>
http://www.mammothcheese.ca
Dec 28, 2011