|
@@ -1,38 +1,134 @@
|
|
|
use async_executor::Executor;
|
|
use async_executor::Executor;
|
|
|
|
|
+use async_std::sync::Mutex;
|
|
|
use log::*;
|
|
use log::*;
|
|
|
use std::{
|
|
use std::{
|
|
|
net::SocketAddr,
|
|
net::SocketAddr,
|
|
|
sync::{Arc, Weak},
|
|
sync::{Arc, Weak},
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-use crate::error::{Error, Result};
|
|
|
|
|
-//use crate::net::error::{Error, Result};
|
|
|
|
|
use crate::{
|
|
use crate::{
|
|
|
|
|
+ error::{Error, Result},
|
|
|
net::{
|
|
net::{
|
|
|
protocols::{ProtocolAddress, ProtocolPing},
|
|
protocols::{ProtocolAddress, ProtocolPing},
|
|
|
sessions::Session,
|
|
sessions::Session,
|
|
|
- Acceptor, AcceptorPtr, ChannelPtr, P2p,
|
|
|
|
|
|
|
+ ChannelPtr, Connector, P2p,
|
|
|
},
|
|
},
|
|
|
system::{StoppableTask, StoppableTaskPtr},
|
|
system::{StoppableTask, StoppableTaskPtr},
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
pub struct ManualSession {
|
|
pub struct ManualSession {
|
|
|
p2p: Weak<P2p>,
|
|
p2p: Weak<P2p>,
|
|
|
|
|
+ connect_slots: Mutex<Vec<StoppableTaskPtr>>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl ManualSession {
|
|
impl ManualSession {
|
|
|
/// Create a new inbound session.
|
|
/// Create a new inbound session.
|
|
|
pub fn new(p2p: Weak<P2p>) -> Arc<Self> {
|
|
pub fn new(p2p: Weak<P2p>) -> Arc<Self> {
|
|
|
- Arc::new(Self { p2p, })
|
|
|
|
|
|
|
+ Arc::new(Self { p2p, connect_slots: Mutex::new(Vec::new()) })
|
|
|
}
|
|
}
|
|
|
- /// Starts the inbound session. Begins by accepting connections and fails if
|
|
|
|
|
- /// the address is not configured. Then runs the channel subscription
|
|
|
|
|
- /// loop.
|
|
|
|
|
- pub fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /// Stop the outbound session.
|
|
|
|
|
+ pub async fn stop(&self) {
|
|
|
|
|
+ let connect_slots = &*self.connect_slots.lock().await;
|
|
|
|
|
+
|
|
|
|
|
+ for slot in connect_slots {
|
|
|
|
|
+ slot.stop().await;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub async fn connect(self: Arc<Self>, addr: &SocketAddr, executor: Arc<Executor<'_>>) {
|
|
|
|
|
+ let task = StoppableTask::new();
|
|
|
|
|
+
|
|
|
|
|
+ task.clone().start(
|
|
|
|
|
+ self.clone().channel_connect_loop(addr.clone(), executor.clone()),
|
|
|
|
|
+ // Ignore stop handler
|
|
|
|
|
+ |_| async {},
|
|
|
|
|
+ Error::ServiceStopped,
|
|
|
|
|
+ executor.clone(),
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ self.connect_slots.lock().await.push(task);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub async fn channel_connect_loop(
|
|
|
|
|
+ self: Arc<Self>,
|
|
|
|
|
+ addr: SocketAddr,
|
|
|
|
|
+ executor: Arc<Executor<'_>>,
|
|
|
|
|
+ ) -> Result<()> {
|
|
|
|
|
+ let connector = Connector::new(self.p2p().settings());
|
|
|
|
|
+
|
|
|
|
|
+ let attempts = self.p2p().settings().manual_attempt_limit;
|
|
|
|
|
+ let mut remaining = attempts;
|
|
|
|
|
+
|
|
|
|
|
+ loop {
|
|
|
|
|
+ // Loop forever if attempts is 0
|
|
|
|
|
+ // Otherwise loop attempts number of times
|
|
|
|
|
+ remaining = if attempts == 0 { 1 } else { remaining - 1 };
|
|
|
|
|
+ if remaining == 0 {
|
|
|
|
|
+ break
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ self.p2p().add_pending(addr).await;
|
|
|
|
|
+
|
|
|
|
|
+ info!(target: "net", "Connecting to manual outbound [{}]", addr);
|
|
|
|
|
+
|
|
|
|
|
+ match connector.connect(addr).await {
|
|
|
|
|
+ Ok(channel) => {
|
|
|
|
|
+ // Blacklist goes here
|
|
|
|
|
+
|
|
|
|
|
+ info!(target: "net", "Connected to manual outbound [{}]", addr);
|
|
|
|
|
+
|
|
|
|
|
+ let stop_sub = channel.subscribe_stop().await;
|
|
|
|
|
+
|
|
|
|
|
+ self.clone().register_channel(channel.clone(), executor.clone()).await?;
|
|
|
|
|
+
|
|
|
|
|
+ // Channel is now connected but not yet setup
|
|
|
|
|
+
|
|
|
|
|
+ // Remove pending lock since register_channel will add the channel to p2p
|
|
|
|
|
+ self.p2p().remove_pending(&addr).await;
|
|
|
|
|
+
|
|
|
|
|
+ self.clone().attach_protocols(channel, executor.clone()).await?;
|
|
|
|
|
+
|
|
|
|
|
+ // Wait for channel to close
|
|
|
|
|
+ stop_sub.receive().await;
|
|
|
|
|
+ }
|
|
|
|
|
+ Err(err) => {
|
|
|
|
|
+ info!(target: "net", "Unable to connect to manual outbound [{}]: {}", addr, err);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ warn!(
|
|
|
|
|
+ target: "net",
|
|
|
|
|
+ "Suspending manual connection to [{}] after {} failed attempts.",
|
|
|
|
|
+ addr,
|
|
|
|
|
+ attempts
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
Ok(())
|
|
Ok(())
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn connect(self: Arc<Self>, addr: &SocketAddr) {
|
|
|
|
|
|
|
+ /// Starts sending keep-alive and address messages across the channels.
|
|
|
|
|
+ async fn attach_protocols(
|
|
|
|
|
+ self: Arc<Self>,
|
|
|
|
|
+ channel: ChannelPtr,
|
|
|
|
|
+ executor: Arc<Executor<'_>>,
|
|
|
|
|
+ ) -> Result<()> {
|
|
|
|
|
+ let settings = self.p2p().settings().clone();
|
|
|
|
|
+ let hosts = self.p2p().hosts();
|
|
|
|
|
+
|
|
|
|
|
+ let protocol_ping = ProtocolPing::new(channel.clone(), settings.clone());
|
|
|
|
|
+ let protocol_addr = ProtocolAddress::new(channel, hosts).await;
|
|
|
|
|
+
|
|
|
|
|
+ protocol_ping.start(executor.clone()).await;
|
|
|
|
|
+ protocol_addr.start(executor).await;
|
|
|
|
|
+
|
|
|
|
|
+ Ok(())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+impl Session for ManualSession {
|
|
|
|
|
+ fn p2p(&self) -> Arc<P2p> {
|
|
|
|
|
+ self.p2p.upgrade().unwrap()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|