Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixnet message handle #435

Merged
merged 15 commits into from
Sep 26, 2023
Merged

Mixnet message handle #435

merged 15 commits into from
Sep 26, 2023

Conversation

al8n
Copy link
Contributor

@al8n al8n commented Sep 25, 2023

Refactor the mixnet fan-in. There are no locks anymore, only one message handle thread. All messages will be sent to the message thread handler, and the message thread will handle send and retry logic.

@al8n al8n added the mixnet label Sep 25, 2023
@al8n al8n added this to the Mixnet milestone Sep 25, 2023
@al8n al8n self-assigned this Sep 25, 2023
@al8n al8n changed the base branch from master to mixnet-error September 25, 2023 06:07
Base automatically changed from mixnet-error to master September 25, 2023 06:21
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
Comment on lines 319 to 330
if msg.retry_count < self.config.max_retries {
msg.retry_count += 1;
return Ok(Some(msg));
}

tracing::error!(
"failed to forward msg to {}: reach the maximum retries",
msg.target,
);
Err(MixnetNodeError::Protocol(ProtocolError::ReachMaxRetries(
self.config.max_retries,
)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have this check twice at the beginning of the function

Comment on lines 271 to 283
if let std::collections::hash_map::Entry::Vacant(e) = self.connections.entry(msg.target) {
match TcpStream::connect(msg.target).await {
Ok(tcp) => {
e.insert(tcp);
}
Err(e) => {
tracing::error!("failed to connect to {}: {e}", msg.target);
return Ok(Some(msg));
}
}
}

let tcp = self.connections.get_mut(&msg.target).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let tcp = self.connections.entry(msg.target).or_insert_with(|| {TcpStream::connect(...)}).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems cannot be done by this way, TcpStream::connect is an async fn.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my bad, you're right!

Comment on lines 259 to 263
/// Send a message to the remote node,
/// return Ok(Some((Duration, Message))) if the message is not sent and the error is retryable
/// return Ok(None) if the message is sent successfully
/// return Err(e) if the message is not sent and the error is not retryable
async fn send(&mut self, mut msg: TargetedMessage) -> Result<Option<TargetedMessage>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hard to read even with a doc comment. I would suggest we create a new enum with more descriptive variantas

Comment on lines 238 to 240
Ok(Some(msg)) => {
let _ = self.message_tx.send(msg);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an example of why the signature of the function it's hard to read, also, a comment explaining this re-queues the message would be helpful, as it's not explicit where the other half of the channel is

}
}
}
Err(e) => self.handle_connection_failure(e, target, body, retry_count),
Copy link
Contributor

@zeegomo zeegomo Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: handle_connection_failure and handle_retry are quite similar, can we reduce duplication?

One idea could be to have something like this but you can get creative!

match self.get_connection(target).await.map(|..| body.write(tcp)) {  // async map exists somewhere
    Err(e) if matches!(err.kind(), ...) | Ok(Err(e)) if e.kind() != ErrorKind::Unsupported => {
      // do the retry with a single shared function
   }
   Ok(Ok(_)) => happy case
   // maybe other cases
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I don't think we need to make Message as enum. I guess we can leave it as it was.

@al8n al8n requested a review from zeegomo September 25, 2023 11:35
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
Comment on lines 266 to 270
async fn handle_msg(&mut self, msg: Message) {
self.send(msg.target, msg.body, msg.retry_count).await
}

async fn send(&mut self, target: SocketAddr, body: Body, retry_count: usize) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have the Message struct, what do you think about having only the send function which accepts a Message? Also, I think we can simplify the signature of the handle_retry function below in the same way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed the signature, but do not know why GitHub does not show the changes.

mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
mixnet/node/src/lib.rs Show resolved Hide resolved
Copy link
Contributor

@youngjoon-lee youngjoon-lee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this works as intended, but I think some things can be polished.

mixnet/node/src/lib.rs Outdated Show resolved Hide resolved
Comment on lines 304 to 308
pub struct Message {
target: SocketAddr,
body: Body,
retry_count: usize,
}
Copy link
Contributor

@youngjoon-lee youngjoon-lee Sep 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the mixnet-related crates, I would like to suggest to have clearly separated terminologies for 'message' and 'packet'. As we've seen so far, we call the object, that the mixnet end-user wants to send, "message". The message is splitted into "packet"s by the mixclient, and these packets are sent to mixnodes. The mixnode forwards packets to other mixnodes, not messages (Only one additional case is that the mixnode also forwards "final payloads" to the destination mixnode).

That is, we don't need to use the terminology "message" in the mixnode layer. In this PR, these two or three terminologies are mixed. This will cause confusions in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the thread is PacketHandler but the struct is "message", which is misleading. I change all "message" to "packet".

.await
.map_err(Into::into);
.map_err(From::from)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Ok(body.write(...).await?) should also work

}
},
_ = tokio::signal::ctrl_c() => {
tracing::info!("Shutting down packet forwarder thread...");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it's not a thread, it's a task

self.send(pkt).await;
} else {
// Channel closed, we should shutdown the packet forwarder thread
tracing::info!("Channel closed, shutting down packet forwarder thread...");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

if let Some(pkt) = pkt {
self.send(pkt).await;
} else {
// Channel closed, we should shutdown the packet forwarder thread
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: not sure it's possible since PacketForwarder internally stores the sending half

@al8n al8n merged commit 8ea341d into master Sep 26, 2023
11 checks passed
@al8n al8n deleted the mixnet-message-handle branch September 26, 2023 10:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants