Compare commits

..

36 Commits

Author SHA1 Message Date
akwizgran
2ba848e445 Set app_package to match applicationIdSuffix. 2018-11-07 09:51:08 +00:00
akwizgran
73f8c5f3f2 Don't crop camera preview before decoding. 2018-10-29 11:05:14 +00:00
Torsten Grote
823dbb1b67 Change package ID and name for prototype 2018-10-23 14:04:28 -03:00
Torsten Grote
1589ea8853 Show QR code again 2018-10-23 14:00:52 -03:00
Torsten Grote
c9ebe14d1e Add error message for invalid links 2018-10-23 13:57:31 -03:00
Torsten Grote
bd3df6e364 Double link size to 128 characters 2018-10-22 13:09:21 -03:00
Torsten Grote
be5a804a46 Show dialog when user tries to add contact with their own link 2018-10-22 12:55:19 -03:00
Torsten Grote
1cd4134cb0 Rearrange layout so sending link comes first 2018-10-22 12:38:51 -03:00
Torsten Grote
6706fea2d3 Make 'Add a Contact' screen scrollable when keyboard is open 2018-10-22 12:07:01 -03:00
akwizgran
62aa0530d8 Hide QR code buttons. 2018-10-22 12:07:01 -03:00
akwizgran
422d0b3c4b Use constant link, derive delay from both links. 2018-10-22 12:07:01 -03:00
akwizgran
9cafd2c340 Initialise addButton early to avoid NPE. 2018-10-22 12:07:01 -03:00
akwizgran
69f01edee3 Combine input and output into one screen. 2018-10-22 12:07:01 -03:00
akwizgran
ca7fea1d95 Lowercase links. 2018-10-22 12:07:01 -03:00
akwizgran
856809e913 Use accent resource so colour is correct for dark theme. 2018-10-22 12:05:19 -03:00
akwizgran
dac10b5e5a Use kobakei's speed dial library. 2018-10-22 12:05:16 -03:00
Torsten Grote
08391a31d0 Hack compound drawable tint for API < 23 2018-10-22 12:02:37 -03:00
Torsten Grote
8bc0bae9db Make link visible in dark theme 2018-10-22 12:02:37 -03:00
Torsten Grote
448c5d3e90 Replace qr code icons in speedial with link icons 2018-10-22 12:02:37 -03:00
Torsten Grote
27be5a0d82 Make QR code another view on the invite link 2018-10-22 12:02:37 -03:00
Torsten Grote
ccd8f16185 Allow multiple pending fake contacts at the same time 2018-10-22 12:02:37 -03:00
Torsten Grote
fc10af73ca Allow actual QR code scanning and use dedicated contact alias fragment 2018-10-22 12:02:37 -03:00
Torsten Grote
6a25f20390 Add (non-functional) button for scanning QR code 2018-10-22 12:02:37 -03:00
Torsten Grote
12f7113b8d Only start one navdrawer activity with contact list 2018-10-22 12:02:37 -03:00
Torsten Grote
56960d51ca Add buttons to switch between showing link and code 2018-10-22 12:02:37 -03:00
Torsten Grote
42e10b1840 Move link input into fragment 2018-10-22 12:02:37 -03:00
Torsten Grote
e0f5c0b1f3 Check if lifecycle is running before adding fake contact 2018-10-22 12:02:37 -03:00
Torsten Grote
22cac6d44a Show QR code by default instead of link 2018-10-22 12:02:37 -03:00
akwizgran
6e109a8804 Accept links without briar:// prefix. 2018-10-22 12:02:37 -03:00
akwizgran
b9bd752f24 Try to make links clickable. 2018-10-22 12:02:37 -03:00
Torsten Grote
5d8f006370 Actually add fake contact ~1 minute after entering link 2018-10-22 12:02:37 -03:00
Torsten Grote
b6b7cfb27a Add pending contact requests screen 2018-10-22 12:02:37 -03:00
akwizgran
89d33a3a84 Use base32 for contact links. 2018-10-22 12:02:37 -03:00
akwizgran
bbdb9e150f Accept text shared by other apps. 2018-10-22 12:02:37 -03:00
akwizgran
f202ddd9a3 Add third speed dial action, share button. 2018-10-22 12:02:37 -03:00
Torsten Grote
ac87f23187 Add Activities for receiving and entering contact link 2018-10-22 12:02:34 -03:00
725 changed files with 9204 additions and 14981 deletions

View File

@@ -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" />

View File

@@ -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
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -9,22 +9,19 @@ import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.util.IoUtils;
import java.io.File;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
class AndroidAccountManager extends AccountManagerImpl
implements AccountManager {
private static final Logger LOG =
getLogger(AndroidAccountManager.class.getName());
Logger.getLogger(AndroidAccountManager.class.getName());
private static final String PREF_DB_KEY = "key";
@@ -40,7 +37,7 @@ class AndroidAccountManager extends AccountManagerImpl
appContext = app.getApplicationContext();
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
@Override
@Nullable
protected String loadEncryptedDatabaseKey() {
@@ -50,7 +47,7 @@ class AndroidAccountManager extends AccountManagerImpl
return key;
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
@Nullable
private String getDatabaseKeyFromPreferences() {
String key = prefs.getString(PREF_DB_KEY, null);
@@ -59,7 +56,7 @@ class AndroidAccountManager extends AccountManagerImpl
return key;
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
private void migrateDatabaseKeyToFile(String key) {
if (storeEncryptedDatabaseKey(key)) {
if (prefs.edit().remove(PREF_DB_KEY).commit())
@@ -84,7 +81,7 @@ class AndroidAccountManager extends AccountManagerImpl
return PreferenceManager.getDefaultSharedPreferences(appContext);
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
private void deleteAppData(SharedPreferences... clear) {
// Clear and commit shared preferences
for (SharedPreferences prefs : clear) {
@@ -100,7 +97,7 @@ class AndroidAccountManager extends AccountManagerImpl
for (File child : children) {
String name = child.getName();
if (!name.equals("lib") && !name.equals("shared_prefs")) {
deleteFileOrDir(child);
IoUtils.deleteFileOrDir(child);
}
}
}

View File

@@ -1,81 +0,0 @@
package org.briarproject.bramble.battery;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.Service;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.content.Intent.ACTION_BATTERY_CHANGED;
import static android.content.Intent.ACTION_POWER_CONNECTED;
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
import static android.os.BatteryManager.EXTRA_PLUGGED;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
class AndroidBatteryManager implements BatteryManager, Service {
private static final Logger LOG =
getLogger(AndroidBatteryManager.class.getName());
private final Context appContext;
private final EventBus eventBus;
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile BroadcastReceiver batteryReceiver = null;
@Inject
AndroidBatteryManager(Application app, EventBus eventBus) {
this.appContext = app.getApplicationContext();
this.eventBus = eventBus;
}
@Override
public boolean isCharging() {
// Get the sticky intent for ACTION_BATTERY_CHANGED
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
Intent i = appContext.registerReceiver(null, filter);
if (i == null) return false;
int status = i.getIntExtra(EXTRA_PLUGGED, 0);
return status != 0;
}
@Override
public void startService() {
if (used.getAndSet(true)) throw new IllegalStateException();
batteryReceiver = new BatteryReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_POWER_CONNECTED);
filter.addAction(ACTION_POWER_DISCONNECTED);
appContext.registerReceiver(batteryReceiver, filter);
}
@Override
public void stopService() {
if (batteryReceiver != null)
appContext.unregisterReceiver(batteryReceiver);
}
private class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent i) {
String action = i.getAction();
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
if (ACTION_POWER_CONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(true));
else if (ACTION_POWER_DISCONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(false));
}
}
}

View File

@@ -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;
}
}

View File

@@ -13,7 +13,8 @@ import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.network.NetworkStatus;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.system.Scheduler;
import java.util.concurrent.Future;
@@ -33,17 +34,16 @@ import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
@NotNullByDefault
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidNetworkManager implements NetworkManager, Service {
private static final Logger LOG =
getLogger(AndroidNetworkManager.class.getName());
Logger.getLogger(AndroidNetworkManager.class.getName());
// See android.net.wifi.WifiManager
private static final String WIFI_AP_STATE_CHANGED_ACTION =
@@ -56,7 +56,6 @@ class AndroidNetworkManager implements NetworkManager, Service {
new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false);
@Nullable
private volatile BroadcastReceiver networkStateReceiver = null;
@Inject
@@ -90,8 +89,9 @@ class AndroidNetworkManager implements NetworkManager, Service {
@Override
public NetworkStatus getNetworkStatus() {
ConnectivityManager cm = (ConnectivityManager) requireNonNull(
appContext.getSystemService(CONNECTIVITY_SERVICE));
ConnectivityManager cm = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE);
if (cm == null) throw new AssertionError();
NetworkInfo net = cm.getActiveNetworkInfo();
boolean connected = net != null && net.isConnected();
boolean wifi = connected && net.getType() == TYPE_WIFI;

View File

@@ -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,

View File

@@ -16,26 +16,18 @@ import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.IoUtils;
import java.io.Closeable;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
@@ -45,27 +37,18 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERA
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
import static java.util.Collections.shuffle;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
import static org.briarproject.bramble.util.LogUtils.logException;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private static final Logger LOG =
getLogger(AndroidBluetoothPlugin.class.getName());
private static final int MAX_DISCOVERY_MS = 10_000;
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
private final AndroidExecutor androidExecutor;
private final Context appContext;
private final Clock clock;
private volatile boolean wasEnabledByUs = false;
private volatile BluetoothStateReceiver receiver = null;
@@ -75,13 +58,12 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, AndroidExecutor androidExecutor,
Context appContext, SecureRandom secureRandom, Clock clock,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
Context appContext, SecureRandom secureRandom, Backoff backoff,
DuplexPluginCallback callback, int maxLatency) {
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
maxLatency);
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.clock = clock;
}
@Override
@@ -161,7 +143,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
@@ -191,77 +177,17 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
s.connect();
return wrapSocket(s);
} catch (IOException e) {
IoUtils.tryToClose(s, LOG, WARNING);
tryToClose(s);
throw e;
}
}
@Override
@Nullable
DuplexTransportConnection discoverAndConnect(String uuid) {
if (adapter == null) return null;
for (String address : discoverDevices()) {
try {
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubMacAddress(address));
return connectTo(address, uuid);
} catch (IOException e) {
if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to "
+ scrubMacAddress(address));
}
}
}
LOG.info("Could not connect to any devices");
return null;
}
private Collection<String> discoverDevices() {
List<String> addresses = new ArrayList<>();
BlockingQueue<Intent> intents = new LinkedBlockingQueue<>();
DiscoveryReceiver receiver = new DiscoveryReceiver(intents);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DISCOVERY_STARTED);
filter.addAction(ACTION_DISCOVERY_FINISHED);
filter.addAction(ACTION_FOUND);
appContext.registerReceiver(receiver, filter);
private void tryToClose(@Nullable Closeable c) {
try {
if (adapter.startDiscovery()) {
long now = clock.currentTimeMillis();
long end = now + MAX_DISCOVERY_MS;
while (now < end) {
Intent i = intents.poll(end - now, MILLISECONDS);
if (i == null) break;
String action = i.getAction();
if (ACTION_DISCOVERY_STARTED.equals(action)) {
LOG.info("Discovery started");
} else if (ACTION_DISCOVERY_FINISHED.equals(action)) {
LOG.info("Discovery finished");
break;
} else if (ACTION_FOUND.equals(action)) {
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
String address = d.getAddress();
if (LOG.isLoggable(INFO))
LOG.info("Discovered " + scrubMacAddress(address));
if (!addresses.contains(address))
addresses.add(address);
}
now = clock.currentTimeMillis();
}
} else {
LOG.info("Could not start discovery");
}
} catch (InterruptedException e) {
LOG.info("Interrupted while discovering devices");
Thread.currentThread().interrupt();
} finally {
LOG.info("Cancelling discovery");
adapter.cancelDiscovery();
appContext.unregisterReceiver(receiver);
if (c != null) c.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
// Shuffle the addresses so we don't always try the same one first
shuffle(addresses);
return addresses;
}
private class BluetoothStateReceiver extends BroadcastReceiver {
@@ -281,18 +207,4 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
}
}
}
private static class DiscoveryReceiver extends BroadcastReceiver {
private final BlockingQueue<Intent> intents;
private DiscoveryReceiver(BlockingQueue<Intent> intents) {
this.intents = intents;
}
@Override
public void onReceive(Context ctx, Intent intent) {
intents.add(intent);
}
}
}

