mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29: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
|
ControlPort 59051
|
||||||
CookieAuthentication 1
|
CookieAuthentication 1
|
||||||
|
DisableNetwork 1
|
||||||
PidFile pid
|
PidFile pid
|
||||||
RunAsDaemon 1
|
RunAsDaemon 1
|
||||||
SafeSocks 1
|
SafeSocks 1
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package org.briarproject.plugins.tor;
|
package org.briarproject.plugins.tor;
|
||||||
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
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.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
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.EventHandler;
|
||||||
import net.freehaven.tor.control.TorControlConnection;
|
import net.freehaven.tor.control.TorControlConnection;
|
||||||
|
|
||||||
import org.briarproject.api.ContactId;
|
import org.briarproject.api.ContactId;
|
||||||
import org.briarproject.api.TransportConfig;
|
import org.briarproject.api.TransportConfig;
|
||||||
import org.briarproject.api.TransportId;
|
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.DuplexPluginCallback;
|
||||||
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
|
||||||
import org.briarproject.util.StringUtils;
|
import org.briarproject.util.StringUtils;
|
||||||
|
|
||||||
import socks.Socks5Proxy;
|
import socks.Socks5Proxy;
|
||||||
import socks.SocksSocket;
|
import socks.SocksSocket;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.FileObserver;
|
import android.os.FileObserver;
|
||||||
|
|
||||||
@@ -75,6 +82,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
private volatile ServerSocket socket = null;
|
private volatile ServerSocket socket = null;
|
||||||
private volatile Socket controlSocket = null;
|
private volatile Socket controlSocket = null;
|
||||||
private volatile TorControlConnection controlConnection = null;
|
private volatile TorControlConnection controlConnection = null;
|
||||||
|
private volatile BroadcastReceiver networkStateReceiver = null;
|
||||||
|
|
||||||
TorPlugin(Executor pluginExecutor, Context appContext,
|
TorPlugin(Executor pluginExecutor, Context appContext,
|
||||||
ShutdownManager shutdownManager, DuplexPluginCallback callback,
|
ShutdownManager shutdownManager, DuplexPluginCallback callback,
|
||||||
@@ -180,21 +188,14 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
// Now we should be able to connect to the new process
|
// Now we should be able to connect to the new process
|
||||||
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
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
|
// Read the PID of the Tor process so we can kill it if necessary
|
||||||
pid = readPidFile();
|
pid = readPidFile();
|
||||||
// Create a shutdown hook to ensure the Tor process is killed
|
// Create a shutdown hook to ensure the Tor process is killed
|
||||||
shutdownManager.addShutdownHook(new Runnable() {
|
shutdownManager.addShutdownHook(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if(tor != null) {
|
killTorProcess();
|
||||||
if(LOG.isLoggable(INFO))
|
killZombieProcess();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Open a control connection and authenticate using the cookie file
|
// 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
|
// Register to receive events from the Tor process
|
||||||
controlConnection.setEventHandler(this);
|
controlConnection.setEventHandler(this);
|
||||||
controlConnection.setEvents(Arrays.asList("NOTICE", "WARN", "ERR"));
|
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
|
// Bind a server socket to receive incoming hidden service connections
|
||||||
pluginExecutor.execute(new Runnable() {
|
pluginExecutor.execute(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -368,6 +372,7 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
// Discard the header line
|
// Discard the header line
|
||||||
if(scanner.hasNextLine()) scanner.nextLine();
|
if(scanner.hasNextLine()) scanner.nextLine();
|
||||||
// Look for a Tor process with our package name
|
// Look for a Tor process with our package name
|
||||||
|
boolean found = false;
|
||||||
while(scanner.hasNextLine()) {
|
while(scanner.hasNextLine()) {
|
||||||
String[] columns = scanner.nextLine().split("\\s+");
|
String[] columns = scanner.nextLine().split("\\s+");
|
||||||
if(columns.length < 3) break;
|
if(columns.length < 3) break;
|
||||||
@@ -377,8 +382,10 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
if(LOG.isLoggable(INFO))
|
if(LOG.isLoggable(INFO))
|
||||||
LOG.info("Killing zombie process " + pid);
|
LOG.info("Killing zombie process " + pid);
|
||||||
android.os.Process.killProcess(pid);
|
android.os.Process.killProcess(pid);
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!found) if(LOG.isLoggable(INFO)) LOG.info("No zombies found");
|
||||||
scanner.close();
|
scanner.close();
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING))
|
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() {
|
private void bind() {
|
||||||
// If there's already a port number stored in config, reuse it
|
// If there's already a port number stored in config, reuse it
|
||||||
String portString = callback.getConfig().get("port");
|
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 {
|
public void stop() throws IOException {
|
||||||
running = false;
|
running = false;
|
||||||
if(socket != null) tryToClose(socket);
|
if(socket != null) tryToClose(socket);
|
||||||
|
if(networkStateReceiver != null)
|
||||||
|
appContext.unregisterReceiver(networkStateReceiver);
|
||||||
try {
|
try {
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Stopping Tor");
|
if(LOG.isLoggable(INFO)) LOG.info("Stopping Tor");
|
||||||
if(controlSocket == null)
|
if(controlSocket == null)
|
||||||
@@ -504,13 +532,13 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
controlConnection = new TorControlConnection(controlSocket);
|
controlConnection = new TorControlConnection(controlSocket);
|
||||||
controlConnection.authenticate(read(cookieFile));
|
controlConnection.authenticate(read(cookieFile));
|
||||||
}
|
}
|
||||||
|
controlConnection.setConf("DisableNetwork", "1");
|
||||||
controlConnection.shutdownTor("TERM");
|
controlConnection.shutdownTor("TERM");
|
||||||
controlSocket.close();
|
controlSocket.close();
|
||||||
} catch(IOException e) {
|
} catch(IOException e) {
|
||||||
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
if(LOG.isLoggable(INFO)) LOG.info("Killing Tor");
|
killTorProcess();
|
||||||
if(tor != null) tor.destroy();
|
killZombieProcess();
|
||||||
if(pid != -1) android.os.Process.killProcess(pid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,4 +631,18 @@ class TorPlugin implements DuplexPlugin, EventHandler {
|
|||||||
latch.countDown();
|
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