sdlan-lib-rs/src/lib.rs
2024-10-21 09:23:29 +08:00

197 lines
5.5 KiB
Rust

mod config;
mod network;
mod pb;
mod tcp;
mod utils;
use std::{sync::atomic::AtomicU8, time::Duration};
use std::net::{SocketAddr, ToSocketAddrs};
pub use network::get_edge;
pub use network::get_install_channel;
use network::{async_main, init_arp, init_edge, NodeConfig};
use tokio::sync::mpsc::{channel, Sender};
use tokio_util::sync::CancellationToken;
use tracing::{debug, error};
pub use utils::{CommandLine, CommandLineInput};
use sdlan_sn_rs::{
peer::SdlanSock,
utils::{create_or_load_uuid, get_sdlan_sock_from_socketaddr, Result, SDLanError},
};
#[derive(Clone)]
#[repr(u8)]
pub enum ConnectionState {
NotConnected = 0,
Connecting = 1,
Connected = 2,
}
pub async fn run_sdlan(
args: CommandLine,
sender: std::sync::mpsc::Sender<bool>,
install_channel: &str,
connecting_chan: Option<Sender<ConnectionState>>, // start_stop_sender: Sender<String>,
// start_stop_receiver: Receiver<String>,
) -> Result<()> {
let (start_stop_sender, start_stop_chan) = channel(20);
let edge_uuid = create_or_load_uuid("")?;
let node_conf = parse_config(edge_uuid, &args).await?;
init_arp();
if let Err(e) = init_edge(&args.token, node_conf, args.tos, start_stop_sender).await {
panic!("failed to init edge: {:?}", e);
}
let _ = sender.send(true);
debug!("edge inited");
let cancel = CancellationToken::new();
let install_chan = install_channel.to_owned();
tokio::spawn(async move {
if let Err(e) =
async_main(install_chan, args, start_stop_chan, cancel, connecting_chan).await
{
error!("failed to run async main: {}", e.as_str());
}
});
Ok(())
}
async fn parse_config(uuid: String, args: &CommandLine) -> Result<NodeConfig> {
if args.sn.len() == 0 {
return Err(SDLanError::NormalError("no sn is specified"));
}
// node_conf.allow_p2p = args.allow_p2p;
let Ok(addr1) = args.nat_server1.to_socket_addrs() else {
return Err(SDLanError::NormalError("nat_server1 format error"));
};
let Some(nat1) = addr1.into_iter().next() else {
return Err(SDLanError::NormalError("get nat_server1 failed"));
};
let Ok(addr2) = args.nat_server2.to_socket_addrs() else {
return Err(SDLanError::NormalError("nat_server2 format error"));
};
let Some(nat2) = addr2.into_iter().next() else {
return Err(SDLanError::NormalError("get nat_server2 failed"));
};
let sns: Vec<&str> = args.sn.split(",").collect();
let mut correct_sns: Vec<_>;
let mut sockaddr: Vec<_>;
loop {
debug!("parsing sns");
(correct_sns, sockaddr) = parse_sns(&sns);
if sockaddr.len() < 1 {
if correct_sns.len() > 0 {
tokio::time::sleep(Duration::from_millis(500)).await;
continue;
// (correct_sns, sockaddr) = parse_sns(&correct_sns);
} else {
// correct_sns == 0, just error
panic!("no correct sns specified");
}
}
// node_conf.super_nodes = sockaddr;
break;
}
let mut register_ttl = 1;
if args.register_ttl > 1 {
register_ttl = args.register_ttl;
}
let node_conf = NodeConfig {
name: args.name.to_owned(),
allow_routing: true,
_drop_multicast: false,
allow_p2p: args.allow_p2p,
mtu: args.mtu,
_tos: 0,
_register_super_interval: config::REGISTER_SUPER_INTERVAL,
register_ttl,
_local_port: 0,
node_uuid: uuid,
super_nodes: sockaddr,
super_node_index: AtomicU8::new(0),
nat_server1: nat1,
nat_server2: nat2,
};
Ok(node_conf)
}
fn parse_sns<'a>(sns: &'a Vec<&'a str>) -> (Vec<&'a str>, Vec<SdlanSock>) {
let mut correct_sns = vec![];
let mut result = vec![];
for sn in sns {
let addr: Vec<_> = sn.split(":").collect();
if addr.len() != 2 {
error!("sn format error: [host:port] => {}", sn);
continue;
}
let Ok(port) = addr[1].parse::<u16>() else {
continue;
};
// store correct format sns
correct_sns.push(*sn);
// node_conf.super_nodes.push(sock);
if let Ok(ipaddr) = dns_lookup::lookup_host(addr[0]) {
for ip in ipaddr {
let sockaddr = SocketAddr::new(ip, port);
let Ok(sock) = get_sdlan_sock_from_socketaddr(sockaddr) else {
error!("failed to parse sn: {}", sn);
continue;
};
result.push(sock);
}
} else {
error!("failed to parse host: {}", sn);
continue;
}
}
(correct_sns, result)
}
#[cfg(test)]
mod test {
use sdlan_sn_rs::config::AF_INET;
use super::*;
#[test]
#[ignore]
fn test_parse_dns() {
let sns = vec!["git.asxalex.pw:80", "121.4.79.234:81"];
let (correct, res) = parse_sns(&sns);
assert_eq!(correct, sns);
assert_eq!(
res,
vec![
SdlanSock {
family: AF_INET,
port: 80,
v4: [10, 167, 69, 157],
v6: [0; 16],
},
SdlanSock {
family: AF_INET,
port: 81,
v4: [121, 4, 79, 234],
v6: [0; 16],
}
]
)
}
}