sdlan
This commit is contained in:
commit
de029dd6e7
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
*.so
|
||||||
2416
Cargo.lock
generated
Normal file
2416
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
19
Cargo.toml
Normal file
19
Cargo.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "sdlan-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dashmap = "6.0.1"
|
||||||
|
etherparse = "0.15.0"
|
||||||
|
futures-util = "0.3.30"
|
||||||
|
num_enum = "0.7.2"
|
||||||
|
once_cell = "1.19.0"
|
||||||
|
prost = "0.12.6"
|
||||||
|
prost-build = "0.12.6"
|
||||||
|
rsa = "0.9.6"
|
||||||
|
sdlan-sn-rs = { git = "ssh://git@git.asxalex.pw/sdlan-v2/sdlan-rs.git" }
|
||||||
|
structopt = "0.3.26"
|
||||||
|
tokio = { version = "1.38.0", futures = ["full"] }
|
||||||
|
tokio-util = "0.7.11"
|
||||||
|
tracing = "0.1.40"
|
||||||
6
Makefile
Normal file
6
Makefile
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pb:
|
||||||
|
cargo run --bin build_pb
|
||||||
|
mv src/pb/_.rs src/pb/message.rs
|
||||||
|
|
||||||
|
libtun-so:
|
||||||
|
cd src/network && gcc -fPIC -shared -o libtuntap.so tuntap.c && cd -
|
||||||
156
message.proto
Normal file
156
message.proto
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
// 基础公共类型定义
|
||||||
|
|
||||||
|
message SDLV4Info {
|
||||||
|
uint32 port = 1;
|
||||||
|
bytes v4 = 2;
|
||||||
|
uint32 nat_type = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLV6Info {
|
||||||
|
uint32 port = 1;
|
||||||
|
bytes v6 = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设备网络地址信息
|
||||||
|
message SDLDevAddr {
|
||||||
|
uint32 network_id = 1;
|
||||||
|
uint32 net_addr = 2;
|
||||||
|
uint32 net_bit_len = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tcp通讯消息
|
||||||
|
message SDLEmpty {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLRegisterSuper {
|
||||||
|
uint32 version = 1;
|
||||||
|
string installed_channel = 2;
|
||||||
|
string client_id = 3;
|
||||||
|
SDLDevAddr dev_addr = 4;
|
||||||
|
string pub_key = 5;
|
||||||
|
string token = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLRegisterSuperAck {
|
||||||
|
SDLDevAddr dev_addr = 1;
|
||||||
|
bytes aes_key = 2;
|
||||||
|
bytes known_ips = 3;
|
||||||
|
uint32 upgrade_type = 4;
|
||||||
|
optional string upgrade_prompt = 5;
|
||||||
|
optional string upgrade_address = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLRegisterSuperNak {
|
||||||
|
uint32 error_code = 1;
|
||||||
|
string error_message = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网络地址查询
|
||||||
|
|
||||||
|
message SDLQueryInfo {
|
||||||
|
uint32 dst_ip = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLPeerInfo {
|
||||||
|
uint32 dst_ip = 1;
|
||||||
|
SDLV4Info v4_info = 2;
|
||||||
|
optional SDLV6Info v6_info = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 事件定义
|
||||||
|
|
||||||
|
message SDLKnownIpEvent {
|
||||||
|
uint32 ip = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLDropIpEvent {
|
||||||
|
uint32 ip = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLNatChangedEvent {
|
||||||
|
uint32 ip = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLSendRegisterEvent {
|
||||||
|
uint32 dst_ip = 1;
|
||||||
|
uint32 nat_ip = 2;
|
||||||
|
uint32 nat_port = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLNetworkShutdownEvent {
|
||||||
|
string message = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 命令定义
|
||||||
|
|
||||||
|
message SDLChangeNetworkCommand {
|
||||||
|
SDLDevAddr dev_addr = 1;
|
||||||
|
bytes aes_key = 2;
|
||||||
|
bytes known_ips = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLCommandAck {
|
||||||
|
// status = true, 表示成功;status = false 表示失败,message是失败原因描述
|
||||||
|
bool status = 1;
|
||||||
|
optional string message = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLFlows {
|
||||||
|
// 服务器转发流量
|
||||||
|
uint32 forward_num = 1;
|
||||||
|
// p2p直接流量
|
||||||
|
uint32 p2p_num = 2;
|
||||||
|
// 接收的流量
|
||||||
|
uint32 inbound_num = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDP通讯消息
|
||||||
|
|
||||||
|
message SDLStunRequest {
|
||||||
|
uint32 cookie = 1;
|
||||||
|
string client_id = 2;
|
||||||
|
uint32 network_id = 3;
|
||||||
|
uint32 ip = 4;
|
||||||
|
uint32 nat_type = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLStunReply {
|
||||||
|
uint32 cookie = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLData {
|
||||||
|
uint32 network_id = 1;
|
||||||
|
uint32 src_ip = 2;
|
||||||
|
uint32 dst_ip = 3;
|
||||||
|
bool is_p2p = 4;
|
||||||
|
uint32 ttl = 5;
|
||||||
|
bytes data = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLRegister {
|
||||||
|
uint32 network_id = 1;
|
||||||
|
uint32 src_ip = 2;
|
||||||
|
uint32 dst_ip = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLRegisterAck {
|
||||||
|
uint32 network_id = 1;
|
||||||
|
uint32 src_ip = 2;
|
||||||
|
uint32 dst_ip = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网络类型探测
|
||||||
|
|
||||||
|
message SDLStunProbe {
|
||||||
|
uint32 cookie = 1;
|
||||||
|
uint32 attr = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SDLStunProbeReply {
|
||||||
|
uint32 cookie = 1;
|
||||||
|
uint32 port = 2;
|
||||||
|
uint32 ip = 3;
|
||||||
|
}
|
||||||
8
src/bin/build_pb/main.rs
Normal file
8
src/bin/build_pb/main.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fn main() {
|
||||||
|
prost_build::Config::new()
|
||||||
|
.out_dir("src/pb")
|
||||||
|
// .out_dir("../tcp_mock/pb")
|
||||||
|
.protoc_arg("--experimental_allow_proto3_optional")
|
||||||
|
.compile_protos(&["message.proto"], &["../sdlan/"])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
9
src/config/mod.rs
Normal file
9
src/config/mod.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub const REGISTER_INTERVAL: u8 = 20;
|
||||||
|
pub const REGISTER_SUPER_INTERVAL: u16 = 20;
|
||||||
|
|
||||||
|
pub const MULITCAST_V4: [u8; 4] = [224, 0, 0, 69];
|
||||||
|
pub const MULTICAST_PORT: u16 = 1969;
|
||||||
|
|
||||||
|
// pub const SUPER_ATTEMPTS_DEFAULT: u8 = 3;
|
||||||
|
|
||||||
|
pub const TCP_PING_TIME: u64 = 7;
|
||||||
5
src/lib.rs
Normal file
5
src/lib.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod config;
|
||||||
|
mod network;
|
||||||
|
mod pb;
|
||||||
|
mod tcp;
|
||||||
|
mod utils;
|
||||||
495
src/network/async_main.rs
Normal file
495
src/network/async_main.rs
Normal file
@ -0,0 +1,495 @@
|
|||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::config::TCP_PING_TIME;
|
||||||
|
use crate::network::{get_edge, ping_to_sn, read_and_parse_packet};
|
||||||
|
use crate::pb::{
|
||||||
|
encode_to_tcp_message, encode_to_udp_message, SdlData, SdlDevAddr, SdlRegisterSuper,
|
||||||
|
SdlRegisterSuperAck, SdlRegisterSuperNak, SdlSendRegisterEvent, SdlStunRequest,
|
||||||
|
};
|
||||||
|
use crate::tcp::{init_tcp_conn, EventType, PacketType, SdlanTcp};
|
||||||
|
use crate::utils::{send_to_sock, CommandLine};
|
||||||
|
use etherparse::IpHeaders;
|
||||||
|
use sdlan_sn_rs::config::{AF_INET, SDLAN_DEFAULT_TTL};
|
||||||
|
use sdlan_sn_rs::peer::SdlanSock;
|
||||||
|
use sdlan_sn_rs::utils::{
|
||||||
|
self, aes_encrypt, create_or_load_uuid, get_current_timestamp, ip_to_string,
|
||||||
|
is_multi_broadcast, rsa_decrypt,
|
||||||
|
};
|
||||||
|
use sdlan_sn_rs::utils::{Result, SDLanError};
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
use tokio::sync::mpsc::{channel, Receiver, Sender};
|
||||||
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
|
use super::{check_peer_registration_needed, init_edge, packet, Node, NodeConfig};
|
||||||
|
use crate::utils::Socket;
|
||||||
|
|
||||||
|
use prost::Message;
|
||||||
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
|
async fn handle_tcp_message(msg: SdlanTcp) {
|
||||||
|
let edge = get_edge();
|
||||||
|
|
||||||
|
// let now = get_current_timestamp();
|
||||||
|
// edge.tcp_pong.store(now, Ordering::Relaxed);
|
||||||
|
|
||||||
|
debug!("got tcp message: {:?}", msg.packet_type);
|
||||||
|
match msg.packet_type {
|
||||||
|
PacketType::RegisterSuperACK => {
|
||||||
|
let Ok(ack) = SdlRegisterSuperAck::decode(&msg.current_packet[..]) else {
|
||||||
|
error!("failed to decode REGISTER_SUPER_ACK");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
debug!("got register super ack: {:?}", ack);
|
||||||
|
let Ok(aes) = rsa_decrypt(&edge.rsa_private, &ack.aes_key) else {
|
||||||
|
error!("failed to rsa decrypt aes key");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Some(dev) = ack.dev_addr else {
|
||||||
|
error!("no dev_addr is specified");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let ip = ip_to_string(&dev.net_addr);
|
||||||
|
debug!("aes key is {:?}, ip is {}/{}", aes, ip, dev.net_bit_len,);
|
||||||
|
edge.device_config
|
||||||
|
.ip
|
||||||
|
.net_addr
|
||||||
|
.store(dev.net_addr, Ordering::Relaxed);
|
||||||
|
edge.device_config
|
||||||
|
.ip
|
||||||
|
.net_bit_len
|
||||||
|
.store(dev.net_bit_len as u8, Ordering::Relaxed);
|
||||||
|
edge.device.reload_config(&edge.device_config);
|
||||||
|
edge.network_id.store(dev.network_id, Ordering::Relaxed);
|
||||||
|
|
||||||
|
edge.set_authorized(true, aes);
|
||||||
|
}
|
||||||
|
PacketType::RegisterSuperNAK => {
|
||||||
|
let Ok(_nak) = SdlRegisterSuperNak::decode(&msg.current_packet[..]) else {
|
||||||
|
error!("failed to decode REGISTER_SUPER_NAK");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
edge.set_authorized(false, Vec::new());
|
||||||
|
// std::process::exit(0);
|
||||||
|
}
|
||||||
|
PacketType::Command => {
|
||||||
|
if msg.current_packet.len() < 1 {
|
||||||
|
error!("malformed COMMAND received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
handle_tcp_command(edge, msg.current_packet[0], &msg.current_packet[1..]).await;
|
||||||
|
}
|
||||||
|
PacketType::Event => {
|
||||||
|
if msg.current_packet.len() < 1 {
|
||||||
|
error!("malformed EVENT received");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Ok(event) = msg.current_packet[0].try_into() else {
|
||||||
|
error!("failed to parse event type");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
handle_tcp_event(edge, event, &msg.current_packet[1..]).await;
|
||||||
|
}
|
||||||
|
PacketType::PeerInfo => {
|
||||||
|
let _ = packet::handle_packet_peer_info(edge, &msg.current_packet[..]).await;
|
||||||
|
}
|
||||||
|
PacketType::Pong => {
|
||||||
|
debug!("tcp pong received");
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
edge.tcp_pong.store(now, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
debug!("tcp not handling {:?}", other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_tcp_command(_edge: &Node, _cmdtype: u8, _cmdprotobuf: &[u8]) {}
|
||||||
|
|
||||||
|
async fn handle_tcp_event(edge: &Node, eventtype: EventType, eventprotobuf: &[u8]) {
|
||||||
|
match eventtype {
|
||||||
|
EventType::SendRegister => {
|
||||||
|
let Ok(reg) = SdlSendRegisterEvent::decode(eventprotobuf) else {
|
||||||
|
error!("failed to decode SendRegister Event");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let v4 = reg.nat_ip.to_be_bytes();
|
||||||
|
check_peer_registration_needed(
|
||||||
|
edge,
|
||||||
|
true,
|
||||||
|
reg.dst_ip,
|
||||||
|
&None,
|
||||||
|
&SdlanSock {
|
||||||
|
family: AF_INET,
|
||||||
|
port: reg.nat_port as u16,
|
||||||
|
v4,
|
||||||
|
v6: [0; 16],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
debug!("unhandled event {:?}", other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn async_main(
|
||||||
|
install_channel: String,
|
||||||
|
args: CommandLine,
|
||||||
|
start_stop_chan: Receiver<bool>,
|
||||||
|
cancel: CancellationToken,
|
||||||
|
) -> Result<()> {
|
||||||
|
// let _ = PidRecorder::new(".pid");
|
||||||
|
|
||||||
|
// // gen public key
|
||||||
|
// gen_rsa_keys(".client");
|
||||||
|
// let mut pubkey = String::new();
|
||||||
|
// File::open(".client/id_rsa.pub")?.read_to_string(&mut pubkey)?;
|
||||||
|
// let privatekey = load_private_key_file(".client/id_rsa")?;
|
||||||
|
|
||||||
|
// // init sock
|
||||||
|
// if args.token.len() == 0 {
|
||||||
|
// println!("failed to load token");
|
||||||
|
// return Ok(());
|
||||||
|
// }
|
||||||
|
// let sock_v4 = Socket::build(0, true, true, args.tos).await?;
|
||||||
|
|
||||||
|
// // allow multicast
|
||||||
|
|
||||||
|
// // TODO: set the sn's tcp socket
|
||||||
|
// // let tcpsock = TCPSocket::build("121.4.79.234:1234").await?;
|
||||||
|
// let tcp_pong = Arc::new(AtomicU64::new(0));
|
||||||
|
// let edge = Node::new(
|
||||||
|
// pubkey,
|
||||||
|
// node_conf,
|
||||||
|
// sock_v4,
|
||||||
|
// &args.token,
|
||||||
|
// privatekey,
|
||||||
|
// tcp_pong.clone(),
|
||||||
|
// );
|
||||||
|
|
||||||
|
let edge = get_edge();
|
||||||
|
|
||||||
|
// let token = args.token.clone();
|
||||||
|
init_tcp_conn(
|
||||||
|
&args.tcp,
|
||||||
|
move |stream| {
|
||||||
|
let token = args.token.clone();
|
||||||
|
let installed_channel = install_channel.to_owned();
|
||||||
|
Box::pin(async {
|
||||||
|
// let edge = get_edge();
|
||||||
|
// let edge = get_edge();
|
||||||
|
// let token = args.token.clone();
|
||||||
|
let register_super = SdlRegisterSuper {
|
||||||
|
version: 1,
|
||||||
|
installed_channel,
|
||||||
|
client_id: edge.config.node_uuid.clone(),
|
||||||
|
dev_addr: Some(SdlDevAddr {
|
||||||
|
net_addr: 0,
|
||||||
|
network_id: 0,
|
||||||
|
net_bit_len: 0,
|
||||||
|
}),
|
||||||
|
pub_key: edge.rsa_pubkey.clone(),
|
||||||
|
token,
|
||||||
|
};
|
||||||
|
let packet_id = edge.get_next_packet_id();
|
||||||
|
let data = encode_to_tcp_message(
|
||||||
|
Some(register_super),
|
||||||
|
packet_id,
|
||||||
|
PacketType::RegisterSuper as u8,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
if let Err(e) = stream.write(&data).await {
|
||||||
|
error!("failed to write to tcp: {}", e.to_string());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|msg| handle_tcp_message(msg),
|
||||||
|
edge.tcp_pong.clone(),
|
||||||
|
// tcp_pong,
|
||||||
|
start_stop_chan,
|
||||||
|
);
|
||||||
|
|
||||||
|
// tcp_conn.send("hello".as_bytes()).await;
|
||||||
|
// tokio::spawn(handle_tcp_message(tcp_conn.data_from_tcp));
|
||||||
|
|
||||||
|
// tcp_conn.send("".as_bytes());
|
||||||
|
|
||||||
|
debug!("waiting for authorization...");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// let _ = edge.send_register_super().await;
|
||||||
|
// let _ = read_and_parse_packet(edge, &edge.udp_sock_v4, Some(Duration::from_secs(3))).await;
|
||||||
|
println!("checking for authorized");
|
||||||
|
if edge.is_authorized() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tokio::select! {
|
||||||
|
_ = tokio::time::sleep(Duration::from_secs(3)) => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_ = cancel.cancelled() => {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let cancel = cancel.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
run_edge_loop(edge, cancel).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let cancel = cancel.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = cancel.cancelled() => {
|
||||||
|
if let Err(e) = edge.send_unregister_super().await {
|
||||||
|
error!("failed to send unregister super: {}", e.as_str());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ = tokio::time::sleep(Duration::from_secs(TCP_PING_TIME)) => {
|
||||||
|
ping_to_sn().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("loop update_supernode_reg exited");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel.cancelled().await;
|
||||||
|
/*
|
||||||
|
match tokio::signal::ctrl_c().await {
|
||||||
|
Ok(()) => {
|
||||||
|
debug!("shutdown received");
|
||||||
|
cancel.cancel();
|
||||||
|
debug!("exiting async_main");
|
||||||
|
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||||
|
debug!("exiting async_main2");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("failed to listen for shutdown signal: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// std::process::exit(0);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run_edge_loop(eee: &'static Node, cancel: CancellationToken) {
|
||||||
|
ping_to_sn().await;
|
||||||
|
{
|
||||||
|
let cancel = cancel.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop_socket_v4(eee, &eee.udp_sock_v4, cancel).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop_tap(eee, cancel).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn loop_socket_v4(eee: &Node, socket: &Socket, cancel: CancellationToken) {
|
||||||
|
debug!("loop sock v4");
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = cancel.cancelled() => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ = read_and_parse_packet(eee, socket,Some(Duration::from_secs(10))) => { }
|
||||||
|
_ = tokio::time::sleep(Duration::from_secs(10)) => {
|
||||||
|
let req = SdlStunRequest {
|
||||||
|
cookie: 0,
|
||||||
|
client_id: eee.config.node_uuid.clone(),
|
||||||
|
network_id: eee.network_id.load(Ordering::Relaxed),
|
||||||
|
ip: eee.device_config.get_ip(),
|
||||||
|
nat_type: 0,
|
||||||
|
};
|
||||||
|
let msg = encode_to_udp_message(Some(req), PacketType::StunRequest as u8).unwrap();
|
||||||
|
if let Err(e) = send_to_sock(eee, &msg, &eee.config.super_nodes[eee.config.super_node_index.load(Ordering::Relaxed) as usize]).await {
|
||||||
|
error!("failed to send to sock: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("loop_socket_v4 exited");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn loop_tap(eee: &'static Node, cancel: CancellationToken) {
|
||||||
|
debug!("loop tap");
|
||||||
|
let (tx, mut rx) = channel(10);
|
||||||
|
tokio::spawn(async {
|
||||||
|
get_tun_flow(eee, tx).await;
|
||||||
|
});
|
||||||
|
|
||||||
|
loop {
|
||||||
|
tokio::select! {
|
||||||
|
_ = cancel.cancelled() => {
|
||||||
|
drop(rx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf = rx.recv() => {
|
||||||
|
if buf.is_none() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
read_and_parse_tun_packet(eee, buf.unwrap()).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("loop_tap exited");
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_tun_flow(eee: &'static Node, tx: Sender<Vec<u8>>) {
|
||||||
|
loop {
|
||||||
|
let buf = tokio::task::spawn_blocking(|| {
|
||||||
|
let mut buf = vec![0; 1800];
|
||||||
|
let Ok(size) = eee.device.recv(&mut buf) else {
|
||||||
|
return vec![];
|
||||||
|
};
|
||||||
|
buf.truncate(size);
|
||||||
|
buf
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if buf.len() == 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Err(e) = tx.send(buf).await {
|
||||||
|
error!("failed to send buf: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_and_parse_tun_packet(eee: &'static Node, buf: Vec<u8>) {
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
debug!("drop packet before authorized");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if eee.stats.last_sup.load(Ordering::Relaxed) == 0 {
|
||||||
|
debug!("drop packet before first registration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// buf.truncate(size);
|
||||||
|
|
||||||
|
edge_send_packet_to_net(eee, &buf).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn edge_send_packet_to_net(eee: &Node, data: &[u8]) {
|
||||||
|
debug!("edge send packet to net({} bytes): {:?}", data.len(), data);
|
||||||
|
match IpHeaders::from_slice(&data) {
|
||||||
|
Ok((iphdr, _payload)) => {
|
||||||
|
let Some(ipv4hdr) = iphdr.ipv4() else {
|
||||||
|
debug!("ipv6 packet ignored");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let dstip = u32::from_be_bytes(ipv4hdr.0.destination);
|
||||||
|
debug!("packet dst ip: {:?}", ipv4hdr.0.destination);
|
||||||
|
let src = u32::from_be_bytes(ipv4hdr.0.source);
|
||||||
|
debug!("packet src ip: {:?}", ipv4hdr.0.source);
|
||||||
|
// packet should be sent to dev
|
||||||
|
debug!("got {} bytes from tun", data.len());
|
||||||
|
if (!eee.config.allow_routing) && (src != eee.device_config.get_ip()) {
|
||||||
|
info!("dropping routed packet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
debug!("drop tun packet due to not authed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let encrypt_key = eee.get_encrypt_key();
|
||||||
|
if encrypt_key.len() == 0 {
|
||||||
|
error!("drop tun packet due to encrypt key len is 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let Ok(encrypted_flow) = aes_encrypt(encrypt_key.as_slice(), data) else {
|
||||||
|
error!("failed to encrypt flow");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let message = SdlData {
|
||||||
|
// TODO: network id should be stored in
|
||||||
|
network_id: eee.network_id.load(Ordering::Relaxed),
|
||||||
|
src_ip: eee.device_config.get_ip(),
|
||||||
|
dst_ip: dstip,
|
||||||
|
is_p2p: true,
|
||||||
|
ttl: SDLAN_DEFAULT_TTL as u32,
|
||||||
|
data: encrypted_flow,
|
||||||
|
};
|
||||||
|
debug!("sending SdlData: {:?}", message);
|
||||||
|
let Ok(flow) = encode_to_udp_message(Some(message), PacketType::Data as u8) else {
|
||||||
|
error!("failed to encode to udp message");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
send_packet_to_net(eee, dstip, &flow).await;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to parse ip packet: {}", e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_packet_to_net(eee: &Node, dst_ip: u32, pkt: &[u8]) {
|
||||||
|
let (dest_sock, is_p2p) = find_peer_destination(eee, dst_ip).await;
|
||||||
|
if is_p2p {
|
||||||
|
eee.stats.tx_p2p.fetch_add(1, Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
eee.stats.tx_sup.fetch_add(1, Ordering::Relaxed);
|
||||||
|
if is_multi_broadcast(dst_ip) {
|
||||||
|
eee.stats.tx_broadcast.fetch_add(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!("send packet PACKET to {}", dest_sock.to_string());
|
||||||
|
if let Err(e) = send_to_sock(eee, pkt, &dest_sock).await {
|
||||||
|
error!("failed to send packet to net: {}", e.as_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn find_peer_destination(eee: &Node, dst_ip: u32) -> (SdlanSock, bool) {
|
||||||
|
if is_multi_broadcast(dst_ip) {
|
||||||
|
return (
|
||||||
|
eee.config.super_nodes[eee.config.super_node_index.load(Ordering::Relaxed) as usize]
|
||||||
|
.deepcopy(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let mut is_p2p = false;
|
||||||
|
let result: SdlanSock;
|
||||||
|
if let Some(dst) = eee.known_peers.get_peer(&dst_ip) {
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
if now - dst.last_seen.load(Ordering::Relaxed) >= ((dst.timeout / 2) as u64) {
|
||||||
|
// too much time elapsed since we saw the peer, need to register again
|
||||||
|
eee.known_peers.delete_peer_with_ip(&dst_ip);
|
||||||
|
result = eee.config.super_nodes
|
||||||
|
[eee.config.super_node_index.load(Ordering::Relaxed) as usize]
|
||||||
|
.deepcopy();
|
||||||
|
} else {
|
||||||
|
// dst.last_seen.store(now, Ordering::Relaxed);
|
||||||
|
is_p2p = true;
|
||||||
|
result = dst.sock.read().unwrap().deepcopy();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = eee.config.super_nodes
|
||||||
|
[eee.config.super_node_index.load(Ordering::Relaxed) as usize]
|
||||||
|
.deepcopy();
|
||||||
|
}
|
||||||
|
if !is_p2p {
|
||||||
|
debug!("check_query_peer_info");
|
||||||
|
super::packet::check_query_peer_info(eee, dst_ip).await;
|
||||||
|
}
|
||||||
|
return (result, is_p2p);
|
||||||
|
}
|
||||||
56
src/network/device.rs
Normal file
56
src/network/device.rs
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
use sdlan_sn_rs::peer::IpSubnet;
|
||||||
|
|
||||||
|
pub struct DeviceConfig {
|
||||||
|
pub ip: IpSubnet,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DeviceConfig {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
DeviceConfig {
|
||||||
|
ip: IpSubnet::new(0, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn set_ip(&self, net_addr: u32, net_bit_len: u8) {
|
||||||
|
if net_bit_len <= 8 || net_bit_len > 32 {
|
||||||
|
error!("configured net bit length error: {}", net_bit_len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.ip.net_addr.store(net_addr, Ordering::Relaxed);
|
||||||
|
self.ip.net_bit_len.store(net_bit_len, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn get_ip(&self) -> u32 {
|
||||||
|
self.ip.net_addr()
|
||||||
|
}
|
||||||
|
pub fn get_net_bit(&self) -> u8 {
|
||||||
|
self.ip.net_bit_len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The mode in which open the virtual network adapter.
|
||||||
|
#[allow(unused)]
|
||||||
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
|
||||||
|
pub enum Mode {
|
||||||
|
/// TUN mode
|
||||||
|
///
|
||||||
|
/// The packets returned are on the IP layer (layer 3), prefixed with 4-byte header (2 bytes
|
||||||
|
/// are flags, 2 bytes are the protocol inside, eg one of
|
||||||
|
/// <https://en.wikipedia.org/wiki/EtherType#Examples>.
|
||||||
|
Tun = 1,
|
||||||
|
/// TAP mode
|
||||||
|
///
|
||||||
|
/// The packets are on the transport layer (layer 2), and start with ethernet frame header.
|
||||||
|
Tap = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub trait TunDevice: ReadWriter {
|
||||||
|
fn name(&self) -> &str;
|
||||||
|
fn mode(&self) -> &Mode;
|
||||||
|
fn get_ip(&self) -> u32;
|
||||||
|
fn get_net_bit(&self) -> u8;
|
||||||
|
}
|
||||||
|
*/
|
||||||
21
src/network/mod.rs
Normal file
21
src/network/mod.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
mod node;
|
||||||
|
pub use node::*;
|
||||||
|
|
||||||
|
mod async_main;
|
||||||
|
pub use async_main::*;
|
||||||
|
|
||||||
|
mod packet;
|
||||||
|
pub use packet::*;
|
||||||
|
|
||||||
|
#[cfg_attr(target_os = "linux", path = "tun_linux.rs")]
|
||||||
|
#[cfg_attr(target_os = "windows", path = "tun_win.rs")]
|
||||||
|
mod tun;
|
||||||
|
|
||||||
|
mod device;
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub trait ReadWriter {
|
||||||
|
fn send(&self, content: &[u8]) -> std::io::Result<usize>;
|
||||||
|
fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize>;
|
||||||
|
}
|
||||||
|
*/
|
||||||
480
src/network/node.rs
Normal file
480
src/network/node.rs
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
use dashmap::DashMap;
|
||||||
|
use rsa::RsaPrivateKey;
|
||||||
|
use sdlan_sn_rs::config::{AF_INET, AF_INET6};
|
||||||
|
use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicU8, Ordering};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use tokio::io::AsyncReadExt;
|
||||||
|
|
||||||
|
use crate::pb::{encode_to_tcp_message, SdlEmpty};
|
||||||
|
use crate::tcp::{get_tcp_conn, PacketType};
|
||||||
|
use crate::utils::{PidRecorder, Socket};
|
||||||
|
|
||||||
|
use sdlan_sn_rs::peer::{is_sdlan_sock_equal, IpSubnet, V6Info};
|
||||||
|
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
|
use super::device::{DeviceConfig, Mode};
|
||||||
|
use super::tun::{new_iface, Iface};
|
||||||
|
use tokio::fs::File;
|
||||||
|
|
||||||
|
use sdlan_sn_rs::utils::{create_or_load_uuid, gen_rsa_keys, load_private_key_file};
|
||||||
|
use sdlan_sn_rs::utils::{Result, SDLanError};
|
||||||
|
|
||||||
|
static EDGE: OnceCell<Node> = OnceCell::new();
|
||||||
|
|
||||||
|
pub async fn init_edge(token: &str, node_conf: NodeConfig, tos: u32) -> Result<()> {
|
||||||
|
if token.len() == 0 {
|
||||||
|
println!("failed to load token");
|
||||||
|
return Err(SDLanError::NormalError("no token is specified"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = PidRecorder::new(".pid");
|
||||||
|
|
||||||
|
// gen public key
|
||||||
|
gen_rsa_keys(".client");
|
||||||
|
let mut pubkey = String::new();
|
||||||
|
|
||||||
|
File::open(".client/id_rsa.pub")
|
||||||
|
.await?
|
||||||
|
.read_to_string(&mut pubkey)
|
||||||
|
.await?;
|
||||||
|
let privatekey = load_private_key_file(".client/id_rsa")?;
|
||||||
|
|
||||||
|
// init sock
|
||||||
|
// let edge_uuid = create_or_load_uuid("")?;
|
||||||
|
//let node_conf = parse_config(edge_uuid, &args).await?;
|
||||||
|
|
||||||
|
let sock_v4 = Socket::build(0, true, true, tos).await?;
|
||||||
|
|
||||||
|
// allow multicast
|
||||||
|
|
||||||
|
// TODO: set the sn's tcp socket
|
||||||
|
// let tcpsock = TCPSocket::build("121.4.79.234:1234").await?;
|
||||||
|
let tcp_pong = Arc::new(AtomicU64::new(0));
|
||||||
|
let edge = Node::new(
|
||||||
|
pubkey,
|
||||||
|
node_conf,
|
||||||
|
sock_v4,
|
||||||
|
token,
|
||||||
|
privatekey,
|
||||||
|
tcp_pong.clone(),
|
||||||
|
);
|
||||||
|
do_init_edge(edge)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_init_edge(edge: Node) -> Result<()> {
|
||||||
|
if let Err(_) = EDGE.set(edge) {
|
||||||
|
return Err(SDLanError::NormalError("initialize sn error"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_edge() -> &'static Node {
|
||||||
|
let edge = EDGE.get();
|
||||||
|
if edge.is_none() {
|
||||||
|
panic!("should init_edge first");
|
||||||
|
}
|
||||||
|
edge.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Node {
|
||||||
|
packet_id: AtomicU32,
|
||||||
|
|
||||||
|
pub network_id: AtomicU32,
|
||||||
|
|
||||||
|
pub tcp_pong: Arc<AtomicU64>,
|
||||||
|
|
||||||
|
// user token info
|
||||||
|
pub _token: String,
|
||||||
|
|
||||||
|
pub device_config: DeviceConfig,
|
||||||
|
pub device: Iface,
|
||||||
|
|
||||||
|
// authorize related
|
||||||
|
pub authorized: AtomicBool,
|
||||||
|
// pub header_key: RwLock<Arc<Vec<u8>>>,
|
||||||
|
pub encrypt_key: RwLock<Arc<Vec<u8>>>,
|
||||||
|
|
||||||
|
pub rsa_pubkey: String,
|
||||||
|
pub rsa_private: RsaPrivateKey,
|
||||||
|
|
||||||
|
pub config: NodeConfig,
|
||||||
|
// pub super_node: Vec<Peer>,
|
||||||
|
// pub super_attempts: AtomicU8,
|
||||||
|
|
||||||
|
// store pending, and known peers
|
||||||
|
pub pending_peers: PeerMap,
|
||||||
|
pub known_peers: PeerMap,
|
||||||
|
|
||||||
|
// pub tcp_sock_v4: TCPSocket,
|
||||||
|
pub udp_sock_v4: Socket,
|
||||||
|
pub udp_sock_v6: RwLock<Arc<Option<Socket>>>,
|
||||||
|
|
||||||
|
pub multicast_sock: SdlanSock,
|
||||||
|
|
||||||
|
pub _local_v6: RwLock<Option<[u8; 16]>>,
|
||||||
|
|
||||||
|
pub stats: NodeStats,
|
||||||
|
|
||||||
|
// last register super time, in unix
|
||||||
|
pub _last_register_req: AtomicU64,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for Node {}
|
||||||
|
|
||||||
|
impl Node {
|
||||||
|
pub fn new(
|
||||||
|
pubkey: String,
|
||||||
|
config: NodeConfig,
|
||||||
|
sock: Socket,
|
||||||
|
// tcpsock: TCPSocket,
|
||||||
|
token: &str,
|
||||||
|
private: RsaPrivateKey,
|
||||||
|
tcp_pong: Arc<AtomicU64>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
packet_id: AtomicU32::new(1),
|
||||||
|
network_id: AtomicU32::new(0),
|
||||||
|
_token: token.to_owned(),
|
||||||
|
|
||||||
|
tcp_pong,
|
||||||
|
|
||||||
|
device_config: DeviceConfig::new(),
|
||||||
|
device: new_iface("dev", Mode::Tun),
|
||||||
|
|
||||||
|
authorized: AtomicBool::new(false),
|
||||||
|
encrypt_key: RwLock::new(Arc::new(Vec::new())),
|
||||||
|
// rsa_pubkey:
|
||||||
|
rsa_pubkey: pubkey,
|
||||||
|
rsa_private: private,
|
||||||
|
config,
|
||||||
|
// super_node: Vec::new(),
|
||||||
|
// super_attempts: AtomicU8::new(0),
|
||||||
|
pending_peers: PeerMap::new(),
|
||||||
|
known_peers: PeerMap::new(),
|
||||||
|
|
||||||
|
// tcp_sock_v4: tcpsock,
|
||||||
|
udp_sock_v4: sock,
|
||||||
|
udp_sock_v6: RwLock::new(Arc::new(None)),
|
||||||
|
multicast_sock: SdlanSock {
|
||||||
|
family: AF_INET,
|
||||||
|
port: config::MULTICAST_PORT,
|
||||||
|
v4: config::MULITCAST_V4,
|
||||||
|
v6: [0; 16],
|
||||||
|
},
|
||||||
|
_local_v6: RwLock::new(None),
|
||||||
|
stats: NodeStats::new(),
|
||||||
|
_last_register_req: AtomicU64::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_next_packet_id(&self) -> u32 {
|
||||||
|
self.packet_id.fetch_add(1, Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_authorized(&self) -> bool {
|
||||||
|
// self.header_key
|
||||||
|
self.authorized.load(Ordering::Relaxed)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_authorized(&self, authorized: bool, encrypt_key: Vec<u8>) {
|
||||||
|
self.authorized.store(authorized, Ordering::Relaxed);
|
||||||
|
*(self.encrypt_key.write().unwrap()) = Arc::new(encrypt_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn get_header_key(&self) -> Arc<Vec<u8>> {
|
||||||
|
// self.header_key.read().unwrap().clone()
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn get_encrypt_key(&self) -> Arc<Vec<u8>> {
|
||||||
|
self.encrypt_key.read().unwrap().clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub fn sn_is_known(&self, sock: &SdlanSock) -> bool {
|
||||||
|
for sn in self.config.super_nodes.iter() {
|
||||||
|
if sn.family != sock.family || sn.port != sock.port {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if sn.family == AF_INET && sn.v4 == sock.v4 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if sn.family == AF_INET6 && sn.v6 == sock.v6 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub fn _remove_v6(&self) {
|
||||||
|
*(self.udp_sock_v6.write().unwrap()) = Arc::new(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn send_to_v4<A: ToSocketAddrs>(&self, info: &[u8], target: A) -> Result<usize> {
|
||||||
|
match self.udp_sock_v4.send_to(info, target).await {
|
||||||
|
Ok(n) => Ok(n),
|
||||||
|
Err(e) => {
|
||||||
|
println!("failed to send");
|
||||||
|
Err(SDLanError::NormalError("failed to send"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn send_to_v6<A: ToSocketAddrs>(&self, info: &[u8], target: A) -> Result<usize> {
|
||||||
|
let m = self.udp_sock_v6.read().unwrap().clone();
|
||||||
|
if let Some(ref l) = m.as_ref() {
|
||||||
|
match l.send_to(info, target).await {
|
||||||
|
Err(e) => {
|
||||||
|
return Err(SDLanError::NormalError("send error"));
|
||||||
|
}
|
||||||
|
Ok(n) => return Ok(n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(SDLanError::NormalError("no udp6 conn is bined"))
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub async fn send_unregister_super(&self) -> Result<()> {
|
||||||
|
let content =
|
||||||
|
encode_to_tcp_message::<SdlEmpty>(None, 0, PacketType::UnRegisterSuper as u8).unwrap();
|
||||||
|
|
||||||
|
let conn = get_tcp_conn();
|
||||||
|
let _ = conn.send(&content).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn send_register_super(&self) -> Result<()> {
|
||||||
|
let packet_id = self.packet_id.fetch_add(1, Ordering::Relaxed);
|
||||||
|
let cmn = Common {
|
||||||
|
packet_id,
|
||||||
|
version: SDLAN_VERSION,
|
||||||
|
id: &self.config.node_uuid,
|
||||||
|
token: self.token,
|
||||||
|
ttl: SDLAN_DEFAULT_TTL,
|
||||||
|
pc: PacketType::PKTRegisterSuper,
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
let rs = RegisterSuper {
|
||||||
|
pass: "encrypt!",
|
||||||
|
cookie: 0,
|
||||||
|
sock: None,
|
||||||
|
v6_info: None,
|
||||||
|
dev_addr: IpSubnetNonAtomic::new(
|
||||||
|
self.device_config.get_ip(),
|
||||||
|
self.device_config.get_net_bit(),
|
||||||
|
),
|
||||||
|
pub_key: self.rsa_pubkey.clone(),
|
||||||
|
};
|
||||||
|
let content = packet::encode_packet(&cmn, &rs)?;
|
||||||
|
|
||||||
|
// self.udp_sock_v4.send_to(&content, self.config.super_nodes)
|
||||||
|
send_to_sock(
|
||||||
|
&self,
|
||||||
|
&content,
|
||||||
|
&self.config.super_nodes[self.config.super_node_index.load(Ordering::Relaxed) as usize],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
// write_to_addr(&sock, "127.0.0.1:7655", &content).await?;
|
||||||
|
// println!("sent!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PeerMap {
|
||||||
|
pub peers: DashMap<u32, Arc<EdgePeer>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
impl PeerMap {
|
||||||
|
pub fn new() -> PeerMap {
|
||||||
|
Self {
|
||||||
|
peers: DashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_peer(&self, ip: &u32) -> Option<Arc<EdgePeer>> {
|
||||||
|
if let Some(v) = self.peers.get(ip) {
|
||||||
|
Some(v.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&self) {
|
||||||
|
self.peers.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_peer_by_sock(&self, sock: &SdlanSock) -> Option<Arc<EdgePeer>> {
|
||||||
|
for s in self.peers.iter() {
|
||||||
|
let m = s.sock.read().unwrap();
|
||||||
|
if is_sdlan_sock_equal(&m, sock) {
|
||||||
|
return Some(s.value().clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete_peer_with_ip(&self, ip: &u32) {
|
||||||
|
self.peers.remove(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn insert_peer(&self, p: Arc<EdgePeer>) {
|
||||||
|
let net_addr = p.dev_addr.net_addr();
|
||||||
|
if net_addr != 0 {
|
||||||
|
self.peers.insert(net_addr, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NodeStats {
|
||||||
|
pub tx_p2p: AtomicU64,
|
||||||
|
pub rx_p2p: AtomicU64,
|
||||||
|
pub tx_sup: AtomicU64,
|
||||||
|
pub rx_sup: AtomicU64,
|
||||||
|
pub tx_broadcast: AtomicU64,
|
||||||
|
pub rx_broadcast: AtomicU64,
|
||||||
|
|
||||||
|
pub last_sup: AtomicU64,
|
||||||
|
pub last_p2p: AtomicU64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeStats {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
tx_p2p: AtomicU64::new(0),
|
||||||
|
rx_p2p: AtomicU64::new(0),
|
||||||
|
tx_sup: AtomicU64::new(0),
|
||||||
|
rx_sup: AtomicU64::new(0),
|
||||||
|
tx_broadcast: AtomicU64::new(0),
|
||||||
|
rx_broadcast: AtomicU64::new(0),
|
||||||
|
|
||||||
|
last_p2p: AtomicU64::new(0),
|
||||||
|
last_sup: AtomicU64::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
use sdlan_sn_rs::peer::SdlanSock;
|
||||||
|
|
||||||
|
use crate::config::{self, REGISTER_INTERVAL};
|
||||||
|
pub struct NodeConfig {
|
||||||
|
// node name
|
||||||
|
pub name: String,
|
||||||
|
// 允许路由
|
||||||
|
pub allow_routing: bool,
|
||||||
|
|
||||||
|
// 丢弃多播,广播消息
|
||||||
|
pub _drop_multicast: bool,
|
||||||
|
|
||||||
|
// 允许p2p打洞
|
||||||
|
pub allow_p2p: bool,
|
||||||
|
|
||||||
|
// mtu of the tun
|
||||||
|
pub mtu: u32,
|
||||||
|
|
||||||
|
// udp消息的服务类型
|
||||||
|
pub _tos: u8,
|
||||||
|
|
||||||
|
// 打洞时候,时间间隔
|
||||||
|
pub _register_super_interval: u16,
|
||||||
|
|
||||||
|
// 打洞时候,register消息的ttl
|
||||||
|
pub register_ttl: u8,
|
||||||
|
|
||||||
|
// 本地打开的udp端口
|
||||||
|
pub _local_port: u16,
|
||||||
|
|
||||||
|
pub node_uuid: String,
|
||||||
|
|
||||||
|
// pub super_attempts: AtomicU8,
|
||||||
|
pub super_nodes: Vec<SdlanSock>,
|
||||||
|
pub super_node_index: AtomicU8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeConfig {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
name: String::new(),
|
||||||
|
allow_routing: true,
|
||||||
|
allow_p2p: true,
|
||||||
|
_drop_multicast: false,
|
||||||
|
_tos: 0,
|
||||||
|
_register_super_interval: config::REGISTER_SUPER_INTERVAL,
|
||||||
|
register_ttl: 1,
|
||||||
|
// any port,
|
||||||
|
_local_port: 0,
|
||||||
|
|
||||||
|
node_uuid: String::new(),
|
||||||
|
|
||||||
|
super_nodes: Vec::new(),
|
||||||
|
// super_attempts: AtomicU8::new(config::SUPER_ATTEMPTS_DEFAULT),
|
||||||
|
super_node_index: AtomicU8::new(0),
|
||||||
|
|
||||||
|
mtu: 1290,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct EdgePeer {
|
||||||
|
pub dev_addr: IpSubnet,
|
||||||
|
|
||||||
|
// 对端对外开放的ip和端口信息
|
||||||
|
pub sock: RwLock<SdlanSock>,
|
||||||
|
// peer's ipv6 info
|
||||||
|
pub _v6_info: RwLock<Option<SdlanSock>>,
|
||||||
|
|
||||||
|
pub timeout: u8,
|
||||||
|
|
||||||
|
// 最近一次遇见
|
||||||
|
pub last_seen: AtomicU64,
|
||||||
|
// 最近一次p2p消息
|
||||||
|
pub last_p2p: AtomicU64,
|
||||||
|
// 最近一次合法时间
|
||||||
|
pub _last_valid_timestamp: AtomicU64,
|
||||||
|
|
||||||
|
// 最近一次发送query
|
||||||
|
pub last_sent_query: AtomicU64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EdgePeer {
|
||||||
|
pub fn new(
|
||||||
|
net_addr: u32,
|
||||||
|
net_bit_len: u8,
|
||||||
|
sock: &SdlanSock,
|
||||||
|
v6info: &Option<V6Info>,
|
||||||
|
now: u64,
|
||||||
|
) -> Self {
|
||||||
|
let mut v6_info = None;
|
||||||
|
if let Some(v6info) = v6info {
|
||||||
|
v6_info = Some(SdlanSock {
|
||||||
|
family: AF_INET6,
|
||||||
|
port: v6info.port,
|
||||||
|
v4: [0; 4],
|
||||||
|
v6: v6info.v6,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
dev_addr: IpSubnet::new(net_addr, net_bit_len),
|
||||||
|
sock: RwLock::new(sock.deepcopy()),
|
||||||
|
_v6_info: RwLock::new(v6_info),
|
||||||
|
timeout: REGISTER_INTERVAL,
|
||||||
|
last_p2p: AtomicU64::new(0),
|
||||||
|
last_seen: AtomicU64::new(0),
|
||||||
|
_last_valid_timestamp: AtomicU64::new(now),
|
||||||
|
last_sent_query: AtomicU64::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
853
src/network/packet.rs
Normal file
853
src/network/packet.rs
Normal file
@ -0,0 +1,853 @@
|
|||||||
|
use std::{net::SocketAddr, sync::atomic::Ordering, time::Duration};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
config::REGISTER_INTERVAL,
|
||||||
|
pb::{
|
||||||
|
encode_to_tcp_message, encode_to_udp_message, SdlData, SdlEmpty, SdlPeerInfo, SdlQueryInfo,
|
||||||
|
SdlRegister, SdlRegisterAck,
|
||||||
|
},
|
||||||
|
tcp::{get_tcp_conn, PacketType},
|
||||||
|
utils::{send_to_sock, Socket},
|
||||||
|
};
|
||||||
|
use etherparse::IpHeaders;
|
||||||
|
use prost::Message;
|
||||||
|
use sdlan_sn_rs::{
|
||||||
|
config::AF_INET,
|
||||||
|
peer::{is_sdlan_sock_equal, SdlanSock, V6Info},
|
||||||
|
utils::{
|
||||||
|
aes_decrypt, get_current_timestamp, get_sdlan_sock_from_socketaddr, ip_to_string,
|
||||||
|
is_multi_broadcast, Result, SDLanError,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use tracing::{debug, error, info};
|
||||||
|
|
||||||
|
use super::{EdgePeer, Node};
|
||||||
|
|
||||||
|
pub async fn read_and_parse_packet(
|
||||||
|
eee: &Node,
|
||||||
|
sock: &Socket,
|
||||||
|
timeout: Option<Duration>,
|
||||||
|
// cancel: CancellationToken,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut buf = vec![0; 3000];
|
||||||
|
let res;
|
||||||
|
if timeout.is_some() {
|
||||||
|
tokio::select! {
|
||||||
|
_ = tokio::time::sleep(timeout.unwrap()) => {
|
||||||
|
return Err(SDLanError::NormalError("timeouted"));
|
||||||
|
}
|
||||||
|
r = sock.recv_from(&mut buf) => {
|
||||||
|
res=r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res = sock.recv_from(&mut buf).await;
|
||||||
|
}
|
||||||
|
debug!("read_and_parse packet, got packet");
|
||||||
|
// let res = sock.recv_from(&mut buf).await;
|
||||||
|
match res {
|
||||||
|
Ok((0, _)) => {
|
||||||
|
// received 0
|
||||||
|
error!("received zero bytes");
|
||||||
|
// return Ok(())
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
// error occured
|
||||||
|
error!("receive error occured: {:?}", e);
|
||||||
|
}
|
||||||
|
Ok((size, from)) => {
|
||||||
|
// size > 0
|
||||||
|
buf.truncate(size);
|
||||||
|
match handle_packet(eee, from, &buf).await {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to handle_packet: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_packet(eee: &Node, addr: SocketAddr, buf: &[u8]) -> Result<()> {
|
||||||
|
if buf.len() < 1 {
|
||||||
|
return Err(SDLanError::NormalError("buf length error"));
|
||||||
|
}
|
||||||
|
let Ok(pkt_type) = PacketType::try_from(buf[0]) else {
|
||||||
|
return Err(SDLanError::NormalError("invalid packet type"));
|
||||||
|
};
|
||||||
|
match pkt_type {
|
||||||
|
PacketType::StunReply => {
|
||||||
|
// stun reply, like pong
|
||||||
|
}
|
||||||
|
PacketType::Register => {
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
error!("dropping REGISTER received before authorized");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
||||||
|
let _ = handle_packet_register(eee, &buf[1..], false, &from_sock).await;
|
||||||
|
}
|
||||||
|
PacketType::RegisterACK => {
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
error!("dropping REGISTER received before authorized");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
||||||
|
let _ = handle_packet_register_ack(eee, &buf[1..], &from_sock).await;
|
||||||
|
}
|
||||||
|
PacketType::Data => {
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
error!("dropping PACKET received before authorized");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(data) = SdlData::decode(&buf[1..]) else {
|
||||||
|
error!("failed to decode to SDLData");
|
||||||
|
return Err(SDLanError::NormalError("failed to decode to SDLData"));
|
||||||
|
};
|
||||||
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
||||||
|
if data.is_p2p {
|
||||||
|
debug!("[P2P] Rx data from {}", from_sock.to_string());
|
||||||
|
} else {
|
||||||
|
debug!(
|
||||||
|
"[PsP] Rx data from {} via {}",
|
||||||
|
ip_to_string(&data.src_ip),
|
||||||
|
from_sock.to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if data.is_p2p {
|
||||||
|
check_peer_registration_needed(eee, !data.is_p2p, data.src_ip, &None, &from_sock)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
handle_tun_packet(eee, !data.is_p2p, data).await;
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
error!("udp not processing {:?}", other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
let pkt_type = buf[0].into();
|
||||||
|
debug!("got packet {} bytes", buf.len());
|
||||||
|
let (cmn, slice) = packet::decode_common(&buf)?;
|
||||||
|
println!("got packet: {:?}", cmn.pc);
|
||||||
|
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
error!("unauthorized, returning");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let from_sn = (cmn.flags & config::SDLAN_FLAGS_FROM_SN) != 0;
|
||||||
|
let from_sock = get_sdlan_sock_from_socketaddr(addr).unwrap();
|
||||||
|
if from_sn {
|
||||||
|
if !eee.sn_is_known(&from_sock) {
|
||||||
|
error!("drop incoming data from unknown supernode");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let res = match cmn.pc {
|
||||||
|
PacketType::PKTPacket => {
|
||||||
|
// handle packet
|
||||||
|
handle_packet_packet(eee, cmn, slice, from_sn, &from_sock).await
|
||||||
|
}
|
||||||
|
PacketType::PKTRegister => {
|
||||||
|
// handle register from other peer
|
||||||
|
handle_packet_register(eee, slice, from_sn, &from_sock).await
|
||||||
|
}
|
||||||
|
PacketType::PKTRegisterACK => {
|
||||||
|
// handle register ack from other peer
|
||||||
|
handle_packet_register_ack(eee, slice, &from_sock).await
|
||||||
|
}
|
||||||
|
PacketType::PKTRegisterSuperAcknowledge => {
|
||||||
|
// handle register super acknowledge
|
||||||
|
handle_packet_register_super_acknowledge(eee)
|
||||||
|
}
|
||||||
|
PacketType::PKTRegisterSuperACK => {
|
||||||
|
// handle register super ack
|
||||||
|
handle_packet_register_super_ack(eee, cmn, slice)
|
||||||
|
}
|
||||||
|
PacketType::PKTRegisterSuperNAK => {
|
||||||
|
// handle register super nak
|
||||||
|
handle_packet_register_super_nak(eee, cmn, slice)
|
||||||
|
}
|
||||||
|
PacketType::PKTPeerInfo => {
|
||||||
|
// handle peer info from sn
|
||||||
|
handle_packet_peer_info(eee, slice).await
|
||||||
|
}
|
||||||
|
PacketType::PKTCommand => {
|
||||||
|
// handle command
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
error!("unknown packet {:?}", other);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = res {
|
||||||
|
error!("handle packet error occured: {}", e.as_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_packet_peer_info(
|
||||||
|
eee: &Node,
|
||||||
|
// cmn: Common<'_>,
|
||||||
|
body: &[u8],
|
||||||
|
//sender_sock: &SdlanSock,
|
||||||
|
) -> Result<()> {
|
||||||
|
let Ok(pi) = SdlPeerInfo::decode(body) else {
|
||||||
|
error!("failed to decode PEER_INFO");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("got peer info: {:?}", pi);
|
||||||
|
|
||||||
|
if pi.v4_info.is_none() {
|
||||||
|
error!("PEER's v4_info is none");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let v4 = pi.v4_info.unwrap();
|
||||||
|
let Ok(v4_u32) = v4.v4.try_into() else {
|
||||||
|
error!("failed to convert v4");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
// let src_ip = u32::from_be_bytes(v4_u32);
|
||||||
|
|
||||||
|
if pi.dst_ip == 0 {
|
||||||
|
// pong from sn
|
||||||
|
} else {
|
||||||
|
match eee.pending_peers.get_peer(&pi.dst_ip) {
|
||||||
|
Some(edgeinfo) => {
|
||||||
|
let sock = SdlanSock {
|
||||||
|
family: AF_INET,
|
||||||
|
port: v4.port as u16,
|
||||||
|
v4: v4_u32,
|
||||||
|
v6: [0; 16],
|
||||||
|
};
|
||||||
|
*(edgeinfo.sock.write().unwrap()) = sock.deepcopy();
|
||||||
|
info!(
|
||||||
|
"Rx PEERINFO for {}: is at {}",
|
||||||
|
ip_to_string(&pi.dst_ip),
|
||||||
|
sock.to_string()
|
||||||
|
);
|
||||||
|
send_register(eee, &sock, &None).await;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
debug!("Rx PEERINFO unknown peer: {}", ip_to_string(&pi.dst_ip));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn handle_packet_register_super_nak(eee: &Node, _cmn: Common<'_>, slice: &[u8]) -> Result<()> {
|
||||||
|
let nak: RegisterSuperNAK = serde_json::from_slice(slice)?;
|
||||||
|
if nak.src_ip == eee.device_config.get_ip() {
|
||||||
|
eee.set_authorized(false, Vec::new());
|
||||||
|
error!("unauthorized");
|
||||||
|
} else {
|
||||||
|
eee.known_peers.delete_peer_with_ip(&nak.src_ip);
|
||||||
|
eee.pending_peers.delete_peer_with_ip(&nak.src_ip);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn handle_packet_register_super_ack(eee: &Node, _cmn: Common<'_>, slice: &[u8]) -> Result<()> {
|
||||||
|
debug!("handling REGISTER_SUPER_ACK");
|
||||||
|
let ack: RegisterSuperACK = serde_json::from_slice(slice)?;
|
||||||
|
|
||||||
|
if ack.dev_addr.net_addr != 0 && ack.dev_addr.net_bit_len != 0 {
|
||||||
|
// i'm authorized or moved;
|
||||||
|
// eee.device
|
||||||
|
eee.device_config
|
||||||
|
.set_ip(ack.dev_addr.net_addr, ack.dev_addr.net_bit_len);
|
||||||
|
debug!(
|
||||||
|
"ip addr assigned: {}/{}",
|
||||||
|
ip_to_string(&ack.dev_addr.net_addr),
|
||||||
|
ack.dev_addr.net_bit_len
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(private_key) = load_private_key_file(".client/id_rsa") else {
|
||||||
|
error!("failed to load private key");
|
||||||
|
return Err(SDLanError::NormalError("failed to load private key"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let encrypt_key = rsa_decrypt(&private_key, &ack.encrypted_key)?;
|
||||||
|
let header_key = rsa_decrypt(&private_key, &ack.header_key)?;
|
||||||
|
|
||||||
|
eee.config
|
||||||
|
.super_attempts
|
||||||
|
.store(SUPER_ATTEMPTS_DEFAULT, Ordering::Relaxed);
|
||||||
|
eee.stats
|
||||||
|
.last_sup
|
||||||
|
.store(get_current_timestamp(), Ordering::Relaxed);
|
||||||
|
debug!("changed to Authorized");
|
||||||
|
eee.set_authorized(true, encrypt_key);
|
||||||
|
|
||||||
|
eee.device.reload_config(&eee.device_config);
|
||||||
|
eee.known_peers.clear();
|
||||||
|
eee.pending_peers.clear();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn handle_packet_register_super_acknowledge(
|
||||||
|
eee: &Node,
|
||||||
|
// cmn: Common<'_>,
|
||||||
|
// slice: &[u8],
|
||||||
|
) -> Result<()> {
|
||||||
|
debug!("handling REGISTER_SUPER_ACKNOWLEDGE");
|
||||||
|
// TODO: should check the common and the slice content.
|
||||||
|
eee.config
|
||||||
|
.super_attempts
|
||||||
|
.store(SUPER_ATTEMPTS_DEFAULT, Ordering::Relaxed);
|
||||||
|
eee.stats
|
||||||
|
.last_sup
|
||||||
|
.store(get_current_timestamp(), Ordering::Relaxed);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
async fn handle_packet_register_ack(
|
||||||
|
eee: &Node,
|
||||||
|
// cmn: Common<'_>,
|
||||||
|
body: &[u8],
|
||||||
|
sender_sock: &SdlanSock,
|
||||||
|
) -> Result<()> {
|
||||||
|
let Ok(ack) = SdlRegisterAck::decode(body) else {
|
||||||
|
println!("failed to decode REGISTER_ACK");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let origin_sender = sender_sock;
|
||||||
|
|
||||||
|
debug!(
|
||||||
|
"Rx REGISTER ACK from {} [{}] to {} via {}",
|
||||||
|
ip_to_string(&ack.src_ip),
|
||||||
|
origin_sender.to_string(),
|
||||||
|
ip_to_string(&ack.dst_ip),
|
||||||
|
sender_sock.to_string(),
|
||||||
|
);
|
||||||
|
peer_set_p2p_confirmed(eee, ack.src_ip, sender_sock);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_packet_register(
|
||||||
|
eee: &Node,
|
||||||
|
// cmn: Common<'_>,
|
||||||
|
body: &[u8],
|
||||||
|
from_sn: bool,
|
||||||
|
sender_sock: &SdlanSock,
|
||||||
|
) -> Result<()> {
|
||||||
|
if !eee.is_authorized() {
|
||||||
|
error!("drop register due to not authed");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let Ok(reg) = SdlRegister::decode(body) else {
|
||||||
|
error!("failed to decode REGISTER");
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
let origin_sender = sender_sock;
|
||||||
|
|
||||||
|
let via_multicast = is_multi_broadcast(reg.dst_ip);
|
||||||
|
if via_multicast && reg.src_ip == eee.device_config.get_ip() {
|
||||||
|
debug!("skipping register from self");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if !from_sn {
|
||||||
|
info!("[P2P] Rx REGISTER from {}", sender_sock.to_string());
|
||||||
|
eee.pending_peers.delete_peer_with_ip(®.src_ip);
|
||||||
|
send_register_ack(eee, origin_sender, ®).await;
|
||||||
|
} else {
|
||||||
|
info!(
|
||||||
|
"[PsP] Rx REGISTER from {} [{}] to {} via {}",
|
||||||
|
ip_to_string(®.src_ip),
|
||||||
|
ip_to_string(®.dst_ip),
|
||||||
|
sender_sock.to_string(),
|
||||||
|
origin_sender.to_string(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
check_peer_registration_needed(eee, from_sn, reg.src_ip, &None, origin_sender).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
async fn handle_packet_packet(
|
||||||
|
eee: &Node,
|
||||||
|
cmn: Common<'_>,
|
||||||
|
body: &[u8],
|
||||||
|
from_sn: bool,
|
||||||
|
sender_sock: &SdlanSock,
|
||||||
|
) -> Result<()> {
|
||||||
|
if eee.stats.last_sup.load(Ordering::Relaxed) == 0 {
|
||||||
|
error!("dropping PACKET received before first registration with sn");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let has_sock = cmn.flags & config::SDLAN_FLAGS_SOCKET != 0;
|
||||||
|
let has_v6 = cmn.flags & config::SDLAN_FLAGS_HAS_V6 != 0;
|
||||||
|
let pkt = packet::Packet::unmarshal(body, has_sock, has_v6)?;
|
||||||
|
|
||||||
|
// let mut orig_sender: &SdlanSock = sender_sock;
|
||||||
|
|
||||||
|
// here, the origin sender ref should be checked
|
||||||
|
// if let Some(ref sk) = pkt.sock {
|
||||||
|
// orig_sender = sk;
|
||||||
|
// }
|
||||||
|
// println!("orig_sender: {:?}", orig_sender);
|
||||||
|
|
||||||
|
let mut origin_sender = sender_sock;
|
||||||
|
if let Some(ref k) = pkt.sock {
|
||||||
|
origin_sender = k;
|
||||||
|
}
|
||||||
|
println!("orig_sender: {:?}", origin_sender);
|
||||||
|
if !from_sn {
|
||||||
|
// data from other peer
|
||||||
|
debug!("[P2P] Rx data from {}", sender_sock.to_string());
|
||||||
|
eee.pending_peers.peers.remove(&pkt.src_ip);
|
||||||
|
} else {
|
||||||
|
// from sn, sock should not be None
|
||||||
|
debug!(
|
||||||
|
"[PsP] Rx data from {} (via {})",
|
||||||
|
origin_sender.to_string(),
|
||||||
|
sender_sock.to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
check_peer_registration_needed(eee, from_sn, pkt.src_ip, &pkt.v6_info, origin_sender).await;
|
||||||
|
// handle_tun_packet(eee, from_sn, pkt).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub async fn check_peer_registration_needed(
|
||||||
|
eee: &Node,
|
||||||
|
from_sn: bool,
|
||||||
|
src_ip: u32,
|
||||||
|
v6_info: &Option<V6Info>,
|
||||||
|
peer_sock: &SdlanSock,
|
||||||
|
) {
|
||||||
|
let mut p = eee.known_peers.get_peer(&src_ip);
|
||||||
|
if let None = p {
|
||||||
|
p = eee.known_peers.get_peer_by_sock(peer_sock);
|
||||||
|
if let Some(ref k) = p {
|
||||||
|
eee.known_peers.insert_peer(k.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match p {
|
||||||
|
None => {
|
||||||
|
let _ = register_with_new_peer(eee, from_sn, src_ip, v6_info, peer_sock).await;
|
||||||
|
// unimplemented!();
|
||||||
|
}
|
||||||
|
Some(k) => {
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
if !from_sn {
|
||||||
|
k.last_p2p.store(now, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
let last_seen = k.last_seen.load(Ordering::Relaxed);
|
||||||
|
// more than 3 seconds
|
||||||
|
if now - last_seen > 3 {
|
||||||
|
check_known_peer_sock_change(eee, from_sn, src_ip, v6_info, peer_sock).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn check_known_peer_sock_change(
|
||||||
|
eee: &Node,
|
||||||
|
from_sn: bool,
|
||||||
|
ip: u32,
|
||||||
|
v6_info: &Option<V6Info>,
|
||||||
|
// dev_addr: &IpSubnet,
|
||||||
|
peersock: &SdlanSock,
|
||||||
|
) {
|
||||||
|
if is_multi_broadcast(ip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
match eee.known_peers.get_peer(&ip) {
|
||||||
|
Some(p) => {
|
||||||
|
if !is_sdlan_sock_equal(&p.sock.read().unwrap(), peersock) {
|
||||||
|
if !from_sn {
|
||||||
|
info!(
|
||||||
|
"peer changed: {}: {} -> {}",
|
||||||
|
ip_to_string(&ip),
|
||||||
|
&p.sock.read().unwrap().to_string(),
|
||||||
|
peersock.to_string()
|
||||||
|
);
|
||||||
|
eee.known_peers.delete_peer_with_ip(&ip);
|
||||||
|
register_with_new_peer(eee, from_sn, ip, v6_info, peersock).await;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// from sn, sn could see a different sock with us, just ignore it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn register_with_new_peer(
|
||||||
|
eee: &Node,
|
||||||
|
from_sn: bool,
|
||||||
|
ip: u32,
|
||||||
|
v6_info: &Option<V6Info>,
|
||||||
|
// dev_addr: &IpSubnet,
|
||||||
|
peersock: &SdlanSock,
|
||||||
|
) {
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
let mut scan = eee.pending_peers.get_peer(&ip);
|
||||||
|
if let None = scan {
|
||||||
|
// such ip not found in pending
|
||||||
|
let temp = Arc::new(EdgePeer::new(
|
||||||
|
ip,
|
||||||
|
eee.device_config.get_net_bit(),
|
||||||
|
peersock,
|
||||||
|
v6_info,
|
||||||
|
now,
|
||||||
|
));
|
||||||
|
debug!(
|
||||||
|
"===> new pending {} => {}",
|
||||||
|
ip_to_string(&ip),
|
||||||
|
peersock.to_string(),
|
||||||
|
);
|
||||||
|
eee.pending_peers.insert_peer(temp.clone());
|
||||||
|
scan = Some(temp);
|
||||||
|
debug!("Pending size: {}", eee.pending_peers.peers.len());
|
||||||
|
|
||||||
|
if from_sn {
|
||||||
|
// should send register to peer
|
||||||
|
if eee.config.register_ttl == 1 {
|
||||||
|
/* We are DMZ host or port is directly accessible. Just let peer to send back the ack */
|
||||||
|
} else if eee.config.register_ttl > 1 {
|
||||||
|
let mut alter = 16;
|
||||||
|
if let Ok(ttl) = eee.udp_sock_v4.ttl() {
|
||||||
|
let mut temp = peersock.deepcopy();
|
||||||
|
send_register(eee, &temp, v6_info).await;
|
||||||
|
|
||||||
|
let _ = eee.udp_sock_v4.set_ttl(eee.config.register_ttl as u32);
|
||||||
|
while alter > 0 {
|
||||||
|
temp.port += 1;
|
||||||
|
send_register(eee, &temp, &None).await;
|
||||||
|
alter -= 1;
|
||||||
|
}
|
||||||
|
let _ = eee.udp_sock_v4.set_ttl(ttl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal STUN
|
||||||
|
send_register(eee, peersock, v6_info).await;
|
||||||
|
}
|
||||||
|
// 发送给sn
|
||||||
|
send_register(
|
||||||
|
eee,
|
||||||
|
&eee.config.super_nodes
|
||||||
|
[eee.config.super_node_index.load(Ordering::Relaxed) as usize],
|
||||||
|
&None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
} else {
|
||||||
|
// P2P register, send directly
|
||||||
|
send_register(eee, peersock, v6_info).await;
|
||||||
|
}
|
||||||
|
register_with_local_peers(eee).await;
|
||||||
|
} else {
|
||||||
|
if let Some(ref s) = scan {
|
||||||
|
*(s.sock.write().unwrap()) = peersock.deepcopy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(s) = scan {
|
||||||
|
s.last_seen
|
||||||
|
.store(get_current_timestamp(), Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn register_with_local_peers(eee: &Node) {
|
||||||
|
if eee.config.allow_p2p {
|
||||||
|
send_register(eee, &eee.multicast_sock, &None).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_register(eee: &Node, sock: &SdlanSock, _v6_info: &Option<V6Info>) {
|
||||||
|
if !eee.config.allow_p2p {
|
||||||
|
debug!("skipping register as p2p is disabled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let network_id = eee.network_id.load(Ordering::Relaxed);
|
||||||
|
if network_id == 0 {
|
||||||
|
error!("not authed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let register = SdlRegister {
|
||||||
|
network_id: network_id,
|
||||||
|
src_ip: eee.device_config.get_ip(),
|
||||||
|
dst_ip: u32::from_be_bytes(sock.v4),
|
||||||
|
};
|
||||||
|
|
||||||
|
let msg = encode_to_udp_message(Some(register), PacketType::Register as u8).unwrap();
|
||||||
|
|
||||||
|
let _ = send_to_sock(eee, &msg, sock).await;
|
||||||
|
/*
|
||||||
|
let key = eee.get_header_key();
|
||||||
|
if key.len() > 0 {
|
||||||
|
if let Ok(cnt) = encode_packet_encrypted(&cmn, &r, key.as_slice()) {
|
||||||
|
let _ = send_to_sock_v4_and_v6(eee, &cnt, sock, v6_info).await;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error!("not authed");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_tun_packet(
|
||||||
|
eee: &Node,
|
||||||
|
from_sn: bool,
|
||||||
|
pkt: SdlData, //orig_sender: &SdlanSock
|
||||||
|
) {
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
if from_sn {
|
||||||
|
if is_multi_broadcast(pkt.dst_ip) {
|
||||||
|
eee.stats.rx_broadcast.fetch_add(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
eee.stats.rx_sup.fetch_add(1, Ordering::Relaxed);
|
||||||
|
eee.stats.last_sup.store(now, Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
eee.stats.rx_p2p.fetch_add(1, Ordering::Relaxed);
|
||||||
|
eee.stats.last_p2p.store(now, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload = pkt.data;
|
||||||
|
let key = eee.get_encrypt_key();
|
||||||
|
if key.len() == 0 {
|
||||||
|
// check the encrypt key
|
||||||
|
error!("packet encrypt key not provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let origin = aes_decrypt(key.as_slice(), &payload);
|
||||||
|
if let Err(_e) = origin {
|
||||||
|
error!("failed to decrypt original data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let data = origin.unwrap();
|
||||||
|
|
||||||
|
debug!("got packet from sock, will send to tun");
|
||||||
|
match IpHeaders::from_slice(&data) {
|
||||||
|
Ok((iphdr, _)) => {
|
||||||
|
if let Some(ipv4hdr) = iphdr.ipv4() {
|
||||||
|
let dstip = u32::from_be_bytes(ipv4hdr.0.destination);
|
||||||
|
if !is_multi_broadcast(dstip) && dstip != eee.device_config.get_ip() {
|
||||||
|
// should not routed to me
|
||||||
|
error!("should not routed to me");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// packet should be sent to dev
|
||||||
|
debug!("writing {} bytes to tun", data.len());
|
||||||
|
if let Err(e) = eee.device.send(&data) {
|
||||||
|
error!("failed to write to tun: {}", e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to parse ip packet: {}", e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_register_ack(eee: &Node, orig_sender: &SdlanSock, reg: &SdlRegister) {
|
||||||
|
if !eee.config.allow_p2p {
|
||||||
|
debug!("Skipping REGISTER ACK as P2P is disallowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let network_id = eee.network_id.load(Ordering::Relaxed);
|
||||||
|
if network_id == 0 {
|
||||||
|
error!("not authed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ack = SdlRegisterAck {
|
||||||
|
network_id,
|
||||||
|
src_ip: eee.device_config.get_ip(),
|
||||||
|
dst_ip: reg.src_ip,
|
||||||
|
};
|
||||||
|
let Ok(ack) = encode_to_udp_message(Some(ack), PacketType::RegisterACK as u8) else {
|
||||||
|
error!("failed to encode to udp message");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let _ = send_to_sock(eee, &ack, orig_sender).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peer_set_p2p_confirmed(eee: &Node, src_ip: u32, sender_sock: &SdlanSock) {
|
||||||
|
let mut scan = eee.pending_peers.get_peer(&src_ip);
|
||||||
|
if let None = scan {
|
||||||
|
scan = eee.pending_peers.get_peer_by_sock(sender_sock);
|
||||||
|
}
|
||||||
|
if let None = scan {
|
||||||
|
error!(
|
||||||
|
"failed to find sender in pending peer: {}",
|
||||||
|
sender_sock.to_string()
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut scan = scan.unwrap();
|
||||||
|
eee.pending_peers.delete_peer_with_ip(&src_ip);
|
||||||
|
match eee.known_peers.get_peer(&src_ip) {
|
||||||
|
Some(scantmp) => {
|
||||||
|
eee.known_peers.delete_peer_with_ip(&src_ip);
|
||||||
|
scan = scantmp;
|
||||||
|
scan.dev_addr.net_addr.store(src_ip, Ordering::Relaxed);
|
||||||
|
scan.dev_addr
|
||||||
|
.net_bit_len
|
||||||
|
.store(eee.device_config.get_net_bit(), Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
*(scan.sock.write().unwrap()) = sender_sock.deepcopy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
scan.last_p2p.store(now, Ordering::Relaxed);
|
||||||
|
scan.last_seen.store(now, Ordering::Relaxed);
|
||||||
|
|
||||||
|
let ip_string = ip_to_string(&src_ip);
|
||||||
|
let sock_string = sender_sock.to_string();
|
||||||
|
info!(
|
||||||
|
"P2P connection established: {} [{}]",
|
||||||
|
&ip_string, &sock_string,
|
||||||
|
);
|
||||||
|
debug!("==> new peer: {} -> {}", &ip_string, &sock_string,);
|
||||||
|
eee.known_peers.insert_peer(scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn check_query_peer_info(eee: &Node, dst_ip: u32) {
|
||||||
|
let scan: Arc<EdgePeer>;
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
match eee.pending_peers.get_peer(&dst_ip) {
|
||||||
|
None => {
|
||||||
|
let sock = SdlanSock {
|
||||||
|
family: AF_INET,
|
||||||
|
port: 0,
|
||||||
|
v4: [0; 4],
|
||||||
|
v6: [0; 16],
|
||||||
|
};
|
||||||
|
let peer = Arc::new(EdgePeer::new(
|
||||||
|
dst_ip,
|
||||||
|
eee.device_config.get_net_bit(),
|
||||||
|
&sock,
|
||||||
|
&None,
|
||||||
|
now,
|
||||||
|
));
|
||||||
|
debug!("insert peer {} to pending", ip_to_string(&dst_ip));
|
||||||
|
eee.pending_peers.insert_peer(peer.clone());
|
||||||
|
scan = peer;
|
||||||
|
}
|
||||||
|
Some(s) => {
|
||||||
|
scan = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug!(
|
||||||
|
"now={}, last_sent_query={}, REGISTER_INTERVAL={}, scan={:?}",
|
||||||
|
now,
|
||||||
|
scan.last_sent_query.load(Ordering::Relaxed),
|
||||||
|
REGISTER_INTERVAL,
|
||||||
|
scan,
|
||||||
|
);
|
||||||
|
if now - scan.last_sent_query.load(Ordering::Relaxed) > (REGISTER_INTERVAL as u64) {
|
||||||
|
/*
|
||||||
|
send_register(
|
||||||
|
eee,
|
||||||
|
&eee.config.super_nodes[eee.config.super_node_index.load(Ordering::Relaxed) as usize],
|
||||||
|
&None,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
*/
|
||||||
|
debug!("sending query for {}", ip_to_string(&dst_ip));
|
||||||
|
if let Ok(()) = send_query_peer(eee, dst_ip).await {
|
||||||
|
scan.last_sent_query.store(now, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn send_query_peer(eee: &Node, dst_ip: u32) -> Result<()> {
|
||||||
|
let network_id = eee.network_id.load(Ordering::Relaxed);
|
||||||
|
|
||||||
|
if network_id == 0 {
|
||||||
|
error!("not authed");
|
||||||
|
return Err(SDLanError::NormalError("not connected"));
|
||||||
|
}
|
||||||
|
let query = SdlQueryInfo { dst_ip };
|
||||||
|
|
||||||
|
let Ok(content) = encode_to_tcp_message(
|
||||||
|
Some(query),
|
||||||
|
eee.get_next_packet_id(),
|
||||||
|
PacketType::QueryInfo as u8,
|
||||||
|
) else {
|
||||||
|
error!("failed to encode query");
|
||||||
|
return Err(SDLanError::NormalError("encode query error"));
|
||||||
|
};
|
||||||
|
let tcp_conn = get_tcp_conn();
|
||||||
|
tcp_conn.send(&content).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn ping_to_sn() {
|
||||||
|
let Ok(msg) = encode_to_tcp_message::<SdlEmpty>(None, 0, PacketType::Ping as u8) else {
|
||||||
|
error!("failed to encode ping");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
debug!("ping to sn");
|
||||||
|
let tcp_conn = get_tcp_conn();
|
||||||
|
if let Err(e) = tcp_conn.send(&msg).await {
|
||||||
|
error!("failed to ping to sn: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn update_supernode_reg(eee: &Node) {
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
let authed = eee.is_authorized();
|
||||||
|
let last_reg = eee.last_register_req.load(Ordering::Relaxed);
|
||||||
|
if !authed {
|
||||||
|
if now > (last_reg + (REGISTER_INTERVAL as u64) / 10) {
|
||||||
|
debug!("update supernode reg, fast retry");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if now < (last_reg + REGISTER_INTERVAL as u64) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if eee.config.super_attempts.load(Ordering::Relaxed) == 0 {
|
||||||
|
eee.config
|
||||||
|
.super_attempts
|
||||||
|
.store(SUPER_ATTEMPTS_DEFAULT, Ordering::Relaxed);
|
||||||
|
error!("sup attempts = 0");
|
||||||
|
// next time, the supernode will use the new one
|
||||||
|
let node_index = eee.config.super_node_index.fetch_add(1, Ordering::Relaxed);
|
||||||
|
if node_index >= (eee.config.super_nodes.len() - 1) as u8 {
|
||||||
|
eee.config.super_node_index.store(0, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eee.config.super_attempts.fetch_sub(1, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
if let Err(e) = eee.send_register_super().await {
|
||||||
|
error!("failed to send register_super: {}", e.as_str());
|
||||||
|
}
|
||||||
|
eee.last_register_req.store(now, Ordering::Relaxed);
|
||||||
|
register_with_local_peers(eee).await;
|
||||||
|
}
|
||||||
|
*/
|
||||||
126
src/network/tun_linux.rs
Normal file
126
src/network/tun_linux.rs
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
use sdlan_sn_rs::utils::{ip_to_string, net_bit_len_to_mask, SDLanError};
|
||||||
|
use std::ffi::CStr;
|
||||||
|
use std::ffi::{c_char, c_int};
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
|
use sdlan_sn_rs::utils::Result;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::os::fd::AsRawFd;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
use tracing::{debug, error};
|
||||||
|
|
||||||
|
use super::device::{DeviceConfig, Mode};
|
||||||
|
|
||||||
|
#[link(name = "tuntap")]
|
||||||
|
extern "C" {
|
||||||
|
fn tuntap_setup(fd: c_int, name: *mut u8, mode: c_int, packet_info: c_int) -> c_int;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub struct Iface {
|
||||||
|
fd: std::fs::File,
|
||||||
|
mode: Mode,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_iface(tunname: &str, mode: Mode) -> Iface {
|
||||||
|
match Iface::without_packet_info(tunname, mode) {
|
||||||
|
Err(e) => {
|
||||||
|
panic!("failed to create tun: {}", e.as_str());
|
||||||
|
}
|
||||||
|
Ok(iface) => iface,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iface {
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn with_packet_info(ifname: &str, mode: Mode) -> Result<Self> {
|
||||||
|
Iface::open_tun(ifname, mode, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn without_packet_info(ifname: &str, mode: Mode) -> Result<Self> {
|
||||||
|
Iface::open_tun(ifname, mode, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_tun(ifname: &str, mode: Mode, need_packet_info: bool) -> Result<Self> {
|
||||||
|
let fs = match OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open("/dev/net/tun")
|
||||||
|
{
|
||||||
|
Ok(fs) => fs,
|
||||||
|
Err(e) => panic!("failed to open tun: {}", e),
|
||||||
|
};
|
||||||
|
let mut name_ptr: *mut u8 = null_mut();
|
||||||
|
let mut success = false;
|
||||||
|
let mut _name = Vec::new();
|
||||||
|
for i in 0..16 {
|
||||||
|
_name = Vec::new();
|
||||||
|
_name.extend_from_slice(ifname.as_bytes());
|
||||||
|
_name.extend_from_slice(i.to_string().as_bytes());
|
||||||
|
_name.extend_from_slice(&[0; 33]);
|
||||||
|
|
||||||
|
name_ptr = _name.as_mut_ptr();
|
||||||
|
|
||||||
|
let result = unsafe {
|
||||||
|
tuntap_setup(
|
||||||
|
fs.as_raw_fd(),
|
||||||
|
name_ptr,
|
||||||
|
mode as c_int,
|
||||||
|
if need_packet_info { 1 } else { 0 },
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if result >= 0 {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if success {
|
||||||
|
let name = unsafe {
|
||||||
|
CStr::from_ptr(name_ptr as *const c_char)
|
||||||
|
.to_string_lossy()
|
||||||
|
.into_owned()
|
||||||
|
};
|
||||||
|
Ok(Iface { fd: fs, mode, name })
|
||||||
|
} else {
|
||||||
|
Err(SDLanError::NormalError("failed to setup tun"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reload_config(&self, device_config: &DeviceConfig) {
|
||||||
|
let netbit = device_config.get_net_bit();
|
||||||
|
let ip = device_config.get_ip();
|
||||||
|
if netbit == 0 || ip == 0 {
|
||||||
|
error!("reload config's ip is 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ip = ip_to_string(&ip);
|
||||||
|
let netbit = ip_to_string(&net_bit_len_to_mask(netbit));
|
||||||
|
|
||||||
|
let res = Command::new("ifconfig")
|
||||||
|
.arg(&self.name)
|
||||||
|
.arg(ip)
|
||||||
|
.arg("netmask")
|
||||||
|
.arg(&netbit)
|
||||||
|
.arg("up")
|
||||||
|
.output();
|
||||||
|
match res {
|
||||||
|
Ok(_) => {
|
||||||
|
debug!("ifconfig ok");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to run ifconfig: {}", e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
(&self.fd).read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(&self, content: &[u8]) -> std::io::Result<usize> {
|
||||||
|
(&self.fd).write(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/network/tun_win.rs
Normal file
54
src/network/tun_win.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use crate::network::ReadWriter;
|
||||||
|
use sdlan_sn_rs::utils::Result;
|
||||||
|
use std::io::{Error, ErrorKind};
|
||||||
|
use std::sync::Arc;
|
||||||
|
use wintun;
|
||||||
|
|
||||||
|
pub struct WinTun {
|
||||||
|
adapter: Arc<wintun::Adapter>,
|
||||||
|
session: Arc<wintun::Session>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadWriter for WinTun {
|
||||||
|
fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
|
||||||
|
let Ok(pkt) = self.session.receive_blocking() else {
|
||||||
|
return Err(Error::new(ErrorKind::Other, "failed to receive"));
|
||||||
|
};
|
||||||
|
let content = pkt.bytes();
|
||||||
|
let length = content.len();
|
||||||
|
if content.len() > buf.len() {
|
||||||
|
return Err(Error::new(ErrorKind::Other, "length not enough"));
|
||||||
|
}
|
||||||
|
for i in 0..content.len() {
|
||||||
|
buf[i] = content[i];
|
||||||
|
}
|
||||||
|
Ok(length)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send(&self, content: &[u8]) -> std::io::Result<usize> {
|
||||||
|
let mut pkt = self
|
||||||
|
.session
|
||||||
|
.allocate_send_packet(content.len() as u16)
|
||||||
|
.unwrap();
|
||||||
|
let buf: &mut [u8] = pkt.bytes_mut();
|
||||||
|
buf.copy_from_slice(content);
|
||||||
|
self.session.send_packet(pkt);
|
||||||
|
Ok(content.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_wintun(path: &str) -> WinTun {
|
||||||
|
let wt = unsafe { wintun::load_from_path(path) }.expect("failed to load wintun");
|
||||||
|
|
||||||
|
let adapter = match wintun::Adapter::open(&wt, "Demo") {
|
||||||
|
Ok(a) => a,
|
||||||
|
Err(_) => wintun::Adapter::create(&wt, "Demo", "Example", None)
|
||||||
|
.expect("failed to create wintun adapter"),
|
||||||
|
};
|
||||||
|
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
|
||||||
|
WinTun { adapter, session }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_tun() -> Result<Box<dyn ReadWriter>> {
|
||||||
|
Ok(Box::new(create_wintun("/path/to/file")))
|
||||||
|
}
|
||||||
64
src/network/tuntap.c
Normal file
64
src/network/tuntap.c
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Since the rust ioctl bindings don't have all the structures and constants,
|
||||||
|
* it's easier to just write the thing in C and link it in.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <linux/if_tun.h>
|
||||||
|
#else
|
||||||
|
#include <net/if.h>
|
||||||
|
#define IFF_TUN 0x0001
|
||||||
|
#define IFF_TAP 0x0002
|
||||||
|
#define IFF_NO_PI 0x1000
|
||||||
|
#define TUNSETIFF _IOW('T', 202, int)
|
||||||
|
#endif
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fd ‒ the fd to turn into TUN or TAP.
|
||||||
|
* name ‒ the name to use. If empty, kernel will assign something by itself.
|
||||||
|
* Must be buffer with capacity at least 33.
|
||||||
|
* mode ‒ 1 = TUN, 2 = TAP.
|
||||||
|
* packet_info ‒ if packet info should be provided, if the given value is 0 it will not prepend packet info.
|
||||||
|
*/
|
||||||
|
int tuntap_setup(int fd, unsigned char *name, int mode, int packet_info)
|
||||||
|
{
|
||||||
|
struct ifreq ifr;
|
||||||
|
memset(&ifr, 0, sizeof ifr);
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
ifr.ifr_flags = IFF_TUN;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ifr.ifr_flags = IFF_TAP;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no packet info needs to be provided add corresponding flag
|
||||||
|
if (!packet_info)
|
||||||
|
{
|
||||||
|
ifr.ifr_flags |= IFF_NO_PI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leave one for terminating '\0'. No idea if it is needed, didn't find
|
||||||
|
// it in the docs, but assuming the worst.
|
||||||
|
strncpy(ifr.ifr_name, (char *)name, IFNAMSIZ - 1);
|
||||||
|
|
||||||
|
int ioresult = ioctl(fd, TUNSETIFF, &ifr);
|
||||||
|
if (ioresult < 0)
|
||||||
|
{
|
||||||
|
return ioresult;
|
||||||
|
}
|
||||||
|
strncpy((char *)name, ifr.ifr_name, IFNAMSIZ < 32 ? IFNAMSIZ : 32);
|
||||||
|
name[32] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
230
src/pb/message.rs
Normal file
230
src/pb/message.rs
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
// This file is @generated by prost-build.
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct Sdlv4Info {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub port: u32,
|
||||||
|
#[prost(bytes = "vec", tag = "2")]
|
||||||
|
pub v4: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub nat_type: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct Sdlv6Info {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub port: u32,
|
||||||
|
#[prost(bytes = "vec", tag = "2")]
|
||||||
|
pub v6: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
}
|
||||||
|
/// 设备网络地址信息
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlDevAddr {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub network_id: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub net_addr: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub net_bit_len: u32,
|
||||||
|
}
|
||||||
|
/// tcp通讯消息
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlEmpty {}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlRegisterSuper {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub version: u32,
|
||||||
|
#[prost(string, tag = "2")]
|
||||||
|
pub installed_channel: ::prost::alloc::string::String,
|
||||||
|
#[prost(string, tag = "3")]
|
||||||
|
pub client_id: ::prost::alloc::string::String,
|
||||||
|
#[prost(message, optional, tag = "4")]
|
||||||
|
pub dev_addr: ::core::option::Option<SdlDevAddr>,
|
||||||
|
#[prost(string, tag = "5")]
|
||||||
|
pub pub_key: ::prost::alloc::string::String,
|
||||||
|
#[prost(string, tag = "6")]
|
||||||
|
pub token: ::prost::alloc::string::String,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlRegisterSuperAck {
|
||||||
|
#[prost(message, optional, tag = "1")]
|
||||||
|
pub dev_addr: ::core::option::Option<SdlDevAddr>,
|
||||||
|
#[prost(bytes = "vec", tag = "2")]
|
||||||
|
pub aes_key: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
#[prost(bytes = "vec", tag = "3")]
|
||||||
|
pub known_ips: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
#[prost(uint32, tag = "4")]
|
||||||
|
pub upgrade_type: u32,
|
||||||
|
#[prost(string, optional, tag = "5")]
|
||||||
|
pub upgrade_prompt: ::core::option::Option<::prost::alloc::string::String>,
|
||||||
|
#[prost(string, optional, tag = "6")]
|
||||||
|
pub upgrade_address: ::core::option::Option<::prost::alloc::string::String>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlRegisterSuperNak {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub error_code: u32,
|
||||||
|
#[prost(string, tag = "2")]
|
||||||
|
pub error_message: ::prost::alloc::string::String,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlQueryInfo {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub dst_ip: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlPeerInfo {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub dst_ip: u32,
|
||||||
|
#[prost(message, optional, tag = "2")]
|
||||||
|
pub v4_info: ::core::option::Option<Sdlv4Info>,
|
||||||
|
#[prost(message, optional, tag = "3")]
|
||||||
|
pub v6_info: ::core::option::Option<Sdlv6Info>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlKnownIpEvent {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub ip: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlDropIpEvent {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub ip: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlNatChangedEvent {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub ip: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlSendRegisterEvent {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub dst_ip: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub nat_ip: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub nat_port: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlNetworkShutdownEvent {
|
||||||
|
#[prost(string, tag = "1")]
|
||||||
|
pub message: ::prost::alloc::string::String,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlChangeNetworkCommand {
|
||||||
|
#[prost(message, optional, tag = "1")]
|
||||||
|
pub dev_addr: ::core::option::Option<SdlDevAddr>,
|
||||||
|
#[prost(bytes = "vec", tag = "2")]
|
||||||
|
pub aes_key: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
#[prost(bytes = "vec", tag = "3")]
|
||||||
|
pub known_ips: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlCommandAck {
|
||||||
|
/// status = true, 表示成功;status = false 表示失败,message是失败原因描述
|
||||||
|
#[prost(bool, tag = "1")]
|
||||||
|
pub status: bool,
|
||||||
|
#[prost(string, optional, tag = "2")]
|
||||||
|
pub message: ::core::option::Option<::prost::alloc::string::String>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlFlows {
|
||||||
|
/// 服务器转发流量
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub forward_num: u32,
|
||||||
|
/// p2p直接流量
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub p2p_num: u32,
|
||||||
|
/// 接收的流量
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub inbound_num: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlStunRequest {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub cookie: u32,
|
||||||
|
#[prost(string, tag = "2")]
|
||||||
|
pub client_id: ::prost::alloc::string::String,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub network_id: u32,
|
||||||
|
#[prost(uint32, tag = "4")]
|
||||||
|
pub ip: u32,
|
||||||
|
#[prost(uint32, tag = "5")]
|
||||||
|
pub nat_type: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlStunReply {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub cookie: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlData {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub network_id: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub src_ip: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub dst_ip: u32,
|
||||||
|
#[prost(bool, tag = "4")]
|
||||||
|
pub is_p2p: bool,
|
||||||
|
#[prost(uint32, tag = "5")]
|
||||||
|
pub ttl: u32,
|
||||||
|
#[prost(bytes = "vec", tag = "6")]
|
||||||
|
pub data: ::prost::alloc::vec::Vec<u8>,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlRegister {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub network_id: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub src_ip: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub dst_ip: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlRegisterAck {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub network_id: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub src_ip: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub dst_ip: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlStunProbe {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub cookie: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub attr: u32,
|
||||||
|
}
|
||||||
|
#[allow(clippy::derive_partial_eq_without_eq)]
|
||||||
|
#[derive(Clone, PartialEq, ::prost::Message)]
|
||||||
|
pub struct SdlStunProbeReply {
|
||||||
|
#[prost(uint32, tag = "1")]
|
||||||
|
pub cookie: u32,
|
||||||
|
#[prost(uint32, tag = "2")]
|
||||||
|
pub port: u32,
|
||||||
|
#[prost(uint32, tag = "3")]
|
||||||
|
pub ip: u32,
|
||||||
|
}
|
||||||
40
src/pb/mod.rs
Normal file
40
src/pb/mod.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
mod message;
|
||||||
|
|
||||||
|
pub use message::*;
|
||||||
|
use prost::Message;
|
||||||
|
use sdlan_sn_rs::utils::Result;
|
||||||
|
|
||||||
|
// tcp message has two-byte of size at header
|
||||||
|
pub fn encode_to_tcp_message<T: Message>(
|
||||||
|
msg: Option<T>,
|
||||||
|
packet_id: u32,
|
||||||
|
packet_type: u8,
|
||||||
|
) -> Result<Vec<u8>> {
|
||||||
|
let mut raw_data = Vec::new();
|
||||||
|
|
||||||
|
if let Some(msg) = msg {
|
||||||
|
msg.encode(&mut raw_data)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = Vec::with_capacity(raw_data.len() + 7);
|
||||||
|
let size = u16::to_be_bytes(raw_data.len() as u16 + 5);
|
||||||
|
result.extend_from_slice(&size);
|
||||||
|
result.extend_from_slice(&u32::to_be_bytes(packet_id));
|
||||||
|
result.push(packet_type);
|
||||||
|
result.extend_from_slice(&raw_data);
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// udp message has no two-byte of size at header
|
||||||
|
pub fn encode_to_udp_message<T: Message>(msg: Option<T>, packet_type: u8) -> Result<Vec<u8>> {
|
||||||
|
let mut raw_data = Vec::new();
|
||||||
|
|
||||||
|
if let Some(msg) = msg {
|
||||||
|
msg.encode(&mut raw_data)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = Vec::with_capacity(raw_data.len() + 1);
|
||||||
|
result.push(packet_type);
|
||||||
|
result.extend_from_slice(&raw_data);
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
5
src/tcp/mod.rs
Normal file
5
src/tcp/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod tcp_codec;
|
||||||
|
mod tcp_conn;
|
||||||
|
|
||||||
|
pub use tcp_codec::*;
|
||||||
|
pub use tcp_conn::*;
|
||||||
203
src/tcp/tcp_codec.rs
Normal file
203
src/tcp/tcp_codec.rs
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
use tokio::{
|
||||||
|
io::{AsyncReadExt, BufReader},
|
||||||
|
net::tcp::OwnedReadHalf,
|
||||||
|
};
|
||||||
|
|
||||||
|
use num_enum::TryFromPrimitive;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SdlanTcp {
|
||||||
|
pub _packet_id: u32,
|
||||||
|
pub packet_type: PacketType,
|
||||||
|
pub current_packet: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum EventType {
|
||||||
|
KnownIP = 0x01,
|
||||||
|
|
||||||
|
DropIP = 0x02,
|
||||||
|
|
||||||
|
NatChanged = 0x03,
|
||||||
|
|
||||||
|
SendRegister = 0x04,
|
||||||
|
|
||||||
|
NetworkShutdown = 0xFF,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum PacketType {
|
||||||
|
Empty = 0x00,
|
||||||
|
RegisterSuper = 0x01,
|
||||||
|
RegisterSuperACK = 0x02,
|
||||||
|
RegisterSuperNAK = 0x04,
|
||||||
|
|
||||||
|
UnRegisterSuper = 0x05,
|
||||||
|
|
||||||
|
QueryInfo = 0x06,
|
||||||
|
PeerInfo = 0x07,
|
||||||
|
|
||||||
|
Ping = 0x08,
|
||||||
|
Pong = 0x09,
|
||||||
|
|
||||||
|
Event = 0x10,
|
||||||
|
|
||||||
|
Command = 0x11,
|
||||||
|
CommandACK = 0x12,
|
||||||
|
|
||||||
|
FlowTracer = 0x15,
|
||||||
|
|
||||||
|
Register = 0x20,
|
||||||
|
RegisterACK = 0x21,
|
||||||
|
|
||||||
|
StunRequest = 0x30,
|
||||||
|
StunReply = 0x31,
|
||||||
|
|
||||||
|
StunProbe = 0x32,
|
||||||
|
StunProbeReply = 0x33,
|
||||||
|
|
||||||
|
Data = 0xff,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_a_packet(
|
||||||
|
reader: &mut BufReader<OwnedReadHalf>,
|
||||||
|
) -> Result<SdlanTcp, std::io::Error> {
|
||||||
|
debug!("read a packet");
|
||||||
|
let size = reader.read_u16().await?;
|
||||||
|
debug!("1");
|
||||||
|
let packet_id = reader.read_u32().await?;
|
||||||
|
debug!("2");
|
||||||
|
let packet_type = reader.read_u8().await?;
|
||||||
|
debug!("3");
|
||||||
|
|
||||||
|
if size < 5 {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"size less than five",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let bufsize = (size - 5) as usize;
|
||||||
|
let mut binary = vec![0; bufsize];
|
||||||
|
|
||||||
|
let mut to_read = bufsize;
|
||||||
|
loop {
|
||||||
|
if to_read == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let size_got = reader.read(&mut binary[(bufsize - to_read)..]).await?;
|
||||||
|
|
||||||
|
if size_got == 0 {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"read got zero bytes",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
to_read -= size_got;
|
||||||
|
}
|
||||||
|
let Ok(packet_type) = packet_type.try_into() else {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"packet type error",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let result = SdlanTcp {
|
||||||
|
_packet_id: packet_id,
|
||||||
|
packet_type,
|
||||||
|
current_packet: binary,
|
||||||
|
};
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn read_a_packet2(reader: &mut OwnedReadHalf) -> Result<SdlanTcp, std::io::Error> {
|
||||||
|
debug!("read a packet");
|
||||||
|
let size = reader.read_u16().await?;
|
||||||
|
debug!("1");
|
||||||
|
let packet_id = reader.read_u32().await?;
|
||||||
|
debug!("2");
|
||||||
|
let packet_type = reader.read_u8().await?;
|
||||||
|
debug!("3");
|
||||||
|
|
||||||
|
if size < 5 {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"size less than five",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut binary = vec![0; (size - 5) as usize];
|
||||||
|
|
||||||
|
let mut bytes_read = 0;
|
||||||
|
loop {
|
||||||
|
let size_got = reader.read(&mut binary[bytes_read..]).await?;
|
||||||
|
if size_got == 0 {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"read got zero bytes",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
bytes_read += size_got;
|
||||||
|
if bytes_read == (size - 5) as usize {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Ok(packet_type) = packet_type.try_into() else {
|
||||||
|
return Err(std::io::Error::new(
|
||||||
|
std::io::ErrorKind::Other,
|
||||||
|
"packet type error",
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let result = SdlanTcp {
|
||||||
|
_packet_id: packet_id,
|
||||||
|
packet_type,
|
||||||
|
current_packet: binary,
|
||||||
|
};
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SdlanTcpCodec {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Item {
|
||||||
|
Data(Vec<u8>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Decoder for SdlanTcpCodec {
|
||||||
|
type Item = SdlanTcp;
|
||||||
|
type Error = std::io::Error;
|
||||||
|
|
||||||
|
fn decode(
|
||||||
|
&mut self,
|
||||||
|
src: &mut tokio_util::bytes::BytesMut,
|
||||||
|
) -> Result<Option<Self::Item>, Self::Error> {
|
||||||
|
if src.is_empty() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
let size = src.get_u16();
|
||||||
|
let packet_id = src.get_u32();
|
||||||
|
let packet_type = src.get_u8();
|
||||||
|
let mut binary = Vec::with_capacity((size - 5).into());
|
||||||
|
for i in 0..(size - 5) {
|
||||||
|
let data = src.get_u8();
|
||||||
|
binary.push(data);
|
||||||
|
}
|
||||||
|
let Ok(packet_type) = packet_type.try_into() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
let result = SdlanTcp {
|
||||||
|
_packet_id: packet_id,
|
||||||
|
packet_type,
|
||||||
|
current_packet: binary,
|
||||||
|
};
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
251
src/tcp/tcp_conn.rs
Normal file
251
src/tcp/tcp_conn.rs
Normal file
@ -0,0 +1,251 @@
|
|||||||
|
use once_cell::sync::OnceCell;
|
||||||
|
use sdlan_sn_rs::utils::{get_current_timestamp, Result, SDLanError};
|
||||||
|
use std::future::Future;
|
||||||
|
use std::sync::atomic::AtomicU64;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::{
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
use tokio::io::BufReader;
|
||||||
|
use tokio_util::sync::CancellationToken;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
|
use futures_util::{future::BoxFuture, pin_mut};
|
||||||
|
use tokio::{
|
||||||
|
io::AsyncWriteExt,
|
||||||
|
net::TcpStream,
|
||||||
|
sync::mpsc::{channel, Receiver, Sender},
|
||||||
|
};
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use crate::config::TCP_PING_TIME;
|
||||||
|
use crate::tcp::read_a_packet;
|
||||||
|
|
||||||
|
use super::tcp_codec::SdlanTcp;
|
||||||
|
|
||||||
|
static GLOBAL_TCP_HANDLE: OnceCell<ReadWriterHandle> = OnceCell::new();
|
||||||
|
|
||||||
|
pub struct ReadWriteActor {
|
||||||
|
// actor接收的发送给tcp的接收端,由handle存放发送端
|
||||||
|
// to_tcp: Receiver<Vec<u8>>,
|
||||||
|
remote: String,
|
||||||
|
connected: Arc<AtomicBool>,
|
||||||
|
pong_time: Arc<AtomicU64>,
|
||||||
|
// actor收到数据之后,发送给上层的发送端口,接收端由handle保存
|
||||||
|
from_tcp: Sender<SdlanTcp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadWriteActor {
|
||||||
|
pub fn new(
|
||||||
|
remote: &str,
|
||||||
|
from_tcp: Sender<SdlanTcp>,
|
||||||
|
connected: Arc<AtomicBool>,
|
||||||
|
pong_time: Arc<AtomicU64>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
// to_tcp,
|
||||||
|
pong_time,
|
||||||
|
connected,
|
||||||
|
remote: remote.to_owned(),
|
||||||
|
from_tcp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run<'a, T>(
|
||||||
|
&self,
|
||||||
|
keep_reconnect: bool,
|
||||||
|
mut to_tcp: Receiver<Vec<u8>>,
|
||||||
|
on_connected: T,
|
||||||
|
mut start_stop_chan: Receiver<bool>,
|
||||||
|
// cancel: CancellationToken,
|
||||||
|
) where
|
||||||
|
T: for<'b> Fn(&'b mut TcpStream) -> BoxFuture<'b, ()>,
|
||||||
|
{
|
||||||
|
// let (tx, rx) = channel(20);
|
||||||
|
let mut started = false;
|
||||||
|
loop {
|
||||||
|
self.connected.store(false, Ordering::Relaxed);
|
||||||
|
if !started {
|
||||||
|
println!("waiting for start");
|
||||||
|
while let Some(m) = start_stop_chan.recv().await {
|
||||||
|
if m {
|
||||||
|
println!("true received");
|
||||||
|
started = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
println!("false received");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("try connecting...");
|
||||||
|
let Ok(mut stream) = TcpStream::connect(&self.remote).await else {
|
||||||
|
self.connected.store(false, Ordering::Relaxed);
|
||||||
|
if keep_reconnect {
|
||||||
|
tokio::select! {
|
||||||
|
_ = tokio::time::sleep(Duration::from_secs(3)) => {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tokio::time::sleep(Duration::from_secs(3)).await;
|
||||||
|
// continue;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.connected.store(true, Ordering::Relaxed);
|
||||||
|
on_connected(&mut stream).await;
|
||||||
|
// stream.write("hello".as_bytes()).await;
|
||||||
|
let (reader, mut write) = stream.into_split();
|
||||||
|
|
||||||
|
let read_from_tcp = async move {
|
||||||
|
let mut buffed_reader = BufReader::new(reader);
|
||||||
|
loop {
|
||||||
|
match read_a_packet(&mut buffed_reader).await {
|
||||||
|
Ok(packet) => {
|
||||||
|
debug!("got packet: {:?}", packet);
|
||||||
|
if let Err(_e) = self.from_tcp.send(packet).await {
|
||||||
|
error!("failed to receive a packet: {:?}", _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to read a packet: {}, reconnecting...", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let write_to_tcp = async {
|
||||||
|
while let Some(data) = to_tcp.recv().await {
|
||||||
|
match write.write(&data).await {
|
||||||
|
Ok(size) => {
|
||||||
|
debug!("{} bytes sent to tcp", size);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("failed to write to tcp: {}", e.to_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("to_tcp recv None");
|
||||||
|
};
|
||||||
|
|
||||||
|
let check_pong = async {
|
||||||
|
loop {
|
||||||
|
tokio::time::sleep(Duration::from_secs(10)).await;
|
||||||
|
|
||||||
|
let connected = self.connected.load(Ordering::Relaxed);
|
||||||
|
let now = get_current_timestamp();
|
||||||
|
if connected && now - self.pong_time.load(Ordering::Relaxed) > TCP_PING_TIME * 2
|
||||||
|
{
|
||||||
|
// pong time expire, need to re-connect
|
||||||
|
error!("pong check expired");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pin_mut!(read_from_tcp, write_to_tcp);
|
||||||
|
|
||||||
|
tokio::select! {
|
||||||
|
_ = read_from_tcp => {},
|
||||||
|
_ = write_to_tcp => {},
|
||||||
|
_ = check_pong => {},
|
||||||
|
Some(false) = start_stop_chan.recv() => {
|
||||||
|
started = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("connect retrying");
|
||||||
|
// future::select(read_from_tcp, write_to_tcp).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ReadWriterHandle {
|
||||||
|
connected: Arc<AtomicBool>,
|
||||||
|
send_to_tcp: Sender<Vec<u8>>,
|
||||||
|
// pub data_from_tcp: Receiver<SdlanTcp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadWriterHandle {
|
||||||
|
pub async fn send(&self, data: &[u8]) -> Result<()> {
|
||||||
|
if self.connected.load(Ordering::Relaxed) {
|
||||||
|
// connected, send to it
|
||||||
|
if let Err(e) = self.send_to_tcp.send(Vec::from(data)).await {
|
||||||
|
println!("failed to send to send_to_tcp: {}", e.to_string());
|
||||||
|
return Err(SDLanError::NormalError("failed to send"));
|
||||||
|
};
|
||||||
|
debug!("tcp info sent");
|
||||||
|
} else {
|
||||||
|
error!("tcp not connected, so not sending data");
|
||||||
|
return Err(SDLanError::NormalError("not connected, so not sending"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new<'a, T, T2, F>(
|
||||||
|
addr: &str,
|
||||||
|
on_connected: T,
|
||||||
|
on_message: T2,
|
||||||
|
pong_time: Arc<AtomicU64>,
|
||||||
|
start_stop_chan: Receiver<bool>,
|
||||||
|
// cancel: CancellationToken,
|
||||||
|
) -> Self
|
||||||
|
where
|
||||||
|
T: for<'b> Fn(&'b mut TcpStream) -> BoxFuture<'b, ()> + Send + 'static,
|
||||||
|
T2: Fn(SdlanTcp) -> F + Send + 'static,
|
||||||
|
F: Future<Output = ()> + Send,
|
||||||
|
{
|
||||||
|
let (send_to_tcp, to_tcp) = channel(20);
|
||||||
|
let (from_tcp, mut data_from_tcp) = channel(20);
|
||||||
|
|
||||||
|
let connected = Arc::new(AtomicBool::new(false));
|
||||||
|
let actor = ReadWriteActor::new(addr, from_tcp, connected.clone(), pong_time);
|
||||||
|
tokio::spawn(async move { actor.run(true, to_tcp, on_connected, start_stop_chan).await });
|
||||||
|
tokio::spawn(async move {
|
||||||
|
loop {
|
||||||
|
if let Some(msg) = data_from_tcp.recv().await {
|
||||||
|
on_message(msg).await;
|
||||||
|
} else {
|
||||||
|
println!("data from tcp exited");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ReadWriterHandle {
|
||||||
|
connected,
|
||||||
|
send_to_tcp,
|
||||||
|
// data_from_tcp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_tcp_conn<'a, T, T2, F>(
|
||||||
|
addr: &str,
|
||||||
|
on_connected: T,
|
||||||
|
on_message: T2,
|
||||||
|
pong_time: Arc<AtomicU64>,
|
||||||
|
// cancel: CancellationToken,
|
||||||
|
start_stop_chan: Receiver<bool>,
|
||||||
|
) where
|
||||||
|
T: for<'b> Fn(&'b mut TcpStream) -> BoxFuture<'b, ()> + Send + 'static,
|
||||||
|
T2: Fn(SdlanTcp) -> F + Send + 'static,
|
||||||
|
F: Future<Output = ()> + Send,
|
||||||
|
{
|
||||||
|
let tcp_handle =
|
||||||
|
ReadWriterHandle::new(addr, on_connected, on_message, pong_time, start_stop_chan);
|
||||||
|
|
||||||
|
GLOBAL_TCP_HANDLE
|
||||||
|
.set(tcp_handle)
|
||||||
|
.expect("failed to set global tcp handle");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_tcp_conn() -> &'static ReadWriterHandle {
|
||||||
|
match GLOBAL_TCP_HANDLE.get() {
|
||||||
|
Some(v) => v,
|
||||||
|
None => panic!("should call init_tcp_conn first"),
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/utils/command.rs
Normal file
47
src/utils/command.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
#[derive(StructOpt, Debug)]
|
||||||
|
pub struct CommandLine {
|
||||||
|
#[structopt(short = "s", long = "sn", default_value = "127.0.0.1:7655")]
|
||||||
|
pub sn: String,
|
||||||
|
|
||||||
|
#[structopt(short = "t", long = "tcp", default_value = "127.0.0.1:7656")]
|
||||||
|
pub tcp: String,
|
||||||
|
|
||||||
|
#[structopt(short = "r")]
|
||||||
|
pub _allow_routing: bool,
|
||||||
|
|
||||||
|
#[structopt(
|
||||||
|
help = "ttl of the register udp4 packet",
|
||||||
|
short = "L",
|
||||||
|
default_value = "1"
|
||||||
|
)]
|
||||||
|
pub register_ttl: u8,
|
||||||
|
|
||||||
|
#[structopt(help = "mtu of the tun", short = "m", default_value = "1290")]
|
||||||
|
pub mtu: u32,
|
||||||
|
|
||||||
|
#[structopt(short = "n", long = "name", default_value = "test-name")]
|
||||||
|
pub name: String,
|
||||||
|
|
||||||
|
#[structopt(long = "tos", default_value = "0")]
|
||||||
|
pub tos: u32,
|
||||||
|
|
||||||
|
#[structopt(long = "token", default_value = "0")]
|
||||||
|
pub token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for CommandLine {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
sn: self.sn.clone(),
|
||||||
|
tcp: self.tcp.clone(),
|
||||||
|
_allow_routing: self._allow_routing,
|
||||||
|
register_ttl: self.register_ttl,
|
||||||
|
mtu: self.mtu,
|
||||||
|
name: self.name.clone(),
|
||||||
|
tos: self.tos,
|
||||||
|
token: self.token.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/utils/mod.rs
Normal file
8
src/utils/mod.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
mod command;
|
||||||
|
pub use command::*;
|
||||||
|
|
||||||
|
mod socks;
|
||||||
|
pub use socks::*;
|
||||||
|
|
||||||
|
mod pid_recorder;
|
||||||
|
pub use pid_recorder::PidRecorder;
|
||||||
36
src/utils/pid_recorder.rs
Normal file
36
src/utils/pid_recorder.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use std::{
|
||||||
|
fs::{self, OpenOptions},
|
||||||
|
io::Write,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PidRecorder(String);
|
||||||
|
|
||||||
|
impl PidRecorder {
|
||||||
|
pub fn new(pidfile: &str) -> Self {
|
||||||
|
let pid = std::process::id();
|
||||||
|
match OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.truncate(true)
|
||||||
|
.open(pidfile)
|
||||||
|
{
|
||||||
|
Ok(mut fp) => {
|
||||||
|
fp.write(format!("{}", pid).as_bytes())
|
||||||
|
.expect("failed to write");
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
println!("failed to open pid file: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Self(pidfile.to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for PidRecorder {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Err(e) = fs::remove_file(&self.0) {
|
||||||
|
println!("failed to remove pid file: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
145
src/utils/socks.rs
Normal file
145
src/utils/socks.rs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
use sdlan_sn_rs::{
|
||||||
|
config::{AF_INET, AF_INET6},
|
||||||
|
utils::{Result, SDLanError},
|
||||||
|
};
|
||||||
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||||
|
use tokio::net::ToSocketAddrs;
|
||||||
|
use tracing::error;
|
||||||
|
|
||||||
|
use sdlan_sn_rs::peer::SdlanSock;
|
||||||
|
use tokio::net::UdpSocket;
|
||||||
|
|
||||||
|
use crate::network::Node;
|
||||||
|
|
||||||
|
pub struct Socket {
|
||||||
|
udp: UdpSocket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Socket {
|
||||||
|
pub async fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], target: A) -> Result<usize> {
|
||||||
|
let m = self.udp.send_to(buf, target).await?;
|
||||||
|
Ok(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
|
||||||
|
let m = self.udp.recv_from(buf).await?;
|
||||||
|
Ok(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ttl(&self) -> Result<u32> {
|
||||||
|
if let Ok(v) = self.udp.ttl() {
|
||||||
|
Ok(v)
|
||||||
|
} else {
|
||||||
|
Err(SDLanError::NormalError("no ttl found"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ttl(&self, ttl: u32) -> Result<()> {
|
||||||
|
if let Ok(_) = self.udp.set_ttl(ttl) {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(SDLanError::NormalError("failed to set ttl"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn build(port: u16, bind_any: bool, join_multicast: bool, tos: u32) -> Result<Self> {
|
||||||
|
let addr = match bind_any {
|
||||||
|
true => "0.0.0.0",
|
||||||
|
false => "127.0.0.1",
|
||||||
|
};
|
||||||
|
let udp = UdpSocket::bind(format!("{}:{}", addr, port)).await?;
|
||||||
|
if join_multicast {
|
||||||
|
if let Err(e) =
|
||||||
|
udp.join_multicast_v4(Ipv4Addr::new(224, 0, 0, 69), Ipv4Addr::new(0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
error!("failed to join multicast: {}", e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tos != 0 {
|
||||||
|
if let Err(e) = udp.set_tos(tos) {
|
||||||
|
error!("failed to set tos: {}", e.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Self { udp })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn send_to_sock_v4_and_v6(
|
||||||
|
// sk: &Socket,
|
||||||
|
eee: &Node,
|
||||||
|
content: &[u8],
|
||||||
|
sock: &SdlanSock,
|
||||||
|
v6: &Option<V6Info>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let _ = send_to_sock(&eee, content, sock).await;
|
||||||
|
if let Some(v6) = v6 {
|
||||||
|
// let sk6 = eee.udp_sock_v6.read().unwrap().clone();
|
||||||
|
let sock = SdlanSock {
|
||||||
|
family: AF_INET6,
|
||||||
|
port: v6.port,
|
||||||
|
v4: [0; 4],
|
||||||
|
v6: v6.v6,
|
||||||
|
};
|
||||||
|
let _ = send_to_sock(eee, content, &sock).await;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub async fn send_to_sock(
|
||||||
|
// sk: &Socket,
|
||||||
|
eee: &Node,
|
||||||
|
content: &[u8],
|
||||||
|
sock: &SdlanSock,
|
||||||
|
// v6: &Option<V6Info>,
|
||||||
|
) -> Result<()> {
|
||||||
|
match sock.family {
|
||||||
|
AF_INET => {
|
||||||
|
// sockv4
|
||||||
|
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::from(sock.v4)), sock.port);
|
||||||
|
eee.udp_sock_v4.send_to(content, addr).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
AF_INET6 => {
|
||||||
|
// sock v6
|
||||||
|
let sk = eee.udp_sock_v6.read().unwrap().clone();
|
||||||
|
match sk.as_ref() {
|
||||||
|
None => {
|
||||||
|
error!("ipv6 not opened, not responding");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(sk) => {
|
||||||
|
let addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::from(sock.v6)), sock.port);
|
||||||
|
sk.send_to(content, addr).await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
error!("unknown family {}, aborting", other);
|
||||||
|
return Err(SDLanError::NormalError("unknown family"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
pub async fn send_to_sock(sk: &Socket, content: &[u8], sock: &SdlanSock) -> Result<usize> {
|
||||||
|
match sock.family {
|
||||||
|
AF_INET => {
|
||||||
|
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::from(sock.v4)), sock.port);
|
||||||
|
let n = sk.send_to(content, addr).await?;
|
||||||
|
return Ok(n);
|
||||||
|
}
|
||||||
|
AF_INET6 => {
|
||||||
|
let addr = SocketAddr::new(IpAddr::V6(Ipv6Addr::from(sock.v6)), sock.port);
|
||||||
|
let n = sk.send_to(content, addr).await?;
|
||||||
|
return Ok(n);
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
error!("AF family {} not implemented", other);
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
Loading…
x
Reference in New Issue
Block a user