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
示例#3
0
 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)
示例#4
0
 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)
示例#6
0
    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