Skip to content

Commit

Permalink
seed command seems to be functional
Browse files Browse the repository at this point in the history
Moved SeedService out of the command closure Command currently spawns
a tokio task to DOS the seed service with `Request::GetPeers` every
second.

Pertains to #54
  • Loading branch information
dconnolly committed Nov 7, 2019
1 parent 9f94f83 commit 31b4496
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 43 deletions.
1 change: 1 addition & 0 deletions zebra-network/src/peer/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ where
// and try to construct an appropriate request object.
let req = match msg {
Message::Addr(addrs) => Some(Request::PushPeers(addrs)),
Message::GetAddr => Some(Request::GetPeers),
_ => {
debug!("unhandled message type");
None
Expand Down
123 changes: 80 additions & 43 deletions zebrad/src/commands/seed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,69 @@
use std::{
future::Future,
pin::Pin,
sync::{Arc, Mutex},
task::{Context, Poll},
};

use abscissa_core::{config, Command, FrameworkError, Options, Runnable};
use futures::stream::StreamExt;
use tower::{buffer::Buffer, Service, ServiceExt};
use zebra_network::{AddressBook, BoxedStdError, Request, Response};

use crate::{config::ZebradConfig, prelude::*};

use abscissa_core::{config, Command, FrameworkError, Options, Runnable};
#[derive(Clone)]
struct SeedService {
address_book: Option<Arc<Mutex<AddressBook>>>,
}

impl SeedService {
fn set_address_book(&mut self, address_book: Arc<Mutex<AddressBook>>) {
debug!("Settings SeedService.address_book: {:?}", address_book);
self.address_book = Some(address_book);
}
}

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, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Ok(()).into()
}

fn call(&mut self, req: Request) -> Self::Future {
info!("SeedService handling a request: {:?}", req);

match &self.address_book {
Some(address_book) => trace!(
"SeedService address_book total: {:?}",
address_book.lock().unwrap().len()
),
_ => (),
};

let response = match req {
Request::GetPeers => match &self.address_book {
Some(address_book) => {
info!("Responding to GetPeers");

Ok::<Response, Self::Error>(Response::Peers(
address_book.lock().unwrap().peers().collect(),
))
}
_ => Ok::<Response, Self::Error>(Response::Ok),
},
_ => Ok::<Response, Self::Error>(Response::Ok),
};

info!("SeedService response: {:?}", response);

return Box::pin(futures::future::ready(response));
}
}

/// `seed` subcommand
///
Expand All @@ -30,6 +87,7 @@ impl config::Override<ZebradConfig> for SeedCmd {
config.tracing.filter = self.filters.join(",");
}

info!("{:?}", config);
Ok(config)
}
}
Expand Down Expand Up @@ -69,54 +127,18 @@ impl Runnable for SeedCmd {
impl SeedCmd {
async fn seed(&self) -> Result<(), failure::Error> {
use failure::Error;
use futures::stream::StreamExt;
use tower::{buffer::Buffer, Service, ServiceExt};
use zebra_network::{AddressBook, Request, Response};

info!("begin tower-based peer handling test stub");

struct SeedService {
address_book: Option<AddressBook>,
}

impl SeedService {
fn set_address_book(&mut self, address_book: AddressBook) {
self.address_book = Some(address_book);
}
}

impl Service<Request> for SeedService {
type Response = Response;
type Error = Error;
type Future =
Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;

fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
Ok(()).into()
}

fn call(&mut self, req: Request) -> Self::Future {
let response = match req {
Request::GetPeers => match &self.address_book {
Some(address_book) => Ok::<Response, failure::Error>(Response::Peers(
address_book.peers().collect(),
)),
_ => Ok::<Response, failure::Error>(Response::Ok),
},
_ => Ok::<Response, failure::Error>(Response::Ok),
};

return Box::pin(futures::future::ready(response));
}
}

let node = Buffer::new(SeedService { address_book: None }, 1);
let mut seed_service = SeedService { address_book: None };
// let node = Buffer::new(seed_service, 1);

let config = app_config().network.clone();
info!("{:?}", config);

// XXX How do I create a service above that answers questions
// about this specific address book?
let (mut peer_set, address_book) = zebra_network::init(config, node).await;
let (mut peer_set, address_book) = zebra_network::init(config, seed_service.clone()).await;

seed_service.set_address_book(address_book.clone());

// XXX Do not tell our DNS seed queries about gossiped addrs
// that we have not connected to before?
Expand All @@ -125,6 +147,21 @@ impl SeedCmd {

info!("peer_set became ready");

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;

Expand Down

0 comments on commit 31b4496

Please sign in to comment.