summaryrefslogtreecommitdiffhomepage
path: root/app/src/main/java/com/wireguard/android/ProfileService.java
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2017-07-31 21:22:02 -0500
committerSamuel Holland <samuel@sholland.org>2017-07-31 21:22:02 -0500
commitb6653fd7f0d28e411c544353194cdfb63016516e (patch)
treedc83f425194e2028b2a7eab6f613563069a0736f /app/src/main/java/com/wireguard/android/ProfileService.java
parent0ea5ae605c327836a298747a6f18f446ebecdc73 (diff)
ProfileService: Implement the rest of its interface
As per the FIXMEs, the list of profiles should eventually become a map. Since it can only be modified on the main thread anyway, the current code is still safe, and it works, it's just not optimal. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'app/src/main/java/com/wireguard/android/ProfileService.java')
-rw-r--r--app/src/main/java/com/wireguard/android/ProfileService.java176
1 files changed, 176 insertions, 0 deletions
diff --git a/app/src/main/java/com/wireguard/android/ProfileService.java b/app/src/main/java/com/wireguard/android/ProfileService.java
index 8925fb50..2d0e55eb 100644
--- a/app/src/main/java/com/wireguard/android/ProfileService.java
+++ b/app/src/main/java/com/wireguard/android/ProfileService.java
@@ -12,8 +12,10 @@ import android.util.Log;
import com.wireguard.config.Profile;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
@@ -47,6 +49,84 @@ public class ProfileService extends Service {
return START_STICKY;
}
+ private class ProfileAdder extends AsyncTask<Void, Void, Boolean> {
+ private final Profile profile;
+
+ private ProfileAdder(Profile profile) {
+ super();
+ this.profile = profile;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ Log.i(TAG, "Adding profile " + profile.getName());
+ try {
+ final String configFile = profile.getName() + ".conf";
+ final FileOutputStream stream = openFileOutput(configFile, MODE_PRIVATE);
+ stream.write(profile.toString().getBytes(StandardCharsets.UTF_8));
+ stream.close();
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "Could not create profile " + profile.getName(), e);
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (!result)
+ return;
+ profile.setIsConnected(false);
+ profiles.add(profile);
+ }
+ }
+
+ private class ProfileConnecter extends AsyncTask<Void, Void, Boolean> {
+ private final Profile profile;
+
+ private ProfileConnecter(Profile profile) {
+ super();
+ this.profile = profile;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ Log.i(TAG, "Running wg-quick up for profile " + profile.getName());
+ final File configFile = new File(getFilesDir(), profile.getName() + ".conf");
+ return RootShell.run(null, "wg-quick up '" + configFile.getPath() + "'") == 0;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (!result)
+ return;
+ profile.setIsConnected(true);
+ }
+ }
+
+ private class ProfileDisconnecter extends AsyncTask<Void, Void, Boolean> {
+ private final Profile profile;
+
+ private ProfileDisconnecter(Profile profile) {
+ super();
+ this.profile = profile;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ Log.i(TAG, "Running wg-quick down for profile " + profile.getName());
+ final File configFile = new File(getFilesDir(), profile.getName() + ".conf");
+ return RootShell.run(null, "wg-quick down '" + configFile.getPath() + "'") == 0;
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (!result)
+ return;
+ profile.setIsConnected(false);
+ }
+ }
+
private class ProfileLoader extends AsyncTask<File, Void, List<Profile>> {
@Override
protected List<Profile> doInBackground(File... files) {
@@ -83,9 +163,82 @@ public class ProfileService extends Service {
}
}
+ private class ProfileRemover extends AsyncTask<Void, Void, Boolean> {
+ private final Profile profile;
+
+ private ProfileRemover(Profile profile) {
+ super();
+ this.profile = profile;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ Log.i(TAG, "Removing profile " + profile.getName());
+ final File configFile = new File(getFilesDir(), profile.getName() + ".conf");
+ if (configFile.delete()) {
+ return true;
+ } else {
+ Log.e(TAG, "Could not delete configuration for profile " + profile.getName());
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (!result)
+ return;
+ profiles.remove(profile);
+ }
+ }
+
+ private class ProfileUpdater extends AsyncTask<Void, Void, Boolean> {
+ private final Profile profile, newProfile;
+ private final boolean wasConnected;
+
+ private ProfileUpdater(Profile profile, Profile newProfile, boolean wasConnected) {
+ super();
+ this.profile = profile;
+ this.newProfile = newProfile;
+ this.wasConnected = wasConnected;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ Log.i(TAG, "Updating profile " + profile.getName());
+ if (!newProfile.getName().equals(profile.getName()))
+ throw new IllegalStateException("Profile name mismatch: " + profile.getName());
+ try {
+ final String configFile = profile.getName() + ".conf";
+ final FileOutputStream stream = openFileOutput(configFile, MODE_PRIVATE);
+ stream.write(newProfile.toString().getBytes(StandardCharsets.UTF_8));
+ stream.close();
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "Could not update profile " + profile.getName(), e);
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (!result)
+ return;
+ // FIXME: This is also why the list of profiles should be a map.
+ final int index = profiles.indexOf(profile);
+ profiles.set(index, newProfile);
+ if (wasConnected)
+ new ProfileConnecter(newProfile).execute();
+ }
+ }
+
private class ProfileServiceBinder extends Binder implements ProfileServiceInterface {
@Override
public void connectProfile(Profile profile) {
+ if (!profiles.contains(profile))
+ return;
+ if (profile.getIsConnected())
+ return;
+ new ProfileConnecter(profile).execute();
}
@Override
@@ -97,6 +250,11 @@ public class ProfileService extends Service {
@Override
public void disconnectProfile(Profile profile) {
+ if (!profiles.contains(profile))
+ return;
+ if (!profile.getIsConnected())
+ return;
+ new ProfileDisconnecter(profile).execute();
}
@Override
@@ -106,10 +264,28 @@ public class ProfileService extends Service {
@Override
public void removeProfile(Profile profile) {
+ if (!profiles.contains(profile))
+ return;
+ if (profile.getIsConnected())
+ new ProfileDisconnecter(profile).execute();
+ new ProfileRemover(profile).execute();
}
@Override
public void saveProfile(Profile newProfile) {
+ // FIXME: This is why the list of profiles should be a map.
+ Profile profile = null;
+ for (Profile p : profiles)
+ if (p.getName().equals(newProfile.getName()))
+ profile = p;
+ if (profile != null) {
+ final boolean wasConnected = profile.getIsConnected();
+ if (wasConnected)
+ new ProfileDisconnecter(profile).execute();
+ new ProfileUpdater(profile, newProfile, wasConnected).execute();
+ } else {
+ new ProfileAdder(newProfile).execute();
+ }
}
}
}