diff --git a/Cargo.toml b/Cargo.toml index af3fcbb..2524347 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ byteorder = "1.5.0" cbc = "0.1.2" dashmap = "5.5.3" lazy_static = "1.4.0" +once_cell = "1.19.0" rand = "0.8.5" rolling-file = { git = "https://git.asxalex.pw/rust/rolling-file" } rsa = "0.9.6" diff --git a/src/bin/sdlan-sn/config/mod.rs b/src/bin/sdlan-sn/config/mod.rs new file mode 100644 index 0000000..e63ce0b --- /dev/null +++ b/src/bin/sdlan-sn/config/mod.rs @@ -0,0 +1,3 @@ +pub const DEFAULT_MIN_AUTO_IP_NET: &'static str = "10.128.0.0"; +pub const DEFAULT_MAX_AUTO_IP_NET: &'static str = "10.255.255.0"; +pub const DEFAULT_IP_NET_BIT_LEN: u8 = 24; diff --git a/src/bin/sdlan-sn/main.rs b/src/bin/sdlan-sn/main.rs index b42ec3a..a2afeb8 100644 --- a/src/bin/sdlan-sn/main.rs +++ b/src/bin/sdlan-sn/main.rs @@ -8,6 +8,7 @@ use std::net::SocketAddr; use std::time::Duration; use tokio::net::UdpSocket; +mod config; mod utils; use utils::license_ok; @@ -43,16 +44,21 @@ async fn main() -> Result<()> { let listener = UdpSocket::bind(SERVER).await?; + let supernode = utils::SuperNode::new(listener); + utils::init_supernode(supernode); + tokio::spawn(async { client(SERVER).await.unwrap(); }); + let listener = utils::get_supernode(); loop { // let mut buffer = [0; 2048]; let mut buffer = vec![0; 2048]; // let mut data = Vec::with_capacity(2048); - let (n, addr) = listener.recv_from(&mut buffer).await?; + let (n, addr) = listener.sock.recv_from(&mut buffer).await?; buffer.truncate(n); + tokio::spawn(async move { if let Err(e) = handle_packet(&buffer, addr).await { error!("failed to handle packet: {:?}", e); diff --git a/src/bin/sdlan-sn/utils/license.rs b/src/bin/sdlan-sn/utils/license.rs new file mode 100644 index 0000000..40772d9 --- /dev/null +++ b/src/bin/sdlan-sn/utils/license.rs @@ -0,0 +1,25 @@ +use sdlan_sn_rs::utils::Result; +use serde::{Deserialize, Serialize}; +use tracing::error; + +#[derive(Serialize, Deserialize)] +struct LicenseInfo<'a> { + // 由谁颁发的 + #[serde(rename = "from")] + from: &'a str, + // 颁发给谁的 + #[serde(rename = "to")] + to: &'a str, + // 有效起始时间 + #[serde(rename = "starts")] + starts: i64, + // 有效结束时间 + #[serde(rename = "ends")] + ends: i64, +} + +pub fn license_ok() -> Result<()> { + // TODO: check license + error!("license expired"); + Ok(()) +} diff --git a/src/bin/sdlan-sn/utils/mod.rs b/src/bin/sdlan-sn/utils/mod.rs index a25b639..a9158f4 100644 --- a/src/bin/sdlan-sn/utils/mod.rs +++ b/src/bin/sdlan-sn/utils/mod.rs @@ -1,25 +1,5 @@ -use sdlan_sn_rs::utils::{rsa_decrypt, Result}; -use serde::{Deserialize, Serialize}; -use tracing::error; +mod sn; +pub use sn::*; -#[derive(Serialize, Deserialize)] -struct LicenseInfo<'a> { - // 由谁颁发的 - #[serde(rename = "from")] - from: &'a str, - // 颁发给谁的 - #[serde(rename = "to")] - to: &'a str, - // 有效起始时间 - #[serde(rename = "starts")] - starts: i64, - // 有效结束时间 - #[serde(rename = "ends")] - ends: i64, -} - -pub fn license_ok() -> Result<()> { - // TODO: check license - error!("license expired"); - Ok(()) -} +mod license; +pub use license::*; diff --git a/src/bin/sdlan-sn/utils/sn.rs b/src/bin/sdlan-sn/utils/sn.rs new file mode 100644 index 0000000..bc4c9fb --- /dev/null +++ b/src/bin/sdlan-sn/utils/sn.rs @@ -0,0 +1,105 @@ +use dashmap::DashMap; +use sdlan_sn_rs::peer::IpSubnet; +use tokio::net::UdpSocket; + +use std::{ + sync::atomic::{AtomicU32, AtomicU8}, + time::{SystemTime, UNIX_EPOCH}, +}; + +use sdlan_sn_rs::utils::{Result, SDLanError}; + +use once_cell::sync::OnceCell; + +static SN: OnceCell = OnceCell::new(); + +pub fn init_supernode(sn: SuperNode) -> Result<()> { + if let Err(e) = SN.set(sn) { + return Err(SDLanError::NormalError("initialize sn error")); + } + Ok(()) +} + +pub fn get_supernode() -> &'static SuperNode { + SN.get().expect("Supernode has not been initialized") +} + +pub struct SuperNode { + // supernode 启动时间 + pub start_time: u64, + // 是否以daemon,后台运行。 + pub daemon: bool, + + // 本地监听的udp端口号 + pub local_port: i16, + + // 该SuperNode包含的所有的网络 + // 在云端创建或者删除网络的时候,需要通知sn修改这个网络信息 + pub networks: DashMap, + + /// 把所有其他的supernode放在这个fedration里面, + /// 在广播或者收到消息发现本地不存在这个目标数据包的时候, + /// 需要把数据包广播到这个fedration中。 + pub fedration: Network, + + /// pending网络,所有未授权的放到这个网络里面 + /// 当某个SN收到来自客户端的信息的时候,需要把客户端加到这个pending + /// 在数据库中保存一条记录,并且在redis中记录一条信息,表明这个客户端 + /// 在我这个Supernode上 + pub pending: Network, + + pub ip_range: AutoIpAssign, + + pub sock: UdpSocket, + + pub auth_key: String, +} + +impl SuperNode { + pub fn new(sock: UdpSocket) -> Self { + let now = SystemTime::now(); + println!("now: {:?}", now); + let start_time = now + .duration_since(UNIX_EPOCH) + .expect("time went backwards") + .as_secs(); + + Self { + start_time, + daemon: false, + local_port: 7655, + networks: DashMap::new(), + fedration: Network::new("*fedration"), + pending: Network::new("*pending"), + ip_range: AutoIpAssign { + start_ip: IpSubnet { + net_addr: AtomicU32::new(0), + net_bit_len: AtomicU8::new(0), + }, + end_ip: IpSubnet { + net_addr: AtomicU32::new(0), + net_bit_len: AtomicU8::new(0), + }, + }, + sock, + auth_key: String::from("encrypt!"), + } + } +} + +pub struct AutoIpAssign { + pub start_ip: IpSubnet, + pub end_ip: IpSubnet, +} + +pub struct Network { + name: String, +} + +impl Network { + fn new(name: &str) -> Self { + Self { + name: name.to_string(), + } + } +} diff --git a/src/bin/sdlan/main.rs b/src/bin/sdlan/main.rs index 7f755fb..c2c4bd3 100644 --- a/src/bin/sdlan/main.rs +++ b/src/bin/sdlan/main.rs @@ -1,2 +1,4 @@ +use tokio::net::UdpSocket; + #[tokio::main] async fn main() {} diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 899a22f..3d57720 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -14,7 +14,7 @@ pub mod test_utils { pub fn generate_info(n: i32) -> Vec { let mut result = vec![]; - for i in 0..n { + for _ in 0..n { let v: u8 = thread_rng().gen_range(0..255); result.push(v); }