Skip to content
This repository was archived by the owner on Aug 15, 2024. It is now read-only.

Commit 1261189

Browse files
authored
Merge pull request #4 from c4dt/build_ios
First working version for iOS
2 parents aa829eb + 4688ed4 commit 1261189

File tree

11 files changed

+174
-400
lines changed

11 files changed

+174
-400
lines changed

.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
debug/
4+
target/
5+
6+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8+
Cargo.lock
9+
10+
# These are backup files generated by rustfmt
11+
**/*.rs.bk
12+
13+
# MSVC Windows builds of rustc generate these, which store debugging information
14+
*.pdb
15+
16+
# For all IntelliJ users out there
17+
*.iml
18+
19+
*.zip

Cargo.toml

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,42 @@
22
name = "arti-rest"
33
version = "0.1.0"
44
authors = ["Linus Gasser <linus.gasser@epfl.ch>",
5-
"Laurent Girod <laurent.girod@epfl.ch>",
6-
"Christian Grigis <christian.grigis@epfl.ch>",
7-
"Valérian Rousset <valerian.rousset@epfl.ch>"]
5+
"Laurent Girod <laurent.girod@epfl.ch>",
6+
"Christian Grigis <christian.grigis@epfl.ch>",
7+
"Valérian Rousset <valerian.rousset@epfl.ch>"]
88
edition = "2018"
99

1010
[lib]
1111
name = "core"
12-
crate-type = ["cdylib", "staticlib"]
12+
crate-type = ["staticlib"]
1313

1414
[dependencies]
1515
log = "0.4.6"
1616
log-panics = "2.0"
1717

1818
# Packages for tor
19-
tor-client = {git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f"}
20-
tor-config = {git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f"}
21-
tor-dirmgr = {git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f"}
22-
tor-proto = {git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f"}
23-
tor-rtcompat = {git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f"}
24-
async-std = {features = ["attributes"]}
19+
tor-client = { git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f" }
20+
tor-config = { git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f" }
21+
tor-dirmgr = { git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f" }
22+
tor-proto = { git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f" }
23+
tor-rtcompat = { git = "https://gitlab.torproject.org/tpo/core/arti.git", rev = "c372671b5ad2663151cbaf2ff392f1e6f0ba292f" }
24+
async-std = { version = "1.9.0", features = ["attributes"] }
2525
serde = { version = "1.0.124", features = ["derive"] }
26-
tokio = {version = "1.0", features = ["full"]}
27-
tokio-util = {version = "0.6.7", features = ["full"]}
26+
tokio = { version = "1.0", features = ["full"] }
27+
tokio-util = { version = "0.6.7", features = ["full"] }
2828
futures = "0.3"
29-
30-
config = "*"
31-
simple-logging = "*"
32-
anyhow = "*"
29+
config = "0.11.0"
30+
simple-logging = "2.0.2"
31+
anyhow = "1.0.40"
3332
tokio-rustls = "0.22"
3433
webpki-roots = "0.21"
3534

3635

3736
[target.'cfg(target_os="android")'.dependencies]
3837
jni = { version = "0.16", default-features = false }
3938
android_logger = "0.8"
40-
openssl-sys = {features = ["vendored"]}
41-
rusqlite = {features = ["bundled"]}
39+
openssl-sys = { version = "0.9.62", features = ["vendored"] }
40+
rusqlite = { version = "0.25.1", features = ["bundled"] }
4241

4342
[target.'cfg(target_os = "ios")'.dependencies]
4443
libc = "0.2"

Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
arxc := arti-rest.xcframework
2+
arxcz := $(arxc).zip
3+
4+
.PHONY: build-ios
5+
build-ios: ios/arti-rest.xcframework $(arxcz)
6+
7+
ios/$(arxc): $(wildcard src/*)
8+
( cd ios; ./build_xcf.sh )
9+
10+
$(arxcz): ios/$(arxc)
11+
cd ios && \
12+
( cd $(arxc) && zip -r ../../$(arxcz) . ) && \
13+
swift package compute-checksum ../$(arxcz)

ios/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.xcframework

ios/Package.swift

Whitespace-only changes.

ios/arti-rest.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include <CoreFoundation/CoreFoundation.h>
2+
3+
#include <stdarg.h>
4+
#include <stdbool.h>
5+
#include <stdint.h>
6+
#include <stdlib.h>
7+
8+
CFStringRef call_tls_get(const char *domain);

ios/build_xcf.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
MODE=release
4+
XCFRAMEWORK_ARGS=""
5+
for arch in x86_64-apple-ios aarch64-apple-ios; do
6+
cargo build --target $arch --$MODE
7+
tdir=../target/$arch/$MODE
8+
mkdir -p $tdir/headers
9+
cp arti-rest.h module.modulemap $tdir/headers
10+
XCFRAMEWORK_ARGS="${XCFRAMEWORK_ARGS} -library $tdir/libcore.a"
11+
XCFRAMEWORK_ARGS="${XCFRAMEWORK_ARGS} -headers $tdir/headers/"
12+
done
13+
14+
XCFFILE=arti-rest.xcframework
15+
rm -rf $XCFFILE
16+
xcodebuild -create-xcframework $XCFRAMEWORK_ARGS -output $XCFFILE

ios/module.modulemap

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module arti_rest {
2+
header "arti-rest.h"
3+
export *
4+
}

src/ffi_android.rs

Lines changed: 7 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
1010
use jni::sys::{jint, jobject, jstring};
1111
use log::info;
1212

13-
use crate::{blocking_google_ch};
13+
use crate::{tls_get};
1414

1515

1616
#[no_mangle]
@@ -34,167 +34,17 @@ pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_initLogger(
3434
}
3535

3636
#[no_mangle]
37-
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_getGoogle(
37+
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_TLS_get(
3838
env: JNIEnv,
3939
_: JClass,
4040
cache_dir_j: JString,
41+
domain_j: JString,
4142
) -> jstring {
4243
let cache_dir: String = env.get_string(cache_dir_j).expect("Couldn't create rust string").into();
43-
let output = match blocking_google_ch(&cache_dir[..]) {
44-
Ok(s) => format!("Google.ch says: {}", s),
45-
Err(e) => format!("Error while calling google: {}", e),
44+
let domain: String = env.get_string(domain_j).expect("Couldn't create rust string").into();
45+
let output = match tls_get(&domain, Some(&cache_dir)) {
46+
Ok(s) => format!("Result is: {}", s),
47+
Err(e) => format!("Error while getting result: {}", e),
4648
};
4749
env.new_string(output).expect("Failed to build java string").into_inner()
4850
}
49-
50-
#[no_mangle]
51-
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_greet(
52-
env: JNIEnv,
53-
_: JClass,
54-
who: JString,
55-
) -> jstring {
56-
let str: String = env.get_string(who)
57-
.expect("Couldn't create rust string").into();
58-
59-
let output = env.new_string(format!("Hello 👋 {}!", str))
60-
.expect("Couldn't create java string");
61-
62-
output.into_inner()
63-
}
64-
65-
#[no_mangle]
66-
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_add(
67-
_env: JNIEnv,
68-
_: JClass,
69-
value1: jint,
70-
value2: jint,
71-
) -> jint {
72-
info!("Passed value1: {}, value2: {}", value1, value2);
73-
value1 + value2
74-
}
75-
76-
#[no_mangle]
77-
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_passObject(
78-
env: JNIEnv,
79-
_: JClass,
80-
object: JObject,
81-
) {
82-
let my_int_j_value_res = env.get_field(object, "intPar", "I");
83-
let my_int: i32 = my_int_j_value_res.unwrap().i().unwrap();
84-
85-
let my_str_j_value = env.get_field(object, "stringPar", "Ljava/lang/String;")
86-
.expect("Couldn't get JValue");
87-
let my_str_j_object = my_str_j_value.l();
88-
let my_str_j_string = JString::from(my_str_j_object.unwrap());
89-
90-
let my_str_java_string = env.get_string(my_str_j_string).unwrap();
91-
let my_str = my_str_java_string.to_str().unwrap();
92-
93-
info!("Passed: {}, {}", my_int, my_str);
94-
}
95-
96-
#[no_mangle]
97-
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_returnObject(
98-
env: JNIEnv,
99-
_: JClass,
100-
) -> jobject {
101-
let cls = env.find_class("com/schuetz/rustandroidios/Dummy");
102-
103-
let my_int_j_value = JValue::from(123);
104-
105-
let str_parameter_j_string = env.new_string("my string parameter")
106-
.expect("Couldn't create java string!");
107-
let str_parameter_j_value = JValue::from(JObject::from(str_parameter_j_string));
108-
109-
let obj = env.new_object(
110-
cls.unwrap(),
111-
"(Ljava/lang/String;I)V",
112-
&[str_parameter_j_value, my_int_j_value],
113-
);
114-
115-
obj.unwrap().into_inner()
116-
}
117-
118-
pub static mut CALLBACK_SENDER: Option<Sender<String>> = None;
119-
120-
#[no_mangle]
121-
pub unsafe extern "system" fn Java_com_schuetz_rustandroidios_JniApi_registerCallback(
122-
env: JNIEnv,
123-
_: JClass,
124-
callback: jobject,
125-
) {
126-
let my_callback = MyCallbackImpl {
127-
java_vm: env.get_java_vm().unwrap(),
128-
callback: env.new_global_ref(callback).unwrap(),
129-
};
130-
register_callback_internal(Box::new(my_callback));
131-
132-
// Let's send a message immediately, to test it
133-
send_to_callback("Hello callback!".to_owned());
134-
}
135-
136-
unsafe fn send_to_callback(string: String) {
137-
match &CALLBACK_SENDER {
138-
Some(s) => {
139-
s.send(string).expect("Couldn't send message to callback!");
140-
}
141-
None => {
142-
info!("No callback registered");
143-
}
144-
}
145-
}
146-
147-
fn register_callback_internal(callback: Box<dyn MyCallback>) {
148-
// Make callback implement Send (marker for thread safe, basically) https://doc.rust-lang.org/std/marker/trait.Send.html
149-
let my_callback =
150-
unsafe { std::mem::transmute::<Box<dyn MyCallback>, Box<dyn MyCallback + Send>>(callback) };
151-
152-
// Create channel
153-
let (tx, rx): (Sender<String>, Receiver<String>) = mpsc::channel();
154-
155-
// Save the sender in a static variable, which will be used to push elements to the callback
156-
unsafe {
157-
CALLBACK_SENDER = Some(tx);
158-
}
159-
160-
// Thread waits for elements pushed to SENDER and calls the callback
161-
thread::spawn(move || {
162-
for string in rx.iter() {
163-
my_callback.call(string)
164-
}
165-
});
166-
}
167-
168-
trait MyCallback {
169-
fn call(&self, par: String);
170-
}
171-
172-
struct MyCallbackImpl {
173-
// The callback passed from Android is a local reference: only valid during the method call.
174-
// To store it, we need to put it in a global reference.
175-
// See https://developer.android.com/training/articles/perf-jni#local-and-global-references
176-
callback: GlobalRef,
177-
178-
// We need JNIEnv to call the callback.
179-
// JNIEnv is valid only in the same thread, so we have to store the vm instead, and use it to get
180-
// a JNIEnv for the current thread.
181-
// See https://developer.android.com/training/articles/perf-jni#javavm-and-jnienvb
182-
java_vm: JavaVM,
183-
}
184-
185-
impl MyCallback for MyCallbackImpl {
186-
fn call(&self, par: String) {
187-
let env = self.java_vm.attach_current_thread().unwrap();
188-
189-
let str = env.new_string(par)
190-
.expect("Couldn't create java string!");
191-
let str_j_value = JValue::from(JObject::from(str));
192-
193-
env.call_method(
194-
self.callback.as_obj(),
195-
"call",
196-
"(Ljava/lang/String;)V",
197-
&[str_j_value],
198-
).expect("Couldn't call callback");
199-
}
200-
}

0 commit comments

Comments
 (0)