[mio] 支持仅使用p2p模式

This commit is contained in:
lubeilin
2024-03-01 21:48:07 +08:00
parent 9673eaab05
commit 119f719a9f
10 changed files with 119 additions and 38 deletions
+27 -6
View File
@@ -11,7 +11,7 @@ use parking_lot::RwLock;
use crate::channel::punch::NatType;
use crate::channel::sender::{AcceptSocketSender, ChannelSender, PacketSender};
use crate::channel::{Route, RouteKey};
use crate::channel::{Route, RouteKey, UseChannelType};
use crate::handle::{ConnectStatus, CurrentDeviceInfo};
/// 传输通道上下文,持有udp socket、tcp socket和路由信息
@@ -21,14 +21,19 @@ pub struct Context {
}
impl Context {
pub fn new(main_udp_socket: Vec<UdpSocket>, first_latency: bool, is_tcp: bool) -> Self {
pub fn new(
main_udp_socket: Vec<UdpSocket>,
use_channel_type: UseChannelType,
first_latency: bool,
is_tcp: bool,
) -> Self {
let channel_num = main_udp_socket.len();
assert_ne!(channel_num, 0, "not channel");
let inner = ContextInner {
main_udp_socket,
sub_udp_socket: RwLock::new(Vec::with_capacity(64)),
tcp_map: RwLock::new(HashMap::with_capacity(64)),
route_table: RouteTable::new(first_latency, channel_num),
route_table: RouteTable::new(use_channel_type, first_latency, channel_num),
is_tcp,
};
Self {
@@ -123,14 +128,14 @@ impl ContextInner {
loop {
let status = if self.route_table.route_one(&cur.virtual_gateway).is_some() {
//已连接
if cur.status == ConnectStatus::Connected {
if cur.status.online() {
return cur;
}
//状态变为已连接
ConnectStatus::Connected
} else {
//未连接
if cur.status == ConnectStatus::Connecting {
if cur.status.offline() {
return cur;
}
//状态变为未连接
@@ -246,12 +251,14 @@ pub struct RouteTable {
RwLock<HashMap<Ipv4Addr, (AtomicUsize, Vec<(Route, AtomicCell<Instant>)>)>>,
first_latency: bool,
channel_num: usize,
use_channel_type: UseChannelType,
}
impl RouteTable {
fn new(first_latency: bool, channel_num: usize) -> Self {
fn new(use_channel_type: UseChannelType, first_latency: bool, channel_num: usize) -> Self {
Self {
route_table: RwLock::new(HashMap::with_capacity(64)),
use_channel_type,
first_latency,
channel_num,
}
@@ -295,6 +302,20 @@ impl RouteTable {
self.add_route_(id, route, false)
}
fn add_route_(&self, id: Ipv4Addr, route: Route, only_if_absent: bool) {
// 限制通道类型
match self.use_channel_type {
UseChannelType::Relay => {
if route.metric < 2 {
return;
}
}
UseChannelType::P2p => {
if route.metric != 1 {
return;
}
}
UseChannelType::All => {}
}
let key = route.route_key();
let mut route_table = self.route_table.write();
let (_, list) = route_table
+36 -1
View File
@@ -1,5 +1,6 @@
use std::io;
use std::net::{SocketAddr, UdpSocket};
use std::str::FromStr;
use std::time::Duration;
use crate::channel::context::Context;
@@ -19,7 +20,40 @@ pub mod tcp_channel;
pub mod udp_channel;
const BUFFER_SIZE: usize = 1024 * 16;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum UseChannelType {
Relay,
P2p,
All,
}
impl UseChannelType {
pub fn is_only_relay(&self) -> bool {
self == &UseChannelType::Relay
}
pub fn is_only_p2p(&self) -> bool {
self == &UseChannelType::P2p
}
pub fn is_all(&self) -> bool {
self == &UseChannelType::All
}
}
impl FromStr for UseChannelType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().trim() {
"relay" => Ok(UseChannelType::Relay),
"p2p" => Ok(UseChannelType::P2p),
"all" => Ok(UseChannelType::All),
_ => Err(format!("not match '{}', enum: relay/p2p/all", s)),
}
}
}
impl Default for UseChannelType {
fn default() -> Self {
UseChannelType::All
}
}
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Status {
Cone,
@@ -104,6 +138,7 @@ impl RouteKey {
pub fn init_context(
ports: Vec<u16>,
use_channel_type: UseChannelType,
first_latency: bool,
is_tcp: bool,
) -> io::Result<(Context, mio::net::TcpListener)> {
@@ -123,7 +158,7 @@ pub fn init_context(
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
udps.push(main_channel);
}
let context = Context::new(udps, first_latency, is_tcp);
let context = Context::new(udps, use_channel_type, first_latency, is_tcp);
let port = context.main_local_udp_port()?[0];
//监听v6+v4双栈,tcp通道使用异步io
+2 -1
View File
@@ -24,7 +24,8 @@ impl FromStr for PunchModel {
match s.to_lowercase().trim() {
"ipv4" => Ok(PunchModel::IPv4),
"ipv6" => Ok(PunchModel::IPv6),
_ => Ok(PunchModel::All),
"all" => Ok(PunchModel::All),
_ => Err(format!("not match '{}', enum: ipv4/ipv6/all", s)),
}
}
}
+13 -8
View File
@@ -15,7 +15,7 @@ use tun::device::IFace;
use crate::channel::context::Context;
use crate::channel::idle::Idle;
use crate::channel::punch::{NatInfo, Punch};
use crate::channel::{init_channel, init_context, Route, RouteKey};
use crate::channel::{init_channel, init_context, Route, RouteKey, UseChannelType};
use crate::cipher::Cipher;
#[cfg(feature = "server_encrypt")]
use crate::cipher::RsaCipher;
@@ -87,7 +87,12 @@ impl Vnt {
}
});
//通道上下文
let (context, tcp_listener) = init_context(ports, config.first_latency, config.tcp)?;
let (context, tcp_listener) = init_context(
ports,
config.use_channel_type,
config.first_latency,
config.tcp,
)?;
let local_ipv4 = nat::local_ipv4();
let local_ipv6 = nat::local_ipv6();
let udp_ports = context.main_local_udp_port()?;
@@ -143,7 +148,7 @@ impl Vnt {
config_info.clone(),
nat_test.clone(),
callback.clone(),
config.relay,
config.use_channel_type,
punch_sender,
peer_nat_info_map.clone(),
external_route.clone(),
@@ -192,8 +197,8 @@ impl Vnt {
let nat_test = nat_test.clone();
let device_list = device_list.clone();
let current_device = current_device.clone();
let relay = config.relay;
if !relay {
let use_channel_type = config.use_channel_type;
if !use_channel_type.is_only_relay() {
// 定时nat探测
maintain::retrieve_nat_type(
&scheduler,
@@ -216,7 +221,7 @@ impl Vnt {
config_info,
punch,
callback,
relay,
use_channel_type,
);
});
}
@@ -247,7 +252,7 @@ pub fn start<Call: VntCallback>(
config_info: BaseConfigInfo,
punch: Punch,
callback: Call,
relay: bool,
use_channel_type: UseChannelType,
) {
// 定时心跳
maintain::heartbeat(
@@ -284,7 +289,7 @@ pub fn start<Call: VntCallback>(
server_cipher.clone(),
config_info.clone(),
);
if !relay {
if !use_channel_type.is_only_relay() {
// 定时打洞
maintain::punch(
&scheduler,
+4 -3
View File
@@ -4,6 +4,7 @@ use std::net::{Ipv4Addr, SocketAddr};
pub use conn::Vnt;
use crate::channel::punch::PunchModel;
use crate::channel::UseChannelType;
use crate::cipher::CipherModel;
mod conn;
@@ -24,7 +25,6 @@ pub struct Config {
pub mtu: Option<u32>,
pub tcp: bool,
pub ip: Option<Ipv4Addr>,
pub relay: bool,
#[cfg(feature = "ip_proxy")]
pub no_proxy: bool,
pub server_encrypt: bool,
@@ -38,6 +38,7 @@ pub struct Config {
pub device_name: Option<String>,
#[cfg(target_os = "android")]
pub device_fd: i32,
pub use_channel_type: UseChannelType,
}
impl Config {
@@ -55,7 +56,6 @@ impl Config {
mtu: Option<u32>,
tcp: bool,
ip: Option<Ipv4Addr>,
relay: bool,
#[cfg(feature = "ip_proxy")] no_proxy: bool,
server_encrypt: bool,
parallel: usize,
@@ -66,6 +66,7 @@ impl Config {
first_latency: bool,
#[cfg(not(target_os = "android"))] device_name: Option<String>,
#[cfg(target_os = "android")] device_fd: i32,
use_channel_type: UseChannelType,
) -> io::Result<Self> {
for x in stun_server.iter_mut() {
if !x.contains(":") {
@@ -96,7 +97,6 @@ impl Config {
mtu,
tcp,
ip,
relay,
#[cfg(feature = "ip_proxy")]
no_proxy,
server_encrypt,
@@ -110,6 +110,7 @@ impl Config {
device_name,
#[cfg(target_os = "android")]
device_fd,
use_channel_type,
})
}
}
+7 -7
View File
@@ -15,7 +15,7 @@ use tun::Device;
use crate::channel::context::Context;
use crate::channel::punch::NatInfo;
use crate::channel::{Route, RouteKey};
use crate::channel::{Route, RouteKey, UseChannelType};
use crate::cipher::Cipher;
use crate::external_route::AllowExternalRoute;
use crate::handle::recv_data::PacketHandler;
@@ -35,7 +35,7 @@ use crate::protocol::{
pub struct ClientPacketHandler {
device: Arc<Device>,
client_cipher: Cipher,
relay: bool,
use_channel_type: UseChannelType,
punch_sender: SyncSender<(Ipv4Addr, NatInfo)>,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
nat_test: NatTest,
@@ -48,7 +48,7 @@ impl ClientPacketHandler {
pub fn new(
device: Arc<Device>,
client_cipher: Cipher,
relay: bool,
use_channel_type: UseChannelType,
punch_sender: SyncSender<(Ipv4Addr, NatInfo)>,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
nat_test: NatTest,
@@ -58,7 +58,7 @@ impl ClientPacketHandler {
Self {
device,
client_cipher,
relay,
use_channel_type,
punch_sender,
peer_nat_info_map,
nat_test,
@@ -189,7 +189,7 @@ impl ClientPacketHandler {
context.route_table.add_route(source, route);
}
ControlPacket::PunchRequest => {
if self.relay {
if self.use_channel_type.is_only_relay() {
return Ok(());
}
//回应
@@ -203,7 +203,7 @@ impl ClientPacketHandler {
context.route_table.add_route_if_absent(source, route);
}
ControlPacket::PunchResponse => {
if self.relay {
if self.use_channel_type.is_only_relay() {
return Ok(());
}
let route = Route::from(route_key, 1, 199);
@@ -237,7 +237,7 @@ impl ClientPacketHandler {
net_packet: NetPacket<&mut [u8]>,
route_key: RouteKey,
) -> io::Result<()> {
if self.relay {
if self.use_channel_type.is_only_relay() {
return Ok(());
}
let source = net_packet.source();
+3 -3
View File
@@ -12,7 +12,7 @@ use tun::Device;
use crate::channel::context::Context;
use crate::channel::handler::RecvChannelHandler;
use crate::channel::punch::NatInfo;
use crate::channel::RouteKey;
use crate::channel::{RouteKey, UseChannelType};
use crate::cipher::Cipher;
#[cfg(feature = "server_encrypt")]
use crate::cipher::RsaCipher;
@@ -60,7 +60,7 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
config_info: BaseConfigInfo,
nat_test: NatTest,
callback: Call,
relay: bool,
use_channel_type: UseChannelType,
punch_sender: SyncSender<(Ipv4Addr, NatInfo)>,
peer_nat_info_map: Arc<RwLock<HashMap<Ipv4Addr, NatInfo>>>,
external_route: ExternalRoute,
@@ -83,7 +83,7 @@ impl<Call: VntCallback> RecvDataHandler<Call> {
let client = ClientPacketHandler::new(
device.clone(),
client_cipher,
relay,
use_channel_type,
punch_sender,
peer_nat_info_map,
nat_test,