Commit 856f726d authored by Max Lv's avatar Max Lv

Refine sendFD #2030

parent c60f7be7
...@@ -48,7 +48,19 @@ public class JniHelper { ...@@ -48,7 +48,19 @@ public class JniHelper {
System.loadLibrary("jni-helper"); System.loadLibrary("jni-helper");
} }
public static native void sendFd(int fd, @NonNull String path) throws ErrnoException; public static void sendFd(int fd, @NonNull String path) throws ErrnoException {
int[] ret = sendFdInternal(fd, path);
if (ret != null) {
if (ret[0] == -1)
throw new ErrnoException("socket", ret[1]);
else if (ret[0] == -2)
throw new ErrnoException("connect", ret[1]);
else if (ret[0] == -3)
throw new ErrnoException("ancil_send_fd", ret[1]);
}
}
public static native int[] sendFdInternal(int fd, @NonNull String path) throws ErrnoException;
@Nullable @Nullable
public static native byte[] parseNumericAddress(@NonNull String str); public static native byte[] parseNumericAddress(@NonNull String str);
} }
...@@ -169,7 +169,9 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -169,7 +169,9 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
super.startNativeProcesses() super.startNativeProcesses()
sendFd(startVpn()) val fd = startVpn()
sendFd(fd)
} }
override fun buildAdditionalArguments(cmd: ArrayList<String>): ArrayList<String> { override fun buildAdditionalArguments(cmd: ArrayList<String>): ArrayList<String> {
...@@ -246,13 +248,8 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -246,13 +248,8 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
cmd += "--dnsgw" cmd += "--dnsgw"
cmd += "127.0.0.1:${DataStore.portLocalDns}" cmd += "127.0.0.1:${DataStore.portLocalDns}"
} }
data.processes.start(cmd) { data.processes.start(cmd)
try {
sendFd(fd)
} catch (e: ErrnoException) {
stopRunner(true, e.message)
}
}
return fd return fd
} }
...@@ -261,11 +258,11 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -261,11 +258,11 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
var tries = 0 var tries = 0
val path = File(Core.deviceStorage.noBackupFilesDir, "sock_path").absolutePath val path = File(Core.deviceStorage.noBackupFilesDir, "sock_path").absolutePath
while (true) try { while (true) try {
Thread.sleep(30L shl tries) Thread.sleep(500L shl tries)
JniHelper.sendFd(fd, path) JniHelper.sendFd(fd, path)
return return
} catch (e: ErrnoException) { } catch (e: ErrnoException) {
if (tries >= 10) throw e if (tries >= 3) throw e
tries += 1 tries += 1
} }
} }
......
Subproject commit 58f8a8883e51e5cb97391c4b6733ce255bf11f95 Subproject commit 9965ce070a5330602a71e97fdd41213e1fdd8d6d
...@@ -10,35 +10,26 @@ ...@@ -10,35 +10,26 @@
using namespace std; using namespace std;
// Based on: https://android.googlesource.com/platform/libcore/+/564c7e8/luni/src/main/native/libcore_io_Linux.cpp#256 // return -1 for socket error
static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor2, const char* functionName, int error) { // return -2 for connect error
jstring detailMessage = env->NewStringUTF(functionName); // return -3 for ancil_send_fd error
if (detailMessage == NULL) {
// Not really much we can do here. We're probably dead in the water,
// but let's try to stumble on...
env->ExceptionClear();
}
env->Throw(reinterpret_cast<jthrowable>(env->NewObject(exceptionClass, ctor2, detailMessage, error)));
env->DeleteLocalRef(detailMessage);
}
static void throwErrnoException(JNIEnv* env, const char* functionName) {
int error = errno;
static jclass ErrnoException = env->FindClass("android/system/ErrnoException");
static jmethodID ctor2 = env->GetMethodID(ErrnoException, "<init>", "(Ljava/lang/String;I)V");
throwException(env, ErrnoException, ctor2, functionName, error);
}
#pragma clang diagnostic ignored "-Wunused-parameter" #pragma clang diagnostic ignored "-Wunused-parameter"
extern "C" { extern "C" {
JNIEXPORT void JNICALL JNIEXPORT jintArray JNICALL
Java_com_github_shadowsocks_JniHelper_sendFd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) { Java_com_github_shadowsocks_JniHelper_sendFdInternal(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) {
int fd; int fd;
struct sockaddr_un addr; struct sockaddr_un addr;
const char *sock_str = env->GetStringUTFChars(path, 0); const char *sock_str = env->GetStringUTFChars(path, 0);
jint info[2] = {0};
jintArray ret = env->NewIntArray(2);
if (ret == nullptr) {
goto quit3;
}
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
throwErrnoException(env, "socket"); info[0] = -1;
info[1] = errno;
goto quit2; goto quit2;
} }
...@@ -47,17 +38,23 @@ JNIEXPORT void JNICALL ...@@ -47,17 +38,23 @@ JNIEXPORT void JNICALL
strncpy(addr.sun_path, sock_str, sizeof(addr.sun_path)-1); strncpy(addr.sun_path, sock_str, sizeof(addr.sun_path)-1);
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
throwErrnoException(env, "connect"); info[0] = -2;
info[1] = errno;
goto quit; goto quit;
} }
if (ancil_send_fd(fd, tun_fd)) throwErrnoException(env, "ancil_send_fd"); if (ancil_send_fd(fd, tun_fd)) {
info[0] = -3;
info[1] = errno;
}
quit: quit:
close(fd); close(fd);
quit2: quit2:
env->ReleaseStringUTFChars(path, sock_str); env->ReleaseStringUTFChars(path, sock_str);
return; env->SetIntArrayRegion(ret, 0, 2, info);
quit3:
return ret;
} }
JNIEXPORT jbyteArray JNICALL JNIEXPORT jbyteArray JNICALL
......
Markdown is supported
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