调整项目结构、尝试支持安卓

This commit is contained in:
lubeilin
2023-01-08 15:38:45 +08:00
parent d956e493af
commit 292893e9dd
76 changed files with 1132 additions and 588 deletions
+70
View File
@@ -0,0 +1,70 @@
use std::net::{SocketAddr, UdpSocket};
use std::time::Duration;
use chrono::Local;
use tokio::sync::watch::Receiver;
use tokio::time::sleep;
use crate::{CurrentDeviceInfo, DEVICE_LIST};
use crate::error::*;
use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE};
use crate::protocol::{control_packet, NetPacket, Protocol, Version};
use crate::protocol::control_packet::PingPacket;
pub async fn start<F>(status_watch: Receiver<ApplicationStatus>,
udp: UdpSocket, cur_info: CurrentDeviceInfo, stop_fn: F)
where F: FnOnce() + Send + 'static {
tokio::spawn(async move {
match handle_loop(status_watch, udp, cur_info.connect_server).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e)
}
}
stop_fn();
});
}
async fn handle_loop(mut status_watch: Receiver<ApplicationStatus>, udp: UdpSocket, server_addr: SocketAddr) -> Result<()> {
const INTERVAL: u64 = 3000;
const MAX_INTERVAL: i64 = 3000 * 3;
let mut buf = [0u8; (4 + 8 + 4)];
let mut net_packet = NetPacket::new(&mut buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Control);
net_packet.set_transport_protocol(control_packet::Protocol::Ping.into());
net_packet.set_ttl(255);
loop {
let current_time = Local::now().timestamp_millis();
{
let mut ping = PingPacket::new(net_packet.payload_mut())?;
ping.set_time(current_time);
let epoch = { DEVICE_LIST.lock().0 };
ping.set_epoch(epoch);
}
let _ = udp.send_to(net_packet.buffer(), server_addr);
for x in DIRECT_ROUTE_TABLE.iter() {
let virtual_ip = x.key().clone();
let route = x.value().clone();
drop(x);
if current_time - route.recv_time <= MAX_INTERVAL {
let _ = udp.send_to(net_packet.buffer(), route.address);
} else {
DIRECT_ROUTE_TABLE.remove_if(&virtual_ip, |_, route| {
current_time - route.recv_time > MAX_INTERVAL
});
}
}
tokio::select! {
_ = sleep(Duration::from_millis(INTERVAL))=>{
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
}
}
}
}
+169
View File
@@ -0,0 +1,169 @@
use std::net::{Ipv4Addr, SocketAddr};
use std::sync::atomic::AtomicI64;
use std::time::Duration;
use chrono::Local;
use dashmap::DashMap;
use lazy_static::lazy_static;
use moka::sync::Cache;
use parking_lot::{const_mutex, Mutex};
use crate::proto::message::NatType;
pub mod heartbeat_handler;
pub mod punch_handler;
pub mod registration_handler;
pub mod tun_handler;
pub mod udp_recv_handler;
lazy_static! {
/// 0. 机器纪元,每一次上线或者下线都会增1,由服务端维护,用于感知网络中机器变化
/// 服务端和客户端的不一致,则服务端会推送新的设备列表
/// 1. 网络中的虚拟ip列表
pub static ref DEVICE_LIST:Mutex<(u32,Vec<Ipv4Addr>)> = const_mutex((0,Vec::new()));
/// 服务器延迟
pub static ref SERVER_RT:AtomicI64 = AtomicI64::new(-1);
/// id
pub static ref ID:AtomicI64 = AtomicI64::new(0);
/// 直连路由表
pub static ref DIRECT_ROUTE_TABLE:DashMap<Ipv4Addr,Route> = DashMap::new();
/// 地址映射
pub static ref ADDR_TABLE:Cache<SocketAddr,Ipv4Addr> = Cache::builder()
.time_to_idle(Duration::from_secs(60*5)).build();
/// 当前设备的nat信息
pub static ref NAT_INFO:Mutex<Option<NatInfo>> = const_mutex(None);
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ApplicationStatus {
Starting,
Stopping,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum ConnectStatus {
Connecting,
Connected,
}
impl Into<u8> for ConnectStatus {
fn into(self) -> u8 {
match self {
ConnectStatus::Connecting => 0,
ConnectStatus::Connected => 1,
}
}
}
#[derive(Clone, Debug)]
pub struct NatInfo {
public_ips: Vec<u32>,
public_port: u16,
public_port_range: u16,
nat_type: NatType,
}
impl NatInfo {
pub fn new(public_ips: Vec<u32>,
public_port: u16,
public_port_range: u16,
nat_type: NatType, ) -> Self {
Self {
public_ips,
public_port,
public_port_range,
nat_type,
}
}
}
/// 初始化nat信息
pub fn init_nat_info(public_ip: u32, public_port: u16) {
match crate::nat::check::public_ip_list() {
Ok((nat_type, ips, port_range)) => {
let mut public_ips = Vec::new();
public_ips.push(public_ip);
for ip in ips {
let ip = u32::from_be_bytes(ip.octets());
if ip != public_ip {
public_ips.push(ip);
}
}
let nat_info = NatInfo::new(public_ips,
public_port,
port_range, nat_type);
// println!("nat信息:{:?}",nat_info);
let mut nat_info_lock = NAT_INFO.lock();
nat_info_lock.replace(nat_info);
}
Err(e) => {
println!("获取nat数据失败,将无法进行udp打洞:{:?}", e);
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct CurrentDeviceInfo {
pub virtual_ip: Ipv4Addr,
pub virtual_gateway: Ipv4Addr,
pub virtual_netmask: Ipv4Addr,
//网络地址
pub virtual_network: Ipv4Addr,
//直接广播地址
pub broadcast_address: Ipv4Addr,
//链接的服务器地址
pub connect_server: SocketAddr,
}
impl CurrentDeviceInfo {
pub fn new(virtual_ip: Ipv4Addr, virtual_gateway: Ipv4Addr, virtual_netmask: Ipv4Addr, connect_server: SocketAddr) -> Self {
let broadcast_address = (!u32::from_be_bytes(virtual_netmask.octets()))
| u32::from_be_bytes(virtual_gateway.octets());
let broadcast_address = Ipv4Addr::from(broadcast_address);
let virtual_network = u32::from_be_bytes(virtual_netmask.octets())
& u32::from_be_bytes(virtual_gateway.octets());
let virtual_network = Ipv4Addr::from(virtual_network);
Self {
virtual_ip,
virtual_netmask,
virtual_gateway,
virtual_network,
broadcast_address,
connect_server,
}
}
}
#[derive(Clone, Debug)]
pub struct Route {
pub route_type: RouteType,
pub address: SocketAddr,
//用心跳探测延迟,收包时更新
pub rt: i64,
//收包时更新,如果太久没有收到消息则剔除
pub recv_time: i64,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RouteType {
ServerRelay,
P2P,
}
impl Into<u8> for RouteType {
fn into(self) -> u8 {
match self {
RouteType::ServerRelay => 0,
RouteType::P2P => 1
}
}
}
impl Route {
pub fn new(address: SocketAddr) -> Self {
Self {
route_type: RouteType::P2P,
address,
rt: -1,
recv_time: Local::now().timestamp_millis(),
}
}
}
+422
View File
@@ -0,0 +1,422 @@
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
use std::thread;
use std::time::Duration;
use dashmap::DashMap;
use lazy_static::lazy_static;
use protobuf::Message;
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::sync::mpsc::error::TrySendError;
use tokio::sync::watch;
use crate::{CurrentDeviceInfo, DEVICE_LIST, handle::NAT_INFO, handle::NatInfo};
use crate::error::*;
use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE};
use crate::proto::message::{NatType, Punch, Step};
use crate::protocol::{control_packet, NetPacket, Protocol, turn_packet, Version};
use crate::protocol::control_packet::PunchRequestPacket;
use crate::protocol::turn_packet::TurnPacket;
lazy_static! {
pub static ref STEP_MAP:DashMap<Ipv4Addr,Step> = DashMap::new();
}
/// 每一种类型一个通道,减少相互干扰
pub fn bounded() -> (PunchSender, ConeReceiver, ReqSymmetricReceiver, ResSymmetricReceiver) {
let (cone_sender, cone_receiver) = tokio::sync::mpsc::channel(3);
let (req_symmetric_sender, req_symmetric_receiver) = tokio::sync::mpsc::channel(1);
let (res_symmetric_sender, res_symmetric_receiver) = tokio::sync::mpsc::channel(1);
(PunchSender::new(cone_sender, req_symmetric_sender, res_symmetric_sender),
ConeReceiver(cone_receiver), ReqSymmetricReceiver(req_symmetric_receiver),
ResSymmetricReceiver(res_symmetric_receiver))
}
pub struct ConeReceiver(Receiver<Punch>);
pub struct ReqSymmetricReceiver(Receiver<Punch>);
pub struct ResSymmetricReceiver(Receiver<Punch>);
#[derive(Clone)]
pub struct PunchSender {
cone_sender: Sender<Punch>,
req_symmetric_sender: Sender<Punch>,
res_symmetric_sender: Sender<Punch>,
}
impl PunchSender {
pub fn new(cone_sender: Sender<Punch>,
req_symmetric_sender: Sender<Punch>,
res_symmetric_sender: Sender<Punch>, ) -> Self {
Self {
cone_sender,
req_symmetric_sender,
res_symmetric_sender,
}
}
// pub fn send(&self, punch: Punch) -> std::result::Result<(), SendError<Punch>> {
// match punch.nat_type.enum_value_or_default() {
// NatType::Symmetric => {
// if punch.reply {
// // 为true表示回应,也就是主动发起的打洞操作
// self.res_symmetric_sender.blocking_send(punch)
// } else {
// self.req_symmetric_sender.blocking_send(punch)
// }
// }
// NatType::Cone => {
// self.cone_sender.blocking_send(punch)
// }
// }
// }
pub fn try_send(&self, punch: Punch) -> std::result::Result<(), TrySendError<Punch>> {
match punch.nat_type.enum_value_or_default() {
NatType::Symmetric => {
if punch.reply {
// 为true表示回应,也就是主动发起的打洞操作
self.res_symmetric_sender.try_send(punch)
} else {
self.req_symmetric_sender.try_send(punch)
}
}
NatType::Cone => {
self.cone_sender.try_send(punch)
}
}
}
}
fn handle(status_watch: &watch::Receiver<ApplicationStatus>, udp: &UdpSocket, punch_list: Vec<Punch>, buf: &[u8]) -> Result<()> {
let mut counter = 0u64;
for punch in punch_list {
let dest = Ipv4Addr::from(punch.virtual_ip);
if DIRECT_ROUTE_TABLE.contains_key(&dest) {
continue;
}
// println!("punch {:?}", punch);
match punch.nat_type.enum_value_or_default() {
NatType::Symmetric => {
match punch.step.enum_value_or_default() {
Step::Step1 | Step::Step2 | Step::Step3 => {
//预测范围发送
for pub_ip in punch.public_ip_list {
let pub_ip = Ipv4Addr::from(pub_ip);
for range in 0..punch.public_port_range + 1 {
if counter & 10 == 10 {
if status_watch.has_changed()? {
return Ok(());
}
}
let right_port = ((punch.public_port + range) & 0xFFFF) as u16;
let left_port = ((0xFFFF + punch.public_port - range) & 0xFFFF) as u16;
if right_port != 0 {
// println!("{:?}", SocketAddr::V4(SocketAddrV4::new(pub_ip, right_port)));
udp.send_to(
buf,
SocketAddr::V4(SocketAddrV4::new(pub_ip, right_port)),
)?;
select_sleep(&mut counter);
}
if left_port != 0 && range != 0 {
// println!("{:?}", SocketAddr::V4(SocketAddrV4::new(pub_ip, right_port)));
if left_port == right_port {
break;
}
udp.send_to(
buf,
SocketAddr::V4(SocketAddrV4::new(pub_ip, left_port)),
)?;
select_sleep(&mut counter);
}
}
}
}
Step::Step4 => {
//全范围发送
for pub_ip in punch.public_ip_list {
let pub_ip = Ipv4Addr::from(pub_ip);
for port in 1..0xFFFF {
if counter & 10 == 10 {
if status_watch.has_changed()? {
return Ok(());
}
}
udp.send_to(
buf,
SocketAddr::V4(SocketAddrV4::new(pub_ip, port)),
)?;
select_sleep(&mut counter);
}
}
}
}
}
NatType::Cone => {
for pub_ip in punch.public_ip_list {
udp.send_to(
buf,
SocketAddr::V4(SocketAddrV4::new(
Ipv4Addr::from(pub_ip),
punch.public_port as u16,
)),
)?;
select_sleep(&mut counter);
}
}
}
}
Ok(())
}
/// 给对称nat发送打洞数据包
pub async fn req_symmetric_handler_start<F>(status_watch: watch::Receiver<ApplicationStatus>,
receiver: ReqSymmetricReceiver,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
stop_fn: F) where F: FnOnce() +Send+'static{
let receiver = receiver.0;
tokio::spawn(async move {
match handle_loop(status_watch, receiver, udp, cur_info).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e)
}
}
stop_fn()
});
}
// pub fn req_symmetric_handle_loop(
// receiver: ReqSymmetricReceiver,
// udp: UdpSocket,
// cur_info: CurrentDeviceInfo,
// ) -> Result<()> {
// let receiver = receiver.0;
// handle_loop(receiver, udp, cur_info)
// }
/// 给对称nat发送打洞数据包,处理主动发起的打洞操作
pub async fn res_symmetric_handler_start<F>(status_watch: watch::Receiver<ApplicationStatus>,
receiver: ResSymmetricReceiver,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
stop_fn: F) where F: FnOnce() +Send+'static{
let receiver = receiver.0;
tokio::spawn(async move {
match res_symmetric_handle_loop(status_watch, receiver, udp, cur_info).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e)
}
}
stop_fn()
});
}
async fn res_symmetric_handle_loop(
mut status_watch: watch::Receiver<ApplicationStatus>,
mut receiver: Receiver<Punch>,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut buf = [0u8; 12];
let mut packet = NetPacket::new(&mut buf)?;
packet.set_version(Version::V1);
packet.set_ttl(255);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
{
let mut punch_packet = PunchRequestPacket::new(packet.payload_mut())?;
punch_packet.set_source(cur_info.virtual_ip);
}
match tokio::time::timeout(Duration::from_secs(30), receiver.recv()).await {
Ok(_) => {}
Err(e) => {}
}
loop {
tokio::select! {
rs = tokio::time::timeout(Duration::from_secs(30), receiver.recv()) =>{
match rs {
Ok(punch) => {
if let Some(punch) = punch{
let mut list = Vec::new();
list.push(punch);
loop {
match receiver.try_recv() {
Ok(punch) => {
list.push(punch);
}
Err(_) => {
break;
}
}
}
for punch in &list {
let dest = Ipv4Addr::from(punch.virtual_ip);
match punch.step.enum_value_or_default() {
Step::Step1 => {
STEP_MAP.insert(dest, Step::Step2);
}
Step::Step2 => {
STEP_MAP.insert(dest, Step::Step3);
}
Step::Step3 => {
STEP_MAP.insert(dest, Step::Step4);
}
Step::Step4 => {
STEP_MAP.insert(dest, Step::Step1);
}
}
}
if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) {
log::error!("{:?}",e)
}
}else {
return Err(Error::Stop("打洞线程通道关闭".to_string()));
}
}
Err(_) => {
punch_request_handle(&udp, &cur_info)?;
}
}
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
}
}
}
}
/// 给锥形nat发送打洞数据包
pub async fn cone_handler_start<F>(status_watch: watch::Receiver<ApplicationStatus>,
receiver: ConeReceiver,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
stop_fn: F) where F: FnOnce()+Send +'static{
let receiver = receiver.0;
tokio::spawn(async move {
match handle_loop(status_watch, receiver, udp, cur_info).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e)
}
}
stop_fn();
});
}
async fn handle_loop(
mut status_watch: watch::Receiver<ApplicationStatus>,
mut receiver: Receiver<Punch>,
udp: UdpSocket,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut buf = [0u8; 12];
let mut packet = NetPacket::new(&mut buf)?;
packet.set_version(Version::V1);
packet.set_ttl(255);
packet.set_protocol(Protocol::Control);
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
{
let mut punch_packet = PunchRequestPacket::new(packet.payload_mut())?;
punch_packet.set_source(cur_info.virtual_ip);
}
loop {
tokio::select! {
punch = receiver.recv() =>{
if let Some(punch) = punch{
let mut list = Vec::new();
list.push(punch);
loop {
match receiver.try_recv() {
Ok(punch) => {
list.push(punch);
}
Err(_) => {
break;
}
}
}
if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) {
log::error!("{:?}",e)
}
}else {
return Err(Error::Stop("打洞线程通道关闭".to_string()));
}
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
}
}
}
}
fn select_sleep(counter: &mut u64) {
*counter += 1;
thread::sleep(Duration::from_millis(1));
}
fn punch_request_handle(udp: &UdpSocket, cur_info: &CurrentDeviceInfo) -> Result<()> {
let nat_info_lock = NAT_INFO.lock();
let nat_info = nat_info_lock.clone();
drop(nat_info_lock);
if let Some(nat_info) = nat_info {
if let Err(e) = send_punch(&udp,
&cur_info,
nat_info) {
log::error!("发送打洞数据失败 {:?}",e)
}
Ok(())
} else {
Err(Error::Stop("未初始化nat信息".to_string()))
}
}
fn send_punch(udp: &UdpSocket, cur_info: &CurrentDeviceInfo, nat_info: NatInfo) -> Result<()> {
let lock = DEVICE_LIST.lock();
let list = lock.1.clone();
drop(lock);
for ip in list {
//只向ip比自己大的发起打洞,避免双方同时发起打洞浪费流量
if ip > cur_info.virtual_ip && !DIRECT_ROUTE_TABLE.contains_key(&ip) {
let step = if let Some(step) = STEP_MAP.get(&ip) {
*step
} else {
Step::Step1
};
let bytes = punch_packet(cur_info.virtual_ip,
nat_info.clone(), ip, step)?;
udp.send_to(&bytes, cur_info.connect_server)?;
}
}
Ok(())
}
fn punch_packet(virtual_ip: Ipv4Addr, nat_info: NatInfo, dest: Ipv4Addr, step: Step) -> Result<Vec<u8>> {
let mut punch_reply = Punch::new();
punch_reply.reply = false;
punch_reply.virtual_ip = u32::from_be_bytes(virtual_ip.octets());
punch_reply.step = protobuf::EnumOrUnknown::new(step);
punch_reply.public_ip_list = nat_info.public_ips;
punch_reply.public_port = nat_info.public_port as u32;
punch_reply.public_port_range = nat_info.public_port_range as u32;
punch_reply.nat_type = protobuf::EnumOrUnknown::new(nat_info.nat_type);
let bytes = punch_reply.write_to_bytes()?;
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + bytes.len()])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(turn_packet::Protocol::Punch.into());
net_packet.set_ttl(255);
let mut turn_packet = TurnPacket::new(net_packet.payload_mut())?;
turn_packet.set_source(virtual_ip);
turn_packet.set_destination(dest);
turn_packet.set_payload(&bytes);
Ok(net_packet.into_buffer())
}
+118
View File
@@ -0,0 +1,118 @@
use std::io;
use std::net::{SocketAddr, UdpSocket};
use std::sync::atomic::{AtomicI64, Ordering};
use std::time::Duration;
use chrono::Local;
use crossbeam::atomic::AtomicCell;
use parking_lot::RwLock;
use protobuf::Message;
use crate::error::*;
use crate::handle::ConnectStatus;
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
use crate::protocol::{error_packet, NetPacket, Protocol, service_packet, Version};
lazy_static::lazy_static! {
static ref REQUEST:RwLock<Option<(String,String)>> = parking_lot::const_rwlock(None);
static ref REGISTRATION_TIME:AtomicI64=AtomicI64::new(0);
pub(crate) static ref CONNECTION_STATUS:AtomicCell<ConnectStatus> = AtomicCell::new(ConnectStatus::Connecting);
}
///向中继服务器注册,token标识一个虚拟网关,mac_address防止多次注册时得到的ip不一致
pub fn registration(
udp: &UdpSocket,
server_address: SocketAddr,
token: String,
mac_address: String,
) -> Result<RegistrationResponse> {
// todo 和服务器通信加密
let request_packet = registration_request_packet(token.clone(), mac_address.clone())?;
let buf = request_packet.buffer();
let mut counter = 0;
let mut recv_buf = [0u8; 10240];
udp.set_read_timeout(Some(Duration::from_millis(500)))?;
loop {
counter += 1;
if counter & 10 == 10 {
return Err(Error::Stop("注册请求超时".to_string()));
}
udp.send_to(buf, server_address)?;
let (len, addr) = match udp.recv_from(&mut recv_buf) {
Ok(ok) => ok,
Err(e) => {
if e.kind() == io::ErrorKind::WouldBlock || e.kind() == io::ErrorKind::TimedOut {
continue;
}
return Err(Error::Io(e));
}
};
if server_address != addr {
continue;
}
let net_packet = NetPacket::new(&recv_buf[..len])?;
match net_packet.protocol() {
Protocol::Service => {
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationResponse => {
let response =
RegistrationResponse::parse_from_bytes(net_packet.payload())?;
let _ = REQUEST.write().replace((token, mac_address));
udp.set_read_timeout(None)?;
CONNECTION_STATUS.store(ConnectStatus::Connected);
return Ok(response);
}
_ => {}
}
}
Protocol::Error => {
match error_packet::Protocol::from(net_packet.transport_protocol()) {
error_packet::Protocol::TokenError => {
return Err(Error::Stop("token错误".to_string()));
}
_ => {}
}
}
_ => {}
}
}
}
fn registration_request_packet(token: String, mac_address: String) -> Result<NetPacket<Vec<u8>>> {
let mut request = RegistrationRequest::new();
request.token = token;
request.mac_address = mac_address;
let bytes = request.write_to_bytes()?;
let buf = vec![0u8; 4 + bytes.len()];
let mut net_packet = NetPacket::new(buf)?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Service);
net_packet.set_transport_protocol(service_packet::Protocol::RegistrationRequest.into());
net_packet.set_ttl(255);
net_packet.set_payload(&bytes);
Ok(net_packet)
}
pub fn fast_registration(udp: &UdpSocket, server_address: SocketAddr) -> Result<()> {
let last = REGISTRATION_TIME.load(Ordering::Relaxed);
let new = Local::now().timestamp_millis();
if new - last < 2000
|| REGISTRATION_TIME
.compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed)
.is_err()
{
//短时间不重复注册
return Ok(());
}
CONNECTION_STATUS.store(ConnectStatus::Connecting);
let lock = REQUEST.read();
let option = lock.clone();
drop(lock);
if let Some((token, mac_address)) = option {
let request_packet = registration_request_packet(token, mac_address)?;
udp.send_to(request_packet.buffer(), server_address)?;
REGISTRATION_TIME.store(Local::now().timestamp_millis(), Ordering::Relaxed);
return Ok(());
}
return Err(Error::Stop("注册信息不存在".to_string()));
}
+178
View File
@@ -0,0 +1,178 @@
/// 接收tun数据,并且转发到udp上
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::os::fd::AsRawFd;
use std::thread;
use chrono::Local;
use tokio::sync::watch;
use packet::icmp::icmp::IcmpPacket;
use packet::icmp::Kind;
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use crate::ApplicationStatus;
use crate::error::*;
use crate::handle::{CurrentDeviceInfo, DIRECT_ROUTE_TABLE};
use crate::protocol::{NetPacket, Protocol, Version};
use crate::protocol::turn_packet::TurnPacket;
use crate::tun_device::TunReader;
/// 是否在一个网段
fn check_dest(dest: Ipv4Addr, cur_info: &CurrentDeviceInfo) -> bool {
u32::from_be_bytes(dest.octets()) & u32::from_be_bytes(cur_info.virtual_netmask.octets())
== u32::from_be_bytes(cur_info.virtual_network.octets())
}
fn icmp(udp: &UdpSocket, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
if ipv4_packet.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp = IcmpPacket::new(ipv4_packet.payload_mut())?;
if icmp.kind() == Kind::EchoRequest {
icmp.set_kind(Kind::EchoReply);
icmp.update_checksum();
let src = ipv4_packet.source_ip();
ipv4_packet.set_source_ip(ipv4_packet.destination_ip());
ipv4_packet.set_destination_ip(src);
ipv4_packet.update_checksum();
let mut addr = udp.local_addr()?;
addr.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
udp.send_to(ipv4_packet.buffer, addr)?;
}
}
Ok(())
}
#[inline]
fn handle(
udp: &UdpSocket,
data: &mut [u8],
cur_info: &CurrentDeviceInfo,
net_packet: &mut NetPacket<Vec<u8>>,
) -> Result<()> {
let data_len = data.len();
let ipv4_packet = match IpV4Packet::new(data) {
Ok(ipv4_packet) => ipv4_packet,
Err(packet::error::Error::Unimplemented) => {
return Ok(());
}
Err(e) => Err(e)?,
};
let src_ip = ipv4_packet.source_ip();
let dest_ip = ipv4_packet.destination_ip();
// if dest_ip == cur_info.broadcast_address {
// // 启动服务后会收到对137端口的广播
// // 137端口是在局域网中提供计算机的名字或IP地址查询服务
// return Ok(());
// }
if src_ip != cur_info.virtual_ip || !check_dest(dest_ip, &cur_info) {
return Ok(());
}
if src_ip == dest_ip {
return icmp(&udp, ipv4_packet);
}
let mut ipv4_turn_packet = TurnPacket::new(net_packet.payload_mut())?;
ipv4_turn_packet.set_source(src_ip);
ipv4_turn_packet.set_destination(dest_ip);
ipv4_turn_packet.set_payload(ipv4_packet.buffer);
//优先发到直连到地址
if let Some(route) = DIRECT_ROUTE_TABLE.get(&dest_ip) {
let current_time = Local::now().timestamp_millis();
if current_time - route.recv_time < 3_000 {
if udp.send_to(&net_packet.buffer()[..(4 + 8 + data_len)], route.address).is_ok() {
return Ok(());
}
}
}
udp.send_to(&net_packet.buffer()[..(4 + 8 + data_len)], cur_info.connect_server)?;
return Ok(());
}
#[cfg(target_os = "windows")]
pub async fn handler_start<F>(mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
tun_reader: TunReader,
cur_info: CurrentDeviceInfo, stop_fn: F)
where F: FnOnce() + Send + 'static {
let session = tun_reader.0.clone();
tokio::spawn(async move {
let _ = status_watch.changed().await;
session.shutdown();
let udp = UdpSocket::bind("0.0.0.0:0").unwrap();
let _ = udp.send_to(&[0],SocketAddr::new(IpAddr::V4(cur_info.virtual_gateway),10));
});
thread::spawn(move || {
if let Err(e) = handle_loop(udp, tun_reader, cur_info) {
log::error!("tun数据处理线程停止 {:?}",e);
}
stop_fn();
});
}
#[cfg(target_os = "windows")]
fn handle_loop(
udp: UdpSocket,
tun_reader: TunReader,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(ipv4::protocol::Protocol::Ipv4.into());
net_packet.set_ttl(255);
loop {
let mut data = tun_reader.next()?;
match handle(&udp, data.bytes_mut(), &cur_info, &mut net_packet) {
Ok(_) => {}
Err(e) => {
println!("{:?}", e)
}
}
}
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub async fn handler_start<F>(mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
tun_reader: TunReader,
cur_info: CurrentDeviceInfo, stop_fn: F)
where F: FnOnce() + Send + 'static {
let raw_fd = tun_reader.0.as_raw_fd();
tokio::spawn(async move {
let _ = status_watch.changed().await;
// 让tun接收线程关闭
unsafe {
libc::close(raw_fd);
}
let udp = UdpSocket::bind("0.0.0.0:0").unwrap();
let _ = udp.send_to(&[0],SocketAddr::new(IpAddr::V4(cur_info.virtual_gateway),10));
});
thread::spawn(move || {
if let Err(e) = handle_loop(udp, tun_reader, cur_info) {
log::error!(" tun数据处理线程停止 {:?}",e);
}
stop_fn();
});
}
#[cfg(any(target_os = "macos", target_os = "linux"))]
pub fn handle_loop(
udp: UdpSocket,
mut tun_reader: TunReader,
cur_info: CurrentDeviceInfo,
) -> Result<()> {
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + 1500])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::Ipv4Turn);
net_packet.set_transport_protocol(0);
net_packet.set_ttl(255);
let mut buf = [0u8; 1500];
loop {
let data = tun_reader.read(&mut buf)?;
match handle(&udp, data, &cur_info, &mut net_packet) {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e)
}
}
}
}
+372
View File
@@ -0,0 +1,372 @@
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::sync::atomic::Ordering;
use std::thread;
use chrono::Local;
use packet::icmp::{icmp, Kind};
use packet::ip::ipv4;
use packet::ip::ipv4::packet::IpV4Packet;
use protobuf::Message;
use tokio::sync::mpsc::{Receiver, Sender};
use tokio::sync::mpsc::error::TrySendError;
use tokio::sync::watch;
use crate::{ApplicationStatus, CurrentDeviceInfo};
use crate::error::*;
use crate::handle::{ADDR_TABLE, ConnectStatus, DEVICE_LIST, DIRECT_ROUTE_TABLE, NAT_INFO, Route, SERVER_RT};
use crate::handle::punch_handler::PunchSender;
use crate::handle::registration_handler::{CONNECTION_STATUS, fast_registration};
use crate::proto::message::{DeviceList, Punch, RegistrationResponse};
use crate::protocol::{control_packet, NetPacket, Protocol, service_packet, turn_packet, Version};
use crate::protocol::control_packet::{ControlPacket, PunchResponsePacket};
use crate::protocol::error_packet::InErrorPacket;
use crate::protocol::turn_packet::TurnPacket;
use crate::tun_device::TunWriter;
const UDP_STOP_BUF: [u8; 1] = [0u8];
pub async fn udp_recv_start<F>(
mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
server_addr: SocketAddr,
other_sender: Sender<(SocketAddr, Vec<u8>)>,
mut tun_writer: TunWriter,
current_device: CurrentDeviceInfo,
stop_fn: F)
where F: FnOnce() + Send + 'static {
{
let udp = udp.try_clone().unwrap();
tokio::spawn(async move {
let _ = status_watch.changed().await;
let mut addr = udp.local_addr().unwrap();
addr.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
udp.send_to(&UDP_STOP_BUF, addr).unwrap();
});
}
thread::spawn(move || {
if let Err(e) = recv_loop(
udp,
server_addr,
other_sender,
tun_writer,
current_device,
) {
log::error!("udp数据处理线程停止 {:?}",e);
}
stop_fn();
});
}
fn recv_loop(
udp: UdpSocket,
server_addr: SocketAddr,
other_sender: Sender<(SocketAddr, Vec<u8>)>,
mut tun_writer: TunWriter,
current_device: CurrentDeviceInfo,
) -> Result<()> {
let mut buf = [0u8; 65536];
let mut local_addr = udp.local_addr()?;
local_addr.set_ip(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
loop {
match udp.recv_from(&mut buf) {
Ok((len, addr)) => {
if addr == local_addr {
if len == 1 && &buf[..len] == &UDP_STOP_BUF {
return Ok(());
}
//本地的包直接再发到网卡,这个主要用于处理当前虚拟ip的icmp ping
if let Ok(ip) = IpV4Packet::new(&buf[..len]) {
if ip.destination_ip() == current_device.virtual_ip {
let _ = tun_writer.write(&buf[..len]);
}
}
continue;
}
match recv_handle(
&udp,
addr,
&mut buf[..len],
&server_addr,
&other_sender,
&mut tun_writer,
&current_device,
) {
Ok(_) => {}
Err(Error::Stop(str)) => {
return Err(Error::Stop(str));
}
Err(e) => {
log::error!("{:?}",e);
}
}
}
Err(e) => {
log::error!("{:?}",e);
}
};
}
}
fn recv_handle(
udp: &UdpSocket,
recv_addr: SocketAddr,
buf: &mut [u8],
_server_addr: &SocketAddr,
other_sender: &Sender<(SocketAddr, Vec<u8>)>,
tun_writer: &mut TunWriter,
current_device: &CurrentDeviceInfo,
) -> Result<()> {
let mut net_packet = NetPacket::new(buf)?;
match net_packet.protocol() {
Protocol::Ipv4Turn => {
let mut ipv4_turn_packet = TurnPacket::new(net_packet.payload_mut())?;
let source = ipv4_turn_packet.source();
let destination = ipv4_turn_packet.destination();
let mut ipv4 = IpV4Packet::new(ipv4_turn_packet.payload_mut())?;
if ipv4.source_ip() == source
&& ipv4.destination_ip() == destination
&& current_device.virtual_ip == ipv4.destination_ip()
{
if ipv4.protocol() == ipv4::protocol::Protocol::Icmp {
let mut icmp_packet = icmp::IcmpPacket::new(ipv4.payload_mut())?;
if icmp_packet.kind() == Kind::EchoRequest {
//开启ping
icmp_packet.set_kind(Kind::EchoReply);
icmp_packet.update_checksum();
ipv4.set_source_ip(destination);
ipv4.set_destination_ip(source);
ipv4.update_checksum();
ipv4_turn_packet.set_source(destination);
ipv4_turn_packet.set_destination(source);
udp.send_to(net_packet.buffer(), recv_addr)?;
} else {
tun_writer.write(ipv4_turn_packet.payload())?;
}
} else {
tun_writer.write(ipv4_turn_packet.payload())?;
}
}
}
Protocol::UnKnow(_) => {}
_ => {
//发送到子线程处理
let v = net_packet.buffer().to_vec();
match other_sender.try_send((recv_addr, v)) {
Ok(_) => {}
Err(TrySendError::Closed(_)) => {
return Err(Error::Stop("子处理线程停止".to_string()));
}
Err(e) => {
log::error!("子线程处理 {:?}",e);
}
}
}
}
Ok(())
}
pub async fn udp_other_recv_start<F>(status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
receiver: Receiver<(SocketAddr, Vec<u8>)>,
current_device: CurrentDeviceInfo,
sender: PunchSender,
stop_fn: F) where F: FnOnce() + Send + 'static {
tokio::spawn(async move {
match other_loop(status_watch, udp, receiver, current_device, sender).await {
Ok(_) => {}
Err(e) => {
log::error!("{:?}",e);
}
}
stop_fn();
});
}
async fn other_loop(
mut status_watch: watch::Receiver<ApplicationStatus>,
udp: UdpSocket,
mut receiver: Receiver<(SocketAddr, Vec<u8>)>,
current_device: CurrentDeviceInfo,
sender: PunchSender,
) -> Result<()> {
loop {
tokio::select! {
rs = receiver.recv()=>{
if let Some((peer_addr, buf)) = rs {
match other_handle(&udp, buf, peer_addr, &current_device, &sender) {
Ok(_) => {}
Err(Error::Stop(str)) => {
return Err(Error::Stop(str));
}
Err(e) => {
log::error!("other_loop {:?}",e);
}
}
}
}
status = status_watch.changed() =>{
status?;
if *status_watch.borrow() != ApplicationStatus::Starting{
return Ok(())
}
}
}
}
}
fn other_handle(
udp: &UdpSocket,
buf: Vec<u8>,
peer_addr: SocketAddr,
current_device: &CurrentDeviceInfo,
sender: &PunchSender,
) -> Result<()> {
let server_addr = current_device.connect_server;
let mut net_packet = NetPacket::new(buf)?;
match net_packet.protocol() {
Protocol::Service => {
if peer_addr != current_device.connect_server {
return Ok(());
}
match service_packet::Protocol::from(net_packet.transport_protocol()) {
service_packet::Protocol::RegistrationRequest => {}
service_packet::Protocol::RegistrationResponse => {
let response = RegistrationResponse::parse_from_bytes(net_packet.payload())?;
crate::handle::init_nat_info(response.public_ip, response.public_port as u16);
CONNECTION_STATUS.store(ConnectStatus::Connected);
//todo 重连之后ip可能会发生改变(目前2分钟内未重连则会释放ip),需要更新本地ip(或者保证重连ip不变)
}
service_packet::Protocol::UpdateDeviceList => {
let device_list = DeviceList::parse_from_bytes(net_packet.payload())?;
let ip_list: Vec<Ipv4Addr> = device_list
.virtual_ip_list
.iter()
.map(|ip| Ipv4Addr::from(*ip))
.collect();
let mut dev = DEVICE_LIST.lock();
if dev.0 < device_list.epoch || device_list.epoch - dev.0 > u32::MAX >> 2 {
dev.0 = device_list.epoch;
dev.1 = ip_list;
}
}
service_packet::Protocol::UnKnow(_) => {}
}
}
Protocol::Error => {
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
InErrorPacket::TokenError => {
if server_addr == peer_addr {
//停止整个应用
return Err(Error::Stop("token无效".to_string()));
}
}
InErrorPacket::Disconnect => {
if server_addr == peer_addr {
fast_registration(&udp, server_addr)?;
}
}
InErrorPacket::OtherError(e) => {
log::error!("OtherError {:?}",e.message());
}
}
}
Protocol::Control => {
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
ControlPacket::PingPacket(ping) => {
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
udp.send_to(&net_packet.buffer()[..12], peer_addr)?;
}
ControlPacket::PongPacket(pong_packet) => {
let current_time = Local::now().timestamp_millis();
let rt = current_time - pong_packet.time();
if rt >= 0 {
if peer_addr == server_addr {
SERVER_RT.store(rt, Ordering::Relaxed)
} else {
//其他设备
if let Some(virtual_ip) = ADDR_TABLE.get(&peer_addr) {
if let Some(mut info) = DIRECT_ROUTE_TABLE.get_mut(&virtual_ip) {
info.rt = rt;
info.recv_time = current_time;
}
}
}
}
}
ControlPacket::PunchRequest(punch_request) => {
// println!("打洞请求:{:?}", punch_request);
let src = punch_request.source();
drop(punch_request);
//回应
let mut punch_response = PunchResponsePacket::new(net_packet.payload_mut())?;
punch_response.set_source(current_device.virtual_ip);
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
udp.send_to(net_packet.buffer(), peer_addr)?;
let route = Route::new(peer_addr);
DIRECT_ROUTE_TABLE.insert(src, route);
ADDR_TABLE.insert(peer_addr, src);
}
ControlPacket::PunchResponse(punch_response) => {
// println!("打洞响应:{:?}", punch_response);
let route = Route::new(peer_addr);
DIRECT_ROUTE_TABLE.insert(punch_response.source(), route);
ADDR_TABLE.insert(peer_addr, punch_response.source());
}
}
}
Protocol::Ipv4Turn => {}
Protocol::OtherTurn => {
let turn_packet = TurnPacket::new(net_packet.payload())?;
// println!("{:?}",turn_packet);
let src = turn_packet.source();
let dest = turn_packet.destination();
if dest == current_device.virtual_ip {
match turn_packet::Protocol::from(net_packet.transport_protocol()) {
turn_packet::Protocol::Punch => {
let punch = Punch::parse_from_bytes(turn_packet.payload())?;
if punch.virtual_ip.to_be_bytes() == src.octets() {
if !punch.reply {
let mut punch_reply = Punch::new();
punch_reply.reply = true;
punch_reply.virtual_ip = u32::from_be_bytes(current_device.virtual_ip.octets());
punch_reply.step = punch.step;
if let Err(_) = sender.try_send(punch) {
return Ok(());
}
let nat_info = NAT_INFO.lock();
if let Some(info) = nat_info.as_ref() {
punch_reply.public_ip_list = info.public_ips.clone();
punch_reply.public_port = info.public_port as u32;
punch_reply.public_port_range = info.public_port_range as u32;
punch_reply.nat_type = protobuf::EnumOrUnknown::new(info.nat_type);
drop(nat_info);
let bytes = punch_reply.write_to_bytes()?;
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + bytes.len()])?;
net_packet.set_version(Version::V1);
net_packet.set_protocol(Protocol::OtherTurn);
net_packet.set_transport_protocol(turn_packet::Protocol::Punch.into());
net_packet.set_ttl(255);
let mut turn_packet = TurnPacket::new(net_packet.payload_mut())?;
turn_packet.set_source(current_device.virtual_ip);
turn_packet.set_destination(src);
turn_packet.set_payload(&bytes);
udp.send_to(net_packet.buffer(), peer_addr)?;
}
} else {
let _ = sender.try_send(punch);
}
}
}
turn_packet::Protocol::UnKnow(_) => {}
}
} else {
panic!("ip")
}
}
Protocol::UnKnow(p) => {
log::error!("未知协议 {}",p);
}
}
Ok(())
}