Start-Stop
Now that we have initialized the network settings we can create an instance of the p2p network.
We will next create a Dchat
struct that will store all the data required
by dchat. For now, it will just hold a pointer to the p2p network.
struct Dchat {
p2p: net::P2pPtr,
}
impl Dchat {
fn new(
p2p: net::P2pPtr,
) -> Self {
Self { p2p }
}
}
Let's build out our realmain
function as follows:
use log::info;
async_daemonize!(realmain);
async fn realmain(args: Args, ex: Arc<smol::Executor<'static>>) -> Result<()> {
let p2p = net::P2p::new(args.net.into(), ex.clone()).await;
info!("Starting P2P network");
p2p.clone().start().await?;
let (signals_handler, signals_task) = SignalHandler::new(ex)?;
signals_handler.wait_termination(signals_task).await?;
info!("Caught termination signal, cleaning up and exiting...");
info!("Stopping P2P network");
p2p.stop().await;
Ok(())
}
Here, we instantiate the p2p network using P2p::new
. We then start it
by calling start
, and handle shutdown signals to safely shutdown the
network using P2p::stop
.
Let's take a quick look at the underlying p2p methods we're using here.
Start
This is start:
/// Starts inbound, outbound, and manual sessions.
pub async fn start(self: Arc<Self>) -> Result<()> {
debug!(target: "net::p2p::start()", "P2P::start() [BEGIN]");
info!(target: "net::p2p::start()", "[P2P] Starting P2P subsystem");
// First attempt any set manual connections
for peer in &self.settings.peers {
self.session_manual().connect(peer.clone()).await;
}
// Start the inbound session
if let Err(err) = self.session_inbound().start().await {
error!(target: "net::p2p::start()", "Failed to start inbound session!: {}", err);
self.session_manual().stop().await;
return Err(err)
}
// Start the outbound session
self.session_outbound().start().await;
info!(target: "net::p2p::start()", "[P2P] P2P subsystem started");
Ok(())
}
start
attempts to start an Inbound
, Manual
or Outbound
session,
which will succeed or fail depending on how your TOML is configured. For
example, if you are an outbound node, session_inbound.start()
will
return with the following message:
info!(target: "net", "Not configured for accepting incoming connections.");
The function calls in start
trigger the following processes:
session_manual.connect
: tries to connect to any peer
addresses we
have specified in the TOML, using a Connector
.
session_inbound.start
: starts an Acceptor
on the inbound address
specified in the TOML, then creates and registers a Channel
on that
address.
session_outbound.start
: tries to establish a connection using a
Connector
to the number of slots we have specified in the TOML field
outbound_connections
. For every Slot
, run
tries to find a valid
address we can connect to through PeerDiscovery
, which loops through
all connected channels and sends out a GetAddr
message. If we don't
have any connected channels, run
performs a SeedSync
.
Stop
This is stop.
/// Stop the running P2P subsystem
pub async fn stop(&self) {
// Stop the sessions
self.session_manual().stop().await;
self.session_inbound().stop().await;
self.session_outbound().stop().await;
}
stop
transmits a shutdown signal to all channels subscribed to the
stop signal and safely shuts down the network.