RPC server

To deploy the JsonRpcInterface, we'll need to create an RPC server using listen_and_serve(). listen_and_serve() is a method defined in DarkFi's rpc module. It starts a JSON-RPC server that is bound to the provided accept URL and uses our previously implemented RequestHandler to handle incoming requests.

Add the following lines to main():

    let accept_addr = settings.accept_addr.clone();
    let rpc = Arc::new(JsonRpcInterface { addr: accept_addr.clone(), p2p });
    let _ex = ex.clone();
    ex.spawn(async move { listen_and_serve(accept_addr.clone(), rpc, _ex).await }).detach();

We create a new JsonRpcInterface inside an Arc pointer and pass in our accept_addr and p2p object.

Next, we create an async block that calls listen_and_serve(). The async block uses the move keyword to takes ownership of the accept_addr and JsonRpcInterface values and pass them into listen_and_serve(). We use an executor to spawn listen_and_serve() as a new thread and detach it in the background.

We have enabled JSON-RPC.

Here's what our complete main() function looks like:

#[async_std::main]
async fn main() -> Result<()> {
    let settings: Result<AppSettings> = match std::env::args().nth(1) {
        Some(id) => match id.as_str() {
            "a" => alice(),
            "b" => bob(),
            _ => Err(ErrorMissingSpecifier.into()),
        },
        None => Err(ErrorMissingSpecifier.into()),
    };

    let settings = settings?.clone();

    let p2p = net::P2p::new(settings.net).await;

    let ex = Arc::new(Executor::new());
    let ex2 = ex.clone();
    let ex3 = ex2.clone();

    let msgs: DchatMsgsBuffer = Arc::new(Mutex::new(vec![DchatMsg { msg: String::new() }]));

    let mut dchat = Dchat::new(p2p.clone(), msgs);

    let accept_addr = settings.accept_addr.clone();
    let rpc = Arc::new(JsonRpcInterface { addr: accept_addr.clone(), p2p });
    let _ex = ex.clone();
    ex.spawn(async move { listen_and_serve(accept_addr.clone(), rpc, _ex).await }).detach();

    let nthreads = std::thread::available_parallelism().unwrap().get();
    let (signal, shutdown) = smol::channel::unbounded::<()>();

    let (_, result) = Parallel::new()
        .each(0..nthreads, |_| smol::future::block_on(ex2.run(shutdown.recv())))
        .finish(|| {
            smol::future::block_on(async move {
                dchat.start(ex3).await?;
                drop(signal);
                Ok(())
            })
        });

    result
}