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