diff --git a/src/android.rs b/src/android.rs index ea7f165..4f642c8 100644 --- a/src/android.rs +++ b/src/android.rs @@ -1,12 +1,15 @@ #![cfg(target_os = "android")] -use crate::{error::Error, main_entry, shutdown, NetworkInterface, Options, Proxy}; +use crate::tun2proxy::TunToProxy; +use crate::{error::Error, tun_to_proxy, NetworkInterface, Options, Proxy}; use jni::{ objects::{JClass, JString}, sys::{jboolean, jint}, JNIEnv, }; +static mut TUN_TO_PROXY: Option = None; + /// # Safety /// /// Running tun2proxy @@ -42,7 +45,11 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_run( let options = Options::new().with_virtual_dns().with_mtu(tun_mtu as usize); let interface = NetworkInterface::Fd(tun_fd); - _ = main_entry(&interface, &proxy, options)?; + let tun2proxy = tun_to_proxy(&interface, &proxy, options)?; + TUN_TO_PROXY = Some(tun2proxy); + if let Some(tun2proxy) = &mut TUN_TO_PROXY { + tun2proxy.run()?; + } Ok::<(), Error>(()) }; if let Err(error) = block() { @@ -59,11 +66,19 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_stop( _env: JNIEnv, _clazz: JClass, ) -> jint { - if let Err(e) = shutdown() { - log::error!("failed to shutdown tun2proxy with error: {:?}", e); - 1 - } else { - 0 + match &mut TUN_TO_PROXY { + None => { + log::error!("tun2proxy not started"); + 1 + } + Some(tun2proxy) => { + if let Err(e) = tun2proxy.shutdown() { + log::error!("failed to shutdown tun2proxy with error: {:?}", e); + 1 + } else { + 0 + } + } } } diff --git a/src/lib.rs b/src/lib.rs index 3f24b92..1c8bb00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,11 +123,11 @@ impl Credentials { } } -pub fn main_entry( +pub fn tun_to_proxy<'a>( interface: &NetworkInterface, proxy: &Proxy, options: Options, -) -> Result<(), Error> { +) -> Result, Error> { let mut ttp = TunToProxy::new(interface, options)?; match proxy.proxy_type { ProxyType::Socks4 => { @@ -148,9 +148,14 @@ pub fn main_entry( ttp.add_connection_manager(HttpManager::new(proxy.addr, proxy.credentials.clone())); } } - ttp.run() + Ok(ttp) } -pub fn shutdown() -> Result<(), Error> { - TunToProxy::shutdown() +pub fn main_entry( + interface: &NetworkInterface, + proxy: &Proxy, + options: Options, +) -> Result<(), Error> { + let ttp = tun_to_proxy(interface, proxy, options); + ttp?.run() } diff --git a/src/tun2proxy.rs b/src/tun2proxy.rs index 7ceb256..402759b 100644 --- a/src/tun2proxy.rs +++ b/src/tun2proxy.rs @@ -242,13 +242,11 @@ pub(crate) trait ConnectionManager { fn get_credentials(&self) -> &Option; } -const TCP_TOKEN: Token = Token(0); +const TUN_TOKEN: Token = Token(0); const UDP_TOKEN: Token = Token(1); const EXIT_TOKEN: Token = Token(2); -const EXIT_LISTENER: &str = "127.0.0.1:34255"; - -pub(crate) struct TunToProxy<'a> { +pub struct TunToProxy<'a> { tun: TunTapInterface, poll: Poll, iface: Interface, @@ -260,11 +258,12 @@ pub(crate) struct TunToProxy<'a> { device: VirtualTunDevice, options: Options, write_sockets: HashSet, - _exit_listener: mio::net::TcpListener, + _exit_receiver: mio::unix::pipe::Receiver, + exit_sender: mio::unix::pipe::Sender, } impl<'a> TunToProxy<'a> { - pub(crate) fn new(interface: &NetworkInterface, options: Options) -> Result { + pub fn new(interface: &NetworkInterface, options: Options) -> Result { let tun = match interface { NetworkInterface::Named(name) => TunTapInterface::new(name.as_str(), Medium::Ip)?, NetworkInterface::Fd(fd) => { @@ -274,13 +273,13 @@ impl<'a> TunToProxy<'a> { let poll = Poll::new()?; poll.registry().register( &mut SourceFd(&tun.as_raw_fd()), - TCP_TOKEN, + TUN_TOKEN, Interest::READABLE, )?; - let mut _exit_listener = mio::net::TcpListener::bind(EXIT_LISTENER.parse()?)?; + let (exit_sender, mut exit_receiver) = mio::unix::pipe::new()?; poll.registry() - .register(&mut _exit_listener, EXIT_TOKEN, Interest::READABLE)?; + .register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?; let config = match tun.capabilities().medium { Medium::Ethernet => Config::new( @@ -313,7 +312,8 @@ impl<'a> TunToProxy<'a> { device: virt, options, write_sockets: HashSet::default(), - _exit_listener, + _exit_receiver: exit_receiver, + exit_sender, }; Ok(tun) } @@ -769,7 +769,7 @@ impl<'a> TunToProxy<'a> { fn udp_event(&mut self, _event: &Event) {} - pub(crate) fn run(&mut self) -> Result<(), Error> { + pub fn run(&mut self) -> Result<(), Error> { let mut events = Events::with_capacity(1024); loop { match self.poll.poll(&mut events, None) { @@ -780,7 +780,7 @@ impl<'a> TunToProxy<'a> { log::info!("exiting..."); return Ok(()); } - TCP_TOKEN => self.tun_event(event)?, + TUN_TOKEN => self.tun_event(event)?, UDP_TOKEN => self.udp_event(event), _ => self.mio_socket_event(event)?, } @@ -798,9 +798,8 @@ impl<'a> TunToProxy<'a> { } } - pub(crate) fn shutdown() -> Result<(), Error> { - let addr: SocketAddr = EXIT_LISTENER.parse()?; - let _ = std::net::TcpStream::connect(addr)?; + pub fn shutdown(&mut self) -> Result<(), Error> { + self.exit_sender.write_all(&[1])?; Ok(()) } }