socketserver.py 26.1 KB
Newer Older
Guido van Rossum's avatar
Guido van Rossum committed
1 2 3 4
"""Generic socket server classes.

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

5 6
For socket-based servers:

Guido van Rossum's avatar
Guido van Rossum committed
7
- address family:
8
        - AF_INET{,6}: IP (Internet Protocol) sockets (default)
9 10
        - AF_UNIX: Unix domain sockets
        - others, e.g. AF_DECNET are conceivable (see <socket.h>
Guido van Rossum's avatar
Guido van Rossum committed
11
- socket type:
12 13
        - SOCK_STREAM (reliable stream, e.g. TCP)
        - SOCK_DGRAM (datagrams, e.g. UDP)
14 15 16

For request-based servers (including socket-based):

Guido van Rossum's avatar
Guido van Rossum committed
17
- client address verification before further looking at the request
18 19
        (This is actually a hook for any processing that needs to look
         at the request before anything else, e.g. logging)
Guido van Rossum's avatar
Guido van Rossum committed
20
- how to handle multiple requests:
21 22 23
        - synchronous (one request is handled at a time)
        - forking (each request is handled by a new process)
        - threading (each request is handled by a new thread)
Guido van Rossum's avatar
Guido van Rossum committed
24 25 26 27 28 29

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

30
There are five classes in an inheritance diagram, four of which represent
Guido van Rossum's avatar
Guido van Rossum committed
31 32
synchronous servers of four types:

33 34 35 36 37
        +------------+
        | BaseServer |
        +------------+
              |
              v
38 39 40 41 42 43 44 45
        +-----------+        +------------------+
        | TCPServer |------->| UnixStreamServer |
        +-----------+        +------------------+
              |
              v
        +-----------+        +--------------------+
        | UDPServer |------->| UnixDatagramServer |
        +-----------+        +--------------------+
Guido van Rossum's avatar
Guido van Rossum committed
46

47
Note that UnixDatagramServer derives from UDPServer, not from
Guido van Rossum's avatar
Guido van Rossum committed
48 49
UnixStreamServer -- the only difference between an IP and a Unix
stream server is the address family, which is simply repeated in both
50
unix server classes.
Guido van Rossum's avatar
Guido van Rossum committed
51 52

Forking and threading versions of each type of server can be created
53
using the ForkingMixIn and ThreadingMixIn mix-in classes.  For
Guido van Rossum's avatar
Guido van Rossum committed
54 55
instance, a threading UDP server class is created as follows:

56
        class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
Guido van Rossum's avatar
Guido van Rossum committed
57

58
The Mix-in class must come first, since it overrides a method defined
59 60
in UDPServer! Setting the various member variables also changes
the behavior of the underlying server mechanism.
Guido van Rossum's avatar
Guido van Rossum committed
61 62 63 64 65 66 67

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

The request handler class must be different for datagram or stream
68 69
services.  This can be hidden by using the request handler
subclasses StreamRequestHandler or DatagramRequestHandler.
Guido van Rossum's avatar
Guido van Rossum committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

Of course, you still have to use your head!

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

On the other hand, if you are building e.g. an HTTP server, where all
data is stored externally (e.g. in the file system), a synchronous
class will essentially render the service "deaf" while one request is
being handled -- which may be for a very long time if a client is slow
Ezio Melotti's avatar
Ezio Melotti committed
85
to read all the data it has requested.  Here a threading or forking
Guido van Rossum's avatar
Guido van Rossum committed
86 87 88 89 90
server is appropriate.

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

Another approach to handling multiple simultaneous requests in an
environment that supports neither threads nor fork (or where these are
too expensive or inappropriate for the service) is to maintain an
97
explicit table of partially finished requests and to use a selector to
Guido van Rossum's avatar
Guido van Rossum committed
98 99 100
decide which request to work on next (or whether to handle a new
incoming request).  This is particularly important for stream services
where each client can potentially be connected for a long time (if
101
threads or subprocesses cannot be used).
Guido van Rossum's avatar
Guido van Rossum committed
102 103 104 105 106 107 108 109 110

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

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

111 112 113 114 115 116 117 118
BaseServer:
- split generic "request" functionality out into BaseServer class.
  Copyright (C) 2000  Luke Kenneth Casson Leighton <lkcl@samba.org>

  example: read entries from a SQL database (requires overriding
  get_request() to return a table entry from the database).
  entry is processed by a RequestHandlerClass.

Guido van Rossum's avatar
Guido van Rossum committed
119 120
"""

