get_info

If you run Alice now, you'll see the following output:

[DEBUG] jsonrpc-server: Trying to bind listener on tcp://127.0.0.1:55054

That indicates that our JSON-RPC server is up and running. However, there's currently no client for us to connect to. That's where dnetview comes in. dnetview implements a JSON-RPC client that calls a single method: get_info().

To use it, let's return to our JsonRpcInterface and add the following method:

#![allow(unused)]
fn main() {
    // RPCAPI:
    // Retrieves P2P network information.
    // --> {"jsonrpc": "2.0", "method": "get_info", "params": [], "id": 42}
    // <-- {"jsonrpc": "2.0", result": {"nodeID": [], "nodeinfo": [], "id": 42}
    async fn get_info(&self, id: Value, _params: Value) -> JsonResult {
        let resp = self.p2p.get_info().await;
        JsonResponse::new(resp, id).into()
    }
}

And add it to handle_request():

#![allow(unused)]
fn main() {
    async fn handle_request(&self, req: JsonRequest) -> JsonResult {
        //...
        match req.method.as_str() {
            Some("ping") => self.pong(req.id, req.params).await,
            Some("get_info") => self.get_info(req.id, req.params).await,
            Some(_) | None => JsonError::new(ErrorCode::MethodNotFound, None, req.id).into(),
        }
    }
}
}

This calls the p2p function get_info() and passes the returned data into a JsonResponse.

Under the hood, this function triggers a hierarchy of get_info() calls which deliver info specific to a node, its inbound or outbound Session's, and the Channel's those Session's run.

Here's what happens:

#![allow(unused)]
fn main() {
        *self_.session_outbound.lock().await = Some(OutboundSession::new(parent));

        register_default_protocols(self_.clone()).await;

        self_
    }

    pub async fn get_info(&self) -> serde_json::Value {
        // Building ext_addr_vec string
        let mut ext_addr_vec = vec![];
        for ext_addr in &self.settings.external_addr {
            ext_addr_vec.push(ext_addr.as_ref().to_string());
        }

        json!({
            "external_addr": format!("{:?}", ext_addr_vec),
}

Here we return two pieces of info that are unique to a node: external_addr and state. We couple that data with SessionInfo by calling get_info() on each Session.

Session::get_info() returns data related to a Session (for example, an Inbound accept_addr in the case of an inbound Session). Session::get_info() then calls the function Channel::get_info() which returns data specific to a Channel. This happens via a child struct called ChannelInfo.

This is ChannelInfo::get_info().

#![allow(unused)]
fn main() {
            last_status: String::new(),
            log,
        }
    }

    async fn get_info(&self) -> serde_json::Value {
        let log = match &self.log {
            Some(l) => {
                let mut lock = l.lock().await;
                let ret = lock.clone();
                *lock = Vec::new();
}

dnetview uses the info returned from Channel and Session and node-specific info like external_addr to display an overview of the p2p network.