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) { 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 { 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 }