@@ -37,18 +37,20 @@ use crate::upgrade::{
3737} ;
3838use futures:: { future:: BoxFuture , prelude:: * } ;
3939use libp2p_core:: { ConnectedPoint , Multiaddr , PeerId } ;
40- use libp2p_core:: upgrade:: { ProtocolName , UpgradeError , NegotiationError , ProtocolError } ;
40+ use libp2p_core:: upgrade:: { self , ProtocolName , UpgradeError , NegotiationError , ProtocolError } ;
4141use rand:: Rng ;
4242use std:: {
43+ cmp,
4344 collections:: { HashMap , HashSet } ,
4445 error,
4546 fmt,
4647 hash:: Hash ,
4748 iter:: { self , FromIterator } ,
48- task:: { Context , Poll }
49+ task:: { Context , Poll } ,
50+ time:: Duration
4951} ;
5052
51- /// A [`ProtocolsHandler`] for multiple other `ProtocolsHandler`s.
53+ /// A [`ProtocolsHandler`] for multiple `ProtocolsHandler`s of the same type .
5254#[ derive( Clone ) ]
5355pub struct MultiHandler < K , H > {
5456 handlers : HashMap < K , H >
7476 /// Create and populate a `MultiHandler` from the given handler iterator.
7577 ///
7678 /// It is an error for any two protocols handlers to share the same protocol name.
79+ ///
80+ /// > **Note**: All handlers should use the same [`upgrade::Version`] for
81+ /// > the inbound and outbound [`SubstreamProtocol`]s.
7782 pub fn try_from_iter < I > ( iter : I ) -> Result < Self , DuplicateProtonameError >
7883 where
7984 I : IntoIterator < Item = ( K , H ) >
@@ -100,17 +105,34 @@ where
100105 type OutboundOpenInfo = ( K , <H as ProtocolsHandler >:: OutboundOpenInfo ) ;
101106
102107 fn listen_protocol ( & self ) -> SubstreamProtocol < Self :: InboundProtocol , Self :: InboundOpenInfo > {
103- let ( upgrade, info) = self . handlers . iter ( )
108+ let ( upgrade, info, timeout , version ) = self . handlers . iter ( )
104109 . map ( |( k, h) | {
105- let ( _, u, i) = h. listen_protocol ( ) . into_upgrade ( ) ;
106- ( k. clone ( ) , ( u, i) )
110+ let p = h. listen_protocol ( ) ;
111+ let t = * p. timeout ( ) ;
112+ let ( v, u, i) = p. into_upgrade ( ) ;
113+ ( k. clone ( ) , ( v, u, i, t) )
107114 } )
108- . fold ( ( Upgrade :: new ( ) , Info :: new ( ) ) , |( mut upg, mut inf) , ( k, ( u, i) ) | {
109- upg. upgrades . push ( ( k. clone ( ) , u) ) ;
110- inf. infos . push ( ( k, i) ) ;
111- ( upg, inf)
112- } ) ;
115+ . fold ( ( Upgrade :: new ( ) , Info :: new ( ) , Duration :: from_secs ( 0 ) , None ) ,
116+ |( mut upg, mut inf, mut timeout, mut version) , ( k, ( v, u, i, t) ) | {
117+ upg. upgrades . push ( ( k. clone ( ) , u) ) ;
118+ inf. infos . push ( ( k, i) ) ;
119+ timeout = cmp:: max ( timeout, t) ;
120+ version = version. map_or ( Some ( v) , |vv|
121+ if v != vv {
122+ // Different upgrade (i.e. protocol negotiation) protocol
123+ // versions are usually incompatible and not negotiated
124+ // themselves, so a protocol upgrade may fail.
125+ log:: warn!( "Differing upgrade versions. Defaulting to V1." ) ;
126+ Some ( upgrade:: Version :: V1 )
127+ } else {
128+ Some ( v)
129+ } ) ;
130+ ( upg, inf, timeout, version)
131+ }
132+ ) ;
113133 SubstreamProtocol :: new ( upgrade, info)
134+ . with_timeout ( timeout)
135+ . with_upgrade_protocol ( version. unwrap_or ( upgrade:: Version :: V1 ) )
114136 }
115137
116138 fn inject_fully_negotiated_outbound (
@@ -293,6 +315,9 @@ where
293315 /// Create and populate an `IntoMultiHandler` from the given iterator.
294316 ///
295317 /// It is an error for any two protocols handlers to share the same protocol name.
318+ ///
319+ /// > **Note**: All handlers should use the same [`upgrade::Version`] for
320+ /// > the inbound and outbound [`SubstreamProtocol`]s.
296321 pub fn try_from_iter < I > ( iter : I ) -> Result < Self , DuplicateProtonameError >
297322 where
298323 I : IntoIterator < Item = ( K , H ) >
0 commit comments