summaryrefslogtreecommitdiffhomepage
path: root/tunnel
diff options
context:
space:
mode:
Diffstat (limited to 'tunnel')
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/Backend.java5
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/BackendException.java23
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java54
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/Statistics.java47
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java9
-rw-r--r--tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java37
6 files changed, 174 insertions, 1 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/Backend.java b/tunnel/src/main/java/com/wireguard/android/backend/Backend.java
index 4c18d98b..c67d672b 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/Backend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/Backend.java
@@ -30,6 +30,7 @@ public interface Backend {
*
* @param tunnel The tunnel to examine the state of.
* @return The state of the tunnel.
+ * @throws Exception Exception raised when retrieving tunnel's state.
*/
Tunnel.State getState(Tunnel tunnel) throws Exception;
@@ -39,6 +40,7 @@ public interface Backend {
*
* @param tunnel The tunnel to retrieve statistics for.
* @return The statistics for the tunnel.
+ * @throws Exception Exception raised when retrieving statistics.
*/
Statistics getStatistics(Tunnel tunnel) throws Exception;
@@ -46,7 +48,7 @@ public interface Backend {
* Determine version of underlying backend.
*
* @return The version of the backend.
- * @throws Exception
+ * @throws Exception Exception raised while retrieving version.
*/
String getVersion() throws Exception;
@@ -59,6 +61,7 @@ public interface Backend {
* {@code TOGGLE}.
* @param config The configuration for this tunnel, may be null if state is {@code DOWN}.
* @return The updated state of the tunnel.
+ * @throws Exception Exception raised while changing state.
*/
Tunnel.State setState(Tunnel tunnel, Tunnel.State state, @Nullable Config config) throws Exception;
}
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/BackendException.java b/tunnel/src/main/java/com/wireguard/android/backend/BackendException.java
index 5552b3ee..b64ebb47 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/BackendException.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/BackendException.java
@@ -7,24 +7,47 @@ package com.wireguard.android.backend;
import com.wireguard.util.NonNullForAll;
+/**
+ * A subclass of {@link Exception} that encapsulates the reasons for a failure originating in
+ * implementations of {@link Backend}.
+ */
@NonNullForAll
public final class BackendException extends Exception {
private final Object[] format;
private final Reason reason;
+ /**
+ * Public constructor for BackendException.
+ *
+ * @param reason The {@link Reason} which caused this exception to be thrown
+ * @param format Format string values used when converting exceptions to user-facing strings.
+ */
public BackendException(final Reason reason, final Object... format) {
this.reason = reason;
this.format = format;
}
+ /**
+ * Get the format string values associated with the instance.
+ *
+ * @return Array of {@link Object} for string formatting purposes
+ */
public Object[] getFormat() {
return format;
}
+ /**
+ * Get the reason for this exception.
+ *
+ * @return Associated {@link Reason} for this exception.
+ */
public Reason getReason() {
return reason;
}
+ /**
+ * Enum class containing all known reasons for why a {@link BackendException} might be thrown.
+ */
public enum Reason {
UNKNOWN_KERNEL_MODULE_NAME,
WG_QUICK_CONFIG_ERROR_CODE,
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
index 9fafc918..5c3bf111 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -34,6 +34,10 @@ import java.util.concurrent.TimeoutException;
import androidx.annotation.Nullable;
import androidx.collection.ArraySet;
+/**
+ * Implementation of {@link Backend} that uses the wireguard-go userspace implementation to provide
+ * WireGuard tunnels.
+ */
@NonNullForAll
public final class GoBackend implements Backend {
private static final String TAG = "WireGuard/GoBackend";
@@ -44,11 +48,22 @@ public final class GoBackend implements Backend {
@Nullable private Tunnel currentTunnel;
private int currentTunnelHandle = -1;
+ /**
+ * Public constructor for GoBackend.
+ *
+ * @param context An Android {@link Context}
+ */
public GoBackend(final Context context) {
SharedLibraryLoader.loadSharedLibrary(context, "wg-go");
this.context = context;
}
+ /**
+ * Set a {@link AlwaysOnCallback} to be invoked when {@link VpnService} is started by the
+ * system's Always-On VPN mode.
+ *
+ * @param cb Callback to be invoked
+ */
public static void setAlwaysOnCallback(final AlwaysOnCallback cb) {
alwaysOnCallback = cb;
}
@@ -65,6 +80,11 @@ public final class GoBackend implements Backend {
private static native String wgVersion();
+ /**
+ * Method to get the names of running tunnels.
+ *
+ * @return A set of string values denoting names of running tunnels.
+ */
@Override
public Set<String> getRunningTunnelNames() {
if (currentTunnel != null) {
@@ -75,11 +95,23 @@ public final class GoBackend implements Backend {
return Collections.emptySet();
}
+ /**
+ * Get the associated {@link State} for a given {@link Tunnel}.
+ *
+ * @param tunnel The tunnel to examine the state of.
+ * @return {@link State} associated with the given tunnel.
+ */
@Override
public State getState(final Tunnel tunnel) {
return currentTunnel == tunnel ? State.UP : State.DOWN;
}
+ /**
+ * Get the associated {@link Statistics} for a given {@link Tunnel}.
+ *
+ * @param tunnel The tunnel to retrieve statistics for.
+ * @return {@link Statistics} associated with the given tunnel.
+ */
@Override
public Statistics getStatistics(final Tunnel tunnel) {
final Statistics stats = new Statistics();
@@ -124,11 +156,26 @@ public final class GoBackend implements Backend {
return stats;
}
+ /**
+ * Get the version of the underlying wireguard-go library.
+ *
+ * @return {@link String} value of the version of the wireguard-go library.
+ */
@Override
public String getVersion() {
return wgVersion();
}
+ /**
+ * Change the state of a given {@link Tunnel}, optionally applying a given {@link Config}.
+ *
+ * @param tunnel The tunnel to control the state of.
+ * @param state The new state for this tunnel. Must be {@code UP}, {@code DOWN}, or
+ * {@code TOGGLE}.
+ * @param config The configuration for this tunnel, may be null if state is {@code DOWN}.
+ * @return {@link State} of the tunnel after state changes are applied.
+ * @throws Exception Exception raised while changing tunnel state.
+ */
@Override
public State setState(final Tunnel tunnel, State state, @Nullable final Config config) throws Exception {
final State originalState = getState(tunnel);
@@ -260,6 +307,10 @@ public final class GoBackend implements Backend {
context.startService(new Intent(context, VpnService.class));
}
+ /**
+ * Callback for {@link GoBackend} that is invoked when {@link VpnService} is started by the
+ * system's Always-On VPN mode.
+ */
public interface AlwaysOnCallback {
void alwaysOnTriggered();
}
@@ -293,6 +344,9 @@ public final class GoBackend implements Backend {
}
}
+ /**
+ * {@link android.net.VpnService} implementation for {@link GoBackend}
+ */
public static class VpnService extends android.net.VpnService {
@Nullable private GoBackend owner;
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/Statistics.java b/tunnel/src/main/java/com/wireguard/android/backend/Statistics.java
index b4e01e76..60f78833 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/Statistics.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/Statistics.java
@@ -14,6 +14,9 @@ import com.wireguard.util.NonNullForAll;
import java.util.HashMap;
import java.util.Map;
+/**
+ * Class representing transfer statistics for a {@link Tunnel} instance.
+ */
@NonNullForAll
public class Statistics {
private final Map<Key, Pair<Long, Long>> peerBytes = new HashMap<>();
@@ -22,31 +25,70 @@ public class Statistics {
Statistics() {
}
+ /**
+ * Add a peer and its current data usage to the internal map.
+ *
+ * @param key A WireGuard public key bound to a particular peer
+ * @param rx The received traffic for the {@link com.wireguard.config.Peer} referenced by
+ * the provided {@link Key}. This value is in bytes
+ * @param tx The transmitted traffic for the {@link com.wireguard.config.Peer} referenced by
+ * the provided {@link Key}. This value is in bytes.
+ */
void add(final Key key, final long rx, final long tx) {
peerBytes.put(key, Pair.create(rx, tx));
lastTouched = SystemClock.elapsedRealtime();
}
+ /**
+ * Check if the statistics are stale, indicating the need for the {@link Backend} to update them.
+ *
+ * @return boolean indicating if the current statistics instance has stale values.
+ */
public boolean isStale() {
return SystemClock.elapsedRealtime() - lastTouched > 900;
}
+ /**
+ * Get the received traffic (in bytes) for the {@link com.wireguard.config.Peer} referenced by
+ * the provided {@link Key}
+ *
+ * @param peer A {@link Key} representing a {@link com.wireguard.config.Peer}.
+ * @return a long representing the number of bytes received by this peer.
+ */
public long peerRx(final Key peer) {
if (!peerBytes.containsKey(peer))
return 0;
return peerBytes.get(peer).first;
}
+ /**
+ * Get the transmitted traffic (in bytes) for the {@link com.wireguard.config.Peer} referenced by
+ * the provided {@link Key}
+ *
+ * @param peer A {@link Key} representing a {@link com.wireguard.config.Peer}.
+ * @return a long representing the number of bytes transmitted by this peer.
+ */
public long peerTx(final Key peer) {
if (!peerBytes.containsKey(peer))
return 0;
return peerBytes.get(peer).second;
}
+ /**
+ * Get the list of peers being tracked by this instance.
+ *
+ * @return An array of {@link Key} instances representing WireGuard
+ * {@link com.wireguard.config.Peer}s
+ */
public Key[] peers() {
return peerBytes.keySet().toArray(new Key[0]);
}
+ /**
+ * Get the total received traffic by all the peers being tracked by this instance
+ *
+ * @return a long representing the number of bytes received by the peers being tracked.
+ */
public long totalRx() {
long rx = 0;
for (final Pair<Long, Long> val : peerBytes.values()) {
@@ -55,6 +97,11 @@ public class Statistics {
return rx;
}
+ /**
+ * Get the total transmitted traffic by all the peers being tracked by this instance
+ *
+ * @return a long representing the number of bytes transmitted by the peers being tracked.
+ */
public long totalTx() {
long tx = 0;
for (final Pair<Long, Long> val : peerBytes.values()) {
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java b/tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java
index a9761929..2f12f6c3 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/Tunnel.java
@@ -36,11 +36,20 @@ public interface Tunnel {
*/
void onStateChange(State newState);
+ /**
+ * Enum class to represent all possible states of a {@link Tunnel}.
+ */
enum State {
DOWN,
TOGGLE,
UP;
+ /**
+ * Get the state of a {@link Tunnel}
+ *
+ * @param running boolean indicating if the tunnel is running.
+ * @return State of the tunnel based on whether or not it is running.
+ */
public static State of(final boolean running) {
return running ? UP : DOWN;
}
diff --git a/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java b/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java
index c5b0aff5..e6605057 100644
--- a/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java
+++ b/tunnel/src/main/java/com/wireguard/android/util/ModuleLoader.java
@@ -31,6 +31,10 @@ import java.util.Map;
import androidx.annotation.Nullable;
+/**
+ * Class that implements the logic for downloading and loading signed, prebuilt modules for
+ * WireGuard into the running kernel.
+ */
@NonNullForAll
@SuppressWarnings("MagicNumber")
public class ModuleLoader {
@@ -43,6 +47,15 @@ public class ModuleLoader {
private final File tmpDir;
private final String userAgent;
+ /**
+ * Public constructor for ModuleLoader
+ *
+ * @param context A {@link Context} instance.
+ * @param rootShell A {@link RootShell} instance used to run elevated commands required for module
+ * loading.
+ * @param userAgent A {@link String} that represents the User-Agent string used for connections
+ * to the upstream server.
+ */
public ModuleLoader(final Context context, final RootShell rootShell, final String userAgent) {
moduleDir = new File(context.getCacheDir(), "kmod");
tmpDir = new File(context.getCacheDir(), "tmp");
@@ -50,10 +63,23 @@ public class ModuleLoader {
this.userAgent = userAgent;
}
+ /**
+ * Check whether a WireGuard module is already loaded into the kernel.
+ *
+ * @return boolean indicating if WireGuard is already enabled in the kernel.
+ */
public static boolean isModuleLoaded() {
return new File("/sys/module/wireguard").exists();
}
+ /**
+ * Download the correct WireGuard module for the device
+ *
+ * @return {@link OsConstants}.EXIT_SUCCESS if everything succeeds, ENOENT otherwise.
+ * @throws IOException if the remote hash list was not found or empty.
+ * @throws RootShellException if {@link RootShell} has a failure executing elevated commands.
+ * @throws NoSuchAlgorithmException if SHA256 algorithm is not available in device JDK.
+ */
public Integer download() throws IOException, RootShellException, NoSuchAlgorithmException {
final List<String> output = new ArrayList<>();
rootShell.run(output, "sha256sum /proc/version|cut -d ' ' -f 1");
@@ -113,10 +139,21 @@ public class ModuleLoader {
return OsConstants.EXIT_SUCCESS;
}
+ /**
+ * Load the downloaded module. ModuleLoader#download must be called before this.
+ *
+ * @throws IOException if {@link RootShell} has a failure executing elevated commands.
+ * @throws RootShellException if {@link RootShell} has a failure executing elevated commands.
+ */
public void loadModule() throws IOException, RootShellException {
rootShell.run(null, String.format("insmod \"%s/wireguard-$(sha256sum /proc/version|cut -d ' ' -f 1).ko\"", moduleDir.getAbsolutePath()));
}
+ /**
+ * Check if the module might already exist in the app's data.
+ *
+ * @return boolean indicating whether downloadable module might exist already.
+ */
public boolean moduleMightExist() {
return moduleDir.exists() && moduleDir.isDirectory();
}