mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-29 17:51:35 +00:00
fix(identify): handle partial push
messages
According to the [spec], all fields within push messages are optional. To handle missing fields, we deserialize push messages into a different struct, patch the previously received, full identify message with it and emit this as the new info.
Previously, we failed to parse the message which causes incompatibility with js-libp2p nodes as they don't send the public key in push messages. See 88c47f51f9/packages/libp2p/src/identify/identify.ts (L205-L210)
.
[spec]: https://github.com/libp2p/specs/tree/master/identify#identifypush
Pull-Request: #4495.
This commit is contained in:
@ -18,7 +18,8 @@
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::protocol::{Identify, InboundPush, Info, OutboundPush, Push, UpgradeError};
|
||||
use crate::protocol::{Identify, InboundPush, OutboundPush, Push, UpgradeError};
|
||||
use crate::protocol::{Info, PushInfo};
|
||||
use either::Either;
|
||||
use futures::future::BoxFuture;
|
||||
use futures::prelude::*;
|
||||
@ -48,7 +49,7 @@ use std::{io, task::Context, task::Poll, time::Duration};
|
||||
/// permitting the underlying connection to be closed.
|
||||
pub struct Handler {
|
||||
remote_peer_id: PeerId,
|
||||
inbound_identify_push: Option<BoxFuture<'static, Result<Info, UpgradeError>>>,
|
||||
inbound_identify_push: Option<BoxFuture<'static, Result<PushInfo, UpgradeError>>>,
|
||||
/// Pending events to yield.
|
||||
events: SmallVec<
|
||||
[ConnectionHandlerEvent<Either<Identify, Push<OutboundPush>>, (), Event, io::Error>; 4],
|
||||
@ -80,6 +81,9 @@ pub struct Handler {
|
||||
/// Address observed by or for the remote.
|
||||
observed_addr: Multiaddr,
|
||||
|
||||
/// Identify information about the remote peer.
|
||||
remote_info: Option<Info>,
|
||||
|
||||
local_supported_protocols: SupportedProtocols,
|
||||
remote_supported_protocols: HashSet<StreamProtocol>,
|
||||
external_addresses: HashSet<Multiaddr>,
|
||||
@ -133,6 +137,7 @@ impl Handler {
|
||||
observed_addr,
|
||||
local_supported_protocols: SupportedProtocols::default(),
|
||||
remote_supported_protocols: HashSet::default(),
|
||||
remote_info: Default::default(),
|
||||
external_addresses,
|
||||
}
|
||||
}
|
||||
@ -176,7 +181,8 @@ impl Handler {
|
||||
) {
|
||||
match output {
|
||||
future::Either::Left(remote_info) => {
|
||||
self.update_supported_protocols_for_remote(&remote_info);
|
||||
self.handle_incoming_info(&remote_info);
|
||||
|
||||
self.events
|
||||
.push(ConnectionHandlerEvent::NotifyBehaviour(Event::Identified(
|
||||
remote_info,
|
||||
@ -213,6 +219,12 @@ impl Handler {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_incoming_info(&mut self, info: &Info) {
|
||||
self.remote_info.replace(info.clone());
|
||||
|
||||
self.update_supported_protocols_for_remote(info);
|
||||
}
|
||||
|
||||
fn update_supported_protocols_for_remote(&mut self, remote_info: &Info) {
|
||||
let new_remote_protocols = HashSet::from_iter(remote_info.protocols.clone());
|
||||
|
||||
@ -318,11 +330,15 @@ impl ConnectionHandler for Handler {
|
||||
{
|
||||
self.inbound_identify_push.take();
|
||||
|
||||
if let Ok(info) = res {
|
||||
self.update_supported_protocols_for_remote(&info);
|
||||
return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(Event::Identified(
|
||||
info,
|
||||
)));
|
||||
if let Ok(remote_push_info) = res {
|
||||
if let Some(mut info) = self.remote_info.clone() {
|
||||
info.merge(remote_push_info);
|
||||
self.handle_incoming_info(&info);
|
||||
|
||||
return Poll::Ready(ConnectionHandlerEvent::NotifyBehaviour(
|
||||
Event::Identified(info),
|
||||
));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user