1*cda5da8dSAndroid Build Coastguard Worker"""Generic socket server classes. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerThis module tries to capture the various aspects of defining a server: 4*cda5da8dSAndroid Build Coastguard Worker 5*cda5da8dSAndroid Build Coastguard WorkerFor socket-based servers: 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Worker- address family: 8*cda5da8dSAndroid Build Coastguard Worker - AF_INET{,6}: IP (Internet Protocol) sockets (default) 9*cda5da8dSAndroid Build Coastguard Worker - AF_UNIX: Unix domain sockets 10*cda5da8dSAndroid Build Coastguard Worker - others, e.g. AF_DECNET are conceivable (see <socket.h> 11*cda5da8dSAndroid Build Coastguard Worker- socket type: 12*cda5da8dSAndroid Build Coastguard Worker - SOCK_STREAM (reliable stream, e.g. TCP) 13*cda5da8dSAndroid Build Coastguard Worker - SOCK_DGRAM (datagrams, e.g. UDP) 14*cda5da8dSAndroid Build Coastguard Worker 15*cda5da8dSAndroid Build Coastguard WorkerFor request-based servers (including socket-based): 16*cda5da8dSAndroid Build Coastguard Worker 17*cda5da8dSAndroid Build Coastguard Worker- client address verification before further looking at the request 18*cda5da8dSAndroid Build Coastguard Worker (This is actually a hook for any processing that needs to look 19*cda5da8dSAndroid Build Coastguard Worker at the request before anything else, e.g. logging) 20*cda5da8dSAndroid Build Coastguard Worker- how to handle multiple requests: 21*cda5da8dSAndroid Build Coastguard Worker - synchronous (one request is handled at a time) 22*cda5da8dSAndroid Build Coastguard Worker - forking (each request is handled by a new process) 23*cda5da8dSAndroid Build Coastguard Worker - threading (each request is handled by a new thread) 24*cda5da8dSAndroid Build Coastguard Worker 25*cda5da8dSAndroid Build Coastguard WorkerThe classes in this module favor the server type that is simplest to 26*cda5da8dSAndroid Build Coastguard Workerwrite: a synchronous TCP/IP server. This is bad class design, but 27*cda5da8dSAndroid Build Coastguard Workersaves some typing. (There's also the issue that a deep class hierarchy 28*cda5da8dSAndroid Build Coastguard Workerslows down method lookups.) 29*cda5da8dSAndroid Build Coastguard Worker 30*cda5da8dSAndroid Build Coastguard WorkerThere are five classes in an inheritance diagram, four of which represent 31*cda5da8dSAndroid Build Coastguard Workersynchronous servers of four types: 32*cda5da8dSAndroid Build Coastguard Worker 33*cda5da8dSAndroid Build Coastguard Worker +------------+ 34*cda5da8dSAndroid Build Coastguard Worker | BaseServer | 35*cda5da8dSAndroid Build Coastguard Worker +------------+ 36*cda5da8dSAndroid Build Coastguard Worker | 37*cda5da8dSAndroid Build Coastguard Worker v 38*cda5da8dSAndroid Build Coastguard Worker +-----------+ +------------------+ 39*cda5da8dSAndroid Build Coastguard Worker | TCPServer |------->| UnixStreamServer | 40*cda5da8dSAndroid Build Coastguard Worker +-----------+ +------------------+ 41*cda5da8dSAndroid Build Coastguard Worker | 42*cda5da8dSAndroid Build Coastguard Worker v 43*cda5da8dSAndroid Build Coastguard Worker +-----------+ +--------------------+ 44*cda5da8dSAndroid Build Coastguard Worker | UDPServer |------->| UnixDatagramServer | 45*cda5da8dSAndroid Build Coastguard Worker +-----------+ +--------------------+ 46*cda5da8dSAndroid Build Coastguard Worker 47*cda5da8dSAndroid Build Coastguard WorkerNote that UnixDatagramServer derives from UDPServer, not from 48*cda5da8dSAndroid Build Coastguard WorkerUnixStreamServer -- the only difference between an IP and a Unix 49*cda5da8dSAndroid Build Coastguard Workerstream server is the address family, which is simply repeated in both 50*cda5da8dSAndroid Build Coastguard Workerunix server classes. 51*cda5da8dSAndroid Build Coastguard Worker 52*cda5da8dSAndroid Build Coastguard WorkerForking and threading versions of each type of server can be created 53*cda5da8dSAndroid Build Coastguard Workerusing the ForkingMixIn and ThreadingMixIn mix-in classes. For 54*cda5da8dSAndroid Build Coastguard Workerinstance, a threading UDP server class is created as follows: 55*cda5da8dSAndroid Build Coastguard Worker 56*cda5da8dSAndroid Build Coastguard Worker class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass 57*cda5da8dSAndroid Build Coastguard Worker 58*cda5da8dSAndroid Build Coastguard WorkerThe Mix-in class must come first, since it overrides a method defined 59*cda5da8dSAndroid Build Coastguard Workerin UDPServer! Setting the various member variables also changes 60*cda5da8dSAndroid Build Coastguard Workerthe behavior of the underlying server mechanism. 61*cda5da8dSAndroid Build Coastguard Worker 62*cda5da8dSAndroid Build Coastguard WorkerTo implement a service, you must derive a class from 63*cda5da8dSAndroid Build Coastguard WorkerBaseRequestHandler and redefine its handle() method. You can then run 64*cda5da8dSAndroid Build Coastguard Workervarious versions of the service by combining one of the server classes 65*cda5da8dSAndroid Build Coastguard Workerwith your request handler class. 66*cda5da8dSAndroid Build Coastguard Worker 67*cda5da8dSAndroid Build Coastguard WorkerThe request handler class must be different for datagram or stream 68*cda5da8dSAndroid Build Coastguard Workerservices. This can be hidden by using the request handler 69*cda5da8dSAndroid Build Coastguard Workersubclasses StreamRequestHandler or DatagramRequestHandler. 70*cda5da8dSAndroid Build Coastguard Worker 71*cda5da8dSAndroid Build Coastguard WorkerOf course, you still have to use your head! 72*cda5da8dSAndroid Build Coastguard Worker 73*cda5da8dSAndroid Build Coastguard WorkerFor instance, it makes no sense to use a forking server if the service 74*cda5da8dSAndroid Build Coastguard Workercontains state in memory that can be modified by requests (since the 75*cda5da8dSAndroid Build Coastguard Workermodifications in the child process would never reach the initial state 76*cda5da8dSAndroid Build Coastguard Workerkept in the parent process and passed to each child). In this case, 77*cda5da8dSAndroid Build Coastguard Workeryou can use a threading server, but you will probably have to use 78*cda5da8dSAndroid Build Coastguard Workerlocks to avoid two requests that come in nearly simultaneous to apply 79*cda5da8dSAndroid Build Coastguard Workerconflicting changes to the server state. 80*cda5da8dSAndroid Build Coastguard Worker 81*cda5da8dSAndroid Build Coastguard WorkerOn the other hand, if you are building e.g. an HTTP server, where all 82*cda5da8dSAndroid Build Coastguard Workerdata is stored externally (e.g. in the file system), a synchronous 83*cda5da8dSAndroid Build Coastguard Workerclass will essentially render the service "deaf" while one request is 84*cda5da8dSAndroid Build Coastguard Workerbeing handled -- which may be for a very long time if a client is slow 85*cda5da8dSAndroid Build Coastguard Workerto read all the data it has requested. Here a threading or forking 86*cda5da8dSAndroid Build Coastguard Workerserver is appropriate. 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard WorkerIn some cases, it may be appropriate to process part of a request 89*cda5da8dSAndroid Build Coastguard Workersynchronously, but to finish processing in a forked child depending on 90*cda5da8dSAndroid Build Coastguard Workerthe request data. This can be implemented by using a synchronous 91*cda5da8dSAndroid Build Coastguard Workerserver and doing an explicit fork in the request handler class 92*cda5da8dSAndroid Build Coastguard Workerhandle() method. 93*cda5da8dSAndroid Build Coastguard Worker 94*cda5da8dSAndroid Build Coastguard WorkerAnother approach to handling multiple simultaneous requests in an 95*cda5da8dSAndroid Build Coastguard Workerenvironment that supports neither threads nor fork (or where these are 96*cda5da8dSAndroid Build Coastguard Workertoo expensive or inappropriate for the service) is to maintain an 97*cda5da8dSAndroid Build Coastguard Workerexplicit table of partially finished requests and to use a selector to 98*cda5da8dSAndroid Build Coastguard Workerdecide which request to work on next (or whether to handle a new 99*cda5da8dSAndroid Build Coastguard Workerincoming request). This is particularly important for stream services 100*cda5da8dSAndroid Build Coastguard Workerwhere each client can potentially be connected for a long time (if 101*cda5da8dSAndroid Build Coastguard Workerthreads or subprocesses cannot be used). 102*cda5da8dSAndroid Build Coastguard Worker 103*cda5da8dSAndroid Build Coastguard WorkerFuture work: 104*cda5da8dSAndroid Build Coastguard Worker- Standard classes for Sun RPC (which uses either UDP or TCP) 105*cda5da8dSAndroid Build Coastguard Worker- Standard mix-in classes to implement various authentication 106*cda5da8dSAndroid Build Coastguard Worker and encryption schemes 107*cda5da8dSAndroid Build Coastguard Worker 108*cda5da8dSAndroid Build Coastguard WorkerXXX Open problems: 109*cda5da8dSAndroid Build Coastguard Worker- What to do with out-of-band data? 110*cda5da8dSAndroid Build Coastguard Worker 111*cda5da8dSAndroid Build Coastguard WorkerBaseServer: 112*cda5da8dSAndroid Build Coastguard Worker- split generic "request" functionality out into BaseServer class. 113*cda5da8dSAndroid Build Coastguard Worker Copyright (C) 2000 Luke Kenneth Casson Leighton <[email protected]> 114*cda5da8dSAndroid Build Coastguard Worker 115*cda5da8dSAndroid Build Coastguard Worker example: read entries from a SQL database (requires overriding 116*cda5da8dSAndroid Build Coastguard Worker get_request() to return a table entry from the database). 117*cda5da8dSAndroid Build Coastguard Worker entry is processed by a RequestHandlerClass. 118*cda5da8dSAndroid Build Coastguard Worker 119*cda5da8dSAndroid Build Coastguard Worker""" 120*cda5da8dSAndroid Build Coastguard Worker 121*cda5da8dSAndroid Build Coastguard Worker# Author of the BaseServer patch: Luke Kenneth Casson Leighton 122*cda5da8dSAndroid Build Coastguard Worker 123*cda5da8dSAndroid Build Coastguard Worker__version__ = "0.4" 124*cda5da8dSAndroid Build Coastguard Worker 125*cda5da8dSAndroid Build Coastguard Worker 126*cda5da8dSAndroid Build Coastguard Workerimport socket 127*cda5da8dSAndroid Build Coastguard Workerimport selectors 128*cda5da8dSAndroid Build Coastguard Workerimport os 129*cda5da8dSAndroid Build Coastguard Workerimport sys 130*cda5da8dSAndroid Build Coastguard Workerimport threading 131*cda5da8dSAndroid Build Coastguard Workerfrom io import BufferedIOBase 132*cda5da8dSAndroid Build Coastguard Workerfrom time import monotonic as time 133*cda5da8dSAndroid Build Coastguard Worker 134*cda5da8dSAndroid Build Coastguard Worker__all__ = ["BaseServer", "TCPServer", "UDPServer", 135*cda5da8dSAndroid Build Coastguard Worker "ThreadingUDPServer", "ThreadingTCPServer", 136*cda5da8dSAndroid Build Coastguard Worker "BaseRequestHandler", "StreamRequestHandler", 137*cda5da8dSAndroid Build Coastguard Worker "DatagramRequestHandler", "ThreadingMixIn"] 138*cda5da8dSAndroid Build Coastguard Workerif hasattr(os, "fork"): 139*cda5da8dSAndroid Build Coastguard Worker __all__.extend(["ForkingUDPServer","ForkingTCPServer", "ForkingMixIn"]) 140*cda5da8dSAndroid Build Coastguard Workerif hasattr(socket, "AF_UNIX"): 141*cda5da8dSAndroid Build Coastguard Worker __all__.extend(["UnixStreamServer","UnixDatagramServer", 142*cda5da8dSAndroid Build Coastguard Worker "ThreadingUnixStreamServer", 143*cda5da8dSAndroid Build Coastguard Worker "ThreadingUnixDatagramServer"]) 144*cda5da8dSAndroid Build Coastguard Worker 145*cda5da8dSAndroid Build Coastguard Worker# poll/select have the advantage of not requiring any extra file descriptor, 146*cda5da8dSAndroid Build Coastguard Worker# contrarily to epoll/kqueue (also, they require a single syscall). 147*cda5da8dSAndroid Build Coastguard Workerif hasattr(selectors, 'PollSelector'): 148*cda5da8dSAndroid Build Coastguard Worker _ServerSelector = selectors.PollSelector 149*cda5da8dSAndroid Build Coastguard Workerelse: 150*cda5da8dSAndroid Build Coastguard Worker _ServerSelector = selectors.SelectSelector 151*cda5da8dSAndroid Build Coastguard Worker 152*cda5da8dSAndroid Build Coastguard Worker 153*cda5da8dSAndroid Build Coastguard Workerclass BaseServer: 154*cda5da8dSAndroid Build Coastguard Worker 155*cda5da8dSAndroid Build Coastguard Worker """Base class for server classes. 156*cda5da8dSAndroid Build Coastguard Worker 157*cda5da8dSAndroid Build Coastguard Worker Methods for the caller: 158*cda5da8dSAndroid Build Coastguard Worker 159*cda5da8dSAndroid Build Coastguard Worker - __init__(server_address, RequestHandlerClass) 160*cda5da8dSAndroid Build Coastguard Worker - serve_forever(poll_interval=0.5) 161*cda5da8dSAndroid Build Coastguard Worker - shutdown() 162*cda5da8dSAndroid Build Coastguard Worker - handle_request() # if you do not use serve_forever() 163*cda5da8dSAndroid Build Coastguard Worker - fileno() -> int # for selector 164*cda5da8dSAndroid Build Coastguard Worker 165*cda5da8dSAndroid Build Coastguard Worker Methods that may be overridden: 166*cda5da8dSAndroid Build Coastguard Worker 167*cda5da8dSAndroid Build Coastguard Worker - server_bind() 168*cda5da8dSAndroid Build Coastguard Worker - server_activate() 169*cda5da8dSAndroid Build Coastguard Worker - get_request() -> request, client_address 170*cda5da8dSAndroid Build Coastguard Worker - handle_timeout() 171*cda5da8dSAndroid Build Coastguard Worker - verify_request(request, client_address) 172*cda5da8dSAndroid Build Coastguard Worker - server_close() 173*cda5da8dSAndroid Build Coastguard Worker - process_request(request, client_address) 174*cda5da8dSAndroid Build Coastguard Worker - shutdown_request(request) 175*cda5da8dSAndroid Build Coastguard Worker - close_request(request) 176*cda5da8dSAndroid Build Coastguard Worker - service_actions() 177*cda5da8dSAndroid Build Coastguard Worker - handle_error() 178*cda5da8dSAndroid Build Coastguard Worker 179*cda5da8dSAndroid Build Coastguard Worker Methods for derived classes: 180*cda5da8dSAndroid Build Coastguard Worker 181*cda5da8dSAndroid Build Coastguard Worker - finish_request(request, client_address) 182*cda5da8dSAndroid Build Coastguard Worker 183*cda5da8dSAndroid Build Coastguard Worker Class variables that may be overridden by derived classes or 184*cda5da8dSAndroid Build Coastguard Worker instances: 185*cda5da8dSAndroid Build Coastguard Worker 186*cda5da8dSAndroid Build Coastguard Worker - timeout 187*cda5da8dSAndroid Build Coastguard Worker - address_family 188*cda5da8dSAndroid Build Coastguard Worker - socket_type 189*cda5da8dSAndroid Build Coastguard Worker - allow_reuse_address 190*cda5da8dSAndroid Build Coastguard Worker - allow_reuse_port 191*cda5da8dSAndroid Build Coastguard Worker 192*cda5da8dSAndroid Build Coastguard Worker Instance variables: 193*cda5da8dSAndroid Build Coastguard Worker 194*cda5da8dSAndroid Build Coastguard Worker - RequestHandlerClass 195*cda5da8dSAndroid Build Coastguard Worker - socket 196*cda5da8dSAndroid Build Coastguard Worker 197*cda5da8dSAndroid Build Coastguard Worker """ 198*cda5da8dSAndroid Build Coastguard Worker 199*cda5da8dSAndroid Build Coastguard Worker timeout = None 200*cda5da8dSAndroid Build Coastguard Worker 201*cda5da8dSAndroid Build Coastguard Worker def __init__(self, server_address, RequestHandlerClass): 202*cda5da8dSAndroid Build Coastguard Worker """Constructor. May be extended, do not override.""" 203*cda5da8dSAndroid Build Coastguard Worker self.server_address = server_address 204*cda5da8dSAndroid Build Coastguard Worker self.RequestHandlerClass = RequestHandlerClass 205*cda5da8dSAndroid Build Coastguard Worker self.__is_shut_down = threading.Event() 206*cda5da8dSAndroid Build Coastguard Worker self.__shutdown_request = False 207*cda5da8dSAndroid Build Coastguard Worker 208*cda5da8dSAndroid Build Coastguard Worker def server_activate(self): 209*cda5da8dSAndroid Build Coastguard Worker """Called by constructor to activate the server. 210*cda5da8dSAndroid Build Coastguard Worker 211*cda5da8dSAndroid Build Coastguard Worker May be overridden. 212*cda5da8dSAndroid Build Coastguard Worker 213*cda5da8dSAndroid Build Coastguard Worker """ 214*cda5da8dSAndroid Build Coastguard Worker pass 215*cda5da8dSAndroid Build Coastguard Worker 216*cda5da8dSAndroid Build Coastguard Worker def serve_forever(self, poll_interval=0.5): 217*cda5da8dSAndroid Build Coastguard Worker """Handle one request at a time until shutdown. 218*cda5da8dSAndroid Build Coastguard Worker 219*cda5da8dSAndroid Build Coastguard Worker Polls for shutdown every poll_interval seconds. Ignores 220*cda5da8dSAndroid Build Coastguard Worker self.timeout. If you need to do periodic tasks, do them in 221*cda5da8dSAndroid Build Coastguard Worker another thread. 222*cda5da8dSAndroid Build Coastguard Worker """ 223*cda5da8dSAndroid Build Coastguard Worker self.__is_shut_down.clear() 224*cda5da8dSAndroid Build Coastguard Worker try: 225*cda5da8dSAndroid Build Coastguard Worker # XXX: Consider using another file descriptor or connecting to the 226*cda5da8dSAndroid Build Coastguard Worker # socket to wake this up instead of polling. Polling reduces our 227*cda5da8dSAndroid Build Coastguard Worker # responsiveness to a shutdown request and wastes cpu at all other 228*cda5da8dSAndroid Build Coastguard Worker # times. 229*cda5da8dSAndroid Build Coastguard Worker with _ServerSelector() as selector: 230*cda5da8dSAndroid Build Coastguard Worker selector.register(self, selectors.EVENT_READ) 231*cda5da8dSAndroid Build Coastguard Worker 232*cda5da8dSAndroid Build Coastguard Worker while not self.__shutdown_request: 233*cda5da8dSAndroid Build Coastguard Worker ready = selector.select(poll_interval) 234*cda5da8dSAndroid Build Coastguard Worker # bpo-35017: shutdown() called during select(), exit immediately. 235*cda5da8dSAndroid Build Coastguard Worker if self.__shutdown_request: 236*cda5da8dSAndroid Build Coastguard Worker break 237*cda5da8dSAndroid Build Coastguard Worker if ready: 238*cda5da8dSAndroid Build Coastguard Worker self._handle_request_noblock() 239*cda5da8dSAndroid Build Coastguard Worker 240*cda5da8dSAndroid Build Coastguard Worker self.service_actions() 241*cda5da8dSAndroid Build Coastguard Worker finally: 242*cda5da8dSAndroid Build Coastguard Worker self.__shutdown_request = False 243*cda5da8dSAndroid Build Coastguard Worker self.__is_shut_down.set() 244*cda5da8dSAndroid Build Coastguard Worker 245*cda5da8dSAndroid Build Coastguard Worker def shutdown(self): 246*cda5da8dSAndroid Build Coastguard Worker """Stops the serve_forever loop. 247*cda5da8dSAndroid Build Coastguard Worker 248*cda5da8dSAndroid Build Coastguard Worker Blocks until the loop has finished. This must be called while 249*cda5da8dSAndroid Build Coastguard Worker serve_forever() is running in another thread, or it will 250*cda5da8dSAndroid Build Coastguard Worker deadlock. 251*cda5da8dSAndroid Build Coastguard Worker """ 252*cda5da8dSAndroid Build Coastguard Worker self.__shutdown_request = True 253*cda5da8dSAndroid Build Coastguard Worker self.__is_shut_down.wait() 254*cda5da8dSAndroid Build Coastguard Worker 255*cda5da8dSAndroid Build Coastguard Worker def service_actions(self): 256*cda5da8dSAndroid Build Coastguard Worker """Called by the serve_forever() loop. 257*cda5da8dSAndroid Build Coastguard Worker 258*cda5da8dSAndroid Build Coastguard Worker May be overridden by a subclass / Mixin to implement any code that 259*cda5da8dSAndroid Build Coastguard Worker needs to be run during the loop. 260*cda5da8dSAndroid Build Coastguard Worker """ 261*cda5da8dSAndroid Build Coastguard Worker pass 262*cda5da8dSAndroid Build Coastguard Worker 263*cda5da8dSAndroid Build Coastguard Worker # The distinction between handling, getting, processing and finishing a 264*cda5da8dSAndroid Build Coastguard Worker # request is fairly arbitrary. Remember: 265*cda5da8dSAndroid Build Coastguard Worker # 266*cda5da8dSAndroid Build Coastguard Worker # - handle_request() is the top-level call. It calls selector.select(), 267*cda5da8dSAndroid Build Coastguard Worker # get_request(), verify_request() and process_request() 268*cda5da8dSAndroid Build Coastguard Worker # - get_request() is different for stream or datagram sockets 269*cda5da8dSAndroid Build Coastguard Worker # - process_request() is the place that may fork a new process or create a 270*cda5da8dSAndroid Build Coastguard Worker # new thread to finish the request 271*cda5da8dSAndroid Build Coastguard Worker # - finish_request() instantiates the request handler class; this 272*cda5da8dSAndroid Build Coastguard Worker # constructor will handle the request all by itself 273*cda5da8dSAndroid Build Coastguard Worker 274*cda5da8dSAndroid Build Coastguard Worker def handle_request(self): 275*cda5da8dSAndroid Build Coastguard Worker """Handle one request, possibly blocking. 276*cda5da8dSAndroid Build Coastguard Worker 277*cda5da8dSAndroid Build Coastguard Worker Respects self.timeout. 278*cda5da8dSAndroid Build Coastguard Worker """ 279*cda5da8dSAndroid Build Coastguard Worker # Support people who used socket.settimeout() to escape 280*cda5da8dSAndroid Build Coastguard Worker # handle_request before self.timeout was available. 281*cda5da8dSAndroid Build Coastguard Worker timeout = self.socket.gettimeout() 282*cda5da8dSAndroid Build Coastguard Worker if timeout is None: 283*cda5da8dSAndroid Build Coastguard Worker timeout = self.timeout 284*cda5da8dSAndroid Build Coastguard Worker elif self.timeout is not None: 285*cda5da8dSAndroid Build Coastguard Worker timeout = min(timeout, self.timeout) 286*cda5da8dSAndroid Build Coastguard Worker if timeout is not None: 287*cda5da8dSAndroid Build Coastguard Worker deadline = time() + timeout 288*cda5da8dSAndroid Build Coastguard Worker 289*cda5da8dSAndroid Build Coastguard Worker # Wait until a request arrives or the timeout expires - the loop is 290*cda5da8dSAndroid Build Coastguard Worker # necessary to accommodate early wakeups due to EINTR. 291*cda5da8dSAndroid Build Coastguard Worker with _ServerSelector() as selector: 292*cda5da8dSAndroid Build Coastguard Worker selector.register(self, selectors.EVENT_READ) 293*cda5da8dSAndroid Build Coastguard Worker 294*cda5da8dSAndroid Build Coastguard Worker while True: 295*cda5da8dSAndroid Build Coastguard Worker ready = selector.select(timeout) 296*cda5da8dSAndroid Build Coastguard Worker if ready: 297*cda5da8dSAndroid Build Coastguard Worker return self._handle_request_noblock() 298*cda5da8dSAndroid Build Coastguard Worker else: 299*cda5da8dSAndroid Build Coastguard Worker if timeout is not None: 300*cda5da8dSAndroid Build Coastguard Worker timeout = deadline - time() 301*cda5da8dSAndroid Build Coastguard Worker if timeout < 0: 302*cda5da8dSAndroid Build Coastguard Worker return self.handle_timeout() 303*cda5da8dSAndroid Build Coastguard Worker 304*cda5da8dSAndroid Build Coastguard Worker def _handle_request_noblock(self): 305*cda5da8dSAndroid Build Coastguard Worker """Handle one request, without blocking. 306*cda5da8dSAndroid Build Coastguard Worker 307*cda5da8dSAndroid Build Coastguard Worker I assume that selector.select() has returned that the socket is 308*cda5da8dSAndroid Build Coastguard Worker readable before this function was called, so there should be no risk of 309*cda5da8dSAndroid Build Coastguard Worker blocking in get_request(). 310*cda5da8dSAndroid Build Coastguard Worker """ 311*cda5da8dSAndroid Build Coastguard Worker try: 312*cda5da8dSAndroid Build Coastguard Worker request, client_address = self.get_request() 313*cda5da8dSAndroid Build Coastguard Worker except OSError: 314*cda5da8dSAndroid Build Coastguard Worker return 315*cda5da8dSAndroid Build Coastguard Worker if self.verify_request(request, client_address): 316*cda5da8dSAndroid Build Coastguard Worker try: 317*cda5da8dSAndroid Build Coastguard Worker self.process_request(request, client_address) 318*cda5da8dSAndroid Build Coastguard Worker except Exception: 319*cda5da8dSAndroid Build Coastguard Worker self.handle_error(request, client_address) 320*cda5da8dSAndroid Build Coastguard Worker self.shutdown_request(request) 321*cda5da8dSAndroid Build Coastguard Worker except: 322*cda5da8dSAndroid Build Coastguard Worker self.shutdown_request(request) 323*cda5da8dSAndroid Build Coastguard Worker raise 324*cda5da8dSAndroid Build Coastguard Worker else: 325*cda5da8dSAndroid Build Coastguard Worker self.shutdown_request(request) 326*cda5da8dSAndroid Build Coastguard Worker 327*cda5da8dSAndroid Build Coastguard Worker def handle_timeout(self): 328*cda5da8dSAndroid Build Coastguard Worker """Called if no new request arrives within self.timeout. 329*cda5da8dSAndroid Build Coastguard Worker 330*cda5da8dSAndroid Build Coastguard Worker Overridden by ForkingMixIn. 331*cda5da8dSAndroid Build Coastguard Worker """ 332*cda5da8dSAndroid Build Coastguard Worker pass 333*cda5da8dSAndroid Build Coastguard Worker 334*cda5da8dSAndroid Build Coastguard Worker def verify_request(self, request, client_address): 335*cda5da8dSAndroid Build Coastguard Worker """Verify the request. May be overridden. 336*cda5da8dSAndroid Build Coastguard Worker 337*cda5da8dSAndroid Build Coastguard Worker Return True if we should proceed with this request. 338*cda5da8dSAndroid Build Coastguard Worker 339*cda5da8dSAndroid Build Coastguard Worker """ 340*cda5da8dSAndroid Build Coastguard Worker return True 341*cda5da8dSAndroid Build Coastguard Worker 342*cda5da8dSAndroid Build Coastguard Worker def process_request(self, request, client_address): 343*cda5da8dSAndroid Build Coastguard Worker """Call finish_request. 344*cda5da8dSAndroid Build Coastguard Worker 345*cda5da8dSAndroid Build Coastguard Worker Overridden by ForkingMixIn and ThreadingMixIn. 346*cda5da8dSAndroid Build Coastguard Worker 347*cda5da8dSAndroid Build Coastguard Worker """ 348*cda5da8dSAndroid Build Coastguard Worker self.finish_request(request, client_address) 349*cda5da8dSAndroid Build Coastguard Worker self.shutdown_request(request) 350*cda5da8dSAndroid Build Coastguard Worker 351*cda5da8dSAndroid Build Coastguard Worker def server_close(self): 352*cda5da8dSAndroid Build Coastguard Worker """Called to clean-up the server. 353*cda5da8dSAndroid Build Coastguard Worker 354*cda5da8dSAndroid Build Coastguard Worker May be overridden. 355*cda5da8dSAndroid Build Coastguard Worker 356*cda5da8dSAndroid Build Coastguard Worker """ 357*cda5da8dSAndroid Build Coastguard Worker pass 358*cda5da8dSAndroid Build Coastguard Worker 359*cda5da8dSAndroid Build Coastguard Worker def finish_request(self, request, client_address): 360*cda5da8dSAndroid Build Coastguard Worker """Finish one request by instantiating RequestHandlerClass.""" 361*cda5da8dSAndroid Build Coastguard Worker self.RequestHandlerClass(request, client_address, self) 362*cda5da8dSAndroid Build Coastguard Worker 363*cda5da8dSAndroid Build Coastguard Worker def shutdown_request(self, request): 364*cda5da8dSAndroid Build Coastguard Worker """Called to shutdown and close an individual request.""" 365*cda5da8dSAndroid Build Coastguard Worker self.close_request(request) 366*cda5da8dSAndroid Build Coastguard Worker 367*cda5da8dSAndroid Build Coastguard Worker def close_request(self, request): 368*cda5da8dSAndroid Build Coastguard Worker """Called to clean up an individual request.""" 369*cda5da8dSAndroid Build Coastguard Worker pass 370*cda5da8dSAndroid Build Coastguard Worker 371*cda5da8dSAndroid Build Coastguard Worker def handle_error(self, request, client_address): 372*cda5da8dSAndroid Build Coastguard Worker """Handle an error gracefully. May be overridden. 373*cda5da8dSAndroid Build Coastguard Worker 374*cda5da8dSAndroid Build Coastguard Worker The default is to print a traceback and continue. 375*cda5da8dSAndroid Build Coastguard Worker 376*cda5da8dSAndroid Build Coastguard Worker """ 377*cda5da8dSAndroid Build Coastguard Worker print('-'*40, file=sys.stderr) 378*cda5da8dSAndroid Build Coastguard Worker print('Exception occurred during processing of request from', 379*cda5da8dSAndroid Build Coastguard Worker client_address, file=sys.stderr) 380*cda5da8dSAndroid Build Coastguard Worker import traceback 381*cda5da8dSAndroid Build Coastguard Worker traceback.print_exc() 382*cda5da8dSAndroid Build Coastguard Worker print('-'*40, file=sys.stderr) 383*cda5da8dSAndroid Build Coastguard Worker 384*cda5da8dSAndroid Build Coastguard Worker def __enter__(self): 385*cda5da8dSAndroid Build Coastguard Worker return self 386*cda5da8dSAndroid Build Coastguard Worker 387*cda5da8dSAndroid Build Coastguard Worker def __exit__(self, *args): 388*cda5da8dSAndroid Build Coastguard Worker self.server_close() 389*cda5da8dSAndroid Build Coastguard Worker 390*cda5da8dSAndroid Build Coastguard Worker 391*cda5da8dSAndroid Build Coastguard Workerclass TCPServer(BaseServer): 392*cda5da8dSAndroid Build Coastguard Worker 393*cda5da8dSAndroid Build Coastguard Worker """Base class for various socket-based server classes. 394*cda5da8dSAndroid Build Coastguard Worker 395*cda5da8dSAndroid Build Coastguard Worker Defaults to synchronous IP stream (i.e., TCP). 396*cda5da8dSAndroid Build Coastguard Worker 397*cda5da8dSAndroid Build Coastguard Worker Methods for the caller: 398*cda5da8dSAndroid Build Coastguard Worker 399*cda5da8dSAndroid Build Coastguard Worker - __init__(server_address, RequestHandlerClass, bind_and_activate=True) 400*cda5da8dSAndroid Build Coastguard Worker - serve_forever(poll_interval=0.5) 401*cda5da8dSAndroid Build Coastguard Worker - shutdown() 402*cda5da8dSAndroid Build Coastguard Worker - handle_request() # if you don't use serve_forever() 403*cda5da8dSAndroid Build Coastguard Worker - fileno() -> int # for selector 404*cda5da8dSAndroid Build Coastguard Worker 405*cda5da8dSAndroid Build Coastguard Worker Methods that may be overridden: 406*cda5da8dSAndroid Build Coastguard Worker 407*cda5da8dSAndroid Build Coastguard Worker - server_bind() 408*cda5da8dSAndroid Build Coastguard Worker - server_activate() 409*cda5da8dSAndroid Build Coastguard Worker - get_request() -> request, client_address 410*cda5da8dSAndroid Build Coastguard Worker - handle_timeout() 411*cda5da8dSAndroid Build Coastguard Worker - verify_request(request, client_address) 412*cda5da8dSAndroid Build Coastguard Worker - process_request(request, client_address) 413*cda5da8dSAndroid Build Coastguard Worker - shutdown_request(request) 414*cda5da8dSAndroid Build Coastguard Worker - close_request(request) 415*cda5da8dSAndroid Build Coastguard Worker - handle_error() 416*cda5da8dSAndroid Build Coastguard Worker 417*cda5da8dSAndroid Build Coastguard Worker Methods for derived classes: 418*cda5da8dSAndroid Build Coastguard Worker 419*cda5da8dSAndroid Build Coastguard Worker - finish_request(request, client_address) 420*cda5da8dSAndroid Build Coastguard Worker 421*cda5da8dSAndroid Build Coastguard Worker Class variables that may be overridden by derived classes or 422*cda5da8dSAndroid Build Coastguard Worker instances: 423*cda5da8dSAndroid Build Coastguard Worker 424*cda5da8dSAndroid Build Coastguard Worker - timeout 425*cda5da8dSAndroid Build Coastguard Worker - address_family 426*cda5da8dSAndroid Build Coastguard Worker - socket_type 427*cda5da8dSAndroid Build Coastguard Worker - request_queue_size (only for stream sockets) 428*cda5da8dSAndroid Build Coastguard Worker - allow_reuse_address 429*cda5da8dSAndroid Build Coastguard Worker - allow_reuse_port 430*cda5da8dSAndroid Build Coastguard Worker 431*cda5da8dSAndroid Build Coastguard Worker Instance variables: 432*cda5da8dSAndroid Build Coastguard Worker 433*cda5da8dSAndroid Build Coastguard Worker - server_address 434*cda5da8dSAndroid Build Coastguard Worker - RequestHandlerClass 435*cda5da8dSAndroid Build Coastguard Worker - socket 436*cda5da8dSAndroid Build Coastguard Worker 437*cda5da8dSAndroid Build Coastguard Worker """ 438*cda5da8dSAndroid Build Coastguard Worker 439*cda5da8dSAndroid Build Coastguard Worker address_family = socket.AF_INET 440*cda5da8dSAndroid Build Coastguard Worker 441*cda5da8dSAndroid Build Coastguard Worker socket_type = socket.SOCK_STREAM 442*cda5da8dSAndroid Build Coastguard Worker 443*cda5da8dSAndroid Build Coastguard Worker request_queue_size = 5 444*cda5da8dSAndroid Build Coastguard Worker 445*cda5da8dSAndroid Build Coastguard Worker allow_reuse_address = False 446*cda5da8dSAndroid Build Coastguard Worker 447*cda5da8dSAndroid Build Coastguard Worker allow_reuse_port = False 448*cda5da8dSAndroid Build Coastguard Worker 449*cda5da8dSAndroid Build Coastguard Worker def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True): 450*cda5da8dSAndroid Build Coastguard Worker """Constructor. May be extended, do not override.""" 451*cda5da8dSAndroid Build Coastguard Worker BaseServer.__init__(self, server_address, RequestHandlerClass) 452*cda5da8dSAndroid Build Coastguard Worker self.socket = socket.socket(self.address_family, 453*cda5da8dSAndroid Build Coastguard Worker self.socket_type) 454*cda5da8dSAndroid Build Coastguard Worker if bind_and_activate: 455*cda5da8dSAndroid Build Coastguard Worker try: 456*cda5da8dSAndroid Build Coastguard Worker self.server_bind() 457*cda5da8dSAndroid Build Coastguard Worker self.server_activate() 458*cda5da8dSAndroid Build Coastguard Worker except: 459*cda5da8dSAndroid Build Coastguard Worker self.server_close() 460*cda5da8dSAndroid Build Coastguard Worker raise 461*cda5da8dSAndroid Build Coastguard Worker 462*cda5da8dSAndroid Build Coastguard Worker def server_bind(self): 463*cda5da8dSAndroid Build Coastguard Worker """Called by constructor to bind the socket. 464*cda5da8dSAndroid Build Coastguard Worker 465*cda5da8dSAndroid Build Coastguard Worker May be overridden. 466*cda5da8dSAndroid Build Coastguard Worker 467*cda5da8dSAndroid Build Coastguard Worker """ 468*cda5da8dSAndroid Build Coastguard Worker if self.allow_reuse_address and hasattr(socket, "SO_REUSEADDR"): 469*cda5da8dSAndroid Build Coastguard Worker self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 470*cda5da8dSAndroid Build Coastguard Worker if self.allow_reuse_port and hasattr(socket, "SO_REUSEPORT"): 471*cda5da8dSAndroid Build Coastguard Worker self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) 472*cda5da8dSAndroid Build Coastguard Worker self.socket.bind(self.server_address) 473*cda5da8dSAndroid Build Coastguard Worker self.server_address = self.socket.getsockname() 474*cda5da8dSAndroid Build Coastguard Worker 475*cda5da8dSAndroid Build Coastguard Worker def server_activate(self): 476*cda5da8dSAndroid Build Coastguard Worker """Called by constructor to activate the server. 477*cda5da8dSAndroid Build Coastguard Worker 478*cda5da8dSAndroid Build Coastguard Worker May be overridden. 479*cda5da8dSAndroid Build Coastguard Worker 480*cda5da8dSAndroid Build Coastguard Worker """ 481*cda5da8dSAndroid Build Coastguard Worker self.socket.listen(self.request_queue_size) 482*cda5da8dSAndroid Build Coastguard Worker 483*cda5da8dSAndroid Build Coastguard Worker def server_close(self): 484*cda5da8dSAndroid Build Coastguard Worker """Called to clean-up the server. 485*cda5da8dSAndroid Build Coastguard Worker 486*cda5da8dSAndroid Build Coastguard Worker May be overridden. 487*cda5da8dSAndroid Build Coastguard Worker 488*cda5da8dSAndroid Build Coastguard Worker """ 489*cda5da8dSAndroid Build Coastguard Worker self.socket.close() 490*cda5da8dSAndroid Build Coastguard Worker 491*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 492*cda5da8dSAndroid Build Coastguard Worker """Return socket file number. 493*cda5da8dSAndroid Build Coastguard Worker 494*cda5da8dSAndroid Build Coastguard Worker Interface required by selector. 495*cda5da8dSAndroid Build Coastguard Worker 496*cda5da8dSAndroid Build Coastguard Worker """ 497*cda5da8dSAndroid Build Coastguard Worker return self.socket.fileno() 498*cda5da8dSAndroid Build Coastguard Worker 499*cda5da8dSAndroid Build Coastguard Worker def get_request(self): 500*cda5da8dSAndroid Build Coastguard Worker """Get the request and client address from the socket. 501*cda5da8dSAndroid Build Coastguard Worker 502*cda5da8dSAndroid Build Coastguard Worker May be overridden. 503*cda5da8dSAndroid Build Coastguard Worker 504*cda5da8dSAndroid Build Coastguard Worker """ 505*cda5da8dSAndroid Build Coastguard Worker return self.socket.accept() 506*cda5da8dSAndroid Build Coastguard Worker 507*cda5da8dSAndroid Build Coastguard Worker def shutdown_request(self, request): 508*cda5da8dSAndroid Build Coastguard Worker """Called to shutdown and close an individual request.""" 509*cda5da8dSAndroid Build Coastguard Worker try: 510*cda5da8dSAndroid Build Coastguard Worker #explicitly shutdown. socket.close() merely releases 511*cda5da8dSAndroid Build Coastguard Worker #the socket and waits for GC to perform the actual close. 512*cda5da8dSAndroid Build Coastguard Worker request.shutdown(socket.SHUT_WR) 513*cda5da8dSAndroid Build Coastguard Worker except OSError: 514*cda5da8dSAndroid Build Coastguard Worker pass #some platforms may raise ENOTCONN here 515*cda5da8dSAndroid Build Coastguard Worker self.close_request(request) 516*cda5da8dSAndroid Build Coastguard Worker 517*cda5da8dSAndroid Build Coastguard Worker def close_request(self, request): 518*cda5da8dSAndroid Build Coastguard Worker """Called to clean up an individual request.""" 519*cda5da8dSAndroid Build Coastguard Worker request.close() 520*cda5da8dSAndroid Build Coastguard Worker 521*cda5da8dSAndroid Build Coastguard Worker 522*cda5da8dSAndroid Build Coastguard Workerclass UDPServer(TCPServer): 523*cda5da8dSAndroid Build Coastguard Worker 524*cda5da8dSAndroid Build Coastguard Worker """UDP server class.""" 525*cda5da8dSAndroid Build Coastguard Worker 526*cda5da8dSAndroid Build Coastguard Worker allow_reuse_address = False 527*cda5da8dSAndroid Build Coastguard Worker 528*cda5da8dSAndroid Build Coastguard Worker allow_reuse_port = False 529*cda5da8dSAndroid Build Coastguard Worker 530*cda5da8dSAndroid Build Coastguard Worker socket_type = socket.SOCK_DGRAM 531*cda5da8dSAndroid Build Coastguard Worker 532*cda5da8dSAndroid Build Coastguard Worker max_packet_size = 8192 533*cda5da8dSAndroid Build Coastguard Worker 534*cda5da8dSAndroid Build Coastguard Worker def get_request(self): 535*cda5da8dSAndroid Build Coastguard Worker data, client_addr = self.socket.recvfrom(self.max_packet_size) 536*cda5da8dSAndroid Build Coastguard Worker return (data, self.socket), client_addr 537*cda5da8dSAndroid Build Coastguard Worker 538*cda5da8dSAndroid Build Coastguard Worker def server_activate(self): 539*cda5da8dSAndroid Build Coastguard Worker # No need to call listen() for UDP. 540*cda5da8dSAndroid Build Coastguard Worker pass 541*cda5da8dSAndroid Build Coastguard Worker 542*cda5da8dSAndroid Build Coastguard Worker def shutdown_request(self, request): 543*cda5da8dSAndroid Build Coastguard Worker # No need to shutdown anything. 544*cda5da8dSAndroid Build Coastguard Worker self.close_request(request) 545*cda5da8dSAndroid Build Coastguard Worker 546*cda5da8dSAndroid Build Coastguard Worker def close_request(self, request): 547*cda5da8dSAndroid Build Coastguard Worker # No need to close anything. 548*cda5da8dSAndroid Build Coastguard Worker pass 549*cda5da8dSAndroid Build Coastguard Worker 550*cda5da8dSAndroid Build Coastguard Workerif hasattr(os, "fork"): 551*cda5da8dSAndroid Build Coastguard Worker class ForkingMixIn: 552*cda5da8dSAndroid Build Coastguard Worker """Mix-in class to handle each request in a new process.""" 553*cda5da8dSAndroid Build Coastguard Worker 554*cda5da8dSAndroid Build Coastguard Worker timeout = 300 555*cda5da8dSAndroid Build Coastguard Worker active_children = None 556*cda5da8dSAndroid Build Coastguard Worker max_children = 40 557*cda5da8dSAndroid Build Coastguard Worker # If true, server_close() waits until all child processes complete. 558*cda5da8dSAndroid Build Coastguard Worker block_on_close = True 559*cda5da8dSAndroid Build Coastguard Worker 560*cda5da8dSAndroid Build Coastguard Worker def collect_children(self, *, blocking=False): 561*cda5da8dSAndroid Build Coastguard Worker """Internal routine to wait for children that have exited.""" 562*cda5da8dSAndroid Build Coastguard Worker if self.active_children is None: 563*cda5da8dSAndroid Build Coastguard Worker return 564*cda5da8dSAndroid Build Coastguard Worker 565*cda5da8dSAndroid Build Coastguard Worker # If we're above the max number of children, wait and reap them until 566*cda5da8dSAndroid Build Coastguard Worker # we go back below threshold. Note that we use waitpid(-1) below to be 567*cda5da8dSAndroid Build Coastguard Worker # able to collect children in size(<defunct children>) syscalls instead 568*cda5da8dSAndroid Build Coastguard Worker # of size(<children>): the downside is that this might reap children 569*cda5da8dSAndroid Build Coastguard Worker # which we didn't spawn, which is why we only resort to this when we're 570*cda5da8dSAndroid Build Coastguard Worker # above max_children. 571*cda5da8dSAndroid Build Coastguard Worker while len(self.active_children) >= self.max_children: 572*cda5da8dSAndroid Build Coastguard Worker try: 573*cda5da8dSAndroid Build Coastguard Worker pid, _ = os.waitpid(-1, 0) 574*cda5da8dSAndroid Build Coastguard Worker self.active_children.discard(pid) 575*cda5da8dSAndroid Build Coastguard Worker except ChildProcessError: 576*cda5da8dSAndroid Build Coastguard Worker # we don't have any children, we're done 577*cda5da8dSAndroid Build Coastguard Worker self.active_children.clear() 578*cda5da8dSAndroid Build Coastguard Worker except OSError: 579*cda5da8dSAndroid Build Coastguard Worker break 580*cda5da8dSAndroid Build Coastguard Worker 581*cda5da8dSAndroid Build Coastguard Worker # Now reap all defunct children. 582*cda5da8dSAndroid Build Coastguard Worker for pid in self.active_children.copy(): 583*cda5da8dSAndroid Build Coastguard Worker try: 584*cda5da8dSAndroid Build Coastguard Worker flags = 0 if blocking else os.WNOHANG 585*cda5da8dSAndroid Build Coastguard Worker pid, _ = os.waitpid(pid, flags) 586*cda5da8dSAndroid Build Coastguard Worker # if the child hasn't exited yet, pid will be 0 and ignored by 587*cda5da8dSAndroid Build Coastguard Worker # discard() below 588*cda5da8dSAndroid Build Coastguard Worker self.active_children.discard(pid) 589*cda5da8dSAndroid Build Coastguard Worker except ChildProcessError: 590*cda5da8dSAndroid Build Coastguard Worker # someone else reaped it 591*cda5da8dSAndroid Build Coastguard Worker self.active_children.discard(pid) 592*cda5da8dSAndroid Build Coastguard Worker except OSError: 593*cda5da8dSAndroid Build Coastguard Worker pass 594*cda5da8dSAndroid Build Coastguard Worker 595*cda5da8dSAndroid Build Coastguard Worker def handle_timeout(self): 596*cda5da8dSAndroid Build Coastguard Worker """Wait for zombies after self.timeout seconds of inactivity. 597*cda5da8dSAndroid Build Coastguard Worker 598*cda5da8dSAndroid Build Coastguard Worker May be extended, do not override. 599*cda5da8dSAndroid Build Coastguard Worker """ 600*cda5da8dSAndroid Build Coastguard Worker self.collect_children() 601*cda5da8dSAndroid Build Coastguard Worker 602*cda5da8dSAndroid Build Coastguard Worker def service_actions(self): 603*cda5da8dSAndroid Build Coastguard Worker """Collect the zombie child processes regularly in the ForkingMixIn. 604*cda5da8dSAndroid Build Coastguard Worker 605*cda5da8dSAndroid Build Coastguard Worker service_actions is called in the BaseServer's serve_forever loop. 606*cda5da8dSAndroid Build Coastguard Worker """ 607*cda5da8dSAndroid Build Coastguard Worker self.collect_children() 608*cda5da8dSAndroid Build Coastguard Worker 609*cda5da8dSAndroid Build Coastguard Worker def process_request(self, request, client_address): 610*cda5da8dSAndroid Build Coastguard Worker """Fork a new subprocess to process the request.""" 611*cda5da8dSAndroid Build Coastguard Worker pid = os.fork() 612*cda5da8dSAndroid Build Coastguard Worker if pid: 613*cda5da8dSAndroid Build Coastguard Worker # Parent process 614*cda5da8dSAndroid Build Coastguard Worker if self.active_children is None: 615*cda5da8dSAndroid Build Coastguard Worker self.active_children = set() 616*cda5da8dSAndroid Build Coastguard Worker self.active_children.add(pid) 617*cda5da8dSAndroid Build Coastguard Worker self.close_request(request) 618*cda5da8dSAndroid Build Coastguard Worker return 619*cda5da8dSAndroid Build Coastguard Worker else: 620*cda5da8dSAndroid Build Coastguard Worker # Child process. 621*cda5da8dSAndroid Build Coastguard Worker # This must never return, hence os._exit()! 622*cda5da8dSAndroid Build Coastguard Worker status = 1 623*cda5da8dSAndroid Build Coastguard Worker try: 624*cda5da8dSAndroid Build Coastguard Worker self.finish_request(request, client_address) 625*cda5da8dSAndroid Build Coastguard Worker status = 0 626*cda5da8dSAndroid Build Coastguard Worker except Exception: 627*cda5da8dSAndroid Build Coastguard Worker self.handle_error(request, client_address) 628*cda5da8dSAndroid Build Coastguard Worker finally: 629*cda5da8dSAndroid Build Coastguard Worker try: 630*cda5da8dSAndroid Build Coastguard Worker self.shutdown_request(request) 631*cda5da8dSAndroid Build Coastguard Worker finally: 632*cda5da8dSAndroid Build Coastguard Worker os._exit(status) 633*cda5da8dSAndroid Build Coastguard Worker 634*cda5da8dSAndroid Build Coastguard Worker def server_close(self): 635*cda5da8dSAndroid Build Coastguard Worker super().server_close() 636*cda5da8dSAndroid Build Coastguard Worker self.collect_children(blocking=self.block_on_close) 637*cda5da8dSAndroid Build Coastguard Worker 638*cda5da8dSAndroid Build Coastguard Worker 639*cda5da8dSAndroid Build Coastguard Workerclass _Threads(list): 640*cda5da8dSAndroid Build Coastguard Worker """ 641*cda5da8dSAndroid Build Coastguard Worker Joinable list of all non-daemon threads. 642*cda5da8dSAndroid Build Coastguard Worker """ 643*cda5da8dSAndroid Build Coastguard Worker def append(self, thread): 644*cda5da8dSAndroid Build Coastguard Worker self.reap() 645*cda5da8dSAndroid Build Coastguard Worker if thread.daemon: 646*cda5da8dSAndroid Build Coastguard Worker return 647*cda5da8dSAndroid Build Coastguard Worker super().append(thread) 648*cda5da8dSAndroid Build Coastguard Worker 649*cda5da8dSAndroid Build Coastguard Worker def pop_all(self): 650*cda5da8dSAndroid Build Coastguard Worker self[:], result = [], self[:] 651*cda5da8dSAndroid Build Coastguard Worker return result 652*cda5da8dSAndroid Build Coastguard Worker 653*cda5da8dSAndroid Build Coastguard Worker def join(self): 654*cda5da8dSAndroid Build Coastguard Worker for thread in self.pop_all(): 655*cda5da8dSAndroid Build Coastguard Worker thread.join() 656*cda5da8dSAndroid Build Coastguard Worker 657*cda5da8dSAndroid Build Coastguard Worker def reap(self): 658*cda5da8dSAndroid Build Coastguard Worker self[:] = (thread for thread in self if thread.is_alive()) 659*cda5da8dSAndroid Build Coastguard Worker 660*cda5da8dSAndroid Build Coastguard Worker 661*cda5da8dSAndroid Build Coastguard Workerclass _NoThreads: 662*cda5da8dSAndroid Build Coastguard Worker """ 663*cda5da8dSAndroid Build Coastguard Worker Degenerate version of _Threads. 664*cda5da8dSAndroid Build Coastguard Worker """ 665*cda5da8dSAndroid Build Coastguard Worker def append(self, thread): 666*cda5da8dSAndroid Build Coastguard Worker pass 667*cda5da8dSAndroid Build Coastguard Worker 668*cda5da8dSAndroid Build Coastguard Worker def join(self): 669*cda5da8dSAndroid Build Coastguard Worker pass 670*cda5da8dSAndroid Build Coastguard Worker 671*cda5da8dSAndroid Build Coastguard Worker 672*cda5da8dSAndroid Build Coastguard Workerclass ThreadingMixIn: 673*cda5da8dSAndroid Build Coastguard Worker """Mix-in class to handle each request in a new thread.""" 674*cda5da8dSAndroid Build Coastguard Worker 675*cda5da8dSAndroid Build Coastguard Worker # Decides how threads will act upon termination of the 676*cda5da8dSAndroid Build Coastguard Worker # main process 677*cda5da8dSAndroid Build Coastguard Worker daemon_threads = False 678*cda5da8dSAndroid Build Coastguard Worker # If true, server_close() waits until all non-daemonic threads terminate. 679*cda5da8dSAndroid Build Coastguard Worker block_on_close = True 680*cda5da8dSAndroid Build Coastguard Worker # Threads object 681*cda5da8dSAndroid Build Coastguard Worker # used by server_close() to wait for all threads completion. 682*cda5da8dSAndroid Build Coastguard Worker _threads = _NoThreads() 683*cda5da8dSAndroid Build Coastguard Worker 684*cda5da8dSAndroid Build Coastguard Worker def process_request_thread(self, request, client_address): 685*cda5da8dSAndroid Build Coastguard Worker """Same as in BaseServer but as a thread. 686*cda5da8dSAndroid Build Coastguard Worker 687*cda5da8dSAndroid Build Coastguard Worker In addition, exception handling is done here. 688*cda5da8dSAndroid Build Coastguard Worker 689*cda5da8dSAndroid Build Coastguard Worker """ 690*cda5da8dSAndroid Build Coastguard Worker try: 691*cda5da8dSAndroid Build Coastguard Worker self.finish_request(request, client_address) 692*cda5da8dSAndroid Build Coastguard Worker except Exception: 693*cda5da8dSAndroid Build Coastguard Worker self.handle_error(request, client_address) 694*cda5da8dSAndroid Build Coastguard Worker finally: 695*cda5da8dSAndroid Build Coastguard Worker self.shutdown_request(request) 696*cda5da8dSAndroid Build Coastguard Worker 697*cda5da8dSAndroid Build Coastguard Worker def process_request(self, request, client_address): 698*cda5da8dSAndroid Build Coastguard Worker """Start a new thread to process the request.""" 699*cda5da8dSAndroid Build Coastguard Worker if self.block_on_close: 700*cda5da8dSAndroid Build Coastguard Worker vars(self).setdefault('_threads', _Threads()) 701*cda5da8dSAndroid Build Coastguard Worker t = threading.Thread(target = self.process_request_thread, 702*cda5da8dSAndroid Build Coastguard Worker args = (request, client_address)) 703*cda5da8dSAndroid Build Coastguard Worker t.daemon = self.daemon_threads 704*cda5da8dSAndroid Build Coastguard Worker self._threads.append(t) 705*cda5da8dSAndroid Build Coastguard Worker t.start() 706*cda5da8dSAndroid Build Coastguard Worker 707*cda5da8dSAndroid Build Coastguard Worker def server_close(self): 708*cda5da8dSAndroid Build Coastguard Worker super().server_close() 709*cda5da8dSAndroid Build Coastguard Worker self._threads.join() 710*cda5da8dSAndroid Build Coastguard Worker 711*cda5da8dSAndroid Build Coastguard Worker 712*cda5da8dSAndroid Build Coastguard Workerif hasattr(os, "fork"): 713*cda5da8dSAndroid Build Coastguard Worker class ForkingUDPServer(ForkingMixIn, UDPServer): pass 714*cda5da8dSAndroid Build Coastguard Worker class ForkingTCPServer(ForkingMixIn, TCPServer): pass 715*cda5da8dSAndroid Build Coastguard Worker 716*cda5da8dSAndroid Build Coastguard Workerclass ThreadingUDPServer(ThreadingMixIn, UDPServer): pass 717*cda5da8dSAndroid Build Coastguard Workerclass ThreadingTCPServer(ThreadingMixIn, TCPServer): pass 718*cda5da8dSAndroid Build Coastguard Worker 719*cda5da8dSAndroid Build Coastguard Workerif hasattr(socket, 'AF_UNIX'): 720*cda5da8dSAndroid Build Coastguard Worker 721*cda5da8dSAndroid Build Coastguard Worker class UnixStreamServer(TCPServer): 722*cda5da8dSAndroid Build Coastguard Worker address_family = socket.AF_UNIX 723*cda5da8dSAndroid Build Coastguard Worker 724*cda5da8dSAndroid Build Coastguard Worker class UnixDatagramServer(UDPServer): 725*cda5da8dSAndroid Build Coastguard Worker address_family = socket.AF_UNIX 726*cda5da8dSAndroid Build Coastguard Worker 727*cda5da8dSAndroid Build Coastguard Worker class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass 728*cda5da8dSAndroid Build Coastguard Worker 729*cda5da8dSAndroid Build Coastguard Worker class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass 730*cda5da8dSAndroid Build Coastguard Worker 731*cda5da8dSAndroid Build Coastguard Workerclass BaseRequestHandler: 732*cda5da8dSAndroid Build Coastguard Worker 733*cda5da8dSAndroid Build Coastguard Worker """Base class for request handler classes. 734*cda5da8dSAndroid Build Coastguard Worker 735*cda5da8dSAndroid Build Coastguard Worker This class is instantiated for each request to be handled. The 736*cda5da8dSAndroid Build Coastguard Worker constructor sets the instance variables request, client_address 737*cda5da8dSAndroid Build Coastguard Worker and server, and then calls the handle() method. To implement a 738*cda5da8dSAndroid Build Coastguard Worker specific service, all you need to do is to derive a class which 739*cda5da8dSAndroid Build Coastguard Worker defines a handle() method. 740*cda5da8dSAndroid Build Coastguard Worker 741*cda5da8dSAndroid Build Coastguard Worker The handle() method can find the request as self.request, the 742*cda5da8dSAndroid Build Coastguard Worker client address as self.client_address, and the server (in case it 743*cda5da8dSAndroid Build Coastguard Worker needs access to per-server information) as self.server. Since a 744*cda5da8dSAndroid Build Coastguard Worker separate instance is created for each request, the handle() method 745*cda5da8dSAndroid Build Coastguard Worker can define other arbitrary instance variables. 746*cda5da8dSAndroid Build Coastguard Worker 747*cda5da8dSAndroid Build Coastguard Worker """ 748*cda5da8dSAndroid Build Coastguard Worker 749*cda5da8dSAndroid Build Coastguard Worker def __init__(self, request, client_address, server): 750*cda5da8dSAndroid Build Coastguard Worker self.request = request 751*cda5da8dSAndroid Build Coastguard Worker self.client_address = client_address 752*cda5da8dSAndroid Build Coastguard Worker self.server = server 753*cda5da8dSAndroid Build Coastguard Worker self.setup() 754*cda5da8dSAndroid Build Coastguard Worker try: 755*cda5da8dSAndroid Build Coastguard Worker self.handle() 756*cda5da8dSAndroid Build Coastguard Worker finally: 757*cda5da8dSAndroid Build Coastguard Worker self.finish() 758*cda5da8dSAndroid Build Coastguard Worker 759*cda5da8dSAndroid Build Coastguard Worker def setup(self): 760*cda5da8dSAndroid Build Coastguard Worker pass 761*cda5da8dSAndroid Build Coastguard Worker 762*cda5da8dSAndroid Build Coastguard Worker def handle(self): 763*cda5da8dSAndroid Build Coastguard Worker pass 764*cda5da8dSAndroid Build Coastguard Worker 765*cda5da8dSAndroid Build Coastguard Worker def finish(self): 766*cda5da8dSAndroid Build Coastguard Worker pass 767*cda5da8dSAndroid Build Coastguard Worker 768*cda5da8dSAndroid Build Coastguard Worker 769*cda5da8dSAndroid Build Coastguard Worker# The following two classes make it possible to use the same service 770*cda5da8dSAndroid Build Coastguard Worker# class for stream or datagram servers. 771*cda5da8dSAndroid Build Coastguard Worker# Each class sets up these instance variables: 772*cda5da8dSAndroid Build Coastguard Worker# - rfile: a file object from which receives the request is read 773*cda5da8dSAndroid Build Coastguard Worker# - wfile: a file object to which the reply is written 774*cda5da8dSAndroid Build Coastguard Worker# When the handle() method returns, wfile is flushed properly 775*cda5da8dSAndroid Build Coastguard Worker 776*cda5da8dSAndroid Build Coastguard Worker 777*cda5da8dSAndroid Build Coastguard Workerclass StreamRequestHandler(BaseRequestHandler): 778*cda5da8dSAndroid Build Coastguard Worker 779*cda5da8dSAndroid Build Coastguard Worker """Define self.rfile and self.wfile for stream sockets.""" 780*cda5da8dSAndroid Build Coastguard Worker 781*cda5da8dSAndroid Build Coastguard Worker # Default buffer sizes for rfile, wfile. 782*cda5da8dSAndroid Build Coastguard Worker # We default rfile to buffered because otherwise it could be 783*cda5da8dSAndroid Build Coastguard Worker # really slow for large data (a getc() call per byte); we make 784*cda5da8dSAndroid Build Coastguard Worker # wfile unbuffered because (a) often after a write() we want to 785*cda5da8dSAndroid Build Coastguard Worker # read and we need to flush the line; (b) big writes to unbuffered 786*cda5da8dSAndroid Build Coastguard Worker # files are typically optimized by stdio even when big reads 787*cda5da8dSAndroid Build Coastguard Worker # aren't. 788*cda5da8dSAndroid Build Coastguard Worker rbufsize = -1 789*cda5da8dSAndroid Build Coastguard Worker wbufsize = 0 790*cda5da8dSAndroid Build Coastguard Worker 791*cda5da8dSAndroid Build Coastguard Worker # A timeout to apply to the request socket, if not None. 792*cda5da8dSAndroid Build Coastguard Worker timeout = None 793*cda5da8dSAndroid Build Coastguard Worker 794*cda5da8dSAndroid Build Coastguard Worker # Disable nagle algorithm for this socket, if True. 795*cda5da8dSAndroid Build Coastguard Worker # Use only when wbufsize != 0, to avoid small packets. 796*cda5da8dSAndroid Build Coastguard Worker disable_nagle_algorithm = False 797*cda5da8dSAndroid Build Coastguard Worker 798*cda5da8dSAndroid Build Coastguard Worker def setup(self): 799*cda5da8dSAndroid Build Coastguard Worker self.connection = self.request 800*cda5da8dSAndroid Build Coastguard Worker if self.timeout is not None: 801*cda5da8dSAndroid Build Coastguard Worker self.connection.settimeout(self.timeout) 802*cda5da8dSAndroid Build Coastguard Worker if self.disable_nagle_algorithm: 803*cda5da8dSAndroid Build Coastguard Worker self.connection.setsockopt(socket.IPPROTO_TCP, 804*cda5da8dSAndroid Build Coastguard Worker socket.TCP_NODELAY, True) 805*cda5da8dSAndroid Build Coastguard Worker self.rfile = self.connection.makefile('rb', self.rbufsize) 806*cda5da8dSAndroid Build Coastguard Worker if self.wbufsize == 0: 807*cda5da8dSAndroid Build Coastguard Worker self.wfile = _SocketWriter(self.connection) 808*cda5da8dSAndroid Build Coastguard Worker else: 809*cda5da8dSAndroid Build Coastguard Worker self.wfile = self.connection.makefile('wb', self.wbufsize) 810*cda5da8dSAndroid Build Coastguard Worker 811*cda5da8dSAndroid Build Coastguard Worker def finish(self): 812*cda5da8dSAndroid Build Coastguard Worker if not self.wfile.closed: 813*cda5da8dSAndroid Build Coastguard Worker try: 814*cda5da8dSAndroid Build Coastguard Worker self.wfile.flush() 815*cda5da8dSAndroid Build Coastguard Worker except socket.error: 816*cda5da8dSAndroid Build Coastguard Worker # A final socket error may have occurred here, such as 817*cda5da8dSAndroid Build Coastguard Worker # the local error ECONNABORTED. 818*cda5da8dSAndroid Build Coastguard Worker pass 819*cda5da8dSAndroid Build Coastguard Worker self.wfile.close() 820*cda5da8dSAndroid Build Coastguard Worker self.rfile.close() 821*cda5da8dSAndroid Build Coastguard Worker 822*cda5da8dSAndroid Build Coastguard Workerclass _SocketWriter(BufferedIOBase): 823*cda5da8dSAndroid Build Coastguard Worker """Simple writable BufferedIOBase implementation for a socket 824*cda5da8dSAndroid Build Coastguard Worker 825*cda5da8dSAndroid Build Coastguard Worker Does not hold data in a buffer, avoiding any need to call flush().""" 826*cda5da8dSAndroid Build Coastguard Worker 827*cda5da8dSAndroid Build Coastguard Worker def __init__(self, sock): 828*cda5da8dSAndroid Build Coastguard Worker self._sock = sock 829*cda5da8dSAndroid Build Coastguard Worker 830*cda5da8dSAndroid Build Coastguard Worker def writable(self): 831*cda5da8dSAndroid Build Coastguard Worker return True 832*cda5da8dSAndroid Build Coastguard Worker 833*cda5da8dSAndroid Build Coastguard Worker def write(self, b): 834*cda5da8dSAndroid Build Coastguard Worker self._sock.sendall(b) 835*cda5da8dSAndroid Build Coastguard Worker with memoryview(b) as view: 836*cda5da8dSAndroid Build Coastguard Worker return view.nbytes 837*cda5da8dSAndroid Build Coastguard Worker 838*cda5da8dSAndroid Build Coastguard Worker def fileno(self): 839*cda5da8dSAndroid Build Coastguard Worker return self._sock.fileno() 840*cda5da8dSAndroid Build Coastguard Worker 841*cda5da8dSAndroid Build Coastguard Workerclass DatagramRequestHandler(BaseRequestHandler): 842*cda5da8dSAndroid Build Coastguard Worker 843*cda5da8dSAndroid Build Coastguard Worker """Define self.rfile and self.wfile for datagram sockets.""" 844*cda5da8dSAndroid Build Coastguard Worker 845*cda5da8dSAndroid Build Coastguard Worker def setup(self): 846*cda5da8dSAndroid Build Coastguard Worker from io import BytesIO 847*cda5da8dSAndroid Build Coastguard Worker self.packet, self.socket = self.request 848*cda5da8dSAndroid Build Coastguard Worker self.rfile = BytesIO(self.packet) 849*cda5da8dSAndroid Build Coastguard Worker self.wfile = BytesIO() 850*cda5da8dSAndroid Build Coastguard Worker 851*cda5da8dSAndroid Build Coastguard Worker def finish(self): 852*cda5da8dSAndroid Build Coastguard Worker self.socket.sendto(self.wfile.getvalue(), self.client_address) 853