Skip to content

Commit cb08d9d

Browse files
committed
DaedalusVpnService: listen network change and update upstream DNS
1 parent 000706a commit cb08d9d

File tree

10 files changed

+123
-87
lines changed

10 files changed

+123
-87
lines changed

app/src/main/java/org/itxtech/daedalus/Daedalus.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616
import com.google.gson.JsonParseException;
1717
import com.google.gson.stream.JsonReader;
1818
import org.itxtech.daedalus.activity.MainActivity;
19+
import org.itxtech.daedalus.server.AbstractDnsServer;
1920
import org.itxtech.daedalus.server.DnsServer;
2021
import org.itxtech.daedalus.server.DnsServerHelper;
2122
import org.itxtech.daedalus.service.DaedalusVpnService;
22-
import org.itxtech.daedalus.util.*;
23+
import org.itxtech.daedalus.util.Configurations;
24+
import org.itxtech.daedalus.util.Logger;
25+
import org.itxtech.daedalus.util.Rule;
26+
import org.itxtech.daedalus.util.RuleResolver;
2327

2428
import java.io.File;
2529
import java.util.ArrayList;
@@ -206,19 +210,8 @@ public static boolean prepareAndActivateService(Context context) {
206210
}
207211

208212
public static void activateService(Context context) {
209-
DaedalusVpnService.primaryServer = DnsServerHelper.getServerById(DnsServerHelper.getPrimary());
210-
DaedalusVpnService.secondaryServer = DnsServerHelper.getServerById(DnsServerHelper.getSecondary());
211-
if (getPrefs().getBoolean("settings_use_system_dns", false)) {
212-
String[] servers = DnsServersDetector.getServers(context);
213-
if (servers != null) {
214-
if (servers.length >= 2) {
215-
DaedalusVpnService.primaryServer = new DnsServer(servers[0], 0);
216-
DaedalusVpnService.secondaryServer = new DnsServer(servers[1], 0);
217-
} else {
218-
DaedalusVpnService.primaryServer = DaedalusVpnService.secondaryServer = new DnsServer(servers[0]);
219-
}
220-
}
221-
}
213+
DaedalusVpnService.primaryServer = (AbstractDnsServer) DnsServerHelper.getServerById(DnsServerHelper.getPrimary()).clone();
214+
DaedalusVpnService.secondaryServer = (AbstractDnsServer) DnsServerHelper.getServerById(DnsServerHelper.getSecondary()).clone();
222215
if (getInstance().prefs.getBoolean("settings_foreground", false)
223216
&& Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
224217
Logger.info("Starting foreground service");

app/src/main/java/org/itxtech/daedalus/fragment/GlobalConfigFragment.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
3939
add("secondary_server");
4040
}}) {
4141
ListPreference listPref = findPreference(k);
42-
listPref.setVisible(visible);
4342
listPref.setEntries(DnsServerHelper.getNames(Daedalus.getInstance()));
4443
listPref.setEntryValues(DnsServerHelper.getIds());
4544
listPref.setSummary(DnsServerHelper.getDescription(listPref.getValue(), Daedalus.getInstance()));
@@ -110,13 +109,6 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
110109

111110
updateOptions(advanced.isChecked(), "settings_advanced");
112111
updateOptions(appFilter.isChecked(), "settings_app_filter");
113-
114-
findPreference("settings_use_system_dns").setOnPreferenceChangeListener((preference, newValue) -> {
115-
boolean vis = !(boolean) newValue;
116-
findPreference("primary_server").setVisible(vis);
117-
findPreference("secondary_server").setVisible(vis);
118-
return true;
119-
});
120112
}
121113