121
# Author of the BaseServer patch: Luke Kenneth Casson Leighton
Guido van Rossum's avatar
Guido van Rossum committed
122

123
__version__ = "0.4"
Guido van Rossum's avatar
Guido van Rossum committed
124 125 126


import socket
127
import selectors
Guido van Rossum's avatar
Guido van Rossum committed
128
import os
129
import sys
130
import threading
131
from io import BufferedIOBase
132
from time import monotonic as time
Guido van Rossum's avatar
Guido van Rossum committed
133

134 135
__all__ = ["BaseServer", "TCPServer", "UDPServer",
           "ThreadingUDPServer", "ThreadingTCPServer",
136
           "BaseRequestHandler", "StreamRequestHandler",
137 138 139
           "DatagramRequestHandler", "ThreadingMixIn"]
if hasattr(os, "fork"):
    __all__.extend(["ForkingUDPServer","ForkingTCPServer", "ForkingMixIn"])
140 141 142 143
if hasattr(socket, "AF_UNIX"):
    __all__.extend(["UnixStreamServer","UnixDatagramServer",
                    "ThreadingUnixStreamServer",
                    "ThreadingUnixDatagramServer"])
Guido van Rossum's avatar
Guido van Rossum committed
144

145 146 147 148 149 150 151
# poll/select have the advantage of not requiring any extra file descriptor,
# contrarily to epoll/kqueue (also, they require a single syscall).
if hasattr(selectors, 'PollSelector'):
    _ServerSelector = selectors.PollSelector
else:
    _ServerSelector = selectors.SelectSelector

152

153
class BaseServer:
Guido van Rossum's avatar
Guido van Rossum committed
154

155
    """Base class for server classes.
Guido van Rossum's avatar
Guido van Rossum committed
156 157 158 159

    Methods for the caller:

    - __init__(server_address, RequestHandlerClass)
Christian Heimes's avatar
Christian Heimes committed
160 161
    - serve_forever(poll_interval=0.5)
    - shutdown()
162
    - handle_request()  # if you do not use serve_forever()
163
    - fileno() -> int   # for selector
Guido van Rossum's avatar
Guido van Rossum committed
164 165 166 167 168 169

    Methods that may be overridden:

    - server_bind()
    - server_activate()
    - get_request() -> request, client_address
170
    - handle_timeout()
Guido van Rossum's avatar
Guido van Rossum committed
171
    - verify_request(request, client_address)
172
    - server_close()
Guido van Rossum's avatar
Guido van Rossum committed
173
    - process_request(request, client_address)
174
    - shutdown_request(request)
175
    - close_request(request)
176
    - service_actions()
Guido van Rossum's avatar
Guido van Rossum committed
177 178 179 180 181 182 183 184 185
    - handle_error()

    Methods for derived classes:

    - finish_request(request, client_address)

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

186
    - timeout
Guido van Rossum's avatar
Guido van Rossum committed
187 188
    - address_family
    - socket_type
189
    - allow_reuse_address
Guido van Rossum's avatar
Guido van Rossum committed
190 191 192 193 194 195 196 197

    Instance variables:

    - RequestHandlerClass
    - socket

    """

198 199
    timeout = None

Guido van Rossum's avatar
Guido van Rossum committed
200
    def __init__(self, server_address, RequestHandlerClass):
