Loading poolpay/wire/Server.py 0 → 100644 +65 −0 Original line number Diff line number Diff line from __future__ import annotations import json from collections.abc import Callable from dataclasses import dataclass, field from pathlib import Path from socketserver import BaseServer, StreamRequestHandler, ThreadingUnixStreamServer from poolpay.wire.Message import Message # Maps Python's BaseServer instances to our Server instances, because apparently that's the only way a request handler # can access its surroundings _servers: dict[BaseServer, Server] = {} @dataclass class Server: socket_path: Path _server: BaseServer = field(init=False) _handlers: list[Callable[[Message], None]] = field(default_factory=list, init=False) class RequestHandler(StreamRequestHandler): def handle(self) -> None: # TODO What to do if line is longer than 1024 bytes? json_str = self.rfile.readline(1024).strip().decode("utf-8") data = json.loads(json_str) response = {"status": "received"} self.wfile.write((json.dumps(response) + "\n").encode("utf-8")) for handler in _servers[self.server]._handlers: handler(data) def __post_init__(self) -> None: self._server = ThreadingUnixStreamServer( str(self.socket_path.resolve()), Server.RequestHandler, bind_and_activate=False, ) _servers[self._server] = self def broadcast(self, message: Message) -> None: """ Brodcast the message to all connected clients (might be none) """ raise NotImplementedError() # TODO def on_receive(self, handle_message: Callable[[Message], None]) -> None: """ Register a handler that is called whenever this server receives a message from any of its clients. """ self._handlers.append(handle_message) def start(self) -> None: """ Start serving. This method is blocking, i.e. does not return. """ self._server.server_bind() self._server.server_activate() self._server.serve_forever() def stop(self) -> None: self._server.shutdown() self._server.server_close() self.socket_path.unlink() Loading
poolpay/wire/Server.py 0 → 100644 +65 −0 Original line number Diff line number Diff line from __future__ import annotations import json from collections.abc import Callable from dataclasses import dataclass, field from pathlib import Path from socketserver import BaseServer, StreamRequestHandler, ThreadingUnixStreamServer from poolpay.wire.Message import Message # Maps Python's BaseServer instances to our Server instances, because apparently that's the only way a request handler # can access its surroundings _servers: dict[BaseServer, Server] = {} @dataclass class Server: socket_path: Path _server: BaseServer = field(init=False) _handlers: list[Callable[[Message], None]] = field(default_factory=list, init=False) class RequestHandler(StreamRequestHandler): def handle(self) -> None: # TODO What to do if line is longer than 1024 bytes? json_str = self.rfile.readline(1024).strip().decode("utf-8") data = json.loads(json_str) response = {"status": "received"} self.wfile.write((json.dumps(response) + "\n").encode("utf-8")) for handler in _servers[self.server]._handlers: handler(data) def __post_init__(self) -> None: self._server = ThreadingUnixStreamServer( str(self.socket_path.resolve()), Server.RequestHandler, bind_and_activate=False, ) _servers[self._server] = self def broadcast(self, message: Message) -> None: """ Brodcast the message to all connected clients (might be none) """ raise NotImplementedError() # TODO def on_receive(self, handle_message: Callable[[Message], None]) -> None: """ Register a handler that is called whenever this server receives a message from any of its clients. """ self._handlers.append(handle_message) def start(self) -> None: """ Start serving. This method is blocking, i.e. does not return. """ self._server.server_bind() self._server.server_activate() self._server.serve_forever() def stop(self) -> None: self._server.shutdown() self._server.server_close() self.socket_path.unlink()