Compare commits

...
90 Commits
Author SHA1 Message Date
Max Lv faad961804 Merge pull request #330 from shadowsocks/unix-socket
Pass the file descriptor through unix domain socket
2015-07-22 18:42:41 +08:00
Max Lv 2f7424d07b fix an issue 2015-07-22 18:34:18 +08:00
Max Lv fd4015fac2 add unix socket 2015-07-22 18:06:28 +08:00
Max Lv f2c39bd16e update shadowsocks-libev 2015-07-22 14:52:30 +08:00
Max Lv e849a9e2cb Merge branch 'master' of github.com:shadowsocks/shadowsocks-android 2015-07-14 09:15:07 +08:00
Max Lv 524d3b6fdc update shadowsocks-libev 2015-07-14 09:14:50 +08:00
Max Lv 6f5db34a6f Update about.html 2015-07-14 09:12:53 +08:00
Max Lv 3c161be1e4 Update README.md 2015-07-14 09:12:18 +08:00
Max Lv 1c30fdb8f2 update shadowsocks-libev 2015-07-13 09:59:46 +08:00
Max Lv ce24ddb9ed update shadowsocks-libev 2015-07-11 08:45:24 +08:00
Max Lv 17eaf25b4f disable fake proc name 2015-07-09 12:00:06 +08:00
Max Lv f4b171a3d9 Update README.md 2015-06-18 14:37:50 +08:00
Max Lv ae9622a1b3 update shadowsocks-libev 2015-06-15 09:46:10 +08:00
Max Lv 44e1b9daa3 fix #317 2015-06-11 09:11:17 +08:00
Max Lv 7a2c42626b update licenses 2015-06-11 08:51:48 +08:00
Max Lv adb979a111 Merge pull request #312 from haobug/depends
update dependency versions
2015-06-06 15:51:31 +04:00
qinghao 1e23307f95 update dependency versions 2015-06-06 15:38:04 +08:00
Max Lv 64e6f14da1 bump version 2015-05-23 20:26:28 +08:00
Max Lv 3dd718dc01 update shadowsocks-libev 2015-05-18 10:03:29 +08:00
Max Lv 942d181e36 bump version 2015-05-10 20:47:11 +08:00
Max Lv fa083a8eca fix #295 2015-05-08 08:57:40 +08:00
Max Lv ef2ff23cd0 fix the style on lolipop 2015-05-02 22:51:26 +08:00
Max Lv c1e208737c Merge pull request #287 from vmlinz/master
Update sbt and sbt-android-plugin
2015-05-01 14:00:35 +08:00
Zaicheng Qi 75bb00593a Add jcenter resolver and update sbt to 0.13.8 2015-05-01 11:38:30 +08:00
Zaicheng Qi 15f25b95a0 Update sbt-android plugin to latest 2015-05-01 10:55:29 +08:00
Max Lv cc9fa4c4a6 refine the drawer indicator 2015-04-30 17:29:40 +08:00
Max Lv 9041404f42 add partial material design 2015-04-30 16:44:27 +08:00
Max Lv 5aae822cdd add qr code 2015-04-29 13:06:27 +08:00
Max Lv 33ed5c65c5 fix #279 2015-04-22 16:52:02 +08:00
Max Lv 1424e056ac disable IPv6 resolver in all route mode. #275 2015-04-09 17:32:00 +08:00
Max Lv ed79e0090e Update README.md 2015-04-08 17:34:10 +08:00
Max Lv 304113ce97 Update README.md 2015-04-08 14:52:21 +08:00
Max Lv 290bf8cb31 Delete .travis.yml 2015-04-08 14:31:45 +08:00
Max Lv fcb0e2ace3 Update README.md 2015-04-08 14:31:30 +08:00
Max Lv f240d5d202 bump version 2015-03-19 16:43:38 +08:00
Max Lv ea85bbd83d refine DNS on Kitkat 2015-03-19 16:34:22 +08:00
Max Lv d3018fc090 update travis 2015-03-10 16:42:02 +08:00
Max Lv f1f585b4d9 update travis 2015-03-10 16:34:40 +08:00
Max Lv 3653f73e0b update travis 2015-03-10 16:15:31 +08:00
Max Lv d648910aac fix travis 2015-03-10 09:59:30 +08:00
Max Lv 1e2f8c3bd3 Merge pull request #258 from lozen130/patch-1
Fix a coding style issue
2015-03-07 14:35:06 +08:00
Lozen Liu b94c16c725 Fix a coding style issue
Method name should conform to the standard
2015-03-07 14:32:29 +08:00
Max Lv a03a6af5ba update #250 2015-02-25 12:20:29 +08:00
Max Lv b9414c6b0a Merge pull request #249 from Mygod/master
Providing up navigation
2015-02-25 07:44:52 +08:00
Mygod 0d54d9cd9b bugfix 2015-02-24 22:52:57 +08:00
Mygod 8611a66cdc fix indent 2015-02-24 22:38:37 +08:00
Mygod 740dcc3ca9 providing up navigation 2015-02-24 22:34:14 +08:00
Max Lv 730efbafc0 refine URL parser 2015-02-09 18:45:40 +08:00
Max Lv 8b05476823 Merge pull request #241 from cloudtrends/master
add export ANDROID_NDK_HOME variable
2015-02-07 08:37:16 +08:00
ChunFeng 50b890423a add export ANDROID_NDK_HOME variable
add export ANDROID_NDK_HOME variable
2015-02-07 07:57:19 +08:00
Max Lv fb63268895 fix a corner case 2015-01-29 10:20:59 +08:00
Max Lv 41934f8909 try to workaround travis-ci's limit 2015-01-28 13:21:12 +08:00
Max Lv bedc7a0443 add caching to travis 2015-01-28 13:14:00 +08:00
Max Lv 537f790386 fix travis-ci 2015-01-28 13:03:29 +08:00
Max Lv 62afcf51d7 update travis-ci 2015-01-28 12:56:55 +08:00
Max Lv 6c1ae68931 update shadowsocks-libev 2015-01-27 21:00:25 +08:00
Max Lv 2703e91bbe bump version 2015-01-27 17:52:06 +08:00
Max Lv 8fba319db2 fix #228 2015-01-25 13:18:42 +08:00
Max Lv 3e04734b9b update shadowsocks-libev 2015-01-21 20:55:35 +08:00
Max Lv fe33997494 update shadowsocks-libev 2015-01-19 12:08:34 +08:00
Max Lv 86cd49d3e1 update shadowsocks-libev 2015-01-16 13:16:07 +08:00
Max Lv ff13792192 update strings 2015-01-16 13:11:51 +08:00
Max Lv f36a8c784d update shadowsocks-libev 2015-01-13 14:44:58 +08:00
Max Lv 57f8c0f307 disable notification auto-hiding on Kitkat and below #216 2015-01-11 21:26:59 +08:00
Max Lv 601c227644 update shadowsocks-libev 2015-01-08 12:14:54 +08:00
Max Lv 220143aee1 fix #211 2015-01-08 10:44:54 +08:00
Max Lv 81a19c4a81 bump version 2015-01-02 14:16:21 +08:00
Max Lv 27cc53baf8 revert to tcp_only mode 2014-12-28 21:47:43 +08:00
Max Lv 935fddcb15 update submodule 2014-12-28 10:05:12 +08:00
Max Lv 49458080a1 bump version 2014-12-28 09:50:11 +08:00
Max Lv 8101fc935e update shadowsocks 2014-12-27 19:55:33 +08:00
Max Lv 491ebe500f remove https dns query 2014-12-27 08:49:08 +08:00
Max Lv 98ce68774a update black list 2014-12-26 22:08:20 +08:00
Max Lv b0e20552dd refine list 2014-12-26 20:02:26 +08:00
Max Lv 0d478cfbc4 refine reject list 2014-12-26 17:54:35 +08:00
Max Lv d1d135ccdd refine dns black list 2014-12-26 17:30:20 +08:00
Max Lv a28303ee76 update reject list 2014-12-26 16:13:07 +08:00
Max Lv 2b09ebcd2c bump version 2014-12-24 17:38:17 +08:00
Max Lv 59ede2586a update google service 2014-12-24 17:26:48 +08:00
Max Lv abd1d0220c bump version for a build error 2014-12-20 16:42:38 +08:00
Max Lv 5427e00012 fallback to gcc 2014-12-20 10:40:13 +08:00
Max Lv 7f226d3f0c replace crouton with snackbar 2014-12-19 17:32:00 +08:00
Max Lv ee3f3c2338 fix for clang 2014-12-19 13:54:38 +08:00
Max Lv 6ac90abbf7 update OpenSSL's header 2014-12-18 15:29:21 +08:00
Max Lv 2f553b156a fix #188 2014-12-18 14:33:32 +08:00
Max Lv dec098fbc5 refine the lock screen receiver 2014-12-18 09:17:57 +08:00
Max Lv 000d03ad4c update shadowsocks-libev 2014-12-17 08:49:43 +08:00
Max Lv 667619f701 tune timeout for long tcp connection 2014-12-17 08:42:43 +08:00
Max Lv afd91b7155 fix #186 2014-12-15 17:19:40 +08:00
Max Lv e10272c8e5 disable uptest in pdnsd 2014-12-14 14:46:16 +08:00
54 changed files with 10720 additions and 46495 deletions
+3 -3
View File
@@ -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
View File
@@ -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
+17 -6
View File
@@ -6,16 +6,16 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
[![Google Play](http://developer.android.com/images/brand/en_generic_rgb_wo_45.png)](https://play.google.com/store/apps/details?id=com.github.shadowsocks)
### TRAVIS CI STATUS
### CI STATUS
[![Build Status](https://secure.travis-ci.org/shadowsocks/shadowsocks-android.png)](http://travis-ci.org/shadowsocks/shadowsocks-android)
[![Build Status](https://drone.io/github.com/shadowsocks/shadowsocks-android/status.png)](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>
+11 -5
View File
@@ -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.**")
+1 -1
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
sbt.version=0.13.5
sbt.version=0.13.8
+1 -1
View File
@@ -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")
+4 -3
View File
@@ -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"/>
+11
View File
@@ -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
View File
@@ -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 \
+50 -2
View File
@@ -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)) {
+139
View File
@@ -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
+21
View File
@@ -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.
+73
View File
@@ -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)
+131
View File
@@ -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__ */
+98
View File
@@ -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 = &nothing;
nothing_ptr.iov_len = 1;
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = &nothing_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 */
+92
View File
@@ -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 = &nothing;
nothing_ptr.iov_len = 1;
msghdr.msg_name = NULL;
msghdr.msg_namelen = 0;
msghdr.msg_iov = &nothing_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 */
+112
View File
@@ -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);
}
+4 -2
View File
@@ -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
+38
View File
@@ -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;",
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

+1 -1
View File
@@ -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"
+8
View File
@@ -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>
+96
View File
@@ -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>
+16 -6
View File
@@ -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>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -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>
View File
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
View File
@@ -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>
+4 -2
View File
@@ -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>
+16 -5
View File
@@ -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 {