Compare commits

...
99 Commits
Author SHA1 Message Date
Max Lv 772bc18eb8 Bump version 2016-09-12 10:28:25 +08:00
Max Lv d503818169 Add missing translation 2016-09-12 10:27:55 +08:00
Max Lv b209e73386 Bump version 2016-09-12 10:11:16 +08:00
Max Lv 6c381b0ecc Fix a crash reported by Goolge Play 2016-09-12 09:49:17 +08:00
Max Lv e3f0fa6756 Fix #871 2016-09-09 22:13:51 +08:00
Max Lv 35cb273592 SuppressLint 2016-09-09 16:47:47 +08:00
Max Lv b76f410c34 Refine header parser 2016-09-09 10:30:22 +08:00
Max Lv d3678531b7 Bump version 2016-09-08 19:23:50 +08:00
Max Lv 122ca599de Add GFWList support 2016-09-08 18:36:39 +08:00
Max Lv 96fcec788c Add issue template 2016-09-05 16:24:51 +08:00
Max Lv 1c67b39a3e Bump version 2016-09-04 10:31:33 +08:00
Max Lv 30fea4a705 Merge branch 'master' of github.com:shadowsocks/shadowsocks-android 2016-09-04 10:19:15 +08:00
Max Lv 7c0763c78a Fix #848 2016-09-01 14:00:23 +08:00
Mygod b8c593b110 Fix crash in GuardedProcess 2016-08-29 13:57:25 +08:00
Mygod 782af959a0 Fix #844 2016-08-29 12:54:55 +08:00
Max Lv 6df227d231 Update kcptun 2016-08-28 18:11:29 +08:00
Max Lv 5b1432e4e8 Handle stdout/stderr of GuardedProcess properly 2016-08-28 17:42:19 +08:00
Max Lv 7ca4e4ec74 Enable android log for kcptun 2016-08-28 08:00:35 +08:00
Mygod 655ef1eed6 Refine TFO 2016-08-27 23:39:06 +08:00
Mygod 04be60577a Revert "Revert "Fix #839 #838""
This reverts commit 264b177b38.
2016-08-27 23:32:13 +08:00
Mygod 63d2ec7b02 Revert "Fix #838 #839"
This reverts commit 32f4d6af47.

