Compare commits

...
72 Commits
Author SHA1 Message Date
Max Lv b272d7ab71 fix #368 2015-09-28 13:07:47 +08:00
Max Lv 09d53033cb update shadowsocks-libev 2015-09-28 10:41:44 +08:00
Max Lv 496c809186 update sdk 2015-09-25 12:32:56 +08:00
Max Lv b58ffb7a95 refine strings 2015-09-25 12:06:10 +08:00
Max Lv 3512542043 fix #366 2015-09-25 09:43:09 +08:00
Max Lv 0c940c8860 update shadowsocks-libev 2015-09-24 18:51:45 +08:00
Max Lv 00253ea3f6 update shadowsocks-libev 2015-09-24 13:08:08 +08:00
Max Lv d836aafe40 refine strings 2015-09-23 16:13:39 +08:00
Max Lv 60360e6a19 update shadowsocks-libev 2015-09-23 13:30:56 +08:00
Max Lv 5939f2776c fix a buffer corruption 2015-09-22 20:36:56 +08:00
Max Lv 0cecc62035 update shadowsocks-libev 2015-09-22 18:34:44 +08:00
Max Lv 7a6fbaca15 bump version 2015-09-21 19:09:16 +08:00
Max Lv 2a3ffd768c update shadowsocks-libev 2015-09-21 14:03:02 +08:00
Max Lv 33b775ea5e update plugin 2015-09-18 16:58:03 +08:00
Max Lv 0be4d39606 update shadowsocks-libev 2015-09-18 12:05:20 +08:00
Max Lv ee7e4c9711 update shadowsocks-libev 2015-09-13 14:30:32 +08:00
Max Lv c1c8ff309c update shadowsocks-libev 2015-09-09 09:12:33 +08:00
Max Lv 8724bf325f update shadowsocks-libev 2015-09-05 19:17:28 +08:00
Max Lv 20395ede5f update shadowsocks-libev 2015-09-04 07:13:59 +08:00
Max Lv 336fa3b775 fix a UI bug 2015-08-31 13:05:45 +08:00
Max Lv 11bfef423a update shadowsocks-libev 2015-08-30 12:09:37 +08:00
Max Lv 6e0534b00f bump version 2015-08-20 15:29:04 +08:00
Max Lv bf960f1a64 fix #350 2015-08-20 15:28:36 +08:00
Max Lv b1e01d2158 fix a typo 2015-08-20 13:08:20 +08:00
Max Lv f344eb783c update chnroute 2015-08-20 13:06:52 +08:00
Max Lv 5f6effba09 Merge pull request #346 from clowwindy/nodelay
add tcp_nagle_disable in tun2socks
2015-08-18 17:34:47 +08:00
clowwindy 97cfd1f869 add tcp_nagle_disable in tun2socks 2015-08-18 17:27:49 +08:00
Max Lv 97bd714beb drop abstract domain socket 2015-08-07 22:30:09 +08:00
Max Lv 9a841e901c refine the exception handling 2015-08-05 12:22:49 +08:00
Max Lv de7e516204 fix MTU 2015-08-05 10:22:45 +08:00
Max Lv c31a5c1951 use abstract namespace 2015-08-04 09:23:36 +08:00
Max Lv 6c47c361f7 update reject list 2015-08-03 14:00:59 +08:00
Max Lv ddd37a3219 update dns 2015-08-03 13:03:30 +08:00
Max Lv 01125d53b3 update shadowsocks-libev 2015-08-03 11:02:40 +08:00
Max Lv 9613d65303 fix a issue of progress dialog 2015-08-02 08:22:20 +08:00
Max Lv a510b11187 update shadowsocks-libev 2015-07-31 16:40:33 +08:00
Max Lv 051e600e59 bump version 2015-07-31 16:30:54 +08:00
Max Lv fea9a6f919 refine the binary update 2015-07-31 16:05:03 +08:00
Max Lv c2c7cabbaf refine dns resolve 2015-07-30 13:35:04 +08:00
Max Lv 092d880c7d refine binary install 2015-07-29 13:49:08 +08:00
Max Lv c208c4bf50 refine profile initilizing 2015-07-28 15:49:05 +08:00
Max Lv 34af6aeef5 refine the IPC to tun2socks 2015-07-28 14:48:21 +08:00
Max Lv d9af2f93e0 fix plugin 2015-07-27 11:09:52 +08:00
Max Lv aae068b7b2 fix a UI issue 2015-07-26 10:22:15 +08:00
Max Lv 7626c1117e bump version 2015-07-26 09:36:04 +08:00
Max Lv 1188b59b05 update shadowsocks-libev 2015-07-26 09:10:46 +08:00
Max Lv cbd46d0c95 enable acl on devices before 5.0 2015-07-26 09:10:17 +08:00
Max Lv 8d02a1a6a4 Merge pull request #334 from shadowsocks/android-ipc
Improve the compatibility by using IPC
2015-07-25 06:59:37 +08:00
Max Lv 9f67636464 update shadowsocks-libev 2015-07-25 06:57:37 +08:00
Max Lv abb97e16c4 play tricks to close fd manually 2015-07-24 23:07:58 +08:00
Max Lv 541f8de2cf close socket properly 2015-07-24 22:35:39 +08:00
Max Lv 7c31f5e5b4 refine IPC handling 2015-07-24 21:38:49 +08:00
Max Lv 809f4c13e0 add management thread 2015-07-24 18:56:01 +08:00
Max Lv 04725803e4 add android ipc feature 2015-07-24 14:15:43 +08:00
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
35 changed files with 1692 additions and 375 deletions
+12 -2
View File
@@ -14,8 +14,8 @@ Help to translate shadowsocks: http://crowdin.net/project/shadowsocks/invite
* JDK 1.7+
* SBT 0.13.0+
* Android SDK r21+
* Android NDK r9+
* Android SDK r24+
* Android NDK r10d+
### BUILD
@@ -58,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>
+5 -3
View File
@@ -31,9 +31,10 @@ 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-base" % "6.5.87",
"com.google.android.gms" % "play-services-ads" % "6.5.87",
"com.android.support" % "support-v4" % "21.0.3"
"com.google.android.gms" % "play-services-base" % "8.1.0",
"com.google.android.gms" % "play-services-ads" % "8.1.0",
"com.google.android.gms" % "play-services-analytics" % "8.1.0",
"com.android.support" % "support-v4" % "23.0.1"
)
libraryDependencies ++= Seq(
@@ -52,5 +53,6 @@ proguardOptions in Android ++= Seq("-keep class android.support.v4.app.** { *; }
"-keep class * extends com.j256.ormlite.** { *; }",
"-keep class com.joanzapata.** { *; }",
"-keepattributes *Annotation*",
"-dontwarn com.google.android.gms.internal.zzhu",
"-dontwarn org.xbill.**",
"-dontwarn com.actionbarsherlock.**")
+2 -2
View File
@@ -7,8 +7,8 @@ function try () {
try pushd src/main
# Build
try $ANDROID_NDK_HOME/ndk-build clean
try $ANDROID_NDK_HOME/ndk-build
#try $ANDROID_NDK_HOME/ndk-build clean
try $ANDROID_NDK_HOME/ndk-build -j8
# copy executables
rm -rf assets/armeabi-v7a
+13 -9
View File
@@ -24,6 +24,8 @@ def main():
"0.0.0.0/8",
"10.0.0.0/8",
"100.64.0.0/10",
"112.124.47.0/24",
"114.114.114.0/24",
"127.0.0.0/8",
"169.254.0.0/16",
"172.16.0.0/12",
@@ -39,16 +41,18 @@ def main():
]))
china_list_set += internal_list
# 取反
all = IPy.IPSet([IPy.IP("0.0.0.0/0")])
# 剔除所有孤立的C段
for ip in china_list_set:
all.discard(ip)
all = china_list_set
filter = itertools.ifilter(lambda x: len(x) <= 65536, all)
for ip in filter:
all.discard(ip)
all.add(IPy.IP(ip.strNormal(0)).make_net('255.255.0.0'))
# 取反
# all = IPy.IPSet([IPy.IP("0.0.0.0/0")])
# 剔除所有孤立的C段
# for ip in china_list_set:
# all.discard(ip)
# filter = itertools.ifilter(lambda x: len(x) <= 65536, all)
# for ip in filter:
# all.discard(ip)
# all.add(IPy.IP(ip.strNormal(0)).make_net('255.255.0.0'))
# 输出结果
for ip in all:
+3 -3
View File
@@ -1,7 +1,7 @@
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.22")
addSbtPlugin("com.hanhuy.sbt" % "android-sdk-plugin" % "1.5.0")
resolvers += Resolver.sbtPluginRepo("snapshots")
resolvers += "Sonatype snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
addSbtPlugin("com.hanhuy.sbt" % "sbt-idea" % "1.7.0-SNAPSHOT")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.7.0-SNAPSHOT")
+2 -2
View File
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.shadowsocks"
android:versionCode="105"
android:versionName="2.6.7">
android:versionCode="117"
android:versionName="2.8.0">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
@@ -10,6 +10,8 @@ public class Config implements Parcelable {
public boolean isBypassApps = false;
public boolean isTrafficStat = false;
public boolean isUdpDns = false;
public boolean isAuth = false;
public boolean isIpv6 = false;
public String profileName = "Untitled";
public String proxy = "127.0.0.1";
@@ -33,13 +35,15 @@ public class Config implements Parcelable {
};
public Config(boolean isGlobalProxy, boolean isGFWList, boolean isBypassApps,
boolean isTrafficStat, boolean isUdpDns, String profileName, String proxy, String sitekey,
boolean isTrafficStat, boolean isUdpDns, boolean isAuth, boolean isIpv6, String profileName, String proxy, String sitekey,
String encMethod, String proxiedAppString, String route, int remotePort, int localPort) {
this.isGlobalProxy = isGlobalProxy;
this.isGFWList = isGFWList;
this.isBypassApps = isBypassApps;
this.isTrafficStat = isTrafficStat;
this.isUdpDns = isUdpDns;
this.isAuth = isAuth;
this.isIpv6 = isIpv6;
this.profileName = profileName;
this.proxy = proxy;
this.sitekey = sitekey;
@@ -60,6 +64,8 @@ public class Config implements Parcelable {
isBypassApps = in.readInt() == 1;
isTrafficStat = in.readInt() == 1;
isUdpDns = in.readInt() == 1;
isAuth = in.readInt() == 1;
isIpv6 = in.readInt() == 1;
profileName = in.readString();
proxy = in.readString();
sitekey = in.readString();
@@ -80,6 +86,8 @@ public class Config implements Parcelable {
out.writeInt(isBypassApps ? 1 : 0);
out.writeInt(isTrafficStat ? 1 : 0);
out.writeInt(isUdpDns ? 1 : 0);
out.writeInt(isAuth ? 1 : 0);
out.writeInt(isIpv6 ? 1 : 0);
out.writeString(profileName);
out.writeString(proxy);
out.writeString(sitekey);
+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,6 @@ public class System {
public static native void exec(String cmd);
public static native String getABI();
public static native int sendfd(int fd);
public static native void jniclose(int fd);
}
+30 -9
View File
@@ -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
########################################################
@@ -234,13 +249,14 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c acl.c
SHADOWSOCKS_SOURCES := local.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c acl.c android.c
LOCAL_MODULE := ss-local
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)/libev \
-I$(LOCAL_PATH)/libancillary \
-I$(LOCAL_PATH)/openssl/include \
-I$(LOCAL_PATH)/shadowsocks-libev/libudns \
-I$(LOCAL_PATH)/shadowsocks-libev/libcork/include \
@@ -248,7 +264,7 @@ LOCAL_CFLAGS := -Wall -O2 -fno-strict-aliasing -DUDPRELAY_LOCAL \
-I$(LOCAL_PATH)/shadowsocks-libev/libsodium/src/libsodium/include/sodium \
-I$(LOCAL_PATH)/shadowsocks-libev/libipset/include
LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork libudns libsodium
LOCAL_STATIC_LIBRARIES := libev libcrypto libipset libcork libudns libsodium libancillary
LOCAL_LDLIBS := -llog
@@ -260,20 +276,21 @@ include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
SHADOWSOCKS_SOURCES := tunnel.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c
SHADOWSOCKS_SOURCES := tunnel.c cache.c udprelay.c encrypt.c utils.c netutils.c json.c jconf.c android.c
LOCAL_MODULE := ss-tunnel
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)/libev \
-I$(LOCAL_PATH)/libancillary \
-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 libcork libudns
LOCAL_STATIC_LIBRARIES := libev libcrypto libsodium libcork libudns libancillary
LOCAL_LDLIBS := -llog
@@ -287,12 +304,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)
@@ -309,7 +327,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 \
+53 -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)) {
@@ -1724,6 +1772,9 @@ err_t listener_accept_func (void *arg, struct tcp_pcb *newpcb, err_t err)
// set client not closed
client->client_closed = 0;
// enable TCP_NODELAY
tcp_nagle_disable(client->pcb);
// setup handler argument
tcp_arg(client->pcb, client);
+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);
}
+44
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,46 @@ void Java_com_github_shadowsocks_system_exec(JNIEnv *env, jobject thiz, jstring
env->ReleaseStringUTFChars(cmd, str);
}
void Java_com_github_shadowsocks_system_jniclose(JNIEnv *env, jobject thiz, jint fd) {
close(fd);
}
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[] = {
{ "jniclose", "(I)V",
(void*) Java_com_github_shadowsocks_system_jniclose },
{ "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;",
+6
View File
@@ -77,6 +77,12 @@
<string name="udp_dns">UDP 转发</string>
<string name="udp_dns_summary">由远程服务器转发 UDP 协议的数据包</string>
<string name="onetime_auth">一次性认证</string>
<string name="onetime_auth_summary">启用一次性认证(实验性)</string>
<string name="ipv6">IPv6 路由</string>
<string name="ipv6_summary">向远程服务器转发 IPv6 流量</string>
<!-- profile -->
<string name="add_profile_dialog">为影梭添加此配置文件?</string>
<string-array name="add_profile_methods">
+35 -1
View File
@@ -85,7 +85,41 @@
<item>101.0.0.0/8</item>
<item>102.0.0.0/7</item>
<item>104.0.0.0/5</item>
<item>112.0.0.0/5</item>
<item>112.0.0.0/10</item>
<item>112.64.0.0/11</item>
<item>112.96.0.0/12</item>
<item>112.112.0.0/13</item>
<item>112.120.0.0/14</item>
<item>112.124.0.0/19</item>
<item>112.124.32.0/21</item>
<item>112.124.40.0/22</item>
<item>112.124.44.0/23</item>
<item>112.124.46.0/24</item>
<item>112.124.48.0/20</item>
<item>112.124.64.0/18</item>
<item>112.124.128.0/17</item>
<item>112.125.0.0/16</item>
<item>112.126.0.0/15</item>
<item>112.128.0.0/9</item>
<item>113.0.0.0/8</item>
<item>114.0.0.0/10</item>
<item>114.64.0.0/11</item>
<item>114.96.0.0/12</item>
<item>114.112.0.0/15</item>
<item>114.114.0.0/18</item>
<item>114.114.64.0/19</item>
<item>114.114.96.0/20</item>
<item>114.114.112.0/23</item>
<item>114.114.115.0/24</item>
<item>114.114.116.0/22</item>
<item>114.114.120.0/21</item>
<item>114.114.128.0/17</item>
<item>114.115.0.0/16</item>
<item>114.116.0.0/14</item>
<item>114.120.0.0/13</item>
<item>114.128.0.0/9</item>
<item>115.0.0.0/8</item>
<item>116.0.0.0/6</item>
<item>120.0.0.0/6</item>
<item>124.0.0.0/7</item>
<item>126.0.0.0/8</item>
+292 -2
View File
@@ -321,6 +321,10 @@
<item>43.239.0.0/19</item>
<item>43.239.32.0/20</item>
<item>43.239.48.0/22</item>
<item>43.239.116.0/22</item>
<item>43.239.120.0/22</item>
<item>43.239.172.0/22</item>
<item>43.239.176.0/22</item>
<item>43.240.0.0/22</item>
<item>43.240.48.0/22</item>
<item>43.240.56.0/21</item>
@@ -505,6 +509,154 @@
<item>43.255.232.0/22</item>
<item>43.255.244.0/22</item>
<item>45.64.112.0/23</item>
<item>45.112.132.0/22</item>
<item>45.112.188.0/22</item>
<item>45.112.208.0/20</item>
<item>45.112.228.0/22</item>
<item>45.112.232.0/21</item>
<item>45.113.12.0/22</item>
<item>45.113.16.0/20</item>
<item>45.113.40.0/22</item>
<item>45.113.52.0/22</item>
<item>45.113.56.0/22</item>
<item>45.113.72.0/22</item>
<item>45.113.108.0/22</item>
<item>45.113.144.0/21</item>
<item>45.113.168.0/22</item>
<item>45.113.176.0/22</item>
<item>45.113.184.0/22</item>
<item>45.113.200.0/21</item>
<item>45.113.208.0/20</item>
<item>45.113.228.0/22</item>
<item>45.113.240.0/22</item>
<item>45.113.252.0/22</item>
<item>45.114.0.0/22</item>
<item>45.114.12.0/22</item>
<item>45.114.32.0/22</item>
<item>45.114.40.0/22</item>
<item>45.114.52.0/22</item>
<item>45.114.96.0/22</item>
<item>45.114.104.0/22</item>
<item>45.114.136.0/22</item>
<item>45.114.196.0/22</item>
<item>45.114.200.0/22</item>
<item>45.114.228.0/22</item>
<item>45.114.236.0/22</item>
<item>45.114.252.0/22</item>
<item>45.115.44.0/22</item>
<item>45.115.100.0/22</item>
<item>45.115.120.0/22</item>
<item>45.115.132.0/22</item>
<item>45.115.144.0/22</item>
<item>45.115.156.0/22</item>
<item>45.115.164.0/22</item>
<item>45.115.200.0/22</item>
<item>45.115.212.0/22</item>
<item>45.115.216.0/22</item>
<item>45.115.228.0/22</item>
<item>45.115.236.0/22</item>
<item>45.115.244.0/22</item>
<item>45.115.248.0/22</item>
<item>45.116.12.0/22</item>
<item>45.116.16.0/21</item>
<item>45.116.24.0/22</item>
<item>45.116.32.0/21</item>
<item>45.116.52.0/22</item>
<item>45.116.60.0/22</item>
<item>45.116.64.0/22</item>
<item>45.116.96.0/21</item>
<item>45.116.140.0/22</item>
<item>45.116.152.0/22</item>
<item>45.116.208.0/22</item>
<item>45.117.8.0/22</item>
<item>45.117.20.0/22</item>
<item>45.117.40.0/22</item>
<item>45.117.68.0/22</item>
<item>45.117.124.0/22</item>
<item>45.117.252.0/22</item>
<item>45.119.52.0/22</item>
<item>45.119.60.0/22</item>
<item>45.119.64.0/21</item>
<item>45.119.72.0/22</item>
<item>45.119.104.0/22</item>
<item>45.119.116.0/22</item>
<item>45.119.160.0/22</item>
<item>45.119.232.0/22</item>
<item>45.120.100.0/22</item>
<item>45.120.140.0/22</item>
<item>45.120.156.0/22</item>
<item>45.120.164.0/22</item>
<item>45.120.220.0/22</item>
<item>45.120.240.0/22</item>
<item>45.121.20.0/22</item>
<item>45.121.52.0/22</item>
<item>45.121.64.0/21</item>
<item>45.121.72.0/22</item>
<item>45.121.92.0/22</item>
<item>45.121.96.0/22</item>
<item>45.121.104.0/22</item>
<item>45.121.172.0/22</item>
<item>45.121.176.0/22</item>
<item>45.121.212.0/22</item>
<item>45.121.240.0/20</item>
<item>45.122.0.0/19</item>
<item>45.122.32.0/21</item>
<item>45.122.40.0/22</item>
<item>45.122.60.0/22</item>
<item>45.122.64.0/19</item>
<item>45.122.96.0/20</item>
<item>45.122.112.0/21</item>
<item>45.122.160.0/19</item>
<item>45.122.192.0/20</item>
<item>45.122.208.0/21</item>
<item>45.122.216.0/22</item>
<item>45.123.28.0/22</item>
<item>45.123.32.0/21</item>
<item>45.123.44.0/22</item>
<item>45.123.48.0/20</item>
<item>45.123.64.0/20</item>
<item>45.123.80.0/21</item>
<item>45.123.88.0/22</item>
<item>45.123.120.0/22</item>
<item>45.123.128.0/21</item>
<item>45.123.136.0/22</item>
<item>45.123.148.0/22</item>
<item>45.123.152.0/21</item>
<item>45.123.164.0/22</item>
<item>45.123.168.0/21</item>
<item>45.123.176.0/21</item>
<item>45.123.184.0/22</item>
<item>45.123.204.0/22</item>
<item>45.123.212.0/22</item>
<item>45.123.224.0/19</item>
<item>45.124.0.0/22</item>
<item>45.124.20.0/22</item>
<item>45.124.28.0/22</item>
<item>45.124.32.0/21</item>
<item>45.124.44.0/22</item>
<item>45.124.68.0/22</item>
<item>45.124.76.0/22</item>
<item>45.124.80.0/22</item>
<item>45.124.100.0/22</item>
<item>45.124.124.0/22</item>
<item>45.124.172.0/22</item>
<item>45.124.176.0/22</item>
<item>45.124.208.0/22</item>
<item>45.124.248.0/21</item>
<item>45.125.12.0/22</item>
<item>45.125.16.0/22</item>
<item>45.125.24.0/21</item>
<item>45.125.32.0/22</item>
<item>45.125.44.0/22</item>
<item>45.125.52.0/22</item>
<item>45.125.56.0/22</item>
<item>45.125.76.0/22</item>
<item>45.125.80.0/20</item>
<item>45.125.96.0/21</item>
<item>45.125.104.0/22</item>
<item>45.125.136.0/22</item>
<item>47.92.0.0/14</item>
<item>47.96.0.0/11</item>
<item>49.4.0.0/14</item>
<item>49.51.0.0/16</item>
<item>49.52.0.0/14</item>
@@ -803,7 +955,6 @@
<item>103.30.96.0/22</item>
<item>103.30.148.0/22</item>
<item>103.30.200.0/22</item>
<item>103.30.216.0/22</item>
<item>103.30.228.0/22</item>
<item>103.30.236.0/22</item>
<item>103.31.0.0/22</item>
@@ -818,6 +969,8 @@
<item>103.35.0.0/19</item>
<item>103.35.32.0/20</item>
<item>103.35.48.0/22</item>
<item>103.35.104.0/22</item>
<item>103.35.116.0/22</item>
<item>103.36.20.0/22</item>
<item>103.36.28.0/22</item>
<item>103.36.36.0/22</item>
@@ -1004,6 +1157,142 @@
<item>103.50.224.0/20</item>
<item>103.50.240.0/21</item>
<item>103.50.248.0/22</item>
<item>103.52.40.0/22</item>
<item>103.52.72.0/21</item>
<item>103.52.80.0/21</item>
<item>103.52.96.0/21</item>
<item>103.52.104.0/22</item>
<item>103.52.160.0/21</item>
<item>103.52.172.0/22</item>
<item>103.52.176.0/22</item>
<item>103.52.184.0/22</item>
<item>103.52.196.0/22</item>
<item>103.53.4.0/22</item>
<item>103.53.64.0/21</item>
<item>103.53.92.0/22</item>
<item>103.53.100.0/22</item>
<item>103.53.124.0/22</item>
<item>103.53.128.0/20</item>
<item>103.53.144.0/22</item>
<item>103.53.160.0/22</item>
<item>103.53.180.0/22</item>
<item>103.53.204.0/22</item>
<item>103.53.208.0/22</item>
<item>103.53.216.0/22</item>
<item>103.53.236.0/22</item>
<item>103.53.248.0/22</item>
<item>103.54.8.0/22</item>
<item>103.54.48.0/22</item>
<item>103.54.60.0/22</item>
<item>103.54.160.0/21</item>
<item>103.54.212.0/22</item>
<item>103.54.228.0/22</item>
<item>103.54.240.0/22</item>
<item>103.55.24.0/22</item>
<item>103.55.80.0/22</item>
<item>103.55.120.0/22</item>
<item>103.55.152.0/22</item>
<item>103.55.172.0/22</item>
<item>103.55.204.0/22</item>
<item>103.55.208.0/22</item>
<item>103.55.228.0/22</item>
<item>103.55.236.0/22</item>
<item>103.55.240.0/22</item>
<item>103.56.8.0/22</item>
<item>103.56.16.0/21</item>
<item>103.56.32.0/22</item>
<item>103.56.52.0/22</item>
<item>103.56.56.0/21</item>
<item>103.56.72.0/21</item>
<item>103.56.100.0/22</item>
<item>103.56.104.0/22</item>
<item>103.56.140.0/22</item>
<item>103.56.152.0/22</item>
<item>103.56.184.0/22</item>
<item>103.56.200.0/22</item>
<item>103.56.216.0/22</item>
<item>103.57.12.0/22</item>
<item>103.57.52.0/22</item>
<item>103.57.56.0/22</item>
<item>103.57.76.0/22</item>
<item>103.57.108.0/22</item>
<item>103.57.136.0/22</item>
<item>103.57.196.0/22</item>
<item>103.58.24.0/22</item>
<item>103.58.182.0/23</item>
<item>103.59.76.0/22</item>
<item>103.59.100.0/22</item>
<item>103.59.112.0/20</item>
<item>103.59.128.0/22</item>
<item>103.59.148.0/22</item>
<item>103.59.164.0/22</item>
<item>103.59.216.0/22</item>
<item>103.60.32.0/22</item>
<item>103.60.44.0/22</item>
<item>103.60.164.0/22</item>
<item>103.60.228.0/22</item>
<item>103.60.236.0/22</item>
<item>103.61.60.0/22</item>
<item>103.61.104.0/22</item>
<item>103.61.140.0/22</item>
<item>103.61.152.0/21</item>
<item>103.61.160.0/22</item>
<item>103.61.172.0/22</item>
<item>103.61.176.0/22</item>
<item>103.61.184.0/21</item>
<item>103.62.24.0/22</item>
<item>103.62.52.0/22</item>
<item>103.62.72.0/21</item>
<item>103.62.80.0/21</item>
<item>103.62.88.0/22</item>
<item>103.62.96.0/19</item>
<item>103.62.128.0/21</item>
<item>103.62.156.0/22</item>
<item>103.62.160.0/19</item>
<item>103.62.192.0/22</item>
<item>103.62.204.0/22</item>
<item>103.62.208.0/20</item>
<item>103.62.224.0/22</item>
<item>103.63.32.0/19</item>
<item>103.63.64.0/20</item>
<item>103.63.80.0/21</item>
<item>103.63.88.0/22</item>
<item>103.63.140.0/22</item>
<item>103.63.144.0/22</item>
<item>103.63.152.0/22</item>
<item>103.63.160.0/20</item>
<item>103.63.176.0/21</item>
<item>103.63.184.0/22</item>
<item>103.63.192.0/20</item>
<item>103.63.208.0/22</item>
<item>103.63.240.0/20</item>
<item>103.192.0.0/19</item>
<item>103.192.48.0/21</item>
<item>103.192.56.0/22</item>
<item>103.192.84.0/22</item>
<item>103.192.88.0/21</item>
<item>103.192.96.0/20</item>
<item>103.192.112.0/22</item>
<item>103.192.128.0/20</item>
<item>103.192.144.0/22</item>
<item>103.192.164.0/22</item>
<item>103.192.188.0/22</item>
<item>103.192.208.0/21</item>
<item>103.192.216.0/22</item>
<item>103.192.252.0/22</item>
<item>103.193.40.0/21</item>
<item>103.193.120.0/21</item>
<item>103.193.140.0/22</item>
<item>103.193.144.0/21</item>
<item>103.193.160.0/22</item>
<item>103.193.188.0/22</item>
<item>103.193.192.0/22</item>
<item>103.193.212.0/22</item>
<item>103.193.216.0/21</item>
<item>103.193.224.0/20</item>
<item>103.193.240.0/22</item>
<item>103.194.16.0/22</item>
<item>103.194.230.0/23</item>
<item>103.224.40.0/21</item>
<item>103.224.60.0/22</item>
<item>103.224.80.0/22</item>
@@ -1096,6 +1385,7 @@
<item>103.236.0.0/18</item>
<item>103.236.64.0/19</item>
<item>103.236.96.0/22</item>
<item>103.236.120.0/22</item>
<item>103.237.0.0/20</item>
<item>103.237.24.0/21</item>
<item>103.237.68.0/22</item>
@@ -1936,6 +2226,7 @@
<item>166.111.0.0/16</item>
<item>167.139.0.0/16</item>
<item>167.189.0.0/16</item>
<item>167.220.244.0/22</item>
<item>168.160.0.0/16</item>
<item>169.254.0.0/16</item>
<item>171.8.0.0/13</item>
@@ -3363,7 +3654,6 @@
<item>210.26.0.0/15</item>
<item>210.28.0.0/14</item>
<item>210.32.0.0/12</item>
<item>210.48.136.0/21</item>
<item>210.51.0.0/16</item>
<item>210.52.0.0/15</item>
<item>210.56.192.0/19</item>
File diff suppressed because one or more lines are too long
+6 -2
View File
@@ -25,10 +25,14 @@
<!-- feature category -->
<string name="feature_cat">Feature Settings</string>
<string name="ipv6">IPv6 Route</string>
<string name="ipv6_summary">Redirect IPv6 traffic to remote</string>
<string name="onetime_auth">One-time Authentication</string>
<string name="onetime_auth_summary">Enable one-time authentication (Experimental)</string>
<string name="http_proxy">HTTP Proxy</string>
<string name="http_proxy_summary">Local HTTP Proxy</string>
<string name="dns_proxy">DNS Proxy</string>
<string name="dns_proxy_summary">Redirect DNS queries to remote server</string>
<string name="dns_proxy_summary">Redirect DNS queries to remote</string>
<string name="auto_set_gfwlist">CHN Route</string>
<string name="auto_set_gfwlist_summary">Bypass all sites located in China
</string>
@@ -46,7 +50,7 @@
<string name="traffic_stat">Traffic Stats</string>
<string name="traffic_stat_summary">Show traffic stats in notification bar</string>
<string name="udp_dns">UDP Forwarding</string>
<string name="udp_dns_summary">Forward UDP packets to remote server</string>
<string name="udp_dns_summary">Forward UDP packets to remote</string>
<!-- notification category -->
<string name="forward_success">Shadowsocks started.</string>
+12
View File
@@ -58,6 +58,12 @@
android:summary="@string/route_list_summary"
android:title="@string/route_list">
</com.github.shadowsocks.preferences.SummaryListPreference>
<CheckBoxPreference
android:key="isIpv6"
android:defaultValue="false"
android:summary="@string/ipv6_summary"
android:title="@string/ipv6">
</CheckBoxPreference>
<CheckBoxPreference
android:defaultValue="true"
android:key="isGlobalProxy"
@@ -78,6 +84,12 @@
android:summary="@string/udp_dns_summary"
android:title="@string/udp_dns">
</CheckBoxPreference>
<CheckBoxPreference
android:key="isAuth"
android:defaultValue="false"
android:summary="@string/onetime_auth_summary"
android:title="@string/onetime_auth">
</CheckBoxPreference>
<CheckBoxPreference
android:key="isAutoConnect"
android:summary="@string/auto_connect_summary"
@@ -127,7 +127,7 @@ object Shadowsocks {
val PROXY_PREFS = Array(Key.profileName, Key.proxy, Key.remotePort, Key.localPort, Key.sitekey,
Key.encMethod)
val FEATRUE_PREFS = Array(Key.route, Key.isGlobalProxy, Key.proxyedApps,
Key.isUdpDns, Key.isAutoConnect)
Key.isUdpDns, Key.isAuth, Key.isIpv6, Key.isAutoConnect)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL, Executable.TUN2SOCKS)
@@ -166,6 +166,8 @@ object Shadowsocks {
case Key.route => updateListPreference(pref, profile.route)
case Key.isGlobalProxy => updateCheckBoxPreference(pref, profile.global)
case Key.isUdpDns => updateCheckBoxPreference(pref, profile.udpdns)
case Key.isAuth => updateCheckBoxPreference(pref, profile.auth)
case Key.isIpv6 => updateCheckBoxPreference(pref, profile.ipv6)
case _ =>
}
}
@@ -185,6 +187,7 @@ class Shadowsocks
// Variables
var switchButton: Switch = null
var progressDialog: ProgressDialog = null
var progressTag = -1
var state = State.INIT
var prepared = false
var currentProfile = new Profile
@@ -218,6 +221,11 @@ class Shadowsocks
state = bgService.getState
// set the listener
switchButton.setOnCheckedChangeListener(Shadowsocks.this)
if (!status.getBoolean(getVersionName, false)) {
status.edit.putBoolean(getVersionName, true).commit()
recovery();
}
}
override def onServiceDisconnected(name: ComponentName) {
@@ -271,9 +279,10 @@ class Shadowsocks
switchButton.setOnCheckedChangeListener(this)
}
private def showProgress(msg: String): Handler = {
private def showProgress(msg: Int): Handler = {
clearDialog()
progressDialog = ProgressDialog.show(this, "", msg, true, false)
progressDialog = ProgressDialog.show(this, "", getString(msg), true, false)
progressTag = msg
new Handler {
override def handleMessage(msg: Message) {
clearDialog()
@@ -397,7 +406,7 @@ class Shadowsocks
}
def prepareStartService() {
showProgress(getString(R.string.connecting))
showProgress(R.string.connecting)
spawn {
if (isVpnEnabled) {
val intent = VpnService.prepare(this)
@@ -474,22 +483,16 @@ class Shadowsocks
addPreferencesFromResource(R.xml.pref_all)
// Update the profile
if (!status.getBoolean(getVersionName, false)) {
currentProfile = profileManager.create()
}
// Initialize the profile
currentProfile = {
profileManager.getProfile(settings.getInt(Key.profileId, -1)) getOrElse currentProfile
}
// Update the profile
if (!status.getBoolean(getVersionName, false)) {
val h = showProgress(getString(R.string.initializing))
status.edit.putBoolean(getVersionName, true).apply()
spawn {
reset()
currentProfile = profileManager.create()
h.sendEmptyMessage(0)
}
}
// Initialize drawer
menuAdapter.setActiveId(settings.getInt(Key.profileId, -1))
menuAdapter.setListener(this)
@@ -617,7 +620,7 @@ class Shadowsocks
which match {
case 0 =>
dialog.dismiss()
val h = showProgress(getString(R.string.loading))
val h = showProgress(R.string.loading)
h.postDelayed(new Runnable() {
def run() {
val integrator = new IntentIntegrator(Shadowsocks.this)
@@ -641,7 +644,7 @@ class Shadowsocks
def reloadProfile() {
drawer.closeMenu(true)
val h = showProgress(getString(R.string.loading))
val h = showProgress(R.string.loading)
handler.postDelayed(new Runnable {
def run() {
@@ -660,7 +663,7 @@ class Shadowsocks
def addProfile(profile: Profile) {
drawer.closeMenu(true)
val h = showProgress(getString(R.string.loading))
val h = showProgress(R.string.loading)
handler.postDelayed(new Runnable {
def run() {
@@ -679,7 +682,7 @@ class Shadowsocks
def addProfile(id: Int) {
drawer.closeMenu(true)
val h = showProgress(getString(R.string.loading))
val h = showProgress(R.string.loading)
handler.postDelayed(new Runnable {
def run() {
@@ -697,7 +700,7 @@ class Shadowsocks
def updateProfile(id: Int) {
drawer.closeMenu(true)
val h = showProgress(getString(R.string.loading))
val h = showProgress(R.string.loading)
handler.postDelayed(new Runnable {
def run() {
@@ -847,7 +850,8 @@ class Shadowsocks
ConfigUtils.refresh(this)
// Check if profile list changed
if (currentProfile.id != settings.getInt(Key.profileId, -1))
val id = settings.getInt(Key.profileId, -1)
if (id != -1 && id != currentProfile.id)
reloadProfile()
}
@@ -915,10 +919,7 @@ class Shadowsocks
Console.runRootCommand(ab.toArray)
}
def reset() {
crashRecovery()
def install() {
copyAssets(System.getABI)
val ab = new ArrayBuffer[String]
@@ -926,12 +927,18 @@ class Shadowsocks
ab.append("chmod 755 " + Path.BASE + executable)
}
Console.runCommand(ab.toArray)
}
def reset() {
crashRecovery()
install()
}
private def recovery() {
val h = showProgress(getString(R.string.recovering))
serviceStop()
val h = showProgress(R.string.recovering)
spawn {
reset()
h.sendEmptyMessage(0)
@@ -964,7 +971,7 @@ class Shadowsocks
}
private def flushDnsCache() {
val h = showProgress(getString(R.string.flushing))
val h = showProgress(R.string.flushing)
spawn {
Utils.toggleAirplaneMode(getBaseContext)
h.sendEmptyMessage(0)
@@ -1082,6 +1089,7 @@ class Shadowsocks
if (progressDialog != null) {
progressDialog.dismiss()
progressDialog = null
progressTag = -1
}
}
@@ -1095,14 +1103,19 @@ class Shadowsocks
if (progressDialog == null) {
progressDialog = ProgressDialog
.show(Shadowsocks.this, "", getString(R.string.connecting), true, true)
progressTag = R.string.connecting
}
setPreferenceEnabled(enabled = false)
case State.CONNECTED =>
clearDialog()
if (progressTag == R.string.connecting) {
clearDialog()
}
changeSwitch(checked = true)
setPreferenceEnabled(enabled = false)
case State.STOPPED =>
clearDialog()
if (progressTag == R.string.stopping || progressTag == R.string.connecting) {
clearDialog()
}
changeSwitch(checked = false)
if (m != null) {
new SnackBar.Builder(Shadowsocks.this)
@@ -1117,6 +1130,7 @@ class Shadowsocks
if (progressDialog == null) {
progressDialog = ProgressDialog
.show(Shadowsocks.this, "", getString(R.string.stopping), true, true)
progressTag = R.string.stopping
}
}
}
@@ -205,6 +205,8 @@ class ShadowsocksNatService extends Service with BaseService {
, "-c" , Path.BASE + "ss-local-nat.conf"
, "-f" , Path.BASE + "ss-local-nat.pid")
if (config.isAuth) cmd += "-A"
if (config.route != Route.ALL) {
cmd += "--acl"
cmd += (Path.BASE + "acl.list")
@@ -233,6 +235,8 @@ class ShadowsocksNatService extends Service with BaseService {
cmd += ("-l" , "8153")
if (config.isAuth) cmd += "-A"
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Console.runCommand(cmd.mkString(" "))
@@ -254,6 +258,8 @@ class ShadowsocksNatService extends Service with BaseService {
, "-c" , Path.BASE + "ss-tunnel-nat.conf"
, "-f" , Path.BASE + "ss-tunnel-nat.pid")
if (config.isAuth) cmdBuf += "-A"
if (BuildConfig.DEBUG) Log.d(TAG, cmdBuf.mkString(" "))
Console.runCommand(cmdBuf.mkString(" "))
}
@@ -265,10 +271,10 @@ class ShadowsocksNatService extends Service with BaseService {
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, blackList, 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)
Path.BASE + "pdnsd-nat.pid", 8163, "")
}
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-nat.conf"))(p => {
@@ -61,18 +61,17 @@ import scala.concurrent.ops._
class ShadowsocksVpnService extends VpnService with BaseService {
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
val TAG = "ShadowsocksVpnService"
val VPN_MTU = 1500
val PRIVATE_VLAN = "26.26.26.%s"
val PRIVATE_VLAN6 = "fdfe:dcba:9876::%s"
var conn: ParcelFileDescriptor = null
var notificationManager: NotificationManager = null
var receiver: BroadcastReceiver = null
var apps: Array[ProxiedApp] = null
var config: Config = null
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
var vpnThread: ShadowsocksVpnThread = null
def isByass(net: SubnetUtils): Boolean = {
val info = net.getInfo
@@ -95,81 +94,70 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
}
def startShadowsocksDaemon() {
if (Utils.isLollipopOrAbove && config.route != Route.ALL) {
val acl: Array[String] = config.route match {
case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
}
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
acl.foreach(item => p.println(item))
})
override def onBind(intent: Intent): IBinder = {
val action = intent.getAction
if (VpnService.SERVICE_INTERFACE == action) {
return super.onBind(intent)
} else if (Action.SERVICE == action) {
return binder
}
val conf = ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, config.localPort,
config.sitekey, config.encMethod, 10)
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd +=(Path.BASE + "ss-local", "-u"
, "-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"
cmd += (Path.BASE + "acl.list")
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Console.runCommand(cmd.mkString(" "))
null
}
def startDnsTunnel() = {
val conf = ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8163,
config.sitekey, config.encMethod, 10)
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd +=(Path.BASE + "ss-tunnel"
, "-u"
, "-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")
override def onCreate() {
super.onCreate()
ConfigUtils.refresh(this)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE)
.asInstanceOf[NotificationManager]
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Console.runCommand(cmd.mkString(" "))
}
def startDnsDaemon() {
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, "0.0.0.0", 8153,
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)
}
}
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => {
p.println(conf)
})
val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-vpn.conf"
override def onRevoke() {
stopRunner()
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Console.runCommand(cmd)
override def stopRunner() {
if (vpnThread != null) {
vpnThread.stopThread()
vpnThread = null
}
// channge the state
changeState(State.STOPPING)
// send event
application.tracker.send(new HitBuilders.EventBuilder()
.setCategory(TAG)
.setAction("stop")
.setLabel(getVersionName)
.build())
// reset VPN
killProcesses()
// close connections
if (conn != null) {
conn.close()
conn = null
}
// stop the service if no callback registered
if (getCallbackCount == 0) {
stopSelf()
}
// clean up the context
if (receiver != null) {
unregisterReceiver(receiver)
receiver = null
}
// channge the state
changeState(State.STOPPED)
}
def getVersionName: String = {
@@ -184,195 +172,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
version
}
def startVpn() {
val builder = new Builder()
builder
.setSession(config.profileName)
.setMtu(VPN_MTU)
.addAddress(PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"), 24)
.addDnsServer("8.8.8.8")
if (Utils.isLollipopOrAbove) {
builder.allowFamily(android.system.OsConstants.AF_INET6)
if (!config.isGlobalProxy) {
val apps = AppManager.getProxiedApps(this, config.proxiedAppString)
val pkgSet: mutable.HashSet[String] = new mutable.HashSet[String]
for (app <- apps) {
if (app.proxied) {
pkgSet.add(app.packageName)
}
}
for (pkg <- pkgSet) {
if (!config.isBypassApps) {
builder.addAllowedApplication(pkg)
} else {
builder.addDisallowedApplication(pkg)
}
}
if (config.isBypassApps) {
builder.addDisallowedApplication(this.getPackageName)
}
} else {
builder.addDisallowedApplication(this.getPackageName)
}
}
if (InetAddressUtils.isIPv6Address(config.proxy)) {
builder.addRoute("0.0.0.0", 0)
} else {
if (!Utils.isLollipopOrAbove) {
config.route match {
case Route.BYPASS_LAN =>
for (i <- 1 to 223) {
if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0"
val cidr = addr + "/8"
val net = new SubnetUtils(cidr)
if (!isByass(net) && !isPrivateA(i)) {
builder.addRoute(addr, 8)
} else {
for (j <- 0 to 255) {
val subAddr = i.toString + "." + j.toString + ".0.0"
val subCidr = subAddr + "/16"
val subNet = new SubnetUtils(subCidr)
if (!isByass(subNet) && !isPrivateB(i, j)) {
builder.addRoute(subAddr, 16)
}
}
}
}
}
case Route.BYPASS_CHN =>
val list = {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
getResources.getStringArray(R.array.simple_route)
} else {
getResources.getStringArray(R.array.gfw_route)
}
}
list.foreach(cidr => {
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
}
})
case Route.ALL =>
for (i <- 1 to 223) {
if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0"
val cidr = addr + "/8"
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
builder.addRoute(addr, 8)
} else {
for (j <- 0 to 255) {
val subAddr = i.toString + "." + j.toString + ".0.0"
val subCidr = subAddr + "/16"
val subNet = new SubnetUtils(subCidr)
if (!isByass(subNet)) {
builder.addRoute(subAddr, 16)
}
}
}
}
}
}
} else {
if (config.route == Route.ALL) {
builder.addRoute("0.0.0.0", 0)
} else {
val privateList = getResources.getStringArray(R.array.bypass_private_route)
privateList.foreach(cidr => {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
})
}
}
}
builder.addRoute("8.8.0.0", 16)
try {
conn = builder.establish()
} catch {
case ex: IllegalStateException =>
changeState(State.STOPPED, ex.getMessage)
conn = null
case ex: Exception => conn = null
}
if (conn == null) {
stopRunner()
return
}
val fd = conn.getFd
var cmd = (Path.BASE +
"tun2socks --netif-ipaddr %s "
+ "--netif-netmask 255.255.255.0 "
+ "--socks-server-addr 127.0.0.1:%d "
+ "--tunfd %d "
+ "--tunmtu %d "
+ "--loglevel 3 "
+ "--pid %stun2socks-vpn.pid")
.formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"), config.localPort, fd, VPN_MTU, Path.BASE)
if (config.isUdpDns)
cmd += " --enable-udprelay"
else
cmd += " --dnsgw %s:8153".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"))
if (Utils.isLollipopOrAbove) {
cmd += " --fake-proc"
}
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
System.exec(cmd)
}
/** Called when the activity is first created. */
def handleConnection: Boolean = {
startShadowsocksDaemon()
if (!config.isUdpDns) {
startDnsDaemon()
startDnsTunnel()
}
startVpn()
true
}
override def onBind(intent: Intent): IBinder = {
val action = intent.getAction
if (VpnService.SERVICE_INTERFACE == action) {
return super.onBind(intent)
} else if (Action.SERVICE == action) {
return binder
}
null
}
override def onCreate() {
super.onCreate()
ConfigUtils.refresh(this)
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE)
.asInstanceOf[NotificationManager]
}
override def onRevoke() {
stopRunner()
}
def killProcesses() {
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "tun2socks")) {
try {
@@ -386,6 +185,9 @@ class ShadowsocksVpnService extends VpnService with BaseService {
override def startRunner(c: Config) {
vpnThread = new ShadowsocksVpnThread(this)
vpnThread.start()
config = c
// ensure the VPNService is prepared
@@ -458,40 +260,201 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
}
override def stopRunner() {
// channge the state
changeState(State.STOPPING)
// send event
application.tracker.send(new HitBuilders.EventBuilder()
.setCategory(TAG)
.setAction("stop")
.setLabel(getVersionName)
.build())
// reset VPN
killProcesses()
// close connections
if (conn != null) {
conn.close()
conn = null
/** Called when the activity is first created. */
def handleConnection: Boolean = {
startShadowsocksDaemon()
if (!config.isUdpDns) {
startDnsDaemon()
startDnsTunnel()
}
// stop the service if no callback registered
if (getCallbackCount == 0) {
stopSelf()
val fd = startVpn()
if (fd != -1) {
var tries = 1
while (tries < 5) {
Thread.sleep(1000 * tries)
if (System.sendfd(fd) != -1) {
return true
}
tries += 1
}
}
false
}
def startShadowsocksDaemon() {
if (config.route != Route.ALL) {
val acl: Array[String] = config.route match {
case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
}
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
acl.foreach(item => p.println(item))
})
}
// clean up the context
if (receiver != null) {
unregisterReceiver(receiver)
receiver = null
val conf = ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, config.localPort,
config.sitekey, config.encMethod, 10)
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (Path.BASE + "ss-local", "-V", "-u"
, "-b", "127.0.0.1"
, "-t", "600"
, "-c", Path.BASE + "ss-local-vpn.conf"
, "-f", Path.BASE + "ss-local-vpn.pid")
if (config.isAuth) cmd += "-A"
if (config.route != Route.ALL) {
cmd += "--acl"
cmd += (Path.BASE + "acl.list")
}
// channge the state
changeState(State.STOPPED)
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Console.runCommand(cmd.mkString(" "))
}
def startDnsTunnel() = {
val conf = ConfigUtils
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8163,
config.sitekey, config.encMethod, 10)
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => {
p.println(conf)
})
val cmd = new ArrayBuffer[String]
cmd += (Path.BASE + "ss-tunnel"
, "-V"
, "-u"
, "-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 (config.isAuth) cmd += "-A"
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Console.runCommand(cmd.mkString(" "))
}
def startDnsDaemon() {
val ipv6 = if (config.isIpv6) "" else "reject = ::/0;"
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, "0.0.0.0", 8153,
Path.BASE + "pdnsd-vpn.pid", reject, blackList, 8163, ipv6)
} else {
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153,
Path.BASE + "pdnsd-vpn.pid", 8163, ipv6)
}
}
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => {
p.println(conf)
})
val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd-vpn.conf"
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Console.runCommand(cmd)
}
override def getContext = getBaseContext
def startVpn(): Int = {
val builder = new Builder()
builder
.setSession(config.profileName)
.setMtu(VPN_MTU)
.addAddress(PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"), 24)
.addDnsServer("8.8.8.8")
if (config.isIpv6) {
builder.addAddress(PRIVATE_VLAN6.formatLocal(Locale.ENGLISH, "1"), 126)
builder.addRoute("::", 0)
}
if (Utils.isLollipopOrAbove) {
if (!config.isGlobalProxy) {
val apps = AppManager.getProxiedApps(this, config.proxiedAppString)
val pkgSet: mutable.HashSet[String] = new mutable.HashSet[String]
for (app <- apps) {
if (app.proxied) {
pkgSet.add(app.packageName)
}
}
for (pkg <- pkgSet) {
if (!config.isBypassApps) {
builder.addAllowedApplication(pkg)
} else {
builder.addDisallowedApplication(pkg)
}
}
}
}
if (config.route == Route.ALL) {
builder.addRoute("0.0.0.0", 0)
} else {
val privateList = getResources.getStringArray(R.array.bypass_private_route)
privateList.foreach(cidr => {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
})
}
builder.addRoute("8.8.0.0", 16)
try {
conn = builder.establish()
} catch {
case ex: IllegalStateException =>
changeState(State.STOPPED, ex.getMessage)
conn = null
case ex: Exception => conn = null
}
if (conn == null) {
stopRunner()
return -1
}
val fd = conn.getFd
var cmd = (Path.BASE +
"tun2socks --netif-ipaddr %s "
+ "--netif-netmask 255.255.255.0 "
+ "--socks-server-addr 127.0.0.1:%d "
+ "--tunfd %d "
+ "--tunmtu %d "
+ "--loglevel 3 "
+ "--pid %stun2socks-vpn.pid")
.formatLocal(Locale.ENGLISH,
PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"),
config.localPort, fd, VPN_MTU, Path.BASE)
if (config.isIpv6)
cmd += " --netif-ip6addr " + PRIVATE_VLAN6.formatLocal(Locale.ENGLISH, "2")
if (config.isUdpDns)
cmd += " --enable-udprelay"
else
cmd += " --dnsgw %s:8153".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"))
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Console.runCommand(cmd)
return fd
}
override def stopBackgroundService() {
@@ -501,6 +464,4 @@ class ShadowsocksVpnService extends VpnService with BaseService {
override def getTag = TAG
override def getServiceMode = Mode.VPN
override def getContext = getBaseContext
}
@@ -0,0 +1,146 @@
/*
* Shadowsocks - A shadowsocks client for Android
* Copyright (C) 2015 <max.c.lv@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
* ___====-_ _-====___
* _--^^^#####// \\#####^^^--_
* _-^##########// ( ) \\##########^-_
* -############// |\^^/| \\############-
* _/############// (@::@) \\############\_
* /#############(( \\// ))#############\
* -###############\\ (oo) //###############-
* -#################\\ / VV \ //#################-
* -###################\\/ \//###################-
* _#/|##########/\######( /\ )######/\##########|\#_
* |/ |#/\#/\#/\/ \#/\##\ | | /##/\#/ \/\#/\#/\#| \|
* ` |/ V V ` V \#\| | | |/#/ V ' V V \| '
* ` ` ` ` / | | | | \ ' ' ' '
* ( | | | | )
* __\ | | | | /__
* (vvv(VVV)(VVV)vvv)
*
* HERE BE DRAGONS
*
*/
package com.github.shadowsocks
import java.io.{File, FileDescriptor, IOException}
import java.util.concurrent.Executors
import android.net.{LocalServerSocket, LocalSocket, LocalSocketAddress}
import android.util.Log
class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
val TAG = "ShadowsocksVpnService"
val PATH = "/data/data/com.github.shadowsocks/protect_path"
@volatile var isRunning: Boolean = true
@volatile var serverSocket: LocalServerSocket = null
def closeServerSocket() {
if (serverSocket != null) {
try {
serverSocket.close()
} catch {
case _: Exception => // ignore
}
serverSocket = null
}
}
def stopThread() {
isRunning = false
closeServerSocket()
}
override def run(): Unit = {
try {
new File(PATH).delete()
} catch {
case _: Exception => // ignore
}
try {
val localSocket = new LocalSocket
localSocket.bind(new LocalSocketAddress(PATH, LocalSocketAddress.Namespace.FILESYSTEM))
serverSocket = new LocalServerSocket(localSocket.getFileDescriptor)
} catch {
case e: IOException =>
Log.e(TAG, "unable to bind", e)
return
}
val pool = Executors.newFixedThreadPool(4)
while (isRunning) {
try {
val socket = serverSocket.accept()
pool.execute(new Runnable {
override def run() {
try {
val input = socket.getInputStream
val output = socket.getOutputStream
input.read()
val fds = socket.getAncillaryFileDescriptors
if (fds.length > 0) {
var ret = false
val getInt = classOf[FileDescriptor].getDeclaredMethod("getInt$")
val fd = getInt.invoke(fds(0)).asInstanceOf[Int]
ret = vpnService.protect(fd)
// Trick to close file decriptor
System.jniclose(fd)
if (ret) {
output.write(0)
} else {
output.write(1)
}
input.close()
output.close()
}
} catch {
case e: Exception =>
Log.e(TAG, "Error when protect socket", e)
}
// close socket
try {
socket.close()
} catch {
case _: Exception => // ignore
}
}})
} catch {
case e: IOException => {
Log.e(TAG, "Error when accept socket", e)
return
}
}
}
}
}
@@ -51,7 +51,7 @@ object DBHelper {
}
class DBHelper(val context: Context)
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 9) {
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 11) {
lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile])
@@ -62,14 +62,23 @@ class DBHelper(val context: Context)
def onUpgrade(database: SQLiteDatabase, connectionSource: ConnectionSource, oldVersion: Int,
newVersion: Int) {
if (oldVersion != newVersion) {
if (oldVersion < 8) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;")
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
} else if (oldVersion < 9) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
} else {
if (oldVersion < 7) {
profileDao.executeRaw("DROP TABLE IF EXISTS 'profile';")
onCreate(database, connectionSource)
} else {
if (oldVersion < 8) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;")
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
}
if (oldVersion < 9) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
}
if (oldVersion < 10) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN auth SMALLINT;")
}
if (oldVersion < 11) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN ipv6 SMALLINT;")
}
}
}
}
@@ -90,6 +90,12 @@ class Profile {
@DatabaseField
var udpdns: Boolean = false
@DatabaseField
var auth: Boolean = false
@DatabaseField
var ipv6: Boolean = false
@DatabaseField(dataType = DataType.LONG_STRING)
var individual: String = ""
@@ -122,6 +122,8 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
edit.putBoolean(Key.isBypassApps, profile.bypass)
edit.putBoolean(Key.isTrafficStat, profile.traffic)
edit.putBoolean(Key.isUdpDns, profile.udpdns)
edit.putBoolean(Key.isAuth, profile.auth)
edit.putBoolean(Key.isIpv6, profile.ipv6)
edit.putString(Key.profileName, profile.name)
edit.putString(Key.proxy, profile.host)
edit.putString(Key.sitekey, profile.password)
@@ -146,6 +148,8 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
profile.bypass = settings.getBoolean(Key.isBypassApps, false)
profile.traffic = settings.getBoolean(Key.isTrafficStat, false)
profile.udpdns = settings.getBoolean(Key.isUdpDns, false)
profile.auth = settings.getBoolean(Key.isAuth, false)
profile.ipv6 = settings.getBoolean(Key.isIpv6, false)
profile.name = settings.getString(Key.profileName, "default")
profile.host = settings.getString(Key.proxy, "127.0.0.1")
profile.password = settings.getString(Key.sitekey, "default")
@@ -82,7 +82,7 @@ object ConfigUtils {
| label = "local";
| ip = 127.0.0.1;
| port = %d;
| reject = ::/0;
| %s
| reject_policy = negate;
| reject_recursively = on;
| timeout = 5;
@@ -159,8 +159,8 @@ object ConfigUtils {
|
|server {
| label = "china-servers";
| ip = 223.5.5.5, 114.114.114.114;
| timeout = 2;
| ip = 114.114.114.114, 112.124.47.27;
| timeout = 4;
| reject = %s;
| reject_policy = fail;
| reject_recursively = on;
@@ -174,7 +174,9 @@ object ConfigUtils {
| label = "local-server";
| ip = 127.0.0.1;
| port = %d;
| timeout = 3;
| %s
| reject_policy = negate;
| reject_recursively = on;
|}
|
|rr {
@@ -240,7 +242,7 @@ object ConfigUtils {
val method = proxy(3).trim
new Config(config.isGlobalProxy, config.isGFWList, config.isBypassApps, config.isTrafficStat,
config.isUdpDns, config.profileName, host, password, method, config.proxiedAppString, config.route, port,
config.isUdpDns, config.isAuth, config.isIpv6, config.profileName, host, password, method, config.proxiedAppString, config.route, port,
config.localPort)
}
@@ -250,6 +252,8 @@ object ConfigUtils {
val isBypassApps = settings.getBoolean(Key.isBypassApps, false)
val isTrafficStat = settings.getBoolean(Key.isTrafficStat, false)
val isUdpDns = settings.getBoolean(Key.isUdpDns, false)
val isAuth = settings.getBoolean(Key.isAuth, false)
val isIpv6 = settings.getBoolean(Key.isIpv6, false)
val profileName = settings.getString(Key.profileName, "default")
val proxy = settings.getString(Key.proxy, "127.0.0.1")
@@ -271,7 +275,7 @@ object ConfigUtils {
}
val proxiedAppString = settings.getString(Key.proxied, "")
new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, isUdpDns, profileName, proxy,
new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, isUdpDns, isAuth, isIpv6, profileName, proxy,
sitekey, encMethod, proxiedAppString, route, remotePort, localPort)
}
}
@@ -79,6 +79,8 @@ object Key {
val isBypassApps = "isBypassApps"
val isTrafficStat = "isTrafficStat"
val isUdpDns = "isUdpDns"
val isAuth= "isAuth"
val isIpv6= "isIpv6"
val proxy = "proxy"
val sitekey = "sitekey"