Commit 2e3baa72 authored by Mygod's avatar Mygod Committed by Max Lv

Move config files to files directory

It looks nicer.

Other changes btw:

* Removes duplicated logcats from GuardedProcess;
* local_port is moved to command line options since that's not sensitive;
* pdnsd uses cache dir;
* Refinements to Utils.
parent 7491a667
Subproject commit 19e222bad8416f20b7694bff75f2cee72a70701e
Subproject commit 4c3c0ce9c33825949e289aa36f217d2de5af48c6
......@@ -20,7 +20,7 @@
package com.github.shadowsocks
import java.io.IOException
import java.io.{File, IOException}
import java.net.InetAddress
import java.util
import java.util.concurrent.TimeUnit
......@@ -63,7 +63,6 @@ trait BaseService extends Service {
private final val bandwidthListeners = new mutable.HashSet[IBinder]() // the binder is the real identifier
lazy val handler = new Handler(getMainLooper)
lazy val restartHanlder = new Handler(getMainLooper)
lazy val protectPath: String = getApplicationInfo.dataDir + "/protect_path"
private val closeReceiver: BroadcastReceiver = (context: Context, _: Intent) => {
Toast.makeText(context, R.string.stopping, Toast.LENGTH_SHORT).show()
......@@ -320,18 +319,17 @@ trait BaseService extends Service {
if (TcpFastOpen.sendEnabled) result += "--fast-open"
result
}
protected def buildShadowsocksConfig(file: String, localPortOffset: Int = 0): String = {
protected final def buildShadowsocksConfig(file: String): String = {
val config = new JSONObject()
.put("server", profile.host)
.put("server_port", profile.remotePort)
.put("local_port", profile.localPort + localPortOffset)
.put("password", profile.password)
.put("method", profile.method)
if (profile.auth) config.put("auth", true)
if (pluginPath != null) config
.put("plugin", Commandline.toString(buildPluginCommandLine()))
.put("plugin_opts", plugin.toString)
IOUtils.writeString(file, config.toString)
IOUtils.writeString(new File(getFilesDir, file), config.toString)
file
}
}
......@@ -27,6 +27,7 @@ import java.util.concurrent.Semaphore
import android.util.Log
import com.github.shadowsocks.utils.CloseUtils._
import com.github.shadowsocks.utils.Commandline
import com.github.shadowsocks.ShadowsocksApplication.app
import scala.collection.JavaConversions._
import scala.collection.immutable.Stream
......@@ -41,7 +42,7 @@ class StreamLogger(is: InputStream, tag: String) extends Thread {
/**
* @author ayanamist@gmail.com
*/
class GuardedProcess(cmd: Seq[String]) {
class GuardedProcess(cmd: String*) {
private val TAG = classOf[GuardedProcess].getSimpleName
@volatile private var guardThread: Thread = _
......@@ -58,10 +59,13 @@ class GuardedProcess(cmd: Seq[String]) {
try {
var callback: () => Unit = null
while (!isDestroyed) {
Log.i(TAG, "start process: " + Commandline.toString(cmd))
if (BuildConfig.DEBUG) Log.d(TAG, "start process: " + Commandline.toString(cmd))
val startTime = currentTimeMillis
process = new ProcessBuilder(cmd).redirectErrorStream(true).start
process = new ProcessBuilder(cmd)
.redirectErrorStream(true)
.directory(app.getFilesDir)
.start()
val is = process.getInputStream
new StreamLogger(is, TAG).start()
......@@ -84,7 +88,7 @@ class GuardedProcess(cmd: Seq[String]) {
}
} catch {
case _: InterruptedException =>
Log.i(TAG, "thread interrupt, destroy process: " + Commandline.toString(cmd))
if (BuildConfig.DEBUG) Log.d(TAG, "thread interrupt, destroy process: " + Commandline.toString(cmd))
process.destroy()
case e: IOException => ioException = e
} finally semaphore.release()
......
......@@ -20,7 +20,7 @@
package com.github.shadowsocks
import java.io.{FileOutputStream, IOException}
import java.io.{File, FileOutputStream, IOException}
import java.util
import java.util.Locale
import java.util.concurrent.TimeUnit
......@@ -184,7 +184,7 @@ 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"
.formatLocal(Locale.ENGLISH, getApplicationInfo.dataDir, task))
.formatLocal(Locale.ENGLISH, getFilesDir.getAbsolutePath, task))
}
if (app.isNatEnabled) {
cmd.append("iptables -t nat -F OUTPUT")
......@@ -204,7 +204,7 @@ class ShadowsocksApplication extends Application {
app.track(e)
}
if (files != null) for (file <- files) autoClose(assetManager.open("acl/" + file))(in =>
autoClose(new FileOutputStream(getApplicationInfo.dataDir + '/' + file))(out =>
autoClose(new FileOutputStream(new File(getFilesDir, file)))(out =>
IOUtils.copy(in, out)))
editor.putInt(Key.currentVersionCode, BuildConfig.VERSION_CODE).apply()
}
......
......@@ -53,76 +53,59 @@ class ShadowsocksNatService extends BaseService {
var su: Shell.Interactive = _
def startShadowsocksDaemon() {
val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so"
, "-b" , "127.0.0.1"
, "-t" , "600"
, "-P", getApplicationInfo.dataDir
, "-c" , buildShadowsocksConfig(getApplicationInfo.dataDir + "/ss-local-nat.conf"))
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.getPath(profile.route)
cmd += Acl.getFile(profile.route).getAbsolutePath
}
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
sslocalProcess = new GuardedProcess(cmd).start()
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 + 53).toString
, "-L" , if (profile.remoteDns == null) "8.8.8.8:53" else profile.remoteDns + ":53"
, "-P", getApplicationInfo.dataDir
, "-c" , buildShadowsocksConfig(getApplicationInfo.dataDir + "/ss-tunnel-nat.conf", 63))
val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so",
"-t", "10",
"-b", "127.0.0.1",
"-l", (profile.localPort + 63).toString,
"-L", if (profile.remoteDns == null) "8.8.8.8:53" else profile.remoteDns + ":53",
"-c", buildShadowsocksConfig("ss-tunnel-nat.conf"))
if (profile.udpdns) cmd.append("-u")
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
sstunnelProcess = new GuardedProcess(cmd).start()
sstunnelProcess = new GuardedProcess(cmd: _*).start()
}
def startDnsDaemon() {
val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0"
val conf = profile.route match {
IOUtils.writeString(new File(getFilesDir, "pdnsd-nat.conf"), profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getApplicationInfo.dataDir,
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath,
"127.0.0.1", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8",
getBlackList, reject, profile.localPort + 63, reject)
case Acl.CHINALIST =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getApplicationInfo.dataDir,
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath,
"127.0.0.1", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222",
"", reject, profile.localPort + 63, reject)
case _ =>
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "", getApplicationInfo.dataDir,
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "", getCacheDir.getAbsolutePath,
"127.0.0.1", profile.localPort + 53, profile.localPort + 63, reject)
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-nat.conf"))(p => {
p.println(conf)
})
val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", getApplicationInfo.dataDir + "/pdnsd-nat.conf")
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
pdnsdProcess = new GuardedProcess(cmd).start()
pdnsdProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", "pdnsd-nat.conf")
.start()
}
def startRedsocksDaemon() {
val conf = ConfigUtils.REDSOCKS.formatLocal(Locale.ENGLISH, profile.localPort)
val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libredsocks.so", "-c", getApplicationInfo.dataDir + "/redsocks-nat.conf")
Utils.printToFile(new File(getApplicationInfo.dataDir + "/redsocks-nat.conf"))(p => {
p.println(conf)
})
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
redsocksProcess = new GuardedProcess(cmd).start()
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. */
......
......@@ -34,7 +34,6 @@ 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 ShadowsocksVpnService extends VpnService with BaseService {
......@@ -163,65 +162,55 @@ class ShadowsocksVpnService extends VpnService with BaseService {
}
override protected def buildPluginCommandLine(): ArrayBuffer[String] =
super.buildPluginCommandLine() ++= Seq("-V", "-P", getApplicationInfo.dataDir)
super.buildPluginCommandLine() ++= Seq("-V", "-P", getFilesDir.getAbsolutePath)
def startShadowsocksDaemon() {
val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so", "-V"
, "-b", "127.0.0.1"
, "-t", "600"
, "-P", getApplicationInfo.dataDir
, "-c", buildShadowsocksConfig(getApplicationInfo.dataDir + "/ss-local-vpn.conf", 0))
val cmd = ArrayBuffer[String](getApplicationInfo.nativeLibraryDir + "/libss-local.so",
"-V",
"-b", "127.0.0.1",
"-l", profile.localPort.toString,
"-t", "600",
"-c", buildShadowsocksConfig("ss-local-vpn.conf"))
if (profile.udpdns) cmd += "-u"
if (profile.route != Acl.ALL) {
cmd += "--acl"
cmd += Acl.getPath(profile.route)
cmd += Acl.getFile(profile.route).getAbsolutePath
}
if (TcpFastOpen.sendEnabled) cmd += "--fast-open"
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
sslocalProcess = new GuardedProcess(cmd).start()
sslocalProcess = new GuardedProcess(cmd: _*).start()
}
def startDnsTunnel() {
val cmd = Array[String](getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so"
, "-V"
, "-t", "10"
, "-b", "127.0.0.1"
, "-L" , if (profile.remoteDns == null) "8.8.8.8:53" else profile.remoteDns + ":53"
, "-P", getApplicationInfo.dataDir
, "-c", buildShadowsocksConfig(getApplicationInfo.dataDir + "/ss-tunnel-vpn.conf", 63))
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
sstunnelProcess = new GuardedProcess(cmd).start()
}
def startDnsTunnel(): Unit =
sstunnelProcess = new GuardedProcess(getApplicationInfo.nativeLibraryDir + "/libss-tunnel.so",
"-V",
"-t", "10",
"-b", "127.0.0.1",
"-l", (profile.localPort + 63).toString,
"-L" , if (profile.remoteDns == null) "8.8.8.8:53" else profile.remoteDns + ":53",
"-c", buildShadowsocksConfig("ss-tunnel-vpn.conf")).start()
def startDnsDaemon() {
val reject = if (profile.ipv6) "224.0.0.0/3" else "224.0.0.0/3, ::/0"
val protect = "protect = \"" + protectPath +"\";"
val conf = profile.route match {
IOUtils.writeString(new File(getFilesDir, "pdnsd-vpn.conf"), profile.route match {
case Acl.BYPASS_CHN | Acl.BYPASS_LAN_CHN | Acl.GFWLIST | Acl.CUSTOM_RULES =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, protect, getApplicationInfo.dataDir,
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath,
"0.0.0.0", profile.localPort + 53, "114.114.114.114, 223.5.5.5, 1.2.4.8",
getBlackList, reject, profile.localPort + 63, reject)
case Acl.CHINALIST =>
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, protect, getApplicationInfo.dataDir,
ConfigUtils.PDNSD_DIRECT.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath,
"0.0.0.0", profile.localPort + 53, "8.8.8.8, 8.8.4.4, 208.67.222.222",
"", reject, profile.localPort + 63, reject)
case _ =>
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, protect, getApplicationInfo.dataDir,
ConfigUtils.PDNSD_LOCAL.formatLocal(Locale.ENGLISH, "protect = \"protect_path\";", getCacheDir.getAbsolutePath,
"0.0.0.0", profile.localPort + 53, profile.localPort + 63, reject)
}
Utils.printToFile(new File(getApplicationInfo.dataDir + "/pdnsd-vpn.conf"))(p => {
p.println(conf)
})
val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", getApplicationInfo.dataDir + "/pdnsd-vpn.conf")
val cmd = Array(getApplicationInfo.nativeLibraryDir + "/libpdnsd.so", "-c", "pdnsd-vpn.conf")
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
pdnsdProcess = new GuardedProcess(cmd).start()
pdnsdProcess = new GuardedProcess(cmd: _*).start()
}
@SuppressLint(Array("NewApi"))
......@@ -281,7 +270,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
"--socks-server-addr", "127.0.0.1:" + profile.localPort,
"--tunfd", fd.toString,
"--tunmtu", VPN_MTU.toString,
"--sock-path", getApplicationInfo.dataDir + "/sock_path",
"--sock-path", "sock_path",
"--loglevel", "3")
if (profile.ipv6)
......@@ -293,9 +282,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
cmd += ("--dnsgw", "%s:%d".formatLocal(Locale.ENGLISH, PRIVATE_VLAN.formatLocal(Locale.ENGLISH, "1"),
profile.localPort + 53))
if (BuildConfig.DEBUG) Log.d(TAG, Commandline.toString(cmd))
tun2socksProcess = new GuardedProcess(cmd).start(() => sendFd(fd))
tun2socksProcess = new GuardedProcess(cmd: _*).start(() => sendFd(fd))
fd
}
......@@ -305,7 +292,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
var tries = 1
while (tries < 5) {
Thread.sleep(1000 * tries)
if (System.sendfd(fd, getApplicationInfo.dataDir + "/sock_path") != -1) {
if (System.sendfd(fd, new File(getFilesDir, "sock_path").getAbsolutePath) != -1) {
return true
}
tries += 1
......
......@@ -32,11 +32,11 @@ object ShadowsocksVpnThread {
val getInt: Method = classOf[FileDescriptor].getDeclaredMethod("getInt$")
}
class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
class ShadowsocksVpnThread(service: ShadowsocksVpnService) extends Thread {
import ShadowsocksVpnThread._
val TAG = "ShadowsocksVpnService"
lazy val PATH: String = vpnService.getApplicationInfo.dataDir + "/protect_path"
val protect = new File(service.getFilesDir, "protect_path")
@volatile var isRunning: Boolean = true
@volatile var serverSocket: LocalServerSocket = _
......@@ -59,11 +59,11 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
override def run() {
new File(PATH).delete()
protect.delete()
try {
val localSocket = new LocalSocket
localSocket.bind(new LocalSocketAddress(PATH, LocalSocketAddress.Namespace.FILESYSTEM))
localSocket.bind(new LocalSocketAddress(protect.getAbsolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
serverSocket = new LocalServerSocket(localSocket.getFileDescriptor)
} catch {
case e: IOException =>
......@@ -89,7 +89,7 @@ class ShadowsocksVpnThread(vpnService: ShadowsocksVpnService) extends Thread {
if (fds.nonEmpty) {
val fd = getInt.invoke(fds(0)).asInstanceOf[Int]
val ret = vpnService.protect(fd)
val ret = service.protect(fd)
// Trick to close file decriptor
System.jniclose(fd)
......
package com.github.shadowsocks.acl
import java.io.FileNotFoundException
import java.io.{File, FileNotFoundException}
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.utils.IOUtils
......@@ -83,7 +83,7 @@ class Acl {
this.subnets ++= (if (bypass) proxySubnets else bypassSubnets)
this
}
final def fromId(id: String): Acl = fromSource(Source.fromFile(Acl.getPath(id)))
final def fromId(id: String): Acl = fromSource(Source.fromFile(Acl.getFile(id)))
override def toString: String = {
val result = new StringBuilder()
......@@ -128,7 +128,7 @@ object Acl {
final val CHINALIST = "china-list"
final val CUSTOM_RULES = "custom-rules"
def getPath(id: String): String = app.getApplicationInfo.dataDir + '/' + id + ".acl"
def getFile(id: String) = new File(app.getFilesDir, id + ".acl")
def customRules: Acl = {
val acl = new Acl()
try acl.fromId(CUSTOM_RULES) catch {
......@@ -138,5 +138,5 @@ object Acl {
acl.bypassHostnames.clear() // everything is bypassed
acl
}
def save(id: String, acl: Acl): Unit = IOUtils.writeString(getPath(id), acl.toString)
def save(id: String, acl: Acl): Unit = IOUtils.writeString(getFile(id), acl.toString)
}
......@@ -25,7 +25,6 @@ import java.util.concurrent.TimeUnit
import com.evernote.android.job.Job.{Params, Result}
import com.evernote.android.job.{Job, JobRequest}
import com.github.shadowsocks.ShadowsocksApplication.app
import com.github.shadowsocks.utils.IOUtils
import scala.io.Source
......@@ -47,11 +46,10 @@ object AclSyncJob {
class AclSyncJob(route: String) extends Job {
override def onRunJob(params: Params): Result = {
val filename = route + ".acl"
try {
//noinspection JavaAccessorMethodCalledAsEmptyParen
IOUtils.writeString(app.getApplicationInfo.dataDir + '/' + filename,
Source.fromURL("https://shadowsocks.org/acl/android/v1/" + filename).mkString)
IOUtils.writeString(Acl.getFile(route),
Source.fromURL("https://shadowsocks.org/acl/android/v1/" + route + ".acl").mkString)
Result.SUCCESS
} catch {
case e: IOException =>
......
......@@ -37,6 +37,8 @@ object IOUtils {
}
}
def writeString(file: File, content: String): Unit =
autoClose(new FileWriter(file))(writer => writer.write(content))
def writeString(file: String, content: String): Unit =
autoClose(new FileWriter(file))(writer => writer.write(content))
......
......@@ -25,6 +25,7 @@ import java.io.File
import eu.chainfire.libsuperuser.Shell
import scala.collection.JavaConverters._
import scala.io.Source
/**
* @author Mygod
......@@ -45,7 +46,7 @@ object TcpFastOpen {
def sendEnabled: Boolean = {
val file = new File("/proc/sys/net/ipv4/tcp_fastopen")
file.canRead && (Utils.readAllLines(file).toInt & 1) > 0
file.canRead && (Source.fromFile(file).mkString.toInt & 1) > 0
}
def enabled(value: Boolean): String = if (sendEnabled != value) {
......
......@@ -32,7 +32,7 @@ import com.github.shadowsocks.ShadowsocksApplication.app
class TrafficMonitorThread(context: Context) extends Thread {
val TAG = "TrafficMonitorThread"
lazy val PATH: String = context.getApplicationInfo.dataDir + "/stat_path"
val stat = new File(context.getFilesDir, "/stat_path")
@volatile var serverSocket: LocalServerSocket = _
@volatile var isRunning: Boolean = true
......@@ -55,11 +55,11 @@ class TrafficMonitorThread(context: Context) extends Thread {
override def run() {
new File(PATH).delete()
stat.delete()
try {
val localSocket = new LocalSocket
localSocket.bind(new LocalSocketAddress(PATH, LocalSocketAddress.Namespace.FILESYSTEM))
localSocket.bind(new LocalSocketAddress(stat.getAbsolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
serverSocket = new LocalServerSocket(localSocket.getFileDescriptor)
} catch {
case e: IOException =>
......
......@@ -20,10 +20,8 @@
package com.github.shadowsocks.utils
import java.io.File
import java.net._
import java.security.MessageDigest
import java.util.Scanner
import android.content.pm.PackageManager
import android.content.{Context, Intent}
......@@ -78,22 +76,6 @@ object Utils {
toast
}
def readAllLines(f: File): String = {
val scanner = new Scanner(f)
try {
scanner.useDelimiter("\\Z")
scanner.next()
} finally scanner.close()
}
def printToFile(f: java.io.File)(op: java.io.PrintWriter => Unit) {
val p = new java.io.PrintWriter(f)
try {
op(p)
} finally {
p.close()
}
}
def resolve(host: String, addrType: Int): Option[String] = {
try {
val lookup = new Lookup(host, addrType)
......@@ -131,20 +113,16 @@ object Utils {
/**
* If there exists a valid IPv6 interface
*/
def isIPv6Support: Boolean = {
try {
for (intf <- enumerationAsScalaIterator(NetworkInterface.getNetworkInterfaces))
for (addr <- enumerationAsScalaIterator(intf.getInetAddresses))
if (addr.isInstanceOf[Inet6Address] && !addr.isLoopbackAddress && !addr.isLinkLocalAddress) {
if (BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected")
return true
}
} catch {
case ex: Exception =>
Log.e(TAG, "Failed to get interfaces' addresses.", ex)
app.track(ex)
}
false
def isIPv6Support: Boolean = try {
val result = NetworkInterface.getNetworkInterfaces.flatMap(_.getInetAddresses)
.count(addr => addr.isInstanceOf[Inet6Address] && !addr.isLoopbackAddress && !addr.isLinkLocalAddress) > 0
if (result && BuildConfig.DEBUG) Log.d(TAG, "IPv6 address detected")
result
} catch {
case ex: Exception =>
Log.e(TAG, "Failed to get interfaces' addresses.", ex)
app.track(ex)
false
}
def startSsService(context: Context) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment