87 lines
2.4 KiB
Rust
Executable File

use std::{
net::{IpAddr, Ipv6Addr},
time::Duration,
};
use sdlan_sn_rs::{config::AF_INET6, peer::SdlanSock};
use std::sync::Arc;
use tokio::{sync::mpsc::Receiver};
use tokio_util::sync::CancellationToken;
use tracing::error;
use crate::{network::loop_socket_v6, utils::Socket};
use super::Node;
pub async fn run_ipv6(edge: &'static Node, mut v6_may_change: Receiver<bool>) {
v6_may_change.recv().await;
loop {
tokio::time::sleep(Duration::from_secs(1)).await;
let mut ipv6 = get_current_ipv6();
if ipv6.is_none() {
tokio::time::sleep(Duration::from_secs(5)).await;
ipv6 = get_current_ipv6();
if ipv6.is_none() {
v6_may_change.recv().await;
continue;
}
}
// ipv6 is not none
let ipv6 = ipv6.unwrap();
/*
let Ok(udpsocket) = UdpSocket::bind(format!("{}:0", ipv6)).await else {
tokio::time::sleep(Duration::from_secs(5)).await;
continue;
};
let port = udpsocket.local_addr().unwrap().port();
let addr = udpsocket.local_addr().unwrap().ip();
println!("ipv6: {}:{}", addr, port);
*/
let socket = Arc::new(Socket::build_v6(ipv6, 0).await.unwrap());
let port = socket.get_local_port();
let socket_clone = socket.clone();
let cancel = CancellationToken::new();
*edge.ipv6.write().unwrap() = Some(SdlanSock {
family: AF_INET6,
port,
v4: [0; 4],
v6: ipv6.octets(),
});
*edge.udp_sock_v6.write().unwrap() = Some(socket);
tokio::select! {
_ = loop_socket_v6(edge, socket_clone, cancel.clone()) => {
}
_ = v6_may_change.recv() => {
cancel.cancel()
}
}
}
}
pub fn get_current_ipv6() -> Option<Ipv6Addr> {
let Ok(ips) = local_ip_address::list_afinet_netifas() else {
error!("failed to get ip address");
return None;
};
for (_, ip) in ips {
match ip {
IpAddr::V4(_ipv4) => {
continue;
}
IpAddr::V6(ipv6) => {
if ipv6.octets()[0] & 0x70 == 0x20 {
// println!("got global ip: {}", ipv6);
return Some(ipv6);
}
}
}
}
None
}