201 202 203
        """Constructor.  May be extended, do not override."""
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
Christian Heimes's avatar
Christian Heimes committed
204
        self.__is_shut_down = threading.Event()
205
        self.__shutdown_request = False
Guido van Rossum's avatar
Guido van Rossum committed
206 207

    def server_activate(self):
208
        """Called by constructor to activate the server.
Guido van Rossum's avatar
Guido van Rossum committed
209

210
        May be overridden.
Guido van Rossum's avatar
Guido van Rossum committed
211

212
        """
213
        pass
Guido van Rossum's avatar
Guido van Rossum committed
214

Christian Heimes's avatar
Christian Heimes committed
215 216 217 218 219 220 221 222
    def serve_forever(self, poll_interval=0.5):
        """Handle one request at a time until shutdown.

        Polls for shutdown every poll_interval seconds. Ignores
        self.timeout. If you need to do periodic tasks, do them in
        another thread.
        """
        self.__is_shut_down.clear()
223
        try:
224 225 226 227 228 229 230 231 232 233 234 235 236
            # XXX: Consider using another file descriptor or connecting to the
            # socket to wake this up instead of polling. Polling reduces our
            # responsiveness to a shutdown request and wastes cpu at all other
            # times.
            with _ServerSelector() as selector:
                selector.register(self, selectors.EVENT_READ)

                while not self.__shutdown_request:
                    ready = selector.select(poll_interval)
                    if ready:
                        self._handle_request_noblock()

                    self.service_actions()
237 238 239
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()
Christian Heimes's avatar
Christian Heimes committed
240 241 242 243 244 245 246 247

    def shutdown(self):
        """Stops the serve_forever loop.

        Blocks until the loop has finished. This must be called while
        serve_forever() is running in another thread, or it will
        deadlock.
        """
248
        self.__shutdown_request = True
Christian Heimes's avatar
Christian Heimes committed
249
        self.__is_shut_down.wait()
Guido van Rossum's avatar
Guido van Rossum committed
250

251 252 253 254 255 256 257 258
    def service_actions(self):
        """Called by the serve_forever() loop.

        May be overridden by a subclass / Mixin to implement any code that
        needs to be run during the loop.
        """
        pass

259 260
    # The distinction between handling, getting, processing and finishing a
    # request is fairly arbitrary.  Remember:
Guido van Rossum's avatar
Guido van Rossum committed
261
    #
262 263
    # - handle_request() is the top-level call.  It calls selector.select(),
    #   get_request(), verify_request() and process_request()
Christian Heimes's avatar
Christian Heimes committed
264
    # - get_request() is different for stream or datagram sockets
265 266 267 268
    # - process_request() is the place that may fork a new process or create a
    #   new thread to finish the request
    # - finish_request() instantiates the request handler class; this
    #   constructor will handle the request all by itself
Guido van Rossum's avatar
Guido van Rossum committed
269 270

    def handle_request(self):
Christian Heimes's avatar
Christian Heimes committed
271 272 273 274 275 276 277 278 279 280 281
        """Handle one request, possibly blocking.

        Respects self.timeout.
        """
        # Support people who used socket.settimeout() to escape
        # handle_request before self.timeout was available.
        timeout = self.socket.gettimeout()
        if timeout is None:
            timeout = self.timeout
        elif self.timeout is not None:
            timeout = min(timeout, self.timeout)
282 283 284 285
        if timeout is not None:
            deadline = time() + timeout

        # Wait until a request arrives or the timeout expires - the loop is
286
        # necessary to accommodate early wakeups due to EINTR.
287 288 289 290 291 292 293 294 295 296 297 298
        with _ServerSelector() as selector:
            selector.register(self, selectors.EVENT_READ)

            while True:
                ready = selector.select(timeout)
                if ready:
                    return self._handle_request_noblock()
                else:
                    if timeout is not None:
                        timeout = deadline - time()
                        if timeout < 0:
                            return self.handle_timeout()
Christian Heimes's avatar
Christian Heimes committed
299 300 301 302

    def _handle_request_noblock(self):
        """Handle one request, without blocking.

303 304 305
        I assume that selector.select() has returned that the socket is
        readable before this function was called, so there should be no risk of
        blocking in get_request().
Christian Heimes's avatar
Christian Heimes committed
306
        """
307
        try:
Christian Heimes's avatar
Christian Heimes committed
308
            request, client_address = self.get_request()
309
        except OSError:
310
            return
311 312 313
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)
314
            except Exception:
315
                self.handle_error(request, client_address)
316
                self.shutdown_request(request)
317 318 319
            except:
                self.shutdown_request(request)
                raise
320 321
        else:
            self.shutdown_request(request)
Guido van Rossum's avatar
Guido van Rossum committed
322

323 324 325 326 327 328 329
    def handle_timeout(self):
        """Called if no new request arrives within self.timeout.

        Overridden by ForkingMixIn.
        """
        pass

Guido van Rossum's avatar
Guido van Rossum committed
330
    def verify_request(self, request, client_address):
331
        """Verify the request.  May be overridden.
Guido van Rossum's avatar
Guido van Rossum committed
332

333
        Return True if we should proceed with this request.
Guido van Rossum's avatar
Guido van Rossum committed
334

335
        """
336
        return True
Guido van Rossum's avatar
Guido van Rossum committed
337 338

    def process_request(self, request, client_address):
339
        """Call finish_request.
Guido van Rossum's avatar
Guido van Rossum committed
340

341
        Overridden by ForkingMixIn and ThreadingMixIn.
Guido van Rossum's avatar
Guido van Rossum committed
342

343 344
        """
        self.finish_request(request, client_address)
345
        self.shutdown_request(request)
Guido van Rossum's avatar
Guido van Rossum committed
346

347 348 349 350 351 352 353 354
    def server_close(self):
        """Called to clean-up the server.

        May be overridden.

        """
        pass

Guido van Rossum's avatar
Guido van Rossum committed
355
    def finish_request(self, request, client_address):
356 357
        """Finish one request by instantiating RequestHandlerClass."""
        self.RequestHandlerClass(request, client_address, self)
Guido van Rossum's avatar
Guido van Rossum committed
358

359 360 361 362
    def shutdown_request(self, request):
        """Called to shutdown and close an individual request."""
        self.close_request(request)

363 364 365 366
    def close_request(self, request):
        """Called to clean up an individual request."""
        pass

Guido van Rossum's avatar
Guido van Rossum committed
367
    def handle_error(self, request, client_address):
368
        """Handle an error gracefully.  May be overridden.
Guido van Rossum's avatar
Guido van Rossum committed
369

370
        The default is to print a traceback and continue.
Guido van Rossum's avatar
Guido van Rossum committed
371

372
        """
373 374 375
        print('-'*40, file=sys.stderr)
        print('Exception happened during processing of request from',
            client_address, file=sys.stderr)
376
        import traceback
377 378
        traceback.print_exc()
        print('-'*40, file=sys.stderr)
Guido van Rossum's avatar
Guido van Rossum committed
379

380 381 382 383 384 385
    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.server_close()

Guido van Rossum's avatar
Guido van Rossum committed
386

387 388 389 390 391 392 393 394
class TCPServer(BaseServer):

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

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

    Methods for the caller:

395
    - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
Christian Heimes's avatar
Christian Heimes committed
396 397
    - serve_forever(poll_interval=0.5)
    - shutdown()
398
    - handle_request()  # if you don't use serve_forever()
399
    - fileno() -> int   # for selector
400 401 402 403 404 405

    Methods that may be overridden:

    - server_bind()
    - server_activate()
    - get_request() -> request, client_address
406
    - handle_timeout()
407 408
    - verify_request(request, client_address)
    - process_request(request, client_address)
