summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java175
1 files changed, 133 insertions, 42 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index 501543b8..dc2e81f5 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -17,19 +17,37 @@
package se.leap.bitmaskclient.eip;
import android.content.*;
+import android.os.AsyncTask;
+import android.support.annotation.VisibleForTesting;
import java.util.*;
import de.blinkt.openvpn.core.*;
+/**
+ * EipStatus is a Singleton that represents a reduced set of a vpn's ConnectionStatus.
+ * EipStatus changes it's state (EipLevel) when ConnectionStatus gets updated by OpenVpnService or
+ * by VoidVpnService.
+ */
public class EipStatus extends Observable implements VpnStatus.StateListener {
public static String TAG = EipStatus.class.getSimpleName();
private static EipStatus current_status;
+ public enum EipLevel {
+ CONNECTING,
+ DISCONNECTING,
+ CONNECTED,
+ DISCONNECTED,
+ BLOCKING,
+ UNKNOWN
+ }
- private static ConnectionStatus level = ConnectionStatus.LEVEL_NOTCONNECTED;
- private static boolean
- wants_to_disconnect = false,
- is_connecting = false;
+ /**
+ * vpn_level holds the connection status of the openvpn vpn and the traffic blocking
+ * void vpn. LEVEL_BLOCKING is set when the latter vpn is up. All other states are set by
+ * openvpn.
+ */
+ private ConnectionStatus vpn_level = ConnectionStatus.LEVEL_NOTCONNECTED;
+ private EipLevel current_eip_level = EipLevel.DISCONNECTED;
int last_error_line = 0;
private String state, log_message;
@@ -48,64 +66,137 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
@Override
public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- updateStatus(state, logmessage, localizedResId, level);
- if (isConnected() || isDisconnected() || wantsToDisconnect()) {
- setConnectedOrDisconnected();
- } else
- setConnecting();
+ current_status = getInstance();
+ current_status.setState(state);
+ current_status.setLogMessage(logmessage);
+ current_status.setLocalizedResId(localizedResId);
+ current_status.setLevel(level);
+ current_status.setEipLevel(level);
}
@Override
public void setConnectedVPN(String uuid) {
}
- private void updateStatus(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- current_status = getInstance();
- current_status.setState(state);
- current_status.setLogMessage(logmessage);
- current_status.setLocalizedResId(localizedResId);
- current_status.setLevel(level);
- current_status.setChanged();
+
+ private void setEipLevel(ConnectionStatus level) {
+ EipLevel tmp = current_eip_level;
+ switch (level) {
+ case LEVEL_CONNECTED:
+ current_eip_level = EipLevel.CONNECTED;
+ break;
+ case LEVEL_VPNPAUSED:
+ throw new IllegalStateException("Ics-Openvpn's VPNPAUSED state is not supported by Bitmask");
+ case LEVEL_CONNECTING_SERVER_REPLIED:
+ case LEVEL_CONNECTING_NO_SERVER_REPLY_YET:
+ case LEVEL_WAITING_FOR_USER_INPUT:
+ case LEVEL_START:
+ current_eip_level = EipLevel.CONNECTING;
+ break;
+ case LEVEL_AUTH_FAILED:
+ case LEVEL_NOTCONNECTED:
+ current_eip_level = EipLevel.DISCONNECTED;
+ break;
+ case LEVEL_NONETWORK:
+ case LEVEL_BLOCKING:
+ setEipLevelWithDelay(level);
+ break;
+ case UNKNOWN_LEVEL:
+ current_eip_level = EipLevel.UNKNOWN; //??
+ break;
+ }
+ if (tmp != current_eip_level) {
+ current_status.setChanged();
+ current_status.notifyObservers();
+ }
}
- public boolean wantsToDisconnect() {
- return wants_to_disconnect;
+ @VisibleForTesting
+ EipLevel getEipLevel() {
+ return current_eip_level;
}
- public boolean isConnecting() {
- return is_connecting;
+ /**
+ * This method intends to ignore states that are valid for less than a second.
+ * This way flickering UI changes can be avoided
+ *
+ * @param futureLevel
+ */
+ private void setEipLevelWithDelay(ConnectionStatus futureLevel) {
+ new DelayTask(current_status.getLevel(), futureLevel).execute();
}
- public boolean isConnected() {
- return level == ConnectionStatus.LEVEL_CONNECTED;
+ private class DelayTask extends AsyncTask<Void, Void, Void> {
+
+ private final ConnectionStatus currentLevel;
+ private final ConnectionStatus futureLevel;
+
+ public DelayTask(ConnectionStatus currentLevel, ConnectionStatus futureLevel) {
+ this.currentLevel = currentLevel;
+ this.futureLevel = futureLevel;
+ }
+ protected Void doInBackground(Void... levels) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ Thread.interrupted();
+ }
+ return null;
+ }
+
+ protected void onPostExecute(Void result) {;
+ if (currentLevel == current_status.getLevel()) {
+ switch (futureLevel) {
+ case LEVEL_NONETWORK:
+ current_eip_level = EipLevel.DISCONNECTED;
+ break;
+ case LEVEL_BLOCKING:
+ current_eip_level = EipLevel.BLOCKING;
+ break;
+ default:
+ break;
+ }
+ current_status.setChanged();
+ current_status.notifyObservers();
+ }
+ }
}
- public boolean isDisconnected() {
- return level == ConnectionStatus.LEVEL_NOTCONNECTED;
+ public boolean isConnecting() {
+ return current_eip_level == EipLevel.CONNECTING;
}
- public boolean isPaused() {
- return level == ConnectionStatus.LEVEL_VPNPAUSED;
+ public boolean isConnected() {
+ return current_eip_level == EipLevel.CONNECTED;
}
- public void setConnecting() {
- is_connecting = true;
+ /**
+ * @return true if current_eip_level is for at least a second {@link EipLevel#BLOCKING}.
+ * See {@link #setEipLevelWithDelay(ConnectionStatus)}.
+ */
+ public boolean isBlocking() {
+ return current_eip_level == EipLevel.BLOCKING;
+ }
- wants_to_disconnect = false;
- current_status.setChanged();
- current_status.notifyObservers();
+ /**
+ *
+ * @return true immediately after traffic blocking VoidVpn was established.
+ */
+ public boolean isBlockingVpnEstablished() {
+ return vpn_level == ConnectionStatus.LEVEL_BLOCKING;
}
- public void setConnectedOrDisconnected() {
- is_connecting = false;
- wants_to_disconnect = false;
- current_status.setChanged();
- current_status.notifyObservers();
+ public boolean isDisconnected() {
+ return current_eip_level == EipLevel.DISCONNECTED;
}
- public void setDisconnecting() {
- wants_to_disconnect = true;
- is_connecting = false;
+ /**
+ * ics-openvpn's paused state is not implemented yet
+ * @return
+ */
+ @Deprecated
+ public boolean isPaused() {
+ return vpn_level == ConnectionStatus.LEVEL_VPNPAUSED;
}
public String getState() {
@@ -121,7 +212,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public ConnectionStatus getLevel() {
- return level;
+ return vpn_level;
}
private void setState(String state) {
@@ -137,7 +228,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
private void setLevel(ConnectionStatus level) {
- EipStatus.level = level;
+ this.vpn_level = level;
}
public boolean errorInLast(int lines, Context context) {
@@ -169,7 +260,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
@Override
public String toString() {
- return "State: " + state + " Level: " + level.toString();
+ return "State: " + state + " Level: " + vpn_level.toString();
}
}