summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java70
1 files changed, 63 insertions, 7 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java
index 539080bc..d39f8bf3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/Shapeshifter.java
@@ -17,37 +17,56 @@
package se.leap.bitmaskclient.pluggableTransports;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
+import java.util.Observable;
+import java.util.Observer;
+
+import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.VpnStatus;
+import se.leap.bitmaskclient.eip.EipStatus;
import shapeshifter.ShapeShifter;
-public class Shapeshifter {
+public class Shapeshifter implements Observer {
public static final String DISPATCHER_PORT = "4430";
public static final String DISPATCHER_IP = "127.0.0.1";
+ private static final int MAX_RETRY = 5;
+ private static final int RETRY_TIME = 4000;
private static final String TAG = Shapeshifter.class.getSimpleName();
private ShapeShifter shapeShifter;
+ private boolean isErrorHandling;
+ private boolean noNetwork;
+ private int retry = 0;
+ private Handler reconnectHandler;
public class ShapeshifterLogger implements shapeshifter.Logger {
@Override
public void log(String s) {
Log.e(TAG, "SHAPESHIFTER ERROR: " + s);
- VpnStatus.logError(VpnStatus.ErrorType.SHAPESHIFTER);
VpnStatus.logError(s);
- try {
- shapeShifter.close();
- } catch (Exception e) {
- e.printStackTrace();
+ isErrorHandling = true;
+ close();
+
+ if (retry < MAX_RETRY && !noNetwork) {
+ retry++;
+ reconnectHandler.postDelayed(Shapeshifter.this::reconnect, RETRY_TIME);
+ } else {
+ VpnStatus.logError(VpnStatus.ErrorType.SHAPESHIFTER);
}
}
}
- public Shapeshifter(Obfs4Options options) {
+ public Shapeshifter(Obfs4Options options) {
shapeShifter = new ShapeShifter();
shapeShifter.setLogger(new ShapeshifterLogger());
setup(options);
+ Looper.prepare();
+ reconnectHandler = new Handler();
+ EipStatus.getInstance().addObserver(this);
Log.d(TAG, "shapeshifter initialized with: \n" + shapeShifter.toString());
}
@@ -72,6 +91,26 @@ public class Shapeshifter {
}
}
+ private void close() {
+ try {
+ shapeShifter.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void reconnect() {
+ try {
+ shapeShifter.open();
+ retry = 0;
+ isErrorHandling = false;
+ } catch (Exception e) {
+ e.printStackTrace();
+ Log.e(TAG, "SHAPESHIFTER RECONNECTION ERROR: " + e.getLocalizedMessage());
+ VpnStatus.logError("Unable to reconnect shapeshifter: " + e.getLocalizedMessage());
+ }
+ }
+
public boolean stop() {
try {
shapeShifter.close();
@@ -80,7 +119,24 @@ public class Shapeshifter {
e.printStackTrace();
VpnStatus.logError(e.getLocalizedMessage());
}
+ EipStatus.getInstance().deleteObserver(this);
return false;
}
+ @Override
+ public void update(Observable observable, Object arg) {
+ if (observable instanceof EipStatus) {
+ EipStatus status = (EipStatus) observable;
+ if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
+ noNetwork = true;
+ } else {
+ noNetwork = false;
+ if (isErrorHandling) {
+ isErrorHandling = false;
+ close();
+ start();
+ }
+ }
+ }
+ }
}