home *** CD-ROM | disk | FTP | other *** search
Text File | 2007-07-25 | 48.1 KB | 1,472 lines |
- =head1 NAME
-
- Net::Server - Extensible, general Perl server engine
-
- =head1 SYNOPSIS
-
- #!/usr/bin/perl -w -T
- package MyPackage;
-
- use base qw(Net::Server);
-
- sub process_request {
- my $self = shift;
- while (<STDIN>) {
- s/\r?\n$//;
- print "You said '$_'\r\n"; # basic echo
- last if /quit/i;
- }
- }
-
- MyPackage->run(port => 160);
-
- =head1 FEATURES
-
- * Single Server Mode
- * Inetd Server Mode
- * Preforking Simple Mode (PreForkSimple)
- * Preforking Managed Mode (PreFork)
- * Forking Mode
- * Multiplexing Mode using a single process
- * Multi port accepts on Single, Preforking, and Forking modes
- * Simultaneous accept/recv on tcp, udp, and unix sockets
- * Safe signal handling in Fork/PreFork avoids perl signal trouble
- * User customizable hooks
- * Chroot ability after bind
- * Change of user and group after bind
- * Basic allow/deny access control
- * Customized logging (choose Syslog, log_file, or STDERR)
- * HUP able server (clean restarts via sig HUP)
- * Dequeue ability in all Fork and PreFork modes.
- * Taint clean
- * Written in Perl
- * Protection against buffer overflow
- * Clean process flow
- * Extensibility
-
- =head1 DESCRIPTION
-
- C<Net::Server> is an extensible, generic Perl server engine.
- C<Net::Server> combines the good properties from
- C<Net::Daemon> (0.34), C<NetServer::Generic> (1.03), and
- C<Net::FTPServer> (1.0), and also from various concepts in
- the Apache Webserver.
-
- C<Net::Server> attempts to be a generic server as in
- C<Net::Daemon> and C<NetServer::Generic>. It includes with
- it the ability to run as an inetd process
- (C<Net::Server::INET>), a single connection server
- (C<Net::Server> or C<Net::Server::Single>), a forking server
- (C<Net::Server::Fork>), a preforking server which maintains
- a constant number of preforked children (C<Net::Server::PreForkSimple>),
- or as a managed preforking server which maintains the number
- of children based on server load (C<Net::Server::PreFork>).
- In all but the inetd type, the server provides the ability to
- connect to one or to multiple server ports.
-
- C<Net::Server> uses ideologies of C<Net::FTPServer> in order
- to provide extensibility. The additional server types are
- made possible via "personalities" or sub classes of the
- C<Net::Server>. By moving the multiple types of servers out of
- the main C<Net::Server> class, the C<Net::Server> concept is
- easily extended to other types (in the near future, we would
- like to add a "Thread" personality).
-
- C<Net::Server> borrows several concepts from the Apache
- Webserver. C<Net::Server> uses "hooks" to allow custom
- servers such as SMTP, HTTP, POP3, etc. to be layered over
- the base C<Net::Server> class. In addition the
- C<Net::Server::PreFork> class borrows concepts of
- min_start_servers, max_servers, and min_waiting servers.
- C<Net::Server::PreFork> also uses the concept of an flock
- serialized accept when accepting on multiple ports (PreFork
- can choose between flock, IPC::Semaphore, and pipe to control
- serialization).
-
- =head1 PERSONALITIES
-
- C<Net::Server> is built around a common class (Net::Server)
- and is extended using sub classes, or C<personalities>.
- Each personality inherits, overrides, or enhances the base
- methods of the base class.
-
- Included with the Net::Server package are several basic
- personalities, each of which has their own use.
-
- =over 4
-
- =item Fork
-
- Found in the module Net/Server/Fork.pm (see
- L<Net::Server::Fork>). This server binds to one or more
- ports and then waits for a connection. When a client
- request is received, the parent forks a child, which then
- handles the client and exits. This is good for moderately
- hit services.
-
- =item INET
-
- Found in the module Net/Server/INET.pm (see
- L<Net::Server::INET>). This server is designed to be used
- with inetd. The C<pre_bind>, C<bind>, C<accept>, and
- C<post_accept> are all overridden as these services are
- taken care of by the INET daemon.
-
- =item MultiType
-
- Found in the module Net/Server/MultiType.pm (see
- L<Net::Server::MultiType>). This server has no server
- functionality of its own. It is designed for servers which
- need a simple way to easily switch between different
- personalities. Multiple C<server_type> parameters may be
- given and Net::Server::MultiType will cycle through until it
- finds a class that it can use.
-
- =item Multiplex
-
- Found in the module Net/Server/Multiplex.pm (see
- L<Net::Server::Multiplex>). This server binds to one or more
- ports. It uses IO::Multiplex to multiplex between waiting
- for new connections and waiting for input on currently
- established connections. This personality is designed to
- run as one process without forking. The C<process_request>
- method is never used but the C<mux_input> callback is used
- instead (see also L<IO::Multiplex>). See
- examples/samplechat.pl for an example using most of the
- features of Net::Server::Multiplex.
-
- =item PreForkSimple
-
- Found in the module Net/Server/PreFork.pm (see
- L<Net::Server::PreFork>). This server binds to one or more
- ports and then forks C<max_servers> child process. The
- server will make sure that at any given time there are always
- C<max_servers> available to receive a client request. Each
- of these children will process up to C<max_requests> client
- connections. This type is good for a heavily hit site that
- can dedicate max_server processes no matter what the load.
- It should scale well for most applications. Multi port accept
- is accomplished using either flock, IPC::Semaphore, or pipe to serialize the
- children. Serialization may also be switched on for single
- port in order to get around an OS that does not allow multiple
- children to accept at the same time. For a further
- discussion of serialization see L<Net::Server::PreFork>.
-
- =item PreFork
-
- Found in the module Net/Server/PreFork.pm (see
- L<Net::Server::PreFork>). This server binds to one or more
- ports and then forks C<min_servers> child process. The
- server will make sure that at any given time there are
- at least C<min_spare_servers> but not more than C<max_spare_servers>
- available to receive a client request, up
- to C<max_servers>. Each of these children will process up
- to C<max_requests> client connections. This type is good
- for a heavily hit site, and should scale well for most
- applications. Multi port accept is accomplished using
- either flock, IPC::Semaphore, or pipe to serialize the
- children. Serialization may also be switched on for single
- port in order to get around an OS that does not allow multiple
- children to accept at the same time. For a further
- discussion of serialization see L<Net::Server::PreFork>.
-
- =item Single
-
- All methods fall back to Net::Server. This personality is
- provided only as parallelism for Net::Server::MultiType.
-
- =back
-
- C<Net::Server> was partially written to make it easy to add
- new personalities. Using separate modules built upon an
- open architecture allows for easy addition of new features,
- a separate development process, and reduced code bloat in
- the core module.
-
- =head1 SOCKET ACCESS
-
- Once started, the Net::Server will take care of binding to
- port and waiting for connections. Once a connection is
- received, the Net::Server will accept on the socket and
- will store the result (the client connection) in
- $self-E<gt>{server}-E<gt>{client}. This property is a
- Socket blessed into the the IO::Socket classes. UDP
- servers are slightly different in that they will perform
- a B<recv> instead of an B<accept>.
-
- To make programming easier, during the post_accept phase,
- STDIN and STDOUT are opened to the client connection. This
- allows for programs to be written using E<lt>STDINE<gt> and
- print "out\n" to print to the client connection. UDP will
- require using a -E<gt>send call.
-
- =head1 SAMPLE CODE
-
- The following is a very simple server. The main
- functionality occurs in the process_request method call as
- shown below. Notice the use of timeouts to prevent Denial
- of Service while reading. (Other examples of using
- C<Net::Server> can, or will, be included with this distribution).
-
- #!/usr/bin/perl -w -T
-
- package MyPackage;
-
- use strict;
- use base qw(Net::Server::PreFork); # any personality will do
-
- MyPackage->run;
-
- ### over-ridden subs below
-
- sub process_request {
- my $self = shift;
- eval {
-
- local $SIG{'ALRM'} = sub { die "Timed Out!\n" };
- my $timeout = 30; # give the user 30 seconds to type some lines
-
- my $previous_alarm = alarm($timeout);
- while (<STDIN>) {
- s/\r?\n$//;
- print "You said '$_'\r\n";
- alarm($timeout);
- }
- alarm($previous_alarm);
-
- };
-
- if ($@ =~ /timed out/i) {
- print STDOUT "Timed Out.\r\n";
- return;
- }
-
- }
-
- 1;
-
- Playing this file from the command line will invoke a
- Net::Server using the PreFork personality. When building a
- server layer over the Net::Server, it is important to use
- features such as timeouts to prevent Denial Of Service
- attacks.
-
- =head1 ARGUMENTS
-
- There are five possible ways to pass arguments to
- Net::Server. They are I<passing to the new method>, I<passing on
- command line>, I<passing parameters to run>, I<using a conf file>,
- I<returning values in the default_values method>, or I<configuring the
- values in post_configure_hook>.
-
- The C<options> method is used to determine which arguments the server
- will search for and can be used to extend the parsed parameters. Any
- arguments found from the command line, parameters passed to run, and
- arguments found in the conf_file will be matched against the keys of
- the options template. Any commandline parameters that do not match
- will be left in place and can be further processed by the server in
- the various hooks (by looking at @ARGV). Arguments passed to new will
- automatically win over any other options (this can be used if you
- would like to disallow a user passing in other arguments).
-
- Arguments consist of key value pairs. On the commandline
- these pairs follow the POSIX fashion of C<--key value> or
- C<--key=value>, and also C<key=value>. In the conf file the
- parameter passing can best be shown by the following regular
- expression: ($key,$val)=~/^(\w+)\s+(\S+?)\s+$/. Passing
- arguments to the run method is done as follows:
- C<Net::Server->run(key1 => 'val1')>. Passing arguments via
- a prebuilt object can best be shown in the following code:
-
- #!/usr/bin/perl -w -T
-
- package MyPackage;
- use strict;
- use base qw(Net::Server);
-
- my $server = MyPackage->new({
- key1 => 'val1',
- });
-
- $server->run;
-
- All five methods for passing arguments may be used at the
- same time. Once an argument has been set, it is not over
- written if another method passes the same argument. C<Net::Server>
- will look for arguments in the following order:
-
- 1) Arguments passed to the C<new> method.
- 2) Arguments passed on command line.
- 3) Arguments passed to the C<run> method.
- 4) Arguments passed via a conf file.
- 5) Arguments set in the C<default_values> method.
-
- Additionally the following hooks are available:
-
- 1) Arguments set in the configure_hook (occurs after new
- but before any of the other areas are checked).
- 2) Arguments set and validated in the post_configure_hook
- (occurs after all of the other areas are checked).
-
- Each of these levels will override parameters of the same
- name specified in subsequent levels. For example, specifying
- --setsid=0 on the command line will override a value of "setsid 1"
- in the conf file.
-
- Note that the configure_hook method doesn't return values
- to set, but is there to allow for setting up configured values
- before the configure method is called.
-
- Key/value pairs used by the server are removed by the
- configuration process so that server layers on top of
- C<Net::Server> can pass and read their own parameters.
-
- =head1 ADDING CUSTOM ARGUMENTS
-
- It is possible to add in your own custom parameters to those parsed
- by Net::Server. The following code shows how this is done:
-
- sub options {
- my $self = shift;
- my $prop = $self->{'server'};
- my $template = shift;
-
- ### setup options in the parent classes
- $self->SUPER::options($template);
-
- ### add a single value option
- $prop->{'my_option'} ||= undef;
- $template->{'my_option'} = \ $prop->{'my_option'};
-
- ### add a multi value option
- $prop->{'an_arrayref_item'} ||= [];
- $template->{'an_arrayref_item'} = $prop->{'an_arrayref_item'};
- }
-
- Overriding the C<options> method allows for adding your own custom
- fields. A template hashref is passed in, that should then be modified
- to contain an of your custom fields. Fields which are intended to
- receive a single scalar value should have a reference to the
- destination scalar given. Fields which are intended to receive
- multiple values should reference the corresponding destination
- arrayref.
-
- You are responsible for validating your custom options once they have
- been parsed. The post_configure_hook is a good place to do your
- validation.
-
- Some emails have asked why we use this "template" method. The idea is
- that you are creating the the data structure to store the values in,
- and you are also creating a way to get the values into the data
- structure. The template is the way to get the values to the servers
- data structure. One of the possibilities (that probably isn't used
- that much) is that by letting you specify the mapping, you could build
- a nested data structure - even though the passed in arguments are
- flat. It also allows you to setup aliases to your names.
-
- For example, a basic structure might look like this:
-
- $prop = $self->{'server'}
-
- $prop->{'my_custom_option'} ||= undef;
- $prop->{'my_custom_array'} ||= [];
-
- $template = {
- my_custom_option => \ $prop->{'my_custom_option'},
- mco => \ $prop->{'my_custom_option'}, # alias
- my_custom_array => $prop->{'my_custom_array'},
- mca => $prop->{'my_custom_array'}, # an alias
- };
-
- $template->{'mco2'} = $template->{'mco'}; # another way to alias
-
- But you could also have more complex data:
-
- $prop = $self->{'server'};
-
- $prop->{'one_layer'} = {
- two_layer => [
- undef,
- undef,
- ],
- };
-
- $template = {
- param1 => \ $prop->{'one_layer'}->{'two_layer'}->[0],
- param2 => \ $prop->{'one_layer'}->{'two_layer'}->[1],
- };
-
- This is of course a contrived example - but it does show that you can
- get the data from the flat passed in arguments to whatever type of
- structure you need - with only a little bit of effort.
-
- =head1 DEFAULT ARGUMENTS FOR Net::Server
-
- The following arguments are available in the default C<Net::Server> or
- C<Net::Server::Single> modules. (Other personalities may use
- additional parameters and may optionally not use parameters from the
- base class.)
-
- Key Value Default
- conf_file "filename" undef
-
- log_level 0-4 2
- log_file (filename|Sys::Syslog) undef
-
- ## syslog parameters
- syslog_logsock (native|unix|inet|udp
- |tcp|stream|console) unix (on Sys::Syslog < 0.15)
- syslog_ident "identity" "net_server"
- syslog_logopt (cons|ndelay|nowait|pid) pid
- syslog_facility \w+ daemon
-
- port \d+ 20203
- host "host" "*"
- proto (tcp|udp|unix) "tcp"
- listen \d+ SOMAXCONN
-
- reverse_lookups 1 undef
- allow /regex/ none
- deny /regex/ none
- cidr_allow CIDR none
- cidr_deny CIDR none
-
- ## daemonization parameters
- pid_file "filename" undef
- chroot "directory" undef
- user (uid|username) "nobody"
- group (gid|group) "nobody"
- background 1 undef
- setsid 1 undef
-
- no_close_by_child (1|undef) undef
-
- ## See Net::Server::Proto::(TCP|UDP|UNIX|etc)
- ## for more sample parameters.
-
- =over 4
-
- =item conf_file
-
- Filename from which to read additional key value pair arguments
- for starting the server. Default is undef.
-
- There are two ways that you can specify a default location for
- a conf_file. The first is to pass the default value to the run
- method as in:
-
- MyServer->run({
- conf_file => '/etc/my_server.conf',
- });
-
- If the end user passes in --conf_file=/etc/their_server.conf then
- the value will be overridden.
-
- The second way to do this was added in the 0.96 version. It uses
- the default_values method as in:
-
- sub default_values {
- return {
- conf_file => '/etc/my_server.conf',
- }
- }
-
- This method has the advantage of also being able to be overridden
- in the run method.
-
- If you do not want the user to be able to specify a conf_file at
- all, you can pass conf_file to the new method when creating your
- object:
-
- MyServer->new({
- conf_file => '/etc/my_server.conf',
- })->run;
-
- If passed this way, the value passed to new will "win" over any of
- the other passed in values.
-
- =item log_level
-
- Ranges from 0 to 4 in level. Specifies what level of error
- will be logged. "O" means logging is off. "4" means very
- verbose. These levels should be able to correlate to syslog
- levels. Default is 2. These levels correlate to syslog levels
- as defined by the following key/value pairs: 0=>'err',
- 1=>'warning', 2=>'notice', 3=>'info', 4=>'debug'.
-
- =item log_file
-
- Name of log file to be written to. If no name is given and
- hook is not overridden, log goes to STDERR. Default is undef.
- If the magic name "Sys::Syslog" is used, all logging will
- take place via the Sys::Syslog module. If syslog is used
- the parameters C<syslog_logsock>, C<syslog_ident>, and
- C<syslog_logopt>,and C<syslog_facility> may also be defined.
- If a C<log_file> is given or if C<setsid> is set, STDIN and
- STDOUT will automatically be opened to /dev/null and STDERR
- will be opened to STDOUT. This will prevent any output
- from ending up at the terminal.
-
- =item pid_file
-
- Filename to store pid of parent process. Generally applies
- only to forking servers. Default is none (undef).
-
- =item syslog_logsock
-
- Only available if C<log_file> is equal to "Sys::Syslog". May
- be either unix, inet, native, console, stream, udp, or tcp, or
- an arrayref of the types to try. Default is "unix" if the version
- of Sys::Syslog < 0.15 - otherwise the default is to not call
- setlogsock.
-
- See L<Sys::Syslog>.
-
- =item syslog_ident
-
- Only available if C<log_file> is equal to "Sys::Syslog". Id
- to prepend on syslog entries. Default is "net_server".
- See L<Sys::Syslog>.
-
- =item syslog_logopt
-
- Only available if C<log_file> is equal to "Sys::Syslog". May
- be either zero or more of "pid","cons","ndelay","nowait".
- Default is "pid". See L<Sys::Syslog>.
-
- =item syslog_facility
-
- Only available if C<log_file> is equal to "Sys::Syslog".
- See L<Sys::Syslog> and L<syslog>. Default is "daemon".
-
- =item port
-
- See L<Net::Server::Proto>.
- Local port/socket on which to bind. If low port, process must
- start as root. If multiple ports are given, all will be
- bound at server startup. May be of the form
- C<host:port/proto>, C<host:port>, C<port/proto>, or C<port>,
- where I<host> represents a hostname residing on the local
- box, where I<port> represents either the number of the port
- (eg. "80") or the service designation (eg. "http"), and
- where I<proto> represents the protocol to be used. See
- L<Net::Server::Proto>. If you are working with unix sockets,
- you may also specify C<socket_file|unix> or
- C<socket_file|type|unix> where type is SOCK_DGRAM or
- SOCK_STREAM. If the protocol is not specified, I<proto> will
- default to the C<proto> specified in the arguments. If C<proto> is not
- specified there it will default to "tcp". If I<host> is not
- specified, I<host> will default to C<host> specified in the
- arguments. If C<host> is not specified there it will
- default to "*". Default port is 20203. Configuration passed
- to new or run may be either a scalar containing a single port
- number or an arrayref of ports.
-
- =item host
-
- Local host or addr upon which to bind port. If a value of '*' is
- given, the server will bind that port on all available addresses
- on the box. See L<Net::Server::Proto>. See L<IO::Socket>. Configuration
- passed to new or run may be either a scalar containing a single
- host or an arrayref of hosts - if the hosts array is shorter than
- the ports array, the last host entry will be used to augment the
- hosts arrary to the size of the ports array.
-
- =item proto
-
- See L<Net::Server::Proto>.
- Protocol to use when binding ports. See L<IO::Socket>. As
- of release 0.70, Net::Server supports tcp, udp, and unix. Other
- types will need to be added later (or custom modules extending the
- Net::Server::Proto class may be used). Configuration
- passed to new or run may be either a scalar containing a single
- proto or an arrayref of protos - if the protos array is shorter than
- the ports array, the last proto entry will be used to augment the
- protos arrary to the size of the ports array.
-
- =item listen
-
- See L<IO::Socket>. Not used with udp protocol (or UNIX SOCK_DGRAM).
-
- =item reverse_lookups
-
- Specify whether to lookup the hostname of the connected IP.
- Information is cached in server object under C<peerhost>
- property. Default is to not use reverse_lookups (undef).
-
- =item allow/deny
-
- May be specified multiple times. Contains regex to compare
- to incoming peeraddr or peerhost (if reverse_lookups has
- been enabled). If allow or deny options are given, the
- incoming client must match an allow and not match a deny or
- the client connection will be closed. Defaults to empty
- array refs.
-
- =item cidr_allow/cidr_deny
-
- May be specified multiple times. Contains a CIDR block to compare to
- incoming peeraddr. If cidr_allow or cidr_deny options are given, the
- incoming client must match a cidr_allow and not match a cidr_deny or
- the client connection will be closed. Defaults to empty array refs.
-
- =item chroot
-
- Directory to chroot to after bind process has taken place
- and the server is still running as root. Defaults to
- undef.
-
- =item user
-
- Userid or username to become after the bind process has
- occured. Defaults to "nobody." If you would like the
- server to run as root, you will have to specify C<user>
- equal to "root".
-
- =item group
-
- Groupid or groupname to become after the bind process has
- occured. Defaults to "nobody." If you would like the
- server to run as root, you will have to specify C<group>
- equal to "root".
-
- =item background
-
- Specifies whether or not the server should fork after the
- bind method to release itself from the command line.
- Defaults to undef. Process will also background if
- C<setsid> is set.
-
- =item setsid
-
- Specifies whether or not the server should fork after the
- bind method to release itself from the command line and then
- run the C<POSIX::setsid()> command to truly daemonize.
- Defaults to undef. If a C<log_file> is given or if
- C<setsid> is set, STDIN and STDOUT will automatically be
- opened to /dev/null and STDERR will be opened to STDOUT.
- This will prevent any output from ending up at the terminal.
-
- =item no_close_by_child
-
- Boolean. Specifies whether or not a forked child process has
- permission or not to shutdown the entire server process. If set to 1,
- the child may NOT signal the parent to shutdown all children. Default
- is undef (not set).
-
- =item no_client_stdout
-
- Boolean. Default undef (not set). Specifies that STDIN and STDOUT
- should not be opened on the client handle once a connection has been
- accepted. By default the Net::Server will open STDIN and STDOUT on
- the client socket making it easier for many types of scripts to read
- directly from and write directly to the socket using normal print and
- read methods. Disabling this is useful on clients that may be opening
- their own connections to STDIN and STDOUT.
-
- This option has no affect on STDIN and STDOUT which has a magic client
- property that is tied to the already open STDIN and STDOUT.
-
- =item leave_children_open_on_hup
-
- Boolean. Default undef (not set). If set, the parent will not attempt
- to close child processes if the parent receives a SIG HUP. The parent
- will rebind the the open port and begin tracking a fresh set of children.
-
- Children of a Fork server will exit after their current request. Children
- of a Prefork type server will finish the current request and then exit.
-
- Note - the newly restarted parent will start up a fresh set of servers on
- fork servers. The new parent will attempt to keep track of the children from
- the former parent but custom communication channels (open pipes from the child
- to the old parent) will no longer be available to the old child processes. New
- child processes will still connect properly to the new parent.
-
- =back
-
- =head1 PROPERTIES
-
- All of the C<ARGUMENTS> listed above become properties of
- the server object under the same name. These properties, as
- well as other internal properties, are available during
- hooks and other method calls.
-
- The structure of a Net::Server object is shown below:
-
- $self = bless( {
- 'server' => {
- 'key1' => 'val1',
- # more key/vals
- }
- }, 'Net::Server' );
-
- This structure was chosen so that all server related
- properties are grouped under a single key of the object
- hashref. This is so that other objects could layer on top
- of the Net::Server object class and still have a fairly
- clean namespace in the hashref.
-
- You may get and set properties in two ways. The suggested
- way is to access properties directly via
-
- my $val = $self->{server}->{key1};
-
- Accessing the properties directly will speed the server process -
- though some would deem this as bad style. A second way has been
- provided for object oriented types who believe in methods. The second
- way consists of the following methods:
-
- my $val = $self->get_property( 'key1' );
- my $self->set_property( key1 => 'val1' );
-
- Properties are allowed to be changed at any time with
- caution (please do not undef the sock property or you will
- close the client connection).
-
- =head1 CONFIGURATION FILE
-
- C<Net::Server> allows for the use of a configuration file to
- read in server parameters. The format of this conf file is
- simple key value pairs. Comments and blank lines are
- ignored.
-
- #-------------- file test.conf --------------
-
- ### user and group to become
- user somebody
- group everybody
-
- ### logging ?
- log_file /var/log/server.log
- log_level 3
- pid_file /tmp/server.pid
-
- ### optional syslog directive
- ### used in place of log_file above
- #log_file Sys::Syslog
- #syslog_logsock unix
- #syslog_ident myserver
- #syslog_logopt pid|cons
-
- ### access control
- allow .+\.(net|com)
- allow domain\.com
- deny a.+
- cidr_allow 127.0.0.0/8
- cidr_allow 192.0.2.0/24
- cidr_deny 192.0.2.4/30
-
- ### background the process?
- background 1
-
- ### ports to bind (this should bind
- ### 127.0.0.1:20205 and localhost:20204)
- ### See Net::Server::Proto
- host 127.0.0.1
- port localhost:20204
- port 20205
-
- ### reverse lookups ?
- # reverse_lookups on
-
- #-------------- file test.conf --------------
-
- =head1 PROCESS FLOW
-
- The process flow is written in an open, easy to
- override, easy to hook, fashion. The basic flow is
- shown below. This is the flow of the C<$self-E<gt>run> method.
-
- $self->configure_hook;
-
- $self->configure(@_);
-
- $self->post_configure;
-
- $self->post_configure_hook;
-
- $self->pre_bind;
-
- $self->bind;
-
- $self->post_bind_hook;
-
- $self->post_bind;
-
- $self->pre_loop_hook;
-
- $self->loop;
-
- ### routines inside a standard $self->loop
- # $self->accept;
- # $self->run_client_connection;
- # $self->done;
-
- $self->pre_server_close_hook;
-
- $self->server_close;
-
- The server then exits.
-
- During the client processing phase
- (C<$self-E<gt>run_client_connection>), the following
- represents the program flow:
-
- $self->post_accept;
-
- $self->get_client_info;
-
- $self->post_accept_hook;
-
- if( $self->allow_deny
-
- && $self->allow_deny_hook ){
-
- $self->process_request;
-
- }else{
-
- $self->request_denied_hook;
-
- }
-
- $self->post_process_request_hook;
-
- $self->post_process_request;
-
- $self->post_client_connection_hook;
-
- The process then loops and waits for the next
- connection. For a more in depth discussion, please
- read the code.
-
- During the server shutdown phase
- (C<$self-E<gt>server_close>), the following
- represents the program flow:
-
- $self->close_children; # if any
-
- $self->post_child_cleanup_hook;
-
- if( Restarting server ){
- $self->restart_close_hook();
- $self->hup_server;
- }
-
- $self->shutdown_sockets;
-
- $self->server_exit;
-
- =head1 MAIN SERVER METHODS
-
- =over 4
-
- =item C<$self-E<gt>run>
-
- This method incorporates the main process flow. This flow
- is listed above.
-
- The method run may be called in any of the following ways.
-
- MyPackage->run(port => 20201);
-
- MyPackage->new({port => 20201})->run;
-
- my $obj = bless {server=>{port => 20201}}, 'MyPackage';
- $obj->run;
-
- The ->run method should typically be the last method called
- in a server start script (the server will exit at the end
- of the ->run method).
-
- =item C<$self-E<gt>configure>
-
- This method attempts to read configurations from the commandline,
- from the run method call, or from a specified conf_file (the conf_file
- may be specified by passed in parameters, or in the default_values).
- All of the configured parameters are then stored in the {"server"}
- property of the Server object.
-
- =item C<$self-E<gt>post_configure>
-
- The post_configure hook begins the startup of the server. During
- this method running server instances are checked for, pid_files are created,
- log_files are created, Sys::Syslog is initialized (as needed), process
- backgrounding occurs and the server closes STDIN and STDOUT (as needed).
-
- =item C<$self-E<gt>pre_bind>
-
- This method is used to initialize all of the socket objects
- used by the server.
-
- =item C<$self-E<gt>bind>
-
- This method actually binds to the inialized sockets (or rebinds
- if the server has been HUPed).
-
- =item C<$self-E<gt>post_bind>
-
- During this method priveleges are dropped.
- The INT, TERM, and QUIT signals are set to run server_close.
- Sig PIPE is set to IGNORE. Sig CHLD is set to sig_chld. And sig
- HUP is set to call sig_hup.
-
- Under the Fork, PreFork, and PreFork simple personalities, these
- signals are registered using Net::Server::SIG to allow for
- safe signal handling.
-
- =item C<$self-E<gt>loop>
-
- During this phase, the server accepts incoming connections.
- The behavior of how the accepting occurs and if a child process
- handles the connection is controlled by what type of Net::Server
- personality the server is using.
-
- Net::Server and Net::Server single accept only one connection at
- a time.
-
- Net::Server::INET runs one connection and then exits (for use by
- inetd or xinetd daemons).
-
- Net::Server::MultiPlex allows for one process to simultaneously
- handle multiple connections (but requires rewriting the process_request
- code to operate in a more "packet-like" manner).
-
- Net::Server::Fork forks off a new child process for each incoming
- connection.
-
- Net::Server::PreForkSimple starts up a fixed number of processes
- that all accept on incoming connections.
-
- Net::Server::PreFork starts up a base number of child processes
- which all accept on incoming connections. The server throttles
- the number of processes running depending upon the number of
- requests coming in (similar to concept to how Apache controls
- its child processes in a PreFork server).
-
- Read the documentation for each of the types for more information.
-
- =item C<$self-E<gt>server_close>
-
- This method is called once the server has been signaled to end, or
- signaled for the server to restart (via HUP), or the loop
- method has been exited.
-
- This method takes care of cleaning up any remaining child processes,
- setting appropriate flags on sockets (for HUPing), closing up
- logging, and then closing open sockets.
-
- =item C<$self-E<gt>server_exit>
-
- This method is called at the end of server_close. It calls exit,
- but may be overridden to do other items. At this point all services
- should be shut down.
-
- =back
-
- =head1 MAIN CLIENT CONNECTION METHODS
-
- =over 4
-
- =item C<$self-E<gt>run_client_connection>
-
- This method is run after the server has accepted and received
- a client connection. The full process flow is listed
- above under PROCESS FLOWS. This method takes care of
- handling each client connection.
-
- =item C<$self-E<gt>post_accept>
-
- This method opens STDIN and STDOUT to the client socket.
- This allows any of the methods during the run_client_connection
- phase to print directly to and read directly from the
- client socket.
-
- =item C<$self-E<gt>get_client_info>
-
- This method looks up information about the client connection
- such as ip address, socket type, and hostname (as needed).
-
- =item C<$self-E<gt>allow_deny>
-
- This method uses the rules defined in the allow and deny configuration
- parameters to determine if the ip address should be accepted.
-
- =item C<$self-E<gt>process_request>
-
- This method is intended to handle all of the client communication.
- At this point STDIN and STDOUT are opened to the client, the ip
- address has been verified. The server can then
- interact with the client connection according to whatever API or
- protocol the server is implementing. Note that the stub implementation
- uses STDIN and STDOUT and will not work if the no_client_stdout flag
- is set.
-
- This is the main method to override.
-
- The default method implements a simple echo server that
- will repeat whatever is sent. It will quit the child if "quit"
- is sent, and will exit the server if "exit" is sent.
-
- =item C<$self-E<gt>post_process_request>
-
- This method is used to clean up the client connection and
- to handle any parent/child accounting for the forking servers.
-
- =back
-
- =head1 HOOKS
-
- C<Net::Server> provides a number of "hooks" allowing for
- servers layered on top of C<Net::Server> to respond at
- different levels of execution without having to "SUPER" class
- the main built-in methods. The placement of the hooks
- can be seen in the PROCESS FLOW section.
-
- Almost all of the default hook methods do nothing. To use a hook
- you simply need to override the method in your subclass. For example
- to add your own post_configure_hook you could do something like the following:
-
- package MyServer;
-
- sub post_configure_hook {
- my $self = shift;
- my $prop = $self->{'server'};
-
- # do some validation here
- }
-
- The following describes the hooks available in the plain Net::Server class
- (other flavors such as Fork or PreFork have additional hooks).
-
- =over 4
-
- =item C<$self-E<gt>configure_hook()>
-
- This hook takes place immediately after the C<-E<gt>run()>
- method is called. This hook allows for setting up the
- object before any built in configuration takes place.
- This allows for custom configurability.
-
- =item C<$self-E<gt>post_configure_hook()>
-
- This hook occurs just after the reading of configuration
- parameters and initiation of logging and pid_file creation.
- It also occurs before the C<-E<gt>pre_bind()> and
- C<-E<gt>bind()> methods are called. This hook allows for
- verifying configuration parameters.
-
- =item C<$self-E<gt>post_bind_hook()>
-
- This hook occurs just after the bind process and just before
- any chrooting, change of user, or change of group occurs.
- At this point the process will still be running as the user
- who started the server.
-
- =item C<$self-E<gt>pre_loop_hook()>
-
- This hook occurs after chroot, change of user, and change of
- group has occured. It allows for preparation before looping
- begins.
-
- =item C<$self-E<gt>can_read_hook()>
-
- This hook occurs after a socket becomes readible on an
- accept_multi_port request (accept_multi_port is used if there are
- multiple bound ports to accept on, or if the "multi_port"
- configuration parameter is set to true). This hook is intended to
- allow for processing of arbitrary handles added to the IO::Select used
- for the accept_multi_port. These handles could be added during the
- post_bind_hook. No internal support is added for processing these
- handles or adding them to the IO::Socket. Care must be used in how
- much occurs during the can_read_hook as a long response time will
- result in the server being susceptible to DOS attacks. A return value
- of true indicates that the Server should not pass the readible handle
- on to the post_accept and process_request phases.
-
- It is generally suggested that other avenues be pursued for sending
- messages via sockets not created by the Net::Server.
-
- =item C<$self-E<gt>post_accept_hook()>
-
- This hook occurs after a client has connected to the server.
- At this point STDIN and STDOUT are mapped to the client
- socket. This hook occurs before the processing of the
- request.
-
- =item C<$self-E<gt>allow_deny_hook()>
-
- This hook allows for the checking of ip and host information
- beyond the C<$self-E<gt>allow_deny()> routine. If this hook
- returns 1, the client request will be processed,
- otherwise, the request will be denied processing.
-
- =item C<$self-E<gt>request_denied_hook()>
-
- This hook occurs if either the C<$self-E<gt>allow_deny()> or
- C<$self-E<gt>allow_deny_hook()> have taken place.
-
- =item C<$self-E<gt>post_process_request_hook()>
-
- This hook occurs after the processing of the request, but
- before the client connection has been closed.
-
- =item C<$self-E<gt>post_client_connection_hook>
-
- This is one final hook that occurs at the very end of the
- run_client_connection method. At this point all other methods
- and hooks that will run during the run_client_connection
- have finished and the client connection has already been closed.
-
- =item C<$self-E<gt>pre_server_close_hook()>
-
- This hook occurs before the server begins shutting down.
-
- =item C<$self-E<gt>write_to_log_hook>
-
- This hook handles writing to log files. The default hook
- is to write to STDERR, or to the filename contained in
- the parameter C<log_file>. The arguments passed are a
- log level of 0 to 4 (4 being very verbose), and a log line.
- If log_file is equal to "Sys::Syslog", then logging will
- go to Sys::Syslog and will bypass the write_to_log_hook.
-
- =item C<$self-E<gt>fatal_hook>
-
- This hook occurs when the server has encountered an
- unrecoverable error. Arguments passed are the error
- message, the package, file, and line number. The hook
- may close the server, but it is suggested that it simply
- return and use the built in shut down features.
-
- =item C<$self-E<gt>post_child_cleanup_hook>
-
- This hook occurs in the parent server process after all
- children have been shut down and just before the server
- either restarts or exits. It is intended for additional
- cleanup of information. At this point pid_files and
- lockfiles still exist.
-
- =item C<$self-E<gt>restart_open_hook>
-
- This hook occurs if a server has been HUPed (restarted
- via the HUP signal. It occurs just before reopening to
- the filenos of the sockets that were already opened.
-
- =item C<$self-E<gt>restart_close_hook>
-
- This hook occurs if a server has been HUPed (restarted
- via the HUP signal. It occurs just before restarting the
- server via exec.
-
- =back
-
- =head1 OTHER METHODS
-
- =over 4
-
- =item C<$self-E<gt>default_values>
-
- Allow for returning configuration values that will be used if no
- other value could be found.
-
- Should return a hashref.
-
- sub default_values {
- return {
- port => 20201,
- };
- }
-
- =item C<$self-E<gt>handle_syslog_error>
-
- Called when log_file is set to 'Sys::Syslog' and an error occurs
- while writing to the syslog. It is passed two arguments, the
- value of $@, and an arrayref containing the arguments that
- were passed to the log method when the error occured.
-
- =item C<$self-E<gt>log>
-
- Parameters are a log_level and a message.
-
- If log_level is set to 'Sys::Syslog', the parameters may alternately
- be a log_level, a format string, and format string parameters.
- (The second parameter is assumed to be a format string if additional
- arguments are passed along). Passing arbitrary format strings to
- Sys::Syslog will allow the server to be vulnerable to exploit. The
- server maintainer should make sure that any string treated as
- a format string is controlled.
-
- # assuming log_file = 'Sys::Syslog'
-
- $self->log(1, "My Message with %s in it");
- # sends "%s", "My Message with %s in it" to syslog
-
- $self->log(1, "My Message with %s in it", "Foo");
- # sends "My Message with %s in it", "Foo" to syslog
-
- If log_file is set to a file (other than Sys::Syslog), the message
- will be appended to the log file by calling the write_to_log_hook.
-
- If the log_file is Sys::Syslog and an error occurs during write,
- the handle_syslog_error method will be called and passed the
- error exception. The default option of handle_syslog_error is
- to die - but could easily be told to do nothing by using the following
- code in your subclassed server:
-
- sub handle_syslog_error {}
-
- It the log had been closed, you could attempt to reopen it in the error
- handler with the following code:
-
- sub handle_syslog_error {
- my $self = shift;
- $self->open_syslog;
- }
-
- =item C<$self-E<gt>new>
-
- As of Net::Server 0.91 there is finally a new method. This method
- takes a class name and an argument hashref as parameters. The argument
- hashref becomes the "server" property of the object.
-
- package MyPackage;
- use base qw(Net::Server);
-
- my $obj = MyPackage->new({port => 20201});
-
- # same as
-
- my $obj = bless {server => {port => 20201}}, 'MyPackage';
-
- =item C<$self-E<gt>open_syslog>
-
- Called during post_configure when the log_file option is set to 'Sys::Syslog'.
- By default it use the parsed configuration options listed in this document.
- If more custom behavior is desired, the method could be overridden and
- Sys::Syslog::openlog should be called with the custom parameters.
-
- =item C<$self-E<gt>shutdown_sockets>
-
- This method will close any remaining open sockets. This is called
- at the end of the server_close method.
-
- =back
-
- =head1 RESTARTING
-
- Each of the server personalities (except for INET), support
- restarting via a HUP signal (see "kill -l"). When a HUP
- is received, the server will close children (if any), make
- sure that sockets are left open, and re-exec using
- the same commandline parameters that initially started the
- server. (Note: for this reason it is important that @ARGV
- is not modified until C<-E<gt>run> is called).
-
- The Net::Server will attempt to find out the commandline used for
- starting the program. The attempt is made before any configuration
- files or other arguments are processed. The outcome of this attempt
- is stored using the method C<-E<gt>commandline>. The stored
- commandline may also be retrieved using the same method name. The
- stored contents will undoubtedly contain Tainted items that will cause
- the server to die during a restart when using the -T flag (Taint
- mode). As it is impossible to arbitrarily decide what is taint safe
- and what is not, the individual program must clean up the tainted
- items before doing a restart.
-
- sub configure_hook{
- my $self = shift;
-
- ### see the contents
- my $ref = $self->commandline;
- use Data::Dumper;
- print Dumper $ref;
-
- ### arbitrary untainting - VERY dangerous
- my @untainted = map {/(.+)/;$1} @$ref;
-
- $self->commandline(\@untainted)
- }
-
- =head1 FILES
-
- The following files are installed as part of this
- distribution.
-
- Net/Server.pm
- Net/Server/Fork.pm
- Net/Server/INET.pm
- Net/Server/MultiType.pm
- Net/Server/PreForkSimple.pm
- Net/Server/PreFork.pm
- Net/Server/Single.pm
- Net/Server/Daemonize.pm
- Net/Server/SIG.pm
- Net/Server/Proto.pm
- Net/Server/Proto/*.pm
-
- =head1 INSTALL
-
- Download and extract tarball before running
- these commands in its base directory:
-
- perl Makefile.PL
- make
- make test
- make install
-
- =head1 AUTHOR
-
- Paul Seamons <paul at seamons.com>
-
- =head1 THANKS
-
- Thanks to Rob Brown (bbb at cpan.org) for help with
- miscellaneous concepts such as tracking down the
- serialized select via flock ala Apache and the reference
- to IO::Select making multiport servers possible. And for
- researching into allowing sockets to remain open upon
- exec (making HUP possible).
-
- Thanks to Jonathan J. Miner <miner at doit.wisc.edu> for
- patching a blatant problem in the reverse lookups.
-
- Thanks to Bennett Todd <bet at rahul.net> for
- pointing out a problem in Solaris 2.5.1 which does not
- allow multiple children to accept on the same port at
- the same time. Also for showing some sample code
- from Viktor Duchovni which now represents the semaphore
- option of the serialize argument in the PreFork server.
-
- Thanks to I<traveler> and I<merlyn> from http://perlmonks.org
- for pointing me in the right direction for determining
- the protocol used on a socket connection.
-
- Thanks to Jeremy Howard <j+daemonize at howard.fm> for
- numerous suggestions and for work on Net::Server::Daemonize.
-
- Thanks to Vadim <vadim at hardison.net> for patches to
- implement parent/child communication on PreFork.pm.
-
- Thanks to Carl Lewis for suggesting "-" in user names.
-
- Thanks to Slaven Rezic for suggesing Reuse => 1 in Proto::UDP.
-
- Thanks to Tim Watt for adding udp_broadcast to Proto::UDP.
-
- Thanks to Christopher A Bongaarts for pointing out problems with
- the Proto::SSL implementation that currently locks around the socket
- accept and the SSL negotiation. See L<Net::Server::Proto::SSL>.
-
- Thanks to Alessandro Zummo for pointing out various bugs including
- some in configuration, commandline args, and cidr_allow.
-
- Thanks to various other people for bug fixes over the years.
- These and future thank-you's are available in the Changes file
- as well as CVS comments.
-
- Thanks to Ben Cohen and tye (on Permonks) for finding and diagnosing
- more correct behavior for dealing with re-opening STDIN and STDOUT on
- the client handles.
-
- Thanks to Mark Martinec for trouble shooting other problems with STDIN
- and STDOUT (he proposed having a flag that is now the no_client_stdout
- flag).
-
- Thanks to David (DSCHWEI) on cpan for asking for the nofatal option
- with syslog.
-
- Thanks to Andreas Kippnick and Peter Beckman for suggesting leaving
- open child connections open during a HUP (this is now available via
- the leave_children_open_on_hup flag).
-
- Thanks to LUPE on cpan for helping patch HUP with taint on.
-
- Thanks to Michael Virnstein for fixing a bug in the check_for_dead
- section of PreFork server.
-
- Thanks to Rob Mueller for patching PreForkSimple to only open
- lock_file once during parent call. This patch should be portable on
- systems supporting flock. Rob also suggested not closing STDIN/STDOUT
- but instead reopening them to /dev/null to prevent spurious warnings.
- Also suggested short circuit in post_accept if in UDP. Also for
- cleaning up some of the child managment code of PreFork.
-
- Thanks to Mark Martinec for suggesting additional log messages for
- failure during accept.
-
- Thanks to Bill Nesbitt and Carlos Velasco for pointing out double
- decrement bug in PreFork.pm (rt #21271)
-
- Thanks to John W. Krahn for pointing out glaring precended with
- non-parened open and ||.
-
- Thanks to Ricardo Signes for pointing out setuid bug for perl 5.6.1
- (rt #21262).
-
- Thanks to Carlos Velasco for updating the Syslog options (rt #21265).
- And for additional fixes later.
-
- Thanks to Steven Lembark for pointing out that no_client_stdout wasn't
- working with the Multiplex server.
-
- Thanks to Peter Beckman for suggesting allowing Sys::SysLog keyworks
- be passed through the ->log method and for suggesting we allow more
- types of characters through in syslog_ident. Also to Peter Beckman
- for pointing out that a poorly setup localhost will cause tests to
- hang.
-
- Thanks to Curtis Wilbar for pointing out that the Fork server called
- post_accept_hook twice. Changed to only let the child process call
- this, but added the pre_fork_hook method.
-
- And just a general Thanks You to everybody who is using Net::Server or
- who has contributed fixes over the years.
-
- Thanks to Paul Miller for some ->autoflush, FileHandle fixes.
-
- Thanks to Patrik Wallstrom for suggesting handling syslog errors better.
-
- Thanks again to Rob Mueller for more logic cleanup for child accounting in PreFork server.
-
- Thanks to David Schweikert for suggesting handling setlogsock a little better on newer
- versions of Sys::Syslog (>= 0.15).
-
- Thanks to Mihail Nasedkin for suggesting adding a hook that is now
- called post_client_connection_hook.
-
- =head1 SEE ALSO
-
- Please see also
- L<Net::Server::Fork>,
- L<Net::Server::INET>,
- L<Net::Server::PreForkSimple>,
- L<Net::Server::PreFork>,
- L<Net::Server::MultiType>,
- L<Net::Server::Single>
-
- =head1 TODO
-
- Improve test suite to fully cover code (using Devel::Cover). Anybody
- that wanted to send me patches to the t/*.t tests that improved coverage
- would earn a big thank you :) (Sorry there isn't a whole lot more than that to give).
-
- =head1 AUTHOR
-
- Paul Seamons <paul at seamons.com>
- http://seamons.com/
-
- Rob Brown <bbb at cpan.org>
-
- =head1 LICENSE
-
- This package may be distributed under the terms of either the
-
- GNU General Public License
- or the
- Perl Artistic License
-
- All rights reserved.
-
- =cut
-