-
Notifications
You must be signed in to change notification settings - Fork 117
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
Emit global uTP payload event in uTP listener when an uTP stream is closed/reset #325
Conversation
78d9946
to
a0a2b33
Compare
13657f7
to
ce193a8
Compare
52115d4
to
19c866d
Compare
19c866d
to
8debf1f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
f7f95b1
to
f303b9a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm generally opposed to this sort of approach, where we send messages to UtpListener
to "ask" for closed uTP streams. In my view, it adds both unnecessary complexity and unnecessary resource consumption.
The approach I would suggest is similar to the way Discv5
emits Discv5Event
to a channel that we can stream. Upon socket close, UtpListener
can emit some message to a channel where the message contains the socket info and any data that the socket received. OverlayService
can listen to this channel to handle those messages.
Yeah, this seems a more robust way to handle the closed streams. Here is an implementation of the above using a global overlay event: ogenev@7ba8356 However, this will require an event channel per network because if we emit a global overlay event, then only one of the overlay networks will consume it because we will run multiple overlay protocols. Also, the connection state is closed inside One major issue I realized today is that now I will try to refactor a bit and first store all active uTP connections in As we are using the same Let me know what you think and if this makes sense to you! |
You know the
My initial thought was that it would work similar to
I really think doing some form of polling is the wrong direction. It seems like it should be possible for the
If Hope these thoughts were helpful. |
Good, I updated the PR description with some TODOs and will re-open it for review when all of them are done. |
9a930fe
to
2e8a7f2
Compare
64f9cf4
to
c5775bf
Compare
As this PR is becoming quite large, I'm going to wrap it and include only the first 3 TODOs here. Updated PR's description and It is open for review now. Implementation of the overlay handler that will dispatch the |
c5775bf
to
5b94bb4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 to the architecture decision & implementation that resulted from the above conversation.
I left some suggestions about comments and naming. Let me know if I've misunderstood anything.
pub enum UtpMessageId { | ||
/// Used to track which stream to which overlay request correspond | ||
#[derive(Debug, Clone, PartialEq)] | ||
pub enum UtpStreamId { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name UtpStreamId
is a bit confusing to me, I think because ConnId
is already acting as an identifier for streams.
I wonder if UtpStreamDataType
or UtpStreamOrigin
would be a more descriptive name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConnId
is not really an identifier for streams in the portal network context, it is identifying all the packets that belong to the same connection. Each uTP socket has one connection ID for sending packets and a different connection ID for receiving packets.
Anyways, I'm happy to rename this if it will improve code readability, what is your opinion @jacobkaufmann?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea sorry I wasn't making sense by conflating the terms stream and connection.
Passing something non-numeric called Id
in the same calls as a numeric Id
is what seemed off to me.
Though looking back, I think I'm splitting hairs. I'm good with leaving it as it is, unless anyone else likes the name UtpStreamOrigin
or UtpStreamDataType
a bit better too.
trin-core/src/utp/stream.rs
Outdated
oneshot::Sender<anyhow::Result<UtpStream>>, | ||
), | ||
/// Request to add uTP stream to the active connections | ||
AddActiveConnection(Enr, ProtocolId, UtpStreamId, ConnId), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if InitiateConnection
would be a more descriptive name for this event.
The name AddActiveConnection
is a little bit confusing to me because it seems like both Connect
and AddActiveConnection
events add an active connection to the utp_connections
. In fact, Connect
seems like it creates more of an "active" connection than AddActiveConnection
does, because by the time a Connect
event happens we necessarily have two participants in the stream, whereas an AddActiveConnection
might only ever result in an inactive connection if the other peer never connects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, the idea of AddActiveConnection
is to create an uTP stream and start listening for incoming SYN packets.
Connect
is creating an uTP stream and is sending SYN packet for a handshake with the remote peer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I feel that there are some comments that we ought to address before merge, but most of my comments are minor or questions about things I don't quite understand. Would like to get clarity on those questions before approval.
In the future, we should minimize refactor changes like naming that add a lot of non-logical line changes to the diff. If possible, deferring those changes can make the PR less noisy.
0674632
to
68e5c81
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor comments, but looks good overall. Giving approval on the assumption that we tested that this does not break any existing uTP functionality with other portal client implementations.
trin-core/src/utp/stream.rs
Outdated
utp_message_id | ||
// Send content data if the stream is listening for FindContent SYN packet | ||
if let UtpStreamId::FindContentData(content_data) = | ||
conn.stream_id.clone() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this clone here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least for now (until we update to rust 1.62), borrowing here shows a warning cannot borrow "*conn" as mutable because it is also borrowed as immutable
. More information can be read here.
{ | ||
// We want to send uTP data only if the content is Content(ByteList) | ||
tokio::spawn(async move { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we no longer doing this in a separate task?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for this at the moment, spawning a new task here requires additional refactoring and adds more complexity. If it causes performance issues, we will change this in the future.
// TODO: Creating random NodeID here just to satisfy handle_find_content signature | ||
// is a hack on top of the history RecursiveFindContent temporally hack. | ||
let node_id = NodeId::random(); | ||
Ok(Response::Content( | ||
self.handle_find_content(find_content, &node_id)?, | ||
)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this does not work, then should we make the NodeId
argument an Option<NodeId>
for handle_find_content
? I would prefer not to have this sort of logic here if we can avoid it.
… outside UtpListener
…P socket closing
68e5c81
to
88ca107
Compare
88ca107
to
92f7a2e
Compare
What was wrong?
UtpListener
runs as a self-contained service in the background and handles all active uTP streams.We need a way to process all closed uTP streams and pass the payload to the overlay service, so we can verify, store and propagate gossip/POKE the received content via uTP.
Subtask of #313.
How was it fixed?
UtpSocket
toUtpStream
.AddActiveConnection
UtpListener request and move the initialization of an uTP stream inside UtpListener.UtpStream
->UtpListener
event channel and emit event insideUtpSocket
when stream state changes toClosed
orReset
.UtpStream
event,UtpListener
processes this event (doing some simple active streams maintenance by removing closed or reset streams) and emit a globalUtpListenerEvent
Manually tested OFFER/ACCEPT scenarios with Fluffy.
To-Do
The next two tasks will be addressed in the next PR (#337) as this is becoming quite large: