Commit e02f9690 authored by Mygod's avatar Mygod

Be more informative about sendFd fails

parent bb8cc7d4
...@@ -38,17 +38,17 @@ ...@@ -38,17 +38,17 @@
package com.github.shadowsocks; package com.github.shadowsocks;
import android.os.Build; import android.system.ErrnoException;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.system.ErrnoException;
public class JniHelper { public class JniHelper {
static { static {
System.loadLibrary("jni-helper"); System.loadLibrary("jni-helper");
} }
public static native int sendFd(int fd, @NonNull String path); public static native void sendFd(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,8 +169,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -169,8 +169,7 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface {
super.startNativeProcesses() super.startNativeProcesses()
val fd = startVpn() sendFd(startVpn())
if (!sendFd(fd)) throw IOException("sendFd failed")
} }
override fun buildAdditionalArguments(cmd: ArrayList<String>): ArrayList<String> { override fun buildAdditionalArguments(cmd: ArrayList<String>): ArrayList<String> {
...@@ -247,19 +246,27 @@ class VpnService : BaseVpnService(), LocalDnsService.Interface { ...@@ -247,19 +246,27 @@ 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) { sendFd(fd) } data.processes.start(cmd) {
try {
sendFd(fd)
} catch (e: ErrnoException) {
stopRunner(true, e.message)
}
}
return fd return fd
} }
private fun sendFd(fd: Int): Boolean { private fun sendFd(fd: Int) {
if (fd != -1) { if (fd == -1) throw IOException("Invalid fd (-1)")
var tries = 0 var tries = 0
while (tries < 10) { val path = File(Core.deviceStorage.filesDir, "sock_path").absolutePath
Thread.sleep(30L shl tries) while (true) try {
if (JniHelper.sendFd(fd, File(Core.deviceStorage.filesDir, "sock_path").absolutePath) != -1) return true Thread.sleep(30L shl tries)
tries += 1 JniHelper.sendFd(fd, path)
} return
} catch (e: ErrnoException) {
if (tries >= 10) throw e
tries += 1
} }
return false
} }
} }
#define LOG_TAG "JniHelper"
#include "jni.h" #include "jni.h"
#include <android/log.h>
#include <algorithm> #include <algorithm>
#include <cerrno> #include <cerrno>
...@@ -9,26 +6,40 @@ ...@@ -9,26 +6,40 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#include <sys/un.h> #include <sys/un.h>
#include <sys/socket.h>
#include <ancillary.h> #include <ancillary.h>
using namespace std; using namespace std;
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0) // Based on: https://android.googlesource.com/platform/libcore/+/564c7e8/luni/src/main/native/libcore_io_Linux.cpp#256
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0) static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor2, const char* functionName, int error) {
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0) jstring detailMessage = env->NewStringUTF(functionName);
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 jint JNICALL JNIEXPORT void JNICALL
Java_com_github_shadowsocks_JniHelper_sendFd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) { Java_com_github_shadowsocks_JniHelper_sendFd(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);
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
LOGE("socket() failed: %s (socket fd = %d)\n", strerror(errno), fd); throwErrnoException(env, "socket");
return (jint)-1; goto quit2;
} }
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
...@@ -36,20 +47,17 @@ JNIEXPORT jint JNICALL ...@@ -36,20 +47,17 @@ JNIEXPORT jint 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) {
LOGE("connect() failed: %s (fd = %d)\n", strerror(errno), fd); throwErrnoException(env, "connect");
close(fd); goto quit;
return (jint)-1;
} }
if (ancil_send_fd(fd, tun_fd)) { if (ancil_send_fd(fd, tun_fd)) throwErrnoException(env, "ancil_send_fd");
LOGE("ancil_send_fd: %s", strerror(errno));
close(fd);
return (jint)-1;
}
quit:
close(fd); close(fd);
quit2:
env->ReleaseStringUTFChars(path, sock_str); env->ReleaseStringUTFChars(path, sock_str);
return 0; return;
} }
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