| Index: src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| diff --git a/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java b/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| index 0017d5aa5089caf618c35ce77c8a5b5bfc9ee370..1134f2c1edb3866c76b5ba074e51cc212ec2d4b8 100644 |
| --- a/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| +++ b/src/org/adblockplus/android/configurators/IptablesProxyConfigurator.java |
| @@ -19,16 +19,23 @@ package org.adblockplus.android.configurators; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| +import java.io.IOException; |
| import java.net.InetAddress; |
| +import java.util.ArrayList; |
| import java.util.List; |
| +import java.util.concurrent.Semaphore; |
| +import java.util.concurrent.TimeoutException; |
| import org.adblockplus.android.Utils; |
| -import com.stericson.RootTools.RootTools; |
| - |
| import android.content.Context; |
| import android.util.Log; |
| +import com.stericson.RootTools.RootTools; |
| +import com.stericson.RootTools.exceptions.RootDeniedException; |
| +import com.stericson.RootTools.execution.Command; |
| +import com.stericson.RootTools.execution.Shell; |
| + |
| /** |
| * Proxy registration using RootTools and iptables. |
| */ |
| @@ -48,11 +55,28 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| this.context = context; |
| } |
| + private static List<String> sendShell(final String command, final int timeout) throws IOException, TimeoutException, |
| + RootDeniedException |
| + { |
| + final CommandOutput cmd = new CommandOutput(0, DEFAULT_TIMEOUT, command); |
| + |
| + Shell.runRootCommand(cmd); |
| + |
| + cmd.waitForCompletion(); |
| + |
| + return cmd.output; |
| + } |
| + |
| @Override |
| public boolean initialize() |
| { |
| try |
| { |
| + // If we don't set `handlerEnabled` to `false`, RootTools uses Handlers |
| + // which get executed on the UI thread which in fact renders it useless |
| + // for our purpose (as it either finished too late or blocks forever). |
| + RootTools.handlerEnabled = false; |
| + |
| if (!RootTools.isAccessGiven()) |
| { |
| throw new IllegalStateException("No root access"); |
| @@ -67,14 +91,14 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| final String path = ipt.getAbsolutePath(); |
| - RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
| + sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
| boolean compatible = false; |
| boolean version = false; |
| final String command = path + " --version\n" + path + " -L -t nat -n\n"; |
| - final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); |
| + final List<String> result = sendShell(command, DEFAULT_TIMEOUT); |
| for (final String line : result) |
| { |
| @@ -99,6 +123,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| } |
| catch (final Exception e) |
| { |
| + Log.e(TAG, "iptables setup failed", e); |
| return false; |
| } |
| } |
| @@ -117,7 +142,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| cmd.append(this.iptables); |
| cmd.append(IPTABLES_ADD_HTTP.replace("{{PORT}}", String.valueOf(port))); |
| - RootTools.sendShell(cmd.toString(), DEFAULT_TIMEOUT); |
| + sendShell(cmd.toString(), DEFAULT_TIMEOUT); |
| this.isRegistered = true; |
| @@ -136,7 +161,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| { |
| try |
| { |
| - RootTools.sendShell(this.iptables + " -t nat -F OUTPUT", DEFAULT_TIMEOUT); |
| + sendShell(this.iptables + " -t nat -F OUTPUT", DEFAULT_TIMEOUT); |
| } |
| catch (final Exception e) |
| { |
| @@ -172,14 +197,14 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| final String path = ipt.getAbsolutePath(); |
| - RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
| + sendShell("chmod 700 " + path, DEFAULT_TIMEOUT); |
| boolean compatible = false; |
| boolean version = false; |
| String command = path + " --version\n" + path + " -L -t nat -n\n"; |
| - final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT); |
| + final List<String> result = sendShell(command, DEFAULT_TIMEOUT); |
| for (final String line : result) |
| { |
| @@ -200,7 +225,7 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| command = path + " -L -t nat -n\n"; |
| - return RootTools.sendShell(command, DEFAULT_TIMEOUT); |
| + return sendShell(command, DEFAULT_TIMEOUT); |
| } |
| catch (final Throwable t) |
| { |
| @@ -231,4 +256,41 @@ public class IptablesProxyConfigurator implements ProxyConfigurator |
| { |
| return "[ProxyConfigurator: " + this.getType() + "]"; |
| } |
| + |
| + private final static class CommandOutput extends Command |
| + { |
| + private final Semaphore completionNotify = new Semaphore(1); |
| + |
| + public List<String> output = new ArrayList<String>(); |
| + |
| + public CommandOutput(final int id, final int timeout, final String command) |
| + { |
| + super(id, timeout, command); |
| + |
| + this.completionNotify.acquireUninterruptibly(); |
| + } |
| + |
| + @Override |
| + public void commandOutput(int id, String line) |
| + { |
| + this.output.add(line); |
| + } |
| + |
| + @Override |
| + public void commandCompleted(int id, int exitCode) |
| + { |
| + this.completionNotify.release(); |
| + } |
| + |
| + @Override |
| + public void commandTerminated(int id, String reason) |
| + { |
| + this.completionNotify.release(); |
| + } |
| + |
| + public void waitForCompletion() |
| + { |
| + this.completionNotify.acquireUninterruptibly(); |
| + } |
| + } |
| } |