Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
faad961804 | ||
|
|
2f7424d07b | ||
|
|
fd4015fac2 | ||
|
|
f2c39bd16e | ||
|
|
e849a9e2cb | ||
|
|
524d3b6fdc | ||
|
|
6f5db34a6f | ||
|
|
3c161be1e4 | ||
|
|
1c30fdb8f2 | ||
|
|
ce24ddb9ed | ||
|
|
17eaf25b4f | ||
|
|
f4b171a3d9 | ||
|
|
ae9622a1b3 | ||
|
|
44e1b9daa3 | ||
|
|
7a2c42626b | ||
|
|
adb979a111 | ||
|
|
1e23307f95 | ||
|
|
64e6f14da1 | ||
|
|
3dd718dc01 | ||
|
|
942d181e36 | ||
|
|
fa083a8eca | ||
|
|
ef2ff23cd0 | ||
|
|
c1e208737c | ||
|
|
75bb00593a | ||
|
|
15f25b95a0 | ||
|
|
cc9fa4c4a6 | ||
|
|
9041404f42 | ||
|
|
5aae822cdd | ||
|
|
33ed5c65c5 | ||
|
|
1424e056ac | ||
|
|
ed79e0090e | ||
|
|
304113ce97 | ||
|
|
290bf8cb31 | ||
|
|
fcb0e2ace3 | ||
|
|
f240d5d202 | ||
|
|
ea85bbd83d | ||
|
|
d3018fc090 | ||
|
|
f1f585b4d9 | ||
|
|
3653f73e0b | ||
|
|
d648910aac | ||
|
|
1e2f8c3bd3 | ||
|
|
b94c16c725 | ||
|
|
a03a6af5ba | ||
|
|
b9414c6b0a | ||
|
|
0d54d9cd9b | ||
|
|
8611a66cdc | ||
|
|
740dcc3ca9 | ||
|
|
730efbafc0 | ||
|
|
8b05476823 | ||
|
|
50b890423a | ||
|
|
fb63268895 | ||
|
|
41934f8909 | ||
|
|
bedc7a0443 | ||
|
|
537f790386 | ||
|
|
62afcf51d7 | ||
|
|
6c1ae68931 | ||
|
|
2703e91bbe | ||
|
|
8fba319db2 | ||
|
|
3e04734b9b | ||
|
|
fe33997494 | ||
|
|
86cd49d3e1 | ||
|
|
ff13792192 | ||
|
|
f36a8c784d | ||
|
|
57f8c0f307 | ||
|
|
601c227644 | ||
|
|
220143aee1 | ||
|
|
81a19c4a81 | ||
|
|
27cc53baf8 | ||
|
|
935fddcb15 | ||
|
|
49458080a1 | ||
|
|
8101fc935e | ||
|
|
491ebe500f | ||
|
|
98ce68774a | ||
|
|
b0e20552dd | ||
|
|
0d478cfbc4 | ||
|
|
d1d135ccdd | ||
|
|
a28303ee76 | ||
|
|
2b09ebcd2c | ||
|
|
59ede2586a | ||
|
|
abd1d0220c | ||
|
|
5427e00012 | ||
|
|
7f226d3f0c | ||
|
|
ee3f3c2338 | ||
|
|
6ac90abbf7 | ||
|
|
2f553b156a | ||
|
|
dec098fbc5 | ||
|
|
000d03ad4c | ||
|
|
667619f701 | ||
|
|
afd91b7155 | ||
|
|
e10272c8e5 |
+3
-3
@@ -1,3 +1,3 @@
|
||||
[submodule "src/main/jni/shadowsocks"]
|
||||
path = src/main/jni/shadowsocks
|
||||
url = https://github.com/madeye/shadowsocks-libev
|
||||
[submodule "src/main/jni/shadowsocks-libev"]
|
||||
path = src/main/jni/shadowsocks-libev
|
||||
url = https://github.com/shadowsocks/shadowsocks-libev
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
language: scala
|
||||
scala:
|
||||
- 2.10.4
|
||||
before_install:
|
||||
- sudo apt-get update
|
||||
install:
|
||||
- sudo apt-get install -y libc6-dev-i386 lib32ncurses5-dev libx11-dev g++-multilib lib32z1-dev ccache
|
||||
- export NDK_CCACHE=ccache
|
||||
- export ARCH=`uname -m`
|
||||
- wget http://dl.google.com/android/android-sdk_r23.0.2-linux.tgz
|
||||
- tar xf android-sdk_r23.0.2-linux.tgz
|
||||
- wget http://dl.google.com/android/ndk/android-ndk-r9d-linux-${ARCH}.tar.bz2
|
||||
- tar xf android-ndk-r9d-linux-${ARCH}.tar.bz2
|
||||
- export ANDROID_NDK_HOME=`pwd`/android-ndk-r9d
|
||||
- export ANDROID_HOME=`pwd`/android-sdk-linux
|
||||
- export PATH=${PATH}:${ANDROID_NDK_HOME}:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools
|
||||
- echo "y" | android update sdk --filter tools,platform-tools,build-tools-21.0.1,android-21,extra-google-m2repository --no-ui --no-https -a
|
||||
- echo "y" | android update sdk --filter extra-android-m2repository --no-ui --no-https -a
|
||||
script:
|
||||
- cp local.properties.travis local.properties
|
||||
- ./build.sh
|
||||
- sbt android:package-release
|
||||
- exit 0
|
||||
@@ -6,16 +6,16 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
|
||||
|
||||
[](https://play.google.com/store/apps/details?id=com.github.shadowsocks)
|
||||
|
||||
### TRAVIS CI STATUS
|
||||
### CI STATUS
|
||||
|
||||
[](http://travis-ci.org/shadowsocks/shadowsocks-android)
|
||||
[](https://drone.io/github.com/shadowsocks/shadowsocks-android/latest)
|
||||
|
||||
### PREREQUISITES
|
||||
|
||||
* JDK 1.6+
|
||||
* SBT 0.12.3
|
||||
* Android SDK r21+
|
||||
* Android NDK r9+
|
||||
* JDK 1.7+
|
||||
* SBT 0.13.0+
|
||||
* Android SDK r24+
|
||||
* Android NDK r10d+
|
||||
|
||||
### BUILD
|
||||
|
||||
@@ -40,6 +40,7 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
|
||||
|
||||
* Install Android SDK and NDK by run `brew install android-ndk android-sdk`
|
||||
* Add `export ANDROID_HOME=/usr/local/Cellar/android-sdk/$version` to your .bashrc , then reopen the shell to load it.
|
||||
* Add `export ANDROID_NDK_HOME=/usr/local/Cellar/android-ndk/$version` to your .bashrc , then reopen the shell to load it.
|
||||
* echo "y" | android update sdk --filter tools,platform-tools,build-tools-21.0.1,android-21,extra-google-m2repository --no-ui --no-https -a
|
||||
* echo "y" | android update sdk --filter extra-android-m2repository --no-ui --no-https -a
|
||||
* Create your key following the instructions at http://developer.android.com/guide/publishing/app-signing.html#cert
|
||||
@@ -57,6 +58,16 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
|
||||
sbt clean android:package-release
|
||||
```
|
||||
|
||||
## OPEN SOURCE LICENSES
|
||||
|
||||
* shadowsocks-libev: [GPLv3](https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE)
|
||||
* tun2socks: [BSD](https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/badvpn/COPYING)
|
||||
* redsocks: [APL 2.0](https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/redsocks/README)
|
||||
* OpenSSL: [OpenSSL](https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/openssl/NOTICE)
|
||||
* 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/shadowsocks-android/blob/master/src/main/jni/libevent/LICENSE)
|
||||
|
||||
### LICENSE
|
||||
|
||||
Copyright (C) 2014 Max Lv <max.c.lv@gmail.com>
|
||||
|
||||
@@ -14,25 +14,30 @@ ndkJavah in Android := List()
|
||||
|
||||
ndkBuild in Android := List()
|
||||
|
||||
typedResources in Android := false
|
||||
|
||||
resolvers += Resolver.jcenterRepo
|
||||
|
||||
resolvers += "JRAF" at "http://JRAF.org/static/maven/2"
|
||||
|
||||
resolvers += "madeye private releases" at "http://madeye-maven-repository.googlecode.com/git/"
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"dnsjava" % "dnsjava" % "2.1.5",
|
||||
"dnsjava" % "dnsjava" % "2.1.7",
|
||||
"com.github.kevinsawicki" % "http-request" % "5.6",
|
||||
"commons-net" % "commons-net" % "3.3",
|
||||
"com.google.zxing" % "android-integration" % "3.1.0"
|
||||
)
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"com.joanzapata.android" % "android-iconify" % "1.0.9",
|
||||
"net.glxn.qrgen" % "android" % "2.0",
|
||||
"net.simonvt.menudrawer" % "menudrawer" % "3.0.6",
|
||||
"com.google.android.gms" % "play-services" % "6.1.71",
|
||||
"com.google.android.gms" % "play-services-base" % "6.5.87",
|
||||
"com.google.android.gms" % "play-services-ads" % "6.5.87",
|
||||
"com.android.support" % "support-v4" % "21.0.3"
|
||||
)
|
||||
|
||||
libraryDependencies ++= Seq(
|
||||
"de.keyboardsurfer.android.widget" % "crouton" % "1.8.4" exclude("com.google.android", "support-v4"),
|
||||
"com.github.mrengineer13" % "snackbar" % "0.5.0",
|
||||
"com.nostra13.universalimageloader" % "universal-image-loader" % "1.8.4",
|
||||
"com.j256.ormlite" % "ormlite-core" % "4.47",
|
||||
"com.j256.ormlite" % "ormlite-android" % "4.47"
|
||||
@@ -45,6 +50,7 @@ proguardOptions in Android ++= Seq("-keep class android.support.v4.app.** { *; }
|
||||
"-keep class org.jraf.android.backport.** { *; }",
|
||||
"-keep class com.github.shadowsocks.** { *; }",
|
||||
"-keep class * extends com.j256.ormlite.** { *; }",
|
||||
"-keep class com.joanzapata.** { *; }",
|
||||
"-keepattributes *Annotation*",
|
||||
"-dontwarn org.xbill.**",
|
||||
"-dontwarn com.actionbarsherlock.**")
|
||||
|
||||
@@ -8,7 +8,7 @@ try pushd src/main
|
||||
|
||||
# Build
|
||||
try $ANDROID_NDK_HOME/ndk-build clean
|
||||
try $ANDROID_NDK_HOME/ndk-build
|
||||
try $ANDROID_NDK_HOME/ndk-build -j8
|
||||
|
||||
# copy executables
|
||||
rm -rf assets/armeabi-v7a
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
-4488
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
sbt.version=0.13.5
|
||||
sbt.version=0.13.8
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
resolvers += Resolver.url("scalasbt releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-snapshots"))(Resolver.ivyStylePatterns)
|
||||
|
||||
addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.3.10")
|
||||
addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.4.6")
|
||||
|
||||
resolvers += Resolver.sbtPluginRepo("snapshots")
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.shadowsocks"
|
||||
android:versionCode="93"
|
||||
android:versionName="2.5.4">
|
||||
android:versionCode="108"
|
||||
android:versionName="2.7.0">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
@@ -65,7 +65,8 @@
|
||||
<activity
|
||||
android:name=".AppManager"
|
||||
android:theme="@style/Theme.AppManager"
|
||||
android:label="@string/app_name">
|
||||
android:label="@string/app_name"
|
||||
android:parentActivityName=".Shadowsocks">
|
||||
<intent-filter>
|
||||
<action android:name="com.github.shadowsocks.AppManager"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
||||
@@ -286,6 +286,17 @@ GNU General Public License for more details.</p>
|
||||
<p>You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>.</p>
|
||||
|
||||
<h3>Open Source Licenses</h3>
|
||||
<ul>
|
||||
<li>shadowsocks-libev: <a href="https://github.com/shadowsocks/shadowsocks-libev/blob/master/LICENSE">GPLv3</a></li>
|
||||
<li>tun2socks: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/badvpn/COPYING">BSD</a></li>
|
||||
<li>redsocks: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/redsocks/README">APL 2.0</a></li>
|
||||
<li>OpenSSL: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/openssl/NOTICE">OpenSSL</a></li>
|
||||
<li>pdnsd: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/pdnsd/COPYING">GPLv3</a></li>
|
||||
<li>libev: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/libev/LICENSE">GPLv2</a></li>
|
||||
<li>libevent: <a href="https://github.com/shadowsocks/shadowsocks-android/blob/master/src/main/jni/libevent/LICENSE">BSD</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
<!-- This document was created with MarkdownPad, the Markdown editor for Windows (http://markdownpad.com) -->
|
||||
|
||||
@@ -45,4 +45,5 @@ public class System {
|
||||
|
||||
public static native void exec(String cmd);
|
||||
public static native String getABI();
|
||||
public static native int sendfd(int fd);
|
||||
}
|
||||
|
||||
+66
-25
@@ -61,8 +61,8 @@ SODIUM_SOURCE := $(crypto_aead_src) $(crypto_auth_src) $(crypto_box_src) \
|
||||
$(crypto_stream_src) $(crypto_verify_src) $(randombytes_src) $(sodium_src)
|
||||
|
||||
LOCAL_MODULE := sodium
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include/sodium \
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include/sodium \
|
||||
-DPACKAGE_NAME=\"libsodium\" -DPACKAGE_TARNAME=\"libsodium\" \
|
||||
-DPACKAGE_VERSION=\"1.0.1\" -DPACKAGE_STRING=\"libsodium\ 1.0.1\" \
|
||||
-DPACKAGE_BUGREPORT=\"https://github.com/jedisct1/libsodium/issues\" \
|
||||
@@ -79,7 +79,7 @@ LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include
|
||||
-DHAVE_WEAK_SYMBOLS=1 -DHAVE_ARC4RANDOM=1 -DHAVE_ARC4RANDOM_BUF=1 \
|
||||
-DHAVE_MLOCK=1 -DHAVE_MPROTECT=1 -DHAVE_POSIX_MEMALIGN=1
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks/libsodium/src/libsodium/,$(SODIUM_SOURCE))
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libsodium/src/libsodium/,$(SODIUM_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
@@ -110,6 +110,21 @@ LOCAL_CFLAGS := -O2 -I$(LOCAL_PATH)/libevent \
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libancillary
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
ANCILLARY_SOURCE := fd_recv.c fd_send.c
|
||||
|
||||
LOCAL_MODULE := libancillary
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/libancillary
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix libancillary/, $(ANCILLARY_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libipset
|
||||
########################################################
|
||||
@@ -126,10 +141,10 @@ set_src = set/allocation.c set/inspection.c set/ipv4_set.c set/ipv6_set.c \
|
||||
IPSET_SOURCE := general.c $(bdd_src) $(map_src) $(set_src)
|
||||
|
||||
LOCAL_MODULE := libipset
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks/libipset/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libcork/include
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks-libev/libipset/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks-libev/libcork/include
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks/libipset/,$(IPSET_SOURCE))
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libipset/,$(IPSET_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
@@ -153,10 +168,29 @@ pthreads_src := pthreads/thread.c
|
||||
CORK_SOURCE := $(cli_src) $(core_src) $(ds_src) $(posix_src) $(pthreads_src)
|
||||
|
||||
LOCAL_MODULE := libcork
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks/libcork/include \
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
|
||||
-DCORK_API=CORK_LOCAL
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks/libcork/,$(CORK_SOURCE))
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libcork/,$(CORK_SOURCE))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
########################################################
|
||||
## libudns
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
UDNS_SOURCES := udns_dn.c udns_dntosp.c udns_parse.c udns_resolver.c udns_init.c \
|
||||
udns_misc.c udns_XtoX.c \
|
||||
udns_rr_a.c udns_rr_ptr.c udns_rr_mx.c udns_rr_txt.c udns_bl.c \
|
||||
udns_rr_srv.c udns_rr_naptr.c udns_codes.c udns_jran.c
|
||||
|
||||
LOCAL_MODULE := libudns
|
||||
LOCAL_CFLAGS += -O2 -I$(LOCAL_PATH)/shadowsocks-libev/libudns \
|
||||
-DHAVE_DECL_INET_NTOP
|
||||
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/libudns/,$(UDNS_SOURCES))
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
@@ -210,48 +244,51 @@ LOCAL_CFLAGS := -Wall -O2 -I$(LOCAL_PATH)/pdnsd
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
########################################################
|
||||
## shadowsocks local library
|
||||
## shadowsocks-libev local library
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c json.c jconf.c acl.c
|
||||
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c acl.c
|
||||
|
||||
LOCAL_MODULE := ss-local
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES))
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
|
||||
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL \
|
||||
-DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H \
|
||||
-I$(LOCAL_PATH)/libev/ \
|
||||
-I$(LOCAL_PATH)/openssl/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libcork/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include/sodium \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libipset/include
|
||||
-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
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork libsodium
|
||||
LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork libudns libsodium
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
||||
########################################################
|
||||
## shadowsocks tunnel
|
||||
## shadowsocks-libev tunnel
|
||||
########################################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
SHADOWSOCKS_SOURCES := tunnel.c cache.c udprelay.c encrypt.c utils.c json.c jconf.c
|
||||
SHADOWSOCKS_SOURCES := tunnel.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c
|
||||
|
||||
LOCAL_MODULE := ss-tunnel
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks/src/, $(SHADOWSOCKS_SOURCES))
|
||||
LOCAL_SRC_FILES := $(addprefix shadowsocks-libev/src/, $(SHADOWSOCKS_SOURCES))
|
||||
LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL -DUDPRELAY_TUNNEL \
|
||||
-DUSE_CRYPTO_OPENSSL -DANDROID -DHAVE_CONFIG_H -DSSTUNNEL_JNI \
|
||||
-I$(LOCAL_PATH)/libev/ \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include \
|
||||
-I$(LOCAL_PATH)/shadowsocks/libsodium/src/libsodium/include/sodium \
|
||||
-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)/openssl/include
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libev libcrypto libsodium
|
||||
LOCAL_STATIC_LIBRARIES := libev libcrypto libsodium libcork libudns
|
||||
|
||||
LOCAL_LDLIBS := -llog
|
||||
|
||||
@@ -265,12 +302,13 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE:= system
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
system.cpp
|
||||
LOCAL_C_INCLUDES:= $(LOCAL_PATH)/libancillary
|
||||
|
||||
LOCAL_SRC_FILES:= system.cpp
|
||||
|
||||
LOCAL_LDLIBS := -ldl -llog
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := cpufeatures
|
||||
LOCAL_STATIC_LIBRARIES := cpufeatures libancillary
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
@@ -287,7 +325,10 @@ LOCAL_CFLAGS += -DBADVPN_LITTLE_ENDIAN -DBADVPN_THREAD_SAFE
|
||||
LOCAL_CFLAGS += -DNDEBUG -DANDROID
|
||||
# LOCAL_CFLAGS += -DTUN2SOCKS_JNI
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libancillary
|
||||
|
||||
LOCAL_C_INCLUDES:= \
|
||||
$(LOCAL_PATH)/libancillary \
|
||||
$(LOCAL_PATH)/badvpn/lwip/src/include/ipv4 \
|
||||
$(LOCAL_PATH)/badvpn/lwip/src/include/ipv6 \
|
||||
$(LOCAL_PATH)/badvpn/lwip/src/include \
|
||||
|
||||
@@ -71,9 +71,13 @@
|
||||
#include <generated/blog_channel_tun2socks.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
#include <ancillary.h>
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/un.h>
|
||||
#include <structure/BAVL.h>
|
||||
|
||||
BAVL connections_tree;
|
||||
typedef struct {
|
||||
BAddr local_addr;
|
||||
@@ -408,7 +412,6 @@ int main (int argc, char **argv)
|
||||
prctl(PR_SET_NAME, "com.github.shadowsocks");
|
||||
}
|
||||
|
||||
|
||||
// handle --help and --version
|
||||
if (options.help) {
|
||||
print_version();
|
||||
@@ -490,11 +493,56 @@ int main (int argc, char **argv)
|
||||
|
||||
#ifdef ANDROID
|
||||
// use supplied file descriptor
|
||||
|
||||
int sock, fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
BLog(BLOG_ERROR, "socket() failed: %s (socket sock = %d)\n", strerror(errno), sock);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
char *path = "/data/data/com.github.shadowsocks/sock_path";
|
||||
unlink(path);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, path, sizeof(addr.sun_path)-1);
|
||||
|
||||
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
BLog(BLOG_ERROR, "bind() failed: %s (sock = %d)\n", strerror(errno), sock);
|
||||
close(sock);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
if (listen(sock, 5) == -1) {
|
||||
BLog(BLOG_ERROR, "listen() failed: %s (sock = %d)\n", strerror(errno), sock);
|
||||
close(sock);
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
int sock2;
|
||||
struct sockaddr_un remote;
|
||||
int t = sizeof(remote);
|
||||
if ((sock2 = accept(sock, (struct sockaddr *)&remote, &t)) == -1) {
|
||||
BLog(BLOG_ERROR, "accept() failed: %s (sock = %d)\n", strerror(errno), sock);
|
||||
continue;
|
||||
}
|
||||
if (ancil_recv_fd(sock2, &fd)) {
|
||||
BLog(BLOG_ERROR, "ancil_recv_fd: %s (sock = %d)\n", strerror(errno), sock2);
|
||||
close(sock2);
|
||||
} else {
|
||||
close(sock2);
|
||||
BLog(BLOG_INFO, "received fd = %d", fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(sock);
|
||||
|
||||
struct BTap_init_data init_data;
|
||||
init_data.dev_type = BTAP_DEV_TUN;
|
||||
init_data.init_type = BTAP_INIT_FD;
|
||||
init_data.init.fd.fd = options.tun_fd;
|
||||
init_data.init.fd.fd = fd;
|
||||
init_data.init.fd.mtu = options.tun_mtu;
|
||||
|
||||
if (!BTap_Init2(&device, &ss, init_data, device_error_handler, NULL)) {
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
This library provide an easy interface to the black magic that can be done
|
||||
on Unix domain sockets, like passing file descriptors from one process to
|
||||
another.
|
||||
|
||||
Programs that uses this library should include the ancillary.h header file.
|
||||
Nothing else is required.
|
||||
|
||||
All functions of this library require the following header:
|
||||
|
||||
#include <ancillary.h>
|
||||
|
||||
At this time, the only ancillary data defined by the Single Unix
|
||||
Specification (v3) is file descriptors.
|
||||
|
||||
Passing file descriptors
|
||||
|
||||
int ancil_send_fd(socket, file_descriptor)
|
||||
int socket: the Unix socket
|
||||
int file_descriptor: the file descriptor
|
||||
Return value: 0 for success, -1 for failure.
|
||||
|
||||
Sends one file descriptor on a socket.
|
||||
In case of failure, errno is set; the possible values are the ones of the
|
||||
sendmsg(2) system call.
|
||||
|
||||
|
||||
int ancil_recv_fd(socket, file_descriptor)
|
||||
int socket: the Unix socket
|
||||
int *file_descriptor: pointer to the returned file descriptor
|
||||
Return value: 0 for success, -1 for failure
|
||||
|
||||
Receives one file descriptor from a socket.
|
||||
In case of success, the file descriptor is stored in the integer pointed
|
||||
to by file_descriptor.
|
||||
In case of failure, errno is set; the possible values are the ones of the
|
||||
recvmsg(2) system call.
|
||||
The behavior is undefined if the recv_fd does not match a send_fd* on the
|
||||
other side.
|
||||
|
||||
|
||||
int ancil_send_fds(socket, file_descriptors, num_file_descriptors)
|
||||
int socket: the Unix socket
|
||||
const int *file_descriptors: array of file descriptors
|
||||
unsigned num_file_descriptors: number of file descriptors
|
||||
Return value: 0 for success, -1 for failure
|
||||
|
||||
Sends several file descriptors on a socket.
|
||||
In case of failure, errno is set; the possible values are the ones of the
|
||||
sendmsg(2) system call.
|
||||
The maximum number of file descriptors that can be sent using this
|
||||
function is ANCIL_MAX_N_FDS; the behavior is undefined in case of
|
||||
overflow, probably a stack corruption.
|
||||
|
||||
|
||||
int ancil_recv_fds(socket, file_descriptors, num_file_descriptors)
|
||||
int socket: the Unix socket
|
||||
int *file_descriptors: return array of file descriptors
|
||||
unsigned num_file_descriptors: number of file descriptors
|
||||
Return value: number of received fd for success, -1 for failure
|
||||
|
||||
Receives several file descriptors from a socket, no more than
|
||||
num_file_descriptors.
|
||||
In case of success, the received file descriptors are stored in the array
|
||||
pointed to by file_descriptors.
|
||||
In case of failure, errno is set; the possible values are the ones of the
|
||||
recvmsg(2) system call.
|
||||
The maximum number of file descriptors that can be received using this
|
||||
function is ANCIL_MAX_N_FDS; the behavior is undefined in case of
|
||||
overflow, probably a stack corruption.
|
||||
The behavior is undefined if the recv_fds does not match a send_fd* on
|
||||
the other side, or if the number of received file descriptors is more than
|
||||
num_file_descriptors.
|
||||
|
||||
|
||||
int ancil_send_fds_with_buffer(socket, fds, num, buffer)
|
||||
int socket: the Unix socket
|
||||
const int *fds: array of file descriptors
|
||||
unsigned num: number of file descriptors
|
||||
void *buffer: buffer to hold the system data structures
|
||||
Return value: 0 for success, -1 for failure
|
||||
|
||||
Sends several file descriptors on a socket.
|
||||
In case of failure, errno is set; the possible values are the ones of the
|
||||
sendmsg(2) system call.
|
||||
The buffer argument must point to a memory area large enough to hold the
|
||||
system data structures, see ANCIL_FD_BUFFER.
|
||||
|
||||
|
||||
int ancil_send_fds_with_buffer(socket, fds, num, buffer)
|
||||
int socket: the Unix socket
|
||||
int *fds: return array of file descriptors
|
||||
unsigned num: number of file descriptors
|
||||
void *buffer: buffer to hold the system data structures
|
||||
Return value: number of received fd for success, -1 for failure
|
||||
|
||||
Receives several file descriptors from a socket, no more than
|
||||
num_file_descriptors.
|
||||
In case of success, the received file descriptors are stored in the array
|
||||
pointed to by file_descriptors.
|
||||
In case of failure, errno is set; the possible values are the ones of the
|
||||
recvmsg(2) system call.
|
||||
The behavior is undefined if the recv_fds does not match a send_fd* on
|
||||
the other side, or if the number of received file descriptors is more than
|
||||
num_file_descriptors.
|
||||
The buffer argument must point to a memory area large enough to hold the
|
||||
system data structures, see ANCIL_FD_BUFFER.
|
||||
|
||||
|
||||
ANCIL_MAX_N_FDS
|
||||
|
||||
Maximum number of file descriptors that can be sent with the sent_fds and
|
||||
recv_fds functions. If you have to send more at once, use the
|
||||
*_with_buffer versions. The value is enough to send "quite a few" file
|
||||
descriptors.
|
||||
|
||||
|
||||
ANCIL_FD_BUFFER(n)
|
||||
int n: number of file descriptors
|
||||
|
||||
Expands to a structure data type large enough to hold the system data
|
||||
structures for n file descriptors. So the address of a variable declared
|
||||
of type ANCIL_FD_BUFFER(n) is suitable as the buffer argument for
|
||||
*_with_buffer on n file descriptors.
|
||||
To use this macro, you need <sys/types.h> and <sys/socket.h>. Bevare: with
|
||||
Solaris, the _XPG4_2 macro must be defined before sys/socket is included.
|
||||
|
||||
|
||||
Tuning the compilation
|
||||
|
||||
This library is designed to be included in projects, not installed in
|
||||
/usr/lib. If your project does not use some of the functions, the
|
||||
TUNE_OPTS variable in the Makefile allows not to build them. It is a list
|
||||
of proprocessor options:
|
||||
|
||||
-DNDEBUG: turn assertions off (see assert(3))
|
||||
-DSPARE_SEND_FDS: do not build ancil_send_fds
|
||||
-DSPARE_SEND_FD: do not build ancil_send_fd
|
||||
-DSPARE_RECV_FDS: do not build ancil_recv_fds
|
||||
-DSPARE_RECV_FD: do not build ancil_recv_fd
|
||||
@@ -0,0 +1,21 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,73 @@
|
||||
###########################################################################
|
||||
# libancillary - black magic on Unix domain sockets
|
||||
# (C) Nicolas George
|
||||
# Makefile - guess what
|
||||
###########################################################################
|
||||
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-Wall -g -O2
|
||||
LDFLAGS=
|
||||
LIBS=
|
||||
AR=ar
|
||||
RANLIB=ranlib
|
||||
RM=rm
|
||||
CP=cp
|
||||
MKDIR=mkdir
|
||||
TAR=tar
|
||||
GZIP=gzip -9
|
||||
|
||||
NAME=libancillary
|
||||
DISTRIBUTION=API COPYING Makefile ancillary.h fd_send.c fd_recv.c test.c
|
||||
VERSION=0.9.1
|
||||
|
||||
OBJECTS=fd_send.o fd_recv.o
|
||||
|
||||
TUNE_OPTS=-DNDEBUG
|
||||
#TUNE_OPTS=-DNDEBUG \
|
||||
-DSPARE_SEND_FDS -DSPARE_SEND_FD -DSPARE_RECV_FDS -DSPARE_RECV_FD
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(CFLAGS) $(TUNE_OPTS) $<
|
||||
|
||||
all: libancillary.a
|
||||
|
||||
libancillary.a: $(OBJECTS)
|
||||
$(AR) cr $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
fd_send.o: ancillary.h
|
||||
fd_recv.o: ancillary.h
|
||||
|
||||
test: test.c libancillary.a
|
||||
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) -L. test.c -lancillary $(LIBS)
|
||||
|
||||
clean:
|
||||
-$(RM) -f *.o *.a test
|
||||
|
||||
dist:
|
||||
$(MKDIR) $(NAME)-$(VERSION)
|
||||
$(CP) $(DISTRIBUTION) $(NAME)-$(VERSION)
|
||||
$(TAR) -cf - $(NAME)-$(VERSION) | $(GZIP) > $(NAME)-$(VERSION).tar.gz
|
||||
$(RM) -rf $(NAME)-$(VERSION)
|
||||
@@ -0,0 +1,131 @@
|
||||
/***************************************************************************
|
||||
* libancillary - black magic on Unix domain sockets
|
||||
* (C) Nicolas George
|
||||
* ancillary.c - public header
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ANCILLARY_H__
|
||||
#define ANCILLARY_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
* Start of the readable part.
|
||||
***************************************************************************/
|
||||
|
||||
#define ANCIL_MAX_N_FDS 960
|
||||
/*
|
||||
* Maximum number of fds that can be sent or received using the "esay"
|
||||
* functions; this is so that all can fit in one page.
|
||||
*/
|
||||
|
||||
extern int
|
||||
ancil_send_fds_with_buffer(int, const int *, unsigned, void *);
|
||||
/*
|
||||
* ancil_send_fds_with_buffer(sock, n_fds, fds, buffer)
|
||||
*
|
||||
* Sends the file descriptors in the array pointed by fds, of length n_fds
|
||||
* on the socket sock.
|
||||
* buffer is a writeable memory area large enough to hold the required data
|
||||
* structures.
|
||||
* Returns: -1 and errno in case of error, 0 in case of success.
|
||||
*/
|
||||
|
||||
extern int
|
||||
ancil_recv_fds_with_buffer(int, int *, unsigned, void *);
|
||||
/*
|
||||
* ancil_recv_fds_with_buffer(sock, n_fds, fds, buffer)
|
||||
*
|
||||
* Receives *n_fds file descriptors into the array pointed by fds
|
||||
* from the socket sock.
|
||||
* buffer is a writeable memory area large enough to hold the required data
|
||||
* structures.
|
||||
* Returns: -1 and errno in case of error, the actual number of received fd
|
||||
* in case of success
|
||||
*/
|
||||
|
||||
#define ANCIL_FD_BUFFER(n) \
|
||||
struct { \
|
||||
struct cmsghdr h; \
|
||||
int fd[n]; \
|
||||
}
|
||||
/* ANCIL_FD_BUFFER(n)
|
||||
*
|
||||
* A structure type suitable to be used as buffer for n file descriptors.
|
||||
* Requires <sys/socket.h>.
|
||||
* Example:
|
||||
* ANCIL_FD_BUFFER(42) buffer;
|
||||
* ancil_recv_fds_with_buffer(sock, 42, my_fds, &buffer);
|
||||
*/
|
||||
|
||||
extern int
|
||||
ancil_send_fds(int, const int *, unsigned);
|
||||
/*
|
||||
* ancil_send_fds(sock, n_fds, fds)
|
||||
*
|
||||
* Sends the file descriptors in the array pointed by fds, of length n_fds
|
||||
* on the socket sock.
|
||||
* n_fds must not be greater than ANCIL_MAX_N_FDS.
|
||||
* Returns: -1 and errno in case of error, 0 in case of success.
|
||||
*/
|
||||
|
||||
extern int
|
||||
ancil_recv_fds(int, int *, unsigned);
|
||||
/*
|
||||
* ancil_recv_fds(sock, n_fds, fds)
|
||||
*
|
||||
* Receives *n_fds file descriptors into the array pointed by fds
|
||||
* from the socket sock.
|
||||
* *n_fds must not be greater than ANCIL_MAX_N_FDS.
|
||||
* Returns: -1 and errno in case of error, the actual number of received fd
|
||||
* in case of success.
|
||||
*/
|
||||
|
||||
|
||||
extern int
|
||||
ancil_send_fd(int, int);
|
||||
/* ancil_recv_fd(sock, fd);
|
||||
*
|
||||
* Sends the file descriptor fd on the socket sock.
|
||||
* Returns : -1 and errno in case of error, 0 in case of success.
|
||||
*/
|
||||
|
||||
extern int
|
||||
ancil_recv_fd(int, int *);
|
||||
/* ancil_send_fd(sock, &fd);
|
||||
*
|
||||
* Receives the file descriptor fd from the socket sock.
|
||||
* Returns : -1 and errno in case of error, 0 in case of success.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ANCILLARY_H__ */
|
||||
@@ -0,0 +1,98 @@
|
||||
/***************************************************************************
|
||||
* libancillary - black magic on Unix domain sockets
|
||||
* (C) Nicolas George
|
||||
* fd_send.c - receiving file descriptors
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _XPG4_2 /* Solaris sucks */
|
||||
# define _XPG4_2
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <assert.h>
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/param.h> /* FreeBSD sucks */
|
||||
#endif
|
||||
|
||||
#include "ancillary.h"
|
||||
|
||||
int
|
||||
ancil_recv_fds_with_buffer(int sock, int *fds, unsigned n_fds, void *buffer)
|
||||
{
|
||||
struct msghdr msghdr;
|
||||
char nothing;
|
||||
struct iovec nothing_ptr;
|
||||
struct cmsghdr *cmsg;
|
||||
int i;
|
||||
|
||||
nothing_ptr.iov_base = ¬hing;
|
||||
nothing_ptr.iov_len = 1;
|
||||
msghdr.msg_name = NULL;
|
||||
msghdr.msg_namelen = 0;
|
||||
msghdr.msg_iov = ¬hing_ptr;
|
||||
msghdr.msg_iovlen = 1;
|
||||
msghdr.msg_flags = 0;
|
||||
msghdr.msg_control = buffer;
|
||||
msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
|
||||
cmsg = CMSG_FIRSTHDR(&msghdr);
|
||||
cmsg->cmsg_len = msghdr.msg_controllen;
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
for(i = 0; i < n_fds; i++)
|
||||
((int *)CMSG_DATA(cmsg))[i] = -1;
|
||||
|
||||
if(recvmsg(sock, &msghdr, 0) < 0)
|
||||
return(-1);
|
||||
for(i = 0; i < n_fds; i++)
|
||||
fds[i] = ((int *)CMSG_DATA(cmsg))[i];
|
||||
n_fds = (msghdr.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
|
||||
return(n_fds);
|
||||
}
|
||||
|
||||
#ifndef SPARE_RECV_FDS
|
||||
int
|
||||
ancil_recv_fds(int sock, int *fd, unsigned n_fds)
|
||||
{
|
||||
ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
|
||||
|
||||
assert(n_fds <= ANCIL_MAX_N_FDS);
|
||||
return(ancil_recv_fds_with_buffer(sock, fd, n_fds, &buffer));
|
||||
}
|
||||
#endif /* SPARE_RECV_FDS */
|
||||
|
||||
#ifndef SPARE_RECV_FD
|
||||
int
|
||||
ancil_recv_fd(int sock, int *fd)
|
||||
{
|
||||
ANCIL_FD_BUFFER(1) buffer;
|
||||
|
||||
return(ancil_recv_fds_with_buffer(sock, fd, 1, &buffer) == 1 ? 0 : -1);
|
||||
}
|
||||
#endif /* SPARE_RECV_FD */
|
||||
@@ -0,0 +1,92 @@
|
||||
/***************************************************************************
|
||||
* libancillary - black magic on Unix domain sockets
|
||||
* (C) Nicolas George
|
||||
* fd_send.c - sending file descriptors
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _XPG4_2 /* Solaris sucks */
|
||||
# define _XPG4_2
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/uio.h>
|
||||
#include <assert.h>
|
||||
#if defined(__FreeBSD__)
|
||||
# include <sys/param.h> /* FreeBSD sucks */
|
||||
#endif
|
||||
|
||||
#include "ancillary.h"
|
||||
|
||||
int
|
||||
ancil_send_fds_with_buffer(int sock, const int *fds, unsigned n_fds, void *buffer)
|
||||
{
|
||||
struct msghdr msghdr;
|
||||
char nothing = '!';
|
||||
struct iovec nothing_ptr;
|
||||
struct cmsghdr *cmsg;
|
||||
int i;
|
||||
|
||||
nothing_ptr.iov_base = ¬hing;
|
||||
nothing_ptr.iov_len = 1;
|
||||
msghdr.msg_name = NULL;
|
||||
msghdr.msg_namelen = 0;
|
||||
msghdr.msg_iov = ¬hing_ptr;
|
||||
msghdr.msg_iovlen = 1;
|
||||
msghdr.msg_flags = 0;
|
||||
msghdr.msg_control = buffer;
|
||||
msghdr.msg_controllen = sizeof(struct cmsghdr) + sizeof(int) * n_fds;
|
||||
cmsg = CMSG_FIRSTHDR(&msghdr);
|
||||
cmsg->cmsg_len = msghdr.msg_controllen;
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
for(i = 0; i < n_fds; i++)
|
||||
((int *)CMSG_DATA(cmsg))[i] = fds[i];
|
||||
return(sendmsg(sock, &msghdr, 0) >= 0 ? 0 : -1);
|
||||
}
|
||||
|
||||
#ifndef SPARE_SEND_FDS
|
||||
int
|
||||
ancil_send_fds(int sock, const int *fds, unsigned n_fds)
|
||||
{
|
||||
ANCIL_FD_BUFFER(ANCIL_MAX_N_FDS) buffer;
|
||||
|
||||
assert(n_fds <= ANCIL_MAX_N_FDS);
|
||||
return(ancil_send_fds_with_buffer(sock, fds, n_fds, &buffer));
|
||||
}
|
||||
#endif /* SPARE_SEND_FDS */
|
||||
|
||||
#ifndef SPARE_SEND_FD
|
||||
int
|
||||
ancil_send_fd(int sock, int fd)
|
||||
{
|
||||
ANCIL_FD_BUFFER(1) buffer;
|
||||
|
||||
return(ancil_send_fds_with_buffer(sock, &fd, 1, &buffer));
|
||||
}
|
||||
#endif /* SPARE_SEND_FD */
|
||||
@@ -0,0 +1,112 @@
|
||||
/***************************************************************************
|
||||
* libancillary - black magic on Unix domain sockets
|
||||
* (C) Nicolas George
|
||||
* test.c - testing and example program
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h>
|
||||
#include "ancillary.h"
|
||||
|
||||
void child_process(int sock)
|
||||
{
|
||||
int fd;
|
||||
int fds[3], nfds;
|
||||
char b[] = "This is on the received fd!\n";
|
||||
|
||||
if(ancil_recv_fd(sock, &fd)) {
|
||||
perror("ancil_recv_fd");
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Received fd: %d\n", fd);
|
||||
}
|
||||
write(fd, b, sizeof(b));
|
||||
close(fd);
|
||||
sleep(2);
|
||||
|
||||
nfds = ancil_recv_fds(sock, fds, 3);
|
||||
if(nfds < 0) {
|
||||
perror("ancil_recv_fds");
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Received %d/3 fds : %d %d %d.\n", nfds,
|
||||
fds[0], fds[1], fds[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void parent_process(int sock)
|
||||
{
|
||||
int fds[2] = { 1, 2 };
|
||||
|
||||
if(ancil_send_fd(sock, 1)) {
|
||||
perror("ancil_send_fd");
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Sent fd.\n");
|
||||
}
|
||||
sleep(1);
|
||||
|
||||
if(ancil_send_fds(sock, fds, 2)) {
|
||||
perror("ancil_send_fds");
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Sent two fds.\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int sock[2];
|
||||
|
||||
if(socketpair(PF_UNIX, SOCK_STREAM, 0, sock)) {
|
||||
perror("socketpair");
|
||||
exit(1);
|
||||
} else {
|
||||
printf("Established socket pair: (%d, %d)\n", sock[0], sock[1]);
|
||||
}
|
||||
|
||||
switch(fork()) {
|
||||
case 0:
|
||||
close(sock[0]);
|
||||
child_process(sock[1]);
|
||||
break;
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
default:
|
||||
close(sock[1]);
|
||||
parent_process(sock[0]);
|
||||
wait(NULL);
|
||||
break;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
@@ -59,7 +59,8 @@ static void
|
||||
ev_arc4random_buf(void *buf, size_t n)
|
||||
{
|
||||
#if defined(_EVENT_HAVE_ARC4RANDOM_BUF) && !defined(__APPLE__)
|
||||
return arc4random_buf(buf, n);
|
||||
arc4random_buf(buf, n);
|
||||
return;
|
||||
#else
|
||||
unsigned char *b = buf;
|
||||
|
||||
@@ -71,7 +72,8 @@ ev_arc4random_buf(void *buf, size_t n)
|
||||
* trickery.)
|
||||
*/
|
||||
if (arc4random_buf != NULL) {
|
||||
return arc4random_buf(buf, n);
|
||||
arc4random_buf(buf, n);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* Make sure that we start out with b at a 4-byte alignment; plenty
|
||||
|
||||
@@ -25,11 +25,11 @@
|
||||
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
|
||||
* major minor fix final patch/beta)
|
||||
*/
|
||||
#define OPENSSL_VERSION_NUMBER 0x1000103fL
|
||||
#define OPENSSL_VERSION_NUMBER 0x100010afL
|
||||
#ifdef OPENSSL_FIPS
|
||||
#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1c-fips 10 May 2012"
|
||||
#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1j-fips 15 Oct 2014"
|
||||
#else
|
||||
#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1c 10 May 2012"
|
||||
#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1j 15 Oct 2014"
|
||||
#endif
|
||||
#define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
|
||||
|
||||
|
||||
Submodule src/main/jni/shadowsocks deleted from 561c28b573
Submodule
+1
Submodule src/main/jni/shadowsocks-libev added at 2b1eef1197
@@ -5,8 +5,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <cpu-features.h>
|
||||
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ancillary.h>
|
||||
|
||||
#define LOGI(...) do { __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); } while(0)
|
||||
#define LOGW(...) do { __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); } while(0)
|
||||
#define LOGE(...) do { __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__); } while(0)
|
||||
@@ -36,9 +43,40 @@ void Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring
|
||||
env->ReleaseStringUTFChars(cmd, str);
|
||||
}
|
||||
|
||||
jint Java_com_github_shadowsocks_system_sendfd(JNIEnv *env, jobject thiz, jint tun_fd) {
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
LOGE("socket() failed: %s (socket fd = %d)\n", strerror(errno), fd);
|
||||
return (jint)-1;
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, "/data/data/com.github.shadowsocks/sock_path", sizeof(addr.sun_path)-1);
|
||||
|
||||
if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
LOGE("connect() failed: %s (fd = %d)\n", strerror(errno), fd);
|
||||
close(fd);
|
||||
return (jint)-1;
|
||||
}
|
||||
|
||||
if (ancil_send_fd(fd, tun_fd)) {
|
||||
LOGE("ancil_send_fd: %s", strerror(errno));
|
||||
close(fd);
|
||||
return (jint)-1;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *classPathName = "com/github/shadowsocks/System";
|
||||
|
||||
static JNINativeMethod method_table[] = {
|
||||
{ "sendfd", "(I)I",
|
||||
(void*) Java_com_github_shadowsocks_system_sendfd },
|
||||
{ "exec", "(Ljava/lang/String;)V",
|
||||
(void*) Java_com_github_shadowsocks_system_exec },
|
||||
{ "getABI", "()Ljava/lang/String;",
|
||||
|
||||
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Executable
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
@@ -9,7 +9,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="24sp"
|
||||
android:textSize="26sp"
|
||||
android:textColor="@color/title"
|
||||
android:text="@string/screen_name"
|
||||
android:layout_alignParentLeft="true"
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item android:id="@+id/action_export"
|
||||
android:title="@string/action_export"
|
||||
android:showAsAction="never" />
|
||||
<item android:id="@+id/action_import"
|
||||
android:title="@string/action_import"
|
||||
android:showAsAction="never" />
|
||||
</menu>
|
||||
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- File created by the Android Action Bar Style Generator
|
||||
|
||||
Copyright (C) 2011 The Android Open Source Project
|
||||
Copyright (C) 2012 readyState Software Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<style name="Theme.Shadow" parent="@android:style/Theme.Material.Light.DarkActionBar">
|
||||
<item name="android:actionBarItemBackground">@drawable/selectable_background_shadow</item>
|
||||
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
||||
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
||||
<item name="android:actionBarTabStyle">@style/ActionBarTabStyle.Shadow</item>
|
||||
<item name="android:actionDropDownStyle">@style/DropDownNav.Shadow</item>
|
||||
<item name="android:actionBarStyle">@style/ActionBar.Solid.Shadow</item>
|
||||
<item name="android:actionModeBackground">@drawable/cab_background_top_shadow</item>
|
||||
<item name="android:actionModeSplitBackground">@drawable/cab_background_bottom_shadow</item>
|
||||
<!-- Light.DarkActionBar specific -->
|
||||
<item name="android:actionBarWidgetTheme">@style/Theme.Shadow.Widget</item>
|
||||
<item name="android:textAppearanceLargePopupMenu">@style/m_textAppearanceLargePopupMenu</item>
|
||||
<item name="android:textAppearanceSmallPopupMenu" >@style/m_textAppearanceSmallPopupMenu</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionBar.Solid.Shadow" parent="@android:style/Widget.Material.ActionBar">
|
||||
<item name="android:background">@drawable/ab_background_textured_shadow</item>
|
||||
<item name="android:backgroundStacked">@drawable/ab_stacked_solid_shadow</item>
|
||||
<item name="android:backgroundSplit">@drawable/ab_background_textured_shadow</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionBar.Transparent.Shadow" parent="@android:style/Widget.Material.ActionBar">
|
||||
<item name="android:background">@drawable/ab_transparent_shadow</item>
|
||||
</style>
|
||||
|
||||
<style name="PopupMenu.Shadow" parent="@android:style/Widget.Material.ListPopupWindow">
|
||||
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
||||
</style>
|
||||
|
||||
<style name="m_textAppearanceSmallPopupMenu" parent="@android:style/TextAppearance.Material.Widget.PopupMenu.Small">
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="m_textAppearanceLargePopupMenu" parent="@android:style/TextAppearance.Material.Widget.PopupMenu.Large">
|
||||
<item name="android:textColor">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="DropDownListView.Shadow" parent="@android:style/Widget.Material.ListView.DropDown">
|
||||
<item name="android:listSelector">@drawable/selectable_background_shadow</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionBarTabStyle.Shadow" parent="@android:style/Widget.Material.ActionBar.TabView">
|
||||
<item name="android:background">@drawable/tab_indicator_ab_shadow</item>
|
||||
</style>
|
||||
|
||||
<style name="DropDownNav.Shadow" parent="@android:style/Widget.Material.Spinner">
|
||||
<item name="android:background">@drawable/spinner_background_ab_shadow</item>
|
||||
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
||||
<item name="android:dropDownSelector">@drawable/selectable_background_shadow</item>
|
||||
</style>
|
||||
|
||||
<!-- this style is only referenced in a Light.DarkActionBar based theme -->
|
||||
<style name="Theme.Shadow.Widget" parent="@android:style/Theme.Material">
|
||||
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
||||
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
<item name="android:textAppearanceLargePopupMenu">@style/m_textAppearanceLargePopupMenu</item>
|
||||
<item name="android:textAppearanceSmallPopupMenu" >@style/m_textAppearanceSmallPopupMenu</item>
|
||||
</style>
|
||||
|
||||
<style name="PopupTheme" parent="@android:style/Theme.Material.Light">
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
|
||||
<item name="android:windowSoftInputMode">stateAlwaysHidden</item>
|
||||
<item name="android:windowActionModeOverlay">true</item>
|
||||
<item name="android:colorBackgroundCacheHint">@null</item>
|
||||
<item name="android:windowCloseOnTouchOutside">true</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@@ -10,13 +10,13 @@
|
||||
<string name="profile">配置文件</string>
|
||||
<string name="profile_summary">配置文件名称</string>
|
||||
<string name="proxy">服务器</string>
|
||||
<string name="proxy_summary">您的影梭服务器的地址</string>
|
||||
<string name="proxy_summary">远程服务器的地址</string>
|
||||
<string name="remote_port">远程端口</string>
|
||||
<string name="remote_port_summary">您的影梭服务器的端口号</string>
|
||||
<string name="remote_port_summary">远程服务器的端口号</string>
|
||||
<string name="port">本地端口</string>
|
||||
<string name="port_summary">您的影梭客户端的端口号</string>
|
||||
<string name="port_summary">本地客户端的端口号</string>
|
||||
<string name="sitekey">密码</string>
|
||||
<string name="sitekey_summary">您的影梭服务器的密码</string>
|
||||
<string name="sitekey_summary">远程服务器的密码</string>
|
||||
<string name="enc_method">加密方法</string>
|
||||
<string name="feature_cat">功能设置</string>
|
||||
<string name="http_proxy">HTTP 代理服务器</string>
|
||||
@@ -47,9 +47,10 @@
|
||||
<string name="service_failed">无法连接远程服务器</string>
|
||||
<string name="stop">停止服务</string>
|
||||
<string name="stopping">正在关闭...</string>
|
||||
<string name="vpn_error">后台服务启动失败:\"%s\"。</string>
|
||||
<string name="vpn_error">后台服务启动失败:%s</string>
|
||||
<string name="ok_iknow">确定</string>
|
||||
<string name="port_alert">端口号应大于1024</string>
|
||||
<string name="close">关闭</string>
|
||||
<string name="port_alert">本地端口号应大于1024</string>
|
||||
<string name="port_empty">端口号不能为空</string>
|
||||
<string name="proxy_empty">代理服务器地址不能为空</string>
|
||||
<string name="crash_alert">检测到意外退出,状态已被重置。</string>
|
||||
@@ -67,6 +68,7 @@
|
||||
<string name="about_title">影梭(shadowsocks)%s</string>
|
||||
<string name="flush_dnscache">刷新 DNS 缓存</string>
|
||||
<string name="flushing">刷新中...</string>
|
||||
<string name="qrcode">二维码</string>
|
||||
<string name="add_profile">添加配置文件</string>
|
||||
|
||||
<string name="enable_nat">启用 NAT 模式.</string>
|
||||
@@ -88,4 +90,12 @@
|
||||
<item>绕过局域网及中国大陆地址</item>
|
||||
</string-array>
|
||||
|
||||
<string name="action_export">导出至剪贴板</string>
|
||||
<string name="action_import">从剪贴板导入</string>
|
||||
<string name="action_export_msg">导出成功</string>
|
||||
<string name="action_export_err">导出失败</string>
|
||||
<string name="action_import_msg">导入成功</string>
|
||||
<string name="action_import_err">导入失败</string>
|
||||
<string name="error">错误</string>
|
||||
|
||||
</resources>
|
||||
|
||||
+187
-9686
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
|
||||
<color name="title_background">#ff5e5e5e</color>
|
||||
<color name="dialog_title_background">#17170443</color>
|
||||
<color name="white">#FFFFFF</color>
|
||||
<color name="black">#000000</color>
|
||||
<color name="grey1">#646464</color>
|
||||
<color name="grey2">#c8c8c8</color>
|
||||
@@ -11,4 +12,4 @@
|
||||
<color name="md__transparent">#00000000</color>
|
||||
<color name="md__defaultBackground">#FF555555</color>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
Executable → Regular
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable → Regular
+15
-6
@@ -14,13 +14,13 @@
|
||||
<string name="profile">Profile</string>
|
||||
<string name="profile_summary">Profile name</string>
|
||||
<string name="proxy">Server</string>
|
||||
<string name="proxy_summary">Hostname or IP Address of your Shadowsocks server</string>
|
||||
<string name="proxy_summary">Hostname or IP of the remote server</string>
|
||||
<string name="remote_port">Remote Port</string>
|
||||
<string name="remote_port_summary">Port number of your Shadowsocks server</string>
|
||||
<string name="remote_port_summary">Port number of the remote server</string>
|
||||
<string name="port">Local Port</string>
|
||||
<string name="port_summary">Port number of your Shadowsocks client</string>
|
||||
<string name="port_summary">Port number of the local server</string>
|
||||
<string name="sitekey">Password</string>
|
||||
<string name="sitekey_summary">Password of your Shadowsocks server</string>
|
||||
<string name="sitekey_summary">Password of the remote server</string>
|
||||
<string name="enc_method">Encrypt Method</string>
|
||||
|
||||
<!-- feature category -->
|
||||
@@ -58,13 +58,15 @@
|
||||
<string name="service_failed">Failed to connect the remote server</string>
|
||||
<string name="stop">Stop the service</string>
|
||||
<string name="stopping">Shutting down...</string>
|
||||
<string name="vpn_error">Error: \"%s\".</string>
|
||||
<string name="vpn_error">%s</string>
|
||||
<string name="enable_nat">Turn on NAT mode.</string>
|
||||
<string name="disable_nat">Turn off NAT mode.</string>
|
||||
<string name="error">ERROR</string>
|
||||
|
||||
<!-- alert category -->
|
||||
<string name="ok_iknow">OK</string>
|
||||
<string name="port_alert">The port number should be greater than 1024</string>
|
||||
<string name="close">Close</string>
|
||||
<string name="port_alert">The local port number should be greater than 1024</string>
|
||||
<string name="port_empty">Port should not be empty</string>
|
||||
<string name="proxy_empty">Proxy should not be empty</string>
|
||||
<string name="crash_alert">An unexpected exit detected, the context has been reset.
|
||||
@@ -83,9 +85,16 @@
|
||||
<string name="recovery">Reset</string>
|
||||
<string name="about">About</string>
|
||||
<string name="about_title">Shadowsocks %s</string>
|
||||
<string name="qrcode">QR Code</string>
|
||||
<string name="flush_dnscache">Flush DNS Cache</string>
|
||||
<string name="flushing">Flushing</string>
|
||||
<string name="add_profile">Add Profile</string>
|
||||
<string name="action_export">Export to Clipboard</string>
|
||||
<string name="action_import">Import from Clipboard</string>
|
||||
<string name="action_export_msg">Successfully export!</string>
|
||||
<string name="action_export_err">Failed to export.</string>
|
||||
<string name="action_import_msg">Successfully import!</string>
|
||||
<string name="action_import_err">Failed to import.</string>
|
||||
|
||||
<!-- profile -->
|
||||
<string name="add_profile_dialog">Add this Shadowsocks Profile?</string>
|
||||
|
||||
@@ -19,7 +19,9 @@
|
||||
<style name="Theme.AppManager" parent="@style/Theme.Shadow">
|
||||
</style>
|
||||
|
||||
<style name="PopupTheme" parent="@android:style/Theme.Translucent.NoTitleBar">
|
||||
<style name="PopupTheme" parent="@android:style/Theme.Holo.Light">
|
||||
<item name="android:windowActionBar">false</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<item name="android:windowIsFloating">false</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
@@ -72,4 +74,4 @@
|
||||
<item name="mdMenuSize">250dp</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
Executable → Regular
+16
-5
@@ -29,13 +29,13 @@
|
||||
<item name="android:actionModeBackground">@drawable/cab_background_top_shadow</item>
|
||||
<item name="android:actionModeSplitBackground">@drawable/cab_background_bottom_shadow</item>
|
||||
<item name="android:actionModeCloseButtonStyle">@style/ActionButton.CloseMode.Shadow</item>
|
||||
|
||||
<!-- Light.DarkActionBar specific -->
|
||||
<!-- Light.DarkActionBar specific -->
|
||||
<item name="android:actionBarWidgetTheme">@style/Theme.Shadow.Widget</item>
|
||||
|
||||
<item name="android:textAppearanceLargePopupMenu">@style/m_textAppearanceLargePopupMenu</item>
|
||||
<item name="android:textAppearanceSmallPopupMenu" >@style/m_textAppearanceSmallPopupMenu</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionBar.Solid.Shadow" parent="@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse">
|
||||
<style name="ActionBar.Solid.Shadow" parent="@android:style/Widget.Holo.ActionBar">
|
||||
<item name="android:background">@drawable/ab_background_textured_shadow</item>
|
||||
<item name="android:backgroundStacked">@drawable/ab_stacked_solid_shadow</item>
|
||||
<item name="android:backgroundSplit">@drawable/ab_background_textured_shadow</item>
|
||||
@@ -51,6 +51,14 @@
|
||||
<item name="android:popupBackground">@drawable/menu_dropdown_panel_shadow</item>
|
||||
</style>
|
||||
|
||||
<style name="m_textAppearanceSmallPopupMenu" parent="@android:style/TextAppearance.Holo.Widget.PopupMenu.Small">
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="m_textAppearanceLargePopupMenu" parent="@android:style/TextAppearance.Holo.Widget.PopupMenu.Large">
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="DropDownListView.Shadow" parent="@android:style/Widget.Holo.ListView.DropDown">
|
||||
<item name="android:listSelector">@drawable/selectable_background_shadow</item>
|
||||
</style>
|
||||
@@ -77,6 +85,9 @@
|
||||
<style name="Theme.Shadow.Widget" parent="@android:style/Theme.Holo">
|
||||
<item name="android:popupMenuStyle">@style/PopupMenu.Shadow</item>
|
||||
<item name="android:dropDownListViewStyle">@style/DropDownListView.Shadow</item>
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
<item name="android:textAppearanceLargePopupMenu">@style/m_textAppearanceLargePopupMenu</item>
|
||||
<item name="android:textAppearanceSmallPopupMenu" >@style/m_textAppearanceSmallPopupMenu</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.app.{Activity, ProgressDialog}
|
||||
import android.content.ClipboardManager
|
||||
import android.content.ClipData
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import android.content.pm.PackageManager
|
||||
@@ -47,6 +49,8 @@ import android.graphics.{Bitmap, PixelFormat}
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.preference.PreferenceManager
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.View.OnClickListener
|
||||
import android.view.ViewGroup
|
||||
@@ -115,7 +119,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
|
||||
var appsLoaded: Boolean = false
|
||||
|
||||
def loadApps(context: Context): Array[ProxiedApp] = {
|
||||
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val proxiedAppString = prefs.getString(Key.proxied, "")
|
||||
val proxiedApps = proxiedAppString.split('|').sortWith(_ < _)
|
||||
|
||||
@@ -218,12 +222,65 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
|
||||
}
|
||||
}
|
||||
|
||||
protected override def onOptionsItemSelected(item: MenuItem): Boolean = {
|
||||
val clipboard = getSystemService(Context.CLIPBOARD_SERVICE).asInstanceOf[ClipboardManager]
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
|
||||
item.getItemId match {
|
||||
case R.id.action_export =>
|
||||
val bypass = prefs.getBoolean(Key.isBypassApps, false)
|
||||
val proxiedAppString = prefs.getString(Key.proxied, "")
|
||||
val clip = ClipData.newPlainText(Key.proxied, bypass + " " + proxiedAppString)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
Toast.makeText(this, R.string.action_export_msg, Toast.LENGTH_SHORT).show()
|
||||
return true
|
||||
case R.id.action_import =>
|
||||
if (clipboard.hasPrimaryClip) {
|
||||
val clipdata = clipboard.getPrimaryClip
|
||||
val label = clipdata.getDescription.getLabel
|
||||
if (label == Key.proxied) {
|
||||
val proxiedAppSequence = clipdata.getItemAt(0).getText
|
||||
if (proxiedAppSequence != null) {
|
||||
val proxiedAppString = proxiedAppSequence.toString
|
||||
if (!proxiedAppString.isEmpty) {
|
||||
val array = proxiedAppString.split(" ")
|
||||
val bypass = array(0).toBoolean
|
||||
val apps = if (array.size > 1) array(1) else ""
|
||||
prefs.edit.putBoolean(Key.isBypassApps, bypass).commit()
|
||||
prefs.edit.putString(Key.proxied, apps).commit()
|
||||
Toast.makeText(this, R.string.action_import_msg, Toast.LENGTH_SHORT).show()
|
||||
// Restart activity
|
||||
val intent = getIntent
|
||||
finish()
|
||||
startActivity(intent)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Toast.makeText(this, R.string.action_import_err, Toast.LENGTH_SHORT).show()
|
||||
return false
|
||||
case android.R.id.home =>
|
||||
navigateUpTo(getParentActivityIntent)
|
||||
return true
|
||||
}
|
||||
super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
protected override def onCreateOptionsMenu(menu: Menu): Boolean = {
|
||||
val inflater = getMenuInflater()
|
||||
inflater.inflate(R.menu.app_manager_menu, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
protected override def onCreate(savedInstanceState: Bundle) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
handler = new Handler()
|
||||
|
||||
getActionBar.setTitle(R.string.proxied_help)
|
||||
val actionBar = getActionBar()
|
||||
actionBar.setTitle(R.string.proxied_help)
|
||||
actionBar.setDisplayHomeAsUpEnabled(true)
|
||||
actionBar.setDisplayShowHomeEnabled(false)
|
||||
this.setContentView(R.layout.layout_apps)
|
||||
this.overlay = View.inflate(this, R.layout.overlay, null).asInstanceOf[TextView]
|
||||
getWindowManager.addView(overlay, new
|
||||
@@ -239,7 +296,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
|
||||
ImageLoader.getInstance().init(config)
|
||||
|
||||
val bypassSwitch = findViewById(R.id.bypassSwitch).asInstanceOf[Switch]
|
||||
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext)
|
||||
bypassSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener {
|
||||
def onCheckedChanged(button: CompoundButton, checked: Boolean) {
|
||||
prefs.edit().putBoolean(Key.isBypassApps, checked).commit()
|
||||
@@ -261,7 +318,7 @@ class AppManager extends Activity with OnCheckedChangeListener with OnClickListe
|
||||
|
||||
def saveAppSettings(context: Context) {
|
||||
if (apps == null) return
|
||||
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val proxiedApps = new StringBuilder
|
||||
apps.foreach(app =>
|
||||
if (app.proxied) {
|
||||
|
||||
@@ -49,8 +49,8 @@ import android.content.Context
|
||||
|
||||
trait BaseService {
|
||||
|
||||
@volatile var state = State.INIT
|
||||
@volatile var callbackCount = 0
|
||||
@volatile private var state = State.INIT
|
||||
@volatile private var callbackCount = 0
|
||||
|
||||
final val callbacks = new RemoteCallbackList[IShadowsocksServiceCallback]
|
||||
|
||||
@@ -100,6 +100,12 @@ trait BaseService {
|
||||
def getTag: String
|
||||
def getContext: Context
|
||||
|
||||
def getCallbackCount(): Int = {
|
||||
callbackCount
|
||||
}
|
||||
def getState(): Int = {
|
||||
state
|
||||
}
|
||||
def changeState(s: Int) {
|
||||
changeState(s, null)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ package com.github.shadowsocks
|
||||
import java.util
|
||||
import java.io.{OutputStream, InputStream, ByteArrayInputStream, ByteArrayOutputStream, IOException, FileOutputStream}
|
||||
import java.util.Locale
|
||||
import java.lang.Math
|
||||
|
||||
import android.app.backup.BackupManager
|
||||
import android.app.{Activity, AlertDialog, ProgressDialog}
|
||||
@@ -56,6 +57,7 @@ import android.view.View.OnLongClickListener
|
||||
import android.view._
|
||||
import android.webkit.{WebView, WebViewClient}
|
||||
import android.widget._
|
||||
import com.github.mrengineer13.snackbar._
|
||||
import com.github.shadowsocks.aidl.{IShadowsocksService, IShadowsocksServiceCallback}
|
||||
import com.github.shadowsocks.database._
|
||||
import com.github.shadowsocks.preferences.{PasswordEditTextPreference, ProfileEditTextPreference, SummaryEditTextPreference}
|
||||
@@ -64,8 +66,11 @@ import com.google.android.gms.ads.{AdRequest, AdSize, AdView}
|
||||
import com.google.android.gms.analytics.HitBuilders
|
||||
import com.google.zxing.integration.android.IntentIntegrator
|
||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader
|
||||
import de.keyboardsurfer.android.widget.crouton.{Configuration, Crouton, Style}
|
||||
import net.simonvt.menudrawer.MenuDrawer
|
||||
import com.joanzapata.android.iconify.Iconify
|
||||
import com.joanzapata.android.iconify.Iconify.IconValue
|
||||
import com.joanzapata.android.iconify.IconDrawable
|
||||
import net.glxn.qrgen.android.QRCode
|
||||
|
||||
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
||||
import scala.concurrent.ops._
|
||||
@@ -205,7 +210,6 @@ class Shadowsocks
|
||||
// Update the UI
|
||||
if (switchButton != null) switchButton.setEnabled(true)
|
||||
if (State.isAvailable(bgService.getState)) {
|
||||
Crouton.cancelAllCroutons()
|
||||
setPreferenceEnabled(enabled = true)
|
||||
} else {
|
||||
changeSwitch(checked = true)
|
||||
@@ -322,7 +326,7 @@ class Shadowsocks
|
||||
}
|
||||
}
|
||||
|
||||
private def crash_recovery() {
|
||||
private def crashRecovery() {
|
||||
val cmd = new ArrayBuffer[String]()
|
||||
|
||||
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) {
|
||||
@@ -367,19 +371,29 @@ class Shadowsocks
|
||||
|
||||
def isTextEmpty(s: String, msg: String): Boolean = {
|
||||
if (s == null || s.length <= 0) {
|
||||
Crouton.makeText(this, msg, Style.ALERT).show()
|
||||
new SnackBar.Builder(this)
|
||||
.withMessage(msg)
|
||||
.withActionMessageId(R.string.error)
|
||||
.withStyle(SnackBar.Style.ALERT)
|
||||
.withDuration(SnackBar.LONG_SNACK)
|
||||
.show()
|
||||
return true
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
def cancelStart() {
|
||||
handler.postDelayed(new Runnable {
|
||||
override def run() {
|
||||
clearDialog()
|
||||
changeSwitch(checked = false)
|
||||
}
|
||||
}, 1000)
|
||||
clearDialog()
|
||||
changeSwitch(checked = false)
|
||||
}
|
||||
|
||||
def isReady(): Boolean = {
|
||||
if (!checkText(Key.proxy)) return false
|
||||
if (!checkText(Key.sitekey)) return false
|
||||
if (!checkNumber(Key.localPort, low = false)) return false
|
||||
if (!checkNumber(Key.remotePort, low = true)) return false
|
||||
if (bgService == null) return false
|
||||
true
|
||||
}
|
||||
|
||||
def prepareStartService() {
|
||||
@@ -393,9 +407,7 @@ class Shadowsocks
|
||||
onActivityResult(Shadowsocks.REQUEST_CONNECT, Activity.RESULT_OK, null)
|
||||
}
|
||||
} else {
|
||||
if (!serviceStart) {
|
||||
cancelStart()
|
||||
}
|
||||
serviceStart()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,7 +416,10 @@ class Shadowsocks
|
||||
if (compoundButton eq switchButton) {
|
||||
checked match {
|
||||
case true =>
|
||||
prepareStartService()
|
||||
if (isReady)
|
||||
prepareStartService()
|
||||
else
|
||||
changeSwitch(checked = false)
|
||||
case false =>
|
||||
serviceStop()
|
||||
}
|
||||
@@ -480,10 +495,16 @@ class Shadowsocks
|
||||
menuAdapter.setListener(this)
|
||||
listView.setAdapter(menuAdapter)
|
||||
drawer.setMenuView(listView)
|
||||
// The drawable that replaces the up indicator in the action bar
|
||||
drawer.setSlideDrawable(R.drawable.ic_drawer)
|
||||
// Whether the previous drawable should be shown
|
||||
drawer.setDrawerIndicatorEnabled(true)
|
||||
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
drawer.setDrawerIndicatorEnabled(false)
|
||||
} else {
|
||||
// The drawable that replaces the up indicator in the action bar
|
||||
drawer.setSlideDrawable(R.drawable.ic_drawer)
|
||||
// Whether the previous drawable should be shown
|
||||
drawer.setDrawerIndicatorEnabled(true)
|
||||
}
|
||||
|
||||
if (!isSinglePane) {
|
||||
drawer.openMenu(false)
|
||||
}
|
||||
@@ -499,7 +520,14 @@ class Shadowsocks
|
||||
getActionBar.setCustomView(switchLayout)
|
||||
getActionBar.setDisplayShowTitleEnabled(false)
|
||||
getActionBar.setDisplayShowCustomEnabled(true)
|
||||
getActionBar.setIcon(R.drawable.ic_stat_shadowsocks)
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
getWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
getWindow.setStatusBarColor(getResources().getColor(R.color.grey3));
|
||||
getActionBar.setDisplayHomeAsUpEnabled(true)
|
||||
getActionBar.setHomeAsUpIndicator(R.drawable.ic_drawer)
|
||||
} else {
|
||||
getActionBar.setIcon(R.drawable.ic_stat_shadowsocks)
|
||||
}
|
||||
title.setOnLongClickListener(new OnLongClickListener {
|
||||
override def onLongClick(v: View): Boolean = {
|
||||
if (Utils.isLollipopOrAbove && bgService != null
|
||||
@@ -610,6 +638,25 @@ class Shadowsocks
|
||||
builder.create().show()
|
||||
}
|
||||
|
||||
def reloadProfile() {
|
||||
drawer.closeMenu(true)
|
||||
|
||||
val h = showProgress(getString(R.string.loading))
|
||||
|
||||
handler.postDelayed(new Runnable {
|
||||
def run() {
|
||||
currentProfile = {
|
||||
profileManager.getProfile(settings.getInt(Key.profileId, -1)) getOrElse currentProfile
|
||||
}
|
||||
menuAdapter.updateList(getMenuList, currentProfile.id)
|
||||
|
||||
updatePreferenceScreen()
|
||||
|
||||
h.sendEmptyMessage(0)
|
||||
}
|
||||
}, 600)
|
||||
}
|
||||
|
||||
def addProfile(profile: Profile) {
|
||||
drawer.closeMenu(true)
|
||||
|
||||
@@ -701,7 +748,7 @@ class Shadowsocks
|
||||
|
||||
def getProfileList: List[Item] = {
|
||||
val list = profileManager.getAllProfiles getOrElse List[Profile]()
|
||||
list.map(p => new Item(p.id, p.name, -1, updateProfile, delProfile))
|
||||
list.map(p => new IconItem(p.id, p.name, -1, updateProfile, delProfile))
|
||||
}
|
||||
|
||||
def getMenuList: List[Any] = {
|
||||
@@ -713,11 +760,13 @@ class Shadowsocks
|
||||
buf ++= getProfileList
|
||||
|
||||
buf +=
|
||||
new Item(-400, getString(R.string.add_profile), android.R.drawable.ic_menu_add, newProfile)
|
||||
new DrawableItem(-400, getString(R.string.add_profile), new IconDrawable(this, IconValue.fa_plus_circle)
|
||||
.colorRes(android.R.color.darker_gray).sizeDp(26), newProfile)
|
||||
|
||||
buf += new Category(getString(R.string.settings))
|
||||
|
||||
buf += new Item(-100, getString(R.string.recovery), android.R.drawable.ic_menu_revert, _ => {
|
||||
buf += new DrawableItem(-100, getString(R.string.recovery), new IconDrawable(this, IconValue.fa_recycle)
|
||||
.colorRes(android.R.color.darker_gray).sizeDp(26), _ => {
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
.setCategory(Shadowsocks.TAG)
|
||||
@@ -728,7 +777,8 @@ class Shadowsocks
|
||||
})
|
||||
|
||||
buf +=
|
||||
new Item(-200, getString(R.string.flush_dnscache), android.R.drawable.ic_menu_delete, _ => {
|
||||
new DrawableItem(-200, getString(R.string.flush_dnscache), new IconDrawable(this, IconValue.fa_refresh)
|
||||
.colorRes(android.R.color.darker_gray).sizeDp(26), _ => {
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
.setCategory(Shadowsocks.TAG)
|
||||
@@ -738,7 +788,20 @@ class Shadowsocks
|
||||
flushDnsCache()
|
||||
})
|
||||
|
||||
buf += new Item(-300, getString(R.string.about), android.R.drawable.ic_menu_info_details, _ => {
|
||||
buf +=
|
||||
new DrawableItem(-300, getString(R.string.qrcode), new IconDrawable(this, IconValue.fa_qrcode)
|
||||
.colorRes(android.R.color.darker_gray).sizeDp(26), _ => {
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
.setCategory(Shadowsocks.TAG)
|
||||
.setAction("qrcode")
|
||||
.setLabel(getVersionName)
|
||||
.build())
|
||||
showQrCode()
|
||||
})
|
||||
|
||||
buf += new DrawableItem(-400, getString(R.string.about), new IconDrawable(this, IconValue.fa_info_circle)
|
||||
.colorRes(android.R.color.darker_gray).sizeDp(26), _ => {
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
.setCategory(Shadowsocks.TAG)
|
||||
@@ -782,6 +845,11 @@ class Shadowsocks
|
||||
switchButton.setOnCheckedChangeListener(Shadowsocks.this)
|
||||
}
|
||||
ConfigUtils.refresh(this)
|
||||
|
||||
// Check if profile list changed
|
||||
val id = settings.getInt(Key.profileId, -1)
|
||||
if (id != -1 && id != currentProfile.id)
|
||||
reloadProfile()
|
||||
}
|
||||
|
||||
private def setPreferenceEnabled(enabled: Boolean) {
|
||||
@@ -828,7 +896,6 @@ class Shadowsocks
|
||||
override def onDestroy() {
|
||||
super.onDestroy()
|
||||
deattachService()
|
||||
Crouton.cancelAllCroutons()
|
||||
unregisterReceiver(preferenceReceiver)
|
||||
new BackupManager(this).dataChanged()
|
||||
if (handler != null) {
|
||||
@@ -851,7 +918,7 @@ class Shadowsocks
|
||||
|
||||
def reset() {
|
||||
|
||||
crash_recovery()
|
||||
crashRecovery()
|
||||
|
||||
copyAssets(System.getABI)
|
||||
|
||||
@@ -872,6 +939,31 @@ class Shadowsocks
|
||||
}
|
||||
}
|
||||
|
||||
private def dp2px(dp: Int): Int = {
|
||||
val displayMetrics = getBaseContext.getResources.getDisplayMetrics()
|
||||
Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT))
|
||||
}
|
||||
|
||||
private def showQrCode() {
|
||||
val image = new ImageView(this)
|
||||
image.setPadding(0, dp2px(20), 0, dp2px(20))
|
||||
image.setLayoutParams(new LinearLayout.LayoutParams(-1, -1))
|
||||
val qrcode = QRCode.from(Parser.generate(currentProfile))
|
||||
.withSize(dp2px(250), dp2px(250)).asInstanceOf[QRCode]
|
||||
image.setImageBitmap(qrcode.bitmap())
|
||||
|
||||
new AlertDialog.Builder(this)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(getString(R.string.close), new DialogInterface.OnClickListener() {
|
||||
override def onClick(dialog: DialogInterface, id: Int) {
|
||||
dialog.cancel()
|
||||
}
|
||||
})
|
||||
.setView(image)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
|
||||
private def flushDnsCache() {
|
||||
val h = showProgress(getString(R.string.flushing))
|
||||
spawn {
|
||||
@@ -891,9 +983,7 @@ class Shadowsocks
|
||||
resultCode match {
|
||||
case Activity.RESULT_OK =>
|
||||
prepared = true
|
||||
if (!serviceStart) {
|
||||
cancelStart()
|
||||
}
|
||||
serviceStart()
|
||||
case _ =>
|
||||
cancelStart()
|
||||
Log.e(Shadowsocks.TAG, "Failed to start VpnService")
|
||||
@@ -927,33 +1017,34 @@ class Shadowsocks
|
||||
try {
|
||||
val port: Int = Integer.valueOf(text)
|
||||
if (!low && port <= 1024) {
|
||||
Crouton.makeText(this, R.string.port_alert, Style.ALERT).show()
|
||||
new SnackBar.Builder(this)
|
||||
.withMessageId(R.string.port_alert)
|
||||
.withActionMessageId(R.string.error)
|
||||
.withStyle(SnackBar.Style.ALERT)
|
||||
.withDuration(SnackBar.LONG_SNACK)
|
||||
.show()
|
||||
return false
|
||||
}
|
||||
} catch {
|
||||
case ex: Exception =>
|
||||
Crouton.makeText(this, R.string.port_alert, Style.ALERT).show()
|
||||
new SnackBar.Builder(this)
|
||||
.withMessageId(R.string.port_alert)
|
||||
.withActionMessageId(R.string.error)
|
||||
.withStyle(SnackBar.Style.ALERT)
|
||||
.withDuration(SnackBar.LONG_SNACK)
|
||||
.show()
|
||||
return false
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
/** Called when connect button is clicked. */
|
||||
def serviceStart: Boolean = {
|
||||
|
||||
if (!checkText(Key.proxy)) return false
|
||||
if (!checkText(Key.sitekey)) return false
|
||||
if (!checkNumber(Key.localPort, low = false)) return false
|
||||
if (!checkNumber(Key.remotePort, low = true)) return false
|
||||
|
||||
if (bgService == null) return false
|
||||
|
||||
def serviceStart() {
|
||||
bgService.start(ConfigUtils.load(settings))
|
||||
|
||||
if (isVpnEnabled) {
|
||||
changeSwitch(checked = false)
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
private def showAbout() {
|
||||
@@ -1014,15 +1105,12 @@ class Shadowsocks
|
||||
case State.STOPPED =>
|
||||
clearDialog()
|
||||
changeSwitch(checked = false)
|
||||
Crouton.cancelAllCroutons()
|
||||
if (m != null) {
|
||||
val style = new Style.Builder().setBackgroundColorValue(Style.holoRedLight).build()
|
||||
val config = new Configuration.Builder()
|
||||
.setDuration(Configuration.DURATION_LONG)
|
||||
.build()
|
||||
Crouton
|
||||
.makeText(Shadowsocks.this, getString(R.string.vpn_error).formatLocal(Locale.ENGLISH, m), style)
|
||||
.setConfiguration(config)
|
||||
new SnackBar.Builder(Shadowsocks.this)
|
||||
.withMessage(getString(R.string.vpn_error).formatLocal(Locale.ENGLISH, m))
|
||||
.withActionMessageId(R.string.error)
|
||||
.withStyle(SnackBar.Style.ALERT)
|
||||
.withDuration(SnackBar.LONG_SNACK)
|
||||
.show()
|
||||
}
|
||||
setPreferenceEnabled(enabled = true)
|
||||
|
||||
@@ -43,7 +43,7 @@ import java.io.File
|
||||
import java.lang.reflect.{InvocationTargetException, Method}
|
||||
import java.util.Locale
|
||||
|
||||
import android.app.{Notification, NotificationManager, PendingIntent, Service}
|
||||
import android.app._
|
||||
import android.content._
|
||||
import android.content.pm.{PackageInfo, PackageManager}
|
||||
import android.net.{Network, ConnectivityManager}
|
||||
@@ -75,6 +75,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
private val mStartForegroundArgs = new Array[AnyRef](2)
|
||||
private val mStopForegroundArgs = new Array[AnyRef](1)
|
||||
|
||||
var lockReceiver: BroadcastReceiver = null
|
||||
var closeReceiver: BroadcastReceiver = null
|
||||
var connReceiver: BroadcastReceiver = null
|
||||
var notificationManager: NotificationManager = null
|
||||
@@ -200,6 +201,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd += (Path.BASE + "ss-local"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-t" , "600"
|
||||
, "-c" , Path.BASE + "ss-local-nat.conf"
|
||||
, "-f" , Path.BASE + "ss-local-nat.pid")
|
||||
|
||||
@@ -223,6 +225,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd += (Path.BASE + "ss-tunnel"
|
||||
, "-u"
|
||||
, "-t" , "10"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-L" , "8.8.8.8:53"
|
||||
, "-c" , Path.BASE + "ss-tunnel-nat.conf"
|
||||
@@ -244,6 +247,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
val cmdBuf = new ArrayBuffer[String]
|
||||
cmdBuf += (Path.BASE + "ss-tunnel"
|
||||
, "-u"
|
||||
, "-t" , "10"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-l" , "8163"
|
||||
, "-L" , "8.8.8.8:53"
|
||||
@@ -259,8 +263,9 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
|
||||
val conf = if (config.route == Route.BYPASS_CHN) {
|
||||
val reject = ConfigUtils.getRejectList(getContext, application)
|
||||
val blackList = ConfigUtils.getBlackList(getContext, application)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153,
|
||||
Path.BASE + "pdnsd-nat.pid", reject, reject, 8163)
|
||||
Path.BASE + "pdnsd-nat.pid", reject, blackList, 8163)
|
||||
} else {
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153,
|
||||
Path.BASE + "pdnsd-nat.pid", 8163)
|
||||
@@ -324,7 +329,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
def notifyForegroundAlert(title: String, info: String) {
|
||||
def notifyForegroundAlert(title: String, info: String, visible: Boolean) {
|
||||
val openIntent = new Intent(this, classOf[Shadowsocks])
|
||||
openIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT)
|
||||
val contentIntent = PendingIntent.getActivity(this, 0, openIntent, 0)
|
||||
@@ -341,7 +346,11 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
|
||||
.addAction(android.R.drawable.ic_menu_close_clear_cancel, getString(R.string.stop),
|
||||
actionIntent)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
|
||||
if (visible)
|
||||
builder.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
else
|
||||
builder.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
|
||||
startForegroundCompat(1, builder.build)
|
||||
}
|
||||
@@ -497,13 +506,41 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
filter.addAction(Intent.ACTION_SHUTDOWN)
|
||||
filter.addAction(Action.CLOSE)
|
||||
closeReceiver = new BroadcastReceiver() {
|
||||
def onReceive(p1: Context, p2: Intent) {
|
||||
Toast.makeText(p1, R.string.stopping, Toast.LENGTH_SHORT).show()
|
||||
def onReceive(context: Context, intent: Intent) {
|
||||
Toast.makeText(context, R.string.stopping, Toast.LENGTH_SHORT).show()
|
||||
stopRunner()
|
||||
}
|
||||
}
|
||||
registerReceiver(closeReceiver, filter)
|
||||
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
val screenFilter = new IntentFilter()
|
||||
screenFilter.addAction(Intent.ACTION_SCREEN_ON)
|
||||
screenFilter.addAction(Intent.ACTION_SCREEN_OFF)
|
||||
screenFilter.addAction(Intent.ACTION_USER_PRESENT)
|
||||
lockReceiver = new BroadcastReceiver() {
|
||||
def onReceive(context: Context, intent: Intent) {
|
||||
if (getState == State.CONNECTED) {
|
||||
val action = intent.getAction
|
||||
if (action == Intent.ACTION_SCREEN_OFF) {
|
||||
notifyForegroundAlert(getString(R.string.forward_success),
|
||||
getString(R.string.service_running).formatLocal(Locale.ENGLISH, config.profileName), false)
|
||||
} else if (action == Intent.ACTION_SCREEN_ON) {
|
||||
val keyGuard = getSystemService(Context.KEYGUARD_SERVICE).asInstanceOf[KeyguardManager]
|
||||
if (!keyGuard.inKeyguardRestrictedInputMode) {
|
||||
notifyForegroundAlert(getString(R.string.forward_success),
|
||||
getString(R.string.service_running).formatLocal(Locale.ENGLISH, config.profileName), true)
|
||||
}
|
||||
} else if (action == Intent.ACTION_USER_PRESENT) {
|
||||
notifyForegroundAlert(getString(R.string.forward_success),
|
||||
getString(R.string.service_running).formatLocal(Locale.ENGLISH, config.profileName), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
registerReceiver(lockReceiver, screenFilter)
|
||||
}
|
||||
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
.setCategory(TAG)
|
||||
@@ -551,7 +588,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
flushDns()
|
||||
|
||||
notifyForegroundAlert(getString(R.string.forward_success),
|
||||
getString(R.string.service_running).formatLocal(Locale.ENGLISH, config.profileName))
|
||||
getString(R.string.service_running).formatLocal(Locale.ENGLISH, config.profileName), true)
|
||||
changeState(State.CONNECTED)
|
||||
} else {
|
||||
changeState(State.STOPPED, getString(R.string.service_failed))
|
||||
@@ -572,6 +609,13 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
closeReceiver = null
|
||||
}
|
||||
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
if (lockReceiver != null) {
|
||||
unregisterReceiver(lockReceiver)
|
||||
lockReceiver = null
|
||||
}
|
||||
}
|
||||
|
||||
// send event
|
||||
application.tracker.send(new HitBuilders.EventBuilder()
|
||||
.setCategory(TAG)
|
||||
@@ -583,7 +627,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
||||
killProcesses()
|
||||
|
||||
// stop the service if no callback registered
|
||||
if (callbackCount == 0) {
|
||||
if (getCallbackCount == 0) {
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,9 @@ class ShadowsocksRunnerActivity extends Activity {
|
||||
override def onServiceConnected(name: ComponentName, service: IBinder) {
|
||||
bgService = IShadowsocksService.Stub.asInterface(service)
|
||||
handler.postDelayed(new Runnable() {
|
||||
override def run() = startBackgroundService()
|
||||
override def run() {
|
||||
if (bgService != null) startBackgroundService()
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
override def onServiceDisconnected(name: ComponentName) {
|
||||
|
||||
@@ -116,9 +116,10 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd +=(Path.BASE + "ss-local", "-u"
|
||||
, "-b", "127.0.0.1"
|
||||
, "-c", Path.BASE + "ss-local-vpn.conf"
|
||||
, "-f", Path.BASE + "ss-local-vpn.pid")
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-t" , "600"
|
||||
, "-c" , Path.BASE + "ss-local-vpn.conf"
|
||||
, "-f" , Path.BASE + "ss-local-vpn.pid")
|
||||
|
||||
if (Utils.isLollipopOrAbove && config.route != Route.ALL) {
|
||||
cmd += "--acl"
|
||||
@@ -139,11 +140,12 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
val cmd = new ArrayBuffer[String]
|
||||
cmd +=(Path.BASE + "ss-tunnel"
|
||||
, "-u"
|
||||
, "-b", "127.0.0.1"
|
||||
, "-l", "8163"
|
||||
, "-L", "8.8.8.8:53"
|
||||
, "-c", Path.BASE + "ss-tunnel-vpn.conf"
|
||||
, "-f", Path.BASE + "ss-tunnel-vpn.pid")
|
||||
, "-t" , "10"
|
||||
, "-b" , "127.0.0.1"
|
||||
, "-l" , "8163"
|
||||
, "-L" , "8.8.8.8:53"
|
||||
, "-c" , Path.BASE + "ss-tunnel-vpn.conf"
|
||||
, "-f" , Path.BASE + "ss-tunnel-vpn.pid")
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
|
||||
Console.runCommand(cmd.mkString(" "))
|
||||
@@ -151,10 +153,11 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
def startDnsDaemon() {
|
||||
val conf = {
|
||||
if (Utils.isLollipopOrAbove && config.route == Route.BYPASS_CHN) {
|
||||
if (config.route == Route.BYPASS_CHN) {
|
||||
val reject = ConfigUtils.getRejectList(getContext, application)
|
||||
val blackList = ConfigUtils.getBlackList(getContext, application)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153,
|
||||
Path.BASE + "pdnsd-vpn.pid", reject, reject, 8163)
|
||||
Path.BASE + "pdnsd-vpn.pid", reject, blackList, 8163)
|
||||
} else {
|
||||
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153,
|
||||
Path.BASE + "pdnsd-vpn.pid", 8163)
|
||||
@@ -181,7 +184,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
version
|
||||
}
|
||||
|
||||
def startVpn() {
|
||||
def startVpn(): Int = {
|
||||
|
||||
val builder = new Builder()
|
||||
builder
|
||||
@@ -307,7 +310,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
if (conn == null) {
|
||||
stopRunner()
|
||||
return
|
||||
return -1
|
||||
}
|
||||
|
||||
val fd = conn.getFd
|
||||
@@ -327,13 +330,15 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
else
|
||||
cmd += " --dnsgw %s:8153".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"))
|
||||
|
||||
if (Utils.isLollipopOrAbove) {
|
||||
cmd += " --fake-proc"
|
||||
}
|
||||
// if (Utils.isLollipopOrAbove) {
|
||||
// cmd += " --fake-proc"
|
||||
// }
|
||||
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
|
||||
|
||||
System.exec(cmd)
|
||||
Console.runCommand(cmd)
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@@ -343,8 +348,19 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
startDnsDaemon()
|
||||
startDnsTunnel()
|
||||
}
|
||||
startVpn()
|
||||
true
|
||||
|
||||
val fd = startVpn()
|
||||
|
||||
if (fd == -1) {
|
||||
false
|
||||
} else {
|
||||
Thread.sleep(1000)
|
||||
if (System.sendfd(fd) == -1) {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def onBind(intent: Intent): IBinder = {
|
||||
@@ -477,7 +493,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
}
|
||||
|
||||
// stop the service if no callback registered
|
||||
if (callbackCount == 0) {
|
||||
if (getCallbackCount == 0) {
|
||||
stopSelf()
|
||||
}
|
||||
|
||||
|
||||
@@ -45,11 +45,24 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.BaseAdapter
|
||||
import android.widget.TextView
|
||||
import android.graphics.drawable.Drawable
|
||||
import com.github.shadowsocks.{R}
|
||||
import android.view.View.{OnLongClickListener, OnClickListener}
|
||||
|
||||
case class Item(id: Int, title: String, iconRes: Int,
|
||||
abstract class Item {
|
||||
def id: Int
|
||||
def title: String
|
||||
def click: Int => Unit
|
||||
def longClick: Int => Boolean
|
||||
}
|
||||
|
||||
case class IconItem(id: Int, title: String, iconRes: Int,
|
||||
click: Int => Unit, longClick: Int => Boolean = _ => false)
|
||||
extends Item
|
||||
|
||||
case class DrawableItem(id: Int, title: String, iconRes: Drawable,
|
||||
click: Int => Unit, longClick: Int => Boolean = _ => false)
|
||||
extends Item
|
||||
|
||||
case class Category(title: String)
|
||||
|
||||
@@ -89,7 +102,8 @@ class MenuAdapter(context: Context, var items: List[Any]) extends BaseAdapter {
|
||||
@Override override def getItemViewType(position: Int): Int = {
|
||||
getItem(position) match {
|
||||
case Category => MenuAdapter.CATEGORY
|
||||
case Item => MenuAdapter.ITEM
|
||||
case IconItem => MenuAdapter.ITEM
|
||||
case DrawableItem => MenuAdapter.ITEM
|
||||
case _ => MenuAdapter.UNDEFINED
|
||||
}
|
||||
}
|
||||
@@ -121,9 +135,18 @@ class MenuAdapter(context: Context, var items: List[Any]) extends BaseAdapter {
|
||||
}
|
||||
val tv: TextView = v.asInstanceOf[TextView]
|
||||
tv.setText(value.title)
|
||||
if (value.iconRes != -1) {
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(value.iconRes, 0, 0, 0)
|
||||
|
||||
value match {
|
||||
case iconItem: IconItem =>
|
||||
if (iconItem.iconRes != -1) {
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(iconItem.iconRes, 0, 0, 0)
|
||||
}
|
||||
case drawableItem: DrawableItem =>
|
||||
if (drawableItem.iconRes != null) {
|
||||
tv.setCompoundDrawablesWithIntrinsicBounds(drawableItem.iconRes, null, null, null)
|
||||
}
|
||||
}
|
||||
|
||||
tv.setOnClickListener(new OnClickListener {
|
||||
def onClick(view: View) {
|
||||
val item = view.getTag(R.id.mdItem).asInstanceOf[Item]
|
||||
|
||||
@@ -82,6 +82,9 @@ object ConfigUtils {
|
||||
| label = "local";
|
||||
| ip = 127.0.0.1;
|
||||
| port = %d;
|
||||
| reject = ::/0;
|
||||
| reject_policy = negate;
|
||||
| reject_recursively = on;
|
||||
| timeout = 5;
|
||||
|}
|
||||
|
|
||||
@@ -123,6 +126,8 @@ object ConfigUtils {
|
||||
|server {
|
||||
| label = "local-server";
|
||||
| ip = 127.0.0.1;
|
||||
| uptest = none;
|
||||
| preset = on;
|
||||
| port = %d;
|
||||
| timeout = 5;
|
||||
|}
|
||||
@@ -143,7 +148,7 @@ object ConfigUtils {
|
||||
| cache_dir = "/data/data/com.github.shadowsocks";
|
||||
| server_ip = %s;
|
||||
| server_port = %d;
|
||||
| query_method = udp_tcp;
|
||||
| query_method = tcp_only;
|
||||
| run_ipv4 = on;
|
||||
| min_ttl = 15m;
|
||||
| max_ttl = 1w;
|
||||
@@ -159,22 +164,10 @@ object ConfigUtils {
|
||||
| reject = %s;
|
||||
| reject_policy = fail;
|
||||
| reject_recursively = on;
|
||||
| uptest = query;
|
||||
| query_test_name = ".";
|
||||
| interval = ontimeout;
|
||||
|}
|
||||
|
|
||||
|server {
|
||||
| label= "secure";
|
||||
| port = 443;
|
||||
| ip = 208.67.220.220,113.20.8.17,77.66.84.233,176.56.237.171;
|
||||
| timeout = 3;
|
||||
| reject = %s;
|
||||
| reject_policy = fail;
|
||||
| reject_recursively = on;
|
||||
| uptest = query;
|
||||
| query_test_name = ".";
|
||||
| interval = ontimeout;
|
||||
| exclude = %s;
|
||||
| policy = included;
|
||||
| uptest = none;
|
||||
| preset = on;
|
||||
|}
|
||||
|
|
||||
|server {
|
||||
@@ -218,6 +211,17 @@ object ConfigUtils {
|
||||
}
|
||||
}
|
||||
|
||||
def getBlackList(context: Context, app: ShadowsocksApplication): String = {
|
||||
val default = context.getString(R.string.black_list)
|
||||
try {
|
||||
val container = app.containerHolder.getContainer
|
||||
val update = container.getString("black_list")
|
||||
if (update == null || update.isEmpty) default else update
|
||||
} catch {
|
||||
case ex: Exception => default
|
||||
}
|
||||
}
|
||||
|
||||
def getPublicConfig(context: Context, container: Container, config: Config): Config = {
|
||||
val url = container.getString("proxy_url")
|
||||
val sig = Utils.getSignature(context)
|
||||
|
||||
@@ -40,11 +40,19 @@
|
||||
package com.github.shadowsocks.utils
|
||||
|
||||
import com.github.shadowsocks.database.Profile
|
||||
import java.util.Locale
|
||||
import android.net.Uri
|
||||
import android.util.{Log, Base64}
|
||||
|
||||
object Parser {
|
||||
val TAG = "ShadowParser"
|
||||
|
||||
def generate (profile: Profile): String = {
|
||||
val path = "%s:%s@%s:%d".formatLocal(Locale.ENGLISH,
|
||||
profile.method, profile.password, profile.host, profile.remotePort)
|
||||
return "ss://" + Base64.encodeToString(path.getBytes, Base64.NO_PADDING)
|
||||
}
|
||||
|
||||
def parse (data: String): Option[Profile] = {
|
||||
try {
|
||||
Log.d(TAG, data)
|
||||
@@ -52,17 +60,21 @@ object Parser {
|
||||
if (uri.getScheme == Scheme.SS) {
|
||||
val encoded = data.replace(Scheme.SS + "://", "")
|
||||
val content = new String(Base64.decode(encoded, Base64.NO_PADDING), "UTF-8")
|
||||
val info = content.split('@')
|
||||
val encinfo = info(0).split(':')
|
||||
val serverinfo = info(1).split(':')
|
||||
val methodIdx = content.indexOf(':')
|
||||
val passwordIdx = content.lastIndexOf('@')
|
||||
val hostIdx = content.lastIndexOf(':')
|
||||
val method = content.substring(0, methodIdx)
|
||||
val password = content.substring(methodIdx + 1, passwordIdx)
|
||||
val host = content.substring(passwordIdx + 1, hostIdx)
|
||||
val port = content.substring(hostIdx + 1)
|
||||
|
||||
val profile = new Profile
|
||||
profile.name = serverinfo(0)
|
||||
profile.host = serverinfo(0)
|
||||
profile.remotePort = serverinfo(1).toInt
|
||||
profile.name = host
|
||||
profile.host = host
|
||||
profile.remotePort = port.toInt
|
||||
profile.localPort = 1080
|
||||
profile.method = encinfo(0)
|
||||
profile.password = encinfo(1)
|
||||
profile.method = method.toLowerCase
|
||||
profile.password = password
|
||||
return Some(profile)
|
||||
}
|
||||
} catch {
|
||||
|
||||
Reference in New Issue
Block a user