122114
private void updateOptions(boolean checked, String pref) {

app/src/main/java/org/itxtech/daedalus/server/AbstractDnsServer.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.itxtech.daedalus.server;
22

3+
import androidx.annotation.NonNull;
4+
35
/**
46
* Daedalus Project
57
*
@@ -11,7 +13,7 @@
1113
* the Free Software Foundation, either version 3 of the License, or
1214
* (at your option) any later version.
1315
*/
14-
public class AbstractDnsServer {
16+
public class AbstractDnsServer implements Cloneable {
1517
public static final int DNS_SERVER_DEFAULT_PORT = 53;
1618

1719
protected String address;
@@ -63,4 +65,14 @@ public String getRealName() {
6365
public boolean isHttpsServer() {
6466
return address.contains("/");
6567
}
68+
69+
@NonNull
70+
@Override
71+
public Object clone() {
72+
try {
73+
return super.clone();
74+
} catch (Exception ignored) {
75+
}
76+
return new AbstractDnsServer("", 0);
77+
}
6678
}

app/src/main/java/org/itxtech/daedalus/service/DaedalusVpnService.java

Lines changed: 81 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,31 @@
44
import android.app.NotificationChannel;
55
import android.app.NotificationManager;
66
import android.app.PendingIntent;
7+
import android.content.BroadcastReceiver;
78
import android.content.Context;
89
import android.content.Intent;
10+
import android.content.IntentFilter;
911
import android.content.pm.PackageManager;
12+
import android.net.ConnectivityManager;
1013
import android.net.VpnService;
1114
import android.os.Build;
1215
import android.os.ParcelFileDescriptor;
1316
import android.system.OsConstants;
1417
import android.util.Log;
18+
import androidx.appcompat.app.AlertDialog;
1519
import androidx.core.app.NotificationCompat;
1620
import org.itxtech.daedalus.Daedalus;
1721
import org.itxtech.daedalus.R;
1822
import org.itxtech.daedalus.activity.MainActivity;
1923
import org.itxtech.daedalus.provider.Provider;
2024
import org.itxtech.daedalus.provider.ProviderPicker;
2125
import org.itxtech.daedalus.receiver.StatusBarBroadcastReceiver;
22-
import org.itxtech.daedalus.util.Logger;
23-
import org.itxtech.daedalus.util.RuleResolver;
2426
import org.itxtech.daedalus.server.AbstractDnsServer;
27+
import org.itxtech.daedalus.server.DnsServer;
2528
import org.itxtech.daedalus.server.DnsServerHelper;
29+
import org.itxtech.daedalus.util.DnsServersDetector;
30+
import org.itxtech.daedalus.util.Logger;
31+
import org.itxtech.daedalus.util.RuleResolver;
2632

2733
import java.net.Inet4Address;
2834
import java.net.Inet6Address;
@@ -54,20 +60,19 @@ public class DaedalusVpnService extends VpnService implements Runnable {
5460

5561
public static AbstractDnsServer primaryServer;
5662
public static AbstractDnsServer secondaryServer;
63+
private static InetAddress aliasPrimary;
64+
private static InetAddress aliasSecondary;
5765

5866
private NotificationCompat.Builder notification = null;
59-
6067
private boolean running = false;
6168
private long lastUpdate = 0;
6269
private boolean statisticQuery;
6370
private Provider provider;
6471
private ParcelFileDescriptor descriptor;
65-
6672
private Thread mThread = null;
67-
6873
public HashMap<String, AbstractDnsServer> dnsServers;
69-
7074
private static boolean activated = false;
75+
private static BroadcastReceiver receiver;
7176

7277
public static boolean isActivated() {
7378
return activated;
@@ -76,6 +81,44 @@ public static boolean isActivated() {
7681
@Override
7782
public void onCreate() {
7883
super.onCreate();
84+
if (Daedalus.getPrefs().getBoolean("settings_use_system_dns", false)) {
85+
registerReceiver(receiver = new BroadcastReceiver() {
86+
@Override
87+
public void onReceive(Context context, Intent intent) {
88+
updateUpstreamServers(context);
89+
}
90+
}, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
91+
}
92+
}
93+
94+
public static void updateUpstreamServers(Context context) {
95+
String[] servers = DnsServersDetector.getServers(context);
96+
if (servers != null) {
97+
if (servers.length >= 2 && (aliasPrimary == null || !aliasPrimary.getHostAddress().equals(servers[0])) &&
98+
(aliasSecondary == null || !aliasSecondary.getHostAddress().equals(servers[0])) &&
99+
(aliasPrimary == null || !aliasPrimary.getHostAddress().equals(servers[1])) &&
100+
(aliasSecondary == null || !aliasSecondary.getHostAddress().equals(servers[1]))) {
101+
primaryServer.setAddress(servers[0]);
102+
primaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT);
103+
secondaryServer.setAddress(servers[1]);
104+
secondaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT);
105+
} else if ((aliasPrimary == null || !aliasPrimary.getHostAddress().equals(servers[0])) &&
106+
(aliasSecondary == null || !aliasSecondary.getHostAddress().equals(servers[0]))) {
107+
primaryServer.setAddress(servers[0]);
108+
primaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT);
109+
secondaryServer.setAddress(servers[0]);
110+
secondaryServer.setPort(DnsServer.DNS_SERVER_DEFAULT_PORT);
111+
} else {
112+
StringBuilder buf = new StringBuilder();
113+
for (String server : servers) {
114+
buf.append(server).append(" ");
115+
}
116+
Logger.error("Invalid upstream DNS " + buf);
117+
}
118+
Logger.info("Upstream DNS updated: " + primaryServer.getAddress() + " " + secondaryServer.getAddress());
119+
} else {
120+
Logger.error("Cannot obtain upstream DNS server!");
121+
}
79122
}
80123

81124
@Override
@@ -85,7 +128,6 @@ public int onStartCommand(Intent intent, int flags, int startId) {
85128
case ACTION_ACTIVATE:
86129
activated = true;
87130
if (Daedalus.getPrefs().getBoolean("settings_notification", true)) {
88-
89131
NotificationManager manager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
90132

91133
NotificationCompat.Builder builder;
@@ -127,12 +169,7 @@ public int onStartCommand(Intent intent, int flags, int startId) {
127169
}
128170

129171
Daedalus.initRuleResolver();
130-
131-
if (this.mThread == null) {
132-
this.mThread = new Thread(this, "DaedalusVpn");
133-
this.running = true;
134-
this.mThread.start();
135-
}
172+
startThread();
136173
Daedalus.updateShortcut(getApplicationContext());
137174
if (MainActivity.getInstance() != null) {
138175
MainActivity.getInstance().startActivity(new Intent(getApplicationContext(), MainActivity.class)
@@ -147,9 +184,20 @@ public int onStartCommand(Intent intent, int flags, int startId) {
147184
return START_NOT_STICKY;
148185
}
149186

187+
private void startThread() {
188+
if (this.mThread == null) {
189+
this.mThread = new Thread(this, "DaedalusVpn");
190+
this.running = true;
191+
this.mThread.start();
192+
}
193+
}
194+
150195
@Override
151196
public void onDestroy() {
152197
stopThread();
198+
if (receiver != null) {
199+
unregisterReceiver(receiver);
200+
}
153201
}
154202

155203
private void stopThread() {
@@ -203,7 +251,8 @@ public void onRevoke() {
203251
stopThread();
204252
}
205253

206-
private InetAddress addDnsServer(Builder builder, String format, byte[] ipv6Template, AbstractDnsServer addr) throws UnknownHostException {
254+
private InetAddress addDnsServer(Builder builder, String format, byte[] ipv6Template, AbstractDnsServer addr)
255+
throws UnknownHostException {
207256
int size = dnsServers.size();
208257
size++;
209258
if (addr.getAddress().contains("/")) {//https uri
@@ -241,7 +290,6 @@ public void run() {
241290
new Intent(this, MainActivity.class).putExtra(MainActivity.LAUNCH_FRAGMENT, MainActivity.FRAGMENT_SETTINGS),
242291
PendingIntent.FLAG_ONE_SHOT));
243292

244-
//Set App Filter
245293
if (Daedalus.getPrefs().getBoolean("settings_app_filter_switch", false)) {
246294
ArrayList<String> apps = Daedalus.configurations.getAppObjects();
247295
if (apps.size() > 0) {
@@ -278,22 +326,16 @@ public void run() {
278326
statisticQuery = Daedalus.getPrefs().getBoolean("settings_count_query_times", false);
279327
byte[] ipv6Template = new byte[]{32, 1, 13, (byte) (184 & 0xFF), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
280328

281-
if (primaryServer.getAddress().contains(":") || secondaryServer.getAddress().contains(":")) {//IPv6
282-
try {
283-
InetAddress addr = Inet6Address.getByAddress(ipv6Template);
284-
Log.d(TAG, "configure: Adding IPv6 address" + addr);
285-
builder.addAddress(addr, 120);
286-
} catch (Exception e) {
287-
Logger.logException(e);
329+
try {
330+
InetAddress addr = Inet6Address.getByAddress(ipv6Template);
331+
Log.d(TAG, "configure: Adding IPv6 address" + addr);
332+
builder.addAddress(addr, 120);
333+
} catch (Exception e) {
334+
Logger.logException(e);
288335

289-
ipv6Template = null;
290-
}
291-
} else {
292336
ipv6Template = null;
293337
}
294338

295-
InetAddress aliasPrimary;
296-
InetAddress aliasSecondary;
297339
if (advanced) {
298340
dnsServers = new HashMap<>();
299341
aliasPrimary = addDnsServer(builder, format, ipv6Template, primaryServer);
@@ -303,8 +345,8 @@ public void run() {
303345
aliasSecondary = InetAddress.getByName(secondaryServer.getAddress());
304346
}
305347

306-
Logger.info("Daedalus VPN service is listening on " + primaryServer + " as " + aliasPrimary.getHostAddress());
307-
Logger.info("Daedalus VPN service is listening on " + secondaryServer + " as " + aliasSecondary.getHostAddress());
348+
Logger.info("Daedalus VPN service is listening on " + primaryServer.getAddress() + " as " + aliasPrimary.getHostAddress());
349+
Logger.info("Daedalus VPN service is listening on " + secondaryServer.getAddress() + " as " + aliasSecondary.getHostAddress());
308350
builder.addDnsServer(aliasPrimary).addDnsServer(aliasSecondary);
309351

310352
if (advanced) {
@@ -325,13 +367,17 @@ public void run() {
325367
Thread.sleep(1000);
326368
}
327369
}
328-
} catch (
329-
InterruptedException ignored) {
330-
} catch (
331-
Exception e) {
370+
} catch (InterruptedException ignored) {
371+
} catch (Exception e) {
372+
MainActivity.getInstance().runOnUiThread(() ->
373+
new AlertDialog.Builder(MainActivity.getInstance())
374+
.setTitle(R.string.error_occurred)
375+
.setMessage(Logger.getExceptionMessage(e))
376+
.setPositiveButton(android.R.string.ok, (d, id) -> {
377+
})
378+
.show());
332379
Logger.logException(e);
333380
} finally {
334-
Log.d(TAG, "quit");
335381
stopThread();
336382
}
337383
}
@@ -354,11 +400,11 @@ private void updateUserInterface() {
354400
}
355401
}
356402

357-
358403
public static class VpnNetworkException extends Exception {
359404
public VpnNetworkException(String s) {
360405
super(s);
361406
}
407+
362408
public VpnNetworkException(String s, Throwable t) {
363409
super(s, t);
364410
}

app/src/main/res/values-v21/styles.xml

Lines changed: 0 additions & 20 deletions
This file was deleted.

app/src/main/res/values-zh-rCN/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,6 @@
104104
<string name="test_test_domain">google.com</string>
105105

106106
<string name="nav_version">版本:</string>
107+
108+
<string name="error_occurred">启动时出现了一个错误</string>
107109
</resources>

app/src/main/res/values-zh-rTW/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,6 @@
101101
<string name="test_test_domain">google.com</string>
102102

103103
<string name="nav_version">版本:</string>
104+
105+
<string name="error_occurred">啟動時出現了一個錯誤</string>
104106
</resources>

app/src/main/res/values/strings.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,6 @@
112112
<string name="nav_version">Version:</string>
113113
<string name="nav_git_commit">Git commit:</string>
114114
<string name="nav_github">GitHub</string>
115+
116+
<string name="error_occurred">An error occurred at startup</string>
115117
</resources>

0 commit comments

Comments
 (0)