Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
com.ccwangluo.accelerator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
sheteng
com.ccwangluo.accelerator
Commits
25bd5347
Commit
25bd5347
authored
Aug 19, 2016
by
Mygod
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refine #816 and error handling in startRunner
parent
d2a527ed
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
126 additions
and
110 deletions
+126
-110
src/main/scala/com/github/shadowsocks/BaseService.scala
src/main/scala/com/github/shadowsocks/BaseService.scala
+14
-5
src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
.../scala/com/github/shadowsocks/ShadowsocksNatService.scala
+27
-42
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
.../scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+41
-62
src/main/scala/com/github/shadowsocks/utils/Utils.scala
src/main/scala/com/github/shadowsocks/utils/Utils.scala
+44
-1
No files found.
src/main/scala/com/github/shadowsocks/BaseService.scala
View file @
25bd5347
...
...
@@ -39,6 +39,7 @@
package
com.github.shadowsocks
import
java.io.IOException
import
java.util.
{
Timer
,
TimerTask
}
import
android.app.Service
...
...
@@ -48,7 +49,6 @@ import android.os.{Handler, RemoteCallbackList}
import
android.text.TextUtils
import
android.util.Log
import
android.widget.Toast
import
com.github.kevinsawicki.http.HttpRequest
import
com.github.shadowsocks.aidl.
{
IShadowsocksService
,
IShadowsocksServiceCallback
}
import
com.github.shadowsocks.utils._
...
...
@@ -60,6 +60,9 @@ trait BaseService extends Service {
@volatile
private
var
state
=
State
.
STOPPED
@volatile
protected
var
profile
:
Profile
=
_
case
class
NameNotResolvedException
()
extends
IOException
case
class
KcpcliParseException
(
cause
:
Throwable
)
extends
Exception
(
cause
)
var
timer
:
Timer
=
_
var
trafficMonitorThread
:
TrafficMonitorThread
=
_
...
...
@@ -136,7 +139,7 @@ trait BaseService extends Service {
false
}
else
true
def
connect
()
=
if
(
profile
.
host
==
"198.199.101.152"
)
try
{
def
connect
()
=
if
(
profile
.
host
==
"198.199.101.152"
)
{
val
holder
=
app
.
containerHolder
val
container
=
holder
.
getContainer
val
url
=
container
.
getString
(
"proxy_url"
)
...
...
@@ -153,8 +156,6 @@ trait BaseService extends Service {
profile
.
remotePort
=
proxy
(
1
).
trim
.
toInt
profile
.
password
=
proxy
(
2
).
trim
profile
.
method
=
proxy
(
3
).
trim
}
catch
{
case
ex
:
Exception
=>
stopRunner
(
true
,
getString
(
R
.
string
.
service_failed
))
}
def
startRunner
(
profile
:
Profile
)
{
...
...
@@ -188,7 +189,15 @@ trait BaseService extends Service {
if
(
profile
.
isMethodUnsafe
)
handler
.
post
(()
=>
Toast
.
makeText
(
this
,
R
.
string
.
method_unsafe
,
Toast
.
LENGTH_LONG
).
show
)
Utils
.
ThrowableFuture
(
connect
)
Utils
.
ThrowableFuture
(
try
connect
catch
{
case
_:
NameNotResolvedException
=>
stopRunner
(
true
,
getString
(
R
.
string
.
invalid_server
))
case
exc
:
KcpcliParseException
=>
stopRunner
(
true
,
getString
(
R
.
string
.
service_failed
)
+
": "
+
exc
.
cause
.
getMessage
)
case
exc
:
Throwable
=>
stopRunner
(
true
,
getString
(
R
.
string
.
service_failed
)
+
": "
+
exc
.
getMessage
)
exc
.
printStackTrace
()
app
.
track
(
exc
)
})
}
def
stopRunner
(
stopService
:
Boolean
,
msg
:
String
=
null
)
{
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
View file @
25bd5347
...
...
@@ -97,8 +97,7 @@ class ShadowsocksNatService extends BaseService {
p
.
println
(
conf
)
})
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/ss-local"
val
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/ss-local"
,
"-b"
,
"127.0.0.1"
,
"-t"
,
"600"
,
"-P"
,
getApplicationInfo
.
dataDir
...
...
@@ -120,15 +119,16 @@ class ShadowsocksNatService extends BaseService {
def
startKcptunDaemon
()
{
if
(
profile
.
kcpcli
==
null
)
profile
.
kcpcli
=
""
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/kcptun"
val
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/kcptun"
,
"-r"
,
profile
.
host
+
":"
+
profile
.
kcpPort
,
"-l"
,
"127.0.0.1:"
+
(
profile
.
localPort
+
90
)
,
profile
.
kcpcli
.
replaceAll
(
"^\\s*([\"'])(.*)\\1\\s*$"
,
"$2"
))
,
"-l"
,
"127.0.0.1:"
+
(
profile
.
localPort
+
90
))
try
cmd
++=
Utils
.
translateCommandline
(
profile
.
kcpcli
)
catch
{
case
exc
:
Exception
=>
throw
KcpcliParseException
(
exc
)
}
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
.
mkString
(
" "
))
kcptunProcess
=
new
GuardedProcess
(
cmd
.
mkString
(
" "
).
split
(
"[ ]{1,}"
).
toSeq
).
start
()
kcptunProcess
=
new
GuardedProcess
(
cmd
).
start
()
}
def
startDNSTunnel
()
{
...
...
@@ -139,8 +139,7 @@ class ShadowsocksNatService extends BaseService {
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/ss-tunnel-nat.conf"
))(
p
=>
{
p
.
println
(
conf
)
})
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/ss-tunnel"
val
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/ss-tunnel"
,
"-u"
,
"-t"
,
"10"
,
"-b"
,
"127.0.0.1"
...
...
@@ -168,8 +167,7 @@ class ShadowsocksNatService extends BaseService {
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/ss-tunnel-nat.conf"
))(
p
=>
{
p
.
println
(
conf
)
})
val
cmdBuf
=
new
ArrayBuffer
[
String
]
cmdBuf
+=
(
getApplicationInfo
.
dataDir
+
"/ss-tunnel"
val
cmdBuf
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/ss-tunnel"
,
"-t"
,
"10"
,
"-b"
,
"127.0.0.1"
,
"-l"
,
(
profile
.
localPort
+
63
).
toString
...
...
@@ -198,27 +196,26 @@ class ShadowsocksNatService extends BaseService {
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/pdnsd-nat.conf"
))(
p
=>
{
p
.
println
(
conf
)
})
val
cmd
=
getApplicationInfo
.
dataDir
+
"/pdnsd -c "
+
getApplicationInfo
.
dataDir
+
"/pdnsd-nat.conf"
val
cmd
=
Array
(
getApplicationInfo
.
dataDir
+
"/pdnsd"
,
"-c"
,
getApplicationInfo
.
dataDir
+
"/pdnsd-nat.conf"
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
.
mkString
(
" "
)
)
pdnsdProcess
=
new
GuardedProcess
(
cmd
.
split
(
" "
).
toSeq
).
start
()
pdnsdProcess
=
new
GuardedProcess
(
cmd
).
start
()
}
def
startRedsocksDaemon
()
{
val
conf
=
ConfigUtils
.
REDSOCKS
.
formatLocal
(
Locale
.
ENGLISH
,
profile
.
localPort
)
val
cmd
=
"%s/redsocks -c %s/redsocks-nat.conf"
.
formatLocal
(
Locale
.
ENGLISH
,
getApplicationInfo
.
dataDir
,
getApplicationInfo
.
dataDir
)
val
cmd
=
Array
(
getApplicationInfo
.
dataDir
+
"/redsocks"
,
"-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
,
cmd
)
redsocksProcess
=
new
GuardedProcess
(
cmd
.
split
(
" "
).
toSeq
).
start
()
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
.
mkString
(
" "
)
)
redsocksProcess
=
new
GuardedProcess
(
cmd
).
start
()
}
/** Called when the activity is first created. */
def
handleConnection
{
def
handleConnection
()
{
startDNSTunnel
()
startRedsocksDaemon
()
...
...
@@ -323,31 +320,19 @@ class ShadowsocksNatService extends BaseService {
override
def
connect
()
{
super
.
connect
()
if
(
profile
!=
null
)
{
// Clean up
killProcesses
()
var
resolved
=
false
if
(!
Utils
.
isNumeric
(
profile
.
host
))
{
Utils
.
resolve
(
profile
.
host
,
enableIPv6
=
true
)
match
{
case
Some
(
a
)
=>
profile
.
host
=
a
resolved
=
true
case
None
=>
resolved
=
false
}
}
else
{
resolved
=
true
}
// Clean up
killProcesses
()
if
(!
resolved
)
stopRunner
(
true
,
getString
(
R
.
string
.
invalid_server
))
else
{
handleConnection
// Set DNS
su
.
addCommand
(
Utils
.
FLUSH_DNS
)
changeState
(
State
.
CONNECTED
)
notification
=
new
ShadowsocksNotification
(
this
,
profile
.
name
,
true
)
}
if
(!
Utils
.
isNumeric
(
profile
.
host
))
Utils
.
resolve
(
profile
.
host
,
enableIPv6
=
true
)
match
{
case
Some
(
a
)
=>
profile
.
host
=
a
case
None
=>
throw
NameNotResolvedException
()
}
handleConnection
()
// Set DNS
su
.
addCommand
(
Utils
.
FLUSH_DNS
)
changeState
(
State
.
CONNECTED
)
notification
=
new
ShadowsocksNotification
(
this
,
profile
.
name
,
true
)
}
override
def
stopRunner
(
stopService
:
Boolean
,
msg
:
String
=
null
)
{
...
...
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
View file @
25bd5347
...
...
@@ -148,42 +148,28 @@ class ShadowsocksVpnService extends VpnService with BaseService {
override
def
connect
()
=
{
super
.
connect
()
if
(
profile
!=
null
)
{
vpnThread
=
new
ShadowsocksVpnThread
(
this
)
vpnThread
.
start
()
// reset the context
killProcesses
()
// Resolve the server address
var
resolved
:
Boolean
=
false
if
(!
Utils
.
isNumeric
(
profile
.
host
))
{
Utils
.
resolve
(
profile
.
host
,
enableIPv6
=
true
)
match
{
case
Some
(
addr
)
=>
profile
.
host
=
addr
resolved
=
true
case
None
=>
resolved
=
false
}
}
else
{
resolved
=
true
}
vpnThread
=
new
ShadowsocksVpnThread
(
this
)
vpnThread
.
start
()
if
(!
resolved
)
stopRunner
(
true
,
getString
(
R
.
string
.
invalid_server
))
else
if
(
handleConnection
)
{
changeState
(
State
.
CONNECTED
)
notification
=
new
ShadowsocksNotification
(
this
,
profile
.
name
)
}
else
{
changeState
(
State
.
STOPPED
,
getString
(
R
.
string
.
service_failed
))
stopRunner
(
true
)
}
// reset the context
killProcesses
(
)
// Resolve the server address
if
(!
Utils
.
isNumeric
(
profile
.
host
))
Utils
.
resolve
(
profile
.
host
,
enableIPv6
=
true
)
match
{
case
Some
(
addr
)
=>
profile
.
host
=
addr
case
None
=>
throw
NameNotResolvedException
()
}
handleConnection
()
changeState
(
State
.
CONNECTED
)
notification
=
new
ShadowsocksNotification
(
this
,
profile
.
name
)
}
/** Called when the activity is first created. */
def
handleConnection
:
Boolean
=
{
def
handleConnection
()
{
val
fd
=
startVpn
()
if
(!
sendFd
(
fd
))
return
false
if
(!
sendFd
(
fd
))
throw
new
Exception
(
"sendFd failed"
)
if
(
profile
.
kcp
)
{
startKcptunDaemon
()
...
...
@@ -199,24 +185,23 @@ class ShadowsocksVpnService extends VpnService with BaseService {
startDnsDaemon
()
startDnsTunnel
()
}
true
}
def
startKcptunDaemon
()
{
if
(
profile
.
kcpcli
==
null
)
profile
.
kcpcli
=
""
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/kcptun"
val
cmd
=
ArrayBuffer
(
getApplicationInfo
.
dataDir
+
"/kcptun"
,
"-r"
,
profile
.
host
+
":"
+
profile
.
kcpPort
,
"-l"
,
"127.0.0.1:"
+
(
profile
.
localPort
+
90
)
,
"--path"
,
getApplicationInfo
.
dataDir
+
"/protect_path"
,
profile
.
kcpcli
.
replaceAll
(
"^\\s*([\"'])(.*)\\1\\s*$"
,
"$2"
))
,
"--path"
,
getApplicationInfo
.
dataDir
+
"/protect_path"
)
try
cmd
++=
Utils
.
translateCommandline
(
profile
.
kcpcli
)
catch
{
case
exc
:
Exception
=>
throw
KcpcliParseException
(
exc
)
}
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
.
mkString
(
" "
))
kcptunProcess
=
new
GuardedProcess
(
cmd
.
mkString
(
" "
).
split
(
"[ ]{1,}"
).
toSeq
).
start
()
kcptunProcess
=
new
GuardedProcess
(
cmd
).
start
()
}
def
startShadowsocksUDPDaemon
()
{
...
...
@@ -227,8 +212,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
p
.
println
(
conf
)
})
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/ss-local"
,
"-V"
,
"-U"
val
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/ss-local"
,
"-V"
,
"-U"
,
"-b"
,
"127.0.0.1"
,
"-t"
,
"600"
,
"-P"
,
getApplicationInfo
.
dataDir
...
...
@@ -267,8 +251,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
p
.
println
(
conf
)
})
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/ss-local"
,
"-V"
val
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/ss-local"
,
"-V"
,
"-b"
,
"127.0.0.1"
,
"-t"
,
"600"
,
"-P"
,
getApplicationInfo
.
dataDir
...
...
@@ -303,8 +286,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/ss-tunnel-vpn.conf"
))(
p
=>
{
p
.
println
(
conf
)
})
val
cmd
=
new
ArrayBuffer
[
String
]
cmd
+=
(
getApplicationInfo
.
dataDir
+
"/ss-tunnel"
val
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/ss-tunnel"
,
"-V"
,
"-t"
,
"10"
,
"-b"
,
"127.0.0.1"
...
...
@@ -333,11 +315,11 @@ class ShadowsocksVpnService extends VpnService with BaseService {
Utils
.
printToFile
(
new
File
(
getApplicationInfo
.
dataDir
+
"/pdnsd-vpn.conf"
))(
p
=>
{
p
.
println
(
conf
)
})
val
cmd
=
getApplicationInfo
.
dataDir
+
"/pdnsd -c "
+
getApplicationInfo
.
dataDir
+
"/pdnsd-vpn.conf"
val
cmd
=
Array
(
getApplicationInfo
.
dataDir
+
"/pdnsd"
,
"-c"
,
getApplicationInfo
.
dataDir
+
"/pdnsd-vpn.conf"
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
.
mkString
(
" "
)
)
pdnsdProcess
=
new
GuardedProcess
(
cmd
.
split
(
" "
).
toSeq
).
start
()
pdnsdProcess
=
new
GuardedProcess
(
cmd
).
start
()
}
def
startVpn
()
:
Int
=
{
...
...
@@ -397,30 +379,27 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val
fd
=
conn
.
getFd
var
cmd
=
(
getApplicationInfo
.
dataDir
+
"/tun2socks --netif-ipaddr %s "
+
"--netif-netmask 255.255.255.0 "
+
"--socks-server-addr 127.0.0.1:%d "
+
"--tunfd %d "
+
"--tunmtu %d "
+
"--sock-path %s "
+
"--loglevel 3"
)
.
formatLocal
(
Locale
.
ENGLISH
,
PRIVATE_VLAN
.
formatLocal
(
Locale
.
ENGLISH
,
"2"
),
profile
.
localPort
,
fd
,
VPN_MTU
,
getApplicationInfo
.
dataDir
+
"/sock_path"
)
var
cmd
=
ArrayBuffer
[
String
](
getApplicationInfo
.
dataDir
+
"/tun2socks"
,
"--netif-ipaddr"
,
PRIVATE_VLAN
.
formatLocal
(
Locale
.
ENGLISH
,
"2"
),
"--netif-netmask"
,
"255.255.255.0"
,
"--socks-server-addr"
,
"127.0.0.1:"
+
profile
.
localPort
,
"--tunfd"
,
fd
.
toString
,
"--tunmtu"
,
VPN_MTU
.
toString
,
"--sock-path"
,
getApplicationInfo
.
dataDir
+
"/sock_path"
,
"--loglevel"
,
"3"
)
if
(
profile
.
ipv6
)
cmd
+=
" --netif-ip6addr "
+
PRIVATE_VLAN6
.
formatLocal
(
Locale
.
ENGLISH
,
"2"
)
cmd
+=
(
"--netif-ip6addr"
,
PRIVATE_VLAN6
.
formatLocal
(
Locale
.
ENGLISH
,
"2"
)
)
if
(
profile
.
udpdns
)
cmd
+=
"
--enable-udprelay"
cmd
+=
"--enable-udprelay"
else
cmd
+=
" --dnsgw %s:%d"
.
formatLocal
(
Locale
.
ENGLISH
,
PRIVATE_VLAN
.
formatLocal
(
Locale
.
ENGLISH
,
"1"
),
profile
.
localPort
+
53
)
cmd
+=
(
"--dnsgw"
,
"%s:%d"
.
formatLocal
(
Locale
.
ENGLISH
,
PRIVATE_VLAN
.
formatLocal
(
Locale
.
ENGLISH
,
"1"
),
profile
.
localPort
+
53
)
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
.
mkString
(
" "
)
)
tun2socksProcess
=
new
GuardedProcess
(
cmd
.
split
(
" "
).
toSeq
).
start
(()
=>
sendFd
(
fd
))
tun2socksProcess
=
new
GuardedProcess
(
cmd
).
start
(()
=>
sendFd
(
fd
))
fd
}
...
...
src/main/scala/com/github/shadowsocks/utils/Utils.scala
View file @
25bd5347
...
...
@@ -41,7 +41,7 @@ package com.github.shadowsocks.utils
import
java.io.File
import
java.net._
import
java.security.MessageDigest
import
java.util.
Scanner
import
java.util.
{
Scanner
,
StringTokenizer
}
import
android.animation.
{
Animator
,
AnimatorListenerAdapter
}
import
android.content.pm.PackageManager
...
...
@@ -58,6 +58,7 @@ import eu.chainfire.libsuperuser.Shell
import
org.xbill.DNS._
import
scala.collection.JavaConversions._
import
scala.collection.mutable.ArrayBuffer
import
scala.concurrent.ExecutionContext.Implicits.global
import
scala.concurrent.Future
import
scala.util.
{
Failure
,
Try
}
...
...
@@ -127,6 +128,48 @@ object Utils {
}
}
/**
* Crack a command line.
* Based on: https://github.com/apache/ant/blob/588ce1f/src/main/org/apache/tools/ant/types/Commandline.java#L471
* @param toProcess the command line to process.
* @return the command line broken into strings.
* An empty or null toProcess parameter results in a zero sized ArrayBuffer.
*/
def
translateCommandline
(
toProcess
:
String
)
:
ArrayBuffer
[
String
]
=
{
if
(
toProcess
==
null
||
toProcess
.
length
==
0
)
return
ArrayBuffer
[
String
]()
val
tok
=
new
StringTokenizer
(
toProcess
,
"\"' "
,
true
)
val
result
=
ArrayBuffer
[
String
]()
val
current
=
new
StringBuilder
()
var
quote
=
' '
var
last
=
" "
while
(
tok
.
hasMoreTokens
)
{
val
nextTok
=
tok
.
nextToken
quote
match
{
case
'\''
=>
nextTok
match
{
case
"'"
=>
quote
=
' '
case
_
=>
current
.
append
(
nextTok
)
}
case
'"'
=>
nextTok
match
{
case
"\""
=>
quote
=
' '
case
_
=>
current
.
append
(
nextTok
)
}
case
_
=>
nextTok
match
{
case
"'"
=>
quote
=
'\''
case
"\""
=>
quote
=
'"'
case
" "
=>
if
(
last
!=
" "
)
{
result
.
append
(
current
.
toString
)
current
.
setLength
(
0
)
}
case
_
=>
current
.
append
(
nextTok
)
}
}
last
=
nextTok
}
if
(
current
.
nonEmpty
)
result
.
append
(
current
.
toString
)
if
(
quote
==
'\''
||
quote
==
'"'
)
throw
new
Exception
(
"Unbalanced quotes in "
+
toProcess
)
result
}
// Because /sys/class/net/* isn't accessible since API level 24
final
val
FLUSH_DNS
=
"for if in /sys/class/net/*; do "
+
"if [ \"down\" != $(cat $if/operstate) ]; then "
+
// up or unknown
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment