Obsolete code cleanup
This commit is contained in:
@@ -29,7 +29,6 @@ resolvers += "JRAF" at "http://JRAF.org/static/maven/2"
|
||||
libraryDependencies ++= Seq(
|
||||
"dnsjava" % "dnsjava" % "2.1.7",
|
||||
"com.github.kevinsawicki" % "http-request" % "6.0",
|
||||
"commons-net" % "commons-net" % "3.5",
|
||||
"eu.chainfire" % "libsuperuser" % "1.0.0.201602271131",
|
||||
"com.google.zxing" % "android-integration" % "3.2.1",
|
||||
"net.glxn.qrgen" % "android" % "2.0",
|
||||
|
||||
@@ -4,7 +4,6 @@ import com.github.shadowsocks.aidl.Config;
|
||||
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback;
|
||||
|
||||
interface IShadowsocksService {
|
||||
int getMode();
|
||||
int getState();
|
||||
|
||||
oneway void registerCallback(IShadowsocksServiceCallback cb);
|
||||
|
||||
@@ -60,7 +60,7 @@ trait BaseService extends Service {
|
||||
|
||||
final val callbacks = new RemoteCallbackList[IShadowsocksServiceCallback]
|
||||
var callbacksCount: Int = _
|
||||
lazy val handler = new Handler(getContext.getMainLooper)
|
||||
lazy val handler = new Handler(getMainLooper)
|
||||
|
||||
private val closeReceiver: BroadcastReceiver = (context: Context, intent: Intent) => {
|
||||
Toast.makeText(context, R.string.stopping, Toast.LENGTH_SHORT).show()
|
||||
@@ -69,10 +69,6 @@ trait BaseService extends Service {
|
||||
var closeReceiverRegistered: Boolean = _
|
||||
|
||||
val binder = new IShadowsocksService.Stub {
|
||||
override def getMode: Int = {
|
||||
getServiceMode
|
||||
}
|
||||
|
||||
override def getState: Int = {
|
||||
state
|
||||
}
|
||||
@@ -125,7 +121,7 @@ trait BaseService extends Service {
|
||||
def startRunner(config: Config) {
|
||||
this.config = config
|
||||
|
||||
startService(new Intent(getContext, getClass))
|
||||
startService(new Intent(this, getClass))
|
||||
TrafficMonitor.reset()
|
||||
trafficMonitorThread = new TrafficMonitorThread(getApplicationContext)
|
||||
trafficMonitorThread.start()
|
||||
@@ -176,16 +172,9 @@ trait BaseService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
def getServiceMode: Int
|
||||
def getTag: String
|
||||
def getContext: Context
|
||||
|
||||
def getState: Int = {
|
||||
state
|
||||
}
|
||||
def changeState(s: Int) {
|
||||
changeState(s, null)
|
||||
}
|
||||
|
||||
def updateTrafficRate() {
|
||||
handler.post(() => {
|
||||
@@ -210,8 +199,8 @@ trait BaseService extends Service {
|
||||
// Service of shadowsocks should always be started explicitly
|
||||
override def onStartCommand(intent: Intent, flags: Int, startId: Int): Int = Service.START_NOT_STICKY
|
||||
|
||||
protected def changeState(s: Int, msg: String) {
|
||||
val handler = new Handler(getContext.getMainLooper)
|
||||
protected def changeState(s: Int, msg: String = null) {
|
||||
val handler = new Handler(getMainLooper)
|
||||
handler.post(() => if (state != s) {
|
||||
if (callbacksCount > 0) {
|
||||
val n = callbacks.beginBroadcast()
|
||||
|
||||
@@ -56,7 +56,7 @@ import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.util.Log
|
||||
import android.view.{View, ViewGroup, ViewParent}
|
||||
import android.view.{View, ViewGroup}
|
||||
import android.widget._
|
||||
import com.github.jorgecastilloprz.FABProgressCircle
|
||||
import com.github.shadowsocks.aidl.IShadowsocksServiceCallback
|
||||
@@ -88,29 +88,25 @@ object Typefaces {
|
||||
}
|
||||
|
||||
object Shadowsocks {
|
||||
|
||||
// Constants
|
||||
val TAG = "Shadowsocks"
|
||||
val REQUEST_CONNECT = 1
|
||||
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL,
|
||||
private final val TAG = "Shadowsocks"
|
||||
private final val REQUEST_CONNECT = 1
|
||||
private val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.SS_TUNNEL, Executable.SS_LOCAL,
|
||||
Executable.TUN2SOCKS)
|
||||
|
||||
}
|
||||
|
||||
class Shadowsocks
|
||||
extends AppCompatActivity with ServiceBoundContext {
|
||||
class Shadowsocks extends AppCompatActivity with ServiceBoundContext {
|
||||
import Shadowsocks._
|
||||
|
||||
// Variables
|
||||
var serviceStarted = false
|
||||
var fab: FloatingActionButton = _
|
||||
var fabProgressCircle: FABProgressCircle = _
|
||||
var progressDialog: ProgressDialog = _
|
||||
var progressTag = -1
|
||||
var state = State.STOPPED
|
||||
var currentProfile = new Profile
|
||||
|
||||
// Services
|
||||
var currentServiceName = classOf[ShadowsocksNatService].getName
|
||||
private val callback = new IShadowsocksServiceCallback.Stub {
|
||||
def stateChanged(s: Int, m: String) {
|
||||
handler.post(() => if (state != s) {
|
||||
@@ -148,7 +144,7 @@ class Shadowsocks
|
||||
if (m == getString(R.string.nat_no_root)) snackbar.setAction(R.string.switch_to_vpn,
|
||||
(_ => preferences.natSwitch.setChecked(false)): View.OnClickListener)
|
||||
snackbar.show
|
||||
Log.e(Shadowsocks.TAG, "Error to start VPN service: " + m)
|
||||
Log.e(TAG, "Error to start VPN service: " + m)
|
||||
}
|
||||
preferences.setEnabled(true)
|
||||
stat.setVisibility(View.GONE)
|
||||
@@ -230,7 +226,7 @@ class Shadowsocks
|
||||
private lazy val preferences =
|
||||
getFragmentManager.findFragmentById(android.R.id.content).asInstanceOf[ShadowsocksSettings]
|
||||
|
||||
var handler = new Handler()
|
||||
val handler = new Handler()
|
||||
|
||||
private def changeSwitch(checked: Boolean) {
|
||||
serviceStarted = checked
|
||||
@@ -244,7 +240,6 @@ class Shadowsocks
|
||||
private def showProgress(msg: Int): Handler = {
|
||||
clearDialog()
|
||||
progressDialog = ProgressDialog.show(this, "", getString(msg), true, false)
|
||||
progressTag = msg
|
||||
new Handler {
|
||||
override def handleMessage(msg: Message) {
|
||||
clearDialog()
|
||||
@@ -259,7 +254,7 @@ class Shadowsocks
|
||||
files = assetManager.list(path)
|
||||
} catch {
|
||||
case e: IOException =>
|
||||
Log.e(Shadowsocks.TAG, e.getMessage)
|
||||
Log.e(TAG, e.getMessage)
|
||||
}
|
||||
if (files != null) {
|
||||
for (file <- files) {
|
||||
@@ -280,7 +275,7 @@ class Shadowsocks
|
||||
out = null
|
||||
} catch {
|
||||
case ex: Exception =>
|
||||
Log.e(Shadowsocks.TAG, ex.getMessage)
|
||||
Log.e(TAG, ex.getMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -331,7 +326,7 @@ class Shadowsocks
|
||||
}
|
||||
if (ShadowsocksApplication.isVpnEnabled) Console.runCommand(cmd.toArray) else {
|
||||
Console.runRootCommand(cmd.toArray)
|
||||
Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT")
|
||||
Console.runRootCommand(Utils.iptables + " -t nat -F OUTPUT")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -345,9 +340,9 @@ class Shadowsocks
|
||||
if (ShadowsocksApplication.isVpnEnabled) {
|
||||
val intent = VpnService.prepare(this)
|
||||
if (intent != null) {
|
||||
startActivityForResult(intent, Shadowsocks.REQUEST_CONNECT)
|
||||
startActivityForResult(intent, REQUEST_CONNECT)
|
||||
} else {
|
||||
handler.post(() => onActivityResult(Shadowsocks.REQUEST_CONNECT, Activity.RESULT_OK, null))
|
||||
handler.post(() => onActivityResult(REQUEST_CONNECT, Activity.RESULT_OK, null))
|
||||
}
|
||||
} else {
|
||||
serviceLoad()
|
||||
@@ -355,13 +350,6 @@ class Shadowsocks
|
||||
}
|
||||
}
|
||||
|
||||
def getLayoutView(view: ViewParent): LinearLayout = {
|
||||
view match {
|
||||
case layout: LinearLayout => layout
|
||||
case _ => if (view != null) getLayoutView(view.getParent) else null
|
||||
}
|
||||
}
|
||||
|
||||
override def onCreate(savedInstanceState: Bundle) {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -565,7 +553,7 @@ class Shadowsocks
|
||||
copyAssets(System.getABI)
|
||||
|
||||
val ab = new ArrayBuffer[String]
|
||||
for (executable <- Shadowsocks.EXECUTABLES) {
|
||||
for (executable <- EXECUTABLES) {
|
||||
ab.append("chmod 755 " + getApplicationInfo.dataDir + "/" + executable)
|
||||
}
|
||||
Console.runCommand(ab.toArray)
|
||||
@@ -594,7 +582,7 @@ class Shadowsocks
|
||||
serviceLoad()
|
||||
case _ =>
|
||||
cancelStart()
|
||||
Log.e(Shadowsocks.TAG, "Failed to start VpnService")
|
||||
Log.e(TAG, "Failed to start VpnService")
|
||||
}
|
||||
|
||||
def serviceStop() {
|
||||
@@ -621,7 +609,6 @@ class Shadowsocks
|
||||
if (progressDialog != null && progressDialog.isShowing) {
|
||||
if (!isDestroyed) progressDialog.dismiss()
|
||||
progressDialog = null
|
||||
progressTag = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ import java.net.{Inet6Address, InetAddress}
|
||||
import java.util.Locale
|
||||
|
||||
import android.content._
|
||||
import android.content.pm.{PackageInfo, PackageManager}
|
||||
import android.net.{ConnectivityManager, Network}
|
||||
import android.os._
|
||||
import android.util.{Log, SparseArray}
|
||||
@@ -64,7 +63,6 @@ class ShadowsocksNatService extends BaseService {
|
||||
"-j DNAT --to-destination 127.0.0.1:8123"
|
||||
|
||||
private var notification: ShadowsocksNotification = _
|
||||
var connReceiver: BroadcastReceiver = _
|
||||
val myUid = android.os.Process.myUid()
|
||||
|
||||
var sslocalProcess: Process = _
|
||||
@@ -144,21 +142,6 @@ class ShadowsocksNatService extends BaseService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def destroyConnectionReceiver() {
|
||||
if (connReceiver != null) {
|
||||
unregisterReceiver(connReceiver)
|
||||
connReceiver = null
|
||||
}
|
||||
resetDns()
|
||||
}
|
||||
|
||||
def initConnectionReceiver() {
|
||||
val filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
|
||||
connReceiver = (context: Context, intent: Intent) => setupDns()
|
||||
registerReceiver(connReceiver, filter)
|
||||
}
|
||||
|
||||
def startShadowsocksDaemon() {
|
||||
if (config.route != Route.ALL) {
|
||||
val acl: Array[Array[String]] = config.route match {
|
||||
@@ -250,8 +233,8 @@ class ShadowsocksNatService extends BaseService {
|
||||
def startDnsDaemon() {
|
||||
|
||||
val conf = if (config.route == Route.BYPASS_CHN || config.route == Route.BYPASS_LAN_CHN) {
|
||||
val reject = ConfigUtils.getRejectList(getContext)
|
||||
val blackList = ConfigUtils.getBlackList(getContext)
|
||||
val reject = ConfigUtils.getRejectList(this)
|
||||
val blackList = ConfigUtils.getBlackList(this)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
|
||||
"127.0.0.1", 8153, reject, blackList, 8163, "")
|
||||
} else {
|
||||
@@ -269,18 +252,6 @@ class ShadowsocksNatService extends BaseService {
|
||||
pdnsdProcess = new GuardedProcess(cmd.split(" ").toSeq).start()
|
||||
}
|
||||
|
||||
def getVersionName: String = {
|
||||
var version: String = null
|
||||
try {
|
||||
val pi: PackageInfo = getPackageManager.getPackageInfo(getPackageName, 0)
|
||||
version = pi.versionName
|
||||
} catch {
|
||||
case e: PackageManager.NameNotFoundException =>
|
||||
version = "Package name not found"
|
||||
}
|
||||
version
|
||||
}
|
||||
|
||||
def startRedsocksDaemon() {
|
||||
val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, config.localPort)
|
||||
val cmd = "%s/redsocks -c %s/redsocks-nat.conf"
|
||||
@@ -337,7 +308,7 @@ class ShadowsocksNatService extends BaseService {
|
||||
pdnsdProcess = null
|
||||
}
|
||||
|
||||
Console.runRootCommand(Utils.getIptables + " -t nat -F OUTPUT")
|
||||
Console.runRootCommand(Utils.iptables + " -t nat -F OUTPUT")
|
||||
}
|
||||
|
||||
def setupIptables() = {
|
||||
@@ -345,9 +316,9 @@ class ShadowsocksNatService extends BaseService {
|
||||
val http_sb = new ArrayBuffer[String]
|
||||
|
||||
init_sb.append("ulimit -n 4096")
|
||||
init_sb.append(Utils.getIptables + " -t nat -F OUTPUT")
|
||||
init_sb.append(Utils.iptables + " -t nat -F OUTPUT")
|
||||
|
||||
val cmd_bypass = Utils.getIptables + CMD_IPTABLES_RETURN
|
||||
val cmd_bypass = Utils.iptables + CMD_IPTABLES_RETURN
|
||||
if (!InetAddress.getByName(config.proxy.toUpperCase).isInstanceOf[Inet6Address]) {
|
||||
init_sb.append(cmd_bypass.replace("-p tcp -d 0.0.0.0", "-d " + config.proxy))
|
||||
}
|
||||
@@ -355,18 +326,18 @@ class ShadowsocksNatService extends BaseService {
|
||||
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(Utils.getIptables
|
||||
init_sb.append(Utils.iptables
|
||||
+ " -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:8153")
|
||||
|
||||
if (!config.isProxyApps || config.isBypassApps) {
|
||||
http_sb.append(Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS)
|
||||
http_sb.append(Utils.iptables + CMD_IPTABLES_DNAT_ADD_SOCKS)
|
||||
}
|
||||
if (config.isProxyApps) {
|
||||
val uidMap = getPackageManager.getInstalledApplications(0).map(ai => ai.packageName -> ai.uid).toMap
|
||||
for (pn <- config.proxiedAppString.split('\n')) uidMap.get(pn) match {
|
||||
case Some(uid) =>
|
||||
if (!config.isBypassApps) {
|
||||
http_sb.append((Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS)
|
||||
http_sb.append((Utils.iptables + 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))
|
||||
@@ -448,8 +419,4 @@ class ShadowsocksNatService extends BaseService {
|
||||
|
||||
super.stopRunner(stopService)
|
||||
}
|
||||
|
||||
override def getTag = TAG
|
||||
override def getServiceMode = Mode.NAT
|
||||
override def getContext = getBaseContext
|
||||
}
|
||||
|
||||
@@ -40,13 +40,20 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.app.{Activity, KeyguardManager}
|
||||
import android.content.{Intent, IntentFilter, Context, BroadcastReceiver}
|
||||
import android.content.{BroadcastReceiver, Context, Intent, IntentFilter}
|
||||
import android.net.VpnService
|
||||
import android.os.{Bundle, Handler}
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.utils.ConfigUtils
|
||||
|
||||
object ShadowsocksRunnerActivity {
|
||||
private final val TAG = "ShadowsocksRunnerActivity"
|
||||
private final val REQUEST_CONNECT = 1
|
||||
}
|
||||
|
||||
class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
|
||||
import ShadowsocksRunnerActivity._
|
||||
|
||||
val handler = new Handler()
|
||||
|
||||
// Variables
|
||||
@@ -60,9 +67,9 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
|
||||
if (ShadowsocksApplication.isVpnEnabled) {
|
||||
val intent = VpnService.prepare(ShadowsocksRunnerActivity.this)
|
||||
if (intent != null) {
|
||||
startActivityForResult(intent, Shadowsocks.REQUEST_CONNECT)
|
||||
startActivityForResult(intent, REQUEST_CONNECT)
|
||||
} else {
|
||||
onActivityResult(Shadowsocks.REQUEST_CONNECT, Activity.RESULT_OK, null)
|
||||
onActivityResult(REQUEST_CONNECT, Activity.RESULT_OK, null)
|
||||
}
|
||||
} else {
|
||||
bgService.use(ConfigUtils.load(ShadowsocksApplication.settings))
|
||||
@@ -104,7 +111,7 @@ class ShadowsocksRunnerActivity extends Activity with ServiceBoundContext {
|
||||
bgService.use(ConfigUtils.load(ShadowsocksApplication.settings))
|
||||
}
|
||||
case _ =>
|
||||
Log.e(Shadowsocks.TAG, "Failed to start VpnService")
|
||||
Log.e(TAG, "Failed to start VpnService")
|
||||
}
|
||||
finish()
|
||||
}
|
||||
|
||||
@@ -45,13 +45,11 @@ import java.util.Locale
|
||||
|
||||
import android.content._
|
||||
import android.content.pm.PackageManager.NameNotFoundException
|
||||
import android.content.pm.{PackageInfo, PackageManager}
|
||||
import android.net.VpnService
|
||||
import android.os._
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.aidl.Config
|
||||
import com.github.shadowsocks.utils._
|
||||
import org.apache.commons.net.util.SubnetUtils
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
@@ -69,27 +67,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
var pdnsdProcess: Process = _
|
||||
var tun2socksProcess: Process = _
|
||||
|
||||
def isByass(net: SubnetUtils): Boolean = {
|
||||
val info = net.getInfo
|
||||
info.isInRange(config.proxy)
|
||||
}
|
||||
|
||||
def isPrivateA(a: Int): Boolean = {
|
||||
if (a == 10 || a == 192 || a == 172) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def isPrivateB(a: Int, b: Int): Boolean = {
|
||||
if (a == 10 || (a == 192 && b == 168) || (a == 172 && b >= 16 && b < 32)) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
override def onBind(intent: Intent): IBinder = {
|
||||
val action = intent.getAction
|
||||
if (VpnService.SERVICE_INTERFACE == action) {
|
||||
@@ -135,18 +112,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
super.stopRunner(stopService)
|
||||
}
|
||||
|
||||
def getVersionName: String = {
|
||||
var version: String = null
|
||||
try {
|
||||
val pi: PackageInfo = getPackageManager.getPackageInfo(getPackageName, 0)
|
||||
version = pi.versionName
|
||||
} catch {
|
||||
case e: PackageManager.NameNotFoundException =>
|
||||
version = "Package name not found"
|
||||
}
|
||||
version
|
||||
}
|
||||
|
||||
def killProcesses() {
|
||||
if (sslocalProcess != null) {
|
||||
sslocalProcess.destroy()
|
||||
@@ -311,8 +276,8 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
val ipv6 = if (config.isIpv6) "" else "reject = ::/0;"
|
||||
val conf = {
|
||||
if (config.route == Route.BYPASS_CHN || config.route == Route.BYPASS_LAN_CHN) {
|
||||
val reject = ConfigUtils.getRejectList(getContext)
|
||||
val blackList = ConfigUtils.getBlackList(getContext)
|
||||
val reject = ConfigUtils.getRejectList(this)
|
||||
val blackList = ConfigUtils.getBlackList(this)
|
||||
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir,
|
||||
"0.0.0.0", 8153, reject, blackList, 8163, ipv6)
|
||||
} else {
|
||||
@@ -330,8 +295,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
pdnsdProcess = new GuardedProcess(cmd.split(" ").toSeq).start()
|
||||
}
|
||||
|
||||
override def getContext = getBaseContext
|
||||
|
||||
def startVpn(): Int = {
|
||||
|
||||
val builder = new Builder()
|
||||
@@ -435,8 +398,4 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
override def getTag = TAG
|
||||
|
||||
override def getServiceMode = Mode.VPN
|
||||
}
|
||||
|
||||
@@ -96,49 +96,6 @@ object ConfigUtils {
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val PDNSD_BYPASS =
|
||||
"""
|
||||
|global {
|
||||
| perm_cache = 2048;
|
||||
| cache_dir = "%s";
|
||||
| server_ip = %s;
|
||||
| server_port = %d;
|
||||
| query_method = tcp_only;
|
||||
| run_ipv4 = on;
|
||||
| min_ttl = 15m;
|
||||
| max_ttl = 1w;
|
||||
| timeout = 10;
|
||||
| daemon = off;
|
||||
|}
|
||||
|
|
||||
|server {
|
||||
| label = "china-servers";
|
||||
| ip = 114.114.114.114, 223.5.5.5;
|
||||
| uptest = none;
|
||||
| preset = on;
|
||||
| include = %s;
|
||||
| policy = excluded;
|
||||
| timeout = 2;
|
||||
|}
|
||||
|
|
||||
|server {
|
||||
| label = "local-server";
|
||||
| ip = 127.0.0.1;
|
||||
| uptest = none;
|
||||
| preset = on;
|
||||
| port = %d;
|
||||
| timeout = 5;
|
||||
|}
|
||||
|
|
||||
|rr {
|
||||
| name=localhost;
|
||||
| reverse=on;
|
||||
| a=127.0.0.1;
|
||||
| owner=localhost;
|
||||
| soa=localhost,root.localhost,42,86400,900,86400,86400;
|
||||
|}
|
||||
""".stripMargin
|
||||
|
||||
val PDNSD_DIRECT =
|
||||
"""
|
||||
|global {
|
||||
|
||||
@@ -63,10 +63,6 @@ object Console {
|
||||
.open()
|
||||
}
|
||||
|
||||
def runCommand(command: String) {
|
||||
runCommand(Array(command))
|
||||
}
|
||||
|
||||
def runCommand(commands: Array[String]) {
|
||||
val shell = openShell()
|
||||
shell.addCommand(commands, 0, ((commandCode: Int, exitCode: Int, output: util.List[String]) =>
|
||||
|
||||
@@ -44,17 +44,9 @@ object Executable {
|
||||
val PDNSD = "pdnsd"
|
||||
val SS_LOCAL = "ss-local"
|
||||
val SS_TUNNEL = "ss-tunnel"
|
||||
val IPTABLES = "iptables"
|
||||
val TUN2SOCKS = "tun2socks"
|
||||
}
|
||||
|
||||
object Msg {
|
||||
val CONNECT_FINISH = 1
|
||||
val CONNECT_SUCCESS = 2
|
||||
val CONNECT_FAIL = 3
|
||||
val VPN_ERROR = 6
|
||||
}
|
||||
|
||||
object Key {
|
||||
val profileId = "profileId"
|
||||
val profileName = "profileName"
|
||||
@@ -63,9 +55,7 @@ object Key {
|
||||
|
||||
val isNAT = "isNAT"
|
||||
val route = "route"
|
||||
val stat = "stat"
|
||||
|
||||
val isRunning = "isRunning"
|
||||
val isAutoConnect = "isAutoConnect"
|
||||
|
||||
val isProxyApps = "isProxyApps"
|
||||
@@ -83,17 +73,6 @@ object Key {
|
||||
val profileTip = "profileTip"
|
||||
}
|
||||
|
||||
object Scheme {
|
||||
val APP = "app://"
|
||||
val PROFILE = "profile://"
|
||||
val SS = "ss"
|
||||
}
|
||||
|
||||
object Mode {
|
||||
val NAT = 0
|
||||
val VPN = 1
|
||||
}
|
||||
|
||||
object State {
|
||||
val CONNECTING = 1
|
||||
val CONNECTED = 2
|
||||
|
||||
@@ -49,8 +49,6 @@ object TaskerSettings {
|
||||
|
||||
def fromIntent(intent: Intent) = new TaskerSettings(if (intent.hasExtra(ApiIntent.EXTRA_BUNDLE))
|
||||
intent.getBundleExtra(ApiIntent.EXTRA_BUNDLE) else Bundle.EMPTY)
|
||||
|
||||
def fromBundle(bundle: Bundle) = new TaskerSettings(bundle)
|
||||
}
|
||||
|
||||
class TaskerSettings(bundle: Bundle) {
|
||||
|
||||
@@ -38,19 +38,15 @@
|
||||
*/
|
||||
package com.github.shadowsocks.utils
|
||||
|
||||
import java.io._
|
||||
import java.net._
|
||||
import java.security.MessageDigest
|
||||
|
||||
import android.animation.{Animator, AnimatorListenerAdapter}
|
||||
import android.app.ActivityManager
|
||||
import android.content.pm.{ApplicationInfo, PackageManager}
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.{Context, Intent}
|
||||
import android.graphics._
|
||||
import android.graphics.drawable.{BitmapDrawable, Drawable}
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.util.{Base64, DisplayMetrics, Log}
|
||||
import android.view.View.MeasureSpec
|
||||
import android.view.{Gravity, View, Window}
|
||||
@@ -61,12 +57,19 @@ import org.xbill.DNS._
|
||||
|
||||
object Utils {
|
||||
|
||||
val TAG: String = "Shadowsocks"
|
||||
val DEFAULT_IPTABLES: String = "/system/bin/iptables"
|
||||
val ALTERNATIVE_IPTABLES: String = "iptables"
|
||||
var initialized: Boolean = false
|
||||
var hasRedirectSupport: Int = -1
|
||||
var iptables: String = null
|
||||
private val TAG = "Shadowsocks"
|
||||
|
||||
/**
|
||||
* Check the system's iptables
|
||||
* Default to use the app's iptables
|
||||
*/
|
||||
private val DEFAULT_IPTABLES = "/system/bin/iptables"
|
||||
private val ALTERNATIVE_IPTABLES = "iptables"
|
||||
lazy val iptables = if (Console.isRoot) {
|
||||
val lines = Console.runRootCommand(DEFAULT_IPTABLES + " --version", DEFAULT_IPTABLES + " -L -t nat -n")
|
||||
if (Console.isRoot && lines != null && !lines.contains("OUTPUT") || !lines.contains("v1.4.")) ALTERNATIVE_IPTABLES
|
||||
else DEFAULT_IPTABLES
|
||||
} else DEFAULT_IPTABLES
|
||||
|
||||
def isLollipopOrAbove: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||
|
||||
@@ -86,31 +89,6 @@ object Utils {
|
||||
* round or floor depending on whether you are using offsets(floor) or
|
||||
* widths(round)
|
||||
*/
|
||||
def dpToPx(context: Context, dp: Float): Float = {
|
||||
val density = context.getResources.getDisplayMetrics.density
|
||||
dp * density
|
||||
}
|
||||
|
||||
def pxToDp(context: Context, px: Float): Float = {
|
||||
val density = context.getResources.getDisplayMetrics.density
|
||||
px / density
|
||||
}
|
||||
|
||||
def getBitmap(text: String, width: Int, height: Int, background: Int): Bitmap = {
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
val size = bitmap.getHeight / 4
|
||||
val canvas = new Canvas(bitmap)
|
||||
canvas.drawColor(background)
|
||||
val paint = new Paint()
|
||||
paint.setColor(Color.WHITE)
|
||||
paint.setTextSize(size)
|
||||
val bounds = new Rect()
|
||||
paint.getTextBounds(text, 0, text.length, bounds)
|
||||
canvas
|
||||
.drawText(text, (bitmap.getWidth - bounds.width()) / 2,
|
||||
bitmap.getHeight - (bitmap.getHeight - bounds.height()) / 2, paint)
|
||||
bitmap
|
||||
}
|
||||
|
||||
// Based on: http://stackoverflow.com/a/21026866/2245107
|
||||
def positionToast(toast: Toast, view: View, window: Window, offsetX: Int = 0, offsetY: Int = 0) = {
|
||||
@@ -165,25 +143,6 @@ object Utils {
|
||||
context.sendBroadcast(disableIntent)
|
||||
}
|
||||
|
||||
def isServiceStarted(name: String, context: Context): Boolean = {
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
val activityManager = context
|
||||
.getSystemService(Context.ACTIVITY_SERVICE)
|
||||
.asInstanceOf[ActivityManager]
|
||||
val services = activityManager.getRunningServices(Integer.MAX_VALUE)
|
||||
|
||||
if (services != null) {
|
||||
for (service <- services) {
|
||||
if (service.service.getClassName == name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
def resolve(host: String, addrType: Int): Option[String] = {
|
||||
try {
|
||||
val lookup = new Lookup(host, addrType)
|
||||
@@ -240,31 +199,6 @@ object Utils {
|
||||
private lazy val isNumericMethod = classOf[InetAddress].getMethod("isNumeric", classOf[String])
|
||||
def isNumeric(address: String): Boolean = isNumericMethod.invoke(null, address).asInstanceOf[Boolean]
|
||||
|
||||
/**
|
||||
* Get local IPv4 address
|
||||
*/
|
||||
def getIPv4Address: Option[String] = {
|
||||
try {
|
||||
val interfaces = NetworkInterface.getNetworkInterfaces
|
||||
while (interfaces.hasMoreElements) {
|
||||
val intf = interfaces.nextElement()
|
||||
val addrs = intf.getInetAddresses
|
||||
while (addrs.hasMoreElements) {
|
||||
val addr = addrs.nextElement()
|
||||
if (!addr.isLoopbackAddress && !addr.isLinkLocalAddress) {
|
||||
if (addr.isInstanceOf[Inet4Address]) {
|
||||
return Some(addr.getHostAddress.toUpperCase)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
case ex: Exception =>
|
||||
Log.e(TAG, "Failed to get interfaces' addresses.", ex)
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/**
|
||||
* If there exists a valid IPv6 interface
|
||||
*/
|
||||
@@ -291,116 +225,6 @@ object Utils {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the system's iptables
|
||||
* Default to use the app's iptables
|
||||
*/
|
||||
def checkIptables() {
|
||||
|
||||
if (!Console.isRoot) {
|
||||
iptables = DEFAULT_IPTABLES
|
||||
return
|
||||
}
|
||||
|
||||
iptables = DEFAULT_IPTABLES
|
||||
|
||||
var compatible: Boolean = false
|
||||
var version: Boolean = false
|
||||
|
||||
val lines = Console.runRootCommand(iptables + " --version", iptables + " -L -t nat -n")
|
||||
if (lines == null) return
|
||||
|
||||
if (lines.contains("OUTPUT")) {
|
||||
compatible = true
|
||||
}
|
||||
if (lines.contains("v1.4.")) {
|
||||
version = true
|
||||
}
|
||||
if (!compatible || !version) {
|
||||
iptables = ALTERNATIVE_IPTABLES
|
||||
if (!new File(iptables).exists) iptables = "iptables"
|
||||
}
|
||||
}
|
||||
|
||||
def drawableToBitmap(drawable: Drawable): Bitmap = {
|
||||
drawable match {
|
||||
case d: BitmapDrawable =>
|
||||
return d.getBitmap
|
||||
case _ =>
|
||||
}
|
||||
|
||||
val width = if (drawable.getIntrinsicWidth > 0) drawable.getIntrinsicWidth else 1
|
||||
val height = if (drawable.getIntrinsicWidth > 0) drawable.getIntrinsicWidth else 1
|
||||
|
||||
val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = new Canvas(bitmap)
|
||||
drawable.setBounds(0, 0, canvas.getWidth, canvas.getHeight)
|
||||
drawable.draw(canvas)
|
||||
|
||||
bitmap
|
||||
}
|
||||
|
||||
def getAppIcon(c: Context, packageName: String): Drawable = {
|
||||
val pm: PackageManager = c.getPackageManager
|
||||
val icon: Drawable = ContextCompat.getDrawable(c, android.R.drawable.sym_def_app_icon)
|
||||
try {
|
||||
pm.getApplicationIcon(packageName)
|
||||
} catch {
|
||||
case e: PackageManager.NameNotFoundException => icon
|
||||
}
|
||||
}
|
||||
|
||||
def getAppIcon(c: Context, uid: Int): Drawable = {
|
||||
val pm: PackageManager = c.getPackageManager
|
||||
val icon: Drawable = ContextCompat.getDrawable(c, android.R.drawable.sym_def_app_icon)
|
||||
val packages: Array[String] = pm.getPackagesForUid(uid)
|
||||
if (packages != null) {
|
||||
if (packages.length >= 1) {
|
||||
try {
|
||||
val appInfo: ApplicationInfo = pm.getApplicationInfo(packages(0), 0)
|
||||
return pm.getApplicationIcon(appInfo)
|
||||
} catch {
|
||||
case e: PackageManager.NameNotFoundException =>
|
||||
Log.e(c.getPackageName, "No package found matching with the uid " + uid)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(c.getPackageName, "Package not found for uid " + uid)
|
||||
}
|
||||
icon
|
||||
}
|
||||
|
||||
def getHasRedirectSupport: Boolean = {
|
||||
if (hasRedirectSupport == -1) initHasRedirectSupported()
|
||||
hasRedirectSupport == 1
|
||||
}
|
||||
|
||||
def getIptables: String = {
|
||||
if (iptables == null) checkIptables()
|
||||
iptables
|
||||
}
|
||||
|
||||
def initHasRedirectSupported() {
|
||||
if (!Console.isRoot) return
|
||||
hasRedirectSupport = 1
|
||||
|
||||
val command = Utils.getIptables + " -t nat -A OUTPUT -p udp --dport 54 -j REDIRECT --to 8154"
|
||||
val lines = Console.runRootCommand(command, command.replace("-A", "-D"))
|
||||
if (lines == null) return
|
||||
if (lines.contains("No chain/target/match")) {
|
||||
hasRedirectSupport = 0
|
||||
}
|
||||
}
|
||||
|
||||
def isInitialized: Boolean = {
|
||||
initialized match {
|
||||
case true => true
|
||||
case _ =>
|
||||
initialized = true
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
def startSsService(context: Context) {
|
||||
val isInstalled: Boolean = ShadowsocksApplication.settings.getBoolean(ShadowsocksApplication.getVersionName, false)
|
||||
if (!isInstalled) return
|
||||
@@ -414,5 +238,3 @@ object Utils {
|
||||
context.sendBroadcast(intent)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user