Mental model of NetworkBehaviour interaction and state managemnt in rust-libp2p #5883
Replies: 4 comments 1 reply
-
Hi! Below are all my personal opinions and I am not a maintainer of the repository, so take them with a huge grain of salt.
You may have to manage that "global state" manually.
Yes. DCUtR uses a relay(R in DCUtR) to do hole-punching through NAT firewalls. So there needs to be at least three peers, and the process doesn't happen automatically because you need to manually listen on the relay and the other peer needs to dial the listened address.
That's right.
This typically doesn't happen automatically. At least you should know which relay to connect to, with
Dialing is an independent process that only performs according to
I am currently working on an example to showcase the composability of
As far as I know, if you compose the behaviours correctly, both cases can have the same result. Because it eventually comes down to |
Beta Was this translation helpful? Give feedback.
-
If A needs to intercept events from B, or needs to call any methods from B. Another example would be when using the However, most of our existing protocols are independent, so you usually compose them as siblings. |
Beta Was this translation helpful? Give feedback.
-
Well, it depends on your network. It's a very common case that the nodes in the network are actually all public, like it is in the IPFS network from which libp2p originates. The libp2p spec on kademlia even states that kademlia servers should be publicly reachable.
It should return no info, because nodes (at least in rust-libp2p) only store a remote peer's address if we dialed it, which can never happen if the peer is not publicly reachable. Only exception is if the peer address was manually added through
Well if relay is active (and the remote peer actually listening via a relay) it would return the relayed address of the remote peer If you and the remote peer support the
I am not sure what you mean by this. Do you mean that peers should attempt a hole punch for establishing a relayed connection? |
Beta Was this translation helpful? Give feedback.
-
I'm not 100% confident in this but I'm pretty sure there is no global state shared between behaviours outside of what swarm passes to them as events (and the behaviour is expected to maintain that state internally when receiving the event, the event is transient). Identify emits events when it identifies new address candidates for a peer that, IIUC, you need to handle and wire into Kad to update its knowledge of peer addresses in its internal state.
We have had mixed results with NAT traversal. As @elenaf9 points out, relay is necessary to handle the signaling coordination to attempt a direct connection between two peers. In our network so far, we find many peers end up relying on the relay for the entire connection - they never do get through the NAT - though its still early and we don't have enough real world data yet to say this definitively. Also with the pluggable stack rust-libp2p provides, I expect us to be able to significantly reduce the longtail of clients that have to use relays over time. Here is my mental model on how NAT traversal works (in general, not just libp2p): https://www.blankenship.io/essays/2024-06-11/
IIUC all behaviours that use the swarm lifecycle hooks are transport/muxer agnostic. If you're implementing a file sharing protocol as a behaviour, it will be able to communicate over any end-to-end connection established by your transport layer (including relayed and direct connections if configured). I also haven't found any file sharing protocols that work with rust-libp2p though haven't gone looking in a while - we ended up implementing our own take on BitSwap to move files around our network. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I migrated this question from the forum because apparently this is the new place to ask questions
I'm trying to better understand how components of a rust-libp2p node interact, especially how network behaviours do. I found this thread very helpful already, but some questions remain open.
As context, I'm currently trying to build a file sharing application that should work well on a large amount of consumer devices that are likely behind NATs and firewalls. I expect to need at least
As explained in the post already mentioned above, the identify protocol should enhance peer discovery, as I understand by increasing the amount of knowledge that nodes in the network have about each other, but it's not required. So far so good. I also understand that this enhancement (a sort of interaction between kademlia and identify) roughly happens as follows:
Please correct me if any of that is (very) wrong.
I would characterize this behaviour as "very async". kademlia and identify do not strictly depend on each other in the sense that a specific sequence of events is particularly important to one or the other. Is that right?
I have noticed two interesting things in the file-sharing and dcutr (can't link, only allowed 2 links as new user) examples:
UPDATE: It does not work over the internet at all. The server listens on
127.0.0.1
. I'm trying to build that out to actually work over the internet, but no success, yeton_dial_attempt_first_hole_punch
functionality.I want to focus on the second point. If such a functionality does not exist, I see two options that this behaviour could fulfill its functions:
Could you clarify which of the two is close to the truth, what I still didn't get right, and any additional details you think would be important to understand?
I also don't yet know how the composability of NetworkBehaviours factors into this picture. Could you explain how the view of the network / general capabilities of Behavior B differs in the following two cases?
or in words: When would I nest B in A instead of make B a sibling of A?
And since we are at the topic of kademlia and hole punching, the final piece I'm not clear on is how kademlia acts without any sort of hole punching mechanism: It's purpose is peer discovery. Let's look at the case where I'm looking for some explicit PeerId. It's supposed to give me back a list of network addresses under which I can (probably) reach that peer, right?! For these addresses to be of use, they need to be dialable. So, assuming that the PeerId I'm querying is behind a firewall and no NAT traversal mechanism is enabled, would kademlia simply return no info on that peer, or would it return addresses that I can never dial successfully? And if e.g. dcutr is active, is it correct that it would return an address to the relay the peer has a reservation with, which I could then use to perform hole punching?
I realize this is a huge topic and I'm sorry to cram all that into a single post. I just really hope that someone can connect the dots between these inter-realated topics
Beta Was this translation helpful? Give feedback.
All reactions