WebSocket server returned by :func:`serve`. This class mirrors the API of :class:`~asyncio.Server`. It keeps track of WebSocket connections in order to close them properly when shutting down. Args: logger: Logger for this server. It defaults to ``logging.g
| 647 | |
| 648 | |
| 649 | class WebSocketServer: |
| 650 | """ |
| 651 | WebSocket server returned by :func:`serve`. |
| 652 | |
| 653 | This class mirrors the API of :class:`~asyncio.Server`. |
| 654 | |
| 655 | It keeps track of WebSocket connections in order to close them properly |
| 656 | when shutting down. |
| 657 | |
| 658 | Args: |
| 659 | logger: Logger for this server. |
| 660 | It defaults to ``logging.getLogger("websockets.server")``. |
| 661 | See the :doc:`logging guide <../../topics/logging>` for details. |
| 662 | |
| 663 | """ |
| 664 | |
| 665 | def __init__(self, logger: LoggerLike | None = None) -> None: |
| 666 | if logger is None: |
| 667 | logger = logging.getLogger("websockets.server") |
| 668 | self.logger = logger |
| 669 | |
| 670 | # Keep track of active connections. |
| 671 | self.websockets: set[WebSocketServerProtocol] = set() |
| 672 | |
| 673 | # Task responsible for closing the server and terminating connections. |
| 674 | self.close_task: asyncio.Task[None] | None = None |
| 675 | |
| 676 | # Completed when the server is closed and connections are terminated. |
| 677 | self.closed_waiter: asyncio.Future[None] |
| 678 | |
| 679 | def wrap(self, server: asyncio.base_events.Server) -> None: |
| 680 | """ |
| 681 | Attach to a given :class:`~asyncio.Server`. |
| 682 | |
| 683 | Since :meth:`~asyncio.loop.create_server` doesn't support injecting a |
| 684 | custom ``Server`` class, the easiest solution that doesn't rely on |
| 685 | private :mod:`asyncio` APIs is to: |
| 686 | |
| 687 | - instantiate a :class:`WebSocketServer` |
| 688 | - give the protocol factory a reference to that instance |
| 689 | - call :meth:`~asyncio.loop.create_server` with the factory |
| 690 | - attach the resulting :class:`~asyncio.Server` with this method |
| 691 | |
| 692 | """ |
| 693 | self.server = server |
| 694 | for sock in server.sockets: |
| 695 | if sock.family == socket.AF_INET: |
| 696 | name = "%s:%d" % sock.getsockname() |
| 697 | elif sock.family == socket.AF_INET6: |
| 698 | name = "[%s]:%d" % sock.getsockname()[:2] |
| 699 | elif sock.family == socket.AF_UNIX: |
| 700 | name = sock.getsockname() |
| 701 | # In the unlikely event that someone runs websockets over a |
| 702 | # protocol other than IP or Unix sockets, avoid crashing. |
| 703 | else: # pragma: no cover |
| 704 | name = str(sock.getsockname()) |
| 705 | self.logger.info("server listening on %s", name) |
| 706 |
no outgoing calls
no test coverage detected
searching dependent graphs…