Compare commits

...
13 Commits
Author SHA1 Message Date
Max Lv efb614030f disable NAT mode again 2014-11-17 20:56:17 +08:00
Max Lv 8f41ea291f bump version 2014-11-17 20:23:10 +08:00
Max Lv 27ba7d64f4 fix a very old bug in redsocks 2014-11-17 19:51:08 +08:00
Max Lv 8fb5d7f8c6 fix a bug in autostart 2014-11-17 14:48:57 +08:00
Max Lv 014692cb84 udpate default settings 2014-11-17 09:44:11 +08:00
Max Lv 948db260b6 bump version 2014-11-17 09:39:34 +08:00
Max Lv b7c3c7d269 enable NAT mode again 2014-11-17 09:15:01 +08:00
Max Lv 897b222aa8 refine some strings 2014-11-17 08:46:12 +08:00
Max Lv 9a724cd063 fix #148 2014-11-16 21:35:54 +08:00
Max Lv b15a4604f2 fix chn list 2014-11-15 12:28:17 +08:00
Max Lv 2e3a2c9544 bypass private IP on Lollipop 2014-11-13 20:33:02 +08:00
Max Lv d6ed052338 clean up 2014-11-13 18:15:39 +08:00
Max Lv 4b99f8e3d6 Fix a bug 2014-11-13 18:04:19 +08:00
25 changed files with 1185 additions and 577 deletions
+1 -1
View File
@@ -780,7 +780,7 @@ static int redsocks_init_instance(redsocks_instance *instance)
int on = 1; int on = 1;
int fd = -1; int fd = -1;
fd = socket(AF_INET, SOCK_STREAM, 0); fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (fd == -1) { if (fd == -1) {
log_errno(LOG_ERR, "socket"); log_errno(LOG_ERR, "socket");
goto fail; goto fail;
+2 -2
View File
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.shadowsocks" package="com.github.shadowsocks"
android:versionCode="77" android:versionCode="81"
android:versionName="2.3.2"> android:versionName="2.4.1">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
@@ -14,6 +14,7 @@ public class Config implements Parcelable {
public String profileName = "Untitled"; public String profileName = "Untitled";
public String proxy = "127.0.0.1"; public String proxy = "127.0.0.1";
public String sitekey = "null"; public String sitekey = "null";
public String route = "all";
public String encMethod = "rc4"; public String encMethod = "rc4";
public String proxiedAppString = ""; public String proxiedAppString = "";
@@ -33,7 +34,7 @@ public class Config implements Parcelable {
public Config(boolean isGlobalProxy, boolean isGFWList, boolean isBypassApps, public Config(boolean isGlobalProxy, boolean isGFWList, boolean isBypassApps,
boolean isTrafficStat, boolean isUdpDns, String profileName, String proxy, String sitekey, boolean isTrafficStat, boolean isUdpDns, String profileName, String proxy, String sitekey,
String encMethod, String proxiedAppString, int remotePort, int localPort) { String encMethod, String proxiedAppString, String route, int remotePort, int localPort) {
this.isGlobalProxy = isGlobalProxy; this.isGlobalProxy = isGlobalProxy;
this.isGFWList = isGFWList; this.isGFWList = isGFWList;
this.isBypassApps = isBypassApps; this.isBypassApps = isBypassApps;
@@ -44,6 +45,7 @@ public class Config implements Parcelable {
this.sitekey = sitekey; this.sitekey = sitekey;
this.encMethod = encMethod; this.encMethod = encMethod;
this.proxiedAppString = proxiedAppString; this.proxiedAppString = proxiedAppString;
this.route = route;
this.remotePort = remotePort; this.remotePort = remotePort;
this.localPort = localPort; this.localPort = localPort;
} }
@@ -63,6 +65,7 @@ public class Config implements Parcelable {
sitekey = in.readString(); sitekey = in.readString();
encMethod = in.readString(); encMethod = in.readString();
proxiedAppString = in.readString(); proxiedAppString = in.readString();
route = in.readString();
remotePort = in.readInt(); remotePort = in.readInt();
localPort = in.readInt(); localPort = in.readInt();
} }
@@ -82,6 +85,7 @@ public class Config implements Parcelable {
out.writeString(sitekey); out.writeString(sitekey);
out.writeString(encMethod); out.writeString(encMethod);
out.writeString(proxiedAppString); out.writeString(proxiedAppString);
out.writeString(route);
out.writeInt(remotePort); out.writeInt(remotePort);
out.writeInt(localPort); out.writeInt(localPort);
} }
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2013 Jorrit "Chainfire" Jongma * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2013 Jorrit "Chainfire" Jongma * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@ package eu.chainfire.libsuperuser;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import com.github.shadowsocks.BuildConfig; import com.github.shadowsocks.BuildConfig;
/** /**
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2013 Jorrit "Chainfire" Jongma * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2013 Jorrit "Chainfire" Jongma * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2012-2013 Jorrit "Chainfire" Jongma * Copyright (C) 2012-2014 Jorrit "Chainfire" Jongma
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
+11 -3
View File
@@ -25,11 +25,13 @@
<string name="dns_proxy_summary">重定向 DNS 查询到远程服务器</string> <string name="dns_proxy_summary">重定向 DNS 查询到远程服务器</string>
<string name="auto_set_gfwlist">国内路由</string> <string name="auto_set_gfwlist">国内路由</string>
<string name="auto_set_gfwlist_summary">绕过所有位于中国的网站</string> <string name="auto_set_gfwlist_summary">绕过所有位于中国的网站</string>
<string name="route_list">路由</string>
<string name="route_list_summary">绕过指定路由列表中的地址</string>
<string name="auto_set_proxy">全局代理</string> <string name="auto_set_proxy">全局代理</string>
<string name="auto_set_proxy_summary">设置系统代理</string> <string name="auto_set_proxy_summary">设置系统代理</string>
<string name="proxied_apps">局部代理</string> <string name="proxied_apps">分应用代理</string>
<string name="proxied_apps_summary">为应用程序分别设置代理</string> <string name="proxied_apps_summary">为应用程序分别设置代理</string>
<string name="proxied_help">局部代理</string> <string name="proxied_help">分应用代理</string>
<string name="bypass_apps">绕行模式</string> <string name="bypass_apps">绕行模式</string>
<string name="bypass_apps_summary">启用该选项,以使所选应用程序的流量不经过代理</string> <string name="bypass_apps_summary">启用该选项,以使所选应用程序的流量不经过代理</string>
<string name="auto_connect">自动连接</string> <string name="auto_connect">自动连接</string>
@@ -67,7 +69,7 @@
<string name="add_profile">添加配置文件</string> <string name="add_profile">添加配置文件</string>
<string name="udp_dns">UDP 转发</string> <string name="udp_dns">UDP 转发</string>
<string name="udp_dns_summary">由远程服务器转发 UDP 协议的 DNS 请求</string> <string name="udp_dns_summary">由远程服务器转发 UDP 协议的数据包</string>
<!-- profile --> <!-- profile -->
<string name="add_profile_dialog">为影梭添加此配置文件?</string> <string name="add_profile_dialog">为影梭添加此配置文件?</string>
@@ -76,4 +78,10 @@
<item>手动设置</item> <item>手动设置</item>
</string-array> </string-array>
<string-array name="route_entry">
<item>全局</item>
<item>绕过局域网地址</item>
<item>绕过局域网及中国大陆地址</item>
</string-array>
</resources> </resources>
+160 -5
View File
@@ -38,7 +38,163 @@
<item>seed-cfb</item> <item>seed-cfb</item>
</string-array> </string-array>
<string-array name="chn_list_full"> <string-array name="route_entry">
<item>All</item>
<item>Bypass LAN</item>
<item>Bypass LAN &amp; China</item>
</string-array>
<string-array name="route_value">
<item>all</item>
<item>bypass-lan</item>
<item>bypass-china</item>
</string-array>
<string-array name="private_route">
<item>0.0.0.0/8</item>
<item>10.0.0.0/8</item>
<item>100.64.0.0/10</item>
<item>127.0.0.0/8</item>
<item>169.254.0.0/16</item>
<item>172.16.0.0/12</item>
<item>192.0.0.0/29</item>
<item>192.0.2.0/24</item>
<item>192.88.99.0/24</item>
<item>192.168.0.0/16</item>
<item>198.18.0.0/15</item>
<item>198.51.100.0/24</item>
<item>203.0.113.0/24</item>
<item>224.0.0.0/3</item>
</string-array>
<string-array name="bypass_private_route">
<item>1.0.0.0/8</item>
<item>2.0.0.0/7</item>
<item>4.0.0.0/6</item>
<item>8.0.0.0/7</item>
<item>11.0.0.0/8</item>
<item>12.0.0.0/6</item>
<item>16.0.0.0/4</item>
<item>32.0.0.0/3</item>
<item>64.0.0.0/3</item>
<item>96.0.0.0/6</item>
<item>100.0.0.0/10</item>
<item>100.128.0.0/9</item>
<item>101.0.0.0/8</item>
<item>102.0.0.0/7</item>
<item>104.0.0.0/5</item>
<item>112.0.0.0/5</item>
<item>120.0.0.0/6</item>
<item>124.0.0.0/7</item>
<item>126.0.0.0/8</item>
<item>128.0.0.0/3</item>
<item>160.0.0.0/5</item>
<item>168.0.0.0/8</item>
<item>169.0.0.0/9</item>
<item>169.128.0.0/10</item>
<item>169.192.0.0/11</item>
<item>169.224.0.0/12</item>
<item>169.240.0.0/13</item>
<item>169.248.0.0/14</item>
<item>169.252.0.0/15</item>
<item>169.255.0.0/16</item>
<item>170.0.0.0/7</item>
<item>172.0.0.0/12</item>
<item>172.32.0.0/11</item>
<item>172.64.0.0/10</item>
<item>172.128.0.0/9</item>
<item>173.0.0.0/8</item>
<item>174.0.0.0/7</item>
<item>176.0.0.0/4</item>
<item>192.0.0.8/29</item>
<item>192.0.0.16/28</item>
<item>192.0.0.32/27</item>
<item>192.0.0.64/26</item>
<item>192.0.0.128/25</item>
<item>192.0.1.0/24</item>
<item>192.0.3.0/24</item>
<item>192.0.4.0/22</item>
<item>192.0.8.0/21</item>
<item>192.0.16.0/20</item>
<item>192.0.32.0/19</item>
<item>192.0.64.0/18</item>
<item>192.0.128.0/17</item>
<item>192.1.0.0/16</item>
<item>192.2.0.0/15</item>
<item>192.4.0.0/14</item>
<item>192.8.0.0/13</item>
<item>192.16.0.0/12</item>
<item>192.32.0.0/11</item>
<item>192.64.0.0/12</item>
<item>192.80.0.0/13</item>
<item>192.88.0.0/18</item>
<item>192.88.64.0/19</item>
<item>192.88.96.0/23</item>
<item>192.88.98.0/24</item>
<item>192.88.100.0/22</item>
<item>192.88.104.0/21</item>
<item>192.88.112.0/20</item>
<item>192.88.128.0/17</item>
<item>192.89.0.0/16</item>
<item>192.90.0.0/15</item>
<item>192.92.0.0/14</item>
<item>192.96.0.0/11</item>
<item>192.128.0.0/11</item>
<item>192.160.0.0/13</item>
<item>192.169.0.0/16</item>
<item>192.170.0.0/15</item>
<item>192.172.0.0/14</item>
<item>192.176.0.0/12</item>
<item>192.192.0.0/10</item>
<item>193.0.0.0/8</item>
<item>194.0.0.0/7</item>
<item>196.0.0.0/7</item>
<item>198.0.0.0/12</item>
<item>198.16.0.0/15</item>
<item>198.20.0.0/14</item>
<item>198.24.0.0/13</item>
<item>198.32.0.0/12</item>
<item>198.48.0.0/15</item>
<item>198.50.0.0/16</item>
<item>198.51.0.0/18</item>
<item>198.51.64.0/19</item>
<item>198.51.96.0/22</item>
<item>198.51.101.0/24</item>
<item>198.51.102.0/23</item>
<item>198.51.104.0/21</item>
<item>198.51.112.0/20</item>
<item>198.51.128.0/17</item>
<item>198.52.0.0/14</item>
<item>198.56.0.0/13</item>
<item>198.64.0.0/10</item>
<item>198.128.0.0/9</item>
<item>199.0.0.0/8</item>
<item>200.0.0.0/7</item>
<item>202.0.0.0/8</item>
<item>203.0.0.0/18</item>
<item>203.0.64.0/19</item>
<item>203.0.96.0/20</item>
<item>203.0.112.0/24</item>
<item>203.0.114.0/23</item>
<item>203.0.116.0/22</item>
<item>203.0.120.0/21</item>
<item>203.0.128.0/17</item>
<item>203.1.0.0/16</item>
<item>203.2.0.0/15</item>
<item>203.4.0.0/14</item>
<item>203.8.0.0/13</item>
<item>203.16.0.0/12</item>
<item>203.32.0.0/11</item>
<item>203.64.0.0/10</item>
<item>203.128.0.0/9</item>
<item>204.0.0.0/6</item>
<item>208.0.0.0/4</item>
</string-array>
<string-array name="chn_route_full">
<item>10.0.0.0/8</item>
<item>172.16.0.0/12</item>
<item>192.168.0.0/16</item>
<item>1.0.1.0/24</item> <item>1.0.1.0/24</item>
<item>1.0.2.0/23</item> <item>1.0.2.0/23</item>
<item>1.0.8.0/21</item> <item>1.0.8.0/21</item>
@@ -3843,9 +3999,8 @@
<item>223.255.252.0/23</item> <item>223.255.252.0/23</item>
</string-array> </string-array>
<string-array name="chn_list"> <string-array name="chn_route">
<item>0.0.0.0/7</item> <item>0.0.0.0/7</item>
<item>10.0.0.0/8</item>
<item>14.0.0.0/8</item> <item>14.0.0.0/8</item>
<item>27.0.0.0/8</item> <item>27.0.0.0/8</item>
<item>36.0.0.0/8</item> <item>36.0.0.0/8</item>
@@ -3890,7 +4045,7 @@
<item>220.0.0.0/6</item> <item>220.0.0.0/6</item>
</string-array> </string-array>
<string-array name="gfw_list"> <string-array name="gfw_route">
<item>1.0.0.0/23</item> <item>1.0.0.0/23</item>
<item>1.0.4.0/22</item> <item>1.0.4.0/22</item>
<item>1.0.16.0/20</item> <item>1.0.16.0/20</item>
@@ -8380,7 +8535,7 @@
<item>223.255.254.0/23</item> <item>223.255.254.0/23</item>
</string-array> </string-array>
<string-array name="simple_list"> <string-array name="simple_route">
<item>1.0.0.0/15</item> <item>1.0.0.0/15</item>
<item>1.2.0.0/16</item> <item>1.2.0.0/16</item>
<item>1.4.0.0/14</item> <item>1.4.0.0/14</item>
+6 -6
View File
@@ -32,13 +32,13 @@
<string name="auto_set_gfwlist">CHN Route</string> <string name="auto_set_gfwlist">CHN Route</string>
<string name="auto_set_gfwlist_summary">Bypass all sites located in China <string name="auto_set_gfwlist_summary">Bypass all sites located in China
</string> </string>
<string name="route_list">Route</string>
<string name="route_list_summary">Bypass IP addresses in the route list</string>
<string name="auto_set_proxy">Global Proxy</string> <string name="auto_set_proxy">Global Proxy</string>
<string name="auto_set_proxy_summary">Set up system-wide proxy <string name="auto_set_proxy_summary">Set up system-wide proxy</string>
</string> <string name="proxied_apps">Per-App Proxy</string>
<string name="proxied_apps">Individual Proxy</string> <string name="proxied_apps_summary">Set proxy for selected apps</string>
<string name="proxied_apps_summary">Set individual proxy for apps <string name="proxied_help">Per-App Proxy</string>
</string>
<string name="proxied_help">Individual Proxy</string>
<string name="bypass_apps">Bypass Mode</string> <string name="bypass_apps">Bypass Mode</string>
<string name="bypass_apps_summary">Enable this option to bypass selected apps</string> <string name="bypass_apps_summary">Enable this option to bypass selected apps</string>
<string name="auto_connect">Auto Connect</string> <string name="auto_connect">Auto Connect</string>
+8 -6
View File
@@ -48,12 +48,14 @@
<PreferenceCategory <PreferenceCategory
android:title="@string/feature_cat"> android:title="@string/feature_cat">
<CheckBoxPreference <com.github.shadowsocks.preferences.SummaryListPreference
android:defaultValue="true" android:defaultValue="all"
android:key="isGFWList" android:key="route"
android:summary="@string/auto_set_gfwlist_summary" android:entries="@array/route_entry"
android:title="@string/auto_set_gfwlist"> android:entryValues="@array/route_value"
</CheckBoxPreference> android:summary="@string/route_list_summary"
android:title="@string/route_list">
</com.github.shadowsocks.preferences.SummaryListPreference>
<CheckBoxPreference <CheckBoxPreference
android:defaultValue="true" android:defaultValue="true"
android:key="isGlobalProxy" android:key="isGlobalProxy"
@@ -120,15 +120,19 @@ object Shadowsocks {
val PREFS_NAME = "Shadowsocks" val PREFS_NAME = "Shadowsocks"
val PROXY_PREFS = Array(Key.profileName, Key.proxy, Key.remotePort, Key.localPort, Key.sitekey, val PROXY_PREFS = Array(Key.profileName, Key.proxy, Key.remotePort, Key.localPort, Key.sitekey,
Key.encMethod) Key.encMethod)
val FEATRUE_PREFS = Array(Key.isGFWList, Key.isGlobalProxy, Key.proxyedApps, val FEATRUE_PREFS = Array(Key.route, Key.isGlobalProxy, Key.proxyedApps,
Key.isUdpDns, Key.isAutoConnect) Key.isUdpDns, Key.isAutoConnect)
val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.IPTABLES) val EXECUTABLES = Array(Executable.PDNSD, Executable.REDSOCKS, Executable.IPTABLES)
// Helper functions // Helper functions
def updateListPreference(pref: Preference, value: String) { def updateListPreference(pref: Preference, value: String) {
pref.setSummary(value)
pref.asInstanceOf[ListPreference].setValue(value) pref.asInstanceOf[ListPreference].setValue(value)
val entry = pref.asInstanceOf[ListPreference].getEntry
if (entry != null)
pref.setSummary(entry)
else
pref.setSummary(value)
} }
def updatePasswordEditTextPreference(pref: Preference, value: String) { def updatePasswordEditTextPreference(pref: Preference, value: String) {
@@ -158,7 +162,7 @@ object Shadowsocks {
case Key.localPort => updateSummaryEditTextPreference(pref, profile.localPort.toString) case Key.localPort => updateSummaryEditTextPreference(pref, profile.localPort.toString)
case Key.sitekey => updatePasswordEditTextPreference(pref, profile.password) case Key.sitekey => updatePasswordEditTextPreference(pref, profile.password)
case Key.encMethod => updateListPreference(pref, profile.method) case Key.encMethod => updateListPreference(pref, profile.method)
case Key.isGFWList => updateCheckBoxPreference(pref, profile.chnroute) case Key.route => updateListPreference(pref, profile.route)
case Key.isGlobalProxy => updateCheckBoxPreference(pref, profile.global) case Key.isGlobalProxy => updateCheckBoxPreference(pref, profile.global)
case Key.isUdpDns => updateCheckBoxPreference(pref, profile.udpdns) case Key.isUdpDns => updateCheckBoxPreference(pref, profile.udpdns)
case _ => case _ =>
@@ -334,10 +338,11 @@ class Shadowsocks
Console.runCommand(ab.toArray) Console.runCommand(ab.toArray)
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (!Utils.isLollipopOrAbove) {
ab.clear() ab.clear()
ab.append("kill -9 `cat /data/data/com.github.shadowsocks/redsocks.pid`") ab.append("kill -9 `cat /data/data/com.github.shadowsocks/redsocks.pid`")
ab.append("rm /data/data/com.github.shadowsocks/redsocks.conf") ab.append("rm /data/data/com.github.shadowsocks/redsocks.conf")
ab.append("rm /data/data/com.github.shadowsocks/redsocks.pid")
ab.append(Utils.getIptables + " -t nat -F OUTPUT") ab.append(Utils.getIptables + " -t nat -F OUTPUT")
Console.runRootCommand(ab.toArray) Console.runRootCommand(ab.toArray)
@@ -497,7 +502,7 @@ class Shadowsocks
// Bind to the service // Bind to the service
spawn { spawn {
val isRoot = Build.VERSION.SDK_INT != Build.VERSION_CODES.LOLLIPOP && Console.isRoot val isRoot = !Utils.isLollipopOrAbove && Console.isRoot
handler.post(new Runnable { handler.post(new Runnable {
override def run() { override def run() {
status.edit.putBoolean(Key.isRoot, isRoot).commit() status.edit.putBoolean(Key.isRoot, isRoot).commit()
@@ -767,7 +772,7 @@ class Shadowsocks
if (pref != null) { if (pref != null) {
if (Seq(Key.isGlobalProxy, Key.proxyedApps) if (Seq(Key.isGlobalProxy, Key.proxyedApps)
.contains(name)) { .contains(name)) {
pref.setEnabled(enabled && (!isVpnEnabled || Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP)) pref.setEnabled(enabled && (Utils.isLollipopOrAbove || !isVpnEnabled))
} else { } else {
pref.setEnabled(enabled) pref.setEnabled(enabled)
} }
@@ -875,8 +880,7 @@ class Shadowsocks
def isVpnEnabled: Boolean = { def isVpnEnabled: Boolean = {
if (vpnEnabled < 0) { if (vpnEnabled < 0) {
vpnEnabled = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP vpnEnabled = if (!status.getBoolean(Key.isRoot, false)) {
|| !status.getBoolean(Key.isRoot, false)) {
1 1
} else { } else {
0 0
@@ -63,7 +63,6 @@ class ShadowsocksNatService extends Service with BaseService {
val TAG = "ShadowsocksNatService" val TAG = "ShadowsocksNatService"
val CMD_IPTABLES_RETURN = " -t nat -A OUTPUT -p tcp -d 0.0.0.0 -j RETURN" val CMD_IPTABLES_RETURN = " -t nat -A OUTPUT -p tcp -d 0.0.0.0 -j RETURN"
val CMD_IPTABLES_REDIRECT_ADD_SOCKS = " -t nat -A OUTPUT -p tcp " + "-j REDIRECT --to 8123"
val CMD_IPTABLES_DNAT_ADD_SOCKS = " -t nat -A OUTPUT -p tcp " + val CMD_IPTABLES_DNAT_ADD_SOCKS = " -t nat -A OUTPUT -p tcp " +
"-j DNAT --to-destination 127.0.0.1:8123" "-j DNAT --to-destination 127.0.0.1:8123"
val DNS_PORT = 8153 val DNS_PORT = 8153
@@ -75,7 +74,6 @@ class ShadowsocksNatService extends Service with BaseService {
var receiver: BroadcastReceiver = null var receiver: BroadcastReceiver = null
var notificationManager: NotificationManager = null var notificationManager: NotificationManager = null
var config: Config = null var config: Config = null
var hasRedirectSupport = false
var apps: Array[ProxiedApp] = null var apps: Array[ProxiedApp] = null
val myUid = Process.myUid() val myUid = Process.myUid()
@@ -93,19 +91,14 @@ class ShadowsocksNatService extends Service with BaseService {
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication] private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
def isACLEnabled: Boolean = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
true
} else {
false
}
}
def startShadowsocksDaemon() { def startShadowsocksDaemon() {
if (isACLEnabled && config.isGFWList) { if (config.route != Route.ALL) {
val chn_list: Array[String] = getResources.getStringArray(R.array.chn_list_full) val acl: Array[String] = config.route match {
ConfigUtils.printToFile(new File(Path.BASE + "chn.acl"))(p => { case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
chn_list.foreach(item => p.println(item)) case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
}
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
acl.foreach(item => p.println(item))
}) })
} }
@@ -117,11 +110,11 @@ class ShadowsocksNatService extends Service with BaseService {
, "-l" , config.localPort.toString , "-l" , config.localPort.toString
, "-k" , config.sitekey , "-k" , config.sitekey
, "-m" , config.encMethod , "-m" , config.encMethod
, "-f" , (Path.BASE + "ss-local.pid")) , "-f" , Path.BASE + "ss-local.pid")
if (config.isGFWList && isACLEnabled) { if (config.route != Route.ALL) {
cmd += "--acl" cmd += "--acl"
cmd += (Path.BASE + "chn.acl") cmd += (Path.BASE + "acl.list")
} }
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
@@ -140,22 +133,31 @@ class ShadowsocksNatService extends Service with BaseService {
, "-p" , config.remotePort.toString , "-p" , config.remotePort.toString
, "-k" , config.sitekey , "-k" , config.sitekey
, "-m" , config.encMethod , "-m" , config.encMethod
, "-f" , (Path.BASE + "ss-tunnel.pid")) , "-f" , Path.BASE + "ss-tunnel.pid")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Core.sstunnel(cmd.toArray) Core.sstunnel(cmd.toArray)
} else { } else {
val conf = { val cmdBuf = new ArrayBuffer[String]
ConfigUtils.PDNSD.format("127.0.0.1") cmdBuf += ("ss-tunnel"
} , "-b", "127.0.0.1"
, "-l", "8163"
, "-L", "8.8.8.8:53"
, "-s", config.proxy
, "-p", config.remotePort.toString
, "-k", config.sitekey
, "-m", config.encMethod
, "-f", Path.BASE + "ss-tunnel.pid")
if (BuildConfig.DEBUG) Log.d(TAG, cmdBuf.mkString(" "))
Core.sstunnel(cmdBuf.toArray)
val conf = ConfigUtils
.PDNSD_BYPASS.format("127.0.0.1", getString(R.string.exclude), 8163)
ConfigUtils.printToFile(new File(Path.BASE + "pdnsd.conf"))(p => { ConfigUtils.printToFile(new File(Path.BASE + "pdnsd.conf"))(p => {
p.println(conf) p.println(conf)
}) })
val cmd = Path.BASE + "pdnsd -c " + Path.BASE + "pdnsd.conf"
val args = "pdnsd -c " + Path.BASE + "pdnsd.conf"
val cmd = Path.BASE + args
if (BuildConfig.DEBUG) Log.d(TAG, cmd) if (BuildConfig.DEBUG) Log.d(TAG, cmd)
Console.runRootCommand(cmd) Core.pdnsd(cmd.split(" "))
} }
} }
@@ -179,7 +181,7 @@ class ShadowsocksNatService extends Service with BaseService {
p.println(conf) p.println(conf)
}) })
val cmd = Path.BASE + args val cmd = Path.BASE + args
Console.runRootCommand(cmd) Console.runCommand(cmd)
} }
/** Called when the activity is first created. */ /** Called when the activity is first created. */
@@ -213,14 +215,13 @@ class ShadowsocksNatService extends Service with BaseService {
val actionIntent = PendingIntent.getBroadcast(this, 0, closeIntent, 0) val actionIntent = PendingIntent.getBroadcast(this, 0, closeIntent, 0)
val builder = new NotificationCompat.Builder(this) val builder = new NotificationCompat.Builder(this)
val icon = getResources.getDrawable(R.drawable.ic_stat_shadowsocks)
builder builder
.setWhen(0) .setWhen(0)
.setTicker(title) .setTicker(title)
.setContentTitle(getString(R.string.app_name)) .setContentTitle(getString(R.string.app_name))
.setContentText(info) .setContentText(info)
.setContentIntent(contentIntent) .setContentIntent(contentIntent)
.setSmallIcon(R.drawable.ic_stat_shadowsocks)
.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)
@@ -299,31 +300,10 @@ class ShadowsocksNatService extends Service with BaseService {
init_sb.append(cmd_bypass.replace("0.0.0.0", "127.0.0.1")) init_sb.append(cmd_bypass.replace("0.0.0.0", "127.0.0.1"))
init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "-m owner --uid-owner " + myUid)) init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "-m owner --uid-owner " + myUid))
if (config.isGFWList) { init_sb.append(Utils.getIptables
if (!isACLEnabled) + " -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:" + DNS_PORT)
{
val chn_list: Array[String] = getResources.getStringArray(R.array.chn_list)
for (item <- chn_list) {
init_sb.append(cmd_bypass.replace("0.0.0.0", item))
}
}
}
if (hasRedirectSupport) {
init_sb
.append(Utils.getIptables + " -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to "
+ DNS_PORT)
} else {
init_sb
.append(Utils.getIptables
+ " -t nat -A OUTPUT -p udp --dport 53 -j DNAT --to-destination 127.0.0.1:"
+ DNS_PORT)
}
if (config.isGlobalProxy || config.isBypassApps) { if (config.isGlobalProxy || config.isBypassApps) {
http_sb.append(if (hasRedirectSupport) { http_sb.append(Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS)
Utils.getIptables + CMD_IPTABLES_REDIRECT_ADD_SOCKS
} else {
Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS
})
} }
if (!config.isGlobalProxy) { if (!config.isGlobalProxy) {
if (apps == null || apps.length <= 0) { if (apps == null || apps.length <= 0) {
@@ -337,11 +317,7 @@ class ShadowsocksNatService extends Service with BaseService {
} }
for (uid <- uidSet) { for (uid <- uidSet) {
if (!config.isBypassApps) { if (!config.isBypassApps) {
http_sb.append((if (hasRedirectSupport) { http_sb.append((Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS).replace("-t nat", "-t nat -m owner --uid-owner " + uid))
Utils.getIptables + CMD_IPTABLES_REDIRECT_ADD_SOCKS
} else {
Utils.getIptables + CMD_IPTABLES_DNAT_ADD_SOCKS
}).replace("-t nat", "-t nat -m owner --uid-owner " + uid))
} else { } else {
init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "-m owner --uid-owner " + uid)) init_sb.append(cmd_bypass.replace("-d 0.0.0.0", "-m owner --uid-owner " + uid))
} }
@@ -445,8 +421,6 @@ class ShadowsocksNatService extends Service with BaseService {
resolved = true resolved = true
} }
hasRedirectSupport = Utils.getHasRedirectSupport
if (resolved && handleConnection) { if (resolved && handleConnection) {
notifyForegroundAlert(getString(R.string.forward_success), notifyForegroundAlert(getString(R.string.forward_success),
getString(R.string.service_running).format(config.profileName)) getString(R.string.service_running).format(config.profileName))
@@ -72,8 +72,7 @@ class ShadowsocksRunnerActivity extends Activity {
def isVpnEnabled: Boolean = { def isVpnEnabled: Boolean = {
if (vpnEnabled < 0) { if (vpnEnabled < 0) {
vpnEnabled = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP vpnEnabled = if (Utils.isLollipopOrAbove || !Console.isRoot) {
|| !Console.isRoot) {
1 1
} else { } else {
0 0
@@ -64,7 +64,6 @@ class ShadowsocksVpnService extends VpnService with BaseService {
val TAG = "ShadowsocksVpnService" val TAG = "ShadowsocksVpnService"
val VPN_MTU = 1500 val VPN_MTU = 1500
val PRIVATE_VLAN = "26.26.26.%s" val PRIVATE_VLAN = "26.26.26.%s"
var conn: ParcelFileDescriptor = null var conn: ParcelFileDescriptor = null
@@ -75,41 +74,52 @@ class ShadowsocksVpnService extends VpnService with BaseService {
private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication] private lazy val application = getApplication.asInstanceOf[ShadowsocksApplication]
def isLollipopOrAbove: Boolean = { def isByass(net: SubnetUtils): Boolean = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { val info = net.getInfo
info.isInRange(config.proxy)
}
def isPrivateA(a: Int): Boolean = {
if (a == 10 || a == 192 || a == 172) {
true true
} else { } else {
false false
} }
} }
def isByass(net: SubnetUtils): Boolean = { def isPrivateB(a: Int, b: Int): Boolean = {
val info = net.getInfo if (a == 10 || (a == 192 && b == 168) || (a == 172 && b >= 16 && b < 32)) {
info.isInRange(config.proxy) true
} else {
false
}
} }
def startShadowsocksDaemon() { def startShadowsocksDaemon() {
if (isLollipopOrAbove && config.isGFWList) { if (Utils.isLollipopOrAbove && config.route != Route.ALL) {
val chn_list: Array[String] = getResources.getStringArray(R.array.chn_list_full) val acl: Array[String] = config.route match {
ConfigUtils.printToFile(new File(Path.BASE + "chn.acl"))(p => { case Route.BYPASS_LAN => getResources.getStringArray(R.array.private_route)
chn_list.foreach(item => p.println(item)) case Route.BYPASS_CHN => getResources.getStringArray(R.array.chn_route_full)
}
ConfigUtils.printToFile(new File(Path.BASE + "acl.list"))(p => {
acl.foreach(item => p.println(item))
}) })
} }
val cmd = new ArrayBuffer[String] val cmd = new ArrayBuffer[String]
cmd += ("ss-local" , "-u" cmd +=("ss-local", "-u"
, "-b" , "127.0.0.1" , "-b", "127.0.0.1"
, "-s" , config.proxy , "-s", config.proxy
, "-p" , config.remotePort.toString , "-p", config.remotePort.toString
, "-l" , config.localPort.toString , "-l", config.localPort.toString
, "-k" , config.sitekey , "-k", config.sitekey
, "-m" , config.encMethod , "-m", config.encMethod
, "-f" , Path.BASE + "ss-local.pid") , "-f", Path.BASE + "ss-local.pid")
if (config.isGFWList && isLollipopOrAbove) { if (Utils.isLollipopOrAbove && config.route != Route.ALL) {
cmd += "--acl" cmd += "--acl"
cmd += (Path.BASE + "chn.acl") cmd += (Path.BASE + "acl.list")
} }
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
@@ -118,22 +128,22 @@ class ShadowsocksVpnService extends VpnService with BaseService {
def startDnsTunnel() = { def startDnsTunnel() = {
val cmd = new ArrayBuffer[String] val cmd = new ArrayBuffer[String]
cmd += ("ss-tunnel" cmd +=("ss-tunnel"
, "-b" , "127.0.0.1" , "-b", "127.0.0.1"
, "-l" , "8163" , "-l", "8163"
, "-L" , "8.8.8.8:53" , "-L", "8.8.8.8:53"
, "-s" , config.proxy , "-s", config.proxy
, "-p" , config.remotePort.toString , "-p", config.remotePort.toString
, "-k" , config.sitekey , "-k", config.sitekey
, "-m" , config.encMethod , "-m", config.encMethod
, "-f" , Path.BASE + "ss-tunnel.pid") , "-f", Path.BASE + "ss-tunnel.pid")
if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" ")) if (BuildConfig.DEBUG) Log.d(TAG, cmd.mkString(" "))
Core.sstunnel(cmd.toArray) Core.sstunnel(cmd.toArray)
} }
def startDnsDaemon() { def startDnsDaemon() {
val conf = { val conf = {
if (isLollipopOrAbove) { if (Utils.isLollipopOrAbove) {
ConfigUtils.PDNSD_BYPASS.format("0.0.0.0", getString(R.string.exclude), 8163) ConfigUtils.PDNSD_BYPASS.format("0.0.0.0", getString(R.string.exclude), 8163)
} else { } else {
ConfigUtils.PDNSD_LOCAL.format("0.0.0.0", 8163) ConfigUtils.PDNSD_LOCAL.format("0.0.0.0", 8163)
@@ -168,7 +178,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
.addAddress(PRIVATE_VLAN.format("1"), 24) .addAddress(PRIVATE_VLAN.format("1"), 24)
.addDnsServer("8.8.8.8") .addDnsServer("8.8.8.8")
if (isLollipopOrAbove) { if (Utils.isLollipopOrAbove) {
if (!config.isGlobalProxy) { if (!config.isGlobalProxy) {
val apps = AppManager.getProxiedApps(this, config.proxiedAppString) val apps = AppManager.getProxiedApps(this, config.proxiedAppString)
val pkgSet: mutable.HashSet[String] = new mutable.HashSet[String] val pkgSet: mutable.HashSet[String] = new mutable.HashSet[String]
@@ -195,48 +205,76 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (InetAddressUtils.isIPv6Address(config.proxy)) { if (InetAddressUtils.isIPv6Address(config.proxy)) {
builder.addRoute("0.0.0.0", 0) builder.addRoute("0.0.0.0", 0)
} else if (!isLollipopOrAbove && config.isGFWList) {
val gfwList = {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
getResources.getStringArray(R.array.simple_list)
} else {
getResources.getStringArray(R.array.gfw_list)
}
}
gfwList.foreach(cidr => {
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
}
})
} else { } else {
if (isLollipopOrAbove) { if (!Utils.isLollipopOrAbove) {
builder.addRoute("0.0.0.0", 0) config.route match {
} else { case Route.ALL =>
for (i <- 1 to 223) { for (i <- 1 to 223) {
if (i != 26 && i != 127) { if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0" val addr = i.toString + ".0.0.0"
val cidr = addr + "/8" val cidr = addr + "/8"
val net = new SubnetUtils(cidr) val net = new SubnetUtils(cidr)
if (!isByass(net)) { if (!isByass(net)) {
if (!InetAddress.getByName(addr).isSiteLocalAddress) { builder.addRoute(addr, 8)
builder.addRoute(addr, 8) } else {
} for (j <- 0 to 255) {
} else { val subAddr = i.toString + "." + j.toString + ".0.0"
for (j <- 0 to 255) { val subCidr = subAddr + "/16"
val subAddr = i.toString + "." + j.toString + ".0.0" val subNet = new SubnetUtils(subCidr)
val subCidr = subAddr + "/16" if (!isByass(subNet)) {
val subNet = new SubnetUtils(subCidr) builder.addRoute(subAddr, 16)
if (!isByass(subNet)) { }
if (!InetAddress.getByName(subAddr).isSiteLocalAddress) {
builder.addRoute(subAddr, 16)
} }
} }
} }
} }
} case Route.BYPASS_LAN =>
for (i <- 1 to 223) {
if (i != 26 && i != 127) {
val addr = i.toString + ".0.0.0"
val cidr = addr + "/8"
val net = new SubnetUtils(cidr)
if (!isByass(net) && !isPrivateA(i)) {
builder.addRoute(addr, 8)
} else {
for (j <- 0 to 255) {
val subAddr = i.toString + "." + j.toString + ".0.0"
val subCidr = subAddr + "/16"
val subNet = new SubnetUtils(subCidr)
if (!isByass(subNet) && !isPrivateB(i, j)) {
builder.addRoute(subAddr, 16)
}
}
}
}
}
case Route.BYPASS_CHN =>
val list = {
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
getResources.getStringArray(R.array.simple_route)
} else {
getResources.getStringArray(R.array.gfw_route)
}
}
list.foreach(cidr => {
val net = new SubnetUtils(cidr)
if (!isByass(net)) {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
}
})
}
} else {
if (config.route == Route.ALL) {
builder.addRoute("0.0.0.0", 0)
} else {
val privateList = getResources.getStringArray(R.array.bypass_private_route)
privateList.foreach(cidr => {
val addr = cidr.split('/')
builder.addRoute(addr(0), addr(1).toInt)
})
} }
} }
} }
@@ -436,6 +474,8 @@ class ShadowsocksVpnService extends VpnService with BaseService {
} }
override def getTag = TAG override def getTag = TAG
override def getServiceMode = Mode.VPN override def getServiceMode = Mode.VPN
override def getContext = getBaseContext override def getContext = getBaseContext
} }
@@ -51,7 +51,7 @@ object DBHelper {
} }
class DBHelper(val context: Context) class DBHelper(val context: Context)
extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 8) { extends OrmLiteSqliteOpenHelper(context, DBHelper.PROFILE, null, 9) {
lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile]) lazy val profileDao: Dao[Profile, Int] = getDao(classOf[Profile])
@@ -64,6 +64,9 @@ class DBHelper(val context: Context)
if (oldVersion != newVersion) { if (oldVersion != newVersion) {
if (oldVersion < 8) { if (oldVersion < 8) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;") profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN udpdns SMALLINT;")
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
} else if (oldVersion < 9) {
profileDao.executeRaw("ALTER TABLE `profile` ADD COLUMN route VARCHAR;")
} else { } else {
profileDao.executeRaw("DROP TABLE IF EXISTS 'profile';") profileDao.executeRaw("DROP TABLE IF EXISTS 'profile';")
onCreate(database, connectionSource) onCreate(database, connectionSource)
@@ -52,20 +52,23 @@ class Profile {
var host: String = "" var host: String = ""
@DatabaseField @DatabaseField
var localPort: Int = 0 var localPort: Int = 1080
@DatabaseField @DatabaseField
var remotePort: Int = 0 var remotePort: Int = 8338
@DatabaseField @DatabaseField
var password: String = "" var password: String = ""
@DatabaseField @DatabaseField
var method: String = "" var method: String = "rc4"
@DatabaseField @DatabaseField
var date: String = "" var date: String = ""
@DatabaseField
var route: String = "all"
@DatabaseField @DatabaseField
var upload: Int = 0 var upload: Int = 0
@@ -77,7 +77,7 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
} catch { } catch {
case ex: Exception => case ex: Exception =>
Log.e(Shadowsocks.TAG, "getProfile", ex) Log.e(Shadowsocks.TAG, "getProfile", ex)
return None None
} }
} }
@@ -130,6 +130,7 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
edit.putString(Key.localPort, profile.localPort.toString) edit.putString(Key.localPort, profile.localPort.toString)
edit.putString(Key.proxied, profile.individual) edit.putString(Key.proxied, profile.individual)
edit.putInt(Key.profileId, profile.id) edit.putInt(Key.profileId, profile.id)
edit.putString(Key.route, profile.route)
edit.commit() edit.commit()
profile profile
@@ -149,19 +150,18 @@ class ProfileManager(settings: SharedPreferences, dbHelper: DBHelper) {
profile.host = settings.getString(Key.proxy, "127.0.0.1") profile.host = settings.getString(Key.proxy, "127.0.0.1")
profile.password = settings.getString(Key.sitekey, "default") profile.password = settings.getString(Key.sitekey, "default")
profile.method = settings.getString(Key.encMethod, "table") profile.method = settings.getString(Key.encMethod, "table")
profile.route = settings.getString(Key.route, "all")
profile.remotePort = try { profile.remotePort = try {
Integer.valueOf(settings.getString(Key.remotePort, "1984")) Integer.valueOf(settings.getString(Key.remotePort, "1984"))
} catch { } catch {
case ex: NumberFormatException => { case ex: NumberFormatException =>
1984 1984
}
} }
profile.localPort = try { profile.localPort = try {
Integer.valueOf(settings.getString(Key.localPort, "1984")) Integer.valueOf(settings.getString(Key.localPort, "1984"))
} catch { } catch {
case ex: NumberFormatException => { case ex: NumberFormatException =>
1984 1984
}
} }
profile.individual = settings.getString(Key.proxied, "") profile.individual = settings.getString(Key.proxied, "")
@@ -48,7 +48,11 @@ class SummaryListPreference(context: Context, attrs: AttributeSet)
override def setValue(text: String) { override def setValue(text: String) {
super.setValue(text) super.setValue(text)
setSummary(text.toUpperCase) val entry = getEntry
if (entry != null)
setSummary(entry)
else
setSummary(text)
} }
override def setSummary(summary: CharSequence) { override def setSummary(summary: CharSequence) {
@@ -198,7 +198,7 @@ object ConfigUtils {
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.isUdpDns, config.profileName, host, password, method, config.proxiedAppString, port, config.isUdpDns, config.profileName, host, password, method, config.proxiedAppString, config.route, port,
config.localPort) config.localPort)
} }
@@ -213,6 +213,8 @@ object ConfigUtils {
val proxy = settings.getString(Key.proxy, "127.0.0.1") val proxy = settings.getString(Key.proxy, "127.0.0.1")
val sitekey = settings.getString(Key.sitekey, "default") val sitekey = settings.getString(Key.sitekey, "default")
val encMethod = settings.getString(Key.encMethod, "table") val encMethod = settings.getString(Key.encMethod, "table")
val route = settings.getString(Key.route, "all")
val remotePort: Int = try { val remotePort: Int = try {
settings.getString(Key.remotePort, "1984").toInt settings.getString(Key.remotePort, "1984").toInt
} catch { } catch {
@@ -228,6 +230,6 @@ object ConfigUtils {
val proxiedAppString = settings.getString(Key.proxied, "") val proxiedAppString = settings.getString(Key.proxied, "")
new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, isUdpDns, profileName, proxy, new Config(isGlobalProxy, isGFWList, isBypassApps, isTrafficStat, isUdpDns, profileName, proxy,
sitekey, encMethod, proxiedAppString, remotePort, localPort) sitekey, encMethod, proxiedAppString, route, remotePort, localPort)
} }
} }
@@ -68,6 +68,7 @@ object Key {
val isRoot = "isRoot" val isRoot = "isRoot"
val status = "status" val status = "status"
val proxyedApps = "proxyedApps" val proxyedApps = "proxyedApps"
val route = "route"
val isRunning = "isRunning" val isRunning = "isRunning"
val isAutoConnect = "isAutoConnect" val isAutoConnect = "isAutoConnect"
@@ -110,3 +111,9 @@ object Action {
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"
} }
object Route {
val ALL = "all"
val BYPASS_LAN = "bypass-lan"
val BYPASS_CHN = "bypass-china"
}
@@ -80,6 +80,14 @@ object Utils {
var data_path: String = null var data_path: String = null
var rootTries = 0 var rootTries = 0
def isLollipopOrAbove: Boolean = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
true
} else {
false
}
}
def getSignature(context: Context): String = { def getSignature(context: Context): String = {
val info = context val info = context
.getPackageManager .getPackageManager