-
Notifications
You must be signed in to change notification settings - Fork 117
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
seed
command
#83
Merged
Merged
seed
command
#83
Changes from 11 commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
89283f9
Default init seed nodes based on network choice
dconnolly 064c2ac
Keep sets of initial peers as Strings in config file
dconnolly 9f94f83
Add SeedService
dconnolly 31b4496
seed command seems to be functional
dconnolly 2c42a83
Yay, SeedService makes a remote 'connect' happy
dconnolly 3cf1710
Clean up some logging and comments on seed service
dconnolly 61ba79b
Remove to-fix comment
dconnolly 4cecf48
Remove autogenerated Abscissa doc comments
dconnolly 9aaaa0e
Update `seed` subcommand description
dconnolly 2a28178
Clean up SeedService.poll_ready with a 'ref mut'
dconnolly 99fb782
Update `Ok(None)` case logging.
dconnolly e9ac1ce
Update tracing invocation to be better manipulated
dconnolly aa6f853
Remove config override, not needed
dconnolly fa2866e
Unwrap address_book in call(), which relies on poll_ready giving a po…
dconnolly 6615b8b
Remove special wait, unneeded for seed
dconnolly File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
//! `seed` subcommand - runs a dns seeder | ||
|
||
use std::{ | ||
future::Future, | ||
pin::Pin, | ||
sync::{Arc, Mutex}, | ||
task::{Context, Poll}, | ||
}; | ||
|
||
use abscissa_core::{config, Command, FrameworkError, Options, Runnable}; | ||
use futures::channel::oneshot; | ||
use tower::{buffer::Buffer, Service, ServiceExt}; | ||
use zebra_network::{AddressBook, BoxedStdError, Request, Response}; | ||
|
||
use crate::{config::ZebradConfig, prelude::*}; | ||
|
||
/// Whether our `SeedService` is poll_ready or not. | ||
#[derive(Debug)] | ||
enum SeederState { | ||
/// Waiting for the address book to be shared with us via the oneshot channel. | ||
AwaitingAddressBook(oneshot::Receiver<Arc<Mutex<AddressBook>>>), | ||
/// Address book received, ready to service requests. | ||
Ready(Arc<Mutex<AddressBook>>), | ||
} | ||
|
||
#[derive(Debug)] | ||
struct SeedService { | ||
state: SeederState, | ||
} | ||
|
||
impl Service<Request> for SeedService { | ||
type Response = Response; | ||
type Error = BoxedStdError; | ||
type Future = | ||
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>; | ||
|
||
fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { | ||
debug!("SeedService.state: {:?}", self.state); | ||
|
||
match self.state { | ||
SeederState::Ready(_) => return Poll::Ready(Ok(())), | ||
SeederState::AwaitingAddressBook(ref mut rx) => match rx.try_recv() { | ||
Err(e) => { | ||
error!("SeedService oneshot sender dropped: {:?}", e); | ||
return Poll::Ready(Err(e.into())); | ||
} | ||
Ok(None) => { | ||
trace!("SeedService hasn't received a message via the oneshot yet."); | ||
return Poll::Pending; | ||
} | ||
Ok(Some(address_book)) => { | ||
info!( | ||
"SeedService received address_book via oneshot {:?}", | ||
address_book | ||
); | ||
self.state = SeederState::Ready(address_book); | ||
return Poll::Ready(Ok(())); | ||
} | ||
}, | ||
} | ||
} | ||
|
||
fn call(&mut self, req: Request) -> Self::Future { | ||
info!("SeedService handling a request: {:?}", req); | ||
|
||
let response = match (req, &self.state) { | ||
dconnolly marked this conversation as resolved.
Show resolved
Hide resolved
|
||
(Request::GetPeers, SeederState::Ready(address_book)) => { | ||
debug!( | ||
"address_book.len(): {:?}", | ||
address_book.lock().unwrap().len() | ||
dconnolly marked this conversation as resolved.
Show resolved
Hide resolved
|
||
); | ||
info!("SeedService responding to GetPeers"); | ||
Ok::<Response, Self::Error>(Response::Peers( | ||
address_book.lock().unwrap().peers().collect(), | ||
)) | ||
} | ||
_ => Ok::<Response, Self::Error>(Response::Ok), | ||
hdevalence marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}; | ||
|
||
info!("SeedService response: {:?}", response); | ||
return Box::pin(futures::future::ready(response)); | ||
} | ||
} | ||
|
||
/// `seed` subcommand | ||
/// | ||
/// A DNS seeder command to spider and collect as many valid peer | ||
/// addresses as we can. | ||
#[derive(Command, Debug, Default, Options)] | ||
pub struct SeedCmd { | ||
/// Filter strings | ||
#[options(free)] | ||
filters: Vec<String>, | ||
} | ||
|
||
impl config::Override<ZebradConfig> for SeedCmd { | ||
dconnolly marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Process the given command line options, overriding settings | ||
// from a configuration file using explicit flags taken from | ||
// command-line arguments. | ||
fn override_config(&self, mut config: ZebradConfig) -> Result<ZebradConfig, FrameworkError> { | ||
if !self.filters.is_empty() { | ||
config.tracing.filter = self.filters.join(","); | ||
} | ||
|
||
Ok(config) | ||
} | ||
} | ||
|
||
impl Runnable for SeedCmd { | ||
/// Start the application. | ||
fn run(&self) { | ||
use crate::components::tokio::TokioComponent; | ||
|
||
let wait = tokio::future::pending::<()>(); | ||
// Combine the seed future with an infinite wait | ||
// so that the program has to be explicitly killed and | ||
// won't die before all tracing messages are written. | ||
let fut = futures::future::join( | ||
async { | ||
match self.seed().await { | ||
Ok(()) => {} | ||
Err(e) => { | ||
// Print any error that occurs. | ||
error!(?e); | ||
} | ||
} | ||
}, | ||
wait, | ||
); | ||
dconnolly marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let _ = app_reader() | ||
.state() | ||
.components | ||
.get_downcast_ref::<TokioComponent>() | ||
.expect("TokioComponent should be available") | ||
.rt | ||
.block_on(fut); | ||
} | ||
} | ||
|
||
impl SeedCmd { | ||
async fn seed(&self) -> Result<(), failure::Error> { | ||
use failure::Error; | ||
|
||
info!("begin tower-based peer handling test stub"); | ||
|
||
let (addressbook_tx, addressbook_rx) = oneshot::channel(); | ||
let seed_service = SeedService { | ||
state: SeederState::AwaitingAddressBook(addressbook_rx), | ||
}; | ||
let node = Buffer::new(seed_service, 1); | ||
|
||
let config = app_config().network.clone(); | ||
|
||
let (mut peer_set, address_book) = zebra_network::init(config, node).await; | ||
|
||
let _ = addressbook_tx.send(address_book); | ||
|
||
info!("waiting for peer_set ready"); | ||
peer_set.ready().await.map_err(Error::from_boxed_compat)?; | ||
|
||
info!("peer_set became ready"); | ||
|
||
#[cfg(dos)] | ||
use std::time::Duration; | ||
use tokio::timer::Interval; | ||
|
||
#[cfg(dos)] | ||
// Fire GetPeers requests at ourselves, for testing. | ||
tokio::spawn(async move { | ||
let mut interval_stream = Interval::new_interval(Duration::from_secs(1)); | ||
|
||
loop { | ||
interval_stream.next().await; | ||
|
||
let _ = seed_service.call(Request::GetPeers); | ||
} | ||
}); | ||
|
||
let eternity = tokio::future::pending::<()>(); | ||
eternity.await; | ||
|
||
Ok(()) | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
take-or-leave-it: since
parse_peers
is never used outside ofinitial_peers
, it could be folded in asmatch self.network { ... } .iter().flat_map(...).flatten().collect()
, and this saves an allocation by only doing onecollect
instead of two.