0ee387d983
* squashing work on using cancellation in nym crates making nym-task wasm compilable removed sending of status messages replaced TaskManager with ShutdownManager in the validator rewarder additional helpers for ShutdownManager simplified ShutdownToken by removing the name field TaskClient => ShutdownToken within all client tasks wip: remove TaskHandle * track all long-living client tasks * add task tracking for most top level tasks within nym-node * improved default builder * split up cancellation module * module documentation and unit tests * nym node fixes and naming consistency * wasm fixes * assert_eq => assert * wasm fixes and made 'run_until_shutdown' take reference instead of ownership * linux-specific fixes to IpPacketRouter * post rebasing fixes for signing monitor * add ShutdownManager constructor to build it from an external token * applying PR review suggestions
131 lines
4.7 KiB
Rust
131 lines
4.7 KiB
Rust
// Copyright 2023 - Nym Technologies SA <contact@nymtech.net>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
use crate::error::NetworkTestingError;
|
|
use crate::processor::{Received, TestPacketProcessor};
|
|
use crate::{log_err, log_info, log_warn};
|
|
use futures::channel::mpsc;
|
|
use futures::StreamExt;
|
|
use nym_crypto::asymmetric::x25519;
|
|
use nym_sphinx::acknowledgements::AckKey;
|
|
use nym_sphinx::receiver::{MessageReceiver, SphinxMessageReceiver};
|
|
use nym_task::ShutdownToken;
|
|
use serde::de::DeserializeOwned;
|
|
use std::sync::Arc;
|
|
|
|
pub type ReceivedSender<T> = mpsc::UnboundedSender<Received<T>>;
|
|
pub type ReceivedReceiver<T> = mpsc::UnboundedReceiver<Received<T>>;
|
|
|
|
// the 'Simple' bit comes from the fact that it expects all received messages to consist of a single `Fragment`
|
|
pub struct SimpleMessageReceiver<T, R: MessageReceiver = SphinxMessageReceiver> {
|
|
message_processor: TestPacketProcessor<T, R>,
|
|
|
|
mixnet_message_receiver: mpsc::UnboundedReceiver<Vec<Vec<u8>>>,
|
|
acks_receiver: mpsc::UnboundedReceiver<Vec<Vec<u8>>>,
|
|
|
|
received_sender: ReceivedSender<T>,
|
|
shutdown: ShutdownToken,
|
|
}
|
|
|
|
impl<T> SimpleMessageReceiver<T, SphinxMessageReceiver> {
|
|
pub fn new_sphinx_receiver(
|
|
local_encryption_keypair: Arc<x25519::KeyPair>,
|
|
ack_key: Arc<AckKey>,
|
|
mixnet_message_receiver: mpsc::UnboundedReceiver<Vec<Vec<u8>>>,
|
|
acks_receiver: mpsc::UnboundedReceiver<Vec<Vec<u8>>>,
|
|
received_sender: ReceivedSender<T>,
|
|
shutdown: ShutdownToken,
|
|
) -> Self {
|
|
Self::new(
|
|
local_encryption_keypair,
|
|
ack_key,
|
|
mixnet_message_receiver,
|
|
acks_receiver,
|
|
received_sender,
|
|
shutdown,
|
|
)
|
|
}
|
|
}
|
|
|
|
impl<T, R: MessageReceiver> SimpleMessageReceiver<T, R> {
|
|
pub fn new(
|
|
local_encryption_keypair: Arc<x25519::KeyPair>,
|
|
ack_key: Arc<AckKey>,
|
|
mixnet_message_receiver: mpsc::UnboundedReceiver<Vec<Vec<u8>>>,
|
|
acks_receiver: mpsc::UnboundedReceiver<Vec<Vec<u8>>>,
|
|
received_sender: ReceivedSender<T>,
|
|
shutdown: ShutdownToken,
|
|
) -> Self {
|
|
SimpleMessageReceiver {
|
|
message_processor: TestPacketProcessor::new(local_encryption_keypair, ack_key),
|
|
mixnet_message_receiver,
|
|
acks_receiver,
|
|
received_sender,
|
|
shutdown,
|
|
}
|
|
}
|
|
|
|
fn forward_received<U: Into<Received<T>>>(&self, received: U) {
|
|
// TODO: remove the unwrap once/if we do graceful shutdowns here
|
|
self.received_sender
|
|
.unbounded_send(received.into())
|
|
.expect("ReceivedReceiver has stopped receiving");
|
|
}
|
|
|
|
fn on_mixnet_message(&mut self, raw_message: Vec<u8>) -> Result<(), NetworkTestingError>
|
|
where
|
|
T: DeserializeOwned,
|
|
{
|
|
let recovered = self.message_processor.process_mixnet_message(raw_message)?;
|
|
self.forward_received(recovered);
|
|
Ok(())
|
|
}
|
|
|
|
fn on_ack(&mut self, raw_ack: Vec<u8>) -> Result<(), NetworkTestingError> {
|
|
let frag_id = self.message_processor.process_ack(raw_ack)?;
|
|
self.forward_received(frag_id);
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn run(&mut self)
|
|
where
|
|
T: DeserializeOwned,
|
|
{
|
|
loop {
|
|
tokio::select! {
|
|
biased;
|
|
_ = self.shutdown.cancelled() => {
|
|
log_info!("SimpleMessageReceiver: received shutdown");
|
|
break
|
|
}
|
|
mixnet_messages = self.mixnet_message_receiver.next() => {
|
|
let Some(mixnet_messages) = mixnet_messages else {
|
|
log_err!("the mixnet messages stream has terminated!");
|
|
// note: this will cause global shutdown, but we have no choice if we stopped receiving mixnet messages
|
|
break
|
|
};
|
|
for message in mixnet_messages {
|
|
if let Err(err) = self.on_mixnet_message(message) {
|
|
log_warn!("failed to process received mixnet message: {err}")
|
|
}
|
|
}
|
|
}
|
|
acks = self.acks_receiver.next() => {
|
|
let Some(acks) = acks else {
|
|
log_err!("the ack messages stream has terminated!");
|
|
// note: this will cause global shutdown, but we have no choice if we stopped receiving mixnet messages
|
|
break
|
|
};
|
|
for ack in acks {
|
|
if let Err(err) = self.on_ack(ack) {
|
|
log_warn!("failed to process received ack message: {err}")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
log_info!("SimpleMessageReceiver: Exiting")
|
|
}
|
|
}
|