"""Generic socket server classes.

This module tries to capture the various aspects of defining a server:

- address family:
	- AF_INET: IP (Internet Protocol) sockets (default)
	- AF_UNIX: Unix domain sockets
	- others, e.g. AF_DECNET are conceivable (see <socket.h>
- socket type:
	- SOCK_STREAM (reliable stream, e.g. TCP)
	- SOCK_DGRAM (datagrams, e.g. UDP)
- client address verification before further looking at the request
	(This is actually a hook for any processing that needs to look
	 at the request before anything else, e.g. logging)
- how to handle multiple requests:
	- synchronous (one request is handled at a time)
	- forking (each request is handled by a new process)
	- threading (each request is handled by a new thread)

The classes in this module favor the server type that is simplest to
write: a synchronous TCP/IP server.  This is bad class design, but
save some typing.  (There's also the issue that a deep class hierarchy
slows down method lookups.)

There are four classes in an inheritance diagram that represent
synchronous servers of four types:

	+-----------+        +------------------+
	| TCPServer |------->| UnixStreamServer |
	+-----------+        +------------------+
	      |
	      v
	+-----------+        +--------------------+
	| UDPServer |------->| UnixDatagramServer |
	+-----------+        +--------------------+

Note that UnixDatagramServer derives from UDPServer, not from
UnixStreamServer -- the only difference between an IP and a Unix
stream server is the address family, which is simply repeated in both
unix server classes.

Forking and threading versions of each type of server can be created
using the ForkingServer and ThreadingServer mix-in classes.  For
instance, a threading UDP server class is created as follows:

	class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass

The Mix-in class must come first, since it overrides a method defined
in UDPServer!

To implement a service, you must derive a class from
BaseRequestHandler and redefine its handle() method.  You can then run
various versions of the service by combining one of the server classes
with your request handler class.

The request handler class must be different for datagram or stream
services.  This can be hidden by using the mix-in request handler
classes StreamRequestHandler or DatagramRequestHandler.

Of course, you still have to use your head!

For instance, it makes no sense to use a forking server if the service
contains state in memory that can be modified by requests (since the
modifications in the child process would never reach the initial state
kept in the parent process and passed to each child).  In this case,
you can use a threading server, but you will probably have to use
locks to avoid two requests that come in nearly simultaneous to apply
conflicting changes to the server state.

On the other hand, if you are building e.g. an HTTP server, where all
data is stored externally (e.g. in the file system), a synchronous
class will essentially render the service "deaf" while one request is
being handled -- which may be for a very long time if a client is slow
to reqd all the data it has requested.  Here a threading or forking
server is appropriate.

In some cases, it may be appropriate to process part of a request
synchronously, but to finish processing in a forked child depending on
the request data.  This can be implemented by using a synchronous
server and doing an explicit fork in the request handler class's
handle() method.

Another approach to handling multiple simultaneous requests in an
environment that supports neither threads nor fork (or where these are
too expensive or inappropriate for the service) is to maintain an
explicit table of partially finished requests and to use select() to
decide which request to work on next (or whether to handle a new
incoming request).  This is particularly important for stream services
where each client can potentially be connected for a long time (if
threads or subprocesses can't be used).

Future work:
- Standard classes for Sun RPC (which uses either UDP or TCP)
- Standard mix-in classes to implement various authentication
  and encryption schemes
- Standard framework for select-based multiplexing

XXX Open problems:
- What to do with out-of-band data?

"""


__version__ = "0.2"


import socket
import sys
import os


