183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""Generic socket server classes.
283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThis module tries to capture the various aspects of defining a server:
483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehFor socket-based servers:
683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- address family:
883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - AF_INET{,6}: IP (Internet Protocol) sockets (default)
983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - AF_UNIX: Unix domain sockets
1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - others, e.g. AF_DECNET are conceivable (see <socket.h>
1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- socket type:
1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - SOCK_STREAM (reliable stream, e.g. TCP)
1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - SOCK_DGRAM (datagrams, e.g. UDP)
1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehFor request-based servers (including socket-based):
1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- client address verification before further looking at the request
1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        (This is actually a hook for any processing that needs to look
1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh         at the request before anything else, e.g. logging)
2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- how to handle multiple requests:
2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - synchronous (one request is handled at a time)
2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - forking (each request is handled by a new process)
2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        - threading (each request is handled by a new thread)
2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe classes in this module favor the server type that is simplest to
2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwrite: a synchronous TCP/IP server.  This is bad class design, but
2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehsave some typing.  (There's also the issue that a deep class hierarchy
2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehslows down method lookups.)
2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThere are five classes in an inheritance diagram, four of which represent
3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehsynchronous servers of four types:
3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        +------------+
3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        | BaseServer |
3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        +------------+
3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              |
3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              v
3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        +-----------+        +------------------+
3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        | TCPServer |------->| UnixStreamServer |
4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        +-----------+        +------------------+
4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              |
4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh              v
4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        +-----------+        +--------------------+
4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        | UDPServer |------->| UnixDatagramServer |
4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        +-----------+        +--------------------+
4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehNote that UnixDatagramServer derives from UDPServer, not from
4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehUnixStreamServer -- the only difference between an IP and a Unix
4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehstream server is the address family, which is simply repeated in both
5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehunix server classes.
5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehForking and threading versions of each type of server can be created
5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehusing the ForkingMixIn and ThreadingMixIn mix-in classes.  For
5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehinstance, a threading UDP server class is created as follows:
5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe Mix-in class must come first, since it overrides a method defined
5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehin UDPServer! Setting the various member variables also changes
6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthe behavior of the underlying server mechanism.
6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehTo implement a service, you must derive a class from
6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehBaseRequestHandler and redefine its handle() method.  You can then run
6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehvarious versions of the service by combining one of the server classes
6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwith your request handler class.
6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehThe request handler class must be different for datagram or stream
6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehservices.  This can be hidden by using the request handler
6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehsubclasses StreamRequestHandler or DatagramRequestHandler.
7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehOf course, you still have to use your head!
7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehFor instance, it makes no sense to use a forking server if the service
7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehcontains state in memory that can be modified by requests (since the
7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehmodifications in the child process would never reach the initial state
7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehkept in the parent process and passed to each child).  In this case,
7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehyou can use a threading server, but you will probably have to use
7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehlocks to avoid two requests that come in nearly simultaneous to apply
7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehconflicting changes to the server state.
8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehOn the other hand, if you are building e.g. an HTTP server, where all
8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdata is stored externally (e.g. in the file system), a synchronous
8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass will essentially render the service "deaf" while one request is
8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehbeing handled -- which may be for a very long time if a client is slow
8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehto read all the data it has requested.  Here a threading or forking
8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehserver is appropriate.
8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehIn some cases, it may be appropriate to process part of a request
8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehsynchronously, but to finish processing in a forked child depending on
9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthe request data.  This can be implemented by using a synchronous
9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehserver and doing an explicit fork in the request handler class
9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehhandle() method.
9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehAnother approach to handling multiple simultaneous requests in an
9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehenvironment that supports neither threads nor fork (or where these are
9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtoo expensive or inappropriate for the service) is to maintain an
9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexplicit table of partially finished requests and to use select() to
9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdecide which request to work on next (or whether to handle a new
9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehincoming request).  This is particularly important for stream services
10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehwhere each client can potentially be connected for a long time (if
10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehthreads or subprocesses cannot be used).
10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehFuture work:
10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- Standard classes for Sun RPC (which uses either UDP or TCP)
10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- Standard mix-in classes to implement various authentication
10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh  and encryption schemes
10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- Standard framework for select-based multiplexing
10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehXXX Open problems:
11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- What to do with out-of-band data?
11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew HsiehBaseServer:
11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh- split generic "request" functionality out into BaseServer class.
11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh  Copyright (C) 2000  Luke Kenneth Casson Leighton <lkcl@samba.org>
11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh  example: read entries from a SQL database (requires overriding
11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh  get_request() to return a table entry from the database).
11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh  entry is processed by a RequestHandlerClass.
11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh"""
12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Author of the BaseServer patch: Luke Kenneth Casson Leighton
12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# XXX Warning!
12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# There is a test suite for this module, but it cannot be run by the
12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# standard regression test.
12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# To run it manually, run Lib/test/test_socketserver.py.
12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__version__ = "0.4"
13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport socket
13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport select
13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport sys
13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport os
13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport errno
13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehtry:
13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import threading
13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehexcept ImportError:
14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    import dummy_threading as threading
14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh__all__ = ["TCPServer","UDPServer","ForkingUDPServer","ForkingTCPServer",
14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh           "ThreadingUDPServer","ThreadingTCPServer","BaseRequestHandler",
14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh           "StreamRequestHandler","DatagramRequestHandler",
14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh           "ThreadingMixIn", "ForkingMixIn"]
14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif hasattr(socket, "AF_UNIX"):
14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    __all__.extend(["UnixStreamServer","UnixDatagramServer",
14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    "ThreadingUnixStreamServer",
14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    "ThreadingUnixDatagramServer"])
15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef _eintr_retry(func, *args):
15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """restart a system call interrupted by EINTR"""
15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    while True:
15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return func(*args)
15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except (OSError, select.error) as e:
15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if e.args[0] != errno.EINTR:
15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise
15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass BaseServer:
16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Base class for server classes.
16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Methods for the caller:
16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - __init__(server_address, RequestHandlerClass)
16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - serve_forever(poll_interval=0.5)
16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - shutdown()
16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - handle_request()  # if you do not use serve_forever()
17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - fileno() -> int   # for select()
17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Methods that may be overridden:
17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - server_bind()
17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - server_activate()
17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - get_request() -> request, client_address
17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - handle_timeout()
17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - verify_request(request, client_address)
17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - server_close()
18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - process_request(request, client_address)
18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - shutdown_request(request)
18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - close_request(request)
18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - handle_error()
18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Methods for derived classes:
18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - finish_request(request, client_address)
18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Class variables that may be overridden by derived classes or
19083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    instances:
19183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - timeout
19383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - address_family
19483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - socket_type
19583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - allow_reuse_address
19683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Instance variables:
19883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
19983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - RequestHandlerClass
20083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - socket
20183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
20383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    timeout = None
20583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
20683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, server_address, RequestHandlerClass):
20783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Constructor.  May be extended, do not override."""
20883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.server_address = server_address
20983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.RequestHandlerClass = RequestHandlerClass
21083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.__is_shut_down = threading.Event()
21183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.__shutdown_request = False
21283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_activate(self):
21483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called by constructor to activate the server.
21583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be overridden.
21783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
21883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
21983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
22083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def serve_forever(self, poll_interval=0.5):
22283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Handle one request at a time until shutdown.
22383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
22483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Polls for shutdown every poll_interval seconds. Ignores
22583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.timeout. If you need to do periodic tasks, do them in
22683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        another thread.
22783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
22883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.__is_shut_down.clear()
22983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
23083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            while not self.__shutdown_request:
23183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # XXX: Consider using another file descriptor or
23283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # connecting to the socket to wake this up instead of
23383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # polling. Polling reduces our responsiveness to a
23483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # shutdown request and wastes cpu at all other times.
23583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                r, w, e = _eintr_retry(select.select, [self], [], [],
23683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                       poll_interval)
23783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                if self in r:
23883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self._handle_request_noblock()
23983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
24083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.__shutdown_request = False
24183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.__is_shut_down.set()
24283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def shutdown(self):
24483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Stops the serve_forever loop.
24583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
24683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Blocks until the loop has finished. This must be called while
24783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        serve_forever() is running in another thread, or it will
24883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        deadlock.
24983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
25083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.__shutdown_request = True
25183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.__is_shut_down.wait()
25283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
25383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # The distinction between handling, getting, processing and
25483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # finishing a request is fairly arbitrary.  Remember:
25583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #
25683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # - handle_request() is the top-level call.  It calls
25783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #   select, get_request(), verify_request() and process_request()
25883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # - get_request() is different for stream or datagram sockets
25983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # - process_request() is the place that may fork a new process
26083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #   or create a new thread to finish the request
26183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # - finish_request() instantiates the request handler class;
26283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    #   this constructor will handle the request all by itself
26383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle_request(self):
26583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Handle one request, possibly blocking.
26683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
26783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Respects self.timeout.
26883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
26983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # Support people who used socket.settimeout() to escape
27083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # handle_request before self.timeout was available.
27183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        timeout = self.socket.gettimeout()
27283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if timeout is None:
27383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            timeout = self.timeout
27483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        elif self.timeout is not None:
27583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            timeout = min(timeout, self.timeout)
27683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        fd_sets = _eintr_retry(select.select, [self], [], [], timeout)
27783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not fd_sets[0]:
27883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.handle_timeout()
27983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return
28083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self._handle_request_noblock()
28183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def _handle_request_noblock(self):
28383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Handle one request, without blocking.
28483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
28583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        I assume that select.select has returned that the socket is
28683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        readable before this function was called, so there should be
28783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        no risk of blocking in get_request().
28883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
28983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
29083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            request, client_address = self.get_request()
29183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except socket.error:
29283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return
29383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.verify_request(request, client_address):
29483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
29583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.process_request(request, client_address)
29683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except:
29783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.handle_error(request, client_address)
29883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.shutdown_request(request)
29983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle_timeout(self):
30183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called if no new request arrives within self.timeout.
30283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Overridden by ForkingMixIn.
30483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
30583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
30683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
30783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def verify_request(self, request, client_address):
30883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Verify the request.  May be overridden.
30983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Return True if we should proceed with this request.
31183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
31383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return True
31483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def process_request(self, request, client_address):
31683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Call finish_request.
31783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
31883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Overridden by ForkingMixIn and ThreadingMixIn.
31983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
32183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.finish_request(request, client_address)
32283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.shutdown_request(request)
32383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_close(self):
32583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called to clean-up the server.
32683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be overridden.
32883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
32983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
33083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
33183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def finish_request(self, request, client_address):
33383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Finish one request by instantiating RequestHandlerClass."""
33483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.RequestHandlerClass(request, client_address, self)
33583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
33683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def shutdown_request(self, request):
33783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called to shutdown and close an individual request."""
33883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.close_request(request)
33983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def close_request(self, request):
34183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called to clean up an individual request."""
34283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
34383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle_error(self, request, client_address):
34583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Handle an error gracefully.  May be overridden.
34683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        The default is to print a traceback and continue.
34883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
34983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
35083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print '-'*40
35183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print 'Exception happened during processing of request from',
35283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print client_address
35383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        import traceback
35483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        traceback.print_exc() # XXX But this goes to stderr!
35583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        print '-'*40
35683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
35883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass TCPServer(BaseServer):
35983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Base class for various socket-based server classes.
36183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Defaults to synchronous IP stream (i.e., TCP).
36383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Methods for the caller:
36583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
36683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
36783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - serve_forever(poll_interval=0.5)
36883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - shutdown()
36983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - handle_request()  # if you don't use serve_forever()
37083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - fileno() -> int   # for select()
37183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Methods that may be overridden:
37383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
37483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - server_bind()
37583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - server_activate()
37683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - get_request() -> request, client_address
37783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - handle_timeout()
37883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - verify_request(request, client_address)
37983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - process_request(request, client_address)
38083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - shutdown_request(request)
38183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - close_request(request)
38283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - handle_error()
38383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Methods for derived classes:
38583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - finish_request(request, client_address)
38783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
38883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Class variables that may be overridden by derived classes or
38983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    instances:
39083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - timeout
39283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - address_family
39383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - socket_type
39483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - request_queue_size (only for stream sockets)
39583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - allow_reuse_address
39683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    Instance variables:
39883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
39983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - server_address
40083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - RequestHandlerClass
40183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    - socket
40283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
40483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    address_family = socket.AF_INET
40683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    socket_type = socket.SOCK_STREAM
40883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
40983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    request_queue_size = 5
41083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    allow_reuse_address = False
41283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
41383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
41483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Constructor.  May be extended, do not override."""
41583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        BaseServer.__init__(self, server_address, RequestHandlerClass)
41683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.socket = socket.socket(self.address_family,
41783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                    self.socket_type)
41883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if bind_and_activate:
41983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.server_bind()
42083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.server_activate()
42183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_bind(self):
42383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called by constructor to bind the socket.
42483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be overridden.
42683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
42783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
42883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.allow_reuse_address:
42983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
43083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.socket.bind(self.server_address)
43183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.server_address = self.socket.getsockname()
43283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
43383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_activate(self):
43483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called by constructor to activate the server.
43583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
43683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be overridden.
43783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
43883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
43983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.socket.listen(self.request_queue_size)
44083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_close(self):
44283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called to clean-up the server.
44383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be overridden.
44583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
44783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.socket.close()
44883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
44983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def fileno(self):
45083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Return socket file number.
45183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        Interface required by select().
45383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
45583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.socket.fileno()
45683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
45783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_request(self):
45883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Get the request and client address from the socket.
45983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be overridden.
46183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
46383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return self.socket.accept()
46483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
46583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def shutdown_request(self, request):
46683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called to shutdown and close an individual request."""
46783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
46883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            #explicitly shutdown.  socket.close() merely releases
46983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            #the socket and waits for GC to perform the actual close.
47083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            request.shutdown(socket.SHUT_WR)
47183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except socket.error:
47283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            pass #some platforms may raise ENOTCONN here
47383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.close_request(request)
47483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
47583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def close_request(self, request):
47683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Called to clean up an individual request."""
47783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        request.close()
47883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
47983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass UDPServer(TCPServer):
48183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """UDP server class."""
48383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    allow_reuse_address = False
48583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    socket_type = socket.SOCK_DGRAM
48783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
48883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    max_packet_size = 8192
48983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def get_request(self):
49183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        data, client_addr = self.socket.recvfrom(self.max_packet_size)
49283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        return (data, self.socket), client_addr
49383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def server_activate(self):
49583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # No need to call listen() for UDP.
49683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
49783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
49883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def shutdown_request(self, request):
49983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # No need to shutdown anything.
50083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.close_request(request)
50183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
50283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def close_request(self, request):
50383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # No need to close anything.
50483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
50583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
50683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ForkingMixIn:
50783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
50883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Mix-in class to handle each request in a new process."""
50983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    timeout = 300
51183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    active_children = None
51283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    max_children = 40
51383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
51483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def collect_children(self):
51583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Internal routine to wait for children that have exited."""
51683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.active_children is None: return
51783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        while len(self.active_children) >= self.max_children:
51883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # XXX: This will wait for any child process, not just ones
51983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # spawned by this library. This could confuse other
52083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # libraries that expect to be able to wait for their own
52183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # children.
52283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
52383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pid, status = os.waitpid(0, 0)
52483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except os.error:
52583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pid = None
52683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if pid not in self.active_children: continue
52783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.active_children.remove(pid)
52883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
52983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # XXX: This loop runs more system calls than it ought
53083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # to. There should be a way to put the active_children into a
53183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # process group and then use os.waitpid(-pgid) to wait for any
53283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # of that set, but I couldn't find a way to allocate pgids
53383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        # that couldn't collide.
53483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        for child in self.active_children:
53583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
53683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pid, status = os.waitpid(child, os.WNOHANG)
53783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except os.error:
53883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pid = None
53983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if not pid: continue
54083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
54183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.active_children.remove(pid)
54283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except ValueError, e:
54383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                raise ValueError('%s. x=%d and list=%r' % (e.message, pid,
54483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                                           self.active_children))
54583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle_timeout(self):
54783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Wait for zombies after self.timeout seconds of inactivity.
54883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
54983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        May be extended, do not override.
55083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
55183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.collect_children()
55283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
55383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def process_request(self, request, client_address):
55483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Fork a new subprocess to process the request."""
55583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.collect_children()
55683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pid = os.fork()
55783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if pid:
55883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Parent process
55983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            if self.active_children is None:
56083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.active_children = []
56183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.active_children.append(pid)
56283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.close_request(request) #close handle in parent process
56383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            return
56483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        else:
56583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # Child process.
56683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            # This must never return, hence os._exit()!
56783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
56883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.finish_request(request, client_address)
56983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.shutdown_request(request)
57083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                os._exit(0)
57183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except:
57283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                try:
57383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self.handle_error(request, client_address)
57483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    self.shutdown_request(request)
57583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                finally:
57683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                    os._exit(1)
57783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
57983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ThreadingMixIn:
58083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Mix-in class to handle each request in a new thread."""
58183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Decides how threads will act upon termination of the
58383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # main process
58483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    daemon_threads = False
58583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def process_request_thread(self, request, client_address):
58783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Same as in BaseServer but as a thread.
58883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
58983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        In addition, exception handling is done here.
59083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
59183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """
59283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
59383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.finish_request(request, client_address)
59483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.shutdown_request(request)
59583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except:
59683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.handle_error(request, client_address)
59783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.shutdown_request(request)
59883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
59983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def process_request(self, request, client_address):
60083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        """Start a new thread to process the request."""
60183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        t = threading.Thread(target = self.process_request_thread,
60283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                             args = (request, client_address))
60383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        t.daemon = self.daemon_threads
60483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        t.start()
60583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
60683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
60783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ForkingUDPServer(ForkingMixIn, UDPServer): pass
60883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ForkingTCPServer(ForkingMixIn, TCPServer): pass
60983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
61183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
61283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehif hasattr(socket, 'AF_UNIX'):
61483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    class UnixStreamServer(TCPServer):
61683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        address_family = socket.AF_UNIX
61783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
61883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    class UnixDatagramServer(UDPServer):
61983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        address_family = socket.AF_UNIX
62083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass
62283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass
62483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass BaseRequestHandler:
62683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Base class for request handler classes.
62883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
62983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    This class is instantiated for each request to be handled.  The
63083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    constructor sets the instance variables request, client_address
63183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    and server, and then calls the handle() method.  To implement a
63283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    specific service, all you need to do is to derive a class which
63383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    defines a handle() method.
63483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
63583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    The handle() method can find the request as self.request, the
63683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    client address as self.client_address, and the server (in case it
63783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    needs access to per-server information) as self.server.  Since a
63883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    separate instance is created for each request, the handle() method
63983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    can define arbitrary other instance variariables.
64083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
64183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """
64283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
64383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def __init__(self, request, client_address, server):
64483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.request = request
64583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.client_address = client_address
64683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.server = server
64783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.setup()
64883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
64983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.handle()
65083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        finally:
65183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.finish()
65283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
65383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def setup(self):
65483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
65583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
65683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def handle(self):
65783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
65883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
65983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def finish(self):
66083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        pass
66183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
66283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
66383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# The following two classes make it possible to use the same service
66483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# class for stream or datagram servers.
66583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# Each class sets up these instance variables:
66683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# - rfile: a file object from which receives the request is read
66783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# - wfile: a file object to which the reply is written
66883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh# When the handle() method returns, wfile is flushed properly
66983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
67083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
67183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass StreamRequestHandler(BaseRequestHandler):
67283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
67383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Define self.rfile and self.wfile for stream sockets."""
67483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
67583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Default buffer sizes for rfile, wfile.
67683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # We default rfile to buffered because otherwise it could be
67783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # really slow for large data (a getc() call per byte); we make
67883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # wfile unbuffered because (a) often after a write() we want to
67983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # read and we need to flush the line; (b) big writes to unbuffered
68083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # files are typically optimized by stdio even when big reads
68183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # aren't.
68283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    rbufsize = -1
68383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    wbufsize = 0
68483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
68583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # A timeout to apply to the request socket, if not None.
68683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    timeout = None
68783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
68883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Disable nagle algorithm for this socket, if True.
68983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # Use only when wbufsize != 0, to avoid small packets.
69083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    disable_nagle_algorithm = False
69183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
69283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def setup(self):
69383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.connection = self.request
69483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.timeout is not None:
69583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.connection.settimeout(self.timeout)
69683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if self.disable_nagle_algorithm:
69783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            self.connection.setsockopt(socket.IPPROTO_TCP,
69883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                                       socket.TCP_NODELAY, True)
69983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.rfile = self.connection.makefile('rb', self.rbufsize)
70083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.wfile = self.connection.makefile('wb', self.wbufsize)
70183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
70283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def finish(self):
70383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        if not self.wfile.closed:
70483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            try:
70583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                self.wfile.flush()
70683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            except socket.error:
70783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # An final socket error may have occurred here, such as
70883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                # the local error ECONNABORTED.
70983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh                pass
71083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.wfile.close()
71183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.rfile.close()
71283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
71383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
71483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass DatagramRequestHandler(BaseRequestHandler):
71583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
71683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # XXX Regrettably, I cannot get this working on Linux;
71783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    # s.recvfrom() doesn't return a meaningful client address.
71883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
71983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    """Define self.rfile and self.wfile for datagram sockets."""
72083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
72183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def setup(self):
72283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        try:
72383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            from cStringIO import StringIO
72483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        except ImportError:
72583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh            from StringIO import StringIO
72683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.packet, self.socket = self.request
72783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.rfile = StringIO(self.packet)
72883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.wfile = StringIO()
72983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh
73083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh    def finish(self):
73183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh        self.socket.sendto(self.wfile.getvalue(), self.client_address)
732