13 Commits

Author SHA1 Message Date
eric
3c57300520 v0.10.11
Some checks failed
ci / test (macos-latest) (push) Has been cancelled
ci / test (ubuntu-latest) (push) Has been cancelled
ci / build-bin-cross (aarch64-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-cross (arm-unknown-linux-musleabi) (push) Has been cancelled
ci / build-bin-cross (armv7-unknown-linux-musleabihf) (push) Has been cancelled
ci / build-bin-cross (i686-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-cross (x86_64-pc-windows-gnu) (push) Has been cancelled
ci / build-bin-cross (x86_64-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-local (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
ci / build-apple (push) Has been cancelled
ci / build-android (push) Has been cancelled
releases / build-bin-cross (aarch64-unknown-linux-musl) (push) Has been cancelled
releases / build-bin-cross (x86_64-pc-windows-gnu) (push) Has been cancelled
releases / build-bin-cross (x86_64-unknown-linux-musl) (push) Has been cancelled
releases / build-bin-local (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
releases / build-apple (push) Has been cancelled
releases / build-android (push) Has been cancelled
releases / create-release (push) Has been cancelled
releases / release-bin (aarch64-unknown-linux-musl) (push) Has been cancelled
releases / release-bin (x86_64-apple-darwin) (push) Has been cancelled
releases / release-bin (x86_64-pc-windows-gnu) (push) Has been cancelled
releases / release-bin (x86_64-unknown-linux-musl) (push) Has been cancelled
releases / release-mobile-libs (push) Has been cancelled
2024-04-18 16:41:59 +08:00
eric
7757552bdc refactor: rename leaf-bin -> leaf-cli 2024-04-18 16:39:58 +08:00
eric
190727f325 net: fix domain resolving for datagram outbound address 2024-04-18 16:38:10 +08:00
eric
4d7908229b net: fixed socket bind 2024-04-13 03:57:21 +08:00
eric
988b280a85 chore: make sure cbindgen installed 2024-04-01 16:30:02 +08:00
Eric Corsican
86aee13347 v0.10.10
Some checks failed
ci / test (macos-latest) (push) Has been cancelled
ci / test (ubuntu-latest) (push) Has been cancelled
ci / build-bin-cross (aarch64-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-cross (arm-unknown-linux-musleabi) (push) Has been cancelled
ci / build-bin-cross (armv7-unknown-linux-musleabihf) (push) Has been cancelled
ci / build-bin-cross (i686-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-cross (x86_64-pc-windows-gnu) (push) Has been cancelled
ci / build-bin-cross (x86_64-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-local (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
ci / build-apple (push) Has been cancelled
ci / build-android (push) Has been cancelled
releases / build-bin-cross (aarch64-unknown-linux-musl) (push) Has been cancelled
releases / build-bin-cross (x86_64-pc-windows-gnu) (push) Has been cancelled
releases / build-bin-cross (x86_64-unknown-linux-musl) (push) Has been cancelled
releases / build-bin-local (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
releases / build-apple (push) Has been cancelled
releases / build-android (push) Has been cancelled
releases / create-release (push) Has been cancelled
releases / release-bin (aarch64-unknown-linux-musl) (push) Has been cancelled
releases / release-bin (x86_64-apple-darwin) (push) Has been cancelled
releases / release-bin (x86_64-pc-windows-gnu) (push) Has been cancelled
releases / release-bin (x86_64-unknown-linux-musl) (push) Has been cancelled
releases / release-mobile-libs (push) Has been cancelled
2024-04-01 16:03:53 +08:00
Xiaobo Liu
cc2e2c2776 docs: fix typo 2024-03-29 06:52:02 +08:00
eric
db75971b77 net: fix IPv6 2024-03-15 04:33:12 +08:00
eric
ae3e64c365 chore: fix rust-protobuf version 2024-02-27 10:21:00 +08:00
eric
3bbb5f7955 android: avoid UAF 2024-02-27 10:15:03 +08:00
eric
15cc8f9d2d android: avoid sending empty string to the logger 2024-02-27 10:07:18 +08:00
eric
2e7055bdd1 v0.10.9
Some checks failed
ci / test (macos-latest) (push) Has been cancelled
ci / test (ubuntu-latest) (push) Has been cancelled
ci / build-bin-cross (aarch64-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-cross (arm-unknown-linux-musleabi) (push) Has been cancelled
ci / build-bin-cross (armv7-unknown-linux-musleabihf) (push) Has been cancelled
ci / build-bin-cross (i686-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-cross (x86_64-pc-windows-gnu) (push) Has been cancelled
ci / build-bin-cross (x86_64-unknown-linux-musl) (push) Has been cancelled
ci / build-bin-local (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
ci / build-apple (push) Has been cancelled
ci / build-android (push) Has been cancelled
releases / build-bin-cross (aarch64-unknown-linux-musl) (push) Has been cancelled
releases / build-bin-cross (x86_64-pc-windows-gnu) (push) Has been cancelled
releases / build-bin-cross (x86_64-unknown-linux-musl) (push) Has been cancelled
releases / build-bin-local (macos-latest, x86_64-apple-darwin) (push) Has been cancelled
releases / build-apple (push) Has been cancelled
releases / build-android (push) Has been cancelled
releases / create-release (push) Has been cancelled
releases / release-bin (aarch64-unknown-linux-musl) (push) Has been cancelled
releases / release-bin (x86_64-apple-darwin) (push) Has been cancelled
releases / release-bin (x86_64-pc-windows-gnu) (push) Has been cancelled
releases / release-bin (x86_64-unknown-linux-musl) (push) Has been cancelled
releases / release-mobile-libs (push) Has been cancelled
2024-01-23 01:29:37 +08:00
eric
d834f500fa ci: remove mips 2024-01-23 01:29:21 +08:00
15 changed files with 187 additions and 108 deletions

View File

@@ -218,13 +218,8 @@ jobs:
matrix:
target:
- x86_64-apple-darwin
- mips-unknown-linux-musl
# - mipsel-unknown-linux-musl
- x86_64-unknown-linux-musl
# - i686-unknown-linux-musl
- aarch64-unknown-linux-musl
# - arm-unknown-linux-musleabi
# - armv7-unknown-linux-musleabihf
- x86_64-pc-windows-gnu
steps:
- name: download upload url

View File

@@ -1,11 +1,11 @@
[workspace]
members = [
"leaf",
"leaf-bin",
"leaf-cli",
"leaf-ffi",
"leaf-plugins/shadowsocks",
]
default-members = ["leaf-bin"]
default-members = ["leaf-cli"]
resolver = "2"
[profile.release]

View File

@@ -5,11 +5,11 @@ export CFG_COMMIT_HASH := $(CFG_COMMIT_HASH)
CFG_COMMIT_DATE := $(shell git log --format="%ci" -n 1)
export CFG_COMMIT_DATE := $(CFG_COMMIT_DATE)
local:
cargo build -p leaf-bin --release
cli:
cargo build -p leaf-cli --release
local-dev:
cargo build -p leaf-bin
cli-dev:
cargo build -p leaf-cli
test:
cargo test -p leaf -- --nocapture

View File

@@ -334,7 +334,7 @@ level 可以是 trace, debug, info, warn, error
"hosts": {
"example.com": [
"192.168.0.1",
"192.168.0.2
"192.168.0.2"
],
"server.com": [
"192.168.0.3"
@@ -1059,7 +1059,7 @@ V2Ray 的 `dat` 文件格式,可以有如下形式:
此外所有非组合类型的 outbound 必须正确配置一个 `bind` 地址,这是连接原网关的网卡的地址,即未连接 VPN 前网卡的 IP 地址:
```json
"outbounds: [
"outbounds": [
{
"bind": "192.168.0.99",
"protocol": "shadowsocks",

View File

@@ -1,6 +1,6 @@
[package]
name = "leaf-bin"
version = "0.10.8"
name = "leaf-cli"
version = "0.10.11"
authors = ["eycorsican <eric.y.corsican@gmail.com>"]
edition = "2021"

View File

@@ -125,7 +125,7 @@ ctrlc = ["tokio/signal"]
[dependencies]
# Common
tokio = { version = "1", features = ["sync", "io-util", "net", "time", "rt", "rt-multi-thread"] }
protobuf = "3.3.0"
protobuf = "=3.3.0"
thiserror = "1.0"
futures = "0.3"
async-trait = "0.1"
@@ -257,4 +257,4 @@ tokio = { version = "1", features = ["fs", "sync", "io-util", "net", "time", "rt
[build-dependencies]
cc = "1.0"
bindgen = "0.68"
protobuf-codegen = "3.3.0"
protobuf-codegen = "=3.3.0"

View File

@@ -6,7 +6,7 @@ use std::time::Duration;
use async_recursion::async_recursion;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::sync::RwLock;
use tracing::{debug, info, trace, warn};
use tracing::{debug, info, warn};
use crate::{
app::SyncDnsClient,
@@ -132,7 +132,7 @@ impl Dispatcher {
tag.to_owned()
}
Err(err) => {
trace!("pick route failed: {}", err);
debug!("pick route failed: {}", err);
if let Some(tag) = self.outbound_manager.read().await.default_handler() {
debug!(
"picked default route [{}] for {} -> {}",
@@ -267,7 +267,7 @@ impl Dispatcher {
tag.to_owned()
}
Err(err) => {
trace!("pick route failed: {}", err);
debug!("pick route failed: {}", err);
if let Some(tag) = self.outbound_manager.read().await.default_handler() {
debug!(
"picked default route [{}] for {} -> {}",

View File

@@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::net::{IpAddr, SocketAddr};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use std::num::NonZeroUsize;
use std::str::FromStr;
use std::sync::{Arc, Weak};
@@ -177,12 +177,21 @@ impl DnsClient {
server: &SocketAddr,
) -> Result<CacheEntry> {
let socket = if is_direct {
debug!("direct lookup");
let socket = self.new_udp_socket(server).await?;
Box::new(StdOutboundDatagram::new(socket))
} else {
debug!("dispatched lookup");
if let Some(dispatcher_weak) = self.dispatcher.as_ref() {
// The source address will be used to determine which address the
// underlying socket will bind.
let source = match server {
SocketAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
SocketAddr::V6(_) => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
};
let sess = Session {
network: Network::Udp,
source,
destination: SocksAddr::from(server),
inbound_tag: "internal".to_string(),
..Default::default()
@@ -265,7 +274,7 @@ impl DnsClient {
break;
};
let entry = CacheEntry { ips, deadline };
trace!("ips for {}:\n{:#?}", host, &entry);
debug!("ips for {}: {:#?}", host, &entry);
return Ok(entry);
} else {
// response with 0 records

View File

@@ -83,10 +83,9 @@ impl NatManager {
let n_removed = n_total - n_remaining;
drop(sessions); // release the lock
if n_removed > 0 {
trace!(
debug!(
"removed {} nat sessions, remaining {} sessions",
n_removed,
n_remaining
n_removed, n_remaining
);
}
tokio::time::sleep(Duration::from_secs(

View File

@@ -7,7 +7,7 @@ use cidr::IpCidr;
use futures::TryFutureExt;
use maxminddb::geoip2::Country;
use maxminddb::Mmap;
use tracing::{debug, trace, warn};
use tracing::{debug, warn};
use crate::app::SyncDnsClient;
use crate::config;
@@ -526,7 +526,7 @@ impl Router {
if !ips.is_empty() {
let mut new_sess = sess.clone();
new_sess.destination = SocksAddr::from((ips[0], sess.destination.port()));
trace!(
debug!(
"re-matching with resolved ip [{}] for [{}]",
ips[0],
sess.destination.host()

View File

@@ -29,18 +29,18 @@ fn log_out(data: &[u8]) {
#[cfg(target_os = "android")]
fn log_out(data: &[u8]) {
if data.is_empty() {
return;
}
unsafe {
let s = match ffi::CString::new(data) {
Ok(s) => s,
Err(_) => return,
};
const ANDROID_LOG_TAG: &str = "leaf";
let tag = ffi::CString::new("leaf").unwrap();
let _ = __android_log_print(
android_LogPriority_ANDROID_LOG_VERBOSE as std::os::raw::c_int,
ffi::CString::new(ANDROID_LOG_TAG)
.unwrap()
.as_c_str()
.as_ptr(),
tag.as_c_str().as_ptr(),
s.as_c_str().as_ptr(),
);
}

View File

@@ -68,28 +68,18 @@ impl OutboundDatagramSendHalf for StdOutboundDatagramSendHalf {
}
}
/// An outbound datagram simply wraps a UDP socket.
pub struct SimpleOutboundDatagram {
pub struct DomainResolveOutboundDatagram {
inner: UdpSocket,
destination: Option<SocksAddr>,
dns_client: SyncDnsClient,
}
impl SimpleOutboundDatagram {
pub fn new(
inner: UdpSocket,
destination: Option<SocksAddr>,
dns_client: SyncDnsClient,
) -> Self {
SimpleOutboundDatagram {
inner,
destination,
dns_client,
}
impl DomainResolveOutboundDatagram {
pub fn new(inner: UdpSocket, dns_client: SyncDnsClient) -> Self {
Self { inner, dns_client }
}
}
impl OutboundDatagram for SimpleOutboundDatagram {
impl OutboundDatagram for DomainResolveOutboundDatagram {
fn split(
self: Box<Self>,
) -> (
@@ -99,8 +89,100 @@ impl OutboundDatagram for SimpleOutboundDatagram {
let r = Arc::new(self.inner);
let s = r.clone();
(
Box::new(SimpleOutboundDatagramRecvHalf(r, self.destination)),
Box::new(SimpleOutboundDatagramSendHalf(s, self.dns_client)),
Box::new(DomainResolveOutboundDatagramRecvHalf(r)),
Box::new(DomainResolveOutboundDatagramSendHalf(s, self.dns_client)),
)
}
}
pub struct DomainResolveOutboundDatagramRecvHalf(Arc<UdpSocket>);
#[async_trait]
impl OutboundDatagramRecvHalf for DomainResolveOutboundDatagramRecvHalf {
async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocksAddr)> {
match self.0.recv_from(buf).await {
Ok((n, a)) => Ok((n, SocksAddr::Ip(unmapped_ipv4(a)))),
Err(e) => Err(e),
}
}
}
pub struct DomainResolveOutboundDatagramSendHalf(Arc<UdpSocket>, SyncDnsClient);
#[async_trait]
impl OutboundDatagramSendHalf for DomainResolveOutboundDatagramSendHalf {
async fn send_to(&mut self, buf: &[u8], target: &SocksAddr) -> io::Result<usize> {
match target {
SocksAddr::Domain(domain, port) => {
let ips = self
.1
.read()
.await
.direct_lookup(domain)
.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
format!("lookup {} failed: {}", domain, e),
)
})
.await?;
let ip = ips
.first()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no results"))?;
self.0.send_to(buf, SocketAddr::new(*ip, *port)).await
}
SocksAddr::Ip(addr) => self.0.send_to(buf, addr).await,
}
}
async fn close(&mut self) -> io::Result<()> {
Ok(())
}
}
/// An outbound datagram that sends to a domain target.
pub struct DomainAssociatedOutboundDatagram {
inner: UdpSocket,
source: SocketAddr,
destination: SocksAddr,
dns_client: SyncDnsClient,
}
impl DomainAssociatedOutboundDatagram {
pub fn new(
inner: UdpSocket,
source: SocketAddr,
destination: SocksAddr,
dns_client: SyncDnsClient,
) -> Self {
DomainAssociatedOutboundDatagram {
inner,
source,
destination,
dns_client,
}
}
}
impl OutboundDatagram for DomainAssociatedOutboundDatagram {
fn split(
self: Box<Self>,
) -> (
Box<dyn OutboundDatagramRecvHalf>,
Box<dyn OutboundDatagramSendHalf>,
) {
let r = Arc::new(self.inner);
let s = r.clone();
(
Box::new(DomainAssociatedOutboundDatagramRecvHalf(
r,
self.destination,
)),
Box::new(DomainAssociatedOutboundDatagramSendHalf(
s,
self.source,
self.dns_client,
)),
)
}
}
@@ -117,36 +199,30 @@ fn unmapped_ipv4(addr: SocketAddr) -> SocketAddr {
addr
}
pub struct SimpleOutboundDatagramRecvHalf(Arc<UdpSocket>, Option<SocksAddr>);
pub struct DomainAssociatedOutboundDatagramRecvHalf(Arc<UdpSocket>, SocksAddr);
#[async_trait]
impl OutboundDatagramRecvHalf for SimpleOutboundDatagramRecvHalf {
impl OutboundDatagramRecvHalf for DomainAssociatedOutboundDatagramRecvHalf {
async fn recv_from(&mut self, buf: &mut [u8]) -> io::Result<(usize, SocksAddr)> {
match self.0.recv_from(buf).await {
Ok((n, a)) => {
if self.1.is_some() {
Ok((n, self.1.as_ref().unwrap().clone()))
} else {
Ok((n, SocksAddr::Ip(unmapped_ipv4(a))))
}
}
Ok((n, _a)) => Ok((n, self.1.clone())),
Err(e) => Err(e),
}
}
}
pub struct SimpleOutboundDatagramSendHalf(Arc<UdpSocket>, SyncDnsClient);
pub struct DomainAssociatedOutboundDatagramSendHalf(Arc<UdpSocket>, SocketAddr, SyncDnsClient);
#[async_trait]
impl OutboundDatagramSendHalf for SimpleOutboundDatagramSendHalf {
impl OutboundDatagramSendHalf for DomainAssociatedOutboundDatagramSendHalf {
async fn send_to(&mut self, buf: &[u8], target: &SocksAddr) -> io::Result<usize> {
let addr = match target {
SocksAddr::Domain(domain, port) => {
let ips = {
self.1
self.2
.read()
.await
.lookup(domain)
.direct_lookup(domain)
.map_err(|e| {
io::Error::new(
io::ErrorKind::Other,
@@ -155,13 +231,20 @@ impl OutboundDatagramSendHalf for SimpleOutboundDatagramSendHalf {
})
.await?
};
if ips.is_empty() {
// FIXME Since FakeDns returns IPv4 address only, it's always bound
// to IPv4 address if FakeDns is used.
//
// If the socket was bound to an IPv4 address, we need an IPv4
// address for sending, and vice versa for IPv6.
let needs_ipv4 = self.1.is_ipv4();
if let Some(ip) = ips.into_iter().find(|x| x.is_ipv4() == needs_ipv4) {
SocketAddr::new(ip, port.to_owned())
} else {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"could not resolve to any address",
));
}
SocketAddr::new(ips[0], port.to_owned())
}
SocksAddr::Ip(a) => a.to_owned(),
};

View File

@@ -8,12 +8,12 @@ use async_trait::async_trait;
use futures::future::select_ok;
use futures::stream::Stream;
use futures::TryFutureExt;
use socket2::SockRef;
use socket2::{Domain, SockRef, Socket, Type};
use thiserror::Error;
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::net::{TcpSocket, TcpStream, UdpSocket};
use tokio::time::timeout;
use tracing::trace;
use tracing::debug;
#[cfg(unix)]
use std::os::unix::io::{AsFd, AsRawFd};
@@ -83,11 +83,7 @@ pub mod vmess;
#[cfg(any(feature = "inbound-ws", feature = "outbound-ws"))]
pub mod ws;
pub use datagram::{
SimpleInboundDatagram, SimpleInboundDatagramRecvHalf, SimpleInboundDatagramSendHalf,
SimpleOutboundDatagram, SimpleOutboundDatagramRecvHalf, SimpleOutboundDatagramSendHalf,
StdOutboundDatagram,
};
pub use datagram::*;
#[derive(Error, Debug)]
pub enum ProxyError {
@@ -207,12 +203,12 @@ async fn bind_socket<T: BindSocket>(socket: &T, indicator: &SocketAddr) -> io::R
match indicator.ip() {
IpAddr::V4(v4) if v4.is_loopback() => {
socket.bind(&SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 0).into())?;
trace!("socket bind loopback v4");
debug!("socket bind loopback v4");
return Ok(());
}
IpAddr::V6(v6) if v6.is_loopback() => {
socket.bind(&SocketAddrV6::new("::1".parse().unwrap(), 0, 0, 0).into())?;
trace!("socket bind loopback v6");
debug!("socket bind loopback v6");
return Ok(());
}
_ => {}
@@ -250,7 +246,7 @@ async fn bind_socket<T: BindSocket>(socket: &T, indicator: &SocketAddr) -> io::R
last_err = Some(io::Error::last_os_error());
continue;
}
trace!("socket bind {}", iface);
debug!("socket bind {}", iface);
return Ok(());
}
#[cfg(target_os = "linux")]
@@ -267,7 +263,7 @@ async fn bind_socket<T: BindSocket>(socket: &T, indicator: &SocketAddr) -> io::R
last_err = Some(io::Error::last_os_error());
continue;
}
trace!("socket bind {}", iface);
debug!("socket bind {}", iface);
return Ok(());
}
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
@@ -286,7 +282,7 @@ async fn bind_socket<T: BindSocket>(socket: &T, indicator: &SocketAddr) -> io::R
last_err = Some(e);
continue;
}
trace!("socket bind {}", addr);
debug!("socket bind {}", addr);
return Ok(());
}
}
@@ -302,26 +298,14 @@ async fn bind_socket<T: BindSocket>(socket: &T, indicator: &SocketAddr) -> io::R
// New UDP socket.
pub async fn new_udp_socket(indicator: &SocketAddr) -> io::Result<UdpSocket> {
use socket2::{Domain, Socket, Type};
let socket = if *option::ENABLE_IPV6 {
// Dual-stack socket.
// FIXME Windows IPV6_V6ONLY?
Socket::new(Domain::IPV6, Type::DGRAM, None)?
} else {
match indicator {
SocketAddr::V4(..) => Socket::new(Domain::IPV4, Type::DGRAM, None)?,
SocketAddr::V6(..) => Socket::new(Domain::IPV6, Type::DGRAM, None)?,
}
let socket = match indicator {
SocketAddr::V4(..) => Socket::new(Domain::IPV4, Type::DGRAM, None)?,
SocketAddr::V6(..) => Socket::new(Domain::IPV6, Type::DGRAM, None)?,
};
socket.set_nonblocking(true)?;
// If the proxy request is coming from an inbound listens on the loopback,
// the indicator could be a loopback address, we must ignore it.
if indicator.ip().is_loopback() || *option::ENABLE_IPV6 {
bind_socket(&socket, &*option::UNSPECIFIED_BIND_ADDR).await?;
} else {
bind_socket(&socket, indicator).await?;
}
bind_socket(&socket, indicator).await?;
#[cfg(target_os = "android")]
protect_socket(socket.as_raw_fd()).await?;
@@ -369,7 +353,7 @@ async fn tcp_dial_task(dial_addr: SocketAddr) -> io::Result<DialResult> {
#[cfg(target_os = "android")]
protect_socket(socket.as_raw_fd()).await?;
trace!("tcp dialing {}", &dial_addr);
debug!("tcp dialing {}", &dial_addr);
let start = tokio::time::Instant::now();
let stream = timeout(
Duration::from_secs(*option::OUTBOUND_DIAL_TIMEOUT),
@@ -380,7 +364,7 @@ async fn tcp_dial_task(dial_addr: SocketAddr) -> io::Result<DialResult> {
apply_socket_opts(&stream)?;
trace!(
debug!(
"tcp {} <-> {} connected in {}ms",
stream.local_addr()?,
&dial_addr,
@@ -423,7 +407,7 @@ pub async fn connect_datagram_outbound(
Network::Udp => {
let socket = new_udp_socket(&sess.source).await?;
Ok(Some(OutboundTransport::Datagram(Box::new(
SimpleOutboundDatagram::new(socket, None, dns_client.clone()),
DomainResolveOutboundDatagram::new(socket, dns_client.clone()),
))))
}
Network::Tcp => {
@@ -431,18 +415,25 @@ pub async fn connect_datagram_outbound(
Ok(Some(OutboundTransport::Stream(stream)))
}
},
OutboundConnect::Direct => {
let socket = new_udp_socket(&sess.source).await?;
let dest = match &sess.destination {
SocksAddr::Domain(domain, port) => {
Some(SocksAddr::Domain(domain.to_owned(), port.to_owned()))
}
_ => None,
};
Ok(Some(OutboundTransport::Datagram(Box::new(
SimpleOutboundDatagram::new(socket, dest, dns_client.clone()),
))))
}
OutboundConnect::Direct => match &sess.destination {
SocksAddr::Domain(domain, port) => {
let socket = new_udp_socket(&sess.source).await?;
Ok(Some(OutboundTransport::Datagram(Box::new(
DomainAssociatedOutboundDatagram::new(
socket,
sess.source.clone(),
SocksAddr::Domain(domain.to_owned(), port.to_owned()),
dns_client.clone(),
),
))))
}
SocksAddr::Ip(_) => {
let socket = new_udp_socket(&sess.source).await?;
Ok(Some(OutboundTransport::Datagram(Box::new(
StdOutboundDatagram::new(socket),
))))
}
},
_ => Ok(None),
}
}

View File

@@ -29,6 +29,8 @@ cargo build -p $package $release_flag --no-default-features --features "default-
cargo build -p $package $release_flag --no-default-features --features "default-openssl outbound-quic" --target x86_64-apple-ios
cargo build -p $package $release_flag --no-default-features --features "default-ring outbound-quic" --target aarch64-apple-ios-sim
cargo install --force cbindgen
# Directories to put the libraries.
rm -rf target/apple/$mode
mkdir -p target/apple/$mode/include