mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Compare commits
7 Commits
hash-trees
...
41-alias-f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68738a5a03 | ||
|
|
1a025d0f40 | ||
|
|
a3593ea8ca | ||
|
|
34eaedbd63 | ||
|
|
44e1ce32ce | ||
|
|
7af4b3d3ca | ||
|
|
1423ca7a15 |
@@ -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="org.briarproject.briar.headless" />
|
||||
<option name="PACKAGE_NAME" value="" />
|
||||
<option name="MAIN_CLASS_NAME" value="" />
|
||||
<option name="METHOD_NAME" value="" />
|
||||
<option name="TEST_OBJECT" value="package" />
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import com.android.build.gradle.tasks.MergeResources
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
@@ -11,8 +9,8 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
versionCode 10105
|
||||
versionName "1.1.5"
|
||||
versionCode 10103
|
||||
versionName "1.1.3"
|
||||
consumerProguardFiles 'proguard-rules.txt'
|
||||
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
@@ -31,9 +29,8 @@ 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.19'
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
@@ -42,29 +39,13 @@ 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"
|
||||
}
|
||||
|
||||
def torBinariesDir = 'src/main/res/raw'
|
||||
|
||||
task cleanTorBinaries {
|
||||
doLast {
|
||||
delete fileTree(torBinariesDir) { include '*.zip' }
|
||||
project.afterEvaluate {
|
||||
copy {
|
||||
from configurations.tor.collect { zipTree(it) }
|
||||
into 'src/main/res/raw'
|
||||
}
|
||||
}
|
||||
|
||||
clean.dependsOn cleanTorBinaries
|
||||
|
||||
task unpackTorBinaries {
|
||||
doLast {
|
||||
copy {
|
||||
from configurations.tor.collect { zipTree(it) }
|
||||
into torBinariesDir
|
||||
}
|
||||
}
|
||||
dependsOn cleanTorBinaries
|
||||
}
|
||||
|
||||
tasks.withType(MergeResources) {
|
||||
inputs.dir torBinariesDir
|
||||
dependsOn unpackTorBinaries
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.briarproject.bramble;
|
||||
|
||||
import org.briarproject.bramble.battery.AndroidBatteryModule;
|
||||
import org.briarproject.bramble.network.AndroidNetworkModule;
|
||||
|
||||
public interface BrambleAndroidEagerSingletons {
|
||||
|
||||
void inject(AndroidBatteryModule.EagerSingletons init);
|
||||
|
||||
void inject(AndroidNetworkModule.EagerSingletons init);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.bramble;
|
||||
|
||||
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;
|
||||
@@ -8,15 +7,10 @@ import org.briarproject.bramble.system.AndroidSystemModule;
|
||||
import dagger.Module;
|
||||
|
||||
@Module(includes = {
|
||||
AndroidBatteryModule.class,
|
||||
AndroidNetworkModule.class,
|
||||
AndroidSystemModule.class,
|
||||
CircumventionModule.class
|
||||
})
|
||||
public class BrambleAndroidModule {
|
||||
|
||||
public static void initEagerSingletons(BrambleAndroidEagerSingletons c) {
|
||||
c.inject(new AndroidBatteryModule.EagerSingletons());
|
||||
c.inject(new AndroidNetworkModule.EagerSingletons());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
package org.briarproject.bramble.battery;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.battery.event.BatteryEvent;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.Service;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.content.Intent.ACTION_BATTERY_CHANGED;
|
||||
import static android.content.Intent.ACTION_POWER_CONNECTED;
|
||||
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
|
||||
import static android.os.BatteryManager.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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.briarproject.bramble.battery;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class AndroidBatteryModule {
|
||||
|
||||
public static class EagerSingletons {
|
||||
@Inject
|
||||
BatteryManager batteryManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
BatteryManager provideBatteryManager(LifecycleManager lifecycleManager,
|
||||
AndroidBatteryManager batteryManager) {
|
||||
lifecycleManager.registerService(batteryManager);
|
||||
return batteryManager;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package org.briarproject.bramble.network;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
@@ -12,11 +11,6 @@ import dagger.Provides;
|
||||
@Module
|
||||
public class AndroidNetworkModule {
|
||||
|
||||
public static class EagerSingletons {
|
||||
@Inject
|
||||
NetworkManager networkManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
|
||||
|
||||
@@ -18,8 +18,8 @@ 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 org.briarproject.bramble.util.IoUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
@@ -51,6 +51,7 @@ 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
|
||||
@@ -160,7 +161,11 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
||||
|
||||
@Override
|
||||
void tryToClose(@Nullable BluetoothServerSocket ss) {
|
||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
||||
try {
|
||||
if (ss != null) ss.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -190,7 +195,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
||||
s.connect();
|
||||
return wrapSocket(s);
|
||||
} catch (IOException e) {
|
||||
IoUtils.tryToClose(s, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -263,6 +268,14 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable Closeable c) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,7 +6,6 @@ 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;
|
||||
@@ -42,18 +41,17 @@ class AndroidTorPlugin extends TorPlugin {
|
||||
Context appContext, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||
Clock clock, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Backoff backoff,
|
||||
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime) {
|
||||
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||
backoff, callback, architecture, maxLatency, maxIdleTime,
|
||||
clock, resourceProvider, circumventionProvider, backoff,
|
||||
callback, architecture, maxLatency, maxIdleTime,
|
||||
appContext.getDir("tor", MODE_PRIVATE));
|
||||
this.appContext = appContext;
|
||||
PowerManager pm = (PowerManager)
|
||||
appContext.getSystemService(POWER_SERVICE);
|
||||
if (pm == null) throw new AssertionError();
|
||||
assert pm != null;
|
||||
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
|
||||
WAKE_LOCK_TAG, 1, MINUTES);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ 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;
|
||||
@@ -49,7 +48,6 @@ 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,
|
||||
@@ -57,8 +55,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
NetworkManager networkManager, LocationUtils locationUtils,
|
||||
EventBus eventBus, SocketFactory torSocketFactory,
|
||||
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Clock clock) {
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
this.scheduler = scheduler;
|
||||
this.appContext = appContext;
|
||||
@@ -69,7 +66,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
this.backoffFactory = backoffFactory;
|
||||
this.resourceProvider = resourceProvider;
|
||||
this.circumventionProvider = circumventionProvider;
|
||||
this.batteryManager = batteryManager;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@@ -108,8 +104,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
|
||||
appContext, networkManager, locationUtils, torSocketFactory,
|
||||
clock, resourceProvider, circumventionProvider, batteryManager,
|
||||
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||
clock, resourceProvider, circumventionProvider, backoff,
|
||||
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||
eventBus.addListener(plugin);
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.bramble.system;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Application;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
@@ -27,7 +26,7 @@ import static android.provider.Settings.Secure.ANDROID_ID;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
||||
class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
|
||||
|
||||
private static final int SEED_LENGTH = 32;
|
||||
|
||||
@@ -38,7 +37,6 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
||||
appContext = app.getApplicationContext();
|
||||
}
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
@Override
|
||||
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
|
||||
super.writeToEntropyPool(out);
|
||||
@@ -51,14 +49,12 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
||||
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
|
||||
if (id != null) out.writeUTF(id);
|
||||
Parcel parcel = Parcel.obtain();
|
||||
WifiManager wm = (WifiManager) appContext.getApplicationContext()
|
||||
.getSystemService(WIFI_SERVICE);
|
||||
if (wm != null) {
|
||||
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
|
||||
if (configs != null) {
|
||||
for (WifiConfiguration config : configs)
|
||||
parcel.writeParcelable(config, 0);
|
||||
}
|
||||
WifiManager wm =
|
||||
(WifiManager) appContext.getSystemService(WIFI_SERVICE);
|
||||
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
|
||||
if (configs != null) {
|
||||
for (WifiConfiguration config : configs)
|
||||
parcel.writeParcelable(config, 0);
|
||||
}
|
||||
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
|
||||
if (bt != null) {
|
||||
@@ -81,13 +77,13 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
|
||||
|
||||
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
||||
private void applyOpenSslFix() {
|
||||
byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(
|
||||
byte[] seed = new LinuxSecureRandomSpi().engineGenerateSeed(
|
||||
SEED_LENGTH);
|
||||
try {
|
||||
// Seed the OpenSSL PRNG
|
||||
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||
.getMethod("RAND_seed", byte[].class)
|
||||
.invoke(null, (Object) seed);
|
||||
.invoke(null, seed);
|
||||
// Mix the output of the Linux PRNG into the OpenSSL PRNG
|
||||
int bytesRead = (Integer) Class.forName(
|
||||
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
|
||||
|
||||
@@ -11,12 +11,15 @@ 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";
|
||||
|
||||
@@ -25,7 +28,7 @@ public class AndroidUtils {
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Collection<String> getSupportedArchitectures() {
|
||||
List<String> abis = new ArrayList<>();
|
||||
if (SDK_INT >= 21) {
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
|
||||
} else {
|
||||
abis.add(Build.CPU_ABI);
|
||||
|
||||
@@ -31,21 +31,16 @@ 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.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.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.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
||||
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
|
||||
'com.google.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:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||
'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',
|
||||
@@ -68,9 +63,7 @@ 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,13 +7,15 @@ apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
|
||||
dependencies {
|
||||
implementation "com.google.dagger:dagger:2.19"
|
||||
implementation "com.google.dagger:dagger:2.0.2"
|
||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.briarproject.bramble.api;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class Pair<A, B> {
|
||||
|
||||
private final A first;
|
||||
private final B second;
|
||||
|
||||
public Pair(A first, B second) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public A getFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
public B getSecond() {
|
||||
return second;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package org.briarproject.bramble.api.battery;
|
||||
|
||||
public interface BatteryManager {
|
||||
|
||||
boolean isCharging();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.briarproject.bramble.api.battery.event;
|
||||
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when the device starts or stops charging.
|
||||
*/
|
||||
public class BatteryEvent extends Event {
|
||||
|
||||
private final boolean charging;
|
||||
|
||||
public BatteryEvent(boolean charging) {
|
||||
this.charging = charging;
|
||||
}
|
||||
|
||||
public boolean isCharging() {
|
||||
return charging;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageContext;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageValidator;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -96,12 +96,6 @@ 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.
|
||||
*/
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.briarproject.bramble.api.data;
|
||||
|
||||
import org.briarproject.bramble.api.Bytes;
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
||||
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||
|
||||
@NotNullByDefault
|
||||
public class BdfStringUtils {
|
||||
|
||||
public static String toString(@Nullable Object o) throws FormatException {
|
||||
return toString(o, 0);
|
||||
}
|
||||
|
||||
private static String toString(@Nullable Object o, int indent)
|
||||
throws FormatException {
|
||||
if (o == null || o == NULL_VALUE) return "null";
|
||||
if (o instanceof Boolean) return o.toString();
|
||||
if (o instanceof Number) return o.toString();
|
||||
if (o instanceof String) return "\"" + o + "\"";
|
||||
if (o instanceof Bytes)
|
||||
return "x" + toHexString(((Bytes) o).getBytes());
|
||||
if (o instanceof byte[])
|
||||
return "x" + toHexString((byte[]) o);
|
||||
if (o instanceof List) {
|
||||
List<?> list = (List) o;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[\n");
|
||||
int i = 0, size = list.size();
|
||||
for (Object e : list) {
|
||||
indent(sb, indent + 1);
|
||||
sb.append(toString(e, indent + 1));
|
||||
if (i++ < size - 1) sb.append(',');
|
||||
sb.append('\n');
|
||||
}
|
||||
indent(sb, indent);
|
||||
sb.append(']');
|
||||
return sb.toString();
|
||||
}
|
||||
if (o instanceof Map) {
|
||||
Map<?, ?> map = (Map) o;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("{\n");
|
||||
int i = 0, size = map.size();
|
||||
for (Entry e : map.entrySet()) {
|
||||
indent(sb, indent + 1);
|
||||
sb.append(toString(e.getKey(), indent + 1));
|
||||
sb.append(": ");
|
||||
sb.append(toString(e.getValue(), indent + 1));
|
||||
if (i++ < size - 1) sb.append(',');
|
||||
sb.append('\n');
|
||||
}
|
||||
indent(sb, indent);
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
}
|
||||
throw new FormatException();
|
||||
}
|
||||
|
||||
private static void indent(StringBuilder sb, int indent) {
|
||||
for (int i = 0; i < indent; i++) sb.append('\t');
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||
import org.briarproject.bramble.api.sync.Offer;
|
||||
import org.briarproject.bramble.api.sync.Request;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
import org.briarproject.bramble.api.transport.KeySet;
|
||||
import org.briarproject.bramble.api.transport.KeySetId;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
@@ -29,6 +28,8 @@ import java.util.Map;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||
|
||||
/**
|
||||
* Encapsulates the database implementation and exposes high-level operations
|
||||
* to other components.
|
||||
@@ -88,14 +89,6 @@ 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.
|
||||
@@ -373,12 +366,12 @@ public interface DatabaseComponent {
|
||||
/**
|
||||
* Returns the IDs and states of all dependencies of the given message.
|
||||
* For missing dependencies and dependencies in other groups, the state
|
||||
* {@link MessageState UNKNOWN} is returned.
|
||||
* {@link State UNKNOWN} is returned.
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
Map<MessageId, MessageState> getMessageDependencies(Transaction txn,
|
||||
MessageId m) throws DbException;
|
||||
Map<MessageId, State> getMessageDependencies(Transaction txn, MessageId m)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the IDs and states of all dependents of the given message.
|
||||
@@ -387,16 +380,15 @@ public interface DatabaseComponent {
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
Map<MessageId, MessageState> getMessageDependents(Transaction txn,
|
||||
MessageId m) throws DbException;
|
||||
Map<MessageId, State> getMessageDependents(Transaction txn, MessageId m)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
* Gets the validation and delivery state of the given message.
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
MessageState getMessageState(Transaction txn, MessageId m)
|
||||
throws DbException;
|
||||
State getMessageState(Transaction txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the status of the given delivered message with respect to the
|
||||
@@ -543,7 +535,7 @@ public interface DatabaseComponent {
|
||||
/**
|
||||
* Sets the validation and delivery state of the given message.
|
||||
*/
|
||||
void setMessageState(Transaction txn, MessageId m, MessageState state)
|
||||
void setMessageState(Transaction txn, MessageId m, State state)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
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,8 +1,5 @@
|
||||
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;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package org.briarproject.bramble.api.db;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface NullableDbCallable<R, E extends Exception> {
|
||||
|
||||
@Nullable
|
||||
R call(Transaction txn) throws DbException, E;
|
||||
}
|
||||
@@ -39,18 +39,4 @@ public class AuthorInfo {
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.briarproject.bramble.api.io;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHash;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface BlockSink {
|
||||
|
||||
/**
|
||||
* Stores a block of the message with the given temporary ID.
|
||||
*/
|
||||
void putBlock(HashingId h, int blockNumber, byte[] data) throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the hash tree path of a previously stored block.
|
||||
*/
|
||||
void setPath(HashingId h, int blockNumber, List<TreeHash> path)
|
||||
throws DbException;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.briarproject.bramble.api.io;
|
||||
|
||||
import org.briarproject.bramble.api.UniqueId;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Type-safe wrapper for a byte array that uniquely identifies a
|
||||
* {@link Message} while it's being hashed and the {@link MessageId} is not
|
||||
* yet known.
|
||||
*/
|
||||
@ThreadSafe
|
||||
@NotNullByDefault
|
||||
public class HashingId extends UniqueId {
|
||||
|
||||
public HashingId(byte[] id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof HashingId && super.equals(o);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package org.briarproject.bramble.api.nullsafety;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@NotNullByDefault
|
||||
public class NullSafety {
|
||||
|
||||
/**
|
||||
* Stand-in for `Objects.requireNonNull()`.
|
||||
*/
|
||||
public static <T> T requireNonNull(@Nullable T t) {
|
||||
if (t == null) throw new NullPointerException();
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.bramble.api.sync;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHash;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface MessageFactory {
|
||||
@@ -11,6 +10,4 @@ public interface MessageFactory {
|
||||
Message createMessage(byte[] raw);
|
||||
|
||||
byte[] getRawMessage(Message m);
|
||||
|
||||
MessageId getMessageId(GroupId g, long timestamp, TreeHash rootHash);
|
||||
}
|
||||
|
||||
@@ -24,12 +24,6 @@ public class MessageId extends UniqueId {
|
||||
public static final String BLOCK_LABEL =
|
||||
"org.briarproject.bramble/MESSAGE_BLOCK";
|
||||
|
||||
/**
|
||||
* Label for hashing two tree hashes to produce a parent.
|
||||
*/
|
||||
public static final String TREE_LABEL =
|
||||
"org.briarproject.bramble/MESSAGE_TREE";
|
||||
|
||||
public MessageId(byte[] id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@@ -35,9 +35,4 @@ public interface SyncConstants {
|
||||
* The maximum number of message IDs in an ack, offer or request record.
|
||||
*/
|
||||
int MAX_MESSAGE_IDS = MAX_RECORD_PAYLOAD_BYTES / UniqueId.LENGTH;
|
||||
|
||||
/**
|
||||
* The maximum length of a message block in bytes.
|
||||
*/
|
||||
int MAX_BLOCK_LENGTH = 32 * 2014; // 32 KiB
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.briarproject.bramble.api.sync;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
/**
|
||||
* Responsible for managing message validators and passing them messages to
|
||||
* validate.
|
||||
*/
|
||||
@NotNullByDefault
|
||||
public interface ValidationManager {
|
||||
|
||||
enum State {
|
||||
|
||||
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
|
||||
|
||||
private final int value;
|
||||
|
||||
State(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static State fromValue(int value) {
|
||||
for (State s : values()) if (s.value == value) return s;
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the message validator for the given client. This method
|
||||
* should be called before
|
||||
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||
*/
|
||||
void registerMessageValidator(ClientId c, int majorVersion,
|
||||
MessageValidator v);
|
||||
|
||||
/**
|
||||
* Registers the incoming message hook for the given client. The hook will
|
||||
* be called once for each incoming message that passes validation. This
|
||||
* method should be called before
|
||||
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||
*/
|
||||
void registerIncomingMessageHook(ClientId c, int majorVersion,
|
||||
IncomingMessageHook hook);
|
||||
|
||||
interface MessageValidator {
|
||||
|
||||
/**
|
||||
* Validates the given message and returns its metadata and
|
||||
* dependencies.
|
||||
*/
|
||||
MessageContext validateMessage(Message m, Group g)
|
||||
throws InvalidMessageException;
|
||||
}
|
||||
|
||||
interface IncomingMessageHook {
|
||||
|
||||
/**
|
||||
* Called once for each incoming message that passes validation.
|
||||
*
|
||||
* @return whether or not this message should be shared
|
||||
* @throws DbException Should only be used for real database errors.
|
||||
* If this is thrown, delivery will be attempted again at next startup,
|
||||
* whereas if an InvalidMessageException is thrown,
|
||||
* the message will be permanently invalidated.
|
||||
* @throws InvalidMessageException for any non-database error
|
||||
* that occurs while handling remotely created data.
|
||||
* This includes errors that occur while handling locally created data
|
||||
* in a context controlled by remotely created data
|
||||
* (for example, parsing the metadata of a dependency
|
||||
* of an incoming message).
|
||||
* Throwing this will delete the incoming message and its metadata
|
||||
* marking it as invalid in the database.
|
||||
* Never rethrow DbException as InvalidMessageException!
|
||||
*/
|
||||
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
||||
throws DbException, InvalidMessageException;
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,11 @@ package org.briarproject.bramble.api.sync.event;
|
||||
import org.briarproject.bramble.api.event.Event;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||
|
||||
/**
|
||||
* An event that is broadcast when a message state changed.
|
||||
*/
|
||||
@@ -16,10 +17,10 @@ public class MessageStateChangedEvent extends Event {
|
||||
|
||||
private final MessageId messageId;
|
||||
private final boolean local;
|
||||
private final MessageState state;
|
||||
private final State state;
|
||||
|
||||
public MessageStateChangedEvent(MessageId messageId, boolean local,
|
||||
MessageState state) {
|
||||
State state) {
|
||||
this.messageId = messageId;
|
||||
this.local = local;
|
||||
this.state = state;
|
||||
@@ -33,7 +34,7 @@ public class MessageStateChangedEvent extends Event {
|
||||
return local;
|
||||
}
|
||||
|
||||
public MessageState getState() {
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public class LeafNode extends TreeNode {
|
||||
|
||||
public LeafNode(TreeHash hash, int blockNumber) {
|
||||
super(hash, 0, blockNumber, blockNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getLeftChild() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getRightChild() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public class ParentNode extends TreeNode {
|
||||
|
||||
private final TreeNode left, right;
|
||||
|
||||
public ParentNode(TreeHash hash, TreeNode left, TreeNode right) {
|
||||
super(hash, Math.max(left.getHeight(), right.getHeight()) + 1,
|
||||
left.getFirstBlockNumber(), right.getLastBlockNumber());
|
||||
this.left = left;
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getLeftChild() {
|
||||
return left;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getRightChild() {
|
||||
return right;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.io.BlockSink;
|
||||
import org.briarproject.bramble.api.io.HashingId;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface StreamHasher {
|
||||
|
||||
/**
|
||||
* Reads the given input stream, divides the data into blocks, stores
|
||||
* the blocks and the resulting hash tree using the given block sink and
|
||||
* temporary ID, and returns the hash tree.
|
||||
*/
|
||||
TreeNode hash(InputStream in, BlockSink sink, HashingId h)
|
||||
throws IOException, DbException;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.UniqueId;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
|
||||
/**
|
||||
* Type-safe wrapper for a byte array that uniquely identifies a sequence of
|
||||
* one or more message blocks.
|
||||
*/
|
||||
@ThreadSafe
|
||||
@NotNullByDefault
|
||||
public class TreeHash extends UniqueId {
|
||||
|
||||
public TreeHash(byte[] id) {
|
||||
super(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o instanceof TreeHash && super.equals(o);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface TreeHasher {
|
||||
|
||||
LeafNode hashBlock(int blockNumber, byte[] data);
|
||||
|
||||
ParentNode mergeTrees(TreeNode left, TreeNode right);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public abstract class TreeNode {
|
||||
|
||||
private final TreeHash hash;
|
||||
private final int height, firstBlockNumber, lastBlockNumber;
|
||||
|
||||
TreeNode(TreeHash hash, int height, int firstBlockNumber,
|
||||
int lastBlockNumber) {
|
||||
this.hash = hash;
|
||||
this.height = height;
|
||||
this.firstBlockNumber = firstBlockNumber;
|
||||
this.lastBlockNumber = lastBlockNumber;
|
||||
}
|
||||
|
||||
public TreeHash getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getFirstBlockNumber() {
|
||||
return firstBlockNumber;
|
||||
}
|
||||
|
||||
public int getLastBlockNumber() {
|
||||
return lastBlockNumber;
|
||||
}
|
||||
|
||||
public abstract TreeNode getLeftChild();
|
||||
|
||||
public abstract TreeNode getRightChild();
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.validation;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Metadata;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
|
||||
public interface IncomingMessageHook {
|
||||
|
||||
/**
|
||||
* Called once for each incoming message that passes validation.
|
||||
*
|
||||
* @return whether or not this message should be shared
|
||||
* @throws DbException Should only be used for real database errors.
|
||||
* If this is thrown, delivery will be attempted again at next startup,
|
||||
* whereas if an InvalidMessageException is thrown,
|
||||
* the message will be permanently invalidated.
|
||||
* @throws InvalidMessageException for any non-database error
|
||||
* that occurs while handling remotely created data.
|
||||
* This includes errors that occur while handling locally created data
|
||||
* in a context controlled by remotely created data
|
||||
* (for example, parsing the metadata of a dependency
|
||||
* of an incoming message).
|
||||
* Throwing this will delete the incoming message and its metadata
|
||||
* marking it as invalid in the database.
|
||||
* Never rethrow DbException as InvalidMessageException!
|
||||
*/
|
||||
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
||||
throws DbException, InvalidMessageException;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.validation;
|
||||
|
||||
public enum MessageState {
|
||||
|
||||
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
|
||||
|
||||
private final int value;
|
||||
|
||||
MessageState(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static MessageState fromValue(int value) {
|
||||
for (MessageState s : values()) if (s.value == value) return s;
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.validation;
|
||||
|
||||
import org.briarproject.bramble.api.sync.Group;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageContext;
|
||||
|
||||
public interface MessageValidator {
|
||||
|
||||
/**
|
||||
* Validates the given message and returns its metadata and
|
||||
* dependencies.
|
||||
*/
|
||||
MessageContext validateMessage(Message m, Group g)
|
||||
throws InvalidMessageException;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package org.briarproject.bramble.api.sync.validation;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.ClientId;
|
||||
|
||||
/**
|
||||
* Responsible for managing message validators and passing them messages to
|
||||
* validate.
|
||||
*/
|
||||
@NotNullByDefault
|
||||
public interface ValidationManager {
|
||||
|
||||
/**
|
||||
* Registers the {@link MessageValidator} for the given client. This method
|
||||
* should be called before
|
||||
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||
*/
|
||||
void registerMessageValidator(ClientId c, int majorVersion,
|
||||
MessageValidator v);
|
||||
|
||||
/**
|
||||
* Registers the {@link IncomingMessageHook} for the given client. The hook
|
||||
* will be called once for each incoming message that passes validation.
|
||||
* This method should be called before
|
||||
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||
*/
|
||||
void registerIncomingMessageHook(ClientId c, int majorVersion,
|
||||
IncomingMessageHook hook);
|
||||
}
|
||||
@@ -8,15 +8,12 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
public class IoUtils {
|
||||
@@ -57,35 +54,16 @@ public class IoUtils {
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
tryToClose(in, LOG, WARNING);
|
||||
tryToClose(out, LOG, WARNING);
|
||||
tryToClose(in);
|
||||
tryToClose(out);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tryToClose(@Nullable Closeable c, Logger logger,
|
||||
Level level) {
|
||||
private static void tryToClose(@Nullable Closeable c) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
} catch (IOException e) {
|
||||
logException(logger, level, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tryToClose(@Nullable Socket s, Logger logger,
|
||||
Level level) {
|
||||
try {
|
||||
if (s != null) s.close();
|
||||
} catch (IOException e) {
|
||||
logException(logger, level, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void tryToClose(@Nullable ServerSocket ss, Logger logger,
|
||||
Level level) {
|
||||
try {
|
||||
if (ss != null) ss.close();
|
||||
} catch (IOException e) {
|
||||
logException(logger, level, e);
|
||||
// We did our best
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ public class OsUtils {
|
||||
@Nullable
|
||||
private static final String os = System.getProperty("os.name");
|
||||
@Nullable
|
||||
private static final String version = System.getProperty("os.version");
|
||||
@Nullable
|
||||
private static final String vendor = System.getProperty("java.vendor");
|
||||
|
||||
public static boolean isWindows() {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class StringUtils {
|
||||
try {
|
||||
return s.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class StringUtils {
|
||||
try {
|
||||
return decoder.decode(buffer).toString();
|
||||
} catch (CharacterCodingException e) {
|
||||
throw new AssertionError(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.briarproject.bramble.api.identity;
|
||||
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
|
||||
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
|
||||
public class AuthorInfoTest extends BrambleTestCase {
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
assertEquals(
|
||||
new AuthorInfo(NONE),
|
||||
new AuthorInfo(NONE, null)
|
||||
);
|
||||
assertEquals(
|
||||
new AuthorInfo(NONE, "test"),
|
||||
new AuthorInfo(NONE, "test")
|
||||
);
|
||||
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE),
|
||||
new AuthorInfo(VERIFIED)
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE, "test"),
|
||||
new AuthorInfo(NONE)
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE),
|
||||
new AuthorInfo(NONE, "test")
|
||||
);
|
||||
assertNotEquals(
|
||||
new AuthorInfo(NONE, "a"),
|
||||
new AuthorInfo(NONE, "b")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,7 @@ dependencyVerification {
|
||||
verify = [
|
||||
'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.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
|
||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||
'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'
|
||||
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
|
||||
@@ -25,8 +25,10 @@ dependencies {
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-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"
|
||||
|
||||
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.19'
|
||||
testApt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
|
||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||
import org.briarproject.bramble.plugin.PluginModule;
|
||||
import org.briarproject.bramble.properties.PropertiesModule;
|
||||
import org.briarproject.bramble.reporting.ReportingModule;
|
||||
import org.briarproject.bramble.sync.validation.ValidationModule;
|
||||
import org.briarproject.bramble.sync.SyncModule;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
import org.briarproject.bramble.transport.TransportModule;
|
||||
import org.briarproject.bramble.versioning.VersioningModule;
|
||||
@@ -31,11 +31,11 @@ public interface BrambleCoreEagerSingletons {
|
||||
|
||||
void inject(ReportingModule.EagerSingletons init);
|
||||
|
||||
void inject(SyncModule.EagerSingletons init);
|
||||
|
||||
void inject(SystemModule.EagerSingletons init);
|
||||
|
||||
void inject(TransportModule.EagerSingletons init);
|
||||
|
||||
void inject(ValidationModule.EagerSingletons init);
|
||||
|
||||
void inject(VersioningModule.EagerSingletons init);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.reporting.ReportingModule;
|
||||
import org.briarproject.bramble.settings.SettingsModule;
|
||||
import org.briarproject.bramble.socks.SocksModule;
|
||||
import org.briarproject.bramble.sync.SyncModule;
|
||||
import org.briarproject.bramble.sync.validation.ValidationModule;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
import org.briarproject.bramble.transport.TransportModule;
|
||||
import org.briarproject.bramble.versioning.VersioningModule;
|
||||
@@ -48,7 +47,6 @@ import dagger.Module;
|
||||
SyncModule.class,
|
||||
SystemModule.class,
|
||||
TransportModule.class,
|
||||
ValidationModule.class,
|
||||
VersioningModule.class
|
||||
})
|
||||
public class BrambleCoreModule {
|
||||
@@ -62,9 +60,9 @@ public class BrambleCoreModule {
|
||||
c.inject(new PluginModule.EagerSingletons());
|
||||
c.inject(new PropertiesModule.EagerSingletons());
|
||||
c.inject(new ReportingModule.EagerSingletons());
|
||||
c.inject(new SyncModule.EagerSingletons());
|
||||
c.inject(new SystemModule.EagerSingletons());
|
||||
c.inject(new TransportModule.EagerSingletons());
|
||||
c.inject(new ValidationModule.EagerSingletons());
|
||||
c.inject(new VersioningModule.EagerSingletons());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.briarproject.bramble.battery;
|
||||
|
||||
import org.briarproject.bramble.api.battery.BatteryManager;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
/**
|
||||
* Provides a default implementation of {@link BatteryManager} for systems
|
||||
* without batteries.
|
||||
*/
|
||||
@Module
|
||||
public class DefaultBatteryManagerModule {
|
||||
|
||||
@Provides
|
||||
BatteryManager provideBatteryManager() {
|
||||
return () -> false;
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,13 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public void addLocalMessage(Message m, BdfDictionary metadata,
|
||||
boolean shared) throws DbException, FormatException {
|
||||
db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
addLocalMessage(txn, m, metadata, shared);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,7 +113,15 @@ class ClientHelperImpl implements ClientHelper {
|
||||
|
||||
@Override
|
||||
public Message getMessage(MessageId m) throws DbException {
|
||||
return db.transactionWithResult(true, txn -> getMessage(txn, m));
|
||||
Message message;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
message = getMessage(txn, m);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -118,7 +132,15 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public BdfList getMessageAsList(MessageId m) throws DbException,
|
||||
FormatException {
|
||||
return db.transactionWithResult(true, txn -> getMessageAsList(txn, m));
|
||||
BdfList list;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
list = getMessageAsList(txn, m);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,8 +152,15 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public BdfDictionary getGroupMetadataAsDictionary(GroupId g)
|
||||
throws DbException, FormatException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getGroupMetadataAsDictionary(txn, g));
|
||||
BdfDictionary dictionary;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
dictionary = getGroupMetadataAsDictionary(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,8 +173,15 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
|
||||
throws DbException, FormatException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getMessageMetadataAsDictionary(txn, m));
|
||||
BdfDictionary dictionary;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
dictionary = getMessageMetadataAsDictionary(txn, m);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -158,8 +194,15 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||
GroupId g) throws DbException, FormatException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getMessageMetadataAsDictionary(txn, g));
|
||||
Map<MessageId, BdfDictionary> map;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
map = getMessageMetadataAsDictionary(txn, g);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -176,8 +219,15 @@ class ClientHelperImpl implements ClientHelper {
|
||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||
GroupId g, BdfDictionary query) throws DbException,
|
||||
FormatException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getMessageMetadataAsDictionary(txn, g, query));
|
||||
Map<MessageId, BdfDictionary> map;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
map = getMessageMetadataAsDictionary(txn, g, query);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -195,7 +245,13 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public void mergeGroupMetadata(GroupId g, BdfDictionary metadata)
|
||||
throws DbException, FormatException {
|
||||
db.transaction(false, txn -> mergeGroupMetadata(txn, g, metadata));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
mergeGroupMetadata(txn, g, metadata);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,7 +263,13 @@ class ClientHelperImpl implements ClientHelper {
|
||||
@Override
|
||||
public void mergeMessageMetadata(MessageId m, BdfDictionary metadata)
|
||||
throws DbException, FormatException {
|
||||
db.transaction(false, txn -> mergeMessageMetadata(txn, m, metadata));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
mergeMessageMetadata(txn, m, metadata);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -13,6 +13,7 @@ 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;
|
||||
@@ -157,8 +158,7 @@ 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,14 +287,19 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
||||
private ContactId addContact(Author remoteAuthor, long timestamp,
|
||||
Map<TransportId, TransportProperties> remoteProperties)
|
||||
throws DbException {
|
||||
return db.transactionWithResult(false, txn -> {
|
||||
ContactId contactId = contactManager.addContact(txn, remoteAuthor,
|
||||
ContactId contactId;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
contactId = contactManager.addContact(txn, remoteAuthor,
|
||||
localAuthor.getId(), masterSecret, timestamp, alice,
|
||||
true, true);
|
||||
transportPropertyManager.addRemoteProperties(txn, contactId,
|
||||
remoteProperties);
|
||||
return contactId;
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return contactId;
|
||||
}
|
||||
|
||||
private void tryToClose(DuplexTransportConnection conn) {
|
||||
|
||||
@@ -79,21 +79,42 @@ class ContactManagerImpl implements ContactManager {
|
||||
public ContactId addContact(Author remote, AuthorId local, SecretKey master,
|
||||
long timestamp, boolean alice, boolean verified, boolean active)
|
||||
throws DbException {
|
||||
return db.transactionWithResult(false, txn ->
|
||||
addContact(txn, remote, local, master, timestamp, alice,
|
||||
verified, active));
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contact getContact(ContactId c) throws DbException {
|
||||
return db.transactionWithResult(true, txn -> db.getContact(txn, c));
|
||||
Contact contact;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
contact = db.getContact(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return contact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
|
||||
throws DbException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getContact(txn, remoteAuthorId, localAuthorId));
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
Contact c = getContact(txn, remoteAuthorId, localAuthorId);
|
||||
db.commitTransaction(txn);
|
||||
return c;
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,8 +132,14 @@ class ContactManagerImpl implements ContactManager {
|
||||
|
||||
@Override
|
||||
public Collection<Contact> getActiveContacts() throws DbException {
|
||||
Collection<Contact> contacts =
|
||||
db.transactionWithResult(true, db::getContacts);
|
||||
Collection<Contact> contacts;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
contacts = db.getContacts(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
List<Contact> active = new ArrayList<>(contacts.size());
|
||||
for (Contact c : contacts) if (c.isActive()) active.add(c);
|
||||
return active;
|
||||
@@ -120,7 +147,13 @@ class ContactManagerImpl implements ContactManager {
|
||||
|
||||
@Override
|
||||
public void removeContact(ContactId c) throws DbException {
|
||||
db.transaction(false, txn -> removeContact(txn, c));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
removeContact(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,20 +163,14 @@ class ContactManagerImpl implements ContactManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContactAlias(Transaction txn, ContactId c,
|
||||
@Nullable String alias) throws DbException {
|
||||
public void setContactAlias(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));
|
||||
db.transaction(false, txn -> db.setContactAlias(txn, c, alias));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,8 +182,15 @@ class ContactManagerImpl implements ContactManager {
|
||||
@Override
|
||||
public boolean contactExists(AuthorId remoteAuthorId,
|
||||
AuthorId localAuthorId) throws DbException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
contactExists(txn, remoteAuthorId, localAuthorId));
|
||||
boolean exists;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
exists = contactExists(txn, remoteAuthorId, localAuthorId);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -29,7 +29,6 @@ import static org.briarproject.bramble.data.Types.STRING_16;
|
||||
import static org.briarproject.bramble.data.Types.STRING_32;
|
||||
import static org.briarproject.bramble.data.Types.STRING_8;
|
||||
import static org.briarproject.bramble.data.Types.TRUE;
|
||||
import static org.briarproject.bramble.util.StringUtils.fromUtf8;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
@@ -254,7 +253,7 @@ class BdfReaderImpl implements BdfReader {
|
||||
if (length < 0 || length > maxBufferSize) throw new FormatException();
|
||||
if (length == 0) return "";
|
||||
readIntoBuffer(length);
|
||||
return fromUtf8(buf, 0, length);
|
||||
return new String(buf, 0, length, "UTF-8");
|
||||
}
|
||||
|
||||
private int readStringLength() throws IOException {
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||
import org.briarproject.bramble.api.transport.KeySet;
|
||||
import org.briarproject.bramble.api.transport.KeySetId;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
@@ -106,7 +106,7 @@ interface Database<T> {
|
||||
* @param sender the contact from whom the message was received, or null
|
||||
* if the message was created locally.
|
||||
*/
|
||||
void addMessage(T txn, Message m, MessageState state, boolean shared,
|
||||
void addMessage(T txn, Message m, State state, boolean shared,
|
||||
@Nullable ContactId sender) throws DbException;
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ interface Database<T> {
|
||||
* in the given state.
|
||||
*/
|
||||
void addMessageDependency(T txn, Message dependent, MessageId dependency,
|
||||
MessageState dependentState) throws DbException;
|
||||
State dependentState) throws DbException;
|
||||
|
||||
/**
|
||||
* Records that a message has been offered by the given contact.
|
||||
@@ -310,11 +310,11 @@ interface Database<T> {
|
||||
/**
|
||||
* Returns the IDs and states of all dependencies of the given message.
|
||||
* For missing dependencies and dependencies in other groups, the state
|
||||
* {@link MessageState UNKNOWN} is returned.
|
||||
* {@link State UNKNOWN} is returned.
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
Map<MessageId, MessageState> getMessageDependencies(T txn, MessageId m)
|
||||
Map<MessageId, State> getMessageDependencies(T txn, MessageId m)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
@@ -324,7 +324,7 @@ interface Database<T> {
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
Map<MessageId, MessageState> getMessageDependents(T txn, MessageId m)
|
||||
Map<MessageId, State> getMessageDependents(T txn, MessageId m)
|
||||
throws DbException;
|
||||
|
||||
/**
|
||||
@@ -383,7 +383,7 @@ interface Database<T> {
|
||||
* <p/>
|
||||
* Read-only.
|
||||
*/
|
||||
MessageState getMessageState(T txn, MessageId m) throws DbException;
|
||||
State getMessageState(T txn, MessageId m) throws DbException;
|
||||
|
||||
/**
|
||||
* Returns the status of all delivered messages in the given group with
|
||||
@@ -637,8 +637,7 @@ interface Database<T> {
|
||||
/**
|
||||
* Sets the validation and delivery state of the given message.
|
||||
*/
|
||||
void setMessageState(T txn, MessageId m, MessageState state)
|
||||
throws DbException;
|
||||
void setMessageState(T txn, MessageId m, State state) throws DbException;
|
||||
|
||||
/**
|
||||
* Sets the reordering window for the given key set and transport in the
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
|
||||
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
|
||||
import org.briarproject.bramble.api.db.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;
|
||||
@@ -43,6 +42,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.MessageStatus;
|
||||
import org.briarproject.bramble.api.sync.Offer;
|
||||
import org.briarproject.bramble.api.sync.Request;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
|
||||
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
|
||||
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
|
||||
@@ -54,7 +54,6 @@ import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
|
||||
import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
|
||||
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
|
||||
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
import org.briarproject.bramble.api.transport.KeySet;
|
||||
import org.briarproject.bramble.api.transport.KeySetId;
|
||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||
@@ -75,8 +74,8 @@ import javax.inject.Inject;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
@@ -194,20 +193,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R, E extends Exception> R transactionWithNullableResult(
|
||||
boolean readOnly, NullableDbCallable<R, E> task)
|
||||
throws DbException, E {
|
||||
Transaction txn = startTransaction(readOnly);
|
||||
try {
|
||||
R result = task.call(txn);
|
||||
commitTransaction(txn);
|
||||
return result;
|
||||
} finally {
|
||||
endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
private T unbox(Transaction transaction) {
|
||||
if (transaction.isCommitted()) throw new IllegalStateException();
|
||||
return txnClass.cast(transaction.unbox());
|
||||
@@ -579,7 +564,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageState getMessageState(Transaction transaction, MessageId m)
|
||||
public State getMessageState(Transaction transaction, MessageId m)
|
||||
throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsMessage(txn, m))
|
||||
@@ -619,8 +604,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MessageId, MessageState> getMessageDependencies(
|
||||
Transaction transaction, MessageId m) throws DbException {
|
||||
public Map<MessageId, State> getMessageDependencies(Transaction transaction,
|
||||
MessageId m) throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsMessage(txn, m))
|
||||
throw new NoSuchMessageException();
|
||||
@@ -628,8 +613,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MessageId, MessageState> getMessageDependents(
|
||||
Transaction transaction, MessageId m) throws DbException {
|
||||
public Map<MessageId, State> getMessageDependents(Transaction transaction,
|
||||
MessageId m) throws DbException {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsMessage(txn, m))
|
||||
throw new NoSuchMessageException();
|
||||
@@ -876,7 +861,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
|
||||
@Override
|
||||
public void setContactAlias(Transaction transaction, ContactId c,
|
||||
@Nullable String alias) throws DbException {
|
||||
String alias) throws DbException {
|
||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsContact(txn, c))
|
||||
@@ -918,7 +903,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
|
||||
@Override
|
||||
public void setMessageState(Transaction transaction, MessageId m,
|
||||
MessageState state) throws DbException {
|
||||
State state) throws DbException {
|
||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsMessage(txn, m))
|
||||
@@ -935,10 +920,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
||||
T txn = unbox(transaction);
|
||||
if (!db.containsMessage(txn, dependent.getId()))
|
||||
throw new NoSuchMessageException();
|
||||
MessageState dependentState =
|
||||
db.getMessageState(txn, dependent.getId());
|
||||
State dependentState = db.getMessageState(txn, dependent.getId());
|
||||
for (MessageId dependency : dependencies) {
|
||||
db.addMessageDependency(txn, dependent, dependency, dependentState);
|
||||
db.addMessageDependency(txn, dependent, dependency,
|
||||
dependentState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package org.briarproject.bramble.db;
|
||||
class DatabaseTypes {
|
||||
|
||||
private final String hashType, secretType, binaryType;
|
||||
private final String counterType, stringType;
|
||||
private final String counterType, stringType;
|
||||
|
||||
public DatabaseTypes(String hashType, String secretType, String binaryType,
|
||||
String counterType, String stringType) {
|
||||
@@ -17,11 +17,11 @@ class DatabaseTypes {
|
||||
/**
|
||||
* 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
|
||||
* <li> _HASH
|
||||
* <li> _SECRET
|
||||
* <li> _BINARY
|
||||
* <li> _COUNTER
|
||||
* <li> _STRING
|
||||
*/
|
||||
String replaceTypes(String s) {
|
||||
s = s.replaceAll("_HASH", hashType);
|
||||
|
||||
@@ -15,23 +15,16 @@ import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
||||
|
||||
/**
|
||||
* Contains all the H2-specific code for the database.
|
||||
*/
|
||||
@NotNullByDefault
|
||||
class H2Database extends JdbcDatabase {
|
||||
|
||||
private static final Logger LOG = getLogger(H2Database.class.getName());
|
||||
|
||||
private static final String HASH_TYPE = "BINARY(32)";
|
||||
private static final String SECRET_TYPE = "BINARY(32)";
|
||||
private static final String BINARY_TYPE = "BINARY";
|
||||
@@ -128,8 +121,8 @@ class H2Database extends JdbcDatabase {
|
||||
s.close();
|
||||
c.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
tryToClose(c, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
tryToClose(c);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,24 +14,16 @@ import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
||||
|
||||
/**
|
||||
* Contains all the HSQLDB-specific code for the database.
|
||||
*/
|
||||
@NotNullByDefault
|
||||
class HyperSqlDatabase extends JdbcDatabase {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(HyperSqlDatabase.class.getName());
|
||||
|
||||
private static final String HASH_TYPE = "BINARY(32)";
|
||||
private static final String SECRET_TYPE = "BINARY(32)";
|
||||
private static final String BINARY_TYPE = "BINARY";
|
||||
@@ -80,8 +72,8 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
s.close();
|
||||
c.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
tryToClose(c, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
tryToClose(c);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -130,8 +122,8 @@ class HyperSqlDatabase extends JdbcDatabase {
|
||||
s.close();
|
||||
c.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
tryToClose(c, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
tryToClose(c);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,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.api.sync.MessageStatus;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.State;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||
import org.briarproject.bramble.api.transport.KeySet;
|
||||
@@ -64,15 +64,14 @@ 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;
|
||||
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.PENDING;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.LAST_COMPACTED_KEY;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_COMPACTION_INTERVAL_MS;
|
||||
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.bramble.util.LogUtils.now;
|
||||
@@ -459,6 +458,30 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
mergeSettings(txn, s, DB_SETTINGS_NAMESPACE);
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable ResultSet rs) {
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
} catch (SQLException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void tryToClose(@Nullable Statement s) {
|
||||
try {
|
||||
if (s != null) s.close();
|
||||
} catch (SQLException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void tryToClose(@Nullable Connection c) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
} catch (SQLException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void createTables(Connection txn) throws DbException {
|
||||
Statement s = null;
|
||||
try {
|
||||
@@ -479,7 +502,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
s.executeUpdate(dbTypes.replaceTypes(CREATE_INCOMING_KEYS));
|
||||
s.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -496,7 +519,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP);
|
||||
s.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -543,7 +566,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
} catch (SQLException e) {
|
||||
// Try to close the connection
|
||||
logException(LOG, WARNING, e);
|
||||
tryToClose(txn, LOG, WARNING);
|
||||
try {
|
||||
txn.close();
|
||||
} catch (SQLException e1) {
|
||||
logException(LOG, WARNING, e1);
|
||||
}
|
||||
// Whatever happens, allow the database to close
|
||||
connectionsLock.lock();
|
||||
try {
|
||||
@@ -632,8 +659,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return c;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -654,7 +681,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -677,7 +704,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
// Create a status row for each message in the group
|
||||
addStatus(txn, c, g, groupShared);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -697,7 +724,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
while (rs.next()) {
|
||||
MessageId id = new MessageId(rs.getBytes(1));
|
||||
long timestamp = rs.getLong(2);
|
||||
MessageState state = MessageState.fromValue(rs.getInt(3));
|
||||
State state = State.fromValue(rs.getInt(3));
|
||||
boolean messageShared = rs.getBoolean(4);
|
||||
int length = rs.getInt(5);
|
||||
boolean deleted = rs.getBoolean(6);
|
||||
@@ -708,8 +735,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
rs.close();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -734,13 +761,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessage(Connection txn, Message m, MessageState state,
|
||||
public void addMessage(Connection txn, Message m, State state,
|
||||
boolean messageShared, @Nullable ContactId sender)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -783,7 +810,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -813,14 +840,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void addStatus(Connection txn, MessageId m, ContactId c, GroupId g,
|
||||
long timestamp, int length, MessageState state, boolean groupShared,
|
||||
long timestamp, int length, State state, boolean groupShared,
|
||||
boolean messageShared, boolean deleted, boolean seen)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
@@ -846,15 +873,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMessageDependency(Connection txn, Message dependent,
|
||||
MessageId dependency, MessageState dependentState)
|
||||
throws DbException {
|
||||
MessageId dependency, State dependentState) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
@@ -865,9 +891,9 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.setBytes(1, dependency.getBytes());
|
||||
ps.setBytes(2, dependent.getGroupId().getBytes());
|
||||
rs = ps.executeQuery();
|
||||
MessageState dependencyState = null;
|
||||
State dependencyState = null;
|
||||
if (rs.next()) {
|
||||
dependencyState = MessageState.fromValue(rs.getInt(1));
|
||||
dependencyState = State.fromValue(rs.getInt(1));
|
||||
if (rs.next()) throw new DbStateException();
|
||||
}
|
||||
rs.close();
|
||||
@@ -888,8 +914,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -908,7 +934,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -988,8 +1014,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return keySetId;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1012,8 +1038,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1034,8 +1060,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1056,8 +1082,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1078,8 +1104,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1100,8 +1126,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1122,8 +1148,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1147,8 +1173,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return found;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1171,8 +1197,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return count;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1196,7 +1222,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1213,7 +1239,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1246,8 +1272,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
return new Contact(c, author, localAuthorId, alias, verified,
|
||||
active);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1283,8 +1309,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return contacts;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1306,8 +1332,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1344,8 +1370,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return contacts;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1368,8 +1394,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return new Group(g, clientId, majorVersion, descriptor);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1396,8 +1422,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return groups;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1422,8 +1448,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return v;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1446,8 +1472,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return visible;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1478,8 +1504,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return localAuthor;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1510,8 +1536,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return authors;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1539,8 +1565,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length);
|
||||
return new Message(m, g, timestamp, body);
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1563,8 +1589,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1601,8 +1627,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (intersection == null) throw new AssertionError();
|
||||
return intersection;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1634,8 +1660,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return all;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1669,8 +1695,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return metadata;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1693,8 +1719,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return metadata;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1719,8 +1745,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return metadata;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1749,8 +1775,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return statuses;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1780,14 +1806,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return status;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MessageId, MessageState> getMessageDependencies(Connection txn,
|
||||
public Map<MessageId, State> getMessageDependencies(Connection txn,
|
||||
MessageId m) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -1798,10 +1824,10 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
Map<MessageId, MessageState> dependencies = new HashMap<>();
|
||||
Map<MessageId, State> dependencies = new HashMap<>();
|
||||
while (rs.next()) {
|
||||
MessageId dependency = new MessageId(rs.getBytes(1));
|
||||
MessageState state = MessageState.fromValue(rs.getInt(2));
|
||||
State state = State.fromValue(rs.getInt(2));
|
||||
if (rs.wasNull())
|
||||
state = UNKNOWN; // Missing or in a different group
|
||||
dependencies.put(dependency, state);
|
||||
@@ -1810,14 +1836,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return dependencies;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MessageId, MessageState> getMessageDependents(Connection txn,
|
||||
public Map<MessageId, State> getMessageDependents(Connection txn,
|
||||
MessageId m) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -1831,24 +1857,24 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps = txn.prepareStatement(sql);
|
||||
ps.setBytes(1, m.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
Map<MessageId, MessageState> dependents = new HashMap<>();
|
||||
Map<MessageId, State> dependents = new HashMap<>();
|
||||
while (rs.next()) {
|
||||
MessageId dependent = new MessageId(rs.getBytes(1));
|
||||
MessageState state = MessageState.fromValue(rs.getInt(2));
|
||||
State state = State.fromValue(rs.getInt(2));
|
||||
dependents.put(dependent, state);
|
||||
}
|
||||
rs.close();
|
||||
ps.close();
|
||||
return dependents;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageState getMessageState(Connection txn, MessageId m)
|
||||
public State getMessageState(Connection txn, MessageId m)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
@@ -1858,14 +1884,14 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.setBytes(1, m.getBytes());
|
||||
rs = ps.executeQuery();
|
||||
if (!rs.next()) throw new DbStateException();
|
||||
MessageState state = MessageState.fromValue(rs.getInt(1));
|
||||
State state = State.fromValue(rs.getInt(1));
|
||||
if (rs.next()) throw new DbStateException();
|
||||
rs.close();
|
||||
ps.close();
|
||||
return state;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1889,8 +1915,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1923,8 +1949,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1948,8 +1974,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -1987,8 +2013,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2006,7 +2032,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
|
||||
private Collection<MessageId> getMessagesInState(Connection txn,
|
||||
MessageState state) throws DbException {
|
||||
State state) throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
@@ -2021,8 +2047,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2049,8 +2075,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2079,8 +2105,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return nextSendTime;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2118,8 +2144,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return ids;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2141,8 +2167,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return s;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2207,8 +2233,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return keys;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2227,7 +2253,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2254,7 +2280,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2281,7 +2307,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2311,7 +2337,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2333,7 +2359,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
rs = ps.executeQuery();
|
||||
if (!rs.next()) throw new DbStateException();
|
||||
GroupId g = new GroupId(rs.getBytes(1));
|
||||
MessageState state = MessageState.fromValue(rs.getInt(2));
|
||||
State state = State.fromValue(rs.getInt(2));
|
||||
rs.close();
|
||||
ps.close();
|
||||
// Insert any keys that don't already exist
|
||||
@@ -2356,8 +2382,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2423,7 +2449,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
}
|
||||
return added;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2470,7 +2496,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2489,7 +2515,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2508,7 +2534,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2527,7 +2553,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2544,7 +2570,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2560,7 +2586,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2588,7 +2614,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2605,7 +2631,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2621,7 +2647,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2640,7 +2666,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
ps.close();
|
||||
return affected == 1;
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2665,7 +2691,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (rows != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2682,7 +2708,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2703,7 +2729,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2722,7 +2748,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2740,7 +2766,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2758,7 +2784,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2777,7 +2803,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2807,7 +2833,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2833,13 +2859,13 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMessageState(Connection txn, MessageId m, MessageState state)
|
||||
public void setMessageState(Connection txn, MessageId m, State state)
|
||||
throws DbException {
|
||||
PreparedStatement ps = null;
|
||||
try {
|
||||
@@ -2886,7 +2912,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2909,7 +2935,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2928,7 +2954,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected < 0 || affected > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -2964,8 +2990,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (affected != 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(rs, LOG, WARNING);
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(rs);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
@@ -3032,7 +3058,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
||||
if (rows < 0 || rows > 1) throw new DbStateException();
|
||||
ps.close();
|
||||
} catch (SQLException e) {
|
||||
tryToClose(ps, LOG, WARNING);
|
||||
tryToClose(ps);
|
||||
throw new DbException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package org.briarproject.bramble.db;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
class JdbcUtils {
|
||||
|
||||
static void tryToClose(@Nullable ResultSet rs, Logger logger, Level level) {
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
} catch (SQLException e) {
|
||||
logException(logger, level, e);
|
||||
}
|
||||
}
|
||||
|
||||
static void tryToClose(@Nullable Statement s, Logger logger, Level level) {
|
||||
try {
|
||||
if (s != null) s.close();
|
||||
} catch (SQLException e) {
|
||||
logException(logger, level, e);
|
||||
}
|
||||
}
|
||||
|
||||
static void tryToClose(@Nullable Connection c, Logger logger, Level level) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
} catch (SQLException e) {
|
||||
logException(logger, level, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,10 @@ import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
class Migration38_39 implements Migration<Connection> {
|
||||
|
||||
@@ -38,8 +40,16 @@ class Migration38_39 implements Migration<Connection> {
|
||||
+ " ALTER COLUMN contactId"
|
||||
+ " SET NOT NULL");
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,10 @@ 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 org.briarproject.bramble.db.JdbcUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
class Migration39_40 implements Migration<Connection> {
|
||||
|
||||
@@ -37,8 +39,16 @@ class Migration39_40 implements Migration<Connection> {
|
||||
+ " ALTER COLUMN eta"
|
||||
+ " SET NOT NULL");
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,11 @@ 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.db.JdbcUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
class Migration40_41 implements Migration<Connection> {
|
||||
|
||||
@@ -37,10 +39,18 @@ class Migration40_41 implements Migration<Connection> {
|
||||
try {
|
||||
s = txn.createStatement();
|
||||
s.execute("ALTER TABLE contacts"
|
||||
+ dbTypes.replaceTypes(" ADD alias _STRING"));
|
||||
+ dbTypes.replaceTypes(" ADD alias VARCHAR"));
|
||||
} catch (SQLException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,16 +67,27 @@ class IdentityManagerImpl implements IdentityManager {
|
||||
LOG.info("No local author to store");
|
||||
return;
|
||||
}
|
||||
db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
|
||||
LOG.info("Local author stored");
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.addLocalAuthor(txn, cached);
|
||||
db.commitTransaction(txn);
|
||||
LOG.info("Local author stored");
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalAuthor getLocalAuthor() throws DbException {
|
||||
if (cachedAuthor == null) {
|
||||
cachedAuthor =
|
||||
db.transactionWithResult(true, this::loadLocalAuthor);
|
||||
LOG.info("Local author loaded");
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
cachedAuthor = loadLocalAuthor(txn);
|
||||
LOG.info("Local author loaded");
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
LocalAuthor cached = cachedAuthor;
|
||||
if (cached == null) throw new AssertionError();
|
||||
|
||||
@@ -6,6 +6,7 @@ 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;
|
||||
@@ -114,16 +115,20 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
||||
dbLatch.countDown();
|
||||
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
|
||||
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
for (Client c : clients) {
|
||||
long start1 = now();
|
||||
start = now();
|
||||
c.createLocalState(txn);
|
||||
if (LOG.isLoggable(FINE)) {
|
||||
logDuration(LOG, "Starting client "
|
||||
+ c.getClass().getSimpleName(), start1);
|
||||
+ c.getClass().getSimpleName(), start);
|
||||
}
|
||||
}
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
for (Service s : services) {
|
||||
start = now();
|
||||
s.startService();
|
||||
|
||||
@@ -4,11 +4,12 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
class FileTransportReader implements TransportConnectionReader {
|
||||
@@ -33,7 +34,11 @@ class FileTransportReader implements TransportConnectionReader {
|
||||
|
||||
@Override
|
||||
public void dispose(boolean exception, boolean recognised) {
|
||||
tryToClose(in, LOG, WARNING);
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
plugin.readerFinished(file, exception, recognised);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@NotNullByDefault
|
||||
class FileTransportWriter implements TransportConnectionWriter {
|
||||
@@ -43,7 +44,11 @@ class FileTransportWriter implements TransportConnectionWriter {
|
||||
|
||||
@Override
|
||||
public void dispose(boolean exception) {
|
||||
tryToClose(out, LOG, WARNING);
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
plugin.writerFinished(file, exception);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.bramble.api.settings.Settings;
|
||||
import org.briarproject.bramble.util.IoUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -36,6 +35,7 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
|
||||
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
||||
|
||||
@NotNullByDefault
|
||||
@@ -293,7 +293,11 @@ class LanTcpPlugin extends TcpPlugin {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
||||
try {
|
||||
ss.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||
import org.briarproject.bramble.util.IoUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -154,8 +153,13 @@ abstract class TcpPlugin implements DuplexPlugin {
|
||||
}
|
||||
|
||||
protected void tryToClose(@Nullable ServerSocket ss) {
|
||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
||||
callback.transportDisabled();
|
||||
try {
|
||||
if (ss != null) ss.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
} finally {
|
||||
callback.transportDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
String getIpPortString(InetSocketAddress a) {
|
||||
|
||||
@@ -4,8 +4,6 @@ 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;
|
||||
@@ -31,6 +29,7 @@ import org.briarproject.bramble.api.system.LocationUtils;
|
||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||
import org.briarproject.bramble.util.IoUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
@@ -97,14 +96,13 @@ 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, obfs4File, configFile;
|
||||
private final File torDirectory, torFile, geoIpFile, configFile;
|
||||
private final File doneFile, cookieFile;
|
||||
private final ConnectionStatus connectionStatus;
|
||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||
@@ -123,8 +121,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||
Clock clock, ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider,
|
||||
BatteryManager batteryManager, Backoff backoff,
|
||||
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||
int maxIdleTime, File torDirectory) {
|
||||
this.ioExecutor = ioExecutor;
|
||||
@@ -134,7 +131,6 @@ 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;
|
||||
@@ -146,7 +142,6 @@ 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");
|
||||
@@ -265,8 +260,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
throw new PluginException(e);
|
||||
}
|
||||
// Check whether we're online
|
||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
||||
batteryManager.isCharging());
|
||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||
// Bind a server socket to receive incoming hidden service connections
|
||||
bind();
|
||||
}
|
||||
@@ -290,20 +284,14 @@ 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);
|
||||
IoUtils.copyAndClose(in, out);
|
||||
doneFile.createNewFile();
|
||||
} catch (IOException e) {
|
||||
IoUtils.tryToClose(in, LOG, WARNING);
|
||||
IoUtils.tryToClose(out, LOG, WARNING);
|
||||
tryToClose(in);
|
||||
tryToClose(out);
|
||||
throw new PluginException(e);
|
||||
}
|
||||
}
|
||||
@@ -326,20 +314,26 @@ 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");
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable Closeable c) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable Socket s) {
|
||||
try {
|
||||
if (s != null) s.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void listFiles(File f) {
|
||||
if (f.isDirectory()) {
|
||||
File[] children = f.listFiles();
|
||||
@@ -361,7 +355,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
return b;
|
||||
} finally {
|
||||
IoUtils.tryToClose(in, LOG, WARNING);
|
||||
tryToClose(in);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,8 +395,13 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable ServerSocket ss) {
|
||||
IoUtils.tryToClose(ss, LOG, WARNING);
|
||||
callback.transportDisabled();
|
||||
try {
|
||||
if (ss != null) ss.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
} finally {
|
||||
callback.transportDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
private void publishHiddenService(String port) {
|
||||
@@ -473,8 +472,6 @@ 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 {
|
||||
@@ -571,7 +568,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
LOG.info("Could not connect to " + scrubOnion(bestOnion)
|
||||
+ ": " + e.toString());
|
||||
}
|
||||
IoUtils.tryToClose(s, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -612,8 +609,7 @@ 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(),
|
||||
batteryManager.isCharging());
|
||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,15 +647,10 @@ 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(),
|
||||
batteryManager.isCharging());
|
||||
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||
}
|
||||
} else if (e instanceof NetworkStatusEvent) {
|
||||
updateConnectionStatus(((NetworkStatusEvent) e).getStatus(),
|
||||
batteryManager.isCharging());
|
||||
} else if (e instanceof BatteryEvent) {
|
||||
updateConnectionStatus(networkManager.getNetworkStatus(),
|
||||
((BatteryEvent) e).isCharging());
|
||||
updateConnectionStatus(((NetworkStatusEvent) e).getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -673,8 +664,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||
});
|
||||
}
|
||||
|
||||
private void updateConnectionStatus(NetworkStatus status,
|
||||
boolean charging) {
|
||||
private void updateConnectionStatus(NetworkStatus status) {
|
||||
connectionStatusExecutor.execute(() -> {
|
||||
if (!running) return;
|
||||
boolean online = status.isConnected();
|
||||
@@ -692,7 +682,6 @@ 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 {
|
||||
@@ -716,24 +705,12 @@ 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();
|
||||
|
||||
@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
|
||||
@@ -142,7 +142,15 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@Override
|
||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||
throws DbException {
|
||||
return db.transactionWithResult(true, this::getLocalProperties);
|
||||
Map<TransportId, TransportProperties> local;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
local = getLocalProperties(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return local;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,8 +176,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
public TransportProperties getLocalProperties(TransportId t)
|
||||
throws DbException {
|
||||
try {
|
||||
return db.transactionWithResult(true, txn -> {
|
||||
TransportProperties p = null;
|
||||
TransportProperties p = null;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
// Find the latest local update
|
||||
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
|
||||
true);
|
||||
@@ -179,8 +188,11 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
latest.messageId);
|
||||
p = parseProperties(message);
|
||||
}
|
||||
return p == null ? new TransportProperties() : p;
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return p == null ? new TransportProperties() : p;
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
@@ -189,12 +201,16 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@Override
|
||||
public Map<ContactId, TransportProperties> getRemoteProperties(
|
||||
TransportId t) throws DbException {
|
||||
return db.transactionWithResult(true, txn -> {
|
||||
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
||||
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
for (Contact c : db.getContacts(txn))
|
||||
remote.put(c.getId(), getRemoteProperties(txn, c, t));
|
||||
return remote;
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return remote;
|
||||
}
|
||||
|
||||
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
||||
@@ -218,15 +234,23 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
@Override
|
||||
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
|
||||
throws DbException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
getRemoteProperties(txn, db.getContact(txn, c), t));
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
||||
throws DbException {
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// Merge the new properties with any existing properties
|
||||
TransportProperties merged;
|
||||
boolean changed;
|
||||
@@ -263,7 +287,10 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||
db.removeMessage(txn, latest.messageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (FormatException e) {
|
||||
throw new DbException(e);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.briarproject.bramble.api.reporting.DevReporter;
|
||||
import org.briarproject.bramble.util.IoUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@@ -25,12 +26,13 @@ import java.net.Socket;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
@@ -64,7 +66,7 @@ class DevReporterImpl implements DevReporter, EventListener {
|
||||
s.setSoTimeout(SOCKET_TIMEOUT);
|
||||
return s;
|
||||
} catch (IOException e) {
|
||||
tryToClose(s, LOG, WARNING);
|
||||
tryToClose(s);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@@ -86,7 +88,8 @@ class DevReporterImpl implements DevReporter, EventListener {
|
||||
writer.append(armoured);
|
||||
writer.flush();
|
||||
} finally {
|
||||
tryToClose(writer, LOG, WARNING);
|
||||
if (writer != null)
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,11 +121,27 @@ class DevReporterImpl implements DevReporter, EventListener {
|
||||
f.delete();
|
||||
} catch (IOException e) {
|
||||
LOG.log(WARNING, "Failed to send reports", e);
|
||||
tryToClose(out, LOG, WARNING);
|
||||
tryToClose(in, LOG, WARNING);
|
||||
tryToClose(out);
|
||||
tryToClose(in);
|
||||
return;
|
||||
}
|
||||
}
|
||||
LOG.info("Reports sent");
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable Closeable c) {
|
||||
try {
|
||||
if (c != null) c.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToClose(@Nullable Socket s) {
|
||||
try {
|
||||
if (s != null) s.close();
|
||||
} catch (IOException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,15 @@ class SettingsManagerImpl implements SettingsManager {
|
||||
|
||||
@Override
|
||||
public Settings getSettings(String namespace) throws DbException {
|
||||
return db.transactionWithResult(true, txn ->
|
||||
db.getSettings(txn, namespace));
|
||||
Settings s;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
s = db.getSettings(txn, namespace);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -35,6 +42,12 @@ class SettingsManagerImpl implements SettingsManager {
|
||||
|
||||
@Override
|
||||
public void mergeSettings(Settings s, String namespace) throws DbException {
|
||||
db.transaction(false, txn -> db.mergeSettings(txn, s, namespace));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.mergeSettings(txn, s, namespace);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.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;
|
||||
@@ -229,8 +230,14 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (interrupted) return;
|
||||
if (!generateAckQueued.getAndSet(false)) throw new AssertionError();
|
||||
try {
|
||||
Ack a = db.transactionWithNullableResult(false, txn ->
|
||||
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
|
||||
Ack a;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated ack: " + (a != null));
|
||||
if (a != null) writerTasks.add(new WriteAck(a));
|
||||
@@ -268,15 +275,16 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (!generateBatchQueued.getAndSet(false))
|
||||
throw new AssertionError();
|
||||
try {
|
||||
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;
|
||||
});
|
||||
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);
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated batch: " + (b != null));
|
||||
if (b != null) writerTasks.add(new WriteBatch(b));
|
||||
@@ -314,12 +322,16 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (!generateOfferQueued.getAndSet(false))
|
||||
throw new AssertionError();
|
||||
try {
|
||||
Offer o = db.transactionWithNullableResult(false, txn -> {
|
||||
Offer offer = db.generateOffer(txn, contactId,
|
||||
MAX_MESSAGE_IDS, maxLatency);
|
||||
Offer o;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
o = db.generateOffer(txn, contactId, MAX_MESSAGE_IDS,
|
||||
maxLatency);
|
||||
setNextSendTime(db.getNextSendTime(txn, contactId));
|
||||
return offer;
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated offer: " + (o != null));
|
||||
if (o != null) writerTasks.add(new WriteOffer(o));
|
||||
@@ -357,8 +369,14 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
||||
if (!generateRequestQueued.getAndSet(false))
|
||||
throw new AssertionError();
|
||||
try {
|
||||
Request r = db.transactionWithNullableResult(false, txn ->
|
||||
db.generateRequest(txn, contactId, MAX_MESSAGE_IDS));
|
||||
Request r;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
r = db.generateRequest(txn, contactId, MAX_MESSAGE_IDS);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated request: " + (r != null));
|
||||
if (r != null) writerTasks.add(new WriteRequest(r));
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.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;
|
||||
@@ -119,8 +120,13 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
db.transaction(false, txn ->
|
||||
db.receiveAck(txn, contactId, ack));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveAck(txn, contactId, ack);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
@@ -140,8 +146,13 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
db.transaction(false, txn ->
|
||||
db.receiveMessage(txn, contactId, message));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveMessage(txn, contactId, message);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
@@ -161,8 +172,13 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
db.transaction(false, txn ->
|
||||
db.receiveOffer(txn, contactId, offer));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveOffer(txn, contactId, offer);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
@@ -182,8 +198,13 @@ class IncomingSession implements SyncSession, EventListener {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
db.transaction(false, txn ->
|
||||
db.receiveRequest(txn, contactId, request));
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
db.receiveRequest(txn, contactId, request);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
interrupt();
|
||||
|
||||
@@ -7,7 +7,6 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
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.api.sync.tree.TreeHash;
|
||||
import org.briarproject.bramble.util.ByteUtils;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
@@ -40,19 +39,13 @@ class MessageFactoryImpl implements MessageFactory {
|
||||
if (body.length == 0) throw new IllegalArgumentException();
|
||||
if (body.length > MAX_MESSAGE_BODY_LENGTH)
|
||||
throw new IllegalArgumentException();
|
||||
MessageId id = getMessageIdFromBody(g, timestamp, body);
|
||||
MessageId id = getMessageId(g, timestamp, body);
|
||||
return new Message(id, g, timestamp, body);
|
||||
}
|
||||
|
||||
private MessageId getMessageIdFromBody(GroupId g, long timestamp,
|
||||
byte[] body) {
|
||||
private MessageId getMessageId(GroupId g, long timestamp, byte[] body) {
|
||||
// There's only one block, so the root hash is the hash of the block
|
||||
byte[] rootHash = crypto.hash(BLOCK_LABEL, FORMAT_VERSION_BYTES, body);
|
||||
return getMessageIdFromRootHash(g, timestamp, rootHash);
|
||||
}
|
||||
|
||||
private MessageId getMessageIdFromRootHash(GroupId g, long timestamp,
|
||||
byte[] rootHash) {
|
||||
byte[] timeBytes = new byte[INT_64_BYTES];
|
||||
ByteUtils.writeUint64(timestamp, timeBytes, 0);
|
||||
byte[] idHash = crypto.hash(ID_LABEL, FORMAT_VERSION_BYTES,
|
||||
@@ -72,7 +65,7 @@ class MessageFactoryImpl implements MessageFactory {
|
||||
long timestamp = ByteUtils.readUint64(raw, UniqueId.LENGTH);
|
||||
byte[] body = new byte[raw.length - MESSAGE_HEADER_LENGTH];
|
||||
System.arraycopy(raw, MESSAGE_HEADER_LENGTH, body, 0, body.length);
|
||||
MessageId id = getMessageIdFromBody(g, timestamp, body);
|
||||
MessageId id = getMessageId(g, timestamp, body);
|
||||
return new Message(id, g, timestamp, body);
|
||||
}
|
||||
|
||||
@@ -85,10 +78,4 @@ class MessageFactoryImpl implements MessageFactory {
|
||||
System.arraycopy(body, 0, raw, MESSAGE_HEADER_LENGTH, body.length);
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageId getMessageId(GroupId g, long timestamp,
|
||||
TreeHash rootHash) {
|
||||
return getMessageIdFromRootHash(g, timestamp, rootHash.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.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;
|
||||
@@ -46,8 +47,7 @@ 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,8 +128,14 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
||||
public void run() {
|
||||
if (interrupted) return;
|
||||
try {
|
||||
Ack a = db.transactionWithNullableResult(false, txn ->
|
||||
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
|
||||
Ack a;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated ack: " + (a != null));
|
||||
if (a == null) decrementOutstandingQueries();
|
||||
@@ -166,10 +172,15 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
||||
public void run() {
|
||||
if (interrupted) return;
|
||||
try {
|
||||
Collection<Message> b =
|
||||
db.transactionWithNullableResult(false, txn ->
|
||||
db.generateBatch(txn, contactId,
|
||||
MAX_RECORD_PAYLOAD_BYTES, maxLatency));
|
||||
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);
|
||||
}
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Generated batch: " + (b != null));
|
||||
if (b == null) decrementOutstandingQueries();
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
package org.briarproject.bramble.sync;
|
||||
|
||||
import org.briarproject.bramble.PoliteExecutor;
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.GroupFactory;
|
||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||
import org.briarproject.bramble.api.sync.SyncRecordReaderFactory;
|
||||
import org.briarproject.bramble.api.sync.SyncRecordWriterFactory;
|
||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
@@ -14,14 +26,29 @@ import dagger.Provides;
|
||||
@Module
|
||||
public class SyncModule {
|
||||
|
||||
public static class EagerSingletons {
|
||||
@Inject
|
||||
ValidationManager validationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of validation tasks to delegate to the crypto
|
||||
* executor concurrently.
|
||||
* <p>
|
||||
* The number of available processors can change during the lifetime of the
|
||||
* JVM, so this is just a reasonable guess.
|
||||
*/
|
||||
private static final int MAX_CONCURRENT_VALIDATION_TASKS =
|
||||
Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
|
||||
|
||||
@Provides
|
||||
GroupFactory provideGroupFactory(GroupFactoryImpl groupFactory) {
|
||||
return groupFactory;
|
||||
GroupFactory provideGroupFactory(CryptoComponent crypto) {
|
||||
return new GroupFactoryImpl(crypto);
|
||||
}
|
||||
|
||||
@Provides
|
||||
MessageFactory provideMessageFactory(MessageFactoryImpl messageFactory) {
|
||||
return messageFactory;
|
||||
MessageFactory provideMessageFactory(CryptoComponent crypto) {
|
||||
return new MessageFactoryImpl(crypto);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -38,8 +65,30 @@ public class SyncModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
SyncSessionFactory provideSyncSessionFactory(
|
||||
SyncSessionFactoryImpl syncSessionFactory) {
|
||||
return syncSessionFactory;
|
||||
SyncSessionFactory provideSyncSessionFactory(DatabaseComponent db,
|
||||
@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
|
||||
Clock clock, SyncRecordReaderFactory recordReaderFactory,
|
||||
SyncRecordWriterFactory recordWriterFactory) {
|
||||
return new SyncSessionFactoryImpl(db, dbExecutor, eventBus, clock,
|
||||
recordReaderFactory, recordWriterFactory);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ValidationManager provideValidationManager(
|
||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||
ValidationManagerImpl validationManager) {
|
||||
lifecycleManager.registerService(validationManager);
|
||||
eventBus.addListener(validationManager);
|
||||
return validationManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ValidationExecutor
|
||||
Executor provideValidationExecutor(
|
||||
@CryptoExecutor Executor cryptoExecutor) {
|
||||
return new PoliteExecutor("ValidationExecutor", cryptoExecutor,
|
||||
MAX_CONCURRENT_VALIDATION_TASKS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.bramble.sync.validation;
|
||||
package org.briarproject.bramble.sync;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.briarproject.bramble.sync.validation;
|
||||
package org.briarproject.bramble.sync;
|
||||
|
||||
import org.briarproject.bramble.api.Pair;
|
||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DatabaseExecutor;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
@@ -18,11 +17,8 @@ import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageContext;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||
import org.briarproject.bramble.api.sync.event.MessageAddedEvent;
|
||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageState;
|
||||
import org.briarproject.bramble.api.sync.validation.MessageValidator;
|
||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
||||
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -40,9 +36,9 @@ import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.INVALID;
|
||||
import static org.briarproject.bramble.api.sync.validation.MessageState.PENDING;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@ThreadSafe
|
||||
@@ -101,8 +97,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void validateOutstandingMessages() {
|
||||
try {
|
||||
Queue<MessageId> unvalidated = new LinkedList<>(
|
||||
db.transactionWithResult(true, db::getMessagesToValidate));
|
||||
Queue<MessageId> unvalidated = new LinkedList<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
unvalidated.addAll(db.getMessagesToValidate(txn));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
validateNextMessageAsync(unvalidated);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -117,14 +119,18 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void validateNextMessage(Queue<MessageId> unvalidated) {
|
||||
try {
|
||||
Pair<Message, Group> mg = db.transactionWithResult(true, txn -> {
|
||||
Message m;
|
||||
Group g;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
MessageId id = unvalidated.poll();
|
||||
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());
|
||||
m = db.getMessage(txn, id);
|
||||
g = db.getGroup(txn, m.getGroupId());
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
validateMessageAsync(m, g);
|
||||
validateNextMessageAsync(unvalidated);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before validation");
|
||||
@@ -144,8 +150,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void deliverOutstandingMessages() {
|
||||
try {
|
||||
Queue<MessageId> pending = new LinkedList<>(
|
||||
db.transactionWithResult(true, db::getPendingMessages));
|
||||
Queue<MessageId> pending = new LinkedList<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
pending.addAll(db.getPendingMessages(txn));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
deliverNextPendingMessageAsync(pending);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -160,24 +172,24 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void deliverNextPendingMessage(Queue<MessageId> pending) {
|
||||
try {
|
||||
Queue<MessageId> toShare = new LinkedList<>();
|
||||
Queue<MessageId> invalidate = new LinkedList<>();
|
||||
db.transaction(false, txn -> {
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
Queue<MessageId> toShare = null;
|
||||
Queue<MessageId> invalidate = null;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
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
|
||||
Map<MessageId, MessageState> states =
|
||||
Map<MessageId, State> states =
|
||||
db.getMessageDependencies(txn, id);
|
||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
||||
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||
if (e.getValue() == INVALID) anyInvalid = true;
|
||||
if (e.getValue() != DELIVERED) allDelivered = false;
|
||||
}
|
||||
if (anyInvalid) {
|
||||
invalidateMessage(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
} else if (allDelivered) {
|
||||
Message m = db.getMessage(txn, id);
|
||||
Group g = db.getGroup(txn, m.getGroupId());
|
||||
@@ -188,19 +200,22 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
DeliveryResult result =
|
||||
deliverMessage(txn, m, c, majorVersion, meta);
|
||||
if (result.valid) {
|
||||
addPendingDependents(txn, id, pending);
|
||||
pending.addAll(getPendingDependents(txn, id));
|
||||
if (result.share) {
|
||||
db.setMessageShared(txn, id);
|
||||
toShare.addAll(states.keySet());
|
||||
toShare = new LinkedList<>(states.keySet());
|
||||
}
|
||||
} else {
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!invalidate.isEmpty()) invalidateNextMessageAsync(invalidate);
|
||||
if (!toShare.isEmpty()) shareNextMessageAsync(toShare);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (invalidate != null) invalidateNextMessageAsync(invalidate);
|
||||
if (toShare != null) shareNextMessageAsync(toShare);
|
||||
deliverNextPendingMessageAsync(pending);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before delivery");
|
||||
@@ -249,19 +264,20 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
MessageContext context) {
|
||||
try {
|
||||
MessageId id = m.getId();
|
||||
Queue<MessageId> invalidate = new LinkedList<>();
|
||||
Queue<MessageId> pending = new LinkedList<>();
|
||||
Queue<MessageId> toShare = new LinkedList<>();
|
||||
db.transaction(false, txn -> {
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
boolean anyInvalid = false, allDelivered = true;
|
||||
Queue<MessageId> invalidate = null;
|
||||
Queue<MessageId> pending = null;
|
||||
Queue<MessageId> toShare = null;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
// Check if message has any dependencies
|
||||
Collection<MessageId> dependencies = context.getDependencies();
|
||||
if (!dependencies.isEmpty()) {
|
||||
db.addMessageDependencies(txn, m, dependencies);
|
||||
// Check if dependencies are valid and delivered
|
||||
Map<MessageId, MessageState> states =
|
||||
Map<MessageId, State> states =
|
||||
db.getMessageDependencies(txn, id);
|
||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
||||
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||
if (e.getValue() == INVALID) anyInvalid = true;
|
||||
if (e.getValue() != DELIVERED) allDelivered = false;
|
||||
}
|
||||
@@ -269,7 +285,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
if (anyInvalid) {
|
||||
if (db.getMessageState(txn, id) != INVALID) {
|
||||
invalidateMessage(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
}
|
||||
} else {
|
||||
Metadata meta = context.getMetadata();
|
||||
@@ -278,22 +294,25 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
DeliveryResult result =
|
||||
deliverMessage(txn, m, c, majorVersion, meta);
|
||||
if (result.valid) {
|
||||
addPendingDependents(txn, id, pending);
|
||||
pending = getPendingDependents(txn, id);
|
||||
if (result.share) {
|
||||
db.setMessageShared(txn, id);
|
||||
toShare.addAll(dependencies);
|
||||
toShare = new LinkedList<>(dependencies);
|
||||
}
|
||||
} else {
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
invalidate = getDependentsToInvalidate(txn, id);
|
||||
}
|
||||
} else {
|
||||
db.setMessageState(txn, id, PENDING);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!invalidate.isEmpty()) invalidateNextMessageAsync(invalidate);
|
||||
if (!pending.isEmpty()) deliverNextPendingMessageAsync(pending);
|
||||
if (!toShare.isEmpty()) shareNextMessageAsync(toShare);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
if (invalidate != null) invalidateNextMessageAsync(invalidate);
|
||||
if (pending != null) deliverNextPendingMessageAsync(pending);
|
||||
if (toShare != null) shareNextMessageAsync(toShare);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed during validation");
|
||||
} catch (NoSuchGroupException e) {
|
||||
@@ -323,12 +342,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private void addPendingDependents(Transaction txn, MessageId m,
|
||||
Queue<MessageId> pending) throws DbException {
|
||||
Map<MessageId, MessageState> states = db.getMessageDependents(txn, m);
|
||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
||||
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
|
||||
throws DbException {
|
||||
Queue<MessageId> pending = new LinkedList<>();
|
||||
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() {
|
||||
@@ -338,8 +359,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void shareOutstandingMessages() {
|
||||
try {
|
||||
Queue<MessageId> toShare = new LinkedList<>(
|
||||
db.transactionWithResult(true, db::getMessagesToShare));
|
||||
Queue<MessageId> toShare = new LinkedList<>();
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
toShare.addAll(db.getMessagesToShare(txn));
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
shareNextMessageAsync(toShare);
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
@@ -360,12 +387,15 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void shareNextMessage(Queue<MessageId> toShare) {
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
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");
|
||||
@@ -386,14 +416,17 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void invalidateNextMessage(Queue<MessageId> invalidate) {
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
MessageId id = invalidate.poll();
|
||||
if (id == null) throw new AssertionError();
|
||||
if (db.getMessageState(txn, id) != INVALID) {
|
||||
invalidateMessage(txn, id);
|
||||
addDependentsToInvalidate(txn, id, invalidate);
|
||||
invalidate.addAll(getDependentsToInvalidate(txn, id));
|
||||
}
|
||||
});
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
invalidateNextMessageAsync(invalidate);
|
||||
} catch (NoSuchMessageException e) {
|
||||
LOG.info("Message removed before invalidation");
|
||||
@@ -412,12 +445,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private void addDependentsToInvalidate(Transaction txn,
|
||||
MessageId m, Queue<MessageId> invalidate) throws DbException {
|
||||
Map<MessageId, MessageState> states = db.getMessageDependents(txn, m);
|
||||
for (Entry<MessageId, MessageState> e : states.entrySet()) {
|
||||
private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
|
||||
MessageId m) throws DbException {
|
||||
Queue<MessageId> invalidate = new LinkedList<>();
|
||||
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
|
||||
@@ -437,8 +472,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
||||
@DatabaseExecutor
|
||||
private void loadGroupAndValidate(Message m) {
|
||||
try {
|
||||
Group g = db.transactionWithResult(true, txn ->
|
||||
db.getGroup(txn, m.getGroupId()));
|
||||
Group g;
|
||||
Transaction txn = db.startTransaction(true);
|
||||
try {
|
||||
g = db.getGroup(txn, m.getGroupId());
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
validateMessageAsync(m, g);
|
||||
} catch (NoSuchGroupException e) {
|
||||
LOG.info("Group removed before validation");
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.briarproject.bramble.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.tree.LeafNode;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeNode;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
interface HashTree {
|
||||
|
||||
void addLeaf(LeafNode leaf);
|
||||
|
||||
TreeNode getRoot();
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.briarproject.bramble.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.tree.LeafNode;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHasher;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeNode;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@NotNullByDefault
|
||||
class HashTreeImpl implements HashTree {
|
||||
|
||||
private final TreeHasher treeHasher;
|
||||
private final Deque<TreeNode> nodes = new LinkedList<>();
|
||||
|
||||
@Inject
|
||||
HashTreeImpl(TreeHasher treeHasher) {
|
||||
this.treeHasher = treeHasher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLeaf(LeafNode leaf) {
|
||||
TreeNode add = leaf;
|
||||
int height = leaf.getHeight();
|
||||
TreeNode last = nodes.peekLast();
|
||||
while (last != null && last.getHeight() == height) {
|
||||
add = treeHasher.mergeTrees(last, add);
|
||||
height = add.getHeight();
|
||||
nodes.removeLast();
|
||||
last = nodes.peekLast();
|
||||
}
|
||||
nodes.addLast(add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getRoot() {
|
||||
TreeNode root = nodes.removeLast();
|
||||
while (!nodes.isEmpty()) {
|
||||
root = treeHasher.mergeTrees(nodes.removeLast(), root);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package org.briarproject.bramble.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.io.BlockSink;
|
||||
import org.briarproject.bramble.api.io.HashingId;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.tree.StreamHasher;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHash;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHasher;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeNode;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
import static java.util.Arrays.copyOfRange;
|
||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_BLOCK_LENGTH;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class StreamHasherImpl implements StreamHasher {
|
||||
|
||||
private final TreeHasher treeHasher;
|
||||
private final Provider<HashTree> hashTreeProvider;
|
||||
|
||||
@Inject
|
||||
StreamHasherImpl(TreeHasher treeHasher,
|
||||
Provider<HashTree> hashTreeProvider) {
|
||||
this.treeHasher = treeHasher;
|
||||
this.hashTreeProvider = hashTreeProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode hash(InputStream in, BlockSink sink, HashingId h)
|
||||
throws IOException, DbException {
|
||||
HashTree tree = hashTreeProvider.get();
|
||||
byte[] block = new byte[MAX_BLOCK_LENGTH];
|
||||
int read;
|
||||
for (int blockNumber = 0; (read = read(in, block)) > 0; blockNumber++) {
|
||||
byte[] data;
|
||||
if (read == block.length) data = block;
|
||||
else data = copyOfRange(block, 0, read);
|
||||
sink.putBlock(h, blockNumber, data);
|
||||
tree.addLeaf(treeHasher.hashBlock(blockNumber, data));
|
||||
}
|
||||
TreeNode root = tree.getRoot();
|
||||
setPaths(sink, h, root, new LinkedList<>());
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a block from the given input stream and returns the number of
|
||||
* bytes read, or 0 if no bytes were read before reaching the end of the
|
||||
* stream.
|
||||
*/
|
||||
private int read(InputStream in, byte[] block) throws IOException {
|
||||
int offset = 0;
|
||||
while (offset < block.length) {
|
||||
int read = in.read(block, offset, block.length - offset);
|
||||
if (read == -1) return offset;
|
||||
offset += read;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
private void setPaths(BlockSink sink, HashingId h, TreeNode node,
|
||||
LinkedList<TreeHash> path) throws DbException {
|
||||
if (node.getHeight() == 0) {
|
||||
// We've reached a leaf - store the path
|
||||
sink.setPath(h, node.getFirstBlockNumber(), path);
|
||||
} else {
|
||||
// Add the right child's hash to the path and traverse the left
|
||||
path.addFirst(node.getRightChild().getHash());
|
||||
setPaths(sink, h, node.getLeftChild(), path);
|
||||
// Add the left child's hash to the path and traverse the right
|
||||
path.removeFirst();
|
||||
path.addFirst(node.getLeftChild().getHash());
|
||||
setPaths(sink, h, node.getRightChild(), path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package org.briarproject.bramble.sync.tree;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.sync.tree.LeafNode;
|
||||
import org.briarproject.bramble.api.sync.tree.ParentNode;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHash;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeHasher;
|
||||
import org.briarproject.bramble.api.sync.tree.TreeNode;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.bramble.api.sync.Message.FORMAT_VERSION;
|
||||
import static org.briarproject.bramble.api.sync.MessageId.BLOCK_LABEL;
|
||||
import static org.briarproject.bramble.api.sync.MessageId.TREE_LABEL;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class TreeHasherImpl implements TreeHasher {
|
||||
|
||||
private static final byte[] FORMAT_VERSION_BYTES =
|
||||
new byte[] {FORMAT_VERSION};
|
||||
|
||||
private final CryptoComponent crypto;
|
||||
|
||||
@Inject
|
||||
TreeHasherImpl(CryptoComponent crypto) {
|
||||
this.crypto = crypto;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LeafNode hashBlock(int blockNumber, byte[] data) {
|
||||
byte[] hash = crypto.hash(BLOCK_LABEL, FORMAT_VERSION_BYTES, data);
|
||||
return new LeafNode(new TreeHash(hash), blockNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParentNode mergeTrees(TreeNode left, TreeNode right) {
|
||||
byte[] hash = crypto.hash(TREE_LABEL, FORMAT_VERSION_BYTES,
|
||||
left.getHash().getBytes(), right.getHash().getBytes());
|
||||
return new ParentNode(new TreeHash(hash), left, right);
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.briarproject.bramble.sync.validation;
|
||||
|
||||
import org.briarproject.bramble.PoliteExecutor;
|
||||
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class ValidationModule {
|
||||
|
||||
public static class EagerSingletons {
|
||||
@Inject
|
||||
ValidationManager validationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of validation tasks to delegate to the crypto
|
||||
* executor concurrently.
|
||||
* <p>
|
||||
* The number of available processors can change during the lifetime of the
|
||||
* JVM, so this is just a reasonable guess.
|
||||
*/
|
||||
private static final int MAX_CONCURRENT_VALIDATION_TASKS =
|
||||
Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ValidationManager provideValidationManager(
|
||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||
ValidationManagerImpl validationManager) {
|
||||
lifecycleManager.registerService(validationManager);
|
||||
eventBus.addListener(validationManager);
|
||||
return validationManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ValidationExecutor
|
||||
Executor provideValidationExecutor(
|
||||
@CryptoExecutor Executor cryptoExecutor) {
|
||||
return new PoliteExecutor("ValidationExecutor", cryptoExecutor,
|
||||
MAX_CONCURRENT_VALIDATION_TASKS);
|
||||
}
|
||||
}
|
||||
@@ -13,33 +13,32 @@ import java.util.logging.Logger;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
class UnixSecureRandomProvider extends AbstractSecureRandomProvider {
|
||||
class LinuxSecureRandomProvider extends AbstractSecureRandomProvider {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(UnixSecureRandomProvider.class.getName());
|
||||
Logger.getLogger(LinuxSecureRandomProvider.class.getName());
|
||||
|
||||
private static final File RANDOM_DEVICE = new File("/dev/urandom");
|
||||
|
||||
private final AtomicBoolean seeded = new AtomicBoolean(false);
|
||||
private final File outputDevice;
|
||||
|
||||
UnixSecureRandomProvider() {
|
||||
LinuxSecureRandomProvider() {
|
||||
this(RANDOM_DEVICE);
|
||||
}
|
||||
|
||||
UnixSecureRandomProvider(File outputDevice) {
|
||||
LinuxSecureRandomProvider(File outputDevice) {
|
||||
this.outputDevice = outputDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Provider getProvider() {
|
||||
if (!seeded.getAndSet(true)) writeSeed();
|
||||
return new UnixProvider();
|
||||
return new LinuxProvider();
|
||||
}
|
||||
|
||||
protected void writeSeed() {
|
||||
@@ -56,15 +55,15 @@ class UnixSecureRandomProvider extends AbstractSecureRandomProvider {
|
||||
}
|
||||
|
||||
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
|
||||
private static class UnixProvider extends Provider {
|
||||
private static class LinuxProvider extends Provider {
|
||||
|
||||
private UnixProvider() {
|
||||
super("UnixPRNG", 1.0, "A Unix-specific PRNG using /dev/urandom");
|
||||
private LinuxProvider() {
|
||||
super("LinuxPRNG", 1.1, "A Linux-specific PRNG using /dev/urandom");
|
||||
// Although /dev/urandom is not a SHA-1 PRNG, some callers
|
||||
// explicitly request a SHA1PRNG SecureRandom and we need to
|
||||
// prevent them from getting the default implementation whose
|
||||
// output may have low entropy.
|
||||
put("SecureRandom.SHA1PRNG", UnixSecureRandomSpi.class.getName());
|
||||
put("SecureRandom.SHA1PRNG", LinuxSecureRandomSpi.class.getName());
|
||||
put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
|
||||
}
|
||||
}
|
||||
@@ -10,24 +10,22 @@ import java.security.SecureRandomSpi;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static java.util.logging.Logger.getLogger;
|
||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||
|
||||
public class UnixSecureRandomSpi extends SecureRandomSpi {
|
||||
public class LinuxSecureRandomSpi extends SecureRandomSpi {
|
||||
|
||||
private static final Logger LOG =
|
||||
getLogger(UnixSecureRandomSpi.class.getName());
|
||||
Logger.getLogger(LinuxSecureRandomSpi.class.getName());
|
||||
|
||||
private static final File RANDOM_DEVICE = new File("/dev/urandom");
|
||||
|
||||
private final File inputDevice, outputDevice;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public UnixSecureRandomSpi() {
|
||||
public LinuxSecureRandomSpi() {
|
||||
this(RANDOM_DEVICE, RANDOM_DEVICE);
|
||||
}
|
||||
|
||||
UnixSecureRandomSpi(File inputDevice, File outputDevice) {
|
||||
LinuxSecureRandomSpi(File inputDevice, File outputDevice) {
|
||||
this.inputDevice = inputDevice;
|
||||
this.outputDevice = outputDevice;
|
||||
}
|
||||
@@ -72,7 +72,8 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
|
||||
transports.put(f.getId(), f.getMaxLatency());
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
for (Contact c : db.getContacts(txn))
|
||||
if (c.isActive()) activeContacts.put(c.getId(), true);
|
||||
for (Entry<TransportId, Integer> e : transports.entrySet())
|
||||
@@ -84,7 +85,10 @@ 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);
|
||||
}
|
||||
@@ -137,8 +141,15 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
||||
return null;
|
||||
}
|
||||
return db.transactionWithNullableResult(false, txn ->
|
||||
m.getStreamContext(txn, c));
|
||||
StreamContext ctx;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
ctx = m.getStreamContext(txn, c);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -149,8 +160,15 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
||||
if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t);
|
||||
return null;
|
||||
}
|
||||
return db.transactionWithNullableResult(false, txn ->
|
||||
m.getStreamContext(txn, tag));
|
||||
StreamContext ctx;
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
ctx = m.getStreamContext(txn, tag);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -162,7 +162,13 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
||||
private void rotateKeys() {
|
||||
dbExecutor.execute(() -> {
|
||||
try {
|
||||
db.transaction(false, this::rotateKeys);
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
rotateKeys(txn);
|
||||
db.commitTransaction(txn);
|
||||
} finally {
|
||||
db.endTransaction(txn);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
logException(LOG, WARNING, e);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||
import org.briarproject.bramble.api.sync.Message;
|
||||
import org.briarproject.bramble.api.sync.MessageId;
|
||||
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
@@ -123,12 +123,16 @@ class ClientVersioningManagerImpl implements ClientVersioningManager, Client,
|
||||
List<ClientVersion> versions = new ArrayList<>(clients);
|
||||
Collections.sort(versions);
|
||||
try {
|
||||
db.transaction(false, txn -> {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.briarproject.bramble.api.client.ClientHelper;
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.data.MetadataEncoder;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.validation.ValidationManager;
|
||||
import org.briarproject.bramble.api.sync.ValidationManager;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
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
|
||||
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
|
||||
@@ -22,7 +22,6 @@ 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;
|
||||
@@ -86,11 +85,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
boolean shared = new Random().nextBoolean();
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(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);
|
||||
@@ -114,10 +116,13 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
expectToList(true);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getMessage(txn, messageId);
|
||||
will(returnValue(message));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
clientHelper.getMessageAsList(messageId);
|
||||
@@ -128,12 +133,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testGetGroupMetadataAsDictionary() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(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,
|
||||
@@ -145,12 +153,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testGetMessageMetadataAsDictionary() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(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,
|
||||
@@ -164,12 +175,15 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
map.put(messageId, dictionary);
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(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));
|
||||
@@ -186,14 +200,17 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
queryMetadata.put("query", getRandomBytes(42));
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(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,
|
||||
@@ -205,11 +222,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testMergeGroupMetadata() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(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);
|
||||
@@ -220,11 +240,14 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
||||
public void testMergeMessageMetadata() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(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);
|
||||
|
||||
@@ -69,14 +69,17 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
boolean alice = new Random().nextBoolean();
|
||||
Transaction txn = new Transaction(null, false);
|
||||
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(false), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(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,
|
||||
@@ -86,10 +89,13 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@Test
|
||||
public void testGetContact() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContact(txn, contactId);
|
||||
will(returnValue(contact));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(contact, contactManager.getContact(contactId));
|
||||
@@ -99,10 +105,13 @@ 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 DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(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));
|
||||
@@ -111,10 +120,12 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@Test(expected = NoSuchContactException.class)
|
||||
public void testGetContactByUnknownAuthor() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||
will(returnValue(emptyList()));
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
contactManager.getContact(remote.getId(), local);
|
||||
@@ -124,26 +135,31 @@ 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 DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||
will(returnValue(contacts));
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
contactManager.getContact(remote.getId(), new AuthorId(getRandomId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveContacts() throws Exception {
|
||||
public void testActiveContacts() throws Exception {
|
||||
Collection<Contact> activeContacts = Collections.singletonList(contact);
|
||||
Collection<Contact> contacts = new ArrayList<>(activeContacts);
|
||||
contacts.add(new Contact(new ContactId(3), remote, local, alias, true,
|
||||
false));
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(txn));
|
||||
oneOf(db).getContacts(txn);
|
||||
will(returnValue(contacts));
|
||||
oneOf(db).commitTransaction(txn);
|
||||
oneOf(db).endTransaction(txn);
|
||||
}});
|
||||
|
||||
assertEquals(activeContacts, contactManager.getActiveContacts());
|
||||
@@ -152,11 +168,14 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
@Test
|
||||
public void testRemoveContact() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(false);
|
||||
will(returnValue(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);
|
||||
@@ -176,7 +195,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
public void testSetContactAlias() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||
oneOf(db).transaction(with(equal(false)), withDbRunnable(txn));
|
||||
oneOf(db).setContactAlias(txn, contactId, alias);
|
||||
}});
|
||||
|
||||
@@ -185,32 +204,35 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSetContactAliasTooLong() throws Exception {
|
||||
Transaction txn = new Transaction(null, false);
|
||||
contactManager.setContactAlias(txn, contactId,
|
||||
contactManager.setContactAlias(contactId,
|
||||
getRandomString(MAX_AUTHOR_NAME_LENGTH + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContactExists() throws Exception {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
context.checking(new DbExpectations() {{
|
||||
oneOf(db).transactionWithResult(with(true), withDbCallable(txn));
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(db).startTransaction(true);
|
||||
will(returnValue(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 {
|
||||
public void testGetAuthorStatus() 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(db).transactionWithResult(with(equal(true)),
|
||||
withDbCallable(txn));
|
||||
oneOf(identityManager).getLocalAuthor(txn);
|
||||
will(returnValue(localAuthor));
|
||||
oneOf(db).getContactsByAuthorId(txn, remote.getId());
|
||||
@@ -223,7 +245,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAuthorInfoTransaction() throws DbException {
|
||||
public void testGetAuthorStatusTransaction() throws DbException {
|
||||
Transaction txn = new Transaction(null, true);
|
||||
|
||||
// check unknown author
|
||||
@@ -242,7 +264,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
Collection<Contact> contacts = singletonList(
|
||||
new Contact(new ContactId(1), remote, localAuthor.getId(),
|
||||
alias, false, true));
|
||||
checkAuthorInfoContext(txn, remote.getId(), contacts);
|
||||
checkAuthorStatusContext(txn, remote.getId(), contacts);
|
||||
authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
|
||||
assertEquals(UNVERIFIED, authorInfo.getStatus());
|
||||
assertEquals(alias, contact.getAlias());
|
||||
@@ -250,7 +272,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
// check verified contact
|
||||
contacts = singletonList(new Contact(new ContactId(1), remote,
|
||||
localAuthor.getId(), alias, true, true));
|
||||
checkAuthorInfoContext(txn, remote.getId(), contacts);
|
||||
checkAuthorStatusContext(txn, remote.getId(), contacts);
|
||||
authorInfo = contactManager.getAuthorInfo(txn, remote.getId());
|
||||
assertEquals(VERIFIED, authorInfo.getStatus());
|
||||
assertEquals(alias, contact.getAlias());
|
||||
@@ -266,7 +288,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
||||
assertNull(authorInfo.getAlias());
|
||||
}
|
||||
|
||||
private void checkAuthorInfoContext(Transaction txn, AuthorId authorId,
|
||||
private void checkAuthorStatusContext(Transaction txn, AuthorId authorId,
|
||||
Collection<Contact> contacts) throws DbException {
|
||||
context.checking(new Expectations() {{
|
||||
oneOf(identityManager).getLocalAuthor(txn);
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.briarproject.bramble.data;
|
||||
|
||||
import org.briarproject.bramble.test.BrambleTestCase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Random;
|
||||
|
||||
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_MAX_BUFFER_SIZE;
|
||||
import static org.briarproject.bramble.api.data.BdfReader.DEFAULT_NESTED_LIMIT;
|
||||
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
public class BdfReaderImplFuzzingTest extends BrambleTestCase {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
assumeTrue(isOptionalTestEnabled(BdfReaderImplFuzzingTest.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringFuzzing() throws Exception {
|
||||
Random random = new Random();
|
||||
byte[] buf = new byte[22];
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(buf);
|
||||
for (int i = 0; i < 100_000_000; i++) {
|
||||
random.nextBytes(buf);
|
||||
buf[0] = 0x41; // String with 1-byte length
|
||||
buf[1] = 0x14; // Length 20 bytes
|
||||
in.reset();
|
||||
BdfReaderImpl r = new BdfReaderImpl(in, DEFAULT_NESTED_LIMIT,
|
||||
DEFAULT_MAX_BUFFER_SIZE);
|
||||
int length = r.readString().length();
|
||||
assertTrue(length >= 0);
|
||||
assertTrue(length <= 20);
|
||||
assertTrue(r.eof());
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user