Skip to content

Allow user to pass SocketProtector callback function for android #1972

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions crates/shadowsocks/src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub use self::{
tcp::{TcpListener, TcpStream},
udp::UdpSocket,
};
#[cfg(target_os = "android")]
pub use self::option::android::{CloneFn, SocketProtectFn, socket_protect_fn};

mod option;
mod sys;
Expand Down
55 changes: 55 additions & 0 deletions crates/shadowsocks/src/net/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub struct ConnectOpts {
/// This is an [Android shadowsocks implementation](https://github.com/shadowsocks/shadowsocks-android) specific feature
#[cfg(target_os = "android")]
pub vpn_protect_path: Option<std::path::PathBuf>,
#[cfg(target_os = "android")]
pub vpn_socket_protect_fn: Option<android::SocketProtectFn<Box<dyn android::CloneFn>>>,

/// Outbound socket binds to this IP address, mostly for choosing network interfaces
///
Expand Down Expand Up @@ -87,3 +89,56 @@ pub struct AcceptOpts {
/// Enable IPV6_V6ONLY option for socket
pub ipv6_only: bool,
}

#[cfg(target_os = "android")]
pub mod android {
pub fn socket_protect_fn<F>(f: F) -> SocketProtectFn<Box<dyn CloneFn>>
where
F: Fn(i32) + Send + Sync + Clone + 'static,
{
SocketProtectFn {
f: Box::new(f),
}
}

pub trait CloneFn: Fn(i32) + Send + Sync {
fn clone_box(&self) -> Box<dyn CloneFn>;
}

impl<F: Clone + Send + Sync + 'static> CloneFn for F
where
F: Fn(i32),
{
fn clone_box(&self) -> Box<dyn CloneFn> {
Box::new(self.clone())
}
}

pub struct SocketProtectFn<F> {
f: F,
}

impl<F> SocketProtectFn<F>
where
F: Fn(i32) + Send + Sync + Clone + 'static
{
pub fn call(&self, fd: i32) {
(self.f)(fd)
}
}

impl Clone for SocketProtectFn<Box<dyn CloneFn>>
{
fn clone(&self) -> Self {
Self {
f: self.f.clone_box(),
}
}
}

impl<F> std::fmt::Debug for SocketProtectFn<F> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SocketProtectFn").finish()
}
}
}
8 changes: 8 additions & 0 deletions crates/shadowsocks/src/net/sys/unix/linux/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ impl TcpStream {
Err(..) => return Err(io::Error::new(ErrorKind::TimedOut, "protect() timeout")),
}
}

if let Some(ref protect_fn) = opts.vpn_socket_protect_fn {
protect_fn.call(socket.as_raw_fd());
}
}

// Set SO_MARK for mark-based routing on Linux (since 2.6.25)
Expand Down Expand Up @@ -344,6 +348,10 @@ pub async fn bind_outbound_udp_socket(bind_addr: &SocketAddr, config: &ConnectOp
Err(..) => return Err(io::Error::new(ErrorKind::TimedOut, "protect() timeout")),
}
}

if let Some(ref protect_fn) = opts.vpn_socket_protect_fn {
protect_fn.call(socket.as_raw_fd());
}
}

// Set SO_MARK for mark-based routing on Linux (since 2.6.25)
Expand Down
Loading