fix: bump msrv to 1.88 (#2054)

This commit is contained in:
Aaron Chen
2025-12-09 02:19:35 +08:00
committed by GitHub
parent 04b3ad8504
commit aa9156a794
27 changed files with 103 additions and 148 deletions

View File

@@ -30,9 +30,9 @@ jobs:
- name: Install Rust - name: Install Rust
run: | run: |
rustup set profile minimal rustup set profile minimal
rustup toolchain install 1.85 rustup toolchain install 1.88
rustup default 1.85 rustup default 1.88
rustup override set 1.85 rustup override set 1.88
- name: Build with All Features Enabled (Unix) - name: Build with All Features Enabled (Unix)
if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }} if: ${{ runner.os == 'Linux' || runner.os == 'macOS' }}
run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline" run: cargo build --verbose --features "full-extra local-flow-stat utility-url-outline"
@@ -63,9 +63,9 @@ jobs:
- name: Install Rust - name: Install Rust
run: | run: |
rustup set profile minimal rustup set profile minimal
rustup toolchain install 1.85 rustup toolchain install 1.88
rustup default 1.85 rustup default 1.88
rustup override set 1.85 rustup override set 1.88
- name: Build with All Features Enabled - name: Build with All Features Enabled
run: cargo build --manifest-path crates/shadowsocks-service/Cargo.toml --verbose --features "full dns-over-tls dns-over-https dns-over-h3 local-dns local-flow-stat local-http-rustls local-tun local-fake-dns local-online-config stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect" run: cargo build --manifest-path crates/shadowsocks-service/Cargo.toml --verbose --features "full dns-over-tls dns-over-https dns-over-h3 local-dns local-flow-stat local-http-rustls local-tun local-fake-dns local-online-config stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect"
@@ -92,8 +92,8 @@ jobs:
- name: Install Rust - name: Install Rust
run: | run: |
rustup set profile minimal rustup set profile minimal
rustup toolchain install 1.85 rustup toolchain install 1.88
rustup default 1.85 rustup default 1.88
rustup override set 1.85 rustup override set 1.88
- name: Build with All Features Enabled - name: Build with All Features Enabled
run: cargo build --manifest-path crates/shadowsocks/Cargo.toml --verbose --features "stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect" run: cargo build --manifest-path crates/shadowsocks/Cargo.toml --verbose --features "stream-cipher aead-cipher-extra aead-cipher-2022 aead-cipher-2022-extra security-replay-attack-detect"

View File

@@ -9,7 +9,7 @@ documentation = "https://docs.rs/shadowsocks-rust"
keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"]
license = "MIT" license = "MIT"
edition = "2024" edition = "2024"
rust-version = "1.85" rust-version = "1.88"
[badges] [badges]
maintenance = { status = "passively-maintained" } maintenance = { status = "passively-maintained" }

View File

@@ -18,8 +18,8 @@ fn main() -> ExitCode {
.about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)"); .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)");
// Allow running `ssservice` as symlink of `sslocal`, `ssserver` and `ssmanager` // Allow running `ssservice` as symlink of `sslocal`, `ssserver` and `ssmanager`
if let Some(program_path) = env::args().next() { if let Some(program_path) = env::args().next()
if let Some(program_name) = Path::new(&program_path).file_name() { && let Some(program_name) = Path::new(&program_path).file_name() {
match program_name.to_str() { match program_name.to_str() {
Some("sslocal") => return local::main(&local::define_command_line_options(app).get_matches()), Some("sslocal") => return local::main(&local::define_command_line_options(app).get_matches()),
Some("ssserver") => return server::main(&server::define_command_line_options(app).get_matches()), Some("ssserver") => return server::main(&server::define_command_line_options(app).get_matches()),
@@ -27,7 +27,6 @@ fn main() -> ExitCode {
_ => {} _ => {}
} }
} }
}
let matches = app let matches = app
.subcommand_required(true) .subcommand_required(true)

View File

@@ -1 +1 @@
msrv = "1.85" msrv = "1.88"

View File

@@ -9,7 +9,7 @@ documentation = "https://docs.rs/shadowsocks-service"
keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"]
license = "MIT" license = "MIT"
edition = "2024" edition = "2024"
rust-version = "1.85" rust-version = "1.88"
[badges] [badges]
maintenance = { status = "passively-maintained" } maintenance = { status = "passively-maintained" }

View File

@@ -208,15 +208,14 @@ impl ParsingRules {
return; return;
} }
} }
} else if let Some(set_rule) = caps.get(2) { } else if let Some(set_rule) = caps.get(2)
if let Ok(set_rule) = str::from_utf8(set_rule.as_bytes()) { && let Ok(set_rule) = str::from_utf8(set_rule.as_bytes()) {
let set_rule = set_rule.replace("\\.", "."); let set_rule = set_rule.replace("\\.", ".");
if self.add_set_rule_inner(&set_rule).is_ok() { if self.add_set_rule_inner(&set_rule).is_ok() {
trace!("REGEX-RULE {} => SET-RULE {}", rule, set_rule); trace!("REGEX-RULE {} => SET-RULE {}", rule, set_rule);
return; return;
} }
} }
}
} }
trace!("REGEX-RULE {}", rule); trace!("REGEX-RULE {}", rule);