409
    - shutdown_request(request)
410
    - close_request(request)
411 412 413 414 415 416 417 418 419
    - handle_error()

    Methods for derived classes:

    - finish_request(request, client_address)

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

420
    - timeout
421 422 423
    - address_family
    - socket_type
    - request_queue_size (only for stream sockets)
424
    - allow_reuse_address
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439

    Instance variables:

    - server_address
    - RequestHandlerClass
    - socket

    """

    address_family = socket.AF_INET

    socket_type = socket.SOCK_STREAM

    request_queue_size = 5

440
    allow_reuse_address = False
441

442
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
443 444 445 446
        """Constructor.  May be extended, do not override."""
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
447
        if bind_and_activate:
448 449 450 451 452 453
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise
454 455 456 457 458 459 460 461 462 463

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

        May be overridden.

        """
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
464
        self.server_address = self.socket.getsockname()
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484

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

        May be overridden.

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

    def server_close(self):
        """Called to clean-up the server.

        May be overridden.

        """
        self.socket.close()

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

485
        Interface required by selector.
486 487 488 489 490 491 492 493 494 495 496 497

        """
        return self.socket.fileno()

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

        May be overridden.

        """
        return self.socket.accept()

498 499
    def shutdown_request(self, request):
        """Called to shutdown and close an individual request."""
500 501 502 503
        try:
            #explicitly shutdown.  socket.close() merely releases
            #the socket and waits for GC to perform the actual close.
            request.shutdown(socket.SHUT_WR)
504
        except OSError:
505
            pass #some platforms may raise ENOTCONN here
506 507 508 509
        self.close_request(request)

    def close_request(self, request):
        """Called to clean up an individual request."""
510 511
        request.close()

512

Guido van Rossum's avatar
Guido van Rossum committed
513 514 515 516
class UDPServer(TCPServer):

    """UDP server class."""

517
    allow_reuse_address = False
518

Guido van Rossum's avatar
Guido van Rossum committed
519 520 521 522 523
    socket_type = socket.SOCK_DGRAM

    max_packet_size = 8192

    def get_request(self):
524 525 526 527 528 529
        data, client_addr = self.socket.recvfrom(self.max_packet_size)
        return (data, self.socket), client_addr

    def server_activate(self):
        # No need to call listen() for UDP.
        pass
Guido van Rossum's avatar
Guido van Rossum committed
530

531 532 533 534
    def shutdown_request(self, request):
        # No need to shutdown anything.
        self.close_request(request)

535 536 537
    def close_request(self, request):
        # No need to close anything.
        pass
Guido van Rossum's avatar
Guido van Rossum committed
538

539
if hasattr(os, "fork"):
540 541
    class ForkingMixIn:
        """Mix-in class to handle each request in a new process."""
Guido van Rossum's avatar
Guido van Rossum committed
542

543 544 545
        timeout = 300
        active_children = None
        max_children = 40
546 547
        # If true, server_close() waits until all child processes complete.
        block_on_close = True
Guido van Rossum's avatar
Guido van Rossum committed
548

549
        def collect_children(self, *, blocking=False):
550
            """Internal routine to wait for children that have exited."""
551
            if self.active_children is None:
552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
                return

            # If we're above the max number of children, wait and reap them until
            # we go back below threshold. Note that we use waitpid(-1) below to be
            # able to collect children in size(<defunct children>) syscalls instead
            # of size(<children>): the downside is that this might reap children
            # which we didn't spawn, which is why we only resort to this when we're
            # above max_children.
            while len(self.active_children) >= self.max_children:
                try:
                    pid, _ = os.waitpid(-1, 0)
                    self.active_children.discard(pid)
                except ChildProcessError:
                    # we don't have any children, we're done
                    self.active_children.clear()
                except OSError:
                    break

            # Now reap all defunct children.
            for pid in self.active_children.copy():
                try:
