-
Notifications
You must be signed in to change notification settings - Fork 1k
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
[tcp] Port-reuse, async-io, if-watch #1887
Conversation
To avoid spawning a background task and thread within `TcpConfig::new()`, with communication via unbounded channels, a `TcpConfig` now keeps track of the listening addresses for port reuse in an `Arc<RwLock>`. Furthermore, an `IfWatcher` is only used by a `TcpListenStream` if it listens on any interface and directly polls the `IfWatcher` both for initialisation and new events. Includes some documentation and test enhancements.
Looks good to me, I like the changes. |
I think
|
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 changes look good to me. Thank you for the elaborate documentation.
Windows and Mac support
I have only tested this on Linux, not Mac nor Windows. Did you had a chance to test either of these platforms?
Tokio support
This pull request removes the tokio based chat example. I would suggest either:
-
Resurrecting the tokio chat example, using a tokio runtime to poll the async-io based TCP stack.
-
Introduce a test polling the async-io TCP stack with a tokio runtime.
I would prefer the latter. Having an automated way to ensure compatibility with async-std and tokio will make maintaining this stack a lot easier. This also ties into the concerns raised above by @quininer.
It is not intended to replace tokio. We are aware that there will be an extra |
I actually intended to re-add it but forgot about it, thanks for the reminder. |
It does replace tokio, it replaces tokio's reactor.
I don't use mdns, sorry, I didn't pay attention to it.
Yes, I want to use tokio's reactor. I think the quality of
I don't think that giving up support is a compromise. But I can understand the difficulty of maintaining both codes, and I will try to provide an abstraction layer. |
Ok, I hope we can find a solution that is acceptable to both |
I plan to work in a separate crate, and I will open a PR when finished. :)
This is unacceptable to me, and I will not update the libp2p version until problem is resolved. |
Yes it uses a C dependency on windows. But conceptionally this is a large step forward, completely separating the reactor from the executor.
Can you elaborate? I am interested in fixing any issues, but it seems a bit like a baseless claim.
That is the advantage of
Can you explain what solution you have in mind? Interestingly @djc also does not find it a good solution on the grounds that "the ecosystem split is overblown as most production users use tokio" and @Darksonn also expressed that this "isn't a solution" suggesting generics instead. Sorry for paraphrasing or if I misrepresented opinions. |
I'm not sure where exactly you are paraphrasing me from, but it does sound like something I would say. Generally I do not think that code that always uses a specific reactor is executor independent. That said, I'm not surprised that you find using macros to write Tokio and async-std versions of the library cumbersome, and I definitely support doing something else. It is almost always possible to write the code using generics rather than macros, and if this is something that you are interested in, I would be happy to point you in the right direction. Note that you do not have to expose a generic interface to the user. For example, hyper provides a non-generic interface using Tokio by default, but you can swap it out via an API based on generics. You could choose to provide non-generic versions with Tokio/async-std's types hard-coded together with an option to use the generic API directly for users that are on a third runtime. |
I don't think C dependency is a large step forward.
I will not respond to it, this is off topic.
No one is talking about executor, I only focus on reactor.
There are many solutions, the simplest is to use features-gate to abstract a minimal subset. A better solution is to use factory generics, which will allow users to customize any tcp stream, not just |
I assume you are aware that compiling anything on windows requires a c toolchain. And mio uses miow written by @yoshuawuts one of the main async-std contributors. I really wouldn't want you to have to use such low quality code. |
@dvc94ch I don't want to discuss digressions with you, please let us focus on how to solve the problem. miow was transferred to @yoshuawuyts at my suggestion, if you know. see yoshuawuyts/miow#23 (comment) |
@quininer thank you for offering to fix this problem, looking forward to you solution. I guess you can get started on if-watch and open a PR. In the interest of not blocking this PR indefeninitely I'd ask you to commit to a timeline. Is 10d until the 25.12.20 enough time for you? |
I do not intend and have no ability to block the PR, I just put forward my opinion, the PR can be merged as it is. |
Again thanks for all the comments. I think for the rust-libp2p maintainers it is as simple as this: If there are tokio users who do take offence with some crates using Regarding the future of this PR, I personally would only be merging it before we find a better abstraction if I can at least temporarily get |
I'd suggest keeping the tcp feature flag and add a |
@romanb any chance we can get this released before christmas? |
Unlikely, since I think many people will be on vacation next week or earlier, including myself, so that proper review of further changes is not really possible. I will update this PR as soon as I have a new proposal for keeping |
To avoid having an extra reactor thread running for tokio users and to make sure all TCP I/O uses the mio-based tokio reactor. Thereby run tests with both backends.
With the recent commits I reintroduced feature flags for What is still missing from this PR is the resurrection of the tokio chat example, which I intend to do early next week before this PR may be merged and released, but I wanted to make the latest changes already visible now for further review. |
This looks great! I made this, but I haven't opened the PR yet. |
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 like the recent additions. I find the Provider
abstraction with the two zero-variant enums neat. I will take another look once the example is in place. Thank you for putting more time and thoughts into this.
I am happy to wait some more in case @quininer would like to suggest additional changes.
Well, at this point you defaced the implementation. Looks like libp2p-rs just achieved feature parity with rust-libp2p. |
I'm not sure I follow. The only difference of the current version to the one you liked is that all
That is great, especially if it is more to your liking, since it seems to specialise for |
Co-authored-by: Max Inden <mail@max-inden.de>
tokio = { version = "0.3", default-features = false, features = ["net"], optional = true } | ||
log = "0.4.11" | ||
socket2 = { version = "0.3.17", features = ["reuseport"] } | ||
tokio-crate = { package = "tokio", version = "0.3", default-features = false, features = ["net"], optional = true } |
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.
Maybe we can use tokio 1.0?
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.
This PR is a continuation of #1845. To recap the main changes:
Permit port reuse for local sockets, primarily to facilitate better NAT traversal. In this context
address_translation
is moved back to theTransport
trait, where it already existed at some point in the past, to allow transport-specific translations, as now used for the TCP transport.Use
async-io
instead of macro-based code generation to support bothtokio
andasync-std
with less boilerplate and for easier code maintenance, thereby removing the need for the respective feature flags, similarly to how it was already done forlibp2p-mdns
.In
libp2p-tcp
, when listening on all interfaces, instead of regularly querying the interfaces withget_if_addrs
to be aware of both new and expired addresses, useif-watch
to be actively notified of interface addresses as they go up/down.Compared to #1845 I made the following changes:
TcpConfig::new()
is no longerasync
and it creates neither background task nor thread. If port reuse is enabled onTcpConfig
(and only then), the listen socket addresses are registered for reuse for outbound connections in anArc<RwLock<HashSet>>
. They are in turn unregistered whenTcpListenStream
s encounter fatal errors or are dropped.A
TcpListenStream
uses anIfWatcher
only if its listen socket is listening on all interfaces, analogously to the previous use ofget_if_addrs
in this case, with the advantage that theTcpListenStream
is aware of expired addresses immediately. If used, theIfWatcher
is lazily initialised when polling theTcpListenStream
for events. ThereforeTcpConfig::new()
need not beasync
, reducing the changes to the public API and making for a smaller diff.<TcpConfig as Transport>::address_translation(listen, observed)
now returnsSome(observed)
when port reuse is enabled instead ofNone
, as we want theobserved
address to be advertised to other peers as an "external address" as-is. I believe that returningNone
as was done in Tcp #1845 is an oversight, but please correct me if I'm mistaken.More elaborate documentation, especially for the new
TcpConfig::port_reuse()
option as well as small test additions.