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

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
+26
View File
@@ -0,0 +1,26 @@
use std::io;
use crossbeam::channel::RecvError;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("packet error")]
PacketError(#[from] packet::error::Error),
#[error("TokioWatchRecvError")]
TokioWatchRecvError(#[from] tokio::sync::watch::error::RecvError),
#[error("Io error")]
Io(#[from] io::Error),
#[error("Channel error")]
Channel(#[from] RecvError),
#[error("Protobuf error")]
Protobuf(#[from] protobuf::Error),
#[error("Invalid packet")]
InvalidPacket,
#[error("Not support")]
NotSupport,
#[error("Stop")]
Stop(String),
}
pub type Result<T> = std::result::Result<T, Error>;
+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(())
}
+211
View File
@@ -0,0 +1,211 @@
use std::io;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, ToSocketAddrs, UdpSocket};
use std::sync::atomic::Ordering;
use crossbeam::sync::WaitGroup;
use tokio::sync::watch;
use error::*;
use crate::handle::{ApplicationStatus, ConnectStatus, CurrentDeviceInfo, DEVICE_LIST, DIRECT_ROUTE_TABLE, Route, RouteType, SERVER_RT};
use crate::handle::registration_handler::CONNECTION_STATUS;
pub mod tun_device;
pub mod nat;
pub mod error;
pub mod handle;
pub mod proto;
pub mod protocol;
#[derive(Clone, Debug)]
pub struct Config {
pub token: String,
pub mac_address: String,
}
impl Config {
pub fn new(token: String, mac_address: String) -> Self {
Self {
token,
mac_address,
}
}
}
pub struct Switch {
current_device: CurrentDeviceInfo,
status_sender: watch::Sender<ApplicationStatus>,
wait_group: WaitGroup,
runtime: Option<tokio::runtime::Runtime>,
}
impl Switch {
pub fn start(config: Config) -> Result<Self> {
let runtime = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
return match runtime.block_on(Switch::start_(config.token, config.mac_address)) {
Ok(mut switch) => {
switch.runtime = Some(runtime);
Ok(switch)
}
Err(e) => {
Err(e)
}
};
}
pub fn stop(self) {
let _ = self.status_sender.send(ApplicationStatus::Stopping);
self.wait_group.wait();
}
pub fn current_device(&self) -> &CurrentDeviceInfo {
&self.current_device
}
pub fn server_rt(&self) -> i64 {
SERVER_RT.load(Ordering::Relaxed)
}
pub fn connection_status(&self) -> ConnectStatus {
CONNECTION_STATUS.load()
}
pub fn device_list(&self) -> Vec<Ipv4Addr> {
let device_list_lock = DEVICE_LIST.lock();
let (_epoch, device_list) = device_list_lock.clone();
drop(device_list_lock);
device_list
}
pub fn route(&self, ip: &Ipv4Addr) -> Route {
if let Some(route_ref) = DIRECT_ROUTE_TABLE.get(ip) {
route_ref.value().clone()
} else {
let mut route = Route::new(self.current_device.connect_server);
route.route_type = RouteType::ServerRelay;
route.rt = self.server_rt() * 2;
route.recv_time = -1;
route
}
}
}
impl Switch {
pub async fn start_(token: String, mac_address: String) -> Result<Self> {
let server_address = "nat1.wherewego.top:29876".to_socket_addrs().unwrap().next().unwrap();
let mut port = 101 as u16;
let udp = loop {
match UdpSocket::bind(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(0), port))) {
Ok(udp) => {
break udp;
}
Err(e) => {
if e.kind() == io::ErrorKind::AddrInUse {
port += 1;
} else {
log::error!("创建udp失败 {:?}",e);
return Err(Error::Stop("udp bind error".to_string()));
}
}
}
};
//注册
let response = handle::registration_handler::registration(&udp, server_address, token, mac_address)?;
{
let ip_list = response
.virtual_ip_list
.iter()
.map(|ip| Ipv4Addr::from(*ip))
.collect();
let mut dev = DEVICE_LIST.lock();
dev.0 = response.epoch;
dev.1 = ip_list;
}
let virtual_ip = Ipv4Addr::from(response.virtual_ip);
let virtual_gateway = Ipv4Addr::from(response.virtual_gateway);
let virtual_netmask = Ipv4Addr::from(response.virtual_netmask);
let (status_sender, status_receiver) = tokio::sync::watch::channel(ApplicationStatus::Starting);
let current_device = CurrentDeviceInfo::new(virtual_ip, virtual_gateway, virtual_netmask, server_address);
let wait_group = WaitGroup::new();
//心跳线程
{
let udp = udp.try_clone()?;
let wait_group1 = wait_group.clone();
handle::heartbeat_handler::start(status_receiver.clone(), udp, current_device, || {
drop(wait_group1);
}).await;
}
//初始化nat数据
handle::init_nat_info(response.public_ip, response.public_port as u16);
// tun服务
let (tun_writer, tun_reader) =
tun_device::create_tun(virtual_ip, virtual_netmask, virtual_gateway)?;
// 打洞数据通道
let (punch_sender, cone_receiver, req_symmetric_receiver, res_symmetric_receiver) = handle::punch_handler::bounded();
//udp数据处理
{
// 低优先级的udp数据通道
let (sender, receiver) = tokio::sync::mpsc::channel(50);
let udp1 = udp.try_clone()?;
let wait_group1 = wait_group.clone();
handle::udp_recv_handler::udp_recv_start(
status_receiver.clone(),
udp1,
server_address,
sender,
tun_writer,
current_device,
|| {
drop(wait_group1);
},
).await;
let udp1 = udp.try_clone()?;
let wait_group1 = wait_group.clone();
handle::udp_recv_handler::udp_other_recv_start(status_receiver.clone(), udp1,
receiver, current_device, punch_sender,
|| {
drop(wait_group1);
}).await;
}
//打洞处理
{
let udp1 = udp.try_clone()?;
let wait_group1 = wait_group.clone();
handle::punch_handler::cone_handler_start(status_receiver.clone(),
cone_receiver, udp1,
current_device,
|| {
drop(wait_group1);
}).await;
let udp1 = udp.try_clone()?;
let wait_group1 = wait_group.clone();
handle::punch_handler::req_symmetric_handler_start(status_receiver.clone(),
req_symmetric_receiver, udp1,
current_device,
|| {
drop(wait_group1);
}).await;
let udp1 = udp.try_clone()?;
let wait_group1 = wait_group.clone();
handle::punch_handler::res_symmetric_handler_start(status_receiver.clone(),
res_symmetric_receiver,
udp1,
current_device,
|| {
drop(wait_group1);
}).await;
}
//tun数据处理
{
let wait_group1 = wait_group.clone();
handle::tun_handler::handler_start(status_receiver.clone(), udp,
tun_reader, current_device,
|| {
drop(wait_group1);
}).await;
}
Ok(Switch {
current_device,
status_sender,
wait_group,
runtime: None,
})
}
}
+157
View File
@@ -0,0 +1,157 @@
use std::{io, thread};
use std::collections::HashSet;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::time::Duration;
use crate::proto::message::NatType;
// #[derive(Debug, Copy, Clone, PartialEq)]
// pub enum NatType {
// Symmetric,
// Cone,
// }
//
// impl Into<u8> for NatType {
// fn into(self) -> u8 {
// match self {
// NatType::Symmetric => 0,
// NatType::Cone => 1,
// }
// }
// }
/// 返回所有公网ip和端口变化范围
pub fn public_ip_list() -> io::Result<(NatType, Vec<Ipv4Addr>, u16)> {
let mut hash_set = HashSet::new();
let mut max_port_range = 0;
let mut nat_type = NatType::Cone;
let mut port = 88;
for _ in 0..3 {
let udp = loop {
match UdpSocket::bind(SocketAddr::new(IpAddr::from(Ipv4Addr::from(0)), port)) {
Ok(udp) => {
break udp;
}
Err(e) => {
if e.kind() == io::ErrorKind::AddrInUse {
port += 1;
continue;
}
return Err(e);
}
}
};
let (set, min_port, max_port) = public_ip_list_(&udp)?;
drop(udp);
let port_range = max_port - min_port;
//有多个ip或者端口有变化,说明是对称nat
if nat_type == NatType::Cone && (set.len() > 1 || port_range != 0) {
nat_type = NatType::Symmetric;
}
if max_port_range < port_range {
max_port_range = port_range;
}
for x in set {
hash_set.insert(x);
}
thread::sleep(Duration::from_micros(5));
}
Ok((nat_type, hash_set.into_iter().collect(), max_port_range))
}
/// 测试样本较少,可能不对
///
/// - 移动宽带:锥形网络、一个ip、端口和局域网端口不相同
/// - 电信宽带:锥形网络、一个ip,端口和局域网端口不相同
/// - 联调宽带:对称网络、端口不变ip轮流用
/// - 移动4g:对称网络、ip端口都变 使用小的端口变化量小
/// - 联通4g:对称网络、只有一个ip 端口变化大
/// - 电信4g:对称网络只有一个ip 公网端口比较连续
/// - 综上:客户端使用小端口,针对对称网络 尝试所有ip 公网端口+-变化量的范围
/// - 打通概率 移动宽带=电信宽带>联调宽带>电信4g>移动4g>>联调4g
pub fn public_ip_list_(udp: &UdpSocket) -> io::Result<(HashSet<Ipv4Addr>, u16, u16)> {
// println!("local port {:?}", udp.local_addr().unwrap().port());
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
let mut buf = [0u8; 128];
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35061")?;
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35062")?;
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35061")?;
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35062")?;
let mut hash_set = HashSet::new();
let mut count = 0;
let mut min_port = 65535;
let mut max_port = 0;
for _ in 0..4 {
if let Ok(len) = udp.recv(&mut buf) {
if len != 16 || &buf[..10] != &b"NatType213"[..] {
continue;
}
let port = u16::from_be_bytes([buf[14], buf[15]]);
if min_port > port {
min_port = port;
}
if max_port < port {
max_port = port;
}
let ip = Ipv4Addr::new(buf[10], buf[11], buf[12], buf[13]);
// println!("pub {:?}:{}", ip, port);
hash_set.insert(ip);
count += 1;
}
}
if count <= 1 {
return Err(io::Error::from(io::ErrorKind::TimedOut));
}
Ok((hash_set, min_port, max_port))
}
/// 返回nat类型
pub fn nat_test() -> io::Result<NatType> {
for _ in 0..3 {
if NatType::Symmetric == nat_test_()? {
return Ok(NatType::Symmetric);
}
thread::sleep(Duration::from_micros(5));
}
Ok(NatType::Cone)
}
pub fn nat_test_() -> io::Result<NatType> {
let udp = UdpSocket::bind("0.0.0.0:0")?;
udp.set_read_timeout(Some(Duration::from_millis(300)))?;
let mut buf = [0u8; 128];
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35061")?;
let _ = udp.send_to(b"NatTest", "nat1.wherewego.top:35062")?;
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35061")?;
let _ = udp.send_to(b"NatTest", "nat2.wherewego.top:35062")?;
let mut tmp_ip_port: Option<[u8; 6]> = None;
let mut count = 0;
for _ in 0..4 {
if let Ok(len) = udp.recv(&mut buf) {
if len != 16 || &buf[..10] != &b"NatType213"[..] {
continue;
}
count += 1;
let mut ip_port = [0u8; 6];
ip_port.copy_from_slice(&buf[10..16]);
if let Some(tmp_ip_port) = &tmp_ip_port {
if tmp_ip_port != &ip_port {
return Ok(NatType::Symmetric);
}
} else {
tmp_ip_port = Some(ip_port);
}
}
}
if count <= 1 {
return Err(io::Error::from(io::ErrorKind::TimedOut));
}
Ok(NatType::Cone)
}
#[test]
fn nat_test_run() {
let udp = UdpSocket::bind("0.0.0.0:101").unwrap();
let print = public_ip_list_(&udp).unwrap();
println!("{:?}", print);
}
+1
View File
@@ -0,0 +1 @@
pub mod check;
+941
View File
@@ -0,0 +1,941 @@
// This file is generated by rust-protobuf 3.2.0. Do not edit
// .proto file is parsed by pure
// @generated
// https://github.com/rust-lang/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy::all)]
#![allow(unused_attributes)]
#![cfg_attr(rustfmt, rustfmt::skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unused_results)]
#![allow(unused_mut)]
//! Generated file from `message.proto`
/// Generated files are compatible only with the same version
/// of protobuf runtime.
const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_2_0;
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RegistrationRequest)
pub struct RegistrationRequest {
// message fields
// @@protoc_insertion_point(field:RegistrationRequest.token)
pub token: ::std::string::String,
// @@protoc_insertion_point(field:RegistrationRequest.mac_address)
pub mac_address: ::std::string::String,
// special fields
// @@protoc_insertion_point(special_field:RegistrationRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a RegistrationRequest {
fn default() -> &'a RegistrationRequest {
<RegistrationRequest as ::protobuf::Message>::default_instance()
}
}
impl RegistrationRequest {
pub fn new() -> RegistrationRequest {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"token",
|m: &RegistrationRequest| { &m.token },
|m: &mut RegistrationRequest| { &mut m.token },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"mac_address",
|m: &RegistrationRequest| { &m.mac_address },
|m: &mut RegistrationRequest| { &mut m.mac_address },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationRequest>(
"RegistrationRequest",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for RegistrationRequest {
const NAME: &'static str = "RegistrationRequest";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.token = is.read_string()?;
},
18 => {
self.mac_address = is.read_string()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.token.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.token);
}
if !self.mac_address.is_empty() {
my_size += ::protobuf::rt::string_size(2, &self.mac_address);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.token.is_empty() {
os.write_string(1, &self.token)?;
}
if !self.mac_address.is_empty() {
os.write_string(2, &self.mac_address)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> RegistrationRequest {
RegistrationRequest::new()
}
fn clear(&mut self) {
self.token.clear();
self.mac_address.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static RegistrationRequest {
static instance: RegistrationRequest = RegistrationRequest {
token: ::std::string::String::new(),
mac_address: ::std::string::String::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for RegistrationRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("RegistrationRequest").unwrap()).clone()
}
}
impl ::std::fmt::Display for RegistrationRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RegistrationRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:RegistrationResponse)
pub struct RegistrationResponse {
// message fields
// @@protoc_insertion_point(field:RegistrationResponse.virtual_ip)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:RegistrationResponse.virtual_gateway)
pub virtual_gateway: u32,
// @@protoc_insertion_point(field:RegistrationResponse.virtual_netmask)
pub virtual_netmask: u32,
// @@protoc_insertion_point(field:RegistrationResponse.epoch)
pub epoch: u32,
// @@protoc_insertion_point(field:RegistrationResponse.virtual_ip_list)
pub virtual_ip_list: ::std::vec::Vec<u32>,
// @@protoc_insertion_point(field:RegistrationResponse.public_ip)
pub public_ip: u32,
// @@protoc_insertion_point(field:RegistrationResponse.public_port)
pub public_port: u32,
// special fields
// @@protoc_insertion_point(special_field:RegistrationResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a RegistrationResponse {
fn default() -> &'a RegistrationResponse {
<RegistrationResponse as ::protobuf::Message>::default_instance()
}
}
impl RegistrationResponse {
pub fn new() -> RegistrationResponse {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(7);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &RegistrationResponse| { &m.virtual_ip },
|m: &mut RegistrationResponse| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_gateway",
|m: &RegistrationResponse| { &m.virtual_gateway },
|m: &mut RegistrationResponse| { &mut m.virtual_gateway },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_netmask",
|m: &RegistrationResponse| { &m.virtual_netmask },
|m: &mut RegistrationResponse| { &mut m.virtual_netmask },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"epoch",
|m: &RegistrationResponse| { &m.epoch },
|m: &mut RegistrationResponse| { &mut m.epoch },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"virtual_ip_list",
|m: &RegistrationResponse| { &m.virtual_ip_list },
|m: &mut RegistrationResponse| { &mut m.virtual_ip_list },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_ip",
|m: &RegistrationResponse| { &m.public_ip },
|m: &mut RegistrationResponse| { &mut m.public_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port",
|m: &RegistrationResponse| { &m.public_port },
|m: &mut RegistrationResponse| { &mut m.public_port },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<RegistrationResponse>(
"RegistrationResponse",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for RegistrationResponse {
const NAME: &'static str = "RegistrationResponse";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
13 => {
self.virtual_ip = is.read_fixed32()?;
},
21 => {
self.virtual_gateway = is.read_fixed32()?;
},
29 => {
self.virtual_netmask = is.read_fixed32()?;
},
32 => {
self.epoch = is.read_uint32()?;
},
42 => {
is.read_repeated_packed_fixed32_into(&mut self.virtual_ip_list)?;
},
45 => {
self.virtual_ip_list.push(is.read_fixed32()?);
},
53 => {
self.public_ip = is.read_fixed32()?;
},
56 => {
self.public_port = is.read_uint32()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
if self.virtual_gateway != 0 {
my_size += 1 + 4;
}
if self.virtual_netmask != 0 {
my_size += 1 + 4;
}
if self.epoch != 0 {
my_size += ::protobuf::rt::uint32_size(4, self.epoch);
}
my_size += 5 * self.virtual_ip_list.len() as u64;
if self.public_ip != 0 {
my_size += 1 + 4;
}
if self.public_port != 0 {
my_size += ::protobuf::rt::uint32_size(7, self.public_port);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if self.virtual_ip != 0 {
os.write_fixed32(1, self.virtual_ip)?;
}
if self.virtual_gateway != 0 {
os.write_fixed32(2, self.virtual_gateway)?;
}
if self.virtual_netmask != 0 {
os.write_fixed32(3, self.virtual_netmask)?;
}
if self.epoch != 0 {
os.write_uint32(4, self.epoch)?;
}
for v in &self.virtual_ip_list {
os.write_fixed32(5, *v)?;
};
if self.public_ip != 0 {
os.write_fixed32(6, self.public_ip)?;
}
if self.public_port != 0 {
os.write_uint32(7, self.public_port)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> RegistrationResponse {
RegistrationResponse::new()
}
fn clear(&mut self) {
self.virtual_ip = 0;
self.virtual_gateway = 0;
self.virtual_netmask = 0;
self.epoch = 0;
self.virtual_ip_list.clear();
self.public_ip = 0;
self.public_port = 0;
self.special_fields.clear();
}
fn default_instance() -> &'static RegistrationResponse {
static instance: RegistrationResponse = RegistrationResponse {
virtual_ip: 0,
virtual_gateway: 0,
virtual_netmask: 0,
epoch: 0,
virtual_ip_list: ::std::vec::Vec::new(),
public_ip: 0,
public_port: 0,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for RegistrationResponse {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("RegistrationResponse").unwrap()).clone()
}
}
impl ::std::fmt::Display for RegistrationResponse {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for RegistrationResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:DeviceList)
pub struct DeviceList {
// message fields
// @@protoc_insertion_point(field:DeviceList.epoch)
pub epoch: u32,
// @@protoc_insertion_point(field:DeviceList.virtual_ip_list)
pub virtual_ip_list: ::std::vec::Vec<u32>,
// special fields
// @@protoc_insertion_point(special_field:DeviceList.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a DeviceList {
fn default() -> &'a DeviceList {
<DeviceList as ::protobuf::Message>::default_instance()
}
}
impl DeviceList {
pub fn new() -> DeviceList {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"epoch",
|m: &DeviceList| { &m.epoch },
|m: &mut DeviceList| { &mut m.epoch },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"virtual_ip_list",
|m: &DeviceList| { &m.virtual_ip_list },
|m: &mut DeviceList| { &mut m.virtual_ip_list },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<DeviceList>(
"DeviceList",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for DeviceList {
const NAME: &'static str = "DeviceList";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
8 => {
self.epoch = is.read_uint32()?;
},
18 => {
is.read_repeated_packed_fixed32_into(&mut self.virtual_ip_list)?;
},
21 => {
self.virtual_ip_list.push(is.read_fixed32()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if self.epoch != 0 {
my_size += ::protobuf::rt::uint32_size(1, self.epoch);
}
my_size += 5 * self.virtual_ip_list.len() as u64;
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if self.epoch != 0 {
os.write_uint32(1, self.epoch)?;
}
for v in &self.virtual_ip_list {
os.write_fixed32(2, *v)?;
};
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> DeviceList {
DeviceList::new()
}
fn clear(&mut self) {
self.epoch = 0;
self.virtual_ip_list.clear();
self.special_fields.clear();
}
fn default_instance() -> &'static DeviceList {
static instance: DeviceList = DeviceList {
epoch: 0,
virtual_ip_list: ::std::vec::Vec::new(),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for DeviceList {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("DeviceList").unwrap()).clone()
}
}
impl ::std::fmt::Display for DeviceList {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for DeviceList {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(PartialEq,Clone,Default,Debug)]
// @@protoc_insertion_point(message:Punch)
pub struct Punch {
// message fields
// @@protoc_insertion_point(field:Punch.virtual_ip)
pub virtual_ip: u32,
// @@protoc_insertion_point(field:Punch.public_ip_list)
pub public_ip_list: ::std::vec::Vec<u32>,
// @@protoc_insertion_point(field:Punch.public_port)
pub public_port: u32,
// @@protoc_insertion_point(field:Punch.public_port_range)
pub public_port_range: u32,
// @@protoc_insertion_point(field:Punch.nat_type)
pub nat_type: ::protobuf::EnumOrUnknown<NatType>,
// @@protoc_insertion_point(field:Punch.reply)
pub reply: bool,
// @@protoc_insertion_point(field:Punch.step)
pub step: ::protobuf::EnumOrUnknown<Step>,
// special fields
// @@protoc_insertion_point(special_field:Punch.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}
impl<'a> ::std::default::Default for &'a Punch {
fn default() -> &'a Punch {
<Punch as ::protobuf::Message>::default_instance()
}
}
impl Punch {
pub fn new() -> Punch {
::std::default::Default::default()
}
fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(7);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"virtual_ip",
|m: &Punch| { &m.virtual_ip },
|m: &mut Punch| { &mut m.virtual_ip },
));
fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>(
"public_ip_list",
|m: &Punch| { &m.public_ip_list },
|m: &mut Punch| { &mut m.public_ip_list },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port",
|m: &Punch| { &m.public_port },
|m: &mut Punch| { &mut m.public_port },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"public_port_range",
|m: &Punch| { &m.public_port_range },
|m: &mut Punch| { &mut m.public_port_range },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"nat_type",
|m: &Punch| { &m.nat_type },
|m: &mut Punch| { &mut m.nat_type },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"reply",
|m: &Punch| { &m.reply },
|m: &mut Punch| { &mut m.reply },
));
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"step",
|m: &Punch| { &m.step },
|m: &mut Punch| { &mut m.step },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<Punch>(
"Punch",
fields,
oneofs,
)
}
}
impl ::protobuf::Message for Punch {
const NAME: &'static str = "Punch";
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
13 => {
self.virtual_ip = is.read_fixed32()?;
},
18 => {
is.read_repeated_packed_fixed32_into(&mut self.public_ip_list)?;
},
21 => {
self.public_ip_list.push(is.read_fixed32()?);
},
24 => {
self.public_port = is.read_uint32()?;
},
32 => {
self.public_port_range = is.read_uint32()?;
},
40 => {
self.nat_type = is.read_enum_or_unknown()?;
},
48 => {
self.reply = is.read_bool()?;
},
56 => {
self.step = is.read_enum_or_unknown()?;
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if self.virtual_ip != 0 {
my_size += 1 + 4;
}
my_size += 5 * self.public_ip_list.len() as u64;
if self.public_port != 0 {
my_size += ::protobuf::rt::uint32_size(3, self.public_port);
}
if self.public_port_range != 0 {
my_size += ::protobuf::rt::uint32_size(4, self.public_port_range);
}
if self.nat_type != ::protobuf::EnumOrUnknown::new(NatType::Symmetric) {
my_size += ::protobuf::rt::int32_size(5, self.nat_type.value());
}
if self.reply != false {
my_size += 1 + 1;
}
if self.step != ::protobuf::EnumOrUnknown::new(Step::Step1) {
my_size += ::protobuf::rt::int32_size(7, self.step.value());
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if self.virtual_ip != 0 {
os.write_fixed32(1, self.virtual_ip)?;
}
for v in &self.public_ip_list {
os.write_fixed32(2, *v)?;
};
if self.public_port != 0 {
os.write_uint32(3, self.public_port)?;
}
if self.public_port_range != 0 {
os.write_uint32(4, self.public_port_range)?;
}
if self.nat_type != ::protobuf::EnumOrUnknown::new(NatType::Symmetric) {
os.write_enum(5, ::protobuf::EnumOrUnknown::value(&self.nat_type))?;
}
if self.reply != false {
os.write_bool(6, self.reply)?;
}
if self.step != ::protobuf::EnumOrUnknown::new(Step::Step1) {
os.write_enum(7, ::protobuf::EnumOrUnknown::value(&self.step))?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}
fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}
fn new() -> Punch {
Punch::new()
}
fn clear(&mut self) {
self.virtual_ip = 0;
self.public_ip_list.clear();
self.public_port = 0;
self.public_port_range = 0;
self.nat_type = ::protobuf::EnumOrUnknown::new(NatType::Symmetric);
self.reply = false;
self.step = ::protobuf::EnumOrUnknown::new(Step::Step1);
self.special_fields.clear();
}
fn default_instance() -> &'static Punch {
static instance: Punch = Punch {
virtual_ip: 0,
public_ip_list: ::std::vec::Vec::new(),
public_port: 0,
public_port_range: 0,
nat_type: ::protobuf::EnumOrUnknown::from_i32(0),
reply: false,
step: ::protobuf::EnumOrUnknown::from_i32(0),
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}
impl ::protobuf::MessageFull for Punch {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("Punch").unwrap()).clone()
}
}
impl ::std::fmt::Display for Punch {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for Punch {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:NatType)
pub enum NatType {
// @@protoc_insertion_point(enum_value:NatType.Symmetric)
Symmetric = 0,
// @@protoc_insertion_point(enum_value:NatType.Cone)
Cone = 1,
}
impl ::protobuf::Enum for NatType {
const NAME: &'static str = "NatType";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<NatType> {
match value {
0 => ::std::option::Option::Some(NatType::Symmetric),
1 => ::std::option::Option::Some(NatType::Cone),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [NatType] = &[
NatType::Symmetric,
NatType::Cone,
];
}
impl ::protobuf::EnumFull for NatType {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().enum_by_package_relative_name("NatType").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
let index = *self as usize;
Self::enum_descriptor().value_by_index(index)
}
}
impl ::std::default::Default for NatType {
fn default() -> Self {
NatType::Symmetric
}
}
impl NatType {
fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<NatType>("NatType")
}
}
#[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)]
// @@protoc_insertion_point(enum:Step)
pub enum Step {
// @@protoc_insertion_point(enum_value:Step.Step1)
Step1 = 0,
// @@protoc_insertion_point(enum_value:Step.Step2)
Step2 = 1,
// @@protoc_insertion_point(enum_value:Step.Step3)
Step3 = 2,
// @@protoc_insertion_point(enum_value:Step.Step4)
Step4 = 3,
}
impl ::protobuf::Enum for Step {
const NAME: &'static str = "Step";
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<Step> {
match value {
0 => ::std::option::Option::Some(Step::Step1),
1 => ::std::option::Option::Some(Step::Step2),
2 => ::std::option::Option::Some(Step::Step3),
3 => ::std::option::Option::Some(Step::Step4),
_ => ::std::option::Option::None
}
}
const VALUES: &'static [Step] = &[
Step::Step1,
Step::Step2,
Step::Step3,
Step::Step4,
];
}
impl ::protobuf::EnumFull for Step {
fn enum_descriptor() -> ::protobuf::reflect::EnumDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().enum_by_package_relative_name("Step").unwrap()).clone()
}
fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor {
let index = *self as usize;
Self::enum_descriptor().value_by_index(index)
}
}
impl ::std::default::Default for Step {
fn default() -> Self {
Step::Step1
}
}
impl Step {
fn generated_enum_descriptor_data() -> ::protobuf::reflect::GeneratedEnumDescriptorData {
::protobuf::reflect::GeneratedEnumDescriptorData::new::<Step>("Step")
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\rmessage.proto\"L\n\x13RegistrationRequest\x12\x14\n\x05token\x18\x01\
\x20\x01(\tR\x05token\x12\x1f\n\x0bmac_address\x18\x02\x20\x01(\tR\nmacA\
ddress\"\x83\x02\n\x14RegistrationResponse\x12\x1d\n\nvirtual_ip\x18\x01\
\x20\x01(\x07R\tvirtualIp\x12'\n\x0fvirtual_gateway\x18\x02\x20\x01(\x07\
R\x0evirtualGateway\x12'\n\x0fvirtual_netmask\x18\x03\x20\x01(\x07R\x0ev\
irtualNetmask\x12\x14\n\x05epoch\x18\x04\x20\x01(\rR\x05epoch\x12&\n\x0f\
virtual_ip_list\x18\x05\x20\x03(\x07R\rvirtualIpList\x12\x1b\n\tpublic_i\
p\x18\x06\x20\x01(\x07R\x08publicIp\x12\x1f\n\x0bpublic_port\x18\x07\x20\
\x01(\rR\npublicPort\"J\n\nDeviceList\x12\x14\n\x05epoch\x18\x01\x20\x01\
(\rR\x05epoch\x12&\n\x0fvirtual_ip_list\x18\x02\x20\x03(\x07R\rvirtualIp\
List\"\xef\x01\n\x05Punch\x12\x1d\n\nvirtual_ip\x18\x01\x20\x01(\x07R\tv\
irtualIp\x12$\n\x0epublic_ip_list\x18\x02\x20\x03(\x07R\x0cpublicIpList\
\x12\x1f\n\x0bpublic_port\x18\x03\x20\x01(\rR\npublicPort\x12*\n\x11publ\
ic_port_range\x18\x04\x20\x01(\rR\x0fpublicPortRange\x12#\n\x08nat_type\
\x18\x05\x20\x01(\x0e2\x08.NatTypeR\x07natType\x12\x14\n\x05reply\x18\
\x06\x20\x01(\x08R\x05reply\x12\x19\n\x04step\x18\x07\x20\x01(\x0e2\x05.\
StepR\x04step*\"\n\x07NatType\x12\r\n\tSymmetric\x10\0\x12\x08\n\x04Cone\
\x10\x01*2\n\x04Step\x12\t\n\x05Step1\x10\0\x12\t\n\x05Step2\x10\x01\x12\
\t\n\x05Step3\x10\x02\x12\t\n\x05Step4\x10\x03b\x06proto3\
";
/// `FileDescriptorProto` object which was a source for this generated file
fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new();
file_descriptor_proto_lazy.get(|| {
::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
})
}
/// `FileDescriptor` object which allows dynamic access to files
pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new();
static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new();
file_descriptor.get(|| {
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
let mut deps = ::std::vec::Vec::with_capacity(0);
let mut messages = ::std::vec::Vec::with_capacity(4);
messages.push(RegistrationRequest::generated_message_descriptor_data());
messages.push(RegistrationResponse::generated_message_descriptor_data());
messages.push(DeviceList::generated_message_descriptor_data());
messages.push(Punch::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(2);
enums.push(NatType::generated_enum_descriptor_data());
enums.push(Step::generated_enum_descriptor_data());
::protobuf::reflect::GeneratedFileDescriptor::new_generated(
file_descriptor_proto(),
deps,
messages,
enums,
)
});
::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor)
})
}
+3
View File
@@ -0,0 +1,3 @@
// @generated
pub mod message;
+223
View File
@@ -0,0 +1,223 @@
use std::fmt;
use std::net::Ipv4Addr;
use crate::error::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Protocol {
Ping,
Pong,
PunchRequest,
PunchResponse,
UnKnow(u8),
}
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Protocol::Ping,
2 => Protocol::Pong,
3 => Protocol::PunchRequest,
4 => Protocol::PunchResponse,
val => Protocol::UnKnow(val),
}
}
}
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::Ping => 1,
Protocol::Pong => 2,
Protocol::PunchRequest => 3,
Protocol::PunchResponse => 4,
Protocol::UnKnow(val) => val,
}
}
}
pub enum ControlPacket<B> {
PingPacket(PingPacket<B>),
PongPacket(PongPacket<B>),
PunchRequest(PunchRequestPacket<B>),
PunchResponse(PunchResponsePacket<B>),
}
impl<B: AsRef<[u8]>> ControlPacket<B> {
pub fn new(protocol: u8, buffer: B) -> Result<ControlPacket<B>> {
match Protocol::from(protocol) {
Protocol::Ping => Ok(ControlPacket::PingPacket(PingPacket::new(buffer)?)),
Protocol::Pong => Ok(ControlPacket::PongPacket(PongPacket::new(buffer)?)),
Protocol::PunchRequest => Ok(ControlPacket::PunchRequest(PunchRequestPacket::new(
buffer,
)?)),
Protocol::PunchResponse => Ok(ControlPacket::PunchResponse(PunchResponsePacket::new(
buffer,
)?)),
Protocol::UnKnow(_) => Err(Error::NotSupport),
}
}
}
/// 网络探针
#[derive(Copy, Clone)]
pub struct PingPacket<B> {
buffer: B,
}
#[derive(Copy, Clone)]
pub struct PongPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> PingPacket<B> {
pub fn new(buffer: B) -> Result<PingPacket<B>> {
let len = buffer.as_ref().len();
if len != 8 + 4 {
return Err(Error::InvalidPacket);
}
Ok(PingPacket { buffer })
}
}
impl<B: AsRef<[u8]>> PingPacket<B> {
pub fn time(&self) -> i64 {
i64::from_be_bytes(self.buffer.as_ref()[..8].try_into().unwrap())
}
pub fn epoch(&self) -> u32 {
u32::from_be_bytes(self.buffer.as_ref()[8..12].try_into().unwrap())
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> PingPacket<B> {
pub fn set_time(&mut self, time: i64) {
self.buffer.as_mut()[..8].copy_from_slice(&time.to_be_bytes())
}
pub fn set_epoch(&mut self, epoch: u32) {
self.buffer.as_mut()[8..12].copy_from_slice(&epoch.to_be_bytes())
}
}
impl<B: AsRef<[u8]>> fmt::Debug for PingPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PingPacket")
.field("time", &self.time())
.field("epoch", &self.epoch())
.finish()
}
}
impl<B: AsRef<[u8]>> PongPacket<B> {
pub fn new(buffer: B) -> Result<PongPacket<B>> {
let len = buffer.as_ref().len();
if len != 8 {
return Err(Error::InvalidPacket);
}
Ok(PongPacket { buffer })
}
}
impl<B: AsRef<[u8]>> PongPacket<B> {
pub fn time(&self) -> i64 {
i64::from_be_bytes(self.buffer.as_ref()[..8].try_into().unwrap())
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> PongPacket<B> {
pub fn set_time(&mut self, time: i64) {
self.buffer.as_mut()[..8].copy_from_slice(&time.to_be_bytes())
}
}
impl<B: AsRef<[u8]>> fmt::Debug for PongPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PongPacket")
.field("time", &self.time())
.finish()
}
}
pub type TurnPongPacket<B> = TurnPingPacket<B>;
/// 探测目标延迟
#[derive(Copy, Clone)]
pub struct TurnPingPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> TurnPingPacket<B> {
pub fn new(buffer: B) -> Result<TurnPingPacket<B>> {
let len = buffer.as_ref().len();
if len != 16 {
return Err(Error::InvalidPacket);
}
Ok(TurnPingPacket { buffer })
}
}
impl<B: AsRef<[u8]>> TurnPingPacket<B> {
// pub fn source(&self) -> Ipv4Addr {
// let tmp:[u8;4] = self.buffer.as_ref()[..4].try_into().unwrap();
// Ipv4Addr::from(tmp)
// }
// pub fn destination(&self) -> Ipv4Addr {
// let tmp:[u8;4] = self.buffer.as_ref()[4..8].try_into().unwrap();
// Ipv4Addr::from(tmp)
// }
pub fn time(&self) -> i64 {
i64::from_be_bytes(self.buffer.as_ref()[8..].try_into().unwrap())
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> TurnPingPacket<B> {
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&source.octets());
}
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&destination.octets());
}
pub fn set_time(&mut self, time: i64) {
self.buffer.as_mut()[8..].copy_from_slice(&time.to_be_bytes())
}
}
pub type PunchResponsePacket<B> = PunchPacket<B>;
pub type PunchRequestPacket<B> = PunchPacket<B>;
/// nat穿透
#[derive(Clone)]
pub struct PunchPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> PunchPacket<B> {
pub fn new(buffer: B) -> Result<PunchPacket<B>> {
let len = buffer.as_ref().len();
if len != 8 {
return Err(Error::InvalidPacket);
}
Ok(Self { buffer })
}
}
impl<B: AsRef<[u8]>> PunchPacket<B> {
pub fn source(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[..4].try_into().unwrap();
Ipv4Addr::from(tmp)
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> PunchPacket<B> {
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&source.octets());
}
}
impl<B: AsRef<[u8]>> fmt::Debug for PunchPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PunchPacket")
.field("source", &self.source())
.finish()
}
}
+69
View File
@@ -0,0 +1,69 @@
use crate::error::*;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Protocol {
TokenError,
Disconnect,
Other(u8),
}
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Self::TokenError,
2 => Self::Disconnect,
val => Self::Other(val),
}
}
}
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::TokenError => 1,
Protocol::Disconnect => 2,
Protocol::Other(val) => val,
}
}
}
pub enum InErrorPacket<B> {
TokenError,
Disconnect,
OtherError(ErrorPacket<B>),
}
impl<B: AsRef<[u8]>> InErrorPacket<B> {
pub fn new(protocol: u8, buffer: B) -> Result<InErrorPacket<B>> {
match Protocol::from(protocol) {
Protocol::TokenError => Ok(InErrorPacket::TokenError),
Protocol::Disconnect => Ok(InErrorPacket::Disconnect),
Protocol::Other(_) => Ok(InErrorPacket::OtherError(ErrorPacket::new(buffer)?)),
}
}
}
pub struct ErrorPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> ErrorPacket<B> {
pub fn new(buffer: B) -> Result<ErrorPacket<B>> {
Ok(Self { buffer })
}
}
impl<B: AsRef<[u8]>> ErrorPacket<B> {
pub fn message(&self) -> Result<String> {
match String::from_utf8(self.buffer.as_ref().to_vec()) {
Ok(str) => Ok(str),
Err(_) => Err(Error::InvalidPacket),
}
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> ErrorPacket<B> {
pub fn set_message(&mut self, message: &str) {
self.buffer.as_mut().copy_from_slice(message.as_bytes())
}
}
+145
View File
@@ -0,0 +1,145 @@
use std::fmt;
use crate::error::*;
pub mod control_packet;
pub mod error_packet;
pub mod service_packet;
pub mod turn_packet;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Version {
V1,
UnKnow(u8),
}
impl From<u8> for Version {
fn from(value: u8) -> Self {
match value {
1 => Version::V1,
val => Version::UnKnow(val),
}
}
}
impl Into<u8> for Version {
fn into(self) -> u8 {
match self {
Version::V1 => 1,
Version::UnKnow(val) => val,
}
}
}
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Protocol {
/// 服务包 用于和服务端交互
Service,
/// 响应异常
Error,
/// 控制协议
Control,
/// 转发ipv4数据
Ipv4Turn,
OtherTurn,
UnKnow(u8),
}
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Protocol::Service,
2 => Protocol::Error,
3 => Protocol::Control,
4 => Protocol::Ipv4Turn,
5 => Protocol::OtherTurn,
val => Protocol::UnKnow(val),
}
}
}
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::Service => 1,
Protocol::Error => 2,
Protocol::Control => 3,
Protocol::Ipv4Turn => 4,
Protocol::OtherTurn => 5,
Protocol::UnKnow(val) => val,
}
}
}
#[derive(Copy, Clone)]
pub struct NetPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn new(buffer: B) -> Result<NetPacket<B>> {
let len = buffer.as_ref().len();
// 不能大于udp最大载荷长度
if len < 4 || len > 65535 - 20 - 8 {
return Err(Error::InvalidPacket);
}
Ok(NetPacket { buffer })
}
pub fn buffer(&self) -> &[u8] {
self.buffer.as_ref()
}
pub fn into_buffer(self) -> B {
self.buffer
}
}
impl<B: AsRef<[u8]>> NetPacket<B> {
pub fn version(&self) -> Version {
Version::from(self.buffer.as_ref()[0])
}
pub fn protocol(&self) -> Protocol {
Protocol::from(self.buffer.as_ref()[1])
}
pub fn transport_protocol(&self) -> u8 {
self.buffer.as_ref()[2]
}
pub fn ttl(&self) -> u8 {
self.buffer.as_ref()[3]
}
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[4..]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> NetPacket<B> {
pub fn set_version(&mut self, version: Version) {
self.buffer.as_mut()[0] = version.into();
}
pub fn set_protocol(&mut self, protocol: Protocol) {
self.buffer.as_mut()[1] = protocol.into();
}
pub fn set_transport_protocol(&mut self, transport_protocol: u8) {
self.buffer.as_mut()[2] = transport_protocol;
}
pub fn set_ttl(&mut self, ttl: u8) {
self.buffer.as_mut()[3] = ttl;
}
pub fn set_payload(&mut self, payload: &[u8]) {
self.buffer.as_mut()[4..payload.len() + 4].copy_from_slice(payload);
}
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[4..]
}
}
impl<B: AsRef<[u8]>> fmt::Debug for NetPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("NetPacket")
.field("version", &self.version())
.field("protocol", &self.protocol())
.field("transport_protocol", &self.transport_protocol())
.field("ttl", &self.ttl())
.field("payload", &self.payload())
.finish()
}
}
+32
View File
@@ -0,0 +1,32 @@
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub enum Protocol {
/// 注册请求
RegistrationRequest,
/// 注册响应
RegistrationResponse,
/// 更新设备列表
UpdateDeviceList,
UnKnow(u8),
}
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Self::RegistrationRequest,
2 => Self::RegistrationResponse,
3 => Self::UpdateDeviceList,
val => Self::UnKnow(val),
}
}
}
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Self::RegistrationRequest => 1,
Self::RegistrationResponse => 2,
Self::UpdateDeviceList => 3,
Self::UnKnow(val) => val,
}
}
}
+81
View File
@@ -0,0 +1,81 @@
use std::fmt;
use std::net::Ipv4Addr;
use crate::error::*;
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Protocol {
Punch,
UnKnow(u8),
}
impl From<u8> for Protocol {
fn from(value: u8) -> Self {
match value {
1 => Protocol::Punch,
val => Protocol::UnKnow(val),
}
}
}
impl Into<u8> for Protocol {
fn into(self) -> u8 {
match self {
Protocol::Punch => 1,
Protocol::UnKnow(val) => val,
}
}
}
pub struct TurnPacket<B> {
buffer: B,
}
impl<B: AsRef<[u8]>> TurnPacket<B> {
pub fn new(buffer: B) -> Result<TurnPacket<B>> {
let len = buffer.as_ref().len();
if len <= 8 {
return Err(Error::InvalidPacket);
}
Ok(Self { buffer })
}
}
impl<B: AsRef<[u8]>> TurnPacket<B> {
pub fn source(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[..4].try_into().unwrap();
Ipv4Addr::from(tmp)
}
pub fn destination(&self) -> Ipv4Addr {
let tmp: [u8; 4] = self.buffer.as_ref()[4..8].try_into().unwrap();
Ipv4Addr::from(tmp)
}
pub fn payload(&self) -> &[u8] {
&self.buffer.as_ref()[8..]
}
}
impl<B: AsRef<[u8]> + AsMut<[u8]>> TurnPacket<B> {
pub fn payload_mut(&mut self) -> &mut [u8] {
&mut self.buffer.as_mut()[8..]
}
pub fn set_source(&mut self, source: Ipv4Addr) {
self.buffer.as_mut()[..4].copy_from_slice(&source.octets());
}
pub fn set_destination(&mut self, destination: Ipv4Addr) {
self.buffer.as_mut()[4..8].copy_from_slice(&destination.octets());
}
pub fn set_payload(&mut self, payload: &[u8]) {
self.buffer.as_mut()[8..payload.len() + 8].copy_from_slice(payload)
}
}
impl<B: AsRef<[u8]>> fmt::Debug for TurnPacket<B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TurnPacket")
.field("source", &self.source())
.field("destination", &self.destination())
.field("payload", &self.payload())
.finish()
}
}
+39
View File
@@ -0,0 +1,39 @@
use std::io;
use std::io::{Error, Read, Write};
use std::net::Ipv4Addr;
use std::os::unix::process::CommandExt;
use std::process::Command;
use bytes::BufMut;
use tun::Device;
use tun::platform::posix::{Reader, Writer};
use crate::tun_device::{TunReader, TunWriter};
pub fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
) -> crate::error::Result<(TunWriter, TunReader)> {
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
.up();
config.platform(|config| {
config.packet_information(true);
});
let mut dev = tun::create(&config).unwrap();
let packet_information = dev.has_packet_information();
let (reader, writer) = dev.split();
Ok((
TunWriter(writer, packet_information),
TunReader(reader, packet_information),
))
}
+68
View File
@@ -0,0 +1,68 @@
use std::io;
use std::io::{Error, Read, Write};
use std::net::Ipv4Addr;
use std::os::unix::process::CommandExt;
use std::process::Command;
use bytes::BufMut;
use tun::Device;
use tun::platform::posix::{Reader, Writer};
use crate::tun_device::{TunReader, TunWriter};
pub fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
) -> crate::error::Result<(TunWriter, TunReader)> {
let mut config = tun::Configuration::default();
config
.destination(gateway)
.address(address)
.netmask(netmask)
.mtu(1420)
.up();
let dev = tun::create(&config).unwrap();
let up_eth_str: String = format!("ifconfig {} {:?} {:?} up ", dev.name(), address, gateway);
let route_add_str: String = format!(
"sudo route -n add -net {:?} -netmask {:?} {:?}",
address, netmask, gateway
);
let up_eth_out = Command::new("sh")
.arg("-c")
.arg(up_eth_str)
.output()
.expect("sh exec error!");
if !up_eth_out.status.success() {
return Err(crate::error::Error::Stop(format!("设置地址失败:{:?}", up_eth_out)));
}
let if_config_out = Command::new("sh")
.arg("-c")
.arg(route_add_str)
.output()
.expect("sh exec error!");
if !if_config_out.status.success() {
return Err(crate::error::Error::Stop(format!("设置路由失败:{:?}", if_config_out)));
}
// println!("{:?}", if_config_out);
// let cmd_str: String = " ifconfig|grep flags=8051|awk -F ':' '{print $1}'|tail -1".to_string();
//
// let cmd_str_out = Command::new("sh")
// .arg("-c")
// .arg(cmd_str)
// .output()
// .expect("sh exec error!");
// if !cmd_str_out.status.success(){
// return Err(Error::Stop(format!("设置路由失败:{:?}", cmd_str_out)));
// }
// println!("{:?}", cmd_str_out);
let packet_information = dev.has_packet_information();
let (reader, writer) = dev.split();
Ok((
TunWriter(writer, packet_information),
TunReader(reader, packet_information),
))
}
+19
View File
@@ -0,0 +1,19 @@
#[cfg(any(target_os = "linux",target_os = "android"))]
pub use linux::create_tun;
#[cfg(target_os = "macos")]
pub use mac::create_tun;
#[cfg(any(unix))]
pub use unix::{TunReader, TunWriter};
#[cfg(target_os = "windows")]
pub use windows::{TunReader, TunWriter};
#[cfg(target_os = "windows")]
pub use windows::create_tun;
#[cfg(target_os = "macos")]
pub mod mac;
#[cfg(any(target_os = "linux",target_os = "android"))]
pub mod linux;
#[cfg(any(unix))]
pub mod unix;
#[cfg(target_os = "windows")]
pub mod windows;
+37
View File
@@ -0,0 +1,37 @@
use std::io;
use std::io::{Read, Write};
use bytes::BufMut;
use tun::platform::posix::{Reader, Writer};
pub struct TunReader(pub(crate) Reader, pub(crate) bool);
impl TunReader {
pub fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> io::Result<&mut [u8]> {
let len = self.0.read(buf)?;
if self.1 {
Ok(&mut buf[4..len])
} else {
Ok(&mut buf[..len])
}
}
}
pub struct TunWriter(pub(crate) Writer, pub(crate) bool);
impl TunWriter {
pub fn write(&mut self, packet: &[u8]) -> io::Result<()> {
if self.1 {
let mut buf = Vec::<u8>::with_capacity(4 + packet.len());
buf.put_u16(0);
#[cfg(any(target_os = "macos", target_os = "ios"))]
buf.put_u16(libc::PF_INET as u16);
#[cfg(any(target_os = "linux", target_os = "android"))]
buf.put_u16(libc::ETH_P_IP as u16);
buf.extend_from_slice(packet);
self.0.write_all(&buf)
} else {
self.0.write_all(packet)
}
}
}
+132
View File
@@ -0,0 +1,132 @@
use std::io;
use std::net::Ipv4Addr;
use std::sync::Arc;
use libloading::Library;
use wintun::{Adapter, Packet, Session};
use crate::error::*;
pub struct TunWriter(Arc<Session>);
impl TunWriter {
pub fn write(&self, buf: &[u8]) -> io::Result<()> {
match self.0.allocate_send_packet(buf.len() as u16) {
Ok(mut packet) => {
packet.bytes_mut().copy_from_slice(buf);
self.0.send_packet(packet);
return Ok(());
}
Err(_) => {}
}
return Err(io::Error::new(io::ErrorKind::Other, "send err"));
}
}
pub struct TunReader(pub(crate) Arc<Session>);
impl TunReader {
pub fn next(&self) -> io::Result<Packet> {
match self.0.receive_blocking() {
Ok(packet) => {
return Ok(packet);
}
Err(_) => {}
}
return Err(io::Error::new(io::ErrorKind::Other, "read err"));
}
}
pub fn create_tun(
address: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
) -> Result<(TunWriter, TunReader)> {
let win_tun = unsafe {
match Library::new("wintun.dll") {
Ok(library) => match wintun::load_from_library(library) {
Ok(win_tun) => win_tun,
Err(e) => {
return Err(Error::Stop(format!("{:?}", e)));
}
},
Err(e) => {
log::error!("wintun.dll not found");
return Err(Error::Stop(format!("wintun.dll not found {:?}", e)));
}
}
};
let adapter = match Adapter::open(&win_tun, "Switch") {
Ok(a) => a,
Err(_) => match Adapter::create(&win_tun, "Switch", "Switch", None) {
Ok(adapter) => adapter,
Err(e) => return Err(Error::Stop(format!("{:?}", e))),
},
};
let index = adapter.get_adapter_index().unwrap();
let set_mtu = format!(
"netsh interface ipv4 set subinterface {} mtu=1420 store=persistent",
index
);
let set_metric = format!("netsh interface ip set interface {} metric=1", index);
let set_address = format!(
"netsh interface ip set address {} static {:?} {:?} ", // gateway={:?}
index, address, netmask,
);
// println!("{}", set_mtu);
// println!("{}", set_metric);
// println!("{}", set_address);
// 执行网卡初始化命令
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(set_mtu)
.output()
.unwrap();
if !out.status.success() {
return Err(Error::Stop(format!("设置mtu失败:{:?}", out)));
}
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(set_metric)
.output()
.unwrap();
if !out.status.success() {
return Err(Error::Stop(format!("设置接口跃点失败:{:?}", out)));
}
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(set_address)
.output()
.unwrap();
if !out.status.success() {
return Err(Error::Stop(format!("设置网络地址失败:{:?}", out)));
}
let dest = {
let ip = address.octets();
let mask = netmask.octets();
Ipv4Addr::from([
ip[0] & mask[0],
ip[1] & mask[1],
ip[2] & mask[2],
ip[3] & mask[3],
])
};
let set_route = format!(
"route add {:?} mask {:?} {:?} if {}",
dest, netmask, gateway, index
);
// println!("{}", set_route);
// 执行添加路由命令
let out = std::process::Command::new("cmd")
.arg("/C")
.arg(set_route)
.output()
.unwrap();
if !out.status.success() {
return Err(Error::Stop(format!("添加路由失败:{:?}", out)));
}
let session = Arc::new(adapter.start_session(wintun::MAX_RING_CAPACITY).unwrap());
let reader_session = session.clone();
Ok((TunWriter(session), TunReader(reader_session)))
}