Embed the topology in the NetworkBehaviour (#889)

* Embed the topology in the NetworkBehaviour

* Put topologies inside of Floodsub and Kad

* Fix core tests

* Fix chat example

* More work

* Some cleanup

* Restore external addresses system
This commit is contained in:
Pierre Krieger
2019-01-26 23:57:53 +01:00
committed by GitHub
parent 30c082dfe5
commit df923526ca
21 changed files with 818 additions and 749 deletions

View File

@ -49,6 +49,7 @@ fn build(ast: &DeriveInput) -> TokenStream {
fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
let name = &ast.ident;
let (_, ty_generics, where_clause) = ast.generics.split_for_impl();
let multiaddr = quote!{::libp2p::core::Multiaddr};
let trait_to_impl = quote!{::libp2p::core::swarm::NetworkBehaviour};
let net_behv_event_proc = quote!{::libp2p::core::swarm::NetworkBehaviourEventProcess};
let either_ident = quote!{::libp2p::core::either::EitherOutput};
@ -70,25 +71,14 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
quote!{#n}
};
// Name of the type parameter that represents the topology.
let topology_generic = {
let mut n = "TTopology".to_string();
// Avoid collisions.
while ast.generics.type_params().any(|tp| tp.ident.to_string() == n) {
n.push('1');
}
let n = Ident::new(&n, name.span());
quote!{#n}
};
let poll_parameters = quote!{::libp2p::core::swarm::PollParameters<#topology_generic>};
let poll_parameters = quote!{::libp2p::core::swarm::PollParameters};
// Build the generics.
let impl_generics = {
let tp = ast.generics.type_params();
let lf = ast.generics.lifetimes();
let cst = ast.generics.const_params();
quote!{<#(#lf,)* #(#tp,)* #(#cst,)* #topology_generic, #substream_generic>}
quote!{<#(#lf,)* #(#tp,)* #(#cst,)* #substream_generic>}
};
// Build the `where ...` clause of the trait implementation.
@ -98,12 +88,12 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
.flat_map(|field| {
let ty = &field.ty;
vec![
quote!{#ty: #trait_to_impl<#topology_generic>},
quote!{Self: #net_behv_event_proc<<#ty as #trait_to_impl<#topology_generic>>::OutEvent>},
quote!{<<#ty as #trait_to_impl<#topology_generic>>::ProtocolsHandler as #into_protocols_handler>::Handler: #protocols_handler<Substream = #substream_generic>},
quote!{#ty: #trait_to_impl},
quote!{Self: #net_behv_event_proc<<#ty as #trait_to_impl>::OutEvent>},
quote!{<<#ty as #trait_to_impl>::ProtocolsHandler as #into_protocols_handler>::Handler: #protocols_handler<Substream = #substream_generic>},
// Note: this bound is required because of https://github.com/rust-lang/rust/issues/55697
quote!{<<<#ty as #trait_to_impl<#topology_generic>>::ProtocolsHandler as #into_protocols_handler>::Handler as #protocols_handler>::InboundProtocol: ::libp2p::core::InboundUpgrade<#substream_generic>},
quote!{<<<#ty as #trait_to_impl<#topology_generic>>::ProtocolsHandler as #into_protocols_handler>::Handler as #protocols_handler>::OutboundProtocol: ::libp2p::core::OutboundUpgrade<#substream_generic>},
quote!{<<<#ty as #trait_to_impl>::ProtocolsHandler as #into_protocols_handler>::Handler as #protocols_handler>::InboundProtocol: ::libp2p::core::InboundUpgrade<#substream_generic>},
quote!{<<<#ty as #trait_to_impl>::ProtocolsHandler as #into_protocols_handler>::Handler as #protocols_handler>::OutboundProtocol: ::libp2p::core::OutboundUpgrade<#substream_generic>},
]
})
.collect::<Vec<_>>();
@ -143,6 +133,20 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
out
};
// Build the list of statements to put in the body of `addresses_of_peer()`.
let addresses_of_peer_stmts = {
data_struct.fields.iter().enumerate().filter_map(move |(field_n, field)| {
if is_ignored(&field) {
return None;
}
Some(match field.ident {
Some(ref i) => quote!{ out.extend(self.#i.addresses_of_peer(peer_id)); },
None => quote!{ out.extend(self.#field_n.addresses_of_peer(peer_id)); },
})
})
};
// Build the list of statements to put in the body of `inject_connected()`.
let inject_connected_stmts = {
let num_fields = data_struct.fields.iter().filter(|f| !is_ignored(f)).count();
@ -216,7 +220,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
continue;
}
let ty = &field.ty;
let field_info = quote!{ <#ty as #trait_to_impl<#topology_generic>>::ProtocolsHandler };
let field_info = quote!{ <#ty as #trait_to_impl>::ProtocolsHandler };
match ph_ty {
Some(ev) => ph_ty = Some(quote!{ #into_proto_select_ident<#ev, #field_info> }),
ref mut ev @ None => *ev = Some(field_info),
@ -321,7 +325,7 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
// Now the magic happens.
let final_quote = quote!{
impl #impl_generics #trait_to_impl<#topology_generic> for #name #ty_generics
impl #impl_generics #trait_to_impl for #name #ty_generics
#where_clause
{
type ProtocolsHandler = #protocols_handler_ty;
@ -333,6 +337,12 @@ fn build_struct(ast: &DeriveInput, data_struct: &DataStruct) -> TokenStream {
#new_handler
}
fn addresses_of_peer(&self, peer_id: &#peer_id) -> Vec<#multiaddr> {
let mut out = Vec::new();
#(#addresses_of_peer_stmts);*
out
}
#[inline]
fn inject_connected(&mut self, peer_id: #peer_id, endpoint: #connected_point) {
#(#inject_connected_stmts);*