diff options
3 files changed, 144 insertions, 121 deletions
| diff --git a/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java b/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java index f0acb6df..ae61adab 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java +++ b/main/src/main/java/de/blinkt/openvpn/core/DeviceStateReceiver.java @@ -23,7 +23,7 @@ import java.util.Objects;  import static de.blinkt.openvpn.core.OpenVPNManagement.pauseReason;
 -public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountListener {
 +public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountListener, OpenVPNManagement.PausedStateCallback {      private final Handler mDisconnectHandler;
      private int lastNetwork = -1;
      private OpenVPNManagement mManagement;
 @@ -59,6 +59,11 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL      };
      private NetworkInfo lastConnectedNetwork;
 +    @Override +    public boolean shouldBeRunning() { +        return shouldBeConnected(); +    } +      enum connectState {
          SHOULDBECONNECTED,
          PENDINGDISCONNECT,
 @@ -123,6 +128,7 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL      public DeviceStateReceiver(OpenVPNManagement magnagement) {
          super();
          mManagement = magnagement;
 +        mManagement.setPauseCallback(this);          mDisconnectHandler = new Handler();
      }
 @@ -224,7 +230,7 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL                  mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable);
                  // Reprotect the sockets just be sure
                  mManagement.networkChange(true);
 -            }  else {
 +            } else {                  /* Different network or connection not established anymore */
                  if (screen == connectState.PENDINGDISCONNECT)
 @@ -233,8 +239,8 @@ public class DeviceStateReceiver extends BroadcastReceiver implements ByteCountL                  if (shouldBeConnected()) {
                      mDisconnectHandler.removeCallbacks(mDelayDisconnectRunnable);
 -                    if (pendingDisconnect)
 -                        mManagement.networkChange(false);
 +                    if (pendingDisconnect || !sameNetwork) +                        mManagement.networkChange(sameNetwork);                      else
                          mManagement.resume();
                  }
 diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java index d7666933..9e17c40d 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVPNManagement.java @@ -6,6 +6,10 @@  package de.blinkt.openvpn.core;  public interface OpenVPNManagement { +    interface PausedStateCallback { +        boolean shouldBeRunning(); +    } +      enum pauseReason {          noNetwork,          userPause, @@ -26,4 +30,6 @@ public interface OpenVPNManagement {       * Rebind the interface       */      void networkChange(boolean sameNetwork); + +    void setPauseCallback(PausedStateCallback callback);  } diff --git a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java index e27feab0..f81c46ad 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java +++ b/main/src/main/java/de/blinkt/openvpn/core/OpenVpnManagementThread.java @@ -6,12 +6,10 @@  package de.blinkt.openvpn.core;
  import android.content.Context;
 -import android.content.SharedPreferences;
  import android.net.LocalServerSocket;
  import android.net.LocalSocket;
  import android.net.LocalSocketAddress;
  import android.os.ParcelFileDescriptor;
 -import android.preference.PreferenceManager;
  import android.support.annotation.NonNull;
  import android.util.Log;
 @@ -41,27 +39,20 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {      private LocalSocket mSocket;
      private VpnProfile mProfile;
      private OpenVPNService mOpenVPNService;
 -    private LinkedList<FileDescriptor> mFDList = new LinkedList<FileDescriptor>();
 +    private LinkedList<FileDescriptor> mFDList = new LinkedList<>();      private LocalServerSocket mServerSocket;
 -    private boolean mReleaseHold = true;
      private boolean mWaitingForRelease = false;
      private long mLastHoldRelease = 0;
 -    private static final Vector<OpenVpnManagementThread> active = new Vector<OpenVpnManagementThread>();
 +    private static final Vector<OpenVpnManagementThread> active = new Vector<>();      private LocalSocket mServerSocketLocal;
      private pauseReason lastPauseReason = pauseReason.noNetwork;
 +    private PausedStateCallback mPauseCallback;      public OpenVpnManagementThread(VpnProfile profile, OpenVPNService openVpnService) {
          mProfile = profile;
          mOpenVPNService = openVpnService;
 -
 -
 -        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(openVpnService);
 -        boolean managemeNetworkState = prefs.getBoolean("netchangereconnect", true);
 -        if (managemeNetworkState)
 -            mReleaseHold = false;
 -
      }
      public boolean openManagementInterface(@NonNull Context c) {
 @@ -81,7 +72,7 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {                  // wait 300 ms before retrying
                  try {
                      Thread.sleep(300);
 -                } catch (InterruptedException e1) {
 +                } catch (InterruptedException ignored) {                  }
              }
 @@ -166,7 +157,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {      //! Hack O Rama 2000!
      private void protectFileDescriptor(FileDescriptor fd) {
 -        Exception exp;
          try {
              Method getInt = FileDescriptor.class.getDeclaredMethod("getInt$");
              int fdint = (Integer) getInt.invoke(fd);
 @@ -182,20 +172,12 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {              //pfd.close();
              NativeUtils.jniclose(fdint);
              return;
 -        } catch (NoSuchMethodException e) {
 -            exp = e;
 -        } catch (IllegalArgumentException e) {
 -            exp = e;
 -        } catch (IllegalAccessException e) {
 -            exp = e;
 -        } catch (InvocationTargetException e) {
 -            exp = e;
 -        } catch (NullPointerException e) {
 -            exp = e;
 +        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException | NullPointerException e) { +            VpnStatus.logException("Failed to retrieve fd from socket (" + fd + ")", e);          }
          Log.d("Openvpn", "Failed to retrieve fd from socket: " + fd);
 -        VpnStatus.logException("Failed to retrieve fd from socket (" + fd + ")", exp);
 +      }
      private String processInput(String pendingInput) {
 @@ -224,28 +206,38 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {              String argument = parts[1];
 -            if (cmd.equals("INFO")) {
 +            switch (cmd) { +                case "INFO":                  /* Ignore greeting from management */
 -                return;
 -            } else if (cmd.equals("PASSWORD")) {
 -                processPWCommand(argument);
 -            } else if (cmd.equals("HOLD")) {
 -                handleHold();
 -            } else if (cmd.equals("NEED-OK")) {
 -                processNeedCommand(argument);
 -            } else if (cmd.equals("BYTECOUNT")) {
 -                processByteCount(argument);
 -            } else if (cmd.equals("STATE")) {
 -                processState(argument);
 -            } else if (cmd.equals("PROXY")) {
 -                processProxyCMD(argument);
 -            } else if (cmd.equals("LOG")) {
 -                processLogMessage(argument);
 -            } else if (cmd.equals("RSA_SIGN")) {
 -                processSignCommand(argument);
 -            } else {
 -                VpnStatus.logWarning("MGMT: Got unrecognized command" + command);
 -                Log.i(TAG, "Got unrecognized command" + command);
 +                    return; +                case "PASSWORD": +                    processPWCommand(argument); +                    break; +                case "HOLD": +                    handleHold(); +                    break; +                case "NEED-OK": +                    processNeedCommand(argument); +                    break; +                case "BYTECOUNT": +                    processByteCount(argument); +                    break; +                case "STATE": +                    processState(argument); +                    break; +                case "PROXY": +                    processProxyCMD(argument); +                    break; +                case "LOG": +                    processLogMessage(argument); +                    break; +                case "RSA_SIGN": +                    processSignCommand(argument); +                    break; +                default: +                    VpnStatus.logWarning("MGMT: Got unrecognized command" + command); +                    Log.i(TAG, "Got unrecognized command" + command); +                    break;              }
          } else if (command.startsWith("SUCCESS:")) {
              /* Ignore this kind of message too */
 @@ -277,16 +269,22 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {          Log.d("OpenVPN", argument);
          VpnStatus.LogLevel level;
 -        if (args[1].equals("I")) {
 -            level = VpnStatus.LogLevel.INFO;
 -        } else if (args[1].equals("W")) {
 -            level = VpnStatus.LogLevel.WARNING;
 -        } else if (args[1].equals("D")) {
 -            level = VpnStatus.LogLevel.VERBOSE;
 -        } else if (args[1].equals("F")) {
 -            level = VpnStatus.LogLevel.ERROR;
 -        } else {
 -            level = VpnStatus.LogLevel.INFO;
 +        switch (args[1]) { +            case "I": +                level = VpnStatus.LogLevel.INFO; +                break; +            case "W": +                level = VpnStatus.LogLevel.WARNING; +                break; +            case "D": +                level = VpnStatus.LogLevel.VERBOSE; +                break; +            case "F": +                level = VpnStatus.LogLevel.ERROR; +                break; +            default: +                level = VpnStatus.LogLevel.INFO; +                break;          }
          int ovpnlevel = Integer.parseInt(args[2]) & 0x0F;
 @@ -298,8 +296,15 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {          VpnStatus.logMessageOpenVPN(level, ovpnlevel, msg);
      }
 +    boolean shouldBeRunning() { +        if (mPauseCallback == null) +            return false; +        else +            return mPauseCallback.shouldBeRunning(); +    } +      private void handleHold() {
 -        if (mReleaseHold) {
 +        if (shouldBeRunning()) {              releaseHoldCmd();
          } else {
              mWaitingForRelease = true;
 @@ -326,11 +331,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {          //managmentCommand("log on all\n");
      }
 +      public void releaseHold() {
 -        mReleaseHold = true;
          if (mWaitingForRelease)
              releaseHoldCmd();
 -
      }
      private void processProxyCMD(String argument) {
 @@ -390,15 +394,19 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {          String status = "ok";
 -        if (needed.equals("PROTECTFD")) {
 -            FileDescriptor fdtoprotect = mFDList.pollFirst();
 -            protectFileDescriptor(fdtoprotect);
 -        } else if (needed.equals("DNSSERVER")) {
 -            mOpenVPNService.addDNS(extra);
 -        } else if (needed.equals("DNSDOMAIN")) {
 -            mOpenVPNService.setDomain(extra);
 -        } else if (needed.equals("ROUTE")) {
 -            String[] routeparts = extra.split(" ");
 +        switch (needed) { +            case "PROTECTFD": +                FileDescriptor fdtoprotect = mFDList.pollFirst(); +                protectFileDescriptor(fdtoprotect); +                break; +            case "DNSSERVER": +                mOpenVPNService.addDNS(extra); +                break; +            case "DNSDOMAIN": +                mOpenVPNService.setDomain(extra); +                break; +            case "ROUTE": { +                String[] routeparts = extra.split(" ");              /*
              buf_printf (&out, "%s %s %s dev %s", network, netmask, gateway, rgi->iface);
 @@ -406,38 +414,46 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {              buf_printf (&out, "%s %s %s", network, netmask, gateway);
              */
 -            if (routeparts.length == 5) {
 -                if (BuildConfig.DEBUG) Assert.assertEquals("dev", routeparts[3]);
 -                mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]);
 -            } else if (routeparts.length >= 3) {
 -                mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null);
 -            } else {
 -                VpnStatus.logError("Unrecognized ROUTE cmd:" + Arrays.toString(routeparts) + " | " + argument);
 +                if (routeparts.length == 5) { +                    if (BuildConfig.DEBUG) Assert.assertEquals("dev", routeparts[3]); +                    mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], routeparts[4]); +                } else if (routeparts.length >= 3) { +                    mOpenVPNService.addRoute(routeparts[0], routeparts[1], routeparts[2], null); +                } else { +                    VpnStatus.logError("Unrecognized ROUTE cmd:" + Arrays.toString(routeparts) + " | " + argument); +                } + +                break; +            } +            case "ROUTE6": { +                String[] routeparts = extra.split(" "); +                mOpenVPNService.addRoutev6(routeparts[0], routeparts[1]); +                break;              }
 -
 -        } else if (needed.equals("ROUTE6")) {
 -            String[] routeparts = extra.split(" ");
 -            mOpenVPNService.addRoutev6(routeparts[0], routeparts[1]);
 -        } else if (needed.equals("IFCONFIG")) {
 -            String[] ifconfigparts = extra.split(" ");
 -            int mtu = Integer.parseInt(ifconfigparts[2]);
 -            mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1], mtu, ifconfigparts[3]);
 -        } else if (needed.equals("IFCONFIG6")) {
 -            mOpenVPNService.setLocalIPv6(extra);
 -
 -        } else if (needed.equals("PERSIST_TUN_ACTION")) {
 -            // check if tun cfg stayed the same
 -            status = mOpenVPNService.getTunReopenStatus();
 -        } else if (needed.equals("OPENTUN")) {
 -            if (sendTunFD(needed, extra))
 +            case "IFCONFIG": +                String[] ifconfigparts = extra.split(" "); +                int mtu = Integer.parseInt(ifconfigparts[2]); +                mOpenVPNService.setLocalIP(ifconfigparts[0], ifconfigparts[1], mtu, ifconfigparts[3]); +                break; +            case "IFCONFIG6": +                mOpenVPNService.setLocalIPv6(extra); + +                break; +            case "PERSIST_TUN_ACTION": +                // check if tun cfg stayed the same +                status = mOpenVPNService.getTunReopenStatus(); +                break; +            case "OPENTUN": +                if (sendTunFD(needed, extra)) +                    return; +                else +                    status = "cancel"; +                // This not nice or anything but setFileDescriptors accepts only FilDescriptor class :( + +                break; +            default: +                Log.e(TAG, "Unkown needok command " + argument);                  return;
 -            else
 -                status = "cancel";
 -            // This not nice or anything but setFileDescriptors accepts only FilDescriptor class :(
 -
 -        } else {
 -            Log.e(TAG, "Unkown needok command " + argument);
 -            return;
          }
          String cmd = String.format("needok '%s' %s\n", needed, status);
 @@ -445,7 +461,6 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {      }
      private boolean sendTunFD(String needed, String extra) {
 -        Exception exp;
          if (!extra.equals("tun")) {
              // We only support tun
              VpnStatus.logError(String.format("Device type %s requested, but only tun is possible with the Android API, sorry!", extra));
 @@ -479,18 +494,10 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {              pfd.close();
              return true;
 -        } catch (NoSuchMethodException e) {
 -            exp = e;
 -        } catch (IllegalArgumentException e) {
 -            exp = e;
 -        } catch (IllegalAccessException e) {
 -            exp = e;
 -        } catch (InvocationTargetException e) {
 -            exp = e;
 -        } catch (IOException e) {
 -            exp = e;
 +        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | +                IOException | IllegalAccessException exp) { +            VpnStatus.logException("Could not send fd over socket", exp);          }
 -        VpnStatus.logException("Could not send fd over socket", exp);
          return false;
      }
 @@ -559,16 +566,20 @@ public class OpenVpnManagementThread implements Runnable, OpenVPNManagement {      @Override
      public void networkChange(boolean samenetwork) {
 -        if (!mWaitingForRelease)
 -            if (samenetwork)
 -                managmentCommand("network-change samenetwork\n");
 -            else
 -                managmentCommand("network-change\n");
 +        if (mWaitingForRelease) +            releaseHold(); +        else if (samenetwork) +            managmentCommand("network-change samenetwork\n"); +        else +            managmentCommand("network-change\n");      }
 -    public void signalusr1() {
 -        mReleaseHold = false;
 +    @Override +    public void setPauseCallback(PausedStateCallback callback) { +        mPauseCallback = callback; +    } +    public void signalusr1() {          if (!mWaitingForRelease)
              managmentCommand("signal SIGUSR1\n");
          else
 | 
