mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Compare commits
132 Commits
1233-remot
...
release-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f4c3c4528 | ||
|
|
636a7dfe72 | ||
|
|
08e99edd42 | ||
|
|
e28bc475df | ||
|
|
88276a4d44 | ||
|
|
f9987c89df | ||
|
|
2c8cb8301f | ||
|
|
c00ee80f0f | ||
|
|
3bfedfdc3d | ||
|
|
ecb63d1acb | ||
|
|
b24914408d | ||
|
|
5ede63edd5 | ||
|
|
4e523c5fbc | ||
|
|
cf79ed5633 | ||
|
|
0a0a6a6369 | ||
|
|
4784980e7b | ||
|
|
3bfa5e2081 | ||
|
|
f2b09deac4 | ||
|
|
ad4729b2f9 | ||
|
|
50cc0a6815 | ||
|
|
32c8ac6576 | ||
|
|
c12422d949 | ||
|
|
3841713c18 | ||
|
|
79232eb558 | ||
|
|
d02b30e751 | ||
|
|
043662a092 | ||
|
|
efc85fb88f | ||
|
|
8b3983ef9e | ||
|
|
6766fb76b2 | ||
|
|
7f74bd1c38 | ||
|
|
951ee30b95 | ||
|
|
c386a0f5eb | ||
|
|
52c778dce3 | ||
|
|
e846a13f50 | ||
|
|
23e9b119d1 | ||
|
|
e6f380296f | ||
|
|
794fb9686b | ||
|
|
bb22b9db10 | ||
|
|
d4f015d054 | ||
|
|
41e5d8900c | ||
|
|
c3cb966009 | ||
|
|
f964d1ef07 | ||
|
|
cccaeeda6c | ||
|
|
483106e00c | ||
|
|
934f14ef31 | ||
|
|
e3abff5ad8 | ||
|
|
391732b239 | ||
|
|
4738bfdd85 | ||
|
|
be1ca89309 | ||
|
|
866be99179 | ||
|
|
48822e2133 | ||
|
|
6883c5caa9 | ||
|
|
8b709969ab | ||
|
|
fe94b65b3b | ||
|
|
f54df1d787 | ||
|
|
a7e826ccf5 | ||
|
|
845eb3262b | ||
|
|
0a46ad439f | ||
|
|
d14d93ea35 | ||
|
|
12a1cf8f8b | ||
|
|
fb2ab861db | ||
|
|
aa15b68d24 | ||
|
|
7059f376f1 | ||
|
|
9313c191c1 | ||
|
|
7746364ae9 | ||
|
|
7429857b28 | ||
|
|
4db64f51a8 | ||
|
|
78172038ef | ||
|
|
7d0c418877 | ||
|
|
5ae4f8f6cb | ||
|
|
45dd10db9d | ||
|
|
5cc8c268ca | ||
|
|
93a6bf2f52 | ||
|
|
852dd46a1b | ||
|
|
4a42e767d3 | ||
|
|
8547b4dc91 | ||
|
|
f6c8a8cec7 | ||
|
|
db8796049e | ||
|
|
e1f31ad381 | ||
|
|
3a15e47ddd | ||
|
|
cf616905d6 | ||
|
|
d3f774f339 | ||
|
|
6c7c488892 | ||
|
|
3fe7aae97e | ||
|
|
ecf417c93b | ||
|
|
c1785c5b13 | ||
|
|
fb2c321a3d | ||
|
|
6e3adc0874 | ||
|
|
cdbe2a00f5 | ||
|
|
a51dc7e0d5 | ||
|
|
0ee7465429 | ||
|
|
7c202189a2 | ||
|
|
da3b2c1591 | ||
|
|
6c5e8ce4cf | ||
|
|
ca700d8d23 | ||
|
|
db11dad61e | ||
|
|
69e7366226 | ||
|
|
90b7b4e67f | ||
|
|
d29812a42b | ||
|
|
baf64e1129 | ||
|
|
88adfabe09 | ||
|
|
6565172e10 | ||
|
|
7447468ce5 | ||
|
|
2db2a1a208 | ||
|
|
0d7e4feaf2 | ||
|
|
eb3983f6b2 | ||
|
|
e2ce49c30e | ||
|
|
adc6fb2fd5 | ||
|
|
969150bff0 | ||
|
|
8fc622f85d | ||
|
|
22eed91019 | ||
|
|
fcb88ed58c | ||
|
|
0d940fc7d7 | ||
|
|
ca6dc33cdd | ||
|
|
53da13794f | ||
|
|
2ab03f48cc | ||
|
|
436f45554d | ||
|
|
51209b5eec | ||
|
|
822597b4c6 | ||
|
|
7c01bc59c0 | ||
|
|
825d342f9b | ||
|
|
34955fecbb | ||
|
|
5c28b60a6b | ||
|
|
9c4fb4fd34 | ||
|
|
3d6a336f6d | ||
|
|
4b7a81177c | ||
|
|
9515e93857 | ||
|
|
efe15df940 | ||
|
|
de611857cf | ||
|
|
8935ec2c2e | ||
|
|
bd00fb1c04 | ||
|
|
3192015cfd |
@@ -3,7 +3,7 @@
|
||||
<module name="briar-headless" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<option name="PACKAGE_NAME" value="" />
|
||||
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="package" />
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import com.android.build.gradle.tasks.MergeResources
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
@@ -9,8 +11,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 10103
|
||||
versionName "1.1.3"
|
||||
versionCode 10105
|
||||
versionName "1.1.5"
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
@@ -29,8 +31,9 @@ configurations {
|
||||
dependencies {
|
||||
implementation project(path: ':bramble-core', configuration: 'default')
|
||||
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.0.2'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
@@ -39,13 +42,29 @@ dependencies {
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4: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"
|
||||
}
|
||||
|
||||
project.afterEvaluate {
|
||||
copy {
|
||||
from configurations.tor.collect { zipTree(it) }
|
||||
into 'src/main/res/raw'
|
||||
def torBinariesDir = 'src/main/res/raw'
|
||||
|
||||
task cleanTorBinaries {
|
||||
doLast {
|
||||
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,5 +1,6 @@
|
||||
package org.briarproject.bramble;
|
||||
|
||||
import org.briarproject.bramble.battery.AndroidBatteryModule;
|
||||
import org.briarproject.bramble.network.AndroidNetworkModule;
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionModule;
|
||||
import org.briarproject.bramble.system.AndroidSystemModule;
|
||||
@@ -7,6 +8,7 @@ import org.briarproject.bramble.system.AndroidSystemModule;
|
||||
import dagger.Module;
|
||||
|
||||
@Module(includes = {
|
||||
AndroidBatteryModule.class,
|
||||
AndroidNetworkModule.class,
|
||||
AndroidSystemModule.class,
|
||||
CircumventionModule.class
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
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.BATTERY_STATUS_CHARGING;
|
||||
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
|
||||
import static android.os.BatteryManager.EXTRA_STATUS;
|
||||
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_STATUS, -1);
|
||||
return status == BATTERY_STATUS_CHARGING ||
|
||||
status == BATTERY_STATUS_FULL;
|
||||
}
|
||||
|
||||
@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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.briarproject.bramble.battery;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class AndroidBatteryModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
BatteryManager provideBatteryManager(LifecycleManager lifecycleManager,
|
||||
AndroidBatteryManager batteryManager) {
|
||||
lifecycleManager.registerService(batteryManager);
|
||||
return batteryManager;
|
||||
}
|
||||
}
|
||||
@@ -16,18 +16,27 @@ import org.briarproject.bramble.api.plugin.PluginException;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
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.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
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_STATE_CHANGED;
|
||||
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
|
||||
@@ -37,8 +46,13 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERA
|
||||
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
|
||||
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
|
||||
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 org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -47,8 +61,11 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
|
||||
|
||||
private static final int MAX_DISCOVERY_MS = 10_000;
|
||||
|
||||
private final AndroidExecutor androidExecutor;
|
||||
private final Context appContext;
|
||||
private final Clock clock;
|
||||
|
||||
private volatile boolean wasEnabledByUs = false;
|
||||
private volatile BluetoothStateReceiver receiver = null;
|
||||
@@ -58,12 +75,13 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
||||
|
||||
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
|
||||
Executor ioExecutor, AndroidExecutor androidExecutor,
|
||||
Context appContext, SecureRandom secureRandom, Backoff backoff,
|
||||
DuplexPluginCallback callback, int maxLatency) {
|
||||
Context appContext, SecureRandom secureRandom, Clock clock,
|
||||
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
|
||||
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
|
||||
maxLatency);
|
||||
this.androidExecutor = androidExecutor;
|
||||
this.appContext = appContext;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -182,6 +200,74 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@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 {
|
||||
if (adapter.startDiscovery()) {
|
||||
long now = clock.currentTimeMillis();
|
||||
long end = now + MAX_DISCOVERY_MS;
|
||||
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 void tryToClose(@Nullable Closeable c) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
@@ -207,4 +293,18 @@ 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,6 +11,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -33,17 +34,19 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
|
||||
private final Context appContext;
|
||||
private final SecureRandom secureRandom;
|
||||
private final EventBus eventBus;
|
||||
private final Clock clock;
|
||||
private final BackoffFactory backoffFactory;
|
||||
|
||||
public AndroidBluetoothPluginFactory(Executor ioExecutor,
|
||||
AndroidExecutor androidExecutor, Context appContext,
|
||||
SecureRandom secureRandom, EventBus eventBus,
|
||||
SecureRandom secureRandom, EventBus eventBus, Clock clock,
|
||||
BackoffFactory backoffFactory) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.androidExecutor = androidExecutor;
|
||||
this.appContext = appContext;
|
||||
this.secureRandom = secureRandom;
|
||||
this.eventBus = eventBus;
|
||||
this.clock = clock;
|
||||
this.backoffFactory = backoffFactory;
|
||||
}
|
||||
|
||||
@@ -65,7 +68,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
|
||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
|
||||
connectionLimiter, ioExecutor, androidExecutor, appContext,
|
||||
secureRandom, backoff, callback, MAX_LATENCY);
|
||||
secureRandom, clock, backoff, callback, MAX_LATENCY);
|
||||
eventBus.addListener(plugin);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.os.PowerManager;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
@@ -41,17 +42,18 @@ class AndroidTorPlugin extends TorPlugin {
|
||||
Context appContext, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||
Clock clock, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Backoff backoff,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime) {
|
||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||
clock, resourceProvider, circumventionProvider, backoff,
|
||||
callback, architecture, maxLatency, maxIdleTime,
|
||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||
backoff, callback, architecture, maxLatency, maxIdleTime,
|
||||
appContext.getDir("tor", MODE_PRIVATE));
|
||||
this.appContext = appContext;
|
||||
PowerManager pm = (PowerManager)
|
||||
appContext.getSystemService(POWER_SERVICE);
|
||||
assert pm != null;
|
||||
if (pm == null) throw new AssertionError();
|
||||
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
|
||||
WAKE_LOCK_TAG, 1, MINUTES);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.briarproject.bramble.plugin.tor;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -48,6 +49,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
private final BackoffFactory backoffFactory;
|
||||
private final ResourceProvider resourceProvider;
|
||||
private final CircumventionProvider circumventionProvider;
|
||||
private final BatteryManager batteryManager;
|
||||
private final Clock clock;
|
||||
|
||||
public AndroidTorPluginFactory(Executor ioExecutor,
|
||||
@@ -55,7 +57,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
NetworkManager networkManager, LocationUtils locationUtils,
|
||||
EventBus eventBus, SocketFactory torSocketFactory,
|
||||
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Clock clock) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.scheduler = scheduler;
|
||||
this.appContext = appContext;
|
||||
@@ -66,6 +69,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
this.backoffFactory = backoffFactory;
|
||||
this.resourceProvider = resourceProvider;
|
||||
this.circumventionProvider = circumventionProvider;
|
||||
this.batteryManager = batteryManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@@ -104,8 +108,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
|
||||
appContext, networkManager, locationUtils, torSocketFactory,
|
||||
clock, resourceProvider, circumventionProvider, backoff,
|
||||
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||
eventBus.addListener(plugin);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,12 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
public class AndroidUtils {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(AndroidUtils.class.getName());
|
||||
|
||||
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
|
||||
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
|
||||
|
||||
@@ -28,7 +25,7 @@ public class AndroidUtils {
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Collection<String> getSupportedArchitectures() {
|
||||
List<String> abis = new ArrayList<>();
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
if (SDK_INT >= 21) {
|
||||
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
|
||||
} else {
|
||||
abis.add(Build.CPU_ABI);
|
||||
|
||||
@@ -31,16 +31,21 @@ dependencyVerification {
|
||||
'com.android.tools:sdklib:26.2.1:sdklib-26.2.1.jar:248df7ad5eac4aeb6f96c394c76760de4b7b89ac056e54d0c21a739368b91b45',
|
||||
'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.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||
'com.google.dagger:dagger-compiler:2.19:dagger-compiler-2.19.jar:27a4b202a2de908182edb261f8c0a264e08e5e4733d7514bc7fbf0d31da5c0fc',
|
||||
'com.google.dagger:dagger-producers:2.19:dagger-producers-2.19.jar:a17663abe0fc38b676026950907d4c5f5e2bf338375415861eaff6e3bdb0b768',
|
||||
'com.google.dagger:dagger-spi:2.19:dagger-spi-2.19.jar:e7a6379d82c841f6aac2866948ad1eed716528707814602842a8d844ce04e2e1',
|
||||
'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.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
|
||||
'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:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9',
|
||||
'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.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.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
||||
'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.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
||||
@@ -63,7 +68,9 @@ dependencyVerification {
|
||||
'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: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.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.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',
|
||||
|
||||
@@ -7,15 +7,13 @@ apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
|
||||
dependencies {
|
||||
implementation "com.google.dagger:dagger:2.0.2"
|
||||
implementation "com.google.dagger:dagger:2.19"
|
||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4: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'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.briarproject.bramble.api.battery;
|
||||
|
||||
public interface BatteryManager {
|
||||
|
||||
boolean isCharging();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,12 @@ import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
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
|
||||
@NotNullByDefault
|
||||
public class Contact {
|
||||
@@ -13,13 +17,21 @@ public class Contact {
|
||||
private final ContactId id;
|
||||
private final Author author;
|
||||
private final AuthorId localAuthorId;
|
||||
@Nullable
|
||||
private final String alias;
|
||||
private final boolean verified, active;
|
||||
|
||||
public Contact(ContactId id, Author author, AuthorId localAuthorId,
|
||||
boolean verified, boolean active) {
|
||||
@Nullable String alias, 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.author = author;
|
||||
this.localAuthorId = localAuthorId;
|
||||
this.alias = alias;
|
||||
this.verified = verified;
|
||||
this.active = active;
|
||||
}
|
||||
@@ -36,6 +48,11 @@ public class Contact {
|
||||
return localAuthorId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getAlias() {
|
||||
return alias;
|
||||
}
|
||||
|
||||
public boolean isVerified() {
|
||||
return verified;
|
||||
}
|
||||
|
||||
@@ -5,11 +5,14 @@ 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.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface ContactManager {
|
||||
|
||||
@@ -93,6 +96,18 @@ public interface ContactManager {
|
||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||
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
|
||||
*/
|
||||
@@ -105,6 +120,16 @@ public interface ContactManager {
|
||||
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
||||
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 {
|
||||
|
||||
void addingContact(Transaction txn, Contact c) throws DbException;
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
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');
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,14 @@ public interface DatabaseComponent {
|
||||
<R, E extends Exception> R transactionWithResult(boolean readOnly,
|
||||
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,
|
||||
* and returns an ID for the contact.
|
||||
@@ -515,6 +523,12 @@ public interface DatabaseComponent {
|
||||
void setContactActive(Transaction txn, ContactId c, boolean active)
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.briarproject.bramble.api.db;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface DbCallable<R, E extends Exception> {
|
||||
|
||||
R call(Transaction txn) throws DbException, E;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.briarproject.bramble.api.db;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface DbRunnable<E extends Exception> {
|
||||
|
||||
void run(Transaction txn) throws DbException, E;
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
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,10 +16,6 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
|
||||
@NotNullByDefault
|
||||
public class Author implements Nameable {
|
||||
|
||||
public enum Status {
|
||||
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
|
||||
}
|
||||
|
||||
/**
|
||||
* The current version of the author structure.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
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,7 +3,6 @@ package org.briarproject.bramble.api.identity;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author.Status;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
@@ -37,14 +36,4 @@ public interface IdentityManager {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
long CONNECTION_TIMEOUT = 20 * 1000;
|
||||
long CONNECTION_TIMEOUT = 60_000;
|
||||
|
||||
/**
|
||||
* The transport identifier for Bluetooth.
|
||||
|
||||
@@ -47,7 +47,7 @@ public class StringUtils {
|
||||
try {
|
||||
return s.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class StringUtils {
|
||||
try {
|
||||
return decoder.decode(buffer).toString();
|
||||
} catch (CharacterCodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
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 = [
|
||||
'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.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||
'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
|
||||
|
||||
apply plugin: 'ru.vyarus.animalsniffer'
|
||||
apply plugin: 'net.ltgt.apt'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
apply from: '../dagger.gradle'
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':bramble-api', configuration: 'default')
|
||||
@@ -17,7 +17,7 @@ dependencies {
|
||||
implementation 'org.whispersystems:curve25519-java:0.5.0'
|
||||
implementation 'org.briarproject:jtorctl:0.3'
|
||||
|
||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
|
||||
@@ -25,10 +25,8 @@ dependencies {
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4: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"
|
||||
|
||||
testApt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
|
||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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,13 +82,7 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public void addLocalMessage(Message m, BdfDictionary metadata,
|
||||
boolean shared) throws DbException, FormatException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
addLocalMessage(txn, m, metadata, shared);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,15 +107,7 @@ class ClientHelperImpl implements ClientHelper {
|
||||
|
||||
@Override
|
||||
public Message getMessage(MessageId m) throws DbException {
|
||||
Message message;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
message = getMessage(txn, m);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return message;
|
||||
return db.transactionWithResult(true, txn -> getMessage(txn, m));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,15 +118,7 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public BdfList getMessageAsList(MessageId m) throws DbException,
|
||||
FormatException {
|
||||
BdfList list;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
list = getMessageAsList(txn, m);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return list;
|
||||
return db.transactionWithResult(true, txn -> getMessageAsList(txn, m));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,15 +130,8 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public BdfDictionary getGroupMetadataAsDictionary(GroupId g)
|
||||
throws DbException, FormatException {
|
||||
BdfDictionary dictionary;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
dictionary = getGroupMetadataAsDictionary(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return dictionary;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getGroupMetadataAsDictionary(txn, g));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,15 +144,8 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
|
||||
throws DbException, FormatException {
|
||||
BdfDictionary dictionary;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
dictionary = getMessageMetadataAsDictionary(txn, m);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return dictionary;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getMessageMetadataAsDictionary(txn, m));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -194,15 +158,8 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||
GroupId g) throws DbException, FormatException {
|
||||
Map<MessageId, BdfDictionary> map;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
map = getMessageMetadataAsDictionary(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return map;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getMessageMetadataAsDictionary(txn, g));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,15 +176,8 @@ class ClientHelperImpl implements ClientHelper {
|
||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||
GroupId g, BdfDictionary query) throws DbException,
|
||||
FormatException {
|
||||
Map<MessageId, BdfDictionary> map;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
map = getMessageMetadataAsDictionary(txn, g, query);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return map;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getMessageMetadataAsDictionary(txn, g, query));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -245,13 +195,7 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public void mergeGroupMetadata(GroupId g, BdfDictionary metadata)
|
||||
throws DbException, FormatException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
mergeGroupMetadata(txn, g, metadata);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn -> mergeGroupMetadata(txn, g, metadata));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -263,13 +207,7 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public void mergeMessageMetadata(MessageId m, BdfDictionary metadata)
|
||||
throws DbException, FormatException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
mergeMessageMetadata(txn, m, metadata);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn -> mergeMessageMetadata(txn, m, metadata));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,7 +13,6 @@ import org.briarproject.bramble.api.data.BdfList;
|
||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
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.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
@@ -158,7 +157,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
||||
streamWriterFactory.createContactExchangeStreamWriter(out,
|
||||
alice ? aliceHeaderKey : bobHeaderKey);
|
||||
RecordWriter recordWriter =
|
||||
recordWriterFactory.createRecordWriter(streamWriter.getOutputStream());
|
||||
recordWriterFactory
|
||||
.createRecordWriter(streamWriter.getOutputStream());
|
||||
|
||||
// Derive the nonces to be signed
|
||||
byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret,
|
||||
@@ -287,19 +287,14 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
||||
private ContactId addContact(Author remoteAuthor, long timestamp,
|
||||
Map<TransportId, TransportProperties> remoteProperties)
|
||||
throws DbException {
|
||||
ContactId contactId;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
contactId = contactManager.addContact(txn, remoteAuthor,
|
||||
return db.transactionWithResult(false, txn -> {
|
||||
ContactId contactId = contactManager.addContact(txn, remoteAuthor,
|
||||
localAuthor.getId(), masterSecret, timestamp, alice,
|
||||
true, true);
|
||||
transportPropertyManager.addRemoteProperties(txn, contactId,
|
||||
remoteProperties);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return contactId;
|
||||
return contactId;
|
||||
});
|
||||
}
|
||||
|
||||
private void tryToClose(DuplexTransportConnection conn) {
|
||||
|
||||
@@ -10,6 +10,9 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
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.transport.KeyManager;
|
||||
|
||||
@@ -18,21 +21,32 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.inject.Inject;
|
||||
|
||||
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
|
||||
@NotNullByDefault
|
||||
class ContactManagerImpl implements ContactManager {
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final KeyManager keyManager;
|
||||
private final IdentityManager identityManager;
|
||||
private final List<ContactHook> hooks;
|
||||
|
||||
@Inject
|
||||
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
|
||||
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
|
||||
IdentityManager identityManager) {
|
||||
this.db = db;
|
||||
this.keyManager = keyManager;
|
||||
this.identityManager = identityManager;
|
||||
hooks = new CopyOnWriteArrayList<>();
|
||||
}
|
||||
|
||||
@@ -65,42 +79,21 @@ class ContactManagerImpl implements ContactManager {
|
||||
public ContactId addContact(Author remote, AuthorId local, SecretKey master,
|
||||
long timestamp, boolean alice, boolean verified, boolean active)
|
||||
throws DbException {
|
||||
ContactId c;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
c = addContact(txn, remote, local, master, timestamp, alice,
|
||||
verified, active);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return c;
|
||||
return db.transactionWithResult(false, txn ->
|
||||
addContact(txn, remote, local, master, timestamp, alice,
|
||||
verified, active));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contact getContact(ContactId c) throws DbException {
|
||||
Contact contact;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
contact = db.getContact(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return contact;
|
||||
return db.transactionWithResult(true, txn -> db.getContact(txn, c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
||||
throws DbException {
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
Contact c = getContact(txn, remoteAuthorId, localAuthorId);
|
||||
db.commitTransaction(txn);
|
||||
return c;
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getContact(txn, remoteAuthorId, localAuthorId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,14 +111,8 @@ class ContactManagerImpl implements ContactManager {
|
||||
|
||||
@Override
|
||||
public Collection<Contact> getActiveContacts() throws DbException {
|
||||
Collection<Contact> contacts;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
contacts = db.getContacts(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Collection<Contact> contacts =
|
||||
db.transactionWithResult(true, db::getContacts);
|
||||
List<Contact> active = new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) if (c.isActive()) active.add(c);
|
||||
return active;
|
||||
@@ -133,13 +120,7 @@ class ContactManagerImpl implements ContactManager {
|
||||
|
||||
@Override
|
||||
public void removeContact(ContactId c) throws DbException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
removeContact(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn -> removeContact(txn, c));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -148,6 +129,23 @@ class ContactManagerImpl implements ContactManager {
|
||||
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
|
||||
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
|
||||
AuthorId localAuthorId) throws DbException {
|
||||
@@ -157,15 +155,8 @@ class ContactManagerImpl implements ContactManager {
|
||||
@Override
|
||||
public boolean contactExists(AuthorId remoteAuthorId,
|
||||
AuthorId localAuthorId) throws DbException {
|
||||
boolean exists;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
exists = contactExists(txn, remoteAuthorId, localAuthorId);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return exists;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
contactExists(txn, remoteAuthorId, localAuthorId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,4 +167,23 @@ class ContactManagerImpl implements ContactManager {
|
||||
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,6 +29,7 @@ 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_8;
|
||||
import static org.briarproject.bramble.data.Types.TRUE;
|
||||
import static org.briarproject.bramble.util.StringUtils.fromUtf8;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
@@ -253,7 +254,7 @@ class BdfReaderImpl implements BdfReader {
|
||||
if (length < 0 || length > maxBufferSize) throw new FormatException();
|
||||
if (length == 0) return "";
|
||||
readIntoBuffer(length);
|
||||
return new String(buf, 0, length, "UTF-8");
|
||||
return fromUtf8(buf, 0, length);
|
||||
}
|
||||
|
||||
private int readStringLength() throws IOException {
|
||||
|
||||
@@ -616,6 +616,12 @@ interface Database<T> {
|
||||
void setContactActive(T txn, ContactId c, boolean active)
|
||||
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
|
||||
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
|
||||
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
|
||||
import org.briarproject.bramble.api.db.NoSuchMessageException;
|
||||
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.event.Event;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
@@ -193,6 +194,20 @@ 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) {
|
||||
if (transaction.isCommitted()) throw new IllegalStateException();
|
||||
return txnClass.cast(transaction.unbox());
|
||||
@@ -859,6 +874,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
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
|
||||
public void setGroupVisibility(Transaction transaction, ContactId c,
|
||||
GroupId g, Visibility v) throws DbException {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,8 @@ class H2Database extends JdbcDatabase {
|
||||
private static final String BINARY_TYPE = "BINARY";
|
||||
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT";
|
||||
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 String url;
|
||||
@@ -40,8 +42,7 @@ class H2Database extends JdbcDatabase {
|
||||
@Inject
|
||||
H2Database(DatabaseConfig config, MessageFactory messageFactory,
|
||||
Clock clock) {
|
||||
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||
messageFactory, clock);
|
||||
super(dbTypes, messageFactory, clock);
|
||||
this.config = config;
|
||||
File dir = config.getDatabaseDirectory();
|
||||
String path = new File(dir, "db").getAbsolutePath();
|
||||
|
||||
@@ -30,6 +30,8 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
private static final String COUNTER_TYPE =
|
||||
"INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1)";
|
||||
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 String url;
|
||||
@@ -40,8 +42,7 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
@Inject
|
||||
HyperSqlDatabase(DatabaseConfig config, MessageFactory messageFactory,
|
||||
Clock clock) {
|
||||
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||
messageFactory, clock);
|
||||
super(dbTypes, messageFactory, clock);
|
||||
this.config = config;
|
||||
File dir = config.getDatabaseDirectory();
|
||||
String path = new File(dir, "db").getAbsolutePath();
|
||||
@@ -78,7 +79,7 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFreeSpace() throws DbException {
|
||||
public long getFreeSpace() {
|
||||
File dir = config.getDatabaseDirectory();
|
||||
long maxSize = config.getMaxSize();
|
||||
long free = dir.getFreeSpace();
|
||||
|
||||
@@ -56,6 +56,7 @@ import java.util.logging.Logger;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.sql.Types.INTEGER;
|
||||
import static java.sql.Types.VARCHAR;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.api.db.Metadata.REMOVE;
|
||||
@@ -83,7 +84,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
|
||||
abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
// Package access for testing
|
||||
static final int CODE_SCHEMA_VERSION = 40;
|
||||
static final int CODE_SCHEMA_VERSION = 41;
|
||||
|
||||
// Rotation period offsets for incoming transport keys
|
||||
private static final int OFFSET_PREV = -1;
|
||||
@@ -113,6 +114,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
+ " authorId _HASH NOT NULL,"
|
||||
+ " formatVersion INT NOT NULL,"
|
||||
+ " name _STRING NOT NULL,"
|
||||
+ " alias _STRING," // Null if no alias exists
|
||||
+ " publicKey _BINARY NOT NULL,"
|
||||
+ " localAuthorId _HASH NOT NULL,"
|
||||
+ " verified BOOLEAN NOT NULL,"
|
||||
@@ -310,10 +312,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
Logger.getLogger(JdbcDatabase.class.getName());
|
||||
|
||||
// Different database libraries use different names for certain types
|
||||
private final String hashType, secretType, binaryType;
|
||||
private final String counterType, stringType;
|
||||
private final MessageFactory messageFactory;
|
||||
private final Clock clock;
|
||||
private final DatabaseTypes dbTypes;
|
||||
|
||||
// Locking: connectionsLock
|
||||
private final LinkedList<Connection> connections = new LinkedList<>();
|
||||
@@ -328,14 +329,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
private final Lock connectionsLock = new ReentrantLock();
|
||||
private final Condition connectionsChanged = connectionsLock.newCondition();
|
||||
|
||||
JdbcDatabase(String hashType, String secretType, String binaryType,
|
||||
String counterType, String stringType,
|
||||
MessageFactory messageFactory, Clock clock) {
|
||||
this.hashType = hashType;
|
||||
this.secretType = secretType;
|
||||
this.binaryType = binaryType;
|
||||
this.counterType = counterType;
|
||||
this.stringType = stringType;
|
||||
JdbcDatabase(DatabaseTypes databaseTypes, MessageFactory messageFactory,
|
||||
Clock clock) {
|
||||
this.dbTypes = databaseTypes;
|
||||
this.messageFactory = messageFactory;
|
||||
this.clock = clock;
|
||||
}
|
||||
@@ -427,7 +423,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
|
||||
// Package access for testing
|
||||
List<Migration<Connection>> getMigrations() {
|
||||
return Arrays.asList(new Migration38_39(), new Migration39_40());
|
||||
return Arrays.asList(
|
||||
new Migration38_39(),
|
||||
new Migration39_40(),
|
||||
new Migration40_41(dbTypes)
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isCompactionDue(Settings s) {
|
||||
@@ -486,20 +486,20 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
Statement s = null;
|
||||
try {
|
||||
s = txn.createStatement();
|
||||
s.executeUpdate(insertTypeNames(CREATE_SETTINGS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_LOCAL_AUTHORS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_CONTACTS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUPS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_METADATA));
|
||||
s.executeUpdate(insertTypeNames(CREATE_GROUP_VISIBILITIES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGE_METADATA));
|
||||
s.executeUpdate(insertTypeNames(CREATE_MESSAGE_DEPENDENCIES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_OFFERS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_STATUSES));
|
||||
s.executeUpdate(insertTypeNames(CREATE_TRANSPORTS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_OUTGOING_KEYS));
|
||||
s.executeUpdate(insertTypeNames(CREATE_INCOMING_KEYS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_SETTINGS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_LOCAL_AUTHORS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_CONTACTS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_GROUPS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_GROUP_METADATA));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_GROUP_VISIBILITIES));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_MESSAGES));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_MESSAGE_METADATA));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_MESSAGE_DEPENDENCIES));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_OFFERS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_STATUSES));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_TRANSPORTS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_OUTGOING_KEYS));
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_INCOMING_KEYS));
|
||||
s.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s);
|
||||
@@ -524,15 +524,6 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
private String insertTypeNames(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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection startTransaction() throws DbException {
|
||||
Connection txn;
|
||||
@@ -1258,8 +1249,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT authorId, formatVersion, name, publicKey,"
|
||||
+ " localAuthorId, verified, active"
|
||||
String sql = "SELECT authorId, formatVersion, name, alias,"
|
||||
+ " publicKey, localAuthorId, verified, active"
|
||||
+ " FROM contacts"
|
||||
+ " WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -1269,15 +1260,17 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
AuthorId authorId = new AuthorId(rs.getBytes(1));
|
||||
int formatVersion = rs.getInt(2);
|
||||
String name = rs.getString(3);
|
||||
byte[] publicKey = rs.getBytes(4);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
|
||||
boolean verified = rs.getBoolean(6);
|
||||
boolean active = rs.getBoolean(7);
|
||||
String alias = rs.getString(4);
|
||||
byte[] publicKey = rs.getBytes(5);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(6));
|
||||
boolean verified = rs.getBoolean(7);
|
||||
boolean active = rs.getBoolean(8);
|
||||
rs.close();
|
||||
ps.close();
|
||||
Author author =
|
||||
new Author(authorId, formatVersion, name, publicKey);
|
||||
return new Contact(c, author, localAuthorId, verified, active);
|
||||
return new Contact(c, author, localAuthorId, alias, verified,
|
||||
active);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
@@ -1292,7 +1285,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT contactId, authorId, formatVersion, name,"
|
||||
+ " publicKey, localAuthorId, verified, active"
|
||||
+ " alias, publicKey, localAuthorId, verified, active"
|
||||
+ " FROM contacts";
|
||||
ps = txn.prepareStatement(sql);
|
||||
rs = ps.executeQuery();
|
||||
@@ -1302,14 +1295,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
AuthorId authorId = new AuthorId(rs.getBytes(2));
|
||||
int formatVersion = rs.getInt(3);
|
||||
String name = rs.getString(4);
|
||||
byte[] publicKey = rs.getBytes(5);
|
||||
String alias = rs.getString(5);
|
||||
byte[] publicKey = rs.getBytes(6);
|
||||
Author author =
|
||||
new Author(authorId, formatVersion, name, publicKey);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(6));
|
||||
boolean verified = rs.getBoolean(7);
|
||||
boolean active = rs.getBoolean(8);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(7));
|
||||
boolean verified = rs.getBoolean(8);
|
||||
boolean active = rs.getBoolean(9);
|
||||
contacts.add(new Contact(contactId, author, localAuthorId,
|
||||
verified, active));
|
||||
alias, verified, active));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -1350,8 +1344,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
String sql = "SELECT contactId, formatVersion, name, publicKey,"
|
||||
+ " localAuthorId, verified, active"
|
||||
String sql = "SELECT contactId, formatVersion, name, alias,"
|
||||
+ " publicKey, localAuthorId, verified, active"
|
||||
+ " FROM contacts"
|
||||
+ " WHERE authorId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
@@ -1362,14 +1356,15 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ContactId c = new ContactId(rs.getInt(1));
|
||||
int formatVersion = rs.getInt(2);
|
||||
String name = rs.getString(3);
|
||||
byte[] publicKey = rs.getBytes(4);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(5));
|
||||
boolean verified = rs.getBoolean(6);
|
||||
boolean active = rs.getBoolean(7);
|
||||
String alias = rs.getString(4);
|
||||
byte[] publicKey = rs.getBytes(5);
|
||||
AuthorId localAuthorId = new AuthorId(rs.getBytes(6));
|
||||
boolean verified = rs.getBoolean(7);
|
||||
boolean active = rs.getBoolean(8);
|
||||
Author author =
|
||||
new Author(remote, formatVersion, name, publicKey);
|
||||
contacts.add(new Contact(c, author, localAuthorId, verified,
|
||||
active));
|
||||
contacts.add(new Contact(c, author, localAuthorId, alias,
|
||||
verified, active));
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
@@ -2794,6 +2789,25 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContactAlias(Connection txn, ContactId c,
|
||||
@Nullable String alias) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
String sql = "UPDATE contacts SET alias = ? WHERE contactId = ?";
|
||||
ps = txn.prepareStatement(sql);
|
||||
if (alias == null) ps.setNull(1, VARCHAR);
|
||||
else ps.setString(1, alias);
|
||||
ps.setInt(2, c.getInt());
|
||||
int affected = ps.executeUpdate();
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupVisibility(Connection txn, ContactId c, GroupId g,
|
||||
boolean shared) throws DbException {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
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 javax.annotation.Nullable;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
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);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable Statement s) {
|
||||
try {
|
||||
if (s != null) s.close();
|
||||
} catch (SQLException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,21 @@
|
||||
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.KeyPair;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
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.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
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.now;
|
||||
|
||||
@@ -75,27 +67,16 @@ class IdentityManagerImpl implements IdentityManager {
|
||||
LOG.info("No local author to store");
|
||||
return;
|
||||
}
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.addLocalAuthor(txn, cached);
|
||||
db.commitTransaction(txn);
|
||||
LOG.info("Local author stored");
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
|
||||
LOG.info("Local author stored");
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalAuthor getLocalAuthor() throws DbException {
|
||||
if (cachedAuthor == null) {
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
cachedAuthor = loadLocalAuthor(txn);
|
||||
LOG.info("Local author loaded");
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
cachedAuthor =
|
||||
db.transactionWithResult(true, this::loadLocalAuthor);
|
||||
LOG.info("Local author loaded");
|
||||
}
|
||||
LocalAuthor cached = cachedAuthor;
|
||||
if (cached == null) throw new AssertionError();
|
||||
@@ -118,26 +99,4 @@ class IdentityManagerImpl implements IdentityManager {
|
||||
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,7 +6,6 @@ import org.briarproject.bramble.api.db.DataTooOldException;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
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.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
@@ -115,20 +114,16 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
||||
dbLatch.countDown();
|
||||
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
|
||||
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
for (Client c : clients) {
|
||||
start = now();
|
||||
long start1 = now();
|
||||
c.createLocalState(txn);
|
||||
if (LOG.isLoggable(FINE)) {
|
||||
logDuration(LOG, "Starting client "
|
||||
+ c.getClass().getSimpleName(), start);
|
||||
+ c.getClass().getSimpleName(), start1);
|
||||
}
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
});
|
||||
for (Service s : services) {
|
||||
start = now();
|
||||
s.startService();
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.bramble.api.settings.Settings;
|
||||
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
@@ -46,6 +45,9 @@ 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.util.LogUtils.logException;
|
||||
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
|
||||
@ParametersNotNullByDefault
|
||||
@@ -96,6 +98,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
abstract DuplexTransportConnection connectTo(String address, String uuid)
|
||||
throws IOException;
|
||||
|
||||
@Nullable
|
||||
abstract DuplexTransportConnection discoverAndConnect(String uuid);
|
||||
|
||||
BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
|
||||
Executor ioExecutor, SecureRandom secureRandom,
|
||||
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
|
||||
@@ -193,7 +198,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
address = getBluetoothAddress();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Local address " + scrubMacAddress(address));
|
||||
if (!StringUtils.isNullOrEmpty(address)) {
|
||||
if (!isNullOrEmpty(address)) {
|
||||
p.put(PROP_ADDRESS, address);
|
||||
changed = true;
|
||||
}
|
||||
@@ -256,9 +261,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
// Try to connect to known devices in parallel
|
||||
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
|
||||
String address = e.getValue().get(PROP_ADDRESS);
|
||||
if (StringUtils.isNullOrEmpty(address)) continue;
|
||||
if (isNullOrEmpty(address)) continue;
|
||||
String uuid = e.getValue().get(PROP_UUID);
|
||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||
if (isNullOrEmpty(uuid)) continue;
|
||||
ContactId c = e.getKey();
|
||||
ioExecutor.execute(() -> {
|
||||
if (!isRunning() || !shouldAllowContactConnections()) return;
|
||||
@@ -309,9 +314,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
if (!isRunning() || !shouldAllowContactConnections()) return null;
|
||||
if (!connectionLimiter.canOpenContactConnection()) return null;
|
||||
String address = p.get(PROP_ADDRESS);
|
||||
if (StringUtils.isNullOrEmpty(address)) return null;
|
||||
if (isNullOrEmpty(address)) return null;
|
||||
String uuid = p.get(PROP_UUID);
|
||||
if (StringUtils.isNullOrEmpty(uuid)) return null;
|
||||
if (isNullOrEmpty(uuid)) return null;
|
||||
DuplexTransportConnection conn = connect(address, uuid);
|
||||
if (conn == null) return null;
|
||||
// TODO: Why don't we reset the backoff here?
|
||||
@@ -326,9 +331,6 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
@Override
|
||||
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
|
||||
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
|
||||
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
|
||||
@@ -346,7 +348,8 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
}
|
||||
BdfList descriptor = new BdfList();
|
||||
descriptor.add(TRANSPORT_ID_BLUETOOTH);
|
||||
descriptor.add(StringUtils.macToBytes(address));
|
||||
String address = getBluetoothAddress();
|
||||
if (address != null) descriptor.add(macToBytes(address));
|
||||
return new BluetoothKeyAgreementListener(descriptor, ss);
|
||||
}
|
||||
|
||||
@@ -354,18 +357,25 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
public DuplexTransportConnection createKeyAgreementConnection(
|
||||
byte[] commitment, BdfList descriptor) {
|
||||
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
|
||||
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Connecting to key agreement UUID " + uuid);
|
||||
DuplexTransportConnection conn = connect(address, uuid);
|
||||
DuplexTransportConnection conn;
|
||||
if (descriptor.size() == 1) {
|
||||
if (LOG.isLoggable(INFO))
|
||||
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);
|
||||
return conn;
|
||||
}
|
||||
@@ -373,7 +383,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
||||
private String parseAddress(BdfList descriptor) throws FormatException {
|
||||
byte[] mac = descriptor.getRaw(1);
|
||||
if (mac.length != 6) throw new FormatException();
|
||||
return StringUtils.macToString(mac);
|
||||
return macToString(mac);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,8 @@ import net.freehaven.tor.control.EventHandler;
|
||||
import net.freehaven.tor.control.TorControlConnection;
|
||||
|
||||
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.data.BdfList;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
@@ -96,13 +98,14 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
private final LocationUtils locationUtils;
|
||||
private final SocketFactory torSocketFactory;
|
||||
private final Clock clock;
|
||||
private final BatteryManager batteryManager;
|
||||
private final Backoff backoff;
|
||||
private final DuplexPluginCallback callback;
|
||||
private final String architecture;
|
||||
private final CircumventionProvider circumventionProvider;
|
||||
private final ResourceProvider resourceProvider;
|
||||
private final int maxLatency, maxIdleTime, socketTimeout;
|
||||
private final File torDirectory, torFile, geoIpFile, configFile;
|
||||
private final File torDirectory, torFile, geoIpFile, obfs4File, configFile;
|
||||
private final File doneFile, cookieFile;
|
||||
private final ConnectionStatus connectionStatus;
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
@@ -121,7 +124,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||
Clock clock, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Backoff backoff,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime, File torDirectory) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
@@ -131,6 +135,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
this.clock = clock;
|
||||
this.resourceProvider = resourceProvider;
|
||||
this.circumventionProvider = circumventionProvider;
|
||||
this.batteryManager = batteryManager;
|
||||
this.backoff = backoff;
|
||||
this.callback = callback;
|
||||
this.architecture = architecture;
|
||||
@@ -142,6 +147,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
this.torDirectory = torDirectory;
|
||||
torFile = new File(torDirectory, "tor");
|
||||
geoIpFile = new File(torDirectory, "geoip");
|
||||
obfs4File = new File(torDirectory, "obfs4proxy");
|
||||
configFile = new File(torDirectory, "torrc");
|
||||
doneFile = new File(torDirectory, "done");
|
||||
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
||||
@@ -260,7 +266,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
throw new PluginException(e);
|
||||
}
|
||||
// Check whether we're online
|
||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
||||
batteryManager.isCharging());
|
||||
// Bind a server socket to receive incoming hidden service connections
|
||||
bind();
|
||||
}
|
||||
@@ -284,6 +291,12 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
in = getGeoIpInputStream();
|
||||
out = new FileOutputStream(geoIpFile);
|
||||
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
|
||||
in = getConfigInputStream();
|
||||
out = new FileOutputStream(configFile);
|
||||
@@ -314,6 +327,16 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
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() {
|
||||
return getClass().getClassLoader().getResourceAsStream("torrc");
|
||||
}
|
||||
@@ -472,6 +495,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
if (enable) {
|
||||
Collection<String> conf = new ArrayList<>();
|
||||
conf.add("UseBridges 1");
|
||||
conf.add("ClientTransportPlugin obfs4 exec " +
|
||||
obfs4File.getAbsolutePath());
|
||||
conf.addAll(circumventionProvider.getBridges());
|
||||
controlConnection.setConf(conf);
|
||||
} else {
|
||||
@@ -609,7 +634,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
LOG.info("OR connection " + status + " " + orName);
|
||||
if (status.equals("CLOSED") || status.equals("FAILED")) {
|
||||
// Check whether we've lost connectivity
|
||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
||||
batteryManager.isCharging());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,10 +673,15 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
// Works around a bug introduced in Tor 0.3.4.8. Could be
|
||||
// replaced with callback.transportDisabled() when fixed.
|
||||
disableNetwork();
|
||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
||||
batteryManager.isCharging());
|
||||
}
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -664,7 +695,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConnectionStatus(NetworkStatus status) {
|
||||
private void updateConnectionStatus(NetworkStatus status,
|
||||
boolean charging) {
|
||||
connectionStatusExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
boolean online = status.isConnected();
|
||||
@@ -682,6 +714,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||
if ("".equals(country)) LOG.info("Country code unknown");
|
||||
else LOG.info("Country code: " + country);
|
||||
LOG.info("Charging: " + charging);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -705,12 +738,24 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
enableBridges(false);
|
||||
enableNetwork(true);
|
||||
}
|
||||
if (online && wifi && charging) {
|
||||
LOG.info("Enabling connection padding");
|
||||
enableConnectionPadding(true);
|
||||
} else {
|
||||
LOG.info("Disabling connection padding");
|
||||
enableConnectionPadding(false);
|
||||
}
|
||||
} catch (IOException 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
|
||||
private void migrateSettings() {
|
||||
Settings sOld = callback.getSettings();
|
||||
|
||||
@@ -142,15 +142,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@Override
|
||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||
throws DbException {
|
||||
Map<TransportId, TransportProperties> local;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
local = getLocalProperties(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return local;
|
||||
return db.transactionWithResult(true, this::getLocalProperties);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,9 +168,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
public TransportProperties getLocalProperties(TransportId t)
|
||||
throws DbException {
|
||||
try {
|
||||
TransportProperties p = null;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
return db.transactionWithResult(true, txn -> {
|
||||
TransportProperties p = null;
|
||||
// Find the latest local update
|
||||
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
|
||||
true);
|
||||
@@ -188,11 +179,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
latest.messageId);
|
||||
p = parseProperties(message);
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return p == null ? new TransportProperties() : p;
|
||||
return p == null ? new TransportProperties() : p;
|
||||
});
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
@@ -201,16 +189,12 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@Override
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties(
|
||||
TransportId t) throws DbException {
|
||||
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
return db.transactionWithResult(true, txn -> {
|
||||
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
||||
for (Contact c : db.getContacts(txn))
|
||||
remote.put(c.getId(), getRemoteProperties(txn, c, t));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return remote;
|
||||
return remote;
|
||||
});
|
||||
}
|
||||
|
||||
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
||||
@@ -234,23 +218,15 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@Override
|
||||
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
|
||||
throws DbException {
|
||||
TransportProperties p;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
p = getRemoteProperties(txn, db.getContact(txn, c), t);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return p;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getRemoteProperties(txn, db.getContact(txn, c), t));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
||||
throws DbException {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
// Merge the new properties with any existing properties
|
||||
TransportProperties merged;
|
||||
boolean changed;
|
||||
@@ -287,10 +263,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
db.removeMessage(txn, latest.messageId);
|
||||
}
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
});
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
|
||||
@@ -23,15 +23,8 @@ class SettingsManagerImpl implements SettingsManager {
|
||||
|
||||
@Override
|
||||
public Settings getSettings(String namespace) throws DbException {
|
||||
Settings s;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
s = db.getSettings(txn, namespace);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return s;
|
||||
return db.transactionWithResult(true, txn ->
|
||||
db.getSettings(txn, namespace));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,12 +35,6 @@ class SettingsManagerImpl implements SettingsManager {
|
||||
|
||||
@Override
|
||||
public void mergeSettings(Settings s, String namespace) throws DbException {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.mergeSettings(txn, s, namespace);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn -> db.mergeSettings(txn, s, namespace));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
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.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
@@ -230,14 +229,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (interrupted) return;
|
||||
if (!generateAckQueued.getAndSet(false)) throw new AssertionError();
|
||||
try {
|
||||
Ack a;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Ack a = db.transactionWithNullableResult(false, txn ->
|
||||
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated ack: " + (a != null));
|
||||
if (a != null) writerTasks.add(new WriteAck(a));
|
||||
@@ -275,16 +268,15 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (!generateBatchQueued.getAndSet(false))
|
||||
throw new AssertionError();
|
||||
try {
|
||||
Collection<Message> b;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
b = db.generateRequestedBatch(txn, contactId,
|
||||
MAX_RECORD_PAYLOAD_BYTES, maxLatency);
|
||||
setNextSendTime(db.getNextSendTime(txn, contactId));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Collection<Message> b =
|
||||
db.transactionWithNullableResult(false, txn -> {
|
||||
Collection<Message> batch =
|
||||
db.generateRequestedBatch(txn, contactId,
|
||||
MAX_RECORD_PAYLOAD_BYTES,
|
||||
maxLatency);
|
||||
setNextSendTime(db.getNextSendTime(txn, contactId));
|
||||
return batch;
|
||||
});
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated batch: " + (b != null));
|
||||
if (b != null) writerTasks.add(new WriteBatch(b));
|
||||
@@ -322,16 +314,12 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (!generateOfferQueued.getAndSet(false))
|
||||
throw new AssertionError();
|
||||
try {
|
||||
Offer o;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
o = db.generateOffer(txn, contactId, MAX_MESSAGE_IDS,
|
||||
maxLatency);
|
||||
Offer o = db.transactionWithNullableResult(false, txn -> {
|
||||
Offer offer = db.generateOffer(txn, contactId,
|
||||
MAX_MESSAGE_IDS, maxLatency);
|
||||
setNextSendTime(db.getNextSendTime(txn, contactId));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return offer;
|
||||
});
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated offer: " + (o != null));
|
||||
if (o != null) writerTasks.add(new WriteOffer(o));
|
||||
@@ -369,14 +357,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (!generateRequestQueued.getAndSet(false))
|
||||
throw new AssertionError();
|
||||
try {
|
||||
Request r;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
r = db.generateRequest(txn, contactId, MAX_MESSAGE_IDS);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Request r = db.transactionWithNullableResult(false, txn ->
|
||||
db.generateRequest(txn, contactId, MAX_MESSAGE_IDS));
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated request: " + (r != null));
|
||||
if (r != null) writerTasks.add(new WriteRequest(r));
|
||||
|
||||
@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
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.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
@@ -120,13 +119,8 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveAck(txn, contactId, ack);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn ->
|
||||
db.receiveAck(txn, contactId, ack));
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
@@ -146,13 +140,8 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveMessage(txn, contactId, message);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn ->
|
||||
db.receiveMessage(txn, contactId, message));
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
@@ -172,13 +161,8 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveOffer(txn, contactId, offer);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn ->
|
||||
db.receiveOffer(txn, contactId, offer));
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
@@ -198,13 +182,8 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveRequest(txn, contactId, request);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, txn ->
|
||||
db.receiveRequest(txn, contactId, request));
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
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.EventBus;
|
||||
import org.briarproject.bramble.api.event.EventListener;
|
||||
@@ -47,7 +46,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(SimplexOutgoingSession.class.getName());
|
||||
|
||||
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
|
||||
private static final ThrowingRunnable<IOException> CLOSE = () -> {
|
||||
};
|
||||
|
||||
private final DatabaseComponent db;
|
||||
private final Executor dbExecutor;
|
||||
@@ -128,14 +128,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
||||
public void run() {
|
||||
if (interrupted) return;
|
||||
try {
|
||||
Ack a;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Ack a = db.transactionWithNullableResult(false, txn ->
|
||||
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated ack: " + (a != null));
|
||||
if (a == null) decrementOutstandingQueries();
|
||||
@@ -172,15 +166,10 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
||||
public void run() {
|
||||
if (interrupted) return;
|
||||
try {
|
||||
Collection<Message> b;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
b = db.generateBatch(txn, contactId,
|
||||
MAX_RECORD_PAYLOAD_BYTES, maxLatency);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Collection<Message> b =
|
||||
db.transactionWithNullableResult(false, txn ->
|
||||
db.generateBatch(txn, contactId,
|
||||
MAX_RECORD_PAYLOAD_BYTES, maxLatency));
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated batch: " + (b != null));
|
||||
if (b == null) decrementOutstandingQueries();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.sync;
|
||||
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -97,14 +98,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void validateOutstandingMessages() {
|
||||
try {
|
||||
Queue<MessageId> unvalidated = new LinkedList<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
unvalidated.addAll(db.getMessagesToValidate(txn));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Queue<MessageId> unvalidated = new LinkedList<>(
|
||||
db.transactionWithResult(true, db::getMessagesToValidate));
|
||||
validateNextMessageAsync(unvalidated);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -119,18 +114,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void validateNextMessage(Queue<MessageId> unvalidated) {
|
||||
try {
|
||||
Message m;
|
||||
Group g;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
Pair<Message, Group> mg = db.transactionWithResult(true, txn -> {
|
||||
MessageId id = unvalidated.poll();
|
||||
m = db.getMessage(txn, id);
|
||||
g = db.getGroup(txn, m.getGroupId());
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
validateMessageAsync(m, g);
|
||||
if (id == null) throw new AssertionError();
|
||||
Message m = db.getMessage(txn, id);
|
||||
Group g = db.getGroup(txn, m.getGroupId());
|
||||
return new Pair<>(m, g);
|
||||
});
|
||||
validateMessageAsync(mg.getFirst(), mg.getSecond());
|
||||
validateNextMessageAsync(unvalidated);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before validation");
|
||||
@@ -150,14 +141,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void deliverOutstandingMessages() {
|
||||
try {
|
||||
Queue<MessageId> pending = new LinkedList<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
pending.addAll(db.getPendingMessages(txn));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Queue<MessageId> pending = new LinkedList<>(
|
||||
db.transactionWithResult(true, db::getPendingMessages));
|
||||
deliverNextPendingMessageAsync(pending);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -172,12 +157,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void deliverNextPendingMessage(Queue<MessageId> pending) {
|
||||
try {
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
Queue<MessageId> toShare = null;
|
||||
Queue<MessageId> invalidate = null;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
Queue<MessageId> toShare = new LinkedList<>();
|
||||
Queue<MessageId> invalidate = new LinkedList<>();
|
||||
db.transaction(false, txn -> {
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
MessageId id = pending.poll();
|
||||
if (id == null) throw new AssertionError();
|
||||
// Check if message is still pending
|
||||
if (db.getMessageState(txn, id) == PENDING) {
|
||||
// Check if dependencies are valid and delivered
|
||||
@@ -189,7 +174,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
if (anyInvalid) {
|
||||
invalidateMessage(txn, id);
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
} else if (allDelivered) {
|
||||
Message m = db.getMessage(txn, id);
|
||||
Group g = db.getGroup(txn, m.getGroupId());
|
||||
@@ -200,22 +185,19 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
DeliveryResult result =
|
||||
deliverMessage(txn, m, c, majorVersion, meta);
|
||||
if (result.valid) {
|
||||
pending.addAll(getPendingDependents(txn, id));
|
||||
addPendingDependents(txn, id, pending);
|
||||
if (result.share) {
|
||||
db.setMessageShared(txn, id);
|
||||
toShare = new LinkedList<>(states.keySet());
|
||||
toShare.addAll(states.keySet());
|
||||
}
|
||||
} else {
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
}
|
||||
}
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (invalidate != null) invalidateNextMessageAsync(invalidate);
|
||||
if (toShare != null) shareNextMessageAsync(toShare);
|
||||
});
|
||||
if (!invalidate.isEmpty()) invalidateNextMessageAsync(invalidate);
|
||||
if (!toShare.isEmpty()) shareNextMessageAsync(toShare);
|
||||
deliverNextPendingMessageAsync(pending);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before delivery");
|
||||
@@ -264,12 +246,11 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
MessageContext context) {
|
||||
try {
|
||||
MessageId id = m.getId();
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
Queue<MessageId> invalidate = null;
|
||||
Queue<MessageId> pending = null;
|
||||
Queue<MessageId> toShare = null;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
Queue<MessageId> invalidate = new LinkedList<>();
|
||||
Queue<MessageId> pending = new LinkedList<>();
|
||||
Queue<MessageId> toShare = new LinkedList<>();
|
||||
db.transaction(false, txn -> {
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
// Check if message has any dependencies
|
||||
Collection<MessageId> dependencies = context.getDependencies();
|
||||
if (!dependencies.isEmpty()) {
|
||||
@@ -285,7 +266,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
if (anyInvalid) {
|
||||
if (db.getMessageState(txn, id) != INVALID) {
|
||||
invalidateMessage(txn, id);
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
}
|
||||
} else {
|
||||
Metadata meta = context.getMetadata();
|
||||
@@ -294,25 +275,22 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
DeliveryResult result =
|
||||
deliverMessage(txn, m, c, majorVersion, meta);
|
||||
if (result.valid) {
|
||||
pending = getPendingDependents(txn, id);
|
||||
addPendingDependents(txn, id, pending);
|
||||
if (result.share) {
|
||||
db.setMessageShared(txn, id);
|
||||
toShare = new LinkedList<>(dependencies);
|
||||
toShare.addAll(dependencies);
|
||||
}
|
||||
} else {
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
}
|
||||
} else {
|
||||
db.setMessageState(txn, id, PENDING);
|
||||
}
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (invalidate != null) invalidateNextMessageAsync(invalidate);
|
||||
if (pending != null) deliverNextPendingMessageAsync(pending);
|
||||
if (toShare != null) shareNextMessageAsync(toShare);
|
||||
});
|
||||
if (!invalidate.isEmpty()) invalidateNextMessageAsync(invalidate);
|
||||
if (!pending.isEmpty()) deliverNextPendingMessageAsync(pending);
|
||||
if (!toShare.isEmpty()) shareNextMessageAsync(toShare);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed during validation");
|
||||
} catch (NoSuchGroupException e) {
|
||||
@@ -342,14 +320,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
|
||||
throws DbException {
|
||||
Queue<MessageId> pending = new LinkedList<>();
|
||||
private void addPendingDependents(Transaction txn, MessageId m,
|
||||
Queue<MessageId> pending) throws DbException {
|
||||
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
||||
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||
if (e.getValue() == PENDING) pending.add(e.getKey());
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
|
||||
private void shareOutstandingMessagesAsync() {
|
||||
@@ -359,14 +335,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void shareOutstandingMessages() {
|
||||
try {
|
||||
Queue<MessageId> toShare = new LinkedList<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
toShare.addAll(db.getMessagesToShare(txn));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Queue<MessageId> toShare = new LinkedList<>(
|
||||
db.transactionWithResult(true, db::getMessagesToShare));
|
||||
shareNextMessageAsync(toShare);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -387,15 +357,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void shareNextMessage(Queue<MessageId> toShare) {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
MessageId id = toShare.poll();
|
||||
if (id == null) throw new AssertionError();
|
||||
db.setMessageShared(txn, id);
|
||||
toShare.addAll(db.getMessageDependencies(txn, id).keySet());
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
});
|
||||
shareNextMessageAsync(toShare);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before sharing");
|
||||
@@ -416,17 +383,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void invalidateNextMessage(Queue<MessageId> invalidate) {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
MessageId id = invalidate.poll();
|
||||
if (id == null) throw new AssertionError();
|
||||
if (db.getMessageState(txn, id) != INVALID) {
|
||||
invalidateMessage(txn, id);
|
||||
invalidate.addAll(getDependentsToInvalidate(txn, id));
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
});
|
||||
invalidateNextMessageAsync(invalidate);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before invalidation");
|
||||
@@ -445,14 +409,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
|
||||
MessageId m) throws DbException {
|
||||
Queue<MessageId> invalidate = new LinkedList<>();
|
||||
private void addDependentsToInvalidate(Transaction txn,
|
||||
MessageId m, Queue<MessageId> invalidate) throws DbException {
|
||||
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
||||
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||
if (e.getValue() != INVALID) invalidate.add(e.getKey());
|
||||
}
|
||||
return invalidate;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -472,14 +434,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void loadGroupAndValidate(Message m) {
|
||||
try {
|
||||
Group g;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
g = db.getGroup(txn, m.getGroupId());
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
Group g = db.transactionWithResult(true, txn ->
|
||||
db.getGroup(txn, m.getGroupId()));
|
||||
validateMessageAsync(m, g);
|
||||
} catch (NoSuchGroupException e) {
|
||||
LOG.info("Group removed before validation");
|
||||
|
||||
@@ -72,8 +72,7 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
|
||||
transports.put(f.getId(), f.getMaxLatency());
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
for (Contact c : db.getContacts(txn))
|
||||
if (c.isActive()) activeContacts.put(c.getId(), true);
|
||||
for (Entry<TransportId, Integer> e : transports.entrySet())
|
||||
@@ -85,10 +84,7 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
managers.put(e.getKey(), m);
|
||||
m.start(txn);
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
});
|
||||
} catch (DbException e) {
|
||||
throw new ServiceException(e);
|
||||
}
|
||||
@@ -141,15 +137,8 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
||||
return null;
|
||||
}
|
||||
StreamContext ctx;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
ctx = m.getStreamContext(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return ctx;
|
||||
return db.transactionWithNullableResult(false, txn ->
|
||||
m.getStreamContext(txn, c));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,15 +149,8 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
||||
return null;
|
||||
}
|
||||
StreamContext ctx;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
ctx = m.getStreamContext(txn, tag);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return ctx;
|
||||
return db.transactionWithNullableResult(false, txn ->
|
||||
m.getStreamContext(txn, tag));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -162,13 +162,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
private void rotateKeys() {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
rotateKeys(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
db.transaction(false, this::rotateKeys);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
|
||||
@@ -123,16 +123,12 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
|
||||
List<ClientVersion> versions = new ArrayList<>(clients);
|
||||
Collections.sort(versions);
|
||||
try {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
if (updateClientVersions(txn, versions)) {
|
||||
for (Contact c : db.getContacts(txn))
|
||||
clientVersionsUpdated(txn, c, versions);
|
||||
}
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
});
|
||||
} catch (DbException e) {
|
||||
throw new ServiceException(e);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
|
||||
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
|
||||
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
|
||||
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
|
||||
Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0
|
||||
Bridge obfs4 52.15.78.72:9443 02069A3C5362476936B62BA6F5ACC41ABD573A9B cert=ijYG/OKc7kqu2YzKNFfeXN7/BG2BOgfEP2KyYEiGDQthnHbsOiTWHeIG0WJVW+BckzDgKw iat-mode=0
|
||||
Bridge obfs4 13.58.29.242:9443 0C58939A77DA6B6B29D4B5236A75865659607AE0 cert=OylWIEHb/ezpq1zWxW0sgKRn+9ARH2eOcQOZ8/Gew+4l+oKOhQ2jUX/Y+FSl61JorXZUWA iat-mode=0
|
||||
Bridge obfs4 45.33.37.112:9443 60A609BB4ABE8D46E634AE81ED29ADAB7776B399 cert=t5v19WmNv5Sc2YPNr8RQids365W7MY8zJwQVkOxBjUMFomMWARDzsbYpcWLLcw0J9Gm+BQ iat-mode=0
|
||||
@@ -22,6 +22,7 @@ import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
@@ -85,14 +86,11 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
boolean shared = new Random().nextBoolean();
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(metadataEncoder).encode(dictionary);
|
||||
will(returnValue(metadata));
|
||||
oneOf(db).addLocalMessage(txn, message, metadata, shared);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
clientHelper.addLocalMessage(message, dictionary, shared);
|
||||
@@ -116,13 +114,10 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
expectToList(true);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessage(txn, messageId);
|
||||
will(returnValue(message));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
clientHelper.getMessageAsList(messageId);
|
||||
@@ -133,15 +128,12 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testGetGroupMetadataAsDictionary() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroupMetadata(txn, groupId);
|
||||
will(returnValue(metadata));
|
||||
oneOf(metadataParser).parse(metadata);
|
||||
will(returnValue(dictionary));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(dictionary,
|
||||
@@ -153,15 +145,12 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testGetMessageMetadataAsDictionary() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessageMetadata(txn, messageId);
|
||||
will(returnValue(metadata));
|
||||
oneOf(metadataParser).parse(metadata);
|
||||
will(returnValue(dictionary));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(dictionary,
|
||||
@@ -175,15 +164,12 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
map.put(messageId, dictionary);
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessageMetadata(txn, groupId);
|
||||
will(returnValue(Collections.singletonMap(messageId, metadata)));
|
||||
oneOf(metadataParser).parse(metadata);
|
||||
will(returnValue(dictionary));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId));
|
||||
@@ -200,17 +186,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
queryMetadata.put("query", getRandomBytes(42));
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(metadataEncoder).encode(query);
|
||||
will(returnValue(queryMetadata));
|
||||
oneOf(db).getMessageMetadata(txn, groupId, queryMetadata);
|
||||
will(returnValue(Collections.singletonMap(messageId, metadata)));
|
||||
oneOf(metadataParser).parse(metadata);
|
||||
will(returnValue(dictionary));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(map,
|
||||
@@ -222,14 +205,11 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testMergeGroupMetadata() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(metadataEncoder).encode(dictionary);
|
||||
will(returnValue(metadata));
|
||||
oneOf(db).mergeGroupMetadata(txn, groupId, metadata);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
clientHelper.mergeGroupMetadata(groupId, dictionary);
|
||||
@@ -240,14 +220,11 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testMergeMessageMetadata() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(metadataEncoder).encode(dictionary);
|
||||
will(returnValue(metadata));
|
||||
oneOf(db).mergeMessageMetadata(txn, messageId, metadata);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
clientHelper.mergeMessageMetadata(messageId, dictionary);
|
||||
|
||||
@@ -5,12 +5,17 @@ import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
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.Transaction;
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
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.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.Mockery;
|
||||
import org.junit.Test;
|
||||
@@ -20,10 +25,20 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
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.getLocalAuthor;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
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.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@@ -31,16 +46,20 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
private final Mockery context = new Mockery();
|
||||
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||
private final KeyManager keyManager = context.mock(KeyManager.class);
|
||||
private final IdentityManager identityManager =
|
||||
context.mock(IdentityManager.class);
|
||||
private final ContactManager contactManager;
|
||||
private final ContactId contactId = new ContactId(42);
|
||||
private final Author remote = getAuthor();
|
||||
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 Contact contact =
|
||||
new Contact(contactId, remote, local, verified, active);
|
||||
new Contact(contactId, remote, local, alias, verified, active);
|
||||
|
||||
public ContactManagerImplTest() {
|
||||
contactManager = new ContactManagerImpl(db, keyManager);
|
||||
contactManager = new ContactManagerImpl(db, keyManager, identityManager);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50,17 +69,14 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
boolean alice = new Random().nextBoolean();
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(false), withDbCallable(txn));
|
||||
oneOf(db).addContact(txn, remote, local, verified, active);
|
||||
will(returnValue(contactId));
|
||||
oneOf(keyManager).addContact(txn, contactId, master, timestamp,
|
||||
alice, active);
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(contactId, contactManager.addContact(remote, local,
|
||||
@@ -70,13 +86,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@Test
|
||||
public void testGetContact() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(contact, contactManager.getContact(contactId));
|
||||
@@ -86,13 +99,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
public void testGetContactByAuthor() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
Collection<Contact> contacts = Collections.singleton(contact);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||
will(returnValue(contacts));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(contact, contactManager.getContact(remote.getId(), local));
|
||||
@@ -101,12 +111,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@Test(expected = NoSuchContactException.class)
|
||||
public void testGetContactByUnknownAuthor() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||
will(returnValue(Collections.emptyList()));
|
||||
oneOf(db).endTransaction(txn);
|
||||
will(returnValue(emptyList()));
|
||||
}});
|
||||
|
||||
contactManager.getContact(remote.getId(), local);
|
||||
@@ -116,30 +124,26 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
public void testGetContactByUnknownLocalAuthor() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
Collection<Contact> contacts = Collections.singleton(contact);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||
will(returnValue(contacts));
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
contactManager.getContact(remote.getId(), new AuthorId(getRandomId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActiveContacts() throws Exception {
|
||||
public void testGetActiveContacts() throws Exception {
|
||||
Collection<Contact> activeContacts = Collections.singletonList(contact);
|
||||
Collection<Contact> contacts = new ArrayList<>(activeContacts);
|
||||
contacts.add(new Contact(new ContactId(3), remote, local, true, false));
|
||||
contacts.add(new Contact(new ContactId(3), remote, local, alias, true,
|
||||
false));
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(activeContacts, contactManager.getActiveContacts());
|
||||
@@ -148,14 +152,11 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@Test
|
||||
public void testRemoveContact() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(db).removeContact(txn, contactId);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
contactManager.removeContact(contactId);
|
||||
@@ -171,19 +172,108 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
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
|
||||
public void testContactExists() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).containsContact(txn, remote.getId(), local);
|
||||
will(returnValue(true));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
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));
|
||||
}});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
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
@@ -53,6 +53,7 @@ import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
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.SHARED;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.VISIBLE;
|
||||
@@ -74,6 +75,7 @@ import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||
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.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -1713,6 +1715,39 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
||||
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
|
||||
public void testSetMessageState() throws Exception {
|
||||
Database<Connection> db = open(false);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
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.KeyPair;
|
||||
import org.briarproject.bramble.api.crypto.PrivateKey;
|
||||
@@ -9,25 +7,18 @@ import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
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.AuthorFactory;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
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.junit.Assert.assertEquals;
|
||||
|
||||
@@ -74,13 +65,10 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAndStoreLocalAuthor() throws DbException {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
public void testRegisterAndStoreLocalAuthor() throws Exception {
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(db).addLocalAuthor(txn, localAuthor);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
identityManager.registerLocalAuthor(localAuthor);
|
||||
@@ -89,14 +77,11 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetLocalAuthor() throws DbException {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
public void testGetLocalAuthor() throws Exception {
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getLocalAuthors(txn);
|
||||
will(returnValue(localAuthors));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
assertEquals(localAuthor, identityManager.getLocalAuthor());
|
||||
}
|
||||
@@ -107,60 +92,4 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
||||
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);
|
||||
}});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,16 +21,18 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyManager.CLIENT_ID;
|
||||
import static org.briarproject.bramble.api.properties.TransportPropertyManager.MAJOR_VERSION;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
@@ -39,6 +41,7 @@ import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMessage;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
@@ -350,14 +353,11 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
new BdfEntry("local", true)
|
||||
));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -385,9 +385,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
));
|
||||
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
will(returnValue(messageMetadata));
|
||||
@@ -396,8 +395,6 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||
fooPropertiesDict);
|
||||
will(returnValue(fooProperties));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -412,8 +409,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Contact contact1 = getContact(false);
|
||||
Contact contact2 = getContact(true);
|
||||
Contact contact3 = getContact(true);
|
||||
List<Contact> contacts =
|
||||
Arrays.asList(contact1, contact2, contact3);
|
||||
List<Contact> contacts = asList(contact1, contact2, contact3);
|
||||
Group contactGroup2 = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
Group contactGroup3 = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
Map<MessageId, BdfDictionary> messageMetadata3 =
|
||||
@@ -441,9 +437,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
));
|
||||
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
// First contact: skipped because not active
|
||||
@@ -466,8 +461,6 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(clientHelper).parseAndValidateTransportProperties(
|
||||
fooPropertiesDict);
|
||||
will(returnValue(fooProperties));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -484,17 +477,16 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
MessageId updateId = new MessageId(getRandomId());
|
||||
Map<MessageId, BdfDictionary> messageMetadata =
|
||||
Collections.singletonMap(updateId, BdfDictionary.of(
|
||||
Map<MessageId, BdfDictionary> messageMetadata = singletonMap(updateId,
|
||||
BdfDictionary.of(
|
||||
new BdfEntry("transportId", "foo"),
|
||||
new BdfEntry("version", 1),
|
||||
new BdfEntry("local", true)
|
||||
));
|
||||
BdfList update = BdfList.of("foo", 1, fooPropertiesDict);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// Merge the new properties with the existing properties
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
@@ -505,8 +497,6 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
fooPropertiesDict);
|
||||
will(returnValue(fooProperties));
|
||||
// Properties are unchanged so we're done
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -519,9 +509,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
Contact contact = getContact(true);
|
||||
Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// There are no existing properties to merge with
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
@@ -540,8 +529,6 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(Collections.emptyMap()));
|
||||
expectStoreMessage(txn, contactGroup.getId(), "foo",
|
||||
fooPropertiesDict, 1, true, true);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -560,10 +547,10 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
);
|
||||
MessageId localGroupUpdateId = new MessageId(getRandomId());
|
||||
Map<MessageId, BdfDictionary> localGroupMessageMetadata =
|
||||
Collections.singletonMap(localGroupUpdateId, oldMetadata);
|
||||
singletonMap(localGroupUpdateId, oldMetadata);
|
||||
MessageId contactGroupUpdateId = new MessageId(getRandomId());
|
||||
Map<MessageId, BdfDictionary> contactGroupMessageMetadata =
|
||||
Collections.singletonMap(contactGroupUpdateId, oldMetadata);
|
||||
singletonMap(contactGroupUpdateId, oldMetadata);
|
||||
TransportProperties oldProperties = new TransportProperties();
|
||||
oldProperties.put("fooKey1", "oldFooValue1");
|
||||
BdfDictionary oldPropertiesDict = BdfDictionary.of(
|
||||
@@ -571,9 +558,8 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
);
|
||||
BdfList oldUpdate = BdfList.of("foo", 1, oldPropertiesDict);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// Merge the new properties with the existing properties
|
||||
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||
localGroup.getId());
|
||||
@@ -601,8 +587,6 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
fooPropertiesDict, 2, true, true);
|
||||
// Delete the previous update
|
||||
oneOf(db).removeMessage(txn, contactGroupUpdateId);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
TransportPropertyManagerImpl t = createInstance();
|
||||
@@ -612,7 +596,7 @@ public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||
private Contact getContact(boolean active) {
|
||||
ContactId c = new ContactId(nextContactId++);
|
||||
return new Contact(c, getAuthor(), localAuthor.getId(),
|
||||
true, active);
|
||||
getRandomString(5), true, active);
|
||||
}
|
||||
|
||||
private void expectGetLocalProperties(Transaction txn) throws Exception {
|
||||
|
||||
@@ -11,8 +11,8 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.SyncRecordWriter;
|
||||
import org.briarproject.bramble.api.transport.StreamWriter;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.briarproject.bramble.test.ImmediateExecutor;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -45,24 +45,20 @@ public class SimplexOutgoingSessionTest extends BrambleMockTestCase {
|
||||
Transaction noAckTxn = new Transaction(null, false);
|
||||
Transaction noMsgTxn = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Add listener
|
||||
oneOf(eventBus).addListener(session);
|
||||
// No acks to send
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(noAckTxn));
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(noAckTxn));
|
||||
oneOf(db).generateAck(noAckTxn, contactId, MAX_MESSAGE_IDS);
|
||||
will(returnValue(null));
|
||||
oneOf(db).commitTransaction(noAckTxn);
|
||||
oneOf(db).endTransaction(noAckTxn);
|
||||
// No messages to send
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(noMsgTxn));
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(noMsgTxn));
|
||||
oneOf(db).generateBatch(with(noMsgTxn), with(contactId),
|
||||
with(any(int.class)), with(MAX_LATENCY));
|
||||
will(returnValue(null));
|
||||
oneOf(db).commitTransaction(noMsgTxn);
|
||||
oneOf(db).endTransaction(noMsgTxn);
|
||||
// Send the end of stream marker
|
||||
oneOf(streamWriter).sendEndOfStream();
|
||||
// Remove listener
|
||||
@@ -83,41 +79,33 @@ public class SimplexOutgoingSessionTest extends BrambleMockTestCase {
|
||||
Transaction msgTxn = new Transaction(null, false);
|
||||
Transaction noMsgTxn = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Add listener
|
||||
oneOf(eventBus).addListener(session);
|
||||
// One ack to send
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(ackTxn));
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(ackTxn));
|
||||
oneOf(db).generateAck(ackTxn, contactId, MAX_MESSAGE_IDS);
|
||||
will(returnValue(ack));
|
||||
oneOf(db).commitTransaction(ackTxn);
|
||||
oneOf(db).endTransaction(ackTxn);
|
||||
oneOf(recordWriter).writeAck(ack);
|
||||
// One message to send
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(msgTxn));
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(msgTxn));
|
||||
oneOf(db).generateBatch(with(msgTxn), with(contactId),
|
||||
with(any(int.class)), with(MAX_LATENCY));
|
||||
will(returnValue(singletonList(message)));
|
||||
oneOf(db).commitTransaction(msgTxn);
|
||||
oneOf(db).endTransaction(msgTxn);
|
||||
oneOf(recordWriter).writeMessage(message);
|
||||
// No more acks
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(noAckTxn));
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(noAckTxn));
|
||||
oneOf(db).generateAck(noAckTxn, contactId, MAX_MESSAGE_IDS);
|
||||
will(returnValue(null));
|
||||
oneOf(db).commitTransaction(noAckTxn);
|
||||
oneOf(db).endTransaction(noAckTxn);
|
||||
// No more messages
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(noMsgTxn));
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(noMsgTxn));
|
||||
oneOf(db).generateBatch(with(noMsgTxn), with(contactId),
|
||||
with(any(int.class)), with(MAX_LATENCY));
|
||||
will(returnValue(null));
|
||||
oneOf(db).commitTransaction(noMsgTxn);
|
||||
oneOf(db).endTransaction(noMsgTxn);
|
||||
// Send the end of stream marker
|
||||
oneOf(streamWriter).sendEndOfStream();
|
||||
// Remove listener
|
||||
|
||||
@@ -18,16 +18,16 @@ import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||
import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.briarproject.bramble.test.ImmediateExecutor;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static java.util.Collections.singletonList;
|
||||
@@ -83,28 +83,19 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn1 = new Transaction(null, true);
|
||||
Transaction txn2 = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// validateOutstandingMessages()
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessagesToValidate(txn);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// deliverOutstandingMessages()
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn1));
|
||||
oneOf(db).getPendingMessages(txn1);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// shareOutstandingMessages()
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn2));
|
||||
oneOf(db).getMessagesToShare(txn2);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
}});
|
||||
|
||||
vm.startService();
|
||||
@@ -121,29 +112,22 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn5 = new Transaction(null, true);
|
||||
Transaction txn6 = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Get messages to validate
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessagesToValidate(txn);
|
||||
will(returnValue(Arrays.asList(messageId, messageId1)));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
will(returnValue(asList(messageId, messageId1)));
|
||||
// Load the first raw message and group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn1));
|
||||
oneOf(db).getMessage(txn1, messageId);
|
||||
will(returnValue(message));
|
||||
oneOf(db).getGroup(txn1, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Validate the first message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResult));
|
||||
// Store the validation result for the first message
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).mergeMessageMetadata(txn2, messageId, metadata);
|
||||
// Deliver the first message
|
||||
oneOf(hook).incomingMessage(txn2, message, metadata);
|
||||
@@ -152,23 +136,17 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Get any pending dependents
|
||||
oneOf(db).getMessageDependents(txn2, messageId);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Load the second raw message and group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn3));
|
||||
oneOf(db).getMessage(txn3, messageId1);
|
||||
will(returnValue(message1));
|
||||
oneOf(db).getGroup(txn3, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
// Validate the second message: invalid
|
||||
oneOf(validator).validateMessage(message1, group);
|
||||
will(throwException(new InvalidMessageException()));
|
||||
// Store the validation result for the second message
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn4));
|
||||
oneOf(db).getMessageState(txn4, messageId1);
|
||||
will(returnValue(UNKNOWN));
|
||||
oneOf(db).setMessageState(txn4, messageId1, INVALID);
|
||||
@@ -177,22 +155,14 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Recursively invalidate any dependents
|
||||
oneOf(db).getMessageDependents(txn4, messageId1);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
// Get pending messages to deliver
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn5));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn5));
|
||||
oneOf(db).getPendingMessages(txn5);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn5);
|
||||
oneOf(db).endTransaction(txn5);
|
||||
// Get messages to share
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn6));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn6));
|
||||
oneOf(db).getMessagesToShare(txn6);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn6);
|
||||
oneOf(db).endTransaction(txn6);
|
||||
}});
|
||||
|
||||
vm.startService();
|
||||
@@ -206,24 +176,17 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn3 = new Transaction(null, false);
|
||||
Transaction txn4 = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Get messages to validate
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessagesToValidate(txn);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Get pending messages to deliver
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn1));
|
||||
oneOf(db).getPendingMessages(txn1);
|
||||
will(returnValue(singletonList(messageId)));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Check whether the message is ready to deliver
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).getMessageState(txn2, messageId);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn2, messageId);
|
||||
@@ -242,11 +205,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Get any pending dependents
|
||||
oneOf(db).getMessageDependents(txn2, messageId);
|
||||
will(returnValue(singletonMap(messageId2, PENDING)));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Check whether the dependent is ready to deliver
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn3));
|
||||
oneOf(db).getMessageState(txn3, messageId2);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn3, messageId2);
|
||||
@@ -265,16 +225,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Get any pending dependents
|
||||
oneOf(db).getMessageDependents(txn3, messageId2);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
|
||||
// Get messages to share
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn4));
|
||||
oneOf(db).getMessagesToShare(txn4);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
}});
|
||||
|
||||
vm.startService();
|
||||
@@ -288,45 +243,30 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn3 = new Transaction(null, false);
|
||||
Transaction txn4 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// No messages to validate
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessagesToValidate(txn);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// No pending messages to deliver
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn1));
|
||||
oneOf(db).getPendingMessages(txn1);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
|
||||
// Get messages to share
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn2));
|
||||
oneOf(db).getMessagesToShare(txn2);
|
||||
will(returnValue(singletonList(messageId)));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Share message and get dependencies
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn3));
|
||||
oneOf(db).setMessageShared(txn3, messageId);
|
||||
oneOf(db).getMessageDependencies(txn3, messageId);
|
||||
will(returnValue(singletonMap(messageId2, DELIVERED)));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
// Share dependency
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn4));
|
||||
oneOf(db).setMessageShared(txn4, messageId2);
|
||||
oneOf(db).getMessageDependencies(txn4, messageId2);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
}});
|
||||
|
||||
vm.startService();
|
||||
@@ -338,20 +278,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
Transaction txn2 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResultWithDependencies));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).addMessageDependencies(txn1, message,
|
||||
validResultWithDependencies.getDependencies());
|
||||
oneOf(db).getMessageDependencies(txn1, messageId);
|
||||
@@ -366,16 +302,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
will(returnValue(emptyMap()));
|
||||
// Share message
|
||||
oneOf(db).setMessageShared(txn1, messageId);
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Share dependencies
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).setMessageShared(txn2, messageId1);
|
||||
oneOf(db).getMessageDependencies(txn2, messageId1);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -391,36 +322,26 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn4 = new Transaction(null, true);
|
||||
Transaction txn5 = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Get messages to validate
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessagesToValidate(txn);
|
||||
will(returnValue(Arrays.asList(messageId, messageId1)));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
will(returnValue(asList(messageId, messageId1)));
|
||||
// Load the first raw message - *gasp* it's gone!
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn1));
|
||||
oneOf(db).getMessage(txn1, messageId);
|
||||
will(throwException(new NoSuchMessageException()));
|
||||
never(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Load the second raw message and group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn2));
|
||||
oneOf(db).getMessage(txn2, messageId1);
|
||||
will(returnValue(message1));
|
||||
oneOf(db).getGroup(txn2, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Validate the second message: invalid
|
||||
oneOf(validator).validateMessage(message1, group);
|
||||
will(throwException(new InvalidMessageException()));
|
||||
// Invalidate the second message
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn3));
|
||||
oneOf(db).getMessageState(txn3, messageId1);
|
||||
will(returnValue(UNKNOWN));
|
||||
oneOf(db).setMessageState(txn3, messageId1, INVALID);
|
||||
@@ -429,22 +350,14 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Recursively invalidate dependents
|
||||
oneOf(db).getMessageDependents(txn3, messageId1);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
// Get pending messages to deliver
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn4));
|
||||
oneOf(db).getPendingMessages(txn4);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
// Get messages to share
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn5));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn5));
|
||||
oneOf(db).getMessagesToShare(txn5);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn5);
|
||||
oneOf(db).endTransaction(txn5);
|
||||
}});
|
||||
|
||||
vm.startService();
|
||||
@@ -460,39 +373,29 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn4 = new Transaction(null, true);
|
||||
Transaction txn5 = new Transaction(null, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Get messages to validate
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getMessagesToValidate(txn);
|
||||
will(returnValue(Arrays.asList(messageId, messageId1)));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
will(returnValue(asList(messageId, messageId1)));
|
||||
// Load the first raw message
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn1));
|
||||
oneOf(db).getMessage(txn1, messageId);
|
||||
will(returnValue(message));
|
||||
// Load the group - *gasp* it's gone!
|
||||
oneOf(db).getGroup(txn1, groupId);
|
||||
will(throwException(new NoSuchGroupException()));
|
||||
never(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Load the second raw message and group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn2));
|
||||
oneOf(db).getMessage(txn2, messageId1);
|
||||
will(returnValue(message1));
|
||||
oneOf(db).getGroup(txn2, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Validate the second message: invalid
|
||||
oneOf(validator).validateMessage(message1, group);
|
||||
will(throwException(new InvalidMessageException()));
|
||||
// Store the validation result for the second message
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn3));
|
||||
oneOf(db).getMessageState(txn3, messageId1);
|
||||
will(returnValue(UNKNOWN));
|
||||
oneOf(db).setMessageState(txn3, messageId1, INVALID);
|
||||
@@ -501,22 +404,14 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Recursively invalidate dependents
|
||||
oneOf(db).getMessageDependents(txn3, messageId1);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
// Get pending messages to deliver
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn4));
|
||||
oneOf(db).getPendingMessages(txn4);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
// Get messages to share
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn5));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn5));
|
||||
oneOf(db).getMessagesToShare(txn5);
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).commitTransaction(txn5);
|
||||
oneOf(db).endTransaction(txn5);
|
||||
}});
|
||||
|
||||
vm.startService();
|
||||
@@ -527,20 +422,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResult));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).mergeMessageMetadata(txn1, messageId, metadata);
|
||||
// Deliver the message
|
||||
oneOf(hook).incomingMessage(txn1, message, metadata);
|
||||
@@ -549,8 +440,6 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Get any pending dependents
|
||||
oneOf(db).getMessageDependents(txn1, messageId);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -567,28 +456,22 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResultWithDependencies));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).addMessageDependencies(txn1, message,
|
||||
validResultWithDependencies.getDependencies());
|
||||
oneOf(db).getMessageDependencies(txn1, messageId);
|
||||
will(returnValue(singletonMap(messageId1, UNKNOWN)));
|
||||
oneOf(db).mergeMessageMetadata(txn1, messageId, metadata);
|
||||
oneOf(db).setMessageState(txn1, messageId, PENDING);
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -600,20 +483,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResultWithDependencies));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).addMessageDependencies(txn1, message,
|
||||
validResultWithDependencies.getDependencies());
|
||||
oneOf(db).getMessageDependencies(txn1, messageId);
|
||||
@@ -626,8 +505,6 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Get any pending dependents
|
||||
oneOf(db).getMessageDependents(txn1, messageId);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -640,20 +517,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
Transaction txn2 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResultWithDependencies));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).addMessageDependencies(txn1, message,
|
||||
validResultWithDependencies.getDependencies());
|
||||
// Check for invalid dependencies
|
||||
@@ -668,11 +541,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Recursively invalidate dependents
|
||||
oneOf(db).getMessageDependents(txn1, messageId);
|
||||
will(returnValue(singletonMap(messageId2, UNKNOWN)));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Invalidate dependent in a new transaction
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).getMessageState(txn2, messageId2);
|
||||
will(returnValue(UNKNOWN));
|
||||
oneOf(db).setMessageState(txn2, messageId2, INVALID);
|
||||
@@ -680,8 +550,6 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(db).deleteMessageMetadata(txn2, messageId2);
|
||||
oneOf(db).getMessageDependents(txn2, messageId2);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -702,20 +570,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn5 = new Transaction(null, false);
|
||||
Transaction txn6 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: invalid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(throwException(new InvalidMessageException()));
|
||||
// Invalidate the message
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).getMessageState(txn1, messageId);
|
||||
will(returnValue(UNKNOWN));
|
||||
oneOf(db).setMessageState(txn1, messageId, INVALID);
|
||||
@@ -724,11 +588,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// The message has two dependents: 1 and 2
|
||||
oneOf(db).getMessageDependents(txn1, messageId);
|
||||
will(returnValue(twoDependents));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Invalidate message 1
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).getMessageState(txn2, messageId1);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).setMessageState(txn2, messageId1, INVALID);
|
||||
@@ -737,11 +598,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 1 has one dependent: 3
|
||||
oneOf(db).getMessageDependents(txn2, messageId1);
|
||||
will(returnValue(singletonMap(messageId3, PENDING)));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Invalidate message 2
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn3));
|
||||
oneOf(db).getMessageState(txn3, messageId2);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).setMessageState(txn3, messageId2, INVALID);
|
||||
@@ -750,11 +608,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 2 has one dependent: 3 (same dependent as 1)
|
||||
oneOf(db).getMessageDependents(txn3, messageId2);
|
||||
will(returnValue(singletonMap(messageId3, PENDING)));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
// Invalidate message 3 (via 1)
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn4));
|
||||
oneOf(db).getMessageState(txn4, messageId3);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).setMessageState(txn4, messageId3, INVALID);
|
||||
@@ -763,18 +618,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 3 has one dependent: 4
|
||||
oneOf(db).getMessageDependents(txn4, messageId3);
|
||||
will(returnValue(singletonMap(messageId4, PENDING)));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
// Invalidate message 3 (again, via 2)
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn5));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn5));
|
||||
oneOf(db).getMessageState(txn5, messageId3);
|
||||
will(returnValue(INVALID)); // Already invalidated
|
||||
oneOf(db).commitTransaction(txn5);
|
||||
oneOf(db).endTransaction(txn5);
|
||||
// Invalidate message 4 (via 1 and 3)
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn6));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn6));
|
||||
oneOf(db).getMessageState(txn6, messageId4);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).setMessageState(txn6, messageId4, INVALID);
|
||||
@@ -783,8 +632,6 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 4 has no dependents
|
||||
oneOf(db).getMessageDependents(txn6, messageId4);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn6);
|
||||
oneOf(db).endTransaction(txn6);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -810,20 +657,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn5 = new Transaction(null, false);
|
||||
Transaction txn6 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResult));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).mergeMessageMetadata(txn1, messageId, metadata);
|
||||
// Deliver the message
|
||||
oneOf(hook).incomingMessage(txn1, message, metadata);
|
||||
@@ -832,11 +675,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// The message has two pending dependents: 1 and 2
|
||||
oneOf(db).getMessageDependents(txn1, messageId);
|
||||
will(returnValue(twoDependents));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Check whether message 1 is ready to be delivered
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).getMessageState(txn2, messageId1);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn2, messageId1);
|
||||
@@ -855,11 +695,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 1 has one pending dependent: 3
|
||||
oneOf(db).getMessageDependents(txn2, messageId1);
|
||||
will(returnValue(singletonMap(messageId3, PENDING)));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
// Check whether message 2 is ready to be delivered
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn3));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn3));
|
||||
oneOf(db).getMessageState(txn3, messageId2);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn3, messageId2);
|
||||
@@ -878,11 +715,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 2 has one pending dependent: 3 (same dependent as 1)
|
||||
oneOf(db).getMessageDependents(txn3, messageId2);
|
||||
will(returnValue(singletonMap(messageId3, PENDING)));
|
||||
oneOf(db).commitTransaction(txn3);
|
||||
oneOf(db).endTransaction(txn3);
|
||||
// Check whether message 3 is ready to be delivered (via 1)
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn4));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn4));
|
||||
oneOf(db).getMessageState(txn4, messageId3);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn4, messageId3);
|
||||
@@ -900,18 +734,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 3 has one pending dependent: 4
|
||||
oneOf(db).getMessageDependents(txn4, messageId3);
|
||||
will(returnValue(singletonMap(messageId4, PENDING)));
|
||||
oneOf(db).commitTransaction(txn4);
|
||||
oneOf(db).endTransaction(txn4);
|
||||
// Check whether message 3 is ready to be delivered (again, via 2)
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn5));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn5));
|
||||
oneOf(db).getMessageState(txn5, messageId3);
|
||||
will(returnValue(DELIVERED)); // Already delivered
|
||||
oneOf(db).commitTransaction(txn5);
|
||||
oneOf(db).endTransaction(txn5);
|
||||
// Check whether message 4 is ready to be delivered (via 1 and 3)
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn6));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn6));
|
||||
oneOf(db).getMessageState(txn6, messageId4);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn6, messageId4);
|
||||
@@ -930,8 +758,6 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Message 4 has no pending dependents
|
||||
oneOf(db).getMessageDependents(txn6, messageId4);
|
||||
will(returnValue(emptyMap()));
|
||||
oneOf(db).commitTransaction(txn6);
|
||||
oneOf(db).endTransaction(txn6);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
@@ -946,20 +772,16 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
Transaction txn2 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Load the group
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
oneOf(db).getGroup(txn, groupId);
|
||||
will(returnValue(group));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
// Validate the message: valid
|
||||
oneOf(validator).validateMessage(message, group);
|
||||
will(returnValue(validResult));
|
||||
// Store the validation result
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
oneOf(db).mergeMessageMetadata(txn1, messageId, metadata);
|
||||
// Deliver the message
|
||||
oneOf(hook).incomingMessage(txn1, message, metadata);
|
||||
@@ -968,17 +790,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
||||
// Get any pending dependents
|
||||
oneOf(db).getMessageDependents(txn1, messageId);
|
||||
will(returnValue(singletonMap(messageId1, PENDING)));
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
// Check whether the pending dependent is ready to be delivered
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn2));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn2));
|
||||
oneOf(db).getMessageState(txn2, messageId1);
|
||||
will(returnValue(PENDING));
|
||||
oneOf(db).getMessageDependencies(txn2, messageId1);
|
||||
will(returnValue(twoDependencies));
|
||||
oneOf(db).commitTransaction(txn2);
|
||||
oneOf(db).endTransaction(txn2);
|
||||
}});
|
||||
|
||||
vm.eventOccurred(new MessageAddedEvent(message, contactId));
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.briarproject.bramble.test;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbCallable;
|
||||
import org.briarproject.bramble.api.db.DbRunnable;
|
||||
import org.briarproject.bramble.api.db.NullableDbCallable;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.jmock.Expectations;
|
||||
|
||||
public class DbExpectations extends Expectations {
|
||||
|
||||
protected <E extends Exception> DbRunnable<E> withDbRunnable(
|
||||
Transaction txn) {
|
||||
addParameterMatcher(any(DbRunnable.class));
|
||||
currentBuilder().setAction(new RunTransactionAction(txn));
|
||||
return null;
|
||||
}
|
||||
|
||||
protected <R, E extends Exception> DbCallable<R, E> withDbCallable(
|
||||
Transaction txn) {
|
||||
addParameterMatcher(any(DbCallable.class));
|
||||
currentBuilder().setAction(new RunTransactionWithResultAction(txn));
|
||||
return null;
|
||||
}
|
||||
|
||||
protected <R, E extends Exception> NullableDbCallable<R, E> withNullableDbCallable(
|
||||
Transaction txn) {
|
||||
addParameterMatcher(any(NullableDbCallable.class));
|
||||
currentBuilder().setAction(
|
||||
new RunTransactionWithNullableResultAction(txn));
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.briarproject.bramble.test;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbRunnable;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.hamcrest.Description;
|
||||
import org.jmock.api.Action;
|
||||
import org.jmock.api.Invocation;
|
||||
|
||||
public class RunTransactionAction implements Action {
|
||||
|
||||
private final Transaction txn;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public RunTransactionAction(Transaction txn) {
|
||||
this.txn = txn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
DbRunnable task = (DbRunnable) invocation.getParameter(1);
|
||||
task.run(txn);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("runs a task inside a database transaction");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.briarproject.bramble.test;
|
||||
|
||||
import org.briarproject.bramble.api.db.NullableDbCallable;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.hamcrest.Description;
|
||||
import org.jmock.api.Action;
|
||||
import org.jmock.api.Invocation;
|
||||
|
||||
public class RunTransactionWithNullableResultAction implements Action {
|
||||
|
||||
private final Transaction txn;
|
||||
|
||||
public RunTransactionWithNullableResultAction(Transaction txn) {
|
||||
this.txn = txn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
NullableDbCallable task =
|
||||
(NullableDbCallable) invocation.getParameter(1);
|
||||
return task.call(txn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("runs a task inside a database transaction");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.briarproject.bramble.test;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbCallable;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.hamcrest.Description;
|
||||
import org.jmock.api.Action;
|
||||
import org.jmock.api.Invocation;
|
||||
|
||||
public class RunTransactionWithResultAction implements Action {
|
||||
|
||||
private final Transaction txn;
|
||||
|
||||
public RunTransactionWithResultAction(Transaction txn) {
|
||||
this.txn = txn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
DbCallable task = (DbCallable) invocation.getParameter(1);
|
||||
return task.call(txn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("runs a task inside a database transaction");
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.bramble.api.transport.KeySetId;
|
||||
import org.briarproject.bramble.api.transport.StreamContext;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.jmock.lib.concurrent.DeterministicExecutor;
|
||||
import org.junit.Before;
|
||||
@@ -33,7 +34,9 @@ import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
@@ -66,17 +69,17 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
Author remoteAuthor = getAuthor();
|
||||
AuthorId localAuthorId = new AuthorId(getRandomId());
|
||||
Collection<Contact> contacts = new ArrayList<>();
|
||||
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true,
|
||||
true));
|
||||
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId,
|
||||
getRandomString(5), true, true));
|
||||
contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId,
|
||||
true, false));
|
||||
getRandomString(5), true, false));
|
||||
SimplexPluginFactory pluginFactory =
|
||||
context.mock(SimplexPluginFactory.class);
|
||||
Collection<SimplexPluginFactory> factories =
|
||||
singletonList(pluginFactory);
|
||||
int maxLatency = 1337;
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(pluginConfig).getSimplexFactories();
|
||||
will(returnValue(factories));
|
||||
oneOf(pluginFactory).getId();
|
||||
@@ -88,13 +91,10 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
.createTransportKeyManager(transportId, maxLatency);
|
||||
will(returnValue(transportKeyManager));
|
||||
oneOf(pluginConfig).getDuplexFactories();
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
oneOf(transportKeyManager).start(txn);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
keyManager.startService();
|
||||
@@ -120,25 +120,21 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
@Test
|
||||
public void testGetStreamContextForInactiveContact() throws Exception {
|
||||
assertEquals(null,
|
||||
keyManager.getStreamContext(inactiveContactId, transportId));
|
||||
assertNull(keyManager.getStreamContext(inactiveContactId, transportId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStreamContextForUnknownTransport() throws Exception {
|
||||
assertEquals(null,
|
||||
keyManager.getStreamContext(contactId, unknownTransportId));
|
||||
assertNull(keyManager.getStreamContext(contactId, unknownTransportId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStreamContextForContact() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(txn));
|
||||
oneOf(transportKeyManager).getStreamContext(txn, contactId);
|
||||
will(returnValue(streamContext));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(streamContext,
|
||||
@@ -148,19 +144,16 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
@Test
|
||||
public void testGetStreamContextForTagAndUnknownTransport()
|
||||
throws Exception {
|
||||
assertEquals(null,
|
||||
keyManager.getStreamContext(unknownTransportId, tag));
|
||||
assertNull(keyManager.getStreamContext(unknownTransportId, tag));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStreamContextForTag() throws Exception {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(txn));
|
||||
oneOf(transportKeyManager).getStreamContext(txn, tag);
|
||||
will(returnValue(streamContext));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(streamContext,
|
||||
@@ -177,7 +170,7 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
keyManager.eventOccurred(event);
|
||||
executor.runUntilIdle();
|
||||
assertEquals(null, keyManager.getStreamContext(contactId, transportId));
|
||||
assertNull(keyManager.getStreamContext(contactId, transportId));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -185,13 +178,11 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
|
||||
ContactStatusChangedEvent event =
|
||||
new ContactStatusChangedEvent(inactiveContactId, true);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithNullableResult(with(false),
|
||||
withNullableDbCallable(txn));
|
||||
oneOf(transportKeyManager).getStreamContext(txn, inactiveContactId);
|
||||
will(returnValue(streamContext));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
keyManager.eventOccurred(event);
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||
import org.briarproject.bramble.api.transport.StreamContext;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.briarproject.bramble.test.RunAction;
|
||||
import org.briarproject.bramble.test.TestUtils;
|
||||
import org.hamcrest.Description;
|
||||
@@ -318,7 +319,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
Transaction txn1 = new Transaction(null, false);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
context.checking(new DbExpectations() {{
|
||||
// Get the current time (the start of rotation period 1000)
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(rotationPeriodLength * 1000));
|
||||
@@ -342,8 +343,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(dbExecutor).execute(with(any(Runnable.class)));
|
||||
will(new RunAction());
|
||||
// Start a transaction for key rotation
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn1));
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn1));
|
||||
// Get the current time (the start of rotation period 1001)
|
||||
oneOf(clock).currentTimeMillis();
|
||||
will(returnValue(rotationPeriodLength * 1001));
|
||||
@@ -364,9 +364,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
// Schedule key rotation at the start of the next rotation period
|
||||
oneOf(scheduler).schedule(with(any(Runnable.class)),
|
||||
with(rotationPeriodLength), with(MILLISECONDS));
|
||||
// Commit the key rotation transaction
|
||||
oneOf(db).commitTransaction(txn1);
|
||||
oneOf(db).endTransaction(txn1);
|
||||
}});
|
||||
|
||||
TransportKeyManager transportKeyManager = new TransportKeyManagerImpl(
|
||||
@@ -539,7 +536,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Invocation invocation) throws Throwable {
|
||||
public Object invoke(Invocation invocation) {
|
||||
byte[] tag = (byte[]) invocation.getParameter(0);
|
||||
random.nextBytes(tag);
|
||||
if (tags != null) tags.add(tag);
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
|
||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||
import org.briarproject.bramble.test.DbExpectations;
|
||||
import org.jmock.Expectations;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -38,6 +39,7 @@ import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
||||
import static org.briarproject.bramble.test.TestUtils.getMessage;
|
||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.briarproject.bramble.versioning.ClientVersioningConstants.GROUP_KEY_CONTACT_ID;
|
||||
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_LOCAL;
|
||||
import static org.briarproject.bramble.versioning.ClientVersioningConstants.MSG_KEY_UPDATE_VERSION;
|
||||
@@ -56,12 +58,13 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
private final Group localGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
private final Group contactGroup = getGroup(CLIENT_ID, MAJOR_VERSION);
|
||||
private final Contact contact = new Contact(new ContactId(123),
|
||||
getAuthor(), getLocalAuthor().getId(), true, true);
|
||||
getAuthor(), getLocalAuthor().getId(), getRandomString(5), true,
|
||||
true);
|
||||
private final ClientId clientId = getClientId();
|
||||
private final long now = System.currentTimeMillis();
|
||||
private final Transaction txn = new Transaction(null, false);
|
||||
|
||||
private ClientVersioningManagerImpl createInstance() throws Exception {
|
||||
private ClientVersioningManagerImpl createInstance() {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID,
|
||||
MAJOR_VERSION);
|
||||
@@ -160,9 +163,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
BdfList localUpdateBody = BdfList.of(BdfList.of(
|
||||
BdfList.of(clientId.getString(), 123, 234, false)), 1L);
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// No client versions have been stored yet
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(emptyList()));
|
||||
@@ -188,8 +190,6 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(clientHelper).getMessageAsList(txn, localUpdateId);
|
||||
will(returnValue(localUpdateBody));
|
||||
// Latest local update is up-to-date, no visibilities have changed
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
@@ -204,17 +204,14 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
BdfList localVersionsBody =
|
||||
BdfList.of(BdfList.of(clientId.getString(), 123, 234));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// Load the old client versions
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(singletonList(localVersionsId)));
|
||||
oneOf(clientHelper).getMessageAsList(txn, localVersionsId);
|
||||
will(returnValue(localVersionsBody));
|
||||
// Client versions are up-to-date
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
@@ -249,9 +246,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// Load the old client versions
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(singletonList(oldLocalVersionsId)));
|
||||
@@ -293,8 +289,6 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
oneOf(clientHelper).addLocalMessage(txn, newLocalUpdate,
|
||||
newLocalUpdateMeta, true);
|
||||
// No visibilities have changed
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
@@ -348,9 +342,8 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
new BdfEntry(MSG_KEY_UPDATE_VERSION, 2L),
|
||||
new BdfEntry(MSG_KEY_LOCAL, true));
|
||||
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(txn));
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
// Load the old client versions
|
||||
oneOf(db).getMessageIds(txn, localGroup.getId());
|
||||
will(returnValue(singletonList(oldLocalVersionsId)));
|
||||
@@ -395,8 +388,6 @@ public class ClientVersioningManagerImplTest extends BrambleMockTestCase {
|
||||
newLocalUpdateMeta, true);
|
||||
// The client's visibility has changed
|
||||
oneOf(hook).onClientVisibilityChanging(txn, contact, visibility);
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
ClientVersioningManagerImpl c = createInstance();
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
||||
'com.google.dagger:dagger-compiler:2.19:dagger-compiler-2.19.jar:27a4b202a2de908182edb261f8c0a264e08e5e4733d7514bc7fbf0d31da5c0fc',
|
||||
'com.google.dagger:dagger-producers:2.19:dagger-producers-2.19.jar:a17663abe0fc38b676026950907d4c5f5e2bf338375415861eaff6e3bdb0b768',
|
||||
'com.google.dagger:dagger-spi:2.19:dagger-spi-2.19.jar:e7a6379d82c841f6aac2866948ad1eed716528707814602842a8d844ce04e2e1',
|
||||
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
|
||||
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
|
||||
'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:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9',
|
||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
||||
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
|
||||
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
||||
@@ -15,7 +23,9 @@ dependencyVerification {
|
||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
||||
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
|
||||
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
||||
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
|
||||
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
||||
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
|
||||
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
|
||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||
|
||||
@@ -2,10 +2,10 @@ apply plugin: 'java-library'
|
||||
sourceCompatibility = 1.8
|
||||
targetCompatibility = 1.8
|
||||
|
||||
apply plugin: 'net.ltgt.apt'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
apply from: '../dagger.gradle'
|
||||
|
||||
configurations {
|
||||
tor
|
||||
@@ -17,8 +17,9 @@ dependencies {
|
||||
implementation 'net.java.dev.jna:jna:4.5.2'
|
||||
implementation 'net.java.dev.jna:jna-platform:4.5.2'
|
||||
tor 'org.briarproject:tor:0.3.4.8@zip'
|
||||
tor 'org.briarproject:obfs4proxy:0.0.7@zip'
|
||||
|
||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||
@@ -26,19 +27,35 @@ dependencies {
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4: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"
|
||||
|
||||
testApt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
}
|
||||
|
||||
project.afterEvaluate {
|
||||
copy {
|
||||
from configurations.tor.collect { zipTree(it) }
|
||||
into 'src/main/resources'
|
||||
def torBinariesDir = 'src/main/resources'
|
||||
|
||||
task cleanTorBinaries {
|
||||
doLast {
|
||||
delete fileTree(torBinariesDir) { include '*.zip' }
|
||||
}
|
||||
}
|
||||
|
||||
clean.dependsOn cleanTorBinaries
|
||||
|
||||
task unpackTorBinaries {
|
||||
doLast {
|
||||
copy {
|
||||
from configurations.tor.collect { zipTree(it) }
|
||||
into torBinariesDir
|
||||
}
|
||||
}
|
||||
dependsOn cleanTorBinaries
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.dir torBinariesDir
|
||||
dependsOn unpackTorBinaries
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
systemProperty 'java.library.path', 'libs'
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package org.briarproject.bramble.network;
|
||||
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.Service;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.network.NetworkStatus;
|
||||
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
|
||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||
|
||||
@@ -23,25 +20,13 @@ import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
class JavaNetworkManager implements NetworkManager, Service {
|
||||
class JavaNetworkManager implements NetworkManager {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(JavaNetworkManager.class.getName());
|
||||
|
||||
private final EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
JavaNetworkManager(EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startService() {
|
||||
eventBus.broadcast(new NetworkStatusEvent(getNetworkStatus()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopService() {
|
||||
JavaNetworkManager() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.bramble.network;
|
||||
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
@@ -13,9 +12,7 @@ public class JavaNetworkModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
|
||||
JavaNetworkManager networkManager) {
|
||||
lifecycleManager.registerService(networkManager);
|
||||
NetworkManager provideNetworkManager(JavaNetworkManager networkManager) {
|
||||
return networkManager;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,12 @@ class JavaBluetoothPlugin extends BluetoothPlugin<StreamConnectionNotifier> {
|
||||
return wrapSocket((StreamConnection) Connector.open(url));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
DuplexTransportConnection discoverAndConnect(String uuid) {
|
||||
return null; // TODO
|
||||
}
|
||||
|
||||
private String makeUrl(String address, String uuid) {
|
||||
return "btspp://" + address + ":" + uuid + ";name=RFCOMM";
|
||||
}
|
||||
|
||||
@@ -10,6 +10,10 @@ import org.briarproject.bramble.api.system.Clock;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
@@ -22,6 +26,7 @@ import javax.annotation.Nullable;
|
||||
import jssc.SerialPortEvent;
|
||||
import jssc.SerialPortEventListener;
|
||||
|
||||
import static java.nio.charset.CodingErrorAction.IGNORE;
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
@@ -35,6 +40,8 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ModemImpl.class.getName());
|
||||
|
||||
private static final Charset US_ASCII = Charset.forName("US-ASCII");
|
||||
private static final int MAX_LINE_LENGTH = 256;
|
||||
private static final int[] BAUD_RATES = {
|
||||
256000, 128000, 115200, 57600, 38400, 19200, 14400, 9600, 4800, 1200
|
||||
@@ -106,7 +113,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
throw e;
|
||||
}
|
||||
// Wait for the event thread to receive "OK"
|
||||
boolean success = false;
|
||||
boolean success;
|
||||
try {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -353,8 +360,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
for (int i = 0; i < b.length; i++) {
|
||||
line[lineLen] = b[i];
|
||||
if (b[i] == '\n') {
|
||||
// FIXME: Use CharsetDecoder to catch invalid ASCII
|
||||
String s = new String(line, 0, lineLen, "US-ASCII").trim();
|
||||
String s = toAscii(line, lineLen).trim();
|
||||
lineLen = 0;
|
||||
if (LOG.isLoggable(INFO)) LOG.info("Modem status: " + s);
|
||||
if (s.startsWith("CONNECT")) {
|
||||
@@ -436,7 +442,7 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
throw e;
|
||||
}
|
||||
// Wait for the event thread to receive "CONNECT"
|
||||
boolean success = false;
|
||||
boolean success;
|
||||
try {
|
||||
lock.lock();
|
||||
try {
|
||||
@@ -461,4 +467,16 @@ class ModemImpl implements Modem, WriteHandler, SerialPortEventListener {
|
||||
stateChange.release();
|
||||
}
|
||||
}
|
||||
|
||||
private String toAscii(byte[] bytes, int len) {
|
||||
CharsetDecoder decoder = US_ASCII.newDecoder();
|
||||
decoder.onMalformedInput(IGNORE);
|
||||
decoder.onUnmappableCharacter(IGNORE);
|
||||
ByteBuffer buffer = ByteBuffer.wrap(bytes, 0, len);
|
||||
try {
|
||||
return decoder.decode(buffer).toString();
|
||||
} catch (CharacterCodingException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.plugin.tor;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.Backoff;
|
||||
@@ -23,12 +24,14 @@ class LinuxTorPlugin extends TorPlugin {
|
||||
LinuxTorPlugin(Executor ioExecutor, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||
Clock clock, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Backoff backoff,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime, File torDirectory) {
|
||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||
clock, resourceProvider, circumventionProvider, backoff,
|
||||
callback, architecture, maxLatency, maxIdleTime, torDirectory);
|
||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||
backoff, callback, architecture, maxLatency, maxIdleTime,
|
||||
torDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.plugin.tor;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
@@ -44,6 +45,7 @@ public class LinuxTorPluginFactory implements DuplexPluginFactory {
|
||||
private final BackoffFactory backoffFactory;
|
||||
private final ResourceProvider resourceProvider;
|
||||
private final CircumventionProvider circumventionProvider;
|
||||
private final BatteryManager batteryManager;
|
||||
private final Clock clock;
|
||||
private final File torDirectory;
|
||||
|
||||
@@ -51,8 +53,8 @@ public class LinuxTorPluginFactory implements DuplexPluginFactory {
|
||||
NetworkManager networkManager, LocationUtils locationUtils,
|
||||
EventBus eventBus, SocketFactory torSocketFactory,
|
||||
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock,
|
||||
File torDirectory) {
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Clock clock, File torDirectory) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.networkManager = networkManager;
|
||||
this.locationUtils = locationUtils;
|
||||
@@ -61,6 +63,7 @@ public class LinuxTorPluginFactory implements DuplexPluginFactory {
|
||||
this.backoffFactory = backoffFactory;
|
||||
this.resourceProvider = resourceProvider;
|
||||
this.circumventionProvider = circumventionProvider;
|
||||
this.batteryManager = batteryManager;
|
||||
this.clock = clock;
|
||||
this.torDirectory = torDirectory;
|
||||
}
|
||||
@@ -92,11 +95,10 @@ public class LinuxTorPluginFactory implements DuplexPluginFactory {
|
||||
|
||||
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||
LinuxTorPlugin plugin =
|
||||
new LinuxTorPlugin(ioExecutor, networkManager, locationUtils,
|
||||
torSocketFactory, clock, resourceProvider,
|
||||
circumventionProvider, backoff, callback, architecture,
|
||||
MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
|
||||
LinuxTorPlugin plugin = new LinuxTorPlugin(ioExecutor, networkManager,
|
||||
locationUtils, torSocketFactory, clock, resourceProvider,
|
||||
circumventionProvider, batteryManager, backoff, callback,
|
||||
architecture, MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
|
||||
eventBus.addListener(plugin);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.briarproject.bramble.plugin.tor;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||
@@ -58,6 +59,8 @@ public class BridgeTest extends BrambleTestCase {
|
||||
@Inject
|
||||
CircumventionProvider circumventionProvider;
|
||||
@Inject
|
||||
BatteryManager batteryManager;
|
||||
@Inject
|
||||
EventBus eventBus;
|
||||
@Inject
|
||||
BackoffFactory backoffFactory;
|
||||
@@ -107,7 +110,8 @@ public class BridgeTest extends BrambleTestCase {
|
||||
};
|
||||
factory = new LinuxTorPluginFactory(ioExecutor, networkManager,
|
||||
locationUtils, eventBus, torSocketFactory, backoffFactory,
|
||||
resourceProvider, bridgeProvider, clock, torDir);
|
||||
resourceProvider, bridgeProvider, batteryManager, clock,
|
||||
torDir);
|
||||
}
|
||||
|
||||
@After
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.bramble.test;
|
||||
|
||||
import org.briarproject.bramble.BrambleJavaModule;
|
||||
import org.briarproject.bramble.battery.DefaultBatteryManagerModule;
|
||||
import org.briarproject.bramble.event.EventModule;
|
||||
import org.briarproject.bramble.plugin.PluginModule;
|
||||
import org.briarproject.bramble.plugin.tor.BridgeTest;
|
||||
@@ -15,6 +16,7 @@ import dagger.Component;
|
||||
@Component(modules = {
|
||||
BrambleJavaModule.class,
|
||||
TestLifecycleModule.class,
|
||||
DefaultBatteryManagerModule.class,
|
||||
PluginModule.class, // needed for BackoffFactory
|
||||
EventModule.class,
|
||||
SystemModule.class,
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
dependencyVerification {
|
||||
verify = [
|
||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
||||
'com.google.dagger:dagger-compiler:2.19:dagger-compiler-2.19.jar:27a4b202a2de908182edb261f8c0a264e08e5e4733d7514bc7fbf0d31da5c0fc',
|
||||
'com.google.dagger:dagger-producers:2.19:dagger-producers-2.19.jar:a17663abe0fc38b676026950907d4c5f5e2bf338375415861eaff6e3bdb0b768',
|
||||
'com.google.dagger:dagger-spi:2.19:dagger-spi-2.19.jar:e7a6379d82c841f6aac2866948ad1eed716528707814602842a8d844ce04e2e1',
|
||||
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
|
||||
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
|
||||
'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:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9',
|
||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
||||
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
|
||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||
'net.java.dev.jna:jna-platform:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6',
|
||||
@@ -12,7 +20,10 @@ dependencyVerification {
|
||||
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||
'org.briarproject:obfs4proxy:0.0.7:obfs4proxy-0.0.7.zip:5b2f693262ce43a7e130f7cc7d5d1617925330640a2eb6d71085e95df8ee0642',
|
||||
'org.briarproject:tor:0.3.4.8:tor-0.3.4.8.zip:bc0158c34002f471a4fe14a6a481816c918eb520a220bb027f64be902beb757f',
|
||||
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
|
||||
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
||||
'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.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||
|
||||
@@ -22,8 +22,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 26
|
||||
versionCode 10103
|
||||
versionName "1.1.3"
|
||||
versionCode 10105
|
||||
versionName "1.1.5"
|
||||
applicationId "org.briarproject.briar.android"
|
||||
buildConfigField "String", "GitHash",
|
||||
"\"${getStdout(['git', 'rev-parse', '--short=7', 'HEAD'], 'No commit hash')}\""
|
||||
@@ -105,6 +105,7 @@ dependencies {
|
||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||
implementation "com.android.support:support-annotations:$supportVersion"
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
implementation "android.arch.lifecycle:extensions:1.1.1"
|
||||
|
||||
implementation('ch.acra:acra:4.11') {
|
||||
exclude module: 'support-v4'
|
||||
@@ -117,27 +118,25 @@ dependencies {
|
||||
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.12.4'
|
||||
implementation 'com.vanniktech:emoji-google:0.5.1'
|
||||
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||
testImplementation 'org.robolectric:robolectric:3.8'
|
||||
testImplementation 'org.robolectric:robolectric:4.0.1'
|
||||
testImplementation 'org.robolectric:shadows-support-v4:3.3.2'
|
||||
testImplementation 'org.mockito:mockito-core:2.13.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4: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 espressoVersion = '3.0.2'
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-core:$espressoVersion"
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-contrib:$espressoVersion"
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-intents:$espressoVersion"
|
||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.0.2"
|
||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.19"
|
||||
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
androidTestScreenshotImplementation "tools.fastlane:screengrab:1.2.0"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
@@ -101,7 +102,7 @@
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.contact.ConversationActivity"
|
||||
android:name="org.briarproject.briar.android.conversation.ConversationActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/BriarTheme.NoActionBar"
|
||||
android:parentActivityName="org.briarproject.briar.android.navdrawer.NavDrawerActivity"
|
||||
@@ -189,10 +190,10 @@
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.sharing.BlogInvitationActivity"
|
||||
android:label="@string/blogs_sharing_invitations_title"
|
||||
android:parentActivityName="org.briarproject.briar.android.contact.ConversationActivity">
|
||||
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.briarproject.briar.android.contact.ConversationActivity"
|
||||
android:value="org.briarproject.briar.android.conversation.ConversationActivity"
|
||||
/>
|
||||
</activity>
|
||||
|
||||
@@ -326,11 +327,11 @@
|
||||
<activity
|
||||
android:name="org.briarproject.briar.android.introduction.IntroductionActivity"
|
||||
android:label="@string/introduction_activity_title"
|
||||
android:parentActivityName="org.briarproject.briar.android.contact.ConversationActivity"
|
||||
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.briarproject.briar.android.contact.ConversationActivity"
|
||||
android:value="org.briarproject.briar.android.conversation.ConversationActivity"
|
||||
/>
|
||||
</activity>
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.arch.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.briarproject.bramble.BrambleAndroidModule;
|
||||
import org.briarproject.bramble.BrambleCoreEagerSingletons;
|
||||
import org.briarproject.bramble.BrambleCoreModule;
|
||||
@@ -41,7 +43,7 @@ import org.briarproject.briar.api.feed.FeedManager;
|
||||
import org.briarproject.briar.api.forum.ForumManager;
|
||||
import org.briarproject.briar.api.forum.ForumSharingManager;
|
||||
import org.briarproject.briar.api.introduction.IntroductionManager;
|
||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.api.privategroup.GroupMessageFactory;
|
||||
@@ -154,6 +156,8 @@ public interface AndroidComponent
|
||||
|
||||
CircumventionProvider circumventionProvider();
|
||||
|
||||
ViewModelProvider.Factory viewModelFactory();
|
||||
|
||||
void inject(SignInReminderReceiver briarService);
|
||||
|
||||
void inject(BriarService briarService);
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.contact.ConversationActivity;
|
||||
import org.briarproject.briar.android.conversation.ConversationActivity;
|
||||
import org.briarproject.briar.android.forum.ForumActivity;
|
||||
import org.briarproject.briar.android.login.SignInReminderReceiver;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
@@ -40,9 +40,9 @@ import org.briarproject.briar.android.splash.SplashScreenActivity;
|
||||
import org.briarproject.briar.android.util.BriarNotificationBuilder;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.blog.event.BlogPostAddedEvent;
|
||||
import org.briarproject.briar.api.conversation.event.ConversationMessageReceivedEvent;
|
||||
import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent;
|
||||
import org.briarproject.briar.api.introduction.event.IntroductionSucceededEvent;
|
||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||
import org.briarproject.briar.api.privategroup.event.GroupMessageAddedEvent;
|
||||
|
||||
import java.util.Set;
|
||||
@@ -72,7 +72,7 @@ import static android.support.v4.app.NotificationCompat.PRIORITY_MIN;
|
||||
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
|
||||
import static android.support.v4.content.ContextCompat.getColor;
|
||||
import static org.briarproject.briar.android.activity.BriarActivity.GROUP_ID;
|
||||
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
|
||||
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_BLOGS;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_CONTACTS;
|
||||
import static org.briarproject.briar.android.navdrawer.NavDrawerActivity.INTENT_FORUMS;
|
||||
@@ -219,8 +219,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
|
||||
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
|
||||
if (s.getNamespace().equals(SETTINGS_NAMESPACE))
|
||||
settings = s.getSettings();
|
||||
} else if (e instanceof PrivateMessageReceivedEvent) {
|
||||
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
||||
} else if (e instanceof ConversationMessageReceivedEvent) {
|
||||
ConversationMessageReceivedEvent p =
|
||||
(ConversationMessageReceivedEvent) e;
|
||||
showContactNotification(p.getContactId());
|
||||
} else if (e instanceof GroupMessageAddedEvent) {
|
||||
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.os.StrictMode;
|
||||
|
||||
import com.vanniktech.emoji.RecentEmoji;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
@@ -32,6 +33,7 @@ import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||
import org.briarproject.briar.android.viewmodel.ViewModelModule;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
@@ -57,7 +59,7 @@ import static java.util.Collections.emptyList;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||
|
||||
@Module
|
||||
@Module(includes = ViewModelModule.class)
|
||||
public class AppModule {
|
||||
|
||||
static class EagerSingletons {
|
||||
@@ -103,15 +105,16 @@ public class AppModule {
|
||||
Application app, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, EventBus eventBus,
|
||||
ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Clock clock) {
|
||||
Context appContext = app.getApplicationContext();
|
||||
DuplexPluginFactory bluetooth =
|
||||
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
||||
appContext, random, eventBus, backoffFactory);
|
||||
appContext, random, eventBus, clock, backoffFactory);
|
||||
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
||||
scheduler, appContext, networkManager, locationUtils, eventBus,
|
||||
torSocketFactory, backoffFactory, resourceProvider,
|
||||
circumventionProvider, clock);
|
||||
circumventionProvider, batteryManager, clock);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
eventBus, backoffFactory, appContext);
|
||||
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
||||
|
||||
@@ -18,8 +18,7 @@ import org.briarproject.bramble.util.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -40,7 +39,7 @@ class RecentEmojiImpl implements RecentEmoji, Client {
|
||||
private static final int EMOJI_LRU_SIZE = 50;
|
||||
|
||||
// UI thread
|
||||
private final LinkedHashSet<Emoji> recentlyUsed = new LinkedHashSet<>();
|
||||
private final LinkedList<Emoji> recentlyUsed = new LinkedList<>();
|
||||
|
||||
private final Executor dbExecutor;
|
||||
private final AndroidExecutor androidExecutor;
|
||||
@@ -62,13 +61,9 @@ class RecentEmojiImpl implements RecentEmoji, Client {
|
||||
@Override
|
||||
public void addEmoji(Emoji emoji) {
|
||||
recentlyUsed.remove(emoji);
|
||||
recentlyUsed.add(emoji);
|
||||
recentlyUsed.add(0, emoji);
|
||||
|
||||
if (recentlyUsed.size() > EMOJI_LRU_SIZE) {
|
||||
Iterator<Emoji> iterator = recentlyUsed.iterator();
|
||||
iterator.next();
|
||||
iterator.remove();
|
||||
}
|
||||
if (recentlyUsed.size() > EMOJI_LRU_SIZE) recentlyUsed.removeLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,9 +15,10 @@ import org.briarproject.briar.android.blog.ReblogFragment;
|
||||
import org.briarproject.briar.android.blog.RssFeedImportActivity;
|
||||
import org.briarproject.briar.android.blog.RssFeedManageActivity;
|
||||
import org.briarproject.briar.android.blog.WriteBlogPostActivity;
|
||||
import org.briarproject.briar.android.conversation.AliasDialogFragment;
|
||||
import org.briarproject.briar.android.contact.ContactListFragment;
|
||||
import org.briarproject.briar.android.contact.ContactModule;
|
||||
import org.briarproject.briar.android.contact.ConversationActivity;
|
||||
import org.briarproject.briar.android.conversation.ConversationActivity;
|
||||
import org.briarproject.briar.android.forum.CreateForumActivity;
|
||||
import org.briarproject.briar.android.forum.ForumActivity;
|
||||
import org.briarproject.briar.android.forum.ForumListFragment;
|
||||
@@ -211,4 +212,7 @@ public interface ActivityComponent {
|
||||
void inject(ScreenFilterDialogFragment fragment);
|
||||
|
||||
void inject(ContactExchangeErrorFragment fragment);
|
||||
|
||||
void inject(AliasDialogFragment aliasDialogFragment);
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.briarproject.briar.api.android.ScreenFilterMonitor.AppDetails;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
@@ -42,6 +43,8 @@ import static android.arch.lifecycle.Lifecycle.State.STARTED;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
|
||||
import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOTS;
|
||||
|
||||
/**
|
||||
@@ -51,6 +54,8 @@ import static org.briarproject.briar.android.TestingConstants.PREVENT_SCREENSHOT
|
||||
public abstract class BaseActivity extends AppCompatActivity
|
||||
implements DestroyableContext, OnTapFilteredListener {
|
||||
|
||||
private final static Logger LOG = getLogger(BaseActivity.class.getName());
|
||||
|
||||
@Inject
|
||||
protected ScreenFilterMonitor screenFilterMonitor;
|
||||
|
||||
@@ -119,6 +124,8 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Starting " + this.getClass().getSimpleName());
|
||||
for (ActivityLifecycleController alc : lifecycleControllers) {
|
||||
alc.onActivityStart();
|
||||
}
|
||||
@@ -137,6 +144,8 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Stopping " + this.getClass().getSimpleName());
|
||||
for (ActivityLifecycleController alc : lifecycleControllers) {
|
||||
alc.onActivityStop();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ public interface RequestCodes {
|
||||
int REQUEST_WRITE_BLOG_POST = 5;
|
||||
int REQUEST_SHARE_BLOG = 6;
|
||||
int REQUEST_RINGTONE = 7;
|
||||
int REQUEST_PERMISSION_CAMERA = 8;
|
||||
int REQUEST_PERMISSION_CAMERA_LOCATION = 8;
|
||||
int REQUEST_DOZE_WHITELISTING = 9;
|
||||
int REQUEST_ENABLE_BLUETOOTH = 10;
|
||||
int REQUEST_BLUETOOTH_DISCOVERABLE = 10;
|
||||
int REQUEST_UNLOCK = 11;
|
||||
int REQUEST_KEYGUARD_UNLOCK = 12;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.briarproject.briar.android.blog;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.identity.Author.Status;
|
||||
import org.briarproject.bramble.api.identity.AuthorInfo;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.api.blog.BlogPostHeader;
|
||||
@@ -15,6 +15,7 @@ import javax.annotation.concurrent.NotThreadSafe;
|
||||
public class BlogPostItem implements Comparable<BlogPostItem> {
|
||||
|
||||
private final BlogPostHeader header;
|
||||
@Nullable
|
||||
protected String text;
|
||||
private boolean read;
|
||||
|
||||
@@ -40,10 +41,11 @@ public class BlogPostItem implements Comparable<BlogPostItem> {
|
||||
return header.getAuthor();
|
||||
}
|
||||
|
||||
Status getAuthorStatus() {
|
||||
return header.getAuthorStatus();
|
||||
AuthorInfo getAuthorInfo() {
|
||||
return header.getAuthorInfo();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import android.view.ViewGroup;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.identity.Author;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.view.AuthorView;
|
||||
@@ -98,9 +97,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
// author and date
|
||||
BlogPostHeader post = item.getPostHeader();
|
||||
Author a = post.getAuthor();
|
||||
author.setAuthor(a);
|
||||
author.setAuthorStatus(post.getAuthorStatus());
|
||||
author.setAuthor(post.getAuthor(), post.getAuthorInfo());
|
||||
author.setDate(post.getTimestamp());
|
||||
author.setPersona(
|
||||
item.isRssFeed() ? AuthorView.RSS_FEED : AuthorView.NORMAL);
|
||||
@@ -143,8 +140,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
private void onBindComment(BlogCommentItem item) {
|
||||
// reblogger
|
||||
reblogger.setAuthor(item.getAuthor());
|
||||
reblogger.setAuthorStatus(item.getAuthorStatus());
|
||||
reblogger.setAuthor(item.getAuthor(), item.getAuthorInfo());
|
||||
reblogger.setDate(item.getTimestamp());
|
||||
if (!fullText) {
|
||||
reblogger.setAuthorClickable(v -> listener.onAuthorClick(item));
|
||||
@@ -165,8 +161,7 @@ class BlogPostViewHolder extends RecyclerView.ViewHolder {
|
||||
AuthorView author = v.findViewById(R.id.authorView);
|
||||
TextView text = v.findViewById(R.id.textView);
|
||||
|
||||
author.setAuthor(c.getAuthor());
|
||||
author.setAuthorStatus(c.getAuthorStatus());
|
||||
author.setAuthor(c.getAuthor(), c.getAuthorInfo());
|
||||
author.setDate(c.getTimestamp());
|
||||
// TODO make author clickable #624
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
@@ -9,6 +10,7 @@ import org.briarproject.briar.android.util.BriarAdapter;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static android.support.v7.util.SortedList.INVALID_POSITION;
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
public abstract class BaseContactListAdapter<I extends ContactItem, VH extends ContactItemViewHolder<I>>
|
||||
extends BriarAdapter<I, VH> {
|
||||
@@ -23,15 +25,15 @@ public abstract class BaseContactListAdapter<I extends ContactItem, VH extends C
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(VH ui, int position) {
|
||||
public void onBindViewHolder(@NonNull VH ui, int position) {
|
||||
I item = items.get(position);
|
||||
ui.bind(item, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(I c1, I c2) {
|
||||
return c1.getContact().getAuthor().getName()
|
||||
.compareTo(c2.getContact().getAuthor().getName());
|
||||
return getContactDisplayName(c1.getContact())
|
||||
.compareTo(getContactDisplayName(c2.getContact()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,8 @@ import javax.annotation.Nullable;
|
||||
|
||||
import im.delight.android.identicons.IdenticonDrawable;
|
||||
|
||||
import static org.briarproject.briar.android.util.UiUtils.getContactDisplayName;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
public class ContactItemViewHolder<I extends ContactItem>
|
||||
@@ -41,8 +43,7 @@ public class ContactItemViewHolder<I extends ContactItem>
|
||||
Author author = item.getContact().getAuthor();
|
||||
avatar.setImageDrawable(
|
||||
new IdenticonDrawable(author.getId().getBytes()));
|
||||
String contactName = author.getName();
|
||||
name.setText(contactName);
|
||||
name.setText(getContactDisplayName(item.getContact()));
|
||||
|
||||
if (bulb != null) {
|
||||
// online/offline
|
||||
|
||||
@@ -31,14 +31,15 @@ import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||
import org.briarproject.briar.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||
import org.briarproject.briar.android.conversation.ConversationActivity;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
|
||||
import org.briarproject.briar.android.view.BriarRecyclerView;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
import org.briarproject.briar.api.messaging.ConversationManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.messaging.event.PrivateMessageReceivedEvent;
|
||||
import org.briarproject.briar.api.conversation.ConversationManager;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
import org.briarproject.briar.api.conversation.event.ConversationMessageReceivedEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -54,7 +55,7 @@ import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.bramble.util.LogUtils.now;
|
||||
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
|
||||
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
@@ -242,15 +243,16 @@ public class ContactListFragment extends BaseFragment implements EventListener {
|
||||
} else if (e instanceof ContactRemovedEvent) {
|
||||
LOG.info("Contact removed, removing item");
|
||||
removeItem(((ContactRemovedEvent) e).getContactId());
|
||||
} else if (e instanceof PrivateMessageReceivedEvent) {
|
||||
LOG.info("Private message received, updating item");
|
||||
PrivateMessageReceivedEvent p = (PrivateMessageReceivedEvent) e;
|
||||
PrivateMessageHeader h = p.getMessageHeader();
|
||||
} else if (e instanceof ConversationMessageReceivedEvent) {
|
||||
LOG.info("Conversation message received, updating item");
|
||||
ConversationMessageReceivedEvent p =
|
||||
(ConversationMessageReceivedEvent) e;
|
||||
ConversationMessageHeader h = p.getMessageHeader();
|
||||
updateItem(p.getContactId(), h);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateItem(ContactId c, PrivateMessageHeader h) {
|
||||
private void updateItem(ContactId c, ConversationMessageHeader h) {
|
||||
runOnUiThreadUnlessDestroyed(() -> {
|
||||
adapter.incrementRevision();
|
||||
int position = adapter.findItemPosition(c);
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.briarproject.briar.android.contact;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.api.client.MessageTracker.GroupCount;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
|
||||
import org.briarproject.briar.api.conversation.ConversationMessageHeader;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@@ -23,7 +23,7 @@ public class ContactListItem extends ContactItem {
|
||||
this.timestamp = count.getLatestMsgTime();
|
||||
}
|
||||
|
||||
void addMessage(PrivateMessageHeader h) {
|
||||
void addMessage(ConversationMessageHeader h) {
|
||||
empty = false;
|
||||
if (h.getTimestamp() > timestamp) timestamp = h.getTimestamp();
|
||||
if (!h.isRead()) unread++;
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.support.annotation.LayoutRes;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
abstract class ConversationItem {
|
||||
|
||||
@Nullable
|
||||
protected String text;
|
||||
private final MessageId id;
|
||||
private final GroupId groupId;
|
||||
private final long time;
|
||||
private boolean read;
|
||||
|
||||
ConversationItem(MessageId id, GroupId groupId, @Nullable String text,
|
||||
long time, boolean read) {
|
||||
this.id = id;
|
||||
this.groupId = groupId;
|
||||
this.text = text;
|
||||
this.time = time;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
MessageId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
GroupId getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
|
||||
void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
abstract public boolean isIncoming();
|
||||
|
||||
@LayoutRes
|
||||
abstract public int getLayout();
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.util.UiUtils;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class ConversationItemViewHolder extends ViewHolder {
|
||||
|
||||
protected final ViewGroup layout;
|
||||
private final TextView text;
|
||||
private final TextView time;
|
||||
|
||||
ConversationItemViewHolder(View v) {
|
||||
super(v);
|
||||
layout = v.findViewById(R.id.layout);
|
||||
text = v.findViewById(R.id.text);
|
||||
time = v.findViewById(R.id.time);
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
void bind(ConversationItem item) {
|
||||
if (item.getText() == null) {
|
||||
text.setText("\u2026");
|
||||
} else {
|
||||
text.setText(StringUtils.trim(item.getText()));
|
||||
}
|
||||
|
||||
long timestamp = item.getTime();
|
||||
time.setText(UiUtils.formatDate(time.getContext(), timestamp));
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user