diff --git a/.gitmodules b/.gitmodules index 09136bb1..ca93a282 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,14 +9,6 @@ path = mobile/src/main/jni/libancillary url = https://github.com/shadowsocks/libancillary.git branch = shadowsocks-android -[submodule "mobile/src/main/jni/libevent"] - path = mobile/src/main/jni/libevent - url = https://github.com/shadowsocks/libevent.git - branch = shadowsocks-android -[submodule "mobile/src/main/jni/redsocks"] - path = mobile/src/main/jni/redsocks - url = https://github.com/shadowsocks/redsocks.git - branch = shadowsocks-android [submodule "mobile/src/main/jni/mbedtls"] path = mobile/src/main/jni/mbedtls url = https://github.com/ARMmbed/mbedtls diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index fbbe3bff..c3ef3499 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ android:required="false"/> - diff --git a/mobile/src/main/jni/Android.mk b/mobile/src/main/jni/Android.mk index ccc3b473..303c88cc 100755 --- a/mobile/src/main/jni/Android.mk +++ b/mobile/src/main/jni/Android.mk @@ -78,32 +78,6 @@ LOCAL_SRC_FILES := $(addprefix libsodium/src/libsodium/,$(SODIUM_SOURCE)) include $(BUILD_STATIC_LIBRARY) -######################################################## -## libevent -######################################################## - -include $(CLEAR_VARS) - -LIBEVENT_SOURCES := \ - buffer.c \ - bufferevent.c bufferevent_filter.c \ - bufferevent_pair.c bufferevent_ratelim.c \ - bufferevent_sock.c epoll.c \ - epoll_sub.c evdns.c event.c \ - event_tagging.c evmap.c \ - evrpc.c evthread.c \ - evthread_pthread.c evutil.c \ - evutil_rand.c http.c \ - listener.c log.c poll.c \ - select.c signal.c strlcpy.c - -LOCAL_MODULE := event -LOCAL_SRC_FILES := $(addprefix libevent/, $(LIBEVENT_SOURCES)) -LOCAL_CFLAGS := -O2 -D_EVENT_HAVE_ARC4RANDOM -I$(LOCAL_PATH)/libevent \ - -I$(LOCAL_PATH)/libevent/include \ - -include $(BUILD_STATIC_LIBRARY) - ######################################################## ## libancillary ######################################################## @@ -200,28 +174,6 @@ LOCAL_SRC_FILES := \ include $(BUILD_STATIC_LIBRARY) -######################################################## -## redsocks -######################################################## - -include $(CLEAR_VARS) - -REDSOCKS_SOURCES := base.c http-connect.c \ - log.c md5.c socks5.c \ - base64.c http-auth.c http-relay.c main.c \ - parser.c redsocks.c socks4.c utils.c - -LOCAL_STATIC_LIBRARIES := libevent - -LOCAL_MODULE := redsocks -LOCAL_SRC_FILES := $(addprefix redsocks/, $(REDSOCKS_SOURCES)) -LOCAL_CFLAGS := -O2 -std=gnu99 -DUSE_IPTABLES \ - -I$(LOCAL_PATH)/redsocks \ - -I$(LOCAL_PATH)/libevent/include \ - -I$(LOCAL_PATH)/libevent - -include $(BUILD_SHARED_EXECUTABLE) - ######################################################## ## shadowsocks-libev local ######################################################## diff --git a/mobile/src/main/jni/libevent b/mobile/src/main/jni/libevent deleted file mode 160000 index 359ca847..00000000 --- a/mobile/src/main/jni/libevent +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 359ca847a649b9c318f9217c0755484d98ecb779 diff --git a/mobile/src/main/jni/redsocks b/mobile/src/main/jni/redsocks deleted file mode 160000 index 274334f1..00000000 --- a/mobile/src/main/jni/redsocks +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 274334f14839431ae003774d99c3d1de337afff4 diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index 09e252b8..ed44e500 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -7,8 +7,8 @@ Profile Switch to another profile or add new profiles - NAT mode (deprecated) - Use NAT mode instead of VPN mode. Requires ROOT permission. + SOCKS5 mode + Enable SOCKS5 proxy mode instead of VPN mode to work with AFWall+ or Orbot Remote DNS Sent: \t\t\t\t\t%3$s\t↑\t%1$s/s\nReceived: \t%4$s\t↓\t%2$s/s %1$s↑\t%2$s↓ @@ -43,7 +43,7 @@ GFW List China List Per-App Proxy - Set proxy for selected apps, requires NAT mode under Android 4.x + Set proxy for selected apps Set proxy for selected apps On Bypass Mode @@ -57,12 +57,10 @@ VPN Service - NAT Service + SOCKS5 Service Shadowsocks started. Invalid server name Failed to connect the remote server - WARNING: NAT mode has been deprecated since Android 5.0 - NAT mode requires ROOT permission Switch to VPN mode Stop Shutting down… @@ -124,7 +122,7 @@ Received: Connecting… Connected, tap to check connection - Connected + Connected Not connected diff --git a/mobile/src/main/res/xml/pref_global.xml b/mobile/src/main/res/xml/pref_global.xml index 7d54d225..d6df49f7 100644 --- a/mobile/src/main/res/xml/pref_global.xml +++ b/mobile/src/main/res/xml/pref_global.xml @@ -8,6 +8,6 @@ android:summary="@string/tcp_fastopen_summary" android:title="TCP Fast Open"/> + android:title="@string/local" + android:summary="@string/local_summary"/> diff --git a/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala b/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala index 9450aac6..5bef0c68 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/MainActivity.scala @@ -117,7 +117,7 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe if (state == State.CONNECTING) fabProgressCircle.beginFinalAnimation() else fabProgressCircle.postDelayed(hideCircle, 1000) fab.setImageResource(R.drawable.ic_start_connected) - statusText.setText(if (app.isNatEnabled) R.string.nat_connected else R.string.vpn_connected) + statusText.setText(if (app.isLocalEnabled) R.string.local_connected else R.string.vpn_connected) case State.STOPPING => fab.setImageResource(R.drawable.ic_start_busy) if (state == State.CONNECTED) fabProgressCircle.show() // ignore for stopped @@ -128,7 +128,6 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe if (m != null) { val snackbar = Snackbar.make(findViewById(R.id.snackbar), getString(R.string.vpn_error).formatLocal(Locale.ENGLISH, m), Snackbar.LENGTH_LONG) - if (m == getString(R.string.nat_no_root)) addDisableNatToSnackbar(snackbar) snackbar.show() Log.e(TAG, "Error to start VPN service: " + m) } @@ -157,16 +156,9 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe override def onServiceConnected() { changeState(bgService.getState) - if (Build.VERSION.SDK_INT >= 21 && app.isNatEnabled) { - val snackbar = Snackbar.make(findViewById(R.id.snackbar), R.string.nat_deprecated, Snackbar.LENGTH_LONG) - addDisableNatToSnackbar(snackbar) - snackbar.show() - } } override def onServiceDisconnected(): Unit = changeState(State.IDLE) - private def addDisableNatToSnackbar(snackbar: Snackbar) = snackbar.setAction(R.string.switch_to_vpn, (_ => - if (state == State.STOPPED) app.dataStore.isNAT = false): View.OnClickListener) override def binderDied(): Unit = handler.post(() => { detachService() @@ -300,7 +292,7 @@ class MainActivity extends Activity with ServiceBoundContext with Drawer.OnDrawe fab = findViewById(R.id.fab).asInstanceOf[FloatingActionButton] fabProgressCircle = findViewById(R.id.fabProgressCircle).asInstanceOf[FABProgressCircle] fab.setOnClickListener(_ => if (state == State.CONNECTED) Utils.stopSsService(this) else Utils.ThrowableFuture { - if (app.isNatEnabled) Utils.startSsService(this) else { + if (app.isLocalEnabled) Utils.startSsService(this) else { val intent = VpnService.prepare(this) if (intent != null) startActivityForResult(intent, REQUEST_CONNECT) else handler.post(() => onActivityResult(REQUEST_CONNECT, Activity.RESULT_OK, null)) diff --git a/mobile/src/main/scala/com/github/shadowsocks/ProfileConfigFragment.scala b/mobile/src/main/scala/com/github/shadowsocks/ProfileConfigFragment.scala index 16cdf902..1f304e6d 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/ProfileConfigFragment.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/ProfileConfigFragment.scala @@ -66,7 +66,7 @@ class ProfileConfigFragment extends PreferenceFragment with OnMenuItemClickListe findPreference(Key.password).setSummary("\u2022" * 32) } isProxyApps = findPreference(Key.proxyApps).asInstanceOf[SwitchPreference] - isProxyApps.setEnabled(Utils.isLollipopOrAbove || app.isNatEnabled) + isProxyApps.setEnabled(Utils.isLollipopOrAbove || app.isLocalEnabled) isProxyApps.setOnPreferenceClickListener(_ => { startActivity(new Intent(getActivity, classOf[AppManager])) isProxyApps.setChecked(true) diff --git a/mobile/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala b/mobile/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala index f588ff2c..4f4ab15c 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/ServiceBoundContext.scala @@ -85,7 +85,7 @@ trait ServiceBoundContext extends Context with IBinder.DeathRecipient { protected def attachService(callback: IShadowsocksServiceCallback.Stub = null) { this.callback = callback if (bgService == null) { - val s = if (app.isNatEnabled) classOf[ShadowsocksNatService] else classOf[ShadowsocksVpnService] + val s = if (app.isLocalEnabled) classOf[ShadowsocksLocalService] else classOf[ShadowsocksVpnService] val intent = new Intent(this, s) intent.setAction(Action.SERVICE) diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala index d8419e0c..296e320d 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksApplication.scala @@ -66,8 +66,8 @@ class ShadowsocksApplication extends Application { lazy val profileManager = new ProfileManager(dbHelper) lazy val dataStore = new OrmLitePreferenceDataStore(dbHelper) - def isNatEnabled: Boolean = dataStore.isNAT - def isVpnEnabled: Boolean = !isNatEnabled + def isLocalEnabled: Boolean = dataStore.isNAT + def isVpnEnabled: Boolean = !isLocalEnabled // send event def track(category: String, action: String): Unit = tracker.send(new HitBuilders.EventBuilder() @@ -156,7 +156,7 @@ class ShadowsocksApplication extends Application { if (Build.VERSION.SDK_INT >= 26) getSystemService(classOf[NotificationManager]).createNotificationChannels(List( new NotificationChannel("service-vpn", getText(R.string.service_vpn), NotificationManager.IMPORTANCE_MIN), - new NotificationChannel("service-nat", getText(R.string.service_nat), NotificationManager.IMPORTANCE_LOW) + new NotificationChannel("service-local", getText(R.string.service_local), NotificationManager.IMPORTANCE_LOW) )) } @@ -165,15 +165,9 @@ class ShadowsocksApplication extends Application { for (task <- Executable.EXECUTABLES) { cmd.append("killall lib%s.so".formatLocal(Locale.ENGLISH, task)) - cmd.append("rm -f %1$s/%2$s-nat.conf %1$s/%2$s-vpn.conf" + cmd.append("rm -f %1$s/%2$s-local.conf %1$s/%2$s-vpn.conf" .formatLocal(Locale.ENGLISH, getFilesDir.getAbsolutePath, task)) } - if (app.isNatEnabled) { - cmd.append("iptables -t nat -F OUTPUT") - cmd.append("echo done") - val result = Shell.SU.run(cmd.toArray) - if (result != null && !result.isEmpty) return // fallback to SH - } Shell.SH.run(cmd.toArray) } diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksLocalService.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksLocalService.scala new file mode 100644 index 00000000..248cd5e6 --- /dev/null +++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksLocalService.scala @@ -0,0 +1,121 @@ +/*******************************************************************************/ +/* */ +/* Copyright (C) 2017 by Max Lv */ +/* Copyright (C) 2017 by Mygod Studio */ +/* */ +/* 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 . */ +/* */ +/*******************************************************************************/ + +package com.github.shadowsocks + +import java.io.File +import java.net.{Inet6Address, InetAddress} +import java.util.Locale + +import android.app.Service +import android.content._ +import android.os._ +import android.util.Log +import com.github.shadowsocks.ShadowsocksApplication.app +import com.github.shadowsocks.acl.{Acl, AclSyncJob} +import com.github.shadowsocks.database.Profile +import com.github.shadowsocks.utils._ + +import scala.collection.JavaConversions._ +import scala.collection.mutable.ArrayBuffer + +class ShadowsocksLocalService extends BaseService { + + val TAG = "ShadowsocksLocalService" + + var sslocalProcess: GuardedProcess = _ + + def startShadowsocksDaemon() { + val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so", + "-b", "127.0.0.1", + "-l", profile.localPort.toString, + "-t", "600", + "-c", buildShadowsocksConfig("ss-local-local.conf")) + + if (TcpFastOpen.sendEnabled) cmd += "--fast-open" + + if (profile.route != Acl.ALL) { + cmd += "--acl" + cmd += Acl.getFile(profile.route match { + case Acl.CUSTOM_RULES => Acl.CUSTOM_RULES_FLATTENED + case route => route + }).getAbsolutePath + } + + sslocalProcess = new GuardedProcess(cmd: _*).start() + } + + /** Called when the activity is first created. */ + def handleConnection() { + + startShadowsocksDaemon() + + } + + def onBind(intent: Intent): IBinder = { + Log.d(TAG, "onBind") + if (Action.SERVICE == intent.getAction) { + binder + } else { + null + } + } + + def killProcesses() { + if (sslocalProcess != null) { + sslocalProcess.destroy() + sslocalProcess = null + } + } + + override def connect() { + super.connect() + + // Clean up + killProcesses() + + if (!Utils.isNumeric(profile.host)) Utils.resolve(profile.host, enableIPv6 = true) match { + case Some(a) => profile.host = a + case None => throw NameNotResolvedException() + } + + handleConnection() + + if (profile.route != Acl.ALL && profile.route != Acl.CUSTOM_RULES) + AclSyncJob.schedule(profile.route) + + changeState(State.CONNECTED) + } + + override def createNotification() = new ShadowsocksNotification(this, profile.name, "service-local", true) + + override def stopRunner(stopService: Boolean, msg: String = null) { + + // channge the state + changeState(State.STOPPING) + + app.track(TAG, "stop") + + // reset NAT + killProcesses() + + super.stopRunner(stopService, msg) + } +} diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala deleted file mode 100644 index dd915eb3..00000000 --- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala +++ /dev/null @@ -1,231 +0,0 @@ -/*******************************************************************************/ -/* */ -/* Copyright (C) 2017 by Max Lv */ -/* Copyright (C) 2017 by Mygod Studio */ -/* */ -/* 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 . */ -/* */ -/*******************************************************************************/ - -package com.github.shadowsocks - -import java.io.File -import java.net.{Inet6Address, InetAddress} -import java.util.Locale - -import android.app.Service -import android.content._ -import android.os._ -import android.util.Log -import com.github.shadowsocks.ShadowsocksApplication.app -import com.github.shadowsocks.acl.{Acl, AclSyncJob} -import com.github.shadowsocks.database.Profile -import com.github.shadowsocks.utils._ -import eu.chainfire.libsuperuser.Shell - -import scala.collection.JavaConversions._ -import scala.collection.mutable.ArrayBuffer - -class ShadowsocksNatService extends BaseService { - - val TAG = "ShadowsocksNatService" - - val CMD_IPTABLES_DNAT_ADD_SOCKS = - "iptables -t nat -A OUTPUT -p tcp -j DNAT --to-destination 127.0.0.1:8123" - - val myUid: Int = android.os.Process.myUid() - - var sslocalProcess: GuardedProcess = _ - var sstunnelProcess: GuardedProcess = _ - var redsocksProcess: GuardedProcess = _ - var overtureProcess: GuardedProcess = _ - var su: Shell.Interactive = _ - - def startShadowsocksDaemon() { - val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so", - "-b", "127.0.0.1", - "-l", profile.localPort.toString, - "-t", "600", - "-c", buildShadowsocksConfig("ss-local-nat.conf")) - - if (TcpFastOpen.sendEnabled) cmd += "--fast-open" - - if (profile.route != Acl.ALL) { - cmd += "--acl" - cmd += Acl.getFile(profile.route match { - case Acl.CUSTOM_RULES => Acl.CUSTOM_RULES_FLATTENED - case route => route - }).getAbsolutePath - } - - sslocalProcess = new GuardedProcess(cmd: _*).start() - } - - def startDNSTunnel() { - val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so", - "-t", "10", - "-b", "127.0.0.1", - "-l", (profile.localPort + 63).toString, - "-L", profile.remoteDns.split(",").head.trim + ":53", - "-c", buildShadowsocksConfig("ss-tunnel-nat.conf")) - - if (profile.udpdns) cmd.append("-u") - - sstunnelProcess = new GuardedProcess(cmd: _*).start() - } - - def startDnsDaemon() { - overtureProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/liboverture.so", - "-c", buildOvertureConfig("overture-nat.conf")) - .start() - } - - def startRedsocksDaemon() { - IOUtils.writeString(new File(getFilesDir, "redsocks-nat.conf"), - ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, profile.localPort)) - redsocksProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libredsocks.so", - "-c", "redsocks-nat.conf").start() - } - - /** Called when the activity is first created. */ - def handleConnection() { - - startRedsocksDaemon() - startShadowsocksDaemon() - - if (!profile.udpdns) - startDnsDaemon() - else - startDNSTunnel() - - setupIptables() - - } - - def onBind(intent: Intent): IBinder = { - Log.d(TAG, "onBind") - if (Action.SERVICE == intent.getAction) { - binder - } else { - null - } - } - - def killProcesses() { - if (sslocalProcess != null) { - sslocalProcess.destroy() - sslocalProcess = null - } - if (sstunnelProcess != null) { - sstunnelProcess.destroy() - sstunnelProcess = null - } - if (redsocksProcess != null) { - redsocksProcess.destroy() - redsocksProcess = null - } - if (overtureProcess != null) { - overtureProcess.destroy() - overtureProcess = null - } - - su.addCommand("iptables -t nat -F OUTPUT") - } - - def setupIptables() { - val init_sb = new ArrayBuffer[String] - val http_sb = new ArrayBuffer[String] - - init_sb.append("ulimit -n 4096") - init_sb.append("iptables -t nat -F OUTPUT") - - val cmd_bypass = "iptables -t nat -A OUTPUT -p tcp -d 0.0.0.0 -j RETURN" - if (!InetAddress.getByName(profile.host.toUpperCase).isInstanceOf[Inet6Address]) { - init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d " + profile.host)) - } - init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d 127.0.0.1")) - init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-m owner --uid-owner " + myUid)) - init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "--dport 53")) - - init_sb.append("iptables -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:" - + (profile.localPort + 53)) - - if (!profile.proxyApps || profile.bypass) { - http_sb.append(CMD_IPTABLES_DNAT_ADD_SOCKS) - } - if (profile.proxyApps) { - val uidMap = getPackageManager.getInstalledApplications(0).map(ai => ai.packageName -> ai.uid).toMap - for (pn <- profile.individual.split('\n')) uidMap.get(pn) match { - case Some(uid) => - if (!profile.bypass) { - http_sb.append(CMD_IPTABLES_DNAT_ADD_SOCKS - .replace("-t nat", "-t nat -m owner --uid-owner " + uid)) - } else { - init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "-m owner --uid-owner " + uid)) - } - case _ => // probably removed package, ignore - } - } - su.addCommand((init_sb ++ http_sb).toArray) - } - - override def onStartCommand(intent: Intent, flags: Int, startId: Int): Int = if (su == null) { - su = new Shell.Builder().useSU().setWantSTDERR(true).setWatchdogTimeout(10).open((_, exitCode, _) => - if (exitCode == 0) super.onStartCommand(intent, flags, startId) else { - if (su != null) { - su.close() - su = null - } - super.stopRunner(stopService = true, getString(R.string.nat_no_root)) - }) - Service.START_NOT_STICKY - } else super.onStartCommand(intent, flags, startId) - - override def connect() { - super.connect() - - // Clean up - killProcesses() - - if (!Utils.isNumeric(profile.host)) Utils.resolve(profile.host, enableIPv6 = true) match { - case Some(a) => profile.host = a - case None => throw NameNotResolvedException() - } - - handleConnection() - - if (profile.route != Acl.ALL && profile.route != Acl.CUSTOM_RULES) - AclSyncJob.schedule(profile.route) - - changeState(State.CONNECTED) - } - - override def createNotification() = new ShadowsocksNotification(this, profile.name, "service-nat", true) - - override def stopRunner(stopService: Boolean, msg: String = null) { - - // channge the state - changeState(State.STOPPING) - - app.track(TAG, "stop") - - // reset NAT - killProcesses() - - su.close() - su = null - - super.stopRunner(stopService, msg) - } -} diff --git a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala index 9fd86e8e..a1c5a9cf 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/ShadowsocksRunnerActivity.scala @@ -46,7 +46,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext { } def startBackgroundService() { - if (app.isNatEnabled) { + if (app.isLocalEnabled) { Utils.startSsService(this) finish() } else { diff --git a/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala b/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala index eae40a19..349ccc58 100644 --- a/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala +++ b/mobile/src/main/scala/com/github/shadowsocks/utils/Utils.scala @@ -33,7 +33,7 @@ import android.view.View.MeasureSpec import android.view.{Gravity, View, Window} import android.widget.Toast import com.github.shadowsocks.ShadowsocksApplication.app -import com.github.shadowsocks.{BuildConfig, ShadowsocksNatService, ShadowsocksVpnService} +import com.github.shadowsocks.{BuildConfig, ShadowsocksLocalService, ShadowsocksVpnService} import org.xbill.DNS._ import scala.collection.JavaConversions._ @@ -138,7 +138,7 @@ object Utils { def startSsService(context: Context) { val intent = - new Intent(context, if (app.dataStore.isNAT) classOf[ShadowsocksNatService] else classOf[ShadowsocksVpnService]) + new Intent(context, if (app.dataStore.isNAT) classOf[ShadowsocksLocalService] else classOf[ShadowsocksVpnService]) if (Build.VERSION.SDK_INT >= 26) context.startForegroundService(intent) else context.startService(intent) } def reloadSsService(context: Context): Unit = context.sendBroadcast(new Intent(Action.RELOAD))