From e759a9ad6226f91675bd609752823ba7384114cf Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 19 Nov 2019 22:35:51 +0100 Subject: implement reconnect mechanism for shapeshifter that gets triggered before a new gateway setup is tested --- .../pluggableTransports/Shapeshifter.java | 70 +++++++++++++++++++--- 1 file changed, 63 insertions(+), 7 deletions(-) (limited to 'app/src/main/java/se/leap') 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(); + } + } + } + } } -- cgit v1.2.3