View File

@@ -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.DuplexPluginFactory;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import java.security.SecureRandom;
import java.util.concurrent.Executor;
@@ -34,19 +33,17 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private final Context appContext;
private final SecureRandom secureRandom;
private final EventBus eventBus;
private final Clock clock;
private final BackoffFactory backoffFactory;
public AndroidBluetoothPluginFactory(Executor ioExecutor,
AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom, EventBus eventBus, Clock clock,
SecureRandom secureRandom, EventBus eventBus,
BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.secureRandom = secureRandom;
this.eventBus = eventBus;
this.clock = clock;
this.backoffFactory = backoffFactory;
}
@@ -68,7 +65,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
connectionLimiter, ioExecutor, androidExecutor, appContext,
secureRandom, clock, backoff, callback, MAX_LATENCY);
secureRandom, backoff, callback, MAX_LATENCY);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -32,19 +32,17 @@ import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;
import static java.util.logging.Logger.getLogger;
@NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private static final Logger LOG =
getLogger(AndroidLanTcpPlugin.class.getName());
private static final byte[] WIFI_AP_ADDRESS_BYTES =
{(byte) 192, (byte) 168, 43, 1};
private static final InetAddress WIFI_AP_ADDRESS;
private static final Logger LOG =
Logger.getLogger(AndroidLanTcpPlugin.class.getName());
static {
try {
WIFI_AP_ADDRESS = InetAddress.getByAddress(WIFI_AP_ADDRESS_BYTES);
@@ -68,8 +66,10 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
// Don't execute more than one connection status check at a time
connectionStatusExecutor =
new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1);
connectivityManager = (ConnectivityManager) requireNonNull(
appContext.getSystemService(CONNECTIVITY_SERVICE));
ConnectivityManager connectivityManager = (ConnectivityManager)
appContext.getSystemService(CONNECTIVITY_SERVICE);
if (connectivityManager == null) throw new AssertionError();
this.connectivityManager = connectivityManager;
wifiManager = (WifiManager) appContext.getApplicationContext()
.getSystemService(WIFI_SERVICE);
socketFactory = SocketFactory.getDefault();

View File

@@ -6,9 +6,9 @@ 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.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.system.Clock;
@@ -25,10 +25,10 @@ import javax.net.SocketFactory;
import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.POWER_SERVICE;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.MINUTES;
@NotNullByDefault
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AndroidTorPlugin extends TorPlugin {
// This tag may prevent Huawei's power manager from killing us
@@ -41,17 +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)
requireNonNull(appContext.getSystemService(POWER_SERVICE));
appContext.getSystemService(POWER_SERVICE);
assert pm != null;
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
}

View File

@@ -1,8 +1,8 @@
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;
@@ -25,15 +25,12 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import javax.net.SocketFactory;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.logging.Logger.getLogger;
@Immutable
@NotNullByDefault
public class AndroidTorPluginFactory implements DuplexPluginFactory {
private static final Logger LOG =
getLogger(AndroidTorPluginFactory.class.getName());
Logger.getLogger(AndroidTorPluginFactory.class.getName());
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
@@ -51,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,
@@ -59,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;
@@ -71,7 +66,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.backoffFactory = backoffFactory;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager;
this.clock = clock;
}
@@ -104,14 +98,14 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
return null;
}
// Use position-independent executable for SDK >= 16
if (SDK_INT >= 16) architecture += "_pie";
if (Build.VERSION.SDK_INT >= 16) architecture += "_pie";
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
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;
}

View File

@@ -15,13 +15,12 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static android.content.Context.TELEPHONY_SERVICE;
import static java.util.logging.Logger.getLogger;
@NotNullByDefault
class AndroidLocationUtils implements LocationUtils {
private static final Logger LOG =
getLogger(AndroidLocationUtils.class.getName());
Logger.getLogger(AndroidLocationUtils.class.getName());
private final Context appContext;
@@ -60,14 +59,14 @@ class AndroidLocationUtils implements LocationUtils {
}
private String getCountryFromPhoneNetwork() {
TelephonyManager tm = (TelephonyManager)
appContext.getSystemService(TELEPHONY_SERVICE);
return tm == null ? "" : tm.getNetworkCountryIso();
Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o;
return tm.getNetworkCountryIso();
}
private String getCountryFromSimCard() {
TelephonyManager tm = (TelephonyManager)
appContext.getSystemService(TELEPHONY_SERVICE);
return tm == null ? "" : tm.getSimCountryIso();
Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o;
return tm.getSimCountryIso();
}
}

View File

