a.0.1.0 move to creates src
This commit is contained in:
1 parent
86d3a3b47f
commit
f22d954105
942 files changed
+275635
-225
No files matched your search
@@ -0,0 +1,18 @@
|
||||
[package]
|
||||
name = "ramshare-android-jni"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
|
||||
[lib]
|
||||
# Имя выходной библиотеки libramshare_ui.so совпадает с System.loadLibrary("ramshare_ui") в Kotlin
|
||||
name = "ramshare_ui"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
ramshare-core = { path = "../core" }
|
||||
tokio.workspace = true
|
||||
tokio-rustls.workspace = true
|
||||
axum.workspace = true
|
||||
parking_lot.workspace = true
|
||||
jni = "0.21"
|
||||
@@ -0,0 +1,153 @@
|
||||
use axum::Router;
|
||||
use jni::{
|
||||
objects::{JClass, JString},
|
||||
sys::{jboolean, jint, JNI_FALSE, JNI_TRUE},
|
||||
JNIEnv,
|
||||
};
|
||||
use parking_lot::Mutex as PlMutex;
|
||||
use ramshare_core::{api, init_app_state, models::AppState, net, p2p, storage, tls};
|
||||
use std::{
|
||||
net::Ipv4Addr,
|
||||
path::Path,
|
||||
sync::{atomic::Ordering, Arc, OnceLock},
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::sync::Notify;
|
||||
|
||||
struct RunningNode {
|
||||
state: Arc<AppState>,
|
||||
stop: Arc<Notify>,
|
||||
}
|
||||
|
||||
static RUNTIME: OnceLock<tokio::runtime::Runtime> = OnceLock::new();
|
||||
static NODE: PlMutex<Option<RunningNode>> = PlMutex::new(None);
|
||||
|
||||
fn rt() -> &'static tokio::runtime::Runtime {
|
||||
RUNTIME.get_or_init(|| {
|
||||
tls::init_crypto();
|
||||
tokio::runtime::Builder::new_multi_thread()
|
||||
.worker_threads(4)
|
||||
.enable_all()
|
||||
.build()
|
||||
.expect("Tokio runtime init failed")
|
||||
})
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_ramshare_app_RamshareNative_startServer<'local>(
|
||||
mut env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
base_dir: JString<'local>,
|
||||
device_name: JString<'local>,
|
||||
p2p_port: jint,
|
||||
ui_port: jint,
|
||||
) -> jboolean {
|
||||
if NODE.lock().is_some() {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
let base_str: String = match env.get_string(&base_dir) {
|
||||
Ok(s) => s.into(),
|
||||
Err(_) => return JNI_FALSE,
|
||||
};
|
||||
let dev_name: String = match env.get_string(&device_name) {
|
||||
Ok(s) => s.into(),
|
||||
Err(_) => "Android-Device".to_string(),
|
||||
};
|
||||
let p2p_port = (p2p_port as u16).max(1024);
|
||||
let ui_port = (ui_port as u16).max(1024);
|
||||
|
||||
let dirs = match storage::resolve_dirs(Some(Path::new(&base_str)), p2p_port) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
eprintln!("[ANDROID ERR] resolve_dirs: {}", e);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
let (state, bind_ip) = match init_app_state(
|
||||
dirs.config,
|
||||
dirs.media,
|
||||
None,
|
||||
&dev_name,
|
||||
p2p_port,
|
||||
None,
|
||||
None,
|
||||
true,
|
||||
false,
|
||||
) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
eprintln!("[ANDROID ERR] init_app_state: {}", e);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
};
|
||||
|
||||
let stop = Arc::new(Notify::new());
|
||||
let stop_wait = stop.clone();
|
||||
let st = state.clone();
|
||||
|
||||
let started = rt().block_on(async move {
|
||||
let server_cfg = tls::server_config(&st.cert_der, &st.key_der)?;
|
||||
let acceptor = tokio_rustls::TlsAcceptor::from(server_cfg);
|
||||
let p2p_listener = tokio::net::TcpListener::bind((bind_ip, p2p_port))
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
let ui_listener = tokio::net::TcpListener::bind((Ipv4Addr::LOCALHOST, ui_port))
|
||||
.await
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
net::start_discovery(st.clone());
|
||||
|
||||
let st_ping = st.clone();
|
||||
let ping_task = tokio::spawn(async move {
|
||||
net::ping_all_peers(&st_ping, false).await;
|
||||
st_ping.maintenance();
|
||||
loop {
|
||||
let secs = st_ping.ping_interval_sec.load(Ordering::Relaxed);
|
||||
tokio::select! {
|
||||
_ = tokio::time::sleep(Duration::from_secs(secs)) => {}
|
||||
_ = st_ping.ping_notify.notified() => {}
|
||||
}
|
||||
net::ping_all_peers(&st_ping, false).await;
|
||||
st_ping.maintenance();
|
||||
}
|
||||
});
|
||||
|
||||
let ui_router = api::control_router(Router::new(), st.clone(), ui_port);
|
||||
let ui_task = tokio::spawn(async move { axum::serve(ui_listener, ui_router).await });
|
||||
let p2p_task = tokio::spawn(p2p::serve(p2p_listener, acceptor, p2p::router(st.clone())));
|
||||
|
||||
tokio::spawn(async move {
|
||||
stop_wait.notified().await;
|
||||
ping_task.abort();
|
||||
ui_task.abort();
|
||||
p2p_task.abort();
|
||||
});
|
||||
|
||||
Ok::<(), String>(())
|
||||
});
|
||||
|
||||
match started {
|
||||
Ok(()) => {
|
||||
*NODE.lock() = Some(RunningNode { state, stop });
|
||||
JNI_TRUE
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("[ANDROID ERR] bind/start: {}", e);
|
||||
JNI_FALSE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "system" fn Java_com_ramshare_app_RamshareNative_stopServer<'local>(
|
||||
_env: JNIEnv<'local>,
|
||||
_class: JClass<'local>,
|
||||
) {
|
||||
if let Some(node) = NODE.lock().take() {
|
||||
node.state.sync_trust_from_disk();
|
||||
node.state.persist_trust();
|
||||
storage::cleanup_partials(&node.state.media_dir);
|
||||
node.stop.notify_waiters();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user