From 809f4c13e01c2fb4c88b42ba68bc5576a5e755a8 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Fri, 24 Jul 2015 18:56:01 +0800 Subject: [PATCH] add management thread --- build.sh | 2 +- src/main/jni/shadowsocks-libev | 2 +- .../shadowsocks/ShadowsocksVpnService.scala | 94 ++------------- .../shadowsocks/ShadowsocksVpnThread.scala | 112 ++++++++++++++++++ 4 files changed, 124 insertions(+), 86 deletions(-) create mode 100644 src/main/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala diff --git a/build.sh b/build.sh index 8c4b249a..513c0323 100755 --- a/build.sh +++ b/build.sh @@ -7,7 +7,7 @@ function try () { try pushd src/main # Build -try $ANDROID_NDK_HOME/ndk-build clean +#try $ANDROID_NDK_HOME/ndk-build clean try $ANDROID_NDK_HOME/ndk-build -j8 # copy executables diff --git a/src/main/jni/shadowsocks-libev b/src/main/jni/shadowsocks-libev index 87fb6365..68000758 160000 --- a/src/main/jni/shadowsocks-libev +++ b/src/main/jni/shadowsocks-libev @@ -1 +1 @@ -Subproject commit 87fb63654515f22943f833f3e31c4e99a95424f2 +Subproject commit 680007589c5aaafede801081e46b013b27c93939 diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala index 8eed9747..3e2587c7 100644 --- a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala @@ -212,89 +212,17 @@ class ShadowsocksVpnService extends VpnService with BaseService { builder.addDisallowedApplication(pkg) } } - - if (config.isBypassApps) { - builder.addDisallowedApplication(this.getPackageName) - } - } else { - builder.addDisallowedApplication(this.getPackageName) } } - if (InetAddressUtils.isIPv6Address(config.proxy)) { + if (config.route == Route.ALL) { 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) - }) - } - } + 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) @@ -330,15 +258,11 @@ 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 (BuildConfig.DEBUG) Log.d(TAG, cmd) Console.runCommand(cmd) - return fd; + return fd } /** Called when the activity is first created. */ @@ -350,7 +274,6 @@ class ShadowsocksVpnService extends VpnService with BaseService { } val fd = startVpn() - if (fd == -1) { false } else { @@ -361,6 +284,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { true } } + } override def onBind(intent: Intent): IBinder = { @@ -380,6 +304,8 @@ class ShadowsocksVpnService extends VpnService with BaseService { notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) .asInstanceOf[NotificationManager] + + new Thread(new ShadowsocksVpnThread(this)).start() } override def onRevoke() { diff --git a/src/main/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala new file mode 100644 index 00000000..bbd8e7a8 --- /dev/null +++ b/src/main/scala/com/github/shadowsocks/ShadowsocksVpnThread.scala @@ -0,0 +1,112 @@ +/* + * Shadowsocks - A shadowsocks client for Android + * Copyright (C) 2015 + * + * 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 . + * + * + * ___====-_ _-====___ + * _--^^^#####// \\#####^^^--_ + * _-^##########// ( ) \\##########^-_ + * -############// |\^^/| \\############- + * _/############// (@::@) \\############\_ + * /#############(( \\// ))#############\ + * -###############\\ (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 android.net.{LocalServerSocket, LocalSocket, LocalSocketAddress} +import android.util.Log + +class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Runnable { + + val TAG = "ShadowsocksVpnService" + val PATH = "/data/data/com.github.shadowsocks/protect_path" + + override def run(): Unit = { + + var serverSocket: LocalServerSocket = null + + try { + new File(PATH).delete() + } catch { + case _ => // 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) + vpnService.stopBackgroundService() + return + } + + Log.d(TAG, "start to accept connections") + + while (true) { + + try { + val socket = serverSocket.accept() + + val input = socket.getInputStream + val output = socket.getOutputStream + + input.read() + + Log.d(TAG, "test") + + 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) + + if (ret) { + socket.setFileDescriptorsForSend(fds) + output.write(0) + } + + input.close() + output.close() + } + } catch { + case e: Exception => + Log.e(TAG, "Error when protect socket", e) + } + + } + } +}