v1.1
This commit is contained in:
@@ -1,80 +1,104 @@
|
||||
use std::net::{SocketAddr, UdpSocket};
|
||||
use std::{io, thread};
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use chrono::Local;
|
||||
use tokio::sync::watch::Receiver;
|
||||
use tokio::time::sleep;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use parking_lot::Mutex;
|
||||
use rand::prelude::SliceRandom;
|
||||
use nat_traversal::channel::Route;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE};
|
||||
use nat_traversal::channel::sender::Sender;
|
||||
use nat_traversal::idle::Idle;
|
||||
|
||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, Version};
|
||||
use crate::protocol::control_packet::PingPacket;
|
||||
use crate::protocol::{control_packet, NetPacket, Protocol, Version};
|
||||
use crate::{CurrentDeviceInfo, DEVICE_LIST};
|
||||
|
||||
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::warn!("{:?}", e)
|
||||
}
|
||||
pub fn start_idle(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = start_idle_(idle, sender) {
|
||||
log::info!("空闲检测线程停止:{:?}",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)?;
|
||||
fn start_idle_(idle: Idle<Ipv4Addr>, sender: Sender<Ipv4Addr>) -> io::Result<()> {
|
||||
loop {
|
||||
let (idle_status, peer_ip, route) = idle.next_idle()?;
|
||||
log::warn!("peer_ip:{:?},route:{:?},idle_status:{:?}",peer_ip,route,idle_status);
|
||||
sender.remove_route(&peer_ip);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_heartbeat(sender: Sender<Ipv4Addr>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = start_heartbeat_(sender, device_list, current_device) {
|
||||
log::info!("空闲检测线程停止:{:?}",e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn start_heartbeat_(sender: Sender<Ipv4Addr>, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<()> {
|
||||
let mut net_packet = NetPacket::new([0u8; 16])?;
|
||||
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);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
let mut count = 0;
|
||||
loop {
|
||||
let current_time = Local::now().timestamp_millis();
|
||||
let current_device = current_device.load();
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
{
|
||||
let current_time = Local::now().timestamp_millis() as u16;
|
||||
let mut ping = PingPacket::new(net_packet.payload_mut())?;
|
||||
ping.set_time(current_time);
|
||||
let epoch = { DEVICE_LIST.lock().0 };
|
||||
let epoch = { device_list.lock().0 };
|
||||
ping.set_epoch(epoch);
|
||||
}
|
||||
let _ = udp.send_to(net_packet.buffer(), server_addr);
|
||||
// 不clone会死锁?
|
||||
for x in DIRECT_ROUTE_TABLE.clone().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
|
||||
});
|
||||
if count % 7 == 0 {
|
||||
let mut route_list: Option<Vec<(Ipv4Addr, Route)>> = None;
|
||||
let peer_list = device_list.lock().1.clone();
|
||||
for peer in peer_list {
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_destination(peer.virtual_ip);
|
||||
if sender.send_to_id(net_packet.buffer(), &peer.virtual_ip).is_err() {
|
||||
//没有路由则发送到网关
|
||||
let _ = sender.send_to_addr(net_packet.buffer(), current_device.connect_server);
|
||||
//再随机发送到其他地址,看有没有客户端符合转发条件
|
||||
let route_list = route_list.get_or_insert_with(|| {
|
||||
let mut l = sender.route_list();
|
||||
l.shuffle(&mut rand::thread_rng());
|
||||
l
|
||||
});
|
||||
let mut num = 0;
|
||||
net_packet.first_set_ttl(2);
|
||||
for (peer_ip, route) in route_list.iter() {
|
||||
if peer_ip != &peer.virtual_ip && route.metric == 1 {
|
||||
let _ = sender.send_to_route(net_packet.buffer(), &route.route_key());
|
||||
num += 1;
|
||||
}
|
||||
if num >= 3 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
tokio::select! {
|
||||
_ = sleep(Duration::from_millis(INTERVAL))=>{
|
||||
|
||||
net_packet.set_destination(current_device.virtual_gateway());
|
||||
if let Err(e) = sender.send_to_addr(net_packet.buffer(), current_device.connect_server) {
|
||||
log::warn!("connect_server:{:?},e:{:?}",current_device.connect_server,e);
|
||||
}
|
||||
status = status_watch.changed() =>{
|
||||
status?;
|
||||
if *status_watch.borrow() != ApplicationStatus::Starting{
|
||||
return Ok(())
|
||||
} else {
|
||||
for (peer_ip, route) in sender.route_list().iter() {
|
||||
net_packet.set_destination(*peer_ip);
|
||||
if let Err(e) = sender.send_to_route(net_packet.buffer(), &route.route_key()) {
|
||||
log::warn!("peer_ip:{:?},route:{:?},e:{:?}",peer_ip,route,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count += 1;
|
||||
thread::sleep(Duration::from_secs(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
-131
@@ -1,38 +1,17 @@
|
||||
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<PeerDeviceInfo>)> = 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);
|
||||
static ref NAT_TEST_ADDRESS:Mutex<Vec<SocketAddr>> = const_mutex(Vec::new());
|
||||
pub mod recv_handler;
|
||||
|
||||
/// 是否在一个网段
|
||||
fn check_dest(dest: Ipv4Addr, virtual_netmask: Ipv4Addr, virtual_network: Ipv4Addr) -> bool {
|
||||
u32::from_be_bytes(dest.octets()) & u32::from_be_bytes(virtual_netmask.octets())
|
||||
== u32::from_be_bytes(virtual_network.octets())
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct PeerDeviceInfo {
|
||||
pub virtual_ip: Ipv4Addr,
|
||||
@@ -74,82 +53,15 @@ impl From<u8> for PeerDeviceStatus {
|
||||
}
|
||||
}
|
||||
|
||||
#[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 {
|
||||
pub public_ips: Vec<u32>,
|
||||
pub public_port: u16,
|
||||
pub public_port_range: u16,
|
||||
pub 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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_nat_test_addr(addrs: Vec<SocketAddr>) {
|
||||
NAT_TEST_ADDRESS.lock().extend_from_slice(&addrs);
|
||||
}
|
||||
|
||||
/// 初始化nat信息
|
||||
pub fn init_nat_info(public_ip: u32, public_port: u16) {
|
||||
let addrs = NAT_TEST_ADDRESS.lock().clone();
|
||||
match crate::nat::check::public_ip_list(&addrs) {
|
||||
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)]
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub struct CurrentDeviceInfo {
|
||||
pub virtual_ip: Ipv4Addr,
|
||||
virtual_ip: Ipv4Addr,
|
||||
pub virtual_gateway: Ipv4Addr,
|
||||
pub virtual_netmask: Ipv4Addr,
|
||||
//网络地址
|
||||
@@ -182,40 +94,16 @@ impl CurrentDeviceInfo {
|
||||
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,
|
||||
}
|
||||
#[inline]
|
||||
pub fn virtual_ip(&self) -> Ipv4Addr {
|
||||
self.virtual_ip
|
||||
}
|
||||
#[inline]
|
||||
pub fn virtual_gateway(&self) -> Ipv4Addr {
|
||||
self.virtual_gateway
|
||||
}
|
||||
}
|
||||
|
||||
impl Route {
|
||||
pub fn new(address: SocketAddr) -> Self {
|
||||
Self {
|
||||
route_type: RouteType::P2P,
|
||||
address,
|
||||
rt: -1,
|
||||
recv_time: Local::now().timestamp_millis(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+113
-375
@@ -1,402 +1,140 @@
|
||||
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket};
|
||||
use std::time::Duration;
|
||||
use std::{io, thread};
|
||||
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use parking_lot::Mutex;
|
||||
use protobuf::Message;
|
||||
use rand::prelude::SliceRandom;
|
||||
use tokio::sync::mpsc::error::TrySendError;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::watch;
|
||||
use nat_traversal::channel::sender::Sender;
|
||||
use nat_traversal::punch::{NatInfo, NatType, Punch};
|
||||
use crate::handle::{CurrentDeviceInfo, PeerDeviceInfo};
|
||||
use crate::nat::NatTest;
|
||||
use crate::proto::message::{PunchInfo, PunchNatType};
|
||||
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, turn_packet, Version};
|
||||
|
||||
use crate::error::*;
|
||||
use crate::handle::{ApplicationStatus, DIRECT_ROUTE_TABLE};
|
||||
use crate::proto::message::{NatType, Punch};
|
||||
use crate::protocol::control_packet::PunchRequestPacket;
|
||||
use crate::protocol::turn_packet::TurnPacket;
|
||||
use crate::protocol::{control_packet, turn_packet, NetPacket, Protocol, Version};
|
||||
use crate::{handle::NatInfo, handle::NAT_INFO, CurrentDeviceInfo, DEVICE_LIST};
|
||||
|
||||
/// 每一种类型一个通道,减少相互干扰
|
||||
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 start_cone(punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = start_(true, punch, current_device) {
|
||||
log::warn!("锥形网络打洞处理线程停止 {:?}",e);
|
||||
}
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn start_symmetric(punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = start_(false, punch, current_device) {
|
||||
log::warn!("对称网络打洞处理线程停止 {:?}",e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn start_(is_cone: bool, mut punch: Punch<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> io::Result<()> {
|
||||
let mut packet = NetPacket::new([0u8; 12])?;
|
||||
packet.set_version(Version::V1);
|
||||
packet.first_set_ttl(1);
|
||||
packet.set_protocol(Protocol::Control);
|
||||
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
|
||||
loop {
|
||||
let (peer_ip, nat_info) = if is_cone {
|
||||
punch.next_cone(None)?
|
||||
} else {
|
||||
punch.next_symmetric(None)?
|
||||
};
|
||||
if let Some(route) = punch.sender().route(&peer_ip) {
|
||||
if route.metric == 1 {
|
||||
//直连地址不需要打洞
|
||||
continue;
|
||||
}
|
||||
NatType::Cone => self.cone_sender.try_send(punch),
|
||||
}
|
||||
packet.set_source(current_device.load().virtual_ip());
|
||||
packet.set_destination(peer_ip);
|
||||
log::info!("发起打洞,目标:{:?},{:?}",peer_ip,nat_info);
|
||||
if let Err(e) = punch.punch(packet.buffer(), peer_ip, nat_info) {
|
||||
log::warn!("peer_ip:{:?},e:{:?}",peer_ip,e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
pub fn start_punch(nat_test: NatTest, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = start_punch_(nat_test, device_list, sender, current_device) {
|
||||
log::warn!("对称网络打洞处理线程停止 {:?}",e);
|
||||
}
|
||||
// println!("punch {:?}", punch);
|
||||
match punch.nat_type.enum_value_or_default() {
|
||||
NatType::Symmetric => {
|
||||
// 假设绑定n个端口,通过NAT对外映射出n个 公网ip:公网端口,随机尝试k次的情况下
|
||||
// 猜中的概率 p = 1-((65535-n)/65535)*((65535-n-1)/(65535-1))*...*((65535-n-k+1)/(65535-k+1))
|
||||
// n取76,k取600,猜中的概率就超过50%了
|
||||
// 前提 自己是锥形网络,否则猜中了也通信不了
|
||||
let mut send_f = |min_port: u16, max_port: u16, k: usize| -> io::Result<()> {
|
||||
let mut nums: Vec<u16> = (min_port..max_port).collect();
|
||||
nums.push(max_port);
|
||||
let mut rng = rand::thread_rng();
|
||||
nums.shuffle(&mut rng);
|
||||
for pub_ip in &punch.public_ip_list {
|
||||
let pub_ip = Ipv4Addr::from(*pub_ip);
|
||||
for port in &nums[..k] {
|
||||
udp.send_to(buf, SocketAddr::V4(SocketAddrV4::new(pub_ip, *port)))?;
|
||||
select_sleep(&mut counter);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
if punch.public_port_range < 600 {
|
||||
//端口变化不大时,在预测的范围内随机发送
|
||||
let min_port = if punch.public_port > punch.public_port_range {
|
||||
punch.public_port - punch.public_port_range
|
||||
} else {
|
||||
1
|
||||
};
|
||||
let max_port = if punch.public_port + punch.public_port_range > 65535 {
|
||||
65535
|
||||
} else {
|
||||
punch.public_port + punch.public_port_range
|
||||
};
|
||||
let k = if max_port - min_port + 1 > 60 {
|
||||
60
|
||||
} else {
|
||||
max_port - min_port + 1
|
||||
};
|
||||
send_f(min_port as u16, max_port as u16, k as usize)?;
|
||||
});
|
||||
}
|
||||
|
||||
fn start_punch_(nat_test: NatTest, device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>, sender: Sender<Ipv4Addr>, current_device: Arc<AtomicCell<CurrentDeviceInfo>>) -> crate::Result<()> {
|
||||
loop {
|
||||
if sender.is_close() {
|
||||
return Ok(());
|
||||
}
|
||||
let current_device = current_device.load();
|
||||
let nat_info = nat_test.nat_info();
|
||||
{
|
||||
let mut list = device_list.lock().clone().1;
|
||||
list.shuffle(&mut rand::thread_rng());
|
||||
let mut count = 0;
|
||||
for info in list {
|
||||
if info.virtual_ip <= current_device.virtual_ip {
|
||||
continue;
|
||||
}
|
||||
// 全端口范围,随机取600个端口发送
|
||||
send_f(1, 65535, 600)?;
|
||||
if let Some(route) = sender.route(&info.virtual_ip) {
|
||||
if route.metric == 1 {
|
||||
//直连地址不需要打洞
|
||||
continue;
|
||||
}
|
||||
}
|
||||
count += 1;
|
||||
if count > 3 {
|
||||
break;
|
||||
}
|
||||
let buf = punch_packet(current_device.virtual_ip(), &nat_info, info.virtual_ip)?;
|
||||
sender.send_to_addr(&buf, current_device.connect_server)?;
|
||||
}
|
||||
}
|
||||
match nat_info.nat_type {
|
||||
NatType::Symmetric => {
|
||||
thread::sleep(Duration::from_secs(28));
|
||||
}
|
||||
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::warn!("{:?}", 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::warn!("{:?}", 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);
|
||||
}
|
||||
loop {
|
||||
tokio::select! {
|
||||
rs = tokio::time::timeout(Duration::from_secs(20), 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Err(e) = handle(&status_watch,&udp, list, packet.buffer()) {
|
||||
log::warn!("{:?}",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(())
|
||||
}
|
||||
thread::sleep(Duration::from_secs(20));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 给锥形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::warn!("{:?}", 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::warn!("{:?}",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;
|
||||
if *counter & 10 == 10 {
|
||||
thread::sleep(Duration::from_millis(2));
|
||||
} else {
|
||||
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::warn!("发送打洞数据失败 {:?}", 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 peer_info in list {
|
||||
let ip = peer_info.virtual_ip;
|
||||
//只向ip比自己大的发起打洞,避免双方同时发起打洞浪费流量
|
||||
if ip > cur_info.virtual_ip && !DIRECT_ROUTE_TABLE.contains_key(&ip) {
|
||||
log::info!("发起打洞 {:?}, peer_info:{:?}", nat_info, peer_info);
|
||||
let bytes = punch_packet(cur_info.virtual_ip, nat_info.clone(), ip)?;
|
||||
udp.send_to(&bytes, cur_info.connect_server)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn punch_packet(virtual_ip: Ipv4Addr, nat_info: NatInfo, dest: Ipv4Addr) -> Result<Vec<u8>> {
|
||||
let mut punch_reply = Punch::new();
|
||||
pub fn punch_packet(virtual_ip: Ipv4Addr, nat_info: &NatInfo, dest: Ipv4Addr) -> crate::Result<Vec<u8>> {
|
||||
let mut punch_reply = PunchInfo::new();
|
||||
punch_reply.reply = false;
|
||||
punch_reply.virtual_ip = u32::from_be_bytes(virtual_ip.octets());
|
||||
punch_reply.public_ip_list = nat_info.public_ips;
|
||||
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|i| {
|
||||
match i {
|
||||
IpAddr::V4(ip) => {
|
||||
u32::from_be_bytes(ip.octets())
|
||||
}
|
||||
IpAddr::V6(_) => {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
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);
|
||||
punch_reply.local_ip = match nat_info.local_ip {
|
||||
IpAddr::V4(ip) => u32::from_be_bytes(ip.octets()),
|
||||
IpAddr::V6(_) => {
|
||||
panic!()
|
||||
}
|
||||
};
|
||||
punch_reply.local_port = nat_info.local_port as u32;
|
||||
punch_reply.nat_type = protobuf::EnumOrUnknown::new(PunchNatType::from(nat_info.nat_type));
|
||||
let bytes = punch_reply.write_to_bytes()?;
|
||||
let mut net_packet = NetPacket::new(vec![0u8; 4 + 8 + bytes.len()])?;
|
||||
let mut net_packet = NetPacket::new(vec![0u8; 12 + 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);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_source(virtual_ip);
|
||||
net_packet.set_destination(dest);
|
||||
net_packet.set_payload(&bytes);
|
||||
Ok(net_packet.into_buffer())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
use std::{io, thread};
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Local;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use crossbeam_skiplist::SkipMap;
|
||||
use parking_lot::Mutex;
|
||||
use protobuf::Message;
|
||||
|
||||
use nat_traversal::channel::{Channel, Route, RouteKey};
|
||||
use nat_traversal::punch::NatInfo;
|
||||
use packet::icmp::{icmp, Kind};
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::handle::{check_dest, ConnectStatus, CurrentDeviceInfo, PeerDeviceInfo};
|
||||
use crate::handle::registration_handler::Register;
|
||||
use crate::nat::NatTest;
|
||||
use crate::proto::message::{DeviceList, PunchInfo, PunchNatType, RegistrationResponse};
|
||||
use crate::protocol::{control_packet, MAX_TTL, NetPacket, Protocol, service_packet, turn_packet, Version};
|
||||
use crate::protocol::control_packet::ControlPacket;
|
||||
use crate::protocol::error_packet::InErrorPacket;
|
||||
use crate::tun_device::TunWriter;
|
||||
|
||||
pub fn start(mut handler: RecvHandler) {
|
||||
thread::spawn(move || {
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
match handler.channel.recv_from(&mut buf, None) {
|
||||
Ok((len, route)) => {
|
||||
if let Err(e) = handler.handle(&mut buf[..len], &route) {
|
||||
log::warn!("数据处理失败:{:?},e:{:?}",route,e);
|
||||
if let Error::Stop(_) = e {
|
||||
let _ = handler.channel.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}",e);
|
||||
// 检查关闭状态
|
||||
if handler.channel.is_close() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub struct RecvHandler {
|
||||
channel: Channel<Ipv4Addr>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
register: Arc<Register>,
|
||||
nat_test: NatTest,
|
||||
tun_writer: TunWriter,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
}
|
||||
|
||||
impl RecvHandler {
|
||||
pub fn new(channel: Channel<Ipv4Addr>,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||
device_list: Arc<Mutex<(u16, Vec<PeerDeviceInfo>)>>,
|
||||
register: Arc<Register>,
|
||||
nat_test: NatTest,
|
||||
tun_writer: TunWriter,
|
||||
connect_status: Arc<AtomicCell<ConnectStatus>>,
|
||||
peer_nat_info_map: Arc<SkipMap<Ipv4Addr, NatInfo>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
channel,
|
||||
current_device,
|
||||
device_list,
|
||||
register,
|
||||
nat_test,
|
||||
tun_writer,
|
||||
connect_status,
|
||||
peer_nat_info_map,
|
||||
}
|
||||
}
|
||||
pub fn try_clone(&self) -> io::Result<Self> {
|
||||
Ok(Self {
|
||||
channel: self.channel.try_clone()?,
|
||||
current_device: self.current_device.clone(),
|
||||
device_list: self.device_list.clone(),
|
||||
register: self.register.clone(),
|
||||
nat_test: self.nat_test.clone(),
|
||||
tun_writer: self.tun_writer.clone(),
|
||||
connect_status: self.connect_status.clone(),
|
||||
peer_nat_info_map: self.peer_nat_info_map.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl RecvHandler {
|
||||
fn handle(&self, buf: &mut [u8], route_key: &RouteKey) -> crate::Result<()> {
|
||||
let mut net_packet = NetPacket::new(buf)?;
|
||||
if net_packet.ttl() == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let source = net_packet.source();
|
||||
let current_device = self.current_device.load();
|
||||
if source == current_device.virtual_ip() {
|
||||
return Ok(());
|
||||
}
|
||||
let destination = net_packet.destination();
|
||||
if current_device.virtual_ip() != destination && self.connect_status.load() == ConnectStatus::Connected {
|
||||
if !check_dest(source, current_device.virtual_netmask, current_device.virtual_network) {
|
||||
log::warn!("转发数据,源地址错误:{:?},当前网络:{:?},route_key:{:?}",source,current_device.virtual_network,route_key);
|
||||
return Ok(());
|
||||
}
|
||||
if !check_dest(destination, current_device.virtual_netmask, current_device.virtual_network) {
|
||||
log::warn!("转发数据,目的地址错误:{:?},当前网络:{:?},route_key:{:?}",destination,current_device.virtual_network,route_key);
|
||||
return Ok(());
|
||||
}
|
||||
let ttl = net_packet.ttl();
|
||||
if ttl > 1 {
|
||||
// 转发
|
||||
net_packet.set_ttl(ttl - 1);
|
||||
if let Some(route) = self.channel.route(&destination) {
|
||||
if route.metric <= net_packet.ttl() {
|
||||
self.channel.send_to_route(net_packet.buffer(), &route.route_key())?;
|
||||
}
|
||||
} else if (ttl > 2 || destination == current_device.virtual_gateway())
|
||||
&& source != current_device.virtual_gateway() {
|
||||
//网关默认要转发一次,生存时间不够的发到网关也会被丢弃
|
||||
self.channel.send_to_addr(net_packet.buffer(), current_device.connect_server)?;
|
||||
}
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
match net_packet.protocol() {
|
||||
Protocol::Ipv4Turn => {
|
||||
let mut ipv4 = IpV4Packet::new(net_packet.payload_mut())?;
|
||||
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();
|
||||
net_packet.set_source(destination);
|
||||
net_packet.set_destination(source);
|
||||
self.channel.send_to_route(net_packet.buffer(), route_key)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
self.tun_writer.write(net_packet.payload())?;
|
||||
}
|
||||
Protocol::Service => {
|
||||
self.service(current_device, source, net_packet, route_key)?;
|
||||
}
|
||||
Protocol::Error => {
|
||||
self.error(current_device, source, net_packet, route_key)?;
|
||||
}
|
||||
Protocol::Control => {
|
||||
self.control(current_device, source, net_packet, route_key)?;
|
||||
}
|
||||
Protocol::OtherTurn => {
|
||||
self.other_turn(current_device, source, net_packet, route_key)?;
|
||||
}
|
||||
Protocol::UnKnow(e) => {
|
||||
log::info!("不支持的协议:{}",e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn service(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
if route_key.addr != current_device.connect_server || source != current_device.virtual_gateway() {
|
||||
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())?;
|
||||
let local_addr = self.channel.local_addr()?;
|
||||
let local_ip = if local_addr.ip().is_unspecified() {
|
||||
local_ip_address::local_ip().unwrap_or(local_addr.ip())
|
||||
} else {
|
||||
local_addr.ip()
|
||||
};
|
||||
let nat_info = self.nat_test.re_test(Ipv4Addr::from(response.public_ip), response.public_port as u16, local_ip, local_addr.port());
|
||||
self.channel.set_nat_type(nat_info.nat_type)?;
|
||||
let new_ip = Ipv4Addr::from(response.virtual_ip);
|
||||
let current_ip = current_device.virtual_ip();
|
||||
if current_ip != new_ip {
|
||||
// ip发生变化
|
||||
log::info!("ip发生变化,old_ip:{:?},new_ip:{:?}",current_ip,new_ip);
|
||||
let old_netmask = current_device.virtual_netmask;
|
||||
let old_gateway = current_device.virtual_gateway();
|
||||
let virtual_ip = Ipv4Addr::from(response.virtual_ip);
|
||||
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
|
||||
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
|
||||
self.tun_writer.change_ip(virtual_ip, virtual_netmask, virtual_gateway, old_netmask, old_gateway)?;
|
||||
let new_current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway,
|
||||
virtual_netmask, current_device.connect_server);
|
||||
if let Err(e) = self.current_device.compare_exchange(current_device, new_current_device) {
|
||||
log::warn!("替换失败:{:?}",e);
|
||||
}
|
||||
}
|
||||
self.connect_status.store(ConnectStatus::Connected);
|
||||
}
|
||||
service_packet::Protocol::PollDeviceList => {}
|
||||
service_packet::Protocol::PushDeviceList => {
|
||||
let device_list_t = DeviceList::parse_from_bytes(net_packet.payload())?;
|
||||
let ip_list = device_list_t
|
||||
.device_info_list
|
||||
.into_iter()
|
||||
.map(|info| {
|
||||
PeerDeviceInfo::new(
|
||||
Ipv4Addr::from(info.virtual_ip),
|
||||
info.name,
|
||||
info.device_status as u8,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
let mut dev = self.device_list.lock();
|
||||
if dev.0 < device_list_t.epoch as u16 || device_list_t.epoch as u16 - dev.0 > u16::MAX >> 2 {
|
||||
dev.0 = device_list_t.epoch as u16;
|
||||
dev.1 = ip_list;
|
||||
}
|
||||
}
|
||||
service_packet::Protocol::UnKnow(u) => {
|
||||
log::warn!("未知服务协议:{}",u);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn error(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
if route_key.addr != current_device.connect_server || source != current_device.virtual_gateway() {
|
||||
return Ok(());
|
||||
}
|
||||
match InErrorPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||
InErrorPacket::TokenError => {
|
||||
return Err(Error::Stop("Token error".to_string()));
|
||||
}
|
||||
InErrorPacket::Disconnect => {
|
||||
self.connect_status.store(ConnectStatus::Connecting);
|
||||
self.register.fast_register()?;
|
||||
}
|
||||
InErrorPacket::AddressExhausted => {
|
||||
//地址用尽
|
||||
return Err(Error::Stop("IP address has been exhausted".to_string()));
|
||||
}
|
||||
InErrorPacket::OtherError(e) => {
|
||||
log::error!("OtherError {:?}", e.message());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn control(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, mut net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
match ControlPacket::new(net_packet.transport_protocol(), net_packet.payload())? {
|
||||
ControlPacket::PingPacket(_) => {
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::Pong.into());
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.first_set_ttl(MAX_TTL);
|
||||
self.channel.send_to_route(net_packet.buffer(), route_key)?;
|
||||
}
|
||||
ControlPacket::PongPacket(pong_packet) => {
|
||||
let current_time = Local::now().timestamp_millis() as u16;
|
||||
if current_time < pong_packet.time() {
|
||||
return Ok(());
|
||||
}
|
||||
let rt = (current_time - pong_packet.time()) as i64;
|
||||
let metric = net_packet.source_ttl() - net_packet.ttl() + 1;
|
||||
if let Some(current_route) = self.channel.route(&source) {
|
||||
if ¤t_route.route_key() == route_key {
|
||||
self.channel.update_route(&source, metric, rt);
|
||||
} else if current_route.metric >= metric && current_route.rt > rt {
|
||||
let route = Route::from(*route_key, metric, rt);
|
||||
self.channel.add_route(source, route);
|
||||
}
|
||||
} else {
|
||||
let route = Route::from(*route_key, metric, rt);
|
||||
self.channel.add_route(source, route);
|
||||
}
|
||||
if route_key.addr == current_device.connect_server && source == current_device.virtual_gateway() {
|
||||
let epoch = self.device_list.lock().0;
|
||||
if pong_packet.epoch() != epoch {
|
||||
let mut poll_device = NetPacket::new([0; 12])?;
|
||||
poll_device.set_source(current_device.virtual_ip());
|
||||
poll_device.set_destination(source);
|
||||
poll_device.set_version(Version::V1);
|
||||
poll_device.first_set_ttl(MAX_TTL);
|
||||
poll_device.set_protocol(Protocol::Service);
|
||||
poll_device.set_transport_protocol(service_packet::Protocol::PollDeviceList.into());
|
||||
self.channel.send_to_route(poll_device.buffer(), route_key)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
ControlPacket::PunchRequest => {
|
||||
log::info!("PunchRequest route_key:{:?}",route_key);
|
||||
//回应
|
||||
net_packet.set_transport_protocol(control_packet::Protocol::PunchResponse.into());
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.first_set_ttl(1);
|
||||
self.channel.send_to_route(net_packet.buffer(), route_key)?;
|
||||
let route = Route::from(*route_key, 1, -1);
|
||||
self.channel.add_route(source, route);
|
||||
}
|
||||
ControlPacket::PunchResponse => {
|
||||
log::info!("PunchResponse route_key:{:?}",route_key);
|
||||
let route = Route::from(*route_key, 1, -1);
|
||||
self.channel.add_route(net_packet.source(), route);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn other_turn(&self, current_device: CurrentDeviceInfo, source: Ipv4Addr, net_packet: NetPacket<&mut [u8]>, route_key: &RouteKey) -> crate::Result<()> {
|
||||
match turn_packet::Protocol::from(net_packet.transport_protocol()) {
|
||||
turn_packet::Protocol::Punch => {
|
||||
let punch_info = PunchInfo::parse_from_bytes(net_packet.payload())?;
|
||||
let public_ips = punch_info.public_ip_list.
|
||||
iter().map(|v| { IpAddr::from(v.to_be_bytes()) }).collect();
|
||||
let peer_nat_info = NatInfo::new(public_ips,
|
||||
punch_info.public_port as u16,
|
||||
punch_info.public_port_range as u16,
|
||||
IpAddr::from(punch_info.local_ip.to_be_bytes()),
|
||||
punch_info.local_port as u16,
|
||||
punch_info.nat_type.enum_value_or_default().into());
|
||||
self.peer_nat_info_map.insert(source, peer_nat_info.clone());
|
||||
if !punch_info.reply {
|
||||
let mut punch_reply = PunchInfo::new();
|
||||
punch_reply.reply = true;
|
||||
let nat_info = self.nat_test.nat_info();
|
||||
punch_reply.public_ip_list = nat_info.public_ips.iter().map(|i| {
|
||||
match i {
|
||||
IpAddr::V4(ip) => {
|
||||
u32::from_be_bytes(ip.octets())
|
||||
}
|
||||
IpAddr::V6(_) => {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
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(PunchNatType::from(nat_info.nat_type));
|
||||
let bytes = punch_reply.write_to_bytes()?;
|
||||
let mut net_packet =
|
||||
NetPacket::new(vec![0u8; 12 + 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.first_set_ttl(MAX_TTL);
|
||||
net_packet.set_source(current_device.virtual_ip());
|
||||
net_packet.set_destination(source);
|
||||
net_packet.set_payload(&bytes);
|
||||
if !peer_nat_info.local_ip.is_unspecified() {
|
||||
let mut packet = NetPacket::new([0u8; 12])?;
|
||||
packet.set_version(Version::V1);
|
||||
packet.first_set_ttl(1);
|
||||
packet.set_protocol(Protocol::Control);
|
||||
packet.set_transport_protocol(control_packet::Protocol::PunchRequest.into());
|
||||
packet.set_source(current_device.virtual_ip());
|
||||
packet.set_destination(source);
|
||||
let _ = self.channel.send_to_addr(packet.buffer(), SocketAddr::new(peer_nat_info.local_ip, peer_nat_info.local_port));
|
||||
}
|
||||
if let Err(e) = self.channel.punch(source, peer_nat_info) {
|
||||
log::warn!("发送到打洞通道失败 {:?}",e);
|
||||
return Ok(());
|
||||
}
|
||||
self.channel.send_to_route(net_packet.buffer(), route_key)?;
|
||||
} else {
|
||||
let _ = self.channel.punch(source, peer_nat_info);
|
||||
}
|
||||
}
|
||||
turn_packet::Protocol::UnKnow(e) => {
|
||||
log::warn!("不支持的转发协议 {:?},source:{:?}",e,source);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,139 +1,136 @@
|
||||
use std::io;
|
||||
use std::net::{SocketAddr, UdpSocket};
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
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 nat_traversal::channel::Channel;
|
||||
use nat_traversal::channel::sender::Sender;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::handle::ConnectStatus;
|
||||
use crate::proto::message::{RegistrationRequest, RegistrationResponse};
|
||||
use crate::protocol::error_packet::InErrorPacket;
|
||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version};
|
||||
use crate::protocol::{service_packet, NetPacket, Protocol, Version, MAX_TTL};
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref REQUEST:RwLock<Option<(String,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不一致
|
||||
///向中继服务器注册,token标识一个虚拟网关,device_id防止多次注册时得到的ip不一致
|
||||
pub fn registration(
|
||||
udp: &UdpSocket,
|
||||
channel: &mut Channel<Ipv4Addr>,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
mac_address: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
) -> Result<RegistrationResponse> {
|
||||
// todo 和服务器通信加密
|
||||
let request_packet =
|
||||
registration_request_packet(token.clone(), mac_address.clone(), name.clone(), false)?;
|
||||
registration_request_packet(token.clone(), device_id.clone(), name.clone(), false)?;
|
||||
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, name));
|
||||
udp.set_read_timeout(None)?;
|
||||
CONNECTION_STATUS.store(ConnectStatus::Connected);
|
||||
return Ok(response);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Protocol::Error => {
|
||||
return match InErrorPacket::new(
|
||||
net_packet.transport_protocol(),
|
||||
net_packet.payload(),
|
||||
) {
|
||||
Ok(e) => match e {
|
||||
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
|
||||
InErrorPacket::Disconnect => Err(Error::Stop("断开连接".to_string())),
|
||||
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
|
||||
InErrorPacket::OtherError(e) => match e.message() {
|
||||
Ok(str) => Err(Error::Stop(str)),
|
||||
Err(e) => Err(Error::Stop(format!("{:?}", e))),
|
||||
},
|
||||
},
|
||||
Err(e) => Err(Error::Stop(format!("{:?}", e))),
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::Stop(format!("数据错误:{:?}", net_packet)));
|
||||
}
|
||||
}
|
||||
channel.send_to_addr(buf, server_address)?;
|
||||
let (len, route) = channel.recv_from(&mut recv_buf, Some(Duration::from_millis(300)))?;
|
||||
if server_address != route.addr {
|
||||
return Err(Error::Warn(format!("数据来源错误:{:?}", route.addr)));
|
||||
}
|
||||
let net_packet = NetPacket::new(&recv_buf[..len])?;
|
||||
return 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())?;
|
||||
Ok(response)
|
||||
}
|
||||
_ => {
|
||||
Err(Error::Warn(format!("数据错误:{:?}", net_packet)))
|
||||
}
|
||||
}
|
||||
}
|
||||
Protocol::Error => {
|
||||
match InErrorPacket::new(
|
||||
net_packet.transport_protocol(),
|
||||
net_packet.payload(),
|
||||
) {
|
||||
Ok(e) => match e {
|
||||
InErrorPacket::TokenError => Err(Error::Stop("token错误".to_string())),
|
||||
InErrorPacket::Disconnect => Err(Error::Warn("断开连接".to_string())),
|
||||
InErrorPacket::AddressExhausted => Err(Error::Stop("地址用尽".to_string())),
|
||||
InErrorPacket::OtherError(e) => match e.message() {
|
||||
Ok(str) => Err(Error::Warn(str)),
|
||||
Err(e) => Err(Error::Warn(format!("{:?}", e))),
|
||||
},
|
||||
},
|
||||
Err(e) => Err(Error::Warn(format!("{:?}", e))),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Err(Error::Warn(format!("数据错误:{:?}", net_packet)))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn registration_request_packet(
|
||||
token: String,
|
||||
mac_address: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
is_fast: bool,
|
||||
) -> Result<NetPacket<Vec<u8>>> {
|
||||
) -> crate::Result<NetPacket<Vec<u8>>> {
|
||||
let mut request = RegistrationRequest::new();
|
||||
request.token = token;
|
||||
request.mac_address = mac_address;
|
||||
request.device_id = device_id;
|
||||
request.name = name;
|
||||
request.is_fast = is_fast;
|
||||
let bytes = request.write_to_bytes()?;
|
||||
let buf = vec![0u8; 4 + bytes.len()];
|
||||
let buf = vec![0u8; 12 + 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.first_set_ttl(MAX_TTL);
|
||||
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
|
||||
pub struct Register {
|
||||
sender: Sender<Ipv4Addr>,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String,
|
||||
time: AtomicI64,
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn new(sender: Sender<Ipv4Addr>,
|
||||
server_address: SocketAddr,
|
||||
token: String,
|
||||
device_id: String,
|
||||
name: String, ) -> Self {
|
||||
Self {
|
||||
sender,
|
||||
server_address,
|
||||
token,
|
||||
device_id,
|
||||
name,
|
||||
time: AtomicI64::new(0),
|
||||
}
|
||||
}
|
||||
pub fn fast_register(&self) -> io::Result<()> {
|
||||
let last = self.time.load(Ordering::Relaxed);
|
||||
let new = Local::now().timestamp_millis();
|
||||
if new - last < 1000
|
||||
|| self.time
|
||||
.compare_exchange(last, new, Ordering::Relaxed, Ordering::Relaxed)
|
||||
.is_err()
|
||||
{
|
||||
//短时间不重复注册
|
||||
return Ok(());
|
||||
{
|
||||
//短时间不重复注册
|
||||
return Ok(());
|
||||
}
|
||||
log::info!("重新连接");
|
||||
let request_packet =
|
||||
registration_request_packet(self.token.clone(),
|
||||
self.device_id.clone(),
|
||||
self.name.clone(), false).unwrap();
|
||||
let buf = request_packet.buffer();
|
||||
self.sender.send_to_addr(buf, self.server_address)?;
|
||||
Ok(())
|
||||
}
|
||||
CONNECTION_STATUS.store(ConnectStatus::Connecting);
|
||||
let lock = REQUEST.read();
|
||||
let option = lock.clone();
|
||||
drop(lock);
|
||||
if let Some((token, mac_address, name)) = option {
|
||||
let request_packet = registration_request_packet(token, mac_address, name, true)?;
|
||||
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()));
|
||||
}
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
use std::{io, thread};
|
||||
/// 接收tun数据,并且转发到udp上
|
||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
|
||||
use std::thread;
|
||||
|
||||
use chrono::Local;
|
||||
use tokio::sync::watch;
|
||||
use std::net::Ipv4Addr;
|
||||
use std::sync::Arc;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
|
||||
use nat_traversal::channel::sender::Sender;
|
||||
use packet::icmp::icmp::IcmpPacket;
|
||||
use packet::icmp::Kind;
|
||||
use packet::ip::ipv4;
|
||||
use packet::ip::ipv4::packet::IpV4Packet;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::handle::{CurrentDeviceInfo, DIRECT_ROUTE_TABLE};
|
||||
use crate::protocol::turn_packet::TurnPacket;
|
||||
use crate::protocol::{NetPacket, Protocol, Version};
|
||||
use crate::tun_device::TunReader;
|
||||
use crate::ApplicationStatus;
|
||||
use crate::handle::{check_dest, CurrentDeviceInfo};
|
||||
use crate::protocol::{MAX_TTL, NetPacket, Protocol, Version};
|
||||
use crate::tun_device::{TunReader, TunWriter};
|
||||
|
||||
/// 是否在一个网段
|
||||
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<()> {
|
||||
fn icmp(tun_writer: &TunWriter, 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 {
|
||||
@@ -33,21 +26,14 @@ fn icmp(udp: &UdpSocket, mut ipv4_packet: IpV4Packet<&mut [u8]>) -> Result<()> {
|
||||
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)?;
|
||||
tun_writer.write(ipv4_packet.buffer)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn handle(
|
||||
udp: &UdpSocket,
|
||||
data: &mut [u8],
|
||||
cur_info: &CurrentDeviceInfo,
|
||||
net_packet: &mut NetPacket<Vec<u8>>,
|
||||
) -> Result<()> {
|
||||
fn handle(sender: &Sender<Ipv4Addr>, data: &mut [u8], tun_writer: &TunWriter, current_device: 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,
|
||||
@@ -63,135 +49,49 @@ fn handle(
|
||||
// // 137端口是在局域网中提供计算机的名字或IP地址查询服务
|
||||
// return Ok(());
|
||||
// }
|
||||
if src_ip != cur_info.virtual_ip || !check_dest(dest_ip, &cur_info) {
|
||||
if src_ip != current_device.virtual_ip() || !check_dest(dest_ip, current_device.virtual_netmask, current_device.virtual_network) {
|
||||
return Ok(());
|
||||
}
|
||||
if src_ip == dest_ip {
|
||||
return icmp(&udp, ipv4_packet);
|
||||
return icmp(&tun_writer, 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);
|
||||
net_packet.set_source(src_ip);
|
||||
net_packet.set_destination(dest_ip);
|
||||
net_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(());
|
||||
}
|
||||
}
|
||||
if sender.send_to_id(&net_packet.buffer()[..(4 + 8 + data_len)], &dest_ip).is_err() {
|
||||
sender.send_to_addr(&net_packet.buffer()[..(4 + 8 + data_len)], current_device.connect_server)?;
|
||||
}
|
||||
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),
|
||||
);
|
||||
});
|
||||
pub fn start(sender: Sender<Ipv4Addr>,
|
||||
tun_reader: TunReader,
|
||||
tun_writer: TunWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) {
|
||||
thread::spawn(move || {
|
||||
if let Err(e) = handle_loop(udp, tun_reader, cur_info) {
|
||||
log::warn!("tun数据处理线程停止 {:?}", e);
|
||||
if let Err(e) = start_(sender, tun_reader, tun_writer, current_device) {
|
||||
log::warn!("{:?}",e);
|
||||
}
|
||||
stop_fn();
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn handle_loop(udp: UdpSocket, tun_reader: TunReader, cur_info: CurrentDeviceInfo) -> Result<()> {
|
||||
fn start_(sender: Sender<Ipv4Addr>,
|
||||
tun_reader: TunReader,
|
||||
tun_writer: TunWriter,
|
||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>, ) -> io::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);
|
||||
net_packet.set_ttl(MAX_TTL);
|
||||
loop {
|
||||
let mut data = tun_reader.next()?;
|
||||
match handle(&udp, data.bytes_mut(), &cur_info, &mut net_packet) {
|
||||
match handle(&sender, data.bytes_mut(), &tun_writer, current_device.load(), &mut net_packet) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "android"))]
|
||||
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,
|
||||
{
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::os::fd::AsRawFd;
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::unix::io::AsRawFd;
|
||||
let raw_fd = tun_reader.0.as_raw_fd();
|
||||
tokio::spawn(async move {
|
||||
let _ = status_watch.changed().await;
|
||||
// 让tun接收线程关闭,问题:如果改变tun配置,可能导致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::warn!(" tun数据处理线程停止 {:?}", e);
|
||||
}
|
||||
stop_fn();
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "android"))]
|
||||
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::warn!("{:?}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,389 +0,0 @@
|
||||
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::error::TrySendError;
|
||||
use tokio::sync::mpsc::{Receiver, Sender};
|
||||
use tokio::sync::watch;
|
||||
|
||||
use crate::error::*;
|
||||
use crate::handle::punch_handler::PunchSender;
|
||||
use crate::handle::registration_handler::{fast_registration, CONNECTION_STATUS};
|
||||
use crate::handle::{
|
||||
ConnectStatus, Route, ADDR_TABLE, DEVICE_LIST, DIRECT_ROUTE_TABLE, NAT_INFO, SERVER_RT,
|
||||
};
|
||||
use crate::proto::message::{DeviceList, Punch, RegistrationResponse};
|
||||
use crate::protocol::control_packet::{ControlPacket, PunchResponsePacket};
|
||||
use crate::protocol::error_packet::InErrorPacket;
|
||||
use crate::protocol::turn_packet::TurnPacket;
|
||||
use crate::protocol::{control_packet, service_packet, turn_packet, NetPacket, Protocol, Version};
|
||||
use crate::tun_device::TunWriter;
|
||||
use crate::{ApplicationStatus, CurrentDeviceInfo, PeerDeviceInfo};
|
||||
|
||||
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>)>,
|
||||
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::warn!("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,
|
||||
¤t_device,
|
||||
) {
|
||||
Ok(_) => {}
|
||||
Err(Error::Stop(str)) => {
|
||||
return Err(Error::Stop(str));
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", 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::warn!("子线程处理 {:?}", 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(_) => {
|
||||
log::info!("udp子处理线程停止");
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", 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, ¤t_device, &sender) {
|
||||
Ok(_) => {}
|
||||
Err(Error::Stop(str)) => {
|
||||
return Err(Error::Stop(str));
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("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);
|
||||
//需要保证重连ip不变
|
||||
}
|
||||
service_packet::Protocol::UpdateDeviceList => {
|
||||
let device_list = DeviceList::parse_from_bytes(net_packet.payload())?;
|
||||
let ip_list = device_list
|
||||
.device_info_list
|
||||
.into_iter()
|
||||
.map(|info| {
|
||||
PeerDeviceInfo::new(
|
||||
Ipv4Addr::from(info.virtual_ip),
|
||||
info.name,
|
||||
info.device_status as u8,
|
||||
)
|
||||
})
|
||||
.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::AddressExhausted => {
|
||||
return Err(Error::Stop("IP address has been exhausted".to_string()));
|
||||
}
|
||||
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());
|
||||
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(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
Protocol::UnKnow(p) => {
|
||||
log::warn!("未知协议 {}", p);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user