Never mind then! I changed my mind.
2016-08-27 23:31:50 +08:00
Mygod 06b6afd557 Update sbt-android 2016-08-27 23:23:58 +08:00
Mygod 32f4d6af47 Fix #838 #839 2016-08-27 23:23:08 +08:00
Mygod 264b177b38 Revert "Fix #839 #838"
This reverts commit 069cc152ca.
2016-08-27 23:15:25 +08:00
Syrone Wong 67a1c5460a Drop redundant rule (#840)
[info] Android NDK: WARNING:jni/Android.mk:mbedtls: LOCAL_LDLIBS is always ignored for static libraries
2016-08-27 20:42:16 +08:00
Max Lv a20b7821f2 Bump version 2016-08-27 17:11:05 +08:00
Max Lv 069cc152ca Fix #839 #838 2016-08-27 17:10:12 +08:00
Max Lv 7b57be669c Bump version 2016-08-27 07:56:10 +08:00
Max Lv 2f051e9eed Update kcptun 2016-08-23 13:52:48 +08:00
Mygod 8d1d018fe1 Remove boot script to disable fast open
Fix #828.
2016-08-23 13:48:05 +08:00
Mygod 3c5bc27750 Refine mount command
Fix #826.
2016-08-22 21:10:41 +08:00
Mygod 6c047eca8e Add error message if failed 2016-08-22 21:10:33 +08:00
Max Lv a31e753841 Update golang 2016-08-21 11:14:09 +08:00
Max Lv c94c509931 KCP with session ID (#823)
* Add sid support

* Update kcptun
2016-08-20 14:09:22 +08:00
Mygod 41417a7546 Refine regex in KcpCliPreference 2016-08-19 19:52:34 +08:00
Mygod 25cfb1623a Remove all the extravagant styles
These styles are either introduced by @AnyOfYou, or exist because of a bug in Android support library. Anyway they can be removed now.
2016-08-19 19:49:43 +08:00
Max Lv c9ce515cca Bump version 2016-08-19 17:57:53 +08:00
Mygod 7802a50603 Fix Travis dependency problem once and for all 2016-08-19 15:53:59 +08:00
Mygod 680a6594f6 Drop compatibility RTL support for Jelly Bean 2016-08-19 15:39:03 +08:00
Mygod b7367835b0 Update support lib 2016-08-19 15:32:02 +08:00
Mygod 25bd5347eb Refine #816 and error handling in startRunner 2016-08-19 15:23:43 +08:00
Max Lv d2a527ed0e Fix #816 2016-08-18 17:49:48 +08:00
Mygod 07ab938719 Prevent createProfile returns null 2016-08-17 12:52:21 +08:00
Mygod b6bfd5bfa0 Fix navigations in ProfileManagerActivity 2016-08-17 12:37:32 +08:00
Mygod f9194df55d Fix accessibility issue for stat and fab 2016-08-17 12:32:27 +08:00
Mygod 958d387b8c Fix su detection 2016-08-17 12:29:17 +08:00
Mygod eee89774df Refine kcpcli help again 2016-08-17 11:50:40 +08:00
Mygod 8454975a13 Fix NAT notifications on Android 4.4 2016-08-17 11:44:22 +08:00
Max Lv 69cb86a7c5 Format the help output of kcptun 2016-08-17 09:09:30 +08:00
Max Lv 45ea903323 Enable fast-open only with ss-local 2016-08-17 08:30:22 +08:00
Mygod f7303e1564 Revert "Promote default settings to kcptun"
This reverts commit 99ff47bd5f.

See discussion at: https://github.com/shadowsocks/kcptun/pull/1
2016-08-16 22:36:18 +08:00
Mygod 99ff47bd5f Promote default settings to kcptun 2016-08-16 22:16:25 +08:00
Mygod 820d71fb07 Add help for kcpcli (#811)
* Add help for kcpcli

* Filter useless parameters
2016-08-16 22:07:01 +08:00
Mygod a9a6e1c1a6 Track caught exceptions (#810) 2016-08-16 21:26:10 +08:00
Mygod 364d873eba Update to AutoCloseable in Java 1.7 2016-08-16 20:51:47 +08:00
Mygod a722257aba Set tcp_fastopen with echo instead of sysctl 2016-08-16 14:48:30 +08:00
Mygod 80d93a84bd Add support for TCP Fast Open (#809)
* Add support for TCP Fast Open

* Remove useless echo done line

* Check return values before proceeding in TcpFastOpen.enabled
2016-08-16 14:37:21 +08:00
Mygod 9b07239ced Refine default kcpcli 2016-08-16 14:02:16 +08:00
Mygod 5c7174fc5e Add default kcpcli 2016-08-16 11:49:14 +08:00
Mygod 536fe92c83 Refine #806 2016-08-16 11:23:21 +08:00
Mygod 29e6deabd0 Update sbt-android 2016-08-16 11:15:14 +08:00
Mygod e6b39444e8 Update to Java 1.7 2016-08-16 10:57:07 +08:00
Mygod 1b480b0163 Order libraryDependencies in alphabetical order
Putting support library after its dependencies could cause build failures on some rare cases.
2016-08-16 10:56:55 +08:00
Mygod c7fc4095ff Remove compatibility code for Jelly Bean 2016-08-16 10:26:52 +08:00
Max Lv 41d585ae22 Drop the support of Android 4.3 and below 2016-08-14 11:40:26 +08:00
Max Lv 63713b1eea Revert toolchain to GCC 4.9 2016-08-14 10:35:04 +08:00
Max Lv dd6cd3977d Fix #806 #804 2016-08-13 17:33:10 +08:00
Max Lv a671ae98b8 Update kcptun 2016-08-12 15:59:34 +08:00
Max Lv 7531eb5f5f Add official mbedtls submodule 2016-08-12 11:17:03 +08:00
Max Lv dca3be8eff Remove our fork of mbedtls 2016-08-12 11:15:41 +08:00
Max Lv a5d620ab02 Replace OpenSSL with mbedTLS 2016-08-12 10:08:11 +08:00
Mygod 0e7dbde4d9 Refine build.sbt 2016-08-11 20:15:13 +08:00
Mygod 7d0277324c Add aes-ctr ciphers
Addresses: https://github.com/shadowsocks/shadowsocks-org/issues/21
2016-08-11 19:28:12 +08:00
Max Lv 08d99caf1c Update kcptun 2016-08-10 13:27:06 +08:00
Max Lv 0a400ef5f9 Trim the KCP parameters 2016-08-09 12:27:32 +08:00
Max Lv cda3650c43 Revert "Fix SecurityException on Asus Fonepads"
This reverts commit f7d422da2b.
2016-08-09 12:10:57 +08:00
Max Lv b1c19f8f03 Bump version 2016-08-09 11:53:13 +08:00
Mygod f7d422da2b Fix SecurityException on Asus Fonepads
This is a bug of their ROMs but the documentation says:

> Must be required by a VpnService, to ensure that only the system can bind to it.
>
> Protection level: signature
>
> Constant Value: "android.permission.BIND_VPN_SERVICE"

And we have `android:exported="false"` set, so I think it's safe to remove this permission restriction.
2016-08-09 10:45:02 +08:00
Mygod 10725c39cb Check QsTile is null 2016-08-09 10:33:03 +08:00
Mygod 4b5c94022b Update sbt-android 2016-08-09 10:16:01 +08:00
Mygod 6afc3f80be Revert "Update dependency (#799)"
This reverts commit a02d19bba0.
2016-08-09 10:12:56 +08:00
Syrone Wong a02d19bba0 Update dependency (#799)
* Run android-update before native building

* Update sbt-android to 1.6.11
2016-08-09 09:36:48 +08:00
Mygod 984e75ae99 Fix incorrect handling of default values on database upgrade 2016-08-09 04:34:51 +08:00
Mygod 3cc1a1602e Fix go install: no install location for directory again 2016-08-08 19:27:24 +08:00
Mygod 72305c5f60 Fix a bug in SummaryEditTextPreference 2016-08-08 18:47:26 +08:00
Mygod 4303c1cd0c Remove signing in Travis builds (#798) 2016-08-08 13:20:10 +08:00
Mygod 5dad89b71e Update prerequisites in README.md 2016-08-08 12:25:11 +08:00
Mygod 109d4728f4 Remove redundant platform-tools install for Travis 2016-08-08 12:12:37 +08:00
Mygod 53b9c1f4af Switch to Android platform on Travis 2016-08-08 11:58:44 +08:00
Mygod 23fc7e9134 Fix go install: no install location for directory error 2016-08-08 03:20:33 +08:00
Mygod e73fc9f881 Refine travis CI 2016-08-08 02:48:06 +08:00
Mygod 941393cab4 Update dependencies 2016-08-08 02:40:12 +08:00
Mygod a6e87cf666 Merge branch 'master' of github.com:shadowsocks/shadowsocks-android 2016-08-08 00:15:38 +08:00
Max Lv 4817539ca2 Fix UDP forward 2016-08-07 10:43:25 +08:00
Max Lv 03c857536d Fix the build scripts 2016-08-07 08:16:55 +08:00
Eva Kane 14038cd152 Fix remove problem (#793) 2016-08-06 23:10:04 +08:00
Syrone Wong 935314a1c5 Fix kcptun license in about page (#792)
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
2016-08-06 22:37:41 +08:00
Max Lv 7263bf11a4 Update license 2016-08-06 19:36:10 +08:00
Mygod 81295e4a51 Remove unnecessary padding for connection test text 2016-07-31 09:57:52 -06:00
75 changed files with 4735 additions and 565 deletions
+18
View File
@@ -0,0 +1,18 @@
Please answer these questions before submitting your issue. Thanks!
### What version of Shadowsocks are you using?
### What Android OS version and device are you using?
### What did you do?
### What did you expect to see?
### What did you see instead?
### What is your config in detail (with all sensitive info masked)?
+6 -3
View File
@@ -9,9 +9,6 @@
path = src/main/jni/libancillary
url = https://github.com/shadowsocks/libancillary.git
branch = shadowsocks-android
[submodule "src/main/jni/openssl"]
path = src/main/jni/openssl
url = https://github.com/shadowsocks/openssl-android.git
[submodule "src/main/jni/libevent"]
path = src/main/jni/libevent
url = https://github.com/shadowsocks/libevent.git
@@ -30,3 +27,9 @@
[submodule "kcptun/go"]
path = kcptun/go
url = https://github.com/shadowsocks/go
[submodule "src/main/jni/mbedtls"]
path = src/main/jni/mbedtls
url = https://github.com/ARMmbed/mbedtls
[submodule "src/main/jni/pcre"]
path = src/main/jni/pcre
url = https://android.googlesource.com/platform/external/pcre
+35 -23
View File
@@ -1,19 +1,16 @@
language: scala
language: android
jdk:
- oraclejdk8
sudo: false
addons:
apt:
packages:
- gcc-multilib
- g++-multilib
- libstdc++6:i386
- libgcc1:i386
- zlib1g:i386
- libncurses5:i386
env:
global:
- NDK_VERSION=r12b
- NDK_CCACHE=ccache
- GOROOT_BOOTSTRAP=$GOROOT
- ANDROID_NDK_HOME=$HOME/.android/android-ndk-${NDK_VERSION}
- SBTPATH=$HOME/.sbt
- PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}
scala:
- 2.11.8
@@ -24,18 +21,33 @@ before_cache:
cache:
directories:
- $HOME/.ivy2/cache
- $HOME/.sbt/boot
- $HOME/.ivy2
- $HOME/.sbt
android:
components:
- tools
- build-tools-24.0.1
- extra-android-m2repository
- extra-google-m2repository
install:
- ./travis-ci/setup.sh
- export NDK_CCACHE=ccache
- export ARCH=`uname -m`
- export GOROOT_BOOTSTRAP=$HOME/.android/go
- export ANDROID_NDK_HOME=$HOME/.android/android-ndk-r12b
- export ANDROID_HOME=$HOME/.android/android-sdk-linux
- export PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}
- cp local.properties.travis local.properties
- >
if [ ! -d "$ANDROID_NDK_HOME" ]; then
mkdir -p $ANDROID_NDK_HOME;
pushd $HOME/.android;
export ARCH=`uname -m`;
wget -q http://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux-${ARCH}.zip;
unzip -q android-ndk-${NDK_VERSION}-linux-${ARCH}.zip;
popd;
fi
- >
if [ ! -f "$SBTPATH/sbt" ]; then
pushd $SBTPATH;
wget -q https://raw.githubusercontent.com/paulp/sbt-extras/master/sbt;
chmod a+x sbt;
popd;
fi
script:
- sbt native-build android:package-release
- $SBTPATH/sbt native-build android:package-debug
+6 -3
View File
@@ -12,8 +12,10 @@ A [shadowsocks](http://shadowsocks.org) client for Android, written in Scala.
* JDK 1.8
* SBT 0.13.0+
* GO 1.4+
* Android SDK r25+
* Go 1.4+
* Android SDK
- Build Tools 24+ (as required by [`sbt-android`](https://github.com/scala-android/sbt-android))
- Android Support Repository and Google Repository (see `build.sbt` for version)
* Android NDK r12b+
### BUILD
@@ -42,10 +44,11 @@ A [shadowsocks](http://shadowsocks.org) client for Android, written in Scala.
* pdnsd: [GPLv3](https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/pdnsd/COPYING)
* libev: [GPLv2](https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/libev/LICENSE)
* libevent: [BSD](https://github.com/shadowsocks/libevent/blob/master/LICENSE)
* kcptun: [MIT](https://github.com/xtaci/kcptun)
### LICENSE
Copyright (C) 2016 by Max Lv <<max.c.lv@gmail.com>> <br/>
Copyright (C) 2016 by Max Lv <<max.c.lv@gmail.com>>
Copyright (C) 2016 by Mygod Studio <<mygodstudio@gmail.com>>
This program is free software: you can redistribute it and/or modify
+16 -23
View File
@@ -10,9 +10,9 @@ scalaVersion := "2.11.8"
compileOrder in Compile := CompileOrder.JavaThenScala
javacOptions ++= Seq("-source", "1.6", "-target", "1.6")
javacOptions ++= Seq("-source", "1.7", "-target", "1.7")
scalacOptions ++= Seq("-target:jvm-1.6", "-Xexperimental")
scalacOptions ++= Seq("-target:jvm-1.7", "-Xexperimental")
ndkJavah in Android := List()
@@ -28,25 +28,22 @@ dexMaxHeap in Android := "4g"
resolvers += Resolver.jcenterRepo
resolvers += "JRAF" at "http://JRAF.org/static/maven/2"
useSupportVectors
libraryDependencies ++= Seq(
"dnsjava" % "dnsjava" % "2.1.7",
"com.github.kevinsawicki" % "http-request" % "6.0",
"eu.chainfire" % "libsuperuser" % "1.0.0.201607041850",
"net.glxn.qrgen" % "android" % "2.0",
"com.google.android.gms" % "play-services-ads" % "9.2.1",
"com.google.android.gms" % "play-services-analytics" % "9.2.1",
"com.android.support" % "design" % "24.1.0",
"com.android.support" % "gridlayout-v7" % "24.1.0",
"com.android.support" % "cardview-v7" % "24.1.0",
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01",
"com.j256.ormlite" % "ormlite-android" % "4.48",
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2",
"com.android.support" % "design" % "24.2.0",
"com.android.support" % "gridlayout-v7" % "24.2.0",
"com.github.clans" % "fab" % "1.6.4",
"me.dm7.barcodescanner" % "zxing" % "1.8.4"
"com.github.jorgecastilloprz" % "fabprogresscircle" % "1.01",
"com.github.kevinsawicki" % "http-request" % "6.0",
"com.google.android.gms" % "play-services-ads" % "9.4.0",
"com.google.android.gms" % "play-services-analytics" % "9.4.0",
"com.j256.ormlite" % "ormlite-android" % "5.0",
"com.twofortyfouram" % "android-plugin-api-for-locale" % "1.0.2",
"dnsjava" % "dnsjava" % "2.1.7",
"eu.chainfire" % "libsuperuser" % "1.0.0.201607041850",
"me.dm7.barcodescanner" % "zxing" % "1.9",
"net.glxn.qrgen" % "android" % "2.0"
)
proguardVersion in Android := "5.2.1"
@@ -55,12 +52,8 @@ proguardCache in Android := Seq()
proguardOptions in Android ++= Seq(
"-keep class com.github.shadowsocks.System { *; }",
"-dontwarn com.google.android.gms.**",
"-keep class com.google.android.gms.**",
"-dontnote com.google.android.gms.internal.**",
"-dontnote com.j256.ormlite.**",
"-dontnote me.dm7.barcodescannerview.**",
"-dontnote org.xbill.**",
"-dontwarn com.google.android.gms.internal.**",
"-dontwarn com.j256.ormlite.**",
"-dontwarn org.xbill.**")
lazy val nativeBuild = TaskKey[Unit]("native-build", "Build native executables")
+8 -5
View File
@@ -7,13 +7,16 @@ function try () {
# Build native binaries
pushd src/main
try $ANDROID_NDK_HOME/ndk-build -j8
# copy executables
rm -rf assets/armeabi-v7a
rm -rf assets/x86
mkdir -p assets/armeabi-v7a
mkdir -p assets/x86
#copy executables
for app in pdnsd redsocks ss-local ss-tunnel tun2socks
do
rm -f assets/armeabi-v7a
rm -f assets/x86
mkdir -p assets/armeabi-v7a
mkdir -p assets/x86
echo $app
try mv libs/armeabi-v7a/$app assets/armeabi-v7a/
try mv libs/x86/$app assets/x86/
done
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
cd ${1}
travis-artifacts upload --path ${2} --target-path nightly
+7 -3
View File
@@ -43,21 +43,25 @@ if [ ! -d "$DIR/go/bin" ]; then
fi
export GOROOT=$DIR/go
export GOPATH=$DEPS
export GOPATH=$DEPS/gopath
export GOBIN=$GOPATH/bin
mkdir -p $GOBIN
export PATH=$GOROOT/bin:$PATH
pushd kcptun/client
echo "Get dependences for kcptun"
go get -u github.com/xtaci/kcp-go
go get -u github.com/xtaci/smux
go get
echo "Cross compile kcptun for arm"
try env CGO_ENABLED=1 CC=$ANDROID_ARM_CC GOOS=android GOARCH=arm GOARM=7 go build
try env CGO_ENABLED=1 CC=$ANDROID_ARM_CC GOOS=android GOARCH=arm GOARM=7 go build -ldflags="-s -w"
try $ANDROID_ARM_STRIP client
try mv client $DIR/../src/main/assets/armeabi-v7a/kcptun
echo "Cross compile kcptun for x86"
try env CGO_ENABLED=1 CC=$ANDROID_X86_CC GOOS=android GOARCH=386 go build
try env CGO_ENABLED=1 CC=$ANDROID_X86_CC GOOS=android GOARCH=386 go build -ldflags="-s -w"
try $ANDROID_X86_STRIP client
try mv client $DIR/../src/main/assets/x86/kcptun
popd
-3
View File
@@ -1,3 +0,0 @@
key.alias: travis
key.store: travis.keystore
key.store.password: travis
+1 -1
View File
@@ -1,4 +1,4 @@
addSbtPlugin("org.scala-android" % "sbt-android" % "1.6.10")
addSbtPlugin("org.scala-android" % "sbt-android" % "1.6.17")
addSbtPlugin("com.timushev.sbt" % "sbt-updates" % "0.1.10")
+4 -4
View File
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" package="com.github.shadowsocks"
android:versionCode="143"
android:versionName="3.0.1">
android:versionCode="155"
android:versionName="3.1.3">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
@@ -19,7 +19,7 @@
android:required="false"/>
<uses-sdk
android:minSdkVersion="16"
android:minSdkVersion="19"
android:targetSdkVersion="24"/>
<application
@@ -109,7 +109,7 @@
android:launchMode="singleInstance"
android:excludeFromRecents="true"
android:taskAffinity=""
android:theme="@style/PopupTheme.QuickSwitch">
android:theme="@style/Theme.Material.Dialog">
<intent-filter>
<action android:name="com.github.shadowsocks.QUICK_SWITCH" />
<category android:name="android.intent.category.DEFAULT"/>
File diff suppressed because it is too large Load Diff
+1
View File
@@ -296,6 +296,7 @@ along with this program. If not, see <a href="http://www.gnu.org/licenses/">http
<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/libevent/blob/shadowsocks-android/LICENSE">GPLv2</a></li>
<li>libevent: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/libevent/LICENSE">BSD</a></li>
<li>kcptun: <a href="https://github.com/xtaci/kcptun/commits/master/LICENSE.md">MIT</a></li>
</ul>
</body>
+69 -17
View File
@@ -222,7 +222,7 @@ include $(CLEAR_VARS)
LIBEVENT_SOURCES := \
buffer.c \
bufferevent.c bufferevent_filter.c \
bufferevent_openssl.c bufferevent_pair.c bufferevent_ratelim.c \
bufferevent_pair.c bufferevent_ratelim.c \
bufferevent_sock.c epoll.c \
epoll_sub.c evdns.c event.c \
event_tagging.c evmap.c \
@@ -236,7 +236,6 @@ LOCAL_MODULE := event
LOCAL_SRC_FILES := $(addprefix libevent/, $(LIBEVENT_SOURCES))
LOCAL_CFLAGS := -O2 -I$(LOCAL_PATH)/libevent \
-I$(LOCAL_PATH)/libevent/include \
-I$(LOCAL_PATH)/openssl/include
include $(BUILD_STATIC_LIBRARY)
@@ -382,25 +381,29 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c acl.c android.c
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c \
utils.c netutils.c json.c jconf.c acl.c http.c tls.c rule.c \
android.c
LOCAL_MODULE := ss-local
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_LOCAL \
-DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H \
-DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H \
-DCONNECT_IN_PROGRESS=EINPROGRESS \
-I$(LOCAL_PATH)/include/shadowsocks-libev \
-I$(LOCAL_PATH)/include \
-I$(LOCAL_PATH)/libancillary \
-I$(LOCAL_PATH)/openssl/include \
-I$(LOCAL_PATH)/mbedtls/include \
-I$(LOCAL_PATH)/pcre \
-I$(LOCAL_PATH)/shadowsocks-libev/libudns \
-I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include/sodium \
-I$(LOCAL_PATH)/shadowsocks-libev/libipset/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libev \
-I$(LOCAL_PATH)/include/shadowsocks-libev
-I$(LOCAL_PATH)/shadowsocks-libev/libev
LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork libudns libsodium libancillary
LOCAL_STATIC_LIBRARIES := libev libmbedtls libipset libcork libudns \
libsodium libancillary libpcre
LOCAL_LDLIBS := -llog
@@ -417,7 +420,7 @@ SHADOWSOCKS_SOURCES := tunnel.c cache.c udprelay.c encrypt.c utils.c netutils.c
LOCAL_MODULE := ss-tunnel
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_TUNNEL \
-DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
-DUSE_CRYPTO_MBEDTLS -DANDROID -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
-DCONNECT_IN_PROGRESS=EINPROGRESS \
-I$(LOCAL_PATH)/libancillary \
-I$(LOCAL_PATH)/include \
@@ -425,11 +428,11 @@ LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DMODULE_TUNNEL \
-I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include/sodium \
-I$(LOCAL_PATH)/openssl/include \
-I$(LOCAL_PATH)/mbedtls/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libev \
-I$(LOCAL_PATH)/include/shadowsocks-libev
LOCAL_STATIC_LIBRARIES := libev libcrypto libsodium libcork libudns libancillary
LOCAL_STATIC_LIBRARIES := libev libmbedtls libsodium libcork libudns libancillary
LOCAL_LDLIBS := -llog
@@ -546,12 +549,61 @@ LOCAL_SRC_FILES := $(addprefix badvpn/, $(TUN2SOCKS_SOURCES))
include $(BUILD_EXECUTABLE)
# OpenSSL
openssl_subdirs := $(addprefix $(LOCAL_PATH)/openssl/,$(addsuffix /Android.mk, \
crypto \
ssl \
))
include $(openssl_subdirs)
########################################################
## mbed TLS
########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := mbedtls
LOCAL_C_INCLUDES := $(LOCAL_PATH)/mbedtls/include
MBEDTLS_SOURCES := $(wildcard $(LOCAL_PATH)/mbedtls/library/*.c)
LOCAL_SRC_FILES := $(MBEDTLS_SOURCES:$(LOCAL_PATH)/%=%)
include $(BUILD_STATIC_LIBRARY)
########################################################
## pcre
########################################################
include $(CLEAR_VARS)
LOCAL_MODULE := pcre
LOCAL_CFLAGS += -DHAVE_CONFIG_H
LOCAL_C_INCLUDES := $(LOCAL_PATH)/pcre/dist $(LOCAL_PATH)/pcre
libpcre_src_files := \
pcre_chartables.c \
dist/pcre_byte_order.c \
dist/pcre_compile.c \
dist/pcre_config.c \
dist/pcre_dfa_exec.c \
dist/pcre_exec.c \
dist/pcre_fullinfo.c \
dist/pcre_get.c \
dist/pcre_globals.c \
dist/pcre_jit_compile.c \
dist/pcre_maketables.c \
dist/pcre_newline.c \
dist/pcre_ord2utf8.c \
dist/pcre_refcount.c \
dist/pcre_string_utils.c \
dist/pcre_study.c \
dist/pcre_tables.c \
dist/pcre_ucd.c \
dist/pcre_valid_utf8.c \
dist/pcre_version.c \
dist/pcre_xclass.c
LOCAL_SRC_FILES := $(addprefix pcre/, $(libpcre_src_files))
include $(BUILD_STATIC_LIBRARY)
# Import cpufeatures
$(call import-module,android/cpufeatures)
+37 -31
View File
@@ -26,7 +26,7 @@
/* #undef HAVE_CCCRYPTORCREATEWITHMODE */
/* Define to 1 if you have the `clock_gettime' function. */
#define HAVE_CLOCK_GETTIME 1
/* #undef HAVE_CLOCK_GETTIME */
/* Define to 1 to use the syscall interface for clock_gettime */
/* #undef HAVE_CLOCK_SYSCALL */
@@ -42,13 +42,13 @@
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the `epoll_ctl' function. */
#define HAVE_EPOLL_CTL 1
/* #undef HAVE_EPOLL_CTL */
/* Define to 1 if you have the `eventfd' function. */
#define HAVE_EVENTFD 1
/* #undef HAVE_EVENTFD */
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
#define HAVE_EVP_ENCRYPTINIT_EX 1
/* #undef HAVE_EVP_ENCRYPTINIT_EX */
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
@@ -66,7 +66,7 @@
/* #undef HAVE_INET_NTOP */
/* Define to 1 if you have the `inotify_init' function. */
#define HAVE_INOTIFY_INIT 1
/* #undef HAVE_INOTIFY_INIT */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
@@ -75,7 +75,7 @@
#define HAVE_IPv6 1
/* Define to 1 if you have the `kqueue' function. */
/* #undef HAVE_KQUEUE */
#define HAVE_KQUEUE 1
/* Define to 1 if you have the <langinfo.h> header file. */
#define HAVE_LANGINFO_H 1
@@ -90,14 +90,14 @@
#define HAVE_LIMITS_H 1
/* Define to 1 if you have the <linux/if.h> header file. */
#define HAVE_LINUX_IF_H 1
/* #undef HAVE_LINUX_IF_H */
/* Define to 1 if you have the <linux/netfilter_ipv4.h> header file. */
#define HAVE_LINUX_NETFILTER_IPV4_H 1
/* #undef HAVE_LINUX_NETFILTER_IPV4_H */
/* Define to 1 if you have the <linux/netfilter_ipv6/ip6_tables.h> header
file. */
#define HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H 1
/* #undef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H */
/* Define to 1 if you have the <locale.h> header file. */
#define HAVE_LOCALE_H 1
@@ -124,25 +124,25 @@
#define HAVE_NET_IF_H 1
/* Define to 1 if you have the <openssl/engine.h> header file. */
#define HAVE_OPENSSL_ENGINE_H 1
/* #undef HAVE_OPENSSL_ENGINE_H */
/* Define to 1 if you have the <openssl/err.h> header file. */
#define HAVE_OPENSSL_ERR_H 1
/* #undef HAVE_OPENSSL_ERR_H */
/* Define to 1 if you have the <openssl/evp.h> header file. */
#define HAVE_OPENSSL_EVP_H 1
/* #undef HAVE_OPENSSL_EVP_H */
/* Define to 1 if you have the <openssl/pem.h> header file. */
#define HAVE_OPENSSL_PEM_H 1
/* #undef HAVE_OPENSSL_PEM_H */
/* Define to 1 if you have the <openssl/rand.h> header file. */
#define HAVE_OPENSSL_RAND_H 1
/* #undef HAVE_OPENSSL_RAND_H */
/* Define to 1 if you have the <openssl/rsa.h> header file. */
#define HAVE_OPENSSL_RSA_H 1
/* #undef HAVE_OPENSSL_RSA_H */
/* Define to 1 if you have the <openssl/sha.h> header file. */
#define HAVE_OPENSSL_SHA_H 1
/* #undef HAVE_OPENSSL_SHA_H */
/* Define to 1 if you have the `poll' function. */
#define HAVE_POLL 1
@@ -160,13 +160,13 @@
#define HAVE_PTHREAD_PRIO_INHERIT 1
/* Define to 1 if you have the `RAND_pseudo_bytes' function. */
#define HAVE_RAND_PSEUDO_BYTES 1
/* #undef HAVE_RAND_PSEUDO_BYTES */
/* Define to 1 if you have the 'select' function. */
#define HAVE_SELECT 1
/* Define to 1 if you have the `setresuid' function. */
#define HAVE_SETRESUID 1
/* #undef HAVE_SETRESUID */
/* Define to 1 if you have the `setreuid' function. */
#define HAVE_SETREUID 1
@@ -175,7 +175,7 @@
#define HAVE_SETRLIMIT 1
/* Define to 1 if you have the `signalfd' function. */
#define HAVE_SIGNALFD 1
/* #undef HAVE_SIGNALFD */
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
@@ -196,16 +196,16 @@
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/epoll.h> header file. */
#define HAVE_SYS_EPOLL_H 1
/* #undef HAVE_SYS_EPOLL_H */
/* Define to 1 if you have the <sys/eventfd.h> header file. */
#define HAVE_SYS_EVENTFD_H 1
/* #undef HAVE_SYS_EVENTFD_H */
/* Define to 1 if you have the <sys/event.h> header file. */
/* #undef HAVE_SYS_EVENT_H */
#define HAVE_SYS_EVENT_H 1
/* Define to 1 if you have the <sys/inotify.h> header file. */
#define HAVE_SYS_INOTIFY_H 1
/* #undef HAVE_SYS_INOTIFY_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
#define HAVE_SYS_IOCTL_H 1
@@ -214,7 +214,7 @@
#define HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/signalfd.h> header file. */
#define HAVE_SYS_SIGNALFD_H 1
/* #undef HAVE_SYS_SIGNALFD_H */
/* Define to 1 if you have the <sys/socket.h> header file. */
#define HAVE_SYS_SOCKET_H 1
@@ -253,10 +253,10 @@
/* #undef HAVE_WS2TCPIP_H */
/* have zlib compression support */
#define HAVE_ZLIB 1
/* #undef HAVE_ZLIB */
/* Define to 1 if you have the <zlib.h> header file. */
#define HAVE_ZLIB_H 1
/* #undef HAVE_ZLIB_H */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
@@ -275,7 +275,7 @@
#define PACKAGE_NAME "shadowsocks-libev"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "shadowsocks-libev 2.4.7"
#define PACKAGE_STRING "shadowsocks-libev 2.4.8"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "shadowsocks-libev"
@@ -284,7 +284,7 @@
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "2.4.7"
#define PACKAGE_VERSION "2.4.8"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
@@ -315,10 +315,10 @@
/* #undef USE_CRYPTO_APPLECC */
/* Use mbed TLS library */
/* #undef USE_CRYPTO_MBEDTLS */
#define USE_CRYPTO_MBEDTLS 1
/* Use OpenSSL library */
#define USE_CRYPTO_OPENSSL 1
/* #undef USE_CRYPTO_OPENSSL */
/* Use PolarSSL library */
/* #undef USE_CRYPTO_POLARSSL */
@@ -346,7 +346,7 @@
/* Version number of package */
#define VERSION "2.4.7"
#define VERSION "2.4.8"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
@@ -417,3 +417,9 @@
/* Define as `fork' if `vfork' does not work. */
/* #undef vfork */
/* Define to 1 if you have the <pcre.h> header file. */
#define HAVE_PCRE_H 1
/* Define to 1 if you have the <pcre/pcre.h> header file. */
/* #undef HAVE_PCRE_PCRE_H */
+1
Submodule src/main/jni/pcre added at 0ea9883633
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+1
View File
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+1
View File
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+1
View File
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -1,3 +1,4 @@
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+2 -1
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -11,4 +12,4 @@
<path
android:fillColor="#fff"
android:pathData="M 9.45 17.56 L 9.46 22 L 12.09 18.41 L 9.45 17.56 L 9.45 17.56 Z" />
</vector>
</vector>
+2 -1
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -11,4 +12,4 @@
<path
android:fillColor="#fff"
android:pathData="M 9.45 17.56 L 12.09 18.41 L 9.46 22 L 9.45 17.56 Z" />
</vector>
</vector>
+2 -1
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--suppress NewApi -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
@@ -22,4 +23,4 @@
<path
android:fillColor="#fff"
android:pathData="M8.56,8.56L0,12.8l6.83,2.57,4.64-3.9ZM6.44,13.08L5,12.55l5-2.47Z" />
</vector>
</vector>
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView android:text="@string/stat" android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary" android:ellipsize="marquee"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<TextView android:id="@+id/connection_test" android:gravity="end"
android:textSize="14sp" android:textColor="?android:attr/textColorSecondary"
android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1"/>
</LinearLayout>
+4 -4
View File
@@ -18,8 +18,8 @@
android:text="@string/on"
android:textSize="18sp"
android:textColor="?android:attr/textColorSecondary"
android:paddingLeft="60dp"
android:paddingRight="8dp"
android:paddingStart="60dp"
android:paddingEnd="8dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:layout_width="match_parent"
@@ -30,8 +30,8 @@
android:text="@string/bypass_apps"
android:textSize="18sp"
android:textColor="?android:attr/textColorSecondary"
android:paddingLeft="60dp"
android:paddingRight="8dp"
android:paddingStart="60dp"
android:paddingEnd="8dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:layout_width="match_parent"
+3 -4
View File
@@ -11,8 +11,8 @@
android:layout_width="60dp"
android:layout_height="48dp"
android:scaleType="fitCenter"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingStart="8dp"
android:paddingEnd="8dp"
android:paddingTop="2dp"
android:paddingBottom="2dp"/>
@@ -28,7 +28,6 @@
android:focusable="false"
android:focusableInTouchMode="false"
android:clickable="false"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"/>
android:layout_marginEnd="8dp"/>
</LinearLayout>
+26 -9
View File
@@ -10,17 +10,35 @@
<LinearLayout android:id="@+id/stat" android:elevation="4dp" android:visibility="gone"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight" android:gravity="center_vertical"
android:paddingStart="16dip" android:paddingEnd="88dip" android:focusable="true"
android:paddingLeft="16dip" android:paddingRight="88dip"
android:paddingStart="16dip" android:paddingEnd="16dip" android:focusable="true"
android:paddingTop="16dip" android:paddingBottom="16dip"
android:background="@drawable/background_stat" android:orientation="vertical">
<include layout="@layout/layout_main_stat_title"/>
android:background="@drawable/background_stat" android:orientation="vertical"
android:nextFocusRight="@+id/fab">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView android:text="@string/stat"
android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary"
android:ellipsize="marquee"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView android:id="@+id/connection_test"
android:gravity="end"
android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
<android.support.v7.widget.GridLayout android:layout_width="match_parent"
android:layout_height="wrap_content" app:columnCount="4">
android:layout_height="wrap_content"
android:paddingEnd="72dip"
app:columnCount="4">
<TextView app:layout_column="0" style="@style/TextAppearance.AppCompat.Body2"
android:ellipsize="marquee" android:text="@string/sent"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="24dp" android:layout_marginEnd="24dp" android:gravity="end"/>
android:layout_marginEnd="24dp"
android:gravity="end"/>
<TextView app:layout_column="1" android:id="@+id/tx" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
android:layout_width="0dp" android:layout_height="wrap_content"
@@ -35,7 +53,8 @@
app:layout_gravity="fill_horizontal" android:gravity="end"/>
<TextView app:layout_row="1" app:layout_column="0" style="@style/TextAppearance.AppCompat.Body2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginRight="24dp" android:layout_marginEnd="24dp" android:gravity="end"
android:layout_marginEnd="24dp"
android:gravity="end"
android:ellipsize="marquee" android:text="@string/received"/>
<TextView app:layout_row="1" app:layout_column="1" android:id="@+id/rx" android:textSize="14sp"
android:textColor="?android:attr/textColorSecondary" android:ellipsize="marquee"
@@ -58,9 +77,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:elevation="6dp"
android:layout_alignBottom="@+id/title_bar"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="@dimen/fab_margin_bottom">
<android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content"
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
android:layout_width="match_parent" android:layout_height="wrap_content">
<TextView android:text="@string/stat" android:textSize="16sp"
android:textColor="?android:attr/textColorPrimary" android:ellipsize="marquee"
android:layout_width="match_parent" android:layout_height="wrap_content"/>
<TextView android:id="@+id/connection_test"
android:textSize="14sp" android:textColor="?android:attr/textColorSecondary"
android:layout_width="match_parent" android:layout_height="wrap_content"/>
</LinearLayout>
-1
View File
@@ -16,7 +16,6 @@
android:layout_height="match_parent"
android:layout_gravity="bottom|end"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
app:menu_colorNormal="@color/material_accent_500"
app:menu_colorPressed="@color/material_accent_700"
@@ -8,8 +8,6 @@
android:background="?android:attr/selectableItemBackground"
android:paddingStart="20dp"
android:paddingEnd="?attr/dialogPreferredPadding"
android:paddingLeft="20dp"
android:paddingRight="?attr/dialogPreferredPadding"
android:focusable="true"
android:nextFocusRight="@+id/share">
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
@@ -23,7 +21,6 @@
android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
android:drawableStart="?android:attr/listChoiceIndicatorSingle"
android:drawableLeft="?android:attr/listChoiceIndicatorSingle"
android:drawablePadding="20dp"
android:maxLines="4"
android:scrollHorizontally="false" />
+9 -19
View File
@@ -1,24 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_margin="8dp"
android:layout_gravity="center_vertical"
app:cardElevation="5dp"
app:cardBackgroundColor="#EEEEEE">
android:layout_height="wrap_content">
<LinearLayout
android:orientation="vertical"
<include layout="@layout/toolbar_light_dark"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/profilesList"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<include layout="@layout/toolbar_light_dark"/>
<android.support.v7.widget.RecyclerView
android:id="@+id/profilesList"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
</android.support.v7.widget.CardView>
android:layout_height="wrap_content"/>
</LinearLayout>
+3 -2
View File
@@ -53,6 +53,8 @@
<string name="bypass_apps_summary">Включите эту опцию для работы выбранных приложений в обход прокси</string>
<string name="auto_connect">Авто Подключение</string>
<string name="auto_connect_summary">Запускать Shadowsocks при включении</string>
<string name="tcp_fastopen_summary">Переключение требует наличия ROOT прав</string>
<string name="tcp_fastopen_summary_unsupported">Неподдерживаемая версия ядра: %s &lt; 3.7.1</string>
<string name="udp_dns">Проброс UDP</string>
<string name="udp_dns_summary">Пробрасывать UDP пакеты на удалённый сервер</string>
@@ -92,8 +94,7 @@
<string name="share_message_nfc_disabled">Сканировать QR код\nAndroid Beam отключен</string>
<string name="turn_on_nfc">Включить NFC &amp; Android Beam</string>
<string name="flush_dnscache">Очистить кэш DNS</string>
<string name="flush_dnscache_summary">Работает только в режиме NAT</string>
<string name="flush_dnscache_summary_root">Работает только в режиме NAT. Требует наличия ROOT прав.</string>
<string name="flush_dnscache_summary">Работает только в режиме NAT. Требует наличия ROOT прав.</string>
<string name="flush_dnscache_no_root">Очистка кэша DNS не работает без налиичя ROOT прав</string>
<string name="flushing">Очистка</string>
<string name="add_profile">Добавить Профиль</string>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.Material.Dialog" parent="Theme.Material.DialogBase"/>
<style name="Theme.Material.Dialog.Alert" parent="Theme.Material.Dialog.AlertBase"/>
</resources>
+4 -2
View File
@@ -32,6 +32,8 @@
<string name="bypass_apps_summary">启用该选项,以使所选应用程序的流量不经过代理</string>
<string name="auto_connect">自动连接</string>
<string name="auto_connect_summary">随系统启动后台服务</string>
<string name="tcp_fastopen_summary">切换需要 ROOT 权限</string>
<string name="tcp_fastopen_summary_unsupported">不支持的内核版本:%s &lt; 3.7.1</string>
<string name="forward_success">后台服务已开始运行。</string>
<string name="service_failed">无法连接远程服务器</string>
<string name="invalid_server">服务器名无效</string>
@@ -58,8 +60,7 @@
<string name="about">关于</string>
<string name="about_title">影梭(shadowsocks)%s</string>
<string name="flush_dnscache">刷新 DNS 缓存</string>
<string name="flush_dnscache_summary">只需在 NAT 模式下使用</string>
<string name="flush_dnscache_summary_root">只需在 NAT 模式下使用,需要 ROOT 权限</string>
<string name="flush_dnscache_summary">只需在 NAT 模式下使用,需要 ROOT 权限</string>
<string name="flush_dnscache_no_root">在没有 ROOT 权限的情况下无法刷新 DNS 缓存</string>
<string name="flushing">刷新中……</string>
<string name="share">分享</string>
@@ -109,6 +110,7 @@
<item>绕过局域网地址</item>
<item>绕过中国大陆地址</item>
<item>绕过局域网及中国大陆地址</item>
<item>仅代理国内无法访问的地址</item>
</string-array>
<string name="action_apply_all">应用设置到所有配置文件</string>
+4 -2
View File
@@ -33,6 +33,8 @@
<string name="bypass_apps_summary">啟用此選項,會略過已選擇的應用程式</string>
<string name="auto_connect">自動連線</string>
<string name="auto_connect_summary">在裝置啟動時啟用 Shadowsocks</string>
<string name="tcp_fastopen_summary">切換需要 ROOT 權限</string>
<string name="tcp_fastopen_summary_unsupported">不支持的內核版本:%s &lt; 3.7.1</string>
<string name="forward_success">Shadowsocks 已啟動。</string>
<string name="service_failed">連線至遠端伺服器失敗</string>
<string name="invalid_server">伺服器名稱無效</string>
@@ -59,8 +61,7 @@
<string name="about">關於</string>
<string name="about_title">Shadowsocks %s</string>
<string name="flush_dnscache">清除 DNS 快取</string>
<string name="flush_dnscache_summary">僅在 NAT 模式可用</string>
<string name="flush_dnscache_summary_root">僅在 NAT 模式可用,需要 ROOT 權限</string>
<string name="flush_dnscache_summary">僅在 NAT 模式可用,需要 ROOT 權限</string>
<string name="flush_dnscache_no_root">在無 ROOT 權限時清除 DNS 快取無法進行</string>
<string name="flushing">清除中……</string>
<string name="share">分享</string>
@@ -111,6 +112,7 @@
<item>略過區域網路位址</item>
<item>略過中國大陸位址</item>
<item>略過區域網路及中國大陸位址</item>
<item>僅代理大陸屏蔽位址</item>
</string-array>
<string name="action_apply_all">應用設置到所有配置文件</string>
+8 -10
View File
@@ -7,15 +7,13 @@
<item>AES-128-CFB</item>
<item>AES-192-CFB</item>
<item>AES-256-CFB</item>
<item>AES-128-CTR</item>
<item>AES-192-CTR</item>
<item>AES-256-CTR</item>
<item>BF-CFB</item>
<item>CAMELLIA-128-CFB</item>
<item>CAMELLIA-192-CFB</item>
<item>CAMELLIA-256-CFB</item>
<item>CAST5-CFB</item>
<item>DES-CFB</item>
<item>IDEA-CFB</item>
<item>RC2-CFB</item>
<item>SEED-CFB</item>
<item>SALSA20</item>
<item>CHACHA20</item>
<item>CHACHA20-IETF</item>
@@ -28,15 +26,13 @@
<item>aes-128-cfb</item>
<item>aes-192-cfb</item>
<item>aes-256-cfb</item>
<item>aes-128-ctr</item>
<item>aes-192-ctr</item>
<item>aes-256-ctr</item>
<item>bf-cfb</item>
<item>camellia-128-cfb</item>
<item>camellia-192-cfb</item>
<item>camellia-256-cfb</item>
<item>cast5-cfb</item>
<item>des-cfb</item>
<item>idea-cfb</item>
<item>rc2-cfb</item>
<item>seed-cfb</item>
<item>salsa20</item>
<item>chacha20</item>
<item>chacha20-ietf</item>
@@ -47,6 +43,7 @@
<item>Bypass LAN</item>
<item>Bypass China</item>
<item>Bypass LAN &amp; China</item>
<item>GFW List</item>
</string-array>
<string-array name="route_value">
@@ -54,6 +51,7 @@
<item>bypass-lan</item>
<item>bypass-china</item>
<item>bypass-lan-china</item>
<item>gfwlist</item>
</string-array>
<string-array name="private_route">
+3 -2
View File
@@ -59,6 +59,8 @@
<string name="bypass_apps_summary">Enable this option to bypass selected apps</string>
<string name="auto_connect">Auto Connect</string>
<string name="auto_connect_summary">Enable Shadowsocks on startup</string>
<string name="tcp_fastopen_summary">Toggling requires ROOT permission</string>
<string name="tcp_fastopen_summary_unsupported">Unsupported kernel version: %s &lt; 3.7.1</string>
<string name="udp_dns">UDP Forwarding</string>
<string name="udp_dns_summary">Forward UDP packets to remote</string>
@@ -98,8 +100,7 @@
<string name="share_message_nfc_disabled">Scan QR code\nAndroid Beam is disabled</string>
<string name="turn_on_nfc">Turn on NFC &amp; Android Beam</string>
<string name="flush_dnscache">Flush DNS cache</string>
<string name="flush_dnscache_summary">Only useful in NAT mode</string>
<string name="flush_dnscache_summary_root">Only useful in NAT mode. Requires ROOT permission.</string>
<string name="flush_dnscache_summary">Only useful in NAT mode. Requires ROOT permission.</string>
<string name="flush_dnscache_no_root">Flush DNS cache cannot proceed without ROOT permission</string>
<string name="flushing">Flushing</string>
<string name="add_profile">Add Profile</string>
+2 -30
View File
@@ -7,8 +7,7 @@
</style>
<style name="Theme.Material" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:alertDialogTheme">@style/Theme.Material.Dialog.Alert</item>
<item name="android:dialogTheme">@style/Theme.Material.Dialog</item>
<!--suppress NewApi -->
<item name="android:navigationBarColor">@color/material_accent_700</item>
<item name="colorAccent">@color/material_accent_500</item>
<item name="colorButtonNormal">@color/material_accent_500</item>
@@ -16,38 +15,11 @@
<item name="colorPrimaryDark">@color/material_accent_700</item>
</style>
<style name="Theme.Material.DialogBase" parent="Theme.AppCompat.Light.Dialog">
<style name="Theme.Material.Dialog" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">@color/material_accent_500</item>
<item name="colorPrimary">@color/material_accent_500</item>
<item name="colorPrimaryDark">@color/material_accent_700</item>
</style>
<style name="Theme.Material.Dialog.AlertBase" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorAccent">@color/material_accent_500</item>
<item name="colorPrimary">@color/material_accent_500</item>
<item name="colorPrimaryDark">@color/material_accent_700</item>
</style>
<style name="Theme.Material.Dialog" parent="Theme.Material.DialogBase">
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="Theme.Material.Dialog.Alert" parent="Theme.Material.Dialog.AlertBase">
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="PopupTheme" parent="Theme.Material.Dialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
<item name="android:colorBackgroundCacheHint">@null</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
<style name="PopupTheme.QuickSwitch" parent="PopupTheme">
<item name="windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
</style>
</resources>
+7 -2
View File
@@ -94,7 +94,7 @@
android:summary="@string/kcp_port_summary"
android:title="@string/kcp_port"/>
<com.github.shadowsocks.preferences.SummaryEditTextPreference
<com.github.shadowsocks.preferences.KcpCliPreference
android:key="kcpcli"
android:persistent="false"
android:summary="@string/kcpcli_summary"
@@ -110,6 +110,11 @@
android:summary="@string/auto_connect_summary"
android:title="@string/auto_connect"/>
<SwitchPreference
android:key="tcp_fastopen"
android:summary="@string/tcp_fastopen_summary"
android:title="TCP Fast Open"/>
<SwitchPreference android:key="isNAT"
android:title="@string/nat"
android:summary="@string/nat_summary"/>
@@ -117,7 +122,7 @@
android:summary="@string/recovery_summary"/>
<Preference android:key="flush_dnscache"
android:title="@string/flush_dnscache"
android:summary="@string/flush_dnscache_summary_root"/>
android:summary="@string/flush_dnscache_summary"/>
<Preference android:key="about" android:title="@string/about"/>
</PreferenceCategory>
@@ -39,6 +39,7 @@
package com.github.shadowsocks
import java.io.IOException
import java.util.{Timer, TimerTask}
import android.app.Service
@@ -48,7 +49,6 @@ import android.os.{Handler, RemoteCallbackList}
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import com.github.kevinsawicki.http.HttpRequest
import com.github.shadowsocks.aidl.{IShadowsocksService, IShadowsocksServiceCallback}
import com.github.shadowsocks.utils._
@@ -60,6 +60,9 @@ trait BaseService extends Service {
@volatile private var state = State.STOPPED
@volatile protected var profile: Profile = _
case class NameNotResolvedException() extends IOException
case class KcpcliParseException(cause: Throwable) extends Exception(cause)
var timer: Timer = _
var trafficMonitorThread: TrafficMonitorThread = _
@@ -136,7 +139,7 @@ trait BaseService extends Service {
false
} else true
def connect() = if (profile.host == "198.199.101.152") try {
def connect() = if (profile.host == "198.199.101.152") {
val holder = app.containerHolder
val container = holder.getContainer
val url = container.getString("proxy_url")
@@ -153,8 +156,6 @@ trait BaseService extends Service {
profile.remotePort = proxy(1).trim.toInt
profile.password = proxy(2).trim
profile.method = proxy(3).trim
} catch {
case ex: Exception => stopRunner(true, getString(R.string.service_failed))
}
def startRunner(profile: Profile) {
@@ -188,7 +189,15 @@ trait BaseService extends Service {
if (profile.isMethodUnsafe) handler.post(() => Toast.makeText(this, R.string.method_unsafe, Toast.LENGTH_LONG).show)
Utils.ThrowableFuture(connect)
Utils.ThrowableFuture(try connect catch {
case _: NameNotResolvedException => stopRunner(true, getString(R.string.invalid_server))
case exc: KcpcliParseException =>
stopRunner(true, getString(R.string.service_failed) + ": " + exc.cause.getMessage)
case exc: Throwable =>
stopRunner(true, getString(R.string.service_failed) + ": " + exc.getMessage)
exc.printStackTrace()
app.track(exc)
})
}
def stopRunner(stopService: Boolean, msg: String = null) {
@@ -39,18 +39,35 @@
package com.github.shadowsocks
import java.io.{IOException, InputStream, OutputStream}
import java.io._
import java.lang.System.currentTimeMillis
import java.util.concurrent.Semaphore
import android.util.Log
import scala.collection.JavaConversions._
import scala.collection.immutable.Stream
import scala.util.control.Exception._
class StreamLogger(is: InputStream, tag: String) extends Thread {
def withCloseable[T <: Closeable, R](t: T)(f: T => R): R = {
allCatch.andFinally{t.close} apply { f(t) }
}
override def run() {
withCloseable(new BufferedReader(new InputStreamReader(is))) {
br => try Stream.continually(br.readLine()).takeWhile(_ != null).foreach(Log.i(tag, _)) catch {
case ignore: IOException =>
}
}
}
}
/**
* @author ayanamist@gmail.com
*/
class GuardedProcess(cmd: Seq[String]) extends Process {
class GuardedProcess(cmd: Seq[String]) {
private val TAG = classOf[GuardedProcess].getSimpleName
@volatile private var guardThread: Thread = _
@@ -72,19 +89,25 @@ class GuardedProcess(cmd: Seq[String]) extends Process {
process = new ProcessBuilder(cmd).redirectErrorStream(true).start
val is = process.getInputStream
new StreamLogger(is, TAG).start
if (callback == null) callback = onRestartCallback else callback()
semaphore.release
process.waitFor
if (isRestart) {
isRestart = false
} else {
if (currentTimeMillis - startTime < 1000) {
Log.w(TAG, "process exit too fast, stop guard: " + cmd)
isDestroyed = true
this.synchronized {
if (isRestart) {
isRestart = false
} else {
if (currentTimeMillis - startTime < 1000) {
Log.w(TAG, "process exit too fast, stop guard: " + cmd)
isDestroyed = true
}
}
}
}
} catch {
case ignored: InterruptedException =>
@@ -114,15 +137,12 @@ class GuardedProcess(cmd: Seq[String]) extends Process {
}
def restart() {
isRestart = true
process.destroy()
this.synchronized {
isRestart = true
process.destroy()
}
}
def exitValue: Int = throw new UnsupportedOperationException
def getErrorStream: InputStream = throw new UnsupportedOperationException
def getInputStream: InputStream = throw new UnsupportedOperationException
def getOutputStream: OutputStream = throw new UnsupportedOperationException
@throws(classOf[InterruptedException])
def waitFor = {
guardThread.join()
@@ -114,12 +114,14 @@ final class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClic
finish
}
def onKey(v: View, keyCode: Int, event: KeyEvent) = if (event.getAction == KeyEvent.ACTION_UP) keyCode match {
def onKey(v: View, keyCode: Int, event: KeyEvent) = if (event.getAction == KeyEvent.ACTION_DOWN) keyCode match {
case KeyEvent.KEYCODE_DPAD_LEFT =>
val index = getAdapterPosition
profilesAdapter.remove(index)
undoManager.remove(index, item)
true
if (index >= 0) {
profilesAdapter.remove(index)
undoManager.remove(index, item)
true
} else false
case _ => false
} else false
}
@@ -78,6 +78,7 @@ object Typefaces {
} catch {
case e: Exception =>
Log.e(TAG, "Could not get typeface '" + assetPath + "' because " + e.getMessage)
app.track(e)
return null
}
}
@@ -185,8 +186,8 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
snackbar.show
}
if (!app.settings.getBoolean(app.getVersionName, false)) {
app.editor.putBoolean(app.getVersionName, true).apply()
if (!app.settings.getBoolean(BuildConfig.VERSION_NAME, false)) {
app.editor.putBoolean(BuildConfig.VERSION_NAME, true).apply()
recovery()
@@ -246,6 +247,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
} catch {
case e: IOException =>
Log.e(TAG, e.getMessage)
app.track(e)
}
if (files != null) {
for (file <- files) {
@@ -267,6 +269,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
} catch {
case ex: Exception =>
Log.e(TAG, ex.getMessage)
app.track(ex)
}
}
}
@@ -481,7 +484,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
private def updatePreferenceScreen(profile: Profile) {
if (profile.host == "198.199.101.152") if (adView == null) {
adView = new AdView(this)
adView.setAdUnitId("ca-app-pub-4984938374218635/1433320509")
adView.setAdUnitId("ca-app-pub-9097031975646651/7760346322")
adView.setAdSize(AdSize.SMART_BANNER)
preferences.getView.asInstanceOf[ViewGroup].addView(adView, 1)
adView.loadAd(new AdRequest.Builder().build())
@@ -500,11 +503,8 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
clearDialog()
}
private var _isDestroyed: Boolean = _
override def isDestroyed = if (Build.VERSION.SDK_INT >= 17) super.isDestroyed else _isDestroyed
override def onDestroy() {
super.onDestroy()
_isDestroyed = true
detachService()
new BackupManager(this).dataChanged()
handler.removeCallbacksAndMessages(null)
@@ -514,6 +514,7 @@ class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
crashRecovery()
copyAssets(System.getABI)
copyAssets("acl")
val ab = new ArrayBuffer[String]
for (executable <- EXECUTABLES) {
@@ -43,12 +43,11 @@ import java.util
import java.util.concurrent.TimeUnit
import android.app.Application
import android.content.pm.PackageManager
import android.preference.PreferenceManager
import android.support.v7.app.AppCompatDelegate
import com.github.shadowsocks.database.{DBHelper, ProfileManager}
import com.github.shadowsocks.utils.{Key, Utils}
import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders}
import com.github.shadowsocks.utils.{Key, Utils, TcpFastOpen}
import com.google.android.gms.analytics.{GoogleAnalytics, HitBuilders, StandardExceptionParser}
import com.google.android.gms.common.api.ResultCallback
import com.google.android.gms.tagmanager.{ContainerHolder, TagManager}
import com.j256.ormlite.logger.LocalLog
@@ -70,17 +69,14 @@ class ShadowsocksApplication extends Application {
def isNatEnabled = settings.getBoolean(Key.isNAT, false)
def isVpnEnabled = !isNatEnabled
def getVersionName = try {
getPackageManager.getPackageInfo(getPackageName, 0).versionName
} catch {
case _: PackageManager.NameNotFoundException => "Package name not found"
case _: Throwable => null
}
// send event
def track(category: String, action: String) = tracker.send(new HitBuilders.EventBuilder()
.setAction(action)
.setLabel(getVersionName)
.setLabel(BuildConfig.VERSION_NAME)
.build())
def track(t: Throwable) = tracker.send(new HitBuilders.ExceptionBuilder()
.setDescription(new StandardExceptionParser(this, null).getDescription(Thread.currentThread.getName, t))
.setFatal(false)
.build())
def profileId = settings.getInt(Key.id, -1)
@@ -115,6 +111,8 @@ class ShadowsocksApplication extends Application {
}
}
pending.setResultCallback(callback, 2, TimeUnit.SECONDS)
TcpFastOpen.enabled(settings.getBoolean(Key.tfo, false))
}
def refreshContainerHolder {
@@ -40,7 +40,6 @@
package com.github.shadowsocks
import java.io.File
import java.lang.Process
import java.net.{Inet6Address, InetAddress}
import java.util.Locale
@@ -65,14 +64,14 @@ class ShadowsocksNatService extends BaseService {
private var notification: ShadowsocksNotification = _
val myUid = android.os.Process.myUid()
var sslocalProcess: Process = _
var sstunnelProcess: Process = _
var redsocksProcess: Process = _
var pdnsdProcess: Process = _
var sslocalProcess: GuardedProcess = _
var sstunnelProcess: GuardedProcess = _
var redsocksProcess: GuardedProcess = _
var pdnsdProcess: GuardedProcess = _
var su: Shell.Interactive = _
def startShadowsocksDaemon() {
if (profile.route != Route.ALL) {
if (profile.route != Route.ALL && profile.route != Route.GFWLIST) {
val acl: Array[Array[String]] = profile.route match {
case Route.BYPASS_LAN => Array(getResources.getStringArray(R.array.private_route))
case Route.BYPASS_CHN => Array(getResources.getStringArray(R.array.chn_route))
@@ -97,8 +96,7 @@ class ShadowsocksNatService extends BaseService {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-local"
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local"
, "-b" , "127.0.0.1"
, "-t" , "600"
, "-P", getApplicationInfo.dataDir
@@ -106,9 +104,14 @@ class ShadowsocksNatService extends BaseService {
if (profile.auth) cmd += "-A"
if (TcpFastOpen.sendEnabled) cmd += "--fast-open"
if (profile.route != Route.ALL) {
cmd += "--acl"
cmd += (getApplicationInfo.dataDir + "/acl.list")
if (profile.route == Route.GFWLIST)
cmd += (getApplicationInfo.dataDir + "/gfwlist.acl")
else
cmd += (getApplicationInfo.dataDir + "/acl.list")
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
@@ -116,16 +119,18 @@ class ShadowsocksNatService extends BaseService {
}
def startKcptunDaemon() {
if (profile.kcpcli == null) profile.kcpcli = ""
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/kcptun"
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/kcptun"
, "-r", profile.host + ":" + profile.kcpPort
, "-l", "127.0.0.1:" + (profile.localPort + 90)
, profile.kcpcli)
, "-l", "127.0.0.1:" + (profile.localPort + 90))
try cmd ++= Utils.translateCommandline(profile.kcpcli) catch {
case exc: Exception => throw KcpcliParseException(exc)
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
kcptunProcess = new GuardedProcess(cmd.mkString(" ").split(" ").toSeq).start()
kcptunProcess = new GuardedProcess(cmd).start()
}
def startDNSTunnel() {
@@ -136,8 +141,7 @@ class ShadowsocksNatService extends BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-tunnel"
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-tunnel"
, "-u"
, "-t" , "10"
, "-b" , "127.0.0.1"
@@ -165,8 +169,7 @@ class ShadowsocksNatService extends BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf"))(p => {
p.println(conf)
})
val cmdBuf = new ArrayBuffer[String]
cmdBuf += (getApplicationInfo.dataDir + "/ss-tunnel"
val cmdBuf = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-tunnel"
, "-t" , "10"
, "-b" , "127.0.0.1"
, "-l" , (profile.localPort + 63).toString
@@ -184,38 +187,40 @@ class ShadowsocksNatService extends BaseService {
def startDnsDaemon() {
val conf = if (profile.route == Route.BYPASS_CHN || profile.route == Route.BYPASS_LAN_CHN) {
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"127.0.0.1", profile.localPort + 53, getBlackList, profile.localPort + 63, "")
} else {
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"127.0.0.1", profile.localPort + 53, profile.localPort + 63, "")
val conf = profile.route match {
case Route.BYPASS_CHN | Route.BYPASS_LAN_CHN | Route.GFWLIST => {
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"127.0.0.1", profile.localPort + 53, getBlackList, profile.localPort + 63, "")
}
case _ => {
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"127.0.0.1", profile.localPort + 53, profile.localPort + 63, "")
}
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => {
p.println(conf)
})
val cmd = getApplicationInfo.dataDir + "/pdnsd -c " + getApplicationInfo.dataDir + "/pdnsd-nat.conf"
val cmd = Array(getApplicationInfo.dataDir + "/pdnsd", "-c", getApplicationInfo.dataDir + "/pdnsd-nat.conf")
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
pdnsdProcess = new GuardedProcess(cmd.split(" ").toSeq).start()
pdnsdProcess = new GuardedProcess(cmd).start()
}
def startRedsocksDaemon() {
val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, profile.localPort)
val cmd = "%s/redsocks -c %s/redsocks-nat.conf"
.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, getApplicationInfo.dataDir)
val cmd = Array(getApplicationInfo.dataDir + "/redsocks", "-c", getApplicationInfo.dataDir + "/redsocks-nat.conf")
Utils.printToFile(new File(getApplicationInfo.dataDir + "/redsocks-nat.conf"))(p => {
p.println(conf)
})
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
redsocksProcess = new GuardedProcess(cmd.split(" ").toSeq).start()
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
redsocksProcess = new GuardedProcess(cmd).start()
}
/** Called when the activity is first created. */
def handleConnection {
def handleConnection() {
startDNSTunnel()
startRedsocksDaemon()
@@ -302,9 +307,11 @@ class ShadowsocksNatService extends BaseService {
override def startRunner(profile: Profile) = if (su == null) {
su = new Shell.Builder().useSU().setWantSTDERR(true).setWatchdogTimeout(10).open((_, exitCode, _) =>
if (exitCode == 0) super.startRunner(profile) else {
Log.wtf(TAG, "libsuperuser#55 has been fixed. Please remove the redundant code.")
su.close()
su = null
if (su != null) {
Log.wtf(TAG, "libsuperuser#55 has been fixed. Please remove the redundant code.")
su.close()
su = null
}
super.stopRunner(true, getString(R.string.nat_no_root))
})
su.waitForIdle()
@@ -318,31 +325,19 @@ class ShadowsocksNatService extends BaseService {
override def connect() {
super.connect()
if (profile != null) {
// Clean up
killProcesses()
// Clean up
killProcesses()
var resolved = false
if (!Utils.isNumeric(profile.host)) {
Utils.resolve(profile.host, enableIPv6 = true) match {
case Some(a) =>
profile.host = a
resolved = true
case None => resolved = false
}
} else {
resolved = true
}
if (!resolved) stopRunner(true, getString(R.string.invalid_server)) else {
handleConnection
// Set DNS
su.addCommand(Utils.FLUSH_DNS)
changeState(State.CONNECTED)
notification = new ShadowsocksNotification(this, profile.name, true)
}
if (!Utils.isNumeric(profile.host)) Utils.resolve(profile.host, enableIPv6 = true) match {
case Some(a) => profile.host = a
case None => throw NameNotResolvedException()
}
handleConnection()
// Set DNS
su.addCommand(Utils.FLUSH_DNS)
changeState(State.CONNECTED)
notification = new ShadowsocksNotification(this, profile.name, true)
}
override def stopRunner(stopService: Boolean, msg: String = null) {
@@ -49,7 +49,6 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
case _ =>
}
private lazy val style = new BigTextStyle(builder)
private val showOnUnlock = visible && Utils.isLollipopOrAbove
private var isVisible = true
update(if (service.getSystemService(Context.POWER_SERVICE).asInstanceOf[PowerManager].isScreenOn)
Intent.ACTION_SCREEN_ON else Intent.ACTION_SCREEN_OFF, true)
@@ -57,19 +56,19 @@ class ShadowsocksNotification(private val service: BaseService, profileName: Str
val screenFilter = new IntentFilter()
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
if (showOnUnlock) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
if (visible && Utils.isLollipopOrAbove) screenFilter.addAction(Intent.ACTION_USER_PRESENT)
service.registerReceiver(lockReceiver, screenFilter)
private def update(action: String, forceShow: Boolean = false) =
if (forceShow || service.getState == State.CONNECTED) action match {
case Intent.ACTION_SCREEN_OFF =>
setVisible(false, forceShow)
setVisible(visible && !Utils.isLollipopOrAbove, forceShow)
unregisterCallback // unregister callback to save battery
case Intent.ACTION_SCREEN_ON =>
setVisible(showOnUnlock && !keyGuard.inKeyguardRestrictedInputMode, forceShow)
setVisible(visible && Utils.isLollipopOrAbove && !keyGuard.inKeyguardRestrictedInputMode, forceShow)
service.binder.registerCallback(callback)
callbackRegistered = true
case Intent.ACTION_USER_PRESENT => setVisible(showOnUnlock, forceShow)
case Intent.ACTION_USER_PRESENT => setVisible(true, forceShow)
}
private def unregisterCallback = if (callbackRegistered) {
@@ -68,7 +68,7 @@ class ShadowsocksQuickSwitchActivity extends AppCompatActivity {
profilesList.setItemAnimator(new DefaultItemAnimator)
profilesList.setAdapter(profilesAdapter)
if (app.profileId >= 0) lm.scrollToPosition(profilesAdapter.profiles.zipWithIndex.collectFirst {
case (profile, i) if profile.id == app.profileId => i + 1
case (profile, i) if profile.id == app.profileId => i
}.getOrElse(0))
}
}
@@ -5,14 +5,15 @@ import java.util.Locale
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.content.{Intent, SharedPreferences}
import android.net.Uri
import android.os.{Build, Bundle}
import android.os.Bundle
import android.preference.{Preference, PreferenceFragment, SwitchPreference}
import android.support.design.widget.Snackbar
import android.support.v7.app.AlertDialog
import android.webkit.{WebView, WebViewClient}
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.preferences._
import com.github.shadowsocks.utils.{Key, Utils}
import com.github.shadowsocks.utils.{Key, TcpFastOpen, Utils}
object ShadowsocksSettings {
// Constants
@@ -36,10 +37,8 @@ object ShadowsocksSettings {
}
def updateSummaryEditTextPreference(pref: Preference, value: String) {
if (value != null) {
pref.setSummary(value)
pref.asInstanceOf[SummaryEditTextPreference].setText(value)
}
pref.setSummary(value)
pref.asInstanceOf[SummaryEditTextPreference].setText(value)
}
def updateSwitchPreference(pref: Preference, value: Boolean) {
@@ -156,15 +155,27 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
}
switch.setChecked(BootReceiver.getEnabled(activity))
val tfo = findPreference(Key.tfo).asInstanceOf[SwitchPreference]
tfo.setChecked(TcpFastOpen.sendEnabled)
tfo.setOnPreferenceChangeListener((_, v) => {
val value = v.asInstanceOf[Boolean]
val result = TcpFastOpen.enabled(value)
if (result != null && result != "Success.")
Snackbar.make(activity.findViewById(android.R.id.content), result, Snackbar.LENGTH_LONG).show()
value == TcpFastOpen.sendEnabled
})
if (!TcpFastOpen.supported) {
tfo.setEnabled(false)
tfo.setSummary(getString(R.string.tcp_fastopen_summary_unsupported, java.lang.System.getProperty("os.version")))
}
findPreference("recovery").setOnPreferenceClickListener((preference: Preference) => {
app.track(TAG, "reset")
activity.recovery()
true
})
val flush = findPreference("flush_dnscache")
if (Build.VERSION.SDK_INT < 17) flush.setSummary(R.string.flush_dnscache_summary)
flush.setOnPreferenceClickListener(_ => {
findPreference("flush_dnscache").setOnPreferenceClickListener(_ => {
app.track(TAG, "flush_dnscache")
activity.flushDnsCache()
true
@@ -186,7 +197,7 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
})
new AlertDialog.Builder(activity)
.setTitle(getString(R.string.about_title).formatLocal(Locale.ENGLISH, app.getVersionName))
.setTitle(getString(R.string.about_title).formatLocal(Locale.ENGLISH, BuildConfig.VERSION_NAME))
.setNegativeButton(getString(android.R.string.ok), null)
.setView(web)
.create()
@@ -196,7 +207,22 @@ class ShadowsocksSettings extends PreferenceFragment with OnSharedPreferenceChan
}
def refreshProfile() {
profile = app.currentProfile.get
val profile = app.currentProfile match {
case Some(profile) => profile
case None => {
app.profileManager.getFirstProfile match {
case Some(profile) => {
app.profileId(profile.id)
profile
}
case None => {
val default = app.profileManager.createDefault()
app.profileId(default.id)
default
}
}
}
}
isProxyApps.setChecked(profile.proxyApps)
}
@@ -25,24 +25,26 @@ final class ShadowsocksTileService extends TileService with ServiceBoundContext
def trafficUpdated(txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) = ()
def stateChanged(state: Int, msg: String) {
val tile = getQsTile
state match {
case State.STOPPED =>
tile.setIcon(iconIdle)
tile.setLabel(getString(R.string.app_name))
tile.setState(Tile.STATE_INACTIVE)
case State.CONNECTED =>
tile.setIcon(iconConnected)
tile.setLabel(app.currentProfile match {
case Some(profile) => profile.name
case None => getString(R.string.app_name)
})
tile.setState(Tile.STATE_ACTIVE)
case _ =>
tile.setIcon(iconBusy)
tile.setLabel(getString(R.string.app_name))
tile.setState(Tile.STATE_UNAVAILABLE)
if (tile != null) {
state match {
case State.STOPPED =>
tile.setIcon(iconIdle)
tile.setLabel(getString(R.string.app_name))
tile.setState(Tile.STATE_INACTIVE)
case State.CONNECTED =>
tile.setIcon(iconConnected)
tile.setLabel(app.currentProfile match {
case Some(profile) => profile.name
case None => getString(R.string.app_name)
})
tile.setState(Tile.STATE_ACTIVE)
case _ =>
tile.setIcon(iconBusy)
tile.setLabel(getString(R.string.app_name))
tile.setState(Tile.STATE_UNAVAILABLE)
}
tile.updateTile
}
tile.updateTile
}
}
@@ -40,17 +40,17 @@
package com.github.shadowsocks
import java.io.File
import java.lang.Process
import java.util.Locale
import android.annotation.SuppressLint
import android.content._
import android.content.pm.PackageManager.NameNotFoundException
import android.net.VpnService
import android.os._
import android.util.Log
import com.github.shadowsocks.utils._
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.database.Profile
import com.github.shadowsocks.utils._
import scala.collection.mutable.ArrayBuffer
@@ -63,10 +63,10 @@ class ShadowsocksVpnService extends VpnService with BaseService {
var vpnThread: ShadowsocksVpnThread = _
private var notification: ShadowsocksNotification = _
var sslocalProcess: Process = _
var sstunnelProcess: Process = _
var pdnsdProcess: Process = _
var tun2socksProcess: Process = _
var sslocalProcess: GuardedProcess = _
var sstunnelProcess: GuardedProcess = _
var pdnsdProcess: GuardedProcess = _
var tun2socksProcess: GuardedProcess = _
override def onBind(intent: Intent): IBinder = {
val action = intent.getAction
@@ -148,73 +148,60 @@ class ShadowsocksVpnService extends VpnService with BaseService {
override def connect() = {
super.connect()
if (profile != null) {
vpnThread = new ShadowsocksVpnThread(this)
vpnThread.start()
vpnThread = new ShadowsocksVpnThread(this)
vpnThread.start()
// reset the context
killProcesses()
// reset the context
killProcesses()
// Resolve the server address
var resolved: Boolean = false
if (!Utils.isNumeric(profile.host)) {
Utils.resolve(profile.host, enableIPv6 = true) match {
case Some(addr) =>
profile.host = addr
resolved = true
case None => resolved = false
}
} else {
resolved = true
}
if (!resolved) stopRunner(true, getString(R.string.invalid_server)) else if (handleConnection) {
changeState(State.CONNECTED)
notification = new ShadowsocksNotification(this, profile.name)
} else {
changeState(State.STOPPED, getString(R.string.service_failed))
stopRunner(true)
}
// Resolve the server address
if (!Utils.isNumeric(profile.host)) Utils.resolve(profile.host, enableIPv6 = true) match {
case Some(addr) => profile.host = addr
case None => throw NameNotResolvedException()
}
handleConnection()
changeState(State.CONNECTED)
notification = new ShadowsocksNotification(this, profile.name)
}
/** Called when the activity is first created. */
def handleConnection: Boolean = {
def handleConnection() {
if (!profile.udpdns) {
startDnsDaemon()
startDnsTunnel()
val fd = startVpn()
if (!sendFd(fd)) throw new Exception("sendFd failed")
if (profile.kcp) {
startKcptunDaemon()
}
startShadowsocksDaemon()
if (profile.udpdns) {
if (profile.udpdns && profile.kcp) {
startShadowsocksUDPDaemon()
}
val fd = startVpn()
val ret = sendFd(fd)
if (ret && profile.kcp) {
startKcptunDaemon()
if (!profile.udpdns) {
startDnsDaemon()
startDnsTunnel()
}
ret
}
def startKcptunDaemon() {
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/kcptun"
if (profile.kcpcli == null) profile.kcpcli = ""
val cmd = ArrayBuffer(getApplicationInfo.dataDir + "/kcptun"
, "-r", profile.host + ":" + profile.kcpPort
, "-l", "127.0.0.1:" + (profile.localPort + 90)
, "--path", getApplicationInfo.dataDir + "/protect_path"
, profile.kcpcli)
, "--path", getApplicationInfo.dataDir + "/protect_path")
try cmd ++= Utils.translateCommandline(profile.kcpcli) catch {
case exc: Exception => throw KcpcliParseException(exc)
}
if (BuildConfig.DEBUG)
Log.d(TAG, cmd.mkString(" "))
kcptunProcess = new GuardedProcess(cmd.mkString(" ").split(" ").toSeq).start()
kcptunProcess = new GuardedProcess(cmd).start()
}
def startShadowsocksUDPDaemon() {
@@ -225,8 +212,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-local", "-V", "-U"
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V", "-U"
, "-b", "127.0.0.1"
, "-t", "600"
, "-P", getApplicationInfo.dataDir
@@ -240,7 +226,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
def startShadowsocksDaemon() {
if (profile.route != Route.ALL) {
if (profile.route != Route.ALL && profile.route != Route.GFWLIST) {
val acl: Array[Array[String]] = profile.route match {
case Route.BYPASS_LAN => Array(getResources.getStringArray(R.array.private_route))
case Route.BYPASS_CHN => Array(getResources.getStringArray(R.array.chn_route))
@@ -265,8 +251,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-local", "-V"
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-local", "-V"
, "-b", "127.0.0.1"
, "-t", "600"
, "-P", getApplicationInfo.dataDir
@@ -274,11 +259,18 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (profile.auth) cmd += "-A"
if (profile.udpdns && !profile.kcp) cmd += "-u"
if (profile.route != Route.ALL) {
cmd += "--acl"
cmd += (getApplicationInfo.dataDir + "/acl.list")
if (profile.route == Route.GFWLIST)
cmd += (getApplicationInfo.dataDir + "/gfwlist.acl")
else
cmd += (getApplicationInfo.dataDir + "/acl.list")
}
if (TcpFastOpen.sendEnabled) cmd += "--fast-open"
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
sslocalProcess = new GuardedProcess(cmd).start()
@@ -297,8 +289,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (getApplicationInfo.dataDir + "/ss-tunnel"
val cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/ss-tunnel"
, "-V"
, "-t", "10"
, "-b", "127.0.0.1"
@@ -315,11 +306,12 @@ class ShadowsocksVpnService extends VpnService with BaseService {
def startDnsDaemon() {
val ipv6 = if (profile.ipv6) "" else "reject = ::/0;"
val conf = {
if (profile.route == Route.BYPASS_CHN || profile.route == Route.BYPASS_LAN_CHN) {
val conf = profile.route match {
case Route.BYPASS_CHN | Route.BYPASS_LAN_CHN | Route.GFWLIST => {
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"0.0.0.0", profile.localPort + 53, getBlackList, profile.localPort + 63, ipv6)
} else {
}
case _ => {
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
"0.0.0.0", profile.localPort + 53, profile.localPort + 63, ipv6)
}
@@ -327,13 +319,14 @@ class ShadowsocksVpnService extends VpnService with BaseService {
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => {
p.println(conf)
})
val cmd = getApplicationInfo.dataDir + "/pdnsd -c " + getApplicationInfo.dataDir + "/pdnsd-vpn.conf"
val cmd = Array(getApplicationInfo.dataDir + "/pdnsd", "-c", getApplicationInfo.dataDir + "/pdnsd-vpn.conf")
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
pdnsdProcess = new GuardedProcess(cmd.split(" ").toSeq).start()
pdnsdProcess = new GuardedProcess(cmd).start()
}
@SuppressLint(Array("NewApi"))
def startVpn(): Int = {
val builder = new Builder()
@@ -360,7 +353,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
} catch {
case ex: NameNotFoundException =>
Log.e(TAG, "Invalid package name", ex);
Log.e(TAG, "Invalid package name", ex)
}
}
}
@@ -382,45 +375,36 @@ class ShadowsocksVpnService extends VpnService with BaseService {
conn = builder.establish()
if (conn == null) changeState(State.STOPPED, getString(R.string.reboot_required))
} catch {
case ex: IllegalStateException =>
changeState(State.STOPPED, ex.getMessage)
conn = null
case ex: Exception =>
ex.printStackTrace()
conn = null
}
if (conn == null) {
stopRunner(true)
return -1
app.track(ex)
stopRunner(true, ex.getMessage)
return -1
}
val fd = conn.getFd
var cmd = (getApplicationInfo.dataDir +
"/tun2socks --netif-ipaddr %s "
+ "--netif-netmask 255.255.255.0 "
+ "--socks-server-addr 127.0.0.1:%d "
+ "--tunfd %d "
+ "--tunmtu %d "
+ "--sock-path %s "
+ "--loglevel 3")
.formatLocal(Locale.ENGLISH,
PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"),
profile.localPort, fd, VPN_MTU, getApplicationInfo.dataDir + "/sock_path")
var cmd = ArrayBuffer[String](getApplicationInfo.dataDir + "/tun2socks",
"--netif-ipaddr", PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"),
"--netif-netmask", "255.255.255.0",
"--socks-server-addr", "127.0.0.1:" + profile.localPort,
"--tunfd", fd.toString,
"--tunmtu", VPN_MTU.toString,
"--sock-path", getApplicationInfo.dataDir + "/sock_path",
"--loglevel", "3")
if (profile.ipv6)
cmd += " --netif-ip6addr " + PRIVATE_VLAN6.formatLocal(Locale.ENGLISH, "2")
cmd += ("--netif-ip6addr", PRIVATE_VLAN6.formatLocal(Locale.ENGLISH, "2"))
if (profile.udpdns)
cmd += " --enable-udprelay"
cmd += "--enable-udprelay"
else
cmd += " --dnsgw %s:%d".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"),
profile.localPort + 53)
cmd += ("--dnsgw", "%s:%d".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"),
profile.localPort + 53))
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
tun2socksProcess = new GuardedProcess(cmd.split(" ").toSeq).start(() => sendFd(fd))
tun2socksProcess = new GuardedProcess(cmd).start(() => sendFd(fd))
fd
}
@@ -44,6 +44,7 @@ import java.util.concurrent.Executors
import android.net.{LocalServerSocket, LocalSocket, LocalSocketAddress}
import android.util.Log
import com.github.shadowsocks.ShadowsocksApplication.app
object ShadowsocksVpnThread {
val getInt = classOf[FileDescriptor].getDeclaredMethod("getInt$")
@@ -56,7 +57,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
lazy val PATH = vpnService.getApplicationInfo.dataDir + "/protect_path"
@volatile var isRunning: Boolean = true
@volatile var serverSocket: LocalServerSocket = null
@volatile var serverSocket: LocalServerSocket = _
def closeServerSocket() {
if (serverSocket != null) {
@@ -76,11 +77,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
override def run() {
try {
new File(PATH).delete()
} catch {
case _: Exception => // ignore
}
new File(PATH).delete()
try {
val localSocket = new LocalSocket
@@ -89,6 +86,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
} catch {
case e: IOException =>
Log.e(TAG, "unable to bind", e)
app.track(e)
return
}
@@ -127,6 +125,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
} catch {
case e: Exception =>
Log.e(TAG, "Error when protect socket", e)
app.track(e)
}
// close socket
@@ -140,6 +139,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
} catch {
case e: IOException =>
Log.e(TAG, "Error when accept socket", e)
app.track(e)
return
}
}
@@ -64,7 +64,7 @@ object DBHelper {
}
class DBHelper(val context: Context)
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 18) {
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 20) {
import DBHelper._
lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile])
@@ -83,10 +83,11 @@ class DBHelper(val context: Context)
}
if (oldVersion < 8) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
}
if (oldVersion < 9) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN route VARCHAR DEFAULT 'all';")
} else if (oldVersion < 19) {
profileDao.executeRawNoArgs("UPDATE `profile` SET route = 'all' WHERE route IS NULL;")
}
if (oldVersion < 10) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN auth SMALLINT;")
@@ -128,11 +129,17 @@ class DBHelper(val context: Context)
if (oldVersion < 17) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcp SMALLINT;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcpcli VARCHAR;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcpcli VARCHAR DEFAULT " +
"'--crypt none --mode normal --mtu 1200 --nocomp --dscp 46 --parityshard 0';")
} else if (oldVersion < 20) {
profileDao.executeRawNoArgs("UPDATE `profile` SET kcpcli = '--crypt none --mode normal --mtu 1200 --nocomp " +
"--dscp 46 --parityshard 0' WHERE kcpcli IS NULL;")
}
if (oldVersion < 18) {
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcpPort INTEGER;")
profileDao.executeRawNoArgs("ALTER TABLE `profile` ADD COLUMN kcpPort INTEGER DEFAULT 8399;")
} else if (oldVersion < 19) {
profileDao.executeRawNoArgs("UPDATE `profile` SET kcpPort = 8399 WHERE kcpPort = 0;")
}
}
}
@@ -106,7 +106,7 @@ class Profile {
var kcpPort: Int = 8399
@DatabaseField
var kcpcli: String = ""
var kcpcli: String = "--crypt none --mode normal --mtu 1200 --nocomp --dscp 46 --parityshard 0"
override def toString = "ss://" + Base64.encodeToString("%s%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
method, if (auth) "-auth" else "", password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP)
@@ -53,9 +53,9 @@ class ProfileManager(dbHelper: DBHelper) {
def setProfileAddedListener(listener: Profile => Any) = this.profileAddedListener = listener
def createProfile(p: Profile = null): Profile = {
val profile = if (p == null) new Profile else p
profile.id = 0
try {
val profile = if (p == null) new Profile else p
profile.id = 0
app.currentProfile match {
case Some(oldProfile) =>
// Copy Feature Settings from old profile
@@ -72,12 +72,12 @@ class ProfileManager(dbHelper: DBHelper) {
if (last != null && last.length == 1 && last(0) != null) profile.userOrder = last(0).toInt + 1
dbHelper.profileDao.createOrUpdate(profile)
if (profileAddedListener != null) profileAddedListener(profile)
profile
} catch {
case ex: Exception =>
Log.e(TAG, "addProfile", ex)
p
app.track(ex)
}
profile
}
def updateProfile(profile: Profile): Boolean = {
@@ -87,6 +87,7 @@ class ProfileManager(dbHelper: DBHelper) {
} catch {
case ex: Exception =>
Log.e(TAG, "updateProfile", ex)
app.track(ex)
false
}
}
@@ -100,6 +101,7 @@ class ProfileManager(dbHelper: DBHelper) {
} catch {
case ex: Exception =>
Log.e(TAG, "getProfile", ex)
app.track(ex)
None
}
}
@@ -111,6 +113,7 @@ class ProfileManager(dbHelper: DBHelper) {
} catch {
case ex: Exception =>
Log.e(TAG, "delProfile", ex)
app.track(ex)
false
}
}
@@ -122,6 +125,7 @@ class ProfileManager(dbHelper: DBHelper) {
} catch {
case ex: Exception =>
Log.e(TAG, "getAllProfiles", ex)
app.track(ex)
None
}
}
@@ -133,6 +137,7 @@ class ProfileManager(dbHelper: DBHelper) {
} catch {
case ex: Exception =>
Log.e(TAG, "getAllProfiles", ex)
app.track(ex)
None
}
}
@@ -0,0 +1,33 @@
package com.github.shadowsocks.preferences
import android.app.AlertDialog
import android.content.{Context, DialogInterface}
import android.util.AttributeSet
import eu.chainfire.libsuperuser.Shell
import scala.collection.JavaConversions._
/**
* @author Mygod
*/
class KcpCliPreference(context: Context, attrs: AttributeSet) extends SummaryEditTextPreference(context, attrs) {
override def onPrepareDialogBuilder(builder: AlertDialog.Builder) {
super.onPrepareDialogBuilder(builder)
builder.setNeutralButton("?", ((_, _) => new AlertDialog.Builder(context)
.setTitle("?")
.setMessage(asScalaBuffer(Shell.SH.run(context.getApplicationInfo.dataDir + "/kcptun --help"))
.dropWhile(line => line != "GLOBAL OPTIONS:")
.drop(1)
.takeWhile(line => line.length() > 3)
.filter(line =>
!line.startsWith(" --localaddr ") &&
!line.startsWith(" --remoteaddr ") &&
!line.startsWith(" --path ") &&
!line.startsWith(" --help,") &&
!line.startsWith(" --version,"))
.mkString("\n")
.replaceAll(" {2,}", "\n")
.substring(1)) // remove 1st \n
.show()): DialogInterface.OnClickListener)
}
}
@@ -41,6 +41,7 @@ package com.github.shadowsocks.preferences
import android.content.Context
import android.preference.EditTextPreference
import android.text.TextUtils
import android.util.AttributeSet
class SummaryEditTextPreference(context: Context, attrs: AttributeSet, defStyle: Int)
@@ -57,7 +58,7 @@ class SummaryEditTextPreference(context: Context, attrs: AttributeSet, defStyle:
}
override def setSummary(summary: CharSequence) {
if (summary.toString.isEmpty) {
if (TextUtils.isEmpty(summary)) {
super.setSummary(mDefaultSummary)
} else {
super.setSummary(summary)
@@ -4,14 +4,11 @@ package com.github.shadowsocks.utils
* @author Mygod
*/
object CloseUtils {
type Closeable = {
def close()
}
type Disconnectable = {
def disconnect()
}
def autoClose[A <: Closeable, B](x: => A)(block: A => B): B = {
def autoClose[A <: AutoCloseable, B](x: => A)(block: A => B): B = {
var a: Option[A] = None
try {
a = Some(x)
@@ -171,6 +171,8 @@ object Key {
val kcp = "kcp"
val kcpPort = "kcpPort"
val kcpcli = "kcpcli"
val tfo = "tcp_fastopen"
}
object State {
@@ -192,4 +194,5 @@ object Route {
val BYPASS_LAN = "bypass-lan"
val BYPASS_CHN = "bypass-china"
val BYPASS_LAN_CHN = "bypass-lan-china"
val GFWLIST = "gfwlist"
}
@@ -0,0 +1,40 @@
package com.github.shadowsocks.utils
import java.io.File
import eu.chainfire.libsuperuser.Shell
import scala.collection.JavaConverters._
/**
* @author Mygod
*/
object TcpFastOpen {
/**
* Is kernel version >= 3.7.1.
*/
lazy val supported = "^(\\d+)\\.(\\d+)\\.(\\d+)".r.findFirstMatchIn(System.getProperty("os.version")) match {
case Some(m) =>
val kernel = m.group(1).toInt
if (kernel < 3) false else if (kernel > 3) true else {
val major = m.group(2).toInt
if (major < 7) false else if (major > 7) true else m.group(3).toInt >= 1
}
case _ => false
}
def sendEnabled = {
val file = new File("/proc/sys/net/ipv4/tcp_fastopen")
file.canRead && (Utils.readAllLines(file).toInt & 1) > 0
}
def enabled(value: Boolean): String = if (sendEnabled != value) {
val res = Shell.run("su", Array(
"if echo " + (if (value) 3 else 0) + " > /proc/sys/net/ipv4/tcp_fastopen; then",
" echo Success.",
"else",
" echo Failed.",
"fi"), null, true)
if (res != null) res.asScala.mkString("\n") else null
} else null
}
@@ -46,13 +46,14 @@ import java.util.concurrent.Executors
import android.content.Context
import android.net.{LocalServerSocket, LocalSocket, LocalSocketAddress}
import android.util.Log
import com.github.shadowsocks.ShadowsocksApplication.app
class TrafficMonitorThread(context: Context) extends Thread {
val TAG = "TrafficMonitorThread"
lazy val PATH = context.getApplicationInfo.dataDir + "/stat_path"
@volatile var serverSocket: LocalServerSocket = null
@volatile var serverSocket: LocalServerSocket = _
@volatile var isRunning: Boolean = true
def closeServerSocket() {
@@ -73,11 +74,7 @@ class TrafficMonitorThread(context: Context) extends Thread {
override def run() {
try {
new File(PATH).delete()
} catch {
case _: Exception => // ignore
}
new File(PATH).delete()
try {
val localSocket = new LocalSocket
@@ -113,6 +110,7 @@ class TrafficMonitorThread(context: Context) extends Thread {
} catch {
case e: Exception =>
Log.e(TAG, "Error when recv traffic stat", e)
app.track(e)
}
// close socket
@@ -126,6 +124,7 @@ class TrafficMonitorThread(context: Context) extends Thread {
} catch {
case e: IOException =>
Log.e(TAG, "Error when accept socket", e)
app.track(e)
return
}
}
@@ -38,15 +38,16 @@
*/
package com.github.shadowsocks.utils
import java.io.File
import java.net._
import java.security.MessageDigest
import java.util.{Scanner, StringTokenizer}
import android.animation.{Animator, AnimatorListenerAdapter}
import android.content.pm.PackageManager
import android.content.{Context, Intent}
import android.graphics._
import android.os.Build
import android.provider.Settings
import android.util.{Base64, DisplayMetrics, Log}
import android.view.View.MeasureSpec
import android.view.{Gravity, View, Window}
@@ -56,6 +57,8 @@ import com.github.shadowsocks.{BuildConfig, ShadowsocksRunnerService}
import eu.chainfire.libsuperuser.Shell
import org.xbill.DNS._
import scala.collection.JavaConversions._
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.{Failure, Try}
@@ -109,6 +112,13 @@ object Utils {
})
}
def readAllLines(f: File) = {
val scanner = new Scanner(f)
try {
scanner.useDelimiter("\\Z")
scanner.next()
} finally scanner.close()
}
def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) {
val p = new java.io.PrintWriter(f)
try {
@@ -118,6 +128,48 @@ object Utils {
}
}
/**
* Crack a command line.
* Based on: https://github.com/apache/ant/blob/588ce1f/src/main/org/apache/tools/ant/types/Commandline.java#L471
* @param toProcess the command line to process.
* @return the command line broken into strings.
* An empty or null toProcess parameter results in a zero sized ArrayBuffer.
*/
def translateCommandline(toProcess: String): ArrayBuffer[String] = {
if (toProcess == null || toProcess.length == 0) return ArrayBuffer[String]()
val tok = new StringTokenizer(toProcess, "\"' ", true)
val result = ArrayBuffer[String]()
val current = new StringBuilder()
var quote = ' '
var last = " "
while (tok.hasMoreTokens) {
val nextTok = tok.nextToken
quote match {
case '\'' => nextTok match {
case "'" => quote = ' '
case _ => current.append(nextTok)
}
case '"' => nextTok match {
case "\"" => quote = ' '
case _ => current.append(nextTok)
}
case _ => nextTok match {
case "'" => quote = '\''
case "\"" => quote = '"'
case " " => if (last != " ") {
result.append(current.toString)
current.setLength(0)
}
case _ => current.append(nextTok)
}
}
last = nextTok
}
if (current.nonEmpty) result.append(current.toString)
if (quote == '\'' || quote == '"') throw new Exception("Unbalanced quotes in " + toProcess)
result
}
// Because /sys/class/net/* isn't accessible since API level 24
final val FLUSH_DNS = "for if in /sys/class/net/*; do " +
"if [ \"down\" != $(cat $if/operstate) ]; then " + // up or unknown
@@ -128,25 +180,7 @@ object Utils {
// Blocked > 3 seconds
def toggleAirplaneMode(context: Context) = {
val result = Shell.SU.run(FLUSH_DNS)
if (result != null && !result.isEmpty) true else if (Build.VERSION.SDK_INT < 17) {
toggleBelowApiLevel17(context)
true
} else false
}
//noinspection ScalaDeprecation
private def toggleBelowApiLevel17(context: Context) {
// Android 4.2 below
Settings.System.putInt(context.getContentResolver, Settings.System.AIRPLANE_MODE_ON, 1)
val enableIntent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
enableIntent.putExtra("state", true)
context.sendBroadcast(enableIntent)
Thread.sleep(3000)
Settings.System.putInt(context.getContentResolver, Settings.System.AIRPLANE_MODE_ON, 0)
val disableIntent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED)
disableIntent.putExtra("state", false)
context.sendBroadcast(disableIntent)
result != null && !result.isEmpty
}
def resolve(host: String, addrType: Int): Option[String] = {
@@ -210,29 +244,22 @@ object Utils {
*/
def isIPv6Support: Boolean = {
try {
val interfaces = NetworkInterface.getNetworkInterfaces
while (interfaces.hasMoreElements) {
val intf = interfaces.nextElement()
val addrs = intf.getInetAddresses
while (addrs.hasMoreElements) {
val addr = addrs.nextElement()
if (!addr.isLoopbackAddress && !addr.isLinkLocalAddress) {
if (addr.isInstanceOf[Inet6Address]) {
if (BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected")
return true
}
for (intf <- enumerationAsScalaIterator(NetworkInterface.getNetworkInterfaces))
for (addr <- enumerationAsScalaIterator(intf.getInetAddresses))
if (addr.isInstanceOf[Inet6Address] && !addr.isLoopbackAddress && !addr.isLinkLocalAddress) {
if (BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected")
return true
}
}
}
} catch {
case ex: Exception =>
Log.e(TAG, "Failed to get interfaces' addresses.", ex)
app.track(ex)
}
false
}
def startSsService(context: Context) {
val isInstalled: Boolean = app.settings.getBoolean(app.getVersionName, false)
val isInstalled: Boolean = app.settings.getBoolean(BuildConfig.VERSION_NAME, false)
if (!isInstalled) return
val intent = new Intent(context, classOf[ShadowsocksRunnerService])
@@ -245,7 +272,9 @@ object Utils {
}
private val handleFailure: Try[_] => Unit = {
case Failure(e) => e.printStackTrace()
case Failure(e) =>
e.printStackTrace()
app.track(e)
case _ =>
}
-34
View File
@@ -1,34 +0,0 @@
#!/bin/bash
export ARCH=`uname -m`
export GOROOT_BOOTSTRAP=$HOME/.android/go
export ANDROID_NDK_HOME=$HOME/.android/android-ndk-r12b
export ANDROID_HOME=$HOME/.android/android-sdk-linux
export PATH=${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}
if [ ! -d "$ANDROID_HOME" ]; then
mkdir -p $ANDROID_HOME
pushd $HOME/.android
wget -q http://dl.google.com/android/android-sdk_r24.4.1-linux.tgz
tar xf android-sdk_r24.4.1-linux.tgz
popd
fi
if [ ! -d "$ANDROID_NDK_HOME" ]; then
mkdir -p $ANDROID_NDK_HOME
pushd $HOME/.android
wget -q http://dl.google.com/android/repository/android-ndk-r12b-linux-${ARCH}.zip
unzip -q android-ndk-r12b-linux-${ARCH}.zip
popd
fi
if [ ! -d "$GOROOT_BOOTSTRAP" ]; then
mkdir -p $GOROOT_BOOTSTRAP
pushd $HOME/.android
wget https://storage.googleapis.com/golang/go1.6.3.linux-amd64.tar.gz
tar xf go1.6.3.linux-amd64.tar.gz
popd
fi
( sleep 5 && while [ 1 ]; do sleep 1; echo y; done ) | android update sdk --filter tools,platform-tools,build-tools-24.0.0,android-23,android-24,extra-google-m2repository --no-ui -a
( sleep 5 && while [ 1 ]; do sleep 1; echo y; done ) | android update sdk --filter extra-android-m2repository --no-ui -a
BIN
View File
Binary file not shown.