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
c4833ddb
Commit
c4833ddb
authored
Feb 09, 2014
by
Max Lv
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add aidl
parent
abf050a4
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
682 additions
and
658 deletions
+682
-658
src/main/AndroidManifest.xml
src/main/AndroidManifest.xml
+8
-3
src/main/java/com/github/shadowsocks/aidl/Config.aidl
src/main/java/com/github/shadowsocks/aidl/Config.aidl
+3
-0
src/main/java/com/github/shadowsocks/aidl/Config.java
src/main/java/com/github/shadowsocks/aidl/Config.java
+86
-0
src/main/java/com/github/shadowsocks/aidl/IShadowsocksService.aidl
...java/com/github/shadowsocks/aidl/IShadowsocksService.aidl
+13
-0
src/main/java/com/github/shadowsocks/aidl/IShadowsocksServiceCallback.aidl
.../github/shadowsocks/aidl/IShadowsocksServiceCallback.aidl
+5
-0
src/main/res/layout/layout_switch.xml
src/main/res/layout/layout_switch.xml
+1
-0
src/main/scala/com/github/shadowsocks/BaseService.scala
src/main/scala/com/github/shadowsocks/BaseService.scala
+81
-0
src/main/scala/com/github/shadowsocks/ShadowVpnActivity.scala
...main/scala/com/github/shadowsocks/ShadowVpnActivity.scala
+21
-11
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
+145
-146
src/main/scala/com/github/shadowsocks/ShadowsocksNatService.scala
.../scala/com/github/shadowsocks/ShadowsocksNatService.scala
+161
-218
src/main/scala/com/github/shadowsocks/ShadowsocksReceiver.scala
...in/scala/com/github/shadowsocks/ShadowsocksReceiver.scala
+1
-17
src/main/scala/com/github/shadowsocks/ShadowsocksVpnService.scala
.../scala/com/github/shadowsocks/ShadowsocksVpnService.scala
+108
-169
src/main/scala/com/github/shadowsocks/utils/ConfigUtils.scala
...main/scala/com/github/shadowsocks/utils/ConfigUtils.scala
+33
-7
src/main/scala/com/github/shadowsocks/utils/Constants.scala
src/main/scala/com/github/shadowsocks/utils/Constants.scala
+16
-87
No files found.
src/main/AndroidManifest.xml
View file @
c4833ddb
...
@@ -70,17 +70,22 @@
...
@@ -70,17 +70,22 @@
</activity>
</activity>
<service
<service
android:name=
".ShadowsocksService"
android:name=
".Shadowsocks
Nat
Service"
android:process=
":proxy"
android:process=
":proxy"
android:exported=
"false"
/>
android:exported=
"false"
>
<intent-filter>
<action
android:name=
"com.github.shadowsocks.ShadowsocksNatService"
/>
</intent-filter>
</service>
<service
<service
android:name=
".ShadowVpnService"
android:name=
".Shadow
socks
VpnService"
android:label=
"@string/app_name"
android:label=
"@string/app_name"
android:process=
":vpn"
android:process=
":vpn"
android:permission=
"android.permission.BIND_VPN_SERVICE"
android:permission=
"android.permission.BIND_VPN_SERVICE"
android:exported=
"false"
>
android:exported=
"false"
>
<intent-filter>
<intent-filter>
<action
android:name=
"com.github.shadowsocks.ShadowsocksVpnService"
/>
<action
android:name=
"android.net.VpnService"
/>
<action
android:name=
"android.net.VpnService"
/>
</intent-filter>
</intent-filter>
</service>
</service>
...
...
src/main/java/com/github/shadowsocks/aidl/Config.aidl
0 → 100644
View file @
c4833ddb
package
com
.
github
.
shadowsocks
.
aidl
;
parcelable
Config
;
\ No newline at end of file
src/main/java/com/github/shadowsocks/aidl/Config.java
0 → 100644
View file @
c4833ddb
package
com.github.shadowsocks.aidl
;
import
android.os.Parcel
;
import
android.os.Parcelable
;
public
class
Config
implements
Parcelable
{
public
boolean
isGlobalProxy
=
true
;
public
boolean
isGFWList
=
true
;
public
boolean
isBypassApps
=
false
;
public
boolean
isTrafficStat
=
false
;
public
String
profileName
=
"Untitled"
;
public
String
proxy
=
"127.0.0.1"
;
public
String
sitekey
=
"null"
;
public
String
encMethod
=
"rc4"
;
public
String
proxiedAppString
=
""
;
public
int
remotePort
=
1984
;
public
int
localPort
=
1080
;
public
static
final
Parcelable
.
Creator
<
Config
>
CREATOR
=
new
Parcelable
.
Creator
<
Config
>()
{
public
Config
createFromParcel
(
Parcel
in
)
{
return
new
Config
(
in
);
}
public
Config
[]
newArray
(
int
size
)
{
return
new
Config
[
size
];
}
};
public
Config
(
boolean
isGlobalProxy
,
boolean
isGFWList
,
boolean
isBypassApps
,
boolean
isTrafficStat
,
String
profileName
,
String
proxy
,
String
sitekey
,
String
encMethod
,
String
proxiedAppString
,
int
remotePort
,
int
localPort
)
{
this
.
isGlobalProxy
=
isGlobalProxy
;
this
.
isGFWList
=
isGFWList
;
this
.
isBypassApps
=
isBypassApps
;
this
.
isTrafficStat
=
isTrafficStat
;
this
.
profileName
=
profileName
;
this
.
proxy
=
proxy
;
this
.
sitekey
=
sitekey
;
this
.
encMethod
=
encMethod
;
this
.
proxiedAppString
=
proxiedAppString
;
this
.
remotePort
=
remotePort
;
this
.
localPort
=
localPort
;
}
private
Config
(
Parcel
in
)
{
readFromParcel
(
in
);
}
public
void
readFromParcel
(
Parcel
in
)
{
isGlobalProxy
=
in
.
readInt
()
==
1
;
isGFWList
=
in
.
readInt
()
==
1
;
isBypassApps
=
in
.
readInt
()
==
1
;
isTrafficStat
=
in
.
readInt
()
==
1
;
profileName
=
in
.
readString
();
proxy
=
in
.
readString
();
sitekey
=
in
.
readString
();
encMethod
=
in
.
readString
();
proxiedAppString
=
in
.
readString
();
remotePort
=
in
.
readInt
();
localPort
=
in
.
readInt
();
}
@Override
public
int
describeContents
()
{
return
0
;
}
@Override
public
void
writeToParcel
(
Parcel
out
,
int
flags
)
{
out
.
writeInt
(
isGlobalProxy
?
1
:
0
);
out
.
writeInt
(
isGFWList
?
1
:
0
);
out
.
writeInt
(
isBypassApps
?
1
:
0
);
out
.
writeInt
(
isTrafficStat
?
1
:
0
);
out
.
writeString
(
profileName
);
out
.
writeString
(
proxy
);
out
.
writeString
(
sitekey
);
out
.
writeString
(
encMethod
);
out
.
writeString
(
proxiedAppString
);
out
.
writeInt
(
remotePort
);
out
.
writeInt
(
localPort
);
}
}
src/main/java/com/github/shadowsocks/aidl/IShadowsocksService.aidl
0 → 100644
View file @
c4833ddb
package
com
.
github
.
shadowsocks
.
aidl
;
import
com
.
github
.
shadowsocks
.
aidl
.
Config
;
import
com
.
github
.
shadowsocks
.
aidl
.
IShadowsocksServiceCallback
;
interface
IShadowsocksService
{
int
getMode
();
int
getState
();
void
start
(
in
Config
config
);
void
stop
();
void
registerCallback
(
IShadowsocksServiceCallback
cb
);
void
unregisterCallback
(
IShadowsocksServiceCallback
cb
);
}
\ No newline at end of file
src/main/java/com/github/shadowsocks/aidl/IShadowsocksServiceCallback.aidl
0 → 100644
View file @
c4833ddb
package
com
.
github
.
shadowsocks
.
aidl
;
interface
IShadowsocksServiceCallback
{
void
stateChanged
(
int
state
,
String
msg
);
}
\ No newline at end of file
src/main/res/layout/layout_switch.xml
View file @
c4833ddb
...
@@ -17,6 +17,7 @@
...
@@ -17,6 +17,7 @@
<org.jraf.android.backport.switchwidget.Switch
<org.jraf.android.backport.switchwidget.Switch
android:id=
"@+id/switchButton"
android:id=
"@+id/switchButton"
android:enabled=
"false"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentRight=
"true"
android:layout_alignParentRight=
"true"
...
...
src/main/scala/com/github/shadowsocks/BaseService.scala
0 → 100644
View file @
c4833ddb
package
com.github.shadowsocks
import
android.os.RemoteCallbackList
import
com.github.shadowsocks.aidl.
{
Config
,
IShadowsocksService
,
IShadowsocksServiceCallback
}
import
com.github.shadowsocks.utils.
{
Path
,
State
}
import
java.io.
{
IOException
,
FileNotFoundException
,
FileReader
,
BufferedReader
}
import
android.util.Log
import
android.app.Notification
trait
BaseService
{
var
state
=
State
.
INIT
final
val
callbacks
=
new
RemoteCallbackList
[
IShadowsocksServiceCallback
]
protected
val
binder
=
new
IShadowsocksService
.
Stub
{
override
def
getMode
:
Int
=
{
getServiceMode
}
override
def
getState
:
Int
=
{
state
}
override
def
unregisterCallback
(
cb
:
IShadowsocksServiceCallback
)
{
if
(
cb
!=
null
)
callbacks
.
unregister
(
cb
)
}
override
def
registerCallback
(
cb
:
IShadowsocksServiceCallback
)
{
if
(
cb
!=
null
)
callbacks
.
register
(
cb
)
}
override
def
stop
()
{
stopRunner
()
}
override
def
start
(
config
:
Config
)
{
startRunner
(
config
)
}
}
def
startRunner
(
config
:
Config
)
def
stopRunner
()
def
getServiceMode
:
Int
def
getTag
:
String
def
changeState
(
s
:
Int
)
{
changeState
(
s
,
null
)
}
protected
def
changeState
(
s
:
Int
,
msg
:
String
)
{
if
(
state
!=
s
)
{
val
n
=
callbacks
.
beginBroadcast
()
for
(
i
<-
0
to
n
-
1
)
{
callbacks
.
getBroadcastItem
(
i
).
stateChanged
(
s
,
msg
)
}
callbacks
.
finishBroadcast
()
state
=
s
}
}
def
getPid
(
name
:
String
)
:
Int
=
{
try
{
val
reader
:
BufferedReader
=
new
BufferedReader
(
new
FileReader
(
Path
.
BASE
+
name
+
".pid"
))
val
line
=
reader
.
readLine
return
Integer
.
valueOf
(
line
)
}
catch
{
case
e
:
FileNotFoundException
=>
Log
.
e
(
getTag
,
"Cannot open pid file: "
+
name
)
case
e
:
IOException
=>
Log
.
e
(
getTag
,
"Cannot read pid file: "
+
name
)
case
e
:
NumberFormatException
=>
Log
.
e
(
getTag
,
"Invalid pid"
,
e
)
}
-
1
}
def
initSoundVibrateLights
(
notification
:
Notification
)
{
notification
.
sound
=
null
}
}
src/main/scala/com/github/shadowsocks/ShadowVpnActivity.scala
View file @
c4833ddb
...
@@ -40,16 +40,28 @@
...
@@ -40,16 +40,28 @@
package
com.github.shadowsocks
package
com.github.shadowsocks
import
android.app.Activity
import
android.app.Activity
import
android.os.
Bundle
import
android.os.
{
IBinder
,
Bundle
}
import
android.net.VpnService
import
android.net.VpnService
import
android.content.
Intent
import
android.content.
{
ComponentName
,
ServiceConnection
,
Intent
}
import
android.util.Log
import
android.util.Log
import
android.preference.PreferenceManager
import
android.preference.PreferenceManager
import
com.github.shadowsocks.utils.
Extra
import
com.github.shadowsocks.utils.
_
import
com.
actionbarsherlock.app.SherlockActivity
import
com.
github.shadowsocks.aidl.IShadowsocksService
class
ShadowVpnActivity
extends
Activity
{
class
ShadowVpnActivity
extends
Activity
{
// Services
var
bgService
:
IShadowsocksService
=
null
val
connection
=
new
ServiceConnection
{
override
def
onServiceConnected
(
name
:
ComponentName
,
service
:
IBinder
)
{
bgService
=
IShadowsocksService
.
Stub
.
asInterface
(
service
)
}
override
def
onServiceDisconnected
(
name
:
ComponentName
)
{
bgService
=
null
}
}
override
def
onCreate
(
savedInstanceState
:
Bundle
)
{
override
def
onCreate
(
savedInstanceState
:
Bundle
)
{
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
val
intent
=
VpnService
.
prepare
(
this
)
val
intent
=
VpnService
.
prepare
(
this
)
...
@@ -62,14 +74,12 @@ class ShadowVpnActivity extends Activity {
...
@@ -62,14 +74,12 @@ class ShadowVpnActivity extends Activity {
override
def
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
)
{
override
def
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
data
:
Intent
)
{
resultCode
match
{
resultCode
match
{
case
Activity
.
RESULT_OK
=>
{
case
Activity
.
RESULT_OK
=>
val
intent
:
Intent
=
new
Intent
(
this
,
classOf
[
ShadowVpnService
])
if
(
bgService
!=
null
)
{
Extra
.
put
(
PreferenceManager
.
getDefaultSharedPreferences
(
this
),
intent
)
bgService
.
start
(
ConfigUtils
.
load
(
PreferenceManager
.
getDefaultSharedPreferences
(
this
)))
startService
(
intent
)
}
}
case
_
=>
case
_
=>
{
Log
.
e
(
Shadowsocks
.
TAG
,
"Failed to start VpnService"
)
Log
.
e
(
Shadowsocks
.
TAG
,
"Failed to start VpnService"
)
}
}
}
finish
()
finish
()
}
}
...
...
src/main/scala/com/github/shadowsocks/Shadowsocks.scala
View file @
c4833ddb
...
@@ -67,12 +67,11 @@ import scala.collection.mutable.ListBuffer
...
@@ -67,12 +67,11 @@ import scala.collection.mutable.ListBuffer
import
com.github.shadowsocks.database.Profile
import
com.github.shadowsocks.database.Profile
import
com.nostra13.universalimageloader.core.download.BaseImageDownloader
import
com.nostra13.universalimageloader.core.download.BaseImageDownloader
import
com.github.shadowsocks.preferences.
{
ProfileEditTextPreference
,
PasswordEditTextPreference
,
SummaryEditTextPreference
}
import
com.github.shadowsocks.preferences.
{
ProfileEditTextPreference
,
PasswordEditTextPreference
,
SummaryEditTextPreference
}
import
com.github.shadowsocks.database.Item
import
com.github.shadowsocks.database.Category
import
com.github.shadowsocks.utils._
import
com.github.shadowsocks.utils._
import
com.github.shadowsocks.database.Item
import
com.github.shadowsocks.database.Item
import
com.github.shadowsocks.database.Category
import
com.github.shadowsocks.database.Category
import
com.google.zxing.integration.android.IntentIntegrator
import
com.google.zxing.integration.android.IntentIntegrator
import
com.github.shadowsocks.aidl.
{
IShadowsocksServiceCallback
,
IShadowsocksService
}
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
)
{
...
@@ -103,10 +102,9 @@ object Typefaces {
...
@@ -103,10 +102,9 @@ object Typefaces {
val
t
:
Typeface
=
Typeface
.
createFromAsset
(
c
.
getAssets
,
assetPath
)
val
t
:
Typeface
=
Typeface
.
createFromAsset
(
c
.
getAssets
,
assetPath
)
cache
.
put
(
assetPath
,
t
)
cache
.
put
(
assetPath
,
t
)
}
catch
{
}
catch
{
case
e
:
Exception
=>
{
case
e
:
Exception
=>
Log
.
e
(
TAG
,
"Could not get typeface '"
+
assetPath
+
"' because "
+
e
.
getMessage
)
Log
.
e
(
TAG
,
"Could not get typeface '"
+
assetPath
+
"' because "
+
e
.
getMessage
)
return
null
return
null
}
}
}
}
}
return
cache
.
get
(
assetPath
)
return
cache
.
get
(
assetPath
)
...
@@ -131,8 +129,7 @@ object Shadowsocks {
...
@@ -131,8 +129,7 @@ object Shadowsocks {
// Flags
// Flags
var
vpnEnabled
=
-
1
var
vpnEnabled
=
-
1
// Help functions
// Helper functions
def
updateListPreference
(
pref
:
Preference
,
value
:
String
)
{
def
updateListPreference
(
pref
:
Preference
,
value
:
String
)
{
pref
.
setSummary
(
value
)
pref
.
setSummary
(
value
)
pref
.
asInstanceOf
[
ListPreference
].
setValue
(
value
)
pref
.
asInstanceOf
[
ListPreference
].
setValue
(
value
)
...
@@ -172,10 +169,6 @@ object Shadowsocks {
...
@@ -172,10 +169,6 @@ object Shadowsocks {
}
}
}
}
def
isServiceStarted
(
context
:
Context
)
:
Boolean
=
{
ShadowsocksService
.
isServiceStarted
(
context
)
||
ShadowVpnService
.
isServiceStarted
(
context
)
}
class
ProxyFragment
extends
UnifiedPreferenceFragment
{
class
ProxyFragment
extends
UnifiedPreferenceFragment
{
var
receiver
:
BroadcastReceiver
=
null
var
receiver
:
BroadcastReceiver
=
null
...
@@ -194,8 +187,8 @@ object Shadowsocks {
...
@@ -194,8 +187,8 @@ object Shadowsocks {
private
def
updatePreferenceScreen
()
{
private
def
updatePreferenceScreen
()
{
for
(
name
<-
Shadowsocks
.
PROXY_PREFS
)
{
for
(
name
<-
Shadowsocks
.
PROXY_PREFS
)
{
val
pref
=
findPreference
(
name
)
val
pref
=
findPreference
(
name
)
Shadowsocks
.
updatePreference
(
pref
,
name
,
Shadowsocks
getActivity
.
asInstanceOf
[
Shadowsocks
].
currentProfile
)
.
updatePreference
(
pref
,
name
,
getActivity
.
asInstanceOf
[
Shadowsocks
].
currentProfile
)
}
}
}
}
...
@@ -252,8 +245,8 @@ object Shadowsocks {
...
@@ -252,8 +245,8 @@ object Shadowsocks {
private
def
updatePreferenceScreen
()
{
private
def
updatePreferenceScreen
()
{
for
(
name
<-
Shadowsocks
.
FEATRUE_PREFS
)
{
for
(
name
<-
Shadowsocks
.
FEATRUE_PREFS
)
{
val
pref
=
findPreference
(
name
)
val
pref
=
findPreference
(
name
)
Shadowsocks
.
updatePreference
(
pref
,
name
,
Shadowsocks
getActivity
.
asInstanceOf
[
Shadowsocks
].
currentProfile
)
.
updatePreference
(
pref
,
name
,
getActivity
.
asInstanceOf
[
Shadowsocks
].
currentProfile
)
}
}
}
}
...
@@ -304,9 +297,61 @@ class Shadowsocks
...
@@ -304,9 +297,61 @@ class Shadowsocks
var
prepared
=
false
var
prepared
=
false
var
currentProfile
=
new
Profile
var
currentProfile
=
new
Profile
// Services
var
currentServiceName
=
classOf
[
ShadowsocksNatService
].
getName
var
bgService
:
IShadowsocksService
=
null
val
callback
=
new
IShadowsocksServiceCallback
.
Stub
{
override
def
stateChanged
(
state
:
Int
,
msg
:
String
)
{
onStateChanged
(
state
,
msg
)
}
}
val
connection
=
new
ServiceConnection
{
override
def
onServiceConnected
(
name
:
ComponentName
,
service
:
IBinder
)
{
// Initialize the background service
bgService
=
IShadowsocksService
.
Stub
.
asInterface
(
service
)
try
{
bgService
.
registerCallback
(
callback
)
}
catch
{
case
ignored
:
RemoteException
=>
// Nothing
}
// Update the UI
switchButton
.
setEnabled
(
true
)
if
(
State
.
isAvailable
(
bgService
.
getState
))
{
if
(
status
.
getBoolean
(
Key
.
isRunning
,
false
))
{
spawn
{
crash_recovery
()
handler
.
sendEmptyMessage
(
MSG_CRASH_RECOVER
)
}
}
Crouton
.
cancelAllCroutons
()
onStateChanged
(
State
.
STOPPED
,
null
)
setPreferenceEnabled
(
enabled
=
true
)
}
else
{
if
(
bgService
.
getMode
==
Mode
.
VPN
)
{
val
style
=
new
Style
.
Builder
().
setBackgroundColorValue
(
Style
.
holoBlueLight
).
build
()
val
config
=
new
Configuration
.
Builder
().
setDuration
(
Configuration
.
DURATION_LONG
).
build
()
Crouton
.
makeText
(
Shadowsocks
.
this
,
R
.
string
.
vpn_status
,
style
)
.
setConfiguration
(
config
)
.
show
()
switchButton
.
setEnabled
(
false
)
}
switchButton
.
setChecked
(
true
)
onStateChanged
(
State
.
CONNECTED
,
null
)
setPreferenceEnabled
(
enabled
=
false
)
}
// set the listener
switchButton
.
setOnCheckedChangeListener
(
Shadowsocks
.
this
)
}
override
def
onServiceDisconnected
(
name
:
ComponentName
)
{
switchButton
.
setEnabled
(
false
)
bgService
=
null
}
}
lazy
val
settings
=
PreferenceManager
.
getDefaultSharedPreferences
(
this
)
lazy
val
settings
=
PreferenceManager
.
getDefaultSharedPreferences
(
this
)
lazy
val
status
=
getSharedPreferences
(
Key
.
status
,
Context
.
MODE_PRIVATE
)
lazy
val
status
=
getSharedPreferences
(
Key
.
status
,
Context
.
MODE_PRIVATE
)
lazy
val
stateReceiver
=
new
StateBroadcastReceiver
lazy
val
preferenceReceiver
=
new
PreferenceBroadcastReceiver
lazy
val
preferenceReceiver
=
new
PreferenceBroadcastReceiver
lazy
val
drawer
=
MenuDrawer
.
attach
(
this
)
lazy
val
drawer
=
MenuDrawer
.
attach
(
this
)
lazy
val
menuAdapter
=
new
MenuAdapter
(
this
,
getMenuList
)
lazy
val
menuAdapter
=
new
MenuAdapter
(
this
,
getMenuList
)
...
@@ -341,9 +386,8 @@ class Shadowsocks
...
@@ -341,9 +386,8 @@ class Shadowsocks
try
{
try
{
files
=
assetManager
.
list
(
path
)
files
=
assetManager
.
list
(
path
)
}
catch
{
}
catch
{
case
e
:
IOException
=>
{
case
e
:
IOException
=>
Log
.
e
(
Shadowsocks
.
TAG
,
e
.
getMessage
)
Log
.
e
(
Shadowsocks
.
TAG
,
e
.
getMessage
)
}
}
}
if
(
files
!=
null
)
{
if
(
files
!=
null
)
{
for
(
file
<-
files
)
{
for
(
file
<-
files
)
{
...
@@ -363,9 +407,8 @@ class Shadowsocks
...
@@ -363,9 +407,8 @@ class Shadowsocks
out
.
close
()
out
.
close
()
out
=
null
out
=
null
}
catch
{
}
catch
{
case
ex
:
Exception
=>
{
case
ex
:
Exception
=>
Log
.
e
(
Shadowsocks
.
TAG
,
ex
.
getMessage
)
Log
.
e
(
Shadowsocks
.
TAG
,
ex
.
getMessage
)
}
}
}
}
}
}
}
...
@@ -409,9 +452,8 @@ class Shadowsocks
...
@@ -409,9 +452,8 @@ class Shadowsocks
val
pi
:
PackageInfo
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
)
val
pi
:
PackageInfo
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
)
version
=
pi
.
versionName
version
=
pi
.
versionName
}
catch
{
}
catch
{
case
e
:
PackageManager.NameNotFoundException
=>
{
case
e
:
PackageManager.NameNotFoundException
=>
version
=
"Package name not found"
version
=
"Package name not found"
}
}
}
version
version
}
}
...
@@ -445,12 +487,10 @@ class Shadowsocks
...
@@ -445,12 +487,10 @@ class Shadowsocks
def
onCheckedChanged
(
compoundButton
:
CompoundButton
,
checked
:
Boolean
)
{
def
onCheckedChanged
(
compoundButton
:
CompoundButton
,
checked
:
Boolean
)
{
if
(
compoundButton
eq
switchButton
)
{
if
(
compoundButton
eq
switchButton
)
{
checked
match
{
checked
match
{
case
true
=>
{
case
true
=>
prepareStartService
()
prepareStartService
()
}
case
false
=>
case
false
=>
{
serviceStop
()
serviceStop
()
}
}
}
}
}
}
}
...
@@ -494,15 +534,26 @@ class Shadowsocks
...
@@ -494,15 +534,26 @@ class Shadowsocks
/** Called when the activity is first created. */
/** Called when the activity is first created. */
override
def
onCreate
(
savedInstanceState
:
Bundle
)
{
override
def
onCreate
(
savedInstanceState
:
Bundle
)
{
// Initialize preference
// Initialize
the
preference
setHeaderRes
(
R
.
xml
.
shadowsocks_headers
)
setHeaderRes
(
R
.
xml
.
shadowsocks_headers
)
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
// Initialize profile
// Initialize
the
profile
currentProfile
=
{
currentProfile
=
{
profileManager
.
getProfile
(
settings
.
getInt
(
Key
.
profileId
,
-
1
))
getOrElse
currentProfile
profileManager
.
getProfile
(
settings
.
getInt
(
Key
.
profileId
,
-
1
))
getOrElse
currentProfile
}
}
// Update the profile
if
(!
status
.
getBoolean
(
getVersionName
,
false
))
{
val
h
=
showProgress
(
getString
(
R
.
string
.
initializing
))
status
.
edit
.
putBoolean
(
getVersionName
,
true
).
apply
()
spawn
{
reset
()
currentProfile
=
profileManager
.
create
()
h
.
sendEmptyMessage
(
0
)
}
}
// Initialize drawer
// Initialize drawer
menuAdapter
.
setActiveId
(
settings
.
getInt
(
Key
.
profileId
,
-
1
))
menuAdapter
.
setActiveId
(
settings
.
getInt
(
Key
.
profileId
,
-
1
))
menuAdapter
.
setListener
(
this
)
menuAdapter
.
setListener
(
this
)
...
@@ -527,23 +578,19 @@ class Shadowsocks
...
@@ -527,23 +578,19 @@ class Shadowsocks
getSupportActionBar
.
setIcon
(
R
.
drawable
.
ic_stat_shadowsocks
)
getSupportActionBar
.
setIcon
(
R
.
drawable
.
ic_stat_shadowsocks
)
// Register broadcast receiver
// Register broadcast receiver
registerReceiver
(
stateReceiver
,
new
IntentFilter
(
Action
.
UPDATE_STATE
))
registerReceiver
(
preferenceReceiver
,
new
IntentFilter
(
Action
.
UPDATE_PREFS
))
registerReceiver
(
preferenceReceiver
,
new
IntentFilter
(
Action
.
UPDATE_PREFS
))
// Update status
// Bind to the service
if
(!
Shadowsocks
.
isServiceStarted
(
this
))
{
spawn
{
spawn
{
status
.
edit
.
putBoolean
(
Key
.
isRoot
,
Utils
.
getRoot
).
apply
()
status
.
edit
.
putBoolean
(
Key
.
isRoot
,
Utils
.
getRoot
).
apply
()
handler
.
post
(
new
Runnable
{
}
override
def
run
()
{
if
(!
status
.
getBoolean
(
getVersionName
,
false
))
{
val
isRoot
=
status
.
getBoolean
(
Key
.
isRoot
,
false
)
val
h
=
showProgress
(
getString
(
R
.
string
.
initializing
))
val
s
=
if
(
isRoot
)
classOf
[
ShadowsocksNatService
]
else
classOf
[
ShadowsocksVpnService
]
status
.
edit
.
putBoolean
(
getVersionName
,
true
).
apply
()
bindService
(
new
Intent
(
s
.
getName
),
connection
,
Context
.
BIND_AUTO_CREATE
)
spawn
{
startService
(
new
Intent
(
Shadowsocks
.
this
,
s
))
reset
()
currentProfile
=
profileManager
.
create
()
h
.
sendEmptyMessage
(
0
)
}
}
}
}
)
}
}
}
}
...
@@ -571,15 +618,15 @@ class Shadowsocks
...
@@ -571,15 +618,15 @@ class Shadowsocks
drawer
.
setActiveView
(
v
,
pos
)
drawer
.
setActiveView
(
v
,
pos
)
}
}
def
newProfile
(
id
:
Int
)
{
def
newProfile
(
id
:
Int
)
{
val
builder
=
new
AlertDialog
.
Builder
(
this
)
val
builder
=
new
AlertDialog
.
Builder
(
this
)
builder
.
setTitle
(
R
.
string
.
add_profile
)
builder
.
setItems
(
R
.
array
.
add_profile_methods
,
new
DialogInterface
.
OnClickListener
()
{
.
setTitle
(
R
.
string
.
add_profile
)
.
setItems
(
R
.
array
.
add_profile_methods
,
new
DialogInterface
.
OnClickListener
()
{
def
onClick
(
dialog
:
DialogInterface
,
which
:
Int
)
{
def
onClick
(
dialog
:
DialogInterface
,
which
:
Int
)
{
which
match
{
which
match
{
case
0
=>
{
case
0
=>
dialog
.
dismiss
()
dialog
.
dismiss
()
val
h
=
showProgress
(
getString
(
R
.
string
.
loading
))
val
h
=
showProgress
(
getString
(
R
.
string
.
loading
))
h
.
postDelayed
(
new
Runnable
()
{
h
.
postDelayed
(
new
Runnable
()
{
...
@@ -589,17 +636,14 @@ class Shadowsocks
...
@@ -589,17 +636,14 @@ class Shadowsocks
h
.
sendEmptyMessage
(
0
)
h
.
sendEmptyMessage
(
0
)
}
}
},
600
)
},
600
)
}
case
1
=>
case
1
=>
{
dialog
.
dismiss
()
dialog
.
dismiss
()
addProfile
(
id
)
addProfile
(
id
)
}
case
_
=>
case
_
=>
}
}
}
}
})
})
builder
.
create
().
show
()
builder
.
create
().
show
()
}
}
def
addProfile
(
profile
:
Profile
)
{
def
addProfile
(
profile
:
Profile
)
{
...
@@ -737,7 +781,7 @@ class Shadowsocks
...
@@ -737,7 +781,7 @@ class Shadowsocks
EasyTracker
EasyTracker
.
getInstance
(
this
)
.
getInstance
(
this
)
.
send
(
.
send
(
MapBuilder
.
createEvent
(
Shadowsocks
.
TAG
,
"flush_dnscache"
,
getVersionName
,
null
).
build
())
MapBuilder
.
createEvent
(
Shadowsocks
.
TAG
,
"flush_dnscache"
,
getVersionName
,
null
).
build
())
flushDnsCache
()
flushDnsCache
()
})
})
...
@@ -753,10 +797,9 @@ class Shadowsocks
...
@@ -753,10 +797,9 @@ class Shadowsocks
override
def
onOptionsItemSelected
(
item
:
com.actionbarsherlock.view.MenuItem
)
:
Boolean
=
{
override
def
onOptionsItemSelected
(
item
:
com.actionbarsherlock.view.MenuItem
)
:
Boolean
=
{
item
.
getItemId
match
{
item
.
getItemId
match
{
case
android
.
R
.
id
.
home
=>
{
case
android
.
R
.
id
.
home
=>
drawer
.
toggleMenu
()
drawer
.
toggleMenu
()
return
true
return
true
}
}
}
super
.
onOptionsItemSelected
(
item
)
super
.
onOptionsItemSelected
(
item
)
}
}
...
@@ -768,38 +811,7 @@ class Shadowsocks
...
@@ -768,38 +811,7 @@ class Shadowsocks
protected
override
def
onResume
()
{
protected
override
def
onResume
()
{
super
.
onResume
()
super
.
onResume
()
if
(!
prepared
)
{
ConfigUtils
.
refresh
(
this
)
if
(
Shadowsocks
.
isServiceStarted
(
this
))
{
switchButton
.
setChecked
(
true
)
if
(
ShadowVpnService
.
isServiceStarted
(
this
))
{
val
style
=
new
Style
.
Builder
().
setBackgroundColorValue
(
Style
.
holoBlueLight
).
build
()
val
config
=
new
Configuration
.
Builder
().
setDuration
(
Configuration
.
DURATION_LONG
).
build
()
switchButton
.
setEnabled
(
false
)
Crouton
.
makeText
(
Shadowsocks
.
this
,
R
.
string
.
vpn_status
,
style
)
.
setConfiguration
(
config
)
.
show
()
}
setPreferenceEnabled
(
enabled
=
false
)
onStateChanged
(
State
.
CONNECTED
,
null
)
}
else
{
switchButton
.
setEnabled
(
true
)
switchButton
.
setChecked
(
false
)
Crouton
.
cancelAllCroutons
()
setPreferenceEnabled
(
enabled
=
true
)
if
(
status
.
getBoolean
(
Key
.
isRunning
,
false
))
{
spawn
{
crash_recovery
()
handler
.
sendEmptyMessage
(
MSG_CRASH_RECOVER
)
}
}
onStateChanged
(
State
.
STOPPED
,
null
)
}
}
switchButton
.
setOnCheckedChangeListener
(
this
)
Config
.
refresh
(
this
)
}
}
private
def
setPreferenceEnabled
(
enabled
:
Boolean
)
{
private
def
setPreferenceEnabled
(
enabled
:
Boolean
)
{
...
@@ -848,8 +860,11 @@ class Shadowsocks
...
@@ -848,8 +860,11 @@ class Shadowsocks
override
def
onDestroy
()
{
override
def
onDestroy
()
{
super
.
onDestroy
()
super
.
onDestroy
()
if
(
bgService
!=
null
)
{
bgService
.
unregisterCallback
(
callback
)
unbindService
(
connection
)
}
Crouton
.
cancelAllCroutons
()
Crouton
.
cancelAllCroutons
()
unregisterReceiver
(
stateReceiver
)
unregisterReceiver
(
preferenceReceiver
)
unregisterReceiver
(
preferenceReceiver
)
new
BackupManager
(
this
).
dataChanged
()
new
BackupManager
(
this
).
dataChanged
()
}
}
...
@@ -891,16 +906,14 @@ class Shadowsocks
...
@@ -891,16 +906,14 @@ class Shadowsocks
}
}
}
else
{
}
else
{
resultCode
match
{
resultCode
match
{
case
Activity
.
RESULT_OK
=>
{
case
Activity
.
RESULT_OK
=>
prepared
=
true
prepared
=
true
if
(!
serviceStart
)
{
if
(!
serviceStart
)
{
switchButton
.
setChecked
(
false
)
switchButton
.
setChecked
(
false
)
}
}
}
case
_
=>
case
_
=>
{
clearDialog
()
clearDialog
()
Log
.
e
(
Shadowsocks
.
TAG
,
"Failed to start VpnService"
)
Log
.
e
(
Shadowsocks
.
TAG
,
"Failed to start VpnService"
)
}
}
}
}
}
}
}
...
@@ -918,7 +931,7 @@ class Shadowsocks
...
@@ -918,7 +931,7 @@ class Shadowsocks
}
}
def
serviceStop
()
{
def
serviceStop
()
{
sendBroadcast
(
new
Intent
(
Action
.
CLOSE
)
)
if
(
bgService
!=
null
)
bgService
.
stop
(
)
}
}
/** Called when connect button is clicked. */
/** Called when connect button is clicked. */
...
@@ -935,26 +948,20 @@ class Shadowsocks
...
@@ -935,26 +948,20 @@ class Shadowsocks
return
false
return
false
}
}
}
catch
{
}
catch
{
case
ex
:
Exception
=>
{
case
ex
:
Exception
=>
this
.
showDialog
(
getString
(
R
.
string
.
port_alert
))
this
.
showDialog
(
getString
(
R
.
string
.
port_alert
))
return
false
return
false
}
}
}
if
(
bgService
==
null
)
return
false
bgService
.
start
(
ConfigUtils
.
load
(
settings
))
if
(
isVpnEnabled
)
{
if
(
isVpnEnabled
)
{
if
(
ShadowVpnService
.
isServiceStarted
(
this
))
return
false
val
intent
:
Intent
=
new
Intent
(
this
,
classOf
[
ShadowVpnService
])
Extra
.
put
(
settings
,
intent
)
startService
(
intent
)
val
style
=
new
Style
.
Builder
().
setBackgroundColorValue
(
Style
.
holoBlueLight
).
build
()
val
style
=
new
Style
.
Builder
().
setBackgroundColorValue
(
Style
.
holoBlueLight
).
build
()
val
config
=
new
Configuration
.
Builder
().
setDuration
(
Configuration
.
DURATION_LONG
).
build
()
val
config
=
new
Configuration
.
Builder
().
setDuration
(
Configuration
.
DURATION_LONG
).
build
()
Crouton
.
makeText
(
Shadowsocks
.
this
,
R
.
string
.
vpn_status
,
style
).
setConfiguration
(
config
).
show
()
Crouton
.
makeText
(
Shadowsocks
.
this
,
R
.
string
.
vpn_status
,
style
).
setConfiguration
(
config
).
show
()
switchButton
.
setEnabled
(
false
)
switchButton
.
setEnabled
(
false
)
}
else
{
if
(
ShadowsocksService
.
isServiceStarted
(
this
))
return
false
val
intent
:
Intent
=
new
Intent
(
this
,
classOf
[
ShadowsocksService
])
Extra
.
put
(
settings
,
intent
)
startService
(
intent
)
}
}
true
true
}
}
...
@@ -974,9 +981,8 @@ class Shadowsocks
...
@@ -974,9 +981,8 @@ class Shadowsocks
try
{
try
{
versionName
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
).
versionName
versionName
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
).
versionName
}
catch
{
}
catch
{
case
ex
:
PackageManager.NameNotFoundException
=>
{
case
ex
:
PackageManager.NameNotFoundException
=>
versionName
=
""
versionName
=
""
}
}
}
new
AlertDialog
.
Builder
(
this
)
new
AlertDialog
.
Builder
(
this
)
...
@@ -1014,44 +1020,45 @@ class Shadowsocks
...
@@ -1014,44 +1020,45 @@ class Shadowsocks
}
}
def
onStateChanged
(
s
:
Int
,
m
:
String
)
{
def
onStateChanged
(
s
:
Int
,
m
:
String
)
{
if
(
state
!=
s
)
{
handler
.
post
(
new
Runnable
{
state
=
s
override
def
run
()
{
state
match
{
if
(
state
!=
s
)
{
case
State
.
CONNECTING
=>
{
state
=
s
if
(
progressDialog
==
null
)
{
state
match
{
progressDialog
=
ProgressDialog
case
State
.
CONNECTING
=>
.
show
(
Shadowsocks
.
this
,
""
,
getString
(
R
.
string
.
connecting
),
true
,
true
)
if
(
progressDialog
==
null
)
{
}
progressDialog
=
ProgressDialog
setPreferenceEnabled
(
enabled
=
false
)
.
show
(
Shadowsocks
.
this
,
""
,
getString
(
R
.
string
.
connecting
),
true
,
true
)
}
}
case
State
.
CONNECTED
=>
{
setPreferenceEnabled
(
enabled
=
false
)
clearDialog
()
case
State
.
CONNECTED
=>
if
(!
switchButton
.
isChecked
)
switchButton
.
setChecked
(
true
)
clearDialog
()
setPreferenceEnabled
(
enabled
=
false
)
if
(!
switchButton
.
isChecked
)
switchButton
.
setChecked
(
true
)
}
setPreferenceEnabled
(
enabled
=
false
)
case
State
.
STOPPED
=>
{
case
State
.
STOPPED
=>
clearDialog
()
clearDialog
()
if
(
switchButton
.
isChecked
)
{
if
(
switchButton
.
isChecked
)
{
switchButton
.
setEnabled
(
true
)
switchButton
.
setEnabled
(
true
)
switchButton
.
setChecked
(
false
)
switchButton
.
setChecked
(
false
)
Crouton
.
cancelAllCroutons
()
Crouton
.
cancelAllCroutons
()
}
}
if
(
m
!=
null
)
{
if
(
m
!=
null
)
{
Crouton
.
cancelAllCroutons
()
Crouton
.
cancelAllCroutons
()
val
style
=
new
Style
.
Builder
().
setBackgroundColorValue
(
Style
.
holoRedLight
).
build
()
val
style
=
new
Style
.
Builder
().
setBackgroundColorValue
(
Style
.
holoRedLight
).
build
()
val
config
=
new
Configuration
.
Builder
()
val
config
=
new
Configuration
.
Builder
()
.
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
).
format
(
m
),
style
)
.
setConfiguration
(
config
)
.
setConfiguration
(
config
)
.
show
()
.
show
()
}
setPreferenceEnabled
(
enabled
=
true
)
}
}
setPreferenceEnabled
(
enabled
=
true
)
if
(!
isSinglePane
)
sendBroadcast
(
new
Intent
(
Action
.
UPDATE_FRAGMENT
)
)
}
}
}
}
if
(!
isSinglePane
)
sendBroadcast
(
new
Intent
(
Action
.
UPDATE_FRAGMENT
))
})
}
}
}
class
PreferenceBroadcastReceiver
extends
BroadcastReceiver
{
class
PreferenceBroadcastReceiver
extends
BroadcastReceiver
{
...
@@ -1061,12 +1068,4 @@ class Shadowsocks
...
@@ -1061,12 +1068,4 @@ class Shadowsocks
}
}
}
}
class
StateBroadcastReceiver
extends
BroadcastReceiver
{
override
def
onReceive
(
context
:
Context
,
intent
:
Intent
)
{
val
state
=
intent
.
getIntExtra
(
Extra
.
STATE
,
State
.
INIT
)
val
message
=
intent
.
getStringExtra
(
Extra
.
MESSAGE
)
onStateChanged
(
state
,
message
)
}
}
}
}
src/main/scala/com/github/shadowsocks/ShadowsocksService.scala
→
src/main/scala/com/github/shadowsocks/Shadowsocks
Nat
Service.scala
View file @
c4833ddb
...
@@ -57,22 +57,16 @@ import org.apache.http.conn.util.InetAddressUtils
...
@@ -57,22 +57,16 @@ import org.apache.http.conn.util.InetAddressUtils
import
scala.collection._
import
scala.collection._
import
java.util.
{
TimerTask
,
Timer
}
import
java.util.
{
TimerTask
,
Timer
}
import
android.net.TrafficStats
import
android.net.TrafficStats
import
scala.concurrent.ops._
import
com.github.shadowsocks.utils._
import
com.github.shadowsocks.utils._
import
scala.Some
import
scala.Some
import
android.graphics.Color
import
android.graphics.Color
import
com.github.shadowsocks.aidl.Config
case
class
TrafficStat
(
tx
:
Long
,
rx
:
Long
,
timestamp
:
Long
)
case
class
TrafficStat
(
tx
:
Long
,
rx
:
Long
,
timestamp
:
Long
)
object
ShadowsocksService
{
class
ShadowsocksNatService
extends
Service
with
BaseService
{
def
isServiceStarted
(
context
:
Context
)
:
Boolean
=
{
Utils
.
isServiceStarted
(
"com.github.shadowsocks.ShadowsocksService"
,
context
)
}
}
class
ShadowsocksService
extends
Service
{
val
TAG
=
"ShadowsocksNatService"
val
TAG
=
"ShadowsocksService"
val
CMD_IPTABLES_RETURN
=
" -t nat -A OUTPUT -p tcp -d 0.0.0.0 -j RETURN\n"
val
CMD_IPTABLES_RETURN
=
" -t nat -A OUTPUT -p tcp -d 0.0.0.0 -j RETURN\n"
val
CMD_IPTABLES_REDIRECT_ADD_SOCKS
=
" -t nat -A OUTPUT -p tcp "
+
"-j REDIRECT --to 8123\n"
val
CMD_IPTABLES_REDIRECT_ADD_SOCKS
=
" -t nat -A OUTPUT -p tcp "
+
"-j REDIRECT --to 8123\n"
...
@@ -80,12 +74,6 @@ class ShadowsocksService extends Service {
...
@@ -80,12 +74,6 @@ class ShadowsocksService extends Service {
"-j DNAT --to-destination 127.0.0.1:8123\n"
"-j DNAT --to-destination 127.0.0.1:8123\n"
val
DNS_PORT
=
8153
val
DNS_PORT
=
8153
val
MSG_CONNECT_FINISH
=
1
val
MSG_CONNECT_SUCCESS
=
2
val
MSG_CONNECT_FAIL
=
3
val
MSG_STOP_SELF
=
4
val
MSG_VPN_ERROR
=
5
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
])
...
@@ -104,56 +92,25 @@ class ShadowsocksService extends Service {
...
@@ -104,56 +92,25 @@ class ShadowsocksService extends Service {
private
var
mStartForegroundArgs
=
new
Array
[
AnyRef
](
2
)
private
var
mStartForegroundArgs
=
new
Array
[
AnyRef
](
2
)
private
var
mStopForegroundArgs
=
new
Array
[
AnyRef
](
1
)
private
var
mStopForegroundArgs
=
new
Array
[
AnyRef
](
1
)
private
var
state
=
State
.
INIT
private
var
last
:
TrafficStat
=
null
private
var
last
:
TrafficStat
=
null
private
var
lastTxRate
=
0
private
var
lastTxRate
=
0
private
var
lastRxRate
=
0
private
var
lastRxRate
=
0
private
var
timer
:
Timer
=
null
private
var
timer
:
Timer
=
null
private
val
TIMER_INTERVAL
=
2
private
val
TIMER_INTERVAL
=
2
private
def
changeState
(
s
:
Int
)
{
if
(
state
!=
s
)
{
state
=
s
val
intent
=
new
Intent
(
Action
.
UPDATE_STATE
)
intent
.
putExtra
(
Extra
.
STATE
,
state
)
sendBroadcast
(
intent
)
}
}
val
handler
:
Handler
=
new
Handler
{
val
handler
:
Handler
=
new
Handler
{
override
def
handleMessage
(
msg
:
Message
)
{
override
def
handleMessage
(
msg
:
Message
)
{
msg
.
what
match
{
msg
.
what
match
{
case
M
SG_
CONNECT_SUCCESS
=>
case
M
sg
.
CONNECT_SUCCESS
=>
changeState
(
State
.
CONNECTED
)
changeState
(
State
.
CONNECTED
)
case
M
SG_
CONNECT_FAIL
=>
case
M
sg
.
CONNECT_FAIL
=>
changeState
(
State
.
STOPPED
)
changeState
(
State
.
STOPPED
)
case
MSG_STOP_SELF
=>
stopSelf
()
case
_
=>
case
_
=>
}
}
super
.
handleMessage
(
msg
)
super
.
handleMessage
(
msg
)
}
}
}
}
def
getPid
(
name
:
String
)
:
Int
=
{
try
{
val
reader
:
BufferedReader
=
new
BufferedReader
(
new
FileReader
(
Path
.
BASE
+
name
+
".pid"
))
val
line
=
reader
.
readLine
return
Integer
.
valueOf
(
line
)
}
catch
{
case
e
:
FileNotFoundException
=>
{
Log
.
e
(
TAG
,
"Cannot open pid file: "
+
name
)
}
case
e
:
IOException
=>
{
Log
.
e
(
TAG
,
"Cannot read pid file: "
+
name
)
}
case
e
:
NumberFormatException
=>
{
Log
.
e
(
TAG
,
"Invalid pid"
,
e
)
}
}
-
1
}
def
startShadowsocksDaemon
()
{
def
startShadowsocksDaemon
()
{
val
cmd
:
String
=
(
Path
.
BASE
+
val
cmd
:
String
=
(
Path
.
BASE
+
"shadowsocks -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -f "
+
"shadowsocks -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -f "
+
...
@@ -165,8 +122,8 @@ class ShadowsocksService extends Service {
...
@@ -165,8 +122,8 @@ class ShadowsocksService extends Service {
def
startDnsDaemon
()
{
def
startDnsDaemon
()
{
val
cmd
:
String
=
Path
.
BASE
+
"pdnsd -c "
+
Path
.
BASE
+
"pdnsd.conf"
val
cmd
:
String
=
Path
.
BASE
+
"pdnsd -c "
+
Path
.
BASE
+
"pdnsd.conf"
val
conf
:
String
=
Config
.
PDNSD
.
format
(
"127.0.0.1"
)
val
conf
:
String
=
Config
Utils
.
PDNSD
.
format
(
"127.0.0.1"
)
Config
.
printToFile
(
new
File
(
Path
.
BASE
+
"pdnsd.conf"
))(
p
=>
{
Config
Utils
.
printToFile
(
new
File
(
Path
.
BASE
+
"pdnsd.conf"
))(
p
=>
{
p
.
println
(
conf
)
p
.
println
(
conf
)
})
})
Utils
.
runCommand
(
cmd
)
Utils
.
runCommand
(
cmd
)
...
@@ -178,101 +135,17 @@ class ShadowsocksService extends Service {
...
@@ -178,101 +135,17 @@ class ShadowsocksService extends Service {
val
pi
:
PackageInfo
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
)
val
pi
:
PackageInfo
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
)
version
=
pi
.
versionName
version
=
pi
.
versionName
}
catch
{
}
catch
{
case
e
:
PackageManager.NameNotFoundException
=>
{
case
e
:
PackageManager.NameNotFoundException
=>
version
=
"Package name not found"
version
=
"Package name not found"
}
}
}
version
version
}
}
def
handleCommand
(
intent
:
Intent
)
{
if
(
intent
==
null
)
{
stopSelf
()
return
}
changeState
(
State
.
CONNECTING
)
config
=
Extra
.
get
(
intent
)
if
(
config
.
isTrafficStat
)
{
// initialize timer
val
task
=
new
TimerTask
{
def
run
()
{
val
pm
=
getSystemService
(
Context
.
POWER_SERVICE
).
asInstanceOf
[
PowerManager
]
val
now
=
new
TrafficStat
(
TrafficStats
.
getUidTxBytes
(
uid
),
TrafficStats
.
getUidRxBytes
(
uid
),
java
.
lang
.
System
.
currentTimeMillis
())
val
txRate
=
((
now
.
tx
-
last
.
tx
)
/
1024
/
TIMER_INTERVAL
).
toInt
val
rxRate
=
((
now
.
rx
-
last
.
rx
)
/
1024
/
TIMER_INTERVAL
).
toInt
last
=
now
if
(
lastTxRate
==
txRate
&&
lastRxRate
==
rxRate
)
{
return
}
else
{
lastTxRate
=
txRate
lastRxRate
=
rxRate
}
if
((
pm
.
isScreenOn
&&
state
==
State
.
CONNECTED
)
||
(
txRate
==
0
&&
rxRate
==
0
))
{
notifyForegroundAlert
(
getString
(
R
.
string
.
forward_success
),
getString
(
R
.
string
.
service_status
).
format
(
math
.
max
(
txRate
,
rxRate
)),
math
.
max
(
txRate
,
rxRate
))
}
}
}
last
=
new
TrafficStat
(
TrafficStats
.
getUidTxBytes
(
uid
),
TrafficStats
.
getUidRxBytes
(
uid
),
java
.
lang
.
System
.
currentTimeMillis
())
timer
=
new
Timer
(
true
)
timer
.
schedule
(
task
,
TIMER_INTERVAL
*
1000
,
TIMER_INTERVAL
*
1000
)
}
spawn
{
if
(
config
.
proxy
==
"198.199.101.152"
)
{
val
container
=
getApplication
.
asInstanceOf
[
ShadowsocksApplication
].
tagContainer
try
{
config
=
Config
.
getPublicConfig
(
getBaseContext
,
container
,
config
)
}
catch
{
case
ex
:
Exception
=>
{
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
stopSelf
()
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_FAIL
,
500
)
return
}
}
}
killProcesses
()
var
resolved
:
Boolean
=
false
if
(!
InetAddressUtils
.
isIPv4Address
(
config
.
proxy
)
&&
!
InetAddressUtils
.
isIPv6Address
(
config
.
proxy
))
{
Utils
.
resolve
(
config
.
proxy
,
enableIPv6
=
true
)
match
{
case
Some
(
a
)
=>
config
.
proxy
=
a
resolved
=
true
case
None
=>
resolved
=
false
}
}
else
{
resolved
=
true
}
hasRedirectSupport
=
Utils
.
getHasRedirectSupport
if
(
resolved
&&
handleConnection
)
{
notifyForegroundAlert
(
getString
(
R
.
string
.
forward_success
),
getString
(
R
.
string
.
service_running
).
format
(
config
.
profileName
))
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_SUCCESS
,
500
)
}
else
{
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
stopSelf
()
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_FAIL
,
500
)
}
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_FINISH
,
500
)
}
}
def
startRedsocksDaemon
()
{
def
startRedsocksDaemon
()
{
val
conf
=
Config
.
REDSOCKS
.
format
(
config
.
localPort
)
val
conf
=
ConfigUtils
.
REDSOCKS
.
format
(
config
.
localPort
)
val
cmd
=
"%sredsocks -p %sredsocks.pid -c %sredsocks.conf"
.
format
(
Path
.
BASE
,
Path
.
BASE
,
Path
.
BASE
)
val
cmd
=
"%sredsocks -p %sredsocks.pid -c %sredsocks.conf"
Config
.
printToFile
(
new
File
(
Path
.
BASE
+
"redsocks.conf"
))(
p
=>
{
.
format
(
Path
.
BASE
,
Path
.
BASE
,
Path
.
BASE
)
ConfigUtils
.
printToFile
(
new
File
(
Path
.
BASE
+
"redsocks.conf"
))(
p
=>
{
p
.
println
(
conf
)
p
.
println
(
conf
)
})
})
Utils
.
runRootCommand
(
cmd
)
Utils
.
runRootCommand
(
cmd
)
...
@@ -291,14 +164,14 @@ class ShadowsocksService extends Service {
...
@@ -291,14 +164,14 @@ class ShadowsocksService extends Service {
try
{
try
{
t
.
join
(
300
)
t
.
join
(
300
)
}
catch
{
}
catch
{
case
ignored
:
InterruptedException
=>
{
case
ignored
:
InterruptedException
=>
}
}
}
!
t
.
isAlive
!
t
.
isAlive
}
}
/** Called when the activity is first created. */
/** Called when the activity is first created. */
def
handleConnection
:
Boolean
=
{
def
handleConnection
:
Boolean
=
{
startShadowsocksDaemon
()
startShadowsocksDaemon
()
startDnsDaemon
()
startDnsDaemon
()
startRedsocksDaemon
()
startRedsocksDaemon
()
...
@@ -308,21 +181,14 @@ class ShadowsocksService extends Service {
...
@@ -308,21 +181,14 @@ class ShadowsocksService extends Service {
true
true
}
}
def
initSoundVibrateLights
(
notification
:
Notification
)
{
notification
.
sound
=
null
notification
.
defaults
|=
Notification
.
DEFAULT_LIGHTS
}
def
invokeMethod
(
method
:
Method
,
args
:
Array
[
AnyRef
])
{
def
invokeMethod
(
method
:
Method
,
args
:
Array
[
AnyRef
])
{
try
{
try
{
method
.
invoke
(
this
,
mStartForegroundArgs
:
_
*
)
method
.
invoke
(
this
,
mStartForegroundArgs
:
_
*
)
}
catch
{
}
catch
{
case
e
:
InvocationTargetException
=>
{
case
e
:
InvocationTargetException
=>
Log
.
w
(
TAG
,
"Unable to invoke method"
,
e
)
Log
.
w
(
TAG
,
"Unable to invoke method"
,
e
)
}
case
e
:
IllegalAccessException
=>
case
e
:
IllegalAccessException
=>
{
Log
.
w
(
TAG
,
"Unable to invoke method"
,
e
)
Log
.
w
(
TAG
,
"Unable to invoke method"
,
e
)
}
}
}
}
}
...
@@ -340,8 +206,9 @@ class ShadowsocksService extends Service {
...
@@ -340,8 +206,9 @@ class ShadowsocksService extends Service {
val
icon
=
getResources
.
getDrawable
(
R
.
drawable
.
ic_stat_shadowsocks
)
val
icon
=
getResources
.
getDrawable
(
R
.
drawable
.
ic_stat_shadowsocks
)
if
(
rate
>=
0
)
{
if
(
rate
>=
0
)
{
val
bitmap
=
Utils
.
getBitmap
(
rate
.
toString
,
icon
.
getIntrinsicWidth
*
4
,
val
bitmap
=
Utils
icon
.
getIntrinsicHeight
*
4
,
Color
.
TRANSPARENT
)
.
getBitmap
(
rate
.
toString
,
icon
.
getIntrinsicWidth
*
4
,
icon
.
getIntrinsicHeight
*
4
,
Color
.
TRANSPARENT
)
builder
.
setLargeIcon
(
bitmap
)
builder
.
setLargeIcon
(
bitmap
)
if
(
rate
<
1000
)
{
if
(
rate
<
1000
)
{
...
@@ -352,7 +219,6 @@ class ShadowsocksService extends Service {
...
@@ -352,7 +219,6 @@ class ShadowsocksService extends Service {
}
else
{
}
else
{
builder
.
setSmallIcon
(
R
.
drawable
.
ic_stat_speed
,
1091
)
builder
.
setSmallIcon
(
R
.
drawable
.
ic_stat_speed
,
1091
)
}
}
}
else
{
}
else
{
builder
.
setSmallIcon
(
R
.
drawable
.
ic_stat_shadowsocks
)
builder
.
setSmallIcon
(
R
.
drawable
.
ic_stat_shadowsocks
)
}
}
...
@@ -364,7 +230,7 @@ class ShadowsocksService extends Service {
...
@@ -364,7 +230,7 @@ class ShadowsocksService extends Service {
.
setContentText
(
info
)
.
setContentText
(
info
)
.
setContentIntent
(
contentIntent
)
.
setContentIntent
(
contentIntent
)
.
addAction
(
android
.
R
.
drawable
.
ic_menu_close_clear_cancel
,
getString
(
R
.
string
.
stop
),
.
addAction
(
android
.
R
.
drawable
.
ic_menu_close_clear_cancel
,
getString
(
R
.
string
.
stop
),
actionIntent
)
actionIntent
)
startForegroundCompat
(
1
,
builder
.
build
)
startForegroundCompat
(
1
,
builder
.
build
)
}
}
...
@@ -386,20 +252,17 @@ class ShadowsocksService extends Service {
...
@@ -386,20 +252,17 @@ class ShadowsocksService extends Service {
}
}
def
onBind
(
intent
:
Intent
)
:
IBinder
=
{
def
onBind
(
intent
:
Intent
)
:
IBinder
=
{
null
if
(
classOf
[
ShadowsocksNatService
].
getName
equals
intent
.
getAction
)
{
binder
}
else
{
null
}
}
}
override
def
onCreate
()
{
override
def
onCreate
()
{
super
.
onCreate
()
super
.
onCreate
()
Config
.
refresh
(
this
)
ConfigUtils
.
refresh
(
this
)
EasyTracker
.
getInstance
(
this
)
.
send
(
MapBuilder
.
createEvent
(
TAG
,
"start"
,
getVersionName
,
0L
)
.
set
(
Fields
.
SESSION_CONTROL
,
"start"
)
.
build
())
notificationManager
=
this
notificationManager
=
this
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
.
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
...
@@ -408,63 +271,19 @@ class ShadowsocksService extends Service {
...
@@ -408,63 +271,19 @@ class ShadowsocksService extends Service {
mStartForeground
=
getClass
.
getMethod
(
"startForeground"
,
mStartForegroundSignature
:
_
*
)
mStartForeground
=
getClass
.
getMethod
(
"startForeground"
,
mStartForegroundSignature
:
_
*
)
mStopForeground
=
getClass
.
getMethod
(
"stopForeground"
,
mStopForegroundSignature
:
_
*
)
mStopForeground
=
getClass
.
getMethod
(
"stopForeground"
,
mStopForegroundSignature
:
_
*
)
}
catch
{
}
catch
{
case
e
:
NoSuchMethodException
=>
{
case
e
:
NoSuchMethodException
=>
mStartForeground
=
{
mStartForeground
=
{
mStopForeground
=
null
mStopForeground
=
null
mStopForeground
mStopForeground
}
}
}
}
}
try
{
try
{
mSetForeground
=
getClass
.
getMethod
(
"setForeground"
,
mSetForegroundSignature
:
_
*
)
mSetForeground
=
getClass
.
getMethod
(
"setForeground"
,
mSetForegroundSignature
:
_
*
)
}
catch
{
}
catch
{
case
e
:
NoSuchMethodException
=>
{
case
e
:
NoSuchMethodException
=>
throw
new
IllegalStateException
(
throw
new
IllegalStateException
(
"OS doesn't have Service.startForeground OR Service.setForeground!"
)
"OS doesn't have Service.startForeground OR Service.setForeground!"
)
}
}
// register close receiver
val
filter
=
new
IntentFilter
()
filter
.
addAction
(
Intent
.
ACTION_SHUTDOWN
)
filter
.
addAction
(
Action
.
CLOSE
)
receiver
=
new
BroadcastReceiver
()
{
def
onReceive
(
p1
:
Context
,
p2
:
Intent
)
{
stopSelf
()
}
}
registerReceiver
(
receiver
,
filter
)
}
/** Called when the activity is closed. */
override
def
onDestroy
()
{
// reset timer
if
(
timer
!=
null
)
{
timer
.
cancel
()
timer
=
null
}
// clean up context
changeState
(
State
.
STOPPED
)
EasyTracker
.
getInstance
(
this
)
.
send
(
MapBuilder
.
createEvent
(
TAG
,
"stop"
,
getVersionName
,
0L
)
.
set
(
Fields
.
SESSION_CONTROL
,
"stop"
)
.
build
())
stopForegroundCompat
(
1
)
if
(
receiver
!=
null
)
{
unregisterReceiver
(
receiver
)
receiver
=
null
}
}
// reset NAT
killProcesses
()
super
.
onDestroy
()
}
}
def
killProcesses
()
{
def
killProcesses
()
{
...
@@ -489,12 +308,7 @@ class ShadowsocksService extends Service {
...
@@ -489,12 +308,7 @@ class ShadowsocksService extends Service {
Utils
.
runCommand
(
sb
.
toString
())
Utils
.
runCommand
(
sb
.
toString
())
}
}
override
def
onStart
(
intent
:
Intent
,
startId
:
Int
)
{
handleCommand
(
intent
)
}
override
def
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
)
:
Int
=
{
override
def
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
)
:
Int
=
{
handleCommand
(
intent
)
Service
.
START_STICKY
Service
.
START_STICKY
}
}
...
@@ -593,12 +407,10 @@ class ShadowsocksService extends Service {
...
@@ -593,12 +407,10 @@ class ShadowsocksService extends Service {
try
{
try
{
mStopForeground
.
invoke
(
this
,
mStopForegroundArgs
:
_
*
)
mStopForeground
.
invoke
(
this
,
mStopForegroundArgs
:
_
*
)
}
catch
{
}
catch
{
case
e
:
InvocationTargetException
=>
{
case
e
:
InvocationTargetException
=>
Log
.
w
(
TAG
,
"Unable to invoke stopForeground"
,
e
)
Log
.
w
(
TAG
,
"Unable to invoke stopForeground"
,
e
)
}
case
e
:
IllegalAccessException
=>
case
e
:
IllegalAccessException
=>
{
Log
.
w
(
TAG
,
"Unable to invoke stopForeground"
,
e
)
Log
.
w
(
TAG
,
"Unable to invoke stopForeground"
,
e
)
}
}
}
return
return
}
}
...
@@ -606,4 +418,135 @@ class ShadowsocksService extends Service {
...
@@ -606,4 +418,135 @@ class ShadowsocksService extends Service {
mSetForegroundArgs
(
0
)
=
boolean2Boolean
(
x
=
false
)
mSetForegroundArgs
(
0
)
=
boolean2Boolean
(
x
=
false
)
invokeMethod
(
mSetForeground
,
mSetForegroundArgs
)
invokeMethod
(
mSetForeground
,
mSetForegroundArgs
)
}
}
override
def
startRunner
(
c
:
Config
)
{
var
config
=
c
// register close receiver
val
filter
=
new
IntentFilter
()
filter
.
addAction
(
Intent
.
ACTION_SHUTDOWN
)
filter
.
addAction
(
Action
.
CLOSE
)
receiver
=
new
BroadcastReceiver
()
{
def
onReceive
(
p1
:
Context
,
p2
:
Intent
)
{
stopRunner
()
}
}
registerReceiver
(
receiver
,
filter
)
// start tracker
EasyTracker
.
getInstance
(
this
)
.
send
(
MapBuilder
.
createEvent
(
TAG
,
"start"
,
getVersionName
,
0L
)
.
set
(
Fields
.
SESSION_CONTROL
,
"start"
)
.
build
())
changeState
(
State
.
CONNECTING
)
if
(
config
.
isTrafficStat
)
{
// initialize timer
val
task
=
new
TimerTask
{
def
run
()
{
val
pm
=
getSystemService
(
Context
.
POWER_SERVICE
).
asInstanceOf
[
PowerManager
]
val
now
=
new
TrafficStat
(
TrafficStats
.
getUidTxBytes
(
uid
),
TrafficStats
.
getUidRxBytes
(
uid
),
java
.
lang
.
System
.
currentTimeMillis
())
val
txRate
=
((
now
.
tx
-
last
.
tx
)
/
1024
/
TIMER_INTERVAL
).
toInt
val
rxRate
=
((
now
.
rx
-
last
.
rx
)
/
1024
/
TIMER_INTERVAL
).
toInt
last
=
now
if
(
lastTxRate
==
txRate
&&
lastRxRate
==
rxRate
)
{
return
}
else
{
lastTxRate
=
txRate
lastRxRate
=
rxRate
}
if
((
pm
.
isScreenOn
&&
state
==
State
.
CONNECTED
)
||
(
txRate
==
0
&&
rxRate
==
0
))
{
notifyForegroundAlert
(
getString
(
R
.
string
.
forward_success
),
getString
(
R
.
string
.
service_status
).
format
(
math
.
max
(
txRate
,
rxRate
)),
math
.
max
(
txRate
,
rxRate
))
}
}
}
last
=
new
TrafficStat
(
TrafficStats
.
getUidTxBytes
(
uid
),
TrafficStats
.
getUidRxBytes
(
uid
),
java
.
lang
.
System
.
currentTimeMillis
())
timer
=
new
Timer
(
true
)
timer
.
schedule
(
task
,
TIMER_INTERVAL
*
1000
,
TIMER_INTERVAL
*
1000
)
}
if
(
config
.
proxy
==
"198.199.101.152"
)
{
val
container
=
getApplication
.
asInstanceOf
[
ShadowsocksApplication
].
tagContainer
try
{
config
=
ConfigUtils
.
getPublicConfig
(
getBaseContext
,
container
,
config
)
}
catch
{
case
ex
:
Exception
=>
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
stopRunner
()
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_FAIL
,
500
)
return
}
}
killProcesses
()
var
resolved
:
Boolean
=
false
if
(!
InetAddressUtils
.
isIPv4Address
(
config
.
proxy
)
&&
!
InetAddressUtils
.
isIPv6Address
(
config
.
proxy
))
{
Utils
.
resolve
(
config
.
proxy
,
enableIPv6
=
true
)
match
{
case
Some
(
a
)
=>
config
.
proxy
=
a
resolved
=
true
case
None
=>
resolved
=
false
}
}
else
{
resolved
=
true
}
hasRedirectSupport
=
Utils
.
getHasRedirectSupport
if
(
resolved
&&
handleConnection
)
{
notifyForegroundAlert
(
getString
(
R
.
string
.
forward_success
),
getString
(
R
.
string
.
service_running
).
format
(
config
.
profileName
))
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_SUCCESS
,
500
)
}
else
{
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
stopRunner
()
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_FAIL
,
500
)
}
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_FINISH
,
500
)
}
override
def
stopRunner
()
{
// change the state
changeState
(
State
.
STOPPED
)
// stop the tracker
EasyTracker
.
getInstance
(
this
)
.
send
(
MapBuilder
.
createEvent
(
TAG
,
"stop"
,
getVersionName
,
0L
)
.
set
(
Fields
.
SESSION_CONTROL
,
"stop"
)
.
build
())
// reset timer
if
(
timer
!=
null
)
{
timer
.
cancel
()
timer
=
null
}
// clean up context
stopForegroundCompat
(
1
)
if
(
receiver
!=
null
)
{
unregisterReceiver
(
receiver
)
receiver
=
null
}
// reset NAT
killProcesses
()
}
override
def
getTag
=
TAG
override
def
getServiceMode
=
Mode
.
NAT
}
}
src/main/scala/com/github/shadowsocks/ShadowsocksReceiver.scala
View file @
c4833ddb
...
@@ -54,33 +54,17 @@ class ShadowsocksReceiver extends BroadcastReceiver {
...
@@ -54,33 +54,17 @@ class ShadowsocksReceiver extends BroadcastReceiver {
val
settings
:
SharedPreferences
=
PreferenceManager
.
getDefaultSharedPreferences
(
context
)
val
settings
:
SharedPreferences
=
PreferenceManager
.
getDefaultSharedPreferences
(
context
)
val
status
=
context
.
getSharedPreferences
(
Key
.
status
,
Context
.
MODE_PRIVATE
)
val
status
=
context
.
getSharedPreferences
(
Key
.
status
,
Context
.
MODE_PRIVATE
)
if
(
intent
.
getAction
==
Action
.
UPDATE_STATE
)
{
val
state
=
intent
.
getIntExtra
(
Extra
.
STATE
,
State
.
INIT
)
val
running
=
state
match
{
case
State
.
CONNECTING
=>
true
case
State
.
CONNECTED
=>
true
case
_
=>
false
}
status
.
edit
.
putBoolean
(
Key
.
isRunning
,
running
).
commit
()
return
}
var
versionName
:
String
=
null
var
versionName
:
String
=
null
try
{
try
{
versionName
=
context
.
getPackageManager
.
getPackageInfo
(
context
.
getPackageName
,
0
).
versionName
versionName
=
context
.
getPackageManager
.
getPackageInfo
(
context
.
getPackageName
,
0
).
versionName
}
catch
{
}
catch
{
case
e
:
PackageManager.NameNotFoundException
=>
{
case
e
:
PackageManager.NameNotFoundException
=>
versionName
=
"NONE"
versionName
=
"NONE"
}
}
}
val
isAutoConnect
:
Boolean
=
settings
.
getBoolean
(
Key
.
isAutoConnect
,
false
)
val
isAutoConnect
:
Boolean
=
settings
.
getBoolean
(
Key
.
isAutoConnect
,
false
)
val
isInstalled
:
Boolean
=
status
.
getBoolean
(
versionName
,
false
)
val
isInstalled
:
Boolean
=
status
.
getBoolean
(
versionName
,
false
)
if
(
isAutoConnect
&&
isInstalled
)
{
if
(
isAutoConnect
&&
isInstalled
)
{
if
(
Utils
.
getRoot
)
{
if
(
Utils
.
getRoot
)
{
if
(
ShadowsocksService
.
isServiceStarted
(
context
))
return
val
intent
:
Intent
=
new
Intent
(
context
,
classOf
[
ShadowsocksService
])
Extra
.
put
(
settings
,
intent
)
context
.
startService
(
intent
)
}
}
}
}
}
}
...
...
src/main/scala/com/github/shadowsocks/ShadowVpnService.scala
→
src/main/scala/com/github/shadowsocks/Shadow
socks
VpnService.scala
View file @
c4833ddb
...
@@ -51,27 +51,15 @@ import java.io._
...
@@ -51,27 +51,15 @@ import java.io._
import
android.net.VpnService
import
android.net.VpnService
import
org.apache.http.conn.util.InetAddressUtils
import
org.apache.http.conn.util.InetAddressUtils
import
android.os.Message
import
android.os.Message
import
scala.concurrent.ops._
import
org.apache.commons.net.util.SubnetUtils
import
org.apache.commons.net.util.SubnetUtils
import
java.net.InetAddress
import
java.net.InetAddress
import
com.github.shadowsocks.utils._
import
com.github.shadowsocks.utils._
import
scala.Some
import
scala.Some
import
com.github.shadowsocks.aidl.Config
object
ShadowVpnService
{
class
ShadowsocksVpnService
extends
VpnService
with
BaseService
{
def
isServiceStarted
(
context
:
Context
)
:
Boolean
=
{
Utils
.
isServiceStarted
(
"com.github.shadowsocks.ShadowVpnService"
,
context
)
}
}
class
ShadowVpnService
extends
VpnService
{
val
TAG
=
"ShadowVpnService"
val
MSG_CONNECT_FINISH
=
1
val
TAG
=
"ShadowsocksVpnService"
val
MSG_CONNECT_SUCCESS
=
2
val
MSG_CONNECT_FAIL
=
3
val
MSG_STOP_SELF
=
5
val
MSG_VPN_ERROR
=
6
val
VPN_MTU
=
1500
val
VPN_MTU
=
1500
...
@@ -83,60 +71,21 @@ class ShadowVpnService extends VpnService {
...
@@ -83,60 +71,21 @@ class ShadowVpnService extends VpnService {
var
apps
:
Array
[
ProxiedApp
]
=
null
var
apps
:
Array
[
ProxiedApp
]
=
null
var
config
:
Config
=
null
var
config
:
Config
=
null
private
var
state
=
State
.
INIT
private
var
message
:
String
=
null
def
changeState
(
s
:
Int
)
{
changeState
(
s
,
null
)
}
def
changeState
(
s
:
Int
,
m
:
String
)
{
if
(
state
!=
s
)
{
state
=
s
if
(
m
!=
null
)
message
=
m
val
intent
=
new
Intent
(
Action
.
UPDATE_STATE
)
intent
.
putExtra
(
Extra
.
STATE
,
state
)
intent
.
putExtra
(
Extra
.
MESSAGE
,
message
)
sendBroadcast
(
intent
)
}
}
val
handler
:
Handler
=
new
Handler
{
val
handler
:
Handler
=
new
Handler
{
override
def
handleMessage
(
msg
:
Message
)
{
override
def
handleMessage
(
msg
:
Message
)
{
msg
.
what
match
{
msg
.
what
match
{
case
M
SG_
CONNECT_SUCCESS
=>
case
M
sg
.
CONNECT_SUCCESS
=>
changeState
(
State
.
CONNECTED
)
changeState
(
State
.
CONNECTED
)
case
M
SG_
CONNECT_FAIL
=>
case
M
sg
.
CONNECT_FAIL
=>
changeState
(
State
.
STOPPED
)
changeState
(
State
.
STOPPED
)
case
M
SG_
VPN_ERROR
=>
case
M
sg
.
VPN_ERROR
=>
if
(
msg
.
obj
!=
null
)
changeState
(
State
.
STOPPED
,
msg
.
obj
.
asInstanceOf
[
String
])
if
(
msg
.
obj
!=
null
)
changeState
(
State
.
STOPPED
,
msg
.
obj
.
asInstanceOf
[
String
])
case
MSG_STOP_SELF
=>
stopSelf
()
case
_
=>
case
_
=>
}
}
super
.
handleMessage
(
msg
)
super
.
handleMessage
(
msg
)
}
}
}
}
def
getPid
(
name
:
String
)
:
Int
=
{
try
{
val
reader
:
BufferedReader
=
new
BufferedReader
(
new
FileReader
(
Path
.
BASE
+
name
+
".pid"
))
val
line
=
reader
.
readLine
return
Integer
.
valueOf
(
line
)
}
catch
{
case
e
:
FileNotFoundException
=>
{
Log
.
e
(
TAG
,
"Cannot open pid file: "
+
name
)
}
case
e
:
IOException
=>
{
Log
.
e
(
TAG
,
"Cannot read pid file: "
+
name
)
}
case
e
:
NumberFormatException
=>
{
Log
.
e
(
TAG
,
"Invalid pid"
,
e
)
}
}
-
1
}
def
startShadowsocksDaemon
()
{
def
startShadowsocksDaemon
()
{
val
cmd
:
String
=
(
Path
.
BASE
+
val
cmd
:
String
=
(
Path
.
BASE
+
"shadowsocks -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -f "
+
"shadowsocks -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -f "
+
...
@@ -148,8 +97,8 @@ class ShadowVpnService extends VpnService {
...
@@ -148,8 +97,8 @@ class ShadowVpnService extends VpnService {
def
startDnsDaemon
()
{
def
startDnsDaemon
()
{
val
cmd
:
String
=
Path
.
BASE
+
"pdnsd -c "
+
Path
.
BASE
+
"pdnsd.conf"
val
cmd
:
String
=
Path
.
BASE
+
"pdnsd -c "
+
Path
.
BASE
+
"pdnsd.conf"
val
conf
:
String
=
Config
.
PDNSD
.
format
(
"0.0.0.0"
)
val
conf
:
String
=
Config
Utils
.
PDNSD
.
format
(
"0.0.0.0"
)
Config
.
printToFile
(
new
File
(
Path
.
BASE
+
"pdnsd.conf"
))(
p
=>
{
Config
Utils
.
printToFile
(
new
File
(
Path
.
BASE
+
"pdnsd.conf"
))(
p
=>
{
p
.
println
(
conf
)
p
.
println
(
conf
)
})
})
Utils
.
runCommand
(
cmd
)
Utils
.
runCommand
(
cmd
)
...
@@ -161,74 +110,12 @@ class ShadowVpnService extends VpnService {
...
@@ -161,74 +110,12 @@ class ShadowVpnService extends VpnService {
val
pi
:
PackageInfo
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
)
val
pi
:
PackageInfo
=
getPackageManager
.
getPackageInfo
(
getPackageName
,
0
)
version
=
pi
.
versionName
version
=
pi
.
versionName
}
catch
{
}
catch
{
case
e
:
PackageManager.NameNotFoundException
=>
{
case
e
:
PackageManager.NameNotFoundException
=>
version
=
"Package name not found"
version
=
"Package name not found"
}
}
}
version
version
}
}
def
handleCommand
(
intent
:
Intent
)
{
if
(
intent
==
null
)
{
stopSelf
()
return
}
if
(
VpnService
.
prepare
(
this
)
!=
null
)
{
val
i
=
new
Intent
(
this
,
classOf
[
ShadowVpnActivity
])
i
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
startActivity
(
i
)
stopSelf
()
return
}
changeState
(
State
.
CONNECTING
)
config
=
Extra
.
get
(
intent
)
spawn
{
if
(
config
.
proxy
==
"198.199.101.152"
)
{
val
container
=
getApplication
.
asInstanceOf
[
ShadowsocksApplication
].
tagContainer
try
{
config
=
Config
.
getPublicConfig
(
getBaseContext
,
container
,
config
)
}
catch
{
case
ex
:
Exception
=>
{
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
stopSelf
()
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_FAIL
,
500
)
return
}
}
}
killProcesses
()
// Resolve server address
var
resolved
:
Boolean
=
false
if
(!
InetAddressUtils
.
isIPv4Address
(
config
.
proxy
)
&&
!
InetAddressUtils
.
isIPv6Address
(
config
.
proxy
))
{
Utils
.
resolve
(
config
.
proxy
,
enableIPv6
=
true
)
match
{
case
Some
(
addr
)
=>
config
.
proxy
=
addr
resolved
=
true
case
None
=>
resolved
=
false
}
}
else
{
resolved
=
true
}
if
(
resolved
&&
handleConnection
)
{
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_SUCCESS
,
300
)
}
else
{
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_FAIL
,
300
)
handler
.
sendEmptyMessageDelayed
(
MSG_STOP_SELF
,
500
)
}
handler
.
sendEmptyMessageDelayed
(
MSG_CONNECT_FINISH
,
300
)
}
}
def
waitForProcess
(
name
:
String
)
:
Boolean
=
{
def
waitForProcess
(
name
:
String
)
:
Boolean
=
{
val
pid
:
Int
=
getPid
(
name
)
val
pid
:
Int
=
getPid
(
name
)
if
(
pid
==
-
1
)
return
false
if
(
pid
==
-
1
)
return
false
...
@@ -242,8 +129,7 @@ class ShadowVpnService extends VpnService {
...
@@ -242,8 +129,7 @@ class ShadowVpnService extends VpnService {
try
{
try
{
t
.
join
(
300
)
t
.
join
(
300
)
}
catch
{
}
catch
{
case
ignored
:
InterruptedException
=>
{
case
ignored
:
InterruptedException
=>
}
}
}
!
t
.
isAlive
!
t
.
isAlive
}
}
...
@@ -308,18 +194,17 @@ class ShadowVpnService extends VpnService {
...
@@ -308,18 +194,17 @@ class ShadowVpnService extends VpnService {
try
{
try
{
conn
=
builder
.
establish
()
conn
=
builder
.
establish
()
}
catch
{
}
catch
{
case
ex
:
IllegalStateException
=>
{
case
ex
:
IllegalStateException
=>
val
msg
=
new
Message
()
val
msg
=
new
Message
()
msg
.
what
=
M
SG_
VPN_ERROR
msg
.
what
=
M
sg
.
VPN_ERROR
msg
.
obj
=
ex
.
getMessage
msg
.
obj
=
ex
.
getMessage
handler
.
sendMessage
(
msg
)
handler
.
sendMessage
(
msg
)
conn
=
null
conn
=
null
}
case
ex
:
Exception
=>
conn
=
null
case
ex
:
Exception
=>
conn
=
null
}
}
if
(
conn
==
null
)
{
if
(
conn
==
null
)
{
stop
Self
()
stop
Runner
()
return
return
}
}
...
@@ -335,7 +220,7 @@ class ShadowVpnService extends VpnService {
...
@@ -335,7 +220,7 @@ class ShadowVpnService extends VpnService {
+
"--loglevel 3 "
+
"--loglevel 3 "
+
"--pid %stun2socks.pid"
)
+
"--pid %stun2socks.pid"
)
.
format
(
PRIVATE_VLAN
.
format
(
"2"
),
PRIVATE_VLAN
.
format
(
"1"
),
config
.
localPort
,
fd
,
VPN_MTU
,
.
format
(
PRIVATE_VLAN
.
format
(
"2"
),
PRIVATE_VLAN
.
format
(
"1"
),
config
.
localPort
,
fd
,
VPN_MTU
,
Path
.
BASE
)
Path
.
BASE
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
)
if
(
BuildConfig
.
DEBUG
)
Log
.
d
(
TAG
,
cmd
)
System
.
exec
(
cmd
)
System
.
exec
(
cmd
)
}
}
...
@@ -348,11 +233,6 @@ class ShadowVpnService extends VpnService {
...
@@ -348,11 +233,6 @@ class ShadowVpnService extends VpnService {
true
true
}
}
def
initSoundVibrateLights
(
notification
:
Notification
)
{
notification
.
sound
=
null
notification
.
defaults
|=
Notification
.
DEFAULT_LIGHTS
}
def
notifyAlert
(
title
:
String
,
info
:
String
)
{
def
notifyAlert
(
title
:
String
,
info
:
String
)
{
val
openIntent
:
Intent
=
new
Intent
(
this
,
classOf
[
Shadowsocks
])
val
openIntent
:
Intent
=
new
Intent
(
this
,
classOf
[
Shadowsocks
])
openIntent
.
setFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
)
openIntent
.
setFlags
(
Intent
.
FLAG_ACTIVITY_CLEAR_TOP
)
...
@@ -373,6 +253,8 @@ class ShadowVpnService extends VpnService {
...
@@ -373,6 +253,8 @@ class ShadowVpnService extends VpnService {
val
action
=
intent
.
getAction
val
action
=
intent
.
getAction
if
(
VpnService
.
SERVICE_INTERFACE
==
action
)
{
if
(
VpnService
.
SERVICE_INTERFACE
==
action
)
{
return
super
.
onBind
(
intent
)
return
super
.
onBind
(
intent
)
}
else
if
(
classOf
[
ShadowsocksVpnService
].
getName
==
action
)
{
return
binder
}
}
null
null
}
}
...
@@ -380,8 +262,46 @@ class ShadowVpnService extends VpnService {
...
@@ -380,8 +262,46 @@ class ShadowVpnService extends VpnService {
override
def
onCreate
()
{
override
def
onCreate
()
{
super
.
onCreate
()
super
.
onCreate
()
Config
.
refresh
(
this
)
ConfigUtils
.
refresh
(
this
)
notificationManager
=
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
.
asInstanceOf
[
NotificationManager
]
}
def
killProcesses
()
{
val
sb
=
new
StringBuilder
if
(!
waitForProcess
(
"shadowsocks"
))
{
sb
++=
"kill -9 `cat /data/data/com.github.shadowsocks/shadowsocks.pid`"
++=
"\n"
sb
++=
"killall -9 shadowsocks"
++=
"\n"
}
if
(!
waitForProcess
(
"tun2socks"
))
{
sb
++=
"kill -9 `cat /data/data/com.github.shadowsocks/tun2socks.pid`"
++=
"\n"
sb
++=
"killall -9 tun2socks"
++=
"\n"
}
if
(!
waitForProcess
(
"pdnsd"
))
{
sb
++=
"kill -9 `cat /data/data/com.github.shadowsocks/pdnsd.pid`"
++=
"\n"
sb
++=
"killall -9 pdnsd"
++=
"\n"
}
Utils
.
runCommand
(
sb
.
toString
())
}
override
def
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
)
:
Int
=
{
Service
.
START_STICKY
}
override
def
startRunner
(
c
:
Config
)
{
var
config
=
c
// ensure the VPNService is prepared
if
(
VpnService
.
prepare
(
this
)
!=
null
)
{
val
i
=
new
Intent
(
this
,
classOf
[
ShadowVpnActivity
])
i
.
addFlags
(
Intent
.
FLAG_ACTIVITY_NEW_TASK
)
startActivity
(
i
)
return
}
// start the tracker
EasyTracker
EasyTracker
.
getInstance
(
this
)
.
getInstance
(
this
)
.
send
(
MapBuilder
.
send
(
MapBuilder
...
@@ -389,26 +309,64 @@ class ShadowVpnService extends VpnService {
...
@@ -389,26 +309,64 @@ class ShadowVpnService extends VpnService {
.
set
(
Fields
.
SESSION_CONTROL
,
"start"
)
.
set
(
Fields
.
SESSION_CONTROL
,
"start"
)
.
build
())
.
build
())
notificationManager
=
getSystemService
(
Context
.
NOTIFICATION_SERVICE
)
.
asInstanceOf
[
NotificationManager
]
// register close receiver
// register close receiver
val
filter
=
new
IntentFilter
()
val
filter
=
new
IntentFilter
()
filter
.
addAction
(
Intent
.
ACTION_SHUTDOWN
)
filter
.
addAction
(
Intent
.
ACTION_SHUTDOWN
)
filter
.
addAction
(
Action
.
CLOSE
)
receiver
=
new
BroadcastReceiver
{
receiver
=
new
BroadcastReceiver
{
def
onReceive
(
p1
:
Context
,
p2
:
Intent
)
{
def
onReceive
(
p1
:
Context
,
p2
:
Intent
)
{
stop
Self
()
stop
Runner
()
}
}
}
}
registerReceiver
(
receiver
,
filter
)
registerReceiver
(
receiver
,
filter
)
}
override
def
onDestroy
()
{
changeState
(
State
.
CONNECTING
)
if
(
config
.
proxy
==
"198.199.101.152"
)
{
val
container
=
getApplication
.
asInstanceOf
[
ShadowsocksApplication
].
tagContainer
try
{
config
=
ConfigUtils
.
getPublicConfig
(
getBaseContext
,
container
,
config
)
}
catch
{
case
ex
:
Exception
=>
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
stopRunner
()
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_FAIL
,
500
)
return
}
}
// reset the context
killProcesses
()
killProcesses
()
// Resolve the server address
var
resolved
:
Boolean
=
false
if
(!
InetAddressUtils
.
isIPv4Address
(
config
.
proxy
)
&&
!
InetAddressUtils
.
isIPv6Address
(
config
.
proxy
))
{
Utils
.
resolve
(
config
.
proxy
,
enableIPv6
=
true
)
match
{
case
Some
(
addr
)
=>
config
.
proxy
=
addr
resolved
=
true
case
None
=>
resolved
=
false
}
}
else
{
resolved
=
true
}
if
(
resolved
&&
handleConnection
)
{
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_SUCCESS
,
300
)
}
else
{
notifyAlert
(
getString
(
R
.
string
.
forward_fail
),
getString
(
R
.
string
.
service_failed
))
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_FAIL
,
300
)
stopRunner
()
}
handler
.
sendEmptyMessageDelayed
(
Msg
.
CONNECT_FINISH
,
300
)
}
override
def
stopRunner
()
{
// channge the state
changeState
(
State
.
STOPPED
)
changeState
(
State
.
STOPPED
)
// stop the tracker
EasyTracker
EasyTracker
.
getInstance
(
this
)
.
getInstance
(
this
)
.
send
(
MapBuilder
.
send
(
MapBuilder
...
@@ -416,45 +374,26 @@ class ShadowVpnService extends VpnService {
...
@@ -416,45 +374,26 @@ class ShadowVpnService extends VpnService {
.
set
(
Fields
.
SESSION_CONTROL
,
"stop"
)
.
set
(
Fields
.
SESSION_CONTROL
,
"stop"
)
.
build
())
.
build
())
// clean up the context
if
(
receiver
!=
null
)
{
if
(
receiver
!=
null
)
{
unregisterReceiver
(
receiver
)
unregisterReceiver
(
receiver
)
receiver
=
null
receiver
=
null
}
}
// reset VPN
killProcesses
()
// close connections
if
(
conn
!=
null
)
{
if
(
conn
!=
null
)
{
conn
.
close
()
conn
.
close
()
conn
=
null
conn
=
null
}
}
// reset notifications
notificationManager
.
cancel
(
1
)
notificationManager
.
cancel
(
1
)
super
.
onDestroy
()
}
}
def
killProcesses
()
{
override
def
getTag
=
TAG
val
sb
=
new
StringBuilder
if
(!
waitForProcess
(
"shadowsocks"
))
{
sb
++=
"kill -9 `cat /data/data/com.github.shadowsocks/shadowsocks.pid`"
++=
"\n"
sb
++=
"killall -9 shadowsocks"
++=
"\n"
}
if
(!
waitForProcess
(
"tun2socks"
))
{
sb
++=
"kill -9 `cat /data/data/com.github.shadowsocks/tun2socks.pid`"
++=
"\n"
sb
++=
"killall -9 tun2socks"
++=
"\n"
}
if
(!
waitForProcess
(
"pdnsd"
))
{
sb
++=
"kill -9 `cat /data/data/com.github.shadowsocks/pdnsd.pid`"
++=
"\n"
sb
++=
"killall -9 pdnsd"
++=
"\n"
}
Utils
.
runCommand
(
sb
.
toString
())
}
override
def
onStart
(
intent
:
Intent
,
startId
:
Int
)
{
handleCommand
(
intent
)
}
override
def
onStartCommand
(
intent
:
Intent
,
flags
:
Int
,
startId
:
Int
)
:
Int
=
{
handleCommand
(
intent
)
Service
.
START_STICKY
}
override
def
getServiceMode
=
Mode
.
VPN
}
}
src/main/scala/com/github/shadowsocks/utils/Config.scala
→
src/main/scala/com/github/shadowsocks/utils/Config
Utils
.scala
View file @
c4833ddb
package
com.github.shadowsocks.utils
package
com.github.shadowsocks.utils
import
android.content.
Context
import
android.content.
{
Intent
,
SharedPreferences
,
Context
}
import
com.github.shadowsocks.ShadowsocksApplication
import
com.github.shadowsocks.ShadowsocksApplication
import
com.google.tagmanager.Container
import
com.google.tagmanager.Container
import
scalaj.http.
{
HttpOptions
,
Http
}
import
scalaj.http.
{
HttpOptions
,
Http
}
import
com.github.shadowsocks.aidl.Config
object
Config
{
object
Config
Utils
{
val
SHADOWSOCKS
=
"{\"server\": [%s], \"server_port\": %d, \"local_port\": %d, \"password\": %s, \"timeout\": %d}"
val
SHADOWSOCKS
=
"{\"server\": [%s], \"server_port\": %d, \"local_port\": %d, \"password\": %s, \"timeout\": %d}"
val
REDSOCKS
=
"base {"
+
val
REDSOCKS
=
"base {"
+
" log_debug = off;"
+
" log_debug = off;"
+
...
@@ -83,10 +84,35 @@ object Config {
...
@@ -83,10 +84,35 @@ object Config {
val
method
=
proxy
(
3
).
trim
val
method
=
proxy
(
3
).
trim
new
Config
(
config
.
isGlobalProxy
,
config
.
isGFWList
,
config
.
isBypassApps
,
config
.
isTrafficStat
,
new
Config
(
config
.
isGlobalProxy
,
config
.
isGFWList
,
config
.
isBypassApps
,
config
.
isTrafficStat
,
config
.
profileName
,
host
,
password
,
method
,
port
,
config
.
localPort
,
config
.
proxiedAppString
)
config
.
profileName
,
host
,
password
,
method
,
config
.
proxiedAppString
,
port
,
config
.
localPort
)
}
}
}
case
class
Config
(
isGlobalProxy
:
Boolean
,
isGFWList
:
Boolean
,
isBypassApps
:
Boolean
,
def
load
(
settings
:
SharedPreferences
)
:
Config
=
{
isTrafficStat
:
Boolean
,
profileName
:
String
,
var
proxy
:
String
,
sitekey
:
String
,
val
isGlobalProxy
=
settings
.
getBoolean
(
Key
.
isGlobalProxy
,
false
)
encMethod
:
String
,
remotePort
:
Int
,
localPort
:
Int
,
proxiedAppString
:
String
)
val
isGFWList
=
settings
.
getBoolean
(
Key
.
isGFWList
,
false
)
val
isBypassApps
=
settings
.
getBoolean
(
Key
.
isBypassApps
,
false
)
val
isTrafficStat
=
settings
.
getBoolean
(
Key
.
isTrafficStat
,
false
)
val
profileName
=
settings
.
getString
(
Key
.
profileName
,
"default"
)
val
proxy
=
settings
.
getString
(
Key
.
proxy
,
"127.0.0.1"
)
val
sitekey
=
settings
.
getString
(
Key
.
sitekey
,
"default"
)
val
encMethod
=
settings
.
getString
(
Key
.
encMethod
,
"table"
)
val
remotePort
:
Int
=
try
{
settings
.
getString
(
Key
.
remotePort
,
"1984"
).
toInt
}
catch
{
case
ex
:
NumberFormatException
=>
1984
}
val
localPort
:
Int
=
try
{
settings
.
getString
(
Key
.
localPort
,
"1984"
).
toInt
}
catch
{
case
ex
:
NumberFormatException
=>
1984
}
val
proxiedAppString
=
settings
.
getString
(
Key
.
proxied
,
""
)
new
Config
(
isGlobalProxy
,
isGFWList
,
isBypassApps
,
isTrafficStat
,
profileName
,
proxy
,
sitekey
,
encMethod
,
proxiedAppString
,
remotePort
,
localPort
)
}
}
\ No newline at end of file
src/main/scala/com/github/shadowsocks/utils/Constants.scala
View file @
c4833ddb
package
com.github.shadowsocks.utils
package
com.github.shadowsocks.utils
import
android.content.
{
Intent
,
SharedPreferences
}
import
android.content.
{
Intent
,
SharedPreferences
}
import
com.github.shadowsocks.aidl.Config
object
Msg
{
val
CONNECT_FINISH
=
1
val
CONNECT_SUCCESS
=
2
val
CONNECT_FAIL
=
3
val
VPN_ERROR
=
6
}
object
Path
{
object
Path
{
val
BASE
=
"/data/data/com.github.shadowsocks/"
val
BASE
=
"/data/data/com.github.shadowsocks/"
...
@@ -37,100 +45,21 @@ object Scheme {
...
@@ -37,100 +45,21 @@ object Scheme {
val
SS
=
"ss"
val
SS
=
"ss"
}
}
object
Mode
{
val
NAT
=
0
val
VPN
=
1
}
object
State
{
object
State
{
val
INIT
=
0
val
INIT
=
0
val
CONNECTING
=
1
val
CONNECTING
=
1
val
CONNECTED
=
2
val
CONNECTED
=
2
val
STOPPED
=
3
val
STOPPED
=
3
def
isAvailable
(
state
:
Int
)
:
Boolean
=
state
!=
CONNECTED
&&
state
!=
CONNECTING
}
}
object
Action
{
object
Action
{
val
CLOSE
=
"com.github.shadowsocks.ACTION_SHUTDOWN"
val
CLOSE
=
"com.github.shadowsocks.CLOSE"
val
UPDATE_STATE
=
"com.github.shadowsocks.ACTION_UPDATE_STATE"
val
UPDATE_FRAGMENT
=
"com.github.shadowsocks.ACTION_UPDATE_FRAGMENT"
val
UPDATE_FRAGMENT
=
"com.github.shadowsocks.ACTION_UPDATE_FRAGMENT"
val
UPDATE_PREFS
=
"com.github.shadowsocks.ACTION_UPDATE_PREFS"
val
UPDATE_PREFS
=
"com.github.shadowsocks.ACTION_UPDATE_PREFS"
}
}
\ No newline at end of file
object
Extra
{
val
STATE
=
"state"
val
MESSAGE
=
"message"
def
save
(
settings
:
SharedPreferences
,
config
:
Config
)
{
val
edit
=
settings
.
edit
()
edit
.
putBoolean
(
Key
.
isGlobalProxy
,
config
.
isGlobalProxy
)
edit
.
putBoolean
(
Key
.
isGFWList
,
config
.
isGFWList
)
edit
.
putBoolean
(
Key
.
isBypassApps
,
config
.
isBypassApps
)
edit
.
putBoolean
(
Key
.
isTrafficStat
,
config
.
isTrafficStat
)
edit
.
putString
(
Key
.
profileName
,
config
.
profileName
)
edit
.
putString
(
Key
.
proxy
,
config
.
proxy
)
edit
.
putString
(
Key
.
sitekey
,
config
.
sitekey
)
edit
.
putString
(
Key
.
encMethod
,
config
.
encMethod
)
edit
.
putString
(
Key
.
remotePort
,
config
.
remotePort
.
toString
)
edit
.
putString
(
Key
.
localPort
,
config
.
localPort
.
toString
)
edit
.
apply
()
}
def
get
(
intent
:
Intent
)
:
Config
=
{
val
isGlobalProxy
=
intent
.
getBooleanExtra
(
Key
.
isGlobalProxy
,
false
)
val
isGFWList
=
intent
.
getBooleanExtra
(
Key
.
isGFWList
,
false
)
val
isBypassApps
=
intent
.
getBooleanExtra
(
Key
.
isBypassApps
,
false
)
val
isTrafficStat
=
intent
.
getBooleanExtra
(
Key
.
isTrafficStat
,
false
)
val
profileName
=
intent
.
getStringExtra
(
Key
.
profileName
)
val
proxy
=
intent
.
getStringExtra
(
Key
.
proxy
)
val
sitekey
=
intent
.
getStringExtra
(
Key
.
sitekey
)
val
encMethod
=
intent
.
getStringExtra
(
Key
.
encMethod
)
val
remotePort
=
intent
.
getIntExtra
(
Key
.
remotePort
,
1984
)
val
localPort
=
intent
.
getIntExtra
(
Key
.
localPort
,
1984
)
val
proxiedString
=
intent
.
getStringExtra
(
Key
.
proxied
)
new
Config
(
isGlobalProxy
,
isGFWList
,
isBypassApps
,
isTrafficStat
,
profileName
,
proxy
,
sitekey
,
encMethod
,
remotePort
,
localPort
,
proxiedString
)
}
def
put
(
settings
:
SharedPreferences
,
intent
:
Intent
)
{
val
isGlobalProxy
=
settings
.
getBoolean
(
Key
.
isGlobalProxy
,
false
)
val
isGFWList
=
settings
.
getBoolean
(
Key
.
isGFWList
,
false
)
val
isBypassApps
=
settings
.
getBoolean
(
Key
.
isBypassApps
,
false
)
val
isTrafficStat
=
settings
.
getBoolean
(
Key
.
isTrafficStat
,
false
)
val
profileName
=
settings
.
getString
(
Key
.
profileName
,
"default"
)
val
proxy
=
settings
.
getString
(
Key
.
proxy
,
"127.0.0.1"
)
val
sitekey
=
settings
.
getString
(
Key
.
sitekey
,
"default"
)
val
encMethod
=
settings
.
getString
(
Key
.
encMethod
,
"table"
)
val
remotePort
:
Int
=
try
{
settings
.
getString
(
Key
.
remotePort
,
"1984"
).
toInt
}
catch
{
case
ex
:
NumberFormatException
=>
{
1984
}
}
val
localProt
:
Int
=
try
{
settings
.
getString
(
Key
.
localPort
,
"1984"
).
toInt
}
catch
{
case
ex
:
NumberFormatException
=>
{
1984
}
}
val
proxiedAppString
=
settings
.
getString
(
Key
.
proxied
,
""
)
intent
.
putExtra
(
Key
.
isGlobalProxy
,
isGlobalProxy
)
intent
.
putExtra
(
Key
.
isGFWList
,
isGFWList
)
intent
.
putExtra
(
Key
.
isBypassApps
,
isBypassApps
)
intent
.
putExtra
(
Key
.
isTrafficStat
,
isTrafficStat
)
intent
.
putExtra
(
Key
.
profileName
,
profileName
)
intent
.
putExtra
(
Key
.
proxy
,
proxy
)
intent
.
putExtra
(
Key
.
sitekey
,
sitekey
)
intent
.
putExtra
(
Key
.
encMethod
,
encMethod
)
intent
.
putExtra
(
Key
.
remotePort
,
remotePort
)
intent
.
putExtra
(
Key
.
localPort
,
localProt
)
intent
.
putExtra
(
Key
.
proxied
,
proxiedAppString
)
}
}
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