[mio] 适配新版vnt,增加jni java端代码
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use jni::objects::{GlobalRef, JString, JValue};
|
||||
use jni::{JNIEnv, JavaVM};
|
||||
use spki::der::pem::LineEnding;
|
||||
use spki::EncodePublicKey;
|
||||
|
||||
use vnt::handle::callback::ConnectInfo;
|
||||
use vnt::{DeviceInfo, ErrorInfo, HandshakeInfo, RegisterInfo, VntCallback};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CallBack {
|
||||
jvm: Arc<JavaVM>,
|
||||
this: GlobalRef,
|
||||
}
|
||||
|
||||
unsafe impl Send for CallBack {}
|
||||
|
||||
impl CallBack {
|
||||
pub fn new(jvm: JavaVM, this: GlobalRef) -> Self {
|
||||
Self {
|
||||
jvm: Arc::new(jvm),
|
||||
this,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CallBack {
|
||||
fn create_tun0(&self, info: DeviceInfo) -> jni::errors::Result<()> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
let param = env.new_object(
|
||||
"top/wherewego/vnt/jni/param/DeviceInfo",
|
||||
"(Ljava/lang/String;Ljava/lang/String;)V",
|
||||
&[
|
||||
JValue::Object(&env.new_string(info.name)?.into()),
|
||||
JValue::Object(&env.new_string(info.version)?.into()),
|
||||
],
|
||||
)?;
|
||||
env.call_method(
|
||||
&self.this,
|
||||
"createTun",
|
||||
"(Ltop/wherewego/vnt/jni/param/DeviceInfo;)V",
|
||||
&[JValue::Object(¶m)],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
fn connect0(&self, info: ConnectInfo) -> jni::errors::Result<()> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
let param = env.new_object(
|
||||
"top/wherewego/vnt/jni/param/ConnectInfo",
|
||||
"(JLjava/lang/String;)V",
|
||||
&[
|
||||
JValue::Long(info.count as _),
|
||||
JValue::Object(&env.new_string(info.address.to_string())?.into()),
|
||||
],
|
||||
)?;
|
||||
env.call_method(
|
||||
&self.this,
|
||||
"connect",
|
||||
"(Ltop/wherewego/vnt/jni/param/ConnectInfo;)V",
|
||||
&[JValue::Object(¶m)],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
fn handshake0(&self, info: HandshakeInfo) -> jni::errors::Result<bool> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
let public_key = if let Some(public_key) = info.public_key {
|
||||
match public_key.to_public_key_pem(LineEnding::CRLF) {
|
||||
Ok(public_key) => env.new_string(public_key)?,
|
||||
Err(e) => {
|
||||
log::warn!("{:?}", e);
|
||||
JString::default()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
JString::default()
|
||||
};
|
||||
let finger = if let Some(finger) = info.finger {
|
||||
env.new_string(finger)?
|
||||
} else {
|
||||
JString::default()
|
||||
};
|
||||
let param = env.new_object(
|
||||
"top/wherewego/vnt/jni/param/HandshakeInfo",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
||||
&[
|
||||
JValue::Object(&public_key),
|
||||
JValue::Object(&finger),
|
||||
JValue::Object(&env.new_string(info.version)?.into()),
|
||||
],
|
||||
)?;
|
||||
let rs = env.call_method(
|
||||
&self.this,
|
||||
"handshake",
|
||||
"(Ltop/wherewego/vnt/jni/param/HandshakeInfo;)Z",
|
||||
&[JValue::Object(¶m)],
|
||||
)?;
|
||||
rs.z()
|
||||
}
|
||||
fn register0(&self, info: RegisterInfo) -> jni::errors::Result<bool> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
let param = env.new_object(
|
||||
"top/wherewego/vnt/jni/param/RegisterInfo",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
||||
&[
|
||||
JValue::Object(&env.new_string(info.virtual_ip.to_string())?.into()),
|
||||
JValue::Object(&env.new_string(info.virtual_netmask.to_string())?.into()),
|
||||
JValue::Object(&env.new_string(info.virtual_gateway.to_string())?.into()),
|
||||
],
|
||||
)?;
|
||||
let rs = env.call_method(
|
||||
&self.this,
|
||||
"register",
|
||||
"(Ltop/wherewego/vnt/jni/param/RegisterInfo;)Z",
|
||||
&[JValue::Object(¶m)],
|
||||
)?;
|
||||
rs.z()
|
||||
}
|
||||
fn error0(&self, info: ErrorInfo) -> jni::errors::Result<()> {
|
||||
let code: u8 = info.code.into();
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
let msg = if let Some(msg) = info.msg {
|
||||
env.new_string(msg)?
|
||||
} else {
|
||||
JString::default()
|
||||
};
|
||||
let param = env.new_object(
|
||||
"top/wherewego/vnt/jni/param/ErrorInfo",
|
||||
"(ILjava/lang/String;)V",
|
||||
&[JValue::Int(code as _), JValue::Object(&msg.into())],
|
||||
)?;
|
||||
env.call_method(
|
||||
&self.this,
|
||||
"error",
|
||||
"(Ltop/wherewego/vnt/jni/param/ErrorInfo;)V",
|
||||
&[JValue::Object(¶m)],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
fn stop0(&self) -> jni::errors::Result<()> {
|
||||
let env = &mut self.jvm.attach_current_thread()? as &mut JNIEnv;
|
||||
env.call_method(&self.this, "error", "()V", &[])?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl VntCallback for CallBack {
|
||||
fn create_tun(&self, info: DeviceInfo) {
|
||||
if let Err(e) = self.create_tun0(info) {
|
||||
log::warn!("create_tun {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn connect(&self, info: ConnectInfo) {
|
||||
if let Err(e) = self.connect0(info) {
|
||||
log::warn!("connect {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn handshake(&self, info: HandshakeInfo) -> bool {
|
||||
self.handshake0(info).unwrap_or_else(|e| {
|
||||
log::warn!("handshake {:?}", e);
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn register(&self, info: RegisterInfo) -> bool {
|
||||
self.register0(info).unwrap_or_else(|e| {
|
||||
log::warn!("register {:?}", e);
|
||||
false
|
||||
})
|
||||
}
|
||||
|
||||
fn error(&self, info: ErrorInfo) {
|
||||
if let Err(e) = self.error0(info) {
|
||||
log::warn!("error {:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
fn stop(&self) {
|
||||
if let Err(e) = self.stop0() {
|
||||
log::warn!("stop {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::str::FromStr;
|
||||
|
||||
use jni::errors::Error;
|
||||
use jni::JNIEnv;
|
||||
use jni::objects::JObject;
|
||||
|
||||
use vnt::channel::punch::PunchModel;
|
||||
use vnt::cipher::CipherModel;
|
||||
use vnt::core::Config;
|
||||
|
||||
use crate::utils::*;
|
||||
|
||||
pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
let tap = env.get_field(&config, "tap", "Z")?.z()?;
|
||||
let token = to_string_not_null(env, &config, "token")?;
|
||||
let name = to_string_not_null(env, &config, "name")?;
|
||||
let device_id = to_string_not_null(env, &config, "deviceId")?;
|
||||
let password = to_string(env, &config, "password")?;
|
||||
let server_address_str = to_string_not_null(env, &config, "server")?;
|
||||
let stun_server = to_string_array_not_null(env, &config, "stunServer")?;
|
||||
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
|
||||
let punch_model = to_string(env, &config, "punchModel")?;
|
||||
let mtu = to_integer(env, &config, "mtu")?.map(|v|v as u32);
|
||||
let tcp = env.get_field(&config, "tcp", "Z")?.z()?;
|
||||
let server_encrypt = env.get_field(&config, "serverEncrypt", "Z")?.z()?;
|
||||
let relay = env.get_field(&config, "relay", "Z")?.z()?;
|
||||
let finger = env.get_field(&config, "finger", "Z")?.z()?;
|
||||
let first_latency = env.get_field(&config, "firstLatency", "Z")?.z()?;
|
||||
let in_ips = to_string_array(env, &config, "inIps")?;
|
||||
let out_ips = to_string_array(env, &config, "outIps")?;
|
||||
let ports =
|
||||
to_i32_array(env, &config, "ports")?.map(|v| v.into_iter().map(|v| v as u16).collect());
|
||||
let ip = if let Some(ip) = to_string(env, &config, "ip")? {
|
||||
match ip.parse() {
|
||||
Ok(ip) => {
|
||||
Some(ip)
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("ip {} err: {}", ip, e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let in_ips = if let Some(in_ips) = in_ips {
|
||||
match common::args_parse::ips_parse(&in_ips) {
|
||||
Ok(in_ips) => in_ips,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("in_ips {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
let out_ips = if let Some(out_ips) = out_ips {
|
||||
match common::args_parse::out_ips_parse(&out_ips) {
|
||||
Ok(out_ips) => out_ips,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("out_ips {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let server_address = match server_address_str.to_socket_addrs() {
|
||||
Ok(mut rs) => {
|
||||
if let Some(addr) = rs.next() {
|
||||
addr
|
||||
} else {
|
||||
env.throw_new("java/lang/RuntimeException", "server address err")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("server address {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
let cipher_model = match CipherModel::from_str(&cipher_model) {
|
||||
Ok(cipher_model) => cipher_model,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("cipher_model {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let device_name = to_string(env, &config, "deviceName")?;
|
||||
#[cfg(target_os = "android")]
|
||||
let device_fd = env.get_field(&config, "deviceFd", "I")?.i()? as i32;
|
||||
let config = match Config::new(
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
tap,
|
||||
token,
|
||||
device_id,
|
||||
name,
|
||||
server_address,
|
||||
server_address_str,
|
||||
stun_server,
|
||||
in_ips,
|
||||
out_ips,
|
||||
password,
|
||||
mtu,
|
||||
tcp,
|
||||
ip,
|
||||
relay,
|
||||
false,
|
||||
server_encrypt,
|
||||
1,
|
||||
cipher_model,
|
||||
finger,
|
||||
PunchModel::from_str(&punch_model.unwrap_or_default()).unwrap_or_default(),
|
||||
ports,
|
||||
first_latency,
|
||||
#[cfg(not(target_os = "android"))]
|
||||
device_name,
|
||||
#[cfg(target_os = "android")]
|
||||
device_fd,
|
||||
) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
Ok(config)
|
||||
}
|
||||
+3
-1
@@ -1,2 +1,4 @@
|
||||
pub mod callback;
|
||||
pub mod config;
|
||||
pub mod vnt;
|
||||
pub mod vnt_util;
|
||||
pub mod utils;
|
||||
@@ -0,0 +1,115 @@
|
||||
use jni::errors::Error;
|
||||
use jni::JNIEnv;
|
||||
use jni::objects::{JIntArray, JObject, JObjectArray, JString};
|
||||
|
||||
pub fn to_string_not_null(
|
||||
env: &mut JNIEnv,
|
||||
config: &JObject,
|
||||
name: &'static str,
|
||||
) -> Result<String, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?;
|
||||
if value.is_null() {
|
||||
env.throw_new("java/lang/NullPointerException", name)
|
||||
.expect("throw");
|
||||
return Err(Error::NullPtr(name));
|
||||
}
|
||||
let binding = JString::from(value);
|
||||
let value = env.get_string(binding.as_ref())?;
|
||||
match value.to_str() {
|
||||
Ok(value) => Ok(value.to_string()),
|
||||
Err(_) => {
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<String>, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?;
|
||||
if value.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
let tmp = JString::from(value);
|
||||
let value = env.get_string(tmp.as_ref())?;
|
||||
match value.to_str() {
|
||||
Ok(value) => Ok(Some(value.to_string())),
|
||||
Err(_) => {
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string_array_not_null(
|
||||
env: &mut JNIEnv,
|
||||
config: &JObject,
|
||||
name: &str,
|
||||
) -> Result<Vec<String>, Error> {
|
||||
match to_string_array(env, config, name)? {
|
||||
None => {
|
||||
env.throw_new("java/lang/NullPointerException", name)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
Some(rs) => Ok(rs),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string_array(
|
||||
env: &mut JNIEnv,
|
||||
config: &JObject,
|
||||
name: &str,
|
||||
) -> Result<Option<Vec<String>>, Error> {
|
||||
let value = env.get_field(config, name, "[Ljava/lang/String;")?.l()?;
|
||||
if value.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
let arr = JObjectArray::from(value);
|
||||
let len = env.get_array_length(&arr)?;
|
||||
let mut rs = Vec::with_capacity(len as usize);
|
||||
for index in 0..len {
|
||||
let object = env.get_object_array_element(&arr, index)?;
|
||||
if object.is_null() {
|
||||
env.throw_new(
|
||||
"java/lang/NullPointerException",
|
||||
format!("{},index={}", name, index),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
match env.get_string(JString::from(object).as_ref())?.to_str() {
|
||||
Ok(value) => {
|
||||
rs.push(value.to_string());
|
||||
}
|
||||
Err(_) => {
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(Some(rs))
|
||||
}
|
||||
|
||||
pub fn to_i32_array(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<Vec<i32>>, Error> {
|
||||
let obj = env.get_field(&config, name, "[I")?.l()?;
|
||||
if obj.is_null() {
|
||||
Ok(None)
|
||||
} else {
|
||||
let j_arr = JIntArray::from(obj);
|
||||
let len = env.get_array_length(&j_arr)?;
|
||||
let mut arr = vec![0i32; len as usize];
|
||||
env.get_int_array_region(j_arr, 0, &mut arr)?;
|
||||
Ok(Some(arr))
|
||||
}
|
||||
}
|
||||
pub fn to_integer(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<i32>, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/Integer;")?.l()?;
|
||||
if value.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
// 调用 intValue
|
||||
return Ok(Some(env.call_method(value,"intValue","()I",&[])?.i()? as _))
|
||||
}
|
||||
+51
-25
@@ -1,45 +1,71 @@
|
||||
use std::ptr;
|
||||
|
||||
use jni::errors::Error;
|
||||
use jni::objects::{JClass, JObject, JValue};
|
||||
use jni::sys::{jboolean, jbyte, jint, jlong, jobject, jobjectArray, jsize};
|
||||
use jni::sys::{jbyte, jint, jlong, jobject, jobjectArray, jsize};
|
||||
use jni::JNIEnv;
|
||||
use std::ptr;
|
||||
|
||||
use vnt::channel::Route;
|
||||
use vnt::core::sync::VntSync;
|
||||
use vnt::core::Vnt;
|
||||
use vnt::handle::PeerDeviceInfo;
|
||||
|
||||
use crate::callback::CallBack;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_new0(
|
||||
mut env: JNIEnv<'static>,
|
||||
_class: JClass,
|
||||
config: JObject,
|
||||
call_back: JObject<'static>,
|
||||
) -> jlong {
|
||||
let jvm = if let Ok(jvm) = env.get_java_vm() {
|
||||
jvm
|
||||
} else {
|
||||
return 0;
|
||||
};
|
||||
match crate::config::new_config(&mut env, config) {
|
||||
Ok(config) => {
|
||||
let call_back = if let Ok(call_back) = env.new_global_ref(call_back) {
|
||||
call_back
|
||||
} else {
|
||||
return 0;
|
||||
};
|
||||
let vnt_util = match Vnt::new(config, CallBack::new(jvm, call_back)) {
|
||||
Ok(vnt_util) => vnt_util,
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
let ptr = Box::into_raw(Box::new(vnt_util));
|
||||
return ptr as jlong;
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_stop0(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt: jlong,
|
||||
) {
|
||||
let vnt = raw_vnt as *mut VntSync;
|
||||
let vnt = raw_vnt as *mut Vnt;
|
||||
let _ = (&*vnt).stop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitStop0(
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_wait0(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt: jlong,
|
||||
) {
|
||||
let vnt = raw_vnt as *mut VntSync;
|
||||
let _ = (&mut *vnt).wait_stop();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitStopMs0(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt: jlong,
|
||||
ms: jlong,
|
||||
) -> jboolean {
|
||||
let vnt = raw_vnt as *mut VntSync;
|
||||
if (&mut *vnt).wait_stop_ms(ms as _) {
|
||||
jni::sys::JNI_TRUE
|
||||
} else {
|
||||
jni::sys::JNI_FALSE
|
||||
}
|
||||
let vnt = raw_vnt as *mut Vnt;
|
||||
let _ = (&*vnt).wait();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
@@ -48,7 +74,7 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_drop0(
|
||||
_class: JClass,
|
||||
raw_vnt: jlong,
|
||||
) {
|
||||
let vnt = raw_vnt as *mut VntSync;
|
||||
let vnt = raw_vnt as *mut Vnt;
|
||||
let _ = Box::from_raw(vnt).stop();
|
||||
}
|
||||
|
||||
@@ -58,7 +84,7 @@ pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
|
||||
_class: JClass,
|
||||
raw_vnt: jlong,
|
||||
) -> jobjectArray {
|
||||
let vnt = raw_vnt as *mut VntSync;
|
||||
let vnt = raw_vnt as *mut Vnt;
|
||||
let vnt = &mut *vnt;
|
||||
let list = vnt.device_list();
|
||||
|
||||
|
||||
@@ -1,386 +0,0 @@
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::ptr;
|
||||
use std::str::FromStr;
|
||||
|
||||
use jni::errors::Error;
|
||||
use jni::objects::{JClass, JObject, JString, JValue};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use jni::sys::jboolean;
|
||||
use jni::sys::{jint, jlong, jobject};
|
||||
use jni::JNIEnv;
|
||||
use vnt::channel::punch::PunchModel;
|
||||
use vnt::cipher::CipherModel;
|
||||
use vnt::core::sync::VntUtilSync;
|
||||
use vnt::core::Config;
|
||||
use vnt::handle::registration_handler::{RegResponse, ReqEnum};
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use vnt::tun_tap_device::DriverInfo;
|
||||
|
||||
fn to_string_not_null(
|
||||
env: &mut JNIEnv,
|
||||
config: &JObject,
|
||||
name: &'static str,
|
||||
) -> Result<String, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?;
|
||||
if value.is_null() {
|
||||
env.throw_new("java/lang/NullPointerException", name)
|
||||
.expect("throw");
|
||||
return Err(Error::NullPtr(name));
|
||||
}
|
||||
let binding = JString::from(value);
|
||||
let value = env.get_string(binding.as_ref())?;
|
||||
match value.to_str() {
|
||||
Ok(value) => Ok(value.to_string()),
|
||||
Err(_) => {
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_string(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<String>, Error> {
|
||||
let value = env.get_field(config, name, "Ljava/lang/String;")?.l()?;
|
||||
if value.is_null() {
|
||||
return Ok(None);
|
||||
}
|
||||
let tmp = JString::from(value);
|
||||
let value = env.get_string(tmp.as_ref())?;
|
||||
match value.to_str() {
|
||||
Ok(value) => Ok(Some(value.to_string())),
|
||||
Err(_) => {
|
||||
env.throw_new("java/lang/RuntimeException", "not utf-8")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_sync(env: &mut JNIEnv, config: JObject) -> Result<VntUtilSync, Error> {
|
||||
let token = to_string_not_null(env, &config, "token")?;
|
||||
let name = to_string_not_null(env, &config, "name")?;
|
||||
let device_id = to_string_not_null(env, &config, "deviceId")?;
|
||||
let password = to_string(env, &config, "password")?;
|
||||
let server_address_str = to_string_not_null(env, &config, "server")?;
|
||||
let stun_server_str = to_string_not_null(env, &config, "stunServer")?;
|
||||
let cipher_model = to_string_not_null(env, &config, "cipherModel")?;
|
||||
let tcp = env.get_field(&config, "tcp", "Z")?.z()?;
|
||||
let finger = env.get_field(&config, "finger", "Z")?.z()?;
|
||||
let first_latency = env.get_field(&config, "firstLatency", "Z")?.z()?;
|
||||
let in_ips = to_string(env, &config, "inIps")?;
|
||||
let out_ips = to_string(env, &config, "outIps")?;
|
||||
let port = env.get_field(&config, "port", "I")?.i()? as u16;
|
||||
let in_ips = if let Some(in_ips) = in_ips {
|
||||
let in_ips: Vec<&str> = in_ips.split("\n").collect();
|
||||
let in_ips = in_ips.iter().map(|v| v.to_string()).collect();
|
||||
match common::args_parse::ips_parse(&in_ips) {
|
||||
Ok(in_ips) => in_ips,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("in_ips {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
let out_ips = if let Some(out_ips) = out_ips {
|
||||
let out_ips: Vec<&str> = out_ips.split("\n").collect();
|
||||
let out_ips = out_ips.iter().map(|v| v.to_string()).collect();
|
||||
match common::args_parse::out_ips_parse(&out_ips) {
|
||||
Ok(out_ips) => out_ips,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("out_ips {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
|
||||
let server_address = match server_address_str.to_socket_addrs() {
|
||||
Ok(mut rs) => {
|
||||
if let Some(addr) = rs.next() {
|
||||
addr
|
||||
} else {
|
||||
env.throw_new("java/lang/RuntimeException", "server address err")
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("server address {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
let cipher_model = match CipherModel::from_str(&cipher_model) {
|
||||
Ok(cipher_model) => cipher_model,
|
||||
Err(e) => {
|
||||
env.throw_new("java/lang/RuntimeException", format!("cipher_model {}", e))
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
let mut stun_server = Vec::new();
|
||||
for addr in stun_server_str.split(",") {
|
||||
stun_server.push(addr.trim().to_string());
|
||||
}
|
||||
let config = match Config::new(
|
||||
false,
|
||||
token,
|
||||
device_id,
|
||||
name,
|
||||
server_address,
|
||||
server_address_str,
|
||||
stun_server,
|
||||
in_ips,
|
||||
out_ips,
|
||||
password,
|
||||
false,
|
||||
None,
|
||||
tcp,
|
||||
None,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
1,
|
||||
cipher_model,
|
||||
finger,
|
||||
PunchModel::All,
|
||||
port,
|
||||
first_latency,
|
||||
) {
|
||||
Ok(config) => config,
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
};
|
||||
match VntUtilSync::new(config) {
|
||||
Ok(vnt_util) => Ok(vnt_util),
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
return Err(Error::JavaException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_new0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
config: JObject,
|
||||
) -> jlong {
|
||||
match new_sync(&mut env, config) {
|
||||
Ok(vnt_util) => {
|
||||
let ptr = Box::into_raw(Box::new(vnt_util));
|
||||
return ptr as jlong;
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_connect0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
) {
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
match (&mut *raw_vnt_util).connect() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt connect error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_register0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
) -> jobject {
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
match (&mut *raw_vnt_util).register() {
|
||||
Ok(response) => match reg_response(&mut env, response) {
|
||||
Ok(res) => {
|
||||
return res;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw(format!("vnt register error {}", e))
|
||||
.expect("throw");
|
||||
}
|
||||
},
|
||||
Err(e) => match e {
|
||||
ReqEnum::TokenError => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/TokenErrorException",
|
||||
"TokenError",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::AddressExhausted => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/AddressExhaustedException",
|
||||
"AddressExhausted",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::Timeout => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/TimeoutException",
|
||||
"Timeout",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::ServerError(str) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt register error {}", str),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::Other(str) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt register error {}", str),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::IpAlreadyExists => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/IpAlreadyExistsException",
|
||||
"IpAlreadyExists",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
ReqEnum::InvalidIp => {
|
||||
env.throw_new(
|
||||
"top/wherewego/vnt/jni/exception/InvalidIpException",
|
||||
"InvalidIp",
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
},
|
||||
}
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0(
|
||||
_env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
fd: jint,
|
||||
) {
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
|
||||
(&mut *raw_vnt_util).create_iface(fd as i32);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_createIface0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
) -> jobject {
|
||||
let raw_vnt_util = raw_vnt_util as *mut VntUtilSync;
|
||||
let rs = (&mut *raw_vnt_util).create_iface();
|
||||
match rs {
|
||||
Ok(driver_info) => match driver_info_e(&mut env, driver_info) {
|
||||
Ok(res) => {
|
||||
return res;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw(format!("vnt create iface error {}", e))
|
||||
.expect("throw");
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt create iface error {}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
return ptr::null_mut();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_VntUtil_build0(
|
||||
mut env: JNIEnv,
|
||||
_class: JClass,
|
||||
raw_vnt_util: jlong,
|
||||
) -> jlong {
|
||||
let raw_vnt_util = Box::from_raw(raw_vnt_util as *mut VntUtilSync);
|
||||
match raw_vnt_util.build() {
|
||||
Ok(rs) => {
|
||||
return Box::into_raw(Box::new(rs)) as jlong;
|
||||
}
|
||||
Err(e) => {
|
||||
env.throw_new(
|
||||
"java/lang/RuntimeException",
|
||||
format!("vnt start error:{:?}", e),
|
||||
)
|
||||
.expect("throw");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn reg_response(env: &mut JNIEnv, response: RegResponse) -> Result<jobject, Error> {
|
||||
let virtual_ip = u32::from(response.virtual_ip);
|
||||
let virtual_gateway = u32::from(response.virtual_gateway);
|
||||
let virtual_netmask = u32::from(response.virtual_netmask);
|
||||
let response = env.new_object(
|
||||
"top/wherewego/vnt/jni/RegResponse",
|
||||
"(III)V",
|
||||
&[
|
||||
JValue::Int(virtual_ip as jint),
|
||||
JValue::Int(virtual_gateway as jint),
|
||||
JValue::Int(virtual_netmask as jint),
|
||||
],
|
||||
)?;
|
||||
Ok(response.into_raw())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn driver_info_e(env: &mut JNIEnv, driver_info: DriverInfo) -> Result<jobject, Error> {
|
||||
let is_tun = driver_info.device_type.is_tun();
|
||||
let name = driver_info.name;
|
||||
let version = driver_info.version;
|
||||
let mac = driver_info.mac.unwrap_or(String::new());
|
||||
let response = env.new_object(
|
||||
"top/wherewego/vnt/jni/DriverInfo",
|
||||
"(ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
||||
&[
|
||||
JValue::Bool(is_tun as jboolean),
|
||||
JValue::Object(&env.new_string(name)?.into()),
|
||||
JValue::Object(&env.new_string(version)?.into()),
|
||||
JValue::Object(&env.new_string(mac)?.into()),
|
||||
],
|
||||
)?;
|
||||
Ok(response.into_raw())
|
||||
}
|
||||
Reference in New Issue
Block a user