async def connect_to_daemon(self, self_hostname: str, daemon_port: uint16): while True: session = None try: if self.shut_down: break session = aiohttp.ClientSession() cert_path, key_path = load_ssl_paths(self.root_path, self.net_config) ssl_context = ssl_context_for_server(cert_path, key_path, require_cert=True) async with session.ws_connect( f"wss://{self_hostname}:{daemon_port}", autoclose=False, autoping=True, ssl_context=ssl_context, max_msg_size=50 * 1024 * 1024, ) as ws: self.websocket = ws await self.connection(ws) self.websocket = None await session.close() except aiohttp.client_exceptions.ClientConnectorError: self.log.warning(f"Cannot connect to daemon at ws://{self_hostname}:{daemon_port}") except Exception as e: tb = traceback.format_exc() self.log.warning(f"Exception: {tb} {type(e)}") finally: if session is not None: await session.close() await asyncio.sleep(2)
async def start_rpc_server( rpc_api: Any, self_hostname: str, daemon_port: uint16, rpc_port: uint16, stop_cb: Callable, root_path: Path, net_config, connect_to_daemon=True, ): """ Starts an HTTP server with the following RPC methods, to be used by local clients to query the node. """ app = aiohttp.web.Application() cert_path, key_path = load_ssl_paths(root_path, net_config) ssl_context = ssl_context_for_server(cert_path, key_path, require_cert=True) rpc_server = RpcServer(rpc_api, rpc_api.service_name, stop_cb, root_path, net_config) rpc_server.rpc_api.service._set_state_changed_callback(rpc_server.state_changed) http_routes: Dict[str, Callable] = rpc_api.get_routes() routes = [aiohttp.web.post(route, rpc_server._wrap_http_handler(func)) for (route, func) in http_routes.items()] routes += [ aiohttp.web.post( "/get_connections", rpc_server._wrap_http_handler(rpc_server.get_connections), ), aiohttp.web.post( "/open_connection", rpc_server._wrap_http_handler(rpc_server.open_connection), ), aiohttp.web.post( "/close_connection", rpc_server._wrap_http_handler(rpc_server.close_connection), ), aiohttp.web.post("/stop_node", rpc_server._wrap_http_handler(rpc_server.stop_node)), ] app.add_routes(routes) if connect_to_daemon: daemon_connection = asyncio.create_task(rpc_server.connect_to_daemon(self_hostname, daemon_port)) runner = aiohttp.web.AppRunner(app, access_log=None) await runner.setup() site = aiohttp.web.TCPSite(runner, self_hostname, int(rpc_port), ssl_context=ssl_context) await site.start() async def cleanup(): await rpc_server.stop() await runner.cleanup() if connect_to_daemon: await daemon_connection return cleanup
def __init__(self, rpc_api: Any, service_name: str, stop_cb: Callable, root_path, net_config): self.rpc_api = rpc_api self.stop_cb: Callable = stop_cb self.log = log self.shut_down = False self.websocket: Optional[aiohttp.ClientWebSocketResponse] = None self.service_name = service_name self.root_path = root_path self.net_config = net_config self.crt_path = root_path / net_config["daemon_ssl"]["private_crt"] self.key_path = root_path / net_config["daemon_ssl"]["private_key"] self.ca_cert_path = root_path / net_config["private_ssl_ca"]["crt"] self.ca_key_path = root_path / net_config["private_ssl_ca"]["key"] self.ssl_context = ssl_context_for_server(self.ca_cert_path, self.ca_key_path, self.crt_path, self.key_path)
def __init__(self, root_path: Path, ca_crt_path: Path, ca_key_path: Path, crt_path: Path, key_path: Path): self.root_path = root_path self.log = log self.services: Dict = dict() self.plots_queue: List[Dict] = [] self.connections: Dict[str, List[WebSocketServerProtocol]] = dict() # service_name : [WebSocket] self.remote_address_map: Dict[WebSocketServerProtocol, str] = dict() # socket: service_name self.ping_job: Optional[asyncio.Task] = None self.net_config = load_config(root_path, "config.yaml") self.self_hostname = self.net_config["self_hostname"] self.daemon_port = self.net_config["daemon_port"] self.websocket_server = None self.ssl_context = ssl_context_for_server(ca_crt_path, ca_key_path, crt_path, key_path) self.shut_down = False
def __init__(self, root_path): self.root_path = root_path self.log = log self.services: Dict = dict() self.plots_queue: List[Dict] = [] self.connections: Dict[ str, List[Any]] = dict() # service_name : [WebSocket] self.remote_address_map: Dict[Any, str] = dict() # socket: service_name self.ping_job = None self.net_config = load_config(root_path, "config.yaml") self.self_hostname = self.net_config["self_hostname"] self.daemon_port = self.net_config["daemon_port"] self.websocket_server = None cert_path, key_path = load_ssl_paths(root_path, self.net_config) self.ssl_context = ssl_context_for_server(cert_path, key_path, require_cert=True)
async def test_daemon_simulation(self, simulation, get_daemon): node1, node2, _, _, _, _, _, _, _, server1 = simulation await server1.start_client(PeerInfo(self_hostname, uint16(21238))) async def num_connections(): count = len( node2.server.connection_by_type[NodeType.FULL_NODE].items()) return count await time_out_assert_custom_interval(60, 1, num_connections, 1) await time_out_assert(1500, node_height_at_least, True, node2, 1) session = aiohttp.ClientSession() crt_path = b_tools.root_path / b_tools.config["daemon_ssl"][ "private_crt"] key_path = b_tools.root_path / b_tools.config["daemon_ssl"][ "private_key"] ca_cert_path = b_tools.root_path / b_tools.config["private_ssl_ca"][ "crt"] ca_key_path = b_tools.root_path / b_tools.config["private_ssl_ca"][ "key"] ssl_context = ssl_context_for_server(ca_cert_path, ca_key_path, crt_path, key_path) ws = await session.ws_connect( "wss://127.0.0.1:55401", autoclose=True, autoping=True, heartbeat=60, ssl_context=ssl_context, max_msg_size=100 * 1024 * 1024, ) service_name = "test_service_name" data = {"service": service_name} payload = create_payload("register_service", data, service_name, "daemon") await ws.send_str(payload) message_queue = asyncio.Queue() async def reader(ws, queue): while True: msg = await ws.receive() if msg.type == aiohttp.WSMsgType.TEXT: message = msg.data.strip() message = json.loads(message) await queue.put(message) elif msg.type == aiohttp.WSMsgType.PING: await ws.pong() elif msg.type == aiohttp.WSMsgType.PONG: continue else: if msg.type == aiohttp.WSMsgType.CLOSE: await ws.close() elif msg.type == aiohttp.WSMsgType.ERROR: await ws.close() elif msg.type == aiohttp.WSMsgType.CLOSED: pass break read_handler = asyncio.create_task(reader(ws, message_queue)) data = {} payload = create_payload("get_blockchain_state", data, service_name, "chia_full_node") await ws.send_str(payload) await asyncio.sleep(5) blockchain_state_found = False while not message_queue.empty(): message = await message_queue.get() if message["command"] == "get_blockchain_state": blockchain_state_found = True await ws.close() read_handler.cancel() assert blockchain_state_found