Use pipe for exiting

This commit is contained in:
B. Blechschmidt 2023-04-27 22:41:54 +02:00
parent 034417f525
commit 5e218c2130
3 changed files with 46 additions and 27 deletions

View file

@ -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<TunToProxy> = 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
}
}
}
}

View file

@ -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<TunToProxy<'a>, 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()
}

View file

@ -242,13 +242,11 @@ pub(crate) trait ConnectionManager {
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 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<Token>,
_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<Self, Error> {
pub fn new(interface: &NetworkInterface, options: Options) -> Result<Self, Error> {
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(())
}
}