diff options
-rw-r--r-- | tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java | 13 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/api-android.go | 12 | ||||
-rw-r--r-- | tunnel/tools/libwg-go/jni.c | 50 |
3 files changed, 63 insertions, 12 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java index 3d0886cf..b7e55465 100644 --- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java +++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java @@ -40,7 +40,7 @@ import androidx.collection.ArraySet; * WireGuard tunnels. */ @NonNullForAll -public final class GoBackend implements Backend { +public final class GoBackend implements Backend, EventHandler { private static final int DNS_RESOLUTION_RETRIES = 10; private static final String TAG = "WireGuard/GoBackend"; @Nullable private static AlwaysOnCallback alwaysOnCallback; @@ -78,7 +78,7 @@ public final class GoBackend implements Backend { private static native void wgTurnOff(int handle); - private static native int wgTurnOn(String ifName, int tunFd, String settings); + private static native int wgTurnOn(String ifName, int tunFd, String settings, EventHandler handler); private static native String wgVersion(); @@ -304,7 +304,7 @@ public final class GoBackend implements Backend { if (tun == null) throw new BackendException(Reason.TUN_CREATION_ERROR); Log.d(TAG, "Go backend " + wgVersion()); - currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig); + currentTunnelHandle = wgTurnOn(tunnel.getName(), tun.detachFd(), goConfig, this); } if (currentTunnelHandle < 0) throw new BackendException(Reason.GO_ACTIVATION_ERROR_CODE, currentTunnelHandle); @@ -329,6 +329,9 @@ public final class GoBackend implements Backend { tunnel.onStateChange(state); } + public void onEvent(String event) { + } + /** * Callback for {@link GoBackend} that is invoked when {@link VpnService} is started by the * system's Always-On VPN mode. @@ -415,3 +418,7 @@ public final class GoBackend implements Backend { } } } + +interface EventHandler { + public void onEvent(String event); +} diff --git a/tunnel/tools/libwg-go/api-android.go b/tunnel/tools/libwg-go/api-android.go index d47c5d76..e3e97c67 100644 --- a/tunnel/tools/libwg-go/api-android.go +++ b/tunnel/tools/libwg-go/api-android.go @@ -7,6 +7,7 @@ package main // #cgo LDFLAGS: -llog // #include <android/log.h> +// extern void wgOnEvent(void *eventHandler, const char *event); import "C" import ( @@ -48,6 +49,7 @@ func (l AndroidLogger) Printf(format string, args ...interface{}) { type TunnelHandle struct { device *device.Device uapi net.Listener + eventHandler unsafe.Pointer } var tunnelHandles map[int32]TunnelHandle @@ -73,7 +75,7 @@ func init() { } //export wgTurnOn -func wgTurnOn(interfaceName string, tunFd int32, settings string) int32 { +func wgTurnOn(interfaceName string, tunFd int32, settings string, eventHandler unsafe.Pointer) int32 { tag := cstring("WireGuard/GoBackend/" + interfaceName) logger := &device.Logger{ Verbosef: AndroidLogger{level: C.ANDROID_LOG_DEBUG, tag: tag}.Printf, @@ -142,21 +144,23 @@ func wgTurnOn(interfaceName string, tunFd int32, settings string) int32 { device.Close() return -1 } - tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi} + tunnelHandles[i] = TunnelHandle{device: device, uapi: uapi, eventHandler: eventHandler} return i } //export wgTurnOff -func wgTurnOff(tunnelHandle int32) { +func wgTurnOff(tunnelHandle int32) unsafe.Pointer { handle, ok := tunnelHandles[tunnelHandle] if !ok { - return + return nil } + eventHandler := handle.eventHandler delete(tunnelHandles, tunnelHandle) if handle.uapi != nil { handle.uapi.Close() } handle.device.Close() + return eventHandler } //export wgGetSocketV4 diff --git a/tunnel/tools/libwg-go/jni.c b/tunnel/tools/libwg-go/jni.c index 7ad94d35..353cb474 100644 --- a/tunnel/tools/libwg-go/jni.c +++ b/tunnel/tools/libwg-go/jni.c @@ -3,31 +3,58 @@ * Copyright © 2017-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */ +#include <assert.h> #include <jni.h> #include <stdlib.h> #include <string.h> +#include <android/log.h> + +#define TAG "WireGuard/GoBackend" struct go_string { const char *str; long n; }; -extern int wgTurnOn(struct go_string ifname, int tun_fd, struct go_string settings); -extern void wgTurnOff(int handle); +extern int wgTurnOn(struct go_string ifname, int tun_fd, struct go_string settings, void *eventHandler); +extern void *wgTurnOff(int handle); extern int wgGetSocketV4(int handle); extern int wgGetSocketV6(int handle); extern char *wgGetConfig(int handle); extern char *wgVersion(); +extern void wgOnEvent(void *eventHandler, const char *event); + +static JavaVM *gVm; +static jclass gEventHandlerClass; +static jmethodID gOnEventMethod; + +JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) +{ + JNIEnv* env; + char buf[128]; + + gVm = vm; + if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { + return JNI_ERR; + } + + gEventHandlerClass = (*env)->FindClass(env, "com/wireguard/android/backend/EventHandler"); -JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNIEnv *env, jclass c, jstring ifname, jint tun_fd, jstring settings) + gOnEventMethod = (*env)->GetMethodID(env, gEventHandlerClass, "onEvent", "(Ljava/lang/String;)V"); + + return JNI_VERSION_1_6; +} + +JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNIEnv *env, jclass c, jstring ifname, jint tun_fd, jstring settings, jobject eventHandler) { const char *ifname_str = (*env)->GetStringUTFChars(env, ifname, 0); size_t ifname_len = (*env)->GetStringUTFLength(env, ifname); const char *settings_str = (*env)->GetStringUTFChars(env, settings, 0); size_t settings_len = (*env)->GetStringUTFLength(env, settings); + jobject event_handler = (*env)->NewGlobalRef(env, eventHandler); int ret = wgTurnOn((struct go_string){ .str = ifname_str, .n = ifname_len }, tun_fd, (struct go_string){ .str = settings_str, .n = settings_len - }); + }, event_handler); (*env)->ReleaseStringUTFChars(env, ifname, ifname_str); (*env)->ReleaseStringUTFChars(env, settings, settings_str); return ret; @@ -35,7 +62,9 @@ JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOn(JNI JNIEXPORT void JNICALL Java_com_wireguard_android_backend_GoBackend_wgTurnOff(JNIEnv *env, jclass c, jint handle) { - wgTurnOff(handle); + jobject event_handler = wgTurnOff(handle); + if (event_handler) + (*env)->DeleteGlobalRef(env, event_handler); } JNIEXPORT jint JNICALL Java_com_wireguard_android_backend_GoBackend_wgGetSocketV4(JNIEnv *env, jclass c, jint handle) @@ -69,3 +98,14 @@ JNIEXPORT jstring JNICALL Java_com_wireguard_android_backend_GoBackend_wgVersion free(version); return ret; } + +void wgOnEvent(void *eventHandler, const char *event) +{ + JavaVMAttachArgs attachArgs = { JNI_VERSION_1_6, NULL, NULL }; + jobject jEventHandler = eventHandler; + JNIEnv *env; + jint rs = (*gVm)->AttachCurrentThread(gVm, &env, &attachArgs); + assert (rs == JNI_OK); + jstring jevent = (*env)->NewStringUTF(env, event); + (*env)->CallVoidMethod(env, jEventHandler, gOnEventMethod, jevent); +} |