// Copyright 2023 - Nym Technologies SA // 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::TaskClient; use serde::de::DeserializeOwned; use std::sync::Arc; pub type ReceivedSender = mpsc::UnboundedSender>; pub type ReceivedReceiver = mpsc::UnboundedReceiver>; // the 'Simple' bit comes from the fact that it expects all received messages to consist of a single `Fragment` pub struct SimpleMessageReceiver { message_processor: TestPacketProcessor, mixnet_message_receiver: mpsc::UnboundedReceiver>>, acks_receiver: mpsc::UnboundedReceiver>>, received_sender: ReceivedSender, shutdown: TaskClient, } impl SimpleMessageReceiver { pub fn new_sphinx_receiver( local_encryption_keypair: Arc, ack_key: Arc, mixnet_message_receiver: mpsc::UnboundedReceiver>>, acks_receiver: mpsc::UnboundedReceiver>>, received_sender: ReceivedSender, shutdown: TaskClient, ) -> Self { Self::new( local_encryption_keypair, ack_key, mixnet_message_receiver, acks_receiver, received_sender, shutdown, ) } } impl SimpleMessageReceiver { pub fn new( local_encryption_keypair: Arc, ack_key: Arc, mixnet_message_receiver: mpsc::UnboundedReceiver>>, acks_receiver: mpsc::UnboundedReceiver>>, received_sender: ReceivedSender, shutdown: TaskClient, ) -> Self { SimpleMessageReceiver { message_processor: TestPacketProcessor::new(local_encryption_keypair, ack_key), mixnet_message_receiver, acks_receiver, received_sender, shutdown, } } fn forward_received>>(&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) -> 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) -> 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, { while !self.shutdown.is_shutdown() { tokio::select! { biased; _ = self.shutdown.recv() => { log_info!("SimpleMessageReceiver: received shutdown") } 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") } }