mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Merge branch 'start-plugins-async' into 'master'
Start plugins asynchronously This prevents other services from getting stuck behind the plugin manager while the Tor plugin is starting, which takes several seconds. The plugin manager waits for each plugin to start before stopping it. I've also added some canaries to plugins and services to ensure instances aren't started more than once. See merge request !181
This commit is contained in:
@@ -42,6 +42,7 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -81,10 +82,10 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
private final Context appContext;
|
||||
|
||||
// The following must only be accessed on the main UI thread
|
||||
private final Map<GroupId, Integer> contactCounts =
|
||||
new HashMap<GroupId, Integer>();
|
||||
private final Map<GroupId, Integer> forumCounts =
|
||||
new HashMap<GroupId, Integer>();
|
||||
private final Map<GroupId, Integer> contactCounts = new HashMap<>();
|
||||
private final Map<GroupId, Integer> forumCounts = new HashMap<>();
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
|
||||
private int contactTotal = 0, forumTotal = 0;
|
||||
private int nextRequestId = 0;
|
||||
private GroupId visibleGroup = null;
|
||||
@@ -106,6 +107,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
@Override
|
||||
public void startService() throws ServiceException {
|
||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||
try {
|
||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
} catch (DbException e) {
|
||||
@@ -116,6 +118,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
@Override
|
||||
public void stopService() throws ServiceException {
|
||||
Future<Void> f = androidExecutor.submit(new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() {
|
||||
clearPrivateMessageNotification();
|
||||
clearForumPostNotification();
|
||||
@@ -125,9 +128,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
});
|
||||
try {
|
||||
f.get();
|
||||
} catch (InterruptedException e) {
|
||||
throw new ServiceException(e);
|
||||
} catch (ExecutionException e) {
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new ServiceException(e);
|
||||
}
|
||||
}
|
||||
@@ -150,6 +151,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
nm.cancel(INTRODUCTION_SUCCESS_NOTIFICATION_ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof SettingsUpdatedEvent) {
|
||||
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
|
||||
@@ -180,6 +182,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
private void loadSettings() {
|
||||
dbExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
||||
@@ -191,8 +194,10 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPrivateMessageNotification(final GroupId g) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = contactCounts.get(g);
|
||||
if (count == null) contactCounts.put(g, 1);
|
||||
@@ -204,8 +209,10 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearPrivateMessageNotification(final GroupId g) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = contactCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
@@ -275,8 +282,10 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
return defaults;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showForumPostNotification(final GroupId g) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = forumCounts.get(g);
|
||||
if (count == null) forumCounts.put(g, 1);
|
||||
@@ -288,8 +297,10 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearForumPostNotification(final GroupId g) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Integer count = forumCounts.remove(g);
|
||||
if (count == null) return; // Already cleared
|
||||
@@ -347,16 +358,20 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void blockNotification(final GroupId g) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
visibleGroup = g;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unblockNotification(final GroupId g) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (g.equals(visibleGroup)) visibleGroup = null;
|
||||
}
|
||||
@@ -365,6 +380,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
private void showNotificationForPrivateConversation(final ContactId c) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
GroupId group = messagingManager.getConversationId(c);
|
||||
@@ -379,6 +395,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
|
||||
private void showIntroductionSucceededNotification(final Contact c) {
|
||||
androidExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
NotificationCompat.Builder b =
|
||||
new NotificationCompat.Builder(appContext);
|
||||
|
||||
@@ -9,9 +9,9 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import org.briarproject.android.api.AndroidExecutor;
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.api.TransportId;
|
||||
import org.briarproject.android.api.AndroidExecutor;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.crypto.PseudoRandom;
|
||||
import org.briarproject.api.keyagreement.KeyAgreementConnection;
|
||||
@@ -41,6 +41,7 @@ import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorCompletionService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||
@@ -80,6 +81,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
private final Backoff backoff;
|
||||
private final DuplexPluginCallback callback;
|
||||
private final int maxLatency;
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
|
||||
private volatile boolean running = false;
|
||||
private volatile boolean wasEnabledByUs = false;
|
||||
@@ -101,24 +103,30 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
this.maxLatency = maxLatency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportId getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxIdleTime() {
|
||||
// Bluetooth detects dead connections so we don't need keepalives
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() throws IOException {
|
||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
|
||||
// with a message queue, so submit it to the AndroidExecutor
|
||||
try {
|
||||
adapter = androidExecutor.submit(new Callable<BluetoothAdapter>() {
|
||||
@Override
|
||||
public BluetoothAdapter call() throws Exception {
|
||||
return BluetoothAdapter.getDefaultAdapter();
|
||||
}
|
||||
@@ -158,6 +166,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
|
||||
private void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isRunning()) return;
|
||||
String address = AndroidUtils.getBluetoothAddress(appContext,
|
||||
@@ -238,6 +247,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
return new DroidtoothTransportConnection(this, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
running = false;
|
||||
if (receiver != null) appContext.unregisterReceiver(receiver);
|
||||
@@ -249,18 +259,22 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return running && adapter.isEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPollingInterval() {
|
||||
return backoff.getPollingInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void poll(Collection<ContactId> connected) {
|
||||
if (!isRunning()) return;
|
||||
backoff.increment();
|
||||
@@ -275,6 +289,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
final String uuid = e.getValue().get(PROP_UUID);
|
||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
BluetoothSocket s = connect(address, uuid);
|
||||
@@ -327,6 +342,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DuplexTransportConnection createConnection(ContactId c) {
|
||||
if (!isRunning()) return null;
|
||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||
@@ -340,10 +356,12 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
return new DroidtoothTransportConnection(this, s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInvitations() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||
long timeout, boolean alice) {
|
||||
if (!isRunning()) return null;
|
||||
@@ -361,9 +379,8 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
}
|
||||
// Create the background tasks
|
||||
CompletionService<BluetoothSocket> complete =
|
||||
new ExecutorCompletionService<BluetoothSocket>(ioExecutor);
|
||||
List<Future<BluetoothSocket>> futures =
|
||||
new ArrayList<Future<BluetoothSocket>>();
|
||||
new ExecutorCompletionService<>(ioExecutor);
|
||||
List<Future<BluetoothSocket>> futures = new ArrayList<>();
|
||||
if (alice) {
|
||||
// Return the first connected socket
|
||||
futures.add(complete.submit(new ListeningTask(ss)));
|
||||
@@ -398,6 +415,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
private void closeSockets(final List<Future<BluetoothSocket>> futures,
|
||||
final BluetoothSocket chosen) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (Future<BluetoothSocket> f : futures) {
|
||||
try {
|
||||
@@ -413,9 +431,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
} catch (InterruptedException e) {
|
||||
LOG.info("Interrupted while closing sockets");
|
||||
return;
|
||||
} catch (ExecutionException e) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
||||
} catch (IOException e) {
|
||||
} catch (ExecutionException | IOException e) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info(e.toString());
|
||||
}
|
||||
}
|
||||
@@ -423,14 +439,15 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsKeyAgreement() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public KeyAgreementListener createKeyAgreementListener(
|
||||
byte[] localCommitment) {
|
||||
@Override
|
||||
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||
// No truncation necessary because COMMIT_LENGTH = 16
|
||||
UUID uuid = UUID.nameUUIDFromBytes(localCommitment);
|
||||
UUID uuid = UUID.nameUUIDFromBytes(commitment);
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
|
||||
// Bind a server socket for receiving invitation connections
|
||||
BluetoothServerSocket ss;
|
||||
@@ -448,8 +465,9 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
return new BluetoothKeyAgreementListener(d, ss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DuplexTransportConnection createKeyAgreementConnection(
|
||||
byte[] remoteCommitment, TransportDescriptor d, long timeout) {
|
||||
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||
if (!isRunning()) return null;
|
||||
if (!ID.equals(d.getIdentifier())) return null;
|
||||
TransportProperties p = d.getProperties();
|
||||
@@ -457,7 +475,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
String address = p.get(PROP_ADDRESS);
|
||||
if (StringUtils.isNullOrEmpty(address)) return null;
|
||||
// No truncation necessary because COMMIT_LENGTH = 16
|
||||
UUID uuid = UUID.nameUUIDFromBytes(remoteCommitment);
|
||||
UUID uuid = UUID.nameUUIDFromBytes(commitment);
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connecting to key agreement UUID " + uuid);
|
||||
BluetoothSocket s = connect(address, uuid.toString());
|
||||
@@ -533,7 +551,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
||||
private static class DiscoveryReceiver extends BroadcastReceiver {
|
||||
|
||||
private final CountDownLatch finished = new CountDownLatch(1);
|
||||
private final List<String> addresses = new ArrayList<String>();
|
||||
private final List<String> addresses = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context ctx, Intent intent) {
|
||||
|
||||
@@ -35,6 +35,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||
running = true;
|
||||
// Register to receive network status events
|
||||
networkStateReceiver = new NetworkStateReceiver();
|
||||
|
||||
@@ -51,6 +51,7 @@ import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipInputStream;
|
||||
@@ -94,6 +95,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
private final File torDirectory, torFile, geoIpFile, configFile;
|
||||
private final File doneFile, cookieFile;
|
||||
private final PowerManager.WakeLock wakeLock;
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
|
||||
private volatile boolean running = false;
|
||||
private volatile ServerSocket socket = null;
|
||||
@@ -130,19 +132,24 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
wakeLock.setReferenceCounted(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportId getId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLatency() {
|
||||
return maxLatency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxIdleTime() {
|
||||
return maxIdleTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() throws IOException {
|
||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||
// Try to connect to an existing Tor process if there is one
|
||||
boolean startProcess = false;
|
||||
try {
|
||||
@@ -210,13 +217,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
// Now we should be able to connect to the new process
|
||||
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
|
||||
}
|
||||
running = true;
|
||||
// Open a control connection and authenticate using the cookie file
|
||||
controlConnection = new TorControlConnection(controlSocket);
|
||||
controlConnection.authenticate(read(cookieFile));
|
||||
// Tell Tor to exit when the control connection is closed
|
||||
controlConnection.takeOwnership();
|
||||
controlConnection.resetConf(Collections.singletonList(OWNER));
|
||||
running = true;
|
||||
// Register to receive events from the Tor process
|
||||
controlConnection.setEventHandler(this);
|
||||
controlConnection.setEvents(Arrays.asList(EVENTS));
|
||||
@@ -226,7 +233,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
if (phase != null && phase.contains("PROGRESS=100")) {
|
||||
LOG.info("Tor has already bootstrapped");
|
||||
connectionStatus.setBootstrapped();
|
||||
sendDevReports();
|
||||
}
|
||||
}
|
||||
// Register to receive network status events
|
||||
@@ -369,6 +375,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
private void bind() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// If there's already a port number stored in config, reuse it
|
||||
String portString = callback.getSettings().get("port");
|
||||
@@ -398,6 +405,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
callback.mergeSettings(s);
|
||||
// Create a hidden service if necessary
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
publishHiddenService(localPort);
|
||||
}
|
||||
@@ -486,6 +494,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws IOException {
|
||||
running = false;
|
||||
tryToClose(socket);
|
||||
@@ -508,18 +517,22 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
wakeLock.release();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return running && connectionStatus.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPollingInterval() {
|
||||
return backoff.getPollingInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void poll(Collection<ContactId> connected) {
|
||||
if (!isRunning()) return;
|
||||
backoff.increment();
|
||||
@@ -530,6 +543,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
private void connectAndCallBack(final ContactId c) {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DuplexTransportConnection d = createConnection(c);
|
||||
if (d != null) {
|
||||
@@ -540,6 +554,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DuplexTransportConnection createConnection(ContactId c) {
|
||||
if (!isRunning()) return null;
|
||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
||||
@@ -566,61 +581,77 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInvitations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DuplexTransportConnection createInvitationConnection(PseudoRandom r,
|
||||
long timeout, boolean alice) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsKeyAgreement() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public KeyAgreementListener createKeyAgreementListener(
|
||||
byte[] commitment) {
|
||||
@Override
|
||||
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DuplexTransportConnection createKeyAgreementConnection(
|
||||
byte[] commitment, TransportDescriptor d, long timeout) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void circuitStatus(String status, String id, String path) {
|
||||
if (status.equals("BUILT") &&
|
||||
connectionStatus.getAndSetCircuitBuilt()) {
|
||||
LOG.info("First circuit built");
|
||||
backoff.reset();
|
||||
if (isRunning()) callback.transportEnabled();
|
||||
if (isRunning()) {
|
||||
sendDevReports();
|
||||
callback.transportEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void streamStatus(String status, String id, String target) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void orConnStatus(String status, String orName) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bandwidthUsed(long read, long written) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newDescriptors(List<String> orList) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void message(String severity, String msg) {
|
||||
if (LOG.isLoggable(INFO)) LOG.info(severity + " " + msg);
|
||||
if (severity.equals("NOTICE") && msg.startsWith("Bootstrapped 100%")) {
|
||||
connectionStatus.setBootstrapped();
|
||||
sendDevReports();
|
||||
backoff.reset();
|
||||
if (isRunning()) callback.transportEnabled();
|
||||
if (isRunning()) {
|
||||
sendDevReports();
|
||||
callback.transportEnabled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unrecognized(String type, String msg) {
|
||||
if (type.equals("HS_DESC") && msg.startsWith("UPLOADED"))
|
||||
LOG.info("Descriptor uploaded");
|
||||
@@ -642,6 +673,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
if (e instanceof SettingsUpdatedEvent) {
|
||||
if (((SettingsUpdatedEvent) e).getNamespace().equals("tor")) {
|
||||
@@ -653,13 +685,14 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
|
||||
private void updateConnectionStatus() {
|
||||
ioExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!running) return;
|
||||
|
||||
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||
ConnectivityManager cm = (ConnectivityManager) o;
|
||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||
boolean online = net != null && net.isConnected();
|
||||
boolean online = net != null && net.isConnected();
|
||||
boolean wifi = online && net.getType() == TYPE_WIFI;
|
||||
String country = locationUtils.getCurrentCountry();
|
||||
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
||||
|
||||
Reference in New Issue
Block a user