#![allow(dead_code)]
use std::collections::BTreeMap;
use anyhow::Context as _;
use rand::Rng;
use zksync_concurrency::{ctx, limiter};
use zksync_consensus_roles::validator;
use super::*;
use crate::{frame, mux, noise, preface, rpc, testonly::make_config, Config};
pub(super) struct Conn {
accept: BTreeMap<mux::CapabilityId, Arc<mux::StreamQueue>>,
connect: BTreeMap<mux::CapabilityId, Arc<mux::StreamQueue>>,
}
pub(super) struct ConnRunner {
mux: mux::Mux,
stream: noise::Stream,
}
impl ConnRunner {
pub(super) async fn run(self, ctx: &ctx::Ctx) -> Result<(), mux::RunError> {
self.mux.run(ctx, self.stream).await
}
}
fn mux_entry<R: rpc::Rpc>(ctx: &ctx::Ctx) -> (mux::CapabilityId, Arc<mux::StreamQueue>) {
(
R::CAPABILITY.id(),
mux::StreamQueue::new(ctx, R::INFLIGHT, limiter::Rate::INF),
)
}
pub(super) async fn connect(
ctx: &ctx::Ctx,
peer: &Config,
genesis: validator::GenesisHash,
) -> ctx::Result<(Conn, ConnRunner)> {
assert!(peer.gossip.dynamic_inbound_limit > 0);
let addr = peer
.public_addr
.resolve(ctx)
.await?
.context("peer.public_addr.resolve()")?[0];
let mut stream = preface::connect(ctx, addr, preface::Endpoint::GossipNet)
.await
.context("preface::connect()")?;
let cfg = make_config(ctx.rng().gen());
handshake::outbound(ctx, &cfg, genesis, &mut stream, &peer.gossip.key.public())
.await
.context("handshake::outbound()")?;
let conn = Conn {
accept: [
mux_entry::<rpc::get_block::Rpc>(ctx),
mux_entry::<rpc::push_block_store_state::Rpc>(ctx),
]
.into(),
connect: [
mux_entry::<rpc::get_block::Rpc>(ctx),
mux_entry::<rpc::push_block_store_state::Rpc>(ctx),
]
.into(),
};
let mux = mux::Mux {
cfg: Arc::new(rpc::MUX_CONFIG.clone()),
accept: conn.accept.clone(),
connect: conn.connect.clone(),
};
Ok((conn, ConnRunner { mux, stream }))
}
impl Conn {
pub(super) async fn open_server<R: rpc::Rpc>(
&self,
ctx: &ctx::Ctx,
) -> ctx::OrCanceled<ServerStream<R>> {
Ok(ServerStream(
self.connect
.get(&R::CAPABILITY.id())
.unwrap()
.open(ctx)
.await?,
std::marker::PhantomData,
))
}
pub(super) async fn open_client<R: rpc::Rpc>(
&self,
ctx: &ctx::Ctx,
) -> ctx::OrCanceled<ClientStream<R>> {
Ok(ClientStream(
self.accept
.get(&R::CAPABILITY.id())
.unwrap()
.open(ctx)
.await?,
std::marker::PhantomData,
))
}
}
pub(super) struct ClientStream<R>(mux::Stream, std::marker::PhantomData<R>);
pub(super) struct ServerStream<R>(mux::Stream, std::marker::PhantomData<R>);
impl<R: rpc::Rpc> ClientStream<R> {
pub(super) async fn send(&mut self, ctx: &ctx::Ctx, req: &R::Req) -> anyhow::Result<()> {
frame::mux_send_proto(ctx, &mut self.0.write, req).await?;
self.0.write.flush(ctx).await?;
Ok(())
}
pub(super) async fn recv(mut self, ctx: &ctx::Ctx) -> anyhow::Result<R::Resp> {
Ok(frame::mux_recv_proto(ctx, &mut self.0.read, usize::MAX)
.await?
.0)
}
}
impl<R: rpc::Rpc> ServerStream<R> {
pub(super) async fn send(mut self, ctx: &ctx::Ctx, resp: &R::Resp) -> anyhow::Result<()> {
frame::mux_send_proto(ctx, &mut self.0.write, resp).await?;
self.0.write.flush(ctx).await?;
Ok(())
}
pub(super) async fn recv(&mut self, ctx: &ctx::Ctx) -> anyhow::Result<R::Req> {
Ok(frame::mux_recv_proto(ctx, &mut self.0.read, usize::MAX)
.await?
.0)
}
}