@@ -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;
@@ -8,6 +7,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Parcel;
import android.os.StrictMode;
import android.provider.Settings;
@@ -22,14 +22,11 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static android.content.Context.WIFI_SERVICE;
import static android.os.Build.FINGERPRINT;
import static android.os.Build.SERIAL;
import static android.os.Build.VERSION.SDK_INT;
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;
@@ -40,27 +37,24 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
appContext = app.getApplicationContext();
}
@SuppressLint("HardwareIds")
@Override
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
super.writeToEntropyPool(out);
out.writeInt(android.os.Process.myPid());
out.writeInt(android.os.Process.myTid());
out.writeInt(android.os.Process.myUid());
if (FINGERPRINT != null) out.writeUTF(FINGERPRINT);
if (SERIAL != null) out.writeUTF(SERIAL);
if (Build.FINGERPRINT != null) out.writeUTF(Build.FINGERPRINT);
if (Build.SERIAL != null) out.writeUTF(Build.SERIAL);
ContentResolver contentResolver = appContext.getContentResolver();
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) {
@@ -76,18 +70,20 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
// Silence strict mode
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskWrites();
super.writeSeed();
if (SDK_INT >= 16 && SDK_INT <= 18) applyOpenSslFix();
if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT <= 18)
applyOpenSslFix();
StrictMode.setThreadPolicy(tp);
}
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
private void applyOpenSslFix() {
byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(SEED_LENGTH);
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")

View File

@@ -3,35 +3,36 @@ package org.briarproject.bramble.util;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import java.io.File;
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.CPU_ABI;
import static android.os.Build.CPU_ABI2;
import static android.os.Build.SUPPORTED_ABIS;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
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";
private static final String STORED_REPORTS = "dev-reports";
@SuppressWarnings("deprecation")
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>();
if (SDK_INT >= 21) {
abis.addAll(asList(SUPPORTED_ABIS));
if (Build.VERSION.SDK_INT >= 21) {
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
} else {
abis.add(CPU_ABI);
if (CPU_ABI2 != null) abis.add(CPU_ABI2);
abis.add(Build.CPU_ABI);
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
}
return abis;
}
@@ -51,7 +52,7 @@ public class AndroidUtils {
}
private static boolean isValidBluetoothAddress(String address) {
return !isNullOrEmpty(address)
return !StringUtils.isNullOrEmpty(address)
&& BluetoothAdapter.checkBluetoothAddress(address)
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
}

View File

@@ -10,19 +10,17 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
@ThreadSafe
@NotNullByDefault
public class RenewableWakeLock {
private static final Logger LOG =
getLogger(RenewableWakeLock.class.getName());
Logger.getLogger(RenewableWakeLock.class.getName());
/**
* Automatically release the lock this many milliseconds after it's due
@@ -38,12 +36,10 @@ public class RenewableWakeLock {
private final Runnable renewTask;
private final Object lock = new Object();
@GuardedBy("lock")
@Nullable
private PowerManager.WakeLock wakeLock;
@GuardedBy("lock")
private PowerManager.WakeLock wakeLock; // Locking: lock
@Nullable
private ScheduledFuture future;
private ScheduledFuture future; // Locking: lock
public RenewableWakeLock(PowerManager powerManager,
ScheduledExecutorService scheduler, int levelAndFlags, String tag,

View File

@@ -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',

View File

@@ -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'
}

View File

@@ -1,14 +1,13 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import java.util.Arrays;
import java.util.Comparator;
import javax.annotation.concurrent.ThreadSafe;
import static org.briarproject.bramble.util.StringUtils.toHexString;
/**
* A wrapper around a byte array, to allow it to be stored in maps etc.
*/
@@ -57,7 +56,8 @@ public class Bytes implements Comparable<Bytes> {
@Override
public String toString() {
return getClass().getSimpleName() + "(" + toHexString(getBytes()) + ")";
return getClass().getSimpleName() +
"(" + StringUtils.toHexString(getBytes()) + ")";
}
public static class BytesComparator implements Comparator<Bytes> {

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -9,8 +10,6 @@ import java.util.Set;
import javax.annotation.concurrent.NotThreadSafe;
import static java.util.Collections.unmodifiableSet;
@NotThreadSafe
@NotNullByDefault
public class Multiset<T> {
@@ -97,6 +96,6 @@ public class Multiset<T> {
* is unmodifiable.
*/
public Set<T> keySet() {
return unmodifiableSet(map.keySet());
return Collections.unmodifiableSet(map.keySet());
}
}

View File

@@ -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;
}
}

View File

@@ -1,6 +0,0 @@
package org.briarproject.bramble.api.battery;
public interface BatteryManager {
boolean isCharging();
}

View File

@@ -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;
}
}

View File

@@ -5,11 +5,10 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import java.util.Collection;
import java.util.Collections;
import javax.annotation.concurrent.Immutable;
import static java.util.Collections.emptyList;
@Immutable
@NotNullByDefault
public class BdfMessageContext {
@@ -24,7 +23,7 @@ public class BdfMessageContext {
}
public BdfMessageContext(BdfDictionary dictionary) {
this(dictionary, emptyList());
this(dictionary, Collections.emptyList());
}
public BdfDictionary getDictionary() {

View File

@@ -9,14 +9,13 @@ 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;
import javax.annotation.concurrent.Immutable;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@Immutable
@@ -24,7 +23,7 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC
public abstract class BdfMessageValidator implements MessageValidator {
protected static final Logger LOG =
getLogger(BdfMessageValidator.class.getName());
Logger.getLogger(BdfMessageValidator.class.getName());
protected final ClientHelper clientHelper;
protected final MetadataEncoder metadataEncoder;

View File

@@ -4,12 +4,8 @@ import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@Immutable
@NotNullByDefault
public class Contact {
@@ -17,21 +13,13 @@ public class Contact {
private final ContactId id;
private final Author author;
private final AuthorId localAuthorId;
@Nullable
private final String alias;
private final boolean verified, active;
public Contact(ContactId id, Author author, AuthorId localAuthorId,
@Nullable String alias, boolean verified, boolean active) {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
}
boolean verified, boolean active) {
this.id = id;
this.author = author;
this.localAuthorId = localAuthorId;
this.alias = alias;
this.verified = verified;
this.active = active;
}
@@ -48,11 +36,6 @@ public class Contact {
return localAuthorId;
}
@Nullable
public String getAlias() {
return alias;
}
public boolean isVerified() {
return verified;
}

View File

@@ -5,16 +5,11 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.contact.PendingContact.PendingContactState.FAILED;
@NotNullByDefault
public interface ContactManager {
@@ -54,35 +49,6 @@ public interface ContactManager {
long timestamp, boolean alice, boolean verified, boolean active)
throws DbException;
/**
* Returns the static link that needs to be sent to the contact to be added.
*/
String getRemoteContactLink();
/**
* Returns true if the given link is syntactically valid.
*/
boolean isValidRemoteContactLink(String link);
/**
* Requests a new contact to be added via the given {@code link}.
*
* @param link The link received from the contact we want to add.
* @param alias The alias the user has given this contact.
* @return A PendingContact representing the contact to be added.
*/
PendingContact addRemoteContactRequest(String link, String alias);
/**
* Returns a list of {@link PendingContact}s.
*/
Collection<PendingContact> getPendingContacts();
/**
* Removes a {@link PendingContact} that is in state {@link FAILED}.
*/
void removePendingContact(PendingContact pendingContact);
/**
* Returns the contact with the given ID.
*/
@@ -127,18 +93,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.
*/
void setContactAlias(ContactId c, @Nullable String alias)
throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
@@ -151,16 +105,6 @@ public interface ContactManager {
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
interface ContactHook {
void addingContact(Transaction txn, Contact c) throws DbException;

View File

@@ -1,54 +0,0 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class PendingContact {
public enum PendingContactState {
WAITING_FOR_CONNECTION,
CONNECTED,
ADDING_CONTACT,
FAILED
}
private final PendingContactId id;
private final String alias;
private final PendingContactState state;
private final long timestamp;
public PendingContact(PendingContactId id, String alias,
PendingContactState state, long timestamp) {
this.id = id;
this.alias = alias;
this.state = state;
this.timestamp = timestamp;
}
public String getAlias() {
return alias;
}
public PendingContactState getState() {
return state;
}
public long getTimestamp() {
return timestamp;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object o) {
return o instanceof PendingContact &&
id.equals(((PendingContact) o).id);
}
}

View File

@@ -1,11 +0,0 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.UniqueId;
public class PendingContactId extends UniqueId {
public PendingContactId(byte[] id) {
super(id);
}
}

View File

@@ -1,34 +0,0 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.PendingContact.PendingContactState;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a pending contact's state is changed.
*/
@Immutable
@NotNullByDefault
public class PendingContactStateChangedEvent extends Event {
private final PendingContactId id;
private final PendingContactState state;
public PendingContactStateChangedEvent(PendingContactId id,
PendingContactState state) {
this.id = id;
this.state = state;
}
public PendingContactId getId() {
return id;
}
public PendingContactState getPendingContactState() {
return state;
}
}

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import javax.annotation.Nullable;
@@ -23,9 +24,9 @@ public class BdfDictionary extends TreeMap<String, Object> {
* );
* </pre>
*/
public static BdfDictionary of(BdfEntry... entries) {
public static BdfDictionary of(Entry<String, ?>... entries) {
BdfDictionary d = new BdfDictionary();
for (BdfEntry e : entries) d.put(e.getKey(), e.getValue());
for (Entry<String, ?> e : entries) d.put(e.getKey(), e.getValue());
return d;
}

View File

@@ -4,12 +4,12 @@ import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
@NotThreadSafe
@@ -22,7 +22,7 @@ public class BdfList extends ArrayList<Object> {
* </pre>
*/
public static BdfList of(Object... items) {
return new BdfList(asList(items));
return new BdfList(Arrays.asList(items));
}
public BdfList() {
@@ -33,7 +33,6 @@ public class BdfList extends ArrayList<Object> {
super(items);
}
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isInRange(int index) {
return index >= 0 && index < size();
}

View File

@@ -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');
}
}

View File

@@ -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
@@ -523,12 +515,6 @@ public interface DatabaseComponent {
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets the given group's visibility to the given contact.
*/
@@ -543,7 +529,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;
/**

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -3,12 +3,11 @@ package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.event.Event;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
import static java.util.Collections.emptyList;
/**
* A wrapper around a database transaction. Transactions are not thread-safe.
*/
@@ -54,7 +53,7 @@ public class Transaction {
* Returns any events attached to the transaction.
*/
public List<Event> getEvents() {
if (events == null) return emptyList();
if (events == null) return Collections.emptyList();
return events;
}

View File

@@ -2,12 +2,12 @@ package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.Nameable;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
/**
* A pseudonym for a user.
@@ -16,6 +16,10 @@ import static org.briarproject.bramble.util.StringUtils.toUtf8;
@NotNullByDefault
public class Author implements Nameable {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
}
/**
* The current version of the author structure.
*/
@@ -28,7 +32,7 @@ public class Author implements Nameable {
public Author(AuthorId id, int formatVersion, String name,
byte[] publicKey) {
int nameLength = toUtf8(name).length;
int nameLength = StringUtils.toUtf8(name).length;
if (nameLength == 0 || nameLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
if (publicKey.length == 0 || publicKey.length > MAX_PUBLIC_KEY_LENGTH)

View File

@@ -1,56 +0,0 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class AuthorInfo {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES;
public boolean isContact() {
return this == UNVERIFIED || this == VERIFIED;
}
}
private final Status status;
@Nullable
private final String alias;
public AuthorInfo(Status status, @Nullable String alias) {
this.status = status;
this.alias = alias;
}
public AuthorInfo(Status status) {
this(status, null);
}
public Status getStatus() {
return status;
}
@Nullable
public String getAlias() {
return alias;
}
@Override
public int hashCode() {
int hashCode = status.ordinal();
if (alias != null) hashCode += alias.hashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof AuthorInfo)) return false;
AuthorInfo info = (AuthorInfo) o;
return status == info.status &&
(alias == null ? info.alias == null : alias.equals(info.alias));
}
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author.Status;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
@@ -36,4 +37,14 @@ public interface IdentityManager {
*/
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/**
* Returns the {@link Status} of the given author.
*/
Status getAuthorStatus(AuthorId a) throws DbException;
/**
* Returns the {@link Status} of the given author.
*/
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
}

View File

@@ -21,7 +21,7 @@ public interface KeyAgreementConstants {
/**
* The connection timeout in milliseconds.
*/
long CONNECTION_TIMEOUT = 60_000;
long CONNECTION_TIMEOUT = 20 * 1000;
/**
* The transport identifier for Bluetooth.

View File

@@ -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;
}
}

View File

@@ -16,7 +16,6 @@ public interface TorConstants {
String PREF_TOR_NETWORK = "network2";
String PREF_TOR_PORT = "port";
String PREF_TOR_MOBILE = "useMobileData";
String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging";
int PREF_TOR_NETWORK_AUTOMATIC = 0;
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;

View File

@@ -1,6 +1,6 @@
package org.briarproject.bramble.api.plugin;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
import org.briarproject.bramble.util.StringUtils;
/**
* Type-safe wrapper for a namespaced string that uniquely identifies a
@@ -11,12 +11,12 @@ public class TransportId {
/**
* The maximum length of a transport identifier in UTF-8 bytes.
*/
public static final int MAX_TRANSPORT_ID_LENGTH = 100;
public static int MAX_TRANSPORT_ID_LENGTH = 100;
private final String id;
public TransportId(String id) {
int length = toUtf8(id).length;
int length = StringUtils.toUtf8(id).length;
if (length == 0 || length > MAX_TRANSPORT_ID_LENGTH)
throw new IllegalArgumentException();
this.id = id;

View File

@@ -1,11 +1,10 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
/**
* Type-safe wrapper for a namespaced string that uniquely identifies a sync
* client.
@@ -17,12 +16,12 @@ public class ClientId implements Comparable<ClientId> {
/**
* The maximum length of a client identifier in UTF-8 bytes.
*/
public static final int MAX_CLIENT_ID_LENGTH = 100;
public static int MAX_CLIENT_ID_LENGTH = 100;
private final String id;
public ClientId(String id) {
int length = toUtf8(id).length;
int length = StringUtils.toUtf8(id).length;
if (length == 0 || length > MAX_CLIENT_ID_LENGTH)
throw new IllegalArgumentException();
this.id = id;

View File

@@ -4,11 +4,10 @@ import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
import java.util.Collections;
import javax.annotation.concurrent.Immutable;
import static java.util.Collections.emptyList;
@Immutable
@NotNullByDefault
public class MessageContext {
@@ -23,7 +22,7 @@ public class MessageContext {
}
public MessageContext(Metadata metadata) {
this(metadata, emptyList());
this(metadata, Collections.emptyList());
}
public Metadata getMetadata() {

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -38,13 +38,6 @@ public interface ClientVersioningManager {
Visibility getClientVisibility(Transaction txn, ContactId contactId,
ClientId clientId, int majorVersion) throws DbException;
/**
* Returns the minor version of the given client that is supported by the
* given contact, or -1 if the contact does not support the client.
*/
int getClientMinorVersion(Transaction txn, ContactId contactId,
ClientId clientId, int majorVersion) throws DbException;
interface ClientVersioningHook {
void onClientVisibilityChanging(Transaction txn, Contact c,

View File

@@ -8,21 +8,17 @@ 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 java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
public class IoUtils {
private static final Logger LOG = getLogger(IoUtils.class.getName());
private static final Logger LOG = Logger.getLogger(IoUtils.class.getName());
public static void deleteFileOrDir(File f) {
if (f.isFile()) {
@@ -58,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
}
}

View File

@@ -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() {

View File

@@ -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);
}
}
@@ -153,4 +153,15 @@ public class StringUtils {
return new String(c);
}
public static String getRandomBase32String(int length) {
char[] c = new char[length];
for (int i = 0; i < length; i++) {
int character = random.nextInt(32);
if (character < 26) c[i] = (char) ('a' + character);
else c[i] = (char) ('2' + (character - 26));
}
return new String(c);
}
}

View File

@@ -7,15 +7,13 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@NotNullByDefault
public class ValidationUtils {
public static void checkLength(@Nullable String s, int minLength,
int maxLength) throws FormatException {
if (s != null) {
int length = toUtf8(s).length;
int length = StringUtils.toUtf8(s).length;
if (length < minLength) throw new FormatException();
if (length > maxLength) throw new FormatException();
}
@@ -23,7 +21,7 @@ public class ValidationUtils {
public static void checkLength(@Nullable String s, int length)
throws FormatException {
if (s != null && toUtf8(s).length != length)
if (s != null && StringUtils.toUtf8(s).length != length)
throw new FormatException();
}

View File

@@ -8,7 +8,6 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.Map.Entry;
import static java.util.Collections.singletonMap;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -20,15 +19,15 @@ public class BdfDictionaryTest extends BrambleTestCase {
public void testConstructors() {
assertEquals(Collections.<String, Object>emptyMap(),
new BdfDictionary());
assertEquals(singletonMap("foo", NULL_VALUE),
new BdfDictionary(singletonMap("foo", NULL_VALUE)));
assertEquals(Collections.singletonMap("foo", NULL_VALUE),
new BdfDictionary(Collections.singletonMap("foo", NULL_VALUE)));
}
@Test
public void testFactoryMethod() {
assertEquals(Collections.<String, Object>emptyMap(),
BdfDictionary.of());
assertEquals(singletonMap("foo", NULL_VALUE),
assertEquals(Collections.singletonMap("foo", NULL_VALUE),
BdfDictionary.of(new BdfEntry("foo", NULL_VALUE)));
}
@@ -68,7 +67,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
}
@Test
public void testKeySetIteratorIsOrderedByKeys() {
public void testKeySetIteratorIsOrderedByKeys() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("a", 1);
d.put("d", 4);
@@ -87,7 +86,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
}
@Test
public void testValuesIteratorIsOrderedByKeys() {
public void testValuesIteratorIsOrderedByKeys() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("a", 1);
d.put("d", 4);
@@ -106,7 +105,7 @@ public class BdfDictionaryTest extends BrambleTestCase {
}
@Test
public void testEntrySetIteratorIsOrderedByKeys() {
public void testEntrySetIteratorIsOrderedByKeys() throws Exception {
BdfDictionary d = new BdfDictionary();
d.put("a", 1);
d.put("d", 4);

View File

@@ -5,31 +5,26 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import java.util.Random;
import java.util.Arrays;
import java.util.Collections;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class BdfListTest extends BrambleTestCase {
private final Random random = new Random();
@Test
public void testConstructors() {
assertEquals(emptyList(), new BdfList());
assertEquals(asList(1, 2, NULL_VALUE),
new BdfList(asList(1, 2, NULL_VALUE)));
assertEquals(Collections.emptyList(), new BdfList());
assertEquals(Arrays.asList(1, 2, NULL_VALUE),
new BdfList(Arrays.asList(1, 2, NULL_VALUE)));
}
@Test
public void testFactoryMethod() {
assertEquals(emptyList(), BdfList.of());
assertEquals(asList(1, 2, NULL_VALUE),
assertEquals(Collections.emptyList(), BdfList.of());
assertEquals(Arrays.asList(1, 2, NULL_VALUE),
BdfList.of(1, 2, NULL_VALUE));
}
@@ -69,21 +64,22 @@ public class BdfListTest extends BrambleTestCase {
}
@Test
public void testIndexOutOfBoundsReturnsDefaultValue() {
@SuppressWarnings("ConstantConditions")
public void testIndexOutOfBoundsReturnsDefaultValue() throws Exception {
BdfList list = BdfList.of(1, 2, 3);
boolean defaultBoolean = random.nextBoolean();
boolean defaultBoolean = true;
assertEquals(defaultBoolean, list.getBoolean(-1, defaultBoolean));
assertEquals(defaultBoolean, list.getBoolean(3, defaultBoolean));
Long defaultLong = random.nextLong();
Long defaultLong = 123L;
assertEquals(defaultLong, list.getLong(-1, defaultLong));
assertEquals(defaultLong, list.getLong(3, defaultLong));
Double defaultDouble = random.nextDouble();
Double defaultDouble = 1.23;
assertEquals(defaultDouble, list.getDouble(-1, defaultDouble));
assertEquals(defaultDouble, list.getDouble(3, defaultDouble));
String defaultString = getRandomString(123);
String defaultString = "123";
assertEquals(defaultString, list.getString(-1, defaultString));
assertEquals(defaultString, list.getString(3, defaultString));
byte[] defaultBytes = getRandomBytes(123);
byte[] defaultBytes = new byte[] {1, 2, 3};
assertArrayEquals(defaultBytes, list.getRaw(-1, defaultBytes));
assertArrayEquals(defaultBytes, list.getRaw(3, defaultBytes));
BdfList defaultList = BdfList.of(1, 2, 3);
@@ -99,17 +95,18 @@ public class BdfListTest extends BrambleTestCase {
}
@Test
public void testWrongTypeReturnsDefaultValue() {
@SuppressWarnings("ConstantConditions")
public void testWrongTypeReturnsDefaultValue() throws Exception {
BdfList list = BdfList.of(1, 2, 3, true);
boolean defaultBoolean = random.nextBoolean();
boolean defaultBoolean = true;
assertEquals(defaultBoolean, list.getBoolean(0, defaultBoolean));
Long defaultLong = random.nextLong();
Long defaultLong = 123L;
assertEquals(defaultLong, list.getLong(3, defaultLong));
Double defaultDouble = random.nextDouble();
Double defaultDouble = 1.23;
assertEquals(defaultDouble, list.getDouble(0, defaultDouble));
String defaultString = getRandomString(123);
String defaultString = "123";
assertEquals(defaultString, list.getString(0, defaultString));
byte[] defaultBytes = getRandomBytes(123);
byte[] defaultBytes = new byte[] {1, 2, 3};
assertArrayEquals(defaultBytes, list.getRaw(0, defaultBytes));
BdfList defaultList = BdfList.of(1, 2, 3);
assertEquals(defaultList, list.getList(0, defaultList));

View File

@@ -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")
);
}
}

View File

@@ -12,10 +12,12 @@ import org.briarproject.bramble.api.sync.Group;
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.util.IoUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -23,7 +25,6 @@ import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Arrays.asList;
import static java.util.Collections.sort;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -32,7 +33,6 @@ import static org.briarproject.bramble.api.properties.TransportPropertyConstants
import static org.briarproject.bramble.api.sync.ClientId.MAX_CLIENT_ID_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
public class TestUtils {
@@ -48,10 +48,8 @@ public class TestUtils {
}
public static void deleteTestDirectory(File testDir) {
deleteFileOrDir(testDir);
// Delete parent directory only if it's empty
//noinspection ResultOfMethodCallIgnored
testDir.getParentFile().delete();
IoUtils.deleteFileOrDir(testDir);
testDir.getParentFile().delete(); // Delete if empty
}
public static byte[] getRandomBytes(int length) {
@@ -147,7 +145,7 @@ public class TestUtils {
if (size == 0) throw new IllegalArgumentException();
List<Double> sorted = new ArrayList<>(size);
for (Number n : samples) sorted.add(n.doubleValue());
sort(sorted);
Collections.sort(sorted);
if (size % 2 == 1) return sorted.get(size / 2);
double low = sorted.get(size / 2 - 1), high = sorted.get(size / 2);
return (low + high) / 2;

View File

@@ -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',

View File

@@ -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'
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -10,7 +10,6 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import static java.util.logging.Level.FINE;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.now;
/**
@@ -43,7 +42,7 @@ public class PoliteExecutor implements Executor {
int maxConcurrentTasks) {
this.delegate = delegate;
this.maxConcurrentTasks = maxConcurrentTasks;
log = getLogger(tag);
log = Logger.getLogger(tag);
}
@Override

View File

@@ -9,7 +9,6 @@ import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault
@@ -23,7 +22,7 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
RejectedExecutionHandler handler) {
super(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue,
handler);
log = getLogger(tag);
log = Logger.getLogger(tag);
}
@Override

View File

@@ -6,7 +6,9 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.util.IoUtils;
import java.io.BufferedReader;
import java.io.File;
@@ -17,21 +19,19 @@ import java.io.InputStreamReader;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@NotNullByDefault
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class AccountManagerImpl implements AccountManager {
private static final Logger LOG =
getLogger(AccountManagerImpl.class.getName());
Logger.getLogger(AccountManagerImpl.class.getName());
private static final String DB_KEY_FILENAME = "db.key";
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
@@ -68,7 +68,7 @@ class AccountManagerImpl implements AccountManager {
return databaseKey;
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
@Nullable
protected String loadEncryptedDatabaseKey() {
String key = readDbKeyFromFile(dbKeyFile);
@@ -83,7 +83,7 @@ class AccountManagerImpl implements AccountManager {
return key;
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
@Nullable
private String readDbKeyFromFile(File f) {
if (!f.exists()) {
@@ -102,8 +102,8 @@ class AccountManagerImpl implements AccountManager {
}
}
@GuardedBy("stateChangeLock")
boolean storeEncryptedDatabaseKey(String hex) {
// Locking: stateChangeLock
protected boolean storeEncryptedDatabaseKey(String hex) {
LOG.info("Storing database key in file");
// Create the directory if necessary
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
@@ -140,7 +140,7 @@ class AccountManagerImpl implements AccountManager {
}
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
private void writeDbKeyToFile(String key, File f) throws IOException {
FileOutputStream out = new FileOutputStream(f);
out.write(key.getBytes("UTF-8"));
@@ -170,7 +170,7 @@ class AccountManagerImpl implements AccountManager {
}
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) {
byte[] plaintext = key.getBytes();
byte[] ciphertext = crypto.encryptWithPassword(plaintext, password);
@@ -181,8 +181,8 @@ class AccountManagerImpl implements AccountManager {
public void deleteAccount() {
synchronized (stateChangeLock) {
LOG.info("Deleting account");
deleteFileOrDir(databaseConfig.getDatabaseKeyDirectory());
deleteFileOrDir(databaseConfig.getDatabaseDirectory());
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseKeyDirectory());
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory());
databaseKey = null;
}
}
@@ -197,7 +197,7 @@ class AccountManagerImpl implements AccountManager {
}
}
@GuardedBy("stateChangeLock")
// Locking: stateChangeLock
@Nullable
private SecretKey loadAndDecryptDatabaseKey(String password) {
String hex = loadEncryptedDatabaseKey();

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
@@ -43,7 +44,6 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.util.LogUtils.logException;
@@ -55,7 +55,7 @@ import static org.briarproject.bramble.util.ValidationUtils.checkSize;
class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private static final Logger LOG =
getLogger(ContactExchangeTaskImpl.class.getName());
Logger.getLogger(ContactExchangeTaskImpl.class.getName());
private static final String SIGNING_LABEL_EXCHANGE =
"org.briarproject.briar.contact/EXCHANGE";
@@ -158,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,
@@ -191,7 +190,6 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
streamWriter.sendEndOfStream();
// Skip any remaining records from the incoming stream
try {
//noinspection InfiniteLoopStatement
while (true) recordReader.readRecord();
} catch (EOFException expected) {
LOG.info("End of stream");
@@ -289,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) {

View File

@@ -3,8 +3,6 @@ package org.briarproject.bramble.contact;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.contact.PendingContact;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
@@ -12,53 +10,29 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.KeyManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.Collections.emptyList;
import static org.briarproject.bramble.api.contact.PendingContact.PendingContactState.WAITING_FOR_CONNECTION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@ThreadSafe
@NotNullByDefault
class ContactManagerImpl implements ContactManager {
private static final int LINK_LENGTH = 64;
private static final String REMOTE_CONTACT_LINK =
"briar://" + getRandomBase32String(LINK_LENGTH);
private static final Pattern LINK_REGEX =
Pattern.compile("(briar://)?([a-z2-7]{" + LINK_LENGTH + "})");
private final DatabaseComponent db;
private final KeyManager keyManager;
private final IdentityManager identityManager;
private final List<ContactHook> hooks;
@Inject
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
IdentityManager identityManager) {
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
this.db = db;
this.keyManager = keyManager;
this.identityManager = identityManager;
hooks = new CopyOnWriteArrayList<>();
}
@@ -91,63 +65,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));
}
@Override
public String getRemoteContactLink() {
// TODO replace with real implementation
return REMOTE_CONTACT_LINK;
}
@SuppressWarnings("SameParameterValue")
private static String getRandomBase32String(int length) {
Random random = new Random();
char[] c = new char[length];
for (int i = 0; i < length; i++) {
int character = random.nextInt(32);
if (character < 26) c[i] = (char) ('a' + character);
else c[i] = (char) ('2' + (character - 26));
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 new String(c);
}
@Override
public boolean isValidRemoteContactLink(String link) {
return LINK_REGEX.matcher(link).matches();
}
@Override
public PendingContact addRemoteContactRequest(String link, String alias) {
// TODO replace with real implementation
PendingContactId id = new PendingContactId(link.getBytes());
return new PendingContact(id, alias, WAITING_FOR_CONNECTION,
System.currentTimeMillis());
}
@Override
public Collection<PendingContact> getPendingContacts() {
// TODO replace with real implementation
return emptyList();
}
@Override
public void removePendingContact(PendingContact pendingContact) {
// TODO replace with real implementation
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
@@ -165,8 +118,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;
@@ -174,7 +133,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
@@ -183,23 +148,6 @@ class ContactManagerImpl implements ContactManager {
db.setContactActive(txn, c, active);
}
@Override
public void setContactAlias(Transaction txn, ContactId c,
@Nullable String alias) throws DbException {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
}
db.setContactAlias(txn, c, alias);
}
@Override
public void setContactAlias(ContactId c, @Nullable String alias)
throws DbException {
db.transaction(false, txn -> setContactAlias(txn, c, alias));
}
@Override
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
@@ -209,8 +157,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
@@ -221,23 +176,4 @@ class ContactManagerImpl implements ContactManager {
db.removeContact(txn, c);
}
@Override
public AuthorInfo getAuthorInfo(AuthorId a) throws DbException {
return db.transactionWithResult(true, txn -> getAuthorInfo(txn, a));
}
@Override
public AuthorInfo getAuthorInfo(Transaction txn, AuthorId authorId)
throws DbException {
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
if (localAuthor.getId().equals(authorId))
return new AuthorInfo(OURSELVES);
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
if (contacts.isEmpty()) return new AuthorInfo(UNKNOWN);
if (contacts.size() > 1) throw new AssertionError();
Contact c = contacts.iterator().next();
if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
else return new AuthorInfo(UNVERIFIED, c.getAlias());
}
}

View File

@@ -2,20 +2,18 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
import org.briarproject.bramble.util.StringUtils;
@NotNullByDefault
class AsciiArmour {
static String wrap(byte[] b, int lineLength) {
String wrapped = toHexString(b);
String wrapped = StringUtils.toHexString(b);
StringBuilder s = new StringBuilder();
int length = wrapped.length();
for (int i = 0; i < length; i += lineLength) {
int end = Math.min(i + lineLength, length);
s.append(wrapped, i, end);
s.append(wrapped.substring(i, end));
s.append("\r\n");
}
return s.toString();
@@ -23,7 +21,7 @@ class AsciiArmour {
static byte[] unwrap(String s) throws FormatException {
try {
return fromHexString(s.replaceAll("[^0-9a-fA-F]", ""));
return StringUtils.fromHexString(s.replaceAll("[^0-9a-fA-F]", ""));
} catch (IllegalArgumentException e) {
throw new FormatException();
}

View File

@@ -12,6 +12,8 @@ import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.CryptoException;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
@@ -28,21 +30,16 @@ import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.lang.System.arraycopy;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
import static org.briarproject.bramble.util.ByteUtils.readUint32;
import static org.briarproject.bramble.util.ByteUtils.writeUint32;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@NotNullByDefault
class CryptoComponentImpl implements CryptoComponent {
private static final Logger LOG =
getLogger(CryptoComponentImpl.class.getName());
Logger.getLogger(CryptoComponentImpl.class.getName());
private static final int SIGNATURE_KEY_PAIR_BITS = 256;
private static final int STORAGE_IV_BYTES = 24; // 196 bits
@@ -191,7 +188,7 @@ class CryptoComponentImpl implements CryptoComponent {
PrivateKey ourPriv = ourKeyPair.getPrivate();
byte[][] hashInputs = new byte[inputs.length + 1][];
hashInputs[0] = performRawKeyAgreement(ourPriv, theirPublicKey);
arraycopy(inputs, 0, hashInputs, 1, inputs.length);
System.arraycopy(inputs, 0, hashInputs, 1, inputs.length);
byte[] hash = hash(label, hashInputs);
if (hash.length != SecretKey.LENGTH) throw new IllegalStateException();
return new SecretKey(hash);
@@ -219,26 +216,26 @@ class CryptoComponentImpl implements CryptoComponent {
private void updateSignature(Signature signature, String label,
byte[] toSign) throws GeneralSecurityException {
byte[] labelBytes = toUtf8(label);
byte[] labelBytes = StringUtils.toUtf8(label);
byte[] length = new byte[INT_32_BYTES];
writeUint32(labelBytes.length, length, 0);
ByteUtils.writeUint32(labelBytes.length, length, 0);
signature.update(length);
signature.update(labelBytes);
writeUint32(toSign.length, length, 0);
ByteUtils.writeUint32(toSign.length, length, 0);
signature.update(length);
signature.update(toSign);
}
@Override
public byte[] hash(String label, byte[]... inputs) {
byte[] labelBytes = toUtf8(label);
byte[] labelBytes = StringUtils.toUtf8(label);
Digest digest = new Blake2bDigest(256);
byte[] length = new byte[INT_32_BYTES];
writeUint32(labelBytes.length, length, 0);
ByteUtils.writeUint32(labelBytes.length, length, 0);
digest.update(length, 0, length.length);
digest.update(labelBytes, 0, labelBytes.length);
for (byte[] input : inputs) {
writeUint32(input.length, length, 0);
ByteUtils.writeUint32(input.length, length, 0);
digest.update(length, 0, length.length);
digest.update(input, 0, input.length);
}
@@ -249,14 +246,14 @@ class CryptoComponentImpl implements CryptoComponent {
@Override
public byte[] mac(String label, SecretKey macKey, byte[]... inputs) {
byte[] labelBytes = toUtf8(label);
byte[] labelBytes = StringUtils.toUtf8(label);
Digest mac = new Blake2bDigest(macKey.getBytes(), 32, null, null);
byte[] length = new byte[INT_32_BYTES];
writeUint32(labelBytes.length, length, 0);
ByteUtils.writeUint32(labelBytes.length, length, 0);
mac.update(length, 0, length.length);
mac.update(labelBytes, 0, labelBytes.length);
for (byte[] input : inputs) {
writeUint32(input.length, length, 0);
ByteUtils.writeUint32(input.length, length, 0);
mac.update(length, 0, length.length);
mac.update(input, 0, input.length);
}
@@ -300,13 +297,13 @@ class CryptoComponentImpl implements CryptoComponent {
output[outputOff] = PBKDF_FORMAT_SCRYPT;
outputOff++;
// Salt
arraycopy(salt, 0, output, outputOff, salt.length);
System.arraycopy(salt, 0, output, outputOff, salt.length);
outputOff += salt.length;
// Cost parameter
writeUint32(cost, output, outputOff);
ByteUtils.writeUint32(cost, output, outputOff);
outputOff += INT_32_BYTES;
// IV
arraycopy(iv, 0, output, outputOff, iv.length);
System.arraycopy(iv, 0, output, outputOff, iv.length);
outputOff += iv.length;
// Initialise the cipher and encrypt the plaintext
try {
@@ -336,16 +333,16 @@ class CryptoComponentImpl implements CryptoComponent {
return null; // Unknown format
// Salt
byte[] salt = new byte[PBKDF_SALT_BYTES];
arraycopy(input, inputOff, salt, 0, salt.length);
System.arraycopy(input, inputOff, salt, 0, salt.length);
inputOff += salt.length;
// Cost parameter
long cost = readUint32(input, inputOff);
long cost = ByteUtils.readUint32(input, inputOff);
inputOff += INT_32_BYTES;
if (cost < 2 || cost > Integer.MAX_VALUE)
return null; // Invalid cost parameter
// IV
byte[] iv = new byte[STORAGE_IV_BYTES];
arraycopy(input, inputOff, iv, 0, iv.length);
System.arraycopy(input, inputOff, iv, 0, iv.length);
inputOff += iv.length;
// Derive the key from the password
SecretKey key = passwordBasedKdf.deriveKey(password, salt, (int) cost);

View File

@@ -7,8 +7,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
import static java.lang.System.arraycopy;
@NotNullByDefault
class Curve25519KeyParser implements KeyParser {
@@ -28,7 +26,7 @@ class Curve25519KeyParser implements KeyParser {
static byte[] clamp(byte[] b) {
byte[] clamped = new byte[32];
arraycopy(b, 0, clamped, 0, 32);
System.arraycopy(b, 0, clamped, 0, 32);
clamped[0] &= 248;
clamped[31] &= 127;
clamped[31] |= 64;

View File

@@ -1,15 +1,13 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.ByteUtils;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
import static org.briarproject.bramble.util.ByteUtils.readUint16;
import static org.briarproject.bramble.util.ByteUtils.writeUint16;
import static org.briarproject.bramble.util.ByteUtils.writeUint64;
@NotNullByDefault
class FrameEncoder {
@@ -18,7 +16,7 @@ class FrameEncoder {
if (dest.length < FRAME_NONCE_LENGTH)
throw new IllegalArgumentException();
if (frameNumber < 0) throw new IllegalArgumentException();
writeUint64(frameNumber, dest, 0);
ByteUtils.writeUint64(frameNumber, dest, 0);
if (header) dest[0] |= 0x80;
for (int i = INT_64_BYTES; i < FRAME_NONCE_LENGTH; i++) dest[i] = 0;
}
@@ -31,8 +29,8 @@ class FrameEncoder {
if (paddingLength < 0) throw new IllegalArgumentException();
if (payloadLength + paddingLength > MAX_PAYLOAD_LENGTH)
throw new IllegalArgumentException();
writeUint16(payloadLength, dest, 0);
writeUint16(paddingLength, dest, INT_16_BYTES);
ByteUtils.writeUint16(payloadLength, dest, 0);
ByteUtils.writeUint16(paddingLength, dest, INT_16_BYTES);
if (finalFrame) dest[0] |= 0x80;
}
@@ -45,12 +43,12 @@ class FrameEncoder {
static int getPayloadLength(byte[] header) {
if (header.length < FRAME_HEADER_PLAINTEXT_LENGTH)
throw new IllegalArgumentException();
return readUint16(header, 0) & 0x7FFF;
return ByteUtils.readUint16(header, 0) & 0x7FFF;
}
static int getPaddingLength(byte[] header) {
if (header.length < FRAME_HEADER_PLAINTEXT_LENGTH)
throw new IllegalArgumentException();
return readUint16(header, INT_16_BYTES);
return ByteUtils.readUint16(header, INT_16_BYTES);
}
}

View File

@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import javax.inject.Inject;
import static java.lang.System.arraycopy;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
class KeyAgreementCryptoImpl implements KeyAgreementCrypto {
@@ -25,7 +24,7 @@ class KeyAgreementCryptoImpl implements KeyAgreementCrypto {
byte[] hash = crypto.hash(COMMIT_LABEL, publicKey.getEncoded());
// The output is the first COMMIT_LENGTH bytes of the hash
byte[] commitment = new byte[COMMIT_LENGTH];
arraycopy(hash, 0, commitment, 0, COMMIT_LENGTH);
System.arraycopy(hash, 0, commitment, 0, COMMIT_LENGTH);
return commitment;
}

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
@@ -44,9 +45,6 @@ import java.util.Scanner;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@Immutable
@NotNullByDefault
public class MessageEncrypter {
@@ -159,7 +157,6 @@ public class MessageEncrypter {
printUsage();
System.exit(1);
}
//noinspection IfCanBeSwitch
if (args[0].equals("generate")) {
if (args.length != 3) {
printUsage();
@@ -213,11 +210,11 @@ public class MessageEncrypter {
MessageEncrypter encrypter = new MessageEncrypter(random);
KeyPair keyPair = encrypter.generateKeyPair();
PrintStream out = new PrintStream(new FileOutputStream(publicKeyFile));
out.print(toHexString(keyPair.getPublic().getEncoded()));
out.print(StringUtils.toHexString(keyPair.getPublic().getEncoded()));
out.flush();
out.close();
out = new PrintStream(new FileOutputStream(privateKeyFile));
out.print(toHexString(keyPair.getPrivate().getEncoded()));
out.print(StringUtils.toHexString(keyPair.getPrivate().getEncoded()));
out.flush();
out.close();
}
@@ -226,7 +223,7 @@ public class MessageEncrypter {
SecureRandom random = new SecureRandom();
MessageEncrypter encrypter = new MessageEncrypter(random);
InputStream in = new FileInputStream(publicKeyFile);
byte[] keyBytes = fromHexString(readFully(in).trim());
byte[] keyBytes = StringUtils.fromHexString(readFully(in).trim());
PublicKey publicKey =
encrypter.getKeyParser().parsePublicKey(keyBytes);
String message = readFully(System.in);
@@ -239,7 +236,7 @@ public class MessageEncrypter {
SecureRandom random = new SecureRandom();
MessageEncrypter encrypter = new MessageEncrypter(random);
InputStream in = new FileInputStream(privateKeyFile);
byte[] keyBytes = fromHexString(readFully(in).trim());
byte[] keyBytes = StringUtils.fromHexString(readFully(in).trim());
PrivateKey privateKey =
encrypter.getKeyParser().parsePrivateKey(keyBytes);
byte[] ciphertext = AsciiArmour.unwrap(readFully(System.in));

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.generators.SCrypt;
import java.util.logging.Logger;
@@ -9,14 +10,13 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
class ScryptKdf implements PasswordBasedKdf {
private static final Logger LOG = getLogger(ScryptKdf.class.getName());
private static final Logger LOG =
Logger.getLogger(ScryptKdf.class.getName());
private static final int MIN_COST = 256; // Min parameter N
private static final int MAX_COST = 1024 * 1024; // Max parameter N
@@ -53,7 +53,7 @@ class ScryptKdf implements PasswordBasedKdf {
@Override
public SecretKey deriveKey(String password, byte[] salt, int cost) {
long start = now();
byte[] passwordBytes = toUtf8(password);
byte[] passwordBytes = StringUtils.toUtf8(password);
SecretKey k = new SecretKey(SCrypt.generate(passwordBytes, salt, cost,
BLOCK_SIZE, PARALLELIZATION, SecretKey.LENGTH));
logDuration(LOG, "Deriving key from password", start);

View File

@@ -16,8 +16,6 @@ import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import static java.lang.System.arraycopy;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -30,7 +28,8 @@ import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault
class Sec1KeyParser implements KeyParser {
private static final Logger LOG = getLogger(Sec1KeyParser.class.getName());
private static final Logger LOG =
Logger.getLogger(Sec1KeyParser.class.getName());
private final ECDomainParameters params;
private final BigInteger modulus;
@@ -57,12 +56,12 @@ class Sec1KeyParser implements KeyParser {
if (encodedKey[0] != 4) throw new GeneralSecurityException();
// The x co-ordinate must be >= 0 and < p
byte[] xBytes = new byte[bytesPerInt];
arraycopy(encodedKey, 1, xBytes, 0, bytesPerInt);
System.arraycopy(encodedKey, 1, xBytes, 0, bytesPerInt);
BigInteger x = new BigInteger(1, xBytes); // Positive signum
if (x.compareTo(modulus) >= 0) throw new GeneralSecurityException();
// The y co-ordinate must be >= 0 and < p
byte[] yBytes = new byte[bytesPerInt];
arraycopy(encodedKey, 1 + bytesPerInt, yBytes, 0, bytesPerInt);
System.arraycopy(encodedKey, 1 + bytesPerInt, yBytes, 0, bytesPerInt);
BigInteger y = new BigInteger(1, yBytes); // Positive signum
if (y.compareTo(modulus) >= 0) throw new GeneralSecurityException();
// Verify that y^2 == x^3 + ax + b (mod p)

View File

@@ -2,8 +2,6 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import static java.lang.System.arraycopy;
@NotNullByDefault
class Sec1Utils {
@@ -12,10 +10,10 @@ class Sec1Utils {
if (src.length < destLen) {
int padding = destLen - src.length;
for (int i = destOff; i < destOff + padding; i++) dest[i] = 0;
arraycopy(src, 0, dest, destOff + padding, src.length);
System.arraycopy(src, 0, dest, destOff + padding, src.length);
} else {
int srcOff = src.length - destLen;
arraycopy(src, srcOff, dest, destOff, destLen);
System.arraycopy(src, srcOff, dest, destOff, destLen);
}
}
}

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.StreamDecrypter;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.ByteUtils;
import java.io.EOFException;
import java.io.IOException;
@@ -13,7 +14,6 @@ import java.security.GeneralSecurityException;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static java.lang.System.arraycopy;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
@@ -26,8 +26,6 @@ import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_H
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_PLAINTEXT_LENGTH;
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
import static org.briarproject.bramble.util.ByteUtils.readUint16;
import static org.briarproject.bramble.util.ByteUtils.readUint64;
@NotThreadSafe
@NotNullByDefault
@@ -132,7 +130,7 @@ class StreamDecrypterImpl implements StreamDecrypter {
}
// Extract the nonce
byte[] streamHeaderNonce = new byte[STREAM_HEADER_NONCE_LENGTH];
arraycopy(streamHeaderCiphertext, 0, streamHeaderNonce, 0,
System.arraycopy(streamHeaderCiphertext, 0, streamHeaderNonce, 0,
STREAM_HEADER_NONCE_LENGTH);
// Decrypt and authenticate the stream header
try {
@@ -147,16 +145,17 @@ class StreamDecrypterImpl implements StreamDecrypter {
throw new FormatException();
}
// Check the protocol version
int receivedProtocolVersion = readUint16(streamHeaderPlaintext, 0);
int receivedProtocolVersion =
ByteUtils.readUint16(streamHeaderPlaintext, 0);
if (receivedProtocolVersion != PROTOCOL_VERSION)
throw new FormatException();
// Check the stream number
long receivedStreamNumber = readUint64(streamHeaderPlaintext,
long receivedStreamNumber = ByteUtils.readUint64(streamHeaderPlaintext,
INT_16_BYTES);
if (receivedStreamNumber != streamNumber) throw new FormatException();
// Extract the frame key
byte[] frameKeyBytes = new byte[SecretKey.LENGTH];
arraycopy(streamHeaderPlaintext, INT_16_BYTES + INT_64_BYTES,
System.arraycopy(streamHeaderPlaintext, INT_16_BYTES + INT_64_BYTES,
frameKeyBytes, 0, SecretKey.LENGTH);
frameKey = new SecretKey(frameKeyBytes);
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.StreamEncrypter;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.ByteUtils;
import java.io.IOException;
import java.io.OutputStream;
@@ -11,7 +12,6 @@ import java.security.GeneralSecurityException;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import static java.lang.System.arraycopy;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_HEADER_PLAINTEXT_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.FRAME_NONCE_LENGTH;
@@ -24,8 +24,6 @@ import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_H
import static org.briarproject.bramble.api.transport.TransportConstants.STREAM_HEADER_PLAINTEXT_LENGTH;
import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
import static org.briarproject.bramble.util.ByteUtils.writeUint16;
import static org.briarproject.bramble.util.ByteUtils.writeUint64;
@NotThreadSafe
@NotNullByDefault
@@ -90,7 +88,7 @@ class StreamEncrypterImpl implements StreamEncrypter {
throw new RuntimeException(badCipher);
}
// Combine the payload and padding
arraycopy(payload, 0, framePlaintext, 0, payloadLength);
System.arraycopy(payload, 0, framePlaintext, 0, payloadLength);
for (int i = 0; i < paddingLength; i++)
framePlaintext[payloadLength + i] = 0;
// Encrypt and authenticate the payload and padding
@@ -120,12 +118,13 @@ class StreamEncrypterImpl implements StreamEncrypter {
private void writeStreamHeader() throws IOException {
// The header contains the protocol version, stream number and frame key
byte[] streamHeaderPlaintext = new byte[STREAM_HEADER_PLAINTEXT_LENGTH];
writeUint16(PROTOCOL_VERSION, streamHeaderPlaintext, 0);
writeUint64(streamNumber, streamHeaderPlaintext, INT_16_BYTES);
arraycopy(frameKey.getBytes(), 0, streamHeaderPlaintext,
ByteUtils.writeUint16(PROTOCOL_VERSION, streamHeaderPlaintext, 0);
ByteUtils.writeUint64(streamNumber, streamHeaderPlaintext,
INT_16_BYTES);
System.arraycopy(frameKey.getBytes(), 0, streamHeaderPlaintext,
INT_16_BYTES + INT_64_BYTES, SecretKey.LENGTH);
byte[] streamHeaderCiphertext = new byte[STREAM_HEADER_LENGTH];
arraycopy(streamHeaderNonce, 0, streamHeaderCiphertext, 0,
System.arraycopy(streamHeaderNonce, 0, streamHeaderCiphertext, 0,
STREAM_HEADER_NONCE_LENGTH);
// Encrypt and authenticate the stream header key
try {

View File

@@ -7,12 +7,13 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.IncomingKeys;
import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import javax.inject.Inject;
import static java.lang.System.arraycopy;
import static org.briarproject.bramble.api.transport.TransportConstants.ALICE_HEADER_LABEL;
import static org.briarproject.bramble.api.transport.TransportConstants.ALICE_TAG_LABEL;
import static org.briarproject.bramble.api.transport.TransportConstants.BOB_HEADER_LABEL;
@@ -23,9 +24,6 @@ import static org.briarproject.bramble.util.ByteUtils.INT_16_BYTES;
import static org.briarproject.bramble.util.ByteUtils.INT_64_BYTES;
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
import static org.briarproject.bramble.util.ByteUtils.writeUint16;
import static org.briarproject.bramble.util.ByteUtils.writeUint64;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
class TransportCryptoImpl implements TransportCrypto {
@@ -93,21 +91,21 @@ class TransportCryptoImpl implements TransportCrypto {
private SecretKey rotateKey(SecretKey k, long rotationPeriod) {
byte[] period = new byte[INT_64_BYTES];
writeUint64(rotationPeriod, period, 0);
ByteUtils.writeUint64(rotationPeriod, period, 0);
return crypto.deriveKey(ROTATE_LABEL, k, period);
}
private SecretKey deriveTagKey(SecretKey master, TransportId t,
boolean alice) {
String label = alice ? ALICE_TAG_LABEL : BOB_TAG_LABEL;
byte[] id = toUtf8(t.getString());
byte[] id = StringUtils.toUtf8(t.getString());
return crypto.deriveKey(label, master, id);
}
private SecretKey deriveHeaderKey(SecretKey master, TransportId t,
boolean alice) {
String label = alice ? ALICE_HEADER_LABEL : BOB_HEADER_LABEL;
byte[] id = toUtf8(t.getString());
byte[] id = StringUtils.toUtf8(t.getString());
return crypto.deriveKey(label, master, id);
}
@@ -127,14 +125,14 @@ class TransportCryptoImpl implements TransportCrypto {
// The input is the protocol version as a 16-bit integer, followed by
// the stream number as a 64-bit integer
byte[] protocolVersionBytes = new byte[INT_16_BYTES];
writeUint16(protocolVersion, protocolVersionBytes, 0);
ByteUtils.writeUint16(protocolVersion, protocolVersionBytes, 0);
prf.update(protocolVersionBytes, 0, protocolVersionBytes.length);
byte[] streamNumberBytes = new byte[INT_64_BYTES];
writeUint64(streamNumber, streamNumberBytes, 0);
ByteUtils.writeUint64(streamNumber, streamNumberBytes, 0);
prf.update(streamNumberBytes, 0, streamNumberBytes.length);
byte[] mac = new byte[macLength];
prf.doFinal(mac, 0);
// The output is the first TAG_LENGTH bytes of the MAC
arraycopy(mac, 0, tag, 0, TAG_LENGTH);
System.arraycopy(mac, 0, tag, 0, TAG_LENGTH);
}
}

View File

@@ -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 {

View File

@@ -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.
@@ -242,7 +242,7 @@ interface Database<T> {
* bytes. This is based on the minimum of the space available on the device
* where the database is stored and the database's configured size.
*/
long getFreeSpace();
long getFreeSpace() throws DbException;
/**
* Returns the group with the given ID.
@@ -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
@@ -616,12 +616,6 @@ interface Database<T> {
void setContactActive(T txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for a contact.
*/
void setContactAlias(T txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets the given group's visibility to the given contact to either
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
@@ -637,8 +631,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

View File

@@ -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,13 +54,13 @@ 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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -71,13 +71,11 @@ import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.Collections.singletonList;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
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;
@@ -88,7 +86,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
class DatabaseComponentImpl<T> implements DatabaseComponent {
private static final Logger LOG =
getLogger(DatabaseComponentImpl.class.getName());
Logger.getLogger(DatabaseComponentImpl.class.getName());
private final Database<T> db;
private final Class<T> txnClass;
@@ -195,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());
@@ -580,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))
@@ -620,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();
@@ -629,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();
@@ -875,16 +859,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new ContactStatusChangedEvent(c, active));
}
@Override
public void setContactAlias(Transaction transaction, ContactId c,
@Nullable String alias) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
db.setContactAlias(txn, c, alias);
}
@Override
public void setGroupVisibility(Transaction transaction, ContactId c,
GroupId g, Visibility v) throws DbException {
@@ -899,7 +873,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
if (old == INVISIBLE) db.addGroupVisibility(txn, c, g, v == SHARED);
else if (v == INVISIBLE) db.removeGroupVisibility(txn, c, g);
else db.setGroupVisibility(txn, c, g, v == SHARED);
List<ContactId> affected = singletonList(c);
List<ContactId> affected = Collections.singletonList(c);
transaction.attach(new GroupVisibilityUpdatedEvent(affected));
}
@@ -919,7 +893,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))
@@ -936,10 +910,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);
}
}

View File

@@ -1,34 +0,0 @@
package org.briarproject.bramble.db;
class DatabaseTypes {
private final String hashType, secretType, binaryType;
private final String counterType, stringType;
public DatabaseTypes(String hashType, String secretType, String binaryType,
String counterType, String stringType) {
this.hashType = hashType;
this.secretType = secretType;
this.binaryType = binaryType;
this.counterType = counterType;
this.stringType = stringType;
}
/**
* Replaces database type placeholders in a statement with the actual types.
* These placeholders are currently supported:
* <li> _HASH
* <li> _SECRET
* <li> _BINARY
* <li> _COUNTER
* <li> _STRING
*/
String replaceTypes(String s) {
s = s.replaceAll("_HASH", hashType);
s = s.replaceAll("_SECRET", secretType);
s = s.replaceAll("_BINARY", binaryType);
s = s.replaceAll("_COUNTER", counterType);
s = s.replaceAll("_STRING", stringType);
return s;
}
}

View File

@@ -7,6 +7,7 @@ import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
import java.io.File;
import java.sql.Connection;
@@ -14,31 +15,21 @@ 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;
import static org.briarproject.bramble.util.StringUtils.toHexString;
/**
* 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";
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT";
private static final String STRING_TYPE = "VARCHAR";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE);
private final DatabaseConfig config;
private final String url;
@@ -49,7 +40,8 @@ class H2Database extends JdbcDatabase {
@Inject
H2Database(DatabaseConfig config, MessageFactory messageFactory,
Clock clock) {
super(dbTypes, messageFactory, clock);
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
messageFactory, clock);
this.config = config;
File dir = config.getDatabaseDirectory();
String path = new File(dir, "db").getAbsolutePath();
@@ -107,7 +99,7 @@ class H2Database extends JdbcDatabase {
Properties props = new Properties();
props.setProperty("user", "user");
// Separate the file password from the user password with a space
String hex = toHexString(key.getBytes());
String hex = StringUtils.toHexString(key.getBytes());
props.put("password", hex + " password");
return DriverManager.getConnection(getUrl(), props);
}
@@ -128,8 +120,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);
}
}

View File

@@ -7,39 +7,29 @@ import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
import java.io.File;
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;
import static org.briarproject.bramble.util.StringUtils.toHexString;
/**
* 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";
private static final String COUNTER_TYPE =
"INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1)";
private static final String STRING_TYPE = "VARCHAR";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE);
private final DatabaseConfig config;
private final String url;
@@ -50,7 +40,8 @@ class HyperSqlDatabase extends JdbcDatabase {
@Inject
HyperSqlDatabase(DatabaseConfig config, MessageFactory messageFactory,
Clock clock) {
super(dbTypes, messageFactory, clock);
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
messageFactory, clock);
this.config = config;
File dir = config.getDatabaseDirectory();
String path = new File(dir, "db").getAbsolutePath();
@@ -80,14 +71,14 @@ 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);
}
}
@Override
public long getFreeSpace() {
public long getFreeSpace() throws DbException {
File dir = config.getDatabaseDirectory();
long maxSize = config.getMaxSize();
long free = dir.getFreeSpace();
@@ -114,7 +105,7 @@ class HyperSqlDatabase extends JdbcDatabase {
protected Connection createConnection() throws SQLException {
SecretKey key = this.key;
if (key == null) throw new IllegalStateException();
String hex = toHexString(key.getBytes());
String hex = StringUtils.toHexString(key.getBytes());
return DriverManager.getConnection(url + ";crypt_key=" + hex);
}
@@ -130,8 +121,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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -7,13 +7,15 @@ 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 Migration38_39 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration38_39.class.getName());
private static final Logger LOG =
Logger.getLogger(Migration38_39.class.getName());
@Override
public int getStartVersion() {
@@ -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);
}
}
}

View File

@@ -7,13 +7,15 @@ 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 Migration39_40 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration39_40.class.getName());
private static final Logger LOG =
Logger.getLogger(Migration39_40.class.getName());
@Override
public int getStartVersion() {
@@ -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);
}
}
}

View File

@@ -1,46 +0,0 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DbException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration40_41 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration40_41.class.getName());
private final DatabaseTypes dbTypes;
Migration40_41(DatabaseTypes databaseTypes) {
this.dbTypes = databaseTypes;
}
@Override
public int getStartVersion() {
return 40;
}
@Override
public int getEndVersion() {
return 41;
}
@Override
public void migrate(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
s.execute("ALTER TABLE contacts"
+ dbTypes.replaceTypes(" ADD alias _STRING"));
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
}

View File

@@ -7,6 +7,8 @@ import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
@@ -14,8 +16,6 @@ import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorId.LABEL;
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
import static org.briarproject.bramble.util.ByteUtils.writeUint32;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@Immutable
@NotNullByDefault
@@ -58,8 +58,8 @@ class AuthorFactoryImpl implements AuthorFactory {
private AuthorId getId(int formatVersion, String name, byte[] publicKey) {
byte[] formatVersionBytes = new byte[INT_32_BYTES];
writeUint32(formatVersion, formatVersionBytes, 0);
ByteUtils.writeUint32(formatVersion, formatVersionBytes, 0);
return new AuthorId(crypto.hash(LABEL, formatVersionBytes,
toUtf8(name), publicKey));
StringUtils.toUtf8(name), publicKey));
}
}

View File

@@ -1,22 +1,29 @@
package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author.Status;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -25,7 +32,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
class IdentityManagerImpl implements IdentityManager {
private static final Logger LOG =
getLogger(IdentityManagerImpl.class.getName());
Logger.getLogger(IdentityManagerImpl.class.getName());
private final DatabaseComponent db;
private final CryptoComponent crypto;
@@ -68,16 +75,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();
@@ -100,4 +118,26 @@ class IdentityManagerImpl implements IdentityManager {
return db.getLocalAuthors(txn).iterator().next();
}
@Override
public Status getAuthorStatus(AuthorId authorId) throws DbException {
Transaction txn = db.startTransaction(true);
try {
return getAuthorStatus(txn, authorId);
} finally {
db.endTransaction(txn);
}
}
@Override
public Status getAuthorStatus(Transaction txn, AuthorId authorId)
throws DbException {
if (getLocalAuthor(txn).getId().equals(authorId)) return OURSELVES;
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
if (contacts.isEmpty()) return UNKNOWN;
for (Contact c : contacts) {
if (c.isVerified()) return VERIFIED;
}
return UNVERIFIED;
}
}

Some files were not shown because too many files have changed in this diff Show More