573 574
                    flags = 0 if blocking else os.WNOHANG
                    pid, _ = os.waitpid(pid, flags)
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611
                    # if the child hasn't exited yet, pid will be 0 and ignored by
                    # discard() below
                    self.active_children.discard(pid)
                except ChildProcessError:
                    # someone else reaped it
                    self.active_children.discard(pid)
                except OSError:
                    pass

        def handle_timeout(self):
            """Wait for zombies after self.timeout seconds of inactivity.

            May be extended, do not override.
            """
            self.collect_children()

        def service_actions(self):
            """Collect the zombie child processes regularly in the ForkingMixIn.

            service_actions is called in the BaseServer's serve_forver loop.
            """
            self.collect_children()

        def process_request(self, request, client_address):
            """Fork a new subprocess to process the request."""
            pid = os.fork()
            if pid:
                # Parent process
                if self.active_children is None:
                    self.active_children = set()
                self.active_children.add(pid)
                self.close_request(request)
                return
            else:
                # Child process.
                # This must never return, hence os._exit()!
                status = 1
612
                try:
613 614 615 616
                    self.finish_request(request, client_address)
                    status = 0
                except Exception:
                    self.handle_error(request, client_address)
617
                finally:
618 619 620 621
                    try:
                        self.shutdown_request(request)
                    finally:
                        os._exit(status)
Guido van Rossum's avatar
Guido van Rossum committed
622

623 624
        def server_close(self):
            super().server_close()
625
            self.collect_children(blocking=self.block_on_close)
626

Guido van Rossum's avatar
Guido van Rossum committed
627 628 629 630

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

631 632
    # Decides how threads will act upon termination of the
    # main process
Fred Drake's avatar
Fred Drake committed
633
    daemon_threads = False
634 635
    # If true, server_close() waits until all non-daemonic threads terminate.
    block_on_close = True
636 637 638
    # For non-daemonic threads, list of threading.Threading objects
    # used by server_close() to wait for all threads completion.
    _threads = None
639

640
    def process_request_thread(self, request, client_address):
641 642 643 644 645 646 647
        """Same as in BaseServer but as a thread.

        In addition, exception handling is done here.

        """
        try:
            self.finish_request(request, client_address)
648
        except Exception:
649
            self.handle_error(request, client_address)
650
        finally:
651
            self.shutdown_request(request)
652

Guido van Rossum's avatar
Guido van Rossum committed
653
    def process_request(self, request, client_address):
654
        """Start a new thread to process the request."""
655
        t = threading.Thread(target = self.process_request_thread,
656
                             args = (request, client_address))
657
        t.daemon = self.daemon_threads
658
        if not t.daemon and self.block_on_close:
659 660 661
            if self._threads is None:
                self._threads = []
            self._threads.append(t)
662
        t.start()
Guido van Rossum's avatar
Guido van Rossum committed
663

664 665
    def server_close(self):
        super().server_close()
666 667 668 669 670 671
        if self.block_on_close:
            threads = self._threads
            self._threads = None
            if threads:
                for thread in threads:
                    thread.join()
672

Guido van Rossum's avatar
Guido van Rossum committed
673

674 675 676
if hasattr(os, "fork"):
    class ForkingUDPServer(ForkingMixIn, UDPServer): pass
    class ForkingTCPServer(ForkingMixIn, TCPServer): pass
Guido van Rossum's avatar
Guido van Rossum committed
677 678 679 680

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

681 682 683 684 685 686 687 688 689 690 691
if hasattr(socket, 'AF_UNIX'):

    class UnixStreamServer(TCPServer):
        address_family = socket.AF_UNIX

    class UnixDatagramServer(UDPServer):
        address_family = socket.AF_UNIX

    class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass

    class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): pass
Guido van Rossum's avatar
Guido van Rossum committed
692 693 694 695 696 697 698 699 700 701 702 703

