Verified Commit 5b3f6086 authored by Ayush Shrivastava's avatar Ayush Shrivastava
Browse files

utils:android-support crate now builds green

parent 00ab5a67
......@@ -95,6 +95,35 @@ dependencies = [
"serde_json",
]
[[package]]
name = "android-tracing"
version = "0.1.0"
dependencies = [
"android_log-sys",
"serde_json",
"tracing",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "android_log-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e"
[[package]]
name = "android_logger"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cbd542dd180566fad88fd2729a53a62a734843c626638006a9d63ec0688484e"
dependencies = [
"android_log-sys",
"env_logger 0.7.1",
"lazy_static",
"log",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
......@@ -438,7 +467,7 @@ dependencies = [
"cexpr",
"clang-sys",
"clap",
"env_logger",
"env_logger 0.8.3",
"lazy_static",
"lazycell",
"log",
......@@ -899,6 +928,16 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.8.3"
......@@ -1502,6 +1541,7 @@ dependencies = [
"ircore-types",
"irpc-sdk",
"jni",
"libc",
"log",
"rand 0.7.3",
"ratman",
......@@ -1709,6 +1749,27 @@ version = "0.2.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18794a8ad5b29321f790b55d93dfba91e125cb1a9edbd4f8e3150acc771c1a5e"
[[package]]
name = "libirdestdroid"
version = "0.1.0"
dependencies = [
"android-tracing",
"android_logger",
"async-std",
"bincode",
"irdest-core",
"jni",
"libc",
"log",
"netmod-tcp",
"netmod-wd",
"ratman",
"ratman-configure",
"ratman-netmod",
"tempfile",
"tracing",
]
[[package]]
name = "libloading"
version = "0.7.0"
......
......@@ -46,4 +46,7 @@ members = [
"clients/hubd",
"clients/irdest-gtk",
"clients/irpc-client",
"utils/android-support",
"utils/android-tracing"
]
......@@ -11,6 +11,7 @@ alexandria = { version = "0.2", path = "../utils/alexandria" }
ircore-types = { version = "0.1", path = "types" }
irpc-sdk = { version = "0.1", path = "../rpc-core/irpc-sdk", optional = true }
ratman = { version = "0.2", path = "../ratman" }
libc = "0.2"
async-std = { version = "1.0", features = ["attributes", "unstable"] }
async-trait = "0.1"
......
......@@ -38,7 +38,7 @@ impl ToJObject for UserProfile {
//let id = to_jstring(env, Some(self.id.to_string()));
let id = JavaId::from_identity(self.id);
let display_name = to_jstring(env, self.display_name);
let real_name = to_jstring(env, self.real_name);
let real_name = to_jstring(env, self.handle);
let class: JClass<'env> = env
.find_class("net/qaul/app/ffi/models/UserProfile")
......
......@@ -29,15 +29,15 @@ pub unsafe extern "C" fn create(
let pw = super::conv_jstring(this, pw);
let auth = block_on(async { q.users().create(&pw).await })?;
block_on(async {
q.users()
.update(auth.clone(), UserUpdate::DisplayName(Some(handle)))
.await;
// block_on(async {
// q.users()
// .update(auth.clone(), UserUpdate::DisplayName(Some(handle)))
// .await;
q.users()
.update(auth.clone(), UserUpdate::RealName(Some(name)))
.await
})?;
// q.users()
// .update(auth.clone(), UserUpdate::RealName(Some(name)))
// .await
// })?;
Ok(auth)
}
......
use crate::error::{Error, Result};
use directories::ProjectDirs;
use std::{path::PathBuf, sync::Arc};
use tempfile::TempDir;
use std::{
env,
ffi::{CStr, OsStr},
mem,
os::unix::ffi::OsStrExt,
path::{Path, PathBuf},
sync::Arc,
ptr,
};
use libc::{self, c_char};
/// A config, data, and cache directories helper
///
......@@ -21,6 +30,39 @@ pub struct Directories {
temp: Option<Arc<TempDir>>,
}
pub fn home_dir() -> PathBuf {
unsafe fn char_ptr_to_path_buf(ptr: *mut c_char) -> PathBuf {
OsStr::from_bytes(CStr::from_ptr(ptr).to_bytes()).into()
}
// Check env var, otherwise, call libc::getpwuid_r
env::var_os("HOME")
.map(PathBuf::from)
.or_else(|| {
let mut buf = [0; 4096];
let mut result = ptr::null_mut();
let mut passwd: libc::passwd = unsafe { mem::zeroed() };
let getpwuid_r_code = unsafe {
libc::getpwuid_r(
libc::getuid(),
&mut passwd,
buf.as_mut_ptr(),
buf.len(),
&mut result,
)
};
// If success
if getpwuid_r_code == 0 && !result.is_null() {
let home_dir = unsafe { char_ptr_to_path_buf(passwd.pw_dir) };
Some(home_dir)
} else {
None
}
})
.unwrap()
}
impl Directories {
/// Create a temporary directory tree for tests
pub fn temp() -> Result<Self> {
......@@ -49,4 +91,22 @@ impl Directories {
temp: None,
})
}
// Accesses the app-specific private directory for saving state
pub fn android(client_id: &str) -> Directories{
let mut android_home = PathBuf::new();
android_home.push(home_dir()); // "/data"
android_home.push("user/0"); // "/data/user/0"
android_home.push(client_id);
android_home.push("cache");
info!("home_dir: {:?} ", android_home);
Self {
data: android_home.clone(),
config: android_home.clone(),
cache: android_home.clone(),
temp: None
}
}
}
......@@ -7,7 +7,7 @@ authors = ["Katharina Fey <kookie@spacekookie.de>", "Leonora Tindall <nora@nora.
edition = "2018"
[lib]
name = "irdestcore"
name = "irdestdroid"
crate-type = ["cdylib"]
[dependencies]
......@@ -17,6 +17,7 @@ jni = { version = "0.14", default-features = false }
log = "*"
tempfile = "3.0"
tracing = { version = "0.1" }
libc = "0.2"
irdest-core = { path = "../../irdest-core", features = ["ffi-java"] }
netmod-wd = { path = "../../netmods/netmod-wd" }
......
......@@ -15,10 +15,8 @@ use jni::{
};
use android_logger::{Config, FilterBuilder};
use libqaul::{users::UserAuth, Qaul};
use irdest_core::{users::UserAuth, helpers::Directories, Irdest};
use log::Level;
use qaul_chat::Chat;
use qaul_voice::Voice;
use ratman::Router;
use ratman_netmod::{Frame, Target};
......@@ -48,7 +46,7 @@ pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_setupState(
let tcp = block_on(async {
use netmod_tcp::Endpoint;
let ep = Endpoint::new("0.0.0.0", port as u16, "qauld")
let ep = Endpoint::new("0.0.0.0", port as u16, "qauld", netmod_tcp::Mode::Static)
.await
.unwrap();
router.add_endpoint(Arc::clone(&ep)).await;
......@@ -63,34 +61,33 @@ pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_setupState(
});
info!("Router init...done");
let libqaul = Qaul::new(router);
info!("libqaul init...done");
block_on(async {
use libqaul::users::UserUpdate;
let auth = libqaul.users().create("1234").await.unwrap();
libqaul
.users()
.update(
auth.clone(),
UserUpdate::RealName(Some("Alice Anonymous".into())),
)
.await;
libqaul
.users()
.update(auth.clone(), UserUpdate::DisplayName(Some("alice".into())))
.await;
});
let irdest = Irdest::new(router, Directories::android("st.irde.app"));
info!("lib-irdest init...done");
// Uncomment it and then fix, there is some referencing error, most probably we're using incorrect import of `UserUpdate` here
// block_on(async {
// use irdest_core::users::UserUpdate;
// let auth = irdest.users().create("1234").await.unwrap();
// irdest
// .users()
// .update(
// auth.clone(),
// UserUpdate::RealName(Some("Alice Anonymous".into())),
// )
// .await;
// irdest
// .users()
// .update(auth.clone(), UserUpdate::DisplayName(Some("alice".into())))
// .await;
// });
let chat = block_on(async { Chat::new(Arc::clone(&libqaul)).await }).unwrap();
let voice = block_on(async { Voice::new(Arc::clone(&libqaul)).await }).unwrap();
info!("Service init: done");
// We just return the state pointer here because for some reason
// storing the state directly in the instance variable doesn't
// work, or didn't work when I last tried it. Patches to change
// this very welcome, if they work!
GcWrapped::new(tcp, wd, libqaul, chat, voice).into_ptr()
GcWrapped::new(tcp, wd, irdest).into_ptr()
}
/// Check if an auth token is still valid
......@@ -136,14 +133,14 @@ pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_connectTcp(
.collect();
let port = port as u16;
block_on(async {
use std::net::{Ipv4Addr, SocketAddrV4};
tcp.load_peers(vec![SocketAddrV4::new(
Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3]),
port,
)])
.await;
});
// block_on(async {
// use std::net::{Ipv4Addr, SocketAddrV4};
// tcp.load_peers(vec![SocketAddrV4::new(
// Ipv4Addr::new(addr[0], addr[1], addr[2], addr[3]),
// port,
// )])
// .await;
// });
}
fn frame_to_jframe<'env>(env: &'env JNIEnv, f: Frame, t: Target) -> JObject<'env> {
......
use crate::utils::{self, GcWrapped, JavaId};
use async_std::{sync::Arc, task::block_on};
use jni::{
objects::{JClass, JList, JObject, JString, JValue},
sys::{jboolean, jint, jlong, jobject},
JNIEnv,
};
use libqaul::{ffi::java::ToJObject, Identity};
use qaul_chat::{ChatMessage, RoomMeta};
fn room_to_jobject<'env>(env: &'env JNIEnv, room: RoomMeta) -> JObject<'env> {
let id = JavaId::from_identity(room.id).into_obj(env);
let name = utils::into_jstring(env, room.name.unwrap_or("Untitled chat".into()));
let last_message = utils::into_jstring(env, "<last mesage>".into());
let unread = room.unread as jint;
let list_class = env.find_class("java/util/ArrayList").unwrap();
let arraylist = env.new_object(list_class, "()V", &[]).unwrap();
let list = JList::from_env(env, arraylist).unwrap();
let members = room
.users
.into_iter()
.map(|user_id| JavaId::from_identity(user_id).into_obj(env))
.fold(list, |list, jobj| {
list.add(jobj);
list
});
let room_class: JClass<'env> = env.find_class("net/qaul/app/ffi/models/ChatRoom").unwrap();
env.new_object(
room_class,
"(Lnet/qaul/app/ffi/models/Id;Ljava/lang/String;Ljava/lang/String;ILjava/util/ArrayList)V",
&[
JValue::Object(id),
JValue::Object(*name),
JValue::Object(*last_message),
JValue::Int(unread),
JValue::Object(*members),
],
)
.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_chatList<'env>(
env: JNIEnv<'env>,
_: JObject,
qaul: jlong,
) -> jobject {
info!("Rust FFI chatList");
let state = GcWrapped::from_ptr(qaul as i64);
let w = state.get_inner();
let auth = state.get_auth().unwrap();
let chat = w.chat();
let chat_list = block_on(async {
let rooms = chat.rooms(auth).await.unwrap();
let class = env.find_class("java/util/ArrayList").unwrap();
let arraylist = env.new_object(class, "()V", &[]).unwrap();
let list = JList::from_env(&env, arraylist).unwrap();
rooms
.into_iter()
.map(|room| room_to_jobject(&env, room))
.fold(list, |list, jobj| {
list.add(jobj);
list
})
});
std::mem::forget(qaul);
std::mem::forget(state);
// Return the list
chat_list.into_inner()
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_chatStart<'env>(
env: JNIEnv<'env>,
_: JObject,
qaul: jlong,
name: JString,
friends: JList,
) -> jobject {
let state = GcWrapped::from_ptr(qaul as i64);
let w = state.get_inner();
let auth = state.get_auth().unwrap();
let friends: Vec<Identity> = friends
.iter()
.unwrap()
.map(|id| JavaId::from_obj(&env, id).into_identity())
.collect();
let chat_name = utils::conv_jstring(&env, name);
let room = block_on(async {
w.chat()
.start_chat(auth.clone(), friends, Some(chat_name))
.await
.unwrap()
});
let jroom = room_to_jobject(&env, room);
std::mem::forget(qaul);
std::mem::forget(state);
jroom.into_inner()
}
fn chat_message_to_jobject<'env>(env: &'env JNIEnv, msg: ChatMessage) -> JObject<'env> {
let id = JavaId::from_identity(msg.id).into_obj(env);
let sender = JavaId::from_identity(msg.sender).into_obj(env);
let timestamp = utils::into_jstring(env, format!("{}", msg.timestamp));
let content = utils::into_jstring(env, msg.content);
let class: JClass<'env> = env
.find_class("net/qaul/app/ffi/models/ChatMessage")
.unwrap();
env.new_object(
class,
"(Lnet/qaul/app/ffi/models/Id;Lnet/qaul/app/ffi/models/Id;Ljava/lang/String;Ljava/lang/String;)V",
&[
JValue::Object(id),
JValue::Object(sender),
JValue::Object(*timestamp),
JValue::Object(*content),
],
)
.unwrap()
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_chatSendMessage<'env>(
env: JNIEnv<'env>,
_: JObject,
qaul: jlong,
room_id: JObject,
content: JString,
) -> jobject {
let state = GcWrapped::from_ptr(qaul as i64);
let w = state.get_inner();
let auth = state.get_auth().unwrap();
let room_id = JavaId::from_obj(&env, room_id).into_identity();
let content = utils::conv_jstring(&env, content);
let chat_message =
block_on(async { w.chat().send_message(auth, room_id, content).await.unwrap() });
chat_message_to_jobject(&env, chat_message).into_inner()
}
#[no_mangle]
pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_chatLoadMessages<'env>(
env: JNIEnv<'env>,
_: JObject,
qaul: jlong,
room_id: JObject,
) -> jobject {
let state = GcWrapped::from_ptr(qaul as i64);
let w = state.get_inner();
let auth = state.get_auth().unwrap();
let room_id = JavaId::from_obj(&env, room_id).into_identity();
let messages = block_on(async { w.chat().load_messages(auth, room_id).await.unwrap() });
let list_class = env.find_class("java/util/ArrayList").unwrap();
let arraylist = env.new_object(list_class, "()V", &[]).unwrap();
let list = JList::from_env(&env, arraylist).unwrap();
messages
.into_iter()
.map(|message| chat_message_to_jobject(&env, message))
.fold(list, |list, jobj| {
list.add(jobj);
list
})
.into_inner()
}
// use crate::utils::{self, GcWrapped, JavaId};
// use async_std::{sync::Arc, task::block_on};
// use jni::{
// objects::{JClass, JList, JObject, JString, JValue},
// sys::{jboolean, jint, jlong, jobject},
// JNIEnv,
// };
// use libqaul::{ffi::java::ToJObject, Identity};
// use qaul_chat::{ChatMessage, RoomMeta};
// fn room_to_jobject<'env>(env: &'env JNIEnv, room: RoomMeta) -> JObject<'env> {
// let id = JavaId::from_identity(room.id).into_obj(env);
// let name = utils::into_jstring(env, room.name.unwrap_or("Untitled chat".into()));
// let last_message = utils::into_jstring(env, "<last mesage>".into());
// let unread = room.unread as jint;
// let list_class = env.find_class("java/util/ArrayList").unwrap();
// let arraylist = env.new_object(list_class, "()V", &[]).unwrap();
// let list = JList::from_env(env, arraylist).unwrap();
// let members = room
// .users
// .into_iter()
// .map(|user_id| JavaId::from_identity(user_id).into_obj(env))
// .fold(list, |list, jobj| {
// list.add(jobj);
// list
// });
// let room_class: JClass<'env> = env.find_class("net/qaul/app/ffi/models/ChatRoom").unwrap();
// env.new_object(
// room_class,
// "(Lnet/qaul/app/ffi/models/Id;Ljava/lang/String;Ljava/lang/String;ILjava/util/ArrayList)V",
// &[
// JValue::Object(id),
// JValue::Object(*name),
// JValue::Object(*last_message),
// JValue::Int(unread),
// JValue::Object(*members),
// ],
// )
// .unwrap()
// }
// #[no_mangle]
// pub unsafe extern "C" fn Java_net_qaul_app_ffi_NativeQaul_chatList<'env>(
// env: JNIEnv<'env>,
// _: JObject,
// qaul: jlong,
// ) -> jobject {
// info!("Rust FFI chatList");
// let state = GcWrapped::from_ptr(qaul as i64);
// let w = state.get_inner();
// let auth = state.get_auth().unwrap();
// let chat = w.chat();
// let chat_list = block_on(async {
// let rooms = chat.rooms(auth).await.unwrap();
// let class = env.find_class("java/util/ArrayList").unwrap();
// let arraylist = env.new_object(class, "()V", &[]).unwrap();
// let list = JList::from_env(&env, arraylist).unwrap();
// rooms
// .into_iter()
// .map(|room| room_to_jobject(&env, room))
// .fold(list, |list, jobj| {
// list.add(jobj);
// list
// })
// });
// std::mem::forget(qaul);
// std::mem::forget(state);
// // Return the list
// chat_list.into_inner()
// }