mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 11:41:51 +00:00
Basic networking service with channel
This commit is contained in:
@@ -13,3 +13,4 @@ slog = "2.4.1"
|
||||
futures = "0.1.25"
|
||||
error-chain = "0.12.0"
|
||||
crossbeam-channel = "0.3.8"
|
||||
tokio = "0.1.16"
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
// generates error types
|
||||
use libp2p;
|
||||
|
||||
use error_chain::{
|
||||
error_chain, error_chain_processing, impl_error_chain_kind, impl_error_chain_processed,
|
||||
impl_extract_backtrace,
|
||||
};
|
||||
|
||||
error_chain! {}
|
||||
error_chain! {
|
||||
links {
|
||||
Libp2p(libp2p::error::Error, libp2p::error::ErrorKind);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,4 +5,5 @@ mod messages;
|
||||
mod service;
|
||||
|
||||
pub use libp2p::NetworkConfig;
|
||||
pub use messages::NodeMessage;
|
||||
pub use service::Service;
|
||||
|
||||
@@ -2,11 +2,15 @@ use libp2p::PeerId;
|
||||
use types::{Hash256, Slot};
|
||||
|
||||
/// Messages between nodes across the network.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum NodeMessage {
|
||||
Status(Status),
|
||||
BlockRequest,
|
||||
// TODO: only for testing - remove
|
||||
Message(String),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Status {
|
||||
/// Current node version.
|
||||
version: u8,
|
||||
@@ -19,6 +23,7 @@ pub struct Status {
|
||||
}
|
||||
|
||||
/// Types of messages that the network service can receive.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum NetworkMessage {
|
||||
/// Send a message to libp2p service.
|
||||
//TODO: Define typing for messages across the wire
|
||||
|
||||
@@ -2,39 +2,135 @@ use crate::error;
|
||||
use crate::message_handler::{HandlerMessage, MessageHandler};
|
||||
use crate::messages::{NetworkMessage, NodeMessage};
|
||||
use crate::NetworkConfig;
|
||||
use crossbeam_channel::{unbounded as channel, Sender};
|
||||
use crossbeam_channel::{unbounded as channel, Sender, TryRecvError};
|
||||
use futures::future::lazy;
|
||||
use futures::future::poll_fn;
|
||||
use futures::prelude::*;
|
||||
use futures::sync::oneshot;
|
||||
use futures::Stream;
|
||||
use libp2p::behaviour::BehaviourEvent;
|
||||
use libp2p::error::Error as libp2pError;
|
||||
use libp2p::Service as LibP2PService;
|
||||
use libp2p::{Libp2pEvent, PeerId};
|
||||
use slog::{debug, info, o, trace, warn, Logger};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tokio::runtime::TaskExecutor;
|
||||
|
||||
/// Service that handles communication between internal services and the libp2p network service.
|
||||
pub struct Service {
|
||||
//libp2p_service: Arc<Mutex<LibP2PService>>,
|
||||
//libp2p_thread: oneshot::Sender<()>,
|
||||
//message_handler: MessageHandler,
|
||||
//message_handler_send: Sender<HandlerMessage>,
|
||||
libp2p_exit: oneshot::Sender<()>,
|
||||
network_send: crossbeam_channel::Sender<NetworkMessage>,
|
||||
//message_handler: MessageHandler,
|
||||
//message_handler_send: Sender<HandlerMessage>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn new(
|
||||
config: NetworkConfig,
|
||||
executor: TaskExecutor,
|
||||
log: slog::Logger,
|
||||
) -> error::Result<(Arc<Self>, Sender<NetworkMessage>)> {
|
||||
debug!(log, "Service starting");
|
||||
let (network_send, network_recv) = channel::<NetworkMessage>();
|
||||
|
||||
// launch message handler thread
|
||||
let message_handler_log = log.new(o!("Service" => "MessageHandler"));
|
||||
let message_handler_send = MessageHandler::new(message_handler_log);
|
||||
let message_handler_send = MessageHandler::new(message_handler_log)?;
|
||||
|
||||
// launch libp2p service
|
||||
let libp2p_log = log.new(o!("Service" => "Libp2p"));
|
||||
let libp2p_service = LibP2PService::new(config, libp2p_log);
|
||||
let libp2p_service = LibP2PService::new(config, libp2p_log)?;
|
||||
|
||||
// TODO: Spawn thread to handle libp2p messages and pass to message handler thread.
|
||||
let network = Service {};
|
||||
let (network_send, libp2p_exit) =
|
||||
spawn_service(libp2p_service, message_handler_send, executor, log)?;
|
||||
let network = Service {
|
||||
libp2p_exit,
|
||||
network_send: network_send.clone(),
|
||||
};
|
||||
|
||||
Ok((Arc::new(network), network_send))
|
||||
}
|
||||
|
||||
// TODO: Testing only
|
||||
pub fn send_message(&self, message: String) {
|
||||
let node_message = NodeMessage::Message(message);
|
||||
self.network_send
|
||||
.send(NetworkMessage::Send(PeerId::random(), node_message));
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_service(
|
||||
libp2p_service: LibP2PService,
|
||||
message_handler_send: crossbeam_channel::Sender<HandlerMessage>,
|
||||
executor: TaskExecutor,
|
||||
log: slog::Logger,
|
||||
) -> error::Result<(
|
||||
crossbeam_channel::Sender<NetworkMessage>,
|
||||
oneshot::Sender<()>,
|
||||
)> {
|
||||
let (network_exit, exit_rx) = oneshot::channel();
|
||||
let (network_send, network_recv) = channel::<NetworkMessage>();
|
||||
|
||||
// spawn on the current executor
|
||||
executor.spawn(
|
||||
network_service(
|
||||
libp2p_service,
|
||||
network_recv,
|
||||
message_handler_send,
|
||||
log.clone(),
|
||||
)
|
||||
// allow for manual termination
|
||||
.select(exit_rx.then(|_| Ok(())))
|
||||
.then(move |_| {
|
||||
debug!(log.clone(), "Network service ended");
|
||||
Ok(())
|
||||
}),
|
||||
);
|
||||
|
||||
Ok((network_send, network_exit))
|
||||
}
|
||||
|
||||
fn network_service(
|
||||
mut libp2p_service: LibP2PService,
|
||||
network_recv: crossbeam_channel::Receiver<NetworkMessage>,
|
||||
message_handler_send: crossbeam_channel::Sender<HandlerMessage>,
|
||||
log: slog::Logger,
|
||||
) -> impl futures::Future<Item = (), Error = libp2p::error::Error> {
|
||||
futures::future::poll_fn(move || -> Result<_, libp2p::error::Error> {
|
||||
// poll the swarm
|
||||
loop {
|
||||
match libp2p_service.poll() {
|
||||
Ok(Async::Ready(Some(Libp2pEvent::Message(m)))) => debug!(
|
||||
libp2p_service.log,
|
||||
"Network Service: Message received: {}", m
|
||||
),
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
// poll the network channel
|
||||
// TODO: refactor - combine poll_fn's?
|
||||
loop {
|
||||
match network_recv.try_recv() {
|
||||
// TODO: Testing message - remove
|
||||
Ok(NetworkMessage::Send(_peer_id, node_message)) => {
|
||||
match node_message {
|
||||
NodeMessage::Message(m) => {
|
||||
debug!(log, "Message received via network channel: {:?}", m);
|
||||
//TODO: Make swarm private
|
||||
//TODO: Implement correct peer id topic message handling
|
||||
libp2p_service.swarm.send_message(m);
|
||||
}
|
||||
//TODO: Handle all NodeMessage types
|
||||
_ => break,
|
||||
};
|
||||
}
|
||||
Err(TryRecvError::Empty) => break,
|
||||
Err(TryRecvError::Disconnected) => {
|
||||
return Err(libp2p::error::Error::from("Network channel disconnected"));
|
||||
}
|
||||
// TODO: Implement all NetworkMessage
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
Ok(Async::NotReady)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user