Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3db8e9d775 | ||
|
|
e708e117be | ||
|
|
836088534b | ||
|
|
6ae97e630e | ||
|
|
bae0b9e746 | ||
|
|
15262343f4 | ||
|
|
be31a0ce82 | ||
|
|
0b0b6137b8 | ||
|
|
156b0c27f5 | ||
|
|
ca99596270 | ||
|
|
e22ffa8601 | ||
|
|
24233f104a |
@@ -22,7 +22,7 @@ libraryDependencies ++= Seq(
|
|||||||
"dnsjava" % "dnsjava" % "2.1.5",
|
"dnsjava" % "dnsjava" % "2.1.5",
|
||||||
"com.github.kevinsawicki" % "http-request" % "5.6",
|
"com.github.kevinsawicki" % "http-request" % "5.6",
|
||||||
"commons-net" % "commons-net" % "3.3",
|
"commons-net" % "commons-net" % "3.3",
|
||||||
"com.google.zxing" % "android-integration" % "2.2"
|
"com.google.zxing" % "android-integration" % "3.1.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.github.shadowsocks"
|
package="com.github.shadowsocks"
|
||||||
android:versionCode="89"
|
android:versionCode="91"
|
||||||
android:versionName="2.5.1">
|
android:versionName="2.5.3">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
|
|||||||
@@ -69,6 +69,9 @@
|
|||||||
<string name="flushing">刷新中...</string>
|
<string name="flushing">刷新中...</string>
|
||||||
<string name="add_profile">添加配置文件</string>
|
<string name="add_profile">添加配置文件</string>
|
||||||
|
|
||||||
|
<string name="enable_nat">启用 NAT 模式.</string>
|
||||||
|
<string name="disable_nat">禁用 NAT 模式.</string>
|
||||||
|
|
||||||
<string name="udp_dns">UDP 转发</string>
|
<string name="udp_dns">UDP 转发</string>
|
||||||
<string name="udp_dns_summary">由远程服务器转发 UDP 协议的数据包</string>
|
<string name="udp_dns_summary">由远程服务器转发 UDP 协议的数据包</string>
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -59,6 +59,8 @@
|
|||||||
<string name="stop">Stop the service</string>
|
<string name="stop">Stop the service</string>
|
||||||
<string name="stopping">Shutting down...</string>
|
<string name="stopping">Shutting down...</string>
|
||||||
<string name="vpn_error">Error: \"%s\".</string>
|
<string name="vpn_error">Error: \"%s\".</string>
|
||||||
|
<string name="enable_nat">Turn on NAT mode.</string>
|
||||||
|
<string name="disable_nat">Turn off NAT mode.</string>
|
||||||
|
|
||||||
<!-- alert category -->
|
<!-- alert category -->
|
||||||
<string name="ok_iknow">OK</string>
|
<string name="ok_iknow">OK</string>
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ package com.github.shadowsocks
|
|||||||
|
|
||||||
import java.util
|
import java.util
|
||||||
import java.io.{OutputStream, InputStream, ByteArrayInputStream, ByteArrayOutputStream, IOException, FileOutputStream}
|
import java.io.{OutputStream, InputStream, ByteArrayInputStream, ByteArrayOutputStream, IOException, FileOutputStream}
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
import android.app.backup.BackupManager
|
import android.app.backup.BackupManager
|
||||||
import android.app.{Activity, AlertDialog, ProgressDialog}
|
import android.app.{Activity, AlertDialog, ProgressDialog}
|
||||||
@@ -51,6 +52,7 @@ import android.net.{Uri, VpnService}
|
|||||||
import android.os._
|
import android.os._
|
||||||
import android.preference._
|
import android.preference._
|
||||||
import android.util.{DisplayMetrics, Log}
|
import android.util.{DisplayMetrics, Log}
|
||||||
|
import android.view.View.OnLongClickListener
|
||||||
import android.view._
|
import android.view._
|
||||||
import android.webkit.{WebView, WebViewClient}
|
import android.webkit.{WebView, WebViewClient}
|
||||||
import android.widget._
|
import android.widget._
|
||||||
@@ -67,7 +69,6 @@ import net.simonvt.menudrawer.MenuDrawer
|
|||||||
|
|
||||||
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
import scala.collection.mutable.{ArrayBuffer, ListBuffer}
|
||||||
import scala.concurrent.ops._
|
import scala.concurrent.ops._
|
||||||
import scala.ref.WeakReference
|
|
||||||
|
|
||||||
class ProfileIconDownloader(context: Context, connectTimeout: Int, readTimeout: Int)
|
class ProfileIconDownloader(context: Context, connectTimeout: Int, readTimeout: Int)
|
||||||
extends BaseImageDownloader(context, connectTimeout, readTimeout) {
|
extends BaseImageDownloader(context, connectTimeout, readTimeout) {
|
||||||
@@ -325,8 +326,8 @@ class Shadowsocks
|
|||||||
val cmd = new ArrayBuffer[String]()
|
val cmd = new ArrayBuffer[String]()
|
||||||
|
|
||||||
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) {
|
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks", "tun2socks")) {
|
||||||
cmd.append("chmod 666 %s%s-nat.pid".format(Path.BASE, task))
|
cmd.append("chmod 666 %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
cmd.append("chmod 666 %s%s-vpn.pid".format(Path.BASE, task))
|
cmd.append("chmod 666 %s%s-vpn.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
}
|
}
|
||||||
Console.runRootCommand(cmd.toArray)
|
Console.runRootCommand(cmd.toArray)
|
||||||
cmd.clear()
|
cmd.clear()
|
||||||
@@ -335,17 +336,17 @@ class Shadowsocks
|
|||||||
try {
|
try {
|
||||||
val pid_nat = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt
|
val pid_nat = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt
|
||||||
val pid_vpn = scala.io.Source.fromFile(Path.BASE + task + "-vpn.pid").mkString.trim.toInt
|
val pid_vpn = scala.io.Source.fromFile(Path.BASE + task + "-vpn.pid").mkString.trim.toInt
|
||||||
cmd.append("kill -9 %d".format(pid_nat))
|
cmd.append("kill -9 %d".formatLocal(Locale.ENGLISH, pid_nat))
|
||||||
cmd.append("kill -9 %d".format(pid_vpn))
|
cmd.append("kill -9 %d".formatLocal(Locale.ENGLISH, pid_vpn))
|
||||||
Process.killProcess(pid_nat)
|
Process.killProcess(pid_nat)
|
||||||
Process.killProcess(pid_vpn)
|
Process.killProcess(pid_vpn)
|
||||||
} catch {
|
} catch {
|
||||||
case e: Throwable => Log.e(Shadowsocks.TAG, "unable to kill " + task)
|
case e: Throwable => Log.e(Shadowsocks.TAG, "unable to kill " + task)
|
||||||
}
|
}
|
||||||
cmd.append("rm -f %s%s-nat.pid".format(Path.BASE, task))
|
cmd.append("rm -f %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
cmd.append("rm -f %s%s-nat.conf".format(Path.BASE, task))
|
cmd.append("rm -f %s%s-nat.conf".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
cmd.append("rm -f %s%s-vpn.pid".format(Path.BASE, task))
|
cmd.append("rm -f %s%s-vpn.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
cmd.append("rm -f %s%s-vpn.conf".format(Path.BASE, task))
|
cmd.append("rm -f %s%s-vpn.conf".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
}
|
}
|
||||||
Console.runCommand(cmd.toArray)
|
Console.runCommand(cmd.toArray)
|
||||||
Console.runRootCommand(cmd.toArray)
|
Console.runRootCommand(cmd.toArray)
|
||||||
@@ -499,13 +500,30 @@ class Shadowsocks
|
|||||||
getActionBar.setDisplayShowTitleEnabled(false)
|
getActionBar.setDisplayShowTitleEnabled(false)
|
||||||
getActionBar.setDisplayShowCustomEnabled(true)
|
getActionBar.setDisplayShowCustomEnabled(true)
|
||||||
getActionBar.setIcon(R.drawable.ic_stat_shadowsocks)
|
getActionBar.setIcon(R.drawable.ic_stat_shadowsocks)
|
||||||
|
title.setOnLongClickListener(new OnLongClickListener {
|
||||||
|
override def onLongClick(v: View): Boolean = {
|
||||||
|
if (Utils.isLollipopOrAbove && bgService != null
|
||||||
|
&& (bgService.getState == State.INIT || bgService.getState == State.STOPPED)) {
|
||||||
|
val natEnabled = status.getBoolean(Key.isNAT, false)
|
||||||
|
status.edit().putBoolean(Key.isNAT, !natEnabled).commit()
|
||||||
|
if (!natEnabled) {
|
||||||
|
Toast.makeText(getBaseContext, R.string.enable_nat, Toast.LENGTH_LONG).show()
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getBaseContext, R.string.disable_nat, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Register broadcast receiver
|
// Register broadcast receiver
|
||||||
registerReceiver(preferenceReceiver, new IntentFilter(Action.UPDATE_PREFS))
|
registerReceiver(preferenceReceiver, new IntentFilter(Action.UPDATE_PREFS))
|
||||||
|
|
||||||
// Bind to the service
|
// Bind to the service
|
||||||
spawn {
|
spawn {
|
||||||
val isRoot = Console.isRoot
|
val isRoot = (!Utils.isLollipopOrAbove || status.getBoolean(Key.isNAT, false)) && Console.isRoot
|
||||||
handler.post(new Runnable {
|
handler.post(new Runnable {
|
||||||
override def run() {
|
override def run() {
|
||||||
status.edit.putBoolean(Key.isRoot, isRoot).commit()
|
status.edit.putBoolean(Key.isRoot, isRoot).commit()
|
||||||
@@ -575,6 +593,9 @@ class Shadowsocks
|
|||||||
h.postDelayed(new Runnable() {
|
h.postDelayed(new Runnable() {
|
||||||
def run() {
|
def run() {
|
||||||
val integrator = new IntentIntegrator(Shadowsocks.this)
|
val integrator = new IntentIntegrator(Shadowsocks.this)
|
||||||
|
val list = new java.util.ArrayList(IntentIntegrator.TARGET_ALL_KNOWN)
|
||||||
|
list.add("tw.com.quickmark")
|
||||||
|
integrator.setTargetApplications(list)
|
||||||
integrator.initiateScan()
|
integrator.initiateScan()
|
||||||
h.sendEmptyMessage(0)
|
h.sendEmptyMessage(0)
|
||||||
}
|
}
|
||||||
@@ -652,7 +673,7 @@ class Shadowsocks
|
|||||||
if (!profile.isDefined) return false
|
if (!profile.isDefined) return false
|
||||||
|
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setMessage(String.format(getString(R.string.remove_profile), profile.get.name))
|
.setMessage(String.format(Locale.ENGLISH, getString(R.string.remove_profile), profile.get.name))
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
|
||||||
override def onClick(dialog: DialogInterface, i: Int) = dialog.cancel()
|
override def onClick(dialog: DialogInterface, i: Int) = dialog.cancel()
|
||||||
@@ -820,7 +841,7 @@ class Shadowsocks
|
|||||||
val ab = new ArrayBuffer[String]
|
val ab = new ArrayBuffer[String]
|
||||||
ab.append("mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system")
|
ab.append("mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system")
|
||||||
for (executable <- Shadowsocks.EXECUTABLES) {
|
for (executable <- Shadowsocks.EXECUTABLES) {
|
||||||
ab.append("cp %s%s /system/bin/".format(Path.BASE, executable))
|
ab.append("cp %s%s /system/bin/".formatLocal(Locale.ENGLISH, Path.BASE, executable))
|
||||||
ab.append("chmod 755 /system/bin/" + executable)
|
ab.append("chmod 755 /system/bin/" + executable)
|
||||||
ab.append("chown root:shell /system/bin/" + executable)
|
ab.append("chown root:shell /system/bin/" + executable)
|
||||||
}
|
}
|
||||||
@@ -956,7 +977,7 @@ class Shadowsocks
|
|||||||
}
|
}
|
||||||
|
|
||||||
new AlertDialog.Builder(this)
|
new AlertDialog.Builder(this)
|
||||||
.setTitle(getString(R.string.about_title).format(versionName))
|
.setTitle(getString(R.string.about_title).formatLocal(Locale.ENGLISH, versionName))
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setNegativeButton(getString(R.string.ok_iknow), new DialogInterface.OnClickListener() {
|
.setNegativeButton(getString(R.string.ok_iknow), new DialogInterface.OnClickListener() {
|
||||||
override def onClick(dialog: DialogInterface, id: Int) {
|
override def onClick(dialog: DialogInterface, id: Int) {
|
||||||
@@ -1001,7 +1022,7 @@ class Shadowsocks
|
|||||||
.setDuration(Configuration.DURATION_LONG)
|
.setDuration(Configuration.DURATION_LONG)
|
||||||
.build()
|
.build()
|
||||||
Crouton
|
Crouton
|
||||||
.makeText(Shadowsocks.this, getString(R.string.vpn_error).format(m), style)
|
.makeText(Shadowsocks.this, getString(R.string.vpn_error).formatLocal(Locale.ENGLISH, m), style)
|
||||||
.setConfiguration(config)
|
.setConfiguration(config)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ package com.github.shadowsocks
|
|||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.reflect.{InvocationTargetException, Method}
|
import java.lang.reflect.{InvocationTargetException, Method}
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
import android.app.{Notification, NotificationManager, PendingIntent, Service}
|
import android.app.{Notification, NotificationManager, PendingIntent, Service}
|
||||||
import android.content._
|
import android.content._
|
||||||
@@ -48,7 +49,7 @@ import android.content.pm.{PackageInfo, PackageManager}
|
|||||||
import android.net.{Network, ConnectivityManager}
|
import android.net.{Network, ConnectivityManager}
|
||||||
import android.os._
|
import android.os._
|
||||||
import android.support.v4.app.NotificationCompat
|
import android.support.v4.app.NotificationCompat
|
||||||
import android.util.Log
|
import android.util.{SparseArray, Log}
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.github.shadowsocks.aidl.Config
|
import com.github.shadowsocks.aidl.Config
|
||||||
import com.github.shadowsocks.utils._
|
import com.github.shadowsocks.utils._
|
||||||
@@ -71,6 +72,9 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
private val mStartForegroundSignature = Array[Class[_]](classOf[Int], classOf[Notification])
|
private val mStartForegroundSignature = Array[Class[_]](classOf[Int], classOf[Notification])
|
||||||
private val mStopForegroundSignature = Array[Class[_]](classOf[Boolean])
|
private val mStopForegroundSignature = Array[Class[_]](classOf[Boolean])
|
||||||
private val mSetForegroundSignature = Array[Class[_]](classOf[Boolean])
|
private val mSetForegroundSignature = Array[Class[_]](classOf[Boolean])
|
||||||
|
private val mSetForegroundArgs = new Array[AnyRef](1)
|
||||||
|
private val mStartForegroundArgs = new Array[AnyRef](2)
|
||||||
|
private val mStopForegroundArgs = new Array[AnyRef](1)
|
||||||
|
|
||||||
var closeReceiver: BroadcastReceiver = null
|
var closeReceiver: BroadcastReceiver = null
|
||||||
var connReceiver: BroadcastReceiver = null
|
var connReceiver: BroadcastReceiver = null
|
||||||
@@ -82,32 +86,61 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
private var mSetForeground: Method = null
|
private var mSetForeground: Method = null
|
||||||
private var mStartForeground: Method = null
|
private var mStartForeground: Method = null
|
||||||
private var mStopForeground: Method = null
|
private var mStopForeground: Method = null
|
||||||
private var mSetForegroundArgs = new Array[AnyRef](1)
|
|
||||||
private var mStartForegroundArgs = new Array[AnyRef](2)
|
|
||||||
private var mStopForegroundArgs = new Array[AnyRef](1)
|
|
||||||
|
|
||||||
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
|
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
|
||||||
|
|
||||||
def setDnsForAllNetwork(dns: String) {
|
private val dnsAddressCache = new SparseArray[String]
|
||||||
|
|
||||||
|
def getNetId(network: Network): Int = {
|
||||||
|
network.getClass.getDeclaredField("netId").get(network).asInstanceOf[Int]
|
||||||
|
}
|
||||||
|
|
||||||
|
def restoreDnsForAllNetwork() {
|
||||||
val manager = getSystemService(Context.CONNECTIVITY_SERVICE).asInstanceOf[ConnectivityManager]
|
val manager = getSystemService(Context.CONNECTIVITY_SERVICE).asInstanceOf[ConnectivityManager]
|
||||||
val networks = manager.getAllNetworks
|
val networks = manager.getAllNetworks
|
||||||
val cmdBuf = new ArrayBuffer[String]()
|
val cmdBuf = new ArrayBuffer[String]()
|
||||||
networks.foreach(network => {
|
networks.foreach(network => {
|
||||||
val networkInfo = manager.getNetworkInfo(network)
|
val netId = getNetId(network)
|
||||||
if (networkInfo.isAvailable) {
|
val oldDns = dnsAddressCache.get(netId)
|
||||||
val netId = network.getClass.getDeclaredField("netId").get(network).asInstanceOf[Int]
|
if (oldDns != null) {
|
||||||
cmdBuf.append("ndc resolver setnetdns %d \"\" %s".format(netId, dns))
|
cmdBuf.append("ndc resolver setnetdns %d \"\" %s".formatLocal(Locale.ENGLISH, netId, oldDns))
|
||||||
|
dnsAddressCache.remove(netId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Console.runRootCommand(cmdBuf.toArray)
|
if (cmdBuf.nonEmpty) Console.runRootCommand(cmdBuf.toArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
def setupDns() = {
|
def setDnsForAllNetwork(dns: String) {
|
||||||
|
val manager = getSystemService(Context.CONNECTIVITY_SERVICE).asInstanceOf[ConnectivityManager]
|
||||||
|
val networks = manager.getAllNetworks
|
||||||
|
if (networks == null) return
|
||||||
|
|
||||||
|
val cmdBuf = new ArrayBuffer[String]()
|
||||||
|
networks.foreach(network => {
|
||||||
|
val networkInfo = manager.getNetworkInfo(network)
|
||||||
|
if (networkInfo == null) return
|
||||||
|
if (networkInfo.isConnected) {
|
||||||
|
val netId = getNetId(network)
|
||||||
|
val curDnsList = manager.getLinkProperties(network).getDnsServers
|
||||||
|
if (curDnsList != null) {
|
||||||
|
import scala.collection.JavaConverters._
|
||||||
|
val curDns = curDnsList.asScala.map(ip => ip.getHostAddress).mkString(" ")
|
||||||
|
if (curDns != dns) {
|
||||||
|
dnsAddressCache.put(netId, curDns)
|
||||||
|
cmdBuf.append("ndc resolver setnetdns %d \"\" %s".formatLocal(Locale.ENGLISH, netId, dns))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (cmdBuf.nonEmpty) Console.runRootCommand(cmdBuf.toArray)
|
||||||
|
}
|
||||||
|
|
||||||
|
def setupDns() {
|
||||||
setDnsForAllNetwork("127.0.0.1")
|
setDnsForAllNetwork("127.0.0.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
def resetDns() = {
|
def resetDns() = {
|
||||||
setDnsForAllNetwork("114.114.114.114 8.8.8.8 208.67.222.222")
|
restoreDnsForAllNetwork()
|
||||||
}
|
}
|
||||||
|
|
||||||
def flushDns() {
|
def flushDns() {
|
||||||
@@ -119,7 +152,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
val networkInfo = manager.getNetworkInfo(network)
|
val networkInfo = manager.getNetworkInfo(network)
|
||||||
if (networkInfo.isAvailable) {
|
if (networkInfo.isAvailable) {
|
||||||
val netId = network.getClass.getDeclaredField("netId").get(network).asInstanceOf[Int]
|
val netId = network.getClass.getDeclaredField("netId").get(network).asInstanceOf[Int]
|
||||||
cmdBuf.append("ndc resolver flushnet %d".format(netId))
|
cmdBuf.append("ndc resolver flushnet %d".formatLocal(Locale.ENGLISH, netId))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
Console.runRootCommand(cmdBuf.toArray)
|
Console.runRootCommand(cmdBuf.toArray)
|
||||||
@@ -159,7 +192,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val conf = ConfigUtils
|
val conf = ConfigUtils
|
||||||
.SHADOWSOCKS.format(config.proxy, config.remotePort, config.localPort,
|
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, config.localPort,
|
||||||
config.sitekey, config.encMethod, 10)
|
config.sitekey, config.encMethod, 10)
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-nat.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-nat.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
@@ -183,7 +216,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
def startTunnel() {
|
def startTunnel() {
|
||||||
if (config.isUdpDns) {
|
if (config.isUdpDns) {
|
||||||
val conf = ConfigUtils
|
val conf = ConfigUtils
|
||||||
.SHADOWSOCKS.format(config.proxy, config.remotePort, 8153,
|
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8153,
|
||||||
config.sitekey, config.encMethod, 10)
|
config.sitekey, config.encMethod, 10)
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
@@ -211,7 +244,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
val conf = ConfigUtils
|
val conf = ConfigUtils
|
||||||
.SHADOWSOCKS.format(config.proxy, config.remotePort, 8163,
|
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8163,
|
||||||
config.sitekey, config.encMethod, 10)
|
config.sitekey, config.encMethod, 10)
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-nat.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
@@ -232,10 +265,10 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
def startDnsDaemon() {
|
def startDnsDaemon() {
|
||||||
val conf = if (Utils.isLollipopOrAbove) {
|
val conf = if (Utils.isLollipopOrAbove) {
|
||||||
ConfigUtils
|
ConfigUtils
|
||||||
.PDNSD_BYPASS.format("127.0.0.1", 53, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163)
|
.PDNSD_BYPASS.formatLocal(Locale.ENGLISH, "127.0.0.1", 53, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163)
|
||||||
} else {
|
} else {
|
||||||
ConfigUtils
|
ConfigUtils
|
||||||
.PDNSD_BYPASS.format("127.0.0.1", 8153, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163)
|
.PDNSD_BYPASS.formatLocal(Locale.ENGLISH, "127.0.0.1", 8153, Path.BASE + "pdnsd-nat.pid", getString(R.string.exclude), 8163)
|
||||||
}
|
}
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-nat.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-nat.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
@@ -265,9 +298,9 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def startRedsocksDaemon() {
|
def startRedsocksDaemon() {
|
||||||
val conf = ConfigUtils.REDSOCKS.format(config.localPort)
|
val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, config.localPort)
|
||||||
val cmd = Path.BASE + "redsocks -p %sredsocks-nat.pid -c %sredsocks-nat.conf"
|
val cmd = Path.BASE + "redsocks -p %sredsocks-nat.pid -c %sredsocks-nat.conf"
|
||||||
.format(Path.BASE, Path.BASE)
|
.formatLocal(Locale.ENGLISH, Path.BASE, Path.BASE)
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "redsocks-nat.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "redsocks-nat.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
})
|
})
|
||||||
@@ -360,7 +393,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
val cmd = new ArrayBuffer[String]()
|
val cmd = new ArrayBuffer[String]()
|
||||||
|
|
||||||
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks")) {
|
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks")) {
|
||||||
cmd.append("chmod 666 %s%s-nat.pid".format(Path.BASE, task))
|
cmd.append("chmod 666 %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
}
|
}
|
||||||
Console.runRootCommand(cmd.toArray)
|
Console.runRootCommand(cmd.toArray)
|
||||||
cmd.clear()
|
cmd.clear()
|
||||||
@@ -368,13 +401,13 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks")) {
|
for (task <- Array("ss-local", "ss-tunnel", "pdnsd", "redsocks")) {
|
||||||
try {
|
try {
|
||||||
val pid = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt
|
val pid = scala.io.Source.fromFile(Path.BASE + task + "-nat.pid").mkString.trim.toInt
|
||||||
cmd.append("kill -9 %d".format(pid))
|
cmd.append("kill -9 %d".formatLocal(Locale.ENGLISH, pid))
|
||||||
Process.killProcess(pid)
|
Process.killProcess(pid)
|
||||||
} catch {
|
} catch {
|
||||||
case e: Throwable => Log.e(TAG, "unable to kill " + task)
|
case e: Throwable => Log.e(TAG, "unable to kill " + task)
|
||||||
}
|
}
|
||||||
cmd.append("rm -f %s%s-nat.pid".format(Path.BASE, task))
|
cmd.append("rm -f %s%s-nat.pid".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
cmd.append("rm -f %s%s-nat.conf".format(Path.BASE, task))
|
cmd.append("rm -f %s%s-nat.conf".formatLocal(Locale.ENGLISH, Path.BASE, task))
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.runRootCommand(cmd.toArray)
|
Console.runRootCommand(cmd.toArray)
|
||||||
@@ -476,7 +509,7 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
filter.addAction(Action.CLOSE)
|
filter.addAction(Action.CLOSE)
|
||||||
closeReceiver = new BroadcastReceiver() {
|
closeReceiver = new BroadcastReceiver() {
|
||||||
def onReceive(p1: Context, p2: Intent) {
|
def onReceive(p1: Context, p2: Intent) {
|
||||||
Toast.makeText(p1, R.string.stopping, Toast.LENGTH_SHORT)
|
Toast.makeText(p1, R.string.stopping, Toast.LENGTH_SHORT).show()
|
||||||
stopRunner()
|
stopRunner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,10 +543,6 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
// Clean up
|
// Clean up
|
||||||
killProcesses()
|
killProcesses()
|
||||||
|
|
||||||
// Set DNS
|
|
||||||
if (Utils.isLollipopOrAbove) setupDns()
|
|
||||||
flushDns()
|
|
||||||
|
|
||||||
var resolved: Boolean = false
|
var resolved: Boolean = false
|
||||||
if (!InetAddressUtils.isIPv4Address(config.proxy) &&
|
if (!InetAddressUtils.isIPv4Address(config.proxy) &&
|
||||||
!InetAddressUtils.isIPv6Address(config.proxy)) {
|
!InetAddressUtils.isIPv6Address(config.proxy)) {
|
||||||
@@ -528,8 +557,13 @@ class ShadowsocksNatService extends Service with BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (resolved && handleConnection) {
|
if (resolved && handleConnection) {
|
||||||
|
|
||||||
|
// Set DNS
|
||||||
|
if (Utils.isLollipopOrAbove) setupDns()
|
||||||
|
flushDns()
|
||||||
|
|
||||||
notifyForegroundAlert(getString(R.string.forward_success),
|
notifyForegroundAlert(getString(R.string.forward_success),
|
||||||
getString(R.string.service_running).format(config.profileName))
|
getString(R.string.service_running).formatLocal(Locale.ENGLISH, config.profileName))
|
||||||
changeState(State.CONNECTED)
|
changeState(State.CONNECTED)
|
||||||
} else {
|
} else {
|
||||||
changeState(State.STOPPED, getString(R.string.service_failed))
|
changeState(State.STOPPED, getString(R.string.service_failed))
|
||||||
|
|||||||
@@ -50,7 +50,8 @@ import com.github.shadowsocks.aidl.IShadowsocksService
|
|||||||
|
|
||||||
class ShadowsocksRunnerActivity extends Activity {
|
class ShadowsocksRunnerActivity extends Activity {
|
||||||
|
|
||||||
lazy val settings = PreferenceManager.getDefaultSharedPreferences(this)
|
private lazy val settings = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
private lazy val status = getSharedPreferences(Key.status, Context.MODE_PRIVATE)
|
||||||
|
|
||||||
val handler = new Handler()
|
val handler = new Handler()
|
||||||
val connection = new ServiceConnection {
|
val connection = new ServiceConnection {
|
||||||
@@ -72,10 +73,10 @@ class ShadowsocksRunnerActivity extends Activity {
|
|||||||
|
|
||||||
def isVpnEnabled: Boolean = {
|
def isVpnEnabled: Boolean = {
|
||||||
if (vpnEnabled < 0) {
|
if (vpnEnabled < 0) {
|
||||||
vpnEnabled = if (!Console.isRoot) {
|
vpnEnabled = if ((!Utils.isLollipopOrAbove || status.getBoolean(Key.isNAT, false)) && Console.isRoot) {
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
0
|
||||||
|
} else {
|
||||||
|
1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vpnEnabled == 1) true else false
|
if (vpnEnabled == 1) true else false
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
package com.github.shadowsocks
|
package com.github.shadowsocks
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
import android.app._
|
import android.app._
|
||||||
import android.content._
|
import android.content._
|
||||||
@@ -107,7 +108,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val conf = ConfigUtils
|
val conf = ConfigUtils
|
||||||
.SHADOWSOCKS.format(config.proxy, config.remotePort, config.localPort,
|
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, config.localPort,
|
||||||
config.sitekey, config.encMethod, 10)
|
config.sitekey, config.encMethod, 10)
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-vpn.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "ss-local-vpn.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
@@ -130,7 +131,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
|
|
||||||
def startDnsTunnel() = {
|
def startDnsTunnel() = {
|
||||||
val conf = ConfigUtils
|
val conf = ConfigUtils
|
||||||
.SHADOWSOCKS.format(config.proxy, config.remotePort, 8163,
|
.SHADOWSOCKS.formatLocal(Locale.ENGLISH, config.proxy, config.remotePort, 8163,
|
||||||
config.sitekey, config.encMethod, 10)
|
config.sitekey, config.encMethod, 10)
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "ss-tunnel-vpn.conf"))(p => {
|
||||||
p.println(conf)
|
p.println(conf)
|
||||||
@@ -150,9 +151,9 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
def startDnsDaemon() {
|
def startDnsDaemon() {
|
||||||
val conf = {
|
val conf = {
|
||||||
if (Utils.isLollipopOrAbove) {
|
if (Utils.isLollipopOrAbove) {
|
||||||
ConfigUtils.PDNSD_BYPASS.format("0.0.0.0", 8153, Path.BASE + "pdnsd-vpn.pid", getString(R.string.exclude), 8163)
|
ConfigUtils.PDNSD_BYPASS.formatLocal(Locale.ENGLISH, "0.0.0.0", 8153, Path.BASE + "pdnsd-vpn.pid", getString(R.string.exclude), 8163)
|
||||||
} else {
|
} else {
|
||||||
ConfigUtils.PDNSD_LOCAL.format("0.0.0.0", 8163)
|
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "0.0.0.0", 8163)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => {
|
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd-vpn.conf"))(p => {
|
||||||
@@ -182,7 +183,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
builder
|
builder
|
||||||
.setSession(config.profileName)
|
.setSession(config.profileName)
|
||||||
.setMtu(VPN_MTU)
|
.setMtu(VPN_MTU)
|
||||||
.addAddress(PRIVATE_VLAN.format("1"), 24)
|
.addAddress(PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"), 24)
|
||||||
.addDnsServer("8.8.8.8")
|
.addDnsServer("8.8.8.8")
|
||||||
|
|
||||||
if (Utils.isLollipopOrAbove) {
|
if (Utils.isLollipopOrAbove) {
|
||||||
@@ -312,12 +313,12 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
|||||||
+ "--tunmtu %d "
|
+ "--tunmtu %d "
|
||||||
+ "--loglevel 3 "
|
+ "--loglevel 3 "
|
||||||
+ "--pid %stun2socks-vpn.pid")
|
+ "--pid %stun2socks-vpn.pid")
|
||||||
.format(PRIVATE_VLAN.format("2"), config.localPort, fd, VPN_MTU, Path.BASE)
|
.formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "2"), config.localPort, fd, VPN_MTU, Path.BASE)
|
||||||
|
|
||||||
if (config.isUdpDns)
|
if (config.isUdpDns)
|
||||||
cmd += " --enable-udprelay"
|
cmd += " --enable-udprelay"
|
||||||
else
|
else
|
||||||
cmd += " --dnsgw %s:8153".format(PRIVATE_VLAN.format("1"))
|
cmd += " --dnsgw %s:8153".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"))
|
||||||
|
|
||||||
if (Utils.isLollipopOrAbove) {
|
if (Utils.isLollipopOrAbove) {
|
||||||
cmd += " --fake-proc"
|
cmd += " --fake-proc"
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ object Key {
|
|||||||
|
|
||||||
val proxied = "Proxyed"
|
val proxied = "Proxyed"
|
||||||
|
|
||||||
|
val isNAT = "isNAT"
|
||||||
val isRoot = "isRoot"
|
val isRoot = "isRoot"
|
||||||
val status = "status"
|
val status = "status"
|
||||||
val proxyedApps = "proxyedApps"
|
val proxyedApps = "proxyedApps"
|
||||||
|
|||||||
Reference in New Issue
Block a user