mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Inform Tor about network connectivity. Dev task #53.
Note that some devices (I'm looking at you, Huawei U8110) misreport connectivity by failing to set EXTRA_NO_CONNECTIVITY and returning true from ConnectivityManager.getActiveNetworkInfo().isConnected() when there's no connectivity.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
ControlPort 59051
|
||||
CookieAuthentication 1
|
||||
DisableNetwork 1
|
||||
PidFile pid
|
||||
RunAsDaemon 1
|
||||
SafeSocks 1
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.briarproject.plugins.tor;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||
import static android.net.ConnectivityManager.EXTRA_NO_CONNECTIVITY;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
@@ -28,6 +30,7 @@ import java.util.zip.ZipInputStream;
|
||||
|
||||
import net.freehaven.tor.control.EventHandler;
|
||||
import net.freehaven.tor.control.TorControlConnection;
|
||||
|
||||
import org.briarproject.api.ContactId;
|
||||
import org.briarproject.api.TransportConfig;
|
||||
import org.briarproject.api.TransportId;
|
||||
@@ -38,9 +41,13 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
|
||||
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.util.StringUtils;
|
||||
|
||||
import socks.Socks5Proxy;
|
||||
import socks.SocksSocket;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Build;
|
||||
import android.os.FileObserver;
|
||||
|
||||
@@ -75,6 +82,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
private volatile ServerSocket socket = null;
|
||||
private volatile Socket controlSocket = null;
|
||||
private volatile TorControlConnection controlConnection = null;
|
||||
private volatile BroadcastReceiver networkStateReceiver = null;
|
||||
|
||||
TorPlugin(Executor pluginExecutor, Context appContext,
|
||||
ShutdownManager shutdownManager, DuplexPluginCallback callback,
|
||||
@@ -180,21 +188,14 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
// Now we should be able to connect to the new process
|
||||
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
||||
}
|
||||
running = true;
|
||||
// Read the PID of the Tor process so we can kill it if necessary
|
||||
pid = readPidFile();
|
||||
// Create a shutdown hook to ensure the Tor process is killed
|
||||
shutdownManager.addShutdownHook(new Runnable() {
|
||||
public void run() {
|
||||
if(tor != null) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Killing Tor via destroy()");
|
||||
tor.destroy();
|
||||
}
|
||||
if(pid != -1) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Killing Tor via killProcess(" + pid + ")");
|
||||
android.os.Process.killProcess(pid);
|
||||
}
|
||||
killTorProcess();
|
||||
killZombieProcess();
|
||||
}
|
||||
});
|
||||
// Open a control connection and authenticate using the cookie file
|
||||
@@ -203,7 +204,10 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
// Register to receive events from the Tor process
|
||||
controlConnection.setEventHandler(this);
|
||||
controlConnection.setEvents(Arrays.asList("NOTICE", "WARN", "ERR"));
|
||||
running = true;
|
||||
// Register to receive network status events
|
||||
networkStateReceiver = new NetworkStateReceiver();
|
||||
IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION);
|
||||
appContext.registerReceiver(networkStateReceiver, filter);
|
||||
// Bind a server socket to receive incoming hidden service connections
|
||||
pluginExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
@@ -368,6 +372,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
// Discard the header line
|
||||
if(scanner.hasNextLine()) scanner.nextLine();
|
||||
// Look for a Tor process with our package name
|
||||
boolean found = false;
|
||||
while(scanner.hasNextLine()) {
|
||||
String[] columns = scanner.nextLine().split("\\s+");
|
||||
if(columns.length < 3) break;
|
||||
@@ -377,8 +382,10 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Killing zombie process " + pid);
|
||||
android.os.Process.killProcess(pid);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if(!found) if(LOG.isLoggable(INFO)) LOG.info("No zombies found");
|
||||
scanner.close();
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
@@ -388,6 +395,19 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void killTorProcess() {
|
||||
if(tor != null) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Killing Tor via destroy()");
|
||||
tor.destroy();
|
||||
}
|
||||
if(pid != -1) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Killing Tor via killProcess(" + pid + ")");
|
||||
android.os.Process.killProcess(pid);
|
||||
}
|
||||
}
|
||||
|
||||
private void bind() {
|
||||
// If there's already a port number stored in config, reuse it
|
||||
String portString = callback.getConfig().get("port");
|
||||
@@ -493,9 +513,17 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private void enableNetwork(boolean enable) throws IOException {
|
||||
if(!running) return;
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Enabling network: " + enable);
|
||||
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
|
||||
}
|
||||
|
||||
public void stop() throws IOException {
|
||||
running = false;
|
||||
if(socket != null) tryToClose(socket);
|
||||
if(networkStateReceiver != null)
|
||||
appContext.unregisterReceiver(networkStateReceiver);
|
||||
try {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Stopping Tor");
|
||||
if(controlSocket == null)
|
||||
@@ -504,13 +532,13 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
controlConnection = new TorControlConnection(controlSocket);
|
||||
controlConnection.authenticate(read(cookieFile));
|
||||
}
|
||||
controlConnection.setConf("DisableNetwork", "1");
|
||||
controlConnection.shutdownTor("TERM");
|
||||
controlSocket.close();
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Killing Tor");
|
||||
if(tor != null) tor.destroy();
|
||||
if(pid != -1) android.os.Process.killProcess(pid);
|
||||
killTorProcess();
|
||||
killZombieProcess();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -603,4 +631,18 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
||||
latch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
private class NetworkStateReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent i) {
|
||||
// Note: Some devices fail to set this extra
|
||||
boolean online = !i.getBooleanExtra(EXTRA_NO_CONNECTIVITY, false);
|
||||
try {
|
||||
enableNetwork(online);
|
||||
} catch(IOException e) {
|
||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user