mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Compare commits
1 Commits
priority-e
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
779d873a70 |
@@ -3,7 +3,7 @@
|
|||||||
<module name="briar-headless" />
|
<module name="briar-headless" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
<option name="ALTERNATIVE_JRE_PATH" />
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
|
<option name="PACKAGE_NAME" value="" />
|
||||||
<option name="MAIN_CLASS_NAME" value="" />
|
<option name="MAIN_CLASS_NAME" value="" />
|
||||||
<option name="METHOD_NAME" value="" />
|
<option name="METHOD_NAME" value="" />
|
||||||
<option name="TEST_OBJECT" value="package" />
|
<option name="TEST_OBJECT" value="package" />
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import com.android.build.gradle.tasks.MergeResources
|
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
apply from: 'witness.gradle'
|
apply from: 'witness.gradle'
|
||||||
@@ -11,8 +9,8 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 10105
|
versionCode 10103
|
||||||
versionName "1.1.5"
|
versionName "1.1.3"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
@@ -31,9 +29,8 @@ configurations {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
tor 'org.briarproject:tor-android:0.3.4.8@zip'
|
tor 'org.briarproject:tor-android:0.3.4.8@zip'
|
||||||
tor 'org.briarproject:obfs4proxy-android:0.0.7@zip'
|
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||||
|
|
||||||
@@ -42,29 +39,13 @@ dependencies {
|
|||||||
testImplementation "org.jmock:jmock:2.8.2"
|
testImplementation "org.jmock:jmock:2.8.2"
|
||||||
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||||
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
def torBinariesDir = 'src/main/res/raw'
|
project.afterEvaluate {
|
||||||
|
copy {
|
||||||
task cleanTorBinaries {
|
from configurations.tor.collect { zipTree(it) }
|
||||||
doLast {
|
into 'src/main/res/raw'
|
||||||
delete fileTree(torBinariesDir) { include '*.zip' }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clean.dependsOn cleanTorBinaries
|
|
||||||
|
|
||||||
task unpackTorBinaries {
|
|
||||||
doLast {
|
|
||||||
copy {
|
|
||||||
from configurations.tor.collect { zipTree(it) }
|
|
||||||
into torBinariesDir
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dependsOn cleanTorBinaries
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(MergeResources) {
|
|
||||||
inputs.dir torBinariesDir
|
|
||||||
dependsOn unpackTorBinaries
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
package org.briarproject.bramble;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.battery.AndroidBatteryModule;
|
|
||||||
import org.briarproject.bramble.network.AndroidNetworkModule;
|
|
||||||
|
|
||||||
public interface BrambleAndroidEagerSingletons {
|
|
||||||
|
|
||||||
void inject(AndroidBatteryModule.EagerSingletons init);
|
|
||||||
|
|
||||||
void inject(AndroidNetworkModule.EagerSingletons init);
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble;
|
package org.briarproject.bramble;
|
||||||
|
|
||||||
import org.briarproject.bramble.battery.AndroidBatteryModule;
|
|
||||||
import org.briarproject.bramble.network.AndroidNetworkModule;
|
import org.briarproject.bramble.network.AndroidNetworkModule;
|
||||||
import org.briarproject.bramble.plugin.tor.CircumventionModule;
|
import org.briarproject.bramble.plugin.tor.CircumventionModule;
|
||||||
import org.briarproject.bramble.system.AndroidSystemModule;
|
import org.briarproject.bramble.system.AndroidSystemModule;
|
||||||
@@ -8,15 +7,10 @@ import org.briarproject.bramble.system.AndroidSystemModule;
|
|||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
|
|
||||||
@Module(includes = {
|
@Module(includes = {
|
||||||
AndroidBatteryModule.class,
|
|
||||||
AndroidNetworkModule.class,
|
AndroidNetworkModule.class,
|
||||||
AndroidSystemModule.class,
|
AndroidSystemModule.class,
|
||||||
CircumventionModule.class
|
CircumventionModule.class
|
||||||
})
|
})
|
||||||
public class BrambleAndroidModule {
|
public class BrambleAndroidModule {
|
||||||
|
|
||||||
public static void initEagerSingletons(BrambleAndroidEagerSingletons c) {
|
|
||||||
c.inject(new AndroidBatteryModule.EagerSingletons());
|
|
||||||
c.inject(new AndroidNetworkModule.EagerSingletons());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,81 +0,0 @@
|
|||||||
package org.briarproject.bramble.battery;
|
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
|
||||||
import org.briarproject.bramble.api.battery.event.BatteryEvent;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.Service;
|
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import static android.content.Intent.ACTION_BATTERY_CHANGED;
|
|
||||||
import static android.content.Intent.ACTION_POWER_CONNECTED;
|
|
||||||
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
|
|
||||||
import static android.os.BatteryManager.EXTRA_PLUGGED;
|
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
|
||||||
|
|
||||||
class AndroidBatteryManager implements BatteryManager, Service {
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
|
||||||
getLogger(AndroidBatteryManager.class.getName());
|
|
||||||
|
|
||||||
private final Context appContext;
|
|
||||||
private final EventBus eventBus;
|
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
private volatile BroadcastReceiver batteryReceiver = null;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
AndroidBatteryManager(Application app, EventBus eventBus) {
|
|
||||||
this.appContext = app.getApplicationContext();
|
|
||||||
this.eventBus = eventBus;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCharging() {
|
|
||||||
// Get the sticky intent for ACTION_BATTERY_CHANGED
|
|
||||||
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
|
|
||||||
Intent i = appContext.registerReceiver(null, filter);
|
|
||||||
if (i == null) return false;
|
|
||||||
int status = i.getIntExtra(EXTRA_PLUGGED, 0);
|
|
||||||
return status != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startService() {
|
|
||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
|
||||||
batteryReceiver = new BatteryReceiver();
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.addAction(ACTION_POWER_CONNECTED);
|
|
||||||
filter.addAction(ACTION_POWER_DISCONNECTED);
|
|
||||||
appContext.registerReceiver(batteryReceiver, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopService() {
|
|
||||||
if (batteryReceiver != null)
|
|
||||||
appContext.unregisterReceiver(batteryReceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
private class BatteryReceiver extends BroadcastReceiver {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context ctx, Intent i) {
|
|
||||||
String action = i.getAction();
|
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
|
|
||||||
if (ACTION_POWER_CONNECTED.equals(action))
|
|
||||||
eventBus.broadcast(new BatteryEvent(true));
|
|
||||||
else if (ACTION_POWER_DISCONNECTED.equals(action))
|
|
||||||
eventBus.broadcast(new BatteryEvent(false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package org.briarproject.bramble.battery;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import dagger.Module;
|
|
||||||
import dagger.Provides;
|
|
||||||
|
|
||||||
@Module
|
|
||||||
public class AndroidBatteryModule {
|
|
||||||
|
|
||||||
public static class EagerSingletons {
|
|
||||||
@Inject
|
|
||||||
BatteryManager batteryManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
BatteryManager provideBatteryManager(LifecycleManager lifecycleManager,
|
|
||||||
AndroidBatteryManager batteryManager) {
|
|
||||||
lifecycleManager.registerService(batteryManager);
|
|
||||||
return batteryManager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ package org.briarproject.bramble.network;
|
|||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.network.NetworkManager;
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
@@ -12,11 +11,6 @@ import dagger.Provides;
|
|||||||
@Module
|
@Module
|
||||||
public class AndroidNetworkModule {
|
public class AndroidNetworkModule {
|
||||||
|
|
||||||
public static class EagerSingletons {
|
|
||||||
@Inject
|
|
||||||
NetworkManager networkManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
|
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
|
||||||
|
|||||||
@@ -16,27 +16,18 @@ import org.briarproject.bramble.api.plugin.PluginException;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
|
||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
|
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED;
|
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
|
||||||
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
|
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
|
||||||
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
|
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
|
||||||
@@ -46,12 +37,8 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERA
|
|||||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
|
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
|
||||||
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
|
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
|
||||||
import static android.bluetooth.BluetoothAdapter.STATE_ON;
|
import static android.bluetooth.BluetoothAdapter.STATE_ON;
|
||||||
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
|
|
||||||
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
|
||||||
import static java.util.logging.Level.INFO;
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -60,11 +47,8 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
|
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
|
||||||
|
|
||||||
private static final int MAX_DISCOVERY_MS = 10_000;
|
|
||||||
|
|
||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
private final Clock clock;
|
|
||||||
|
|
||||||
private volatile boolean wasEnabledByUs = false;
|
private volatile boolean wasEnabledByUs = false;
|
||||||
private volatile BluetoothStateReceiver receiver = null;
|
private volatile BluetoothStateReceiver receiver = null;
|
||||||
@@ -74,13 +58,12 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
|
|
||||||
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
|
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
|
||||||
Executor ioExecutor, AndroidExecutor androidExecutor,
|
Executor ioExecutor, AndroidExecutor androidExecutor,
|
||||||
Context appContext, SecureRandom secureRandom, Clock clock,
|
Context appContext, SecureRandom secureRandom, Backoff backoff,
|
||||||
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
|
DuplexPluginCallback callback, int maxLatency) {
|
||||||
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
|
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
|
||||||
maxLatency);
|
maxLatency);
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.clock = clock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -160,7 +143,11 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void tryToClose(@Nullable BluetoothServerSocket ss) {
|
void tryToClose(@Nullable BluetoothServerSocket ss) {
|
||||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
try {
|
||||||
|
if (ss != null) ss.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -190,77 +177,17 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
s.connect();
|
s.connect();
|
||||||
return wrapSocket(s);
|
return wrapSocket(s);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
IoUtils.tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void tryToClose(@Nullable Closeable c) {
|
||||||
@Nullable
|
|
||||||
DuplexTransportConnection discoverAndConnect(String uuid) {
|
|
||||||
if (adapter == null) return null;
|
|
||||||
for (String address : discoverDevices()) {
|
|
||||||
try {
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Connecting to " + scrubMacAddress(address));
|
|
||||||
return connectTo(address, uuid);
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
|
||||||
LOG.info("Could not connect to "
|
|
||||||
+ scrubMacAddress(address));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG.info("Could not connect to any devices");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Collection<String> discoverDevices() {
|
|
||||||
List<String> addresses = new ArrayList<>();
|
|
||||||
BlockingQueue<Intent> intents = new LinkedBlockingQueue<>();
|
|
||||||
DiscoveryReceiver receiver = new DiscoveryReceiver(intents);
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.addAction(ACTION_DISCOVERY_STARTED);
|
|
||||||
filter.addAction(ACTION_DISCOVERY_FINISHED);
|
|
||||||
filter.addAction(ACTION_FOUND);
|
|
||||||
appContext.registerReceiver(receiver, filter);
|
|
||||||
try {
|
try {
|
||||||
if (adapter.startDiscovery()) {
|
if (c != null) c.close();
|
||||||
long now = clock.currentTimeMillis();
|
} catch (IOException e) {
|
||||||
long end = now + MAX_DISCOVERY_MS;
|
logException(LOG, WARNING, e);
|
||||||
while (now < end) {
|
|
||||||
Intent i = intents.poll(end - now, MILLISECONDS);
|
|
||||||
if (i == null) break;
|
|
||||||
String action = i.getAction();
|
|
||||||
if (ACTION_DISCOVERY_STARTED.equals(action)) {
|
|
||||||
LOG.info("Discovery started");
|
|
||||||
} else if (ACTION_DISCOVERY_FINISHED.equals(action)) {
|
|
||||||
LOG.info("Discovery finished");
|
|
||||||
break;
|
|
||||||
} else if (ACTION_FOUND.equals(action)) {
|
|
||||||
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
|
|
||||||
String address = d.getAddress();
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Discovered " + scrubMacAddress(address));
|
|
||||||
if (!addresses.contains(address))
|
|
||||||
addresses.add(address);
|
|
||||||
}
|
|
||||||
now = clock.currentTimeMillis();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOG.info("Could not start discovery");
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOG.info("Interrupted while discovering devices");
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
} finally {
|
|
||||||
LOG.info("Cancelling discovery");
|
|
||||||
adapter.cancelDiscovery();
|
|
||||||
appContext.unregisterReceiver(receiver);
|
|
||||||
}
|
}
|
||||||
// Shuffle the addresses so we don't always try the same one first
|
|
||||||
Collections.shuffle(addresses);
|
|
||||||
return addresses;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||||
@@ -280,18 +207,4 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DiscoveryReceiver extends BroadcastReceiver {
|
|
||||||
|
|
||||||
private final BlockingQueue<Intent> intents;
|
|
||||||
|
|
||||||
private DiscoveryReceiver(BlockingQueue<Intent> intents) {
|
|
||||||
this.intents = intents;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context ctx, Intent intent) {
|
|
||||||
intents.add(intent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -34,19 +33,17 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
|
|||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
private final SecureRandom secureRandom;
|
private final SecureRandom secureRandom;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final Clock clock;
|
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
|
|
||||||
public AndroidBluetoothPluginFactory(Executor ioExecutor,
|
public AndroidBluetoothPluginFactory(Executor ioExecutor,
|
||||||
AndroidExecutor androidExecutor, Context appContext,
|
AndroidExecutor androidExecutor, Context appContext,
|
||||||
SecureRandom secureRandom, EventBus eventBus, Clock clock,
|
SecureRandom secureRandom, EventBus eventBus,
|
||||||
BackoffFactory backoffFactory) {
|
BackoffFactory backoffFactory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.secureRandom = secureRandom;
|
this.secureRandom = secureRandom;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.clock = clock;
|
|
||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +65,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
|
|||||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
|
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
|
||||||
connectionLimiter, ioExecutor, androidExecutor, appContext,
|
connectionLimiter, ioExecutor, androidExecutor, appContext,
|
||||||
secureRandom, clock, backoff, callback, MAX_LATENCY);
|
secureRandom, backoff, callback, MAX_LATENCY);
|
||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
|
||||||
import org.briarproject.bramble.api.network.NetworkManager;
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
@@ -42,18 +41,17 @@ class AndroidTorPlugin extends TorPlugin {
|
|||||||
Context appContext, NetworkManager networkManager,
|
Context appContext, NetworkManager networkManager,
|
||||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||||
Clock clock, ResourceProvider resourceProvider,
|
Clock clock, ResourceProvider resourceProvider,
|
||||||
CircumventionProvider circumventionProvider,
|
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||||
BatteryManager batteryManager, Backoff backoff,
|
|
||||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||||
int maxIdleTime) {
|
int maxIdleTime) {
|
||||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
clock, resourceProvider, circumventionProvider, backoff,
|
||||||
backoff, callback, architecture, maxLatency, maxIdleTime,
|
callback, architecture, maxLatency, maxIdleTime,
|
||||||
appContext.getDir("tor", MODE_PRIVATE));
|
appContext.getDir("tor", MODE_PRIVATE));
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
PowerManager pm = (PowerManager)
|
PowerManager pm = (PowerManager)
|
||||||
appContext.getSystemService(POWER_SERVICE);
|
appContext.getSystemService(POWER_SERVICE);
|
||||||
if (pm == null) throw new AssertionError();
|
assert pm != null;
|
||||||
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
|
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
|
||||||
WAKE_LOCK_TAG, 1, MINUTES);
|
WAKE_LOCK_TAG, 1, MINUTES);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.briarproject.bramble.plugin.tor;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.network.NetworkManager;
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
@@ -49,7 +48,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
|||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
private final ResourceProvider resourceProvider;
|
private final ResourceProvider resourceProvider;
|
||||||
private final CircumventionProvider circumventionProvider;
|
private final CircumventionProvider circumventionProvider;
|
||||||
private final BatteryManager batteryManager;
|
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
|
||||||
public AndroidTorPluginFactory(Executor ioExecutor,
|
public AndroidTorPluginFactory(Executor ioExecutor,
|
||||||
@@ -57,8 +55,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
|||||||
NetworkManager networkManager, LocationUtils locationUtils,
|
NetworkManager networkManager, LocationUtils locationUtils,
|
||||||
EventBus eventBus, SocketFactory torSocketFactory,
|
EventBus eventBus, SocketFactory torSocketFactory,
|
||||||
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
|
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
|
||||||
CircumventionProvider circumventionProvider,
|
CircumventionProvider circumventionProvider, Clock clock) {
|
||||||
BatteryManager batteryManager, Clock clock) {
|
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
@@ -69,7 +66,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
|||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
this.resourceProvider = resourceProvider;
|
this.resourceProvider = resourceProvider;
|
||||||
this.circumventionProvider = circumventionProvider;
|
this.circumventionProvider = circumventionProvider;
|
||||||
this.batteryManager = batteryManager;
|
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +104,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
|||||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
|
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
|
||||||
appContext, networkManager, locationUtils, torSocketFactory,
|
appContext, networkManager, locationUtils, torSocketFactory,
|
||||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
clock, resourceProvider, circumventionProvider, backoff,
|
||||||
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble.system;
|
package org.briarproject.bramble.system;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.bluetooth.BluetoothDevice;
|
import android.bluetooth.BluetoothDevice;
|
||||||
@@ -27,7 +26,7 @@ import static android.provider.Settings.Secure.ANDROID_ID;
|
|||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
|
||||||
|
|
||||||
private static final int SEED_LENGTH = 32;
|
private static final int SEED_LENGTH = 32;
|
||||||
|
|
||||||
@@ -38,7 +37,6 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
|||||||
appContext = app.getApplicationContext();
|
appContext = app.getApplicationContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("HardwareIds")
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
|
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
|
||||||
super.writeToEntropyPool(out);
|
super.writeToEntropyPool(out);
|
||||||
@@ -51,14 +49,12 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
|||||||
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
|
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
|
||||||
if (id != null) out.writeUTF(id);
|
if (id != null) out.writeUTF(id);
|
||||||
Parcel parcel = Parcel.obtain();
|
Parcel parcel = Parcel.obtain();
|
||||||
WifiManager wm = (WifiManager) appContext.getApplicationContext()
|
WifiManager wm =
|
||||||
.getSystemService(WIFI_SERVICE);
|
(WifiManager) appContext.getSystemService(WIFI_SERVICE);
|
||||||
if (wm != null) {
|
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
|
||||||
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
|
if (configs != null) {
|
||||||
if (configs != null) {
|
for (WifiConfiguration config : configs)
|
||||||
for (WifiConfiguration config : configs)
|
parcel.writeParcelable(config, 0);
|
||||||
parcel.writeParcelable(config, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
||||||
if (bt != null) {
|
if (bt != null) {
|
||||||
@@ -81,13 +77,13 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
|||||||
|
|
||||||
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
||||||
private void applyOpenSslFix() {
|
private void applyOpenSslFix() {
|
||||||
byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(
|
byte[] seed = new LinuxSecureRandomSpi().engineGenerateSeed(
|
||||||
SEED_LENGTH);
|
SEED_LENGTH);
|
||||||
try {
|
try {
|
||||||
// Seed the OpenSSL PRNG
|
// Seed the OpenSSL PRNG
|
||||||
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||||
.getMethod("RAND_seed", byte[].class)
|
.getMethod("RAND_seed", byte[].class)
|
||||||
.invoke(null, (Object) seed);
|
.invoke(null, seed);
|
||||||
// Mix the output of the Linux PRNG into the OpenSSL PRNG
|
// Mix the output of the Linux PRNG into the OpenSSL PRNG
|
||||||
int bytesRead = (Integer) Class.forName(
|
int bytesRead = (Integer) Class.forName(
|
||||||
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||||
|
|||||||
@@ -11,12 +11,15 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
|
|
||||||
public class AndroidUtils {
|
public class AndroidUtils {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(AndroidUtils.class.getName());
|
||||||
|
|
||||||
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
|
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
|
||||||
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
|
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
|
||||||
|
|
||||||
@@ -25,7 +28,7 @@ public class AndroidUtils {
|
|||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
public static Collection<String> getSupportedArchitectures() {
|
public static Collection<String> getSupportedArchitectures() {
|
||||||
List<String> abis = new ArrayList<>();
|
List<String> abis = new ArrayList<>();
|
||||||
if (SDK_INT >= 21) {
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
|
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
|
||||||
} else {
|
} else {
|
||||||
abis.add(Build.CPU_ABI);
|
abis.add(Build.CPU_ABI);
|
||||||
|
|||||||
@@ -1,51 +1,46 @@
|
|||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
'com.android.tools.analytics-library:protos:26.2.1:protos-26.2.1.jar:2f371f5b1f551e85ab08be4d6a2873471b3d44afd1ebf6aa3298f3b796bf691f',
|
'com.android.tools.analytics-library:protos:26.2.0:protos-26.2.0.jar:306784ac579be37f64f110204ea3fad8568e09e10817bb574bac0fc71b6402c5',
|
||||||
'com.android.tools.analytics-library:shared:26.2.1:shared-26.2.1.jar:4c1e4e705fa4d45f23aaea230557f6508155012d9c296337787c1d7b26a97f5a',
|
'com.android.tools.analytics-library:shared:26.2.0:shared-26.2.0.jar:10782c593b7edcaf63cf79f7179c4652fee1c01298e0d81d888eea5ea1c320d4',
|
||||||
'com.android.tools.analytics-library:tracker:26.2.1:tracker-26.2.1.jar:4a624ecc976539f755ddb0bb8dfc2dd3d08326cfec59a098dbd70f701ca7fb75',
|
'com.android.tools.analytics-library:tracker:26.2.0:tracker-26.2.0.jar:74e3cf587bcd6f5f14a6cddb8123c6940baf9947582f5356c25dd852c4726564',
|
||||||
'com.android.tools.build:aapt2:3.2.1-4818971:aapt2-3.2.1-4818971-linux.jar:f431b6f96c91a2c155144b091a9c97d9805c589fe8efc9c930b6cd346cb60a1e',
|
'com.android.tools.build:aapt2:3.2.0-4818971:aapt2-3.2.0-4818971-linux.jar:0d86e045e9eb009ab8add53cf0e5c0f48674e8c8a4edd3b19fc978ea38508bb1',
|
||||||
'com.android.tools.build:apksig:3.2.1:apksig-3.2.1.jar:2b46f2feffea66037aab29e4261b2433c190194a6ef97b958511eb157f2ccba5',
|
'com.android.tools.build:apksig:3.2.0:apksig-3.2.0.jar:d393b14a2f85a4052645fa0b59e111b46dea0fd59a934bec6cf1e997a0640e30',
|
||||||
'com.android.tools.build:apkzlib:3.2.1:apkzlib-3.2.1.jar:c39ad0313905932431fe81c8899c2cf39a4d92ad6c4edcaa4b25432f461452aa',
|
'com.android.tools.build:apkzlib:3.2.0:apkzlib-3.2.0.jar:d8a3404d63a1037207bc2eb472209c606f8143d201f484da9dacd04ffa538c31',
|
||||||
'com.android.tools.build:builder-model:3.2.1:builder-model-3.2.1.jar:a9f68e6abcec122f9cb5ad352d3f05a3eb03acbcdca95e4d25c16310c2c965ff',
|
'com.android.tools.build:builder-model:3.2.0:builder-model-3.2.0.jar:7deb28465f2303fdc9df58ba83d080193edefe1624784d3ce9e0a0949ae05a49',
|
||||||
'com.android.tools.build:builder-test-api:3.2.1:builder-test-api-3.2.1.jar:533ac6c2b5884bb54967a33791f2628dfdfac7981af39417a333b43d4379b6be',
|
'com.android.tools.build:builder-test-api:3.2.0:builder-test-api-3.2.0.jar:b7c6676da0793240f16874c4008f12ed3ed1bc56a4a73f5e760044024ac9a02a',
|
||||||
'com.android.tools.build:builder:3.2.1:builder-3.2.1.jar:aedcbfd115dbe91d09b4113e66ef50589b558d0aa3b2f133b1d867c9b87fae83',
|
'com.android.tools.build:builder:3.2.0:builder-3.2.0.jar:191df45703f615a02db16ce5ce78489f1ec91f9b83e677bec5de29de765e326d',
|
||||||
'com.android.tools.build:gradle-api:3.2.1:gradle-api-3.2.1.jar:57cf0ac5ac1dca8afdb3f62b94265e776e7dcfa641cc3844fb53a05193de208d',
|
'com.android.tools.build:gradle-api:3.2.0:gradle-api-3.2.0.jar:5645c5ee4138b1354b24bed43e005964296a5f1ef48b6772ed9800159dcc2830',
|
||||||
'com.android.tools.build:manifest-merger:26.2.1:manifest-merger-26.2.1.jar:8830573263361035d38cfdcb51e2db94029c93865b21334f5fbf8a27984281a6',
|
'com.android.tools.build:manifest-merger:26.2.0:manifest-merger-26.2.0.jar:b821830bf067852688673cae01fb571c04da094985a3894878070b50f0587edf',
|
||||||
'com.android.tools.ddms:ddmlib:26.2.1:ddmlib-26.2.1.jar:a4bf0a29a19980bf27269465cc782064656750b77c26728f82f9e148b705218b',
|
'com.android.tools.ddms:ddmlib:26.2.0:ddmlib-26.2.0.jar:ff9b6951698a6ec005b25e5e3b5f7fe960f566131ba8fcdf713392e10cc2dd50',
|
||||||
'com.android.tools.external.com-intellij:intellij-core:26.2.1:intellij-core-26.2.1.jar:4925ad1892c2687cb1a63427d440ef519c8c59215fefe0dc5d541d5d411fcafe',
|
'com.android.tools.external.com-intellij:intellij-core:26.2.0:intellij-core-26.2.0.jar:03724f5aff30c8fff3d0b0c05e71f8dc21f246952fe1f3b5916bfb594e337bad',
|
||||||
'com.android.tools.external.com-intellij:kotlin-compiler:26.2.1:kotlin-compiler-26.2.1.jar:daa064fd708f340ee25fb9823c4c74104ac77f1370b76d907eb9ae6daec0a2ae',
|
'com.android.tools.external.com-intellij:kotlin-compiler:26.2.0:kotlin-compiler-26.2.0.jar:2f82e0c2687afe7c4941bdf6702d9a16d71d030a7ddb384a04a0537a361f4bb1',
|
||||||
'com.android.tools.external.org-jetbrains:uast:26.2.1:uast-26.2.1.jar:f10f7258d2ab9189562cc0f9ad838c0378fdba439229173390a99de02ebac75b',
|
'com.android.tools.external.org-jetbrains:uast:26.2.0:uast-26.2.0.jar:a439cafcddb2963620fd737005e3ce0560313362ede37e6c6eac5f10ff19eb94',
|
||||||
'com.android.tools.layoutlib:layoutlib-api:26.2.1:layoutlib-api-26.2.1.jar:ddbf4fca123733fa011595b1cc1f4ac2937ed327b60990711fafc33c775c2ade',
|
'com.android.tools.layoutlib:layoutlib-api:26.2.0:layoutlib-api-26.2.0.jar:5987488847729bad6a1e72cd5dcc46b68b61d8f05ef60858b87ed1d3b9bacc58',
|
||||||
'com.android.tools.lint:lint-api:26.2.1:lint-api-26.2.1.jar:3b57e739de567b98bc9ab56c2c0ee66fc026b4adf5843e8f9804ca0666a6f66e',
|
'com.android.tools.lint:lint-api:26.2.0:lint-api-26.2.0.jar:aa4dc0399b6ae602286b9b106c661b50f6a8e1143c5949d3e7fd93c4a4d1513d',
|
||||||
'com.android.tools.lint:lint-checks:26.2.1:lint-checks-26.2.1.jar:c86f4cc9aaee722ee4ad70062f7b5af91e9b041914af27adc09f545ab0fb3bc6',
|
'com.android.tools.lint:lint-checks:26.2.0:lint-checks-26.2.0.jar:c8c8dfdbd5c97a371e239b6000f4c6929bce315c2b13e690aaf34e3fcb045520',
|
||||||
'com.android.tools.lint:lint-gradle-api:26.2.1:lint-gradle-api-26.2.1.jar:2283e7af32e301565f2a797e531f0fc8c648077d457afb3ffdddbee638976c2f',
|
'com.android.tools.lint:lint-gradle-api:26.2.0:lint-gradle-api-26.2.0.jar:befc1ad242e5e89e8977b2f799c465fee1b096ac645eba659acab832980599cd',
|
||||||
'com.android.tools.lint:lint-gradle:26.2.1:lint-gradle-26.2.1.jar:8fd90b2f3ec788cbb9801c07ab3e1ea2255aa31a6093157d7ea0ff13d0315ecb',
|
'com.android.tools.lint:lint-gradle:26.2.0:lint-gradle-26.2.0.jar:332d257f20537020fd268468f678ccfbcc0be494fa50526b63c532836dc7c5dd',
|
||||||
'com.android.tools.lint:lint-kotlin:26.2.1:lint-kotlin-26.2.1.jar:7a6a5d2b18f69cf1b900d857c2632b4c683713c533295933b8b759f8cab4a877',
|
'com.android.tools.lint:lint-kotlin:26.2.0:lint-kotlin-26.2.0.jar:c149e09434aa24a6f7161dbd4b09f08c46f018cb0ee1ee2d1a32bf3b5015e081',
|
||||||
'com.android.tools.lint:lint:26.2.1:lint-26.2.1.jar:7848b82ae988b90dee259ae7c7e86e05cbf52db6cd21c8bbd38ce7df08f3f8c5',
|
'com.android.tools.lint:lint:26.2.0:lint-26.2.0.jar:4df411ea5ef106780073c6e953ab591a55d52e94c9b1cd2f99970a124eca405e',
|
||||||
'com.android.tools:annotations:26.2.1:annotations-26.2.1.jar:7391c6a1e080174b96e64ceb078dadd31ce4d8a2d2fee0ec65be202126f90f24',
|
'com.android.tools:annotations:26.2.0:annotations-26.2.0.jar:af775f75168acbadb2ff61d6955e4fbeca9b1bd9f7a40b54ab7a489e30af45bb',
|
||||||
'com.android.tools:common:26.2.1:common-26.2.1.jar:a50aab2d6411ff68f4004a87c7e93d87d8e980a0ec3b352246549897ea2d78e5',
|
'com.android.tools:common:26.2.0:common-26.2.0.jar:3e60e91bc7c7a634bbfae3522c5e0b49e8a268a2d69904bed4bd55833f8bb0c9',
|
||||||
'com.android.tools:dvlib:26.2.1:dvlib-26.2.1.jar:72a83bf2839b1df9b1fbf67ba45d1bfb9f966cd774da4320c762b2be8f1688aa',
|
'com.android.tools:dvlib:26.2.0:dvlib-26.2.0.jar:c4d8fac5b8432e3676256ece4e25c3e55e8ef2da4298fb060cc6086d7e2235fc',
|
||||||
'com.android.tools:repository:26.2.1:repository-26.2.1.jar:fa74dae09103faef703df38550ad8fa244c5b6d1bf90d6198be932292b3d9cc1',
|
'com.android.tools:repository:26.2.0:repository-26.2.0.jar:9c9e320195e7e6d9bbdf9b5b0ed1d7e4da3625ad344902cb47b32c9ef8306d82',
|
||||||
'com.android.tools:sdk-common:26.2.1:sdk-common-26.2.1.jar:759d4b292ca69a35cf961fca377b54158fc6c88108978006999442e80a011cf4',
|
'com.android.tools:sdk-common:26.2.0:sdk-common-26.2.0.jar:1e32745633177b28419041d9bd182bb99b51d1a7ad3f9b1c8b5292ed799656cd',
|
||||||
'com.android.tools:sdklib:26.2.1:sdklib-26.2.1.jar:248df7ad5eac4aeb6f96c394c76760de4b7b89ac056e54d0c21a739368b91b45',
|
'com.android.tools:sdklib:26.2.0:sdklib-26.2.0.jar:08e2715f9abd3870df8e311f77ff6f3dae61193c1f6a2de78bf2e49c6ba4725a',
|
||||||
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
||||||
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825',
|
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825',
|
||||||
'com.google.dagger:dagger-compiler:2.19:dagger-compiler-2.19.jar:27a4b202a2de908182edb261f8c0a264e08e5e4733d7514bc7fbf0d31da5c0fc',
|
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
'com.google.dagger:dagger-producers:2.19:dagger-producers-2.19.jar:a17663abe0fc38b676026950907d4c5f5e2bf338375415861eaff6e3bdb0b768',
|
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
'com.google.dagger:dagger-spi:2.19:dagger-spi-2.19.jar:e7a6379d82c841f6aac2866948ad1eed716528707814602842a8d844ce04e2e1',
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
|
|
||||||
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
||||||
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
|
|
||||||
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
|
|
||||||
'com.google.guava:guava:23.0:guava-23.0.jar:7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596',
|
'com.google.guava:guava:23.0:guava-23.0.jar:7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596',
|
||||||
'com.google.guava:guava:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9',
|
|
||||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
||||||
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
||||||
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
||||||
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
|
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
|
||||||
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
|
||||||
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
||||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||||
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
||||||
@@ -68,9 +63,7 @@ dependencyVerification {
|
|||||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
||||||
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
||||||
'org.briarproject:obfs4proxy-android:0.0.7:obfs4proxy-android-0.0.7.zip:abdfb5d889d848de9bf214f9276abbf454808a505b870819eccc9a9e985bf617',
|
|
||||||
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
|
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
|
||||||
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
|
||||||
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
||||||
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
||||||
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
||||||
@@ -79,10 +72,9 @@ dependencyVerification {
|
|||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71:kotlin-stdlib-common-1.2.71.jar:63999687ff2fce8a592dd180ffbbf8f1d21c26b4044c55cdc74ff3cf3b3cf328',
|
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71:kotlin-stdlib-jdk7-1.2.71.jar:b136bd61b240e07d4d92ce00d3bd1dbf584400a7bf5f220c2f3cd22446858082',
|
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71:kotlin-stdlib-jdk8-1.2.71.jar:ac3c8abf47790b64b4f7e2509a53f0c145e061ac1612a597520535d199946ea9',
|
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib:1.2.71:kotlin-stdlib-1.2.71.jar:4c895c270b87f5fec2a2796e1d89c15407ee821de961527c28588bb46afbc68b',
|
|
||||||
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
||||||
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
||||||
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
|
|||||||
@@ -7,13 +7,15 @@ apply plugin: 'witness'
|
|||||||
apply from: 'witness.gradle'
|
apply from: 'witness.gradle'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "com.google.dagger:dagger:2.19"
|
implementation "com.google.dagger:dagger:2.0.2"
|
||||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation "org.jmock:jmock:2.8.2"
|
testImplementation "org.jmock:jmock:2.8.2"
|
||||||
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||||
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||||
|
|
||||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package org.briarproject.bramble.api;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
@NotNullByDefault
|
|
||||||
public class Pair<A, B> {
|
|
||||||
|
|
||||||
private final A first;
|
|
||||||
private final B second;
|
|
||||||
|
|
||||||
public Pair(A first, B second) {
|
|
||||||
this.first = first;
|
|
||||||
this.second = second;
|
|
||||||
}
|
|
||||||
|
|
||||||
public A getFirst() {
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
public B getSecond() {
|
|
||||||
return second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.battery;
|
|
||||||
|
|
||||||
public interface BatteryManager {
|
|
||||||
|
|
||||||
boolean isCharging();
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.battery.event;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.event.Event;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An event that is broadcast when the device starts or stops charging.
|
|
||||||
*/
|
|
||||||
public class BatteryEvent extends Event {
|
|
||||||
|
|
||||||
private final boolean charging;
|
|
||||||
|
|
||||||
public BatteryEvent(boolean charging) {
|
|
||||||
this.charging = charging;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCharging() {
|
|
||||||
return charging;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.sync.Group;
|
|||||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageContext;
|
import org.briarproject.bramble.api.sync.MessageContext;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageValidator;
|
import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|||||||
@@ -4,12 +4,8 @@ import org.briarproject.bramble.api.identity.Author;
|
|||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
|
||||||
import static org.briarproject.bramble.util.StringUtils.toUtf8;
|
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class Contact {
|
public class Contact {
|
||||||
@@ -17,21 +13,13 @@ public class Contact {
|
|||||||
private final ContactId id;
|
private final ContactId id;
|
||||||
private final Author author;
|
private final Author author;
|
||||||
private final AuthorId localAuthorId;
|
private final AuthorId localAuthorId;
|
||||||
@Nullable
|
|
||||||
private final String alias;
|
|
||||||
private final boolean verified, active;
|
private final boolean verified, active;
|
||||||
|
|
||||||
public Contact(ContactId id, Author author, AuthorId localAuthorId,
|
public Contact(ContactId id, Author author, AuthorId localAuthorId,
|
||||||
@Nullable String alias, boolean verified, boolean active) {
|
boolean verified, boolean active) {
|
||||||
if (alias != null) {
|
|
||||||
int aliasLength = toUtf8(alias).length;
|
|
||||||
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.author = author;
|
this.author = author;
|
||||||
this.localAuthorId = localAuthorId;
|
this.localAuthorId = localAuthorId;
|
||||||
this.alias = alias;
|
|
||||||
this.verified = verified;
|
this.verified = verified;
|
||||||
this.active = active;
|
this.active = active;
|
||||||
}
|
}
|
||||||
@@ -48,11 +36,6 @@ public class Contact {
|
|||||||
return localAuthorId;
|
return localAuthorId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getAlias() {
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isVerified() {
|
public boolean isVerified() {
|
||||||
return verified;
|
return verified;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,16 +5,11 @@ import org.briarproject.bramble.api.db.DbException;
|
|||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.contact.PendingContact.PendingContactState.FAILED;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface ContactManager {
|
public interface ContactManager {
|
||||||
|
|
||||||
@@ -54,35 +49,6 @@ public interface ContactManager {
|
|||||||
long timestamp, boolean alice, boolean verified, boolean active)
|
long timestamp, boolean alice, boolean verified, boolean active)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the static link that needs to be sent to the contact to be added.
|
|
||||||
*/
|
|
||||||
String getRemoteContactLink();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the given link is syntactically valid.
|
|
||||||
*/
|
|
||||||
boolean isValidRemoteContactLink(String link);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests a new contact to be added via the given {@code link}.
|
|
||||||
*
|
|
||||||
* @param link The link received from the contact we want to add.
|
|
||||||
* @param alias The alias the user has given this contact.
|
|
||||||
* @return A PendingContact representing the contact to be added.
|
|
||||||
*/
|
|
||||||
PendingContact addRemoteContactRequest(String link, String alias);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a list of {@link PendingContact}s.
|
|
||||||
*/
|
|
||||||
Collection<PendingContact> getPendingContacts();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes a {@link PendingContact} that is in state {@link FAILED}.
|
|
||||||
*/
|
|
||||||
void removePendingContact(PendingContact pendingContact);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the contact with the given ID.
|
* Returns the contact with the given ID.
|
||||||
*/
|
*/
|
||||||
@@ -127,18 +93,6 @@ public interface ContactManager {
|
|||||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an alias name for the contact or unsets it if alias is null.
|
|
||||||
*/
|
|
||||||
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an alias name for the contact or unsets it if alias is null.
|
|
||||||
*/
|
|
||||||
void setContactAlias(ContactId c, @Nullable String alias)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if a contact with this name and public key already exists
|
* Return true if a contact with this name and public key already exists
|
||||||
*/
|
*/
|
||||||
@@ -151,16 +105,6 @@ public interface ContactManager {
|
|||||||
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link AuthorInfo} for the given author.
|
|
||||||
*/
|
|
||||||
AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the {@link AuthorInfo} for the given author.
|
|
||||||
*/
|
|
||||||
AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
|
|
||||||
|
|
||||||
interface ContactHook {
|
interface ContactHook {
|
||||||
|
|
||||||
void addingContact(Transaction txn, Contact c) throws DbException;
|
void addingContact(Transaction txn, Contact c) throws DbException;
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.contact;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
@NotNullByDefault
|
|
||||||
public class PendingContact {
|
|
||||||
|
|
||||||
public enum PendingContactState {
|
|
||||||
WAITING_FOR_CONNECTION,
|
|
||||||
CONNECTED,
|
|
||||||
ADDING_CONTACT,
|
|
||||||
FAILED
|
|
||||||
}
|
|
||||||
|
|
||||||
private final PendingContactId id;
|
|
||||||
private final String alias;
|
|
||||||
private final PendingContactState state;
|
|
||||||
private final long timestamp;
|
|
||||||
|
|
||||||
public PendingContact(PendingContactId id, String alias,
|
|
||||||
PendingContactState state, long timestamp) {
|
|
||||||
this.id = id;
|
|
||||||
this.alias = alias;
|
|
||||||
this.state = state;
|
|
||||||
this.timestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAlias() {
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PendingContactState getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimestamp() {
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return id.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
return o instanceof PendingContact &&
|
|
||||||
id.equals(((PendingContact) o).id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.contact;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.UniqueId;
|
|
||||||
|
|
||||||
public class PendingContactId extends UniqueId {
|
|
||||||
|
|
||||||
public PendingContactId(byte[] id) {
|
|
||||||
super(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.contact.event;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.PendingContact.PendingContactState;
|
|
||||||
import org.briarproject.bramble.api.contact.PendingContactId;
|
|
||||||
import org.briarproject.bramble.api.event.Event;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An event that is broadcast when a pending contact's state is changed.
|
|
||||||
*/
|
|
||||||
@Immutable
|
|
||||||
@NotNullByDefault
|
|
||||||
public class PendingContactStateChangedEvent extends Event {
|
|
||||||
|
|
||||||
private final PendingContactId id;
|
|
||||||
private final PendingContactState state;
|
|
||||||
|
|
||||||
public PendingContactStateChangedEvent(PendingContactId id,
|
|
||||||
PendingContactState state) {
|
|
||||||
this.id = id;
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PendingContactId getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PendingContactState getPendingContactState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.data;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.Bytes;
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
|
||||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public class BdfStringUtils {
|
|
||||||
|
|
||||||
public static String toString(@Nullable Object o) throws FormatException {
|
|
||||||
return toString(o, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String toString(@Nullable Object o, int indent)
|
|
||||||
throws FormatException {
|
|
||||||
if (o == null || o == NULL_VALUE) return "null";
|
|
||||||
if (o instanceof Boolean) return o.toString();
|
|
||||||
if (o instanceof Number) return o.toString();
|
|
||||||
if (o instanceof String) return "\"" + o + "\"";
|
|
||||||
if (o instanceof Bytes)
|
|
||||||
return "x" + toHexString(((Bytes) o).getBytes());
|
|
||||||
if (o instanceof byte[])
|
|
||||||
return "x" + toHexString((byte[]) o);
|
|
||||||
if (o instanceof List) {
|
|
||||||
List<?> list = (List) o;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("[\n");
|
|
||||||
int i = 0, size = list.size();
|
|
||||||
for (Object e : list) {
|
|
||||||
indent(sb, indent + 1);
|
|
||||||
sb.append(toString(e, indent + 1));
|
|
||||||
if (i++ < size - 1) sb.append(',');
|
|
||||||
sb.append('\n');
|
|
||||||
}
|
|
||||||
indent(sb, indent);
|
|
||||||
sb.append(']');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
if (o instanceof Map) {
|
|
||||||
Map<?, ?> map = (Map) o;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("{\n");
|
|
||||||
int i = 0, size = map.size();
|
|
||||||
for (Entry e : map.entrySet()) {
|
|
||||||
indent(sb, indent + 1);
|
|
||||||
sb.append(toString(e.getKey(), indent + 1));
|
|
||||||
sb.append(": ");
|
|
||||||
sb.append(toString(e.getValue(), indent + 1));
|
|
||||||
if (i++ < size - 1) sb.append(',');
|
|
||||||
sb.append('\n');
|
|
||||||
}
|
|
||||||
indent(sb, indent);
|
|
||||||
sb.append('}');
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
throw new FormatException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void indent(StringBuilder sb, int indent) {
|
|
||||||
for (int i = 0; i < indent; i++) sb.append('\t');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.api.sync.MessageId;
|
|||||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||||
import org.briarproject.bramble.api.sync.Offer;
|
import org.briarproject.bramble.api.sync.Offer;
|
||||||
import org.briarproject.bramble.api.sync.Request;
|
import org.briarproject.bramble.api.sync.Request;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
|
||||||
import org.briarproject.bramble.api.transport.KeySet;
|
import org.briarproject.bramble.api.transport.KeySet;
|
||||||
import org.briarproject.bramble.api.transport.KeySetId;
|
import org.briarproject.bramble.api.transport.KeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -29,6 +28,8 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates the database implementation and exposes high-level operations
|
* Encapsulates the database implementation and exposes high-level operations
|
||||||
* to other components.
|
* to other components.
|
||||||
@@ -88,14 +89,6 @@ public interface DatabaseComponent {
|
|||||||
<R, E extends Exception> R transactionWithResult(boolean readOnly,
|
<R, E extends Exception> R transactionWithResult(boolean readOnly,
|
||||||
DbCallable<R, E> task) throws DbException, E;
|
DbCallable<R, E> task) throws DbException, E;
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the given task within a transaction and returns the result of the
|
|
||||||
* task, which may be null.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
<R, E extends Exception> R transactionWithNullableResult(boolean readOnly,
|
|
||||||
NullableDbCallable<R, E> task) throws DbException, E;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a contact associated with the given local and remote pseudonyms,
|
* Stores a contact associated with the given local and remote pseudonyms,
|
||||||
* and returns an ID for the contact.
|
* and returns an ID for the contact.
|
||||||
@@ -373,12 +366,12 @@ public interface DatabaseComponent {
|
|||||||
/**
|
/**
|
||||||
* Returns the IDs and states of all dependencies of the given message.
|
* Returns the IDs and states of all dependencies of the given message.
|
||||||
* For missing dependencies and dependencies in other groups, the state
|
* For missing dependencies and dependencies in other groups, the state
|
||||||
* {@link MessageState UNKNOWN} is returned.
|
* {@link State UNKNOWN} is returned.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
Map<MessageId, MessageState> getMessageDependencies(Transaction txn,
|
Map<MessageId, State> getMessageDependencies(Transaction txn, MessageId m)
|
||||||
MessageId m) throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs and states of all dependents of the given message.
|
* Returns the IDs and states of all dependents of the given message.
|
||||||
@@ -387,16 +380,15 @@ public interface DatabaseComponent {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
Map<MessageId, MessageState> getMessageDependents(Transaction txn,
|
Map<MessageId, State> getMessageDependents(Transaction txn, MessageId m)
|
||||||
MessageId m) throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the validation and delivery state of the given message.
|
* Gets the validation and delivery state of the given message.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
MessageState getMessageState(Transaction txn, MessageId m)
|
State getMessageState(Transaction txn, MessageId m) throws DbException;
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the status of the given delivered message with respect to the
|
* Returns the status of the given delivered message with respect to the
|
||||||
@@ -523,12 +515,6 @@ public interface DatabaseComponent {
|
|||||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an alias name for the contact or unsets it if alias is null.
|
|
||||||
*/
|
|
||||||
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the given group's visibility to the given contact.
|
* Sets the given group's visibility to the given contact.
|
||||||
*/
|
*/
|
||||||
@@ -543,7 +529,7 @@ public interface DatabaseComponent {
|
|||||||
/**
|
/**
|
||||||
* Sets the validation and delivery state of the given message.
|
* Sets the validation and delivery state of the given message.
|
||||||
*/
|
*/
|
||||||
void setMessageState(Transaction txn, MessageId m, MessageState state)
|
void setMessageState(Transaction txn, MessageId m, State state)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
package org.briarproject.bramble.api.db;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public interface DbCallable<R, E extends Exception> {
|
public interface DbCallable<R, E extends Exception> {
|
||||||
|
|
||||||
R call(Transaction txn) throws DbException, E;
|
R call(Transaction txn) throws DbException, E;
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
package org.briarproject.bramble.api.db;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public interface DbRunnable<E extends Exception> {
|
public interface DbRunnable<E extends Exception> {
|
||||||
|
|
||||||
void run(Transaction txn) throws DbException, E;
|
void run(Transaction txn) throws DbException, E;
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public interface NullableDbCallable<R, E extends Exception> {
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
R call(Transaction txn) throws DbException, E;
|
|
||||||
}
|
|
||||||
@@ -16,6 +16,10 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class Author implements Nameable {
|
public class Author implements Nameable {
|
||||||
|
|
||||||
|
public enum Status {
|
||||||
|
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current version of the author structure.
|
* The current version of the author structure.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.identity;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
@NotNullByDefault
|
|
||||||
public class AuthorInfo {
|
|
||||||
|
|
||||||
public enum Status {
|
|
||||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES;
|
|
||||||
|
|
||||||
public boolean isContact() {
|
|
||||||
return this == UNVERIFIED || this == VERIFIED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Status status;
|
|
||||||
@Nullable
|
|
||||||
private final String alias;
|
|
||||||
|
|
||||||
public AuthorInfo(Status status, @Nullable String alias) {
|
|
||||||
this.status = status;
|
|
||||||
this.alias = alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AuthorInfo(Status status) {
|
|
||||||
this(status, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Status getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public String getAlias() {
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hashCode = status.ordinal();
|
|
||||||
if (alias != null) hashCode += alias.hashCode();
|
|
||||||
return hashCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof AuthorInfo)) return false;
|
|
||||||
AuthorInfo info = (AuthorInfo) o;
|
|
||||||
return status == info.status &&
|
|
||||||
(alias == null ? info.alias == null : alias.equals(info.alias));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.identity;
|
|||||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
|
import org.briarproject.bramble.api.identity.Author.Status;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -36,4 +37,14 @@ public interface IdentityManager {
|
|||||||
*/
|
*/
|
||||||
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
|
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Status} of the given author.
|
||||||
|
*/
|
||||||
|
Status getAuthorStatus(AuthorId a) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Status} of the given author.
|
||||||
|
*/
|
||||||
|
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public interface KeyAgreementConstants {
|
|||||||
/**
|
/**
|
||||||
* The connection timeout in milliseconds.
|
* The connection timeout in milliseconds.
|
||||||
*/
|
*/
|
||||||
long CONNECTION_TIMEOUT = 60_000;
|
long CONNECTION_TIMEOUT = 20 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transport identifier for Bluetooth.
|
* The transport identifier for Bluetooth.
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.nullsafety;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public class NullSafety {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stand-in for `Objects.requireNonNull()`.
|
|
||||||
*/
|
|
||||||
public static <T> T requireNonNull(@Nullable T t) {
|
|
||||||
if (t == null) throw new NullPointerException();
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,6 @@ public interface TorConstants {
|
|||||||
String PREF_TOR_NETWORK = "network2";
|
String PREF_TOR_NETWORK = "network2";
|
||||||
String PREF_TOR_PORT = "port";
|
String PREF_TOR_PORT = "port";
|
||||||
String PREF_TOR_MOBILE = "useMobileData";
|
String PREF_TOR_MOBILE = "useMobileData";
|
||||||
String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging";
|
|
||||||
|
|
||||||
int PREF_TOR_NETWORK_AUTOMATIC = 0;
|
int PREF_TOR_NETWORK_AUTOMATIC = 0;
|
||||||
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;
|
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package org.briarproject.bramble.api.sync;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Metadata;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responsible for managing message validators and passing them messages to
|
||||||
|
* validate.
|
||||||
|
*/
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface ValidationManager {
|
||||||
|
|
||||||
|
enum State {
|
||||||
|
|
||||||
|
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
State(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static State fromValue(int value) {
|
||||||
|
for (State s : values()) if (s.value == value) return s;
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the message validator for the given client. This method
|
||||||
|
* should be called before
|
||||||
|
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||||
|
*/
|
||||||
|
void registerMessageValidator(ClientId c, int majorVersion,
|
||||||
|
MessageValidator v);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the incoming message hook for the given client. The hook will
|
||||||
|
* be called once for each incoming message that passes validation. This
|
||||||
|
* method should be called before
|
||||||
|
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||||
|
*/
|
||||||
|
void registerIncomingMessageHook(ClientId c, int majorVersion,
|
||||||
|
IncomingMessageHook hook);
|
||||||
|
|
||||||
|
interface MessageValidator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the given message and returns its metadata and
|
||||||
|
* dependencies.
|
||||||
|
*/
|
||||||
|
MessageContext validateMessage(Message m, Group g)
|
||||||
|
throws InvalidMessageException;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IncomingMessageHook {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called once for each incoming message that passes validation.
|
||||||
|
*
|
||||||
|
* @return whether or not this message should be shared
|
||||||
|
* @throws DbException Should only be used for real database errors.
|
||||||
|
* If this is thrown, delivery will be attempted again at next startup,
|
||||||
|
* whereas if an InvalidMessageException is thrown,
|
||||||
|
* the message will be permanently invalidated.
|
||||||
|
* @throws InvalidMessageException for any non-database error
|
||||||
|
* that occurs while handling remotely created data.
|
||||||
|
* This includes errors that occur while handling locally created data
|
||||||
|
* in a context controlled by remotely created data
|
||||||
|
* (for example, parsing the metadata of a dependency
|
||||||
|
* of an incoming message).
|
||||||
|
* Throwing this will delete the incoming message and its metadata
|
||||||
|
* marking it as invalid in the database.
|
||||||
|
* Never rethrow DbException as InvalidMessageException!
|
||||||
|
*/
|
||||||
|
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
||||||
|
throws DbException, InvalidMessageException;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,10 +3,11 @@ package org.briarproject.bramble.api.sync.event;
|
|||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event that is broadcast when a message state changed.
|
* An event that is broadcast when a message state changed.
|
||||||
*/
|
*/
|
||||||
@@ -16,10 +17,10 @@ public class MessageStateChangedEvent extends Event {
|
|||||||
|
|
||||||
private final MessageId messageId;
|
private final MessageId messageId;
|
||||||
private final boolean local;
|
private final boolean local;
|
||||||
private final MessageState state;
|
private final State state;
|
||||||
|
|
||||||
public MessageStateChangedEvent(MessageId messageId, boolean local,
|
public MessageStateChangedEvent(MessageId messageId, boolean local,
|
||||||
MessageState state) {
|
State state) {
|
||||||
this.messageId = messageId;
|
this.messageId = messageId;
|
||||||
this.local = local;
|
this.local = local;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
@@ -33,7 +34,7 @@ public class MessageStateChangedEvent extends Event {
|
|||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MessageState getState() {
|
public State getState() {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.sync.validation;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.db.Metadata;
|
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
|
||||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
|
||||||
|
|
||||||
public interface IncomingMessageHook {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called once for each incoming message that passes validation.
|
|
||||||
*
|
|
||||||
* @return whether or not this message should be shared
|
|
||||||
* @throws DbException Should only be used for real database errors.
|
|
||||||
* If this is thrown, delivery will be attempted again at next startup,
|
|
||||||
* whereas if an InvalidMessageException is thrown,
|
|
||||||
* the message will be permanently invalidated.
|
|
||||||
* @throws InvalidMessageException for any non-database error
|
|
||||||
* that occurs while handling remotely created data.
|
|
||||||
* This includes errors that occur while handling locally created data
|
|
||||||
* in a context controlled by remotely created data
|
|
||||||
* (for example, parsing the metadata of a dependency
|
|
||||||
* of an incoming message).
|
|
||||||
* Throwing this will delete the incoming message and its metadata
|
|
||||||
* marking it as invalid in the database.
|
|
||||||
* Never rethrow DbException as InvalidMessageException!
|
|
||||||
*/
|
|
||||||
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
|
||||||
throws DbException, InvalidMessageException;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.sync.validation;
|
|
||||||
|
|
||||||
public enum MessageState {
|
|
||||||
|
|
||||||
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
|
|
||||||
|
|
||||||
private final int value;
|
|
||||||
|
|
||||||
MessageState(int value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MessageState fromValue(int value) {
|
|
||||||
for (MessageState s : values()) if (s.value == value) return s;
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.sync.validation;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.sync.Group;
|
|
||||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
|
||||||
import org.briarproject.bramble.api.sync.MessageContext;
|
|
||||||
|
|
||||||
public interface MessageValidator {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the given message and returns its metadata and
|
|
||||||
* dependencies.
|
|
||||||
*/
|
|
||||||
MessageContext validateMessage(Message m, Group g)
|
|
||||||
throws InvalidMessageException;
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.sync.validation;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
import org.briarproject.bramble.api.sync.ClientId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Responsible for managing message validators and passing them messages to
|
|
||||||
* validate.
|
|
||||||
*/
|
|
||||||
@NotNullByDefault
|
|
||||||
public interface ValidationManager {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the {@link MessageValidator} for the given client. This method
|
|
||||||
* should be called before
|
|
||||||
* {@link LifecycleManager#startServices(SecretKey)}.
|
|
||||||
*/
|
|
||||||
void registerMessageValidator(ClientId c, int majorVersion,
|
|
||||||
MessageValidator v);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers the {@link IncomingMessageHook} for the given client. The hook
|
|
||||||
* will be called once for each incoming message that passes validation.
|
|
||||||
* This method should be called before
|
|
||||||
* {@link LifecycleManager#startServices(SecretKey)}.
|
|
||||||
*/
|
|
||||||
void registerIncomingMessageHook(ClientId c, int majorVersion,
|
|
||||||
IncomingMessageHook hook);
|
|
||||||
}
|
|
||||||
@@ -38,13 +38,6 @@ public interface ClientVersioningManager {
|
|||||||
Visibility getClientVisibility(Transaction txn, ContactId contactId,
|
Visibility getClientVisibility(Transaction txn, ContactId contactId,
|
||||||
ClientId clientId, int majorVersion) throws DbException;
|
ClientId clientId, int majorVersion) throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the minor version of the given client that is supported by the
|
|
||||||
* given contact, or -1 if the contact does not support the client.
|
|
||||||
*/
|
|
||||||
int getClientMinorVersion(Transaction txn, ContactId contactId,
|
|
||||||
ClientId clientId, int majorVersion) throws DbException;
|
|
||||||
|
|
||||||
interface ClientVersioningHook {
|
interface ClientVersioningHook {
|
||||||
|
|
||||||
void onClientVisibilityChanging(Transaction txn, Contact c,
|
void onClientVisibilityChanging(Transaction txn, Contact c,
|
||||||
|
|||||||
@@ -8,15 +8,12 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.ServerSocket;
|
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class IoUtils {
|
public class IoUtils {
|
||||||
@@ -57,35 +54,16 @@ public class IoUtils {
|
|||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
out.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
tryToClose(in, LOG, WARNING);
|
tryToClose(in);
|
||||||
tryToClose(out, LOG, WARNING);
|
tryToClose(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tryToClose(@Nullable Closeable c, Logger logger,
|
private static void tryToClose(@Nullable Closeable c) {
|
||||||
Level level) {
|
|
||||||
try {
|
try {
|
||||||
if (c != null) c.close();
|
if (c != null) c.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logException(logger, level, e);
|
// We did our best
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void tryToClose(@Nullable Socket s, Logger logger,
|
|
||||||
Level level) {
|
|
||||||
try {
|
|
||||||
if (s != null) s.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logException(logger, level, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void tryToClose(@Nullable ServerSocket ss, Logger logger,
|
|
||||||
Level level) {
|
|
||||||
try {
|
|
||||||
if (ss != null) ss.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
logException(logger, level, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ public class OsUtils {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private static final String os = System.getProperty("os.name");
|
private static final String os = System.getProperty("os.name");
|
||||||
@Nullable
|
@Nullable
|
||||||
|
private static final String version = System.getProperty("os.version");
|
||||||
|
@Nullable
|
||||||
private static final String vendor = System.getProperty("java.vendor");
|
private static final String vendor = System.getProperty("java.vendor");
|
||||||
|
|
||||||
public static boolean isWindows() {
|
public static boolean isWindows() {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class StringUtils {
|
|||||||
try {
|
try {
|
||||||
return s.getBytes("UTF-8");
|
return s.getBytes("UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new AssertionError(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ public class StringUtils {
|
|||||||
try {
|
try {
|
||||||
return decoder.decode(buffer).toString();
|
return decoder.decode(buffer).toString();
|
||||||
} catch (CharacterCodingException e) {
|
} catch (CharacterCodingException e) {
|
||||||
throw new AssertionError(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
package org.briarproject.bramble.api.identity;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotEquals;
|
|
||||||
|
|
||||||
public class AuthorInfoTest extends BrambleTestCase {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEquals() {
|
|
||||||
assertEquals(
|
|
||||||
new AuthorInfo(NONE),
|
|
||||||
new AuthorInfo(NONE, null)
|
|
||||||
);
|
|
||||||
assertEquals(
|
|
||||||
new AuthorInfo(NONE, "test"),
|
|
||||||
new AuthorInfo(NONE, "test")
|
|
||||||
);
|
|
||||||
|
|
||||||
assertNotEquals(
|
|
||||||
new AuthorInfo(NONE),
|
|
||||||
new AuthorInfo(VERIFIED)
|
|
||||||
);
|
|
||||||
assertNotEquals(
|
|
||||||
new AuthorInfo(NONE, "test"),
|
|
||||||
new AuthorInfo(NONE)
|
|
||||||
);
|
|
||||||
assertNotEquals(
|
|
||||||
new AuthorInfo(NONE),
|
|
||||||
new AuthorInfo(NONE, "test")
|
|
||||||
);
|
|
||||||
assertNotEquals(
|
|
||||||
new AuthorInfo(NONE, "a"),
|
|
||||||
new AuthorInfo(NONE, "b")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@ dependencyVerification {
|
|||||||
verify = [
|
verify = [
|
||||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||||
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ sourceCompatibility = 1.8
|
|||||||
targetCompatibility = 1.8
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
apply plugin: 'ru.vyarus.animalsniffer'
|
apply plugin: 'ru.vyarus.animalsniffer'
|
||||||
|
apply plugin: 'net.ltgt.apt'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
apply from: 'witness.gradle'
|
apply from: 'witness.gradle'
|
||||||
apply from: '../dagger.gradle'
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-api', configuration: 'default')
|
implementation project(path: ':bramble-api', configuration: 'default')
|
||||||
@@ -17,7 +17,7 @@ dependencies {
|
|||||||
implementation 'org.whispersystems:curve25519-java:0.5.0'
|
implementation 'org.whispersystems:curve25519-java:0.5.0'
|
||||||
implementation 'org.briarproject:jtorctl:0.3'
|
implementation 'org.briarproject:jtorctl:0.3'
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||||
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
|
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
|
||||||
@@ -25,8 +25,10 @@ dependencies {
|
|||||||
testImplementation "org.jmock:jmock:2.8.2"
|
testImplementation "org.jmock:jmock:2.8.2"
|
||||||
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||||
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||||
|
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||||
|
|
||||||
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
testApt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
|
|||||||
import org.briarproject.bramble.plugin.PluginModule;
|
import org.briarproject.bramble.plugin.PluginModule;
|
||||||
import org.briarproject.bramble.properties.PropertiesModule;
|
import org.briarproject.bramble.properties.PropertiesModule;
|
||||||
import org.briarproject.bramble.reporting.ReportingModule;
|
import org.briarproject.bramble.reporting.ReportingModule;
|
||||||
import org.briarproject.bramble.sync.validation.ValidationModule;
|
import org.briarproject.bramble.sync.SyncModule;
|
||||||
import org.briarproject.bramble.system.SystemModule;
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
import org.briarproject.bramble.transport.TransportModule;
|
import org.briarproject.bramble.transport.TransportModule;
|
||||||
import org.briarproject.bramble.versioning.VersioningModule;
|
import org.briarproject.bramble.versioning.VersioningModule;
|
||||||
@@ -31,11 +31,11 @@ public interface BrambleCoreEagerSingletons {
|
|||||||
|
|
||||||
void inject(ReportingModule.EagerSingletons init);
|
void inject(ReportingModule.EagerSingletons init);
|
||||||
|
|
||||||
|
void inject(SyncModule.EagerSingletons init);
|
||||||
|
|
||||||
void inject(SystemModule.EagerSingletons init);
|
void inject(SystemModule.EagerSingletons init);
|
||||||
|
|
||||||
void inject(TransportModule.EagerSingletons init);
|
void inject(TransportModule.EagerSingletons init);
|
||||||
|
|
||||||
void inject(ValidationModule.EagerSingletons init);
|
|
||||||
|
|
||||||
void inject(VersioningModule.EagerSingletons init);
|
void inject(VersioningModule.EagerSingletons init);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.reporting.ReportingModule;
|
|||||||
import org.briarproject.bramble.settings.SettingsModule;
|
import org.briarproject.bramble.settings.SettingsModule;
|
||||||
import org.briarproject.bramble.socks.SocksModule;
|
import org.briarproject.bramble.socks.SocksModule;
|
||||||
import org.briarproject.bramble.sync.SyncModule;
|
import org.briarproject.bramble.sync.SyncModule;
|
||||||
import org.briarproject.bramble.sync.validation.ValidationModule;
|
|
||||||
import org.briarproject.bramble.system.SystemModule;
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
import org.briarproject.bramble.transport.TransportModule;
|
import org.briarproject.bramble.transport.TransportModule;
|
||||||
import org.briarproject.bramble.versioning.VersioningModule;
|
import org.briarproject.bramble.versioning.VersioningModule;
|
||||||
@@ -48,7 +47,6 @@ import dagger.Module;
|
|||||||
SyncModule.class,
|
SyncModule.class,
|
||||||
SystemModule.class,
|
SystemModule.class,
|
||||||
TransportModule.class,
|
TransportModule.class,
|
||||||
ValidationModule.class,
|
|
||||||
VersioningModule.class
|
VersioningModule.class
|
||||||
})
|
})
|
||||||
public class BrambleCoreModule {
|
public class BrambleCoreModule {
|
||||||
@@ -62,9 +60,9 @@ public class BrambleCoreModule {
|
|||||||
c.inject(new PluginModule.EagerSingletons());
|
c.inject(new PluginModule.EagerSingletons());
|
||||||
c.inject(new PropertiesModule.EagerSingletons());
|
c.inject(new PropertiesModule.EagerSingletons());
|
||||||
c.inject(new ReportingModule.EagerSingletons());
|
c.inject(new ReportingModule.EagerSingletons());
|
||||||
|
c.inject(new SyncModule.EagerSingletons());
|
||||||
c.inject(new SystemModule.EagerSingletons());
|
c.inject(new SystemModule.EagerSingletons());
|
||||||
c.inject(new TransportModule.EagerSingletons());
|
c.inject(new TransportModule.EagerSingletons());
|
||||||
c.inject(new ValidationModule.EagerSingletons());
|
|
||||||
c.inject(new VersioningModule.EagerSingletons());
|
c.inject(new VersioningModule.EagerSingletons());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
package org.briarproject.bramble;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.Queue;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
public class PriorityExecutor {
|
|
||||||
|
|
||||||
private final Object lock = new Object();
|
|
||||||
private final Executor delegate, high, low;
|
|
||||||
@GuardedBy("lock")
|
|
||||||
private final Queue<Runnable> highQueue = new LinkedList<>();
|
|
||||||
@GuardedBy("lock")
|
|
||||||
private final Queue<Runnable> lowQueue = new LinkedList<>();
|
|
||||||
|
|
||||||
@GuardedBy("lock")
|
|
||||||
private boolean isTaskRunning = false;
|
|
||||||
|
|
||||||
public PriorityExecutor(Executor delegate) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
high = r -> submit(r, true);
|
|
||||||
low = r -> submit(r, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Executor getHighPriorityExecutor() {
|
|
||||||
return high;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Executor getLowPriorityExecutor() {
|
|
||||||
return low;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void submit(Runnable r, boolean isHighPriority) {
|
|
||||||
Runnable wrapped = () -> {
|
|
||||||
try {
|
|
||||||
r.run();
|
|
||||||
} finally {
|
|
||||||
scheduleNext();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
synchronized (lock) {
|
|
||||||
if (!isTaskRunning && highQueue.isEmpty() &&
|
|
||||||
(isHighPriority || lowQueue.isEmpty())) {
|
|
||||||
isTaskRunning = true;
|
|
||||||
delegate.execute(wrapped);
|
|
||||||
} else if (isHighPriority) {
|
|
||||||
highQueue.add(wrapped);
|
|
||||||
} else {
|
|
||||||
lowQueue.add(wrapped);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleNext() {
|
|
||||||
synchronized (lock) {
|
|
||||||
Runnable next = highQueue.poll();
|
|
||||||
if (next == null) next = lowQueue.poll();
|
|
||||||
if (next == null) isTaskRunning = false;
|
|
||||||
else delegate.execute(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package org.briarproject.bramble.battery;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
|
||||||
|
|
||||||
import dagger.Module;
|
|
||||||
import dagger.Provides;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a default implementation of {@link BatteryManager} for systems
|
|
||||||
* without batteries.
|
|
||||||
*/
|
|
||||||
@Module
|
|
||||||
public class DefaultBatteryManagerModule {
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
BatteryManager provideBatteryManager() {
|
|
||||||
return () -> false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -82,7 +82,13 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public void addLocalMessage(Message m, BdfDictionary metadata,
|
public void addLocalMessage(Message m, BdfDictionary metadata,
|
||||||
boolean shared) throws DbException, FormatException {
|
boolean shared) throws DbException, FormatException {
|
||||||
db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
addLocalMessage(txn, m, metadata, shared);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -107,7 +113,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message getMessage(MessageId m) throws DbException {
|
public Message getMessage(MessageId m) throws DbException {
|
||||||
return db.transactionWithResult(true, txn -> getMessage(txn, m));
|
Message message;
|
||||||
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
message = getMessage(txn, m);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -118,7 +132,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public BdfList getMessageAsList(MessageId m) throws DbException,
|
public BdfList getMessageAsList(MessageId m) throws DbException,
|
||||||
FormatException {
|
FormatException {
|
||||||
return db.transactionWithResult(true, txn -> getMessageAsList(txn, m));
|
BdfList list;
|
||||||
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
list = getMessageAsList(txn, m);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,8 +152,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public BdfDictionary getGroupMetadataAsDictionary(GroupId g)
|
public BdfDictionary getGroupMetadataAsDictionary(GroupId g)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
return db.transactionWithResult(true, txn ->
|
BdfDictionary dictionary;
|
||||||
getGroupMetadataAsDictionary(txn, g));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
dictionary = getGroupMetadataAsDictionary(txn, g);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -144,8 +173,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
|
public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
return db.transactionWithResult(true, txn ->
|
BdfDictionary dictionary;
|
||||||
getMessageMetadataAsDictionary(txn, m));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
dictionary = getMessageMetadataAsDictionary(txn, m);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return dictionary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -158,8 +194,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||||
GroupId g) throws DbException, FormatException {
|
GroupId g) throws DbException, FormatException {
|
||||||
return db.transactionWithResult(true, txn ->
|
Map<MessageId, BdfDictionary> map;
|
||||||
getMessageMetadataAsDictionary(txn, g));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
map = getMessageMetadataAsDictionary(txn, g);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -176,8 +219,15 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||||
GroupId g, BdfDictionary query) throws DbException,
|
GroupId g, BdfDictionary query) throws DbException,
|
||||||
FormatException {
|
FormatException {
|
||||||
return db.transactionWithResult(true, txn ->
|
Map<MessageId, BdfDictionary> map;
|
||||||
getMessageMetadataAsDictionary(txn, g, query));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
map = getMessageMetadataAsDictionary(txn, g, query);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -195,7 +245,13 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public void mergeGroupMetadata(GroupId g, BdfDictionary metadata)
|
public void mergeGroupMetadata(GroupId g, BdfDictionary metadata)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
db.transaction(false, txn -> mergeGroupMetadata(txn, g, metadata));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
mergeGroupMetadata(txn, g, metadata);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -207,7 +263,13 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
@Override
|
@Override
|
||||||
public void mergeMessageMetadata(MessageId m, BdfDictionary metadata)
|
public void mergeMessageMetadata(MessageId m, BdfDictionary metadata)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
db.transaction(false, txn -> mergeMessageMetadata(txn, m, metadata));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
mergeMessageMetadata(txn, m, metadata);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.briarproject.bramble.api.data.BdfList;
|
|||||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
@@ -157,8 +158,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
streamWriterFactory.createContactExchangeStreamWriter(out,
|
streamWriterFactory.createContactExchangeStreamWriter(out,
|
||||||
alice ? aliceHeaderKey : bobHeaderKey);
|
alice ? aliceHeaderKey : bobHeaderKey);
|
||||||
RecordWriter recordWriter =
|
RecordWriter recordWriter =
|
||||||
recordWriterFactory
|
recordWriterFactory.createRecordWriter(streamWriter.getOutputStream());
|
||||||
.createRecordWriter(streamWriter.getOutputStream());
|
|
||||||
|
|
||||||
// Derive the nonces to be signed
|
// Derive the nonces to be signed
|
||||||
byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret,
|
byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret,
|
||||||
@@ -287,14 +287,19 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
private ContactId addContact(Author remoteAuthor, long timestamp,
|
private ContactId addContact(Author remoteAuthor, long timestamp,
|
||||||
Map<TransportId, TransportProperties> remoteProperties)
|
Map<TransportId, TransportProperties> remoteProperties)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
return db.transactionWithResult(false, txn -> {
|
ContactId contactId;
|
||||||
ContactId contactId = contactManager.addContact(txn, remoteAuthor,
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
contactId = contactManager.addContact(txn, remoteAuthor,
|
||||||
localAuthor.getId(), masterSecret, timestamp, alice,
|
localAuthor.getId(), masterSecret, timestamp, alice,
|
||||||
true, true);
|
true, true);
|
||||||
transportPropertyManager.addRemoteProperties(txn, contactId,
|
transportPropertyManager.addRemoteProperties(txn, contactId,
|
||||||
remoteProperties);
|
remoteProperties);
|
||||||
return contactId;
|
db.commitTransaction(txn);
|
||||||
});
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return contactId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToClose(DuplexTransportConnection conn) {
|
private void tryToClose(DuplexTransportConnection conn) {
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package org.briarproject.bramble.contact;
|
|||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
import org.briarproject.bramble.api.contact.PendingContact;
|
|
||||||
import org.briarproject.bramble.api.contact.PendingContactId;
|
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
@@ -12,53 +10,29 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
|
|||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.transport.KeyManager;
|
import org.briarproject.bramble.api.transport.KeyManager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
|
||||||
import static org.briarproject.bramble.api.contact.PendingContact.PendingContactState.WAITING_FOR_CONNECTION;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
|
|
||||||
import static org.briarproject.bramble.util.StringUtils.toUtf8;
|
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class ContactManagerImpl implements ContactManager {
|
class ContactManagerImpl implements ContactManager {
|
||||||
|
|
||||||
private static final int LINK_LENGTH = 64;
|
|
||||||
private static final String REMOTE_CONTACT_LINK =
|
|
||||||
"briar://" + getRandomBase32String(LINK_LENGTH);
|
|
||||||
private static final Pattern LINK_REGEX =
|
|
||||||
Pattern.compile("(briar://)?([a-z2-7]{" + LINK_LENGTH + "})");
|
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final KeyManager keyManager;
|
private final KeyManager keyManager;
|
||||||
private final IdentityManager identityManager;
|
|
||||||
private final List<ContactHook> hooks;
|
private final List<ContactHook> hooks;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
|
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
|
||||||
IdentityManager identityManager) {
|
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.keyManager = keyManager;
|
this.keyManager = keyManager;
|
||||||
this.identityManager = identityManager;
|
|
||||||
hooks = new CopyOnWriteArrayList<>();
|
hooks = new CopyOnWriteArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,63 +65,42 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
public ContactId addContact(Author remote, AuthorId local, SecretKey master,
|
public ContactId addContact(Author remote, AuthorId local, SecretKey master,
|
||||||
long timestamp, boolean alice, boolean verified, boolean active)
|
long timestamp, boolean alice, boolean verified, boolean active)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
return db.transactionWithResult(false, txn ->
|
ContactId c;
|
||||||
addContact(txn, remote, local, master, timestamp, alice,
|
Transaction txn = db.startTransaction(false);
|
||||||
verified, active));
|
try {
|
||||||
}
|
c = addContact(txn, remote, local, master, timestamp, alice,
|
||||||
|
verified, active);
|
||||||
@Override
|
db.commitTransaction(txn);
|
||||||
public String getRemoteContactLink() {
|
} finally {
|
||||||
// TODO replace with real implementation
|
db.endTransaction(txn);
|
||||||
return REMOTE_CONTACT_LINK;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("SameParameterValue")
|
|
||||||
private static String getRandomBase32String(int length) {
|
|
||||||
Random random = new Random();
|
|
||||||
char[] c = new char[length];
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
int character = random.nextInt(32);
|
|
||||||
if (character < 26) c[i] = (char) ('a' + character);
|
|
||||||
else c[i] = (char) ('2' + (character - 26));
|
|
||||||
}
|
}
|
||||||
return new String(c);
|
return c;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isValidRemoteContactLink(String link) {
|
|
||||||
return LINK_REGEX.matcher(link).matches();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PendingContact addRemoteContactRequest(String link, String alias) {
|
|
||||||
// TODO replace with real implementation
|
|
||||||
PendingContactId id = new PendingContactId(link.getBytes());
|
|
||||||
return new PendingContact(id, alias, WAITING_FOR_CONNECTION,
|
|
||||||
System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<PendingContact> getPendingContacts() {
|
|
||||||
// TODO replace with real implementation
|
|
||||||
return emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removePendingContact(PendingContact pendingContact) {
|
|
||||||
// TODO replace with real implementation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Contact getContact(ContactId c) throws DbException {
|
public Contact getContact(ContactId c) throws DbException {
|
||||||
return db.transactionWithResult(true, txn -> db.getContact(txn, c));
|
Contact contact;
|
||||||
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
contact = db.getContact(txn, c);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
return db.transactionWithResult(true, txn ->
|
Transaction txn = db.startTransaction(true);
|
||||||
getContact(txn, remoteAuthorId, localAuthorId));
|
try {
|
||||||
|
Contact c = getContact(txn, remoteAuthorId, localAuthorId);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
return c;
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -165,8 +118,14 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Contact> getActiveContacts() throws DbException {
|
public Collection<Contact> getActiveContacts() throws DbException {
|
||||||
Collection<Contact> contacts =
|
Collection<Contact> contacts;
|
||||||
db.transactionWithResult(true, db::getContacts);
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
contacts = db.getContacts(txn);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
List<Contact> active = new ArrayList<>(contacts.size());
|
List<Contact> active = new ArrayList<>(contacts.size());
|
||||||
for (Contact c : contacts) if (c.isActive()) active.add(c);
|
for (Contact c : contacts) if (c.isActive()) active.add(c);
|
||||||
return active;
|
return active;
|
||||||
@@ -174,7 +133,13 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeContact(ContactId c) throws DbException {
|
public void removeContact(ContactId c) throws DbException {
|
||||||
db.transaction(false, txn -> removeContact(txn, c));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
removeContact(txn, c);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -183,23 +148,6 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
db.setContactActive(txn, c, active);
|
db.setContactActive(txn, c, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setContactAlias(Transaction txn, ContactId c,
|
|
||||||
@Nullable String alias) throws DbException {
|
|
||||||
if (alias != null) {
|
|
||||||
int aliasLength = toUtf8(alias).length;
|
|
||||||
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
db.setContactAlias(txn, c, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setContactAlias(ContactId c, @Nullable String alias)
|
|
||||||
throws DbException {
|
|
||||||
db.transaction(false, txn -> setContactAlias(txn, c, alias));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
|
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
|
||||||
AuthorId localAuthorId) throws DbException {
|
AuthorId localAuthorId) throws DbException {
|
||||||
@@ -209,8 +157,15 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
@Override
|
@Override
|
||||||
public boolean contactExists(AuthorId remoteAuthorId,
|
public boolean contactExists(AuthorId remoteAuthorId,
|
||||||
AuthorId localAuthorId) throws DbException {
|
AuthorId localAuthorId) throws DbException {
|
||||||
return db.transactionWithResult(true, txn ->
|
boolean exists;
|
||||||
contactExists(txn, remoteAuthorId, localAuthorId));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
exists = contactExists(txn, remoteAuthorId, localAuthorId);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -221,23 +176,4 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
db.removeContact(txn, c);
|
db.removeContact(txn, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthorInfo getAuthorInfo(AuthorId a) throws DbException {
|
|
||||||
return db.transactionWithResult(true, txn -> getAuthorInfo(txn, a));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AuthorInfo getAuthorInfo(Transaction txn, AuthorId authorId)
|
|
||||||
throws DbException {
|
|
||||||
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
|
|
||||||
if (localAuthor.getId().equals(authorId))
|
|
||||||
return new AuthorInfo(OURSELVES);
|
|
||||||
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
|
|
||||||
if (contacts.isEmpty()) return new AuthorInfo(UNKNOWN);
|
|
||||||
if (contacts.size() > 1) throw new AssertionError();
|
|
||||||
Contact c = contacts.iterator().next();
|
|
||||||
if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
|
|
||||||
else return new AuthorInfo(UNVERIFIED, c.getAlias());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import static org.briarproject.bramble.data.Types.STRING_16;
|
|||||||
import static org.briarproject.bramble.data.Types.STRING_32;
|
import static org.briarproject.bramble.data.Types.STRING_32;
|
||||||
import static org.briarproject.bramble.data.Types.STRING_8;
|
import static org.briarproject.bramble.data.Types.STRING_8;
|
||||||
import static org.briarproject.bramble.data.Types.TRUE;
|
import static org.briarproject.bramble.data.Types.TRUE;
|
||||||
import static org.briarproject.bramble.util.StringUtils.fromUtf8;
|
|
||||||
|
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -254,7 +253,7 @@ class BdfReaderImpl implements BdfReader {
|
|||||||
if (length < 0 || length > maxBufferSize) throw new FormatException();
|
if (length < 0 || length > maxBufferSize) throw new FormatException();
|
||||||
if (length == 0) return "";
|
if (length == 0) return "";
|
||||||
readIntoBuffer(length);
|
readIntoBuffer(length);
|
||||||
return fromUtf8(buf, 0, length);
|
return new String(buf, 0, length, "UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readStringLength() throws IOException {
|
private int readStringLength() throws IOException {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||||
import org.briarproject.bramble.api.transport.KeySet;
|
import org.briarproject.bramble.api.transport.KeySet;
|
||||||
import org.briarproject.bramble.api.transport.KeySetId;
|
import org.briarproject.bramble.api.transport.KeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -106,7 +106,7 @@ interface Database<T> {
|
|||||||
* @param sender the contact from whom the message was received, or null
|
* @param sender the contact from whom the message was received, or null
|
||||||
* if the message was created locally.
|
* if the message was created locally.
|
||||||
*/
|
*/
|
||||||
void addMessage(T txn, Message m, MessageState state, boolean shared,
|
void addMessage(T txn, Message m, State state, boolean shared,
|
||||||
@Nullable ContactId sender) throws DbException;
|
@Nullable ContactId sender) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,7 +114,7 @@ interface Database<T> {
|
|||||||
* in the given state.
|
* in the given state.
|
||||||
*/
|
*/
|
||||||
void addMessageDependency(T txn, Message dependent, MessageId dependency,
|
void addMessageDependency(T txn, Message dependent, MessageId dependency,
|
||||||
MessageState dependentState) throws DbException;
|
State dependentState) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Records that a message has been offered by the given contact.
|
* Records that a message has been offered by the given contact.
|
||||||
@@ -310,11 +310,11 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Returns the IDs and states of all dependencies of the given message.
|
* Returns the IDs and states of all dependencies of the given message.
|
||||||
* For missing dependencies and dependencies in other groups, the state
|
* For missing dependencies and dependencies in other groups, the state
|
||||||
* {@link MessageState UNKNOWN} is returned.
|
* {@link State UNKNOWN} is returned.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
Map<MessageId, MessageState> getMessageDependencies(T txn, MessageId m)
|
Map<MessageId, State> getMessageDependencies(T txn, MessageId m)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -324,7 +324,7 @@ interface Database<T> {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
Map<MessageId, MessageState> getMessageDependents(T txn, MessageId m)
|
Map<MessageId, State> getMessageDependents(T txn, MessageId m)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -383,7 +383,7 @@ interface Database<T> {
|
|||||||
* <p/>
|
* <p/>
|
||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
MessageState getMessageState(T txn, MessageId m) throws DbException;
|
State getMessageState(T txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the status of all delivered messages in the given group with
|
* Returns the status of all delivered messages in the given group with
|
||||||
@@ -616,12 +616,6 @@ interface Database<T> {
|
|||||||
void setContactActive(T txn, ContactId c, boolean active)
|
void setContactActive(T txn, ContactId c, boolean active)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets an alias name for a contact.
|
|
||||||
*/
|
|
||||||
void setContactAlias(T txn, ContactId c, @Nullable String alias)
|
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the given group's visibility to the given contact to either
|
* Sets the given group's visibility to the given contact to either
|
||||||
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||||
@@ -637,8 +631,7 @@ interface Database<T> {
|
|||||||
/**
|
/**
|
||||||
* Sets the validation and delivery state of the given message.
|
* Sets the validation and delivery state of the given message.
|
||||||
*/
|
*/
|
||||||
void setMessageState(T txn, MessageId m, MessageState state)
|
void setMessageState(T txn, MessageId m, State state) throws DbException;
|
||||||
throws DbException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the reordering window for the given key set and transport in the
|
* Sets the reordering window for the given key set and transport in the
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
|
|||||||
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
|
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
|
||||||
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
||||||
import org.briarproject.bramble.api.db.NoSuchTransportException;
|
import org.briarproject.bramble.api.db.NoSuchTransportException;
|
||||||
import org.briarproject.bramble.api.db.NullableDbCallable;
|
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
@@ -43,6 +42,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
|||||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||||
import org.briarproject.bramble.api.sync.Offer;
|
import org.briarproject.bramble.api.sync.Offer;
|
||||||
import org.briarproject.bramble.api.sync.Request;
|
import org.briarproject.bramble.api.sync.Request;
|
||||||
|
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||||
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
|
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
|
||||||
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
||||||
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
|
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
|
||||||
@@ -54,7 +54,6 @@ import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
|
|||||||
import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
|
import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
|
||||||
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
|
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
|
||||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
|
||||||
import org.briarproject.bramble.api.transport.KeySet;
|
import org.briarproject.bramble.api.transport.KeySet;
|
||||||
import org.briarproject.bramble.api.transport.KeySetId;
|
import org.briarproject.bramble.api.transport.KeySetId;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
@@ -75,8 +74,8 @@ import javax.inject.Inject;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
@@ -194,20 +193,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <R, E extends Exception> R transactionWithNullableResult(
|
|
||||||
boolean readOnly, NullableDbCallable<R, E> task)
|
|
||||||
throws DbException, E {
|
|
||||||
Transaction txn = startTransaction(readOnly);
|
|
||||||
try {
|
|
||||||
R result = task.call(txn);
|
|
||||||
commitTransaction(txn);
|
|
||||||
return result;
|
|
||||||
} finally {
|
|
||||||
endTransaction(txn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private T unbox(Transaction transaction) {
|
private T unbox(Transaction transaction) {
|
||||||
if (transaction.isCommitted()) throw new IllegalStateException();
|
if (transaction.isCommitted()) throw new IllegalStateException();
|
||||||
return txnClass.cast(transaction.unbox());
|
return txnClass.cast(transaction.unbox());
|
||||||
@@ -579,7 +564,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageState getMessageState(Transaction transaction, MessageId m)
|
public State getMessageState(Transaction transaction, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsMessage(txn, m))
|
if (!db.containsMessage(txn, m))
|
||||||
@@ -619,8 +604,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<MessageId, MessageState> getMessageDependencies(
|
public Map<MessageId, State> getMessageDependencies(Transaction transaction,
|
||||||
Transaction transaction, MessageId m) throws DbException {
|
MessageId m) throws DbException {
|
||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsMessage(txn, m))
|
if (!db.containsMessage(txn, m))
|
||||||
throw new NoSuchMessageException();
|
throw new NoSuchMessageException();
|
||||||
@@ -628,8 +613,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<MessageId, MessageState> getMessageDependents(
|
public Map<MessageId, State> getMessageDependents(Transaction transaction,
|
||||||
Transaction transaction, MessageId m) throws DbException {
|
MessageId m) throws DbException {
|
||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsMessage(txn, m))
|
if (!db.containsMessage(txn, m))
|
||||||
throw new NoSuchMessageException();
|
throw new NoSuchMessageException();
|
||||||
@@ -874,16 +859,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
transaction.attach(new ContactStatusChangedEvent(c, active));
|
transaction.attach(new ContactStatusChangedEvent(c, active));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setContactAlias(Transaction transaction, ContactId c,
|
|
||||||
@Nullable String alias) throws DbException {
|
|
||||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
|
||||||
T txn = unbox(transaction);
|
|
||||||
if (!db.containsContact(txn, c))
|
|
||||||
throw new NoSuchContactException();
|
|
||||||
db.setContactAlias(txn, c, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setGroupVisibility(Transaction transaction, ContactId c,
|
public void setGroupVisibility(Transaction transaction, ContactId c,
|
||||||
GroupId g, Visibility v) throws DbException {
|
GroupId g, Visibility v) throws DbException {
|
||||||
@@ -918,7 +893,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setMessageState(Transaction transaction, MessageId m,
|
public void setMessageState(Transaction transaction, MessageId m,
|
||||||
MessageState state) throws DbException {
|
State state) throws DbException {
|
||||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsMessage(txn, m))
|
if (!db.containsMessage(txn, m))
|
||||||
@@ -935,10 +910,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsMessage(txn, dependent.getId()))
|
if (!db.containsMessage(txn, dependent.getId()))
|
||||||
throw new NoSuchMessageException();
|
throw new NoSuchMessageException();
|
||||||
MessageState dependentState =
|
State dependentState = db.getMessageState(txn, dependent.getId());
|
||||||
db.getMessageState(txn, dependent.getId());
|
|
||||||
for (MessageId dependency : dependencies) {
|
for (MessageId dependency : dependencies) {
|
||||||
db.addMessageDependency(txn, dependent, dependency, dependentState);
|
db.addMessageDependency(txn, dependent, dependency,
|
||||||
|
dependentState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
package org.briarproject.bramble.db;
|
|
||||||
|
|
||||||
class DatabaseTypes {
|
|
||||||
|
|
||||||
private final String hashType, secretType, binaryType;
|
|
||||||
private final String counterType, stringType;
|
|
||||||
|
|
||||||
public DatabaseTypes(String hashType, String secretType, String binaryType,
|
|
||||||
String counterType, String stringType) {
|
|
||||||
this.hashType = hashType;
|
|
||||||
this.secretType = secretType;
|
|
||||||
this.binaryType = binaryType;
|
|
||||||
this.counterType = counterType;
|
|
||||||
this.stringType = stringType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces database type placeholders in a statement with the actual types.
|
|
||||||
* These placeholders are currently supported:
|
|
||||||
* <li> _HASH
|
|
||||||
* <li> _SECRET
|
|
||||||
* <li> _BINARY
|
|
||||||
* <li> _COUNTER
|
|
||||||
* <li> _STRING
|
|
||||||
*/
|
|
||||||
String replaceTypes(String s) {
|
|
||||||
s = s.replaceAll("_HASH", hashType);
|
|
||||||
s = s.replaceAll("_SECRET", secretType);
|
|
||||||
s = s.replaceAll("_BINARY", binaryType);
|
|
||||||
s = s.replaceAll("_COUNTER", counterType);
|
|
||||||
s = s.replaceAll("_STRING", stringType);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,30 +15,21 @@ import java.sql.DriverManager;
|
|||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
|
||||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all the H2-specific code for the database.
|
* Contains all the H2-specific code for the database.
|
||||||
*/
|
*/
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class H2Database extends JdbcDatabase {
|
class H2Database extends JdbcDatabase {
|
||||||
|
|
||||||
private static final Logger LOG = getLogger(H2Database.class.getName());
|
|
||||||
|
|
||||||
private static final String HASH_TYPE = "BINARY(32)";
|
private static final String HASH_TYPE = "BINARY(32)";
|
||||||
private static final String SECRET_TYPE = "BINARY(32)";
|
private static final String SECRET_TYPE = "BINARY(32)";
|
||||||
private static final String BINARY_TYPE = "BINARY";
|
private static final String BINARY_TYPE = "BINARY";
|
||||||
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT";
|
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT";
|
||||||
private static final String STRING_TYPE = "VARCHAR";
|
private static final String STRING_TYPE = "VARCHAR";
|
||||||
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
|
|
||||||
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE);
|
|
||||||
|
|
||||||
private final DatabaseConfig config;
|
private final DatabaseConfig config;
|
||||||
private final String url;
|
private final String url;
|
||||||
@@ -49,7 +40,8 @@ class H2Database extends JdbcDatabase {
|
|||||||
@Inject
|
@Inject
|
||||||
H2Database(DatabaseConfig config, MessageFactory messageFactory,
|
H2Database(DatabaseConfig config, MessageFactory messageFactory,
|
||||||
Clock clock) {
|
Clock clock) {
|
||||||
super(dbTypes, messageFactory, clock);
|
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||||
|
messageFactory, clock);
|
||||||
this.config = config;
|
this.config = config;
|
||||||
File dir = config.getDatabaseDirectory();
|
File dir = config.getDatabaseDirectory();
|
||||||
String path = new File(dir, "db").getAbsolutePath();
|
String path = new File(dir, "db").getAbsolutePath();
|
||||||
@@ -128,8 +120,8 @@ class H2Database extends JdbcDatabase {
|
|||||||
s.close();
|
s.close();
|
||||||
c.close();
|
c.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
tryToClose(c, LOG, WARNING);
|
tryToClose(c);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,32 +14,22 @@ import java.sql.Connection;
|
|||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
|
||||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all the HSQLDB-specific code for the database.
|
* Contains all the HSQLDB-specific code for the database.
|
||||||
*/
|
*/
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class HyperSqlDatabase extends JdbcDatabase {
|
class HyperSqlDatabase extends JdbcDatabase {
|
||||||
|
|
||||||
private static final Logger LOG =
|
|
||||||
getLogger(HyperSqlDatabase.class.getName());
|
|
||||||
|
|
||||||
private static final String HASH_TYPE = "BINARY(32)";
|
private static final String HASH_TYPE = "BINARY(32)";
|
||||||
private static final String SECRET_TYPE = "BINARY(32)";
|
private static final String SECRET_TYPE = "BINARY(32)";
|
||||||
private static final String BINARY_TYPE = "BINARY";
|
private static final String BINARY_TYPE = "BINARY";
|
||||||
private static final String COUNTER_TYPE =
|
private static final String COUNTER_TYPE =
|
||||||
"INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1)";
|
"INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1)";
|
||||||
private static final String STRING_TYPE = "VARCHAR";
|
private static final String STRING_TYPE = "VARCHAR";
|
||||||
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
|
|
||||||
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE);
|
|
||||||
|
|
||||||
private final DatabaseConfig config;
|
private final DatabaseConfig config;
|
||||||
private final String url;
|
private final String url;
|
||||||
@@ -50,7 +40,8 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
@Inject
|
@Inject
|
||||||
HyperSqlDatabase(DatabaseConfig config, MessageFactory messageFactory,
|
HyperSqlDatabase(DatabaseConfig config, MessageFactory messageFactory,
|
||||||
Clock clock) {
|
Clock clock) {
|
||||||
super(dbTypes, messageFactory, clock);
|
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||||
|
messageFactory, clock);
|
||||||
this.config = config;
|
this.config = config;
|
||||||
File dir = config.getDatabaseDirectory();
|
File dir = config.getDatabaseDirectory();
|
||||||
String path = new File(dir, "db").getAbsolutePath();
|
String path = new File(dir, "db").getAbsolutePath();
|
||||||
@@ -80,14 +71,14 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
s.close();
|
s.close();
|
||||||
c.close();
|
c.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
tryToClose(c, LOG, WARNING);
|
tryToClose(c);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFreeSpace() {
|
public long getFreeSpace() throws DbException {
|
||||||
File dir = config.getDatabaseDirectory();
|
File dir = config.getDatabaseDirectory();
|
||||||
long maxSize = config.getMaxSize();
|
long maxSize = config.getMaxSize();
|
||||||
long free = dir.getFreeSpace();
|
long free = dir.getFreeSpace();
|
||||||
@@ -130,8 +121,8 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
s.close();
|
s.close();
|
||||||
c.close();
|
c.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
tryToClose(c, LOG, WARNING);
|
tryToClose(c);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,42 +0,0 @@
|
|||||||
package org.briarproject.bramble.db;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
|
||||||
class JdbcUtils {
|
|
||||||
|
|
||||||
static void tryToClose(@Nullable ResultSet rs, Logger logger, Level level) {
|
|
||||||
try {
|
|
||||||
if (rs != null) rs.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logException(logger, level, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tryToClose(@Nullable Statement s, Logger logger, Level level) {
|
|
||||||
try {
|
|
||||||
if (s != null) s.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logException(logger, level, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tryToClose(@Nullable Connection c, Logger logger, Level level) {
|
|
||||||
try {
|
|
||||||
if (c != null) c.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logException(logger, level, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,8 +7,10 @@ import java.sql.SQLException;
|
|||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
class Migration38_39 implements Migration<Connection> {
|
class Migration38_39 implements Migration<Connection> {
|
||||||
|
|
||||||
@@ -38,8 +40,16 @@ class Migration38_39 implements Migration<Connection> {
|
|||||||
+ " ALTER COLUMN contactId"
|
+ " ALTER COLUMN contactId"
|
||||||
+ " SET NOT NULL");
|
+ " SET NOT NULL");
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(@Nullable Statement s) {
|
||||||
|
try {
|
||||||
|
if (s != null) s.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import java.sql.SQLException;
|
|||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
class Migration39_40 implements Migration<Connection> {
|
class Migration39_40 implements Migration<Connection> {
|
||||||
|
|
||||||
@@ -37,8 +39,16 @@ class Migration39_40 implements Migration<Connection> {
|
|||||||
+ " ALTER COLUMN eta"
|
+ " ALTER COLUMN eta"
|
||||||
+ " SET NOT NULL");
|
+ " SET NOT NULL");
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(@Nullable Statement s) {
|
||||||
|
try {
|
||||||
|
if (s != null) s.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +0,0 @@
|
|||||||
package org.briarproject.bramble.db;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
|
||||||
import static java.util.logging.Logger.getLogger;
|
|
||||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
|
||||||
|
|
||||||
class Migration40_41 implements Migration<Connection> {
|
|
||||||
|
|
||||||
private static final Logger LOG = getLogger(Migration40_41.class.getName());
|
|
||||||
|
|
||||||
private final DatabaseTypes dbTypes;
|
|
||||||
|
|
||||||
public Migration40_41(DatabaseTypes databaseTypes) {
|
|
||||||
this.dbTypes = databaseTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getStartVersion() {
|
|
||||||
return 40;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getEndVersion() {
|
|
||||||
return 41;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void migrate(Connection txn) throws DbException {
|
|
||||||
Statement s = null;
|
|
||||||
try {
|
|
||||||
s = txn.createStatement();
|
|
||||||
s.execute("ALTER TABLE contacts"
|
|
||||||
+ dbTypes.replaceTypes(" ADD alias _STRING"));
|
|
||||||
} catch (SQLException e) {
|
|
||||||
tryToClose(s, LOG, WARNING);
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +1,29 @@
|
|||||||
package org.briarproject.bramble.identity;
|
package org.briarproject.bramble.identity;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
|
import org.briarproject.bramble.api.identity.Author.Status;
|
||||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@@ -67,16 +75,27 @@ class IdentityManagerImpl implements IdentityManager {
|
|||||||
LOG.info("No local author to store");
|
LOG.info("No local author to store");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
|
Transaction txn = db.startTransaction(false);
|
||||||
LOG.info("Local author stored");
|
try {
|
||||||
|
db.addLocalAuthor(txn, cached);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
LOG.info("Local author stored");
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LocalAuthor getLocalAuthor() throws DbException {
|
public LocalAuthor getLocalAuthor() throws DbException {
|
||||||
if (cachedAuthor == null) {
|
if (cachedAuthor == null) {
|
||||||
cachedAuthor =
|
Transaction txn = db.startTransaction(true);
|
||||||
db.transactionWithResult(true, this::loadLocalAuthor);
|
try {
|
||||||
LOG.info("Local author loaded");
|
cachedAuthor = loadLocalAuthor(txn);
|
||||||
|
LOG.info("Local author loaded");
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LocalAuthor cached = cachedAuthor;
|
LocalAuthor cached = cachedAuthor;
|
||||||
if (cached == null) throw new AssertionError();
|
if (cached == null) throw new AssertionError();
|
||||||
@@ -99,4 +118,26 @@ class IdentityManagerImpl implements IdentityManager {
|
|||||||
return db.getLocalAuthors(txn).iterator().next();
|
return db.getLocalAuthors(txn).iterator().next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status getAuthorStatus(AuthorId authorId) throws DbException {
|
||||||
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
return getAuthorStatus(txn, authorId);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status getAuthorStatus(Transaction txn, AuthorId authorId)
|
||||||
|
throws DbException {
|
||||||
|
if (getLocalAuthor(txn).getId().equals(authorId)) return OURSELVES;
|
||||||
|
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
|
||||||
|
if (contacts.isEmpty()) return UNKNOWN;
|
||||||
|
for (Contact c : contacts) {
|
||||||
|
if (c.isVerified()) return VERIFIED;
|
||||||
|
}
|
||||||
|
return UNVERIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.db.DataTooOldException;
|
|||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.MigrationListener;
|
import org.briarproject.bramble.api.db.MigrationListener;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
@@ -114,16 +115,20 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
dbLatch.countDown();
|
dbLatch.countDown();
|
||||||
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
|
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
|
||||||
|
|
||||||
db.transaction(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
for (Client c : clients) {
|
for (Client c : clients) {
|
||||||
long start1 = now();
|
start = now();
|
||||||
c.createLocalState(txn);
|
c.createLocalState(txn);
|
||||||
if (LOG.isLoggable(FINE)) {
|
if (LOG.isLoggable(FINE)) {
|
||||||
logDuration(LOG, "Starting client "
|
logDuration(LOG, "Starting client "
|
||||||
+ c.getClass().getSimpleName(), start1);
|
+ c.getClass().getSimpleName(), start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
for (Service s : services) {
|
for (Service s : services) {
|
||||||
start = now();
|
start = now();
|
||||||
s.startService();
|
s.startService();
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
|
|||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
@@ -45,9 +46,6 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
|||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
|
||||||
import static org.briarproject.bramble.util.StringUtils.macToBytes;
|
|
||||||
import static org.briarproject.bramble.util.StringUtils.macToString;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -98,9 +96,6 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
abstract DuplexTransportConnection connectTo(String address, String uuid)
|
abstract DuplexTransportConnection connectTo(String address, String uuid)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
abstract DuplexTransportConnection discoverAndConnect(String uuid);
|
|
||||||
|
|
||||||
BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
|
BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
|
||||||
Executor ioExecutor, SecureRandom secureRandom,
|
Executor ioExecutor, SecureRandom secureRandom,
|
||||||
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
|
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
|
||||||
@@ -198,7 +193,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
address = getBluetoothAddress();
|
address = getBluetoothAddress();
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Local address " + scrubMacAddress(address));
|
LOG.info("Local address " + scrubMacAddress(address));
|
||||||
if (!isNullOrEmpty(address)) {
|
if (!StringUtils.isNullOrEmpty(address)) {
|
||||||
p.put(PROP_ADDRESS, address);
|
p.put(PROP_ADDRESS, address);
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
@@ -261,9 +256,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
// Try to connect to known devices in parallel
|
// Try to connect to known devices in parallel
|
||||||
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
|
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
|
||||||
String address = e.getValue().get(PROP_ADDRESS);
|
String address = e.getValue().get(PROP_ADDRESS);
|
||||||
if (isNullOrEmpty(address)) continue;
|
if (StringUtils.isNullOrEmpty(address)) continue;
|
||||||
String uuid = e.getValue().get(PROP_UUID);
|
String uuid = e.getValue().get(PROP_UUID);
|
||||||
if (isNullOrEmpty(uuid)) continue;
|
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||||
ContactId c = e.getKey();
|
ContactId c = e.getKey();
|
||||||
ioExecutor.execute(() -> {
|
ioExecutor.execute(() -> {
|
||||||
if (!isRunning() || !shouldAllowContactConnections()) return;
|
if (!isRunning() || !shouldAllowContactConnections()) return;
|
||||||
@@ -314,9 +309,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
if (!isRunning() || !shouldAllowContactConnections()) return null;
|
if (!isRunning() || !shouldAllowContactConnections()) return null;
|
||||||
if (!connectionLimiter.canOpenContactConnection()) return null;
|
if (!connectionLimiter.canOpenContactConnection()) return null;
|
||||||
String address = p.get(PROP_ADDRESS);
|
String address = p.get(PROP_ADDRESS);
|
||||||
if (isNullOrEmpty(address)) return null;
|
if (StringUtils.isNullOrEmpty(address)) return null;
|
||||||
String uuid = p.get(PROP_UUID);
|
String uuid = p.get(PROP_UUID);
|
||||||
if (isNullOrEmpty(uuid)) return null;
|
if (StringUtils.isNullOrEmpty(uuid)) return null;
|
||||||
DuplexTransportConnection conn = connect(address, uuid);
|
DuplexTransportConnection conn = connect(address, uuid);
|
||||||
if (conn == null) return null;
|
if (conn == null) return null;
|
||||||
// TODO: Why don't we reset the backoff here?
|
// TODO: Why don't we reset the backoff here?
|
||||||
@@ -331,6 +326,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
|
// There's no point listening if we can't discover our own address
|
||||||
|
String address = getBluetoothAddress();
|
||||||
|
if (address == null) return null;
|
||||||
// No truncation necessary because COMMIT_LENGTH = 16
|
// No truncation necessary because COMMIT_LENGTH = 16
|
||||||
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
|
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
|
||||||
@@ -348,8 +346,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
}
|
}
|
||||||
BdfList descriptor = new BdfList();
|
BdfList descriptor = new BdfList();
|
||||||
descriptor.add(TRANSPORT_ID_BLUETOOTH);
|
descriptor.add(TRANSPORT_ID_BLUETOOTH);
|
||||||
String address = getBluetoothAddress();
|
descriptor.add(StringUtils.macToBytes(address));
|
||||||
if (address != null) descriptor.add(macToBytes(address));
|
|
||||||
return new BluetoothKeyAgreementListener(descriptor, ss);
|
return new BluetoothKeyAgreementListener(descriptor, ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,25 +354,18 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
public DuplexTransportConnection createKeyAgreementConnection(
|
public DuplexTransportConnection createKeyAgreementConnection(
|
||||||
byte[] commitment, BdfList descriptor) {
|
byte[] commitment, BdfList descriptor) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
|
String address;
|
||||||
|
try {
|
||||||
|
address = parseAddress(descriptor);
|
||||||
|
} catch (FormatException e) {
|
||||||
|
LOG.info("Invalid address in key agreement descriptor");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
// No truncation necessary because COMMIT_LENGTH = 16
|
// No truncation necessary because COMMIT_LENGTH = 16
|
||||||
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
||||||
DuplexTransportConnection conn;
|
if (LOG.isLoggable(INFO))
|
||||||
if (descriptor.size() == 1) {
|
LOG.info("Connecting to key agreement UUID " + uuid);
|
||||||
if (LOG.isLoggable(INFO))
|
DuplexTransportConnection conn = connect(address, uuid);
|
||||||
LOG.info("Discovering address for key agreement UUID " + uuid);
|
|
||||||
conn = discoverAndConnect(uuid);
|
|
||||||
} else {
|
|
||||||
String address;
|
|
||||||
try {
|
|
||||||
address = parseAddress(descriptor);
|
|
||||||
} catch (FormatException e) {
|
|
||||||
LOG.info("Invalid address in key agreement descriptor");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Connecting to key agreement UUID " + uuid);
|
|
||||||
conn = connect(address, uuid);
|
|
||||||
}
|
|
||||||
if (conn != null) connectionLimiter.keyAgreementConnectionOpened(conn);
|
if (conn != null) connectionLimiter.keyAgreementConnectionOpened(conn);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
@@ -383,7 +373,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
private String parseAddress(BdfList descriptor) throws FormatException {
|
private String parseAddress(BdfList descriptor) throws FormatException {
|
||||||
byte[] mac = descriptor.getRaw(1);
|
byte[] mac = descriptor.getRaw(1);
|
||||||
if (mac.length != 6) throw new FormatException();
|
if (mac.length != 6) throw new FormatException();
|
||||||
return macToString(mac);
|
return StringUtils.macToString(mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class FileTransportReader implements TransportConnectionReader {
|
class FileTransportReader implements TransportConnectionReader {
|
||||||
@@ -33,7 +34,11 @@ class FileTransportReader implements TransportConnectionReader {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose(boolean exception, boolean recognised) {
|
public void dispose(boolean exception, boolean recognised) {
|
||||||
tryToClose(in, LOG, WARNING);
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
plugin.readerFinished(file, exception, recognised);
|
plugin.readerFinished(file, exception, recognised);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class FileTransportWriter implements TransportConnectionWriter {
|
class FileTransportWriter implements TransportConnectionWriter {
|
||||||
@@ -43,7 +44,11 @@ class FileTransportWriter implements TransportConnectionWriter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose(boolean exception) {
|
public void dispose(boolean exception) {
|
||||||
tryToClose(out, LOG, WARNING);
|
try {
|
||||||
|
out.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
plugin.writerFinished(file, exception);
|
plugin.writerFinished(file, exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -36,6 +35,7 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
|||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -293,7 +293,11 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
try {
|
||||||
|
ss.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -154,8 +153,13 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void tryToClose(@Nullable ServerSocket ss) {
|
protected void tryToClose(@Nullable ServerSocket ss) {
|
||||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
try {
|
||||||
callback.transportDisabled();
|
if (ss != null) ss.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
} finally {
|
||||||
|
callback.transportDisabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getIpPortString(InetSocketAddress a) {
|
String getIpPortString(InetSocketAddress a) {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import net.freehaven.tor.control.EventHandler;
|
|||||||
import net.freehaven.tor.control.TorControlConnection;
|
import net.freehaven.tor.control.TorControlConnection;
|
||||||
|
|
||||||
import org.briarproject.bramble.PoliteExecutor;
|
import org.briarproject.bramble.PoliteExecutor;
|
||||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
|
||||||
import org.briarproject.bramble.api.battery.event.BatteryEvent;
|
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
@@ -31,6 +29,7 @@ import org.briarproject.bramble.api.system.LocationUtils;
|
|||||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.EOFException;
|
import java.io.EOFException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
@@ -69,7 +68,6 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
|||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_AUTOMATIC;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
|
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V2;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V2;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
|
||||||
@@ -98,14 +96,13 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
private final SocketFactory torSocketFactory;
|
private final SocketFactory torSocketFactory;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final BatteryManager batteryManager;
|
|
||||||
private final Backoff backoff;
|
private final Backoff backoff;
|
||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final String architecture;
|
private final String architecture;
|
||||||
private final CircumventionProvider circumventionProvider;
|
private final CircumventionProvider circumventionProvider;
|
||||||
private final ResourceProvider resourceProvider;
|
private final ResourceProvider resourceProvider;
|
||||||
private final int maxLatency, maxIdleTime, socketTimeout;
|
private final int maxLatency, maxIdleTime, socketTimeout;
|
||||||
private final File torDirectory, torFile, geoIpFile, obfs4File, configFile;
|
private final File torDirectory, torFile, geoIpFile, configFile;
|
||||||
private final File doneFile, cookieFile;
|
private final File doneFile, cookieFile;
|
||||||
private final ConnectionStatus connectionStatus;
|
private final ConnectionStatus connectionStatus;
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
@@ -124,8 +121,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
|
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
|
||||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||||
Clock clock, ResourceProvider resourceProvider,
|
Clock clock, ResourceProvider resourceProvider,
|
||||||
CircumventionProvider circumventionProvider,
|
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||||
BatteryManager batteryManager, Backoff backoff,
|
|
||||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||||
int maxIdleTime, File torDirectory) {
|
int maxIdleTime, File torDirectory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
@@ -135,7 +131,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.resourceProvider = resourceProvider;
|
this.resourceProvider = resourceProvider;
|
||||||
this.circumventionProvider = circumventionProvider;
|
this.circumventionProvider = circumventionProvider;
|
||||||
this.batteryManager = batteryManager;
|
|
||||||
this.backoff = backoff;
|
this.backoff = backoff;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.architecture = architecture;
|
this.architecture = architecture;
|
||||||
@@ -147,7 +142,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
this.torDirectory = torDirectory;
|
this.torDirectory = torDirectory;
|
||||||
torFile = new File(torDirectory, "tor");
|
torFile = new File(torDirectory, "tor");
|
||||||
geoIpFile = new File(torDirectory, "geoip");
|
geoIpFile = new File(torDirectory, "geoip");
|
||||||
obfs4File = new File(torDirectory, "obfs4proxy");
|
|
||||||
configFile = new File(torDirectory, "torrc");
|
configFile = new File(torDirectory, "torrc");
|
||||||
doneFile = new File(torDirectory, "done");
|
doneFile = new File(torDirectory, "done");
|
||||||
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
||||||
@@ -266,8 +260,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
throw new PluginException(e);
|
throw new PluginException(e);
|
||||||
}
|
}
|
||||||
// Check whether we're online
|
// Check whether we're online
|
||||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
batteryManager.isCharging());
|
|
||||||
// Bind a server socket to receive incoming hidden service connections
|
// Bind a server socket to receive incoming hidden service connections
|
||||||
bind();
|
bind();
|
||||||
}
|
}
|
||||||
@@ -291,20 +284,14 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
in = getGeoIpInputStream();
|
in = getGeoIpInputStream();
|
||||||
out = new FileOutputStream(geoIpFile);
|
out = new FileOutputStream(geoIpFile);
|
||||||
IoUtils.copyAndClose(in, out);
|
IoUtils.copyAndClose(in, out);
|
||||||
// Unzip the Obfs4 proxy to the filesystem
|
|
||||||
in = getObfs4InputStream();
|
|
||||||
out = new FileOutputStream(obfs4File);
|
|
||||||
IoUtils.copyAndClose(in, out);
|
|
||||||
// Make the Obfs4 proxy executable
|
|
||||||
if (!obfs4File.setExecutable(true, true)) throw new IOException();
|
|
||||||
// Copy the config file to the filesystem
|
// Copy the config file to the filesystem
|
||||||
in = getConfigInputStream();
|
in = getConfigInputStream();
|
||||||
out = new FileOutputStream(configFile);
|
out = new FileOutputStream(configFile);
|
||||||
IoUtils.copyAndClose(in, out);
|
IoUtils.copyAndClose(in, out);
|
||||||
doneFile.createNewFile();
|
doneFile.createNewFile();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
IoUtils.tryToClose(in, LOG, WARNING);
|
tryToClose(in);
|
||||||
IoUtils.tryToClose(out, LOG, WARNING);
|
tryToClose(out);
|
||||||
throw new PluginException(e);
|
throw new PluginException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,20 +314,26 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
return zin;
|
return zin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getObfs4InputStream() throws IOException {
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Installing obfs4proxy binary for " + architecture);
|
|
||||||
InputStream in = resourceProvider
|
|
||||||
.getResourceInputStream("obfs4proxy_" + architecture, ".zip");
|
|
||||||
ZipInputStream zin = new ZipInputStream(in);
|
|
||||||
if (zin.getNextEntry() == null) throw new IOException();
|
|
||||||
return zin;
|
|
||||||
}
|
|
||||||
|
|
||||||
private InputStream getConfigInputStream() {
|
private InputStream getConfigInputStream() {
|
||||||
return getClass().getClassLoader().getResourceAsStream("torrc");
|
return getClass().getClassLoader().getResourceAsStream("torrc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(@Nullable Closeable c) {
|
||||||
|
try {
|
||||||
|
if (c != null) c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryToClose(@Nullable Socket s) {
|
||||||
|
try {
|
||||||
|
if (s != null) s.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void listFiles(File f) {
|
private void listFiles(File f) {
|
||||||
if (f.isDirectory()) {
|
if (f.isDirectory()) {
|
||||||
File[] children = f.listFiles();
|
File[] children = f.listFiles();
|
||||||
@@ -362,7 +355,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
return b;
|
return b;
|
||||||
} finally {
|
} finally {
|
||||||
IoUtils.tryToClose(in, LOG, WARNING);
|
tryToClose(in);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,8 +395,13 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void tryToClose(@Nullable ServerSocket ss) {
|
private void tryToClose(@Nullable ServerSocket ss) {
|
||||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
try {
|
||||||
callback.transportDisabled();
|
if (ss != null) ss.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
} finally {
|
||||||
|
callback.transportDisabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void publishHiddenService(String port) {
|
private void publishHiddenService(String port) {
|
||||||
@@ -474,8 +472,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (enable) {
|
if (enable) {
|
||||||
Collection<String> conf = new ArrayList<>();
|
Collection<String> conf = new ArrayList<>();
|
||||||
conf.add("UseBridges 1");
|
conf.add("UseBridges 1");
|
||||||
conf.add("ClientTransportPlugin obfs4 exec " +
|
|
||||||
obfs4File.getAbsolutePath());
|
|
||||||
conf.addAll(circumventionProvider.getBridges());
|
conf.addAll(circumventionProvider.getBridges());
|
||||||
controlConnection.setConf(conf);
|
controlConnection.setConf(conf);
|
||||||
} else {
|
} else {
|
||||||
@@ -572,7 +568,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
LOG.info("Could not connect to " + scrubOnion(bestOnion)
|
LOG.info("Could not connect to " + scrubOnion(bestOnion)
|
||||||
+ ": " + e.toString());
|
+ ": " + e.toString());
|
||||||
}
|
}
|
||||||
IoUtils.tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -613,8 +609,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
LOG.info("OR connection " + status + " " + orName);
|
LOG.info("OR connection " + status + " " + orName);
|
||||||
if (status.equals("CLOSED") || status.equals("FAILED")) {
|
if (status.equals("CLOSED") || status.equals("FAILED")) {
|
||||||
// Check whether we've lost connectivity
|
// Check whether we've lost connectivity
|
||||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
batteryManager.isCharging());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,20 +644,13 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (s.getNamespace().equals(ID.getString())) {
|
if (s.getNamespace().equals(ID.getString())) {
|
||||||
LOG.info("Tor settings updated");
|
LOG.info("Tor settings updated");
|
||||||
settings = s.getSettings();
|
settings = s.getSettings();
|
||||||
// Works around a bug introduced in Tor 0.3.4.8.
|
// Works around a bug introduced in Tor 0.3.4.8. Could be
|
||||||
// https://trac.torproject.org/projects/tor/ticket/28027
|
// replaced with callback.transportDisabled() when fixed.
|
||||||
// Could be replaced with callback.transportDisabled()
|
|
||||||
// when fixed.
|
|
||||||
disableNetwork();
|
disableNetwork();
|
||||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
batteryManager.isCharging());
|
|
||||||
}
|
}
|
||||||
} else if (e instanceof NetworkStatusEvent) {
|
} else if (e instanceof NetworkStatusEvent) {
|
||||||
updateConnectionStatus(((NetworkStatusEvent) e).getStatus(),
|
updateConnectionStatus(((NetworkStatusEvent) e).getStatus());
|
||||||
batteryManager.isCharging());
|
|
||||||
} else if (e instanceof BatteryEvent) {
|
|
||||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
|
||||||
((BatteryEvent) e).isCharging());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,8 +664,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateConnectionStatus(NetworkStatus status,
|
private void updateConnectionStatus(NetworkStatus status) {
|
||||||
boolean charging) {
|
|
||||||
connectionStatusExecutor.execute(() -> {
|
connectionStatusExecutor.execute(() -> {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
boolean online = status.isConnected();
|
boolean online = status.isConnected();
|
||||||
@@ -688,8 +675,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
int network = settings.getInt(PREF_TOR_NETWORK,
|
int network = settings.getInt(PREF_TOR_NETWORK,
|
||||||
PREF_TOR_NETWORK_AUTOMATIC);
|
PREF_TOR_NETWORK_AUTOMATIC);
|
||||||
boolean useMobile = settings.getBoolean(PREF_TOR_MOBILE, true);
|
boolean useMobile = settings.getBoolean(PREF_TOR_MOBILE, true);
|
||||||
boolean onlyWhenCharging =
|
|
||||||
settings.getBoolean(PREF_TOR_ONLY_WHEN_CHARGING, false);
|
|
||||||
boolean bridgesWork = circumventionProvider.doBridgesWork(country);
|
boolean bridgesWork = circumventionProvider.doBridgesWork(country);
|
||||||
boolean automatic = network == PREF_TOR_NETWORK_AUTOMATIC;
|
boolean automatic = network == PREF_TOR_NETWORK_AUTOMATIC;
|
||||||
|
|
||||||
@@ -697,19 +682,15 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||||
if ("".equals(country)) LOG.info("Country code unknown");
|
if ("".equals(country)) LOG.info("Country code unknown");
|
||||||
else LOG.info("Country code: " + country);
|
else LOG.info("Country code: " + country);
|
||||||
LOG.info("Charging: " + charging);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!online) {
|
if (!online) {
|
||||||
LOG.info("Disabling network, device is offline");
|
LOG.info("Disabling network, device is offline");
|
||||||
enableNetwork(false);
|
enableNetwork(false);
|
||||||
} else if (!charging && onlyWhenCharging) {
|
|
||||||
LOG.info("Disabling network, device is on battery");
|
|
||||||
enableNetwork(false);
|
|
||||||
} else if (network == PREF_TOR_NETWORK_NEVER ||
|
} else if (network == PREF_TOR_NETWORK_NEVER ||
|
||||||
(!useMobile && !wifi)) {
|
(!useMobile && !wifi)) {
|
||||||
LOG.info("Disabling network, device is using mobile data");
|
LOG.info("Disabling network due to setting");
|
||||||
enableNetwork(false);
|
enableNetwork(false);
|
||||||
} else if (automatic && blocked && !bridgesWork) {
|
} else if (automatic && blocked && !bridgesWork) {
|
||||||
LOG.info("Disabling network, country is blocked");
|
LOG.info("Disabling network, country is blocked");
|
||||||
@@ -724,24 +705,12 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
enableBridges(false);
|
enableBridges(false);
|
||||||
enableNetwork(true);
|
enableNetwork(true);
|
||||||
}
|
}
|
||||||
if (online && wifi && charging) {
|
|
||||||
LOG.info("Enabling connection padding");
|
|
||||||
enableConnectionPadding(true);
|
|
||||||
} else {
|
|
||||||
LOG.info("Disabling connection padding");
|
|
||||||
enableConnectionPadding(false);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableConnectionPadding(boolean enable) throws IOException {
|
|
||||||
if (!running) return;
|
|
||||||
controlConnection.setConf("ConnectionPadding", enable ? "1" : "0");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO remove when sufficient time has passed. Added 2018-08-15
|
// TODO remove when sufficient time has passed. Added 2018-08-15
|
||||||
private void migrateSettings() {
|
private void migrateSettings() {
|
||||||
Settings sOld = callback.getSettings();
|
Settings sOld = callback.getSettings();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
|
|||||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
||||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
|
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
|
||||||
@@ -142,7 +142,15 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
@Override
|
@Override
|
||||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||||
throws DbException {
|
throws DbException {
|
||||||
return db.transactionWithResult(true, this::getLocalProperties);
|
Map<TransportId, TransportProperties> local;
|
||||||
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
local = getLocalProperties(txn);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -168,8 +176,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
public TransportProperties getLocalProperties(TransportId t)
|
public TransportProperties getLocalProperties(TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
try {
|
try {
|
||||||
return db.transactionWithResult(true, txn -> {
|
TransportProperties p = null;
|
||||||
TransportProperties p = null;
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
// Find the latest local update
|
// Find the latest local update
|
||||||
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
|
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
|
||||||
true);
|
true);
|
||||||
@@ -179,8 +188,11 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
latest.messageId);
|
latest.messageId);
|
||||||
p = parseProperties(message);
|
p = parseProperties(message);
|
||||||
}
|
}
|
||||||
return p == null ? new TransportProperties() : p;
|
db.commitTransaction(txn);
|
||||||
});
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return p == null ? new TransportProperties() : p;
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
@@ -189,12 +201,16 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
@Override
|
@Override
|
||||||
public Map<ContactId, TransportProperties> getRemoteProperties(
|
public Map<ContactId, TransportProperties> getRemoteProperties(
|
||||||
TransportId t) throws DbException {
|
TransportId t) throws DbException {
|
||||||
return db.transactionWithResult(true, txn -> {
|
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
||||||
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
for (Contact c : db.getContacts(txn))
|
for (Contact c : db.getContacts(txn))
|
||||||
remote.put(c.getId(), getRemoteProperties(txn, c, t));
|
remote.put(c.getId(), getRemoteProperties(txn, c, t));
|
||||||
return remote;
|
db.commitTransaction(txn);
|
||||||
});
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
||||||
@@ -218,15 +234,23 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
@Override
|
@Override
|
||||||
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
|
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
return db.transactionWithResult(true, txn ->
|
TransportProperties p;
|
||||||
getRemoteProperties(txn, db.getContact(txn, c), t));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
p = getRemoteProperties(txn, db.getContact(txn, c), t);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
// Merge the new properties with any existing properties
|
// Merge the new properties with any existing properties
|
||||||
TransportProperties merged;
|
TransportProperties merged;
|
||||||
boolean changed;
|
boolean changed;
|
||||||
@@ -263,7 +287,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
db.removeMessage(txn, latest.messageId);
|
db.removeMessage(txn, latest.messageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.briarproject.bramble.api.reporting.DevReporter;
|
|||||||
import org.briarproject.bramble.util.IoUtils;
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@@ -25,12 +26,13 @@ import java.net.Socket;
|
|||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -64,7 +66,7 @@ class DevReporterImpl implements DevReporter, EventListener {
|
|||||||
s.setSoTimeout(SOCKET_TIMEOUT);
|
s.setSoTimeout(SOCKET_TIMEOUT);
|
||||||
return s;
|
return s;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
tryToClose(s, LOG, WARNING);
|
tryToClose(s);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +88,8 @@ class DevReporterImpl implements DevReporter, EventListener {
|
|||||||
writer.append(armoured);
|
writer.append(armoured);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
} finally {
|
} finally {
|
||||||
tryToClose(writer, LOG, WARNING);
|
if (writer != null)
|
||||||
|
writer.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,11 +121,27 @@ class DevReporterImpl implements DevReporter, EventListener {
|
|||||||
f.delete();
|
f.delete();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
LOG.log(WARNING, "Failed to send reports", e);
|
LOG.log(WARNING, "Failed to send reports", e);
|
||||||
tryToClose(out, LOG, WARNING);
|
tryToClose(out);
|
||||||
tryToClose(in, LOG, WARNING);
|
tryToClose(in);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG.info("Reports sent");
|
LOG.info("Reports sent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tryToClose(@Nullable Closeable c) {
|
||||||
|
try {
|
||||||
|
if (c != null) c.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryToClose(@Nullable Socket s) {
|
||||||
|
try {
|
||||||
|
if (s != null) s.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,8 +23,15 @@ class SettingsManagerImpl implements SettingsManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Settings getSettings(String namespace) throws DbException {
|
public Settings getSettings(String namespace) throws DbException {
|
||||||
return db.transactionWithResult(true, txn ->
|
Settings s;
|
||||||
db.getSettings(txn, namespace));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
s = db.getSettings(txn, namespace);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -35,6 +42,12 @@ class SettingsManagerImpl implements SettingsManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeSettings(Settings s, String namespace) throws DbException {
|
public void mergeSettings(Settings s, String namespace) throws DbException {
|
||||||
db.transaction(false, txn -> db.mergeSettings(txn, s, namespace));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
db.mergeSettings(txn, s, namespace);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
|||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
@@ -229,8 +230,14 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
if (interrupted) return;
|
if (interrupted) return;
|
||||||
if (!generateAckQueued.getAndSet(false)) throw new AssertionError();
|
if (!generateAckQueued.getAndSet(false)) throw new AssertionError();
|
||||||
try {
|
try {
|
||||||
Ack a = db.transactionWithNullableResult(false, txn ->
|
Ack a;
|
||||||
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Generated ack: " + (a != null));
|
LOG.info("Generated ack: " + (a != null));
|
||||||
if (a != null) writerTasks.add(new WriteAck(a));
|
if (a != null) writerTasks.add(new WriteAck(a));
|
||||||
@@ -268,15 +275,16 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
if (!generateBatchQueued.getAndSet(false))
|
if (!generateBatchQueued.getAndSet(false))
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
try {
|
try {
|
||||||
Collection<Message> b =
|
Collection<Message> b;
|
||||||
db.transactionWithNullableResult(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
Collection<Message> batch =
|
try {
|
||||||
db.generateRequestedBatch(txn, contactId,
|
b = db.generateRequestedBatch(txn, contactId,
|
||||||
MAX_RECORD_PAYLOAD_BYTES,
|
MAX_RECORD_PAYLOAD_BYTES, maxLatency);
|
||||||
maxLatency);
|
setNextSendTime(db.getNextSendTime(txn, contactId));
|
||||||
setNextSendTime(db.getNextSendTime(txn, contactId));
|
db.commitTransaction(txn);
|
||||||
return batch;
|
} finally {
|
||||||
});
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Generated batch: " + (b != null));
|
LOG.info("Generated batch: " + (b != null));
|
||||||
if (b != null) writerTasks.add(new WriteBatch(b));
|
if (b != null) writerTasks.add(new WriteBatch(b));
|
||||||
@@ -314,12 +322,16 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
if (!generateOfferQueued.getAndSet(false))
|
if (!generateOfferQueued.getAndSet(false))
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
try {
|
try {
|
||||||
Offer o = db.transactionWithNullableResult(false, txn -> {
|
Offer o;
|
||||||
Offer offer = db.generateOffer(txn, contactId,
|
Transaction txn = db.startTransaction(false);
|
||||||
MAX_MESSAGE_IDS, maxLatency);
|
try {
|
||||||
|
o = db.generateOffer(txn, contactId, MAX_MESSAGE_IDS,
|
||||||
|
maxLatency);
|
||||||
setNextSendTime(db.getNextSendTime(txn, contactId));
|
setNextSendTime(db.getNextSendTime(txn, contactId));
|
||||||
return offer;
|
db.commitTransaction(txn);
|
||||||
});
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Generated offer: " + (o != null));
|
LOG.info("Generated offer: " + (o != null));
|
||||||
if (o != null) writerTasks.add(new WriteOffer(o));
|
if (o != null) writerTasks.add(new WriteOffer(o));
|
||||||
@@ -357,8 +369,14 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
if (!generateRequestQueued.getAndSet(false))
|
if (!generateRequestQueued.getAndSet(false))
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
try {
|
try {
|
||||||
Request r = db.transactionWithNullableResult(false, txn ->
|
Request r;
|
||||||
db.generateRequest(txn, contactId, MAX_MESSAGE_IDS));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
r = db.generateRequest(txn, contactId, MAX_MESSAGE_IDS);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Generated request: " + (r != null));
|
LOG.info("Generated request: " + (r != null));
|
||||||
if (r != null) writerTasks.add(new WriteRequest(r));
|
if (r != null) writerTasks.add(new WriteRequest(r));
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
|||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
@@ -119,8 +120,13 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn ->
|
Transaction txn = db.startTransaction(false);
|
||||||
db.receiveAck(txn, contactId, ack));
|
try {
|
||||||
|
db.receiveAck(txn, contactId, ack);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
@@ -140,8 +146,13 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn ->
|
Transaction txn = db.startTransaction(false);
|
||||||
db.receiveMessage(txn, contactId, message));
|
try {
|
||||||
|
db.receiveMessage(txn, contactId, message);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
@@ -161,8 +172,13 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn ->
|
Transaction txn = db.startTransaction(false);
|
||||||
db.receiveOffer(txn, contactId, offer));
|
try {
|
||||||
|
db.receiveOffer(txn, contactId, offer);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
@@ -182,8 +198,13 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn ->
|
Transaction txn = db.startTransaction(false);
|
||||||
db.receiveRequest(txn, contactId, request));
|
try {
|
||||||
|
db.receiveRequest(txn, contactId, request);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
|||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
@@ -46,8 +47,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(SimplexOutgoingSession.class.getName());
|
Logger.getLogger(SimplexOutgoingSession.class.getName());
|
||||||
|
|
||||||
private static final ThrowingRunnable<IOException> CLOSE = () -> {
|
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
|
||||||
};
|
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final Executor dbExecutor;
|
private final Executor dbExecutor;
|
||||||
@@ -128,8 +128,14 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
public void run() {
|
public void run() {
|
||||||
if (interrupted) return;
|
if (interrupted) return;
|
||||||
try {
|
try {
|
||||||
Ack a = db.transactionWithNullableResult(false, txn ->
|
Ack a;
|
||||||
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Generated ack: " + (a != null));
|
LOG.info("Generated ack: " + (a != null));
|
||||||
if (a == null) decrementOutstandingQueries();
|
if (a == null) decrementOutstandingQueries();
|
||||||
@@ -166,10 +172,15 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
public void run() {
|
public void run() {
|
||||||
if (interrupted) return;
|
if (interrupted) return;
|
||||||
try {
|
try {
|
||||||
Collection<Message> b =
|
Collection<Message> b;
|
||||||
db.transactionWithNullableResult(false, txn ->
|
Transaction txn = db.startTransaction(false);
|
||||||
db.generateBatch(txn, contactId,
|
try {
|
||||||
MAX_RECORD_PAYLOAD_BYTES, maxLatency));
|
b = db.generateBatch(txn, contactId,
|
||||||
|
MAX_RECORD_PAYLOAD_BYTES, maxLatency);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Generated batch: " + (b != null));
|
LOG.info("Generated batch: " + (b != null));
|
||||||
if (b == null) decrementOutstandingQueries();
|
if (b == null) decrementOutstandingQueries();
|
||||||
|
|||||||
@@ -1,11 +1,23 @@
|
|||||||
package org.briarproject.bramble.sync;
|
package org.briarproject.bramble.sync;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.PoliteExecutor;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.sync.GroupFactory;
|
import org.briarproject.bramble.api.sync.GroupFactory;
|
||||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
import org.briarproject.bramble.api.sync.SyncRecordReaderFactory;
|
import org.briarproject.bramble.api.sync.SyncRecordReaderFactory;
|
||||||
import org.briarproject.bramble.api.sync.SyncRecordWriterFactory;
|
import org.briarproject.bramble.api.sync.SyncRecordWriterFactory;
|
||||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||||
|
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
@@ -14,14 +26,29 @@ import dagger.Provides;
|
|||||||
@Module
|
@Module
|
||||||
public class SyncModule {
|
public class SyncModule {
|
||||||
|
|
||||||
|
public static class EagerSingletons {
|
||||||
|
@Inject
|
||||||
|
ValidationManager validationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of validation tasks to delegate to the crypto
|
||||||
|
* executor concurrently.
|
||||||
|
* <p>
|
||||||
|
* The number of available processors can change during the lifetime of the
|
||||||
|
* JVM, so this is just a reasonable guess.
|
||||||
|
*/
|
||||||
|
private static final int MAX_CONCURRENT_VALIDATION_TASKS =
|
||||||
|
Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
GroupFactory provideGroupFactory(GroupFactoryImpl groupFactory) {
|
GroupFactory provideGroupFactory(CryptoComponent crypto) {
|
||||||
return groupFactory;
|
return new GroupFactoryImpl(crypto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
MessageFactory provideMessageFactory(MessageFactoryImpl messageFactory) {
|
MessageFactory provideMessageFactory(CryptoComponent crypto) {
|
||||||
return messageFactory;
|
return new MessageFactoryImpl(crypto);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@@ -38,8 +65,30 @@ public class SyncModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
SyncSessionFactory provideSyncSessionFactory(
|
SyncSessionFactory provideSyncSessionFactory(DatabaseComponent db,
|
||||||
SyncSessionFactoryImpl syncSessionFactory) {
|
@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
|
||||||
return syncSessionFactory;
|
Clock clock, SyncRecordReaderFactory recordReaderFactory,
|
||||||
|
SyncRecordWriterFactory recordWriterFactory) {
|
||||||
|
return new SyncSessionFactoryImpl(db, dbExecutor, eventBus, clock,
|
||||||
|
recordReaderFactory, recordWriterFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
ValidationManager provideValidationManager(
|
||||||
|
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||||
|
ValidationManagerImpl validationManager) {
|
||||||
|
lifecycleManager.registerService(validationManager);
|
||||||
|
eventBus.addListener(validationManager);
|
||||||
|
return validationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@ValidationExecutor
|
||||||
|
Executor provideValidationExecutor(
|
||||||
|
@CryptoExecutor Executor cryptoExecutor) {
|
||||||
|
return new PoliteExecutor("ValidationExecutor", cryptoExecutor,
|
||||||
|
MAX_CONCURRENT_VALIDATION_TASKS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package org.briarproject.bramble.sync.validation;
|
package org.briarproject.bramble.sync;
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble.sync.validation;
|
package org.briarproject.bramble.sync;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.Pair;
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
@@ -18,11 +17,8 @@ import org.briarproject.bramble.api.sync.InvalidMessageException;
|
|||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageContext;
|
import org.briarproject.bramble.api.sync.MessageContext;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||||
import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
|
import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
|
||||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageValidator;
|
|
||||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
|
||||||
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
|
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -40,9 +36,9 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
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;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.INVALID;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@@ -101,8 +97,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void validateOutstandingMessages() {
|
private void validateOutstandingMessages() {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> unvalidated = new LinkedList<>(
|
Queue<MessageId> unvalidated = new LinkedList<>();
|
||||||
db.transactionWithResult(true, db::getMessagesToValidate));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
unvalidated.addAll(db.getMessagesToValidate(txn));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
validateNextMessageAsync(unvalidated);
|
validateNextMessageAsync(unvalidated);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -117,14 +119,18 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void validateNextMessage(Queue<MessageId> unvalidated) {
|
private void validateNextMessage(Queue<MessageId> unvalidated) {
|
||||||
try {
|
try {
|
||||||
Pair<Message, Group> mg = db.transactionWithResult(true, txn -> {
|
Message m;
|
||||||
|
Group g;
|
||||||
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
MessageId id = unvalidated.poll();
|
MessageId id = unvalidated.poll();
|
||||||
if (id == null) throw new AssertionError();
|
m = db.getMessage(txn, id);
|
||||||
Message m = db.getMessage(txn, id);
|
g = db.getGroup(txn, m.getGroupId());
|
||||||
Group g = db.getGroup(txn, m.getGroupId());
|
db.commitTransaction(txn);
|
||||||
return new Pair<>(m, g);
|
} finally {
|
||||||
});
|
db.endTransaction(txn);
|
||||||
validateMessageAsync(mg.getFirst(), mg.getSecond());
|
}
|
||||||
|
validateMessageAsync(m, g);
|
||||||
validateNextMessageAsync(unvalidated);
|
validateNextMessageAsync(unvalidated);
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
LOG.info("Message removed before validation");
|
LOG.info("Message removed before validation");
|
||||||
@@ -144,8 +150,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void deliverOutstandingMessages() {
|
private void deliverOutstandingMessages() {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> pending = new LinkedList<>(
|
Queue<MessageId> pending = new LinkedList<>();
|
||||||
db.transactionWithResult(true, db::getPendingMessages));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
pending.addAll(db.getPendingMessages(txn));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
deliverNextPendingMessageAsync(pending);
|
deliverNextPendingMessageAsync(pending);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -160,24 +172,24 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void deliverNextPendingMessage(Queue<MessageId> pending) {
|
private void deliverNextPendingMessage(Queue<MessageId> pending) {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> toShare = new LinkedList<>();
|
boolean anyInvalid = false, allDelivered = true;
|
||||||
Queue<MessageId> invalidate = new LinkedList<>();
|
Queue<MessageId> toShare = null;
|
||||||
db.transaction(false, txn -> {
|
Queue<MessageId> invalidate = null;
|
||||||
boolean anyInvalid = false, allDelivered = true;
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
MessageId id = pending.poll();
|
MessageId id = pending.poll();
|
||||||
if (id == null) throw new AssertionError();
|
|
||||||
// Check if message is still pending
|
// Check if message is still pending
|
||||||
if (db.getMessageState(txn, id) == PENDING) {
|
if (db.getMessageState(txn, id) == PENDING) {
|
||||||
// Check if dependencies are valid and delivered
|
// Check if dependencies are valid and delivered
|
||||||
Map<MessageId, MessageState> states =
|
Map<MessageId, State> states =
|
||||||
db.getMessageDependencies(txn, id);
|
db.getMessageDependencies(txn, id);
|
||||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||||
if (e.getValue() == INVALID) anyInvalid = true;
|
if (e.getValue() == INVALID) anyInvalid = true;
|
||||||
if (e.getValue() != DELIVERED) allDelivered = false;
|
if (e.getValue() != DELIVERED) allDelivered = false;
|
||||||
}
|
}
|
||||||
if (anyInvalid) {
|
if (anyInvalid) {
|
||||||
invalidateMessage(txn, id);
|
invalidateMessage(txn, id);
|
||||||
addDependentsToInvalidate(txn, id, invalidate);
|
invalidate = getDependentsToInvalidate(txn, id);
|
||||||
} else if (allDelivered) {
|
} else if (allDelivered) {
|
||||||
Message m = db.getMessage(txn, id);
|
Message m = db.getMessage(txn, id);
|
||||||
Group g = db.getGroup(txn, m.getGroupId());
|
Group g = db.getGroup(txn, m.getGroupId());
|
||||||
@@ -188,19 +200,22 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
DeliveryResult result =
|
DeliveryResult result =
|
||||||
deliverMessage(txn, m, c, majorVersion, meta);
|
deliverMessage(txn, m, c, majorVersion, meta);
|
||||||
if (result.valid) {
|
if (result.valid) {
|
||||||
addPendingDependents(txn, id, pending);
|
pending.addAll(getPendingDependents(txn, id));
|
||||||
if (result.share) {
|
if (result.share) {
|
||||||
db.setMessageShared(txn, id);
|
db.setMessageShared(txn, id);
|
||||||
toShare.addAll(states.keySet());
|
toShare = new LinkedList<>(states.keySet());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addDependentsToInvalidate(txn, id, invalidate);
|
invalidate = getDependentsToInvalidate(txn, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
if (!invalidate.isEmpty()) invalidateNextMessageAsync(invalidate);
|
} finally {
|
||||||
if (!toShare.isEmpty()) shareNextMessageAsync(toShare);
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
if (invalidate != null) invalidateNextMessageAsync(invalidate);
|
||||||
|
if (toShare != null) shareNextMessageAsync(toShare);
|
||||||
deliverNextPendingMessageAsync(pending);
|
deliverNextPendingMessageAsync(pending);
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
LOG.info("Message removed before delivery");
|
LOG.info("Message removed before delivery");
|
||||||
@@ -249,19 +264,20 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
MessageContext context) {
|
MessageContext context) {
|
||||||
try {
|
try {
|
||||||
MessageId id = m.getId();
|
MessageId id = m.getId();
|
||||||
Queue<MessageId> invalidate = new LinkedList<>();
|
boolean anyInvalid = false, allDelivered = true;
|
||||||
Queue<MessageId> pending = new LinkedList<>();
|
Queue<MessageId> invalidate = null;
|
||||||
Queue<MessageId> toShare = new LinkedList<>();
|
Queue<MessageId> pending = null;
|
||||||
db.transaction(false, txn -> {
|
Queue<MessageId> toShare = null;
|
||||||
boolean anyInvalid = false, allDelivered = true;
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
// Check if message has any dependencies
|
// Check if message has any dependencies
|
||||||
Collection<MessageId> dependencies = context.getDependencies();
|
Collection<MessageId> dependencies = context.getDependencies();
|
||||||
if (!dependencies.isEmpty()) {
|
if (!dependencies.isEmpty()) {
|
||||||
db.addMessageDependencies(txn, m, dependencies);
|
db.addMessageDependencies(txn, m, dependencies);
|
||||||
// Check if dependencies are valid and delivered
|
// Check if dependencies are valid and delivered
|
||||||
Map<MessageId, MessageState> states =
|
Map<MessageId, State> states =
|
||||||
db.getMessageDependencies(txn, id);
|
db.getMessageDependencies(txn, id);
|
||||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||||
if (e.getValue() == INVALID) anyInvalid = true;
|
if (e.getValue() == INVALID) anyInvalid = true;
|
||||||
if (e.getValue() != DELIVERED) allDelivered = false;
|
if (e.getValue() != DELIVERED) allDelivered = false;
|
||||||
}
|
}
|
||||||
@@ -269,7 +285,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
if (anyInvalid) {
|
if (anyInvalid) {
|
||||||
if (db.getMessageState(txn, id) != INVALID) {
|
if (db.getMessageState(txn, id) != INVALID) {
|
||||||
invalidateMessage(txn, id);
|
invalidateMessage(txn, id);
|
||||||
addDependentsToInvalidate(txn, id, invalidate);
|
invalidate = getDependentsToInvalidate(txn, id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Metadata meta = context.getMetadata();
|
Metadata meta = context.getMetadata();
|
||||||
@@ -278,22 +294,25 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
DeliveryResult result =
|
DeliveryResult result =
|
||||||
deliverMessage(txn, m, c, majorVersion, meta);
|
deliverMessage(txn, m, c, majorVersion, meta);
|
||||||
if (result.valid) {
|
if (result.valid) {
|
||||||
addPendingDependents(txn, id, pending);
|
pending = getPendingDependents(txn, id);
|
||||||
if (result.share) {
|
if (result.share) {
|
||||||
db.setMessageShared(txn, id);
|
db.setMessageShared(txn, id);
|
||||||
toShare.addAll(dependencies);
|
toShare = new LinkedList<>(dependencies);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
addDependentsToInvalidate(txn, id, invalidate);
|
invalidate = getDependentsToInvalidate(txn, id);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
db.setMessageState(txn, id, PENDING);
|
db.setMessageState(txn, id, PENDING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
if (!invalidate.isEmpty()) invalidateNextMessageAsync(invalidate);
|
} finally {
|
||||||
if (!pending.isEmpty()) deliverNextPendingMessageAsync(pending);
|
db.endTransaction(txn);
|
||||||
if (!toShare.isEmpty()) shareNextMessageAsync(toShare);
|
}
|
||||||
|
if (invalidate != null) invalidateNextMessageAsync(invalidate);
|
||||||
|
if (pending != null) deliverNextPendingMessageAsync(pending);
|
||||||
|
if (toShare != null) shareNextMessageAsync(toShare);
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
LOG.info("Message removed during validation");
|
LOG.info("Message removed during validation");
|
||||||
} catch (NoSuchGroupException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
@@ -323,12 +342,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void addPendingDependents(Transaction txn, MessageId m,
|
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
|
||||||
Queue<MessageId> pending) throws DbException {
|
throws DbException {
|
||||||
Map<MessageId, MessageState> states = db.getMessageDependents(txn, m);
|
Queue<MessageId> pending = new LinkedList<>();
|
||||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
||||||
|
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||||
if (e.getValue() == PENDING) pending.add(e.getKey());
|
if (e.getValue() == PENDING) pending.add(e.getKey());
|
||||||
}
|
}
|
||||||
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shareOutstandingMessagesAsync() {
|
private void shareOutstandingMessagesAsync() {
|
||||||
@@ -338,8 +359,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void shareOutstandingMessages() {
|
private void shareOutstandingMessages() {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> toShare = new LinkedList<>(
|
Queue<MessageId> toShare = new LinkedList<>();
|
||||||
db.transactionWithResult(true, db::getMessagesToShare));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
toShare.addAll(db.getMessagesToShare(txn));
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
shareNextMessageAsync(toShare);
|
shareNextMessageAsync(toShare);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
@@ -360,12 +387,15 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void shareNextMessage(Queue<MessageId> toShare) {
|
private void shareNextMessage(Queue<MessageId> toShare) {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
MessageId id = toShare.poll();
|
MessageId id = toShare.poll();
|
||||||
if (id == null) throw new AssertionError();
|
|
||||||
db.setMessageShared(txn, id);
|
db.setMessageShared(txn, id);
|
||||||
toShare.addAll(db.getMessageDependencies(txn, id).keySet());
|
toShare.addAll(db.getMessageDependencies(txn, id).keySet());
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
shareNextMessageAsync(toShare);
|
shareNextMessageAsync(toShare);
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
LOG.info("Message removed before sharing");
|
LOG.info("Message removed before sharing");
|
||||||
@@ -386,14 +416,17 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void invalidateNextMessage(Queue<MessageId> invalidate) {
|
private void invalidateNextMessage(Queue<MessageId> invalidate) {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
MessageId id = invalidate.poll();
|
MessageId id = invalidate.poll();
|
||||||
if (id == null) throw new AssertionError();
|
|
||||||
if (db.getMessageState(txn, id) != INVALID) {
|
if (db.getMessageState(txn, id) != INVALID) {
|
||||||
invalidateMessage(txn, id);
|
invalidateMessage(txn, id);
|
||||||
addDependentsToInvalidate(txn, id, invalidate);
|
invalidate.addAll(getDependentsToInvalidate(txn, id));
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
invalidateNextMessageAsync(invalidate);
|
invalidateNextMessageAsync(invalidate);
|
||||||
} catch (NoSuchMessageException e) {
|
} catch (NoSuchMessageException e) {
|
||||||
LOG.info("Message removed before invalidation");
|
LOG.info("Message removed before invalidation");
|
||||||
@@ -412,12 +445,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void addDependentsToInvalidate(Transaction txn,
|
private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
|
||||||
MessageId m, Queue<MessageId> invalidate) throws DbException {
|
MessageId m) throws DbException {
|
||||||
Map<MessageId, MessageState> states = db.getMessageDependents(txn, m);
|
Queue<MessageId> invalidate = new LinkedList<>();
|
||||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
||||||
|
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||||
if (e.getValue() != INVALID) invalidate.add(e.getKey());
|
if (e.getValue() != INVALID) invalidate.add(e.getKey());
|
||||||
}
|
}
|
||||||
|
return invalidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -437,8 +472,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void loadGroupAndValidate(Message m) {
|
private void loadGroupAndValidate(Message m) {
|
||||||
try {
|
try {
|
||||||
Group g = db.transactionWithResult(true, txn ->
|
Group g;
|
||||||
db.getGroup(txn, m.getGroupId()));
|
Transaction txn = db.startTransaction(true);
|
||||||
|
try {
|
||||||
|
g = db.getGroup(txn, m.getGroupId());
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
validateMessageAsync(m, g);
|
validateMessageAsync(m, g);
|
||||||
} catch (NoSuchGroupException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
LOG.info("Group removed before validation");
|
LOG.info("Group removed before validation");
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
package org.briarproject.bramble.sync.validation;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.PoliteExecutor;
|
|
||||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
|
||||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import dagger.Module;
|
|
||||||
import dagger.Provides;
|
|
||||||
|
|
||||||
@Module
|
|
||||||
public class ValidationModule {
|
|
||||||
|
|
||||||
public static class EagerSingletons {
|
|
||||||
@Inject
|
|
||||||
ValidationManager validationManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The maximum number of validation tasks to delegate to the crypto
|
|
||||||
* executor concurrently.
|
|
||||||
* <p>
|
|
||||||
* The number of available processors can change during the lifetime of the
|
|
||||||
* JVM, so this is just a reasonable guess.
|
|
||||||
*/
|
|
||||||
private static final int MAX_CONCURRENT_VALIDATION_TASKS =
|
|
||||||
Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
ValidationManager provideValidationManager(
|
|
||||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
|
||||||
ValidationManagerImpl validationManager) {
|
|
||||||
lifecycleManager.registerService(validationManager);
|
|
||||||
eventBus.addListener(validationManager);
|
|
||||||
return validationManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
@ValidationExecutor
|
|
||||||
Executor provideValidationExecutor(
|
|
||||||
@CryptoExecutor Executor cryptoExecutor) {
|
|
||||||
return new PoliteExecutor("ValidationExecutor", cryptoExecutor,
|
|
||||||
MAX_CONCURRENT_VALIDATION_TASKS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,33 +13,32 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class UnixSecureRandomProvider extends AbstractSecureRandomProvider {
|
class LinuxSecureRandomProvider extends AbstractSecureRandomProvider {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(UnixSecureRandomProvider.class.getName());
|
Logger.getLogger(LinuxSecureRandomProvider.class.getName());
|
||||||
|
|
||||||
private static final File RANDOM_DEVICE = new File("/dev/urandom");
|
private static final File RANDOM_DEVICE = new File("/dev/urandom");
|
||||||
|
|
||||||
private final AtomicBoolean seeded = new AtomicBoolean(false);
|
private final AtomicBoolean seeded = new AtomicBoolean(false);
|
||||||
private final File outputDevice;
|
private final File outputDevice;
|
||||||
|
|
||||||
UnixSecureRandomProvider() {
|
LinuxSecureRandomProvider() {
|
||||||
this(RANDOM_DEVICE);
|
this(RANDOM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnixSecureRandomProvider(File outputDevice) {
|
LinuxSecureRandomProvider(File outputDevice) {
|
||||||
this.outputDevice = outputDevice;
|
this.outputDevice = outputDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Provider getProvider() {
|
public Provider getProvider() {
|
||||||
if (!seeded.getAndSet(true)) writeSeed();
|
if (!seeded.getAndSet(true)) writeSeed();
|
||||||
return new UnixProvider();
|
return new LinuxProvider();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeSeed() {
|
protected void writeSeed() {
|
||||||
@@ -56,15 +55,15 @@ class UnixSecureRandomProvider extends AbstractSecureRandomProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
||||||
private static class UnixProvider extends Provider {
|
private static class LinuxProvider extends Provider {
|
||||||
|
|
||||||
private UnixProvider() {
|
private LinuxProvider() {
|
||||||
super("UnixPRNG", 1.0, "A Unix-specific PRNG using /dev/urandom");
|
super("LinuxPRNG", 1.1, "A Linux-specific PRNG using /dev/urandom");
|
||||||
// Although /dev/urandom is not a SHA-1 PRNG, some callers
|
// Although /dev/urandom is not a SHA-1 PRNG, some callers
|
||||||
// explicitly request a SHA1PRNG SecureRandom and we need to
|
// explicitly request a SHA1PRNG SecureRandom and we need to
|
||||||
// prevent them from getting the default implementation whose
|
// prevent them from getting the default implementation whose
|
||||||
// output may have low entropy.
|
// output may have low entropy.
|
||||||
put("SecureRandom.SHA1PRNG", UnixSecureRandomSpi.class.getName());
|
put("SecureRandom.SHA1PRNG", LinuxSecureRandomSpi.class.getName());
|
||||||
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
|
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,24 +10,22 @@ import java.security.SecureRandomSpi;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
public class UnixSecureRandomSpi extends SecureRandomSpi {
|
public class LinuxSecureRandomSpi extends SecureRandomSpi {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
getLogger(UnixSecureRandomSpi.class.getName());
|
Logger.getLogger(LinuxSecureRandomSpi.class.getName());
|
||||||
|
|
||||||
private static final File RANDOM_DEVICE = new File("/dev/urandom");
|
private static final File RANDOM_DEVICE = new File("/dev/urandom");
|
||||||
|
|
||||||
private final File inputDevice, outputDevice;
|
private final File inputDevice, outputDevice;
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
public LinuxSecureRandomSpi() {
|
||||||
public UnixSecureRandomSpi() {
|
|
||||||
this(RANDOM_DEVICE, RANDOM_DEVICE);
|
this(RANDOM_DEVICE, RANDOM_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnixSecureRandomSpi(File inputDevice, File outputDevice) {
|
LinuxSecureRandomSpi(File inputDevice, File outputDevice) {
|
||||||
this.inputDevice = inputDevice;
|
this.inputDevice = inputDevice;
|
||||||
this.outputDevice = outputDevice;
|
this.outputDevice = outputDevice;
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,8 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
|
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
|
||||||
transports.put(f.getId(), f.getMaxLatency());
|
transports.put(f.getId(), f.getMaxLatency());
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
for (Contact c : db.getContacts(txn))
|
for (Contact c : db.getContacts(txn))
|
||||||
if (c.isActive()) activeContacts.put(c.getId(), true);
|
if (c.isActive()) activeContacts.put(c.getId(), true);
|
||||||
for (Entry<TransportId, Integer> e : transports.entrySet())
|
for (Entry<TransportId, Integer> e : transports.entrySet())
|
||||||
@@ -84,7 +85,10 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
managers.put(e.getKey(), m);
|
managers.put(e.getKey(), m);
|
||||||
m.start(txn);
|
m.start(txn);
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
throw new ServiceException(e);
|
throw new ServiceException(e);
|
||||||
}
|
}
|
||||||
@@ -137,8 +141,15 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return db.transactionWithNullableResult(false, txn ->
|
StreamContext ctx;
|
||||||
m.getStreamContext(txn, c));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
ctx = m.getStreamContext(txn, c);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -149,8 +160,15 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return db.transactionWithNullableResult(false, txn ->
|
StreamContext ctx;
|
||||||
m.getStreamContext(txn, tag));
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
ctx = m.getStreamContext(txn, tag);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -162,7 +162,13 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
private void rotateKeys() {
|
private void rotateKeys() {
|
||||||
dbExecutor.execute(() -> {
|
dbExecutor.execute(() -> {
|
||||||
try {
|
try {
|
||||||
db.transaction(false, this::rotateKeys);
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
rotateKeys(txn);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
|
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
|
||||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||||
@@ -89,9 +89,14 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
|
|||||||
public Visibility getClientVisibility(Transaction txn, ContactId contactId,
|
public Visibility getClientVisibility(Transaction txn, ContactId contactId,
|
||||||
ClientId clientId, int majorVersion) throws DbException {
|
ClientId clientId, int majorVersion) throws DbException {
|
||||||
try {
|
try {
|
||||||
LatestUpdates latest = findLatestUpdates(txn, contactId);
|
Contact contact = db.getContact(txn, contactId);
|
||||||
if (latest == null || latest.remote == null) return INVISIBLE;
|
Group g = getContactGroup(contact);
|
||||||
|
// Contact may be in the process of being added or removed, so
|
||||||
|
// contact group may not exist
|
||||||
|
if (!db.containsGroup(txn, g.getId())) return INVISIBLE;
|
||||||
|
LatestUpdates latest = findLatestUpdates(txn, g.getId());
|
||||||
if (latest.local == null) throw new DbException();
|
if (latest.local == null) throw new DbException();
|
||||||
|
if (latest.remote == null) return INVISIBLE;
|
||||||
Update localUpdate = loadUpdate(txn, latest.local.messageId);
|
Update localUpdate = loadUpdate(txn, latest.local.messageId);
|
||||||
Update remoteUpdate = loadUpdate(txn, latest.remote.messageId);
|
Update remoteUpdate = loadUpdate(txn, latest.remote.messageId);
|
||||||
Map<ClientMajorVersion, Visibility> visibilities =
|
Map<ClientMajorVersion, Visibility> visibilities =
|
||||||
@@ -105,24 +110,6 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getClientMinorVersion(Transaction txn, ContactId contactId,
|
|
||||||
ClientId clientId, int majorVersion) throws DbException {
|
|
||||||
try {
|
|
||||||
LatestUpdates latest = findLatestUpdates(txn, contactId);
|
|
||||||
if (latest == null || latest.remote == null) return -1;
|
|
||||||
Update remoteUpdate = loadUpdate(txn, latest.remote.messageId);
|
|
||||||
ClientMajorVersion cv =
|
|
||||||
new ClientMajorVersion(clientId, majorVersion);
|
|
||||||
for (ClientState remote : remoteUpdate.states) {
|
|
||||||
if (remote.majorVersion.equals(cv)) return remote.minorVersion;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
} catch (FormatException e) {
|
|
||||||
throw new DbException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createLocalState(Transaction txn) throws DbException {
|
public void createLocalState(Transaction txn) throws DbException {
|
||||||
if (db.containsGroup(txn, localGroup.getId())) return;
|
if (db.containsGroup(txn, localGroup.getId())) return;
|
||||||
@@ -136,12 +123,16 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
|
|||||||
List<ClientVersion> versions = new ArrayList<>(clients);
|
List<ClientVersion> versions = new ArrayList<>(clients);
|
||||||
Collections.sort(versions);
|
Collections.sort(versions);
|
||||||
try {
|
try {
|
||||||
db.transaction(false, txn -> {
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
if (updateClientVersions(txn, versions)) {
|
if (updateClientVersions(txn, versions)) {
|
||||||
for (Contact c : db.getContacts(txn))
|
for (Contact c : db.getContacts(txn))
|
||||||
clientVersionsUpdated(txn, c, versions);
|
clientVersionsUpdated(txn, c, versions);
|
||||||
}
|
}
|
||||||
});
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
throw new ServiceException(e);
|
throw new ServiceException(e);
|
||||||
}
|
}
|
||||||
@@ -349,17 +340,6 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
|
|||||||
MAJOR_VERSION, c);
|
MAJOR_VERSION, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private LatestUpdates findLatestUpdates(Transaction txn, ContactId c)
|
|
||||||
throws DbException, FormatException {
|
|
||||||
Contact contact = db.getContact(txn, c);
|
|
||||||
Group g = getContactGroup(contact);
|
|
||||||
// Contact may be in the process of being added or removed, so
|
|
||||||
// contact group may not exist
|
|
||||||
if (!db.containsGroup(txn, g.getId())) return null;
|
|
||||||
return findLatestUpdates(txn, g.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private LatestUpdates findLatestUpdates(Transaction txn, GroupId g)
|
private LatestUpdates findLatestUpdates(Transaction txn, GroupId g)
|
||||||
throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
Map<MessageId, BdfDictionary> metadata =
|
Map<MessageId, BdfDictionary> metadata =
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
|
|||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0
|
Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
|
||||||
Bridge obfs4 52.15.78.72:9443 02069A3C5362476936B62BA6F5ACC41ABD573A9B cert=ijYG/OKc7kqu2YzKNFfeXN7/BG2BOgfEP2KyYEiGDQthnHbsOiTWHeIG0WJVW+BckzDgKw iat-mode=0
|
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
|
||||||
Bridge obfs4 13.58.29.242:9443 0C58939A77DA6B6B29D4B5236A75865659607AE0 cert=OylWIEHb/ezpq1zWxW0sgKRn+9ARH2eOcQOZ8/Gew+4l+oKOhQ2jUX/Y+FSl61JorXZUWA iat-mode=0
|
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
|
||||||
Bridge obfs4 45.33.37.112:9443 60A609BB4ABE8D46E634AE81ED29ADAB7776B399 cert=t5v19WmNv5Sc2YPNr8RQids365W7MY8zJwQVkOxBjUMFomMWARDzsbYpcWLLcw0J9Gm+BQ iat-mode=0
|
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
|
||||||
|
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
|
||||||
|
Bridge 85.229.131.78:444 50E433CCC5FEC11CC34CB4D92033561E065EA106
|
||||||
|
Bridge 178.62.62.193:8443 391B1F9B6A28A1C5FAE1872283985F975E5DB029
|
||||||
|
Bridge 45.76.29.92:8443 ECF1DD51A46FDEF2C50CED992EEEAE8DED18DA0C
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
package org.briarproject.bramble;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import static java.util.Arrays.asList;
|
|
||||||
import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
public class PriorityExecutorTest extends BrambleTestCase {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHighPriorityTasksAreDelegatedInOrderOfSubmission()
|
|
||||||
throws Exception {
|
|
||||||
Executor delegate = newSingleThreadExecutor();
|
|
||||||
PriorityExecutor priority = new PriorityExecutor(delegate);
|
|
||||||
Executor high = priority.getHighPriorityExecutor();
|
|
||||||
testTasksAreDelegatedInOrderOfSubmission(high);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLowPriorityTasksAreDelegatedInOrderOfSubmission()
|
|
||||||
throws Exception {
|
|
||||||
Executor delegate = newSingleThreadExecutor();
|
|
||||||
PriorityExecutor priority = new PriorityExecutor(delegate);
|
|
||||||
Executor low = priority.getLowPriorityExecutor();
|
|
||||||
testTasksAreDelegatedInOrderOfSubmission(low);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHighPriorityTasksAreRunFirst() throws Exception {
|
|
||||||
Executor delegate = newSingleThreadExecutor();
|
|
||||||
PriorityExecutor priority = new PriorityExecutor(delegate);
|
|
||||||
Executor high = priority.getHighPriorityExecutor();
|
|
||||||
Executor low = priority.getLowPriorityExecutor();
|
|
||||||
// Submit a task that will block, causing other tasks to be queued
|
|
||||||
CountDownLatch cork = new CountDownLatch(1);
|
|
||||||
low.execute(() -> {
|
|
||||||
try {
|
|
||||||
cork.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// Submit alternating tasks to the high and low priority executors
|
|
||||||
List<Integer> results = new Vector<>();
|
|
||||||
CountDownLatch tasksFinished = new CountDownLatch(10);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
int result = i;
|
|
||||||
Runnable task = () -> {
|
|
||||||
results.add(result);
|
|
||||||
tasksFinished.countDown();
|
|
||||||
};
|
|
||||||
if (i % 2 == 0) high.execute(task);
|
|
||||||
else low.execute(task);
|
|
||||||
}
|
|
||||||
// Release the cork and wait for all tasks to finish
|
|
||||||
cork.countDown();
|
|
||||||
tasksFinished.await();
|
|
||||||
// The high-priority tasks should have run before the low-priority tasks
|
|
||||||
assertEquals(asList(0, 2, 4, 6, 8, 1, 3, 5, 7, 9), results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testTasksAreDelegatedInOrderOfSubmission(Executor e)
|
|
||||||
throws Exception {
|
|
||||||
List<Integer> results = new Vector<>();
|
|
||||||
CountDownLatch tasksFinished = new CountDownLatch(10);
|
|
||||||
for (int i = 0; i < 10; i++) {
|
|
||||||
int result = i;
|
|
||||||
e.execute(() -> {
|
|
||||||
results.add(result);
|
|
||||||
tasksFinished.countDown();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Wait for all the tasks to finish
|
|
||||||
tasksFinished.await();
|
|
||||||
// The tasks should have run in the order they were submitted
|
|
||||||
assertEquals(asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), results);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,7 +22,6 @@ import org.briarproject.bramble.api.sync.Message;
|
|||||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.DbExpectations;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
@@ -86,11 +85,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
boolean shared = new Random().nextBoolean();
|
boolean shared = new Random().nextBoolean();
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(metadataEncoder).encode(dictionary);
|
oneOf(metadataEncoder).encode(dictionary);
|
||||||
will(returnValue(metadata));
|
will(returnValue(metadata));
|
||||||
oneOf(db).addLocalMessage(txn, message, metadata, shared);
|
oneOf(db).addLocalMessage(txn, message, metadata, shared);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
clientHelper.addLocalMessage(message, dictionary, shared);
|
clientHelper.addLocalMessage(message, dictionary, shared);
|
||||||
@@ -114,10 +116,13 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
expectToList(true);
|
expectToList(true);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getMessage(txn, messageId);
|
oneOf(db).getMessage(txn, messageId);
|
||||||
will(returnValue(message));
|
will(returnValue(message));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
clientHelper.getMessageAsList(messageId);
|
clientHelper.getMessageAsList(messageId);
|
||||||
@@ -128,12 +133,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
public void testGetGroupMetadataAsDictionary() throws Exception {
|
public void testGetGroupMetadataAsDictionary() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getGroupMetadata(txn, groupId);
|
oneOf(db).getGroupMetadata(txn, groupId);
|
||||||
will(returnValue(metadata));
|
will(returnValue(metadata));
|
||||||
oneOf(metadataParser).parse(metadata);
|
oneOf(metadataParser).parse(metadata);
|
||||||
will(returnValue(dictionary));
|
will(returnValue(dictionary));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(dictionary,
|
assertEquals(dictionary,
|
||||||
@@ -145,12 +153,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
public void testGetMessageMetadataAsDictionary() throws Exception {
|
public void testGetMessageMetadataAsDictionary() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getMessageMetadata(txn, messageId);
|
oneOf(db).getMessageMetadata(txn, messageId);
|
||||||
will(returnValue(metadata));
|
will(returnValue(metadata));
|
||||||
oneOf(metadataParser).parse(metadata);
|
oneOf(metadataParser).parse(metadata);
|
||||||
will(returnValue(dictionary));
|
will(returnValue(dictionary));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(dictionary,
|
assertEquals(dictionary,
|
||||||
@@ -164,12 +175,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
map.put(messageId, dictionary);
|
map.put(messageId, dictionary);
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getMessageMetadata(txn, groupId);
|
oneOf(db).getMessageMetadata(txn, groupId);
|
||||||
will(returnValue(Collections.singletonMap(messageId, metadata)));
|
will(returnValue(Collections.singletonMap(messageId, metadata)));
|
||||||
oneOf(metadataParser).parse(metadata);
|
oneOf(metadataParser).parse(metadata);
|
||||||
will(returnValue(dictionary));
|
will(returnValue(dictionary));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId));
|
assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId));
|
||||||
@@ -186,14 +200,17 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
queryMetadata.put("query", getRandomBytes(42));
|
queryMetadata.put("query", getRandomBytes(42));
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(metadataEncoder).encode(query);
|
oneOf(metadataEncoder).encode(query);
|
||||||
will(returnValue(queryMetadata));
|
will(returnValue(queryMetadata));
|
||||||
oneOf(db).getMessageMetadata(txn, groupId, queryMetadata);
|
oneOf(db).getMessageMetadata(txn, groupId, queryMetadata);
|
||||||
will(returnValue(Collections.singletonMap(messageId, metadata)));
|
will(returnValue(Collections.singletonMap(messageId, metadata)));
|
||||||
oneOf(metadataParser).parse(metadata);
|
oneOf(metadataParser).parse(metadata);
|
||||||
will(returnValue(dictionary));
|
will(returnValue(dictionary));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(map,
|
assertEquals(map,
|
||||||
@@ -205,11 +222,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
public void testMergeGroupMetadata() throws Exception {
|
public void testMergeGroupMetadata() throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(metadataEncoder).encode(dictionary);
|
oneOf(metadataEncoder).encode(dictionary);
|
||||||
will(returnValue(metadata));
|
will(returnValue(metadata));
|
||||||
oneOf(db).mergeGroupMetadata(txn, groupId, metadata);
|
oneOf(db).mergeGroupMetadata(txn, groupId, metadata);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
clientHelper.mergeGroupMetadata(groupId, dictionary);
|
clientHelper.mergeGroupMetadata(groupId, dictionary);
|
||||||
@@ -220,11 +240,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
public void testMergeMessageMetadata() throws Exception {
|
public void testMergeMessageMetadata() throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(metadataEncoder).encode(dictionary);
|
oneOf(metadataEncoder).encode(dictionary);
|
||||||
will(returnValue(metadata));
|
will(returnValue(metadata));
|
||||||
oneOf(db).mergeMessageMetadata(txn, messageId, metadata);
|
oneOf(db).mergeMessageMetadata(txn, messageId, metadata);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
clientHelper.mergeMessageMetadata(messageId, dictionary);
|
clientHelper.mergeMessageMetadata(messageId, dictionary);
|
||||||
|
|||||||
@@ -5,17 +5,12 @@ import org.briarproject.bramble.api.contact.ContactId;
|
|||||||
import org.briarproject.bramble.api.contact.ContactManager;
|
import org.briarproject.bramble.api.contact.ContactManager;
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.db.NoSuchContactException;
|
import org.briarproject.bramble.api.db.NoSuchContactException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.transport.KeyManager;
|
import org.briarproject.bramble.api.transport.KeyManager;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.DbExpectations;
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -25,20 +20,10 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
|
||||||
import static java.util.Collections.singletonList;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class ContactManagerImplTest extends BrambleMockTestCase {
|
public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||||
@@ -46,20 +31,16 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
private final Mockery context = new Mockery();
|
private final Mockery context = new Mockery();
|
||||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||||
private final KeyManager keyManager = context.mock(KeyManager.class);
|
private final KeyManager keyManager = context.mock(KeyManager.class);
|
||||||
private final IdentityManager identityManager =
|
|
||||||
context.mock(IdentityManager.class);
|
|
||||||
private final ContactManager contactManager;
|
private final ContactManager contactManager;
|
||||||
private final ContactId contactId = new ContactId(42);
|
private final ContactId contactId = new ContactId(42);
|
||||||
private final Author remote = getAuthor();
|
private final Author remote = getAuthor();
|
||||||
private final AuthorId local = new AuthorId(getRandomId());
|
private final AuthorId local = new AuthorId(getRandomId());
|
||||||
private final LocalAuthor localAuthor = getLocalAuthor();
|
|
||||||
private final String alias = getRandomString(MAX_AUTHOR_NAME_LENGTH);
|
|
||||||
private final boolean verified = false, active = true;
|
private final boolean verified = false, active = true;
|
||||||
private final Contact contact =
|
private final Contact contact =
|
||||||
new Contact(contactId, remote, local, alias, verified, active);
|
new Contact(contactId, remote, local, verified, active);
|
||||||
|
|
||||||
public ContactManagerImplTest() {
|
public ContactManagerImplTest() {
|
||||||
contactManager = new ContactManagerImpl(db, keyManager, identityManager);
|
contactManager = new ContactManagerImpl(db, keyManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -69,14 +50,17 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
boolean alice = new Random().nextBoolean();
|
boolean alice = new Random().nextBoolean();
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(false), withDbCallable(txn));
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).addContact(txn, remote, local, verified, active);
|
oneOf(db).addContact(txn, remote, local, verified, active);
|
||||||
will(returnValue(contactId));
|
will(returnValue(contactId));
|
||||||
oneOf(keyManager).addContact(txn, contactId, master, timestamp,
|
oneOf(keyManager).addContact(txn, contactId, master, timestamp,
|
||||||
alice, active);
|
alice, active);
|
||||||
oneOf(db).getContact(txn, contactId);
|
oneOf(db).getContact(txn, contactId);
|
||||||
will(returnValue(contact));
|
will(returnValue(contact));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(contactId, contactManager.addContact(remote, local,
|
assertEquals(contactId, contactManager.addContact(remote, local,
|
||||||
@@ -86,10 +70,13 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetContact() throws Exception {
|
public void testGetContact() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getContact(txn, contactId);
|
oneOf(db).getContact(txn, contactId);
|
||||||
will(returnValue(contact));
|
will(returnValue(contact));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(contact, contactManager.getContact(contactId));
|
assertEquals(contact, contactManager.getContact(contactId));
|
||||||
@@ -99,10 +86,13 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testGetContactByAuthor() throws Exception {
|
public void testGetContactByAuthor() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
Collection<Contact> contacts = Collections.singleton(contact);
|
Collection<Contact> contacts = Collections.singleton(contact);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||||
will(returnValue(contacts));
|
will(returnValue(contacts));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(contact, contactManager.getContact(remote.getId(), local));
|
assertEquals(contact, contactManager.getContact(remote.getId(), local));
|
||||||
@@ -111,10 +101,12 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test(expected = NoSuchContactException.class)
|
@Test(expected = NoSuchContactException.class)
|
||||||
public void testGetContactByUnknownAuthor() throws Exception {
|
public void testGetContactByUnknownAuthor() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||||
will(returnValue(emptyList()));
|
will(returnValue(Collections.emptyList()));
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
contactManager.getContact(remote.getId(), local);
|
contactManager.getContact(remote.getId(), local);
|
||||||
@@ -124,26 +116,30 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
public void testGetContactByUnknownLocalAuthor() throws Exception {
|
public void testGetContactByUnknownLocalAuthor() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
Collection<Contact> contacts = Collections.singleton(contact);
|
Collection<Contact> contacts = Collections.singleton(contact);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||||
will(returnValue(contacts));
|
will(returnValue(contacts));
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
contactManager.getContact(remote.getId(), new AuthorId(getRandomId()));
|
contactManager.getContact(remote.getId(), new AuthorId(getRandomId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetActiveContacts() throws Exception {
|
public void testActiveContacts() throws Exception {
|
||||||
Collection<Contact> activeContacts = Collections.singletonList(contact);
|
Collection<Contact> activeContacts = Collections.singletonList(contact);
|
||||||
Collection<Contact> contacts = new ArrayList<>(activeContacts);
|
Collection<Contact> contacts = new ArrayList<>(activeContacts);
|
||||||
contacts.add(new Contact(new ContactId(3), remote, local, alias, true,
|
contacts.add(new Contact(new ContactId(3), remote, local, true, false));
|
||||||
false));
|
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getContacts(txn);
|
oneOf(db).getContacts(txn);
|
||||||
will(returnValue(contacts));
|
will(returnValue(contacts));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(activeContacts, contactManager.getActiveContacts());
|
assertEquals(activeContacts, contactManager.getActiveContacts());
|
||||||
@@ -152,11 +148,14 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testRemoveContact() throws Exception {
|
public void testRemoveContact() throws Exception {
|
||||||
Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getContact(txn, contactId);
|
oneOf(db).getContact(txn, contactId);
|
||||||
will(returnValue(contact));
|
will(returnValue(contact));
|
||||||
oneOf(db).removeContact(txn, contactId);
|
oneOf(db).removeContact(txn, contactId);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
contactManager.removeContact(contactId);
|
contactManager.removeContact(contactId);
|
||||||
@@ -172,108 +171,19 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
contactManager.setContactActive(txn, contactId, active);
|
contactManager.setContactActive(txn, contactId, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetContactAlias() throws Exception {
|
|
||||||
Transaction txn = new Transaction(null, false);
|
|
||||||
context.checking(new DbExpectations() {{
|
|
||||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
|
||||||
oneOf(db).setContactAlias(txn, contactId, alias);
|
|
||||||
}});
|
|
||||||
|
|
||||||
contactManager.setContactAlias(contactId, alias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
|
||||||
public void testSetContactAliasTooLong() throws Exception {
|
|
||||||
Transaction txn = new Transaction(null, false);
|
|
||||||
contactManager.setContactAlias(txn, contactId,
|
|
||||||
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContactExists() throws Exception {
|
public void testContactExists() throws Exception {
|
||||||
Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).containsContact(txn, remote.getId(), local);
|
oneOf(db).containsContact(txn, remote.getId(), local);
|
||||||
will(returnValue(true));
|
will(returnValue(true));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertTrue(contactManager.contactExists(remote.getId(), local));
|
assertTrue(contactManager.contactExists(remote.getId(), local));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetAuthorInfo() throws Exception {
|
|
||||||
Transaction txn = new Transaction(null, true);
|
|
||||||
Collection<Contact> contacts = singletonList(
|
|
||||||
new Contact(new ContactId(1), remote, localAuthor.getId(),
|
|
||||||
alias, false, true));
|
|
||||||
|
|
||||||
context.checking(new DbExpectations() {{
|
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
|
||||||
oneOf(identityManager).getLocalAuthor(txn);
|
|
||||||
will(returnValue(localAuthor));
|
|
||||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
|
||||||
will(returnValue(contacts));
|
|
||||||
}});
|
|
||||||
AuthorInfo authorInfo =
|
|
||||||
contactManager.getAuthorInfo(txn, remote.getId());
|
|
||||||
assertEquals(UNVERIFIED, authorInfo.getStatus());
|
|
||||||
assertEquals(alias, contact.getAlias());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetAuthorInfoTransaction() throws DbException {
|
|
||||||
Transaction txn = new Transaction(null, true);
|
|
||||||
|
|
||||||
// check unknown author
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(identityManager).getLocalAuthor(txn);
|
|
||||||
will(returnValue(localAuthor));
|
|
||||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
|
||||||
will(returnValue(emptyList()));
|
|
||||||
}});
|
|
||||||
AuthorInfo authorInfo =
|
|
||||||
contactManager.getAuthorInfo(txn, remote.getId());
|
|
||||||
assertEquals(UNKNOWN, authorInfo.getStatus());
|
|
||||||
assertNull(authorInfo.getAlias());
|
|
||||||
|
|
||||||
// check unverified contact
|
|
||||||
Collection<Contact> contacts = singletonList(
|
|
||||||
new Contact(new ContactId(1), remote, localAuthor.getId(),
|
|
||||||
alias, false, true));
|
|
||||||
checkAuthorInfoContext(txn, remote.getId(), contacts);
|
|
||||||
authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
|
|
||||||
assertEquals(UNVERIFIED, authorInfo.getStatus());
|
|
||||||
assertEquals(alias, contact.getAlias());
|
|
||||||
|
|
||||||
// check verified contact
|
|
||||||
contacts = singletonList(new Contact(new ContactId(1), remote,
|
|
||||||
localAuthor.getId(), alias, true, true));
|
|
||||||
checkAuthorInfoContext(txn, remote.getId(), contacts);
|
|
||||||
authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
|
|
||||||
assertEquals(VERIFIED, authorInfo.getStatus());
|
|
||||||
assertEquals(alias, contact.getAlias());
|
|
||||||
|
|
||||||
// check ourselves
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(identityManager).getLocalAuthor(txn);
|
|
||||||
will(returnValue(localAuthor));
|
|
||||||
never(db).getContactsByAuthorId(txn, remote.getId());
|
|
||||||
}});
|
|
||||||
authorInfo = contactManager.getAuthorInfo(txn, localAuthor.getId());
|
|
||||||
assertEquals(OURSELVES, authorInfo.getStatus());
|
|
||||||
assertNull(authorInfo.getAlias());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkAuthorInfoContext(Transaction txn, AuthorId authorId,
|
|
||||||
Collection<Contact> contacts) throws DbException {
|
|
||||||
context.checking(new Expectations() {{
|
|
||||||
oneOf(identityManager).getLocalAuthor(txn);
|
|
||||||
will(returnValue(localAuthor));
|
|
||||||
oneOf(db).getContactsByAuthorId(txn, authorId);
|
|
||||||
will(returnValue(contacts));
|
|
||||||
}});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
package org.briarproject.bramble.data;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE;
|
|
||||||
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_NESTED_LIMIT;
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assume.assumeTrue;
|
|
||||||
|
|
||||||
public class BdfReaderImplFuzzingTest extends BrambleTestCase {
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
assumeTrue(isOptionalTestEnabled(BdfReaderImplFuzzingTest.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStringFuzzing() throws Exception {
|
|
||||||
Random random = new Random();
|
|
||||||
byte[] buf = new byte[22];
|
|
||||||
ByteArrayInputStream in = new ByteArrayInputStream(buf);
|
|
||||||
for (int i = 0; i < 100_000_000; i++) {
|
|
||||||
random.nextBytes(buf);
|
|
||||||
buf[0] = 0x41; // String with 1-byte length
|
|
||||||
buf[1] = 0x14; // Length 20 bytes
|
|
||||||
in.reset();
|
|
||||||
BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
|
|
||||||
DEFAULT_MAX_BUFFER_SIZE);
|
|
||||||
int length = r.readString().length();
|
|
||||||
assertTrue(length >= 0);
|
|
||||||
assertTrue(length <= 20);
|
|
||||||
assertTrue(r.eof());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,7 @@ import org.briarproject.bramble.api.sync.Group;
|
|||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.UTest;
|
import org.briarproject.bramble.test.UTest;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
@@ -33,7 +33,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import static java.util.logging.Level.OFF;
|
import static java.util.logging.Level.OFF;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
|
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||||
@@ -565,8 +565,7 @@ public abstract class DatabasePerformanceTest extends BrambleTestCase {
|
|||||||
for (int k = 0; k < MESSAGES_PER_GROUP; k++) {
|
for (int k = 0; k < MESSAGES_PER_GROUP; k++) {
|
||||||
Message m = getMessage(g.getId());
|
Message m = getMessage(g.getId());
|
||||||
messages.add(m);
|
messages.add(m);
|
||||||
MessageState state =
|
State state = State.fromValue(random.nextInt(4));
|
||||||
MessageState.fromValue(random.nextInt(4));
|
|
||||||
boolean shared = random.nextBoolean();
|
boolean shared = random.nextBoolean();
|
||||||
ContactId sender = random.nextBoolean() ? c : null;
|
ContactId sender = random.nextBoolean() ? c : null;
|
||||||
db.addMessage(txn, m, state, shared, sender);
|
db.addMessage(txn, m, state, shared, sender);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import org.briarproject.bramble.api.sync.Message;
|
|||||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||||
import org.briarproject.bramble.api.transport.KeySet;
|
import org.briarproject.bramble.api.transport.KeySet;
|
||||||
@@ -53,15 +53,14 @@ import static java.util.Collections.singletonList;
|
|||||||
import static java.util.Collections.singletonMap;
|
import static java.util.Collections.singletonMap;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
import static org.briarproject.bramble.api.db.Metadata.REMOVE;
|
import static org.briarproject.bramble.api.db.Metadata.REMOVE;
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.INVALID;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
||||||
@@ -75,7 +74,6 @@ import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
|||||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
@@ -1309,7 +1307,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.addMessageDependency(txn, message1, messageId3, PENDING);
|
db.addMessageDependency(txn, message1, messageId3, PENDING);
|
||||||
db.addMessageDependency(txn, message2, messageId4, INVALID);
|
db.addMessageDependency(txn, message2, messageId4, INVALID);
|
||||||
|
|
||||||
Map<MessageId, MessageState> dependencies;
|
Map<MessageId, State> dependencies;
|
||||||
|
|
||||||
// Retrieve dependencies for root
|
// Retrieve dependencies for root
|
||||||
dependencies = db.getMessageDependencies(txn, messageId);
|
dependencies = db.getMessageDependencies(txn, messageId);
|
||||||
@@ -1333,7 +1331,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
dependencies = db.getMessageDependencies(txn, messageId4);
|
dependencies = db.getMessageDependencies(txn, messageId4);
|
||||||
assertEquals(0, dependencies.size());
|
assertEquals(0, dependencies.size());
|
||||||
|
|
||||||
Map<MessageId, MessageState> dependents;
|
Map<MessageId, State> dependents;
|
||||||
|
|
||||||
// Root message does not have dependents
|
// Root message does not have dependents
|
||||||
dependents = db.getMessageDependents(txn, messageId);
|
dependents = db.getMessageDependents(txn, messageId);
|
||||||
@@ -1408,7 +1406,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.addMessageDependency(txn, message, messageId3, PENDING);
|
db.addMessageDependency(txn, message, messageId3, PENDING);
|
||||||
|
|
||||||
// Retrieve the dependencies for the root
|
// Retrieve the dependencies for the root
|
||||||
Map<MessageId, MessageState> dependencies;
|
Map<MessageId, State> dependencies;
|
||||||
dependencies = db.getMessageDependencies(txn, messageId);
|
dependencies = db.getMessageDependencies(txn, messageId);
|
||||||
|
|
||||||
// The cross-group dependency should have state UNKNOWN
|
// The cross-group dependency should have state UNKNOWN
|
||||||
@@ -1421,7 +1419,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
assertEquals(DELIVERED, dependencies.get(messageId3));
|
assertEquals(DELIVERED, dependencies.get(messageId3));
|
||||||
|
|
||||||
// Retrieve the dependents for the message in the second group
|
// Retrieve the dependents for the message in the second group
|
||||||
Map<MessageId, MessageState> dependents;
|
Map<MessageId, State> dependents;
|
||||||
dependents = db.getMessageDependents(txn, messageId1);
|
dependents = db.getMessageDependents(txn, messageId1);
|
||||||
|
|
||||||
// The cross-group dependent should be excluded
|
// The cross-group dependent should be excluded
|
||||||
@@ -1715,39 +1713,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSetContactAlias() throws Exception {
|
|
||||||
Database<Connection> db = open(false);
|
|
||||||
Connection txn = db.startTransaction();
|
|
||||||
|
|
||||||
// Add a contact
|
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
|
||||||
assertEquals(contactId, db.addContact(txn, author, localAuthor.getId(),
|
|
||||||
true, true));
|
|
||||||
|
|
||||||
// The contact should have no alias
|
|
||||||
Contact contact = db.getContact(txn, contactId);
|
|
||||||
assertNull(contact.getAlias());
|
|
||||||
|
|
||||||
// Set a contact alias
|
|
||||||
String alias = getRandomString(MAX_AUTHOR_NAME_LENGTH);
|
|
||||||
db.setContactAlias(txn, contactId, alias);
|
|
||||||
|
|
||||||
// The contact should have an alias
|
|
||||||
contact = db.getContact(txn, contactId);
|
|
||||||
assertEquals(alias, contact.getAlias());
|
|
||||||
|
|
||||||
// Set the contact alias null
|
|
||||||
db.setContactAlias(txn, contactId, null);
|
|
||||||
|
|
||||||
// The contact should have no alias
|
|
||||||
contact = db.getContact(txn, contactId);
|
|
||||||
assertNull(contact.getAlias());
|
|
||||||
|
|
||||||
db.commitTransaction(txn);
|
|
||||||
db.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetMessageState() throws Exception {
|
public void testSetMessageState() throws Exception {
|
||||||
Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.briarproject.bramble.identity;
|
package org.briarproject.bramble.identity;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||||
@@ -7,18 +9,25 @@ import org.briarproject.bramble.api.crypto.PublicKey;
|
|||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.DbExpectations;
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
|
||||||
|
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getAuthor;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
@@ -65,10 +74,13 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegisterAndStoreLocalAuthor() throws Exception {
|
public void testRegisterAndStoreLocalAuthor() throws DbException {
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).addLocalAuthor(txn, localAuthor);
|
oneOf(db).addLocalAuthor(txn, localAuthor);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
identityManager.registerLocalAuthor(localAuthor);
|
identityManager.registerLocalAuthor(localAuthor);
|
||||||
@@ -77,11 +89,14 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetLocalAuthor() throws Exception {
|
public void testGetLocalAuthor() throws DbException {
|
||||||
context.checking(new DbExpectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
oneOf(db).getLocalAuthors(txn);
|
oneOf(db).getLocalAuthors(txn);
|
||||||
will(returnValue(localAuthors));
|
will(returnValue(localAuthors));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
assertEquals(localAuthor, identityManager.getLocalAuthor());
|
assertEquals(localAuthor, identityManager.getLocalAuthor());
|
||||||
}
|
}
|
||||||
@@ -92,4 +107,60 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
assertEquals(localAuthor, identityManager.getLocalAuthor());
|
assertEquals(localAuthor, identityManager.getLocalAuthor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAuthorStatus() throws DbException {
|
||||||
|
Author author = getAuthor();
|
||||||
|
AuthorId authorId = author.getId();
|
||||||
|
Collection<Contact> contacts = new ArrayList<>();
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(db).getLocalAuthors(txn);
|
||||||
|
will(returnValue(localAuthors));
|
||||||
|
oneOf(db).getContactsByAuthorId(txn, authorId);
|
||||||
|
will(returnValue(contacts));
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
|
||||||
|
|
||||||
|
// add one unverified contact
|
||||||
|
Contact contact = new Contact(new ContactId(1), author,
|
||||||
|
localAuthor.getId(), false, true);
|
||||||
|
contacts.add(contact);
|
||||||
|
|
||||||
|
checkAuthorStatusContext(authorId, contacts);
|
||||||
|
assertEquals(UNVERIFIED, identityManager.getAuthorStatus(authorId));
|
||||||
|
|
||||||
|
// add one verified contact
|
||||||
|
Contact contact2 = new Contact(new ContactId(1), author,
|
||||||
|
localAuthor.getId(), true, true);
|
||||||
|
contacts.add(contact2);
|
||||||
|
|
||||||
|
checkAuthorStatusContext(authorId, contacts);
|
||||||
|
assertEquals(VERIFIED, identityManager.getAuthorStatus(authorId));
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
|
never(db).getLocalAuthors(txn);
|
||||||
|
never(db).getContactsByAuthorId(txn, authorId);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
assertEquals(OURSELVES,
|
||||||
|
identityManager.getAuthorStatus(localAuthor.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkAuthorStatusContext(AuthorId authorId,
|
||||||
|
Collection<Contact> contacts) throws DbException {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(true);
|
||||||
|
will(returnValue(txn));
|
||||||
|
never(db).getLocalAuthors(txn);
|
||||||
|
oneOf(db).getContactsByAuthorId(txn, authorId);
|
||||||
|
will(returnValue(contacts));
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user