pub use crate::protocols::rpc::error::RpcError;
use crate::{
error::NetworkError,
peer_manager::{
ConnectionNotification, ConnectionRequestSender, PeerManagerNotification,
PeerManagerRequestSender,
},
transport::ConnectionMetadata,
ProtocolId,
};
use aptos_logger::prelude::*;
use aptos_types::{network_address::NetworkAddress, PeerId};
use async_trait::async_trait;
use bytes::Bytes;
use channel::aptos_channel;
use futures::{
channel::oneshot,
future,
stream::{FilterMap, FusedStream, Map, Select, Stream, StreamExt},
task::{Context, Poll},
};
use pin_project::pin_project;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use short_hex_str::AsShortHexStr;
use std::{cmp::min, iter::FromIterator, marker::PhantomData, pin::Pin, time::Duration};
use super::wire::handshake::v1::ProtocolIdSet;
use std::fmt::Debug;
pub trait Message: DeserializeOwned + Serialize {}
impl<T: DeserializeOwned + Serialize> Message for T {}
#[derive(Debug)]
pub enum Event<TMessage> {
Message(PeerId, TMessage),
RpcRequest(
PeerId,
TMessage,
ProtocolId,
oneshot::Sender<Result<Bytes, RpcError>>,
),
NewPeer(ConnectionMetadata),
LostPeer(ConnectionMetadata),
}
impl<TMessage: PartialEq> PartialEq for Event<TMessage> {
fn eq(&self, other: &Event<TMessage>) -> bool {
use Event::*;
match (self, other) {
(Message(pid1, msg1), Message(pid2, msg2)) => pid1 == pid2 && msg1 == msg2,
(RpcRequest(pid1, msg1, proto1, _), RpcRequest(pid2, msg2, proto2, _)) => {
pid1 == pid2 && msg1 == msg2 && proto1 == proto2
}
(NewPeer(metadata1), NewPeer(metadata2)) => metadata1 == metadata2,
(LostPeer(metadata1), LostPeer(metadata2)) => metadata1 == metadata2,
_ => false,
}
}
}
#[derive(Clone, Default)]
pub struct AppConfig {
pub protocols: ProtocolIdSet,
pub inbound_queue: Option<aptos_channel::Config>,
}
impl AppConfig {
pub fn client(protocols: impl IntoIterator<Item = ProtocolId>) -> Self {
Self {
protocols: ProtocolIdSet::from_iter(protocols),
inbound_queue: None,
}
}
pub fn service(
protocols: impl IntoIterator<Item = ProtocolId>,
inbound_queue: aptos_channel::Config,
) -> Self {
Self {
protocols: ProtocolIdSet::from_iter(protocols),
inbound_queue: Some(inbound_queue),
}
}
pub fn p2p(
protocols: impl IntoIterator<Item = ProtocolId>,
inbound_queue: aptos_channel::Config,
) -> Self {
Self {
protocols: ProtocolIdSet::from_iter(protocols),
inbound_queue: Some(inbound_queue),
}
}
}
#[pin_project]
pub struct NetworkEvents<TMessage> {
#[pin]
event_stream: Select<
FilterMap<
aptos_channel::Receiver<(PeerId, ProtocolId), PeerManagerNotification>,
future::Ready<Option<Event<TMessage>>>,
fn(PeerManagerNotification) -> future::Ready<Option<Event<TMessage>>>,
>,
Map<
aptos_channel::Receiver<PeerId, ConnectionNotification>,
fn(ConnectionNotification) -> Event<TMessage>,
>,
>,
_marker: PhantomData<TMessage>,
}
pub trait NewNetworkEvents {
fn new(
peer_mgr_notifs_rx: aptos_channel::Receiver<(PeerId, ProtocolId), PeerManagerNotification>,
connection_notifs_rx: aptos_channel::Receiver<PeerId, ConnectionNotification>,
) -> Self;
}
impl<TMessage: Message> NewNetworkEvents for NetworkEvents<TMessage> {
fn new(
peer_mgr_notifs_rx: aptos_channel::Receiver<(PeerId, ProtocolId), PeerManagerNotification>,
connection_notifs_rx: aptos_channel::Receiver<PeerId, ConnectionNotification>,
) -> Self {
let data_event_stream = peer_mgr_notifs_rx.filter_map(
peer_mgr_notif_to_event
as fn(PeerManagerNotification) -> future::Ready<Option<Event<TMessage>>>,
);
let control_event_stream = connection_notifs_rx
.map(control_msg_to_event as fn(ConnectionNotification) -> Event<TMessage>);
Self {
event_stream: ::futures::stream::select(data_event_stream, control_event_stream),
_marker: PhantomData,
}
}
}
impl<TMessage> Stream for NetworkEvents<TMessage> {
type Item = Event<TMessage>;
fn poll_next(self: Pin<&mut Self>, context: &mut Context) -> Poll<Option<Self::Item>> {
self.project().event_stream.poll_next(context)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.event_stream.size_hint()
}
}
fn peer_mgr_notif_to_event<TMessage: Message>(
notif: PeerManagerNotification,
) -> future::Ready<Option<Event<TMessage>>> {
let maybe_event = match notif {
PeerManagerNotification::RecvRpc(peer_id, rpc_req) => {
request_to_network_event(peer_id, &rpc_req)
.map(|msg| Event::RpcRequest(peer_id, msg, rpc_req.protocol_id, rpc_req.res_tx))
}
PeerManagerNotification::RecvMessage(peer_id, request) => {
request_to_network_event(peer_id, &request).map(|msg| Event::Message(peer_id, msg))
}
};
future::ready(maybe_event)
}
fn request_to_network_event<TMessage: Message, Request: SerializedRequest>(
peer_id: PeerId,
request: &Request,
) -> Option<TMessage> {
match request.to_message() {
Ok(msg) => Some(msg),
Err(err) => {
let data = &request.data();
warn!(
SecurityEvent::InvalidNetworkEvent,
error = ?err,
remote_peer_id = peer_id.short_str(),
protocol_id = request.protocol_id(),
data_prefix = hex::encode(&data[..min(16, data.len())]),
);
None
}
}
}
fn control_msg_to_event<TMessage>(notif: ConnectionNotification) -> Event<TMessage> {
match notif {
ConnectionNotification::NewPeer(metadata, _context) => Event::NewPeer(metadata),
ConnectionNotification::LostPeer(metadata, _context, _reason) => Event::LostPeer(metadata),
}
}
impl<TMessage> FusedStream for NetworkEvents<TMessage> {
fn is_terminated(&self) -> bool {
self.event_stream.is_terminated()
}
}
#[derive(Clone, Debug)]
pub struct NetworkSender<TMessage> {
peer_mgr_reqs_tx: PeerManagerRequestSender,
connection_reqs_tx: ConnectionRequestSender,
_marker: PhantomData<TMessage>,
}
pub trait NewNetworkSender {
fn new(
peer_mgr_reqs_tx: PeerManagerRequestSender,
connection_reqs_tx: ConnectionRequestSender,
) -> Self;
}
impl<TMessage> NewNetworkSender for NetworkSender<TMessage> {
fn new(
peer_mgr_reqs_tx: PeerManagerRequestSender,
connection_reqs_tx: ConnectionRequestSender,
) -> Self {
Self {
peer_mgr_reqs_tx,
connection_reqs_tx,
_marker: PhantomData,
}
}
}
impl<TMessage> NetworkSender<TMessage> {
pub async fn dial_peer(&self, peer: PeerId, addr: NetworkAddress) -> Result<(), NetworkError> {
self.connection_reqs_tx.dial_peer(peer, addr).await?;
Ok(())
}
pub async fn disconnect_peer(&self, peer: PeerId) -> Result<(), NetworkError> {
self.connection_reqs_tx.disconnect_peer(peer).await?;
Ok(())
}
}
impl<TMessage: Message> NetworkSender<TMessage> {
pub fn send_to(
&self,
recipient: PeerId,
protocol: ProtocolId,
message: TMessage,
) -> Result<(), NetworkError> {
let mdata = protocol.to_bytes(&message)?.into();
self.peer_mgr_reqs_tx.send_to(recipient, protocol, mdata)?;
Ok(())
}
pub fn send_to_many(
&self,
recipients: impl Iterator<Item = PeerId>,
protocol: ProtocolId,
message: TMessage,
) -> Result<(), NetworkError> {
let mdata = protocol.to_bytes(&message)?.into();
self.peer_mgr_reqs_tx
.send_to_many(recipients, protocol, mdata)?;
Ok(())
}
pub async fn send_rpc(
&self,
recipient: PeerId,
protocol: ProtocolId,
req_msg: TMessage,
timeout: Duration,
) -> Result<TMessage, RpcError> {
let req_data = protocol.to_bytes(&req_msg)?.into();
let res_data = self
.peer_mgr_reqs_tx
.send_rpc(recipient, protocol, req_data, timeout)
.await?;
let res_msg: TMessage = protocol.from_bytes(&res_data)?;
Ok(res_msg)
}
}
#[async_trait]
pub trait ApplicationNetworkSender<TMessage: Send>: Clone {
fn send_to(&self, _recipient: PeerId, _message: TMessage) -> Result<(), NetworkError> {
unimplemented!()
}
fn send_to_many(
&self,
_recipients: impl Iterator<Item = PeerId>,
_message: TMessage,
) -> Result<(), NetworkError> {
unimplemented!()
}
async fn send_rpc(
&self,
recipient: PeerId,
req_msg: TMessage,
timeout: Duration,
) -> Result<TMessage, RpcError>;
}
pub trait SerializedRequest {
fn protocol_id(&self) -> ProtocolId;
fn data(&self) -> &Bytes;
fn to_message<'a, TMessage: Deserialize<'a>>(&'a self) -> anyhow::Result<TMessage> {
self.protocol_id().from_bytes(self.data())
}
}