made the Stream return a single message at each call

This commit is contained in:
Jędrzej Stuczyński
2023-08-09 14:39:57 +01:00
parent e705b76b36
commit de6c1ba1f0
3 changed files with 55 additions and 10 deletions
@@ -28,9 +28,7 @@ async fn main() {
// receiving task
tokio::spawn(async move {
if let Some(received) = client.next().await {
for r in received {
println!("Received: {}", String::from_utf8_lossy(&r.message));
}
println!("Received: {}", String::from_utf8_lossy(&received.message));
}
client.disconnect().await;
+4 -4
View File
@@ -496,15 +496,15 @@ where
let reconstructed_receiver = client_output.register_receiver()?;
Ok(MixnetClient {
Ok(MixnetClient::new(
nym_address,
client_input,
client_output,
client_state,
reconstructed_receiver,
task_manager: started_client.task_manager,
packet_type: None,
})
started_client.task_manager,
None,
))
}
}
+50 -3
View File
@@ -2,7 +2,8 @@ use crate::mixnet::client::MixnetClientBuilder;
use crate::mixnet::traits::MixnetMessageSender;
use crate::{Error, Result};
use async_trait::async_trait;
use futures::{Stream, StreamExt};
use futures::{ready, Stream, StreamExt};
use log::error;
use nym_client_core::client::{
base_client::{ClientInput, ClientOutput, ClientState},
inbound_messages::InputMessage,
@@ -42,9 +43,33 @@ pub struct MixnetClient {
/// The task manager that controlls all the spawned tasks that the clients uses to do it's job.
pub(crate) task_manager: TaskManager,
pub(crate) packet_type: Option<PacketType>,
// internal state used for the `Stream` implementation
_buffered: Vec<ReconstructedMessage>,
}
impl MixnetClient {
pub(crate) fn new(
nym_address: Recipient,
client_input: ClientInput,
client_output: ClientOutput,
client_state: ClientState,
reconstructed_receiver: ReconstructedMessagesReceiver,
task_manager: TaskManager,
packet_type: Option<PacketType>,
) -> Self {
Self {
nym_address,
client_input,
client_output,
client_state,
reconstructed_receiver,
task_manager,
packet_type,
_buffered: Vec::new(),
}
}
/// Create a new client and connect to the mixnet using ephemeral in-memory keys that are
/// discarded at application close.
///
@@ -145,10 +170,32 @@ pub struct MixnetClientSender {
}
impl Stream for MixnetClient {
type Item = Vec<ReconstructedMessage>;
type Item = ReconstructedMessage;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Pin::new(&mut self.reconstructed_receiver).poll_next(cx)
if let Some(next) = self._buffered.pop() {
cx.waker().wake_by_ref();
return Poll::Ready(Some(next));
}
match ready!(Pin::new(&mut self.reconstructed_receiver).poll_next(cx)) {
None => Poll::Ready(None),
Some(mut msgs) => {
// the vector itself should never be empty
if let Some(next) = msgs.pop() {
// there's more than a single message - buffer them and wake the waker
// to get polled again immediately
if !msgs.is_empty() {
self._buffered = msgs;
cx.waker().wake_by_ref();
}
Poll::Ready(Some(next))
} else {
error!("the reconstructed messages vector is empty - please let the developers know if you see this message");
cx.waker().wake_by_ref();
Poll::Pending
}
}
}
}
}