View File

@@ -2388,9 +2388,9 @@ impl Config {
} }
// Security // Security
if let Some(sec) = config.security { if let Some(sec) = config.security
if let Some(replay_attack) = sec.replay_attack { && let Some(replay_attack) = sec.replay_attack
if let Some(policy) = replay_attack.policy { && let Some(policy) = replay_attack.policy {
match policy.parse::<ReplayAttackPolicy>() { match policy.parse::<ReplayAttackPolicy>() {
Ok(p) => nconfig.security.replay_attack.policy = p, Ok(p) => nconfig.security.replay_attack.policy = p,
Err(..) => { Err(..) => {
@@ -2399,8 +2399,6 @@ impl Config {
} }
} }
} }
}
}
if let Some(balancer) = config.balancer { if let Some(balancer) = config.balancer {
nconfig.balancer = BalancerConfig { nconfig.balancer = BalancerConfig {
@@ -2620,19 +2618,17 @@ impl Config {
} }
// Balancer related checks // Balancer related checks
if let Some(rtt) = self.balancer.max_server_rtt { if let Some(rtt) = self.balancer.max_server_rtt
if rtt.as_secs() == 0 { && rtt.as_secs() == 0 {
let err = Error::new(ErrorKind::Invalid, "balancer.max_server_rtt must be > 0", None); let err = Error::new(ErrorKind::Invalid, "balancer.max_server_rtt must be > 0", None);
return Err(err); return Err(err);
} }
}
if let Some(intv) = self.balancer.check_interval { if let Some(intv) = self.balancer.check_interval
if intv.as_secs() == 0 { && intv.as_secs() == 0 {
let err = Error::new(ErrorKind::Invalid, "balancer.check_interval must be > 0", None); let err = Error::new(ErrorKind::Invalid, "balancer.check_interval must be > 0", None);
return Err(err); return Err(err);
} }
}
} }
if self.config_type.is_server() && self.server.is_empty() { if self.config_type.is_server() && self.server.is_empty() {
@@ -2667,12 +2663,11 @@ impl Config {
let server = &inst.config; let server = &inst.config;
// Plugin shouldn't be an empty string // Plugin shouldn't be an empty string
if let Some(plugin) = server.plugin() { if let Some(plugin) = server.plugin()
if plugin.plugin.trim().is_empty() { && plugin.plugin.trim().is_empty() {
let err = Error::new(ErrorKind::Malformed, "`plugin` shouldn't be an empty string", None); let err = Error::new(ErrorKind::Malformed, "`plugin` shouldn't be an empty string", None);
return Err(err); return Err(err);
} }
}
// Server's domain name shouldn't be an empty string // Server's domain name shouldn't be an empty string
match server.addr() { match server.addr() {
@@ -3072,14 +3067,13 @@ impl fmt::Display for Config {
jconf.mode = Some(m.mode.to_string()); jconf.mode = Some(m.mode.to_string());
} }
if jconf.method.is_none() { if jconf.method.is_none()
if let Some(ref m) = m.method { && let Some(ref m) = m.method {
jconf.method = Some(m.to_string()); jconf.method = Some(m.to_string());
} }
}
if jconf.plugin.is_none() { if jconf.plugin.is_none()
if let Some(ref p) = m.plugin { && let Some(ref p) = m.plugin {
jconf.plugin = Some(p.plugin.clone()); jconf.plugin = Some(p.plugin.clone());
if let Some(ref o) = p.plugin_opts { if let Some(ref o) = p.plugin_opts {
jconf.plugin_opts = Some(o.clone()); jconf.plugin_opts = Some(o.clone());
@@ -3088,7 +3082,6 @@ impl fmt::Display for Config {
jconf.plugin_args = Some(p.plugin_args.clone()); jconf.plugin_args = Some(p.plugin_args.clone());
} }
} }
}
} }
if self.no_delay { if self.no_delay {
@@ -3194,8 +3187,8 @@ impl fmt::Display for Config {
/// If value is in format `${VAR_NAME}` then it will try to read from `VAR_NAME` environment variable. /// If value is in format `${VAR_NAME}` then it will try to read from `VAR_NAME` environment variable.
/// It will return the original value if fails to read `${VAR_NAME}`. /// It will return the original value if fails to read `${VAR_NAME}`.
pub fn read_variable_field_value(value: &str) -> Cow<'_, str> { pub fn read_variable_field_value(value: &str) -> Cow<'_, str> {
if let Some(left_over) = value.strip_prefix("${") { if let Some(left_over) = value.strip_prefix("${")
if let Some(var_name) = left_over.strip_suffix('}') { && let Some(var_name) = left_over.strip_suffix('}') {
match env::var(var_name) { match env::var(var_name) {
Ok(value) => return value.into(), Ok(value) => return value.into(),
Err(err) => { Err(err) => {
@@ -3206,7 +3199,6 @@ pub fn read_variable_field_value(value: &str) -> Cow<'_, str> {
} }
} }
} }
}
value.into() value.into()
} }

View File

@@ -163,11 +163,10 @@ impl PingBalancerBuilder {
} }
pub async fn build(self) -> io::Result<PingBalancer> { pub async fn build(self) -> io::Result<PingBalancer> {
if let Some(intv) = self.check_best_interval { if let Some(intv) = self.check_best_interval
if intv > self.check_interval { && intv > self.check_interval {
return Err(io::Error::other("check_interval must be >= check_best_interval")); return Err(io::Error::other("check_interval must be >= check_best_interval"));
} }
}
let (shared_context, task_abortable) = PingBalancerContext::new( let (shared_context, task_abortable) = PingBalancerContext::new(
self.servers, self.servers,

View File

@@ -193,7 +193,7 @@ impl ServerStat {
vlat_abs_diff.sort_unstable(); vlat_abs_diff.sort_unstable();
let abs_diff_median_mid = vlat_abs_diff.len() / 2; let abs_diff_median_mid = vlat_abs_diff.len() / 2;
self.data.latency_mad = if vlat_abs_diff.len() % 2 == 0 { self.data.latency_mad = if vlat_abs_diff.len().is_multiple_of(2) {
(vlat_abs_diff[abs_diff_median_mid] + vlat_abs_diff[abs_diff_median_mid - 1]) / 2 (vlat_abs_diff[abs_diff_median_mid] + vlat_abs_diff[abs_diff_median_mid - 1]) / 2
} else { } else {
vlat_abs_diff[abs_diff_median_mid] vlat_abs_diff[abs_diff_median_mid]

View File

@@ -515,12 +515,11 @@ where
} }
}; };
if UDP_SOCKET_SUPPORT_DUAL_STACK { if UDP_SOCKET_SUPPORT_DUAL_STACK
if let SocketAddr::V4(saddr) = target_addr { && let SocketAddr::V4(saddr) = target_addr {
let mapped_ip = saddr.ip().to_ipv6_mapped(); let mapped_ip = saddr.ip().to_ipv6_mapped();
target_addr = SocketAddr::V6(SocketAddrV6::new(mapped_ip, saddr.port(), 0, 0)); target_addr = SocketAddr::V6(SocketAddrV6::new(mapped_ip, saddr.port(), 0, 0));
} }
}
let n = socket.send_to(data, target_addr).await?; let n = socket.send_to(data, target_addr).await?;
if n != data.len() { if n != data.len() {

View File

@@ -214,15 +214,14 @@ impl OnlineConfigService {
// Check plugin whitelist // Check plugin whitelist
if let Some(ref allowed_plugins) = self.allowed_plugins { if let Some(ref allowed_plugins) = self.allowed_plugins {
for server in &online_config.server { for server in &online_config.server {
if let Some(plugin) = server.config.plugin() { if let Some(plugin) = server.config.plugin()
if !allowed_plugins.contains(&plugin.plugin) { && !allowed_plugins.contains(&plugin.plugin) {
error!( error!(
"server-loader task found not allowed plugin: {}, url: {}", "server-loader task found not allowed plugin: {}, url: {}",
plugin.plugin, self.config_url plugin.plugin, self.config_url
); );
return Err(io::Error::other(format!("not allowed plugin: {}", plugin.plugin))); return Err(io::Error::other(format!("not allowed plugin: {}", plugin.plugin)));
} }
}
} }
} }

View File

@@ -63,11 +63,10 @@ async fn handle_redir_client(
// Get forward address from socket // Get forward address from socket
// //
// Try to convert IPv4 mapped IPv6 address for dual-stack mode. // Try to convert IPv4 mapped IPv6 address for dual-stack mode.
if let SocketAddr::V6(ref a) = daddr { if let SocketAddr::V6(ref a) = daddr
if let Some(v4) = to_ipv4_mapped(a.ip()) { && let Some(v4) = to_ipv4_mapped(a.ip()) {
daddr = SocketAddr::new(IpAddr::from(v4), a.port()); daddr = SocketAddr::new(IpAddr::from(v4), a.port());
} }
}
let target_addr = Address::from(daddr); let target_addr = Address::from(daddr);
establish_client_tcp_redir(context, balancer, s, peer_addr, &target_addr).await establish_client_tcp_redir(context, balancer, s, peer_addr, &target_addr).await
} }

View File

@@ -296,11 +296,10 @@ impl RedirUdpServer {
} }
// Try to convert IPv4 mapped IPv6 address for dual-stack mode. // Try to convert IPv4 mapped IPv6 address for dual-stack mode.
if let SocketAddr::V6(ref a) = dst { if let SocketAddr::V6(ref a) = dst
if let Some(v4) = to_ipv4_mapped(a.ip()) { && let Some(v4) = to_ipv4_mapped(a.ip()) {
dst = SocketAddr::new(IpAddr::from(v4), a.port()); dst = SocketAddr::new(IpAddr::from(v4), a.port());
} }
}
if let Err(err) = manager.send_to(src, Address::from(dst), pkt).await { if let Err(err) = manager.send_to(src, Address::from(dst), pkt).await {
debug!( debug!(

View File

@@ -71,8 +71,8 @@ impl UdpRedirSocket {
socket.set_nonblocking(true)?; socket.set_nonblocking(true)?;
socket.set_reuse_address(true)?; socket.set_reuse_address(true)?;
if reuse_port { if reuse_port
if let Err(err) = socket.set_reuse_port(true) { && let Err(err) = socket.set_reuse_port(true) {
if let Some(libc::ENOPROTOOPT) = err.raw_os_error() { if let Some(libc::ENOPROTOOPT) = err.raw_os_error() {
// SO_REUSEPORT is supported after 3.9 // SO_REUSEPORT is supported after 3.9
trace!("failed to set SO_REUSEPORT, error: {}", err); trace!("failed to set SO_REUSEPORT, error: {}", err);
@@ -81,7 +81,6 @@ impl UdpRedirSocket {
return Err(err); return Err(err);
} }
} }
}
let sock_addr = SockAddr::from(addr); let sock_addr = SockAddr::from(addr);

View File

@@ -52,8 +52,8 @@ impl UdpRedirSocket {
socket.set_nonblocking(true)?; socket.set_nonblocking(true)?;
socket.set_reuse_address(true)?; socket.set_reuse_address(true)?;
if reuse_port { if reuse_port
if let Err(err) = socket.set_reuse_port(true) { && let Err(err) = socket.set_reuse_port(true) {
if let Some(libc::ENOPROTOOPT) = err.raw_os_error() { if let Some(libc::ENOPROTOOPT) = err.raw_os_error() {
trace!("failed to set SO_REUSEPORT, error: {}", err); trace!("failed to set SO_REUSEPORT, error: {}", err);
} else { } else {
@@ -61,7 +61,6 @@ impl UdpRedirSocket {
return Err(err); return Err(err);
} }
} }
}
let sock_addr = SockAddr::from(addr); let sock_addr = SockAddr::from(addr);

View File

@@ -159,11 +159,10 @@ impl AsyncRead for TcpConnection {
} }
// Nothing could be read. Wait for notify. // Nothing could be read. Wait for notify.
if let Some(old_waker) = control.recv_waker.replace(cx.waker().clone()) { if let Some(old_waker) = control.recv_waker.replace(cx.waker().clone())
if !old_waker.will_wake(cx.waker()) { && !old_waker.will_wake(cx.waker()) {
old_waker.wake(); old_waker.wake();
} }
}
return Poll::Pending; return Poll::Pending;
} }
@@ -191,11 +190,10 @@ impl AsyncWrite for TcpConnection {
// Write to buffer // Write to buffer
if control.send_buffer.is_full() { if control.send_buffer.is_full() {
if let Some(old_waker) = control.send_waker.replace(cx.waker().clone()) { if let Some(old_waker) = control.send_waker.replace(cx.waker().clone())
if !old_waker.will_wake(cx.waker()) { && !old_waker.will_wake(cx.waker()) {
old_waker.wake(); old_waker.wake();
} }
}
return Poll::Pending; return Poll::Pending;
} }
@@ -224,11 +222,10 @@ impl AsyncWrite for TcpConnection {
control.send_state = TcpSocketState::Close; control.send_state = TcpSocketState::Close;
} }
if let Some(old_waker) = control.send_waker.replace(cx.waker().clone()) { if let Some(old_waker) = control.send_waker.replace(cx.waker().clone())
if !old_waker.will_wake(cx.waker()) { && !old_waker.will_wake(cx.waker()) {
old_waker.wake(); old_waker.wake();
} }
}
self.manager_notify.notify(); self.manager_notify.notify();
Poll::Pending Poll::Pending
@@ -421,11 +418,10 @@ impl TcpTun {
wake_receiver = true; wake_receiver = true;
} }
if wake_receiver && control.recv_waker.is_some() { if wake_receiver && control.recv_waker.is_some()
if let Some(waker) = control.recv_waker.take() { && let Some(waker) = control.recv_waker.take() {
waker.wake(); waker.wake();
} }
}
// Check if writable // Check if writable
let mut wake_sender = false; let mut wake_sender = false;
@@ -456,11 +452,10 @@ impl TcpTun {
} }
} }
if wake_sender && control.send_waker.is_some() { if wake_sender && control.send_waker.is_some()
if let Some(waker) = control.send_waker.take() { && let Some(waker) = control.send_waker.take() {
waker.wake(); waker.wake();
} }
}
} }
for socket_handle in sockets_to_remove { for socket_handle in sockets_to_remove {
@@ -601,11 +596,10 @@ async fn handle_redir_client(
// Get forward address from socket // Get forward address from socket
// //
// Try to convert IPv4 mapped IPv6 address for dual-stack mode. // Try to convert IPv4 mapped IPv6 address for dual-stack mode.
if let SocketAddr::V6(ref a) = daddr { if let SocketAddr::V6(ref a) = daddr
if let Some(v4) = to_ipv4_mapped(a.ip()) { && let Some(v4) = to_ipv4_mapped(a.ip()) {
daddr = SocketAddr::new(IpAddr::from(v4), a.port()); daddr = SocketAddr::new(IpAddr::from(v4), a.port());
} }
}
let target_addr = Address::from(daddr); let target_addr = Address::from(daddr);
establish_client_tcp_redir(context, balancer, s, peer_addr, &target_addr).await establish_client_tcp_redir(context, balancer, s, peer_addr, &target_addr).await
} }

View File

@@ -329,8 +329,8 @@ impl Manager {
}; };
let pid_path = self.server_pid_path(port); let pid_path = self.server_pid_path(port);
if pid_path.exists() { if pid_path.exists()
if let Ok(mut pid_file) = File::open(&pid_path) { && let Ok(mut pid_file) = File::open(&pid_path) {
let mut pid_content = String::new(); let mut pid_content = String::new();
if pid_file.read_to_string(&mut pid_content).is_ok() { if pid_file.read_to_string(&mut pid_content).is_ok() {
let pid_content = pid_content.trim(); let pid_content = pid_content.trim();
@@ -346,7 +346,6 @@ impl Manager {
} }
} }
} }
}
let server_config_path = self.server_config_path(port); let server_config_path = self.server_config_path(port);

View File

@@ -593,15 +593,14 @@ impl UdpAssociationContext {
data: &[u8], data: &[u8],
control: &Option<UdpSocketControlData>, control: &Option<UdpSocketControlData>,
) { ) {
if let Some(ref mut session) = self.client_session { if let Some(ref mut session) = self.client_session
if peer_addr != self.peer_addr { && peer_addr != self.peer_addr {
debug!( debug!(
"udp relay for {} changed to {}, session: {:?}", "udp relay for {} changed to {}, session: {:?}",
self.peer_addr, peer_addr, session.client_session_id self.peer_addr, peer_addr, session.client_session_id
); );
self.peer_addr = peer_addr; self.peer_addr = peer_addr;
} }
}
trace!( trace!(
"udp relay {} -> {} with {} bytes, control: {:?}", "udp relay {} -> {} with {} bytes, control: {:?}",
@@ -737,11 +736,10 @@ impl UdpAssociationContext {
// It is an undefined behavior in shadowsocks' protocol about how to handle IPv4-mapped-IPv6. // It is an undefined behavior in shadowsocks' protocol about how to handle IPv4-mapped-IPv6.
// But for some implementations, they may expect the target address to be IPv4, because // But for some implementations, they may expect the target address to be IPv4, because
// the peer address is IPv4 when calling `sendto`. // the peer address is IPv4 when calling `sendto`.
if let Address::SocketAddress(SocketAddr::V6(ref v6)) = addr { if let Address::SocketAddress(SocketAddr::V6(ref v6)) = addr
if let Some(v4) = to_ipv4_mapped(v6.ip()) { && let Some(v4) = to_ipv4_mapped(v6.ip()) {
addr = Address::SocketAddress(SocketAddr::new(v4.into(), v6.port())); addr = Address::SocketAddress(SocketAddr::new(v4.into(), v6.port()));
} }
}
match self.client_session { match self.client_session {
None => { None => {

View File

@@ -9,7 +9,7 @@ documentation = "https://docs.rs/shadowsocks-core"
keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"] keywords = ["shadowsocks", "proxy", "socks", "socks5", "firewall"]
license = "MIT" license = "MIT"
edition = "2024" edition = "2024"
rust-version = "1.85" rust-version = "1.88"
[badges] [badges]
maintenance = { status = "passively-maintained" } maintenance = { status = "passively-maintained" }

View File

@@ -695,21 +695,19 @@ impl ServerConfig {
/// Get server's TCP external address /// Get server's TCP external address
pub fn tcp_external_addr(&self) -> &ServerAddr { pub fn tcp_external_addr(&self) -> &ServerAddr {
if let Some(plugin) = self.plugin() { if let Some(plugin) = self.plugin()
if plugin.plugin_mode.enable_tcp() { && plugin.plugin_mode.enable_tcp() {
return self.plugin_addr.as_ref().unwrap_or(&self.addr); return self.plugin_addr.as_ref().unwrap_or(&self.addr);
} }
}
&self.addr &self.addr
} }
/// Get server's UDP external address /// Get server's UDP external address
pub fn udp_external_addr(&self) -> &ServerAddr { pub fn udp_external_addr(&self) -> &ServerAddr {
if let Some(plugin) = self.plugin() { if let Some(plugin) = self.plugin()
if plugin.plugin_mode.enable_udp() { && plugin.plugin_mode.enable_udp() {
return self.plugin_addr.as_ref().unwrap_or(&self.addr); return self.plugin_addr.as_ref().unwrap_or(&self.addr);
} }
}
&self.addr &self.addr
} }

View File

@@ -167,15 +167,14 @@ static IP_STACK_CAPABILITIES: LazyLock<IpStackCapabilities> = LazyLock::new(|| {
} }
// Check IPv6 (::1) // Check IPv6 (::1)
if let Ok(ipv6_socket) = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP)) { if let Ok(ipv6_socket) = Socket::new(Domain::IPV6, Type::STREAM, Some(Protocol::TCP))
if ipv6_socket.set_only_v6(true).is_ok() { && ipv6_socket.set_only_v6(true).is_ok() {
let local_host = SockAddr::from(SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 0)); let local_host = SockAddr::from(SocketAddr::new(Ipv6Addr::LOCALHOST.into(), 0));
if ipv6_socket.bind(&local_host).is_ok() { if ipv6_socket.bind(&local_host).is_ok() {
caps.support_ipv6 = true; caps.support_ipv6 = true;
debug!("IpStackCapability support_ipv6=true"); debug!("IpStackCapability support_ipv6=true");
} }
} }
}
// Check IPv4-mapped-IPv6 (127.0.0.1) // Check IPv4-mapped-IPv6 (127.0.0.1)
if check_ipv4_mapped_ipv6_capability().is_ok() { if check_ipv4_mapped_ipv6_capability().is_ok() {

View File

@@ -390,11 +390,10 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOp
UdpSocket::from_std(socket.into())? UdpSocket::from_std(socket.into())?
}; };
if !config.udp.allow_fragmentation { if !config.udp.allow_fragmentation
if let Err(err) = set_disable_ip_fragmentation(af, &socket) { && let Err(err) = set_disable_ip_fragmentation(af, &socket) {
warn!("failed to disable IP fragmentation, error: {}", err); warn!("failed to disable IP fragmentation, error: {}", err);
} }
}
// Set IP_BOUND_IF for BSD-like // Set IP_BOUND_IF for BSD-like
if let Some(ref iface) = config.bind_interface { if let Some(ref iface) = config.bind_interface {

View File

@@ -310,11 +310,10 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOp
UdpSocket::from_std(socket.into())? UdpSocket::from_std(socket.into())?
}; };
if !config.udp.allow_fragmentation { if !config.udp.allow_fragmentation
if let Err(err) = set_disable_ip_fragmentation(af, &socket) { && let Err(err) = set_disable_ip_fragmentation(af, &socket) {
warn!("failed to disable IP fragmentation, error: {}", err); warn!("failed to disable IP fragmentation, error: {}", err);
} }
}
// Any traffic except localhost should be protected // Any traffic except localhost should be protected
// This is a workaround for VPNService // This is a workaround for VPNService

View File

@@ -189,11 +189,10 @@ impl UdpSocket {
/// Wrapper of `UdpSocket::poll_send` /// Wrapper of `UdpSocket::poll_send`
pub fn poll_send(&self, cx: &mut TaskContext<'_>, buf: &[u8]) -> Poll<io::Result<usize>> { pub fn poll_send(&self, cx: &mut TaskContext<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
// Check MTU // Check MTU
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if buf.len() > mtu { && buf.len() > mtu {
return Err(make_mtu_error(buf.len(), mtu)).into(); return Err(make_mtu_error(buf.len(), mtu)).into();
} }
}
self.socket.poll_send(cx, buf) self.socket.poll_send(cx, buf)
} }
@@ -202,11 +201,10 @@ impl UdpSocket {
#[inline] #[inline]
pub async fn send(&self, buf: &[u8]) -> io::Result<usize> { pub async fn send(&self, buf: &[u8]) -> io::Result<usize> {
// Check MTU // Check MTU
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if buf.len() > mtu { && buf.len() > mtu {
return Err(make_mtu_error(buf.len(), mtu)); return Err(make_mtu_error(buf.len(), mtu));
} }
}
self.socket.send(buf).await self.socket.send(buf).await
} }
@@ -214,11 +212,10 @@ impl UdpSocket {
/// Wrapper of `UdpSocket::poll_send_to` /// Wrapper of `UdpSocket::poll_send_to`
pub fn poll_send_to(&self, cx: &mut TaskContext<'_>, buf: &[u8], target: SocketAddr) -> Poll<io::Result<usize>> { pub fn poll_send_to(&self, cx: &mut TaskContext<'_>, buf: &[u8], target: SocketAddr) -> Poll<io::Result<usize>> {
// Check MTU // Check MTU
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if buf.len() > mtu { && buf.len() > mtu {
return Err(make_mtu_error(buf.len(), mtu)).into(); return Err(make_mtu_error(buf.len(), mtu)).into();
} }
}
self.socket.poll_send_to(cx, buf, target) self.socket.poll_send_to(cx, buf, target)
} }
@@ -227,11 +224,10 @@ impl UdpSocket {
#[inline] #[inline]
pub async fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], target: A) -> io::Result<usize> { pub async fn send_to<A: ToSocketAddrs>(&self, buf: &[u8], target: A) -> io::Result<usize> {
// Check MTU // Check MTU
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if buf.len() > mtu { && buf.len() > mtu {
return Err(make_mtu_error(buf.len(), mtu)); return Err(make_mtu_error(buf.len(), mtu));
} }
}
self.socket.send_to(buf, target).await self.socket.send_to(buf, target).await
} }
@@ -241,11 +237,10 @@ impl UdpSocket {
pub fn poll_recv(&self, cx: &mut TaskContext<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> { pub fn poll_recv(&self, cx: &mut TaskContext<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<()>> {
ready!(self.socket.poll_recv(cx, buf))?; ready!(self.socket.poll_recv(cx, buf))?;
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if buf.filled().len() > mtu { && buf.filled().len() > mtu {
return Err(make_mtu_error(buf.filled().len(), mtu)).into(); return Err(make_mtu_error(buf.filled().len(), mtu)).into();
} }
}
Ok(()).into() Ok(()).into()
} }
@@ -255,11 +250,10 @@ impl UdpSocket {
pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
let n = self.socket.recv(buf).await?; let n = self.socket.recv(buf).await?;
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if n > mtu { && n > mtu {
return Err(make_mtu_error(n, mtu)); return Err(make_mtu_error(n, mtu));
} }
}
Ok(n) Ok(n)
} }
@@ -269,11 +263,10 @@ impl UdpSocket {
pub fn poll_recv_from(&self, cx: &mut TaskContext<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<SocketAddr>> { pub fn poll_recv_from(&self, cx: &mut TaskContext<'_>, buf: &mut ReadBuf<'_>) -> Poll<io::Result<SocketAddr>> {
let addr = ready!(self.socket.poll_recv_from(cx, buf))?; let addr = ready!(self.socket.poll_recv_from(cx, buf))?;
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if buf.filled().len() > mtu { && buf.filled().len() > mtu {
return Err(make_mtu_error(buf.filled().len(), mtu)).into(); return Err(make_mtu_error(buf.filled().len(), mtu)).into();
} }
}
Ok(addr).into() Ok(addr).into()
} }
@@ -283,11 +276,10 @@ impl UdpSocket {
pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
let (n, addr) = self.socket.recv_from(buf).await?; let (n, addr) = self.socket.recv_from(buf).await?;
if let Some(mtu) = self.mtu { if let Some(mtu) = self.mtu
if n > mtu { && n > mtu {
return Err(make_mtu_error(n, mtu)); return Err(make_mtu_error(n, mtu));
} }
}
Ok((n, addr)) Ok((n, addr))
} }

View File

@@ -159,11 +159,10 @@ where
// Wakeup writer task because we have already received the salt // Wakeup writer task because we have already received the salt
#[cfg(feature = "aead-cipher-2022")] #[cfg(feature = "aead-cipher-2022")]
if let ProxyServerStreamWriteState::PrepareHeader(waker) = this.writer_state { if let ProxyServerStreamWriteState::PrepareHeader(waker) = this.writer_state
if let Some(waker) = waker.take() { && let Some(waker) = waker.take() {
waker.wake(); waker.wake();
} }
}
Ok(()).into() Ok(()).into()
} }
@@ -190,11 +189,10 @@ where
*(this.writer_state) = ProxyServerStreamWriteState::Established; *(this.writer_state) = ProxyServerStreamWriteState::Established;
} else { } else {
// Reader didn't receive the salt from client yet. // Reader didn't receive the salt from client yet.
if let Some(waker) = waker.take() { if let Some(waker) = waker.take()
if !waker.will_wake(cx.waker()) { && !waker.will_wake(cx.waker()) {
waker.wake(); waker.wake();
} }
}
*waker = Some(cx.waker().clone()); *waker = Some(cx.waker().clone());
return Poll::Pending; return Poll::Pending;
} }

View File

@@ -755,17 +755,15 @@ pub fn create(matches: &ArgMatches) -> ShadowsocksResult<(Runtime, impl Future<O
#[cfg(feature = "local-redir")] #[cfg(feature = "local-redir")]
{ {
if RedirType::tcp_default() != RedirType::NotSupported { if RedirType::tcp_default() != RedirType::NotSupported
if let Some(tcp_redir) = matches.get_one::<String>("TCP_REDIR") { && let Some(tcp_redir) = matches.get_one::<String>("TCP_REDIR") {
local_config.tcp_redir = tcp_redir.parse::<RedirType>().expect("tcp-redir"); local_config.tcp_redir = tcp_redir.parse::<RedirType>().expect("tcp-redir");
} }
}
if RedirType::udp_default() != RedirType::NotSupported { if RedirType::udp_default() != RedirType::NotSupported
if let Some(udp_redir) = matches.get_one::<String>("UDP_REDIR") { && let Some(udp_redir) = matches.get_one::<String>("UDP_REDIR") {
local_config.udp_redir = udp_redir.parse::<RedirType>().expect("udp-redir"); local_config.udp_redir = udp_redir.parse::<RedirType>().expect("udp-redir");
} }
}
} }
#[cfg(feature = "local-dns")] #[cfg(feature = "local-dns")]

View File

@@ -404,17 +404,15 @@ pub fn create(matches: &ArgMatches) -> ShadowsocksResult<(Runtime, impl Future<O
} }
// Overrides // Overrides
if matches.get_flag("UDP_ONLY") { if matches.get_flag("UDP_ONLY")
if let Some(ref mut m) = config.manager { && let Some(ref mut m) = config.manager {
m.mode = Mode::UdpOnly; m.mode = Mode::UdpOnly;
} }
}
if matches.get_flag("TCP_AND_UDP") { if matches.get_flag("TCP_AND_UDP")
if let Some(ref mut m) = config.manager { && let Some(ref mut m) = config.manager {
m.mode = Mode::TcpAndUdp; m.mode = Mode::TcpAndUdp;
} }
}
if let Some(acl_file) = matches.get_one::<String>("ACL") { if let Some(acl_file) = matches.get_one::<String>("ACL") {
let acl = AccessControl::load_from_file(acl_file) let acl = AccessControl::load_from_file(acl_file)