-
Notifications
You must be signed in to change notification settings - Fork 984
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
Refactor the crate to use stable futures #1328
Conversation
* Switch to stable futures * Remove from_fn * Fix secio * Fix core --lib tests
* Upgrade libp2p-kad to stable futures * Fix comment
* protocols/noise: Fix obvious future errors * protocol/noise: Make Handshake methods independent functions * protocols/noise: Abstract T and C for handshake * protocols/noise: Replace FutureResult with Result * protocols/noise: Introduce recv_identity stub * protocols/noise: Implement recv_identity stub * protocols/noise: Change NoiseConfig::Future from Handshake to Result * protocols/noise: Adjust to new Poll syntax * protocols/noise: Return early on state creation failure * protocols/noise: Add bounds Async{Write,Read} to initiator / respoder * protocols/noise: Add Protocol trait bound for C in rt functions * protocols/noise: Do io operations on state.io instead of state * protocols/noise: Have upgrade_xxx return a pinned future * protocols/noise: Have NoiseOutput::poll_read self be mutable * protocols/noise: Make recv_identity buffers mutable * protocols/noise: Fix warnings * protocols/noise: Replace NoiseOutput io::Read impl with AsyncRead * protocols/noise: Replace NoiseOutput io::Write impl with AsyncWrite * protocols/noise: Adjust tests to new futures * protocols/noise: Don't use {AsyncRead,AsyncWrite,TryStream}*Ext* bound * protocols/noise: Don't use async_closure feature * protocols/noise: use futures::ready! macro * protocols/noise: Make NoiseOutput AsyncRead return unsafe NopInitializer The previous implementation of AsyncRead for NoiseOutput would operate on uninitialized buffers, given that it properly returned the number of bytest that were written to the buffer. With this patch the current implementation operates on uninitialized buffers as well by returning an Initializer::nop() in AsyncRead::initializer. * protocols/noise: Remove resolved TODO questions * protocols/noise: Remove 'this = self' comment Given that `let mut this = &mut *self` is not specific to a pinned self, but follows the dereference coercion [1] happening at compile time when trying to mutably borrow two distinct struct fields, this patch removes the code comment. [1] ```rust let x = &mut self.deref_mut().x; let y = &mut self.deref_mut().y; // error // --- let mut this = self.deref_mut(); let x = &mut this.x; let y = &mut this.y; // ok ``` * Remove redundant nested futures. * protocols/noise/Cargo: Update to futures preview 0.3.0-alpha.18 * protocols/noise: Improve formatting * protocols/noise: Return pinned future on authenticated noise upgrade * protocols/noise: Specify Output of Future embedded in Handshake directly * *: Ensure Noise handshake futures are Send * Revert "*: Ensure Noise handshake futures are Send" This reverts commit 555c2df. * protocols/noise: Ensure NoiseConfig Future is Send * protocols/noise: Use relative import path for {In,Out}boundUpgrade
Upgrade websocket transport to soketto 0.3.0.
* Configurable multistream-select protocol. Add V1Lazy variant. (#1245) Make the multistream-select protocol (version) configurable on transport upgrades as well as for individual substreams. Add a "lazy" variant of multistream-select 1.0 that delays sending of negotiation protocol frames as much as possible but is only safe to use under additional assumptions that go beyond what is required by the multistream-select v1 specification. * Improve the code readability of the chat example (#1253) * Add bridged chats (#1252) * Try fix CI (#1261) * Print Rust version on CI * Don't print where not appropriate * Change caching strategy * Remove win32 build * Remove win32 from list * Update libsecp256k1 dep to 0.3.0 (#1258) * Update libsecp256k1 dep to 0.3.0 * Sign now cannot fail * Upgrade url and percent-encoding deps to 2.1.0 (#1267) * Upgrade percent-encoding dep to 2.1.0 * Upgrade url dep to 2.1.0 * Fix more conflicts * Revert CIPHERS set to null (#1273)
* Configurable multistream-select protocol. Add V1Lazy variant. (#1245) Make the multistream-select protocol (version) configurable on transport upgrades as well as for individual substreams. Add a "lazy" variant of multistream-select 1.0 that delays sending of negotiation protocol frames as much as possible but is only safe to use under additional assumptions that go beyond what is required by the multistream-select v1 specification. * Improve the code readability of the chat example (#1253) * Add bridged chats (#1252) * Try fix CI (#1261) * Print Rust version on CI * Don't print where not appropriate * Change caching strategy * Remove win32 build * Remove win32 from list * Update libsecp256k1 dep to 0.3.0 (#1258) * Update libsecp256k1 dep to 0.3.0 * Sign now cannot fail * Upgrade url and percent-encoding deps to 2.1.0 (#1267) * Upgrade percent-encoding dep to 2.1.0 * Upgrade url dep to 2.1.0 * Revert CIPHERS set to null (#1273) * Update dependency versions (#1265) * Update versions of many dependencies * Bump version of rand * Updates for changed APIs in rand, ring, and webpki * Replace references to `snow::Session` `Session` no longer exists in `snow` but the replacement is two structs `HandshakeState` and `TransportState` Something will have to be done to harmonize `NoiseOutput.session` * Add precise type for UnparsedPublicKey * Update data structures/functions to match new snow's API * Delete diff.diff Remove accidentally committed diff file * Remove commented lines in identity/rsa.rs * Bump libsecp256k1 to 0.3.1 * Implement /plaintext/2.0.0 (#1236) * WIP * plaintext/2.0.0 * Refactor protobuf related issues to compatible with the spec * Rename: new PlainTextConfig -> PlainText2Config * Keep plaintext/1.0.0 as PlainText1Config * Config contains pubkey * Rename: proposition -> exchange * Add PeerId to Exchange * Check the validity of the remote's `Exchange` * Tweak * Delete unused import * Add debug log * Delete unused field: public_key_encoded * Delete unused field: local * Delete unused field: exchange_bytes * The inner instance should not be public * identity::Publickey::Rsa is not available on wasm * Delete PeerId from Config as it should be generated from the pubkey * Catch up for #1240 * Tweak * Update protocols/plaintext/src/error.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update protocols/plaintext/src/handshake.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update protocols/plaintext/src/error.rs Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Update protocols/plaintext/src/error.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Update protocols/plaintext/src/error.rs Co-Authored-By: Roman Borschel <romanb@users.noreply.github.com> * Rename: pubkey -> local_public_key * Delete unused error * Rename: PeerIdValidationFailed -> InvalidPeerId * Fix: HandShake -> Handshake * Use bytes insteadof Publickey to avoid code duplication * Replace with ProtobufError * Merge HandshakeContext<()> into HandshakeContext<Local> * Improve the peer ID validation to simplify the handshake * Propagate Remote to allow extracting the PeerId from the Remote * Collapse the same kind of errors into the variant * [noise]: `sodiumoxide 0.2.5` (#1276) Fixes rustsec/advisory-db#192 * examples/ipfs-kad.rs: Remove outdated reference to `without_init` (#1280) * CircleCI Test Fix (#1282) * Disabling "Docker Layer Caching" because it breaks one of the circleci checks * Bump to trigger CircleCI build * unbump * zeroize: Upgrade to v1.0 (#1284) v1.0 final release is out. Release notes: iqlusioninc/crates#279 * *: Consolidate protobuf scripts and update to rust-protobuf 2.8.1 (#1275) * *: Consolidate protobuf generation scripts * *: Update to rust-protobuf 2.8.1 * *: Mark protobuf generated modules with '_proto' * examples: Add distributed key value store (#1281) * examples: Add distributed key value store This commit adds a basic distributed key value store supporting GET and PUT commands using Kademlia and mDNS. * examples/distributed-key-value-store: Fix typo * Simple Warning Cleanup (#1278) * Cleaning up warnings - removing unused `use` * Cleaning up warnings - unused tuple value * Cleaning up warnings - removing dead code * Cleaning up warnings - fixing deprecated name * Cleaning up warnings - removing dead code * Revert "Cleaning up warnings - removing dead code" This reverts commit f18a765. * Enable the std feature of ring (#1289)
* *: Remove usage of custom buffer initialization usage With version `0.3.0-alpha.19` the futures-preview crate makes the `AsyncRead::initializer` API unstable. In order to improve interoperability with e.g. both a library depending on alpha.18 as well as a library depending on alpha.19 and in order for rust-libp2p to become stable again, this commit removes all usages of the unstable `initializer` API. * protocols/noise: Remove NoiseOutput Asyncread initializer * transports/tcp: Remove TcpTransStream AsyncRead initializer * *: Remove version pinning of futures-preview to 0.3.0-alpha.18 With version 0.3.0-alpha.19 the futures-preview crate makes the AsyncRead::initializer API unstable. Given that the previous commits removed usage of the initializer API, the version pinning is not needed any longer.
* Implement Debug for (ed25519|secp256k1)::(Keypair|SecretKey) (#1285) * Fix possible arithmetic overflow in libp2p-kad. (#1291) When the number of active queries exceeds the (internal) JOBS_MAX_QUERIES limit, which is only supposed to bound the number of concurrent queries relating to background jobs, an arithmetic overflow occurs. This is fixed by using saturating subtraction. * protocols/plaintext: Add example on how to upgrade with PlainTextConfig1 (#1286) * [mdns] - Support for long mDNS names (Bug #1232) (#1287) * Dead code -- commenting out with a note referencing future implementation * Adding "std" feature so that cargo can build in other directories (notably `misc/mdns`, so that I could run these tests) * Permitting `PeerID` to be built from an `Identity` multihash * The length limit for DNS labels is 63 characters, as per RFC1035 * Allocates the vector with capacity for the service name plus additional QNAME encoding bytes * Added support for encoding/decoding peer IDs with an encoded length greater than 63 characters * Removing "std" from ring features Co-Authored-By: Pierre Krieger <pierre.krieger1708@gmail.com> * Retaining MAX_INLINE_KEY_LENGTH with comment about future usage * `segment_peer_id` consumes `peer_id` ... plus an early return for IDs that don't need to be segmented * Fixing logic * Bump most dependencies (#1268) * Bump most dependencies This actually builds 😊. * Bump all dependencies Includes the excellent work of @rschulman in #1265. * Remove use of ed25519-dalek fork * Monomorphize more dependencies * Add compatibility hack for rand Cargo allows a crate to depend on multiple versions of another, but `cargo-web` panics in that situation. Use a wrapper crate to work around the panic. * Use @tomaka’s idea for using a newer `rand` instead of my own ugly hack. * Switch to Parity master as its dependency-bumping PR has been merged. * Update some depenendencies again * Remove unwraps and `#[allow(deprecated)]`. * Remove spurious changes to dependencies Bumping minor or patch versions is not needed, and increases likelyhood of merge conflicts. * Remove some redundant Cargo.toml changes * Replace a retry loop with an expect `ed25519::SecretKey::from_bytes` will never fail for 32-byte inputs. * Revert changes that don’t belong in this PR * Remove using void to bypass ICE (#1295) * Publish 0.13.0 (#1294)
* Update `rw-stream-sink` to futures-0.3. * Update core, tcp, secio and mplex to futures-0.3. On top of #1301
Update yamux to development version. For the boxed `futures::stream::Stream` we have to decide if we require a `Send` bound or not. Since some upgrades may produce outputs which are `!Send` we offer both upgrade versions.
* Update libp2p-uds to futures 0.3 * Some clean-up
…1306) * protocols/plaintext: Move to stable futures and use unsigned varints The plaintext 2.0 specification requires to use unsigned varints for frame length delimiting instead of fixed 4 byte integer frame length delimiting. This commit aligns the implementation with the specification. * protocols/secio: Fix doc comment BytesMut -> Vec<u8> * protocols/plaintext: Add quick check smoke test * protocols/plaintext: Rework imports and log levels * protocols/plaintext: Use BytesMut instead of Vec<u8> * protocols/plaintext: Use BoxFuture
* misc/mdns/service: Use async std with stack pinned futures * misc/mdns: Define mdns broadcast address as lazy static * misc/mdns: Drop future before borrowing their arguments again * misc/mdns: Send queries on query socket, not socket * misc/mdns: Use poll_next_unpin on query interval stream * misc/mdns: Ensure underlying task is woken up on next interval tick * misc/mdns: Wrap match expression in scope to drop future early * misc/mdns: Adjust 'discovery_ourselves' test * misc/mdns: Make query interval fire instantly on first tick This is an optimization only important for short lived use cases, e.g. unit tests. Instead of waiting for 20 seconds at first, the query interval fires right away and thereby the service makes progress instantly. * misc/mdns: Adjust MdnsService documentation tests * misc/mdns: Do not drop UDP socket send and reicv futures Libp2p-mdns uses the async-std crate for network io. This crate only offers async send and receive functions. In order to use this in non async/await functions one needs to keep the future returned by the crate functions around across `poll` invocations. The future returned by the crate functions references the io resource. Thus one has to keep both the io resource as well as the future referencing it. This results in a self-referencing struct which is not possible to create with safe Rust. Instead, by having `MdnsService::next` (former `MdnsService::poll`) take ownership of `self`, the Rust async magic takes care of the above (See code comments for more details). As a (negative) side effect, given that `MdnsService::next` takes ownership of `self`, there is nothing to bind the lifetime of the returned `MdnsPacket` to. With no better solution in mind, this patch makes `MdnsPacket` static, not referencing the `MdnsService` receive buffer. * misc/mdns: Fix code comments and remove *if Free* TODO * misc/mdns: Minor refactorings * misc/mdns: Build responses in behaviour.rs directly * misc/mdns: Move response ttl duration to constant * misc/mdns: Remove optimization todo comment * misc/mdns: Add query interval test * misc/mdns: Move packet parsing into MdnPacket impl * misc/mdns: Don't have receiving packets starve the query interval When we 'await' on receiving a packet on the udp socket without receiving a single packet we starve the remaining logic of the mdns service, in this case the logic triggered on the receive interval. * misc/mdns: Add debug_assert to MaybeBusyMdnsService check * misc/mdns: Implement Debug for MaybeBusyMdnsService * misc/mdns: Make ownership note a normal comment, not a doc comment * misc/mdns: Have discovered_peers return an iterator
Mostly mechanical. Creating a `CommonTransport` yields an `io::Result<_>` now since creating the `DnsConfig` may fail with an `io::Error` when creating the `ThreadPool`. The `DnsConfig` `Transport` impl had to be changed slightly: (a) PR [[1311]] requires some `Send` bounds. (b) The async block had to be changed to work around lifetime inference issues which resulted in an "one type is more general than the other" error. [1311]: #1311
So the reason for this is that when the dialling swarm tries to connect to the address before the listener has bound to it, the connection refused error is eventually ignored. It will bubble up through the layers until finally reaching the swarm as a |
|
Makes sense, but I am curious where such errors should be handled? (On a related note, the |
Merge master in stable-futures
Co-Authored-By: Max Inden <mail@max-inden.de>
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.
Looks good! I have a few comments, but that is all.
} | ||
} | ||
}, | ||
MaybeBusyMdnsService::Poisoned => panic!("Mdns poisoned"), |
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 is a very useful design pattern for Rust futures. Thanks!
MDNS_RESPONSE_TTL, | ||
); | ||
service.enqueue_response(resp.unwrap()); | ||
} else { debug_assert!(false); } |
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.
What happens in release mode? It seems wrong to continue in an invalid state.
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.
We could panic in release mode as well. But given that MDns is probably only a auxiliary component, I think panicing would be a bit exaggerated. In case you have suggestions how we could enforce MaybeBusyMdnsService
to be Free
at compile time, I am happy to do a follow up pull request.
MDNS_RESPONSE_TTL, | ||
); | ||
service.enqueue_response(resp); | ||
} else { debug_assert!(false); } |
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.
Ditto
core/Cargo.toml
Outdated
parking_lot = "0.9.0" | ||
protobuf = "2.8" | ||
pin-project = "0.4.6" | ||
protobuf = "= 2.8.1" |
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.
Ideally we would do protobuf generation in build.rs
. This is okay so long as we are not missing out on upstream security fixes.
sender: mpsc::Sender<Channel<Bytes>>, | ||
channel_to_send: Option<Channel<Bytes>>, | ||
channel_to_return: Option<Channel<Bytes>>, | ||
sender: mpsc::Sender<Channel<Vec<u8>>>, |
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 this change?
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.
Because of changes in the Sink
trait
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> { | ||
// It is debatable whether we should poll the inner future first or the timer first. | ||
// For example, if you start dialing with a timeout of 10 seconds, then after 15 seconds | ||
// the dialing succeeds on the wire, then after 20 seconds you poll, then depending on |
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 think we should poll the inner future first.
|
||
// We start by importing the remote's public key into the WebCrypto world. | ||
let public_key = { | ||
// Note: contrary to what one might think, we shouldn't add the "deriveBits" usage. |
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?
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.
It's how the WebCrypto API is defined. Also, this is old code not relevant to this PR.
|
||
DnsConfig { | ||
trace!("Created a DNS thread pool"); |
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.
Should we switch to trust-dns
? Not now, obviously.
Co-Authored-By: Demi Obenour <48690212+DemiMarie-parity@users.noreply.github.com>
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 skimmed most of it. Kudos to everyone involved in this PR, this really seems to have been a lot of work (and a lot of it chore).
@@ -58,6 +54,9 @@ where | |||
} | |||
} | |||
|
|||
impl<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr, TUserData, TConnInfo, TPeerId> Unpin for | |||
CollectionStream<TInEvent, TOutEvent, THandler, TReachErr, THandlerErr, TUserData, TConnInfo, TPeerId> { } |
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.
How come this explicit impl is necessary?
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.
Otherwise Unpin
is implemented automatically only if all the fields are Unpin
as well.
It is never a bad idea to implement Unpin
for a type (provided you don't use unsafe
). The reason why we do it for this type is because it implements the Stream
trait, but we could theoretically implement Unpin
for all the types we define.
core/src/nodes/network.rs
Outdated
/// Start sending an event to the node. | ||
pub fn start_send_event(&mut self, event: TInEvent) -> StartSend<TInEvent, ()> { | ||
/// Sends an event to the handler of the node. | ||
pub fn send_event<'s: 'a>(&'s mut self, event: TInEvent) -> impl Future<Output = ()> + 's + 'a { |
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.
What does the use of both 's
and 'a
with 's: 'a
accomplish?
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 think that this is a bug with Rust in general. I will try to make it compile by removing a bound, but the chances are high that it's not possible.
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:
pub fn send_event<'s>(&'s mut self, event: TInEvent) -> impl Future<Output = ()> + 's {
Results in:
error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
--> core/src/nodes/network.rs:1647:61
|
1647 | pub fn send_event<'s>(&'s mut self, event: TInEvent) -> impl Future<Output = ()> + 's {
And this:
pub fn send_event(&mut self, event: TInEvent) -> impl Future<Output = ()> + 'a {
Leads to:
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> core/src/nodes/network.rs:1649:34
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.
But why not
pub fn send_event(&'a mut self, event: TInEvent) -> impl Future<Output = ()> + 'a {
which compiles and expresses what I would expect (that the returned future cannot outlive self
which contains references with lifetime 'a
).
core/src/nodes/tasks/manager.rs
Outdated
/// If no tokio executor is available, we move tasks to this list, and futures are polled on | ||
/// the current thread instead. | ||
local_spawns: Vec<Box<dyn Future<Item = (), Error = ()> + Send>>, | ||
/// If no executor is available, we move tasks to this list, and futures are polled on the |
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 no executor is available, we move tasks to this list, and futures are polled on the | |
/// If no executor is available, we move tasks to this set, and futures are polled on the |
core/src/nodes/tasks/manager.rs
Outdated
task.pending = Some(AsyncSink::NotReady(msg)) | ||
match task.sender.start_send(msg) { | ||
Ok(()) => {}, | ||
Err(ref err) if err.is_full() => {}, // TODO: somehow report to user? |
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 at least a log statement meanwhile?
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'll add the logging, but note that this isn't supposed to happen in practice. The user is supposed to call poll_ready_broadcast
beforehand, to make sure that room is available. And since both these functions require &mut self
, they're not racy.
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.
And since both these functions require
&mut self
, they're not racy.
I do not think this implication is valid. Given a type T
with two operations a
and b
, each of which requires &mut self
, we can wrap T
in a Mutex
, e.g. Arc<Mutex<T>>
and have:
// thread 1 (t1: Arc<Mutex<T>>):
t1.lock().a();
t1.lock().b();
// thread 2 (t2: Arc<Mutex<T>>):
t2.lock().a();
t2.lock().b();
where the MutexGuard
is dropped after each call to a
or b
, resulting in sequences such as a
a
b
b
for example.
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.
That is true for any Rust struct that exists.
The point is that you can use them in a non-racy way. We can't prevent stupidity.
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.
We can't prevent stupidity.
The current API in master
apparently can.
match self.inner.get_mut().sender.start_send(msg) { | ||
Ok(()) => {}, | ||
Err(ref err) if err.is_full() => {}, // TODO: somehow report to user? | ||
Err(_) => {}, |
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 at least log something?
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.
Same as above. poll_ready_broadcast
would return an error if the channel is closed.
This time it's possible for the function to be racy (as the background task can close the channel after poll_ready_broadcast
but before start_broadcast
), but the API is racy anyway as the background task can be in the process of closing the channel while start_broadcast
is being called.
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 don't think we should add any logging, as this is actually a normal path of execution. Network connections can close at any point, and this is what happens if a connection has been closed.
@@ -79,19 +82,24 @@ pub struct AndThenStream<TListener, TMap> { | |||
fun: TMap | |||
} | |||
|
|||
impl<TListener, TMap> Unpin for AndThenStream<TListener, TMap> { |
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.
Similar to the other case, I'm wondering why such impls are necessary. Just curious.
Another small review fix
Co-Authored-By: Max Inden <mail@max-inden.de>
Another review fix for stable-futures branch
Address review on stable-futures
Rewrites lots of parts of the library to use stable futures rather than futures 0.1.
This unlocks the possibility to use async/await, and opens the door for further API refactorings later on.
There is one test failure right now, the "network simultaneous dial" test, which seems to be caused by the
V1Lazy
upgrade system. This needs to be investigated.When it comes to reviewing, I don't know what everyone's opinion is. While many individual changes to the
stable-futures
branch have already been reviewed, unfortunately most of the changes made early on (notably incore
andswarm
haven't). I think most of the reviewing should be straight-forward, as most of the code is a 1:1 port of the old code.A few things have changed:
ProtocolsHandler::poll
doesn't return anError
anymore. Instead,ProtocolsHandlerEvent
(the return value ofpoll
) has a newClose
variant, which corresponds to what an error represented before.async-std
for networking, rather thantokio
. This is for two reasons: this unties us from tokio (async-std futures can be polled with anything, while tokio networking futures can only be polled with tokio), andasync-std
was ready beforetokio
was.poll
function (i.e.NetworkBehaviour
,ProtocolsHandler
,NodeHandler
) now have a&mut Context
parameter to reflect the changes in theFuture
trait.core::upgrade
module was refactored. It now contains a few async methods that allow reading or writing a length-delimited message from a socket.