|
@@ -2,23 +2,14 @@
|
|
|
|
|
|
mod tls;
|
|
mod tls;
|
|
use tls::*;
|
|
use tls::*;
|
|
|
|
+mod callback_framed;
|
|
|
|
+use callback_framed::{CallbackFramed, DeserCallback};
|
|
|
|
|
|
use btlib::{bterr, crypto::Creds, error::BoxInIoErr, BlockPath, Result, Writecap};
|
|
use btlib::{bterr, crypto::Creds, error::BoxInIoErr, BlockPath, Result, Writecap};
|
|
use btserde::{read_from, write_to};
|
|
use btserde::{read_from, write_to};
|
|
use bytes::{BufMut, BytesMut};
|
|
use bytes::{BufMut, BytesMut};
|
|
-use core::{
|
|
|
|
- future::Future,
|
|
|
|
- marker::Send,
|
|
|
|
- ops::DerefMut,
|
|
|
|
- pin::Pin,
|
|
|
|
- task::{Context, Poll},
|
|
|
|
-};
|
|
|
|
-use futures::{
|
|
|
|
- future::{ready, Ready},
|
|
|
|
- sink::Send as SendFut,
|
|
|
|
- stream::Stream,
|
|
|
|
- SinkExt, StreamExt,
|
|
|
|
-};
|
|
|
|
|
|
+use core::{future::Future, marker::Send, ops::DerefMut, pin::Pin};
|
|
|
|
+use futures::{sink::Send as SendFut, SinkExt, StreamExt};
|
|
use log::error;
|
|
use log::error;
|
|
use quinn::{Connection, Endpoint, RecvStream, SendStream};
|
|
use quinn::{Connection, Endpoint, RecvStream, SendStream};
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
@@ -27,27 +18,69 @@ use std::{
|
|
collections::hash_map::DefaultHasher,
|
|
collections::hash_map::DefaultHasher,
|
|
hash::{Hash, Hasher},
|
|
hash::{Hash, Hasher},
|
|
marker::PhantomData,
|
|
marker::PhantomData,
|
|
- net::{IpAddr, SocketAddr},
|
|
|
|
|
|
+ net::{IpAddr, Ipv6Addr, SocketAddr},
|
|
sync::Arc,
|
|
sync::Arc,
|
|
};
|
|
};
|
|
use tokio::{
|
|
use tokio::{
|
|
select,
|
|
select,
|
|
- sync::{broadcast, mpsc, Mutex},
|
|
|
|
|
|
+ sync::{broadcast, Mutex},
|
|
};
|
|
};
|
|
-use tokio_stream::wrappers::ReceiverStream;
|
|
|
|
use tokio_util::codec::{Decoder, Encoder, Framed, FramedParts, FramedRead, FramedWrite};
|
|
use tokio_util::codec::{Decoder, Encoder, Framed, FramedParts, FramedRead, FramedWrite};
|
|
|
|
|
|
-/// Returns a [Router] which can be used to make a [Receiver] for the given path and
|
|
|
|
-/// [Sender] instances for any path.
|
|
|
|
-pub fn router<C: 'static + Creds + Send + Sync>(
|
|
|
|
|
|
+/// Returns a [Receiver] bound to the given [IpAddr] which receives messages at the bind path of
|
|
|
|
+/// the given [Writecap] of the given credentials. The returned type can be used to make
|
|
|
|
+/// [Transmitter]s for any path.
|
|
|
|
+pub fn receiver<C: 'static + Creds + Send + Sync, F: 'static + MsgCallback>(
|
|
ip_addr: IpAddr,
|
|
ip_addr: IpAddr,
|
|
creds: Arc<C>,
|
|
creds: Arc<C>,
|
|
-) -> Result<impl Router> {
|
|
|
|
|
|
+ callback: F,
|
|
|
|
+) -> Result<impl Receiver> {
|
|
let writecap = creds.writecap().ok_or(btlib::BlockError::MissingWritecap)?;
|
|
let writecap = creds.writecap().ok_or(btlib::BlockError::MissingWritecap)?;
|
|
let addr = Arc::new(BlockAddr::new(ip_addr, Arc::new(writecap.bind_path())));
|
|
let addr = Arc::new(BlockAddr::new(ip_addr, Arc::new(writecap.bind_path())));
|
|
- QuicRouter::new(addr, Arc::new(CertResolver::new(creds)?))
|
|
|
|
|
|
+ QuicReceiver::new(addr, Arc::new(CertResolver::new(creds)?), callback)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+pub async fn transmitter<C: 'static + Creds + Send + Sync>(
|
|
|
|
+ addr: Arc<BlockAddr>,
|
|
|
|
+ creds: Arc<C>,
|
|
|
|
+) -> Result<impl Transmitter> {
|
|
|
|
+ let resolver = Arc::new(CertResolver::new(creds)?);
|
|
|
|
+ let endpoint = Endpoint::client(SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0))?;
|
|
|
|
+ QuicTransmitter::from_endpoint(endpoint, addr, resolver).await
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+pub trait MsgCallback: Clone + Send + Sync + Unpin {
|
|
|
|
+ type Arg<'de>: CallMsg<'de>
|
|
|
|
+ where
|
|
|
|
+ Self: 'de;
|
|
|
|
+ type Return;
|
|
|
|
+ type CallFut<'de>: Future<Output = Self::Return> + Send
|
|
|
|
+ where
|
|
|
|
+ Self: 'de;
|
|
|
|
+ fn call<'de>(&'de self, arg: MsgReceived<Self::Arg<'de>>) -> Self::CallFut<'de>;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<T: MsgCallback> MsgCallback for &T {
|
|
|
|
+ type Arg<'de> = T::Arg<'de> where Self: 'de;
|
|
|
|
+ type Return = T::Return;
|
|
|
|
+ type CallFut<'de> = T::CallFut<'de> where Self: 'de;
|
|
|
|
+ fn call<'de>(&'de self, arg: MsgReceived<Self::Arg<'de>>) -> Self::CallFut<'de> {
|
|
|
|
+ (*self).call(arg)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/// Trait for messages which can be transmitted using the call method.
|
|
|
|
+pub trait CallMsg<'de>: Serialize + Deserialize<'de> + Send + Sync {
|
|
|
|
+ type Reply: Serialize + DeserializeOwned + Send;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#[derive(Serialize, Deserialize)]
|
|
|
|
+pub enum NoReply {}
|
|
|
|
+
|
|
|
|
+/// Trait for messages which can be transmitted using the send method.
|
|
|
|
+/// Types which implement this trait should specify [NoReply] as their reply type.
|
|
|
|
+pub trait SendMsg<'de>: CallMsg<'de> {}
|
|
|
|
+
|
|
/// An address which identifies a block on the network. An instance of this struct can be
|
|
/// An address which identifies a block on the network. An instance of this struct can be
|
|
/// used to get a socket address for the block this address refers to.
|
|
/// used to get a socket address for the block this address refers to.
|
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
|
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
|
|
@@ -87,24 +120,6 @@ impl BlockAddr {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/// Trait for messages which can be transmitted using the call method.
|
|
|
|
-pub trait CallTx: Serialize + Send {
|
|
|
|
- type Reply: 'static + DeserializeOwned + Send;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/// Trait for messages which can be transmitted using the send method.
|
|
|
|
-/// Types which implement this trait should choose `()` as their reply type.
|
|
|
|
-pub trait SendTx: CallTx {}
|
|
|
|
-
|
|
|
|
-/// Trait for messages which are received from the call method.
|
|
|
|
-pub trait CallRx: 'static + DeserializeOwned + Send {
|
|
|
|
- type Reply<'a>: 'a + Serialize + Send;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/// Trait for messages which are received from the send method.
|
|
|
|
-/// Types which implement this trait should choose `()` as their reply type.
|
|
|
|
-pub trait SendRx: CallRx {}
|
|
|
|
-
|
|
|
|
/// Indicates whether a message was sent using `call` or `send`.
|
|
/// Indicates whether a message was sent using `call` or `send`.
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
|
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
|
|
enum MsgKind {
|
|
enum MsgKind {
|
|
@@ -144,11 +159,11 @@ impl<T> Envelope<T> {
|
|
pub struct MsgReceived<T> {
|
|
pub struct MsgReceived<T> {
|
|
from: Arc<BlockPath>,
|
|
from: Arc<BlockPath>,
|
|
msg: Envelope<T>,
|
|
msg: Envelope<T>,
|
|
- replier: Replier,
|
|
|
|
|
|
+ replier: Option<Replier>,
|
|
}
|
|
}
|
|
|
|
|
|
impl<T> MsgReceived<T> {
|
|
impl<T> MsgReceived<T> {
|
|
- fn new(from: Arc<BlockPath>, msg: Envelope<T>, replier: Replier) -> Self {
|
|
|
|
|
|
+ fn new(from: Arc<BlockPath>, msg: Envelope<T>, replier: Option<Replier>) -> Self {
|
|
Self { from, msg, replier }
|
|
Self { from, msg, replier }
|
|
}
|
|
}
|
|
|
|
|
|
@@ -164,44 +179,53 @@ impl<T> MsgReceived<T> {
|
|
|
|
|
|
/// Returns true if and only if this messages needs to be replied to.
|
|
/// Returns true if and only if this messages needs to be replied to.
|
|
pub fn needs_reply(&self) -> bool {
|
|
pub fn needs_reply(&self) -> bool {
|
|
- self.replier.parts.is_some()
|
|
|
|
|
|
+ self.replier.is_some()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: CallRx> MsgReceived<T> {
|
|
|
|
- /// Replies to this message. This method must be called exactly once for [CallRx] messages
|
|
|
|
- /// and exactly zero times for [SendRx] messages. The `needs_reply` method can be called
|
|
|
|
- /// on this instance to determine if a reply still needs to be sent.
|
|
|
|
- pub async fn reply<'a>(&mut self, reply: T::Reply<'a>) -> Result<()> {
|
|
|
|
- self.replier.reply(reply).await
|
|
|
|
|
|
+impl<'de, T: CallMsg<'de>> MsgReceived<T> {
|
|
|
|
+ /// Returns a type which can be used to reply to this message, if this message requires a
|
|
|
|
+ /// reply and it has not yet been sent.
|
|
|
|
+ pub fn take_replier(&mut self) -> Option<Replier> {
|
|
|
|
+ self.replier.take()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-/// A type which can be used to receive messages.
|
|
|
|
-pub trait Receiver<T>: Stream<Item = Result<MsgReceived<T>>> {
|
|
|
|
|
|
+/// Trait for receiving messages and creating [Transmitter]s.
|
|
|
|
+pub trait Receiver {
|
|
/// The address at which messages will be received.
|
|
/// The address at which messages will be received.
|
|
- fn addr(&self) -> &BlockAddr;
|
|
|
|
|
|
+ fn addr(&self) -> &Arc<BlockAddr>;
|
|
|
|
+
|
|
|
|
+ type Transmitter: Transmitter + Send;
|
|
|
|
+ type TransmitterFut<'a>: 'a + Future<Output = Result<Self::Transmitter>> + Send
|
|
|
|
+ where
|
|
|
|
+ Self: 'a;
|
|
|
|
+
|
|
|
|
+ /// Creates a [Transmitter] which is connected to the given address.
|
|
|
|
+ fn transmitter(&self, addr: Arc<BlockAddr>) -> Self::TransmitterFut<'_>;
|
|
}
|
|
}
|
|
|
|
|
|
/// A type which can be used to transmit messages.
|
|
/// A type which can be used to transmit messages.
|
|
pub trait Transmitter {
|
|
pub trait Transmitter {
|
|
- type SendFut<'a, T>: 'a + Future<Output = Result<()>> + Send
|
|
|
|
|
|
+ type SendFut<'s, T>: 's + Future<Output = Result<()>> + Send
|
|
where
|
|
where
|
|
- Self: 'a,
|
|
|
|
- T: 'a + Serialize + Send;
|
|
|
|
|
|
+ Self: 's,
|
|
|
|
+ T: 's + Serialize + Send;
|
|
|
|
|
|
/// Transmit a message to the connected [Receiver] without waiting for a reply.
|
|
/// Transmit a message to the connected [Receiver] without waiting for a reply.
|
|
- fn send<'a, T: 'a + SendTx>(&'a mut self, msg: T) -> Self::SendFut<'a, T>;
|
|
|
|
|
|
+ fn send<'de, T: 'de + SendMsg<'de>>(&'de mut self, msg: T) -> Self::SendFut<'de, T>;
|
|
|
|
|
|
- type CallFut<'a, T>: 'a + Future<Output = Result<T::Reply>> + Send
|
|
|
|
|
|
+ type CallFut<'s, 'de, T>: 's + Future<Output = Result<T::Reply>> + Send
|
|
where
|
|
where
|
|
- Self: 'a,
|
|
|
|
- T: 'a + CallTx;
|
|
|
|
|
|
+ Self: 's,
|
|
|
|
+ T: 's + CallMsg<'de>,
|
|
|
|
+ T::Reply: 's;
|
|
|
|
|
|
/// Transmit a message to the connected [Receiver] and wait for a reply.
|
|
/// Transmit a message to the connected [Receiver] and wait for a reply.
|
|
- fn call<'a, T>(&'a mut self, msg: T) -> Self::CallFut<'a, T>
|
|
|
|
|
|
+ fn call<'s, 'de, T>(&'s mut self, msg: T) -> Self::CallFut<'s, 'de, T>
|
|
where
|
|
where
|
|
- T: 'a + CallTx;
|
|
|
|
|
|
+ T: 's + CallMsg<'de>,
|
|
|
|
+ T::Reply: 's;
|
|
|
|
|
|
type FinishFut: Future<Output = Result<()>> + Send;
|
|
type FinishFut: Future<Output = Result<()>> + Send;
|
|
|
|
|
|
@@ -209,27 +233,7 @@ pub trait Transmitter {
|
|
fn finish(self) -> Self::FinishFut;
|
|
fn finish(self) -> Self::FinishFut;
|
|
|
|
|
|
/// Returns the address that this instance is transmitting to.
|
|
/// Returns the address that this instance is transmitting to.
|
|
- fn addr(&self) -> &BlockAddr;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/// Trait for types which can create [Transmitter]s and [Receiver]s.
|
|
|
|
-pub trait Router {
|
|
|
|
- type Transmitter: Transmitter + Send;
|
|
|
|
- type TransmitterFut<'a>: 'a + Future<Output = Result<Self::Transmitter>> + Send
|
|
|
|
- where
|
|
|
|
- Self: 'a;
|
|
|
|
-
|
|
|
|
- /// Creates a [Transmitter] which is connected to the given address.
|
|
|
|
- fn transmitter(&self, addr: Arc<BlockAddr>) -> Self::TransmitterFut<'_>;
|
|
|
|
-
|
|
|
|
- type Receiver<T: CallRx>: Receiver<T> + Send + Unpin;
|
|
|
|
- type ReceiverFut<'a, T>: 'a + Future<Output = Result<Self::Receiver<T>>> + Send
|
|
|
|
- where
|
|
|
|
- T: CallRx,
|
|
|
|
- Self: 'a;
|
|
|
|
-
|
|
|
|
- /// Creates a [Receiver] which will receive message at the address of this [Router].
|
|
|
|
- fn receiver<T: CallRx>(&self) -> Self::ReceiverFut<'_, T>;
|
|
|
|
|
|
+ fn addr(&self) -> &Arc<BlockAddr>;
|
|
}
|
|
}
|
|
|
|
|
|
/// Encodes messages using [btserde].
|
|
/// Encodes messages using [btserde].
|
|
@@ -299,82 +303,60 @@ impl<T: DeserializeOwned> Decoder for MsgDecoder<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-struct QuicRouter {
|
|
|
|
- recv_addr: Arc<BlockAddr>,
|
|
|
|
- resolver: Arc<CertResolver>,
|
|
|
|
- endpoint: Endpoint,
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl QuicRouter {
|
|
|
|
- fn new(recv_addr: Arc<BlockAddr>, resolver: Arc<CertResolver>) -> Result<Self> {
|
|
|
|
- let socket_addr = recv_addr.socket_addr();
|
|
|
|
- let endpoint = Endpoint::server(server_config(resolver.clone())?, socket_addr)?;
|
|
|
|
- Ok(Self {
|
|
|
|
- endpoint,
|
|
|
|
- resolver,
|
|
|
|
- recv_addr,
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-impl Router for QuicRouter {
|
|
|
|
- type Receiver<T: CallRx> = QuicReceiver<T>;
|
|
|
|
- type ReceiverFut<'a, T: CallRx> = Ready<Result<QuicReceiver<T>>>;
|
|
|
|
-
|
|
|
|
- fn receiver<T: CallRx>(&self) -> Self::ReceiverFut<'_, T> {
|
|
|
|
- ready(QuicReceiver::new(
|
|
|
|
- self.endpoint.clone(),
|
|
|
|
- self.recv_addr.clone(),
|
|
|
|
- ))
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- type Transmitter = QuicSender;
|
|
|
|
- type TransmitterFut<'a> = Pin<Box<dyn 'a + Future<Output = Result<QuicSender>> + Send>>;
|
|
|
|
-
|
|
|
|
- fn transmitter(&self, addr: Arc<BlockAddr>) -> Self::TransmitterFut<'_> {
|
|
|
|
- Box::pin(async {
|
|
|
|
- QuicSender::from_endpoint(self.endpoint.clone(), addr, self.resolver.clone()).await
|
|
|
|
- })
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
type SharedFrameParts = Arc<Mutex<Option<FramedParts<SendStream, MsgEncoder>>>>;
|
|
type SharedFrameParts = Arc<Mutex<Option<FramedParts<SendStream, MsgEncoder>>>>;
|
|
|
|
|
|
#[derive(Clone)]
|
|
#[derive(Clone)]
|
|
-struct Replier {
|
|
|
|
- parts: Option<SharedFrameParts>,
|
|
|
|
|
|
+pub struct Replier {
|
|
|
|
+ parts: SharedFrameParts,
|
|
}
|
|
}
|
|
|
|
|
|
impl Replier {
|
|
impl Replier {
|
|
fn new(send_stream: SendStream) -> Self {
|
|
fn new(send_stream: SendStream) -> Self {
|
|
let parts = FramedParts::new::<()>(send_stream, MsgEncoder::new());
|
|
let parts = FramedParts::new::<()>(send_stream, MsgEncoder::new());
|
|
- let parts = Some(Arc::new(Mutex::new(Some(parts))));
|
|
|
|
|
|
+ let parts = Arc::new(Mutex::new(Some(parts)));
|
|
Self { parts }
|
|
Self { parts }
|
|
}
|
|
}
|
|
|
|
|
|
- fn empty() -> Self {
|
|
|
|
- Self { parts: None }
|
|
|
|
|
|
+ pub async fn reply<T: Serialize + Send>(self, reply: T) -> Result<()> {
|
|
|
|
+ let parts = self.parts;
|
|
|
|
+ let mut guard = parts.lock().await;
|
|
|
|
+ // We must ensure the parts are put back before we leave this block.
|
|
|
|
+ let parts = guard.take().unwrap();
|
|
|
|
+ let mut stream = Framed::from_parts(parts);
|
|
|
|
+ let result = stream.send(reply).await;
|
|
|
|
+ *guard = Some(stream.into_parts());
|
|
|
|
+ result
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
|
|
- async fn reply<T: Serialize + Send>(&mut self, reply: T) -> Result<()> {
|
|
|
|
- let parts = self
|
|
|
|
- .parts
|
|
|
|
- .take()
|
|
|
|
- .ok_or_else(|| bterr!("reply has already been sent"))?;
|
|
|
|
- let result = {
|
|
|
|
- let mut guard = parts.lock().await;
|
|
|
|
- // We must ensure the parts are put back before we leave this block.
|
|
|
|
- let parts = guard.take().unwrap();
|
|
|
|
- let mut stream = Framed::from_parts(parts);
|
|
|
|
- let result = stream.send(reply).await;
|
|
|
|
- *guard = Some(stream.into_parts());
|
|
|
|
- result
|
|
|
|
- };
|
|
|
|
- if result.is_err() {
|
|
|
|
- // If the result is an error put back the parts so the caller may try again.
|
|
|
|
- self.parts = Some(parts);
|
|
|
|
|
|
+#[derive(Clone)]
|
|
|
|
+struct MsgRecvdCallback<F> {
|
|
|
|
+ path: Arc<BlockPath>,
|
|
|
|
+ replier: Replier,
|
|
|
|
+ inner: F,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<F: MsgCallback> MsgRecvdCallback<F> {
|
|
|
|
+ fn new(path: Arc<BlockPath>, replier: Replier, inner: F) -> Self {
|
|
|
|
+ Self {
|
|
|
|
+ path,
|
|
|
|
+ replier,
|
|
|
|
+ inner,
|
|
}
|
|
}
|
|
- result
|
|
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl<F: MsgCallback> DeserCallback for MsgRecvdCallback<F> {
|
|
|
|
+ type Arg<'de> = Envelope<F::Arg<'de>> where Self: 'de;
|
|
|
|
+ type Return = F::Return;
|
|
|
|
+ type CallFut<'s> = F::CallFut<'s> where F: 's;
|
|
|
|
+ fn call<'de>(&'de self, arg: Envelope<F::Arg<'de>>) -> Self::CallFut<'de> {
|
|
|
|
+ let replier = match arg.kind {
|
|
|
|
+ MsgKind::Call => Some(self.replier.clone()),
|
|
|
|
+ MsgKind::Send => None,
|
|
|
|
+ };
|
|
|
|
+ self.inner
|
|
|
|
+ .call(MsgReceived::new(self.path.clone(), arg, replier))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -423,30 +405,34 @@ macro_rules! await_or_stop {
|
|
};
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
-struct QuicReceiver<T> {
|
|
|
|
|
|
+struct QuicReceiver {
|
|
recv_addr: Arc<BlockAddr>,
|
|
recv_addr: Arc<BlockAddr>,
|
|
stop_tx: broadcast::Sender<()>,
|
|
stop_tx: broadcast::Sender<()>,
|
|
- stream: ReceiverStream<Result<MsgReceived<T>>>,
|
|
|
|
|
|
+ endpoint: Endpoint,
|
|
|
|
+ resolver: Arc<CertResolver>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: CallRx> QuicReceiver<T> {
|
|
|
|
- /// The size of the buffer to store received messages in.
|
|
|
|
- const MSG_BUF_SZ: usize = 64;
|
|
|
|
-
|
|
|
|
- fn new(endpoint: Endpoint, recv_addr: Arc<BlockAddr>) -> Result<Self> {
|
|
|
|
|
|
+impl QuicReceiver {
|
|
|
|
+ fn new<F: 'static + MsgCallback>(
|
|
|
|
+ recv_addr: Arc<BlockAddr>,
|
|
|
|
+ resolver: Arc<CertResolver>,
|
|
|
|
+ callback: F,
|
|
|
|
+ ) -> Result<Self> {
|
|
|
|
+ let socket_addr = recv_addr.socket_addr();
|
|
|
|
+ let endpoint = Endpoint::server(server_config(resolver.clone())?, socket_addr)?;
|
|
let (stop_tx, stop_rx) = broadcast::channel(1);
|
|
let (stop_tx, stop_rx) = broadcast::channel(1);
|
|
- let (msg_tx, msg_rx) = mpsc::channel(Self::MSG_BUF_SZ);
|
|
|
|
- tokio::spawn(Self::server_loop(endpoint, msg_tx, stop_rx));
|
|
|
|
|
|
+ tokio::spawn(Self::server_loop(endpoint.clone(), callback, stop_rx));
|
|
Ok(Self {
|
|
Ok(Self {
|
|
recv_addr,
|
|
recv_addr,
|
|
stop_tx,
|
|
stop_tx,
|
|
- stream: ReceiverStream::new(msg_rx),
|
|
|
|
|
|
+ endpoint,
|
|
|
|
+ resolver,
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
- async fn server_loop(
|
|
|
|
|
|
+ async fn server_loop<F: 'static + MsgCallback>(
|
|
endpoint: Endpoint,
|
|
endpoint: Endpoint,
|
|
- msg_tx: mpsc::Sender<Result<MsgReceived<T>>>,
|
|
|
|
|
|
+ callback: F,
|
|
mut stop_rx: broadcast::Receiver<()>,
|
|
mut stop_rx: broadcast::Receiver<()>,
|
|
) {
|
|
) {
|
|
loop {
|
|
loop {
|
|
@@ -456,29 +442,15 @@ impl<T: CallRx> QuicReceiver<T> {
|
|
));
|
|
));
|
|
tokio::spawn(Self::handle_connection(
|
|
tokio::spawn(Self::handle_connection(
|
|
connection,
|
|
connection,
|
|
- msg_tx.clone(),
|
|
|
|
|
|
+ callback.clone(),
|
|
stop_rx.resubscribe(),
|
|
stop_rx.resubscribe(),
|
|
));
|
|
));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- /// Returns the path the client is bound to.
|
|
|
|
- fn client_path(peer_identity: Option<Box<dyn Any>>) -> Result<Arc<BlockPath>> {
|
|
|
|
- let peer_identity =
|
|
|
|
- peer_identity.ok_or_else(|| bterr!("connection did not contain a peer identity"))?;
|
|
|
|
- let client_certs = peer_identity
|
|
|
|
- .downcast::<Vec<rustls::Certificate>>()
|
|
|
|
- .map_err(|_| bterr!("failed to downcast peer_identity to certificate chain"))?;
|
|
|
|
- let first = client_certs
|
|
|
|
- .first()
|
|
|
|
- .ok_or_else(|| bterr!("no certificates were presented by the client"))?;
|
|
|
|
- let (writecap, ..) = Writecap::from_cert_chain(first, &client_certs[1..])?;
|
|
|
|
- Ok(Arc::new(writecap.bind_path()))
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- async fn handle_connection(
|
|
|
|
|
|
+ async fn handle_connection<F: MsgCallback>(
|
|
connection: Connection,
|
|
connection: Connection,
|
|
- msg_tx: mpsc::Sender<Result<MsgReceived<T>>>,
|
|
|
|
|
|
+ callback: F,
|
|
mut stop_rx: broadcast::Receiver<()>,
|
|
mut stop_rx: broadcast::Receiver<()>,
|
|
) {
|
|
) {
|
|
let client_path = unwrap_or_return!(
|
|
let client_path = unwrap_or_return!(
|
|
@@ -490,28 +462,32 @@ impl<T: CallRx> QuicReceiver<T> {
|
|
|err| error!("error accepting receive stream: {err}")
|
|
|err| error!("error accepting receive stream: {err}")
|
|
);
|
|
);
|
|
let replier = Replier::new(send_stream);
|
|
let replier = Replier::new(send_stream);
|
|
- let mut msg_stream = FramedRead::new(recv_stream, MsgDecoder::<Envelope<T>>::new());
|
|
|
|
|
|
+ let callback = MsgRecvdCallback::new(client_path, replier, callback);
|
|
|
|
+ let mut msg_stream = CallbackFramed::new(recv_stream);
|
|
loop {
|
|
loop {
|
|
- let decode_result = await_or_stop!(msg_stream.next(), stop_rx.recv());
|
|
|
|
|
|
+ let decode_result = await_or_stop!(msg_stream.next(callback.clone()), stop_rx.recv());
|
|
if let Err(ref err) = decode_result {
|
|
if let Err(ref err) = decode_result {
|
|
error!("msg_stream produced an error: {err}");
|
|
error!("msg_stream produced an error: {err}");
|
|
}
|
|
}
|
|
- let msg_received = decode_result.map(|envelope| {
|
|
|
|
- let replier = match envelope.kind {
|
|
|
|
- MsgKind::Call => replier.clone(),
|
|
|
|
- MsgKind::Send => Replier::empty(),
|
|
|
|
- };
|
|
|
|
- MsgReceived::new(client_path.clone(), envelope, replier)
|
|
|
|
- });
|
|
|
|
- let send_result = msg_tx.send(msg_received).await;
|
|
|
|
- if let Err(err) = send_result {
|
|
|
|
- error!("error sending message to mpsc queue: {err}");
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /// Returns the path the client is bound to.
|
|
|
|
+ fn client_path(peer_identity: Option<Box<dyn Any>>) -> Result<Arc<BlockPath>> {
|
|
|
|
+ let peer_identity =
|
|
|
|
+ peer_identity.ok_or_else(|| bterr!("connection did not contain a peer identity"))?;
|
|
|
|
+ let client_certs = peer_identity
|
|
|
|
+ .downcast::<Vec<rustls::Certificate>>()
|
|
|
|
+ .map_err(|_| bterr!("failed to downcast peer_identity to certificate chain"))?;
|
|
|
|
+ let first = client_certs
|
|
|
|
+ .first()
|
|
|
|
+ .ok_or_else(|| bterr!("no certificates were presented by the client"))?;
|
|
|
|
+ let (writecap, ..) = Writecap::from_cert_chain(first, &client_certs[1..])?;
|
|
|
|
+ Ok(Arc::new(writecap.bind_path()))
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T> Drop for QuicReceiver<T> {
|
|
|
|
|
|
+impl Drop for QuicReceiver {
|
|
fn drop(&mut self) {
|
|
fn drop(&mut self) {
|
|
// This result will be a failure if the tasks have already returned, which is not a
|
|
// This result will be a failure if the tasks have already returned, which is not a
|
|
// problem.
|
|
// problem.
|
|
@@ -519,27 +495,28 @@ impl<T> Drop for QuicReceiver<T> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-impl<T: CallRx> Stream for QuicReceiver<T> {
|
|
|
|
- type Item = Result<MsgReceived<T>>;
|
|
|
|
-
|
|
|
|
- fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
|
|
|
- self.stream.poll_next_unpin(cx)
|
|
|
|
|
|
+impl Receiver for QuicReceiver {
|
|
|
|
+ fn addr(&self) -> &Arc<BlockAddr> {
|
|
|
|
+ &self.recv_addr
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
|
|
-impl<T: CallRx> Receiver<T> for QuicReceiver<T> {
|
|
|
|
- fn addr(&self) -> &BlockAddr {
|
|
|
|
- &self.recv_addr
|
|
|
|
|
|
+ type Transmitter = QuicTransmitter;
|
|
|
|
+ type TransmitterFut<'a> = Pin<Box<dyn 'a + Future<Output = Result<QuicTransmitter>> + Send>>;
|
|
|
|
+
|
|
|
|
+ fn transmitter(&self, addr: Arc<BlockAddr>) -> Self::TransmitterFut<'_> {
|
|
|
|
+ Box::pin(async {
|
|
|
|
+ QuicTransmitter::from_endpoint(self.endpoint.clone(), addr, self.resolver.clone()).await
|
|
|
|
+ })
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-struct QuicSender {
|
|
|
|
|
|
+struct QuicTransmitter {
|
|
addr: Arc<BlockAddr>,
|
|
addr: Arc<BlockAddr>,
|
|
sink: FramedWrite<SendStream, MsgEncoder>,
|
|
sink: FramedWrite<SendStream, MsgEncoder>,
|
|
recv_stream: Mutex<RecvStream>,
|
|
recv_stream: Mutex<RecvStream>,
|
|
}
|
|
}
|
|
|
|
|
|
-impl QuicSender {
|
|
|
|
|
|
+impl QuicTransmitter {
|
|
async fn from_endpoint(
|
|
async fn from_endpoint(
|
|
endpoint: Endpoint,
|
|
endpoint: Endpoint,
|
|
addr: Arc<BlockAddr>,
|
|
addr: Arc<BlockAddr>,
|
|
@@ -567,15 +544,15 @@ impl QuicSender {
|
|
/// https://github.com/rust-lang/rust/issues/63063
|
|
/// https://github.com/rust-lang/rust/issues/63063
|
|
/// feature lands the future types in this implementation should be rewritten to
|
|
/// feature lands the future types in this implementation should be rewritten to
|
|
/// use it.
|
|
/// use it.
|
|
-impl Transmitter for QuicSender {
|
|
|
|
- fn addr(&self) -> &BlockAddr {
|
|
|
|
|
|
+impl Transmitter for QuicTransmitter {
|
|
|
|
+ fn addr(&self) -> &Arc<BlockAddr> {
|
|
&self.addr
|
|
&self.addr
|
|
}
|
|
}
|
|
|
|
|
|
- type SendFut<'a, T> = SendFut<'a, FramedWrite<SendStream, MsgEncoder>, Envelope<T>>
|
|
|
|
- where T: 'a + Serialize + Send;
|
|
|
|
|
|
+ type SendFut<'s, T> = SendFut<'s, FramedWrite<SendStream, MsgEncoder>, Envelope<T>>
|
|
|
|
+ where T: 's + Serialize + Send;
|
|
|
|
|
|
- fn send<'a, T: 'a + Serialize + Send>(&'a mut self, msg: T) -> Self::SendFut<'a, T> {
|
|
|
|
|
|
+ fn send<'de, T: 'de + SendMsg<'de>>(&'de mut self, msg: T) -> Self::SendFut<'de, T> {
|
|
self.sink.send(Envelope::send(msg))
|
|
self.sink.send(Envelope::send(msg))
|
|
}
|
|
}
|
|
|
|
|
|
@@ -588,13 +565,15 @@ impl Transmitter for QuicSender {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
- type CallFut<'a, T> = Pin<Box<dyn 'a + Future<Output = Result<T::Reply>> + Send>>
|
|
|
|
|
|
+ type CallFut<'s, 'de, T> = Pin<Box<dyn 's + Future<Output = Result<T::Reply>> + Send>>
|
|
where
|
|
where
|
|
- T: 'a + CallTx;
|
|
|
|
|
|
+ T: 's + CallMsg<'de>,
|
|
|
|
+ T::Reply: 's;
|
|
|
|
|
|
- fn call<'a, T>(&'a mut self, msg: T) -> Self::CallFut<'a, T>
|
|
|
|
|
|
+ fn call<'s, 'de, T>(&'s mut self, msg: T) -> Self::CallFut<'s, 'de, T>
|
|
where
|
|
where
|
|
- T: 'a + CallTx,
|
|
|
|
|
|
+ T: 's + CallMsg<'de>,
|
|
|
|
+ T::Reply: 's,
|
|
{
|
|
{
|
|
Box::pin(async move {
|
|
Box::pin(async move {
|
|
self.sink.send(Envelope::call(msg)).await?;
|
|
self.sink.send(Envelope::call(msg)).await?;
|
|
@@ -607,14 +586,3 @@ impl Transmitter for QuicSender {
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
-/// This is an identify function which allows you to specify a type parameter for the output
|
|
|
|
-/// of a future.
|
|
|
|
-/// TODO: This was needed to work around a failure in type inference for types with higher-rank
|
|
|
|
-/// lifetimes. Once this issue is resolved this can be removed:
|
|
|
|
-/// https://github.com/rust-lang/rust/issues/102211
|
|
|
|
-pub fn assert_send<'a, T>(
|
|
|
|
- fut: impl 'a + Future<Output = T> + Send,
|
|
|
|
-) -> impl 'a + Future<Output = T> + Send {
|
|
|
|
- fut
|
|
|
|
-}
|
|
|