Commit ab6c75f6 authored by ankitgusai19's avatar ankitgusai19
Browse files

-Demo to test select! exit from Android. Dummy proxy method added to showcase...

-Demo to test select! exit from Android. Dummy proxy method added to showcase the functionality as proxy connection is not established successfully
parent d1ecdfd5
......@@ -13,7 +13,6 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
......
......@@ -3,6 +3,8 @@ package net.example;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
......@@ -12,8 +14,20 @@ public class MainActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyClass myClass = new MyClass();
TextView text = (TextView) this.findViewById(R.id.textField);
String res = MyClass.myMethod("ifconfig.me", getCacheDir().getAbsolutePath());
text.setText(res);
//String res = myClass.myMethod("ifconfig.me", getCacheDir().getAbsolutePath());
new Thread(() -> {
Log.d("TAG", "onCreate: before start dummy");
String res = myClass.startDummyProxy(getCacheDir().getAbsolutePath());
Log.d("TAG", "onCreate: after start dummy");
runOnUiThread(()-> text.setText(res));
}).start();
findViewById(R.id.button).setOnClickListener(view -> myClass.stopDummyProxy(myClass.exitPointer));
}
}
\ No newline at end of file
package net.example;
class MyClass {
static native String myMethod(final String target, final String storage);
long exitPointer = 0;
native String myMethod(final String target, final String storage);
native void closeProxy(long exitPointer);
native String startDummyProxy(final String storage);
native void stopDummyProxy(long exitPointer);
static {
System.loadLibrary("arti_mobile");
}
......
......@@ -16,4 +16,14 @@
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Close"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textField" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -15,21 +15,18 @@ futures = "0.3.19"
# used to forward logs to system logger
tracing-subscriber = "0.3.3"
# dependancies to make logs available with logcat
tracing-android = "0.1.6"
# dependancies specific to iOS
[target.'cfg(target_os = "ios")'.dependencies]
tracing-oslog = "0.1.2"
# dependancies specific to Android
[target.'cfg(target_os = "android")'.dependencies]
# the java native interface
jni = { version = "0.19", default-features = false }
# dependancies to make logs available with logcat
tracing-android = "0.1.6"
# dependancy to help implementing lockf, for android < 7.0
libc = "0.2.112"
......
......@@ -2,21 +2,27 @@
use crate::run_arti;
use crate::run_dummy_arti;
use anyhow::Result;
use std::sync::Once;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::prelude::*;
use jni::objects::{JClass, JString};
use futures::channel::oneshot::*;
use jni::objects::{JClass, JObject, JString};
use jni::sys::jstring;
use jni::JNIEnv;
use futures::channel::oneshot;
use futures::channel::oneshot::*;
pub const HOLDER_FIELD_NAME: &str = "exitPointer";
/// Create a static method myMethod on class net.example.MyClass
#[no_mangle]
pub extern "C" fn Java_net_example_MyClass_myMethod(
env: JNIEnv,
_: JClass,
object: JObject,
target: JString,
cache_dir: JString,
) -> jstring {
......@@ -24,6 +30,18 @@ pub extern "C" fn Java_net_example_MyClass_myMethod(
// it shouldn't stop Arti from functionning however!
let _ = init_logger();
let (sender, receiver) = oneshot::channel::<()>();
//save sender reference in JAVA, so in exit call we can retrive it and trigger receiver
let _ = match env.set_rust_field(object, HOLDER_FIELD_NAME, sender) {
Ok(()) => {
println!("set_rust_field success");
}
Err(error) => {
println!("Error set_rust_field");
}
};
let result = match run_arti(
&env.get_string(target)
.expect("target is invalid")
......@@ -46,13 +64,104 @@ pub extern "C" fn Java_net_example_MyClass_myMethod(
static LOGGER: Once = Once::new();
fn init_logger() -> Result<()> {
if LOGGER.is_completed() {
let layer = tracing_android::layer("rust.arti")?;
LOGGER.call_once(|| Subscriber::new().with(layer).init());
}
LOGGER.call_once(|| {
let layer = tracing_android::layer("rust.arti").unwrap();
Subscriber::new().with(layer).init();
//set_global_default(subscriber);
// Set panic hook
std::panic::set_hook(Box::new(|msg| {
println!("arti-core: {:?}", msg);
}));
});
Ok(())
}
#[no_mangle]
pub extern "C" fn Java_net_example_MyClass_closeProxy(
env: JNIEnv,
object: JObject,
cache_dir: JString,
) {
println!("closing proxy...");
//Retriving sender to trigger close
match env.take_rust_field::<JObject, &str, Sender<()>>(object, HOLDER_FIELD_NAME) {
Ok(sender) => {
println!("is cancelled {}", sender.is_canceled());
match sender.send(()) {
Ok(()) => {
println!("send OK");
}
Err(error) => {
println!("send FAILED");
println!("{:?}", error);
}
}
}
Err(error) => println!("take_rust_field error {:?}", error),
}
//let sender: std::sync::MutexGuard<i32> = get_holder(&env, &class);
//sender.deref().send()
}
#[no_mangle]
pub extern "C" fn Java_net_example_MyClass_startDummyProxy(
env: JNIEnv,
object: JObject,
cache_dir: JString,
) -> jstring {
let _ = init_logger();
let (sender, receiver) = oneshot::channel::<>();
//save sender reference in JAVA, so in exit call we can retrive it and trigger receiver
let _ = match env.set_rust_field(object, HOLDER_FIELD_NAME, sender) {
Ok(()) => {
println!("set_rust_field success");
}
Err(error) => {
println!("Error set_rust_field");
}
};
let result = match run_dummy_arti(receiver) {
Ok(res) => format!("Http body: {}", res),
Err(e) => format!("Error: {}", e),
};
let output = env
.new_string(result)
.expect("failed to create java string");
output.into_inner()
}
#[no_mangle]
pub extern "C" fn Java_net_example_MyClass_stopDummyProxy(
env: JNIEnv,
object: JObject,
) {
match env.take_rust_field::<JObject, &str, Sender<()>>(object, HOLDER_FIELD_NAME) {
Ok(sender) => {
println!("is cancelled {}", sender.is_canceled());
match sender.send(()) {
Ok(()) => {
println!("send OK");
}
Err(error) => {
println!("send FAILED");
println!("{:?}", error);
}
}
}
Err(error) => println!("take_rust_field error {:?}", error),
}
}
/// Android 5.0 to 6.0 misses this function, which prevent Arti from running. This is a translation
/// to Rust of Musl implementation. If you don't plan to support anything below Android 7.0, you
/// should probably not copy this code.
......
use anyhow::Result;
use futures::{AsyncReadExt, AsyncWriteExt};
use futures::{AsyncReadExt, AsyncWriteExt, FutureExt};
use arti_client::{config::TorClientConfigBuilder, TorClient};
use futures::channel::oneshot;
use futures::channel::oneshot::*;
use tor_rtcompat::BlockOn;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::prelude::*;
fn run_arti(to: &str, cache: &str) -> Result<String> {
let runtime = tor_rtcompat::PreferredRuntime::create()?;
let rt_copy = runtime.clone();
......@@ -16,7 +21,8 @@ fn run_arti(to: &str, cache: &str) -> Result<String> {
rt_copy.block_on(async {
let client = TorClient::with_runtime(runtime)
.config(config)
.create_bootstrapped().await?;
.create_bootstrapped()
.await?;
let mut stream = client.connect((to, 80)).await?;
stream.write_all(b"GET / HTTP/1.1\r\nHost: ").await?;
......@@ -33,6 +39,23 @@ fn run_arti(to: &str, cache: &str) -> Result<String> {
})
}
fn run_dummy_arti(exit: Receiver<()>) -> Result<String> {
let (sender, receiver) = oneshot::channel::<()>();
let runtime = tor_rtcompat::PreferredRuntime::create()?;
let rt_copy = runtime.clone();
println!("dummy_proxy");
rt_copy.block_on(async {
futures::select! (
r = receiver.fuse() => println!("sasa"),
r = exit.fuse() => println!("sasa")
)
});
Ok(String::from("RT unblocked"))
}
/// Expose the JNI interface for Android
#[cfg(target_os = "android")]
pub mod android;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment