不再需要jni

This commit is contained in:
lbl8603
2024-06-15 20:44:20 +08:00
parent 1a385a777e
commit 1e5e15f1f5
21 changed files with 0 additions and 1784 deletions
-21
View File
@@ -1,21 +0,0 @@
[package]
name = "vnt-jni"
version = "1.2.10"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
common = { path = "../common" }
vnt = {path="../vnt"}
parking_lot = "0.12.1"
jni = { version = "0.21.1", default-features = false }
log = "0.4.20"
spki = { version = "0.7.2", features = ["fingerprint", "alloc","base64","pem"]}
[target.'cfg(target_os = "android")'.dependencies]
android_logger = "0.13"
[lib]
crate-type = ["staticlib", "cdylib"]
-1
View File
@@ -1 +0,0 @@
## 提供给安卓端使用
@@ -1,77 +0,0 @@
package top.wherewego.vnt.jni;
import top.wherewego.vnt.jni.param.*;
/**
* 回调
*
* @author https://github.com/lbl8603/vnt
*/
public interface CallBack {
/**
* 连接成功的回调
*/
void success();
/**
* 创建虚拟网卡成功的回调方法
* 仅在 windows/linux/macos上使用
*
* @param info 网卡信息
*/
void createTun(DeviceInfo info);
/**
* 连接服务端
*
* @param info 将要连接的服务端信息
*/
void connect(ConnectInfo info);
/**
* 和服务端握手
*
* @param info 握手信息
* @return 是否确认握手
*/
boolean handshake(HandshakeInfo info);
/**
* 注册成功回调
*
* @param info 注册信息
* @return 是否确认注册信息
*/
boolean register(RegisterInfo info);
/**
* 创建网卡回调
* 仅在android上使用
*
* @param info 创建配置
* @return 网卡fd
*/
int generateTun(DeviceConfig info);
/**
* 对端用户列表
*
* @param infoArray
*/
void peerClientList(PeerClientInfo[] infoArray);
/**
* 异常回调
*
* @param info 错误信息
*/
void error(ErrorInfo info);
/**
* 服务停止
*/
void stop();
}
@@ -1,333 +0,0 @@
package top.wherewego.vnt.jni;
import java.io.Serializable;
import java.util.Arrays;
/**
* 启动配置
*
* @author https://github.com/lbl8603/vnt
*/
public class Config implements Serializable {
/**
* 是否是tap模式,仅支持windows
*/
private boolean tap;
/**
* 组网标识
*/
private String token;
/**
* 设备名称
*/
private String name;
/**
* 客户端间加密的密码
*/
private String password;
/**
* 客户端间加密模式 aes_gcm/aes_cbc/aes_ecb/sm4_cbc
*/
private String cipherModel;
/**
* 打洞模式 ipv4/ipv6/all
*/
private String punchModel;
/**
* mtu 默认自动计算
*/
private Integer mtu;
/**
* 是否开启服务端加密
*/
private boolean serverEncrypt;
/**
* 设备id,请使用唯一值
*/
private String deviceId;
/**
* 服务端地址
*/
private String server;
/**
* dns地址
*/
private String[] dns;
/**
* 端口映射
*/
private String[] portMapping;
/**
* stun服务地址
*/
private String[] stunServer;
/**
* 和服务端使用tcp通信,默认使用udp
*/
private boolean tcp;
/**
* 指定组网IP
*/
private String ip;
/**
* 开启加密指纹校验
*/
private boolean finger;
/**
* 延迟优先,默认p2p优先
*/
private boolean firstLatency;
/**
* 点对网入口 格式 192.168.0.0/26,10.26.0.2
*/
private String[] inIps;
/**
* 点对网出口 格式 192.168.0.0/26
*/
private String[] outIps;
/**
* 端口组,udp会监听一组端口,tcp监听ports[0]端口
*/
private int[] ports;
/**
* 虚拟网卡名称 仅在linux、windows、macos上支持
*/
private String deviceName;
/**
* enum: relay/p2p/all
*/
private String useChannel;
/**
* 模拟丢包率,取0~1之间的数,为null表示不丢包,1表示全部丢包
*/
private Double packetLossRate;
/**
* 模拟延迟 单位毫秒(ms)
*/
private Integer packetDelay;
public Config() {
}
public boolean isTap() {
return tap;
}
public void setTap(boolean tap) {
this.tap = tap;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getCipherModel() {
return cipherModel;
}
public void setCipherModel(String cipherModel) {
this.cipherModel = cipherModel;
}
public String getPunchModel() {
return punchModel;
}
public void setPunchModel(String punchModel) {
this.punchModel = punchModel;
}
public Integer getMtu() {
return mtu;
}
public void setMtu(Integer mtu) {
this.mtu = mtu;
}
public boolean isServerEncrypt() {
return serverEncrypt;
}
public void setServerEncrypt(boolean serverEncrypt) {
this.serverEncrypt = serverEncrypt;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getServer() {
return server;
}
public void setServer(String server) {
this.server = server;
}
public String[] getDns() {
return dns;
}
public void setDns(String[] dns) {
this.dns = dns;
}
public String[] getPortMapping() {
return portMapping;
}
public void setPortMapping(String[] portMapping) {
this.portMapping = portMapping;
}
public String[] getStunServer() {
return stunServer;
}
public void setStunServer(String[] stunServer) {
this.stunServer = stunServer;
}
public boolean isTcp() {
return tcp;
}
public void setTcp(boolean tcp) {
this.tcp = tcp;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public boolean isFinger() {
return finger;
}
public void setFinger(boolean finger) {
this.finger = finger;
}
public boolean isFirstLatency() {
return firstLatency;
}
public void setFirstLatency(boolean firstLatency) {
this.firstLatency = firstLatency;
}
public String[] getInIps() {
return inIps;
}
public void setInIps(String[] inIps) {
this.inIps = inIps;
}
public String[] getOutIps() {
return outIps;
}
public void setOutIps(String[] outIps) {
this.outIps = outIps;
}
public int[] getPorts() {
return ports;
}
public void setPorts(int[] ports) {
this.ports = ports;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getUseChannel() {
return useChannel;
}
public void setUseChannel(String useChannel) {
this.useChannel = useChannel;
}
public Double getPacketLossRate() {
return packetLossRate;
}
public void setPacketLossRate(Double packetLossRate) {
this.packetLossRate = packetLossRate;
}
public Integer getPacketDelay() {
return packetDelay;
}
public void setPacketDelay(Integer packetDelay) {
this.packetDelay = packetDelay;
}
@Override
public String toString() {
return "Config{" +
"tap=" + tap +
", token='" + token + '\'' +
", name='" + name + '\'' +
", password='" + password + '\'' +
", cipherModel='" + cipherModel + '\'' +
", punchModel='" + punchModel + '\'' +
", mtu=" + mtu +
", serverEncrypt=" + serverEncrypt +
", deviceId='" + deviceId + '\'' +
", server='" + server + '\'' +
", dns=" + Arrays.toString(dns) +
", portMapping=" + Arrays.toString(portMapping) +
", stunServer=" + Arrays.toString(stunServer) +
", tcp=" + tcp +
", ip='" + ip + '\'' +
", finger=" + finger +
", firstLatency=" + firstLatency +
", inIps=" + Arrays.toString(inIps) +
", outIps=" + Arrays.toString(outIps) +
", ports=" + Arrays.toString(ports) +
", deviceName='" + deviceName + '\'' +
", useChannel='" + useChannel + '\'' +
", packetLossRate=" + packetLossRate +
", packetDelay=" + packetDelay +
'}';
}
}
@@ -1,43 +0,0 @@
package top.wherewego.vnt.jni;
/**
* ip转换
*
* @author https://github.com/lbl8603/vnt
*/
public class IpUtils {
/**
* 将整数的ip地址转成字符串,例如 0 转成 "0.0.0.0"
*
* @param ipAddress
* @return
*/
public static String intToIpAddress(int ipAddress) {
return ((ipAddress & 0xFF000000) >>> 24) + "." +
((ipAddress & 0x00FF0000) >>> 16) + "." +
((ipAddress & 0x0000FF00) >>> 8) + "." +
(ipAddress & 0x000000FF);
}
/**
* 返回掩码的长度
*
* @param subnetMask
* @return
*/
public static int subnetMaskToPrefixLength(int subnetMask) {
int prefixLength = 0;
int bit = 1 << 31;
while (subnetMask != 0) {
if ((subnetMask & bit) != bit) {
break;
}
prefixLength++;
subnetMask <<= 1;
}
return prefixLength;
}
}
@@ -1,46 +0,0 @@
package top.wherewego.vnt.jni;
/**
* 对端设备信息
*
* @author https://github.com/lbl8603/vnt
*/
public class PeerRouteInfo {
private final int virtualIp;
private final String name;
private final String status;
private final Route route;
public PeerRouteInfo(int virtualIp, String name, String status, Route route) {
this.virtualIp = virtualIp;
this.name = name;
this.status = status;
this.route = route;
}
public int getVirtualIp() {
return virtualIp;
}
public String getName() {
return name;
}
public String getStatus() {
return status;
}
public Route getRoute() {
return route;
}
@Override
public String toString() {
return "PeerDeviceInfo{" +
"virtualIp=" + IpUtils.intToIpAddress(virtualIp) +
", name='" + name + '\'' +
", status='" + status + '\'' +
", route=" + route +
'}';
}
}
@@ -1,50 +0,0 @@
package top.wherewego.vnt.jni;
/**
* 路由信息
*
* @author https://github.com/lbl8603/vnt
*/
public class Route {
/**
* 是否使用tcp
*/
private final boolean tcp;
private final String address;
private final byte metric;
private final int rt;
public Route(boolean tcp, String address, byte metric, int rt) {
this.tcp = tcp;
this.address = address;
this.metric = metric;
this.rt = rt;
}
public boolean isTcp() {
return tcp;
}
public String getAddress() {
return address;
}
public byte getMetric() {
return metric;
}
public int getRt() {
return rt;
}
@Override
public String toString() {
return "Route{" +
"tcp=" + tcp +
", address='" + address + '\'' +
", metric=" + metric +
", rt=" + rt +
'}';
}
}
@@ -1,53 +0,0 @@
package top.wherewego.vnt.jni;
import java.io.Closeable;
import java.io.IOException;
/**
* vnt的Java映射
*
* @author https://github.com/lbl8603/vnt
*/
public class Vnt implements Closeable {
private final long raw;
public Vnt(Config config, CallBack callBack) throws Exception {
this.raw = new0(config, callBack);
if (this.raw == 0) {
throw new RuntimeException();
}
}
public void stop() {
stop0(raw);
}
public void await() {
wait0(raw);
}
public boolean awaitTimeout(long ms) {
return waitTimeout0(raw, ms);
}
public PeerRouteInfo[] list() {
return list0(raw);
}
private native long new0(Config config, CallBack callBack) throws Exception;
private native void stop0(long raw);
private native void wait0(long raw);
private native boolean waitTimeout0(long raw, long ms);
private native void drop0(long raw);
private native PeerRouteInfo[] list0(long raw);
@Override
public void close() throws IOException {
drop0(raw);
}
}
@@ -1,32 +0,0 @@
package top.wherewego.vnt.jni.param;
/**
* 连接信息
*
* @author https://github.com/lbl8603/vnt
*/
public class ConnectInfo {
private final long count;
private final String address;
public ConnectInfo(long count, String address) {
this.count = count;
this.address = address;
}
public long getCount() {
return count;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "ConnectInfo{" +
"count=" + count +
", address='" + address + '\'' +
'}';
}
}
@@ -1,72 +0,0 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
import java.util.Arrays;
/**
* 创建网卡所需信息,仅在android上使用
*
* @author https://github.com/lbl8603/vnt
*/
public class DeviceConfig {
/**
* 虚拟IP
*/
public final int virtualIp;
/**
* 掩码
*/
public final int virtualNetmask;
/**
* 网关
*/
public final int virtualGateway;
/**
* 虚拟网段
*/
public final int virtualNetwork;
/**
* 额外路由,来自点对网的路由配置
*/
public final String[] externalRoute;
public DeviceConfig(int virtualIp, int virtualNetmask, int virtualGateway, int virtualNetwork, String[] externalRoute) {
this.virtualIp = virtualIp;
this.virtualNetmask = virtualNetmask;
this.virtualGateway = virtualGateway;
this.virtualNetwork = virtualNetwork;
this.externalRoute = externalRoute;
}
public int getVirtualIp() {
return virtualIp;
}
public int getVirtualNetmask() {
return virtualNetmask;
}
public int getVirtualGateway() {
return virtualGateway;
}
public int getVirtualNetwork() {
return virtualNetwork;
}
public String[] getExternalRoute() {
return externalRoute;
}
@Override
public String toString() {
return "DeviceConfig{" +
"virtualIp=" + IpUtils.intToIpAddress(virtualIp) +
", virtualNetmask=" + IpUtils.intToIpAddress(virtualNetmask) +
", virtualGateway=" + IpUtils.intToIpAddress(virtualGateway) +
", virtualNetwork=" + IpUtils.intToIpAddress(virtualNetwork) +
", externalRoute=" + Arrays.toString(externalRoute) +
'}';
}
}
@@ -1,38 +0,0 @@
package top.wherewego.vnt.jni.param;
/**
* 网卡信息 仅在 windows/linux/macos上使用
*
* @author https://github.com/lbl8603/vnt
*/
public class DeviceInfo {
/**
* 虚拟网卡名称
*/
private final String name;
/**
* 虚拟网卡版本
*/
private final String version;
public DeviceInfo(String name, String version) {
this.name = name;
this.version = version;
}
public String getName() {
return name;
}
public String getVersion() {
return version;
}
@Override
public String toString() {
return "DeviceInfo{" +
"name='" + name + '\'' +
", version='" + version + '\'' +
'}';
}
}
@@ -1,65 +0,0 @@
package top.wherewego.vnt.jni.param;
/**
* 异常回调信息
*
* @author https://github.com/lbl8603/vnt
*/
public class ErrorInfo {
/**
* 错误码
*/
public final ErrorCodeEnum code;
/**
* 错误信息,可能为空
*/
public final String msg;
public ErrorInfo(int code, String msg) {
switch (code) {
case 1:
this.code = ErrorCodeEnum.TokenError;
break;
case 2:
this.code = ErrorCodeEnum.Disconnect;
break;
case 3:
this.code = ErrorCodeEnum.AddressExhausted;
break;
case 4:
this.code = ErrorCodeEnum.IpAlreadyExists;
break;
case 5:
this.code = ErrorCodeEnum.InvalidIp;
break;
default:
this.code = ErrorCodeEnum.Unknown;
}
this.msg = msg;
}
public ErrorCodeEnum getCode() {
return code;
}
public String getMsg() {
return msg;
}
public enum ErrorCodeEnum {
TokenError,
Disconnect,
AddressExhausted,
IpAlreadyExists,
InvalidIp,
Unknown,
}
@Override
public String toString() {
return "ErrorInfo{" +
"code=" + code +
", msg='" + msg + '\'' +
'}';
}
}
@@ -1,54 +0,0 @@
package top.wherewego.vnt.jni.param;
/**
* 握手回调信息
*
* @author https://github.com/lbl8603/vnt
*/
public class HandshakeInfo {
/**
* 公钥 pem格式 CRLF分隔,不加密时为空
*/
private final String publicKey;
/**
* 公钥签名,不加密时为空
*/
private final String finger;
/**
* 服务端版本
*/
private final String version;
public HandshakeInfo() {
this.publicKey = "publicKey";
this.finger = "finger";
this.version = "version";
}
public HandshakeInfo(String publicKey, String finger, String version) {
this.publicKey = publicKey;
this.finger = finger;
this.version = version;
}
public String getPublicKey() {
return publicKey;
}
public String getFinger() {
return finger;
}
public String getVersion() {
return version;
}
@Override
public String toString() {
return "HandshakeInfo{" +
"publicKey='" + publicKey + '\'' +
", finger='" + finger + '\'' +
", version='" + version + '\'' +
'}';
}
}
@@ -1,60 +0,0 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
/**
* 创建网卡所需信息,仅在android上使用
*
* @author https://github.com/lbl8603/vnt
*/
public class PeerClientInfo {
/**
* 虚拟IP
*/
public final int virtualIp;
/**
* 名称
*/
public final String name;
/**
* 是否在线
*/
public final boolean online;
/**
* 是否开启客户端加密,不同加密状态的不能通信
*/
public final boolean clientSecret;
public PeerClientInfo(int virtualIp, String name, boolean online, boolean clientSecret) {
this.virtualIp = virtualIp;
this.name = name;
this.online = online;
this.clientSecret = clientSecret;
}
public int getVirtualIp() {
return virtualIp;
}
public String getName() {
return name;
}
public boolean isOnline() {
return online;
}
public boolean isClientSecret() {
return clientSecret;
}
@Override
public String toString() {
return "PeerDeviceInfo{" +
"virtualIp=" + IpUtils.intToIpAddress(virtualIp) +
", name='" + name + '\'' +
", online=" + online +
", clientSecret=" + clientSecret +
'}';
}
}
@@ -1,50 +0,0 @@
package top.wherewego.vnt.jni.param;
import top.wherewego.vnt.jni.IpUtils;
/**
* 注册回调信息
*
* @author https://github.com/lbl8603/vnt
*/
public class RegisterInfo {
/**
* 虚拟IP
*/
public final int virtualIp;
/**
* 掩码
*/
public final int virtualNetmask;
/**
* 网关
*/
public final int virtualGateway;
public RegisterInfo(int virtualIp, int virtualNetmask, int virtualGateway) {
this.virtualIp = virtualIp;
this.virtualNetmask = virtualNetmask;
this.virtualGateway = virtualGateway;
}
public int getVirtualIp() {
return virtualIp;
}
public int getVirtualNetmask() {
return virtualNetmask;
}
public int getVirtualGateway() {
return virtualGateway;
}
@Override
public String toString() {
return "RegisterInfo{" +
"virtualIp='" + IpUtils.intToIpAddress(virtualIp) + '\'' +
", virtualNetmask='" + IpUtils.intToIpAddress(virtualNetmask) + '\'' +
", virtualGateway='" + IpUtils.intToIpAddress(virtualGateway) + '\'' +
'}';
}
}
-322
View File
@@ -1,322 +0,0 @@
use std::sync::Arc;
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
use jni::{JNIEnv, JavaVM};
use spki::der::pem::LineEnding;
use spki::EncodePublicKey;
use vnt::handle::callback::ConnectInfo;
#[cfg(target_os = "android")]
use vnt::handle::callback::DeviceConfig;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
use vnt::DeviceInfo;
use vnt::{ErrorInfo, HandshakeInfo, PeerClientInfo, RegisterInfo, VntCallback};
#[derive(Clone)]
pub struct CallBack {
jvm: Arc<JavaVM>,
this: GlobalRef,
connect_info_class: GlobalRef,
handshake_info_class: GlobalRef,
error_info_class: GlobalRef,
register_info_class: GlobalRef,
#[cfg(target_os = "android")]
device_config_class: GlobalRef,
peer_client_info_class: GlobalRef,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_info_class: GlobalRef,
}
unsafe impl Send for CallBack {}
fn find_class_global_ref(env: &mut JNIEnv, class: &str) -> jni::errors::Result<GlobalRef> {
let class = env.find_class(class)?;
env.new_global_ref(class)
}
impl CallBack {
pub fn new(jvm: JavaVM, this: GlobalRef) -> jni::errors::Result<Self> {
let mut env = jvm.attach_current_thread_as_daemon()?;
let connect_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/ConnectInfo")?;
let handshake_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/HandshakeInfo")?;
let error_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/ErrorInfo")?;
let register_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/RegisterInfo")?;
#[cfg(target_os = "android")]
let device_config_class = crate::callback::find_class_global_ref(
&mut env,
"top/wherewego/vnt/jni/param/DeviceConfig",
)?;
let peer_client_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/PeerClientInfo")?;
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
let device_info_class =
find_class_global_ref(&mut env, "top/wherewego/vnt/jni/param/DeviceInfo")?;
Ok(Self {
jvm: Arc::new(jvm),
this,
connect_info_class,
handshake_info_class,
error_info_class,
register_info_class,
#[cfg(target_os = "android")]
device_config_class,
peer_client_info_class,
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
device_info_class,
})
}
}
impl CallBack {
fn success0(&self) -> jni::errors::Result<()> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
env.call_method(&self.this, "success", "()V", &[])?;
Ok(())
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn create_tun0(&self, info: DeviceInfo) -> jni::errors::Result<()> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.device_info_class.as_raw()) };
let param = env.new_object(
class,
"(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(&param)],
)?;
Ok(())
}
fn connect0(&self, info: ConnectInfo) -> jni::errors::Result<()> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.connect_info_class.as_raw()) };
let param = env.new_object(
class,
"(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(&param)],
)?;
Ok(())
}
fn handshake0(&self, info: HandshakeInfo) -> jni::errors::Result<bool> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
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 class = unsafe { JClass::from_raw(self.handshake_info_class.as_raw()) };
let param = env.new_object(
class,
"(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(&param)],
)?;
rs.z()
}
fn register0(&self, info: RegisterInfo) -> jni::errors::Result<bool> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.register_info_class.as_raw()) };
let param = env.new_object(
class,
"(III)V",
&[
JValue::Int(u32::from(info.virtual_ip) as _),
JValue::Int(u32::from(info.virtual_netmask) as _),
JValue::Int(u32::from(info.virtual_gateway) as _),
],
)?;
let rs = env.call_method(
&self.this,
"register",
"(Ltop/wherewego/vnt/jni/param/RegisterInfo;)Z",
&[JValue::Object(&param)],
)?;
rs.z()
}
#[cfg(target_os = "android")]
fn generate_tun0(&self, info: DeviceConfig) -> jni::errors::Result<u32> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.device_config_class.as_raw()) };
let object_array = env.new_object_array(
info.external_route.len() as _,
"java/lang/String",
JObject::null(),
)?;
for (index, (network, mask)) in info.external_route.into_iter().enumerate() {
let param =
env.new_string(format!("{}/{}", network, u32::from(mask).leading_ones()))?;
env.set_object_array_element(&object_array, index as _, &param)?;
}
let param = env.new_object(
class,
"(IIII[Ljava/lang/String;)V",
&[
JValue::Int(u32::from(info.virtual_ip) as _),
JValue::Int(u32::from(info.virtual_netmask) as _),
JValue::Int(u32::from(info.virtual_gateway) as _),
JValue::Int(u32::from(info.virtual_network) as _),
JValue::Object(&object_array),
],
)?;
let rs = env.call_method(
&self.this,
"generateTun",
"(Ltop/wherewego/vnt/jni/param/DeviceConfig;)I",
&[JValue::Object(&param)],
)?;
rs.i().map(|v| v as _)
}
fn peer_client_list0(&self, info_vec: Vec<PeerClientInfo>) -> jni::errors::Result<()> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.peer_client_info_class.as_raw()) };
let object_array = env.new_object_array(info_vec.len() as _, &class, JObject::null())?;
for (index, info) in info_vec.into_iter().enumerate() {
let param = env.new_object(
&class,
"(ILjava/lang/String;ZZ)V",
&[
JValue::Int(u32::from(info.virtual_ip) as _),
JValue::Object(&env.new_string(info.name)?.into()),
JValue::Bool(info.status.is_online() as _),
JValue::Bool(info.client_secret as _),
],
)?;
env.set_object_array_element(&object_array, index as _, &param)?;
}
env.call_method(
&self.this,
"peerClientList",
"([Ltop/wherewego/vnt/jni/param/PeerClientInfo;)V",
&[JValue::Object(&object_array)],
)?;
Ok(())
}
fn error0(&self, info: ErrorInfo) -> jni::errors::Result<()> {
let code: u8 = info.code.into();
let mut env = self.jvm.attach_current_thread_as_daemon()?;
let class = unsafe { JClass::from_raw(self.error_info_class.as_raw()) };
let msg = if let Some(msg) = info.msg {
env.new_string(msg)?
} else {
JString::default()
};
let param = env.new_object(
class,
"(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(&param)],
)?;
Ok(())
}
fn stop0(&self) -> jni::errors::Result<()> {
let mut env = self.jvm.attach_current_thread_as_daemon()?;
env.call_method(&self.this, "stop", "()V", &[])?;
Ok(())
}
}
impl VntCallback for CallBack {
fn success(&self) {
if let Err(e) = self.success0() {
log::warn!("success {:?}", e);
}
}
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
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
})
}
#[cfg(target_os = "android")]
fn generate_tun(&self, info: DeviceConfig) -> u32 {
self.generate_tun0(info).unwrap_or_else(|e| {
log::warn!("generate_tun {:?}", e);
0
})
}
fn peer_client_list(&self, info: Vec<PeerClientInfo>) {
if let Err(e) = self.peer_client_list0(info) {
log::warn!("peer_client_list {:?}", e);
}
}
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);
}
}
}
-135
View File
@@ -1,135 +0,0 @@
use std::str::FromStr;
use jni::errors::Error;
use jni::objects::JObject;
use jni::JNIEnv;
use vnt::channel::punch::PunchModel;
use vnt::channel::UseChannelType;
use vnt::cipher::CipherModel;
use vnt::compression::Compressor;
use vnt::core::Config;
use crate::utils::*;
pub fn new_config(env: &mut JNIEnv, config: JObject) -> Result<Config, Error> {
#[cfg(target_os = "windows")]
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 dns = to_string_array(env, &config, "dns")?.unwrap_or_else(|| vec![]);
let port_mapping = to_string_array(env, &config, "portMapping")?.unwrap_or_else(|| vec![]);
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 use_channel = to_string(env, &config, "useChannel")?;
let finger = env.get_field(&config, "finger", "Z")?.z()?;
let first_latency = env.get_field(&config, "firstLatency", "Z")?.z()?;
let packet_delay = to_integer(env, &config, "packetDelay")?
.map(|v| v as u32)
.unwrap_or_default();
let packet_loss_rate = to_double(env, &config, "packetLossRate")?;
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 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")?;
let config = match Config::new(
#[cfg(target_os = "windows")]
tap,
token,
device_id,
name,
server_address_str,
dns,
stun_server,
in_ips,
out_ips,
password,
mtu,
tcp,
ip,
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,
UseChannelType::from_str(&use_channel.unwrap_or_default()).unwrap_or_default(),
packet_loss_rate,
packet_delay,
port_mapping,
Compressor::None,
) {
Ok(config) => config,
Err(e) => {
env.throw_new(
"java/lang/RuntimeException",
format!("vnt start error {:?}", e),
)
.expect("throw");
return Err(Error::JavaException);
}
};
Ok(config)
}
-5
View File
@@ -1,5 +0,0 @@
pub mod callback;
pub mod config;
pub mod utils;
pub mod vnt;
pub(crate) mod vnt_logger;
-131
View File
@@ -1,131 +0,0 @@
use jni::errors::Error;
use jni::objects::{JIntArray, JObject, JObjectArray, JString};
use jni::JNIEnv;
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 _
));
}
pub fn to_double(env: &mut JNIEnv, config: &JObject, name: &str) -> Result<Option<f64>, Error> {
let value = env.get_field(config, name, "Ljava/lang/Double;")?.l()?;
if value.is_null() {
return Ok(None);
}
// 调用 intValue
return Ok(Some(
env.call_method(value, "doubleValue", "()D", &[])?.d()? as _,
));
}
-184
View File
@@ -1,184 +0,0 @@
use std::ptr;
use std::time::Duration;
use jni::errors::Error;
use jni::objects::{JClass, JObject, JValue};
use jni::sys::{jboolean, jint, jlong, jobject, jobjectArray, jsize};
use jni::JNIEnv;
use vnt::channel::Route;
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 {
crate::vnt_logger::init_log();
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 call_back = match CallBack::new(jvm, call_back) {
Ok(call_back) => call_back,
Err(_) => {
return 0;
}
};
let vnt_util = match Vnt::new(config, 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 Vnt;
let _ = (&*vnt).stop();
}
#[no_mangle]
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 Vnt;
let _ = (&*vnt).wait();
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_waitTimeout0(
_env: JNIEnv,
_class: JClass,
raw_vnt: jlong,
time: jlong,
) -> jboolean {
let vnt = raw_vnt as *mut Vnt;
(&*vnt).wait_timeout(Duration::from_millis(time as _)) as _
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_drop0(
_env: JNIEnv,
_class: JClass,
raw_vnt: jlong,
) {
let vnt = raw_vnt as *mut Vnt;
let _ = Box::from_raw(vnt).stop();
}
#[no_mangle]
pub unsafe extern "C" fn Java_top_wherewego_vnt_jni_Vnt_list0(
mut env: JNIEnv,
_class: JClass,
raw_vnt: jlong,
) -> jobjectArray {
let vnt = raw_vnt as *mut Vnt;
let vnt = &mut *vnt;
let list = vnt.device_list();
let arr = match env.new_object_array(
list.len() as jsize,
"top/wherewego/vnt/jni/PeerRouteInfo",
JObject::null(),
) {
Ok(arr) => arr,
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("error:{:?}", e))
.expect("throw");
return ptr::null_mut();
}
};
for (index, peer) in list.into_iter().enumerate() {
let route = if let Some(route) = vnt.route(&peer.virtual_ip) {
match route_parse(&mut env, route) {
Ok(route) => JObject::from_raw(route),
Err(_) => JObject::null(),
}
} else {
JObject::null()
};
match peer_device_info_parse(&mut env, peer, route) {
Ok(peer) => {
match env.set_object_array_element(&arr, index as jsize, JObject::from_raw(peer)) {
Ok(_) => {}
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("error:{:?}", e))
.expect("throw");
return ptr::null_mut();
}
}
}
Err(e) => {
env.throw_new("java/lang/RuntimeException", format!("error:{:?}", e))
.expect("throw");
return ptr::null_mut();
}
}
}
arr.as_raw()
}
fn route_parse(env: &mut JNIEnv, route: Route) -> Result<jobject, Error> {
let rs = env.new_object(
"top/wherewego/vnt/jni/Route",
"(ZLjava/lang/String;BI)V",
&[
JValue::Bool(route.is_tcp as _),
JValue::Object(&env.new_string(route.addr.to_string())?.into()),
JValue::Byte(route.metric as _),
JValue::Int(route.rt as _),
],
)?;
Ok(rs.as_raw())
}
fn peer_device_info_parse(
env: &mut JNIEnv,
peer: PeerDeviceInfo,
route: JObject,
) -> Result<jobject, Error> {
let virtual_ip = u32::from(peer.virtual_ip);
let name = peer.name.to_string();
let status = format!("{:?}", peer.status);
let rs = env.new_object(
"top/wherewego/vnt/jni/PeerRouteInfo",
"(ILjava/lang/String;Ljava/lang/String;Ltop/wherewego/vnt/jni/Route;)V",
&[
JValue::Int(virtual_ip as jint),
JValue::Object(&env.new_string(name)?.into()),
JValue::Object(&env.new_string(status)?.into()),
JValue::Object(&route),
],
)?;
Ok(rs.as_raw())
}
-12
View File
@@ -1,12 +0,0 @@
#[cfg(target_os = "android")]
pub fn init_log() {
use android_logger::Config;
use log::LevelFilter;
android_logger::init_once(
Config::default()
.with_max_level(LevelFilter::Info) // limit log level
.with_tag("vnt_jni"), // logs will show under mytag tag
);
}
#[cfg(not(target_os = "android"))]
pub fn init_log() {}