diff --git a/ffi/TerracottaAndroidAPI.java b/ffi/TerracottaAndroidAPI.java index dbaff0e..a307e63 100644 --- a/ffi/TerracottaAndroidAPI.java +++ b/ffi/TerracottaAndroidAPI.java @@ -18,6 +18,7 @@ import java.net.UnknownHostException; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -234,32 +235,35 @@ public static void setWaiting() { /** *

Set Terracotta Android into 'host-scanning' state.

* - * @param player the player's name. A default value will be taken if it's null. + * @param room the room code, which may be used if it's valid. + * @param player the player's name. A default value will be taken if it's null. + * @param extraNodes extra public server nodes for EasyTier. * @throws IllegalStateException if Terracotta Android hasn't been initialized. * @implNote Usually, this method doesn't take a long time to fetch states. * However, when initializing the EasyTier, state fetching may block for ~1 seconds. */ - public static void setScanning(@Nullable String room, @Nullable String player) { + public static void setScanning(@Nullable String room, @Nullable String player, @Nullable List extraNodes) { assertStarted(); - setScanning0(room, player); + setScanning0(room, player, extraNodes == null ? null : String.join("\0", extraNodes)); } /** *

Set Terracotta Android into 'guest-connecting' state.

* - * @param room the room code. False will be returned if it's invalid. - * @param player the player's name. A default value will be taken if it's null. + * @param room the room code. False will be returned if it's invalid. + * @param player the player's name. A default value will be taken if it's null. + * @param extraNodes extra public server nodes for EasyTier. * @return True if room code is valid, false otherwise. * @throws IllegalStateException if Terracotta Android hasn't been initialized. * @throws NullPointerException if room is null. * @implNote Usually, this method doesn't take a long time to fetch states. * However, when initializing the EasyTier, state fetching may block for ~1 seconds. */ - public static boolean setGuesting(String room, @Nullable String player) { + public static boolean setGuesting(String room, @Nullable String player, @Nullable List extraNodes) { Objects.requireNonNull(room, "room"); assertStarted(); - return setGuesting0(room, player); + return setGuesting0(room, player, extraNodes == null ? null : String.join("\0", extraNodes)); } /** @@ -381,7 +385,7 @@ public static void panic() { private static final long FD_PENDING = ((long) Integer.MAX_VALUE) + 1; private static final long FD_REJECT = FD_PENDING + 1; -; + @SuppressWarnings("unused") // Native callback private static int onVpnServiceStateChanged(byte ip1, byte ip2, byte ip3, byte ip4, short network_length, String cidr) throws UnknownHostException { if (pendingRequest != null) { @@ -460,9 +464,9 @@ private static void assertStarted() { private static native void setWaiting0(); - private static native void setScanning0(String room, String player); + private static native void setScanning0(String room, String player, String extraNodes); - private static native boolean setGuesting0(String room, String player); + private static native boolean setGuesting0(String room, String player, String extraNodes); private static native int verifyRoomCode0(String room); diff --git a/src/lib.rs b/src/lib.rs index c05a357..ba2efdb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -138,8 +138,8 @@ extern "system" fn JNI_OnLoad(vm: JavaVM, _: *mut c_void) -> jint { of!["start0", "(Ljava/lang/String;I)I", jni_start], of!["getState0", "()Ljava/lang/String;", jni_get_state], of!["setWaiting0", "()V", jni_set_waiting], - of!["setScanning0", "(Ljava/lang/String;Ljava/lang/String;)V", jni_set_scanning], - of!["setGuesting0", "(Ljava/lang/String;Ljava/lang/String;)Z", jni_set_guesting], + of!["setScanning0", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", jni_set_scanning], + of!["setGuesting0", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Z", jni_set_guesting], of!["verifyRoomCode0", "(Ljava/lang/String;)I", jni_verify_room_code], of!["getMetadata0", "()Ljava/lang/String;", jni_get_metadata], of!["prepareExportLogs0", "()J", jni_prepare_export_logs], @@ -276,20 +276,24 @@ extern "system" fn jni_set_waiting<'l>(jenv: JNIEnv<'l>, _: JClass<'l>) { } } -extern "system" fn jni_set_scanning<'l>(jenv: JNIEnv<'l>, _: JClass<'l>, room: JString<'l>, player: JString<'l>) { +extern "system" fn jni_set_scanning<'l>(jenv: JNIEnv<'l>, _: JClass<'l>, room: JString<'l>, player: JString<'l>, extra_nodes: JString<'l>) { try_jvm! { |jenv| let room = parse_jstring(&jenv, &room); let player = parse_jstring(&jenv, &player); - controller::set_scanning(room, player, vec![]); + let extra_nodes = parse_jstring(&jenv, &extra_nodes); + let extra_nodes: Vec = extra_nodes.map(|s| s.split("\0").map(|s| s.into()).collect()).unwrap_or(vec![]); + controller::set_scanning(room, player, extra_nodes); } } -extern "system" fn jni_set_guesting<'l>(jenv: JNIEnv<'l>, _: JClass<'l>, room: JString<'l>, player: JString<'l>) -> jboolean { +extern "system" fn jni_set_guesting<'l>(jenv: JNIEnv<'l>, _: JClass<'l>, room: JString<'l>, player: JString<'l>, extra_nodes: JString<'l>) -> jboolean { try_jvm! { |jenv| let room = parse_jstring(&jenv, &room).expect("'room' must not be NULL."); let player = parse_jstring(&jenv, &player); + let extra_nodes = parse_jstring(&jenv, &extra_nodes); + let extra_nodes: Vec = extra_nodes.map(|s| s.split("\0").map(|s| s.into()).collect()).unwrap_or(vec![]); - if let Some(room) = Room::from(&room) && controller::set_guesting(room, player, vec![]) { + if let Some(room) = Room::from(&room) && controller::set_guesting(room, player, extra_nodes) { JNI_TRUE } else { JNI_FALSE