Browse Source

Use pipe for exiting

pull/41/head
B. Blechschmidt 3 years ago
parent
commit
5e218c2130
  1. 29
      src/android.rs
  2. 15
      src/lib.rs
  3. 29
      src/tun2proxy.rs

29
src/android.rs

@ -1,12 +1,15 @@
#![cfg(target_os = "android")] #![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::{ use jni::{
objects::{JClass, JString}, objects::{JClass, JString},
sys::{jboolean, jint}, sys::{jboolean, jint},
JNIEnv, JNIEnv,
}; };
static mut TUN_TO_PROXY: Option<TunToProxy> = None;
/// # Safety /// # Safety
/// ///
/// Running tun2proxy /// 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 options = Options::new().with_virtual_dns().with_mtu(tun_mtu as usize);
let interface = NetworkInterface::Fd(tun_fd); 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>(()) Ok::<(), Error>(())
}; };
if let Err(error) = block() { if let Err(error) = block() {
@ -59,11 +66,19 @@ pub unsafe extern "C" fn Java_com_github_shadowsocks_bg_Tun2proxy_stop(
_env: JNIEnv, _env: JNIEnv,
_clazz: JClass, _clazz: JClass,
) -> jint { ) -> jint {
if let Err(e) = shutdown() { match &mut TUN_TO_PROXY {
log::error!("failed to shutdown tun2proxy with error: {:?}", e); None => {
1 log::error!("tun2proxy not started");
} else { 1
0 }
Some(tun2proxy) => {
if let Err(e) = tun2proxy.shutdown() {
log::error!("failed to shutdown tun2proxy with error: {:?}", e);
1
} else {
0
}
}
} }
} }

15
src/lib.rs

@ -123,11 +123,11 @@ impl Credentials {
} }
} }
pub fn main_entry( pub fn tun_to_proxy<'a>(
interface: &NetworkInterface, interface: &NetworkInterface,
proxy: &Proxy, proxy: &Proxy,
options: Options, options: Options,
) -> Result<(), Error> { ) -> Result<TunToProxy<'a>, Error> {
let mut ttp = TunToProxy::new(interface, options)?; let mut ttp = TunToProxy::new(interface, options)?;
match proxy.proxy_type { match proxy.proxy_type {
ProxyType::Socks4 => { ProxyType::Socks4 => {
@ -148,9 +148,14 @@ pub fn main_entry(
ttp.add_connection_manager(HttpManager::new(proxy.addr, proxy.credentials.clone())); ttp.add_connection_manager(HttpManager::new(proxy.addr, proxy.credentials.clone()));
} }
} }
ttp.run() Ok(ttp)
} }
pub fn shutdown() -> Result<(), Error> { pub fn main_entry(
TunToProxy::shutdown() interface: &NetworkInterface,
proxy: &Proxy,
options: Options,
) -> Result<(), Error> {
let ttp = tun_to_proxy(interface, proxy, options);
ttp?.run()
} }

29
src/tun2proxy.rs

@ -242,13 +242,11 @@ pub(crate) trait ConnectionManager {
fn get_credentials(&self) -> &Option<Credentials>; fn get_credentials(&self) -> &Option<Credentials>;
} }
const TCP_TOKEN: Token = Token(0); const TUN_TOKEN: Token = Token(0);
const UDP_TOKEN: Token = Token(1); const UDP_TOKEN: Token = Token(1);
const EXIT_TOKEN: Token = Token(2); const EXIT_TOKEN: Token = Token(2);
const EXIT_LISTENER: &str = "127.0.0.1:34255"; pub struct TunToProxy<'a> {
pub(crate) struct TunToProxy<'a> {
tun: TunTapInterface, tun: TunTapInterface,
poll: Poll, poll: Poll,
iface: Interface, iface: Interface,
@ -260,11 +258,12 @@ pub(crate) struct TunToProxy<'a> {
device: VirtualTunDevice, device: VirtualTunDevice,
options: Options, options: Options,
write_sockets: HashSet<Token>, write_sockets: HashSet<Token>,
_exit_listener: mio::net::TcpListener, _exit_receiver: mio::unix::pipe::Receiver,
exit_sender: mio::unix::pipe::Sender,
} }
impl<'a> TunToProxy<'a> { impl<'a> TunToProxy<'a> {
pub(crate) fn new(interface: &NetworkInterface, options: Options) -> Result<Self, Error> { pub fn new(interface: &NetworkInterface, options: Options) -> Result<Self, Error> {
let tun = match interface { let tun = match interface {
NetworkInterface::Named(name) => TunTapInterface::new(name.as_str(), Medium::Ip)?, NetworkInterface::Named(name) => TunTapInterface::new(name.as_str(), Medium::Ip)?,
NetworkInterface::Fd(fd) => { NetworkInterface::Fd(fd) => {
@ -274,13 +273,13 @@ impl<'a> TunToProxy<'a> {
let poll = Poll::new()?; let poll = Poll::new()?;
poll.registry().register( poll.registry().register(
&mut SourceFd(&tun.as_raw_fd()), &mut SourceFd(&tun.as_raw_fd()),
TCP_TOKEN, TUN_TOKEN,
Interest::READABLE, 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() poll.registry()
.register(&mut _exit_listener, EXIT_TOKEN, Interest::READABLE)?; .register(&mut exit_receiver, EXIT_TOKEN, Interest::READABLE)?;
let config = match tun.capabilities().medium { let config = match tun.capabilities().medium {
Medium::Ethernet => Config::new( Medium::Ethernet => Config::new(
@ -313,7 +312,8 @@ impl<'a> TunToProxy<'a> {
device: virt, device: virt,
options, options,
write_sockets: HashSet::default(), write_sockets: HashSet::default(),
_exit_listener, _exit_receiver: exit_receiver,
exit_sender,
}; };
Ok(tun) Ok(tun)
} }
@ -769,7 +769,7 @@ impl<'a> TunToProxy<'a> {
fn udp_event(&mut self, _event: &Event) {} 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); let mut events = Events::with_capacity(1024);
loop { loop {
match self.poll.poll(&mut events, None) { match self.poll.poll(&mut events, None) {
@ -780,7 +780,7 @@ impl<'a> TunToProxy<'a> {
log::info!("exiting..."); log::info!("exiting...");
return Ok(()); return Ok(());
} }
TCP_TOKEN => self.tun_event(event)?, TUN_TOKEN => self.tun_event(event)?,
UDP_TOKEN => self.udp_event(event), UDP_TOKEN => self.udp_event(event),
_ => self.mio_socket_event(event)?, _ => self.mio_socket_event(event)?,
} }
@ -798,9 +798,8 @@ impl<'a> TunToProxy<'a> {
} }
} }
pub(crate) fn shutdown() -> Result<(), Error> { pub fn shutdown(&mut self) -> Result<(), Error> {
let addr: SocketAddr = EXIT_LISTENER.parse()?; self.exit_sender.write_all(&[1])?;
let _ = std::net::TcpStream::connect(addr)?;
Ok(()) Ok(())
} }
} }

Loading…
Cancel
Save