class TCPServer:

    """Base class for various socket-based server classes.

    Defaults to synchronous IP stream (i.e., TCP).

    Methods for the caller:

    - __init__(server_address, RequestHandlerClass)
    - serve_forever()
    - handle_request()	# if you don't use serve_forever()
    - fileno() -> int	# for select()

    Methods that may be overridden:

    - server_bind()
    - server_activate()
    - get_request() -> request, client_address
    - verify_request(request, client_address)
    - process_request(request, client_address)
    - handle_error()

    Methods for derived classes:

    - finish_request(request, client_address)

    Class variables that may be overridden by derived classes or
    instances:

    - address_family
    - socket_type
    - request_queue_size (only for stream sockets)

    Instance variables:

    - server_address
    - RequestHandlerClass
    - socket

    """

    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    request_queue_size = 5

    def __init__(self, server_address, RequestHandlerClass):
	"""Constructor.  May be extended, do not override."""
	self.server_address = server_address
	self.RequestHandlerClass = RequestHandlerClass
	self.socket = socket.socket(self.address_family,
				    self.socket_type)
	self.server_bind()
	self.server_activate()

    def server_bind(self):
	"""Called by constructor to bind the socket.

	May be overridden.

	"""
	self.socket.bind(self.server_address)

    def server_activate(self):
	"""Called by constructor to activate the server.

	May be overridden.

	"""
	self.socket.listen(self.request_queue_size)

    def fileno(self):
	"""Return socket file number.

	Interface required by select().

	"""
	return self.socket.fileno()

    def serve_forever(self):
	"""Handle one request at a time until doomsday."""
	while 1:
	    self.handle_request()

    # The distinction between handling, getting, processing and
    # finishing a request is fairly arbitrary.  Remember:
    #
    # - handle_request() is the top-level call.  It calls
    #   get_request(), verify_request() and process_request()
    # - get_request() is different for stream or datagram sockets
    # - process_request() is the place that may fork a new process
    #   or create a new thread to finish the request
    # - finish_request() instantiates the request handler class;
    #   this constructor will handle the request all by itself

    def handle_request(self):
	"""Handle one request, possibly blocking."""
	request, client_address = self.get_request()
	if self.verify_request(request, client_address):
	    try:
		self.process_request(request, client_address)
	    except:
		self.handle_error(request, client_address)

    def get_request(self):
	"""Get the request and client address from the socket.

	May be overridden.

	"""
	return self.socket.accept()

    def verify_request(self, request, client_address):
	"""Verify the request.  May be overridden.

	Return true if we should proceed with this request.

	"""
	return 1

    def process_request(self, request, client_address):
	"""Call finish_request.

	Overridden by ForkingMixIn and ThreadingMixIn.

	"""
	self.finish_request(request, client_address)

    def finish_request(self, request, client_address):
	"""Finish one request by instantiating RequestHandlerClass."""
	self.RequestHandlerClass(request, client_address, self)

    def handle_error(self, request, client_address):
	"""Handle an error gracefully.  May be overridden.

	The default is to print a traceback and continue.

	"""
	print '-'*40
	print 'Exception happened during processing of request from',
	print client_address
	import traceback
	traceback.print_exc()
	print '-'*40


class UDPServer(TCPServer):

    """UDP server class."""

    socket_type = socket.SOCK_DGRAM

    max_packet_size = 8192

    def get_request(self):
	return self.socket.recvfrom(self.max_packet_size)


if hasattr(socket, 'AF_UNIX'):

    class UnixStreamServer(TCPServer):

	address_family = socket.AF_UNIX


    class UnixDatagramServer(UDPServer):

	address_family = socket.AF_UNIX


class ForkingMixIn:

    """Mix-in class to handle each request in a new process."""

    active_children = None

    def collect_children(self):
	"""Internal routine to wait for died children."""
	while self.active_children:
	    pid, status = os.waitpid(0, os.WNOHANG)
	    if not pid: break
	    self.active_children.remove(pid)

    def process_request(self, request, client_address):
	"""Fork a new subprocess to process the request."""
	self.collect_children()
	pid = os.fork()
	if pid:
	    # Parent process
	    if self.active_children is None:
		self.active_children = []
	    self.active_children.append(pid)
	    return
	else:
	    # Child process.
	    # This must never return, hence os._exit()!
	    try:
		self.finish_request(request, client_address)
		os._exit(0)
	    except:
		try:
		    self.handle_error(request,
				      client_address)
		finally:
		    os._exit(1)


class ThreadingMixIn:

    """Mix-in class to handle each request in a new thread."""

    def process_request(self, request, client_address):
	"""Start a new thread to process the request."""
	import thread
	thread.start_new_thread(self.finish_request,
				(request, client_address))


class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass

class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass


class BaseRequestHandler:

    """Base class for request handler classes.

    This class is instantiated for each request to be handled.  The
    constructor sets the instance variables request, client_address
    and server, and then calls the handle() method.  To implement a
    specific service, all you need to do is to derive a class which
    defines a handle() method.

    The handle() method can find the request as self.request, the
    client address as self.client_request, and the server (in case it
    needs access to per-server information) as self.server.  Since a
    separate instance is created for each request, the handle() method
    can define arbitrary other instance variariables.

    """

    def __init__(self, request, client_address, server):
	self.request = request
	self.client_address = client_address
	self.server = server
	try:
	    self.setup()
	    self.handle()
	    self.finish()
	finally:
	    sys.exc_traceback = None	# Help garbage collection

    def setup(self):
	pass

    def __del__(self):
	pass

    def handle(self):
	pass

    def finish(self):
	pass


# The following two classes make it possible to use the same service
# class for stream or datagram servers.
# Each class sets up these instance variables:
# - rfile: a file object from which receives the request is read
# - wfile: a file object to which the reply is written
# When the handle() method returns, wfile is flushed properly


class StreamRequestHandler(BaseRequestHandler):

    """Define self.rfile and self.wfile for stream sockets."""

    def setup(self):
	self.connection = self.request
	self.rfile = self.connection.makefile('rb', 0)
	self.wfile = self.connection.makefile('wb', 0)

    def finish(self):
	self.wfile.flush()


class DatagramRequestHandler(BaseRequestHandler):

    """Define self.rfile and self.wfile for datagram sockets."""

    def setup(self):
	import StringIO
	self.packet, self.socket = self.request
	self.rfile = StringIO.StringIO(self.packet)
	self.wfile = StringIO.StringIO(self.packet)

    def finish(self):
	self.socket.send(self.wfile.getvalue())
