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
}