支持ipv6服务端
This commit is contained in:
@@ -1,27 +1,26 @@
|
|||||||
|
use std::{io, thread};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::net::{Ipv4Addr, Shutdown, SocketAddr};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::net::UdpSocket as StdUdpSocket;
|
use std::net::UdpSocket as StdUdpSocket;
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
use crossbeam_utils::atomic::AtomicCell;
|
use crossbeam_utils::atomic::AtomicCell;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use tokio::net::UdpSocket;
|
use tokio::net::UdpSocket;
|
||||||
use tokio::sync::watch::{channel, Receiver, Sender};
|
use tokio::sync::watch::{channel, Receiver, Sender};
|
||||||
|
|
||||||
|
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID};
|
||||||
use crate::channel::punch::NatType;
|
use crate::channel::punch::NatType;
|
||||||
use crate::channel::{Route, RouteKey, Status, TCP_ID, UDP_ID, UDP_V6_ID};
|
|
||||||
use crate::core::status::VntWorker;
|
use crate::core::status::VntWorker;
|
||||||
use crate::handle::recv_handler::ChannelDataHandler;
|
|
||||||
use crate::handle::CurrentDeviceInfo;
|
use crate::handle::CurrentDeviceInfo;
|
||||||
|
use crate::handle::recv_handler::ChannelDataHandler;
|
||||||
|
|
||||||
pub struct ContextInner {
|
pub struct ContextInner {
|
||||||
//udp用于打洞、服务端通信(可选)
|
//udp用于打洞、服务端通信(可选)
|
||||||
pub(crate) main_channel: Arc<StdUdpSocket>,
|
pub(crate) main_channel: Arc<StdUdpSocket>,
|
||||||
pub(crate) main_channel_ipv6: Option<Arc<StdUdpSocket>>,
|
|
||||||
//在udp的基础上,可以选择使用tcp和服务端通信
|
//在udp的基础上,可以选择使用tcp和服务端通信
|
||||||
pub(crate) main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
|
pub(crate) main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
|
||||||
pub(crate) route_table: RwLock<HashMap<Ipv4Addr, Vec<(Route, AtomicCell<Instant>)>>>,
|
pub(crate) route_table: RwLock<HashMap<Ipv4Addr, Vec<(Route, AtomicCell<Instant>)>>>,
|
||||||
@@ -41,7 +40,6 @@ pub struct Context {
|
|||||||
impl Context {
|
impl Context {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
main_channel: Arc<StdUdpSocket>,
|
main_channel: Arc<StdUdpSocket>,
|
||||||
main_channel_ipv6: Option<Arc<StdUdpSocket>>,
|
|
||||||
main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
|
main_tcp_channel: Option<std::sync::mpsc::SyncSender<Vec<u8>>>,
|
||||||
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
current_device: Arc<AtomicCell<CurrentDeviceInfo>>,
|
||||||
_channel_num: usize,
|
_channel_num: usize,
|
||||||
@@ -52,7 +50,6 @@ impl Context {
|
|||||||
let (status_sender, status_receiver) = channel(Status::Cone);
|
let (status_sender, status_receiver) = channel(Status::Cone);
|
||||||
let inner = Arc::new(ContextInner {
|
let inner = Arc::new(ContextInner {
|
||||||
main_channel,
|
main_channel,
|
||||||
main_channel_ipv6,
|
|
||||||
main_tcp_channel,
|
main_tcp_channel,
|
||||||
route_table: RwLock::new(HashMap::with_capacity(16)),
|
route_table: RwLock::new(HashMap::with_capacity(16)),
|
||||||
status_receiver,
|
status_receiver,
|
||||||
@@ -75,18 +72,12 @@ impl Context {
|
|||||||
}
|
}
|
||||||
pub fn close(&self) -> io::Result<()> {
|
pub fn close(&self) -> io::Result<()> {
|
||||||
let _ = self.inner.status_sender.send(Status::Close);
|
let _ = self.inner.status_sender.send(Status::Close);
|
||||||
if let Ok(port) = self.main_local_ipv4_port() {
|
if let Ok(port) = self.main_local_udp_port() {
|
||||||
let _ = StdUdpSocket::bind("127.0.0.1:0")?.send_to(
|
let _ = StdUdpSocket::bind("127.0.0.1:0")?.send_to(
|
||||||
b"stop",
|
b"stop",
|
||||||
SocketAddr::V4(std::net::SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)),
|
SocketAddr::V4(std::net::SocketAddrV4::new(Ipv4Addr::LOCALHOST, port)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if let Ok(port) = self.main_local_ipv6_port() {
|
|
||||||
let _ = StdUdpSocket::bind("[::]:0")?.send_to(
|
|
||||||
b"stop",
|
|
||||||
SocketAddr::V6(std::net::SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if let Some(tcp) = &self.inner.main_tcp_channel {
|
if let Some(tcp) = &self.inner.main_tcp_channel {
|
||||||
let _ = tcp.send(vec![]);
|
let _ = tcp.send(vec![]);
|
||||||
}
|
}
|
||||||
@@ -111,32 +102,18 @@ impl Context {
|
|||||||
pub fn switch_to_symmetric(&self) {
|
pub fn switch_to_symmetric(&self) {
|
||||||
let _ = self.inner.status_sender.send(Status::Symmetric);
|
let _ = self.inner.status_sender.send(Status::Symmetric);
|
||||||
}
|
}
|
||||||
pub fn main_local_ipv4_port(&self) -> io::Result<u16> {
|
pub fn main_local_udp_port(&self) -> io::Result<u16> {
|
||||||
self.inner.main_channel.local_addr().map(|k| k.port())
|
self.inner.main_channel.local_addr().map(|k| k.port())
|
||||||
}
|
}
|
||||||
pub fn main_local_ipv6_port(&self) -> io::Result<u16> {
|
|
||||||
if let Some(ipv6) = &self.inner.main_channel_ipv6 {
|
|
||||||
ipv6.local_addr().map(|k| k.port())
|
|
||||||
} else {
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn insert_udp(&self, id: usize, udp: Arc<UdpSocket>) {
|
fn insert_udp(&self, id: usize, udp: Arc<UdpSocket>) {
|
||||||
self.inner.udp_map.write().insert(id, udp);
|
self.inner.udp_map.write().insert(id, udp);
|
||||||
}
|
}
|
||||||
fn remove_udp(&self, id: usize) {
|
fn remove_udp(&self, id: usize) {
|
||||||
self.inner.udp_map.write().remove(&id);
|
self.inner.udp_map.write().remove(&id);
|
||||||
}
|
}
|
||||||
|
#[inline]
|
||||||
pub fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
pub fn send_main_udp(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||||
if addr.is_ipv6() {
|
self.inner.main_channel.send_to(buf, addr)
|
||||||
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
|
||||||
udp_ipv6.send_to(buf, addr)
|
|
||||||
} else {
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6"))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.inner.main_channel.send_to(buf, addr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
pub fn send_main(&self, buf: &[u8], addr: SocketAddr) -> io::Result<usize> {
|
||||||
@@ -209,13 +186,6 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
|
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
|
||||||
UDP_V6_ID => {
|
|
||||||
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
|
||||||
udp_ipv6.send_to(buf, route_key.addr)
|
|
||||||
} else {
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(udp) = self.get_udp_by_route(route_key) {
|
if let Some(udp) = self.get_udp_by_route(route_key) {
|
||||||
return udp.send_to(buf, route_key.addr).await;
|
return udp.send_to(buf, route_key.addr).await;
|
||||||
@@ -238,13 +208,6 @@ impl Context {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
|
UDP_ID => self.inner.main_channel.send_to(buf, route_key.addr),
|
||||||
UDP_V6_ID => {
|
|
||||||
if let Some(udp_ipv6) = &self.inner.main_channel_ipv6 {
|
|
||||||
udp_ipv6.send_to(buf, route_key.addr)
|
|
||||||
} else {
|
|
||||||
Err(io::Error::new(io::ErrorKind::Other, "not ipv6 udp"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(udp) = self.get_udp_by_route(route_key) {
|
if let Some(udp) = self.get_udp_by_route(route_key) {
|
||||||
return udp.try_send_to(buf, route_key.addr);
|
return udp.try_send_to(buf, route_key.addr);
|
||||||
@@ -584,28 +547,6 @@ impl Channel {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
if let Some(main_channel_ipv6) = &context.inner.main_channel_ipv6 {
|
|
||||||
let worker = worker.worker("main_channel_ipv6");
|
|
||||||
let context = context.clone();
|
|
||||||
let main_channel_ipv6 = main_channel_ipv6.clone();
|
|
||||||
let handler = handler.clone();
|
|
||||||
let buf_sender = buf_sender.clone();
|
|
||||||
thread::Builder::new()
|
|
||||||
.name("ipv6-recv".into())
|
|
||||||
.spawn(move || {
|
|
||||||
log::info!("启动udp v6");
|
|
||||||
Self::main_start_(
|
|
||||||
worker,
|
|
||||||
context,
|
|
||||||
UDP_V6_ID,
|
|
||||||
main_channel_ipv6,
|
|
||||||
handler,
|
|
||||||
buf_sender,
|
|
||||||
head_reserve,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
let worker = worker.worker("main_channel_1");
|
let worker = worker.worker("main_channel_1");
|
||||||
let context = context.clone();
|
let context = context.clone();
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ pub mod sender;
|
|||||||
|
|
||||||
const TCP_ID: usize = 0;
|
const TCP_ID: usize = 0;
|
||||||
const UDP_ID: usize = 1;
|
const UDP_ID: usize = 1;
|
||||||
const UDP_V6_ID: usize = 2;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
|
|||||||
+7
-21
@@ -57,7 +57,6 @@ pub struct Vnt {
|
|||||||
pub struct VntUtil {
|
pub struct VntUtil {
|
||||||
config: Config,
|
config: Config,
|
||||||
main_channel: UdpSocket,
|
main_channel: UdpSocket,
|
||||||
main_channel_ipv6: Option<UdpSocket>,
|
|
||||||
main_tcp_channel: Option<TcpStream>,
|
main_tcp_channel: Option<TcpStream>,
|
||||||
response: Option<RegResponse>,
|
response: Option<RegResponse>,
|
||||||
iface: Option<(DeviceWriter, DeviceReader)>,
|
iface: Option<(DeviceWriter, DeviceReader)>,
|
||||||
@@ -67,24 +66,14 @@ pub struct VntUtil {
|
|||||||
|
|
||||||
impl VntUtil {
|
impl VntUtil {
|
||||||
pub fn new(config: Config) -> io::Result<VntUtil> {
|
pub fn new(config: Config) -> io::Result<VntUtil> {
|
||||||
|
let address: SocketAddr = format!("[::]:{}", config.port).parse().unwrap();
|
||||||
//单个udp用同步的性能更好,但是代理和多端口监听用异步更方便,这里将两者结合起来
|
//单个udp用同步的性能更好,但是代理和多端口监听用异步更方便,这里将两者结合起来
|
||||||
let main_channel = UdpSocket::bind(format!("0.0.0.0:{}", config.port))?;
|
let socket = socket2::Socket::new(socket2::Domain::IPV6,socket2::Type::DGRAM,None)?;
|
||||||
|
socket.set_only_v6(false)?;
|
||||||
|
socket.bind(&address.into())?;
|
||||||
|
let main_channel:UdpSocket = socket.into();
|
||||||
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
|
main_channel.set_write_timeout(Some(Duration::from_secs(5)))?;
|
||||||
main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
|
main_channel.set_read_timeout(Some(Duration::from_secs(2)))?;
|
||||||
let main_channel_ipv6 = if config.punch_model != PunchModel::IPv4 {
|
|
||||||
match UdpSocket::bind(format!("[::]:{}", config.port)) {
|
|
||||||
Ok(main_channel_ipv6) => {
|
|
||||||
main_channel_ipv6.set_write_timeout(Some(Duration::from_secs(5)))?;
|
|
||||||
Some(main_channel_ipv6)
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
log::warn!("绑定ipv6地址失败:{}", e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let server_cipher = if config.server_encrypt {
|
let server_cipher = if config.server_encrypt {
|
||||||
let mut key = [0u8; 32];
|
let mut key = [0u8; 32];
|
||||||
rand::thread_rng().fill(&mut key);
|
rand::thread_rng().fill(&mut key);
|
||||||
@@ -95,7 +84,6 @@ impl VntUtil {
|
|||||||
Ok(VntUtil {
|
Ok(VntUtil {
|
||||||
config,
|
config,
|
||||||
main_channel,
|
main_channel,
|
||||||
main_channel_ipv6,
|
|
||||||
main_tcp_channel: None,
|
main_tcp_channel: None,
|
||||||
response: None,
|
response: None,
|
||||||
iface: None,
|
iface: None,
|
||||||
@@ -256,7 +244,6 @@ impl VntUtil {
|
|||||||
};
|
};
|
||||||
let context = Context::new(
|
let context = Context::new(
|
||||||
Arc::new(self.main_channel),
|
Arc::new(self.main_channel),
|
||||||
self.main_channel_ipv6.map(|v| Arc::new(v)),
|
|
||||||
tcp_sender,
|
tcp_sender,
|
||||||
current_device.clone(),
|
current_device.clone(),
|
||||||
1,
|
1,
|
||||||
@@ -282,11 +269,10 @@ impl VntUtil {
|
|||||||
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
|
let connect_status = Arc::new(AtomicCell::new(ConnectStatus::Connected));
|
||||||
let public_ip = response.public_ip;
|
let public_ip = response.public_ip;
|
||||||
let public_port = response.public_port;
|
let public_port = response.public_port;
|
||||||
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
let local_port = context.main_local_udp_port().unwrap_or(0);
|
||||||
|
|
||||||
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
|
let local_ipv4_addr = crate::nat::local_ipv4_addr(local_port);
|
||||||
let ipv6_port = context.main_local_ipv6_port().unwrap_or(0);
|
let ipv6_addr = crate::nat::local_ipv6_addr(local_port);
|
||||||
let ipv6_addr = crate::nat::local_ipv6_addr(ipv6_port);
|
|
||||||
// NAT检测
|
// NAT检测
|
||||||
let nat_test = NatTest::new(
|
let nat_test = NatTest::new(
|
||||||
config.stun_server.clone(),
|
config.stun_server.clone(),
|
||||||
|
|||||||
@@ -592,9 +592,8 @@ impl ChannelDataHandler {
|
|||||||
.build()
|
.build()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.block_on(async move {
|
.block_on(async move {
|
||||||
let local_port = context.main_local_ipv4_port().unwrap_or(0);
|
let local_port = context.main_local_udp_port().unwrap_or(0);
|
||||||
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
|
let local_ipv4_addr = nat::local_ipv4_addr(local_port);
|
||||||
let local_port = context.main_local_ipv6_port().unwrap_or(0);
|
|
||||||
let ipv6_addr = nat::local_ipv6_addr(local_port);
|
let ipv6_addr = nat::local_ipv6_addr(local_port);
|
||||||
let nat_info = nat_test
|
let nat_info = nat_test
|
||||||
.re_test(
|
.re_test(
|
||||||
|
|||||||
Reference in New Issue
Block a user