GNU Serveez
1 Using Serveez
1.1 Building and installing
1.1.1 Rebuild the package from the sources
1.1.1.1 Getting the source
1.1.1.2 Requirements
1.1.1.3 Installation
1.2 Environment variables
1.3 Starting Serveez
1.4 Command line options
1.5 Configuring Serveez
1.5.1 Define ports
1.5.1.1 Port configuration items
1.5.1.2 TCP port definition
1.5.1.3 Pipe port definition
1.5.1.4 ICMP port definition
1.5.1.5 UDP port definition
1.5.2 Define servers
1.5.3 Bind servers to ports
1.5.4 Additional configuration possibilities
1.5.4.1 output
1.5.4.2 augmenting
1.5.4.3 abstractions
1.5.4.4 rpc
1.5.4.5 misc
2 Concept
2.1 Overall concept
2.2 I/O Strategy
2.2.1 Limits on open filehandles
2.3 Alternatives to Serveez’s I/O strategy
3 Server
3.1 Introduction to servers
3.2 Writing servers
3.2.1 Embedded servers
3.2.1.1 Prerequisites
3.2.1.2 Server definition
3.2.2 Guile servers
3.2.2.1 Underlying libserveez
3.2.2.2 Special Data Types
3.2.2.3 Passing Binary Data
3.2.2.4 Server Definition
3.2.2.5 Predefined Procedures
3.2.2.6 Callback Prototypes
3.2.3 Builtin servers
3.2.3.1 Making and configuring preparations
3.2.3.2 Server header file ‘foo-proto.h’
3.2.3.3 Server implementation file ‘foo-proto.c’
3.2.3.4 Server definition
3.2.3.5 Server callbacks
3.2.3.6 Make your server available
3.2.3.7 More detailed description of the callback system and structures
3.2.3.8 Using coservers
3.3 Some words about server configuration
3.4 Existing servers
3.4.1 HTTP Server
3.4.1.1 General description
3.4.1.2 Configuration
3.4.2 IRC Server
3.4.2.1 General description
3.4.2.2 Configuration
3.4.3 Control Protocol Server
3.4.3.1 General description
3.4.3.2 Using the Control Protocol
3.4.3.3 Configuration
3.4.4 Foo Server
3.4.4.1 General description
3.4.4.2 Configuration
3.4.5 SNTP Server
3.4.5.1 General
3.4.5.2 Configuration
3.4.6 Gnutella Spider
3.4.6.1 What is it ?
3.4.6.2 Configuration
3.4.7 Tunnel Server
3.4.7.1 General description
3.4.7.2 Extended ICMP protocol specification
3.4.7.3 Configuration
3.4.8 Fake Ident Server
3.4.8.1 General description
3.4.8.2 Configuration
3.4.9 Passthrough Server
3.4.9.1 General description
3.4.9.2 Configuration
3.4.10 Mandel Server
3.4.10.1 General description
3.4.10.2 Configuration
4 Coserver
4.1 What are coservers
4.2 Writing coservers
4.2.1 Making and configuring preparations
4.2.2 Coserver header file
4.2.3 Coserver implementation file
4.2.4 Make your coserver available in Serveez
4.3 Existing coservers
4.3.1 Identification (Ident) coserver
4.3.2 Domain Name Server (DNS) coserver
4.3.3 Reverse Domain Name Server (reverse DNS) coserver
5 Embedding
5.1 Embedding Serveez
5.1.1 Compiling and linking
5.1.2 A simple example
5.2 Embedding API
5.2.1 Library features
5.2.2 Memory management
5.2.3 Data structures
5.2.3.1 Array
5.2.3.2 Hashtable
5.2.4 svz_address_t
5.2.5 Utility functions
5.2.6 Networking and other low level functions
5.2.7 Client connections
5.2.7.1 TCP sockets
5.2.7.2 Pipe connections
5.2.7.3 UDP sockets
5.2.7.4 ICMP sockets
5.2.7.5 Raw sockets
5.2.7.6 Passthrough connections
5.2.8 Socket management
5.2.9 Coserver functions
5.2.10 Codec functions
5.2.11 Server types
5.2.11.1 Macros for setting up a new server type
5.2.11.2 General server type functionality
5.2.11.3 Dynamic server loading
5.2.12 Server functions
5.2.12.1 Server functionality
5.2.12.2 Configuration
5.2.12.3 Bindings
5.2.12.4 Server core
5.2.12.5 Server loop
5.2.12.6 Server sockets
5.2.13 Port configurations
5.2.14 Boot functions
5.2.14.1 Runtime parameters
5.2.15 Network interface functions
5.2.16 Useful Windows functions
6 Porting issues
7 Bibliography
Appendix A GNU Free Documentation License
Index
GNU Serveez
***********
This manual documents GNU Serveez 0.3.1, released 11 December 2021.
GNU Serveez is a server framework. It provides routines and help for
implementing IP-based servers (currently TCP, UDP and ICMP). It supports
named pipes for all connection-oriented protocols.
We think it is worth the effort because many people need server
functionality within their applications. However, many people
experience problems with select(2) or poll(2) loops, and with
non-blocking operations.
GNU Serveez demonstrates various aspects of advanced network
programming in a portable manner. It is known to compile and run on
GNU/Linux systems, as well as on other 32-bit and 64-bit flavours of
Unix and on Microsoft Windows (9x/ME/NT/2000/XP).
You can use it for implementing your own servers or for understanding
how certain network services and operations work.
The package includes a number of servers that work already: an HTTP
server, an IRC server, a Gnutella spider and some others. One of the
highlights is that you can run all protocols on the same port. The
application itself is single threaded but it uses helper processes for
concurrent name resolution and ident lookups.
1 Using Serveez
***************
We know, you usually don’t read the documentation. Who does. But
please, read at the very least this chapter. It contains information on
the basic concepts. Larger parts of the manual can be used as a
reference manual for the various servers.
1.1 Building and installing
===========================
1.1.1 Rebuild the package from the sources
------------------------------------------
You can skip this section if you are familiar with the GNU’ish way of
configuring, compiling and installing a GNU package.
1.1.1.1 Getting the source
..........................
Serveez can be found on , on one of
the mirrors () or at its original
location .
1.1.1.2 Requirements
....................
Serveez needs GNU Guile (Ubiquitous Intelligent Language for
Extensions). The current version of Serveez is known to work with Guile
1.3 and later. Guile can be downloaded at
.
When installing Guile, consider specifying to its ‘configure’ script
options along the lines of:
--enable-static --disable-shared
--disable-debug-freelist
--disable-debug-malloc
--disable-guile-debug
--disable-arrays --disable-posix
--enable-networking --disable-regex
--without-threads --enable-ltdl-convenience
This option set is tuned for Guile 1.4 and may or may not work for
your particular installation; you may need to experiment a bit. Most
important is that the program ‘guile-config’ be findable in a directory
named in the ‘PATH’ environment variable. If not, configuration will
fail with message “Guile not found”.
1.1.1.3 Installation
....................
Unpack the distribution tarball:
sleepless ~> gzip -cd serveez-0.3.1.tar.gz | tar xvf -
Change into the source directory:
sleepless ~> cd serveez-0.3.1
Configure the source package for your system:
Normally, this is done by running the ‘configure’ script in the
top-level directory. GNU Serveez needs a reasonably conformant C99
compiler to build. If the ‘configure’ script is not able to
automatically find and enable such a compiler, you can specify it
directly using the ‘CC’ command-line option. For example:
sleepless ~> ./configure --prefix /gnu CC='/gnu/bin/gcc'
Note that in this example you can achieve the same results by
making sure ‘/gnu/bin’ is in the ‘PATH’ env var.
In previous Serveez releases, the ‘configure’ script had some
builtin compiler flags for warnings and optimizations, conveniently
exposed via command-line options. These are no longer available;
instead, you can use ‘CFLAGS’ for such purposes (see below). Here
is a complete list of the ‘configure’ script options. The list of
known options can the obtained via ‘./configure --help’.
‘--enable-debug’
All of the debug messages (debug: some annoying crap text) can
be suppressed by setting the debug level (-v). If you do not
want these messages built in at all then disable this feature.
‘--enable-control-proto’
If you enable this feature the control protocol will be
supported by Serveez. This protocol is for remote control of
the server.
‘--enable-irc-proto’
Enabling this feature tells the software package to support
the IRC (Internet Relay Chat) protocol.
‘--enable-irc-ts’
This feature is only available if you enabled the IRC
protocol. If you enabled both of them then Serveez will
support the so called TimeStamp protocol, which is an EFNet
extension of the original IRC protocol. In order to connect
to EFNet you MUST use this option.
‘--enable-http-proto’
When using Serveez as part of the textSure (C) chat system you
will will have need of an additional web server. This option
makes Serveez support a simple HTTP protocol.
‘--enable-flood’
If you enable this feature Serveez will support a simple
built-in flood protection. It is always useful to protect the
software from flood clients.
‘--with-mingw=DIR’
When compiling under M$-Windows the DIR argument specifies the
path to the extra MinGW32 library and header files. If you
want the final executable to use the Cygwin project’s
‘cygwin1.dll’ instead, you have to disable this option by
passing the configure script ‘--without-mingw’ or
‘--with-mingw=no’.
‘--enable-sntp-proto’
This option enables support for a simple network time protocol
server.
‘--enable-poll’
If the target system supports ‘poll’ and this feature is
enabled the main file descriptor loop is done via ‘poll’.
This helps to work around the (g)libc’s file descriptor limit.
Otherwise Serveez always falls back to the ‘select’ system
call.
‘--enable-sendfile’
This option enables the use of the ‘sendfile’ system call.
Disabling it using ‘--disable-sendfile’ provides a work-around
for bogus implementations of ‘sendfile’.
‘--enable-gnutella’
If you do *not* want the Gnutella spider client compiled in
you need to *disable* this option.
‘--enable-crypt’
This option tells Serveez to process any passwords as
‘crypt’ed.
‘--enable-tunnel’
If you enable this feature the port forwarder will be
included. This is useful if you plan to use Serveez as a
gateway or firewall workaround.
‘--enable-fakeident’
By enabling this you will get a fake ident server included in
the binary executable.
‘--enable-guile-server’
If you enable this feature the user is able to write servers
using Guile.
‘--enable-passthrough’
This includes the program passthrough server in the Serveez
binary. The server provides basic inetd functionality.
‘--enable-iflist’
If Serveez is unable to detect the correct list of local
network interfaces (‘serveez -i’) you can disable this option
and setup them manually in the configuration file.
‘--enable-heap-count’
This option depends on ‘--enable-debug’. With the debugging
option disabled there is also no support for heap counters.
The heap counters are used to detect memory leaks in Serveez.
‘--enable-libserveez-install’
This causes ‘make install’ to also copy libserveez and its
header files to ‘$(libdir)’ and ‘$(includedir)’, respectively.
While Serveez is in alpha (version less than ‘0.8.0’), this
option is disabled by default.
For maximum flexibility and reproducibility, we recommend enabling
warnings and optimizations specifying ‘CFLAGS’ as a command-line
option to the ‘configure’ script. For reference, here is the
collected set of flags built into previous Serveez releases:
(warnings)
-W -fullwarn -pedantic -ansi
-Wall -Wcast-align -Wstrict-prototypes
-Wformat -Wno-unused -Wno-long-long
(optimizations)
-O2 -fomit-frame-pointer -fstrength-reduce
-funroll-loops -finline-functions
-fexpensive-optimizations -fcaller-saves
-frerun-loop-opt -foptimize-register-move
-ffunction-cse -fpeephole -momit-leaf-frame-pointer
-fschedule-insns2 -m486 -march=pentiumpro -O3
Note that not all flags may be compatible with your compiler or
even each other. That’s one of the reasons we no longer take this
approach. *Note (autoconf)Defining Variables::.
sleepless ~/serveez-0.3.1> ./configure \
CFLAGS='-g -O3 -Wall -Wextra'
Now compile the package:
sleepless ~/serveez-0.3.1> make
Install serveez:
You must have root privileges if you want to install the package in
the standard location ‘/usr/local’ or in any location that is only
writable by root.
sleepless ~/serveez-0.3.1> make install
If you have problems building the package out of the box this is due
to GNU libtool’s inability to handle dynamic linking in most cases.
That is why we recommend to try to configure the package with
‘--disable-shared’.
1.2 Environment variables
=========================
When using the serveezopt package or playing around with the dynamic
server module loader of Serveez you can tell the core API of Serveez
(which is the ‘libserveez.[so|dll]’ library) to use an additional load
path to find these server modules. The environment variable
‘SERVEEZ_LOAD_PATH’ holds this information. You can set it up via:
on Unices
sleepless ~> export SERVEEZ_LOAD_PATH=/home/lib:/usr/local/lib
or on Windows
C:\HOME> set SERVEEZ_LOAD_PATH=C:\HOME\LIB;C:\USR\LOCAL\LIB
1.3 Starting Serveez
====================
When Serveez is started it reads its configuration from a file called
‘serveez.cfg’ in the current directory and runs the server loop
afterwards. Press <^C> to abort the execution of this program. Serveez
is not interactive and does not automatically detach from the terminal.
1.4 Command line options
========================
‘-h, --help’
Display this help and exit.
‘-V, --version’
Display version information and exit.
‘-L, --list-servers’
Display prefix and description of each builtin server, one per
line, and exit. If Serveez was configured to include the Guile
server (*note Build and install::), the output includes an
additional line:
(dynamic) (servers defined in scheme)
‘-i, --iflist’
List local network interfaces and exit.
‘-f, --cfg-file=FILENAME’
File to use as configuration file (serveez.cfg).
‘-v, --verbose=LEVEL’
Set level of logging verbosity.
‘-l, --log-file=FILENAME’
Use ‘FILENAME’ for logging (default is stderr).
‘-P, --password=STRING’
Set the password for control connections. This option is available
only if the control protocol is enabled. *Note Control Protocol
Server::.
‘-m, --max-sockets=COUNT’
Set the maximum number of socket descriptors.
‘-d, --daemon’
Start as daemon in background.
‘-c, --stdin’
Use standard input as configuration file.
‘-s, --solitary’
Do not start any builtin coserver instances.
1.5 Configuring Serveez
=======================
As noted above Serveez is configured via a configuration file which is
by default ‘serveez.cfg’ and can be set by passing the ‘-f’ command line
argument. When you pipe a file into Serveez or pass the ‘-c’ argument
on the command line the input stream will be used as configuration file
no matter whether you passed a ‘-f’ command line switch or not.
To make configuring more fun we did not invent yet another
configuration file format. Instead we use a dialect of the Scheme
programming language called GNU Guile
(). There is no need to be worried
if you are not a programmer. What you have to do is really simple and
this document shows you everything you need to know. We also provide
many examples. However there are some simple concepts you have to
understand. The following paragraphs will explain them.
The idea of the configuration file is this: Serveez starts, runs the
configuration file (other applications usually just read them and
remember the settings) and finally enters its main loop doing the things
you wanted it to.
There are three things you have to do in the configuration file.
1.5.1 Define ports
------------------
A ‘port’ (in Serveez) is a transport endpoint. You might know them from
other TCP or UDP server applications. For example: web servers (HTTP)
usually listen on TCP port 80. However, there is more than TCP ports:
we have UDP, ICMP and named pipes each with different options to set.
Every port has a unique name you assign to it. The name of the port is
later used to bind servers to it.
The following examples show how you setup different types of port
configurations. You start to define such a port using the procedure
‘define-port!’. The first argument specifies the name of the port
configuration. The remaining argument describes the port in detail.
1.5.1.1 Port configuration items
................................
This table describes each configuration item for a port in Serveez.
Note that not each item applies to every kind of port configuration.
‘proto (string)’
This is the main configuration item for a port configuration
setting up the type of port. Valid values are ‘tcp’, ‘udp’,
‘icmp’, ‘raw’ and ‘pipe’. This configuration item decides which of
the remaining configuration items apply and which do not.
‘port (integer in the range 0..65535)’
The ‘port’ item determines the network port number on which TCP and
UDP servers will listen. Thus it does not make sense for ICMP and
named pipes. If you pass ‘0’ Serveez will determine a free port in
the range between 1 and 65535.
‘recv (string or associative list)’
This item describes the receiving (listening) end of a named pipe
connection, i.e., the filename of a fifo node to which a client can
connect by opening it for writing. Both the ‘recv’ and ‘send’ item
apply to named pipes only. The value can either be an associative
list or a simple filename. Using a simple filename leaves
additional options to use default values. They deal mainly with
file permissions and are described below.
‘send (string or associative list)’
This item is the sending end of a named pipe connection. It is
used to send data when the receiving (listening) end has detected a
connection. The following table enumerates the additional options
you can setup if you pass an associative list and not a simple
filename.
‘name (string)’
The filename of the named pipe. On Windows systems you can
also specify the hostname on which the pipe should be created
in the format ‘\\hostname\pipe\name’. By default (if you
leave the leading ‘\\hostname\pipe\’ part) the pipe will be
created on ‘\\.\pipe\name’ which refers to a pipe on the local
machine.
‘permission (octal integer)’
This specifies the file permissions a named pipe should be
created with. The given number is interpreted in a Unix’ish
style (e.g., ‘#o0666’ is a permission field for reading and
writing for the creating user, all users in the same group and
all other users).
‘user (string)’
The file owner (username) of the named pipe in textual form.
‘group (string)’
The file owner group (groupname) of the named pipe in textual
form. If this item is left it defaults to the file owner’s
primary group.
‘uid (integer)’
The file owner of the named pipe as a user id. You are meant
to specify either the ‘uid’ item or the ‘user’ item. Serveez
will complain about conflicting values.
‘gid (integer)’
The file owner group of the named pipe as a group id. This
item defaults to the file owner’s primary group id. You are
meant to specify either the ‘gid’ item or the ‘group’ item.
Serveez will croak about conflicting values.
‘ipaddr (string)’
This configuration item specifies the IP address (either in dotted
decimal form e.g., ‘192.168.2.1’ or as a device description which
can be obtained via ‘serveez -i’) to which a server is bound to.
The ‘*’ keyword for all known IP addresses and the ‘any’ keyword
for any IP address are also valid values. The default value is
‘*’. The configuration item applies to network ports (TCP, UDP and
ICMP) only.
‘device (string)’
The ‘device’ configuration item also refers to the IP address a
server can be bound to. It overrides the ‘ipaddr’ item. Valid
values are network device descriptions (probably no aliases and no
loopback devices). It applies to network ports (TCP, UDP and ICMP)
only.
A note on device bindings: Device bindings are based on the
‘SO_BINDTODEVICE’ socket layer option. This option is not
available on all systems. We only tested it on GNU/Linux (2.2.18
and 2.4.17 as of this writing). Device bindings are very
restrictive: only root can do it and only physical devices are
possible. The loopback device cannot be used and no interface
alias (i.e., ‘eth0:0’). A device binding can only be reached from
the physical outside but it includes all aliases for the device.
So if you bind to device ‘eth0’ even ‘eth0:0’ (and all other
aliases) are used. The connection has to be made from a remote
machine. The advantage of this kind of binding is that it survives
changes of IP addresses. This is tested for ethernet networks
(i.e., eth*) and isdn dialups (i.e., ippp*). It does not work for
modem dialups (i.e., ppp*) (at least for Stefan’s PCMCIA modem).
The problem seems to be the dialup logic actually destroying ppp*.
Other opinions are welcome. Device bindings always win: If you
bind to ‘*’ (or an individual IP address) and to the corresponding
device, connections are made with the device binding. The order of
the ‘bind-server!’ statements do not matter. This feature is not
thoroughly tested.
‘backlog (integer)’
The ‘backlog’ parameter defines the maximum length the queue of
pending connections may grow to. If a connection request arrives
with the queue full the client may receive an error. This
parameter applies to TCP ports only.
‘type (integer in the range 0..255)’
This item applies to ICMP ports only. It defines the message type
identifier used to send ICMP packets (e.g., ‘8’ is an echo message
i.e., PING).
‘send-buffer-size (integer)’
The ‘send-buffer-size’ configuration item defines the maximum
number of bytes the send queue of a client is allowed to grow to.
The item influences the “send buffer overrun error condition”. For
packet oriented protocols (UDP and ICMP) you need to specify at
least the maximum number of bytes a single packets can have. For
UDP and ICMP this is 64 KByte. The value specified here is an
initial value. It is used unless the server bound to this port
changes it.
‘recv-buffer-size (integer)’
The ‘recv-buffer-size’ configuration item defines the maximum
number of bytes the receive queue of a client is allowed to grow
to. The item influences the “receive buffer underrun error
condition”. The value specified here is an initial value. It is
used unless the server bound to this port changes it.
‘connect-frequency (integer)’
This item determines the maximum number of connections per second
the port will accept. It is a kind of “hammer protection”. The
item is evaluated for each remote client machine separately. It
applies to TCP ports.
‘allow (list of strings)’
Both the ‘allow’ and ‘deny’ lists are lists of IP addresses in
dotted decimal form (e.g., ‘192.168.2.1’). The ‘allow’ list
defines the remote machines which are allowed to connect to the
port. It applies to TCP ports.
‘deny (list of strings)’
The ‘deny’ list defines the remote machines which are not allowed
to connect to the port. Each connection from one of these IP
addresses will be refused and shut down immediately. It applies to
TCP ports.
1.5.1.2 TCP port definition
...........................
Definition of a TCP port configuration with the name ‘foo-tcp-port’.
The enhanced settings are all optional including the IPADDR property
which defaults to ‘*’. The IPADDR item can contain any form of a dotted
decimal internet address, a ‘*’, ‘any’ or an interface description which
you can obtain by running ‘serveez -i’.
(define-port! 'foo-tcp-port '(
;; usual settings
(proto . tcp) ;; protocol is tcp
(port . 42421) ;; network port 42421
(ipaddr . *) ;; bind to all known interfaces
(device . eth0) ;; bind to network card
;; enhanced settings
(backlog . 5) ;; enqueue max. 5 connections
(connect-frequency . 1) ;; allow 1 connect per second
(send-buffer-size . 1024) ;; initial send buffer size in bytes
(recv-buffer-size . 1024) ;; initial receive buffer size in bytes
;; allow connections from these ip addresses
(allow . (127.0.0.1 127.0.0.2))
;; refuse connections from this ip address
(deny . (192.168.2.7))
))
1.5.1.3 Pipe port definition
............................
Definition of a pipe port configuration with the name ‘foo-pipe-port’.
When bound to a server it creates the receiving end and listens on that.
If some client accesses this named pipe the server opens the sending end
which the client has to open for reading previously.
The only mandatory item is the file name of each pipe. If you want
to specify a user creating the named pipe (file ownership) use either
the USER or the UID setting. Same goes for the items GROUP and GID.
(define-port! 'foo-pipe-port `(
(proto . pipe) ;; protocol is named pipe
;; specify the receiving endpoint
(recv . ((name . ".foo-recv") ;; name of the pipe
(permissions . #o0666) ;; create it with these permissions
(user . "calvin") ;; as user "calvin"
(uid . 50) ;; with the user id 50
(group . "heros") ;; which is in the group "heros"
(gid . 100))) ;; with the group id 100
;; specify the sending endpoint
(send . ((name . ".foo-send")
(permissions . #o0666)
(user . "hobbes")
(uid . 51)
(group . "stuffed")
(gid . 101)))
))
1.5.1.4 ICMP port definition
............................
Define an ICMP port configuration which will accept connections from the
network interface ‘127.0.0.1’ only and communicates via the message type
8 as described in the *note Tunnel Server:: chapter. The name of this
port configuration is ‘foo-icmp-port’. When you are going to bind some
server to this kind of port you have to ensure root (or Administrator
under Windows) privileges.
(define-port! 'foo-icmp-port '((proto . icmp)
(ipaddr . 127.0.0.1)
(type . 8)))
1.5.1.5 UDP port definition
...........................
Simple definition of a UDP port configuration with the name
‘foo-udp-port’.
(define-port! 'foo-udp-port `((proto . udp)
(port . 27952)))
1.5.2 Define servers
--------------------
A ‘server’ (in Serveez) is a snippet of code that implements some
protocol. There are many servers built into Serveez but you can
implement your own, too. For example we provide a webserver
implementing the Hypertext Transfer Protocol (HTTP). Each server has a
different set of options you can change. You can have many instances of
every server, each with a different set of options. For example: You
can create a webserver on TCP port 42420 publishing the Serveez
documentation and also have another webserver on a different port
publishing something else. Every server has a unique name you assign to
it. The name of the server is later used to bind it to a port.
The following example instantiates a server with the short name
“foo”. Each server in Serveez has got a short name. *Note Existing
servers::, for the details. This example demonstrates everything which
is possible in server configurations. You start a definition of a
server with the procedure ‘define-server!’. The following argument
specifies the name of the server instance (in this case ‘foo-server’)
which starts with the short name. The second argument describes the
server in detail. Each configuration item is setup with a ‘(key .
value)’ pair where KEY is the name of the configuration item and VALUE
is the value which depends on the type of the item. *Note Configuring
servers::, for a detailed description of each type of value.
(define-server! 'foo-server '(
(bar . 100) ;; number
(reply . "Booo") ;; character string
(messages . ;; list of strings
("Welcome to the foo test server."
"This one echos your lines."))
(ports . (5 6 7 8 9)) ;; list of numbers
(port . foo-tcp-port) ;; a port configuration
(assoc . (( "GNU" . "great" ) ;; associative list
( "Tree" . "tall" )))
(truth . #f) ;; boolean value
))
Serveez provides a number of server types. Each of them has a short
name. The name of the server instance has to begin with this short name
followed by a dash (-). You can append any suffix then. In the example
above “foo” is the short name and ‘foo-server’ the name of the server
instance.
1.5.3 Bind servers to ports
---------------------------
Finally you can bind servers to ports. When you do so the server you
created listens on the port, accepts connections and serves clients. It
does so as soon as Serveez enters its main loop right after running the
configuration file. Serveez won’t stop until you interrupt it (e.g., by
pressing <^C> in the terminal you started it in).
This example binds the server ‘foo-server’ (s.a.) to the port
‘foo-tcp-port’ which was described above. Therefore you need to call
the procedure ‘bind-server!’ which takes two arguments specifying the
name of a port configuration and a server instance. Both need to be
defined before you can write this statement.
(bind-server! 'foo-tcp-port 'foo-server)
One of the main features of Serveez is that you can bind multiple
servers to the same port. This for example is useful to pass braindead
firewall configurations or proxy servers. It is also possible to bind
servers to ports they are actually not designed for. This might be used
for debugging servers or other funny things (again, think about the
firewall). This is the point we have to warn you: Some protocols cannot
share the same port (e.g., the tunnel server) and some protocols simply
won’t work on ’wrong’ ports. Additionally, you will not get error
messages when that happens. The server just will not work then.
1.5.4 Additional configuration possibilities
--------------------------------------------
The three procedures ‘define-port!’, ‘define-server!’ and ‘bind-server!’
return ‘#t’ on success and ‘#f’ on failure. For your convenience we
provide some more built-in procedures, some of which are based upon
those above.
1.5.4.1 output
..............
-- Scheme Procedure: fs s [args...]
Return a string made by applying ‘simple-format #f’ to S and ARGS.
For example:
(fs "~A-~S" 'foo 42)
⇒ "foo-42"
-- Scheme Procedure: println [object...]
Do ‘display’ on each OBJECT. Then, output a newline.
-- Scheme Procedure: printsln spacer [object...]
For each OBJECT, do ‘display’ on it and on SPACER, as well. Then,
output a newline.
1.5.4.2 augmenting
..................
-- Scheme Procedure: interface-add! interface
Add INTERFACE to the list of known network interfaces. You can get
the list of known interfaces by running the shell command ‘serveez
-i’. The INTERFACE argument must be in dotted decimal form (e.g.,
‘127.0.0.1’). Serveez provides this procedure for systems where it
is unable to detect the list of network interface automatically.
-- Scheme Procedure: loadpath-add! [dir...]
Append DIR... to the server modules load path.
-- Scheme Procedure: serveez-load filename
Try to load FILENAME (via ‘primitive-load’). If FILENAME is not
absolute, search for it in the list of directories returned by
‘serveez-loadpath’. Return ‘#t’ if successful, ‘#f’ otherwise.
1.5.4.3 abstractions
....................
-- Scheme Procedure: bind-servers! [args...]
Bind all servers and ports in ARGS to each other. This is a
cross-product operation; given S servers, and P ports, ‘S * P’
bindings will be created.
-- Scheme Procedure: create-tcp-port! basename port
Define a new TCP port named by concatenating BASENAME and PORT.
Return the new name.
-- Scheme Procedure: bind-tcp-port-range! from to [servers...]
Bind the list of SERVERS to simple TCP port configurations whose
network ports range between FROM and TO both inclusive.
-- Scheme Procedure: create-udp-port! basename port
Define a new UDP port named by concatenating BASENAME and PORT.
Return the new name.
-- Scheme Procedure: bind-udp-port-range! from to [servers...]
Bind the list of SERVERS to simple UDP port configurations whose
network ports range between FROM and TO both inclusive.
1.5.4.4 rpc
...........
-- Scheme Procedure: getrpcent
Return the next RPC entry as a vector of the form: ‘#(NAME ALIASES
PROGRAM-NUMBER)’. NAME is a symbol, ALIASES is a list (possibly
empty) of symbols, and PROGRAM-NUMBER is an integer. If the list
is exhausted, return ‘#f’.
-- Scheme Procedure: getrpcbyname name
Return the RPC entry for NAME, a string. (FIXME: Should be able to
handle a symbol, too.) If no such service exists, signal error.
-- Scheme Procedure: getrpcbynumber number
Return the RPC entry for NUMBER, an integer. If no such service
exists, signal error.
-- Scheme Procedure: setrpcent [stayopen]
Open and rewind the file ‘/etc/rpc’. If optional arg STAYOPEN (an
integer) is non-zero, the database will not be closed after each
call to ‘getrpc’ (or its derivatives ‘getrpcent’, ‘getrpcbyname’,
‘getrpcbynumber’).
-- Scheme Procedure: endrpcent
Close the file ‘/etc/rpc’.
1.5.4.5 misc
............
-- Scheme Procedure: serveez-verbosity [level]
Return the verbosity level (an integer). Optional arg LEVEL means
set it to that level, instead. This setting is overridden by the
command-line ‘-v’ option.
-- Scheme Procedure: serveez-maxsockets [max]
Return the maximum number of open sockets permitted (an integer).
Optional arg MAX means set it to that number, instead. This
setting is overridden by the command-line ‘-m’ option.
-- Scheme Procedure: serveez-passwd [pw]
Return the control password (a string). Optional arg PW sets it to
that, instead. This effectively does nothing if the control
protocol is not enabled.
We now have a closer look at the internals of Serveez. If you are
not interested in that have a look at the existing servers (*Note
Existing servers::.).
2 Concept
*********
2.1 Overall concept
===================
The primary functionality Serveez provides is a framework for Internet
services. It can act as a kind of server collection and may even
replace super-servers such as the inetd daemon.
Its key features and benefits are:
• support for packet and connection oriented protocols
Serveez currently supports two server types. TCP and named pipe
servers are connection oriented servers. This type of server
accepts a client’s connection request and communicates with it
using a dedicated connection. The format of the incoming and
outgoing data streams are irrelevant to Serveez. Packet oriented
servers (like UDP and ICMP) receive data packets and respond to the
sender with data packets. A server in Serveez can detect whether
it is bound to a packet or connection oriented port configuration
and thus can act as the expected type.
• server and client functionality
Besides a wide variety of server capabilities, Serveez also
contains some client functionality. This may be necessary when a
server is meant to establish a connection to another server in
response to an incoming request. For example, imagine a protocol
where a client tells the server, “Let me be the server. Please
connect to this HOST at this PORT”. You are also able to implement
pure clients.
• platform portability
When writing this software the authors were always mindful of
platform portability. Serveez compiles and runs on various Unix
platforms as well as on Windows systems. *Note Porting issues::,
for details. Most of the routines in the core library can be used
without regard to the platform on which you are programming or the
details of its underlying system calls. Exceptions are noted in
the documentation. Platform portability also means that the server
code you write will run on other systems, too.
• powerful configuration capabilities
Server configuration has always been a complicated but very
important issue. When Serveez starts up it runs the configuration
file using the programming language Guile. In contradiction, other
(server) applications just read their configuration files and
remember the settings in it. This makes them powerful enough to
adapt the Serveez settings dynamically. Using the Guile
interpreter also means that you can split your configuration into
separate files and load these, perhaps conditionally, from the main
configuration file.
• easy server implementation
Serveez is a server framework. When implementing a new server the
programmer need pay little or no attention to the networking code
but is free to direct his attention to the protocol the server is
meant to support. That protocol may be an established one such as
HTTP, or may be a custom protocol fitting the specific
application’s requirements. The *note Writing servers:: section
describes this process in detail.
• code reusability
The Serveez package comes along with a core library (depending on
the system this is a static library, shared library or a DLL) and
its API which contains most of the functionality necessary to write
an Internet server. Most probably, a programmer can also use the
library for other (network programming related) purposes.
• server instantiation and network port sharing
Once you have written a protocol server and integrated into
Serveez’s concept of servers the user can instantiate (multiply)
the server. At the first glimpse this sounds silly, but with
different server configurations it does not. If, for example, an
administrator wishes to run multiple HTTP servers with different
document roots, Serveez will handle them all in a single process.
Also if the same administrator wants to run a HTTP server and some
other server on the same network port this is possible with
Serveez. You can run a single server on different network ports,
too.
2.2 I/O Strategy
================
Serveez’s I/O strategy is the traditional ‘select’ method. It is
serving many clients in a single server thread. This is done by setting
all network handles to non-blocking mode. We then use ‘select’ to tell
which network handles have data waiting. This is the traditional Unix
style multiplexing.
An important bottleneck in this method is that a ‘read’ or ‘sendfile’
from disk blocks if the data is not in core at the moment. Setting
non-blocking mode on a disk file handle has no effect. The same thing
applies to memory-mapped disk files. The first time a server needs disk
I/O, its process blocks, all clients have to wait, and raw non-threaded
performance may go to waste.
Unfortunately, ‘select’ is limited to the number of ‘FD_SETSIZE’
handles. This limit is compiled into the standard library, user
programs and sometimes the kernel. Nevertheless, Serveez is able to
serve about one thousand and more clients on GNU/Linux, a hundred on
Win95 and more on later Windows systems.
We chose this method anyway because it seems to be the most portable.
An alternative method to multiplex client network connections is
‘poll’. It is automatically used when ‘configure’ finds ‘poll’ to be
available. This will work around the builtin (g)libc’s ‘select’ file
descriptor limit.
2.2.1 Limits on open filehandles
--------------------------------
‘Any Unix’
The limits set by ‘ulimit’ or ‘setrlimit’.
‘Solaris’
See the Solaris FAQ, question 3.45.
‘FreeBSD’
Use sysctl -w kern.maxfiles=nnnn to raise limit.
‘GNU/Linux’
See Bodo Bauer’s /proc documentation. On current 2.2.x kernels,
echo 32768 > /proc/sys/fs/file-max
increases the system limit on open files, and
ulimit -n 32768
increases the current process’ limit. We verified that a process
on Linux kernel 2.2.5 (plus patches) can open at least 31000 file
descriptors this way. It has also been verified that a process on
2.2.12 can open at least 90000 file descriptors this way (with
appropriate limits). The upper bound seems to be available memory.
‘Windows 9x/ME’
On Win9x machines, there is quite a low limit imposed by the
kernel: 100 connections system wide (!). You can increase this
limit by editing the registry key
HKLM\System\CurrentControlSet\Services\VxD\MSTCP\MaxConnections.
On Windows 95, the key is a DWORD; on Windows 98, it’s a string.
We have seen some reports of instability when this value is
increased to more than a few times its default value.
‘Windows NT/2000’
More than 2000 connections tested. It seems like the limit is due
to available physical memory.
2.3 Alternatives to Serveez’s I/O strategy
==========================================
One of the problems with the traditional ‘select’ method with
non-blocking file descriptors occurs when passing a large number of
descriptors to the ‘select’ system call. The server loop then goes
through all the descriptors, decides which has pending data, then reads
and handles this data. For a large number of connections (say, 90000)
this results in temporary CPU load peaks even if there is no network
traffic.
Along with this behaviour comes the problem of “starving”
connections. Connections which reside at the beginning of the ‘select’
set are processed immediately while those at the end are processed
significantly later and may possibly die because of buffer overruns.
This is the reason why Serveez features priority connection: it serves
listening sockets first and rolls the order of the remaining
connections. In this way, non-priority connections are handled in a
“round robin” fashion.
Other server implementations solve these problems differently. Some
start a new process for each connection (fully-threaded server) or split
the ‘select’ set into pieces and let different processes handle them
(threaded server). This method shifts the priority scheduling to the
underlying operating system. Another method is the use of asynchronous
I/O based upon signals where the server process receives a signal when
data arrives for a connection. The signal handler queues these events
in order of arrival and the main server loop continuously processes this
queue.
3 Server
********
3.1 Introduction to servers
===========================
Serveez is a kind of server server. It allows different protocol
servers to listen on various TCP/UDP ports, on ICMP sockets and on named
pipes. Servers are instantiated with a certain configuration. It is
possible to run multiple different servers on the same port.
This chapter covers all questions about how to write your own
Internet protocol server with this package. Most of the common tasks of
such a server have got a generic solution (default routines) which could
be “overridden” by your own routines. There are some examples within
this package. They are showing the possibilities with this package and
how to implement servers.
The ‘foo’ server does not do anything at all and is of no actual use
but could be a basis for a new protocol server. We are now going to
describe how this specific server works. Eventually the reader might
get an impression of what is going on.
For better understanding the text below we will use the following
terminology:
server definition
A server definition is a ‘svz_servertype_t’ structure which
contains server specific members like its name, different
callbacks, a single default configuration and a list of
configuration items which determines what can be configured.
server configuration
A server configuration can be any kind of structure. The default
server configuration must be specified within the server definition
(see above). When instantiating a server (which is done via the
configuration file) the configuration items specified in the server
definition get processed and are put into a copy of the default
configuration. Thus we get an instance.
server instance
A server instance is a copy of the server definition including the
modified server configuration. A server gets instantiated by the
configuration file parser. The concept of server instances has
been introduced because we wanted Serveez to have the following
features. A single server can have multiple instances with
different behaviour due to different server configurations. A
server instance can be bound to multiple port configurations.
Different server instances (of the same and/or different server
type) can share the same port configuration.
port configuration
A port configuration in Serveez is represented by the
‘svz_portcfg_t’ structure. Depending on a shared flag it contains
different type of information specifying a transport endpoint.
*Note Define ports::, for more on this topic. It also can be a
special configuration item within a server configuration. This is
necessary if a server needs for some reason a remote transport
endpoint. A server instance does not usually need to know about
the port configuration it is bound to.
3.2 Writing servers
===================
Serveez is meant to be a server framework. That is why it supports
various ways to implement Internet servers. First of all there are some
servers already included in the main serveez package (*note Existing
servers::). These are called ‘Builtin servers’. Another possibility to
add a new server are ‘Embedded servers’ which are shared libraries (or
DLL’s) containing the server implementation. These can be dynamically
loaded by Serveez at runtime. This kind of server is also called
‘Server modules’. A third possibility are the ‘Guile servers’ which
allow even unexperienced schemers to write an Internet server.
This section describes each of the above possibilities in detail.
3.2.1 Embedded servers
----------------------
The core library of Serveez can be used to write standalone server
modules. Serveez defines a certain interface for shared libraries which
contain such server modules. If Serveez detects an unknown server type
(server type which is not builtin) in its configuration file it tries to
load a shared library containing this server type during startup.
3.2.1.1 Prerequisites
.....................
In order to implement a server module you need an existing installation
of Serveez. This can be achieved issuing the following commands:
$ ./configure --enable-shared --prefix=/usr/local
$ make
$ make install
After successful installation you are able to compile and link
against the Serveez core API. The headers should be available in
‘/usr/local/include’ and the library itself (‘libserveez.so’ or
‘libserveez.dll’) is located in ‘/usr/local/lib’ if you passed the
configure script ‘--prefix=/usr/local’.
3.2.1.2 Server definition
.........................
The interface mentioned in the introduction is defined via the extern
declaration of the server type in the shared library of the server
module. Imagine you want to implement a server type called ‘foo’. This
requires the external symbol ‘foo_server_definition’ in the shared
library. You can achieve this inserting the following lines into your
header file:
/* Either Unices. */
extern svz_servertype_t foo_server_definition;
/* Or Windows. */
__declspec (dllexport) extern svz_servertype_t foo_server_definition;
The data symbol ‘foo_server_definition’ must be statically filled
with the proper content (*Note Builtin servers::.)
3.2.2 Guile servers
-------------------
This section describes the Guile interface to Serveez which provides the
ability to write servers with Guile. Of course, you could do this
without any help from Serveez, but it makes the task a lot easier. This
interface reduces the Guile implementation of an Internet server to a
simple data processor.
3.2.2.1 Underlying libserveez
.............................
-- Scheme Procedure: libserveez-features
Return a list of symbols representing the features of the
underlying libserveez. For details, *Note Library features::.
3.2.2.2 Special Data Types
..........................
Serveez extends Guile by various new data types which represent internal
data structures of Serveez’s core API.
• ‘#’ represents a server type.
• ‘#’ represents a server (an instance of a server type).
• ‘#’ represents a socket structure.
3.2.2.3 Passing Binary Data
...........................
The new binary data type (‘#’) provides access to any kind
of unstructured data. It manages the data exchange between Guile and
Serveez. There are some conversion procedures for strings and lists
which help to process this binary data in a more complex (guile’ish)
way.
-- Scheme Procedure: binary->string binary
Convert the given binary smob BINARY into a string. Return the
string itself.
-- Scheme Procedure: string->binary string
Convert the given STRING into a binary smob. The data pointer of
the binary smob is marked as garbage which must be ‘free’’d in the
sweep phase of the garbage collector.
-- Scheme Procedure: binary? obj
Return ‘#t’ if OBJ is an instance of the binary smob type.
-- Scheme Procedure: list->binary list
Convert the scheme list LIST into a binary smob. Each of the
elements of LIST is checked for validity. The elements can be
either exact numbers in a byte’s range or characters.
-- Scheme Procedure: binary->list binary
Convert the given binary smob BINARY into a scheme list. The list
is empty if the size of BINARY is zero.
-- Scheme Procedure: binary-search binary needle
Search through the binary smob BINARY for NEEDLE, which can be an
exact number, character, string or another binary smob. Return
‘#f’ if the needle could not be found, or a positive number
indicating the position of the first occurrence of NEEDLE in the
binary smob BINARY.
-- Scheme Procedure: binary-set! binary index value
Set the byte at position INDEX of the binary smob BINARY to the
value given in VALUE which can be either a character or an exact
number.
-- Scheme Procedure: binary-ref binary index
Obtain the byte at position INDEX of the binary smob BINARY.
-- Scheme Procedure: binary-length binary
Return the size in bytes of the binary smob BINARY.
-- Scheme Procedure: binary-concat! binary append
Append either the binary smob or string APPEND onto the binary smob
BINARY. If BINARY has been a simple data pointer reference it is
then a standalone binary smob as returned by ‘string->binary’.
-- Scheme Procedure: binary-subset binary start [end]
Create a subset binary smob from the given binary smob BINARY. The
range of this subset is specified by START and END both inclusive
(thus the resulting size is ‘END - START + 1’). With a single
exception: If END is not given or specified with -1, return all
data until the end of BINARY.
-- Scheme Procedure: binary-reverse binary
Return a new binary smob with the reverse byte order of the given
binary smob BINARY.
-- Scheme Procedure: binary-reverse! binary
Perform an in-place reversal of the given binary smob BINARY and
return it.
-- Scheme Procedure: binary-long-ref binary index
Return the ‘long’ value of the binary smob BINARY at the array
index INDEX.
-- Scheme Procedure: binary-long-set! binary index value
Set the ‘long’ value of the binary smob BINARY at the array index
INDEX to the given value VALUE. Return the previous (overridden)
value.
-- Scheme Procedure: binary-int-ref binary index
Return the ‘int’ value of the binary smob BINARY at the array index
INDEX.
-- Scheme Procedure: binary-int-set! binary index value
Set the ‘int’ value of the binary smob BINARY at the array index
INDEX to the given value VALUE. Return the previous (overridden)
value.
-- Scheme Procedure: binary-short-ref binary index
Return the ‘short’ value of the binary smob BINARY at the array
index INDEX.
-- Scheme Procedure: binary-short-set! binary index value
Set the ‘short’ value of the binary smob BINARY at the array index
INDEX to the given value VALUE. Return the previous (overridden)
value.
-- Scheme Procedure: binary-char-ref binary index
Return the ‘char’ value of the binary smob BINARY at the array
index INDEX.
-- Scheme Procedure: binary-char-set! binary index value
Set the ‘char’ value of the binary smob BINARY at the array index
INDEX to the given value VALUE. Return the previous (overridden)
value.
3.2.2.4 Server Definition
.........................
In order to set up a new server type, you use the procedure
‘define-servertype!’. This procedure takes one argument which must be
an associative list specifying the server type in detail. There are
optional and mandatory elements you can set up in this alist.
The following example shows the overall syntax of this procedure:
(define-servertype! '(
;; Mandatory: server type prefix for later use in (define-server!)
(prefix . "foo")
;; Mandatory: server type description
(description . "guile foo server")
;; Mandatory for TCP and PIPE servers: protocol detection
(detect-proto . foo-detect-proto)
;; Optional: global server type initialisation
(global-init . foo-global-init)
;; Optional: server instance initialisation
(init . foo-init)
;; Optional: server instance finalisation
(finalize . foo-finalize)
;; Optional: global server type finalisation
(global-finalize . foo-global-finalize)
;; Mandatory for TCP and PIPE servers: socket connection
(connect-socket . foo-connect-socket)
;; Optional: server instance info
(info-server . foo-info-server)
;; Optional: client info
(info-client . foo-info-client)
;; Optional: server instance reset callback
(reset . foo-reset)
;; Optional: server instance notifier
(notify . foo-notify)
;; Mandatory for UDP and ICMP servers: packet handler
(handle-request . foo-handle-request)
;; Mandatory: server type configuration (may be an empty list)
(configuration . (
;; The server configuration is an alist (associative list) again.
;; Each item consists of an item name and a list describing the
;; item itself.
;; Syntax: (key . (type defaultable default))
(foo-integer . (integer #t 0))
(foo-integer-array . (intarray #t (1 2 3 4 5)))
(foo-string . (string #t "default-foo-string"))
(foo-string-array . (strarray #t ("guile" "foo" "server")))
(foo-hash . (hash #t (("foo" . "bar"))))
(foo-port . (portcfg #t foo-port))
(foo-boolean . (boolean #t #t))
))))
-- Scheme Procedure: define-servertype! args
Define a new server type based on ARGS. (If everything works fine
you have a freshly registered server type afterwards.) Return ‘#t’
on success.
3.2.2.5 Predefined Procedures
.............................
The following subset of procedures may be used to implement a Guile
server. They should be used within the callbacks defined in the
‘define-servertype!’ procedure. Each of these callbacks gets passed the
appropriate arguments needed to stuff into the following procedures.
Please have a look at the example Guile servers for the details.
-- Scheme Procedure: svz:sock? sock
Return ‘#t’ if the given cell SOCK is an instance of a valid
‘#’, otherwise ‘#f’.
-- Scheme Procedure: svz:sock:check-request sock [proc]
Set the ‘check-request’ member of the socket structure SOCK to
PROC. Return the previously handler if there is any.
-- Scheme Procedure: svz:sock:check-oob-request sock [proc]
Set the ‘check-oob-request’ callback of the given socket structure
SOCK to PROC, returning the previous callback (if there was any set
before). The callback is run whenever urgent data (out-of-band)
has been detected on the socket.
-- Scheme Procedure: svz:sock:send-oob sock oob
Send byte OOB as urgent (out-of-band) data through the underlying
TCP stream of TCP SOCK. Return ‘#t’ on successful completion and
otherwise (either it failed to send the byte or the passed socket
is not a TCP socket) ‘#f’.
-- Scheme Procedure: svz:sock:handle-request sock [proc]
Set the ‘handle-request’ member of the socket structure SOCK to
PROC. Return the previously set handler if there is any.
-- Scheme Procedure: svz:sock:boundary sock boundary
Setup the packet boundary of the socket SOCK. The given string
value BOUNDARY can contain any kind of data. If BOUNDARY is an
exact number, set up the socket to parse fixed sized packets. More
precisely, set the ‘check-request’ callback of the given socket
structure SOCK to an internal routine which runs the socket’s
‘handle-request’ callback when it detects a complete packet
specified by BOUNDARY.
For instance, you can arrange for Serveez to pass the
‘handle-request’ procedure lines of text by calling
‘(svz:sock:boundary sock "\n")’.
-- Scheme Procedure: svz:sock:floodprotect sock [flag]
Set or unset the flood protection bit of the given socket SOCK.
Return the previous value of this bit (‘#t’ or ‘#f’). The FLAG
argument must be either boolean or an exact number and is optional.
-- Scheme Procedure: svz:sock:print sock buffer
Write BUFFER (string or binary smob) to the socket SOCK. Return
‘#t’ on success and ‘#f’ on failure.
-- Scheme Procedure: svz:sock:final-print sock
Schedule the socket SOCK for shutdown after all data within the
send buffer queue has been sent. You should call this right
*before* the last call to ‘svz:sock:print’.
-- Scheme Procedure: svz:sock:no-delay sock [enable]
Turn the Nagle algorithm for the TCP socket SOCK on or off
depending on the optional ENABLE argument. Return the previous
state of this flag (‘#f’ if Nagle is active, ‘#t’ otherwise). By
default this flag is switched off. This socket option is useful
when dealing with small packet transfer in order to disable
unnecessary delays.
-- Scheme Procedure: svz:sock:send-buffer sock
Return the send buffer of the socket SOCK as a binary smob.
-- Scheme Procedure: svz:sock:send-buffer-size sock [size]
Return the current send buffer size and fill status in bytes of the
socket SOCK as a pair of exact numbers. If the optional argument
SIZE is given, set the send buffer to the specified size in bytes.
-- Scheme Procedure: svz:sock:receive-buffer sock
Return the receive buffer of the socket SOCK as a binary smob.
-- Scheme Procedure: svz:sock:receive-buffer-size sock [size]
Return the current receive buffers size and fill status in bytes of
the socket SOCK as a pair of exact numbers. If the optional
argument SIZE is given, set the receive buffer to the specified
size in bytes.
-- Scheme Procedure: svz:sock:receive-buffer-reduce sock [length]
Dequeue LENGTH bytes from the receive buffer of the socket SOCK, or
all bytes if LENGTH is omitted. Return the number of bytes
actually shuffled away.
-- Scheme Procedure: svz:sock:connect host proto [port]
Establish a network connection to the given HOST [ :PORT ]. If
PROTO equals ‘PROTO_ICMP’ the PORT argument is ignored. Valid
identifiers for PROTO are ‘PROTO_TCP’, ‘PROTO_UDP’ and
‘PROTO_ICMP’. The HOST argument must be either a string in dotted
decimal form, a valid hostname or an exact number in host byte
order. When giving a hostname this operation might block. The
PORT argument must be an exact number in the range from 0 to 65535,
also in host byte order. Return a valid ‘#’ or ‘#f’ on
failure.
-- Scheme Procedure: svz:sock:disconnected sock [proc]
Set the ‘disconnected-socket’ member of the socket structure SOCK
to PROC. The given callback runs whenever the socket is lost for
some external reason. Return the previously set handler if there
is one.
-- Scheme Procedure: svz:sock:kicked sock [proc]
Set the ‘kicked-socket’ callback of the given socket structure SOCK
to PROC and return any previously set procedure. This callback
gets called whenever the socket gets closed by Serveez
intentionally.
-- Scheme Procedure: svz:sock:trigger sock [proc]
Set the ‘trigger’ callback of the socket structure SOCK to PROC and
return any previously set procedure. The callback is run when the
‘trigger-condition’ callback returns ‘#t’.
-- Scheme Procedure: svz:sock:trigger-condition sock [proc]
Set the ‘trigger-condition’ callback for the socket structure SOCK
to PROC. Return the previously set procedure if available. The
callback is run once every server loop indicating whether the
‘trigger’ callback should be run or not.
-- Scheme Procedure: svz:sock:idle sock [proc]
Set the ‘idle’ callback of the socket structure SOCK to PROC.
Return any previously set procedure. The callback is run by the
periodic task scheduler when the ‘idle-counter’ of the socket
structure drops to zero. If this counter is not zero it gets
decremented once a second. The ‘idle’ callback can reset
‘idle-counter’ to some value and thus can re-schedule itself for a
later task.
-- Scheme Procedure: svz:sock:idle-counter sock [counter]
Return the socket structure SOCK’s current ‘idle-counter’ value.
If the optional argument COUNTER is given, the set the
‘idle-counter’. Please have a look at the ‘svz:sock:idle’
procedure for the exact meaning of this value.
-- Scheme Procedure: svz:sock:parent sock [parent]
Return the given socket’s SOCK parent and optionally set it to the
socket PARENT. Return either a valid ‘#’ object or an
empty list.
-- Scheme Procedure: svz:sock:referrer sock [referrer]
Return the given socket’s SOCK referrer and optionally set it to
the socket REFERRER. Return either a valid ‘#’ or an
empty list.
-- Scheme Procedure: svz:sock:server sock [server]
Return the ‘#’ object associated with the given
argument SOCK. The optional argument SERVER can be used to
redefine this association and must be a valid ‘#’
object. For a usual socket callback like ‘connect-socket’ or
‘handle-request’, the association is already in place. But for
sockets created by ‘svz:sock:connect’, you can use it in order to
make the returned socket object part of a server.
-- Scheme Procedure: svz:sock:local-address sock [address]
Return the current local address as a pair like ‘(host . port)’
with both entries in network byte order. If you pass the optional
argument ADDRESS, you can set the local address of the socket SOCK.
-- Scheme Procedure: svz:sock:remote-address sock [address]
Return the current remote address as a pair like ‘(host . port)’
with both entries in network byte order. If you pass the optional
argument ADDRESS, you can set the remote address of the socket
SOCK.
-- Scheme Procedure: svz:sock:find ident
Return the ‘#’ specified by IDENT, a pair of integers
in the form ‘(identification . version)’. If that socket no longer
exists, return ‘#f’.
-- Scheme Procedure: svz:sock:ident sock
Return a pair of numbers identifying the given ‘#’
SOCK, which can be passed to ‘svz:sock:find’. This may be
necessary when you are passing a ‘#’ through coserver
callback arguments in order to verify that the passed
‘#’ is still valid when the coserver callback runs.
-- Scheme Procedure: svz:sock:protocol sock
Return one of the ‘PROTO_TCP’, ‘PROTO_UDP’, ‘PROTO_ICMP’,
‘PROTO_RAW’ or ‘PROTO_PIPE’ constants indicating the type of the
socket structure SOCK. If there is no protocol information
available, return ‘#f’.
-- Scheme Procedure: svz:read-file port size
Return either a binary smob containing a data block read from the
open input port PORT with a maximum number of SIZE bytes, or the
end-of-file object if the underlying ports end has been reached.
The size of the returned binary smob may be less than the requested
size SIZE if it exceed the current size of the given port PORT.
Throw an exception if an error occurred while reading from the
port.
-- Scheme Procedure: svz:server? server
Return ‘#t’ if the given cell SERVER is an instance of a valid
‘#’, otherwise ‘#f’.
-- Scheme Procedure: svz:server:listeners server
Return a list of listening ‘#’ smobs to which the given
server instance SERVER is currently bound, or an empty list if
there is no such binding yet.
-- Scheme Procedure: svz:server:clients server
Return a list of ‘#’ client smobs associated with the
given server instance SERVER in arbitrary order, or an empty list
if there is no such client.
-- Scheme Procedure: svz:server:config-ref server key
Return the configuration item specified by KEY of the given server
instance SERVER. You can pass this procedure a socket, too, in
which case the appropriate server instance is looked up. If the
given string KEY is invalid (not defined in the configuration alist
in ‘define-servertype!’), then return an empty list.
-- Scheme Procedure: serveez-port? name
Return ‘#t’ if the given string NAME corresponds with a registered
port configuration, otherwise ‘#f’.
-- Scheme Procedure: serveez-server? name
Check whether the given string NAME corresponds with an
instantiated server name and return ‘#t’ if so.
-- Scheme Procedure: serveez-servertype? name
Check whether the given string NAME is a valid server type prefix
known in Serveez and return ‘#t’ if so. Otherwise return ‘#f’.
-- Scheme Procedure: serveez-exceptions [enable]
Control the use of exception handlers for the Guile procedure calls
of Guile server callbacks. If the optional argument ENABLE is
‘#t’, enable exception handling; if ‘#f’, disable it. Return the
current (boolean) setting.
-- Scheme Procedure: serveez-nuke [exit-value]
Shutdown all network connections and terminate after the next event
loop. You should use this instead of calling ‘quit’. Optional arg
EXIT-VALUE specifies an exit value for the serveez program. It is
mapped to a number via ‘scm_exit_value’.
-- Scheme Procedure: serveez-loadpath [args]
Make the search path for the Serveez core library accessible to
Scheme. Return a list a each path as previously defined. If ARGS
is specified, override the current definition of this load path
with it. The load path is used to tell Serveez where it can find
additional server modules.
-- Scheme Procedure: serveez-interfaces [args]
Make the list of local interfaces accessible to Scheme. Return the
local interfaces as a list of ip addresses in dotted decimal form.
If ARGS are specified, they are added as additional local
interfaces.
-- Scheme Procedure: getrpc [arg]
Lookup a network rpc service ARG (name or service number), and
return a network rpc service object. If given no arguments, it
behave like ‘getrpcent’.
-- Scheme Procedure: setrpc [stayopen]
Open and rewind the file ‘/etc/rpc’. If the STAYOPEN flag is
non-zero, the net data base will not be closed after each call to
‘getrpc’. If STAYOPEN is omitted, this is equivalent to calling
‘endrpcent’. Otherwise it is equivalent to calling ‘setrpcent’
with arg 1.
-- Scheme Procedure: portmap prognum versnum [protocol [port]]
Establish a (portmap service) mapping between the triple
[PROGNUM,VERSNUM,PROTOCOL] and PORT on the machine’s portmap
service. The value of PROTOCOL is most likely ‘IPPROTO_UDP’ or
‘IPPROTO_TCP’. If instead PROTOCOL and PORT are omitted, destroy
all mapping between the triple [PROGNUM,VERSNUM,*] and ports on the
machine’s portmap service.
-- Scheme Procedure: portmap-list [address]
Return a list of the current RPC program-to-port mappings on the
host located at IP address ADDRESS, which defaults to the local
machine’s IP address. Return an empty list if either there is no
such list available or an error occurred while fetching the list.
-- Scheme Procedure: svz:coserver:dns host callback
Enqueue the HOST string argument into the internal DNS coserver
queue. When the coserver responds, the procedure CALLBACK is run
as ‘(callback addr)’. The ADDR argument passed to the callback is
a string representing the appropriate IP address for the given
hostname HOST.
-- Scheme Procedure: svz:coserver:reverse-dns addr callback
Enqueue the given ADDR argument, which must be an IP address in
network byte order, into the internal reverse DNS coserver queue.
When the coserver responds, the procedure CALLBACK is run as
‘(callback host)’ where HOST is the hostname of the requested IP
address ADDR.
-- Scheme Procedure: svz:coserver:ident sock callback
Enqueue the given ‘#’ SOCK into the internal ident
coserver queue. When the coserver responds, it runs the procedure
CALLBACK as ‘(callback user)’, where USER is the corresponding
username for the client connection SOCK.
3.2.2.6 Callback Prototypes
...........................
The Guile interface of Serveez is completely callback driven. Callbacks
can be set up in the associative list passed to ‘define-servertype!’, or
by using the predefined procedures described in the previous section.
Each of the callbacks is passed certain arguments and is meant to return
specific values to indicate success or failure. This section describes
each of these callbacks.
-- Scheme Procedure: global-init servertype
This callback is invoked once for every type of server right after
the ‘define-servertype!’ statement. Here you can initialise
resources shared between all instances of your server type. The
callback is optional and can be set up in ‘define-servertype!’. It
should return zero to indicate success and non-zero to indicate
failure. If the global initialiser fails, Serveez will refuse to
register the server type.
-- Scheme Procedure: global-finalize servertype
If you want to free shared resources, which were possibly allocated
within the global initialiser, you can do so here. The callback is
invoked when Serveez shuts down (issued by ‘serveez-nuke’) or the
server type gets unregistered for some reason. It should return
zero to signal success. The callback can be set up in
‘define-servertype!’ and is optional.
-- Scheme Procedure: init server
Within this callback you can initialise everything you might need
for a single instance of your server. The callback is invoked for
each server instance which has been created by ‘define-server!’ and
should return zero to indicate success, otherwise Serveez rejects
the server instance. The callback can be set up in
‘define-servertype!’ and is optional.
-- Scheme Procedure: finalize server
The server instance finaliser gets its instance representation
passed as argument. You need to free all resources used by this
server instance which might have been allocated within the server
instance initialiser or consumed while running. You can set this
callback in the ‘define-servertype!’ statement. The callback is
optional and should return zero to indicate success.
-- Scheme Procedure: detect-proto server socket
Connection oriented protocols like TCP and PIPE allow more than one
server to be listening on the same network port. Therefore, it is
necessary to be able to detect the type of client connecting to a
port.
This callback takes two arguments; the first is the server instance
and the second is the client socket object containing the client
connection information. You can set up this callback in the
‘define-servertype!’ statement.
Serveez may invoke this callback several times as data becomes
available from the client until one of the servers recognises it.
The servers can retrieve the data received so far using the
‘svz:sock:receive-buffer’ call.
To indicate successful client detection, you need to return a
non-zero value. (Note that for historical reasons, this is
inconsistent with other procedures which return zero on successful
completion.) Once the server has indicated success, Serveez
invokes any further callbacks for the connection only on that
server.
If no server has recognised the client after the first 16 bytes,
Serveez will close the connection. The connection will also be
closed if the client has not sent enough data for a server to
recognise it within 30 seconds of connecting.
If multiple servers are listening on the same network port, Serveez
invokes this callback for each of them in an arbitrary order. Only
one server at most should indicate successful detection.
This callback is mandatory for servers which get bound to
connection oriented protocol (TCP and PIPE) port configurations by
‘bind-server!’.
-- Scheme Procedure: connect-socket server socket
If the client detection signalled success, this callback is invoked
to assign the client connection to a server instance. The
arguments are the same as the detection callback. In this callback
you can assign all the connection specific callbacks for your
server and perform some initial tasks. Basically you should
specify the ‘handle-request’ and/or ‘check-request’ callback. This
can be achieved by calling ‘svz:sock:handle-request’ and
‘svz:sock:check-request’. The ‘connect-socket’ callback is also
mandatory for connection oriented protocols and must be defined in
‘define-servertype!’. On success you should return zero, otherwise
the connection will be shutdown by Serveez.
-- Scheme Procedure: info-server server
This callback gets invoked when requested by the builtin *note
Control Protocol Server::. The callback is optional and can be set
up in ‘define-servertype!’. The returned character string can be
multiple lines separated by ‘\r\n’ (but without a trailing
separator). Usually you will return information about the server
instance configuration and/or state.
-- Scheme Procedure: info-client server socket
This callback is optional. You can set it up in the
‘define-servertype!’ procedure. It is meant to provide socket
structure specific information. (The socket structure is a
client/child of the given server instance.) You need to return a
single line character string without trailing newlines. The
information provided can be requested by the builtin *note Control
Protocol Server::.
-- Scheme Procedure: notify server
The server instance notifier callback will be invoked whenever
there is idle time available. In practice, it is run approximately
once a second. A server instance can use it to perform periodic
tasks. The callback is optional and can be set up in
‘define-servertype!’.
-- Scheme Procedure: reset server
This callback is invoked when the Serveez process receives a
‘SIGHUP’ signal which can be issued via ‘killall -HUP serveez’ from
user land. If the underlying operating system does not provide
‘SIGHUP’ there is no use for this callback. It provides the
possibility to perform asynchronous tasks scheduled from outside
Serveez. You can optionally set it up in the ‘define-servertype!’
procedure.
-- Scheme Procedure: handle-request socket binary size
This callback is invoked whenever a complete packet has been
detected in the receive buffer. The packet data is passed to the
callback as a ‘#’. The SIZE argument is passed for
convenience and specifies the length of the packet in bytes.
The detection, and therefore the invocation, can be made in one of
two ways. When Serveez can determine itself when a packet is
complete, the callback will be invoked directly. Serveez can make
this determination for connections with packet oriented protocols
such as UDP and ICMP, or if you tell Serveez how to parse the
packet using ‘svz:sock:boundary sock delimiter’ or
‘svz:sock:boundary sock size’ and do not specify a ‘check-request’
callback.
Whenever you specify a ‘check-request’ callback to determine when a
packet is complete, it becomes the responsiblity of that callback
to invoke ‘handle-request’ itself.
Serveez recognises two different return value meanings. For
connection oriented protocols (TCP and PIPE), zero indicates
success and non-zero failure; on failure, Serveez will shutdown the
connection. For packet oriented protocols (UDP and ICMP), a
non-zero return value indicates that your server was able to
process the passed packet data, otherwise (zero return value) the
packet can be passed to other servers listening on the same port
configuration.
This callback must be specified in ‘define-servertype!’ for packet
oriented protocols (UDP and ICMP) but is optional otherwise. You
can modify the callback by calling ‘svz:sock:handle-request’.
-- Scheme Procedure: check-request socket
This callback is invoked whenever new data has arrived in the
receive buffer. The receive buffer of the given ‘#’
can be obtained using ‘svz:sock:receive-buffer’. The callback is
initially not set and can be set up with ‘svz:sock:check-request’.
Its purpose is to check whether a complete request was received.
If so, it should be handled (by running the ‘handle-request’
callback) and removed from the receive buffer (using
‘svz:sock:receive-buffer-reduce’). The callback is for connection
oriented protocols (TCP and PIPE) only. You should return zero to
indicate success and non-zero to indicate failure. On failure
Serveez shuts the connection down.
-- Scheme Procedure: disconnected socket
The ‘disconnected’ callback gets invoked whenever the socket is
lost for some external reason and is going to be shutdown by
Serveez. It can be set up with ‘svz:sock:disconnected’.
-- Scheme Procedure: kicked socket reason
This callback gets invoked whenever the socket gets closed by
Serveez intentionally. It can be set up with ‘svz:sock:kicked’.
The REASON argument can be either ‘KICK_FLOOD’, indicating the
socket is a victim of the builtin flood protection, or ‘KICK_QUEUE’
which indicates a send buffer overflow.
-- Scheme Procedure: idle socket
The ‘idle’ callback gets invoked from the periodic task scheduler,
which maintains a ‘idle-counter’ for each socket structure. This
counter is decremented whenever Serveez becomes idle and the
callback is invoked when it drops to zero. The ‘idle’ callback can
set its socket’s ‘idle-counter’ to some value with the procedure
‘svz:sock:idle-counter’ and thus re-schedule itself for a later
task. You can set up this callback with ‘svz:sock:idle’.
-- Scheme Procedure: trigger-condition socket
This callback is invoked once every server loop for the socket
structure. If you return ‘#f’ nothing else is happening.
Otherwise the ‘trigger’ callback will be invoked immediately. You
can set up the callback using the procedure
‘svz:sock:trigger-condition’.
-- Scheme Procedure: trigger socket
The ‘trigger’ callback is invoked when the ‘trigger-condition’
returns ‘#t’. The callback can be set up with the procedure
‘svz:sock:trigger’. Returning a non-zero value shuts the
connection down. A zero return value indicates success. This
callback can be used to perform connection related updates, e.g.,
you can ensure a certain send buffer fill.
-- Scheme Procedure: check-oob-request socket oob-byte
This callback is invoked whenever urgent data (out-of-band) has
been detected on a socket. Initially this event is ignored and the
callback can be set up with the procedure
‘svz:sock:check-oob-request’. The OOB-BYTE argument is a number
containing the received out-of-band data byte ranging from 0 to
255. If the callback returns non-zero the connection will be
shutdown. A zero return value indicates success. You can use
‘svz:sock:send-oob’ to send a single out-of-band data byte.
*Please note*: The urgent data is not supported by all operating
systems. Also it does not work for all types of network protocols.
We verified it to be working for TCP streams on GNU/Linux 2.x.x and
Windows 95; let us know if/how it works on other platforms.
3.2.3 Builtin servers
---------------------
All of the servers listed in *note Existing servers:: are builtin
servers. The following sections describe in detail how to setup a new
builtin server type. This kind of server will be part of the Serveez
executable. That is why you should make it configurable in the
configure script via a ‘--enable-xxxserver’ argument.
3.2.3.1 Making and configuring preparations
...........................................
Serveez is configured and built via automake and autoconf. That is why
you are not supposed to write your own Makefiles but simplified
‘Makefile.am’s. Automake will automatically generate dependencies and
compiler/linker command lines. Here are the steps you basically need to
follow:
• Change to the ‘src/’ directory in the source tree.
• Edit the ‘Makefile.am’. Add your sub directory name and library
name which you are going to create.
• Now create the sub directory and change into it.
• You need to create a new ‘Makefile.am’ therein. If you want to
have this file ‘configure’d you need to add a further line to the
‘AC_OUTPUT’ statement in ‘configure.ac’ which is in the top level
directory. You have to put at least the following into the newly
created ‘Makefile.am’:
noinst_LIBRARIES = libfoo.a
libfoo_a_SOURCES = foo-proto.h foo-proto.c
INCLUDES = $(SERVEEZ_CFLAGS) -I$(top_srcdir)/src
CLEANFILES = *~
MAINTAINERCLEANFILES = Makefile.in
• Just have a look at all the other server directories. For more
information about automake read the info pages.
3.2.3.2 Server header file ‘foo-proto.h’
........................................
This file contains at least your server’s ‘extern’ declaration of your
server definition which must be available from the outside. The ‘foo’
server implements all kinds of configuration items which can be
integers, integer arrays, strings, string arrays, port configurations,
booleans and hash maps. Every item of the server configuration can
later be manipulated from the configuration file.
3.2.3.3 Server implementation file ‘foo-proto.c’
................................................
If you want to define default values for your configuration you have to
define them somewhere and put them into the default configuration
structure. This structure will be used to instantiate your server. For
this example we simply called it simply ‘foo_config’.
In order to associate the configuration items in a server
configuration to keywords within the configuration file you have to
define an array of key-value-pairs. This is done in the
‘foo_config_prototype’ field. There are several macros which make
different associations. These are the ‘SVZ_REGISTER_*’ macros which
take three arguments. The first argument is the keyword which will
occur in the configuration file, the second is the associated item in
your default configuration structure and the last argument specifies if
this item is defaultable or not.
3.2.3.4 Server definition
.........................
The server definition is in a way the ‘class’ of your server. Together
with the default values (‘foo_config_prototype’) it serves as a template
for newly instantiated servers. The structure contains a long and a
short description of your server. The short name is used as the prefix
for all server instances of this specific type. The long description is
used in the control protocol (*Note Control Protocol Server::.). The
server definition also contains the callbacks your server (mandatorily)
provides.
3.2.3.5 Server callbacks
........................
There are several callback routines, which get called in order to
instantiate the server and for describing the actual behaviour of your
server. Here are the description of all of these callbacks. Some of
them have to be implemented. Others have reasonable default values.
‘global initializer (optional)’
This callback is executed once for every type of server. Here you
can initialize data or whatever is shared between all instances of
your server. For instance the HTTP server initializes its file
cache here.
‘global finalizer (optional)’
If you want to free shared resources which were possibly allocated
within the global initializer you can do so here. The foo server
frees its default hash previously allocated in the global
initializer.
‘instance initializer (mandatory)’
Within this routine you can initialize everything you might need
for one instance of your server. The foo server does not do
anything in this callback.
‘instance finalizer (optional)’
The server instance finalizer gets its instance representation as
argument. You have to free all resources used by this server
instance.
‘protocol detection (mandatory)’
Because it is possible to have more than one server listening on
one network port we need to detect the type of client which is
connecting to this port. The foo server checks if the first five
bytes the client was sending is identifying it as a foo client.
This routine is getting two arguments where the first one is a
pointer to this servers instance and the second is the client
socket object containing all information of the client connection.
This structure is described a bit later. Be patient. For
successful client detection return non-zero value.
‘socket connection (mandatory)’
If the client detection signaled success this routine is called to
assign the client connection to the server instance. The arguments
are just the same as in the detection routine. In this callback
you can assign all the connection specific callbacks for your
server and do some initial things. The foo server sets the
‘check_request’ callback to the default ‘svz_sock_check_request’
which is using the packet delimiter information to find whole
packets. When a client sent such a packet the ‘handle_request’
callback is executed. That is why the foo server assigns the
‘handle_request’ method.
‘client info (optional)’
If this callback is given the control protocol (*Note Control
Protocol Server::.) can give information about a specific client
if requested with ‘stat id NUM’. The first argument given is the
server instance and the second one the client’s socket structure.
You have to return a static single line character string.
‘server info (optional)’
This function is called when listing the server instances via ‘stat
all’ from the control protocol (*Note Control Protocol Server::.).
The returned character string might be multilined separated by
‘\r\n’ (no trailing separator). Usually you will return all the
server configuration information.
‘notifier (optional)’
If this callback is not ‘NULL’ it is called whenever there is some
time left. It gets the server instance itself as argument.
Actually it gets called every second.
‘handle request (mandatory for UDP and ICMP servers)’
The arguments to this callback are the client’s socket structure,
the address of the packet data and its length. When implementing a
UDP or ICMP server you need to return non-zero if your server could
process the packet. Thus it is possible that there are multiple
UDP servers on a single port.
3.2.3.6 Make your server available
..................................
You distribute your server by editing the ‘cfgfile.c’ file in the ‘src/’
directory. There you have to include the servers header file and add
the server definition by calling ‘svz_servertype_add’
3.2.3.7 More detailed description of the callback system and structures
.......................................................................
The client connection information is stored within the ‘svz_socket_t’
object. All of the client connection specific callbacks get this object
as first argument. Following is a description of the most important
elements of this object.
‘int id’
The socket id is a unique id for a client connection.
‘int version’
This item validates this socket structure. If you pass the ‘id’
and ‘version’ to a coserver you can check if the delivered socket
structure is the original or not within the coserver callback.
‘int proto’
The ‘proto’ flag determines a server sockets protocol type which
can be ‘PROTO_PIPE’, ‘PROTO_TCP’, ‘PROTO_UDP’, ‘PROTO_ICMP’ or
‘PROTO_RAW’.
‘int flags’
The flag field of the client connection contains informations about
the state of this connection. See ‘socket.h’ in the
‘src/libserveez/’ directory for more information. Basically this
bitfield specifies how this object is handled by the main server
loop.
‘int userflags’
This bitfield could be used for protocol specific information. You
can use it for any information.
‘char *boundary, int boundary_size’
If you are going to write a packet oriented protocol server you can
use the ‘svz_sock_check_request’ method to parse packets. These
two properties describe the packet delimiter.
‘char *send_buffer, int send_buffer_size, int send_buffer_fill’
This is the outgoing data for a client connection object.
‘char *recv_buffer, int recv_buffer_size, int recv_buffer_fill’
Within the receive buffer all incoming data for a connection object
is stored. This buffer is at least used for the client detection
callback.
‘int read_socket (svz_socket_t)’
This callback gets called whenever data is available on the socket.
Normally, this is set to a default function which reads all
available data from the socket and feeds it to ‘check_request’, but
specific sockets may need other policies.
‘int write_socket (svz_socket_t)’
This routine is called when data is is valid in the output buffer
and the socket gets available for writing. You normally leave this
callback untouched. It simply writes as much data as possible to
the socket and removes the data from the send buffer.
‘int disconnected_socket (svz_socket_t)’
This gets called whenever the socket is lost for some external
reason.
‘int connected_socket (svz_socket_t)’
If some piece of code tries to connect to another host via
‘svz_tcp_connect’ this connection might be established some time
later. This callback gets called when the socket is finally
connected.
‘int kicked_socket (svz_socket_t, int)’
We call this whenever the socket gets closed by us. The second
argument specifies a reason.
‘int check_request (svz_socket_t)’
This gets called whenever data was read from the socket. Its
purpose is to check whether a complete request was read, and if it
was, it should be handled and removed from the input buffer.
‘int handle_request (svz_socket_t, char *, int)’
This gets called when the ‘check_request’ got a valid packet. The
request arguments contains the actual packet and the second
argument is the length of this packet including the packet
delimiter.
‘int idle_func (svz_socket_t)’
This callback gets called from the periodic task scheduler.
Whenever ‘idle_counter’ (see below) is non-zero, it is decremented
and ‘idle_func’ gets called when it drops to zero. ‘idle_func’ can
reset ‘idle_counter’ to some value and thus can re-schedule itself
for a later task.
‘int idle_counter’
Counter for calls to ‘idle_func’.
‘void *data’
Miscellaneous field. Listener keeps array of server instances
here. This array is ‘NULL’ terminated. Some servers store server
specific information here.
‘void *cfg’
When the final protocol detection has been done ‘cfg’ should
contain a pointer to the actual configuration hash map taken from
the server instance object.
3.2.3.8 Using coservers
.......................
Coservers are designed to complete blocking tasks. Each coserver runs
in its own thread/process. There are several coservers implemented: the
dns, reverse dns and ident coserver. You need to implement the callback
which gets called when a coserver completed its task. This routine must
be a ‘svz_coserver_handle_result_t’. The first argument is the actual
coserver result which might be ‘NULL’ if the request could not be
fulfilled and the latter two arguments are the arguments you specified
yourself when issuing the request. To invoke a coserver you use one of
the ‘svz_coserver_*’ macros. The foo server uses the reverse dns
coserver to identify the host name of the remote client.
3.3 Some words about server configuration
=========================================
If you define a server you basically pass an instance name and a list of
items to the ‘define-server!’ procedure. Each item has a name and a
value. A value has a type. We provide several types: integers
(numbers), integer arrays, strings, string arrays, booleans
(yes/no-values), hashes (associations) and port configurations.
The following table shows how each kind of value is set up in the
configuration file. ITEM is the name of the item to be configured.
Integer
Example: (item . 42)
Integer array
Example: (item . (0 1 2 3))
String
Example: (item . "a character string")
String array
Example: (item . ("abc" "cba" "bca" "acb"))
Boolean
A normal boolean in guile is represented by #t or #f. But the
configuration file parser additional understand some bare words and
numbers.
Example: (item . #f)
Hash
Hash maps associate keys with values. Both must be character
strings.
Example: (item . (key1 . "value1") (key2 . "value2"))
Port configuration
*Note Define ports::, for more information on this. When
configuring a port configuration you need to define it via
‘define-port!’ previously and put its symbolic name into the
configuration.
Example: (item . foo-tcp-port)
The next chapter describes the servers currently implemented using
Serveez. The configuration items used by each of them are described in
the following format:
‘NameOfTheItem (Type, default: DefaultValue, Comments)’
Description of the configuration item named ‘NameOfTheItem’ (case
sensitive). ‘Type’ can be either ‘integer’, ‘integer array’,
‘string’, ‘string array’, ‘boolean’, ‘hash’ or ‘port
configuration’. The ‘Comments’ is an optional text.
The example configuration file ‘data/serveez.cfg’ contains an example
definition of each server already implemented. You can copy and modify
the example for an easy start.
3.4 Existing servers
====================
3.4.1 HTTP Server
-----------------
3.4.1.1 General description
...........................
The integrated HTTP server was originally meant to be a simple but fast
document server. But now it can even execute CGI scripts. The GET,
HEAD and POST methods are fully functional. Additionally Serveez
produces directory listings when no standard document file (e.g.,
‘index.html’) has been found at the requested document node (directory).
Furthermore it implements a file cache for speeding up repetitive HTTP
request.
In comparison to other web server projects like Apache and Roxen this
web server is really fast. Comparative benchmarks will follow. The
benchmark system is a 233 MHz Mobile Pentium MMX. Both the server and
the client (http_load - multiprocessing http test client) ran on the
same computer.
‘Small files’
The small-file test load consists of 1000 files, each 1KB long,
requested randomly.
concurrent fetches 1 10 50 100 200 500 1000
hits/second 501 520 481 475 420 390 295
‘CGI’
The CGI test load consists of a trivial “hello world” C program. I
noticed GNU/Linux (2.2.17 in this case, probably others too) to
throw “Resource temporarily unavailable” errors when ‘fork’ing very
fast. This limits the test to about 200 concurrent fetches on the
test system.
‘Large files’
The large-file test load consists of 100 files, each 1MB long,
requested randomly. Also, each connection is throttled to simulate
a 33.6Kbps modem. Note that 1000 33.6Kbps connections is 3/4 of a
T3. There was no problem to get 1000+ concurrent fetches.
3.4.1.2 Configuration
.....................
The following options can be set from the configuration file.
‘indexfile (string, default: index.html)’
The ‘indexfile’ parameter is the default file served by the HTTP
server when the user does not specify a file but a document node
(e.g., ).
‘docs (string, default: ../show)’
The ‘docs’ parameter is the document root where the server finds
its web documents.
‘userdir (string, default: public_html)’
Each ‘~user’ request gets converted into the given users home
directory. The string will be appended to this directory. Its
default value is ‘public_html’.
‘cgi-url (string, default: /cgi-bin)’
This parameter is the first part of the URL the HTTP server
identifies a CGI request. For instance if you specify here
‘/cgi-bin’ and the user requests
then the HTTP server tries to
execute the program ‘test.pl’ within the ‘cgi-dir’ (see below) and
pipes its output to the user.
‘cgi-dir (string, default: ./cgibin)’
The ‘cgi-dir’ is the CGI document root (on the server).
‘cgi-application (hash, default: empty)’
Within the MinGW32 port you can use this hash to associate certain
file suffices with applications on your computer (e.g., ‘pl’ with
‘perl’). This is necessary because there is no possibility to
check whether a file is executable on Win32.
‘cache-size (integer, default: 200 kb)’
This specifies the size of the document cache in bytes for each
cache entry.
‘cache-entries (integer, default: 64)’
This parameter specifies the maximum number of HTTP file cache
entries (files). When you instantiate more than one HTTP server
the biggest value wins. The HTTP file cache is shared by all HTTP
servers.
*Please note*: If your harddrive/filesystem combination proves to
be faster than the HTTP file cache you should disable it by setting
both ‘cache-size’ and ‘cache-entries’ to zero.
‘timeout (integer, default: 15)’
The ‘timeout’ value is the amount of time in seconds after which a
keep-alive connection (this is a HTTP/1.1 feature) will be closed
when it has been idle.
‘keepalive (integer, default: 10)’
On one keep-alive connection can be served the number of
‘keepalive’ documents at all. Then the connection will be closed.
Both this and the ‘timeout’ value are just to be on the safe side.
They protect against idle and high traffic connections.
‘default-type (string, default: text/plain)’
The ‘default-type’ is the default content type the HTTP server
assumes if it can not identify a served file by the ‘types’ hash
and the ‘type-file’ (see below).
‘type-file (string, default: /etc/mime.types)’
This should be a file like the ‘/etc/mime.types’ on Unix systems.
It associates file suffices with MIME types.
‘types (hash, default: empty)’
If you want to specify special content types do it here. This
parameter is a hash map associating file suffices with HTTP content
types (MIME types).
‘admin (string, default: root@localhost)’
Your address, where problems with the server should be e-mailed.
This address appears on some server-generated pages, such as error
documents.
‘host (string, default: localhost)’
This is the host name of your web server. Sometimes the server has
to send back its own name to the client. It will use this value.
Be aware that you cannot invent such a name.
‘nslookup (boolean, default: false)’
If this is true the HTTP server invokes a reverse DNS lookup for
each client connection in order to replace the remote ip address
with the remote host name in the access logfile.
‘ident (boolean, default: false)’
If this is true the HTTP server processes identd requests for each
client connection for logging purposes.
‘logfile (string, default: http-access.log)’
The location of the access logfile. For each HTTP request a line
gets appended to this file.
‘logformat (string, default: CLF)’
The format of the access logfile. There are special placeholders
for different kinds of logging information. The default log format
is the Common Log Format (CLF). It contains a separate line for
each request. A line is composed of several tokens separated by
spaces.
CLF = host ident authuser date request status bytes
If a token does not have a value then it is represented by a hyphen
(-). The meanings and values of these tokens are as follows:
‘%h (host)’
The fully-qualified domain name of the client, or its IP
number if the name is not available.
‘%i (ident)’
This is the identity information reported by the client. Not
active, so we will see a hyphen (-).
‘%u (authuser)’
If the request was for an password protected document, then
this is the userid used in the request.
‘%t (date)’
The date and time of the request, in the following format:
date = [day/month/year:hour:minute:second zone]
day = 2*digit
month = 3*letter
year = 4*digit
hour = 2*digit
minute = 2*digit
second = 2*digit
zone = (`+' | `-') 4*digit
‘%R (request)’
The request line from the client, enclosed in double quotes
(").
‘%r (referrer)’
Which document referred to this document.
‘%a (agent)’
What kind of web browser did the remote client use.
‘%c (status)’
The three digit status code returned to the client.
‘%l (bytes)’
The number of bytes in the object returned to the client, not
including any headers.
3.4.2 IRC Server
----------------
3.4.2.1 General description
...........................
Internet Relay Chat. The mother of all chat systems. The integrated
IRC server is intended to be compatible with the EFNet. There are no
good possibilities to test this in real life, so it is still under heavy
construction. But it can be used as a standalone server anyway.
IRC itself is a teleconferencing system, which (through the use of
the client-server model) is well-suited for running on many machines in
a distributed fashion. A typical setup involves a single process (the
server) forming a central point for clients (or other servers) to
connect to, performing the required message delivery/multiplexing and
other functions.
The server forms the backbone of IRC, providing a point for clients
and servers to connect to. Clients connect to talk to each other.
Servers connect to build up a network of servers. IRC server
connections have to build up a spanning tree. Loops are not allowed.
Each server acts as a central node for the rest of the network it sees.
3.4.2.2 Configuration
.....................
The following table shows the configuration keys provided. Most of the
configuration items are similar to those of an Hybrid IRC server. They
seem archaic at first sight but IRC operators are used to it. Refer to
the Hybrid documentation for further information. It can be found on
the EFNet web page.
‘MOTD-file (string, default: ../data/irc-MOTD.txt)’
When a user initially joins it will get this file’s content as the
message of the day comment. When changing on disk the server will
notice that and reload the file automatically.
‘INFO-file (string, default: no file)’
The ‘INFO-file’s content gets displayed when the user issues the
/INFO command.
‘tsdelta (integer, default: 0)’
This value is the timestamp delta value to UTC (Coordinated
Universal Time) in seconds.
‘channels-per-user (integer, default: 10)’
Configures the maximum number of channels a single local user can
join.
‘admininfo (string, no default)’
Some administrative information delivered on the /ADMIN command.
‘M-line (string, no default, mandatory)’
The TCP level configuration of this IRC server. The server info
field is sometimes given to the client for informational use. The
server will croak about if the settings do not correspond with the
actual bindings. The format of this line is:
":" virtual hostname
":" optional bind address (real hostname)
":" server info: "World's best IRC server"
":" port
‘A-line (string, no default, mandatory)’
The administrative info, printed by the /ADMIN command.
":" administrative info (department, university)
":" the server's geographical location
":" email address for a person responsible for the IRC server
‘Y-lines (string array, no default, suggested)’
The connection classes. They are used in other parameters (e.g.,
I-lines). A Y-line describes a group of connections. You usually
have at least two Y-lines: One for server connections and one for
client connections. Format of each line is:
":" class number (higher numbers refer to a higher priority)
":" ping frequency (in seconds)
":" connect frequency in seconds for servers, 0 for
client classes
":" maximum number of links in this class
":" send queue size
‘I-lines (string array, no default, mandatory)’
Authorization of clients, wildcards permitted, a valid client is
matched OR .
":" user@ip, you can specify ‘NOMATCH’ here to force
matching user@host
":" password (optional)
":" user@host
":" password (optional)
":" connection class number (YLine)
‘O-lines (string array, no default, optional)’
Authorize operator, wildcards allowed.
":" user@host, user@ forces checking ident
":" password
":" nick
‘o-lines (string array, no default, optional)’
Authorize local operator.
":" user@host, user@ forces checking ident
":" password
":" nick
‘C-lines (string array, no default, networked)’
List of servers to connect to. Note: C and N lines can also use
the user@ combination in order to check specific users (ident)
starting servers. C and N lines are usually given in pairs.
":" host name
":" password
":" server name (virtual)
":" port (if not given we will not connect)
":" connection class number (YLine)
‘N-lines (string array, no default, networked)’
Servers which may connect.
":" host name
":" password
":" server name (virtual host name)
":" password
":" how many components of your own server's name to strip
off the front and be replaced with a ‘*’.
":" connection class number (YLine)
‘K-lines (string array, no default, optional)’
Kill user, wildcards allowed.
":" host
":" time of day
":" user
3.4.3 Control Protocol Server
-----------------------------
If the GNU Serveez package is configured with the control protocol
enabled, running ‘serveez --help’ will show the option ‘-P’ and the
following documentation applies. Otherwise, feel free to skip to the
next section.
3.4.3.1 General description
...........................
Serveez implements something like a telnet protocol for administrative
purposes. You just need to start a telnet session like:
$ telnet www.lkcc.org 42420
After pressing you will be asked for a password which you might
setup passing Serveez the -P argument. *Note Using Serveez::. The next
section describes the interactive commands available.
3.4.3.2 Using the Control Protocol
..................................
‘help’
This command will give you a very short help screen of all
available commands.
‘quit’
This command closes the connection to Serveez.
‘restart ident’
Restarts the internal ident coserver. This is useful if you just
want to start a new one if the old one died or is otherwise
unusable.
‘restart dns’
Restarts the internal dns lookup server.
‘restart reverse dns’
Restarts the internal reverse dns lookup server.
‘killall’
This might be useful if Serveez seems to be unstable but you do not
want to restart it. With ‘killall’ you disconnect all client
network connections except the control protocol connections.
‘kill id NUM’
Disconnects a specific connection identified by its ID. These IDs
will be stated when you type ‘stat con’ (see below).
‘stat’
General statistics about Serveez. This will show you some useful
information about the computer Serveez is running on and about the
state of Serveez in general.
‘stat coserver’
Statistics about all running coserver instances.
‘stat SERVER’
This command is for selecting certain server instances to be
listed. SERVER is one of server names you specified in the
configuration file.
‘stat id NUM’
Show statistics about a specific connection. This will give you
all available information about every connection you specified.
*Note Writing servers::, for more information about how to provide
these information.
‘stat con’
Connection statistics. This will give a list of all socket
structures within Serveez. If you want more detailed information
about specific connections, coservers or servers you need to
request these information with ‘stat id NUM’ or ‘stat all’.
‘stat all’
Server and coserver instance statistics. This command lists all
the information about instantiated servers and coservers. *Note
Writing servers::, for more information about how to provide these
information.
‘stat cache’
HTTP cache statistics. This command produces an output something
like the following where ‘File’ is the short name of the cache
entry, ‘Size’ the cache size, ‘Usage’ the amount of connections
currently using this entry, ‘Hits’ the amount of cache hits,
‘Recent’ the cache strategy flag (newer entries have larger
numbers) and ‘Ready’ is the current state of the cache entry.
File Size Usage Hits Recent Ready
zlib-1.1.3-20000531.zip 45393 0 0 1 Yes
texinfo.tex 200531 0 0 2 Yes
shayne.txt 2534 0 1 1 Yes
Total : 248458 byte in 3 cache entries
‘kill cache’
Reinitialize the HTTP file cache. Flushes all files from the
cache.
3.4.3.3 Configuration
.....................
There is nothing to be configured yet.
3.4.4 Foo Server
----------------
3.4.4.1 General description
...........................
The Foo Server is a simple example on how to write Internet protocol
servers with Serveez. *Note Writing servers::.
3.4.4.2 Configuration
.....................
There are all kinds of configuration items. They are used to explain
the implementation of servers. A complete list will follow.
‘port (port configuration, default: tcp, 42421, *)’
Sets up the TCP port and local address.
‘bar (integer, no default)’
Some integer value. Printed as server information.
‘reply (string, default: Default reply)’
Some string. Printed as server information.
‘messages (string array, default: ...)’
Some string array which is actually a list of strings. Also
printed as server information.
‘ports (integer array, default: 1, 2, 3, 4)’
Some array of integer numbers. Printed as server information.
‘assoc (hash, default, default: ...)’
An hash map associating keys with values. Printed as server
information.
‘truth (boolean, default: true)’
Some boolean value. Printed as server information.
3.4.5 SNTP Server
-----------------
3.4.5.1 General
...............
The SNTP server can be queried with the ‘netdate’ command. It is used
to synchronize time and dates between Internet hosts. The protocol is
described in the ARPA Internet RFC 868. Thus it is not really an SNTP
server as described by RFC 2030 (Simple Network Time Protocol (SNTP)
Version 4 for IPv4, IPv6 and OSI). It is rather an excellent example on
how to implement a UDP server in Serveez.
This protocol provides a site-independent, machine readable date and
time. The Time service sends back time in seconds since midnight on
January first 1900.
One motivation arises from the fact that not all systems have a
date/time clock, and all are subject to occasional human or machine
error. The use of time-servers makes it possible to quickly confirm or
correct a system’s idea of the time, by making a brief poll of several
independent sites on the network.
3.4.5.2 Configuration
.....................
The configuration of this server does not require any item.
3.4.6 Gnutella Spider
---------------------
3.4.6.1 What is it ?
....................
The Gnutella net is a peer-to-peer network which is based on client
programs only. There are no servers. The network itself is formed by
client connections only. Generally the Gnutella network is for sharing
files of any kind.
This Gnutella spider is for seeking the needle in the haystack. Once
connected to the network it regularly tries to find certain files in
there. It keeps track of all connected clients and tries to reconnect
them if the current connections are lost.
Gnutella, however has nothing to do with the GNU project. The
original client is just a free (as in free beer) piece of software.
With Serveez you have a free (as in freedom) way to use it. Have a look
at the Gnutella page for further information.
3.4.6.2 Configuration
.....................
The Gnutella spider knows the following configurations items.
‘net-url (string, default: gnutella-net)’
If you want to see the host catcher list of this Gnutella spider
you can connect to this port with any WWW browser at
. The ‘host:port’ combinations depend on
the bindings.
‘hosts (string array, no default)’
This is the start of the haystack, the initial host list of the
clients the spider tries to connect to. Each list item should be
of the format ‘ip:port’ (e.g., ‘146.145.85.34:6346’). You can also
pass Internet host names. If the port information is left blank it
defaults to 6346. If you need some entry point for the Gnutella
network have a look at or
.
‘search (string array, default: Puppe3000, Meret Becker)’
This is the needle. Each search line is either a set of space
delimited tokens where every token must match. Or a kind of
wildcard expression including ‘?’ and ‘*’. Search lines are always
matched case insensitive.
‘search-limit (integer, default: 30)’
This limits how many results the Gnutella spider returns to other
people searching your files. This is for protection against ‘*’
search requests.
‘max-ttl (integer, default: 5)’
Every Gnutella packet has got a TTL. This is the maximum TTL
allowed for outgoing packets. When a packet comes in it gets its
TTL value decremented and is forwarded to it destination. If
however an incoming packet has a TTL larger than ‘max-ttl’ the ttl
value is set to ‘max-ttl’. This is necessary since most people use
far too large TTL values.
‘ttl (integer, default: 5)’
When creating a new Gnutella packet we use this as TTL. Please use
a sane value. This ttl needs not to be as large as it is for IP
packets. A value below 10 is more than enough. Have a look at the
Gnutella page for a calculation of a ’sane value’.
‘download-path (string, default: /tmp)’
This is where the spider saves needles in.
‘share-path (string, default: /tmp)’
Here are all the files we share with others. The Gnutella spider
will recurse into directories. So be careful with this option.
‘max-downloads (integer, default: 4)’
Maximum number of concurrent downloads from the network.
‘max-uploads (integer, default: 4)’
Maximum number of concurrent uploads to the network.
‘connection-speed (integer, default: 28)’
This is what we send as our connection speed in KBit/s. We also
use this value to throttle down the network transfer rate for file
uploads.
‘min-speed (integer, default: 28)’
Search for needles on hosts with a minimum speed. Set it to 0 if
you do not care about that. This value is in KBit/s, too.
‘file-extensions (string array, default: empty list)’
If we get replies on search queries we check if the file extension
of this reply matches one of these extensions. Useful extensions
are ‘mp3’ and ‘mpg’.
‘connections (integer, default: 4)’
This is the number of concurrent connections the Gnutella spider
tries to keep up to the network. The IP addresses and the port
information is taken from the host catcher hash.
‘force-ip (string, default: not set)’
You can force the Gnutella spider to send outgoing replies with
this IP as host information. Must be in dotted decimals notation.
This is useful if you are behind a masquerading gateway. You need
to install some kind of port forwarder on the gateway so other
people can reach you from the outside. Serveez is a good port
forwarder.
‘force-port (integer, default: not set)’
Force the Gnutella spider to send outgoing replies with the
‘force-port’ as port information. See above for more information.
‘disable (boolean, default: false)’
With this configuration option you can disable the bindings for a
Gnutella server instance. This means that no remote client can
connect without being told so (e.g., by push requests).
3.4.7 Tunnel Server
-------------------
3.4.7.1 General description
...........................
The Tunnel server is for mapping one port configuration to another. So
we should rather speak of a port forwarder. Two port forwarders can
form a tunnel. Generally this means that you can setup Serveez to
accept network or pipe connections in order to pass all transfer data on
this line to another port configuration. This can be useful to work
around gateways and firewalls. When instantiating an ICMP source or
destination you must ensure root privileges for the application. On
Windows NT and Windows 2000 you need to be either logged in as
Administrator or have set the registry key
HKLM\System\CurrentControlSet\Services\Afd\Parameters\DisableRawSecurity
to 1 (DWORD). One of the given examples in ‘serveez.cfg’ shows how you
can setup a tunnel server for forwarding a pipe connection. Please keep
in mind when forwarding a TCP or pipe connection over ICMP or UDP you
loose reliability since the latter two are packet oriented rather than
connection oriented. We are not willing to implement our own TCP stack
to work on ICMP/UDP directly.
Forwarding between the same types of connection is always possible.
When forwarding to an ICMP tunnel we use a special protocol which we
will outline in the following section.
3.4.7.2 Extended ICMP protocol specification
............................................
Since ICMP (Internet Control Message Protocol) does have a fixed packet
format we had to extend it in order to use it for our own purposes. The
protocol field of the IP header contains a binary ‘1’ which is the
identifier for ICMP (e.g., ‘6’ identifies TCP). When creating an ICMP
socket the IP header is always generated by the kernel. This is the
main difference to raw sockets where the IP header must be generated at
userspace level.
When receiving an ICMP packet it also contains the IP header. When
sending an ICMP packet you must not prepend this IP header. The kernel
will do this itself. The IP header always follows the actual ICMP
header followed by the ICMP packet data. Since this section does not
cover raw sockets we leave the IP header structure out here.
The modified ICMP message format is as:
Offset Size Meaning
0 1 Message type.
1 1 Message type sub code.
2 2 Checksum.
4 2 Senders unique identifier.
6 2 Sequence number.
8 2 Port number.
10 0 - 65506 Packet load.
Each of these fields can be modified and processed by Serveez and do
not get touched by the kernel at all. The ICMP socket implementation of
Serveez differentiates two types of sockets: listening and connected
ICMP sockets. This is non-standard because it actually makes no sense
since there is no difference for the kernel. The introduction of these
semantics allow Serveez to forward data between connection-oriented (TCP
and named pipes) and packet-oriented (UDP and ICMP) protocols.
Message type
Valid message types are for instance ‘8’ for an echo message and
‘0’ for its echo reply. These two messages are used for the
systems builtin ping services. Serveez uses its own message type
identifier which is ‘42’ (‘ICMP_SERVEEZ’) by default.
Message type sub code
Serveez also defines its own message type sub codes described in
the following table.
Sub code Constant identifier Description
0 ‘ICMP_SERVEEZ_DATA’ packet contains data
1 ‘ICMP_SERVEEZ_REQ’ unused
2 ‘ICMP_SERVEEZ_ACK’ unused
3 ‘ICMP_SERVEEZ_CLOSE’ disconnection message
4 ‘ICMP_SERVEEZ_CONNECT’ connect message
Checksum
The checksum field of the ICMP header is used to check the ICMP
headers and the payloads (packet data) validity. We are using the
standard Internet Checksum algorithm described in RFC 1071. If the
check failed we drop the packet.
Senders unique identifier
The senders identifier field is used to determine if a received
packet has been sent by the sender itself and should therefore be
dropped. This happens because each ICMP socket setup for receiving
gets all sent ICMP packets system wide. Thus Serveez will even be
notified if the kernel creates some echo reply or destination
unreachable message due to a request completely outside the scope
of Serveez.
Sequence number
Each connected ICMP socket increments its sequence number when
sending a packet. Thus a connection message type packet of such a
socket always has a zero sequence number. This field could (but is
not yet) also be used to reorder ICMP packets or to detect missing
packets.
Port number
The port field of the modified packet format helps Serveez to
establish connected ICMP sockets. A simple packet filter detects
if a received packet is kind of reply to a sockets sent packets by
comparing this port number. The packet is dropped if the
comparison fails and it is not a listening socket.
Except the data message type subcode all ICMP packets created and
sent by Serveez have a zero payload. The connect message subcode
identifies a new connection and the disconnection message subcode its
shutdown without actually transmitting data. These two subcodes emulate
a TCP connections ‘connect’, ‘accept’ and ‘shutdown’ system call.
3.4.7.3 Configuration
.....................
This might be the most easiest configuration to setup. You essentially
need to define the source port configuration and the target port
configuration. The ‘serveez.cfg’ in the ‘data/’ directory shows two
example configurations how to tunnel TCP connections over UDP and ICMP.
The UDP tunnel accesses the standard HTTP port 80 and the ICMP tunnel
accesses the standard Telnet port 23.
‘source (port configuration, no default)’
The source port configuration. This is usually the same you bind
the server to.
‘target (port configuration, no default)’
The target port configuration.
3.4.8 Fake Ident Server
-----------------------
3.4.8.1 General description
...........................
Most systems run the ’ident protocol’ on port 113. Internet hosts can
connect to that port and find out what user is having a connection to
the host. For example a webserver can query your username when you
fetch a file (e.g., Serveez’ internal ident-coserver can do that). Most
IRC servers protect themselves by allowing only users that have a valid
ident response. Therefore mIRC (for windoze) has a built in ident
server. This fake ident server can be used to ’fake’ a response. This
is useful when you connect through a masquerading gateway and the
gateway cannot handle ident requests correctly. (Or, of course, you are
using windoze, need an ident response and do not have mIRC at hand.)
This server has two modes of operation. In one mode all requests get
‘ERROR : NO-USER’ as response. This is a valid but not very helpful
response. The other mode makes the server send a valid and useful
response. It contains a system type and a username. The system type is
usually ’UNIX’. Others are valid but never used (at least i have never
seen something else).
3.4.8.2 Configuration
.....................
This server is easy to configure.
‘systemtype (string, default: UNIX)’
The system type to respond. The username field of the response has
other meanings depending on this field, so do not make things up
here. Read the RFC to learn more.
‘username (string, default: )’
If no username is set (which means this field does not appear in
the configuration file) the server runs in the
flag-all-requests-as-error mode. Use your favourite nickname here.
3.4.9 Passthrough Server
------------------------
3.4.9.1 General description
...........................
The program passthrough server provides basic inetd functionality.
Basically it can accept connections and pass this connection to the
standard input (stdin) and standard output (stdout) handles of programs.
Depending on the platform (operating system) the user is able to
configure different methods how this can be achieved.
3.4.9.2 Configuration
.....................
This server has different types of configuration options specifying its
behaviour. Some of them are mandatory and some are optional. The very
least to configure is the program to be started when a new connection is
made.
‘binary (string, no default)’
This parameter specifies the program to execute when a new
connection has been accepted. The parameter is mandatory and must
be a fully qualified file name (including path).
‘directory (string, no default)’
This will be the working directory of the executed program. If you
omit this parameter the server uses the current directory (the
directory is not changed).
‘user (string, no default)’
If you omit this parameter no user or group will be set for the
started program. Otherwise you need to specify this information in
the format ‘user[.group]’. If the group is omitted the user’s
primary group will be used.
‘argv (string array, no default)’
This list of character strings is going to be the program’s
argument list (command line). If the first list item (which is
argv[0] and the program’s name) is left blank it defaults to the
name specified in the ‘binary’ parameter.
‘do-fork (boolean, default: true)’
This flag specifies the method used to pass the connection to the
program. If it is true the server uses the Unix’ish ‘fork’ and
‘exec’ method. Otherwise it will pass the data through a unnamed
pair of sockets [ or two pairs of anonymous pipes ].
‘single-threaded (boolean, default: true)’
This parameter applies to servers bound to UDP and ICMP port
configurations only. For programs which process all incoming
packets and eventually time out, the program is said to be
‘single-threaded’ and should use a true value here. If a program
gets a packet and can receive further packets, it is said to be a
‘multi-threaded’ program, and should use a false value.
‘thread-frequency (integer, default: 40)’
The optional ‘thread-frequency’ parameter specifies the maximum
number of program instances that may be spawned from the server
within an interval of 60 seconds.
3.4.10 Mandel Server
--------------------
3.4.10.1 General description
............................
The distributed Mandelbrot server is an Internet server completely
written in Guile with the help of the API provided by the underlying
Serveez application. The reader will not see any occurrence of the
networking API of Guile.
It implements a protocol called ‘dnc’. ‘dnc’ - short for
“Distributed Number Cruncher”. The Mandelbrot server manages the
computation of a graphic visualization of the Mandelbrot set fractal.
Each client can connect to the server and ask for something to calculate
and is meant to send its result back to the server. Finally the server
produces a bitmap in the XPM format and uses a specified viewer
application to bring it onto your screen.
3.4.10.2 Configuration
......................
The server can be setup to manage the calculation of the Mandelbrot set
at various locations (rectangular region in the complex plane), in a
specific pixel resolution and colour depth. Moreover you can define the
name of the final output file and the viewer application the output file
is displayed with.
‘start (string, default: -2.0-1.5i)’
Specifies the upper left corner of the final bitmap in the complex
plane.
‘end (string, default: +1.1+1.5i)’
Specifies the lower right corner of the final bitmap in the complex
plane.
‘x-res (integer, default: 320)’
The real part pixel resolution.
‘y-res (integer, default: 240)’
The imaginary part pixel resolution.
‘colors (integer, default: 256)’
Number of maximum colours used in the bitmap. Also determines the
maximum iteration depth.
‘outfile (string, default: mandel.xpm)’
When the Mandel server has managed to calculate the whole bitmap it
produces an output file in the XPM format. You can specify the
name and location of this output file.
‘viewer (string, default: xv)’
Here you can setup your favourite bitmap viewer application. It
should be able to parse and display the XPM format.
4 Coserver
**********
4.1 What are coservers
======================
If it is necessary to complete blocking tasks in Serveez you have to use
coservers. The actual implementation differs on platforms. On Unices
they are implemented as processes communicating with Serveez over pipes.
On Win32 Serveez uses threads and shared memory.
4.2 Writing coservers
=====================
4.2.1 Making and configuring preparations
-----------------------------------------
First you have to change into the ‘src/libserveez/coserver/’ directory
of the Serveez package. Then edit the ‘Makefile.am’ and add your header
and implementation file to the ‘libcoserver_la_SOURCES’ variable.
4.2.2 Coserver header file
--------------------------
You have to declare the coserver handle routine here. This callback
gets the input buffer argument and delivers the output buffer result.
Both of these buffers are supposed to be lines separated by a ‘\n’.
4.2.3 Coserver implementation file
----------------------------------
Here you need to ‘#include "libserveez/coserver/coserver.h"’ and
implement the coserver handle routine declared in the coserver header
file. This can be any blocking system call. On successful completion
you can return the result or ‘NULL’ on errors. The input and output
buffers are plain strings and can have any format with one exception.
Because the coservers communicate via a line protocol with Serveez these
buffers must not contain ‘\n’ (0x0d).
4.2.4 Make your coserver available in Serveez
---------------------------------------------
For this you have to edit ‘coserver.h’ and ‘coserver.c’ files which are
located in the ‘src/libserveez/coserver/’ directory. In the header file
you have to define a further ‘COSERVER_*’ id (macro) and set the
‘MAX_COSERVER_TYPES’ define to the appropriate value. Then you should
define a further ‘svz_coserver_*’ macro in the same file.
In ‘coserver.c’ you have to implement the ‘svz_coserver_*’ macro.
This macro takes three arguments. The first is always specific to your
coserver and is used to create the actual request string. Then follows
the result callback routine, and an optional argument for this callback.
The latter two are simply passed to the ‘svz_coserver_send_request’
routine. This routine takes four arguments where the first is the
previously defined ‘COSERVER_*’ id and the second is the input buffer
for the coserver handle routine without the trailing ‘\n’.
Then you need to add your coserver to the ‘svz_coservertypes’ array
specifying the ‘COSERVER_*’ id, the coserver description, the coserver
handle routine discussed above, the number of coserver instances to be
created and an optional initialization routine.
4.3 Existing coservers
======================
4.3.1 Identification (Ident) coserver
-------------------------------------
The Identification protocol is briefly documented in RFC1413. It
provides a means to determine the identity of a user of a particular TCP
connection. Given a TCP port number pair, it returns a character string
which identifies the owner of that connection on the server’s (that is
the client’s) system.
This is a connection based application on TCP. A server listens for
TCP connections on TCP port 113 (decimal). Once a connection is
established, the server reads a line of data which specifies the
connection of interest. If it exists, the system dependent user
identifier of the connection of interest is sent as the reply. The
server may then either shut down the connection or it may continue to
read/respond to more queries.
The Ident coserver is a client to this kind of service. For every
established network connection you can use this service by calling the
appropriate macro from ‘coserver.h’. But you could also use the Ident
coserver as is without this macro. The messages from Serveez to this
coserver are formatted this way:
Format:
RemoteAddressInDottedDecimals ":" RemotePort ":" LocalPort
Macro:
svz_coserver_ident (sock, MyIdentCallback, sock->id, sock->version);
In this context ‘sock’ is of type ‘svz_socket_t’ and
‘MyIdentCallback’ is something like the following example. Both of the
last two (optional) arguments identify a valid socket structure and
‘user’ can be ‘NULL’ if there is no ident daemon running on the foreign
machine. The last two argument within the above macro will be the last
two arguments in the callback below. Thus you will know what kind of
data the invocation of the callback is related to.
Callback:
int
MyIdentCallback (char *user, int id, int version)
{
printf ("Identified user: %s\n", user);
return 0;
}
4.3.2 Domain Name Server (DNS) coserver
---------------------------------------
The DNS coserver is using ‘gethostbyname’ to translate a given hostname
to the associated IP address. The format of the coserver input line and
the macro from ‘coserver.h’ is shown below. The IRC server is currently
using this coserver for resolving its ‘?-Lines’. *Note Existing
servers::, for more information. In the example below ‘realhost’ is
something like ‘www.lkcc.org’.
Format:
RemoteHostname
Macro:
svz_coserver_dns (realhost, irc_connect_server, ircserver, NULL);
Callback:
int
irc_connect_server (char *ip, irc_server_t *server)
{
printf ("The ip address is: %s\n", ip);
return 0;
}
4.3.3 Reverse Domain Name Server (reverse DNS) coserver
-------------------------------------------------------
As easily guessed from the name this coserver is just doing the reverse
as the DNS coserver. It translates a given IP address into a hostname
using ‘gethostbyaddr’. In the macro the ip address is given as an
‘unsigned long’ in host byte order. The Reverse DNS coserver itself
takes something like ‘192.168.2.1’.
Format:
RemoteAddressInDottedDecimals
Macro:
svz_coserver_reverse (addr, MyReverseCallback, sock->id, sock->version);
Callback:
int
MyReverseCallback (char *host, int id, int version)
{
printf ("Hostname is: %s\n", host);
return 0;
}
5 Embedding
***********
This chapter documents how to embed Serveez into C programs and
describes all parts of the API it provides.
The Serveez core library provides all of the functionality necessary
in order to write Internet protocol servers (currently TCP, UDP, ICMP
and RAW sockets), pipe servers (connection-oriented via a pair of named
pipes) and coservers in a portable way. All of the included servers are
based upon this library, which encapsulates the native network and file
system programming interface of different Unices and Windows systems.
The following sections will give the reader an overview about how to
use its core library.
5.1 Embedding Serveez
=====================
This chapter deals with embedding the Serveez core library into
standalone C/C++ applications and using it in order to write additional
servers.
5.1.1 Compiling and linking
---------------------------
When you have installed a version of Serveez passing the ‘configure’
script the ‘$prefix’ argument, e.g., ‘./configure --prefix=/usr/local’,
you will find the ‘libserveez’ library in ‘/usr/local/lib’ and the
include headers in ‘/usr/local/include’. If you want to compile a C
program using the Serveez API and link against the Serveez core library
‘libserveez’, which is ‘libserveez.so’ for Unices and ‘libserveez.dll’
for Windows systems, you need to tell the compiler and linker where to
find the headers and libraries.
Most C compilers you can use will understand the following command
line options for this purpose. The ‘-I’ argument specifies the
directory of additional include headers, the ‘-L’ argument the direcory
to additional libraries and the ‘-l’ argument the library itself to link
against.
$ cc test.c -I/usr/local/include -o test -L/usr/local/lib -lserveez
In order to obtain the correct compiler and linker flag you can also
run the ‘serveez-config’ script which gets installed with the Serveez
package. The ‘serveez-config’ script can be invoked with the following
set of option.
‘-h, --help’
Displays the usage information.
‘-v, --version’
Displays installed Serveez version.
‘-l, --ldflags’
Prints the linker flags (libraries to link with including directory
information).
‘-c, --cflags’
Prints the compiler flags to compile with.
5.1.2 A simple example
----------------------
The following small example shows how to use the Serveez core library to
print the list of known network interface. As you will notice there are
three major steps to do: Include the library header with ‘#include
’, initialize the library via ‘svz_boot’ and finalize it
via ‘svz_halt’. In between these calls you can use all of the API
functions, variables and macros described in *note Embedding API::.
#include
#include
#include
static int
display_ifc (const svz_interface_t *ifc,
void *closure)
{
char *addr = svz_inet_ntoa (ifc->ipaddr);
if (ifc->description)
/* interface with description */
printf ("%40s: %s\n",
ifc->description, addr);
else
/* interface with interface # only */
printf ("%31s%09lu: %s\n",
"interface # ", ifc->index, addr);
return 0;
}
int
main (int argc, char **argv)
{
/* Library initialization. */
svz_boot ("example");
/* Display a list of interfaces. */
printf ("local interfaces:\n");
svz_foreach_interface (display_ifc, NULL);
/* Library finalization. */
svz_halt ();
return EXIT_SUCCESS;
}
5.2 Embedding API
=================
In this chapter the reader will find a short description of each
function, global variable and macro provided by the Serveez core
library. The API can either be used to implement a new server or
coserver module for use with Serveez or for supporting network and
server functionality within your own applications without caring about
the details and system programming.
Most of the Serveez core library interface functionality should be
prefixed with ‘svz_’. Small symbols will refer to functions and
variables in most cases and big letter symbols refer to macros.
[FIXME: The subsections are named inconsistently because originally,
the API reference was a separate document; on merge, weirdness like
“Port config funcs” was necessary to avoid conflict with the other “Port
configuration” node. —ttn]
5.2.1 Library features
----------------------
The ‘configure’ script used to build libserveez takes many options
(*note Build and install::). Some of these are encapsulated by
‘svz_library_features’.
-- Function: const char * const * svz_library_features (size_t *COUNT)
Return a list (length saved to COUNT) of strings representing the
features compiled into libserveez.
Here is a table describing the features in detail:
‘debug’
Present when ‘--enable-debug’.
‘heap-counters’
Present when ‘--enable-heap-count’.
‘interface-list’
Present when ‘--enable-iflist’.
‘poll’
Present when ‘--enable-poll’ and you have poll(2).
‘sendfile’
Present when ‘--enable-sendfile’ and you have sendfile(2) or some
workalike (e.g., ‘TransmitFile’).
‘log-mutex’
Present when ‘svz_log’ uses a mutex around its internal stdio
operations, implying that you have some kind of thread capability
(perhaps in a separate library). If your system has
‘fwrite_unlocked’, the configure script assumes that ‘fwrite’ et al
already operate in a locked fashion, and disables this.
‘flood-protection’
Present when ‘--enable-flood’.
‘core’
The networking core. This is always present.
5.2.2 Memory management
-----------------------
The core library of Serveez is able to keep track of the memory an
application or part of a program consumes, and also controls itself in
the same manner. When you are using this memory allocator interface you
can determine and afterwards remove memory leaks. This is a very
important feature as servers are by nature long-lived programs.
The three allocator function pointers for ‘malloc’, ‘realloc’ and
‘free’ make it possible to instruct Serveez to use different kinds of
memory, which might be necessary if you want the library to work with
shared memory arenas or any other underlying memory API.
-- Function: void svz_set_mm_funcs (svz_malloc_func_t CUS_MALLOC,
svz_realloc_func_t CUS_REALLOC, svz_free_func_t CUS_FREE)
Set the internal memory management functions to CUS_MALLOC,
CUS_REALLOC and CUS_FREE, respectively. The default internal
values are ‘malloc’, ‘realloc’ and ‘free’.
-- Function: void * svz_malloc (size_t SIZE)
Allocate SIZE bytes of memory and return a pointer to this block.
-- Function: void * svz_calloc (size_t SIZE)
Allocate SIZE bytes of memory and return a pointer to this block.
The memory is cleared (filled with zeros).
-- Function: void * svz_realloc (void *PTR, size_t SIZE)
Change the size of a block of memory at PTR, previously returned by
‘svz_malloc’, to SIZE bytes. If PTR is ‘NULL’, allocate a new
block.
-- Function: void svz_free (void *PTR)
Free a block of memory at PTR, previously returned by ‘svz_malloc’
or ‘svz_realloc’. If PTR is ‘NULL’, do nothing.
-- Function: char * svz_strdup (const char *SRC)
Duplicate the given string SRC if it is not ‘NULL’ and has non-zero
length. Return the new string.
-- Function: void svz_get_curalloc (size_t *TO)
Write values to ‘to[0]’ and ‘to[1]’ representing the number of
currently allocated bytes and blocks, respectively. If Serveez was
not configured with ‘--enable-debug’, the values are always 0.
5.2.3 Data structures
---------------------
Since most servers need to store information about its clients or want
to keep track of data during runtime, we include a pair of of useful
data structures. The actual aim was to provide higher level data
structures which the C programming language does not support. Some of
the included servers which come with Serveez make extensive use of them.
5.2.3.1 Array
.............
The array data structure is a simple array implementation. Each array
has a size and capacity. The array indices range from zero to the
array’s size minus one. You can put any kind of data into this array
which fits into the size of a pointer. The array grows automatically if
necessary.
-- Function: svz_array_t * svz_array_create (size_t CAPACITY,
svz_free_func_t DESTROY)
Create a new array with the initial capacity CAPACITY and return a
pointer to it. If CAPACITY is zero it defaults to some value. If
DESTROY is non-‘NULL’, ‘svz_array_destroy’ calls that function
(typically used to free dynamically allocated memory). For
example, if the array contains data allocated by ‘svz_malloc’,
DESTROY should be specified as ‘svz_free’. If the array contains
data which should not be released, DESTROY should be ‘NULL’.
-- Function: void svz_array_destroy (svz_array_t *ARRAY)
Completely destroy the array ARRAY. The ARRAY handle is invalid
afterwards. The routine runs the DESTROY callback for each element
of the array.
-- Function: void * svz_array_get (svz_array_t *ARRAY, size_t INDEX)
Return the array element at the position INDEX of the array ARRAY
if the index is within the array range. Return ‘NULL’ if not.
-- Function: void * svz_array_set (svz_array_t *ARRAY, size_t INDEX,
void *VALUE)
Replace the array element at the position INDEX of the array ARRAY
with the value VALUE and return the previous value at this index.
Return ‘NULL’ and do nothing if ARRAY is ‘NULL’ or the INDEX is out
of the array range.
-- Function: void svz_array_add (svz_array_t *ARRAY, void *VALUE)
Append the value VALUE at the end of the array ARRAY. Do nothing
if ARRAY is ‘NULL’.
-- Function: void * svz_array_del (svz_array_t *ARRAY, size_t INDEX)
Remove the array element at the position INDEX of the array ARRAY.
Return its previous value or ‘NULL’ if the index is out of the
array’s range.
-- Function: size_t svz_array_size (svz_array_t *ARRAY)
Return the current size of ARRAY.
-- Macro: svz_array_foreach (array, value, i)
Expand into a ‘for’-statement header, for iterating over ARRAY. On
each cycle, VALUE is assigned to successive elements of ARRAY, and
I the element’s position.
5.2.3.2 Hashtable
.................
A hashtable associates keys of arbitrary size and content with values.
This data structure is also called associative array sometimes because
you use keys in order to access values instead of numbers. You cannot
store two values associated with the same key. The values can have any
simple C types like integers or pointers.
-- Function: svz_hash_t * svz_hash_create (size_t SIZE,
svz_free_func_t DESTROY)
Create a new hash table with an initial capacity SIZE. Return a
non-zero pointer to the newly created hash. The size is calculated
down to a binary value. The DESTROY callback specifies an element
destruction callback for use by ‘svz_hash_clear’ and
‘svz_hash_destroy’ for each value. If no such operation should be
performed the argument must be ‘NULL’.
-- Function: svz_hash_t * svz_hash_configure (svz_hash_t *HASH,
size_t (* keylen) (const char *) ,
unsigned long (* code) (const char *) ,
int (* equals) (const char *, const char *)
Set the internal KEYLEN, CODE and and EQUALS functions for hash
table HASH. Return HASH.
KEYLEN takes ‘const char *data’ and returns ‘size_t’, the number of
bytes in DATA representing the key.
CODE takes ‘const char *data’ and returns ‘unsigned long’.
EQUALS takes ‘const char *data1, const char *data2’ and returns
‘int’, which should be non-zero if equal.
As a special case, a ‘NULL’ value means don’t set that function,
leaving it to its default value.
-- Function: void svz_hash_destroy (svz_hash_t *HASH)
Destroy the existing hash table HASH, ‘svz_free’ing all keys within
the hash, the hash table and the hash itself. If a non-‘NULL’
element destruction callback was specified to ‘svz_hash_create’,
that function is called on each value.
-- Function: void * svz_hash_delete (svz_hash_t *HASH, const char *KEY)
Delete an existing entry accessed via a KEY from the hash table
HASH. Return ‘NULL’ if there is no such key, otherwise the
previous value.
-- Function: void * svz_hash_put (svz_hash_t *HASH, const char *KEY,
void *VALUE)
Add a new element consisting of KEY and VALUE to HASH. When KEY
already exists, replace and return the old value. *Note*: This is
sometimes the source of memory leaks.
-- Function: void * svz_hash_get (const svz_hash_t *HASH,
const char *KEY)
Return the value associated with KEY in the hash table HASH, or
‘NULL’ if there is no such key.
-- Function: void svz_hash_foreach (svz_hash_do_t *FUNC,
svz_hash_t *HASH, void *CLOSURE)
Iterate FUNC over each key/value pair in HASH. FUNC is called with
three ‘void *’ args: the key, the value and the opaque (to
‘svz_hash_foreach’) CLOSURE.
-- Function: size_t svz_hash_size (const svz_hash_t *HASH)
Return the number of keys in the hash table HASH. If HASH is
‘NULL’, return zero.
-- Function: char * svz_hash_contains (const svz_hash_t *HASH,
void *VALUE)
Return the key associated with VALUE in the hash table HASH, or
‘NULL’ if there is no such value.
-- Function: int svz_hash_exists (const svz_hash_t *HASH, char *KEY)
Return non-zero if ‘key’ is stored within the hash table ‘hash’,
otherwise zero. This function is useful when you cannot tell
whether the return value of ‘svz_hash_get’ (‘== NULL’) indicates a
real value in the hash or a non-existing hash key.
5.2.4 svz_address_t
-------------------
A network address comprises a “family”, such as ‘AF_INET’ (also known as
IPv4), and its “bits” in network byte order, such as the bytes 127, 0, 0
and 1 (also known as the “IPv4 loopback address”). Many libserveez
functions take ‘svz_address_t *’.
*Please note*: Although ‘svz_address_t’ supports(1) IPv6, the rest of
libserveez it does not (yet). This means you can freely create and
manipulate address objects with the functions described in this section,
but any attempt to pass to the rest of libserveez an address with a
FAMILY other than ‘AF_INET’ will immediately abort the process. When
full IPv6 support is in place, this blurb will be deleted and the list
returned by ‘svz_library_features’ will include an appropriate indicator
(*note Library features::).
-- Function: svz_address_t * svz_address_make (int FAMILY,
const void *BITS)
Return an address object to hold an address in FAMILY, represented
by BITS. FAMILY must be one of:
‘AF_INET’
An IPv4 address; BITS is ‘in_addr_t *’.
‘AF_INET6’
(if supported by your system) An IPv6 address; BITS is ‘struct
in6_addr *’.
The BITS are expected in network byte order. If there are
problems, return ‘NULL’.
-- Function: int svz_address_family (const svz_address_t *ADDR)
Return the address family of ADDR.
-- Function: int svz_address_to (void *DEST, const svz_address_t *ADDR)
Copy the address bits out of ADDR to DEST. Return 0 on success, -1
if either ADDR or DEST is ‘NULL’, or the ADDR family is
‘AF_UNSPEC’.
-- Function: int svz_address_same (const svz_address_t *A,
const svz_address_t *B)
Return 1 if A and B represent the same address (identical family
and bits), otherwise 0.
-- Function: const char * svz_pp_address (char *BUF, size_t SIZE,
const svz_address_t *ADDR)
Format an external representation of ADDR into BUF, of SIZE bytes.
The format depends on the family of ADDR. For IPv4, this is
numbers-and-dots. For IPv6, it is “the most appropriate IPv6
network address format for ADDR”, according to the manpage of
‘inet_ntop’, the function that actually does the work.
If BUF or ADDR is ‘NULL’, or SIZE is not big enough, return ‘NULL’.
Otherwise, return BUF.
-- Function: const char * svz_pp_addr_port (char *BUF, size_t SIZE,
const svz_address_t *ADDR, in_port_t PORT)
Format an external representation of ADDR and PORT (in network byte
order) into BUF, of SIZE bytes. The address “xrep” (external
representation) is done by ‘svz_pp_address’, q.v. The rest of the
formatting depends on the ADDR family.
Family Formatting
--------------------------------------------------------------------------
‘AF_INET’ (IPv4) ‘XREP:PORT’
‘AF_INET6’ (IPv6) ‘[XREP]:PORT’
If BUF or ADDR is ‘NULL’, or SIZE is not big enough, return ‘NULL’.
Otherwise, return BUF.
-- Function: svz_address_t * svz_address_copy
(const svz_address_t *ADDR)
Return a copy of ADDR.
-- Macro: SVZ_SET_ADDR (place, family, bits)
Expand to a series of commands. First, if PLACE is non-‘NULL’,
then ‘svz_free’ it. Next, assign to PLACE a new address object
made by calling ‘svz_address_make’ with FAMILY and BITS.
-- Macro: SVZ_PP_ADDR (buf, addr)
Expand to a call to ‘svz_pp_address’, passing it BUF and ‘sizeof
BUF’, in addition to ADDR.
-- Macro: SVZ_PP_ADDR_PORT (buf, addr, port)
Expand to a call to ‘svz_pp_addr_port’, passing it BUF and ‘sizeof
BUF’, in addition to ADDR and PORT.
---------- Footnotes ----------
(1) that is, if your system supports it
5.2.5 Utility functions
-----------------------
Within this section you will find some miscellaneous functionality and
left overs of the C API.
-- Function: void svz_log (int LEVEL, const char *FORMAT, ...)
Print a message to the log system. LEVEL specifies the prefix.
-- Function: void svz_log_setfile (FILE *FILE)
Set the file stream FILE to the log file all messages are printed
to. Can also be ‘stdout’ or ‘stderr’.
-- Function: int svz_hexdump (FILE *OUT, char *ACTION, int FROM,
char *BUFFER, int LEN, int MAX)
Dump BUFFER with the length LEN to the file stream OUT. Display
description ACTION along with origin and size info first, followed
by the hexadecimal text representation. Stop output at either MAX
or LEN (if MAX is zero) bytes. FROM is a numerical identifier of
the buffers creator.
-- Function: char * svz_itoa (unsigned int I)
Convert an unsigned integer to its decimal string representation,
returning a pointer to an internal buffer. (You should copy the
result.)
-- Function: unsigned int svz_atoi (char *STR)
Convert string STR in decimal format to an unsigned integer. Stop
conversion on any invalid characters.
-- Function: char * svz_getcwd (void)
Return the current working directory in a newly allocated string.
(You should ‘svz_free’ it when done.)
-- Function: int svz_openfiles (int MAX_SOCKETS)
Check for the current and maximum limit of open files of the
current process and try to set the limit to MAX_SOCKETS.
-- Function: char * svz_time (long T)
Transform the given binary data T (UTC time) to an ASCII time text
representation without any trailing characters.
-- Function: char * svz_tolower (char *STR)
Convert the given string STR to lower case text representation.
-- Function: char * svz_sys_version (void)
Return a statically-allocated string describing some operating
system version details.
-- Function: int svz_socket_unavailable_error_p (void)
Return 1 if there was a "socket unavailable" error recently, 0
otherwise. This checks ‘svz_errno’ against ‘WSAEWOULDBLOCK’
(woe32) or ‘EAGAIN’ (Unix).
-- Function: const char * svz_sys_strerror (void)
Return a string describing the most recent system error.
The next two functions log (with ‘SVZ_LOG_ERROR’) the current “system
error” or “network error”, forming the prefix of the message using FMT
and ARGS. This formatted prefix cannot exceed 255 bytes. The rest of
the message comprises: colon, space, error description, newline.
-- Function: void svz_log_sys_error (char const *FMT, ...)
Log the current “system error”.
-- Function: void svz_log_net_error (char const *FMT, ...)
Log the current “network error”.
-- Function: int svz_mingw_at_least_nt4_p (void)
Return 1 if running MinGW (Windows) NT4x or later, otherwise 0.
5.2.6 Networking and other low level functions
----------------------------------------------
This chapter deals with the basic networking and file systems functions.
It encapsulates systems calls in a portable manner. These functions
should behave identically on Windows and Unices.
-- Function: char * svz_inet_ntoa (in_addr_t IP)
Convert IP, an address in network byte order, to its dotted decimal
representation, returning a pointer to a statically allocated
buffer. (You should copy the result.)
-- Function: int svz_inet_aton (char *STR, struct sockaddr_in *ADDR)
Convert the Internet host address STR from the standard
numbers-and-dots notation into binary data and store it in the
structure that ADDR points to. Return zero if the address is
valid, nonzero otherwise. As a special case, if STR is ‘*’
(asterisk), store ‘INADDR_ANY’ in ADDR.
-- Function: int svz_closesocket (svz_t_socket SOCKFD)
Close the socket SOCK. Return 0 if successful, -1 otherwise.
-- Function: int svz_fd_cloexec (int FD)
Set the close-on-exec flag of the given file descriptor FD and
return zero on success. Otherwise return non-zero.
-- Function: int svz_tcp_cork (svz_t_socket FD, int SET)
Enable or disable the ‘TCP_CORK’ socket option of the socket FD.
This is useful for performance reasons when using ‘sendfile’ with
any prepending or trailing data not inside the file to transmit.
Return zero on success, otherwise non-zero.
-- Function: int svz_tcp_nodelay (svz_t_socket FD, int SET, int *OLD)
Enable or disable the ‘TCP_NODELAY’ setting for the socket FD
depending on the flag SET, effectively enabling or disabling the
Nagle algorithm. This means that packets are always sent as soon
as possible and no unnecessary delays are introduced. If OLD is
not ‘NULL’, save the old setting there. Return zero on success,
otherwise non-zero.
-- Function: int svz_sendfile (int OUT_FD, int IN_FD, off_t *OFFSET,
size_t COUNT)
Transmit data between one file descriptor and another where IN_FD
is the source and OUT_FD the destination. The OFFSET argument is a
pointer to a variable holding the input file pointer position from
which reading starts. On return, the OFFSET variable will be set
to the offset of the byte following the last byte that was read.
COUNT is the number of bytes to copy. Return the number of bytes
actually read/written or -1 on errors.
-- Function: int svz_open (const char *FILE, int FLAGS, mode_t MODE)
Open the filename FILE and convert it into a file handle. The
given FLAGS specify the access mode and the MODE argument the
permissions if the ‘O_CREAT’ flag is set.
-- Function: int svz_close (int FD)
Close the given file handle FD. Return -1 on errors.
-- Function: int svz_fstat (int FD, struct stat *BUF)
Return information about the specified file associated with the
file descriptor FD returned by ‘svz_open’. Store available
information in the stat buffer BUF.
-- Function: FILE * svz_fopen (const char *FILE, const char *MODE)
Open the file whose name is the string pointed to by FILE and
associate a stream with it.
-- Function: int svz_fclose (FILE *F)
Dissociate the named stream F from its underlying file.
5.2.7 Client connections
------------------------
Serveez tries to handle all kinds of Internet protocols like TCP
(connection oriented), UDP, ICMP and RAW (packet oriented) and
communication across named pipes (also connection oriented) in the same
way. Therefore it uses a structure called ‘svz_socket_t’ which is the
abstraction of any kind of communication endpoint (can be client or
server or both together).
5.2.7.1 TCP sockets
...................
TCP sockets provide a reliable, stream oriented, full duplex connection
between two sockets on top of the Internet Protocol (IP). TCP guarantees
that the data arrives in order and retransmits lost packets. It
generates and checks a per packet checksum to catch transmission errors.
TCP does not preserve record boundaries.
-- Function: svz_socket_t * svz_tcp_connect (svz_address_t *HOST,
in_port_t PORT)
Create a TCP connection to host HOST and set the socket descriptor
in structure SOCK to the resulting socket. Return ‘NULL’ on
errors.
-- Function: int svz_tcp_read_socket (svz_socket_t *SOCK)
Read all data from SOCK and call the ‘check_request’ function for
the socket, if set. Return -1 if the socket has died, zero
otherwise.
This is the default function for reading from SOCK.
-- Function: int svz_tcp_send_oob (svz_socket_t *SOCK)
If the underlying operating system supports urgent data
(out-of-band) in TCP streams, try to send the byte in ‘sock->oob’
through the socket structure SOCK as out-of-band data. Return zero
on success and -1 otherwise (also if urgent data is not supported).
5.2.7.2 Pipe connections
........................
The pipe implementation supports both named and anonymous pipes. Pipe
servers are implemented as listeners on a file system FIFO on Unices or
“Named Pipes” on Windows (can be shared over a Windows network).
A FIFO special file is similar to a pipe, except that it is created
in a different way. Instead of being an anonymous communications
channel, a FIFO special file is entered into the file system.
Once you have created a FIFO special file in this way, any process
can open it for reading or writing, in the same way as an ordinary file.
However, it has to be open at both ends simultaneously before you can
proceed to do any input or output operations on it.
-- Function: svz_socket_t * svz_pipe_create (svz_t_handle RECV_FD,
svz_t_handle SEND_FD)
Create a socket structure containing both the pipe descriptors
RECV_FD and SEND_FD. Return ‘NULL’ on errors.
-- Function: int svz_pipe_create_pair (svz_t_handle PIPE_DESC[2])
Create a (non blocking) pair of pipes. This differs in Win32 and
Unices. Return a non-zero value on errors.
-- Function: svz_socket_t * svz_pipe_connect (svz_pipe_t *RECV,
svz_pipe_t *SEND)
Create a pipe connection socket structure to the pair of named
pipes RECV and SEND. Return ‘NULL’ on errors.
-- Function: int svz_invalid_handle_p (svz_t_handle HANDLE)
Return 1 if HANDLE is invalid, otherwise 0.
-- Function: void svz_invalidate_handle (svz_t_handle *HREF)
Invalidate the handle pointed at by HREF.
-- Function: int svz_closehandle (svz_t_handle HANDLE)
Close HANDLE. Return 0 if successful, -1 otherwise.
5.2.7.3 UDP sockets
...................
The UDP sockets implement a connectionless, unreliable datagram packet
service. Packets may be reordered or duplicated before they arrive.
UDP generates and checks checksums to catch transmission errors.
-- Function: svz_socket_t * svz_udp_connect (svz_address_t *HOST,
in_port_t PORT)
Create a UDP connection to HOST at PORT and set the socket
descriptor in structure SOCK to the resulting socket. Return a
‘NULL’ value on errors.
This function can be used for port bouncing. If you assign the
‘handle_request’ callback to something server specific and the CFG
field of the server’s configuration to the returned socket
structure, this socket is able to handle a dedicated UDP connection
to some other UDP server.
-- Function: int svz_udp_write (svz_socket_t *SOCK, char *BUF,
int LENGTH)
Write BUF into the send queue of the UDP socket SOCK. If LENGTH
argument supersedes the maximum length for UDP messages it is split
into smaller packets.
5.2.7.4 ICMP sockets
....................
The ICMP socket implementation is currently used in the tunnel server
which comes with the Serveez package. It implements a user protocol
receiving and sending ICMP packets by opening a raw socket with the
protocol ‘IPPROTO_ICMP’.
The types of ICMP packets passed to the socket can be filtered using
the ‘ICMP_FILTER’ socket option (or by software as done here). ICMP
packets are always processed by the kernel too, even when passed to a
user socket.
-- Function: svz_socket_t * svz_icmp_connect (svz_address_t *HOST,
in_port_t PORT, uint8_t TYPE)
Create an ICMP socket for receiving and sending. Return ‘NULL’ on
errors, otherwise an enqueued socket structure.
-- Function: int svz_icmp_send_control (svz_socket_t *SOCK,
uint8_t TYPE)
“If you are calling this function we will send an empty ICMP packet
signaling that this connection is going down soon.” [ttn sez: huh?]
-- Function: int svz_icmp_write (svz_socket_t *SOCK, char *BUF,
int LENGTH)
Send BUF with length LENGTH via this ICMP socket SOCK. If LENGTH
supersedes the maximum ICMP message size the buffer is split into
smaller packets.
5.2.7.5 Raw sockets
...................
A raw socket receives or sends the raw datagram not including link-level
headers. It is currently used by the ICMP socket implementation of the
core library. The IPv4 layer generates an IP header when sending a
packet unless the ‘IP_HDRINCL’ socket option is enabled on the socket.
When it is enabled, the packet must contain an IP header. For receiving
the IP header is always included in the packet.
Only processes with an effective userid of zero (Administrator or
root) or the ‘CAP_NET_RAW’ capability are allowed to open raw sockets.
All packets or errors matching the protocol number specified for the raw
socket are passed to this socket. A protocol of ‘IPPROTO_RAW’ implies
enabled ‘IP_HDRINCL’ and receives all IP protocols. Sending is not
allowed.
[FIXME: All funcs internalized! Write something else here!]
5.2.7.6 Passthrough connections
...............................
The functions described in this section allow you to pass through client
connections to the standard input (stdin) and standard output (stdout)
of external programs. Some of the routines deal with the management of
program environments. Basically, there are two methods for passing
through a duplex connection: the Unix’ish ‘fork’ and ‘exec’ method and
the shuffle method where the main process keeps control over the
communication on the original duplex connection and passes this data
through two pairs of pipes, or yet another socket connection, to the
child process. All of the three method are implemented calling them
‘SVZ_PROCESS_FORK’, ‘SVZ_PROCESS_SHUFFLE_PIPE’ and
‘SVZ_PROCESS_SHUFFLE_SOCK’.
-- Function: int svz_sock_process (svz_socket_t *SOCK, char *BIN,
char *DIR, char **ARGV, svz_envblock_t *ENVP, int FORKP,
char *USER)
Start a new program BIN, a fully qualified executable filename,
passing the socket or pipe descriptor(s) in the socket structure
SOCK to its stdin and stdout.
If DIR is non-‘NULL’, it specifies the working directory of the new
process.
The program arguments and the environment of the new process are
taken from ARGV and ENVP. Normally ‘argv[0]’ should be set to the
program’s name. If ‘NULL’, it defaults to BIN.
The FORKP argument is a flag that controls the passthrough method.
If non-zero, pipe descriptors or the socket descriptor are passed
to the child process directly through ‘fork’ and ‘exec’.
Otherwise, socket transactions are passed via a pair or pipes or
sockets (depending on whether or not the system provides
‘socketpair’).
You can pass the user and group identifications in the format
‘user[.group]’ (group is optional), as ‘SVZ_PROCESS_NONE’ or
‘SVZ_PROCESS_OWNER’ in the USER argument. This specifies the
permissions of the new child process. If ‘SVZ_PROCESS_OWNER’ is
passed the permissions are set to the executable file BIN owner;
‘SVZ_PROCESS_NONE’ does not change user or group.
Return the new process id on success, -1 on failure.
*Please note*: On M$-Windows platforms it is not possible to pass a
socket connection to stdin/stdout of a child process. That is why this
function creates an inheritable version of the socket and puts the
socket handle number into the environment variables ‘SEND_HANDLE’ and
‘RECV_HANDLE’. A spawned child process can use these handles as if they
were self-created. After calling ‘WSAStartup’ the child process can
‘send’ and ‘recv’ as usual.
Relatedly, Windoze does not use ‘SIGCHLD’ to inform the parent when a
child dies, so for that platform, you should use the next function
(which is not otherwise available):
-- Function: int svz_mingw_child_dead_p (char *PREFIX,
svz_t_handle *PID)
Check child pointed at by PID by waiting a bit. If it is dead,
close and invalidate its handle, and return 1. Otherwise, return
0. PREFIX is for error messages; it should be either the empty
string, or a string ending in colon and space.
On non-Windoze, this is the function you want to use:
-- Function: int svz_most_recent_dead_child_p (svz_t_handle PID)
Return 1 if a child process PID died recently, updating other
internal state by side effect. Otherwise, return 0.
-- Function: void svz_envblock_setup (void)
Set up internal tables for environment block wrangling.
This function must be called once after ‘svz_boot’ so that
subsequent functions (like ‘svz_envblock_default’) can work
correctly.
-- Function: svz_envblock_t * svz_envblock_create (void)
Create and return a fresh environment block, useful for passing to
‘svz_envblock_default’ and ‘svz_envblock_add’. Its size is
initially set to zero.
-- Function: int svz_envblock_default (svz_envblock_t *ENV)
Fill environment block ENV with the environment variables from the
current process, replacing its current contents (if any).
-- Function: int svz_envblock_add (svz_envblock_t *ENV, char *FORMAT,
...)
Insert a new environment variable into environment block ENV. The
FORMAT argument is a ‘printf’-style format string describing how to
format the optional arguments. You specify environment variables
in the ‘VAR=VALUE’ format.
-- Function: void svz_envblock_destroy (svz_envblock_t *ENV)
Destroy environment block ENV completely. Afterwards, ENV is
invalid and should therefore not be further referenced.
-- Function: void * svz_envblock_get (svz_envblock_t *ENV)
Convert environment block ENV into something which can be passed to
‘execve’ (Unix) or ‘CreateProcess’ (Windows). Additionally, under
Windows, sort the environment block.
(Unfortunately the layout of environment blocks in Unices and
Windows differ. On Unices you have a NULL terminated array of
character strings (i.e., ‘char **’) and on Windows systems you have
a simple character string containing the environment variables in
the format ‘VAR=VALUE’ each separated by a zero byte (i.e., ‘char
*’). The end of the list is indicated by a further zero byte.)
5.2.8 Socket management
-----------------------
The functions described in this section deal with the operations on C
structures called ‘svz_socket_t’. See the description of each function
for details on which kind of socket it can handle and what they are for.
-- Function: int svz_sock_nconnections (void)
Return the number of currently connected sockets.
-- Function: int svz_sock_write (svz_socket_t *SOCK, char *BUF,
int LEN)
Write LEN bytes from the memory location pointed to by BUF to the
output buffer of the socket SOCK. Also try to flush the buffer to
the socket of SOCK if possible. Return a non-zero value on error,
which normally means a buffer overflow.
-- Function: int svz_sock_printf (svz_socket_t *SOCK, const char *FMT,
...)
Print a formatted string on the socket SOCK. FMT is the
‘printf’-style format string, which describes how to format the
optional arguments.
-- Function: int svz_sock_resize_buffers (svz_socket_t *SOCK,
int SEND_BUF_SIZE, int RECV_BUF_SIZE)
Resize the send and receive buffers for the socket SOCK.
SEND_BUF_SIZE is the new size for the send buffer, RECV_BUF_SIZE
for the receive buffer. Note that data may be lost when the
buffers shrink. For a new buffer size of 0 the buffer is freed and
the pointer set to NULL.
-- Function: int svz_sock_check_request (svz_socket_t *SOCK)
Check for the kind of packet delimiter within SOCK and and assign
one of the default ‘check_request’ routines (one or more byte
delimiters or a fixed size).
Afterwards this function will never ever be called again because
the callback gets overwritten here.
-- Function: void svz_sock_reduce_recv (svz_socket_t *SOCK, int LEN)
Shorten the receive buffer of SOCK by LEN bytes.
-- Function: void svz_sock_reduce_send (svz_socket_t *SOCK, int LEN)
Reduce the send buffer of SOCK by LEN bytes.
Because libserveez manages the creation and destruction of
‘svz_socket_t’ objects internally, the following API element is useful
for syncronizing client-code references to those objects with those
objects.
-- Function: void svz_sock_prefree (int ADDSUB, svz_sock_prefree_fn FN)
Register (if ADDSUB is non-zero), or unregister (otherwise) the
function FN to be called immediately prior to a ‘svz_socket_t’
being freed. FN is called with one arg ‘sock’, and should not
return anything. In other words:
typedef void (svz_sock_prefree_fn) (const svz_socket_t *);
Note the ‘const’!
5.2.9 Coserver functions
------------------------
This section describes the internal coserver interface of Serveez.
Coservers are helper processes meant to perform blocking tasks. This is
necessary because Serveez itself is single threaded. Each coserver is
connected via a pair of pipes to the main thread of Serveez
communicating over a simple text line protocol. Each request/response
is separated by a newline character.
-- Function: int svz_foreach_coserver (svz_coserver_do_t *FUNC,
void *CLOSURE)
Call FUNC for each coserver, passing additionally the second arg
CLOSURE. If FUNC returns a negative value, return immediately with
that value (breaking out of the loop), otherwise, return 0.
-- Function: void svz_coserver_check (void)
Under woe32 check if there was any response from an active
coserver. Moreover keep the coserver threads/processes alive. If
one of the coservers dies due to buffer overrun or might be
overloaded, start a new one.
Call this function whenever there is time, e.g., within the timeout
of the ‘select’ system call.
-- Function: void svz_coserver_destroy (int TYPE)
Destroy specific coservers with the type TYPE. All instances of
this coserver type will be stopped.
-- Function: svz_coserver_t * svz_coserver_create (int TYPE)
Create and return a single coserver with the given type TYPE.
-- Function: const char * svz_coserver_type_name
(const svz_coserver_t *COSERVER)
Return the type name of COSERVER.
-- Function: void svz_coserver_rdns_invoke (svz_address_t *ADDR,
svz_coserver_handle_result_t CB, void *CLOSURE)
Enqueue a request for the reverse DNS coserver to resolve address
ADDR, arranging for callback CB to be called with two args: the
hostname (a string) and the opaque data CLOSURE.
-- Function: void svz_coserver_dns_invoke (char *HOST,
svz_coserver_handle_result_t CB, void *CLOSURE)
Enqueue a request for the DNS coserver to resolve HOST, arranging
for callback CB to be called with two args: the ip address in
dots-and-numbers notation and the opaque data CLOSURE.
-- Function: void svz_coserver_ident_invoke (svz_socket_t *SOCK,
svz_coserver_handle_result_t CB, void *CLOSURE)
Enqueue a request for the ident coserver to resolve the client
identity at SOCK, arranging for callback CB to be called with two
args: the identity (string) and the opaque data CLOSURE.
To make use of coservers, you need to start the coserver interface by
calling ‘svz_updn_all_coservers’ once before, and once after, entering
the main server loop.
-- Function: int svz_updn_all_coservers (int DIRECTION)
If DIRECTION is non-zero, init coserver internals. Otherwise,
finalize them. Return 0 if successful.
If DIRECTION is positive, init also starts one instance each of the
builtin servers. If negative, it doesn’t.
5.2.10 Codec functions
----------------------
The codec interface of the Serveez core API supplies routines for
setting up socket structures to perform encoding or decoding of its
receive or send buffers. It is a transparent layer of buffer
transition. The interface itself tries to unify different types of
codecs. In order to add a new codec the programmer needs to write some
wrapper functions around the actual implementation to fulfill certain
entry and exit semantics of this interface.
-- Function: int svz_foreach_codec (svz_codec_do_t *FUNC,
void *CLOSURE)
Call FUNC for each codec, passing additionally the second arg
CLOSURE. If FUNC returns a negative value, return immediately with
that value (breaking out of the loop), otherwise, return 0.
-- Function: svz_codec_t * svz_codec_get (char *DESCRIPTION, int TYPE)
Find an appropriate codec for the given DESCRIPTION and TYPE (one
of either ‘SVZ_CODEC_ENCODER’ or ‘SVZ_CODEC_DECODER’). Return
‘NULL’ if there is no such codec registered.
-- Function: void svz_codec_ratio (svz_codec_t *CODEC,
svz_codec_data_t *DATA)
Print a text representation of a codec’s current ratio in percent
if possible.
-- Function: int svz_codec_register (svz_codec_t *CODEC)
Register CODEC. Does not register invalid or duplicate codecs.
Return zero on success, non-zero otherwise.
-- Function: int svz_codec_unregister (svz_codec_t *CODEC)
Remove CODEC from the list of known codecs. Return zero if the
codec could be successfully removed, non-zero otherwise.
-- Function: int svz_codec_sock_receive_setup (svz_socket_t *SOCK,
svz_codec_t *CODEC)
Arrange for SOCK to decode or encode its receive data via CODEC.
Return zero on success, non-zero otherwise.
(You need to have set the ‘check_request’ method previously for
this to work.)
-- Function: int svz_codec_sock_receive (svz_socket_t *SOCK)
“This routine is the new ‘check_request’ callback for reading
codecs. It is applied in ‘svz_codec_sock_receive_setup’. Usually
it gets called whenever there is data in the receive buffer. It
lets the current receive buffer be the input of the codec. The
output buffer of the codec gets the new receive buffer of SOCK.
The old ‘check_request’ callback of SOCK gets called afterwards.
When leaving this function, the receive buffer gets restored again
with the bytes snipped consumed by the codec itself.” [ttn sez:
huh?]
-- Function: int svz_codec_sock_send_setup (svz_socket_t *SOCK,
svz_codec_t *CODEC)
Arrange for SOCK to encode or decode its send buffer via CODEC.
Return zero on success, non-zero otherwise.
(You need to have properly set the ‘write_socket’ member of SOCK
previously for this to work.)
-- Function: int svz_codec_sock_send (svz_socket_t *SOCK)
“This is the new ‘write_socket’ callback for SOCK which is called
whenever there is data within the send buffer available and SOCK is
scheduled for writing. It uses the current send buffer as input
buffer for the codec. The output buffer of the codec is used to
invoke the ‘write_socket’ callback saved within
‘svz_codec_sock_send_setup’. After this the send buffer is
restored again without the bytes consumed by the codec.” [ttn sez:
huh?]
-- Function: int svz_codec_sock_disconnect (svz_socket_t *SOCK)
Try to release the resources of both the receiving and sending
codec of SOCK.
This callback is used as the ‘disconnected_socket’ callback of the
socket structure SOCK. It is called by default if the codec socket
structure SOCK gets disconnected for some external reason.
-- Function: svz_codec_t * svz_codec_sock_detect (svz_socket_t *SOCK)
Return a valid codec detected by scanning the receive buffer of
SOCK, or ‘NULL’ if no codec could be detected.
5.2.11 Server types
-------------------
As already noted in the main Serveez manual a server type is the main
specification of the abilities and configuration items of a server which
can be instantiated. It is represented by ‘svz_servertype_t’ in
Serveez. It contains server specific members like its name, different
callbacks, a single default configuration and a list of configuration
items which determine what can be configured.
5.2.11.1 Macros for setting up a new server type
................................................
When specifying a server type you also need to define configuration
items for it. These items refer to addresses in the example
configuration of the server type. These macros can be used to define
such items.
-- Macro: SVZ_REGISTER_INT (name, item, defaultable)
Register a simple integer. C-type: ‘int’. The given NAME
specifies the symbolic name of the integer and ITEM the integer
itself (not its address). The DEFAULTABLE argument can be either
‘SVZ_ITEM_DEFAULTABLE’ or ‘SVZ_ITEM_NOTDEFAULTABLE’.
-- Macro: SVZ_REGISTER_BOOL (name, item, defaultable)
Register a boolean value. C-type: ‘int’.
-- Macro: SVZ_REGISTER_INTARRAY (name, item, defaultable)
Register an array of integers. C-type: ‘svz_array_t *’.
-- Macro: SVZ_REGISTER_STR (name, item, defaultable)
Register a simple character string. C-type: ‘char *’.
-- Macro: SVZ_REGISTER_STRARRAY (name, item, defaultable)
Register a string array. C-type: ‘svz_array_t *’.
-- Macro: SVZ_REGISTER_HASH (name, item, defaultable)
Register a hash table associating strings with strings only.
C-type: ‘svz_hash_t *’.
-- Macro: SVZ_REGISTER_PORTCFG (name, item, defaultable)
Register a port configuration. C-type: ‘svz_portcfg_t *’.
-- Macro: SVZ_REGISTER_END ()
Indicate the end of the list of configuration items. It is the
only mandatory item you need to specify in an example server type
configuration.
-- Macro: SVZ_CONFIG_DEFINE (description, config, prototypes)
Expand to a data structure that properly associates the example
configuration CONFIG with the name DESCRIPTION and its
configuration items PROTOTYPES, for use within a server type
definition.
5.2.11.2 General server type functionality
..........................................
The following set of functions are used to manage the list of known
server types in the Serveez core library. Serveez itself uses some of
these functions to register its builtin server types.
-- Function: int svz_foreach_servertype (svz_servertype_do_t *FUNC,
void *CLOSURE)
Call FUNC for each servertype, passing additionally the second arg
CLOSURE. If FUNC returns a negative value, return immediately with
that value (breaking out of the loop), otherwise, return 0.
-- Function: void svz_servertype_add (svz_servertype_t *SERVER)
Add the server type SERVER to the currently registered servers.
-- Function: svz_servertype_t * svz_servertype_get (char *NAME,
int DYNAMIC)
Find a servertype definition by its short name. If DYNAMIC is set
to non-zero, try to load a shared library that provides that
servertype. Return ‘NULL’ if no server with the given variable
prefix NAME has been found.
-- Function: svz_servertype_t * svz_servertype_find
(svz_server_t *SERVER)
Find a given server instances SERVER server type. Return ‘NULL’ if
there is no such server type (which should never occur since a
server is a child of a server type).
5.2.11.3 Dynamic server loading
...............................
The core API of Serveez is able to register server types dynamically at
runtime. It uses the dynamic linker capabilities of the underlying
operating system to load shared libraries (or DLLs on Win32). This has
been successfully tested on Windows and GNU/Linux. Other systems are
supported but yet untested. Please tell us if you notice misbehaviour
of any sort.
-- Function: void svz_dynload_path_set (svz_array_t *PATHS)
Set the additional search paths for the serveez library. The given
array of strings gets ‘svz_free’d.
-- Function: svz_array_t * svz_dynload_path_get (void)
Create an array of strings containing each an additional search
path. The loadpath is hold in the environment variable
‘SERVEEZ_LOAD_PATH’ which can be set from outside the library or
modified using ‘svz_dynload_path_set’. The returned array needs to
be destroyed after usage.
5.2.12 Server functions
-----------------------
A server in Serveez is an instantiated (configured) server type. It is
merely a copy of a specific server type with a unique server name, and
is represented by ‘svz_server_t’ in the core library.
5.2.12.1 Server functionality
.............................
This section contains functions dealing with the list of known servers
in the core library of Serveez, also with the basics like creation and
destruction of such servers.
-- Function: void svz_foreach_server (svz_server_do_t *FUNC,
void *CLOSURE)
Call FUNC for each server, passing additionally the second arg
CLOSURE.
-- Function: svz_server_t * svz_server_find (void *CFG)
Find a server instance by the given configuration structure CFG.
Return ‘NULL’ if there is no such configuration in any server
instance.
-- Function: svz_array_t * svz_server_clients (svz_server_t *SERVER)
Return a list of clients (socket structures) which are associated
with the given server instance SERVER. If there is no such socket,
return ‘NULL’. Caller should ‘svz_array_destroy’ the returned
array.
-- Function: svz_server_t * svz_server_get (char *NAME)
Get the server instance with the given instance name NAME. Return
‘NULL’ if there is no such server yet.
-- Function: int svz_updn_all_servers (int DIRECTION)
If DIRECTION is non-zero, run the initializers of all servers,
returning -1 if some server did not think it is a good idea to run.
Otherwise, run the local finalizers for all server instances.
5.2.12.2 Configuration
......................
These functions provide an interface for configuring a server. They are
used to create and modify the default configuration of a server type in
order to create a server configuration.
-- Function: int svz_config_type_instantiate (char *TYPE, char *NAME,
char *INSTANCE, void *OPTIONS,
svz_config_accessor_t *ACCESSOR, size_t EBUFSZ, char *EBUF)
Instantiate a configurable type. The TYPE argument specifies the
configurable type name, NAME the name of the type (in the domain of
the configurable type) and INSTANCE the instance name of the type.
Return zero on success, otherwise -1.
-- Function: void svz_config_free (svz_config_prototype_t *PROTOTYPE,
void *CFG)
Release the configuration CFG of the given configuration prototype
PROTOTYPE. If CFG is ‘NULL’, do nothing.
-- Function: void * svz_collect (int TYPE, size_t COUNT, void *DATA)
Create a collection of TYPE, given the COUNT items of DATA. Valid
values of TYPE are one of: ‘SVZ_INTARRAY’, ‘SVZ_STRARRAY’,
‘SVZ_STRHASH’. For a string hash, DATA should be alternating keys
and values; the returned hash table will have ‘COUNT / 2’ elements.
The C type of DATA for an int array should be ‘int[]’, and for
string array or hash it should be ‘char*[]’. On error (either bad
TYPE or odd COUNT for string hash), return ‘NULL’.
Here are some convenience macros for ‘svz_collect’:
-- Macro: SVZ_COLLECT_INTARRAY (cvar)
Return an integer array ‘svz_array_t *’ created from ‘int CVAR[]’.
-- Macro: SVZ_COLLECT_STRARRAY (cvar)
Return a string array ‘svz_array_t *’ created from ‘char *CVAR[]’.
-- Macro: SVZ_COLLECT_STRHASH (cvar)
Return a string hash ‘svz_hash_t *’ created from ‘char *CVAR[]’.
5.2.12.3 Bindings
.................
The following functionality represents the relationship between port
configurations as described in *note Port config funcs:: and server
instances. When binding a server to a specific port configuration the
core library creates listeners as needed by itself.
-- Function: int svz_server_bind (svz_server_t *SERVER,
svz_portcfg_t *PORT)
Bind the server instance SERVER to the port configuration PORT if
possible. Return non-zero on errors, otherwise zero. It might
occur that a single server is bound to more than one network port
if, e.g., the TCP/IP address is specified by ‘*’ (asterisk) since
this gets expanded to the known list of interfaces.
-- Function: svz_array_t * svz_server_portcfgs (svz_server_t *SERVER)
Return an array of port configurations to which the server instance
SERVER is currently bound to, or ‘NULL’ if there is no such
binding. Caller should ‘svz_array_destroy’ the returned array when
done.
-- Function: svz_array_t * svz_server_listeners (svz_server_t *SERVER)
Return an array of listening socket structures to which the server
instance SERVER is currently bound to, or ‘NULL’ if there is no
such binding. Caller should ‘svz_array_destroy’ the returned array
when done.
-- Function: svz_array_t * svz_sock_servers (svz_socket_t *SOCK)
Return the array of server instances bound to the listening SOCK,
or ‘NULL’ if there are no bindings. Caller should
‘svz_array_destroy’ the returned array when done.
-- Function: int svz_binding_contains_server (svz_socket_t *SOCK,
svz_server_t *SERVER)
Checks whether the server instance SERVER is bound to the server
socket structure SOCK. Return one if so, otherwise zero.
-- Function: size_t svz_pp_server_bindings (char *BUF, size_t SIZE,
svz_server_t *SERVER)
Format a space-separated list of current port configuration
bindings for SERVER into BUF, which has SIZE bytes. The string is
guaranteed to be nul-terminated. Return the length (at most ‘SIZE
- 1’) of the formatted string.
5.2.12.4 Server core
....................
-- Variable: svz_t_handle svz_child_died
Set to a non-zero value whenever the server receives a SIGCHLD
signal.
-- Function: int svz_shutting_down_p (void)
Return non-zero if the core is in the process of shutting down
(typically as a result of a signal).
-- Function: int svz_foreach_socket (svz_socket_do_t *FUNC,
void *CLOSURE)
Call FUNC for each socket, passing additionally the second arg
CLOSURE. If FUNC returns a negative value, return immediately with
that value (breaking out of the loop), otherwise, return 0.
-- Function: svz_socket_t * svz_sock_find (int ID, int VERSION)
Return the socket structure for the socket id ID and the version
VERSION, or ‘NULL’ if no such socket exists. If VERSION is -1 it
is not checked.
-- Function: int svz_sock_schedule_for_shutdown (svz_socket_t *SOCK)
Mark socket SOCK as killed. That means that no further operations
except disconnecting and freeing are allowed. All marked sockets
will be deleted once the server loop is through.
-- Function: int svz_sock_enqueue (svz_socket_t *SOCK)
Enqueue the socket SOCK into the list of sockets handled by the
server loop.
-- Function: void svz_sock_setparent (svz_socket_t *CHILD,
svz_socket_t *PARENT)
Set the CHILD socket’s parent to PARENT.
This should be called whenever a listener accepts a connection and
creates a new child socket.
-- Function: svz_socket_t * svz_sock_getparent (svz_socket_t *CHILD)
Return the CHILD socket’s parent socket structure, or ‘NULL’ if
this socket does not exist anymore. This might happen if a
listener dies for some reason.
-- Function: void svz_sock_setreferrer (svz_socket_t *SOCK,
svz_socket_t *REFERRER)
Set the referring socket structure of SOCK to REFERRER. If
REFERRER is ‘NULL’ the reference will be invalidated.
This can be used to create some relationship between two socket
structures.
-- Function: svz_socket_t * svz_sock_getreferrer (svz_socket_t *SOCK)
Get the referrer of the socket structure SOCK. Return ‘NULL’ if
there is no such socket.
-- Function: svz_portcfg_t * svz_sock_portcfg (svz_socket_t *SOCK)
Return the parent’s port configuration of SOCK, or ‘NULL’ if the
given socket has no parent, i.e. is a listener.
5.2.12.5 Server loop
....................
This section describes the main server loop functionality. There two
modes of operation. The default mode as used in Serveez is to jump into
the loop and wait until the core library drops out of it. In the other
mode, the caller tells the Serveez core library to scan (and process)
its socket chain once and return immediately. Thus, caller is able to
issue additional functionality in between each pass, useful if such
functionality cannot be handled within the timers (notifiers) of servers
and sockets.
-- Function: void svz_loop_pre (void)
Initialize top-of-cycle state.
Call this function once before using ‘svz_loop_one’.
-- Function: void svz_loop_post (void)
Clean up bottom-of-cycle state.
Call this function once after using ‘svz_loop_one’.
-- Function: void svz_loop (void)
Loop, serving. In other words, handle all signals, incoming and
outgoing connections and listening server sockets.
-- Function: void svz_loop_one (void)
Handle all things once.
This function is called regularly by ‘svz_loop’.
5.2.12.6 Server sockets
.......................
This section deals with creating and handling listeners. These
functions provide the default routines invoked when accepting a new
connection on a listener. This is necessary for connection oriented
protocols (TCP and named pipes) only.
[FIXME: All funcs internalized! Write something else here!]
5.2.13 Port configurations
--------------------------
A port configuration is a structure defining a network or file system
configuration. Depending on the type of a server, it can be bound to
one or more port configurations. There are two major types of port
configurations: connection oriented (TCP and PIPE), and packet oriented
(ICMP, UDP and RAW).
-- Function: struct sockaddr_in * svz_portcfg_addr
(svz_portcfg_t *PORT)
Return the pointer of the ‘sockaddr_in’ structure of the given port
configuration PORT if it is a network port configuration.
Otherwise return ‘NULL’.
-- Function: in_port_t svz_portcfg_port (svz_portcfg_t *PORT)
Return the UDP or TCP port of the given port configuration or zero
if it neither TCP nor UDP.
-- Function: char * svz_portcfg_ipaddr (svz_portcfg_t *PORT)
Return the pointer to the ip address ‘ipaddr’ of the given port
configuration PORT if it is a network port configuration.
Otherwise return ‘NULL’.
-- Function: char * svz_portcfg_device (svz_portcfg_t *PORT)
Return the network device name stored in the given port
configuration PORT if it is a network port configuration. Return
‘NULL’ if there is no such device set or if the port configuration
is not a network port configuration.
Serveez maintains an internal list of port configurations, with each
identified by its name. When you bind a server to a port configuration,
it does not get bound to a certain name but to its content. If there
are two or more port configuration specifying the same network or file
system configuration just a single one gets actually used.
-- Function: svz_portcfg_t * svz_portcfg_create (void)
Create a new blank port configuration.
-- Function: int svz_portcfg_equal (svz_portcfg_t *A, svz_portcfg_t *B)
Check if two given port configurations structures are equal, i.e.
specifying the same network port or pipe files. Return
‘SVZ_PORTCFG_EQUAL’ if A and B are identical, ‘SVZ_PORTCFG_MATCH’
if the network address of either port configuration contains the
other (INADDR_ANY match), and otherwise ‘SVZ_PORTCFG_NOMATCH’ or
possibly ‘SVZ_PORTCFG_CONFLICT’.
-- Function: svz_portcfg_t * svz_portcfg_add (char *NAME,
svz_portcfg_t *PORT)
Add the given port configuration PORT associated with the name NAME
to the list of known port configurations. Return ‘NULL’ on errors.
If the return port configuration equals the given port
configuration the given one has been successfully added.
-- Function: svz_portcfg_t * svz_portcfg_get (char *NAME)
Return the port configuration associated with the given name NAME.
Return ‘NULL’ on errors.
-- Function: void svz_portcfg_destroy (svz_portcfg_t *PORT)
Make the given port configuration PORT completely unusable,
removing it from the list of known port configurations. Do nothing
if PORT is ‘NULL’.
-- Function: int svz_portcfg_mkaddr (svz_portcfg_t *THIS)
Construct the ‘sockaddr_in’ fields from the ‘ipaddr’ field. Return
zero if it worked. If it does not work, the ‘ipaddr’ field did not
consist of an ip address in dotted decimal form.
-- Function: svz_portcfg_t * svz_portcfg_dup (svz_portcfg_t *PORT)
Make a copy of the given port configuration PORT.
5.2.14 Boot functions
---------------------
The most important functions are ‘svz_boot’ and ‘svz_halt’ which must be
the first and the last call to the core API.
-- Function: void svz_boot (char const *CLIENT)
Initialize the core library. CLIENT is typically a program’s
‘argv[0]’. If ‘NULL’, take it to be ‘anonymous’.
-- Function: long svz_uptime (void)
Return the number of seconds since ‘svz_boot’ was called, or -1 if
‘svz_boot’ has not yet been called.
-- Function: void svz_halt (void)
Finalization of the core library.
5.2.14.1 Runtime parameters
...........................
There are several runtime parameters indicating the abilities of the
libserveez core API:
‘SVZ_RUNPARM_VERBOSITY’
The log-level verbosity.
‘SVZ_RUNPARM_MAX_SOCKETS’
Maxium number of clients allowed to connect.
These are manipulated by ‘svz_runparm’ and two convenience macros,
both of which accept “nick”, a C token without the prefix ‘SVZ_RUNPARM_’
(e.g., ‘VERBOSITY’).
-- Function: int svz_runparm (int A, int B)
Set or get a runtime parameter. If A is -1, return the value of
runtime parameter B. If A specifies a runtime parameter, set it to
B and return 0. Otherwise, return -1.
-- Macro: SVZ_RUNPARM (nick)
Return the value of runtime parameter NICK.
-- Macro: SVZ_RUNPARM_X (nick, val)
Set the runtime paramater NICK to have value VAL, an integer.
5.2.15 Network interface functions
----------------------------------
The network interface functions of the Serveez core API allow access to
the network devices on your system. The system administrator can set up
these devices to be bound to different Internet addresses and thereby
split the network configuration into different “domains”. Thus, the
system is able to separate the traffic of different networks. If set up
correctly, Serveez can follow these rules.
-- Function: int svz_foreach_interface (svz_interface_do_t *FUNC,
void *CLOSURE)
Call FUNC for each interface, passing additionally the second arg
CLOSURE. If FUNC returns a negative value, return immediately with
that value (breaking out of the loop), otherwise, return 0.
-- Function: int svz_interface_add (size_t INDEX, char *DESC,
int FAMILY, const void *BITS, int DETECTED)
Add a network interface to the current list of known interfaces.
Drop duplicate entries. The given arguments INDEX specifies the
network interface index number, DESC an interface desription,
FAMILY an address-family (e.g., ‘AF_INET’), BITS the address data
in network-byte order, and the DETECTED flag if the given network
interface has been detected by Serveez itself or not.
5.2.16 Useful Windows functions
-------------------------------
Serveez is meant to run on Windows systems as well (with some
restrictions of course). These functions are available with the Windows
implementation of the Serveez core API only. They allow access to the
Windows registry database and some other useful things.
-- Function: int svz_windoze_daemon_control (char *PROG)
If PROG is non-NULL, start the daemon thread with it. Otherwise
(if PROG is NULL), stop the daemon thread. Return 0 on success, -1
on failure.
-- Function: WCHAR * svz_windoze_asc2uni (CHAR *ASC)
Convert an ASCII string into a UNICODE string.
-- Function: CHAR * svz_windoze_uni2asc (WCHAR *UNICODE)
Convert a UNICODE string into an ASCII string.
6 Porting issues
****************
Serveez was always designed with an eye on maximum portability.
Autoconf and Automake have done a great job at this. A lot of
‘#define’’s help to work around some of the different Unix’ oddities.
Have a look at ‘config.h’ for a complete list of all these conditionals.
Most doubtful might be the Win32 port. There are two different ways
of compiling Serveez on Win32: Cygwin and MinGW. The Cygwin version of
Serveez depends on the Unix emulation layer DLL ‘cygwin1.dll’. Both
versions work but it is preferable to use MinGW for performance reasons.
The Cygwin version is slow and limited to a very low number (some 64) of
open files/network connections.(1)
There are major differences between the Win32 and Unix
implementations due to the completely different API those systems
provide.
Processes and Threads
Because process communication is usually done by a pair of
unidirectional pipes we chose that method in order to implement the
coservers in Unix. The Win32 implementation are threads which are
still part of the main process.
Sockets and Handles
On Win32 systems there is a difference in network sockets and file
descriptors. Thus we had to implement quite a complex main socket
loop.
Named Pipes
Both systems Unix and Win32 do provide this functionality (Windows
NT 4.0 and above). The main differences here are the completely
different APIs. On a common Unix you create a named pipe within
the filesystem via ‘mkfifo’. On Win32 you have to
‘CreateNamedPipe’ which will create some special network device. A
further difference is what you can do with these pipes. On Win32
systems this ‘network device’ is valid on remote machines. Named
pipes on Unix are unidirectional, on Win32 they are bidirectional
and instantiatable.
Winsock Versions
There are some difference between the original Winsock 1.1 API and
the new version 2.2.x. In a nutshell, WinSock 2 is WinSock 1.1 on
steroids, it’s a superset of 1.1’s APIs and architecture. In
addition to its new features, it also clarifies existing
ambiguities in the 1.1 WinSock specification and adds new
extensions that take advantage of operating system features and
enhance application performance and efficiency. Finally, WinSock 2
includes a number of new protocol-specific extensions. These
extensions –such as multicast socket options– are relegated to a
separate annex, since the main WinSock 2 protocol specification is
protocol-independent.
The Winsock DLL and import library for version 1.1 are
‘wsock32.dll’ and ‘wsock32.lib’ and for version 2.2 it is
‘ws2_32.dll’ and ‘ws2_32.lib’. Serveez is currently using version
2.2.
The Winsock API is still a bit buggy. Connected datagram behaviors
are not pertinent to any WinSock 2 features, but to generic
WinSock. On Win95 it is possible to use ‘recvfrom’/‘WSARecvFrom’
on a “connected” UDP socket, but on NT4 ‘recvfrom’/‘WSARecvFrom’
fail with 10056 (‘WSAEISCONN’). NOTE: ‘sendto’/‘WSASendTo’ fail
with ‘WSAEISCONN’ on both (which I do not see any reason for, but
anyway ...).
Raw sockets on Windows systems
Raw sockets require Winsock 2. To use them under Windows NT/2000,
you must be logged in as an Administrator. On any other
Microsoft’s we were trying to use the ‘ICMP.DLL’ (an idiotic and
almost useless API) without success. Microsoft says they will
replace it as soon as something better comes along. (Microsoft’s
been saying this since the Windows 95 days, however, yet this
functionality still exists in Windows 2000.) It seems like you
cannot send ICMP or even raw packets from the userspace of Windows
(except via the ‘ICMP.DLL’ which is limited to echo requests). We
also noticed that you cannot receive any packets previously sent.
The only thing which works on all Windows systems
(9x/ME/NT/2000/XP) is receiving packets the “kernel” itself
generated (like echo replies). One good thing we noticed about
Windows 2000 is that the checksums of fragmented ICMP packets get
correctly recalculated. That is not the case in the current Linux
kernels.
Miscellaneous
To use the Win32 Winsock in the Cygwin port, you just need to
‘#define Win32_Winsock’ and ‘#include "windows.h"’ at the top of
your source file(s). You will also want to add ‘-lwsock32’ to the
compiler’s command line so you link against ‘libwsock32.a’.
What preprocessor macros do I need to know about ? We use ‘_WIN32’
to signify access to the Win32 API and ‘__CYGWIN__’ for access to
the Cygwin environment provided by the dll. We chose ‘_WIN32’
because this is what Microsoft defines in VC++ and we thought it
would be a good idea for compatibility with VC++ code to follow
their example. We use ‘_MFC_VER’ to indicate code that should be
compiled with VC++.
Why we do not use pipes for coservers ? Windows differentiates
between sockets and file descriptors, that is why you can not
‘select’ file descriptors. Please ‘close’ the pipe’s descriptors
via ‘CloseHandle’ and not ‘closesocket’, because this will fail.
The C run-time libraries have a preset limit for the number of
files that can be open at any one time. The limit for applications
that link with the single-thread static library (‘LIBC.LIB’) is 64
file handles or 20 file streams. Applications that link with
either the static or dynamic multithread library (‘LIBCMT.LIB’ or
‘MSVCRT.LIB’ and ‘MSVCRT.DLL’), have a limit of 256 file handles or
40 file streams. Attempting to open more than the maximum number
of file handles or file streams causes program failure.
As far as I know, one of the big limitations of Winsock is that the
SOCKET type is *not* equivalent to file descriptor. It is however
with BSD and POSIX sockets. That is one of the major reasons for
using a separate data type, SOCKET, not an int, a typical type for
a file descriptor. This implies that you cannot mix SOCKETs and
stdio, sorry. This is the case when you use ‘-mno-cygwin’.
Actually they are regular file handles, just like any other. There
is a bug in all 9x/kernel32 libc/msv/crtdll interface
implementations ‘GetFileType’ returns ‘TYPE_UNKNOWN’ for socket
handles. Since this is AFAIK the only unknown type there is, you
know you have a socket handle. There is a fix in the more recent
perl distributions that you can use as a general solution.
‘-loldnames -lperlcrt -lmsvcrt’ will get you ‘TYPE_CHAR’ for socket
handles.
Now follows the list on which operating systems and architectures
Serveez has been build and tested successfully.
• FreeBSD 3.3, 4.0, 4.3, 4.4, 4.5, 4.6, 4.7 on Intel
• FreeBSD 4.0, 4.4, 4.6 on Alpha
• NetBSD 1.5, 1.6 on Alpha
• OpenBSD 3.0, 3.1 on Alpha
• OpenBSD 3.1 on Intel
• GNU/Linux 2.x.x on Intel
• GNU/Linux 2.x.x on Alpha
• GNU/Linux 2.2.x on Sparc64 (UltraSparcII + MachV)
• GNU/Linux 2.x.x on PowerPC (RS/6000)
• GNU/Linux 2.4.x on ia64 (Itanium)
• GNU/Linux 2.4.x on StrongARM (iPAQ)
• GNU/Linux 2.4.x on Motorola 680x0
• GNU/Linux 2.4.x on IBM S/390
• GNU/Linux 2.4.x on HP PA-RISC
• GNU/Linux 2.4.x on MIPS
• Solaris 2.6, 2.7 on Sparc32, Sparc64
• SunOS 5.8 on Sparc32
• SunOS 5.6 on Intel
• AIX 4.3 on RS/6000
• MacOS X10.1/Darwin 1.4, 5.4, 5.5 on PowerPC (Macintosh)
• Windows 95 on Intel
• Windows 98 on Intel
• Windows Millennium Edition on Intel
• Windows NT 4.0 on Intel
• Windows 2000 on Intel
• Windows XP on Intel
• IRIX 6.x on MIPS
• Tru64/OSF1 UNIX V4.0 (former Digital UNIX) on Alpha
• Tru64/OSF1 UNIX V5.x (former Digital UNIX) on Alpha
• HP-UX B.11.11 on HP PA-RISC (PA-8700/PA-8600)
• HP-UX B.11.22 on ia64 (Itanium)
---------- Footnotes ----------
(1) This was written circa 2003—maybe the situation is now improved.
7 Bibliography
**************
This section contain some of the documents and resources we read and
used to implement various parts of this package. They appear in no
specific order.
1. RFC 760
The Internet Protocol
2. RFC 1071
Computing the Internet Checksum
3. RFC 1413
Identification Protocol
4. RFC 1459
Internet Relay Chat Protocol
5. RFC 1945
Hypertext Transfer Protocol – HTTP/1.0
6. RFC 2068
Hypertext Transfer Protocol – HTTP/1.1
7. RFC 2616
Hypertext Transfer Protocol – HTTP/1.1
8. RFC 768
User Datagram Protocol
9. RFC 791
Internet Protocol
10. RFC 777
Internet Control Message Protocol
11.
Home of the MinGW (Minimal GNU for Windows) project
12.
The Gnutella Protocol
13.
The official EFNet site (includes Hybrid IRC server)
14.
Winsock Development Information
15.
Winsock Programmer’s FAQ
Appendix A GNU Free Documentation License
*****************************************
Version 1.3, 3 November 2008
Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
0. PREAMBLE
The purpose of this License is to make a manual, textbook, or other
functional and useful document “free” in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or
noncommercially. Secondarily, this License preserves for the
author and publisher a way to get credit for their work, while not
being considered responsible for modifications made by others.
This License is a kind of “copyleft”, which means that derivative
works of the document must themselves be free in the same sense.
It complements the GNU General Public License, which is a copyleft
license designed for free software.
We have designed this License in order to use it for manuals for
free software, because free software needs free documentation: a
free program should come with manuals providing the same freedoms
that the software does. But this License is not limited to
software manuals; it can be used for any textual work, regardless
of subject matter or whether it is published as a printed book. We
recommend this License principally for works whose purpose is
instruction or reference.
1. APPLICABILITY AND DEFINITIONS
This License applies to any manual or other work, in any medium,
that contains a notice placed by the copyright holder saying it can
be distributed under the terms of this License. Such a notice
grants a world-wide, royalty-free license, unlimited in duration,
to use that work under the conditions stated herein. The
“Document”, below, refers to any such manual or work. Any member
of the public is a licensee, and is addressed as “you”. You accept
the license if you copy, modify or distribute the work in a way
requiring permission under copyright law.
A “Modified Version” of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
A “Secondary Section” is a named appendix or a front-matter section
of the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document’s overall
subject (or to related matters) and contains nothing that could
fall directly within that overall subject. (Thus, if the Document
is in part a textbook of mathematics, a Secondary Section may not
explain any mathematics.) The relationship could be a matter of
historical connection with the subject or with related matters, or
of legal, commercial, philosophical, ethical or political position
regarding them.
The “Invariant Sections” are certain Secondary Sections whose
titles are designated, as being those of Invariant Sections, in the
notice that says that the Document is released under this License.
If a section does not fit the above definition of Secondary then it
is not allowed to be designated as Invariant. The Document may
contain zero Invariant Sections. If the Document does not identify
any Invariant Sections then there are none.
The “Cover Texts” are certain short passages of text that are
listed, as Front-Cover Texts or Back-Cover Texts, in the notice
that says that the Document is released under this License. A
Front-Cover Text may be at most 5 words, and a Back-Cover Text may
be at most 25 words.
A “Transparent” copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed
of pixels) generic paint programs or (for drawings) some widely
available drawing editor, and that is suitable for input to text
formatters or for automatic translation to a variety of formats
suitable for input to text formatters. A copy made in an otherwise
Transparent file format whose markup, or absence of markup, has
been arranged to thwart or discourage subsequent modification by
readers is not Transparent. An image format is not Transparent if
used for any substantial amount of text. A copy that is not
“Transparent” is called “Opaque”.
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format,
SGML or XML using a publicly available DTD, and standard-conforming
simple HTML, PostScript or PDF designed for human modification.
Examples of transparent image formats include PNG, XCF and JPG.
Opaque formats include proprietary formats that can be read and
edited only by proprietary word processors, SGML or XML for which
the DTD and/or processing tools are not generally available, and
the machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
The “Title Page” means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the
material this License requires to appear in the title page. For
works in formats which do not have any title page as such, “Title
Page” means the text near the most prominent appearance of the
work’s title, preceding the beginning of the body of the text.
The “publisher” means any person or entity that distributes copies
of the Document to the public.
A section “Entitled XYZ” means a named subunit of the Document
whose title either is precisely XYZ or contains XYZ in parentheses
following text that translates XYZ in another language. (Here XYZ
stands for a specific section name mentioned below, such as
“Acknowledgements”, “Dedications”, “Endorsements”, or “History”.)
To “Preserve the Title” of such a section when you modify the
Document means that it remains a section “Entitled XYZ” according
to this definition.
The Document may include Warranty Disclaimers next to the notice
which states that this License applies to the Document. These
Warranty Disclaimers are considered to be included by reference in
this License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and
has no effect on the meaning of this License.
2. VERBATIM COPYING
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License
applies to the Document are reproduced in all copies, and that you
add no other conditions whatsoever to those of this License. You
may not use technical measures to obstruct or control the reading
or further copying of the copies you make or distribute. However,
you may accept compensation in exchange for copies. If you
distribute a large enough number of copies you must also follow the
conditions in section 3.
You may also lend copies, under the same conditions stated above,
and you may publicly display copies.
3. COPYING IN QUANTITY
If you publish printed copies (or copies in media that commonly
have printed covers) of the Document, numbering more than 100, and
the Document’s license notice requires Cover Texts, you must
enclose the copies in covers that carry, clearly and legibly, all
these Cover Texts: Front-Cover Texts on the front cover, and
Back-Cover Texts on the back cover. Both covers must also clearly
and legibly identify you as the publisher of these copies. The
front cover must present the full title with all words of the title
equally prominent and visible. You may add other material on the
covers in addition. Copying with changes limited to the covers, as
long as they preserve the title of the Document and satisfy these
conditions, can be treated as verbatim copying in other respects.
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto
adjacent pages.
If you publish or distribute Opaque copies of the Document
numbering more than 100, you must either include a machine-readable
Transparent copy along with each Opaque copy, or state in or with
each Opaque copy a computer-network location from which the general
network-using public has access to download using public-standard
network protocols a complete Transparent copy of the Document, free
of added material. If you use the latter option, you must take
reasonably prudent steps, when you begin distribution of Opaque
copies in quantity, to ensure that this Transparent copy will
remain thus accessible at the stated location until at least one
year after the last time you distribute an Opaque copy (directly or
through your agents or retailers) of that edition to the public.
It is requested, but not required, that you contact the authors of
the Document well before redistributing any large number of copies,
to give them a chance to provide you with an updated version of the
Document.
4. MODIFICATIONS
You may copy and distribute a Modified Version of the Document
under the conditions of sections 2 and 3 above, provided that you
release the Modified Version under precisely this License, with the
Modified Version filling the role of the Document, thus licensing
distribution and modification of the Modified Version to whoever
possesses a copy of it. In addition, you must do these things in
the Modified Version:
A. Use in the Title Page (and on the covers, if any) a title
distinct from that of the Document, and from those of previous
versions (which should, if there were any, be listed in the
History section of the Document). You may use the same title
as a previous version if the original publisher of that
version gives permission.
B. List on the Title Page, as authors, one or more persons or
entities responsible for authorship of the modifications in
the Modified Version, together with at least five of the
principal authors of the Document (all of its principal
authors, if it has fewer than five), unless they release you
from this requirement.
C. State on the Title page the name of the publisher of the
Modified Version, as the publisher.
D. Preserve all the copyright notices of the Document.
E. Add an appropriate copyright notice for your modifications
adjacent to the other copyright notices.
F. Include, immediately after the copyright notices, a license
notice giving the public permission to use the Modified
Version under the terms of this License, in the form shown in
the Addendum below.
G. Preserve in that license notice the full lists of Invariant
Sections and required Cover Texts given in the Document’s
license notice.
H. Include an unaltered copy of this License.
I. Preserve the section Entitled “History”, Preserve its Title,
and add to it an item stating at least the title, year, new
authors, and publisher of the Modified Version as given on the
Title Page. If there is no section Entitled “History” in the
Document, create one stating the title, year, authors, and
publisher of the Document as given on its Title Page, then add
an item describing the Modified Version as stated in the
previous sentence.
J. Preserve the network location, if any, given in the Document
for public access to a Transparent copy of the Document, and
likewise the network locations given in the Document for
previous versions it was based on. These may be placed in the
“History” section. You may omit a network location for a work
that was published at least four years before the Document
itself, or if the original publisher of the version it refers
to gives permission.
K. For any section Entitled “Acknowledgements” or “Dedications”,
Preserve the Title of the section, and preserve in the section
all the substance and tone of each of the contributor
acknowledgements and/or dedications given therein.
L. Preserve all the Invariant Sections of the Document, unaltered
in their text and in their titles. Section numbers or the
equivalent are not considered part of the section titles.
M. Delete any section Entitled “Endorsements”. Such a section
may not be included in the Modified Version.
N. Do not retitle any existing section to be Entitled
“Endorsements” or to conflict in title with any Invariant
Section.
O. Preserve any Warranty Disclaimers.
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no
material copied from the Document, you may at your option designate
some or all of these sections as invariant. To do this, add their
titles to the list of Invariant Sections in the Modified Version’s
license notice. These titles must be distinct from any other
section titles.
You may add a section Entitled “Endorsements”, provided it contains
nothing but endorsements of your Modified Version by various
parties—for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of
a standard.
You may add a passage of up to five words as a Front-Cover Text,
and a passage of up to 25 words as a Back-Cover Text, to the end of
the list of Cover Texts in the Modified Version. Only one passage
of Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity. If the Document
already includes a cover text for the same cover, previously added
by you or by arrangement made by the same entity you are acting on
behalf of, you may not add another; but you may replace the old
one, on explicit permission from the previous publisher that added
the old one.
The author(s) and publisher(s) of the Document do not by this
License give permission to use their names for publicity for or to
assert or imply endorsement of any Modified Version.
5. COMBINING DOCUMENTS
You may combine the Document with other documents released under
this License, under the terms defined in section 4 above for
modified versions, provided that you include in the combination all
of the Invariant Sections of all of the original documents,
unmodified, and list them all as Invariant Sections of your
combined work in its license notice, and that you preserve all
their Warranty Disclaimers.
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy. If there are multiple Invariant Sections with the same name
but different contents, make the title of each such section unique
by adding at the end of it, in parentheses, the name of the
original author or publisher of that section if known, or else a
unique number. Make the same adjustment to the section titles in
the list of Invariant Sections in the license notice of the
combined work.
In the combination, you must combine any sections Entitled
“History” in the various original documents, forming one section
Entitled “History”; likewise combine any sections Entitled
“Acknowledgements”, and any sections Entitled “Dedications”. You
must delete all sections Entitled “Endorsements.”
6. COLLECTIONS OF DOCUMENTS
You may make a collection consisting of the Document and other
documents released under this License, and replace the individual
copies of this License in the various documents with a single copy
that is included in the collection, provided that you follow the
rules of this License for verbatim copying of each of the documents
in all other respects.
You may extract a single document from such a collection, and
distribute it individually under this License, provided you insert
a copy of this License into the extracted document, and follow this
License in all other respects regarding verbatim copying of that
document.
7. AGGREGATION WITH INDEPENDENT WORKS
A compilation of the Document or its derivatives with other
separate and independent documents or works, in or on a volume of a
storage or distribution medium, is called an “aggregate” if the
copyright resulting from the compilation is not used to limit the
legal rights of the compilation’s users beyond what the individual
works permit. When the Document is included in an aggregate, this
License does not apply to the other works in the aggregate which
are not themselves derivative works of the Document.
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half
of the entire aggregate, the Document’s Cover Texts may be placed
on covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic
form. Otherwise they must appear on printed covers that bracket
the whole aggregate.
8. TRANSLATION
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section
4. Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections. You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also
include the original English version of this License and the
original versions of those notices and disclaimers. In case of a
disagreement between the translation and the original version of
this License or a notice or disclaimer, the original version will
prevail.
If a section in the Document is Entitled “Acknowledgements”,
“Dedications”, or “History”, the requirement (section 4) to
Preserve its Title (section 1) will typically require changing the
actual title.
9. TERMINATION
You may not copy, modify, sublicense, or distribute the Document
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense, or distribute it is void,
and will automatically terminate your rights under this License.
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the
copyright holder fails to notify you of the violation by some
reasonable means prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from
that copyright holder, and you cure the violation prior to 30 days
after your receipt of the notice.
Termination of your rights under this section does not terminate
the licenses of parties who have received copies or rights from you
under this License. If your rights have been terminated and not
permanently reinstated, receipt of a copy of some or all of the
same material does not give you any rights to use it.
10. FUTURE REVISIONS OF THIS LICENSE
The Free Software Foundation may publish new, revised versions of
the GNU Free Documentation License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns. See
.
Each version of the License is given a distinguishing version
number. If the Document specifies that a particular numbered
version of this License “or any later version” applies to it, you
have the option of following the terms and conditions either of
that specified version or of any later version that has been
published (not as a draft) by the Free Software Foundation. If the
Document does not specify a version number of this License, you may
choose any version ever published (not as a draft) by the Free
Software Foundation. If the Document specifies that a proxy can
decide which future versions of this License can be used, that
proxy’s public statement of acceptance of a version permanently
authorizes you to choose that version for the Document.
11. RELICENSING
“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any
World Wide Web server that publishes copyrightable works and also
provides prominent facilities for anybody to edit those works. A
public wiki that anybody can edit is an example of such a server.
A “Massive Multiauthor Collaboration” (or “MMC”) contained in the
site means any set of copyrightable works thus published on the MMC
site.
“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0
license published by Creative Commons Corporation, a not-for-profit
corporation with a principal place of business in San Francisco,
California, as well as future copyleft versions of that license
published by that same organization.
“Incorporate” means to publish or republish a Document, in whole or
in part, as part of another Document.
An MMC is “eligible for relicensing” if it is licensed under this
License, and if all works that were first published under this
License somewhere other than this MMC, and subsequently
incorporated in whole or in part into the MMC, (1) had no cover
texts or invariant sections, and (2) were thus incorporated prior
to November 1, 2008.
The operator of an MMC Site may republish an MMC contained in the
site under CC-BY-SA on the same site at any time before August 1,
2009, provided the MMC is eligible for relicensing.
ADDENDUM: How to use this License for your documents
====================================================
To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and license
notices just after the title page:
Copyright (C) YEAR YOUR NAME.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license is included in the section entitled ``GNU
Free Documentation License''.
If you have Invariant Sections, Front-Cover Texts and Back-Cover
Texts, replace the “with...Texts.” line with this:
with the Invariant Sections being LIST THEIR TITLES, with
the Front-Cover Texts being LIST, and with the Back-Cover Texts
being LIST.
If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.
If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of free
software license, such as the GNU General Public License, to permit
their use in free software.
Index
*****
* Menu:
* binary->list: Guile servers. (line 1269)
* binary->string: Guile servers. (line 1252)
* binary-char-ref: Guile servers. (line 1338)
* binary-char-set!: Guile servers. (line 1342)
* binary-concat!: Guile servers. (line 1291)
* binary-int-ref: Guile servers. (line 1320)
* binary-int-set!: Guile servers. (line 1324)
* binary-length: Guile servers. (line 1288)
* binary-long-ref: Guile servers. (line 1311)
* binary-long-set!: Guile servers. (line 1315)
* binary-ref: Guile servers. (line 1285)
* binary-reverse: Guile servers. (line 1303)
* binary-reverse!: Guile servers. (line 1307)
* binary-search: Guile servers. (line 1273)
* binary-set!: Guile servers. (line 1280)
* binary-short-ref: Guile servers. (line 1329)
* binary-short-set!: Guile servers. (line 1333)
* binary-subset: Guile servers. (line 1296)
* binary?: Guile servers. (line 1261)
* bind-servers!: Bind servers to ports.
(line 846)
* bind-tcp-port-range!: Bind servers to ports.
(line 855)
* bind-udp-port-range!: Bind servers to ports.
(line 863)
* check-oob-request: Guile servers. (line 1925)
* check-request: Guile servers. (line 1876)
* connect-socket: Guile servers. (line 1798)
* create-tcp-port!: Bind servers to ports.
(line 851)
* create-udp-port!: Bind servers to ports.
(line 859)
* define-servertype!: Guile servers. (line 1414)
* detect-proto: Guile servers. (line 1762)
* disconnected: Guile servers. (line 1889)
* embedding: Embedding. (line 3342)
* endrpcent: Bind servers to ports.
(line 890)
* finalize: Guile servers. (line 1754)
* fs: Bind servers to ports.
(line 811)
* getrpc: Guile servers. (line 1673)
* getrpcbyname: Bind servers to ports.
(line 876)
* getrpcbynumber: Bind servers to ports.
(line 880)
* getrpcent: Bind servers to ports.
(line 870)
* global-finalize: Guile servers. (line 1738)
* global-init: Guile servers. (line 1729)
* handle-request: Guile servers. (line 1844)
* idle: Guile servers. (line 1901)
* info-client: Guile servers. (line 1819)
* info-server: Guile servers. (line 1811)
* init: Guile servers. (line 1746)
* interface-add!: Bind servers to ports.
(line 828)
* kicked: Guile servers. (line 1894)
* libserveez-features: Guile servers. (line 1227)
* list->binary: Guile servers. (line 1264)
* loadpath-add!: Bind servers to ports.
(line 835)
* notify: Guile servers. (line 1828)
* portmap: Guile servers. (line 1685)
* portmap-list: Guile servers. (line 1693)
* println: Bind servers to ports.
(line 818)
* printsln: Bind servers to ports.
(line 821)
* reset: Guile servers. (line 1835)
* serveez-exceptions: Guile servers. (line 1648)
* serveez-interfaces: Guile servers. (line 1667)
* serveez-load: Bind servers to ports.
(line 838)
* serveez-loadpath: Guile servers. (line 1660)
* serveez-maxsockets: Bind servers to ports.
(line 901)
* serveez-nuke: Guile servers. (line 1654)
* serveez-passwd: Bind servers to ports.
(line 906)
* serveez-port?: Guile servers. (line 1636)
* serveez-server?: Guile servers. (line 1640)
* serveez-servertype?: Guile servers. (line 1644)
* serveez-verbosity: Bind servers to ports.
(line 896)
* setrpc: Guile servers. (line 1678)
* setrpcent: Bind servers to ports.
(line 884)
* string->binary: Guile servers. (line 1256)
* svz:coserver:dns: Guile servers. (line 1699)
* svz:coserver:ident: Guile servers. (line 1713)
* svz:coserver:reverse-dns: Guile servers. (line 1706)
* svz:read-file: Guile servers. (line 1606)
* svz:server:clients: Guile servers. (line 1624)
* svz:server:config-ref: Guile servers. (line 1629)
* svz:server:listeners: Guile servers. (line 1619)
* svz:server?: Guile servers. (line 1615)
* svz:sock:boundary: Guile servers. (line 1452)
* svz:sock:check-oob-request: Guile servers. (line 1436)
* svz:sock:check-request: Guile servers. (line 1432)
* svz:sock:connect: Guile servers. (line 1509)
* svz:sock:disconnected: Guile servers. (line 1520)
* svz:sock:final-print: Guile servers. (line 1474)
* svz:sock:find: Guile servers. (line 1588)
* svz:sock:floodprotect: Guile servers. (line 1465)
* svz:sock:handle-request: Guile servers. (line 1448)
* svz:sock:ident: Guile servers. (line 1593)
* svz:sock:idle: Guile servers. (line 1543)
* svz:sock:idle-counter: Guile servers. (line 1552)
* svz:sock:kicked: Guile servers. (line 1526)
* svz:sock:local-address: Guile servers. (line 1577)
* svz:sock:no-delay: Guile servers. (line 1479)
* svz:sock:parent: Guile servers. (line 1558)
* svz:sock:print: Guile servers. (line 1470)
* svz:sock:protocol: Guile servers. (line 1600)
* svz:sock:receive-buffer: Guile servers. (line 1495)
* svz:sock:receive-buffer-reduce: Guile servers. (line 1504)
* svz:sock:receive-buffer-size: Guile servers. (line 1498)
* svz:sock:referrer: Guile servers. (line 1563)
* svz:sock:remote-address: Guile servers. (line 1582)
* svz:sock:send-buffer: Guile servers. (line 1487)
* svz:sock:send-buffer-size: Guile servers. (line 1490)
* svz:sock:send-oob: Guile servers. (line 1442)
* svz:sock:server: Guile servers. (line 1568)
* svz:sock:trigger: Guile servers. (line 1532)
* svz:sock:trigger-condition: Guile servers. (line 1537)
* svz:sock?: Guile servers. (line 1428)
* svz_address_copy: svz_address_t. (line 3764)
* svz_address_family: svz_address_t. (line 3725)
* svz_address_make: svz_address_t. (line 3710)
* svz_address_same: svz_address_t. (line 3733)
* svz_address_to: svz_address_t. (line 3728)
* svz_array_add: Array. (line 3597)
* svz_array_create: Array. (line 3571)
* svz_array_del: Array. (line 3601)
* svz_array_destroy: Array. (line 3581)
* svz_array_foreach: Array. (line 3609)
* svz_array_get: Array. (line 3586)
* svz_array_set: Array. (line 3590)
* svz_array_size: Array. (line 3606)
* svz_atoi: Utility functions. (line 3811)
* svz_binding_contains_server: Server binding. (line 4608)
* svz_boot: Booting. (line 4797)
* svz_calloc: Memory management. (line 3531)
* svz_child_died: Server core. (line 4623)
* svz_close: Core functions. (line 3911)
* svz_closehandle: Pipe connections. (line 3998)
* svz_closesocket: Core functions. (line 3875)
* svz_codec_get: Codec functions. (line 4325)
* svz_codec_ratio: Codec functions. (line 4330)
* svz_codec_register: Codec functions. (line 4335)
* svz_codec_sock_detect: Codec functions. (line 4388)
* svz_codec_sock_disconnect: Codec functions. (line 4380)
* svz_codec_sock_receive: Codec functions. (line 4351)
* svz_codec_sock_receive_setup: Codec functions. (line 4343)
* svz_codec_sock_send: Codec functions. (line 4370)
* svz_codec_sock_send_setup: Codec functions. (line 4362)
* svz_codec_unregister: Codec functions. (line 4339)
* svz_collect: Server configuration.
(line 4555)
* SVZ_COLLECT_INTARRAY: Server configuration.
(line 4566)
* SVZ_COLLECT_STRARRAY: Server configuration.
(line 4569)
* SVZ_COLLECT_STRHASH: Server configuration.
(line 4572)
* SVZ_CONFIG_DEFINE: Macros for setting up a new server type.
(line 4440)
* svz_config_free: Server configuration.
(line 4550)
* svz_config_type_instantiate: Server configuration.
(line 4542)
* svz_coserver_check: Coserver functions. (line 4259)
* svz_coserver_create: Coserver functions. (line 4272)
* svz_coserver_destroy: Coserver functions. (line 4268)
* svz_coserver_dns_invoke: Coserver functions. (line 4285)
* svz_coserver_ident_invoke: Coserver functions. (line 4291)
* svz_coserver_rdns_invoke: Coserver functions. (line 4279)
* svz_coserver_type_name: Coserver functions. (line 4275)
* svz_dynload_path_get: Dynamic server loading.
(line 4489)
* svz_dynload_path_set: Dynamic server loading.
(line 4485)
* svz_envblock_add: Passthrough connections.
(line 4160)
* svz_envblock_create: Passthrough connections.
(line 4151)
* svz_envblock_default: Passthrough connections.
(line 4156)
* svz_envblock_destroy: Passthrough connections.
(line 4167)
* svz_envblock_get: Passthrough connections.
(line 4171)
* svz_envblock_setup: Passthrough connections.
(line 4144)
* svz_fclose: Core functions. (line 3923)
* svz_fd_cloexec: Core functions. (line 3878)
* svz_fopen: Core functions. (line 3919)
* svz_foreach_codec: Codec functions. (line 4319)
* svz_foreach_coserver: Coserver functions. (line 4253)
* svz_foreach_interface: Interface. (line 4845)
* svz_foreach_server: Server functionality.
(line 4510)
* svz_foreach_servertype: General server type functionality.
(line 4453)
* svz_foreach_socket: Server core. (line 4631)
* svz_free: Memory management. (line 3540)
* svz_fstat: Core functions. (line 3914)
* svz_getcwd: Utility functions. (line 3815)
* svz_get_curalloc: Memory management. (line 3548)
* svz_halt: Booting. (line 4805)
* svz_hash_configure: Hashtable. (line 3632)
* svz_hash_contains: Hashtable. (line 3682)
* svz_hash_create: Hashtable. (line 3623)
* svz_hash_delete: Hashtable. (line 3656)
* svz_hash_destroy: Hashtable. (line 3650)
* svz_hash_exists: Hashtable. (line 3687)
* svz_hash_foreach: Hashtable. (line 3672)
* svz_hash_get: Hashtable. (line 3667)
* svz_hash_put: Hashtable. (line 3661)
* svz_hash_size: Hashtable. (line 3678)
* svz_hexdump: Utility functions. (line 3798)
* svz_icmp_connect: ICMP sockets. (line 4039)
* svz_icmp_send_control: ICMP sockets. (line 4044)
* svz_icmp_write: ICMP sockets. (line 4049)
* svz_inet_aton: Core functions. (line 3868)
* svz_inet_ntoa: Core functions. (line 3863)
* svz_interface_add: Interface. (line 4851)
* svz_invalidate_handle: Pipe connections. (line 3995)
* svz_invalid_handle_p: Pipe connections. (line 3992)
* svz_itoa: Utility functions. (line 3806)
* svz_library_features: Library features. (line 3473)
* svz_log: Utility functions. (line 3791)
* svz_log_net_error: Utility functions. (line 3850)
* svz_log_setfile: Utility functions. (line 3794)
* svz_log_sys_error: Utility functions. (line 3847)
* svz_loop: Server loop. (line 4701)
* svz_loop_one: Server loop. (line 4705)
* svz_loop_post: Server loop. (line 4696)
* svz_loop_pre: Server loop. (line 4691)
* svz_malloc: Memory management. (line 3528)
* svz_mingw_at_least_nt4_p: Utility functions. (line 3853)
* svz_mingw_child_dead_p: Passthrough connections.
(line 4131)
* svz_most_recent_dead_child_p: Passthrough connections.
(line 4140)
* svz_open: Core functions. (line 3906)
* svz_openfiles: Utility functions. (line 3819)
* svz_pipe_connect: Pipe connections. (line 3987)
* svz_pipe_create: Pipe connections. (line 3978)
* svz_pipe_create_pair: Pipe connections. (line 3983)
* svz_portcfg_add: Port config funcs. (line 4767)
* svz_portcfg_addr: Port config funcs. (line 4729)
* svz_portcfg_create: Port config funcs. (line 4756)
* svz_portcfg_destroy: Port config funcs. (line 4778)
* svz_portcfg_device: Port config funcs. (line 4744)
* svz_portcfg_dup: Port config funcs. (line 4788)
* svz_portcfg_equal: Port config funcs. (line 4759)
* svz_portcfg_get: Port config funcs. (line 4774)
* svz_portcfg_ipaddr: Port config funcs. (line 4739)
* svz_portcfg_mkaddr: Port config funcs. (line 4783)
* svz_portcfg_port: Port config funcs. (line 4735)
* SVZ_PP_ADDR: svz_address_t. (line 3773)
* svz_pp_address: svz_address_t. (line 3738)
* svz_pp_addr_port: svz_address_t. (line 3749)
* SVZ_PP_ADDR_PORT: svz_address_t. (line 3777)
* svz_pp_server_bindings: Server binding. (line 4613)
* svz_realloc: Memory management. (line 3535)
* SVZ_REGISTER_BOOL: Macros for setting up a new server type.
(line 4416)
* SVZ_REGISTER_END: Macros for setting up a new server type.
(line 4435)
* SVZ_REGISTER_HASH: Macros for setting up a new server type.
(line 4428)
* SVZ_REGISTER_INT: Macros for setting up a new server type.
(line 4410)
* SVZ_REGISTER_INTARRAY: Macros for setting up a new server type.
(line 4419)
* SVZ_REGISTER_PORTCFG: Macros for setting up a new server type.
(line 4432)
* SVZ_REGISTER_STR: Macros for setting up a new server type.
(line 4422)
* SVZ_REGISTER_STRARRAY: Macros for setting up a new server type.
(line 4425)
* svz_runparm: Booting. (line 4824)
* SVZ_RUNPARM: Booting. (line 4829)
* SVZ_RUNPARM_X: Booting. (line 4832)
* svz_sendfile: Core functions. (line 3896)
* svz_servertype_add: General server type functionality.
(line 4459)
* svz_servertype_find: General server type functionality.
(line 4469)
* svz_servertype_get: General server type functionality.
(line 4462)
* svz_server_bind: Server binding. (line 4583)
* svz_server_clients: Server functionality.
(line 4520)
* svz_server_find: Server functionality.
(line 4515)
* svz_server_get: Server functionality.
(line 4526)
* svz_server_listeners: Server binding. (line 4597)
* svz_server_portcfgs: Server binding. (line 4591)
* SVZ_SET_ADDR: svz_address_t. (line 3768)
* svz_set_mm_funcs: Memory management. (line 3522)
* svz_shutting_down_p: Server core. (line 4627)
* svz_socket_unavailable_error_p: Utility functions. (line 3834)
* svz_sock_check_request: Socket management. (line 4214)
* svz_sock_enqueue: Server core. (line 4647)
* svz_sock_find: Server core. (line 4637)
* svz_sock_getparent: Server core. (line 4658)
* svz_sock_getreferrer: Server core. (line 4671)
* svz_sock_nconnections: Socket management. (line 4190)
* svz_sock_portcfg: Server core. (line 4675)
* svz_sock_prefree: Socket management. (line 4233)
* svz_sock_prefree_fn: Socket management. (line 4239)
* svz_sock_printf: Socket management. (line 4200)
* svz_sock_process: Passthrough connections.
(line 4089)
* svz_sock_reduce_recv: Socket management. (line 4222)
* svz_sock_reduce_send: Socket management. (line 4225)
* svz_sock_resize_buffers: Socket management. (line 4206)
* svz_sock_schedule_for_shutdown: Server core. (line 4642)
* svz_sock_servers: Server binding. (line 4603)
* svz_sock_setparent: Server core. (line 4651)
* svz_sock_setreferrer: Server core. (line 4663)
* svz_sock_write: Socket management. (line 4193)
* svz_strdup: Memory management. (line 3544)
* svz_sys_strerror: Utility functions. (line 3839)
* svz_sys_version: Utility functions. (line 3830)
* svz_tcp_connect: TCP sockets. (line 3945)
* svz_tcp_cork: Core functions. (line 3882)
* svz_tcp_nodelay: Core functions. (line 3888)
* svz_tcp_read_socket: TCP sockets. (line 3950)
* svz_tcp_send_oob: TCP sockets. (line 3956)
* svz_time: Utility functions. (line 3823)
* svz_tolower: Utility functions. (line 3827)
* svz_udp_connect: UDP sockets. (line 4008)
* svz_udp_write: UDP sockets. (line 4020)
* svz_updn_all_coservers: Coserver functions. (line 4301)
* svz_updn_all_servers: Server functionality.
(line 4530)
* svz_uptime: Booting. (line 4801)
* svz_windoze_asc2uni: Windoze. (line 4873)
* svz_windoze_daemon_control: Windoze. (line 4868)
* svz_windoze_uni2asc: Windoze. (line 4876)
* trigger: Guile servers. (line 1917)
* trigger-condition: Guile servers. (line 1910)