1
Fork 0
mirror of https://github.com/thegeneralist01/p2p-failover synced 2026-01-11 15:40:29 +01:00

use anyhow for errors

This commit is contained in:
TheGeneralist 2025-03-23 21:21:10 +01:00
parent ee83a166ce
commit 5b4bc54c1f
No known key found for this signature in database
GPG key ID: C391D4D52D630F45
4 changed files with 43 additions and 45 deletions

5
Cargo.lock generated
View file

@ -43,9 +43,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.95" version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
@ -879,6 +879,7 @@ dependencies = [
name = "p2p-failover" name = "p2p-failover"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"chrono", "chrono",
"dateparser", "dateparser",
"notify", "notify",

View file

@ -11,3 +11,4 @@ serde_yaml = "0.9"
reqwest = "0.12.12" reqwest = "0.12.12"
tokio = { version = "=1.40.0", features = ["full"] } tokio = { version = "=1.40.0", features = ["full"] }
notify = "8.0.0" notify = "8.0.0"
anyhow = "1.0.97"

View file

@ -1,3 +1,4 @@
use anyhow::Result;
use p2p_failover::{file_watcher, node::Node, parser::Parser, tcp_listener}; use p2p_failover::{file_watcher, node::Node, parser::Parser, tcp_listener};
use std::{ use std::{
fs::File, fs::File,
@ -6,7 +7,7 @@ use std::{
}; };
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> { async fn main() -> Result<()> {
let config_path = let config_path =
std::env::var("P2P_CONFIG_PATH").unwrap_or_else(|_| "p2p-failover.config.yaml".to_string()); std::env::var("P2P_CONFIG_PATH").unwrap_or_else(|_| "p2p-failover.config.yaml".to_string());

View file

@ -1,3 +1,4 @@
use anyhow::{bail, Result};
use std::{ use std::{
io::{BufRead, BufReader}, io::{BufRead, BufReader},
sync::mpsc, sync::mpsc,
@ -25,7 +26,7 @@ pub struct NodeInfo {
pub target: String, pub target: String,
pub port: u32, pub port: u32,
pub preference: u8, pub preference: u8,
stream: Option<TcpStream>, streamp: Option<TcpStream>,
} }
impl NodeInfo { impl NodeInfo {
@ -34,24 +35,24 @@ impl NodeInfo {
target: String, target: String,
port: u32, port: u32,
preference: u8, preference: u8,
stream: Option<TcpStream>, streamp: Option<TcpStream>,
) -> NodeInfo { ) -> NodeInfo {
NodeInfo { NodeInfo {
target_name, target_name,
target, target,
port, port,
preference, preference,
stream, streamp,
} }
} }
pub fn update_config( pub fn update_config(
&mut self, &mut self,
config_self_mutex: Arc<Mutex<Config>>, config_self_mutex: Arc<Mutex<Config>>,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<()> {
if let Some(ref mut stream) = self.stream { if let Some(ref mut streamp) = self.streamp {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let read_stream = stream.try_clone().unwrap(); let read_stream = streamp.try_clone().unwrap();
thread::spawn(move || { thread::spawn(move || {
let mut reader = BufReader::new(read_stream); let mut reader = BufReader::new(read_stream);
@ -76,7 +77,7 @@ impl NodeInfo {
// tx.send(response).unwrap_or_default(); // tx.send(response).unwrap_or_default();
}); });
stream.write_all(b"GET CONFIG\n")?; streamp.write_all(b"GET CONFIG\n")?;
let s = match rx.recv_timeout(Duration::from_secs(2)) { let s = match rx.recv_timeout(Duration::from_secs(2)) {
Ok(response) => { Ok(response) => {
@ -90,17 +91,14 @@ impl NodeInfo {
}; };
if s.is_empty() { if s.is_empty() {
debug!("Empty response: {:?}", s); debug!("Empty response: {:?}", s);
return Err(Box::new(std::io::Error::new( bail!("No response");
std::io::ErrorKind::Other,
"No response",
)));
} }
let cfg: Config = match serde_yaml::from_str(&s) { let cfg: Config = match serde_yaml::from_str(&s) {
Ok(cfg) => cfg, Ok(cfg) => cfg,
Err(e) => { Err(e) => {
debug!("Error parsing config: {:?}", e); debug!("Error parsing config: {:?}", e);
return Err(Box::new(e)); bail!(e);
} }
}; };
@ -141,11 +139,8 @@ impl NodeInfo {
return Ok(()); return Ok(());
} }
debug!("No stream for {}", self.target_name); debug!("No streamp for {}", self.target_name);
Err(Box::new(std::io::Error::new( bail!("No streamp");
std::io::ErrorKind::Other,
"No stream",
)))
} }
} }
@ -170,7 +165,7 @@ impl NodeConnections {
pub fn get_node_connection(&self, node_name: String) -> Option<Arc<Mutex<NodeInfo>>> { pub fn get_node_connection(&self, node_name: String) -> Option<Arc<Mutex<NodeInfo>>> {
for connection in &self.connections { for connection in &self.connections {
let conn = connection.lock().unwrap(); let conn = connection.lock().unwrap();
if conn.target_name == node_name && conn.stream.is_some() { if conn.target_name == node_name && conn.streamp.is_some() {
return Some(connection.clone()); return Some(connection.clone());
} }
} }
@ -207,19 +202,19 @@ impl NodeConnections {
let connection = connection.unwrap(); let connection = connection.unwrap();
let connection_guard = connection.lock().unwrap(); let connection_guard = connection.lock().unwrap();
if connection_guard.stream.is_none() { if connection_guard.streamp.is_none() {
return false; return false;
} }
let mut stream = connection_guard let mut streamp = connection_guard
.stream .streamp
.as_ref() .as_ref()
.unwrap() .unwrap()
.try_clone() .try_clone()
.unwrap(); .unwrap();
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let read_stream = stream.try_clone().unwrap(); let read_stream = streamp.try_clone().unwrap();
thread::spawn(move || { thread::spawn(move || {
let mut reader = BufReader::new(read_stream); let mut reader = BufReader::new(read_stream);
@ -237,9 +232,9 @@ impl NodeConnections {
}); });
// Write PING // Write PING
let _ = stream.write_all(b"PING\n"); let _ = streamp.write_all(b"PING\n");
let _ = stream.flush(); let _ = streamp.flush();
let reply = rx.recv_timeout(Duration::from_secs(2)).unwrap_or_default(); let reply = rx.recv_timeout(Duration::from_secs(2)).unwrap_or_default();
if reply == -1 { if reply == -1 {
@ -250,13 +245,13 @@ impl NodeConnections {
pub fn create_node_connection(&mut self, node: &ProviderNode) -> Option<Arc<Mutex<NodeInfo>>> { pub fn create_node_connection(&mut self, node: &ProviderNode) -> Option<Arc<Mutex<NodeInfo>>> {
// TODO: DDNS // TODO: DDNS
let stream = TcpStream::connect_timeout( let streamp = TcpStream::connect_timeout(
&std::net::SocketAddr::new(node.ip.clone().parse().unwrap(), node.port as u16), &std::net::SocketAddr::new(node.ip.clone().parse().unwrap(), node.port as u16),
Duration::from_millis(500), Duration::from_millis(500),
); );
match stream { match streamp {
Ok(stream) => { Ok(streamp) => {
let connection = Arc::new(Mutex::new(NodeInfo::new( let connection = Arc::new(Mutex::new(NodeInfo::new(
node.name.clone(), node.name.clone(),
if node.preference == 0 { if node.preference == 0 {
@ -266,7 +261,7 @@ impl NodeConnections {
}, },
node.port, node.port,
node.preference, node.preference,
Some(stream), Some(streamp),
))); )));
self.connections.push(connection.clone()); self.connections.push(connection.clone());
@ -275,7 +270,7 @@ impl NodeConnections {
Err(error) => { Err(error) => {
if error.kind() != std::io::ErrorKind::ConnectionRefused { if error.kind() != std::io::ErrorKind::ConnectionRefused {
log!("-> Problem creating the stream: {:?}", error); log!("-> Problem creating the streamp: {:?}", error);
} }
None None
} }
@ -295,17 +290,17 @@ impl NodeConnections {
pub fn confirm(&mut self, source: &str, is_ip: bool) -> Option<String> { pub fn confirm(&mut self, source: &str, is_ip: bool) -> Option<String> {
for connection in &self.connections { for connection in &self.connections {
let conn = connection.lock().unwrap(); let conn = connection.lock().unwrap();
if conn.stream.is_none() { if conn.streamp.is_none() {
continue; continue;
} }
let mut stream = conn.stream.as_ref().unwrap(); let mut streamp = conn.streamp.as_ref().unwrap();
stream streamp
.write_all(format!("CONFIRM:{}:{}\n", is_ip as u8, source).as_bytes()) .write_all(format!("CONFIRM:{}:{}\n", is_ip as u8, source).as_bytes())
.unwrap(); .unwrap();
let reader = BufReader::new(stream); let reader = BufReader::new(streamp);
// let mut writer = &stream; // let mut writer = &streamp;
let sis_ip = is_ip.to_string(); let sis_ip = is_ip.to_string();
@ -355,14 +350,14 @@ impl NodeConnections {
) -> Option<ProviderNode> { ) -> Option<ProviderNode> {
for connection in &self.connections { for connection in &self.connections {
let conn = connection.lock().unwrap(); let conn = connection.lock().unwrap();
if conn.stream.is_none() || conn.target_name != target_name { if conn.streamp.is_none() || conn.target_name != target_name {
continue; continue;
} }
let mut stream = conn.stream.as_ref().unwrap(); let mut streamp = conn.streamp.as_ref().unwrap();
stream.write_all(b"GET CONFIG\n").unwrap(); streamp.write_all(b"GET CONFIG\n").unwrap();
let reader = BufReader::new(stream); let reader = BufReader::new(streamp);
for line in reader.lines() { for line in reader.lines() {
if line.is_err() { if line.is_err() {
@ -375,7 +370,7 @@ impl NodeConnections {
let cfg = match parser.parse(None) { let cfg = match parser.parse(None) {
Ok(cfg) => cfg, Ok(cfg) => cfg,
Err(_) => { Err(_) => {
stream.write_all(b"AUTH FAIL: BAD CONFIG\n").unwrap(); streamp.write_all(b"AUTH FAIL: BAD CONFIG\n").unwrap();
continue; continue;
} }
}; };
@ -393,12 +388,12 @@ impl NodeConnections {
fn is_connection_alive(connection: Arc<Mutex<NodeInfo>>) -> bool { fn is_connection_alive(connection: Arc<Mutex<NodeInfo>>) -> bool {
let connection_guard = connection.lock().unwrap(); let connection_guard = connection.lock().unwrap();
if connection_guard.stream.is_none() { if connection_guard.streamp.is_none() {
return false; return false;
} }
let mut stream = connection_guard.stream.as_ref().unwrap(); let mut streamp = connection_guard.streamp.as_ref().unwrap();
match stream.write(&[]) { match streamp.write(&[]) {
Ok(_) => true, Ok(_) => true,
Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => true, Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => true,
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => false, Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => false,