a.0.1.0 move to creates src

This commit is contained in:
netadmin committed 2026-10-27 22:23:15 +03:00
1 parent 86d3a3b47f
commit f22d954105
942 files changed
+275635 -225

No files matched your search

+18
View File
@@ -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"
+153
View File
@@ -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();
}
}