From aa71142549ab2aa31d5f8cdbded93b54e5dcf24f Mon Sep 17 00:00:00 2001 From: Max Lv Date: Fri, 27 Jun 2014 14:42:12 +0800 Subject: [PATCH 1/3] using jni based to WAR Android L issue --- build-ndk.sh | 2 +- jni/Android.mk | 33 ++++++++++++++----- .../shadowsocks/ShadowsocksNatService.scala | 5 +-- .../shadowsocks/ShadowsocksVpnService.scala | 14 +++----- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/build-ndk.sh b/build-ndk.sh index c127ad7f..6678ff04 100755 --- a/build-ndk.sh +++ b/build-ndk.sh @@ -4,7 +4,7 @@ ndk-build mkdir -p src/main/assets/armeabi mkdir -p src/main/assets/armeabi-v7a mkdir -p src/main/assets/x86 -for app in ip6tables iptables pdnsd redsocks ss-local ss-tunnel tun2socks +for app in ip6tables iptables pdnsd redsocks ss-tunnel do mv libs/armeabi/$app src/main/assets/armeabi/ mv libs/armeabi-v7a/$app src/main/assets/armeabi-v7a/ diff --git a/jni/Android.mk b/jni/Android.mk index 2d4feca0..39af4ce1 100755 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -143,16 +143,30 @@ LOCAL_CFLAGS := -Wall -O2 -I$(LOCAL_PATH)/pdnsd include $(BUILD_EXECUTABLE) ######################################################## -## shadowsocks local +## pdnsd library +######################################################## + +include $(CLEAR_VARS) + +PDNSD_SOURCES := $(wildcard $(LOCAL_PATH)/pdnsd/src/*.c) main-jni.cpp + +LOCAL_MODULE := pdnsd-jni +LOCAL_SRC_FILES := $(PDNSD_SOURCES:$(LOCAL_PATH)/%=%) +LOCAL_CFLAGS := -Wall -O2 -DPDNSD_JNI -I$(LOCAL_PATH)/pdnsd + +include $(BUILD_SHARED_LIBRARY) + +######################################################## +## shadowsocks local library ######################################################## include $(CLEAR_VARS) SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c json.c jconf.c acl.c -LOCAL_MODULE := ss-local -LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES)) -LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL \ +LOCAL_MODULE := ss-local-jni +LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES)) main-jni.cpp +LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL -DSSLOCAL_JNI \ -DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H \ -I$(LOCAL_PATH)/libev/ \ -I$(LOCAL_PATH)/openssl/include \ @@ -163,7 +177,7 @@ LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork LOCAL_LDLIBS := -llog -include $(BUILD_EXECUTABLE) +include $(BUILD_SHARED_LIBRARY) ######################################################## ## shadowsocks tunnel @@ -204,7 +218,7 @@ LOCAL_STATIC_LIBRARIES := cpufeatures include $(BUILD_SHARED_LIBRARY) ######################################################## -## tun2socks +## tun2socks-library ######################################################## include $(CLEAR_VARS) @@ -214,6 +228,7 @@ LOCAL_CFLAGS += -DBADVPN_THREADWORK_USE_PTHREAD -DBADVPN_LINUX -DBADVPN_BREACTOR LOCAL_CFLAGS += -DBADVPN_USE_SELFPIPE -DBADVPN_USE_EPOLL LOCAL_CFLAGS += -DBADVPN_LITTLE_ENDIAN -DBADVPN_THREAD_SAFE LOCAL_CFLAGS += -DNDEBUG -DANDROID +LOCAL_CFLAGS += -DTUN2SOCKS_JNI LOCAL_C_INCLUDES:= \ $(LOCAL_PATH)/badvpn/lwip/src/include/ipv4 \ @@ -283,13 +298,13 @@ TUN2SOCKS_SOURCES := \ tun2socks/SocksUdpGwClient.c \ udpgw_client/UdpGwClient.c -LOCAL_MODULE := tun2socks +LOCAL_MODULE := tun2socks-jni LOCAL_LDLIBS := -ldl -llog -LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES)) +LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES)) main-jni.cpp -include $(BUILD_EXECUTABLE) +include $(BUILD_SHARED_LIBRARY) # OpenSSL openssl_subdirs := $(addprefix $(LOCAL_PATH)/openssl/,$(addsuffix /Android.mk, \ diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala index 39137b75..93163739 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala @@ -119,12 +119,13 @@ class ShadowsocksNatService extends Service with BaseService { } val args = (Path.BASE + - "ss-local -b 127.0.0.1 -s '%s' -p '%d' -l '%d' -k ''%s' -m '%s' -f " + + "ss-local -b 127.0.0.1 -s %s -p %d -l %d -k %s -m %s -f " + Path.BASE + "ss-local.pid") .format(config.proxy, config.remotePort, config.localPort, config.sitekey, config.encMethod) val cmd = if (config.isGFWList && isACLEnabled) args + " --acl " + Path.BASE + "chn.acl" else args if (BuildConfig.DEBUG) Log.d(TAG, cmd) - Console.runCommand(cmd) + + Core.sslocal(cmd.split(" ")) } def startDnsDaemon() { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index 96195592..32b0fc3e 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -82,11 +82,11 @@ class ShadowsocksVpnService extends VpnService with BaseService { def startShadowsocksDaemon() { val cmd: String = (Path.BASE + - "ss-local -b 127.0.0.1 -s '%s' -p '%d' -l '%d' -k '%s' -m '%s' -u -f " + + "ss-local -b 127.0.0.1 -s %s -p %d -l %d -k %s -m %s -u -f " + Path.BASE + "ss-local.pid") .format(config.proxy, config.remotePort, config.localPort, config.sitekey, config.encMethod) if (BuildConfig.DEBUG) Log.d(TAG, cmd) - System.exec(cmd) + Core.sslocal(cmd.split(" ")) } def startDnsDaemon() { @@ -101,7 +101,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { }) val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd.conf" if (BuildConfig.DEBUG) Log.d(TAG, cmd) - System.exec(cmd) + Core.pdnsd(cmd.split(" ")) } def getVersionName: String = { @@ -202,10 +202,9 @@ class ShadowsocksVpnService extends VpnService with BaseService { else cmd += " --dnsgw %s:8153".format(PRIVATE_VLAN.format("1")) - if (BuildConfig.DEBUG) - Log.d(TAG, cmd) + if (BuildConfig.DEBUG) Log.d(TAG, cmd) - System.exec(cmd) + Core.tun2socks(cmd.split(" ")) } /** Called when the activity is first created. */ @@ -260,11 +259,8 @@ class ShadowsocksVpnService extends VpnService with BaseService { val ab = new ArrayBuffer[String] ab.append("kill -9 `cat " + Path.BASE + "ss-local.pid`") - ab.append("killall -9 ss-local") ab.append("kill -9 `cat " + Path.BASE + "tun2socks.pid`") - ab.append("killall -9 tun2socks") ab.append("kill -15 `cat " + Path.BASE + "pdnsd.pid`") - ab.append("killall -15 pdnsd") Console.runCommand(ab.toArray) } From 8ece167ffd105300f4aaa684d061c540a3c15021 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Fri, 27 Jun 2014 14:58:11 +0800 Subject: [PATCH 2/3] add missing files --- jni/main-jni.cpp | 84 +++++++++++++++++++ .../java/com/github/shadowsocks/Core.java | 51 +++++++++++ 2 files changed, 135 insertions(+) create mode 100644 jni/main-jni.cpp create mode 100755 src/main/java/com/github/shadowsocks/Core.java diff --git a/jni/main-jni.cpp b/jni/main-jni.cpp new file mode 100644 index 00000000..fa0298ac --- /dev/null +++ b/jni/main-jni.cpp @@ -0,0 +1,84 @@ +#include +#include +#include + +typedef unsigned short char16_t; + +class String8 { +public: + String8() { + mString = 0; + } + + ~String8() { + if (mString) { + free(mString); + } + } + + void set(const char16_t* o, size_t numChars) { + if (mString) { + free(mString); + } + mString = (char*) malloc(numChars + 1); + if (!mString) { + return; + } + for (size_t i = 0; i < numChars; i++) { + mString[i] = (char) o[i]; + } + mString[numChars] = '\0'; + } + + const char* string() { + return mString; + } +private: + char* mString; +}; + +extern "C" { + +int main(int argc, char* args[]); + +#if defined(PDNSD_JNI) +jint Java_com_github_shadowsocks_Core_pdnsd(JNIEnv *env, jobject thiz, jobjectArray argv) { +#elif defined(SSLOCAL_JNI) +jint Java_com_github_shadowsocks_Core_sslocal(JNIEnv *env, jobject thiz, jobjectArray argv) { +#elif defined(SSTUNNEL_JNI) +jint Java_com_github_shadowsocks_Core_sstunnel(JNIEnv *env, jobject thiz, jobjectArray argv) { +#elif defined(TUN2SOCKS_JNI) +jint Java_com_github_shadowsocks_Core_tun2socks(JNIEnv *env, jobject thiz, jobjectArray argv) { +#else +#error "invalid header" +#endif + + int argc = argv ? env->GetArrayLength(argv) : 0; + char **args = NULL; + String8 tmp_8; + + if (argc > 0) { + args = (char **)malloc((argc+1)*sizeof(char *)); + for (int i = 0; i < argc; ++i) { + jstring arg = reinterpret_cast(env->GetObjectArrayElement(argv, i)); + const jchar *str = env->GetStringCritical(arg, 0); + tmp_8.set(str, env->GetStringLength(arg)); + env->ReleaseStringCritical(arg, str); + args[i] = strdup(tmp_8.string()); + } + args[argc] = NULL; + + pid_t pid; + pid = fork(); + if (pid == 0) { + int ret = main(argc, args); + return ret; + } + + if (args != NULL) free(args); + } + + return 0; +} + +} diff --git a/src/main/java/com/github/shadowsocks/Core.java b/src/main/java/com/github/shadowsocks/Core.java new file mode 100755 index 00000000..7af88993 --- /dev/null +++ b/src/main/java/com/github/shadowsocks/Core.java @@ -0,0 +1,51 @@ +/* Shadowsocks - A shadowsocks client for Android + * Copyright (C) 2012 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * + * ___====-_ _-====___ + * _--^^^#####// \\#####^^^--_ + * _-^##########// ( ) \\##########^-_ + * -############// |\^^/| \\############- + * _/############// (@::@) \\############\_ + * /#############(( \\// ))#############\ + * -###############\\ (oo) //###############- + * -#################\\ / VV \ //#################- + * -###################\\/ \//###################- + * _#/|##########/\######( /\ )######/\##########|\#_ + * |/ |#/\#/\#/\/ \#/\##\ | | /##/\#/ \/\#/\#/\#| \| + * ` |/ V V ` V \#\| | | |/#/ V ' V V \| ' + * ` ` ` ` / | | | | \ ' ' ' ' + * ( | | | | ) + * __\ | | | | /__ + * (vvv(VVV)(VVV)vvv) + * + * HERE BE DRAGONS + * + */ + +package com.github.shadowsocks; + +public class Core { + static { + java.lang.System.loadLibrary("ss-local-jni"); + java.lang.System.loadLibrary("tun2socks-jni"); + java.lang.System.loadLibrary("pdnsd-jni"); + } + + public static native void sslocal(String[] cmd); + public static native void tun2socks(String[] cmd); + public static native void pdnsd(String[] cmd); +} From 5aefc885c89a97ab60e10151dd741379f30119ab Mon Sep 17 00:00:00 2001 From: Max Lv Date: Fri, 27 Jun 2014 16:04:09 +0800 Subject: [PATCH 3/3] update travis --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9799b7a8..8e38b84f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,14 +11,14 @@ before_install: - sudo apt-get install ccache - export NDK_CCACHE=ccache - export ARCH=`uname -m` -- wget http://dl.google.com/android/android-sdk_r22.6.2-linux.tgz -- tar xf android-sdk_r22.6.2-linux.tgz +- wget http://dl.google.com/android/android-sdk_r23-linux.tgz +- tar xf android-sdk_r23-linux.tgz - wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-${ARCH}.tar.bz2 - tar xf android-ndk-r9d-linux-${ARCH}.tar.bz2 - export ANDROID_NDK_HOME=`pwd`/android-ndk-r9d - export ANDROID_HOME=`pwd`/android-sdk-linux - export PATH=${PATH}:${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools -- echo "y" | android update sdk --filter tools,platform-tools,build-tools-19.0.3,android-19,extra-google-m2repository,extra-android-m2repository --no-ui --no-https -a +- echo "y" | android update sdk --filter tools,platform-tools,build-tools-20,android-19,extra-google-m2repository,extra-android-m2repository --no-ui --no-https -a install: - gem install --version 0.8.9 faraday - gem install travis-artifacts