class BaseRequestHandler:

    """Base class for request handler classes.

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

    The handle() method can find the request as self.request, the
704
    client address as self.client_address, and the server (in case it
Guido van Rossum's avatar
Guido van Rossum committed
705 706
    needs access to per-server information) as self.server.  Since a
    separate instance is created for each request, the handle() method
707
    can define other arbitrary instance variables.
Guido van Rossum's avatar
Guido van Rossum committed
708 709 710 711

    """

    def __init__(self, request, client_address, server):
712 713 714
        self.request = request
        self.client_address = client_address
        self.server = server
715
        self.setup()
716 717 718 719
        try:
            self.handle()
        finally:
            self.finish()
Guido van Rossum's avatar
Guido van Rossum committed
720 721

    def setup(self):
722
        pass
Guido van Rossum's avatar
Guido van Rossum committed
723 724

    def handle(self):
725
        pass
Guido van Rossum's avatar
Guido van Rossum committed
726 727

    def finish(self):
728
        pass
Guido van Rossum's avatar
Guido van Rossum committed
729 730 731 732 733 734 735 736 737 738 739 740 741 742


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


class StreamRequestHandler(BaseRequestHandler):

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

743 744 745 746 747 748 749 750 751 752
    # Default buffer sizes for rfile, wfile.
    # We default rfile to buffered because otherwise it could be
    # really slow for large data (a getc() call per byte); we make
    # wfile unbuffered because (a) often after a write() we want to
    # read and we need to flush the line; (b) big writes to unbuffered
    # files are typically optimized by stdio even when big reads
    # aren't.
    rbufsize = -1
    wbufsize = 0

753 754 755
    # A timeout to apply to the request socket, if not None.
    timeout = None

Ezio Melotti's avatar
Ezio Melotti committed
756
    # Disable nagle algorithm for this socket, if True.
757 758 759
    # Use only when wbufsize != 0, to avoid small packets.
    disable_nagle_algorithm = False

Guido van Rossum's avatar
Guido van Rossum committed
760
    def setup(self):
761
        self.connection = self.request
762 763
        if self.timeout is not None:
            self.connection.settimeout(self.timeout)
764 765 766
        if self.disable_nagle_algorithm:
            self.connection.setsockopt(socket.IPPROTO_TCP,
                                       socket.TCP_NODELAY, True)
767
        self.rfile = self.connection.makefile('rb', self.rbufsize)
768 769 770 771
        if self.wbufsize == 0:
            self.wfile = _SocketWriter(self.connection)
        else:
            self.wfile = self.connection.makefile('wb', self.wbufsize)
Guido van Rossum's avatar
Guido van Rossum committed
772 773

    def finish(self):
774
        if not self.wfile.closed:
775 776 777
            try:
                self.wfile.flush()
            except socket.error:
778
                # A final socket error may have occurred here, such as
779 780
                # the local error ECONNABORTED.
                pass
781 782
        self.wfile.close()
        self.rfile.close()
Guido van Rossum's avatar
Guido van Rossum committed
783

784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
class _SocketWriter(BufferedIOBase):
    """Simple writable BufferedIOBase implementation for a socket

    Does not hold data in a buffer, avoiding any need to call flush()."""

    def __init__(self, sock):
        self._sock = sock

    def writable(self):
        return True

    def write(self, b):
        self._sock.sendall(b)
        with memoryview(b) as view:
            return view.nbytes

    def fileno(self):
        return self._sock.fileno()
Guido van Rossum's avatar
Guido van Rossum committed
802 803 804 805 806 807

class DatagramRequestHandler(BaseRequestHandler):

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

    def setup(self):
808
        from io import BytesIO
809
        self.packet, self.socket = self.request
810 811
        self.rfile = BytesIO(self.packet)
        self.wfile = BytesIO()
Guido van Rossum's avatar
Guido van Rossum committed
812 813

    def finish(self):
814
        self.socket.sendto(self.wfile.getvalue(), self.client_address)