Compare commits

..
8 Commits
Author SHA1 Message Date
Max Lv c920c0daa4 Bump version 2017-02-24 19:37:23 +08:00
Mygod 8e3854b496 Update dependencies 2017-02-24 19:37:23 +08:00
Max Lv ad42167b2e Update shadowsocks-libev 2017-02-24 19:37:23 +08:00
Max Lv 3bf0963c5a Trim remoteDns 2017-02-24 19:37:23 +08:00
Max Lv c3315d35ed Fix #1130 2017-02-24 19:37:23 +08:00
Max Lv 103dc10a0a Update shadowsocks-libev 2017-02-24 19:37:23 +08:00
Max Lv 36c94b8d83 Fix a memory leak 2017-02-24 19:37:22 +08:00
Mygod df72b29302 Fix malformed URL in about.html 2017-02-23 15:17:57 +08:00
28 changed files with 198 additions and 7582 deletions
-1
View File
@@ -9,4 +9,3 @@ local.sbt
mobile/src/main/libs mobile/src/main/libs
mobile/src/main/obj mobile/src/main/obj
mobile/src/main/jni/overture
+4 -3
View File
@@ -17,6 +17,10 @@
path = mobile/src/main/jni/redsocks path = mobile/src/main/jni/redsocks
url = https://github.com/shadowsocks/redsocks.git url = https://github.com/shadowsocks/redsocks.git
branch = shadowsocks-android branch = shadowsocks-android
[submodule "mobile/src/main/jni/pdnsd"]
path = mobile/src/main/jni/pdnsd
url = https://github.com/shadowsocks/pdnsd.git
branch = shadowsocks-android
[submodule "mobile/src/main/jni/mbedtls"] [submodule "mobile/src/main/jni/mbedtls"]
path = mobile/src/main/jni/mbedtls path = mobile/src/main/jni/mbedtls
url = https://github.com/ARMmbed/mbedtls url = https://github.com/ARMmbed/mbedtls
@@ -33,6 +37,3 @@
[submodule "mobile/src/main/jni/libudns"] [submodule "mobile/src/main/jni/libudns"]
path = mobile/src/main/jni/libudns path = mobile/src/main/jni/libudns
url = https://github.com/shadowsocks/libudns.git url = https://github.com/shadowsocks/libudns.git
[submodule "mobile/src/overture"]
path = mobile/src/overture
url = https://github.com/shadowsocks/overture-android.git
+2 -3
View File
@@ -5,9 +5,8 @@ jdk:
env: env:
global: global:
- NDK_VERSION=r14 - NDK_VERSION=r12b
- NDK_CCACHE=ccache - NDK_CCACHE=ccache
- GOROOT_BOOTSTRAP=$GOROOT
- ANDROID_NDK_HOME=$HOME/.android/android-ndk-${NDK_VERSION} - ANDROID_NDK_HOME=$HOME/.android/android-ndk-${NDK_VERSION}
- SBTPATH=$HOME/.sbt - SBTPATH=$HOME/.sbt
- PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH} - PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}
@@ -50,4 +49,4 @@ install:
fi fi
script: script:
- $SBTPATH/sbt go-build android:package - $SBTPATH/sbt android:package
+4 -6
View File
@@ -12,17 +12,15 @@ A [shadowsocks](http://shadowsocks.org) client for Android, written in Scala.
* JDK 1.8 * JDK 1.8
* SBT 0.13.0+ * SBT 0.13.0+
* Go 1.4+
* Android SDK * Android SDK
- Build Tools 25+ - Build Tools 25+
- Android Support Repository and Google Repository (see `build.sbt` for version) - Android Support Repository and Google Repository (see `build.sbt` for version)
* Android NDK r14+ * Android NDK r12b+
### BUILD ### BUILD
* Set environment variable `ANDROID_HOME` to `/path/to/android-sdk` * Set environment variable `ANDROID_HOME` to `/path/to/android-sdk`
* (optional) Set environment variable `ANDROID_NDK_HOME` to `/path/to/android-ndk` (default: `$ANDROID_HOME/ndk-bundle`) * Set environment variable `ANDROID_NDK_HOME` to `/path/to/android-ndk`
* Set environment variable `GOROOT_BOOTSTRAP` to `/path/to/go`
* Create your key following the instructions at https://developer.android.com/studio/publish/app-signing.html * Create your key following the instructions at https://developer.android.com/studio/publish/app-signing.html
* Create `mobile/local.properties` from `mobile/local.properties.example` with your own key information * Create `mobile/local.properties` from `mobile/local.properties.example` with your own key information
* Invoke the building like this * Invoke the building like this
@@ -31,7 +29,7 @@ A [shadowsocks](http://shadowsocks.org) client for Android, written in Scala.
git submodule update --init --recursive git submodule update --init --recursive
# Build the App # Build the App
sbt clean go-build android:package-release sbt clean android:package-release
``` ```
### TRANSLATE ### TRANSLATE
@@ -52,7 +50,7 @@ Translators can go to [POEditor](https://poeditor.com/join/project/u5VHO9vhSf) t
<li>pcre: <a href="https://android.googlesource.com/platform/external/pcre/+/master/dist2/LICENCE">BSD</a></li> <li>pcre: <a href="https://android.googlesource.com/platform/external/pcre/+/master/dist2/LICENCE">BSD</a></li>
<li>libancillary: <a href="https://github.com/shadowsocks/libancillary/blob/shadowsocks-android/COPYING">BSD</a></li> <li>libancillary: <a href="https://github.com/shadowsocks/libancillary/blob/shadowsocks-android/COPYING">BSD</a></li>
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li> <li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
<li>overture: <a href="https://github.com/shawn1m/overture/blob/master/LICENSE">MIT</a></li> <li>pdnsd: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/pdnsd/COPYING">GPLv3</a></li>
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li> <li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li>
<li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li> <li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li>
<li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li> <li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li>
+1 -1
View File
@@ -18,7 +18,7 @@ lazy val commonSettings = Seq(
typedResources := false typedResources := false
) )
val supportLibsVersion = "25.2.0" val supportLibsVersion = "25.1.1"
lazy val root = Project(id = "shadowsocks-android", base = file(".")) lazy val root = Project(id = "shadowsocks-android", base = file("."))
.settings(commonSettings) .settings(commonSettings)
.aggregate(plugin, mobile) .aggregate(plugin, mobile)
+4 -12
View File
@@ -2,8 +2,8 @@ enablePlugins(AndroidApp)
android.useSupportVectors android.useSupportVectors
name := "shadowsocks" name := "shadowsocks"
version := "4.1.2" version := "4.0.4"
versionCode := Some(182) versionCode := Some(179)
proguardOptions ++= proguardOptions ++=
"-keep class com.github.shadowsocks.JniHelper { *; }" :: "-keep class com.github.shadowsocks.JniHelper { *; }" ::
@@ -19,7 +19,7 @@ val playServicesVersion = "10.2.0"
resolvers += Resolver.jcenterRepo resolvers += Resolver.jcenterRepo
libraryDependencies ++= libraryDependencies ++=
"com.futuremind.recyclerfastscroll" % "fastscroll" % "0.2.5" :: "com.futuremind.recyclerfastscroll" % "fastscroll" % "0.2.5" ::
"com.evernote" % "android-job" % "1.1.7" :: "com.evernote" % "android-job" % "1.1.6" ::
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01" :: "com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01" ::
"com.google.android.gms" % "play-services-ads" % playServicesVersion :: "com.google.android.gms" % "play-services-ads" % playServicesVersion ::
"com.google.android.gms" % "play-services-analytics" % playServicesVersion :: "com.google.android.gms" % "play-services-analytics" % playServicesVersion ::
@@ -28,7 +28,7 @@ libraryDependencies ++=
"com.mikepenz" % "crossfader" % "1.5.0" :: "com.mikepenz" % "crossfader" % "1.5.0" ::
"com.mikepenz" % "fastadapter" % "2.1.7" :: "com.mikepenz" % "fastadapter" % "2.1.7" ::
"com.mikepenz" % "iconics-core" % "2.8.2" :: "com.mikepenz" % "iconics-core" % "2.8.2" ::
"com.mikepenz" % "materialdrawer" % "5.8.2" :: "com.mikepenz" % "materialdrawer" % "5.8.1" ::
"com.mikepenz" % "materialize" % "1.0.1" :: "com.mikepenz" % "materialize" % "1.0.1" ::
"com.squareup.okhttp3" % "okhttp" % "3.6.0" :: "com.squareup.okhttp3" % "okhttp" % "3.6.0" ::
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" :: "com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2" ::
@@ -36,11 +36,3 @@ libraryDependencies ++=
"eu.chainfire" % "libsuperuser" % "1.0.0.201608240809" :: "eu.chainfire" % "libsuperuser" % "1.0.0.201608240809" ::
"net.glxn.qrgen" % "android" % "2.0" :: "net.glxn.qrgen" % "android" % "2.0" ::
Nil Nil
lazy val goBuild = TaskKey[Unit]("go-build", "Build go and kcptun")
goBuild := {
Process(Seq("mobile/src/overture/make.bash", minSdkVersion.value)) ! streams.value.log match {
case 0 => // Success!
case n => sys.error(s"Native build script exit code: $n")
}
}
-2
View File
@@ -144,8 +144,6 @@
android:process=":bg"/> android:process=":bg"/>
<service android:name="com.evernote.android.job.gcm.PlatformGcmService" <service android:name="com.evernote.android.job.gcm.PlatformGcmService"
android:process=":bg"/> android:process=":bg"/>
<service android:name="com.evernote.android.job.JobRescheduleService"
android:process=":bg"/>
<receiver android:name="com.evernote.android.job.v14.PlatformAlarmReceiver" <receiver android:name="com.evernote.android.job.v14.PlatformAlarmReceiver"
android:process=":bg"/> android:process=":bg"/>
<receiver android:name="com.evernote.android.job.JobBootReceiver" <receiver android:name="com.evernote.android.job.JobBootReceiver"
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-1
View File
@@ -1 +0,0 @@
127.0.0.1 localhost
+2 -2
View File
@@ -275,7 +275,7 @@ img {
<body> <body>
<p>A <a href="http://shadowsocks.org">Shadowsocks</a> client for Android, written in Scala.</p> <p>A <a href="http://shadowsocks.org">Shadowsocks</a> client for Android, written in Scala.</p>
<p>Copyright (C) 2017 by Max Lv <a href="&#x6d;&#97;&#x69;&#108;&#116;&#111;&#x3a;&#x6d;&#97;x&#46;&#99;.&#108;&#118;&#x40;&#103;&#109;&#97;&#x69;&#108;&#46;&#x63;&#x6f;&#109;">&#x6d;&#97;&#x78;.&#x63;&#x2e;&#108;v&#64;&#x67;&#109;&#x61;&#x69;&#108;&#x2e;&#99;&#111;&#109;</a></p> <p>Copyright (C) 2017 by Max Lv <a href="&#x6d;&#97;&#x69;&#108;&#116;&#111;&#x3a;&#x6d;&#97;x&#46;&#99;.&#108;&#118;&#x40;&#103;&#109;&#97;&#x69;&#108;&#46;&#x63;&#x6f;&#109;">&#x6d;&#97;&#x78;.&#x63;&#x2e;&#108;v&#64;&#x67;&#109;&#x61;&#x69;&#108;&#x2e;&#99;&#111;&#109;</a></p>
<p>Copyright (C) 2017 by Mygod Studio <a href="contact-shadowsocks-android@mygod.be">contact-shadowsocks-android@mygod.be</a></p> <p>Copyright (C) 2017 by Mygod Studio <a href="mailto:contact-shadowsocks-android@mygod.be">contact-shadowsocks-android@mygod.be</a></p>
<p>This program is free software: you can redistribute it and/or modify <p>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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
@@ -296,7 +296,7 @@ along with this program. If not, see <a href="http://www.gnu.org/licenses/">http
<li>pcre: <a href="https://android.googlesource.com/platform/external/pcre/+/master/dist2/LICENCE">BSD</a></li> <li>pcre: <a href="https://android.googlesource.com/platform/external/pcre/+/master/dist2/LICENCE">BSD</a></li>
<li>libancillary: <a href="https://github.com/shadowsocks/libancillary/blob/shadowsocks-android/COPYING">BSD</a></li> <li>libancillary: <a href="https://github.com/shadowsocks/libancillary/blob/shadowsocks-android/COPYING">BSD</a></li>
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li> <li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
<li>overture: <a href="https://github.com/shawn1m/overture/blob/master/LICENSE">MIT</a></li> <li>pdnsd: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/pdnsd/COPYING">GPLv3</a></li>
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li> <li>libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/libev/LICENSE">GPLv2</a></li>
<li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li> <li>libsodium: <a href="https://github.com/jedisct1/libsodium/blob/master/LICENSE">ISC</a></li>
<li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li> <li>libudns: <a href="https://github.com/shadowsocks/libudns/blob/master/COPYING.LGPL">LGPL</a></li>
@@ -54,19 +54,7 @@ public class JniHelper {
? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno); ? new ErrnoException("kill", errno) : new Exception("kill failed: " + errno);
} }
@Deprecated // only implemented for before API 24
public static boolean waitForCompat(Process process, long millis) throws Exception {
if (Build.VERSION.SDK_INT >= 24) throw new UnsupportedOperationException("Never call this method in OpenJDK!");
final Object mutex = getExitValueMutex(process);
synchronized (mutex) {
if (getExitValue(process) == null) mutex.wait(millis);
return getExitValue(process) != null;
}
}
private static native int sigterm(Process process); private static native int sigterm(Process process);
private static native Integer getExitValue(Process process);
private static native Object getExitValueMutex(Process process);
public static native int sendFd(int fd, String path); public static native int sendFd(int fd, String path);
public static native void close(int fd); public static native void close(int fd);
} }
+18 -12
View File
@@ -97,7 +97,7 @@ LIBEVENT_SOURCES := \
LOCAL_MODULE := event LOCAL_MODULE := event
LOCAL_SRC_FILES := $(addprefix libevent/, $(LIBEVENT_SOURCES)) LOCAL_SRC_FILES := $(addprefix libevent/, $(LIBEVENT_SOURCES))
LOCAL_CFLAGS := -O2 -D_EVENT_HAVE_ARC4RANDOM -I$(LOCAL_PATH)/libevent \ LOCAL_CFLAGS := -O2 -I$(LOCAL_PATH)/libevent \
-I$(LOCAL_PATH)/libevent/include \ -I$(LOCAL_PATH)/libevent/include \
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
@@ -239,6 +239,23 @@ LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \
include $(BUILD_SHARED_EXECUTABLE) include $(BUILD_SHARED_EXECUTABLE)
########################################################
## pdnsd
########################################################
include $(CLEAR_VARS)
PDNSD_SOURCES := $(wildcard $(LOCAL_PATH)/pdnsd/src/*.c)
LOCAL_MODULE := pdnsd
LOCAL_SRC_FILES := $(PDNSD_SOURCES:$(LOCAL_PATH)/%=%)
LOCAL_CFLAGS := -DANDROID -Wall -O2 -I$(LOCAL_PATH)/pdnsd \
-I$(LOCAL_PATH)/include/pdnsd -I$(LOCAL_PATH)/libancillary
LOCAL_STATIC_LIBRARIES := libancillary
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_EXECUTABLE)
######################################################## ########################################################
## shadowsocks-libev local ## shadowsocks-libev local
######################################################## ########################################################
@@ -477,17 +494,6 @@ LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files))
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
########################################################
## overture
########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := overture
LOCAL_SRC_FILES := overture/$(TARGET_ARCH_ABI)/liboverture.so
include $(PREBUILT_SHARED_LIBRARY)
# Import cpufeatures # Import cpufeatures
$(call import-module,android/cpufeatures) $(call import-module,android/cpufeatures)
+1 -1
View File
@@ -1,4 +1,4 @@
APP_ABI := armeabi-v7a arm64-v8a x86 APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-19 APP_PLATFORM := android-19
APP_STL := stlport_static APP_STL := stlport_static
NDK_TOOLCHAIN_VERSION := clang NDK_TOOLCHAIN_VERSION := clang
+4 -32
View File
@@ -22,7 +22,7 @@
#define THROW(env, clazz, msg) do { env->ThrowNew(env->FindClass(clazz), msg); } while (0) #define THROW(env, clazz, msg) do { env->ThrowNew(env->FindClass(clazz), msg); } while (0)
static jclass ProcessImpl; static jclass ProcessImpl;
static jfieldID ProcessImpl_pid, ProcessImpl_exitValue, ProcessImpl_exitValueMutex; static jfieldID ProcessImpl_pid;
static int sdk_version() { static int sdk_version() {
char version[PROP_VALUE_MAX + 1]; char version[PROP_VALUE_MAX + 1];
@@ -41,24 +41,6 @@ jint Java_com_github_shadowsocks_jnihelper_sigterm(JNIEnv *env, jobject thiz, jo
return kill(pid, SIGTERM) == -1 && errno != ESRCH ? errno : 0; return kill(pid, SIGTERM) == -1 && errno != ESRCH ? errno : 0;
} }
jobject Java_com_github_shadowsocks_jnihelper_getExitValue(JNIEnv *env, jobject thiz, jobject process) {
if (!env->IsInstanceOf(process, ProcessImpl)) {
THROW(env, "java/lang/ClassCastException",
"Unsupported process object. Only java.lang.ProcessManager$ProcessImpl is accepted.");
return NULL;
}
return env->GetObjectField(process, ProcessImpl_exitValue);
}
jobject Java_com_github_shadowsocks_jnihelper_getExitValueMutex(JNIEnv *env, jobject thiz, jobject process) {
if (!env->IsInstanceOf(process, ProcessImpl)) {
THROW(env, "java/lang/ClassCastException",
"Unsupported process object. Only java.lang.ProcessManager$ProcessImpl is accepted.");
return NULL;
}
return env->GetObjectField(process, ProcessImpl_exitValueMutex);
}
void Java_com_github_shadowsocks_jnihelper_close(JNIEnv *env, jobject thiz, jint fd) { void Java_com_github_shadowsocks_jnihelper_close(JNIEnv *env, jobject thiz, jint fd) {
close(fd); close(fd);
} }
@@ -102,13 +84,11 @@ static JNINativeMethod method_table[] = {
{ "sendFd", "(ILjava/lang/String;)I", { "sendFd", "(ILjava/lang/String;)I",
(void*) Java_com_github_shadowsocks_jnihelper_sendfd }, (void*) Java_com_github_shadowsocks_jnihelper_sendfd },
{ "sigterm", "(Ljava/lang/Process;)I", { "sigterm", "(Ljava/lang/Process;)I",
(void*) Java_com_github_shadowsocks_jnihelper_sigterm }, (void*) Java_com_github_shadowsocks_jnihelper_sigterm }
{ "getExitValue", "(Ljava/lang/Process;)Ljava/lang/Integer;",
(void*) Java_com_github_shadowsocks_jnihelper_getExitValue },
{ "getExitValueMutex", "(Ljava/lang/Process;)Ljava/lang/Object;",
(void*) Java_com_github_shadowsocks_jnihelper_getExitValueMutex }
}; };
/* /*
* Register several native methods for one class. * Register several native methods for one class.
*/ */
@@ -181,14 +161,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.pid not found"); THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.pid not found");
goto bail; goto bail;
} }
if (!(ProcessImpl_exitValue = env->GetFieldID(ProcessImpl, "exitValue", "Ljava/lang/Integer;"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.exitValue not found");
goto bail;
}
if (!(ProcessImpl_exitValueMutex = env->GetFieldID(ProcessImpl, "exitValueMutex", "Ljava/lang/Object;"))) {
THROW(env, "java/lang/RuntimeException", "ProcessManager$ProcessImpl.exitValueMutex not found");
goto bail;
}
} }
result = JNI_VERSION_1_6; result = JNI_VERSION_1_6;
@@ -39,11 +39,11 @@ import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.plugin.{PluginConfiguration, PluginManager, PluginOptions} import com.github.shadowsocks.plugin.{PluginConfiguration, PluginManager, PluginOptions}
import com.github.shadowsocks.utils._ import com.github.shadowsocks.utils._
import okhttp3.{Dns, FormBody, OkHttpClient, Request} import okhttp3.{Dns, FormBody, OkHttpClient, Request}
import org.json.{JSONArray, JSONObject} import org.json.JSONObject
import scala.collection.JavaConversions._
import scala.collection.mutable import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
import scala.collection.JavaConversions._
import scala.util.Random import scala.util.Random
trait BaseService extends Service { trait BaseService extends Service {
@@ -328,44 +328,4 @@ trait BaseService extends Service {
IOUtils.writeString(new File(getFilesDir, file), config.toString) IOUtils.writeString(new File(getFilesDir, file), config.toString)
file file
} }
protected final def buildOvertureConfig(file: String): String = {
val config = new JSONObject()
.put("BindAddress", ":" + (profile.localPort + 53))
.put("RedirectIPv6Record", true)
.put("DomainBase64Decode", true)
.put("HostsFile", "hosts")
.put("MinimumTTL", 3600)
.put("CacheSize", 4096)
def makeDns(name: String, address: String, edns: Boolean = true) = {
val dns = new JSONObject()
.put("Name", name)
.put("Address", address + ":53")
.put("Timeout", 6)
.put("EDNSClientSubnet", new JSONObject().put("Policy", "disable"))
if (edns) dns
.put("Protocol", "tcp")
.put("Socks5Address", "127.0.0.1:" + profile.localPort)
else dns.put("Protocol", "udp")
dns
}
profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES => config
.put("PrimaryDNS", new JSONArray(Array(
makeDns("Primary-1", "119.29.29.29", edns = false),
makeDns("Primary-2", "114.114.114.114", edns = false)
)))
.put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", profile.remoteDns)))
.put("IPNetworkFile", "china_ip_list.txt")
.put("DomainFile", "gfwlist.txt")
case Acl.CHINALIST => config
.put("PrimaryDNS", new JSONArray().put(makeDns("Primary", "119.29.29.29")))
.put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", profile.remoteDns)))
case _ => config
.put("PrimaryDNS", new JSONArray().put(makeDns("Primary", profile.remoteDns)))
.put("AlternativeDNS", new JSONArray().put(makeDns("Alternative", "208.67.222.222")))
}
IOUtils.writeString(new File(getFilesDir, file), config.toString)
file
}
} }
@@ -115,7 +115,7 @@ class GuardedProcess(cmd: String*) {
private def destroyProcess() { private def destroyProcess() {
if (Build.VERSION.SDK_INT < 24) { if (Build.VERSION.SDK_INT < 24) {
JniHelper.sigtermCompat(process) JniHelper.sigtermCompat(process)
JniHelper.waitForCompat(process, 500) process.waitFor()
} }
process.destroy() process.destroy()
} }
@@ -197,17 +197,15 @@ class ShadowsocksApplication extends Application {
def copyAssets() { def copyAssets() {
val assetManager = getAssets val assetManager = getAssets
for (dir <- List("acl", "overture")) { var files: Array[String] = null
var files: Array[String] = null try files = assetManager.list("acl") catch {
try files = assetManager.list(dir) catch { case e: IOException =>
case e: IOException => Log.e(TAG, e.getMessage)
Log.e(TAG, e.getMessage) app.track(e)
app.track(e)
}
if (files != null) for (file <- files) autoClose(assetManager.open(dir + "/" + file))(in =>
autoClose(new FileOutputStream(new File(getFilesDir, file)))(out =>
IOUtils.copy(in, out)))
} }
if (files != null) for (file <- files) autoClose(assetManager.open("acl/" + file))(in =>
autoClose(new FileOutputStream(new File(getFilesDir, file)))(out =>
IOUtils.copy(in, out)))
editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply() editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply()
} }
@@ -49,7 +49,7 @@ class ShadowsocksNatService extends BaseService {
var sslocalProcess: GuardedProcess = _ var sslocalProcess: GuardedProcess = _
var sstunnelProcess: GuardedProcess = _ var sstunnelProcess: GuardedProcess = _
var redsocksProcess: GuardedProcess = _ var redsocksProcess: GuardedProcess = _
var overtureProcess: GuardedProcess = _ var pdnsdProcess: GuardedProcess = _
var su: Shell.Interactive = _ var su: Shell.Interactive = _
def startShadowsocksDaemon() { def startShadowsocksDaemon() {
@@ -83,8 +83,21 @@ class ShadowsocksNatService extends BaseService {
} }
def startDnsDaemon() { def startDnsDaemon() {
overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0"
"-c", buildOvertureConfig("overture-nat.conf")) IOUtils.writeString(new File(getFilesDir, "pdnsd-nat.conf"), profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath,
"127.0.0.1", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8",
getBlackList, reject, profile.localPort + 63, reject)
case Acl.CHINALIST =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath,
"127.0.0.1", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222",
"", reject, profile.localPort + 63, reject)
case _ =>
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath,
"127.0.0.1", profile.localPort + 53, profile.localPort + 63, reject)
})
pdnsdProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", "pdnsd-nat.conf")
.start() .start()
} }
@@ -98,13 +111,11 @@ class ShadowsocksNatService extends BaseService {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
def handleConnection() { def handleConnection() {
startDNSTunnel()
startRedsocksDaemon() startRedsocksDaemon()
startShadowsocksDaemon() startShadowsocksDaemon()
if (!profile.udpdns) if (!profile.udpdns) startDnsDaemon()
startDnsDaemon()
else
startDNSTunnel()
setupIptables() setupIptables()
@@ -132,9 +143,9 @@ class ShadowsocksNatService extends BaseService {
redsocksProcess.destroy() redsocksProcess.destroy()
redsocksProcess = null redsocksProcess = null
} }
if (overtureProcess != null) { if (pdnsdProcess != null) {
overtureProcess.destroy() pdnsdProcess.destroy()
overtureProcess = null pdnsdProcess = null
} }
su.addCommand("iptables -t nat -F OUTPUT") su.addCommand("iptables -t nat -F OUTPUT")
@@ -45,7 +45,8 @@ class ShadowsocksVpnService extends VpnService with BaseService {
private var notification: ShadowsocksNotification = _ private var notification: ShadowsocksNotification = _
var sslocalProcess: GuardedProcess = _ var sslocalProcess: GuardedProcess = _
var overtureProcess: GuardedProcess = _ var sstunnelProcess: GuardedProcess = _
var pdnsdProcess: GuardedProcess = _
var tun2socksProcess: GuardedProcess = _ var tun2socksProcess: GuardedProcess = _
override def onBind(intent: Intent): IBinder = { override def onBind(intent: Intent): IBinder = {
@@ -93,13 +94,17 @@ class ShadowsocksVpnService extends VpnService with BaseService {
sslocalProcess.destroy() sslocalProcess.destroy()
sslocalProcess = null sslocalProcess = null
} }
if (sstunnelProcess != null) {
sstunnelProcess.destroy()
sstunnelProcess = null
}
if (tun2socksProcess != null) { if (tun2socksProcess != null) {
tun2socksProcess.destroy() tun2socksProcess.destroy()
tun2socksProcess = null tun2socksProcess = null
} }
if (overtureProcess != null) { if (pdnsdProcess != null) {
overtureProcess.destroy() pdnsdProcess.destroy()
overtureProcess = null pdnsdProcess = null
} }
} }
@@ -144,14 +149,15 @@ class ShadowsocksVpnService extends VpnService with BaseService {
/** Called when the activity is first created. */ /** Called when the activity is first created. */
def handleConnection() { def handleConnection() {
val fd = startVpn()
if (!sendFd(fd)) throw new Exception("sendFd failed")
startShadowsocksDaemon() startShadowsocksDaemon()
if (!profile.udpdns) { if (!profile.udpdns) {
startDnsDaemon() startDnsDaemon()
startDnsTunnel()
} }
val fd = startVpn()
if (!sendFd(fd)) throw new Exception("sendFd failed")
} }
override protected def buildPluginCommandLine(): ArrayBuffer[String] = super.buildPluginCommandLine() += "-V" override protected def buildPluginCommandLine(): ArrayBuffer[String] = super.buildPluginCommandLine() += "-V"
@@ -176,10 +182,33 @@ class ShadowsocksVpnService extends VpnService with BaseService {
sslocalProcess = new GuardedProcess(cmd: _*).start() sslocalProcess = new GuardedProcess(cmd: _*).start()
} }
def startDnsTunnel(): Unit =
sstunnelProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so",
"-V",
"-t", "10",
"-b", "127.0.0.1",
"-l", (profile.localPort + 63).toString,
"-L" , profile.remoteDns.trim + ":53",
"-c", buildShadowsocksConfig("ss-tunnel-vpn.conf")).start()
def startDnsDaemon() { def startDnsDaemon() {
overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0"
"-c", buildOvertureConfig("overture-vpn.conf"), "-V") IOUtils.writeString(new File(getFilesDir, "pdnsd-vpn.conf"), profile.route match {
.start() case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath,
"0.0.0.0", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8",
getBlackList, reject, profile.localPort + 63, reject)
case Acl.CHINALIST =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath,
"0.0.0.0", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222",
"", reject, profile.localPort + 63, reject)
case _ =>
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath,
"0.0.0.0", profile.localPort + 53, profile.localPort + 63, reject)
})
val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", "pdnsd-vpn.conf")
pdnsdProcess = new GuardedProcess(cmd: _*).start()
} }
def startVpn(): Int = { def startVpn(): Int = {
@@ -45,6 +45,86 @@ object ConfigUtils {
" port = %d;\n" + " port = %d;\n" +
" type = socks5;\n" + " type = socks5;\n" +
"}\n" "}\n"
val PDNSD_LOCAL =
"""
|global {
| perm_cache = 2048;
| %s
| cache_dir = "%s";
| server_ip = %s;
| server_port = %d;
| query_method = tcp_only;
| min_ttl = 15m;
| max_ttl = 1w;
| timeout = 10;
| daemon = off;
|}
|
|server {
| label = "local";
| ip = 127.0.0.1;
| port = %d;
| reject = %s;
| reject_policy = negate;
| reject_recursively = on;
|}
|
|rr {
| name=localhost;
| reverse=on;
| a=127.0.0.1;
| owner=localhost;
| soa=localhost,root.localhost,42,86400,900,86400,86400;
|}
""".stripMargin
val PDNSD_DIRECT =
"""
|global {
| perm_cache = 2048;
| %s
| cache_dir = "%s";
| server_ip = %s;
| server_port = %d;
| query_method = udp_only;
| min_ttl = 15m;
| max_ttl = 1w;
| timeout = 10;
| daemon = off;
| par_queries = 4;
|}
|
|server {
| label = "remote-servers";
| ip = %s;
| timeout = 3;
| query_method = udp_only;
| %s
| policy = included;
| reject = %s;
| reject_policy = fail;
| reject_recursively = on;
|}
|
|server {
| label = "local-server";
| ip = 127.0.0.1;
| query_method = tcp_only;
| port = %d;
| reject = %s;
| reject_policy = negate;
| reject_recursively = on;
|}
|
|rr {
| name=localhost;
| reverse=on;
| a=127.0.0.1;
| owner=localhost;
| soa=localhost,root.localhost,42,86400,900,86400,86400;
|}
""".stripMargin
} }
object Key { object Key {
@@ -28,14 +28,14 @@ object Parser {
val TAG = "ShadowParser" val TAG = "ShadowParser"
private val pattern = "(?i)ss://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]".r private val pattern = "(?i)ss://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]".r
private val userInfoPattern = "^(.+?):(.*)$".r private val userInfoPattern = "^(.+?):(.*)$".r
private val legacyPattern = "^(.+?):(.*)@(.+?):(\\d+?)$".r private val legacyPattern = "^((.+?):(.*)@(.+?):(\\d+?))$".r
def findAll(data: CharSequence): Iterator[Profile] = def findAll(data: CharSequence): Iterator[Profile] =
pattern.findAllMatchIn(if (data == null) "" else data).map(m => { pattern.findAllMatchIn(if (data == null) "" else data).map(m => {
val uri = Uri.parse(m.matched) val uri = Uri.parse(m.matched)
uri.getUserInfo match { uri.getUserInfo match {
case null => val str = new String(Base64.decode(uri.getHost, Base64.NO_PADDING), "UTF-8"); str match { case null => new String(Base64.decode(uri.getHost, Base64.NO_PADDING), "UTF-8") match {
case legacyPattern(method, password, host, port) => // legacy uri case legacyPattern(_, method, password, host, port) => // legacy uri
val profile = new Profile val profile = new Profile
profile.method = method.toLowerCase profile.method = method.toLowerCase
profile.password = password profile.password = password
-2
View File
@@ -1,5 +1,3 @@
* 0.0.3:
* Update support library version to 25.2.0.
* 0.0.2: * 0.0.2:
* Add `getOrDefault` to `PluginOptions`; * Add `getOrDefault` to `PluginOptions`;
* Update support library version to 25.1.1. * Update support library version to 25.1.1.
+1 -1
View File
@@ -2,7 +2,7 @@ enablePlugins(AndroidLib)
android.useSupportVectors android.useSupportVectors
name := "plugin" name := "plugin"
version := "0.0.3" version := "0.0.2"
pomExtra in Global := { pomExtra in Global := {
<url>https://github.com/shadowsocks/shadowsocks-android</url> <url>https://github.com/shadowsocks/shadowsocks-android</url>
+1 -1
View File
@@ -1,4 +1,4 @@
addSbtPlugin("org.scala-android" % "sbt-android" % "1.7.6") addSbtPlugin("org.scala-android" % "sbt-android" % "1.7.5")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.10") addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.10")