mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Compare commits
142 Commits
beta-0.16.
...
beta-0.16.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
347c2f22c1 | ||
|
|
a8ea191ffb | ||
|
|
2a4c22757b | ||
|
|
28ebbbc7d1 | ||
|
|
5e7d08f05d | ||
|
|
ea005748dc | ||
|
|
b021bfab5e | ||
|
|
29cd105a1d | ||
|
|
be2e68e96c | ||
|
|
9dd3f81bb7 | ||
|
|
5d918591d4 | ||
|
|
f1c027fa4d | ||
|
|
d2d3ccf68d | ||
|
|
f4efed54d5 | ||
|
|
459538e40c | ||
|
|
183f501761 | ||
|
|
65ee5f539b | ||
|
|
604339326c | ||
|
|
0acec1343f | ||
|
|
0434756bbd | ||
|
|
e233433140 | ||
|
|
c63f285f53 | ||
|
|
0800188718 | ||
|
|
6188e48beb | ||
|
|
5726e29b56 | ||
|
|
5d70399de0 | ||
|
|
73202dde5e | ||
|
|
a98ac8233c | ||
|
|
bee3e244fc | ||
|
|
da25999a15 | ||
|
|
62049df342 | ||
|
|
024e5aa90f | ||
|
|
6d791481d5 | ||
|
|
0a807d0893 | ||
|
|
23596bbdd4 | ||
|
|
fe79954138 | ||
|
|
9902c023ca | ||
|
|
e8baee6734 | ||
|
|
a8dc029e56 | ||
|
|
74e3fee7aa | ||
|
|
05aac696b7 | ||
|
|
48918f4727 | ||
|
|
303b5bd395 | ||
|
|
97733a52c8 | ||
|
|
89dcbec599 | ||
|
|
6497809fe1 | ||
|
|
9f3a63d8c4 | ||
|
|
748fa77d94 | ||
|
|
4ca86ee4eb | ||
|
|
ec2f372933 | ||
|
|
4267800db2 | ||
|
|
bb8cb9bcbb | ||
|
|
d5b9e15ee1 | ||
|
|
43ee3246f6 | ||
|
|
b56724dee5 | ||
|
|
92748ac872 | ||
|
|
b89686c287 | ||
|
|
a34692630b | ||
|
|
735208562a | ||
|
|
49826fdc56 | ||
|
|
e8c54a609c | ||
|
|
ece2c51358 | ||
|
|
3ec8af4661 | ||
|
|
77a08596fe | ||
|
|
879f699b2b | ||
|
|
d7383a3361 | ||
|
|
a5b321a93b | ||
|
|
5fa6b0ca1c | ||
|
|
27328afe3c | ||
|
|
2d26af1ae2 | ||
|
|
6db8f33e8f | ||
|
|
d6a7e6d52c | ||
|
|
df99b3b666 | ||
|
|
0f1c9f4fe2 | ||
|
|
5dcd5f79dc | ||
|
|
8a81171739 | ||
|
|
1c4f20f76f | ||
|
|
f84fa588f6 | ||
|
|
e30e34f342 | ||
|
|
fc93ced067 | ||
|
|
bb7df72d31 | ||
|
|
f8425658e4 | ||
|
|
53c8cf09b6 | ||
|
|
9f29bf4949 | ||
|
|
98e2adf794 | ||
|
|
2a43e0b0ed | ||
|
|
773ae73820 | ||
|
|
009db57bc5 | ||
|
|
5e98126e77 | ||
|
|
bd7ebfd83a | ||
|
|
10f41ef157 | ||
|
|
1dd4960109 | ||
|
|
75413b6c86 | ||
|
|
b2180582a7 | ||
|
|
8211ce7ae3 | ||
|
|
e6b1597fa7 | ||
|
|
8937d3cd9c | ||
|
|
51f320d147 | ||
|
|
e402a894bb | ||
|
|
9b577f1219 | ||
|
|
220f678403 | ||
|
|
4173fc4daa | ||
|
|
c6756d2145 | ||
|
|
6731f6eeb5 | ||
|
|
6f7f8b40e3 | ||
|
|
1a83b2c99b | ||
|
|
f641fae1c7 | ||
|
|
deb43d9872 | ||
|
|
cee4e1305e | ||
|
|
a1f989c43c | ||
|
|
b67abadbac | ||
|
|
8c29c85696 | ||
|
|
4fe4c298d7 | ||
|
|
13d35229d5 | ||
|
|
f0137b41b6 | ||
|
|
b221d21903 | ||
|
|
8bac202626 | ||
|
|
973151c949 | ||
|
|
ed26ab78a5 | ||
|
|
8454b2d235 | ||
|
|
91d0f89f60 | ||
|
|
e074672e86 | ||
|
|
6c1901fe5b | ||
|
|
49052be627 | ||
|
|
5b5b540630 | ||
|
|
9993bac3a1 | ||
|
|
3c95988693 | ||
|
|
fc5c3b470e | ||
|
|
53f05a72ba | ||
|
|
2c10ae7d06 | ||
|
|
6b9010c557 | ||
|
|
1bf0fdfa81 | ||
|
|
237759aac0 | ||
|
|
2a141e0a97 | ||
|
|
d6900be68e | ||
|
|
a35d7c7204 | ||
|
|
86287f9241 | ||
|
|
0b2e3dd96f | ||
|
|
90aa1d1ce7 | ||
|
|
5c51259269 | ||
|
|
7eefa07052 | ||
|
|
eb9d0c00a8 |
@@ -6,9 +6,18 @@ cache:
|
|||||||
- .gradle/caches
|
- .gradle/caches
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
- set -e
|
||||||
- export GRADLE_USER_HOME=$PWD/.gradle
|
- export GRADLE_USER_HOME=$PWD/.gradle
|
||||||
# - export ANDROID_COMPILE_SDK=`sed -n 's,.*compileSdkVersion\s*\([0-9][0-9]*\).*,\1,p' app/build.gradle`
|
# Accept the license for the Android build tools
|
||||||
# - echo y | android --silent update sdk --no-ui --filter android-${ANDROID_COMPILE_SDK}
|
- echo y | /opt/android-sdk/tools/bin/sdkmanager "build-tools;26.0.2"
|
||||||
|
# Download OpenJDK 6 so we can compile against its standard library
|
||||||
|
- JDK_FILE=openjdk-6-jre-headless_6b38-1.13.10-1~deb7u1_amd64.deb
|
||||||
|
- if [ ! -d openjdk ]
|
||||||
|
- then
|
||||||
|
- wget -q http://ftp.uk.debian.org/debian/pool/main/o/openjdk-6/$JDK_FILE
|
||||||
|
- dpkg-deb -x $JDK_FILE openjdk
|
||||||
|
- fi
|
||||||
|
- export JAVA_6_HOME=$PWD/openjdk/usr/lib/jvm/java-6-openjdk-amd64
|
||||||
|
|
||||||
test:
|
test:
|
||||||
script:
|
script:
|
||||||
|
|||||||
@@ -6,99 +6,90 @@ apply plugin: 'witness'
|
|||||||
apply plugin: 'de.undercouch.download'
|
apply plugin: 'de.undercouch.download'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion 27
|
||||||
buildToolsVersion "23.0.3"
|
buildToolsVersion '26.0.2'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 22
|
targetSdkVersion 26
|
||||||
versionCode 1610
|
versionCode 1617
|
||||||
versionName "0.16.10"
|
versionName "0.16.17"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_7
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':bramble-core')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
implementation fileTree(dir: 'libs', include: '*.jar')
|
||||||
provided 'javax.annotation:jsr250-api:1.0'
|
|
||||||
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
|
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
def torBinaryDir = 'src/main/res/raw'
|
dependencyVerification {
|
||||||
|
verify = [
|
||||||
task downloadTorGeoIp(type: Download) {
|
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||||
src 'https://briarproject.org/build/geoip-2017-09-06.zip'
|
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
dest "$torBinaryDir/geoip.zip"
|
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
onlyIfNewer true
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
|
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
|
||||||
|
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||||
|
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||||
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
|
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
||||||
|
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128-runtime.jar:e357a0f1d573c2f702a273992b1b6cb661734f66311854efb3778a888515c5b5',
|
||||||
|
'org.jacoco:org.jacoco.agent:0.7.4.201502262128:org.jacoco.agent-0.7.4.201502262128.jar:47b4bec6df11a1118da3953da8b9fa1e7079d6fec857faa1a3cf912e53a6fd4e',
|
||||||
|
'org.jacoco:org.jacoco.ant:0.7.4.201502262128:org.jacoco.ant-0.7.4.201502262128.jar:013ce2a68ba57a3c59215ae0dec4df3498c078062a38c3b94c841fc14450f283',
|
||||||
|
'org.jacoco:org.jacoco.core:0.7.4.201502262128:org.jacoco.core-0.7.4.201502262128.jar:ec4c74554312fac5116350164786f91b35c9e082fa4ea598bfa42b5db05d7abb',
|
||||||
|
'org.jacoco:org.jacoco.report:0.7.4.201502262128:org.jacoco.report-0.7.4.201502262128.jar:7a3554c605e088e7e323b1084656243f0444fa353e2f2dee1f1a4204eb64ff09',
|
||||||
|
'org.ow2.asm:asm-debug-all:5.0.1:asm-debug-all-5.0.1.jar:4734de5b515a454b0096db6971fb068e5f70e6f10bbee2b3bd2fdfe5d978ed57',
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadTorBinaryArm(type: Download) {
|
ext.torBinaryDir = 'src/main/res/raw'
|
||||||
src 'https://briarproject.org/build/tor-0.2.9.12-arm.zip'
|
ext.torVersion = '0.2.9.14'
|
||||||
dest "$torBinaryDir/tor_arm.zip"
|
ext.geoipVersion = '2017-11-06'
|
||||||
onlyIfNewer true
|
ext.torDownloadUrl = 'https://briarproject.org/build/'
|
||||||
|
|
||||||
|
def torBinaries = [
|
||||||
|
"tor_arm" : '1710ea6c47b7f4c1a88bdf4858c7893837635db10e8866854eed8d61629f50e8',
|
||||||
|
"tor_arm_pie": '974e6949507db8fa2ea45231817c2c3677ed4ccf5488a2252317d744b0be1917',
|
||||||
|
"tor_x86" : '3a5e45b3f051fcda9353b098b7086e762ffe7ba9242f7d7c8bf6523faaa8b1e9',
|
||||||
|
"tor_x86_pie": 'd1d96d8ce1a4b68accf04850185780d10cd5563d3552f7e1f040f8ca32cb4e51',
|
||||||
|
"geoip" : '8239b98374493529a29096e45fc5877d4d6fdad0146ad8380b291f90d61484ea'
|
||||||
|
]
|
||||||
|
|
||||||
|
def downloadBinary(name) {
|
||||||
|
return tasks.create("downloadBinary${name}", Download) {
|
||||||
|
src "${torDownloadUrl}${name}.zip"
|
||||||
|
.replace('tor_', "tor-${torVersion}-")
|
||||||
|
.replace('geoip', "geoip-${geoipVersion}")
|
||||||
|
.replaceAll('_', '-')
|
||||||
|
dest "${torBinaryDir}/${name}.zip"
|
||||||
|
onlyIfNewer true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task downloadTorBinaryArmPie(type: Download) {
|
def verifyBinary(name, chksum) {
|
||||||
src 'https://briarproject.org/build/tor-0.2.9.12-arm-pie.zip'
|
return tasks.create([
|
||||||
dest "$torBinaryDir/tor_arm_pie.zip"
|
name : "verifyBinary${name}",
|
||||||
onlyIfNewer true
|
type : Verify,
|
||||||
}
|
dependsOn: downloadBinary(name)]) {
|
||||||
|
src "${torBinaryDir}/${name}.zip"
|
||||||
task downloadTorBinaryX86(type: Download) {
|
algorithm 'SHA-256'
|
||||||
src 'https://briarproject.org/build/tor-0.2.9.12-x86.zip'
|
checksum chksum
|
||||||
dest "$torBinaryDir/tor_x86.zip"
|
}
|
||||||
onlyIfNewer true
|
|
||||||
}
|
|
||||||
|
|
||||||
task downloadTorBinaryX86Pie(type: Download) {
|
|
||||||
src 'https://briarproject.org/build/tor-0.2.9.12-x86-pie.zip'
|
|
||||||
dest "$torBinaryDir/tor_x86_pie.zip"
|
|
||||||
onlyIfNewer true
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
|
|
||||||
src "$torBinaryDir/geoip.zip"
|
|
||||||
algorithm 'SHA-256'
|
|
||||||
checksum 'fe49d3adb86d3c512373101422a017dbb86c85a570524663f09dd8ce143a24f3'
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
|
|
||||||
src "$torBinaryDir/tor_arm.zip"
|
|
||||||
algorithm 'SHA-256'
|
|
||||||
checksum '8ed0b347ffed1d6a4d2fd14495118eb92be83e9cc06e057e15220dc288b31688'
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
|
|
||||||
src "$torBinaryDir/tor_arm_pie.zip"
|
|
||||||
algorithm 'SHA-256'
|
|
||||||
checksum '64403262511c29f462ca5e7c7621bfc3c944898364d1d5ad35a016bb8a034283'
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
|
|
||||||
src "$torBinaryDir/tor_x86.zip"
|
|
||||||
algorithm 'SHA-256'
|
|
||||||
checksum '61e014607a2079bcf1646289c67bff6372b1aded6e1d8d83d7791efda9a4d5ab'
|
|
||||||
}
|
|
||||||
|
|
||||||
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
|
|
||||||
src "$torBinaryDir/tor_x86_pie.zip"
|
|
||||||
algorithm 'SHA-256'
|
|
||||||
checksum '18fbc98356697dd0895836ab46d5c9877d1c539193464f7db1e82a65adaaf288'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
preBuild.dependsOn {
|
torBinaries.every { key, value ->
|
||||||
[
|
preBuild.dependsOn.add(verifyBinary(key, value))
|
||||||
'verifyTorGeoIp',
|
|
||||||
'verifyTorBinaryArm',
|
|
||||||
'verifyTorBinaryArmPie',
|
|
||||||
'verifyTorBinaryX86',
|
|
||||||
'verifyTorBinaryX86Pie'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,6 @@
|
|||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.READ_LOGS"/>
|
<uses-permission android:name="android.permission.READ_LOGS"/>
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
<!-- Since API 23, this is needed to add contacts via Bluetooth -->
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
|||||||
import org.briarproject.bramble.api.reporting.DevReporter;
|
import org.briarproject.bramble.api.reporting.DevReporter;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.Scheduler;
|
||||||
import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory;
|
import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory;
|
||||||
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
||||||
import org.briarproject.bramble.plugin.tor.TorPluginFactory;
|
import org.briarproject.bramble.plugin.tor.TorPluginFactory;
|
||||||
@@ -22,6 +23,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
@@ -33,19 +35,20 @@ public class AndroidPluginModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||||
|
@Scheduler ScheduledExecutorService scheduler,
|
||||||
AndroidExecutor androidExecutor, SecureRandom random,
|
AndroidExecutor androidExecutor, SecureRandom random,
|
||||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
||||||
Application app, LocationUtils locationUtils, DevReporter reporter,
|
Application app, LocationUtils locationUtils, DevReporter reporter,
|
||||||
EventBus eventBus) {
|
EventBus eventBus) {
|
||||||
Context appContext = app.getApplicationContext();
|
Context appContext = app.getApplicationContext();
|
||||||
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
|
DuplexPluginFactory bluetooth = new DroidtoothPluginFactory(ioExecutor,
|
||||||
androidExecutor, appContext, random, backoffFactory);
|
androidExecutor, appContext, random, eventBus, backoffFactory);
|
||||||
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, appContext,
|
DuplexPluginFactory tor = new TorPluginFactory(ioExecutor, scheduler,
|
||||||
locationUtils, reporter, eventBus, torSocketFactory,
|
appContext, locationUtils, reporter, eventBus,
|
||||||
backoffFactory);
|
torSocketFactory, backoffFactory);
|
||||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||||
backoffFactory, appContext);
|
backoffFactory, appContext);
|
||||||
final Collection<DuplexPluginFactory> duplex =
|
Collection<DuplexPluginFactory> duplex =
|
||||||
Arrays.asList(bluetooth, tor, lan);
|
Arrays.asList(bluetooth, tor, lan);
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
PluginConfig pluginConfig = new PluginConfig() {
|
PluginConfig pluginConfig = new PluginConfig() {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import android.content.IntentFilter;
|
|||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
@@ -22,6 +24,8 @@ import org.briarproject.bramble.api.plugin.TransportId;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
|
import org.briarproject.bramble.api.plugin.event.DisableBluetoothEvent;
|
||||||
|
import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
|
||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
@@ -63,7 +67,7 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
|||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
class DroidtoothPlugin implements DuplexPlugin {
|
class DroidtoothPlugin implements DuplexPlugin, EventListener {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(DroidtoothPlugin.class.getName());
|
Logger.getLogger(DroidtoothPlugin.class.getName());
|
||||||
@@ -120,12 +124,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
// with a message queue, so submit it to the AndroidExecutor
|
// with a message queue, so submit it to the AndroidExecutor
|
||||||
try {
|
try {
|
||||||
adapter = androidExecutor.runOnBackgroundThread(
|
adapter = androidExecutor.runOnBackgroundThread(
|
||||||
new Callable<BluetoothAdapter>() {
|
BluetoothAdapter::getDefaultAdapter).get();
|
||||||
@Override
|
|
||||||
public BluetoothAdapter call() throws Exception {
|
|
||||||
return BluetoothAdapter.getDefaultAdapter();
|
|
||||||
}
|
|
||||||
}).get();
|
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
LOG.warning("Interrupted while getting BluetoothAdapter");
|
LOG.warning("Interrupted while getting BluetoothAdapter");
|
||||||
@@ -150,9 +149,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
} else {
|
} else {
|
||||||
// Enable Bluetooth if settings allow
|
// Enable Bluetooth if settings allow
|
||||||
if (callback.getSettings().getBoolean(PREF_BT_ENABLE, false)) {
|
if (callback.getSettings().getBoolean(PREF_BT_ENABLE, false)) {
|
||||||
wasEnabledByUs = true;
|
enableAdapter();
|
||||||
if (adapter.enable()) LOG.info("Enabling Bluetooth");
|
|
||||||
else LOG.info("Could not enable Bluetooth");
|
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Not enabling Bluetooth");
|
LOG.info("Not enabling Bluetooth");
|
||||||
}
|
}
|
||||||
@@ -160,40 +157,36 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
if (!isRunning()) return;
|
||||||
public void run() {
|
String address = AndroidUtils.getBluetoothAddress(appContext,
|
||||||
if (!isRunning()) return;
|
adapter);
|
||||||
String address = AndroidUtils.getBluetoothAddress(appContext,
|
if (LOG.isLoggable(INFO))
|
||||||
adapter);
|
LOG.info("Local address " + scrubMacAddress(address));
|
||||||
if (LOG.isLoggable(INFO))
|
if (!StringUtils.isNullOrEmpty(address)) {
|
||||||
LOG.info("Local address " + scrubMacAddress(address));
|
// Advertise the Bluetooth address to contacts
|
||||||
if (!StringUtils.isNullOrEmpty(address)) {
|
TransportProperties p = new TransportProperties();
|
||||||
// Advertise the Bluetooth address to contacts
|
p.put(PROP_ADDRESS, address);
|
||||||
TransportProperties p = new TransportProperties();
|
callback.mergeLocalProperties(p);
|
||||||
p.put(PROP_ADDRESS, address);
|
|
||||||
callback.mergeLocalProperties(p);
|
|
||||||
}
|
|
||||||
// Bind a server socket to accept connections from contacts
|
|
||||||
BluetoothServerSocket ss;
|
|
||||||
try {
|
|
||||||
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
|
|
||||||
"RFCOMM", getUuid());
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!isRunning()) {
|
|
||||||
tryToClose(ss);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG.info("Socket bound");
|
|
||||||
socket = ss;
|
|
||||||
backoff.reset();
|
|
||||||
callback.transportEnabled();
|
|
||||||
acceptContactConnections();
|
|
||||||
}
|
}
|
||||||
|
// Bind a server socket to accept connections from contacts
|
||||||
|
BluetoothServerSocket ss;
|
||||||
|
try {
|
||||||
|
ss = adapter.listenUsingInsecureRfcommWithServiceRecord(
|
||||||
|
"RFCOMM", getUuid());
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isRunning()) {
|
||||||
|
tryToClose(ss);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG.info("Socket bound");
|
||||||
|
socket = ss;
|
||||||
|
backoff.reset();
|
||||||
|
callback.transportEnabled();
|
||||||
|
acceptContactConnections();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,13 +236,27 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
return new DroidtoothTransportConnection(this, s);
|
return new DroidtoothTransportConnection(this, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void enableAdapter() {
|
||||||
|
if (adapter != null && !adapter.isEnabled()) {
|
||||||
|
if (adapter.enable()) {
|
||||||
|
LOG.info("Enabling Bluetooth");
|
||||||
|
wasEnabledByUs = true;
|
||||||
|
} else {
|
||||||
|
LOG.info("Could not enable Bluetooth");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
if (receiver != null) appContext.unregisterReceiver(receiver);
|
if (receiver != null) appContext.unregisterReceiver(receiver);
|
||||||
tryToClose(socket);
|
tryToClose(socket);
|
||||||
// Disable Bluetooth if we enabled it and it's still enabled
|
disableAdapter();
|
||||||
if (wasEnabledByUs && adapter.isEnabled()) {
|
}
|
||||||
|
|
||||||
|
private void disableAdapter() {
|
||||||
|
if (adapter != null && adapter.isEnabled() && wasEnabledByUs) {
|
||||||
if (adapter.disable()) LOG.info("Disabling Bluetooth");
|
if (adapter.disable()) LOG.info("Disabling Bluetooth");
|
||||||
else LOG.info("Could not disable Bluetooth");
|
else LOG.info("Could not disable Bluetooth");
|
||||||
}
|
}
|
||||||
@@ -278,21 +285,18 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
Map<ContactId, TransportProperties> remote =
|
Map<ContactId, TransportProperties> remote =
|
||||||
callback.getRemoteProperties();
|
callback.getRemoteProperties();
|
||||||
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
|
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
|
||||||
final ContactId c = e.getKey();
|
ContactId c = e.getKey();
|
||||||
if (connected.contains(c)) continue;
|
if (connected.contains(c)) continue;
|
||||||
final String address = e.getValue().get(PROP_ADDRESS);
|
String address = e.getValue().get(PROP_ADDRESS);
|
||||||
if (StringUtils.isNullOrEmpty(address)) continue;
|
if (StringUtils.isNullOrEmpty(address)) continue;
|
||||||
final String uuid = e.getValue().get(PROP_UUID);
|
String uuid = e.getValue().get(PROP_UUID);
|
||||||
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
if (StringUtils.isNullOrEmpty(uuid)) continue;
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
if (!running) return;
|
||||||
public void run() {
|
BluetoothSocket s = connect(address, uuid);
|
||||||
if (!running) return;
|
if (s != null) {
|
||||||
BluetoothSocket s = connect(address, uuid);
|
backoff.reset();
|
||||||
if (s != null) {
|
callback.outgoingConnectionCreated(c, wrapSocket(s));
|
||||||
backoff.reset();
|
|
||||||
callback.outgoingConnectionCreated(c, wrapSocket(s));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -347,8 +351,7 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p = callback.getRemoteProperties(c);
|
||||||
if (p == null) return null;
|
|
||||||
String address = p.get(PROP_ADDRESS);
|
String address = p.get(PROP_ADDRESS);
|
||||||
if (StringUtils.isNullOrEmpty(address)) return null;
|
if (StringUtils.isNullOrEmpty(address)) return null;
|
||||||
String uuid = p.get(PROP_UUID);
|
String uuid = p.get(PROP_UUID);
|
||||||
@@ -413,6 +416,23 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
return StringUtils.macToString(mac);
|
return StringUtils.macToString(mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if (e instanceof EnableBluetoothEvent) {
|
||||||
|
enableAdapterAsync();
|
||||||
|
} else if (e instanceof DisableBluetoothEvent) {
|
||||||
|
disableAdapterAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableAdapterAsync() {
|
||||||
|
ioExecutor.execute(this::enableAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void disableAdapterAsync() {
|
||||||
|
ioExecutor.execute(this::disableAdapter);
|
||||||
|
}
|
||||||
|
|
||||||
private class BluetoothStateReceiver extends BroadcastReceiver {
|
private class BluetoothStateReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -448,16 +468,13 @@ class DroidtoothPlugin implements DuplexPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Callable<KeyAgreementConnection> listen() {
|
public Callable<KeyAgreementConnection> listen() {
|
||||||
return new Callable<KeyAgreementConnection>() {
|
return () -> {
|
||||||
@Override
|
BluetoothSocket s = ss.accept();
|
||||||
public KeyAgreementConnection call() throws IOException {
|
if (LOG.isLoggable(INFO))
|
||||||
BluetoothSocket s = ss.accept();
|
LOG.info(ID.getString() + ": Incoming connection");
|
||||||
if (LOG.isLoggable(INFO))
|
return new KeyAgreementConnection(
|
||||||
LOG.info(ID.getString() + ": Incoming connection");
|
new DroidtoothTransportConnection(
|
||||||
return new KeyAgreementConnection(
|
DroidtoothPlugin.this, s), ID);
|
||||||
new DroidtoothTransportConnection(
|
|
||||||
DroidtoothPlugin.this, s), ID);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin.droidtooth;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.Backoff;
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||||
@@ -31,15 +32,18 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
|
|||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
private final SecureRandom secureRandom;
|
private final SecureRandom secureRandom;
|
||||||
|
private final EventBus eventBus;
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
|
|
||||||
public DroidtoothPluginFactory(Executor ioExecutor,
|
public DroidtoothPluginFactory(Executor ioExecutor,
|
||||||
AndroidExecutor androidExecutor, Context appContext,
|
AndroidExecutor androidExecutor, Context appContext,
|
||||||
SecureRandom secureRandom, BackoffFactory backoffFactory) {
|
SecureRandom secureRandom, EventBus eventBus,
|
||||||
|
BackoffFactory backoffFactory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.secureRandom = secureRandom;
|
this.secureRandom = secureRandom;
|
||||||
|
this.eventBus = eventBus;
|
||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +61,10 @@ public class DroidtoothPluginFactory implements DuplexPluginFactory {
|
|||||||
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
public DuplexPlugin createPlugin(DuplexPluginCallback callback) {
|
||||||
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
return new DroidtoothPlugin(ioExecutor, androidExecutor, appContext,
|
DroidtoothPlugin plugin = new DroidtoothPlugin(ioExecutor,
|
||||||
secureRandom, backoff, callback, MAX_LATENCY);
|
androidExecutor, appContext, secureRandom, backoff, callback,
|
||||||
|
MAX_LATENCY);
|
||||||
|
eventBus.addListener(plugin);
|
||||||
|
return plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,10 +55,16 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
@@ -69,10 +75,15 @@ import javax.net.SocketFactory;
|
|||||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
import static android.content.Context.POWER_SERVICE;
|
import static android.content.Context.POWER_SERVICE;
|
||||||
|
import static android.content.Intent.ACTION_SCREEN_OFF;
|
||||||
|
import static android.content.Intent.ACTION_SCREEN_ON;
|
||||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
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 android.os.PowerManager.PARTIAL_WAKE_LOCK;
|
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
|
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
|
||||||
@@ -84,13 +95,13 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
|
|||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WIFI;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||||
|
|
||||||
private static final String PROP_ONION = "onion";
|
|
||||||
private static final String[] EVENTS = {
|
private static final String[] EVENTS = {
|
||||||
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
||||||
};
|
};
|
||||||
@@ -101,6 +112,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
Logger.getLogger(TorPlugin.class.getName());
|
Logger.getLogger(TorPlugin.class.getName());
|
||||||
|
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
|
private final ScheduledExecutorService scheduler;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
private final DevReporter reporter;
|
private final DevReporter reporter;
|
||||||
@@ -113,6 +125,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private final File torDirectory, torFile, geoIpFile, configFile;
|
private final File torDirectory, torFile, geoIpFile, configFile;
|
||||||
private final File doneFile, cookieFile;
|
private final File doneFile, cookieFile;
|
||||||
private final PowerManager.WakeLock wakeLock;
|
private final PowerManager.WakeLock wakeLock;
|
||||||
|
private final Lock connectionStatusLock;
|
||||||
|
private final AtomicReference<Future<?>> connectivityCheck =
|
||||||
|
new AtomicReference<>();
|
||||||
private final AtomicBoolean used = new AtomicBoolean(false);
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
@@ -121,12 +136,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private volatile TorControlConnection controlConnection = null;
|
private volatile TorControlConnection controlConnection = null;
|
||||||
private volatile BroadcastReceiver networkStateReceiver = null;
|
private volatile BroadcastReceiver networkStateReceiver = null;
|
||||||
|
|
||||||
TorPlugin(Executor ioExecutor, Context appContext,
|
TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
|
||||||
LocationUtils locationUtils, DevReporter reporter,
|
Context appContext, LocationUtils locationUtils,
|
||||||
SocketFactory torSocketFactory, Backoff backoff,
|
DevReporter reporter, SocketFactory torSocketFactory,
|
||||||
DuplexPluginCallback callback, String architecture, int maxLatency,
|
Backoff backoff, DuplexPluginCallback callback,
|
||||||
int maxIdleTime) {
|
String architecture, int maxLatency, int maxIdleTime) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.scheduler = scheduler;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.locationUtils = locationUtils;
|
this.locationUtils = locationUtils;
|
||||||
this.reporter = reporter;
|
this.reporter = reporter;
|
||||||
@@ -148,8 +164,10 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
||||||
Object o = appContext.getSystemService(POWER_SERVICE);
|
Object o = appContext.getSystemService(POWER_SERVICE);
|
||||||
PowerManager pm = (PowerManager) o;
|
PowerManager pm = (PowerManager) o;
|
||||||
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "TorPlugin");
|
// This tag will prevent Huawei's powermanager from killing us.
|
||||||
|
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
|
||||||
wakeLock.setReferenceCounted(false);
|
wakeLock.setReferenceCounted(false);
|
||||||
|
connectionStatusLock = new ReentrantLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -202,11 +220,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
Scanner stdout = new Scanner(torProcess.getInputStream());
|
Scanner stdout = new Scanner(torProcess.getInputStream());
|
||||||
Scanner stderr = new Scanner(torProcess.getErrorStream());
|
Scanner stderr = new Scanner(torProcess.getErrorStream());
|
||||||
while (stdout.hasNextLine() || stderr.hasNextLine()){
|
while (stdout.hasNextLine() || stderr.hasNextLine()) {
|
||||||
if(stdout.hasNextLine()) {
|
if (stdout.hasNextLine()) {
|
||||||
LOG.info(stdout.nextLine());
|
LOG.info(stdout.nextLine());
|
||||||
}
|
}
|
||||||
if(stderr.hasNextLine()){
|
if (stderr.hasNextLine()) {
|
||||||
LOG.info(stderr.nextLine());
|
LOG.info(stderr.nextLine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,7 +273,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
// Register to receive network status events
|
// Register to receive network status events
|
||||||
networkStateReceiver = new NetworkStateReceiver();
|
networkStateReceiver = new NetworkStateReceiver();
|
||||||
IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION);
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(CONNECTIVITY_ACTION);
|
||||||
|
filter.addAction(ACTION_SCREEN_ON);
|
||||||
|
filter.addAction(ACTION_SCREEN_OFF);
|
||||||
|
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
|
||||||
appContext.registerReceiver(networkStateReceiver, filter);
|
appContext.registerReceiver(networkStateReceiver, filter);
|
||||||
// Bind a server socket to receive incoming hidden service connections
|
// Bind a server socket to receive incoming hidden service connections
|
||||||
bind();
|
bind();
|
||||||
@@ -368,57 +390,45 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void sendDevReports() {
|
private void sendDevReports() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
// TODO: Trigger this with a TransportEnabledEvent
|
||||||
public void run() {
|
File reportDir = AndroidUtils.getReportDir(appContext);
|
||||||
// TODO: Trigger this with a TransportEnabledEvent
|
reporter.sendReports(reportDir);
|
||||||
File reportDir = AndroidUtils.getReportDir(appContext);
|
|
||||||
reporter.sendReports(reportDir);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bind() {
|
private void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
// If there's already a port number stored in config, reuse it
|
||||||
public void run() {
|
String portString = callback.getSettings().get(PREF_TOR_PORT);
|
||||||
// If there's already a port number stored in config, reuse it
|
int port;
|
||||||
String portString = callback.getSettings().get(PREF_TOR_PORT);
|
if (StringUtils.isNullOrEmpty(portString)) port = 0;
|
||||||
int port;
|
else port = Integer.parseInt(portString);
|
||||||
if (StringUtils.isNullOrEmpty(portString)) port = 0;
|
// Bind a server socket to receive connections from Tor
|
||||||
else port = Integer.parseInt(portString);
|
ServerSocket ss = null;
|
||||||
// Bind a server socket to receive connections from Tor
|
try {
|
||||||
ServerSocket ss = null;
|
ss = new ServerSocket();
|
||||||
try {
|
ss.bind(new InetSocketAddress("127.0.0.1", port));
|
||||||
ss = new ServerSocket();
|
} catch (IOException e) {
|
||||||
ss.bind(new InetSocketAddress("127.0.0.1", port));
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
} catch (IOException e) {
|
tryToClose(ss);
|
||||||
if (LOG.isLoggable(WARNING))
|
return;
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
tryToClose(ss);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!running) {
|
|
||||||
tryToClose(ss);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
socket = ss;
|
|
||||||
// Store the port number
|
|
||||||
final String localPort = String.valueOf(ss.getLocalPort());
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.put(PREF_TOR_PORT, localPort);
|
|
||||||
callback.mergeSettings(s);
|
|
||||||
// Create a hidden service if necessary
|
|
||||||
ioExecutor.execute(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
publishHiddenService(localPort);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
backoff.reset();
|
|
||||||
// Accept incoming hidden service connections from Tor
|
|
||||||
acceptContactConnections(ss);
|
|
||||||
}
|
}
|
||||||
|
if (!running) {
|
||||||
|
tryToClose(ss);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket = ss;
|
||||||
|
// Store the port number
|
||||||
|
String localPort = String.valueOf(ss.getLocalPort());
|
||||||
|
Settings s = new Settings();
|
||||||
|
s.put(PREF_TOR_PORT, localPort);
|
||||||
|
callback.mergeSettings(s);
|
||||||
|
// Create a hidden service if necessary
|
||||||
|
ioExecutor.execute(() -> publishHiddenService(localPort));
|
||||||
|
backoff.reset();
|
||||||
|
// Accept incoming hidden service connections from Tor
|
||||||
|
acceptContactConnections(ss);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -538,20 +548,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if (!isRunning()) return;
|
if (!isRunning()) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
// TODO: Pass properties to connectAndCallBack()
|
Map<ContactId, TransportProperties> remote =
|
||||||
for (ContactId c : callback.getRemoteProperties().keySet())
|
callback.getRemoteProperties();
|
||||||
if (!connected.contains(c)) connectAndCallBack(c);
|
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
|
||||||
|
ContactId c = e.getKey();
|
||||||
|
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectAndCallBack(final ContactId c) {
|
private void connectAndCallBack(ContactId c, TransportProperties p) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
if (!isRunning()) return;
|
||||||
public void run() {
|
DuplexTransportConnection d = createConnection(p);
|
||||||
DuplexTransportConnection d = createConnection(c);
|
if (d != null) {
|
||||||
if (d != null) {
|
backoff.reset();
|
||||||
backoff.reset();
|
callback.outgoingConnectionCreated(c, d);
|
||||||
callback.outgoingConnectionCreated(c, d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -559,8 +570,11 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
return createConnection(callback.getRemoteProperties(c));
|
||||||
if (p == null) return null;
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private DuplexTransportConnection createConnection(TransportProperties p) {
|
||||||
String onion = p.get(PROP_ONION);
|
String onion = p.get(PROP_ONION);
|
||||||
if (StringUtils.isNullOrEmpty(onion)) return null;
|
if (StringUtils.isNullOrEmpty(onion)) return null;
|
||||||
if (!ONION.matcher(onion).matches()) {
|
if (!ONION.matcher(onion).matches()) {
|
||||||
@@ -624,6 +638,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
@Override
|
@Override
|
||||||
public void orConnStatus(String status, String orName) {
|
public void orConnStatus(String status, String orName) {
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
|
if (LOG.isLoggable(INFO)) LOG.info("OR connection " + status);
|
||||||
|
if (status.equals("CLOSED") || status.equals("FAILED"))
|
||||||
|
updateConnectionStatus(); // Check whether we've lost connectivity
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -663,7 +679,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(int event, String path) {
|
public void onEvent(int event, @Nullable String path) {
|
||||||
stopWatching();
|
stopWatching();
|
||||||
latch.countDown();
|
latch.countDown();
|
||||||
}
|
}
|
||||||
@@ -681,60 +697,75 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateConnectionStatus() {
|
private void updateConnectionStatus() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
if (!running) return;
|
||||||
public void run() {
|
try {
|
||||||
if (!running) return;
|
connectionStatusLock.lock();
|
||||||
|
updateConnectionStatusLocked();
|
||||||
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
} finally {
|
||||||
ConnectivityManager cm = (ConnectivityManager) o;
|
connectionStatusLock.unlock();
|
||||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
|
||||||
boolean online = net != null && net.isConnected();
|
|
||||||
boolean wifi = online && net.getType() == TYPE_WIFI;
|
|
||||||
String country = locationUtils.getCurrentCountry();
|
|
||||||
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
|
||||||
country);
|
|
||||||
Settings s = callback.getSettings();
|
|
||||||
int network = s.getInt(PREF_TOR_NETWORK,
|
|
||||||
PREF_TOR_NETWORK_ALWAYS);
|
|
||||||
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
|
||||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
|
||||||
if ("".equals(country)) LOG.info("Country code unknown");
|
|
||||||
else LOG.info("Country code: " + country);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!online) {
|
|
||||||
LOG.info("Disabling network, device is offline");
|
|
||||||
enableNetwork(false);
|
|
||||||
} else if (blocked) {
|
|
||||||
LOG.info("Disabling network, country is blocked");
|
|
||||||
enableNetwork(false);
|
|
||||||
} else if (network == PREF_TOR_NETWORK_NEVER
|
|
||||||
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
|
|
||||||
LOG.info("Disabling network due to data setting");
|
|
||||||
enableNetwork(false);
|
|
||||||
} else {
|
|
||||||
LOG.info("Enabling network");
|
|
||||||
enableNetwork(true);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locking: connectionStatusLock
|
||||||
|
private void updateConnectionStatusLocked() {
|
||||||
|
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||||
|
ConnectivityManager cm = (ConnectivityManager) o;
|
||||||
|
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||||
|
boolean online = net != null && net.isConnected();
|
||||||
|
boolean wifi = online && net.getType() == TYPE_WIFI;
|
||||||
|
String country = locationUtils.getCurrentCountry();
|
||||||
|
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
||||||
|
country);
|
||||||
|
Settings s = callback.getSettings();
|
||||||
|
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
|
||||||
|
|
||||||
|
if (LOG.isLoggable(INFO)) {
|
||||||
|
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||||
|
if ("".equals(country)) LOG.info("Country code unknown");
|
||||||
|
else LOG.info("Country code: " + country);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!online) {
|
||||||
|
LOG.info("Disabling network, device is offline");
|
||||||
|
enableNetwork(false);
|
||||||
|
} else if (blocked) {
|
||||||
|
LOG.info("Disabling network, country is blocked");
|
||||||
|
enableNetwork(false);
|
||||||
|
} else if (network == PREF_TOR_NETWORK_NEVER
|
||||||
|
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
|
||||||
|
LOG.info("Disabling network due to data setting");
|
||||||
|
enableNetwork(false);
|
||||||
|
} else {
|
||||||
|
LOG.info("Enabling network");
|
||||||
|
enableNetwork(true);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleConnectionStatusUpdate() {
|
||||||
|
Future<?> newConnectivityCheck =
|
||||||
|
scheduler.schedule(this::updateConnectionStatus, 1, MINUTES);
|
||||||
|
Future<?> oldConnectivityCheck =
|
||||||
|
connectivityCheck.getAndSet(newConnectivityCheck);
|
||||||
|
if (oldConnectivityCheck != null) oldConnectivityCheck.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
private class NetworkStateReceiver extends BroadcastReceiver {
|
private class NetworkStateReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context ctx, Intent i) {
|
public void onReceive(Context ctx, Intent i) {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
if (CONNECTIVITY_ACTION.equals(i.getAction())) {
|
String action = i.getAction();
|
||||||
LOG.info("Detected connectivity change");
|
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
|
||||||
updateConnectionStatus();
|
updateConnectionStatus();
|
||||||
|
if (ACTION_SCREEN_ON.equals(action)
|
||||||
|
|| ACTION_SCREEN_OFF.equals(action)) {
|
||||||
|
scheduleConnectionStatusUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.briarproject.bramble.api.system.LocationUtils;
|
|||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
@@ -36,6 +37,7 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
|||||||
private static final double BACKOFF_BASE = 1.2;
|
private static final double BACKOFF_BASE = 1.2;
|
||||||
|
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
|
private final ScheduledExecutorService scheduler;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
private final DevReporter reporter;
|
private final DevReporter reporter;
|
||||||
@@ -43,11 +45,13 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
|||||||
private final SocketFactory torSocketFactory;
|
private final SocketFactory torSocketFactory;
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
|
|
||||||
public TorPluginFactory(Executor ioExecutor, Context appContext,
|
public TorPluginFactory(Executor ioExecutor,
|
||||||
|
ScheduledExecutorService scheduler, Context appContext,
|
||||||
LocationUtils locationUtils, DevReporter reporter,
|
LocationUtils locationUtils, DevReporter reporter,
|
||||||
EventBus eventBus, SocketFactory torSocketFactory,
|
EventBus eventBus, SocketFactory torSocketFactory,
|
||||||
BackoffFactory backoffFactory) {
|
BackoffFactory backoffFactory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.scheduler = scheduler;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
this.locationUtils = locationUtils;
|
this.locationUtils = locationUtils;
|
||||||
this.reporter = reporter;
|
this.reporter = reporter;
|
||||||
@@ -89,9 +93,9 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
|||||||
|
|
||||||
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
|
||||||
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
MAX_POLLING_INTERVAL, BACKOFF_BASE);
|
||||||
TorPlugin plugin = new TorPlugin(ioExecutor, appContext, locationUtils,
|
TorPlugin plugin = new TorPlugin(ioExecutor, scheduler, appContext,
|
||||||
reporter, torSocketFactory, backoff, callback, architecture,
|
locationUtils, reporter, torSocketFactory, backoff, callback,
|
||||||
MAX_LATENCY, MAX_IDLE_TIME);
|
architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,14 +27,11 @@ class AndroidExecutorImpl implements AndroidExecutor {
|
|||||||
@Inject
|
@Inject
|
||||||
AndroidExecutorImpl(Application app) {
|
AndroidExecutorImpl(Application app) {
|
||||||
uiHandler = new Handler(app.getApplicationContext().getMainLooper());
|
uiHandler = new Handler(app.getApplicationContext().getMainLooper());
|
||||||
loop = new Runnable() {
|
loop = () -> {
|
||||||
@Override
|
Looper.prepare();
|
||||||
public void run() {
|
backgroundHandler = new Handler();
|
||||||
Looper.prepare();
|
startLatch.countDown();
|
||||||
backgroundHandler = new Handler();
|
Looper.loop();
|
||||||
startLatch.countDown();
|
|
||||||
Looper.loop();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +1,39 @@
|
|||||||
apply plugin: 'java'
|
apply plugin: 'java-library'
|
||||||
sourceCompatibility = 1.6
|
sourceCompatibility = 1.8
|
||||||
targetCompatibility = 1.6
|
targetCompatibility = 1.8
|
||||||
|
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile "com.google.dagger:dagger:2.0.2"
|
implementation "com.google.dagger:dagger:2.0.2"
|
||||||
compile 'com.google.dagger:dagger-compiler:2.0.2'
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
compile 'com.google.code.findbugs:jsr305:3.0.2'
|
|
||||||
|
|
||||||
testCompile 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testCompile "org.jmock:jmock:2.8.2"
|
testImplementation "org.jmock:jmock:2.8.2"
|
||||||
testCompile "org.jmock:jmock-junit4:2.8.2"
|
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||||
testCompile "org.jmock:jmock-legacy:2.8.2"
|
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||||
testCompile "org.hamcrest:hamcrest-library:1.3"
|
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||||
testCompile "org.hamcrest:hamcrest-core:1.3"
|
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||||
'com.google.code.findbugs:jsr305:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
|
||||||
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
|
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
|
||||||
|
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
|
||||||
|
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
|
||||||
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,3 +48,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
|
|||||||
artifacts {
|
artifacts {
|
||||||
testOutput jarTest
|
testOutput jarTest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a Java 6 JRE is available, check we're not using any Java 7 or 8 APIs
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
useJava6StandardLibrary(it)
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class BdfMessageContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BdfMessageContext(BdfDictionary dictionary) {
|
public BdfMessageContext(BdfDictionary dictionary) {
|
||||||
this(dictionary, Collections.<MessageId>emptyList());
|
this(dictionary, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public BdfDictionary getDictionary() {
|
public BdfDictionary getDictionary() {
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import org.briarproject.bramble.api.Bytes;
|
|||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentSkipListMap;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
public class BdfDictionary extends ConcurrentSkipListMap<String, Object> {
|
@NotThreadSafe
|
||||||
|
public class BdfDictionary extends TreeMap<String, Object> {
|
||||||
|
|
||||||
public static final Object NULL_VALUE = new Object();
|
public static final Object NULL_VALUE = new Object();
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,17 @@ package org.briarproject.bramble.api.data;
|
|||||||
import org.briarproject.bramble.api.Bytes;
|
import org.briarproject.bramble.api.Bytes;
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
|
||||||
|
|
||||||
public class BdfList extends Vector<Object> {
|
@NotThreadSafe
|
||||||
|
public class BdfList extends ArrayList<Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory method for constructing lists inline.
|
* Factory method for constructing lists inline.
|
||||||
|
|||||||
@@ -122,8 +122,9 @@ public interface DatabaseComponent {
|
|||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the message with the given ID. The message ID and any other
|
* Deletes the message with the given ID. Unlike
|
||||||
* associated data are not deleted.
|
* {@link #removeMessage(Transaction, MessageId)}, the message ID and any
|
||||||
|
* other associated data are not deleted.
|
||||||
*/
|
*/
|
||||||
void deleteMessage(Transaction txn, MessageId m) throws DbException;
|
void deleteMessage(Transaction txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
@@ -452,6 +453,11 @@ public interface DatabaseComponent {
|
|||||||
*/
|
*/
|
||||||
void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException;
|
void removeLocalAuthor(Transaction txn, AuthorId a) throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a message (and all associated state) from the database.
|
||||||
|
*/
|
||||||
|
void removeMessage(Transaction txn, MessageId m) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a transport (and all associated state) from the database.
|
* Removes a transport (and all associated state) from the database.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
package org.briarproject.bramble.api.db;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
@ThreadSafe
|
@NotThreadSafe
|
||||||
public class Metadata extends Hashtable<String, byte[]> {
|
public class Metadata extends TreeMap<String, byte[]> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special value to indicate that a key is being removed.
|
* Special value to indicate that a key is being removed.
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class Transaction {
|
|||||||
* committed.
|
* committed.
|
||||||
*/
|
*/
|
||||||
public void attach(Event e) {
|
public void attach(Event e) {
|
||||||
if (events == null) events = new ArrayList<Event>();
|
if (events == null) events = new ArrayList<>();
|
||||||
events.add(e);
|
events.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,10 @@ public interface LanTcpConstants {
|
|||||||
|
|
||||||
TransportId ID = new TransportId("org.briarproject.bramble.lan");
|
TransportId ID = new TransportId("org.briarproject.bramble.lan");
|
||||||
|
|
||||||
|
// a transport property (shared with contacts)
|
||||||
|
String PROP_IP_PORTS = "ipPorts";
|
||||||
|
|
||||||
|
// a local setting
|
||||||
String PREF_LAN_IP_PORTS = "ipPorts";
|
String PREF_LAN_IP_PORTS = "ipPorts";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ public interface PluginCallback {
|
|||||||
*/
|
*/
|
||||||
Map<ContactId, TransportProperties> getRemoteProperties();
|
Map<ContactId, TransportProperties> getRemoteProperties();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the plugin's remote transport properties for the given contact.
|
||||||
|
*/
|
||||||
|
TransportProperties getRemoteProperties(ContactId c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the given settings with the namespaced settings
|
* Merges the given settings with the namespaced settings
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ public interface TorConstants {
|
|||||||
|
|
||||||
TransportId ID = new TransportId("org.briarproject.bramble.tor");
|
TransportId ID = new TransportId("org.briarproject.bramble.tor");
|
||||||
|
|
||||||
|
String PROP_ONION = "onion";
|
||||||
|
|
||||||
int SOCKS_PORT = 59050;
|
int SOCKS_PORT = 59050;
|
||||||
int CONTROL_PORT = 59051;
|
int CONTROL_PORT = 59051;
|
||||||
|
|
||||||
@@ -16,4 +18,5 @@ public interface TorConstants {
|
|||||||
int PREF_TOR_NETWORK_NEVER = 0;
|
int PREF_TOR_NETWORK_NEVER = 0;
|
||||||
int PREF_TOR_NETWORK_WIFI = 1;
|
int PREF_TOR_NETWORK_WIFI = 1;
|
||||||
int PREF_TOR_NETWORK_ALWAYS = 2;
|
int PREF_TOR_NETWORK_ALWAYS = 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package org.briarproject.bramble.api.plugin.event;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event that asks the Bluetooth plugin to disable the Bluetooth adapter if
|
||||||
|
* we previously enabled it.
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
public class DisableBluetoothEvent extends Event {
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package org.briarproject.bramble.api.plugin.event;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event asks the Bluetooth plugin to enable the Bluetooth adapter.
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
public class EnableBluetoothEvent extends Event {
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ public interface TransportPropertyManager {
|
|||||||
/**
|
/**
|
||||||
* Returns the local transport properties for all transports.
|
* Returns the local transport properties for all transports.
|
||||||
* <br/>
|
* <br/>
|
||||||
* Read-Only
|
* TODO: Transaction can be read-only when code is simplified
|
||||||
*/
|
*/
|
||||||
Map<TransportId, TransportProperties> getLocalProperties(Transaction txn)
|
Map<TransportId, TransportProperties> getLocalProperties(Transaction txn)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
@@ -49,6 +49,13 @@ public interface TransportPropertyManager {
|
|||||||
Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
|
Map<ContactId, TransportProperties> getRemoteProperties(TransportId t)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the remote transport properties for the given contact and
|
||||||
|
* transport.
|
||||||
|
*/
|
||||||
|
TransportProperties getRemoteProperties(ContactId c, TransportId t)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges the given properties with the existing local properties for the
|
* Merges the given properties with the existing local properties for the
|
||||||
* given transport.
|
* given transport.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public class MessageContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MessageContext(Metadata metadata) {
|
public MessageContext(Metadata metadata) {
|
||||||
this(metadata, Collections.<MessageId>emptyList());
|
this(metadata, Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Metadata getMetadata() {
|
public Metadata getMetadata() {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import java.nio.charset.CharacterCodingException;
|
|||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetDecoder;
|
import java.nio.charset.CharsetDecoder;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Random;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -27,6 +28,7 @@ public class StringUtils {
|
|||||||
'0', '1', '2', '3', '4', '5', '6', '7',
|
'0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
|
||||||
};
|
};
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
public static boolean isNullOrEmpty(@Nullable String s) {
|
public static boolean isNullOrEmpty(@Nullable String s) {
|
||||||
return s == null || s.length() == 0;
|
return s == null || s.length() == 0;
|
||||||
@@ -139,4 +141,12 @@ public class StringUtils {
|
|||||||
}
|
}
|
||||||
return s.toString();
|
return s.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getRandomString(int length) {
|
||||||
|
char[] c = new char[length];
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
c[i] = (char) ('a' + random.nextInt(26));
|
||||||
|
return new String(c);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ package org.briarproject.bramble.test;
|
|||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
|
||||||
public abstract class BrambleMockTestCase extends
|
public abstract class BrambleMockTestCase extends BrambleTestCase {
|
||||||
BrambleTestCase {
|
|
||||||
|
|
||||||
protected final Mockery context = new Mockery();
|
protected final Mockery context = new Mockery();
|
||||||
|
|
||||||
|
|||||||
@@ -8,12 +8,9 @@ public abstract class BrambleTestCase {
|
|||||||
|
|
||||||
public BrambleTestCase() {
|
public BrambleTestCase() {
|
||||||
// Ensure exceptions thrown on worker threads cause tests to fail
|
// Ensure exceptions thrown on worker threads cause tests to fail
|
||||||
UncaughtExceptionHandler fail = new UncaughtExceptionHandler() {
|
UncaughtExceptionHandler fail = (thread, throwable) -> {
|
||||||
@Override
|
throwable.printStackTrace();
|
||||||
public void uncaughtException(Thread thread, Throwable throwable) {
|
fail();
|
||||||
throwable.printStackTrace();
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Thread.setDefaultUncaughtExceptionHandler(fail);
|
Thread.setDefaultUncaughtExceptionHandler(fail);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,27 @@ package org.briarproject.bramble.test;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.UniqueId;
|
import org.briarproject.bramble.api.UniqueId;
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.sync.ClientId;
|
||||||
|
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 org.briarproject.bramble.util.IoUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
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.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||||
|
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
|
|
||||||
public class TestUtils {
|
public class TestUtils {
|
||||||
|
|
||||||
private static final AtomicInteger nextTestDir =
|
private static final AtomicInteger nextTestDir =
|
||||||
@@ -34,15 +49,54 @@ public class TestUtils {
|
|||||||
return getRandomBytes(UniqueId.LENGTH);
|
return getRandomBytes(UniqueId.LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getRandomString(int length) {
|
|
||||||
char[] c = new char[length];
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
c[i] = (char) ('a' + random.nextInt(26));
|
|
||||||
return new String(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SecretKey getSecretKey() {
|
public static SecretKey getSecretKey() {
|
||||||
return new SecretKey(getRandomBytes(SecretKey.LENGTH));
|
return new SecretKey(getRandomBytes(SecretKey.LENGTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LocalAuthor getLocalAuthor() {
|
||||||
|
return getLocalAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LocalAuthor getLocalAuthor(int nameLength) {
|
||||||
|
AuthorId id = new AuthorId(getRandomId());
|
||||||
|
String name = getRandomString(nameLength);
|
||||||
|
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
long created = System.currentTimeMillis();
|
||||||
|
return new LocalAuthor(id, name, publicKey, privateKey, created);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Author getAuthor() {
|
||||||
|
return getAuthor(1 + random.nextInt(MAX_AUTHOR_NAME_LENGTH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Author getAuthor(int nameLength) {
|
||||||
|
AuthorId id = new AuthorId(getRandomId());
|
||||||
|
String name = getRandomString(nameLength);
|
||||||
|
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
return new Author(id, name, publicKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Group getGroup(ClientId clientId) {
|
||||||
|
int descriptorLength = 1 + random.nextInt(MAX_GROUP_DESCRIPTOR_LENGTH);
|
||||||
|
return getGroup(clientId, descriptorLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Group getGroup(ClientId clientId, int descriptorLength) {
|
||||||
|
GroupId groupId = new GroupId(getRandomId());
|
||||||
|
byte[] descriptor = getRandomBytes(descriptorLength);
|
||||||
|
return new Group(groupId, clientId, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message getMessage(GroupId groupId) {
|
||||||
|
int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH);
|
||||||
|
return getMessage(groupId, MESSAGE_HEADER_LENGTH + bodyLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message getMessage(GroupId groupId, int rawLength) {
|
||||||
|
MessageId id = new MessageId(getRandomId());
|
||||||
|
byte[] raw = getRandomBytes(rawLength);
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
return new Message(id, groupId, timestamp, raw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +1,54 @@
|
|||||||
plugins {
|
apply plugin: 'java-library'
|
||||||
id 'java'
|
sourceCompatibility = 1.8
|
||||||
id 'net.ltgt.apt' version '0.9'
|
targetCompatibility = 1.8
|
||||||
id 'idea'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceCompatibility = 1.6
|
|
||||||
targetCompatibility = 1.6
|
|
||||||
|
|
||||||
|
apply plugin: 'net.ltgt.apt'
|
||||||
|
apply plugin: 'idea'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':bramble-api')
|
implementation project(path: ':bramble-api', configuration: 'default')
|
||||||
compile 'com.madgag.spongycastle:core:1.56.0.0'
|
implementation 'com.madgag.spongycastle:core:1.58.0.0'
|
||||||
compile 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
|
implementation 'com.h2database:h2:1.4.192' // This is the last version that supports Java 1.6
|
||||||
compile 'org.bitlet:weupnp:0.1.4'
|
implementation 'org.bitlet:weupnp:0.1.4'
|
||||||
|
|
||||||
testCompile project(path: ':bramble-api', configuration: 'testOutput')
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
|
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||||
|
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"
|
||||||
|
|
||||||
|
testApt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
dependencyVerification {
|
||||||
verify = [
|
verify = [
|
||||||
'com.madgag.spongycastle:core:5e791b0eaa9e0c4594231b44f616a52adddb7dccedeb0ad9ad74887e19499a23',
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
'com.h2database:h2:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
|
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||||
'org.bitlet:weupnp:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
|
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
|
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
|
||||||
|
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
|
||||||
|
'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',
|
||||||
|
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
|
||||||
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
|
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
|
||||||
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
|
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
||||||
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
|
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
|
||||||
|
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
|
||||||
|
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
|
||||||
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,3 +63,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
|
|||||||
artifacts {
|
artifacts {
|
||||||
testOutput jarTest
|
testOutput jarTest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a Java 6 JRE is available, check we're not using any Java 7 or 8 APIs
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
useJava6StandardLibrary(it)
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class PoliteExecutor implements Executor {
|
|||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private final Queue<Runnable> queue = new LinkedList<Runnable>();
|
private final Queue<Runnable> queue = new LinkedList<>();
|
||||||
private final Executor delegate;
|
private final Executor delegate;
|
||||||
private final int maxConcurrentTasks;
|
private final int maxConcurrentTasks;
|
||||||
private final Logger log;
|
private final Logger log;
|
||||||
@@ -48,20 +48,17 @@ public class PoliteExecutor implements Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(final Runnable r) {
|
public void execute(Runnable r) {
|
||||||
final long submitted = System.currentTimeMillis();
|
long submitted = System.currentTimeMillis();
|
||||||
Runnable wrapped = new Runnable() {
|
Runnable wrapped = () -> {
|
||||||
@Override
|
if (log.isLoggable(LOG_LEVEL)) {
|
||||||
public void run() {
|
long queued = System.currentTimeMillis() - submitted;
|
||||||
if (log.isLoggable(LOG_LEVEL)) {
|
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
||||||
long queued = System.currentTimeMillis() - submitted;
|
}
|
||||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
try {
|
||||||
}
|
r.run();
|
||||||
try {
|
} finally {
|
||||||
r.run();
|
scheduleNext();
|
||||||
} finally {
|
|
||||||
scheduleNext();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
|
|||||||
@@ -28,19 +28,16 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(final Runnable r) {
|
public void execute(Runnable r) {
|
||||||
if (log.isLoggable(LOG_LEVEL)) {
|
if (log.isLoggable(LOG_LEVEL)) {
|
||||||
final long submitted = System.currentTimeMillis();
|
long submitted = System.currentTimeMillis();
|
||||||
super.execute(new Runnable() {
|
super.execute(() -> {
|
||||||
@Override
|
long started = System.currentTimeMillis();
|
||||||
public void run() {
|
long queued = started - submitted;
|
||||||
long started = System.currentTimeMillis();
|
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
||||||
long queued = started - submitted;
|
r.run();
|
||||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
long executing = System.currentTimeMillis() - started;
|
||||||
r.run();
|
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
|
||||||
long executing = System.currentTimeMillis() - started;
|
|
||||||
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
super.execute(r);
|
super.execute(r);
|
||||||
|
|||||||
@@ -201,8 +201,7 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
|
||||||
Transaction txn, GroupId g) throws DbException, FormatException {
|
Transaction txn, GroupId g) throws DbException, FormatException {
|
||||||
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g);
|
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g);
|
||||||
Map<MessageId, BdfDictionary> parsed =
|
Map<MessageId, BdfDictionary> parsed = new HashMap<>(raw.size());
|
||||||
new HashMap<MessageId, BdfDictionary>(raw.size());
|
|
||||||
for (Entry<MessageId, Metadata> e : raw.entrySet())
|
for (Entry<MessageId, Metadata> e : raw.entrySet())
|
||||||
parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
|
parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
|
||||||
return parsed;
|
return parsed;
|
||||||
@@ -229,8 +228,7 @@ class ClientHelperImpl implements ClientHelper {
|
|||||||
FormatException {
|
FormatException {
|
||||||
Metadata metadata = metadataEncoder.encode(query);
|
Metadata metadata = metadataEncoder.encode(query);
|
||||||
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g, metadata);
|
Map<MessageId, Metadata> raw = db.getMessageMetadata(txn, g, metadata);
|
||||||
Map<MessageId, BdfDictionary> parsed =
|
Map<MessageId, BdfDictionary> parsed = new HashMap<>(raw.size());
|
||||||
new HashMap<MessageId, BdfDictionary>(raw.size());
|
|
||||||
for (Entry<MessageId, Metadata> e : raw.entrySet())
|
for (Entry<MessageId, Metadata> e : raw.entrySet())
|
||||||
parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
|
parsed.put(e.getKey(), metadataParser.parse(e.getValue()));
|
||||||
return parsed;
|
return parsed;
|
||||||
|
|||||||
@@ -184,12 +184,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
// Close the outgoing stream and expect EOF on the incoming stream
|
// Close the outgoing stream and expect EOF on the incoming stream
|
||||||
w.close();
|
w.close();
|
||||||
if (!r.eof()) LOG.warning("Unexpected data at end of connection");
|
if (!r.eof()) LOG.warning("Unexpected data at end of connection");
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException | IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
listener.contactExchangeFailed();
|
|
||||||
tryToClose(conn, true);
|
|
||||||
return;
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
listener.contactExchangeFailed();
|
listener.contactExchangeFailed();
|
||||||
tryToClose(conn, true);
|
tryToClose(conn, true);
|
||||||
@@ -276,8 +271,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
|
|
||||||
private Map<TransportId, TransportProperties> receiveTransportProperties(
|
private Map<TransportId, TransportProperties> receiveTransportProperties(
|
||||||
BdfReader r) throws IOException {
|
BdfReader r) throws IOException {
|
||||||
Map<TransportId, TransportProperties> remote =
|
Map<TransportId, TransportProperties> remote = new HashMap<>();
|
||||||
new HashMap<TransportId, TransportProperties>();
|
|
||||||
r.readListStart();
|
r.readListStart();
|
||||||
while (!r.hasListEnd()) {
|
while (!r.hasListEnd()) {
|
||||||
r.readListStart();
|
r.readListStart();
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
|
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.keyManager = keyManager;
|
this.keyManager = keyManager;
|
||||||
addHooks = new CopyOnWriteArrayList<AddContactHook>();
|
addHooks = new CopyOnWriteArrayList<>();
|
||||||
removeHooks = new CopyOnWriteArrayList<RemoveContactHook>();
|
removeHooks = new CopyOnWriteArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -125,7 +125,7 @@ class ContactManagerImpl implements ContactManager {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
List<Contact> active = new ArrayList<Contact>(contacts.size());
|
List<Contact> active = new ArrayList<>(contacts.size());
|
||||||
for (Contact c : contacts) if (c.isActive()) active.add(c);
|
for (Contact c : contacts) if (c.isActive()) active.add(c);
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -602,8 +602,8 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
|
|
||||||
// Package access for testing
|
// Package access for testing
|
||||||
int chooseIterationCount(int targetMillis) {
|
int chooseIterationCount(int targetMillis) {
|
||||||
List<Long> quickSamples = new ArrayList<Long>(PBKDF_SAMPLES);
|
List<Long> quickSamples = new ArrayList<>(PBKDF_SAMPLES);
|
||||||
List<Long> slowSamples = new ArrayList<Long>(PBKDF_SAMPLES);
|
List<Long> slowSamples = new ArrayList<>(PBKDF_SAMPLES);
|
||||||
long iterationNanos = 0, initNanos = 0;
|
long iterationNanos = 0, initNanos = 0;
|
||||||
while (iterationNanos <= 0 || initNanos <= 0) {
|
while (iterationNanos <= 0 || initNanos <= 0) {
|
||||||
// Sample the running time with one iteration and two iterations
|
// Sample the running time with one iteration and two iterations
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public class CryptoModule {
|
|||||||
|
|
||||||
public CryptoModule() {
|
public CryptoModule() {
|
||||||
// Use an unbounded queue
|
// Use an unbounded queue
|
||||||
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
|
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||||
// Discard tasks that are submitted during shutdown
|
// Discard tasks that are submitted during shutdown
|
||||||
RejectedExecutionHandler policy =
|
RejectedExecutionHandler policy =
|
||||||
new ThreadPoolExecutor.DiscardPolicy();
|
new ThreadPoolExecutor.DiscardPolicy();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class PasswordStrengthEstimatorImpl implements PasswordStrengthEstimator {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float estimateStrength(String password) {
|
public float estimateStrength(String password) {
|
||||||
HashSet<Character> unique = new HashSet<Character>();
|
HashSet<Character> unique = new HashSet<>();
|
||||||
int length = password.length();
|
int length = password.length();
|
||||||
for (int i = 0; i < length; i++) unique.add(password.charAt(i));
|
for (int i = 0; i < length; i++) unique.add(password.charAt(i));
|
||||||
return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS);
|
return Math.min(1, (float) unique.size() / STRONG_UNIQUE_CHARS);
|
||||||
|
|||||||
@@ -90,8 +90,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
private final ReentrantReadWriteLock lock =
|
private final ReentrantReadWriteLock lock =
|
||||||
new ReentrantReadWriteLock(true);
|
new ReentrantReadWriteLock(true);
|
||||||
|
|
||||||
private volatile int shutdownHandle = -1;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DatabaseComponentImpl(Database<T> db, Class<T> txnClass, EventBus eventBus,
|
DatabaseComponentImpl(Database<T> db, Class<T> txnClass, EventBus eventBus,
|
||||||
ShutdownManager shutdown) {
|
ShutdownManager shutdown) {
|
||||||
@@ -103,26 +101,20 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean open() throws DbException {
|
public boolean open() throws DbException {
|
||||||
Runnable shutdownHook = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
close();
|
|
||||||
} catch (DbException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
boolean reopened = db.open();
|
boolean reopened = db.open();
|
||||||
shutdownHandle = shutdown.addShutdownHook(shutdownHook);
|
shutdown.addShutdownHook(() -> {
|
||||||
|
try {
|
||||||
|
close();
|
||||||
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
}
|
||||||
|
});
|
||||||
return reopened;
|
return reopened;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws DbException {
|
public void close() throws DbException {
|
||||||
if (closed.getAndSet(true)) return;
|
if (closed.getAndSet(true)) return;
|
||||||
shutdown.removeShutdownHook(shutdownHandle);
|
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +133,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new Transaction(db.startTransaction(), readOnly);
|
return new Transaction(db.startTransaction(), readOnly);
|
||||||
} catch (DbException e) {
|
} catch (DbException | RuntimeException e) {
|
||||||
if (readOnly) lock.readLock().unlock();
|
|
||||||
else lock.writeLock().unlock();
|
|
||||||
throw e;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
if (readOnly) lock.readLock().unlock();
|
if (readOnly) lock.readLock().unlock();
|
||||||
else lock.writeLock().unlock();
|
else lock.writeLock().unlock();
|
||||||
throw e;
|
throw e;
|
||||||
@@ -331,7 +319,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
if (!db.containsContact(txn, c))
|
if (!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength);
|
Collection<MessageId> ids = db.getMessagesToSend(txn, c, maxLength);
|
||||||
List<byte[]> messages = new ArrayList<byte[]>(ids.size());
|
List<byte[]> messages = new ArrayList<>(ids.size());
|
||||||
for (MessageId m : ids) {
|
for (MessageId m : ids) {
|
||||||
messages.add(db.getRawMessage(txn, m));
|
messages.add(db.getRawMessage(txn, m));
|
||||||
db.updateExpiryTime(txn, c, m, maxLatency);
|
db.updateExpiryTime(txn, c, m, maxLatency);
|
||||||
@@ -381,7 +369,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c,
|
Collection<MessageId> ids = db.getRequestedMessagesToSend(txn, c,
|
||||||
maxLength);
|
maxLength);
|
||||||
List<byte[]> messages = new ArrayList<byte[]>(ids.size());
|
List<byte[]> messages = new ArrayList<>(ids.size());
|
||||||
for (MessageId m : ids) {
|
for (MessageId m : ids) {
|
||||||
messages.add(db.getRawMessage(txn, m));
|
messages.add(db.getRawMessage(txn, m));
|
||||||
db.updateExpiryTime(txn, c, m, maxLatency);
|
db.updateExpiryTime(txn, c, m, maxLatency);
|
||||||
@@ -661,7 +649,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
if (!db.containsContact(txn, c))
|
if (!db.containsContact(txn, c))
|
||||||
throw new NoSuchContactException();
|
throw new NoSuchContactException();
|
||||||
Collection<MessageId> acked = new ArrayList<MessageId>();
|
Collection<MessageId> acked = new ArrayList<>();
|
||||||
for (MessageId m : a.getMessageIds()) {
|
for (MessageId m : a.getMessageIds()) {
|
||||||
if (db.containsVisibleMessage(txn, c, m)) {
|
if (db.containsVisibleMessage(txn, c, m)) {
|
||||||
db.raiseSeenFlag(txn, c, m);
|
db.raiseSeenFlag(txn, c, m);
|
||||||
@@ -770,6 +758,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
transaction.attach(new LocalAuthorRemovedEvent(a));
|
transaction.attach(new LocalAuthorRemovedEvent(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeMessage(Transaction transaction, MessageId m)
|
||||||
|
throws DbException {
|
||||||
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
|
T txn = unbox(transaction);
|
||||||
|
if (!db.containsMessage(txn, m))
|
||||||
|
throw new NoSuchMessageException();
|
||||||
|
db.removeMessage(txn, m);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeTransport(Transaction transaction, TransportId t)
|
public void removeTransport(Transaction transaction, TransportId t)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -886,8 +884,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
Map<ContactId, TransportKeys> keys) throws DbException {
|
Map<ContactId, TransportKeys> keys) throws DbException {
|
||||||
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
if (transaction.isReadOnly()) throw new IllegalArgumentException();
|
||||||
T txn = unbox(transaction);
|
T txn = unbox(transaction);
|
||||||
Map<ContactId, TransportKeys> filtered =
|
Map<ContactId, TransportKeys> filtered = new HashMap<>();
|
||||||
new HashMap<ContactId, TransportKeys>();
|
|
||||||
for (Entry<ContactId, TransportKeys> e : keys.entrySet()) {
|
for (Entry<ContactId, TransportKeys> e : keys.entrySet()) {
|
||||||
ContactId c = e.getKey();
|
ContactId c = e.getKey();
|
||||||
TransportKeys k = e.getValue();
|
TransportKeys k = e.getValue();
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class DatabaseExecutorModule {
|
|||||||
|
|
||||||
public DatabaseExecutorModule() {
|
public DatabaseExecutorModule() {
|
||||||
// Use an unbounded queue
|
// Use an unbounded queue
|
||||||
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
|
BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
|
||||||
// Discard tasks that are submitted during shutdown
|
// Discard tasks that are submitted during shutdown
|
||||||
RejectedExecutionHandler policy =
|
RejectedExecutionHandler policy =
|
||||||
new ThreadPoolExecutor.DiscardPolicy();
|
new ThreadPoolExecutor.DiscardPolicy();
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class DatabaseModule {
|
|||||||
@Singleton
|
@Singleton
|
||||||
DatabaseComponent provideDatabaseComponent(Database<Connection> db,
|
DatabaseComponent provideDatabaseComponent(Database<Connection> db,
|
||||||
EventBus eventBus, ShutdownManager shutdown) {
|
EventBus eventBus, ShutdownManager shutdown) {
|
||||||
return new DatabaseComponentImpl<Connection>(db, Connection.class,
|
return new DatabaseComponentImpl<>(db, Connection.class, eventBus,
|
||||||
eventBus, shutdown);
|
shutdown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,30 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " REFERENCES transports (transportId)"
|
+ " REFERENCES transports (transportId)"
|
||||||
+ " ON DELETE CASCADE)";
|
+ " ON DELETE CASCADE)";
|
||||||
|
|
||||||
|
private static final String INDEX_CONTACTS_BY_AUTHOR_ID =
|
||||||
|
"CREATE INDEX IF NOT EXISTS contactsByAuthorId"
|
||||||
|
+ " ON contacts (authorId)";
|
||||||
|
|
||||||
|
private static final String INDEX_MESSAGES_BY_GROUP_ID =
|
||||||
|
"CREATE INDEX IF NOT EXISTS messagesByGroupId"
|
||||||
|
+ " ON messages (groupId)";
|
||||||
|
|
||||||
|
private static final String INDEX_OFFERS_BY_CONTACT_ID =
|
||||||
|
"CREATE INDEX IF NOT EXISTS offersByContactId"
|
||||||
|
+ " ON offers (contactId)";
|
||||||
|
|
||||||
|
private static final String INDEX_GROUPS_BY_CLIENT_ID =
|
||||||
|
"CREATE INDEX IF NOT EXISTS groupsByClientId"
|
||||||
|
+ " ON groups (clientId)";
|
||||||
|
|
||||||
|
private static final String INDEX_MESSAGE_METADATA_BY_MESSAGE_ID =
|
||||||
|
"CREATE INDEX IF NOT EXISTS messageMetadataByMessageId"
|
||||||
|
+ " ON messageMetadata (messageId)";
|
||||||
|
|
||||||
|
private static final String INDEX_GROUP_METADATA_BY_GROUP_ID =
|
||||||
|
"CREATE INDEX IF NOT EXISTS groupMetadataByGroupId"
|
||||||
|
+ " ON groupMetadata (groupId)";
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(JdbcDatabase.class.getName());
|
Logger.getLogger(JdbcDatabase.class.getName());
|
||||||
|
|
||||||
@@ -239,8 +263,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
private final String hashType, binaryType, counterType, secretType;
|
private final String hashType, binaryType, counterType, secretType;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
|
|
||||||
private final LinkedList<Connection> connections =
|
// Locking: connectionsLock
|
||||||
new LinkedList<Connection>(); // Locking: connectionsLock
|
private final LinkedList<Connection> connections = new LinkedList<>();
|
||||||
|
|
||||||
private int openConnections = 0; // Locking: connectionsLock
|
private int openConnections = 0; // Locking: connectionsLock
|
||||||
private boolean closed = false; // Locking: connectionsLock
|
private boolean closed = false; // Locking: connectionsLock
|
||||||
@@ -267,7 +291,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
// Open the database and create the tables if necessary
|
// Open the database and create the tables and indexes if necessary
|
||||||
Connection txn = startTransaction();
|
Connection txn = startTransaction();
|
||||||
try {
|
try {
|
||||||
if (reopen) {
|
if (reopen) {
|
||||||
@@ -276,6 +300,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
createTables(txn);
|
createTables(txn);
|
||||||
storeSchemaVersion(txn);
|
storeSchemaVersion(txn);
|
||||||
}
|
}
|
||||||
|
createIndexes(txn);
|
||||||
commitTransaction(txn);
|
commitTransaction(txn);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
abortTransaction(txn);
|
abortTransaction(txn);
|
||||||
@@ -340,6 +365,23 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createIndexes(Connection txn) throws DbException {
|
||||||
|
Statement s = null;
|
||||||
|
try {
|
||||||
|
s = txn.createStatement();
|
||||||
|
s.executeUpdate(INDEX_CONTACTS_BY_AUTHOR_ID);
|
||||||
|
s.executeUpdate(INDEX_MESSAGES_BY_GROUP_ID);
|
||||||
|
s.executeUpdate(INDEX_OFFERS_BY_CONTACT_ID);
|
||||||
|
s.executeUpdate(INDEX_GROUPS_BY_CLIENT_ID);
|
||||||
|
s.executeUpdate(INDEX_MESSAGE_METADATA_BY_MESSAGE_ID);
|
||||||
|
s.executeUpdate(INDEX_GROUP_METADATA_BY_GROUP_ID);
|
||||||
|
s.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
tryToClose(s);
|
||||||
|
throw new DbException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String insertTypeNames(String s) {
|
private String insertTypeNames(String s) {
|
||||||
s = s.replaceAll("HASH", hashType);
|
s = s.replaceAll("HASH", hashType);
|
||||||
s = s.replaceAll("BINARY", binaryType);
|
s = s.replaceAll("BINARY", binaryType);
|
||||||
@@ -993,7 +1035,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " FROM contacts";
|
+ " FROM contacts";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<Contact> contacts = new ArrayList<Contact>();
|
List<Contact> contacts = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
ContactId contactId = new ContactId(rs.getInt(1));
|
ContactId contactId = new ContactId(rs.getInt(1));
|
||||||
AuthorId authorId = new AuthorId(rs.getBytes(2));
|
AuthorId authorId = new AuthorId(rs.getBytes(2));
|
||||||
@@ -1027,7 +1069,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, local.getBytes());
|
ps.setBytes(1, local.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<ContactId> ids = new ArrayList<ContactId>();
|
List<ContactId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new ContactId(rs.getInt(1)));
|
while (rs.next()) ids.add(new ContactId(rs.getInt(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1052,7 +1094,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, remote.getBytes());
|
ps.setBytes(1, remote.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<Contact> contacts = new ArrayList<Contact>();
|
List<Contact> contacts = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
ContactId c = new ContactId(rs.getInt(1));
|
ContactId c = new ContactId(rs.getInt(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
@@ -1108,7 +1150,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setString(1, c.getString());
|
ps.setString(1, c.getString());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<Group> groups = new ArrayList<Group>();
|
List<Group> groups = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
GroupId id = new GroupId(rs.getBytes(1));
|
GroupId id = new GroupId(rs.getBytes(1));
|
||||||
byte[] descriptor = rs.getBytes(2);
|
byte[] descriptor = rs.getBytes(2);
|
||||||
@@ -1161,7 +1203,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<ContactId> visible = new ArrayList<ContactId>();
|
List<ContactId> visible = new ArrayList<>();
|
||||||
while (rs.next()) visible.add(new ContactId(rs.getInt(1)));
|
while (rs.next()) visible.add(new ContactId(rs.getInt(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1213,7 +1255,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
+ " FROM localAuthors";
|
+ " FROM localAuthors";
|
||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<LocalAuthor> authors = new ArrayList<LocalAuthor>();
|
List<LocalAuthor> authors = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
AuthorId authorId = new AuthorId(rs.getBytes(1));
|
AuthorId authorId = new AuthorId(rs.getBytes(1));
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
@@ -1243,7 +1285,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1266,7 +1308,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(1, state.getValue());
|
ps.setInt(1, state.getValue());
|
||||||
ps.setBytes(2, g.getBytes());
|
ps.setBytes(2, g.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1301,7 +1343,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setString(3, e.getKey());
|
ps.setString(3, e.getKey());
|
||||||
ps.setBytes(4, e.getValue());
|
ps.setBytes(4, e.getValue());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
Set<MessageId> ids = new HashSet<MessageId>();
|
Set<MessageId> ids = new HashSet<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1335,7 +1377,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(1, DELIVERED.getValue());
|
ps.setInt(1, DELIVERED.getValue());
|
||||||
ps.setBytes(2, g.getBytes());
|
ps.setBytes(2, g.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
Map<MessageId, Metadata> all = new HashMap<MessageId, Metadata>();
|
Map<MessageId, Metadata> all = new HashMap<>();
|
||||||
Metadata metadata = null;
|
Metadata metadata = null;
|
||||||
MessageId lastMessageId = null;
|
MessageId lastMessageId = null;
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
@@ -1364,8 +1406,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
Collection<MessageId> matches = getMessageIds(txn, g, query);
|
Collection<MessageId> matches = getMessageIds(txn, g, query);
|
||||||
if (matches.isEmpty()) return Collections.emptyMap();
|
if (matches.isEmpty()) return Collections.emptyMap();
|
||||||
// Retrieve the metadata for each match
|
// Retrieve the metadata for each match
|
||||||
Map<MessageId, Metadata> all = new HashMap<MessageId, Metadata>(
|
Map<MessageId, Metadata> all = new HashMap<>(matches.size());
|
||||||
matches.size());
|
|
||||||
for (MessageId m : matches) all.put(m, getMessageMetadata(txn, m));
|
for (MessageId m : matches) all.put(m, getMessageMetadata(txn, m));
|
||||||
return all;
|
return all;
|
||||||
}
|
}
|
||||||
@@ -1463,7 +1504,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setBytes(1, g.getBytes());
|
ps.setBytes(1, g.getBytes());
|
||||||
ps.setInt(2, c.getInt());
|
ps.setInt(2, c.getInt());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageStatus> statuses = new ArrayList<MessageStatus>();
|
List<MessageStatus> statuses = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
MessageId messageId = new MessageId(rs.getBytes(1));
|
MessageId messageId = new MessageId(rs.getBytes(1));
|
||||||
boolean sent = rs.getBoolean(2);
|
boolean sent = rs.getBoolean(2);
|
||||||
@@ -1522,7 +1563,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getBytes());
|
ps.setBytes(1, m.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
Map<MessageId, State> dependencies = new HashMap<MessageId, State>();
|
Map<MessageId, State> dependencies = new HashMap<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
MessageId dependency = new MessageId(rs.getBytes(1));
|
MessageId dependency = new MessageId(rs.getBytes(1));
|
||||||
State state = State.fromValue(rs.getInt(2));
|
State state = State.fromValue(rs.getInt(2));
|
||||||
@@ -1560,7 +1601,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setBytes(1, m.getBytes());
|
ps.setBytes(1, m.getBytes());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
Map<MessageId, State> dependents = new HashMap<MessageId, State>();
|
Map<MessageId, State> dependents = new HashMap<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
MessageId dependent = new MessageId(rs.getBytes(1));
|
MessageId dependent = new MessageId(rs.getBytes(1));
|
||||||
State state = State.fromValue(rs.getInt(2));
|
State state = State.fromValue(rs.getInt(2));
|
||||||
@@ -1612,7 +1653,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
ps.setInt(2, maxMessages);
|
ps.setInt(2, maxMessages);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1648,7 +1689,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setLong(3, now);
|
ps.setLong(3, now);
|
||||||
ps.setInt(4, maxMessages);
|
ps.setInt(4, maxMessages);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1673,7 +1714,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(1, c.getInt());
|
ps.setInt(1, c.getInt());
|
||||||
ps.setInt(2, maxMessages);
|
ps.setInt(2, maxMessages);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1708,7 +1749,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(2, DELIVERED.getValue());
|
ps.setInt(2, DELIVERED.getValue());
|
||||||
ps.setLong(3, now);
|
ps.setLong(3, now);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
int total = 0;
|
int total = 0;
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
int length = rs.getInt(1);
|
int length = rs.getInt(1);
|
||||||
@@ -1750,7 +1791,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(1, state.getValue());
|
ps.setInt(1, state.getValue());
|
||||||
ps.setString(2, c.getString());
|
ps.setString(2, c.getString());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1780,7 +1821,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setString(1, c.getString());
|
ps.setString(1, c.getString());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
while (rs.next()) ids.add(new MessageId(rs.getBytes(1)));
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
@@ -1839,7 +1880,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps.setInt(2, DELIVERED.getValue());
|
ps.setInt(2, DELIVERED.getValue());
|
||||||
ps.setLong(3, now);
|
ps.setLong(3, now);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
int total = 0;
|
int total = 0;
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
int length = rs.getInt(1);
|
int length = rs.getInt(1);
|
||||||
@@ -1893,7 +1934,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setString(1, t.getString());
|
ps.setString(1, t.getString());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
List<IncomingKeys> inKeys = new ArrayList<IncomingKeys>();
|
List<IncomingKeys> inKeys = new ArrayList<>();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
long rotationPeriod = rs.getLong(1);
|
long rotationPeriod = rs.getLong(1);
|
||||||
SecretKey tagKey = new SecretKey(rs.getBytes(2));
|
SecretKey tagKey = new SecretKey(rs.getBytes(2));
|
||||||
@@ -1913,8 +1954,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
ps = txn.prepareStatement(sql);
|
ps = txn.prepareStatement(sql);
|
||||||
ps.setString(1, t.getString());
|
ps.setString(1, t.getString());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
Map<ContactId, TransportKeys> keys =
|
Map<ContactId, TransportKeys> keys = new HashMap<>();
|
||||||
new HashMap<ContactId, TransportKeys>();
|
|
||||||
for (int i = 0; rs.next(); i++) {
|
for (int i = 0; rs.next(); i++) {
|
||||||
// There should be three times as many incoming keys
|
// There should be three times as many incoming keys
|
||||||
if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
|
if (inKeys.size() < (i + 1) * 3) throw new DbStateException();
|
||||||
@@ -2032,8 +2072,8 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
// Determine which keys are being removed
|
// Determine which keys are being removed
|
||||||
List<String> removed = new ArrayList<String>();
|
List<String> removed = new ArrayList<>();
|
||||||
Map<String, byte[]> retained = new HashMap<String, byte[]>();
|
Map<String, byte[]> retained = new HashMap<>();
|
||||||
for (Entry<String, byte[]> e : meta.entrySet()) {
|
for (Entry<String, byte[]> e : meta.entrySet()) {
|
||||||
if (e.getValue() == REMOVE) removed.add(e.getKey());
|
if (e.getValue() == REMOVE) removed.add(e.getKey());
|
||||||
else retained.put(e.getKey(), e.getValue());
|
else retained.put(e.getKey(), e.getValue());
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
class EventBusImpl implements EventBus {
|
class EventBusImpl implements EventBus {
|
||||||
|
|
||||||
private final Collection<EventListener> listeners =
|
private final Collection<EventListener> listeners =
|
||||||
new CopyOnWriteArrayList<EventListener>();
|
new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(EventListener l) {
|
public void addListener(EventListener l) {
|
||||||
|
|||||||
@@ -50,10 +50,9 @@ class KeyAgreementConnector {
|
|||||||
private final PluginManager pluginManager;
|
private final PluginManager pluginManager;
|
||||||
private final CompletionService<KeyAgreementConnection> connect;
|
private final CompletionService<KeyAgreementConnection> connect;
|
||||||
|
|
||||||
private final List<KeyAgreementListener> listeners =
|
private final List<KeyAgreementListener> listeners = new ArrayList<>();
|
||||||
new ArrayList<KeyAgreementListener>();
|
|
||||||
private final List<Future<KeyAgreementConnection>> pending =
|
private final List<Future<KeyAgreementConnection>> pending =
|
||||||
new ArrayList<Future<KeyAgreementConnection>>();
|
new ArrayList<>();
|
||||||
|
|
||||||
private volatile boolean connecting = false;
|
private volatile boolean connecting = false;
|
||||||
private volatile boolean alice = false;
|
private volatile boolean alice = false;
|
||||||
@@ -65,8 +64,7 @@ class KeyAgreementConnector {
|
|||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
this.pluginManager = pluginManager;
|
this.pluginManager = pluginManager;
|
||||||
connect = new ExecutorCompletionService<KeyAgreementConnection>(
|
connect = new ExecutorCompletionService<>(ioExecutor);
|
||||||
ioExecutor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Payload listen(KeyPair localKeyPair) {
|
public Payload listen(KeyPair localKeyPair) {
|
||||||
@@ -75,8 +73,7 @@ class KeyAgreementConnector {
|
|||||||
byte[] commitment = crypto.deriveKeyCommitment(
|
byte[] commitment = crypto.deriveKeyCommitment(
|
||||||
localKeyPair.getPublic().getEncoded());
|
localKeyPair.getPublic().getEncoded());
|
||||||
// Start all listeners and collect their descriptors
|
// Start all listeners and collect their descriptors
|
||||||
List<TransportDescriptor> descriptors =
|
List<TransportDescriptor> descriptors = new ArrayList<>();
|
||||||
new ArrayList<TransportDescriptor>();
|
|
||||||
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {
|
for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {
|
||||||
KeyAgreementListener l =
|
KeyAgreementListener l =
|
||||||
plugin.createKeyAgreementListener(commitment);
|
plugin.createKeyAgreementListener(commitment);
|
||||||
@@ -132,10 +129,7 @@ class KeyAgreementConnector {
|
|||||||
LOG.info("Interrupted while waiting for connection");
|
LOG.info("Interrupted while waiting for connection");
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
return null;
|
return null;
|
||||||
} catch (ExecutionException e) {
|
} catch (ExecutionException | IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
return null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -51,8 +51,7 @@ class PayloadParserImpl implements PayloadParser {
|
|||||||
byte[] commitment = payload.getRaw(1);
|
byte[] commitment = payload.getRaw(1);
|
||||||
if (commitment.length != COMMIT_LENGTH) throw new FormatException();
|
if (commitment.length != COMMIT_LENGTH) throw new FormatException();
|
||||||
// Remaining elements: transport descriptors
|
// Remaining elements: transport descriptors
|
||||||
List<TransportDescriptor> recognised =
|
List<TransportDescriptor> recognised = new ArrayList<>();
|
||||||
new ArrayList<TransportDescriptor>();
|
|
||||||
for (int i = 2; i < payload.size(); i++) {
|
for (int i = 2; i < payload.size(); i++) {
|
||||||
BdfList descriptor = payload.getList(i);
|
BdfList descriptor = payload.getList(i);
|
||||||
long transportId = descriptor.getLong(0);
|
long transportId = descriptor.getLong(0);
|
||||||
|
|||||||
@@ -63,9 +63,9 @@ class LifecycleManagerImpl implements LifecycleManager {
|
|||||||
this.crypto = crypto;
|
this.crypto = crypto;
|
||||||
this.authorFactory = authorFactory;
|
this.authorFactory = authorFactory;
|
||||||
this.identityManager = identityManager;
|
this.identityManager = identityManager;
|
||||||
services = new CopyOnWriteArrayList<Service>();
|
services = new CopyOnWriteArrayList<>();
|
||||||
clients = new CopyOnWriteArrayList<Client>();
|
clients = new CopyOnWriteArrayList<>();
|
||||||
executors = new CopyOnWriteArrayList<ExecutorService>();
|
executors = new CopyOnWriteArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -88,7 +88,7 @@ class LifecycleManagerImpl implements LifecycleManager {
|
|||||||
executors.add(e);
|
executors.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalAuthor createLocalAuthor(final String nickname) {
|
private LocalAuthor createLocalAuthor(String nickname) {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
||||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||||
@@ -203,9 +203,7 @@ class LifecycleManagerImpl implements LifecycleManager {
|
|||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Closing database took " + duration + " ms");
|
LOG.info("Closing database took " + duration + " ms");
|
||||||
shutdownLatch.countDown();
|
shutdownLatch.countDown();
|
||||||
} catch (DbException e) {
|
} catch (DbException | ServiceException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
} catch (ServiceException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
} finally {
|
} finally {
|
||||||
startStopSemaphore.release();
|
startStopSemaphore.release();
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public class LifecycleModule {
|
|||||||
|
|
||||||
public LifecycleModule() {
|
public LifecycleModule() {
|
||||||
// The thread pool is unbounded, so use direct handoff
|
// The thread pool is unbounded, so use direct handoff
|
||||||
BlockingQueue<Runnable> queue = new SynchronousQueue<Runnable>();
|
BlockingQueue<Runnable> queue = new SynchronousQueue<>();
|
||||||
// Discard tasks that are submitted during shutdown
|
// Discard tasks that are submitted during shutdown
|
||||||
RejectedExecutionHandler policy =
|
RejectedExecutionHandler policy =
|
||||||
new ThreadPoolExecutor.DiscardPolicy();
|
new ThreadPoolExecutor.DiscardPolicy();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ShutdownManagerImpl implements ShutdownManager {
|
|||||||
private int nextHandle = 0;
|
private int nextHandle = 0;
|
||||||
|
|
||||||
ShutdownManagerImpl() {
|
ShutdownManagerImpl() {
|
||||||
hooks = new HashMap<Integer, Thread>();
|
hooks = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -134,11 +134,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
byte[] tag = readTag(reader);
|
byte[] tag = readTag(reader);
|
||||||
ctx = keyManager.getStreamContext(transportId, tag);
|
ctx = keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException e) {
|
} catch (IOException | DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
disposeReader(true, false);
|
|
||||||
return;
|
|
||||||
} catch (DbException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
disposeReader(true, false);
|
disposeReader(true, false);
|
||||||
return;
|
return;
|
||||||
@@ -249,11 +245,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
byte[] tag = readTag(reader);
|
byte[] tag = readTag(reader);
|
||||||
ctx = keyManager.getStreamContext(transportId, tag);
|
ctx = keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException e) {
|
} catch (IOException | DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
disposeReader(true, false);
|
|
||||||
return;
|
|
||||||
} catch (DbException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
disposeReader(true, false);
|
disposeReader(true, false);
|
||||||
return;
|
return;
|
||||||
@@ -266,12 +258,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
contactId = ctx.getContactId();
|
contactId = ctx.getContactId();
|
||||||
connectionRegistry.registerConnection(contactId, transportId, true);
|
connectionRegistry.registerConnection(contactId, transportId, true);
|
||||||
// Start the outgoing session on another thread
|
// Start the outgoing session on another thread
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(this::runOutgoingSession);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runOutgoingSession();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
// Create and run the incoming session
|
// Create and run the incoming session
|
||||||
incomingSession = createIncomingSession(ctx, reader);
|
incomingSession = createIncomingSession(ctx, reader);
|
||||||
@@ -368,12 +355,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Start the incoming session on another thread
|
// Start the incoming session on another thread
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(this::runIncomingSession);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runIncomingSession();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
// Create and run the outgoing session
|
// Create and run the outgoing session
|
||||||
outgoingSession = createDuplexOutgoingSession(ctx, writer);
|
outgoingSession = createDuplexOutgoingSession(ctx, writer);
|
||||||
@@ -391,11 +373,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
byte[] tag = readTag(reader);
|
byte[] tag = readTag(reader);
|
||||||
ctx = keyManager.getStreamContext(transportId, tag);
|
ctx = keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException e) {
|
} catch (IOException | DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
disposeReader(true, false);
|
|
||||||
return;
|
|
||||||
} catch (DbException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
disposeReader(true, false);
|
disposeReader(true, false);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
@Inject
|
@Inject
|
||||||
ConnectionRegistryImpl(EventBus eventBus) {
|
ConnectionRegistryImpl(EventBus eventBus) {
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
connections = new HashMap<TransportId, Map<ContactId, Integer>>();
|
connections = new HashMap<>();
|
||||||
contactCounts = new HashMap<ContactId, Integer>();
|
contactCounts = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,7 +58,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
try {
|
try {
|
||||||
Map<ContactId, Integer> m = connections.get(t);
|
Map<ContactId, Integer> m = connections.get(t);
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
m = new HashMap<ContactId, Integer>();
|
m = new HashMap<>();
|
||||||
connections.put(t, m);
|
connections.put(t, m);
|
||||||
}
|
}
|
||||||
Integer count = m.get(c);
|
Integer count = m.get(c);
|
||||||
@@ -124,7 +124,7 @@ class ConnectionRegistryImpl implements ConnectionRegistry {
|
|||||||
try {
|
try {
|
||||||
Map<ContactId, Integer> m = connections.get(t);
|
Map<ContactId, Integer> m = connections.get(t);
|
||||||
if (m == null) return Collections.emptyList();
|
if (m == null) return Collections.emptyList();
|
||||||
List<ContactId> ids = new ArrayList<ContactId>(m.keySet());
|
List<ContactId> ids = new ArrayList<>(m.keySet());
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info(ids.size() + " contacts connected");
|
LOG.info(ids.size() + " contacts connected");
|
||||||
return ids;
|
return ids;
|
||||||
|
|||||||
@@ -82,10 +82,10 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
this.settingsManager = settingsManager;
|
this.settingsManager = settingsManager;
|
||||||
this.transportPropertyManager = transportPropertyManager;
|
this.transportPropertyManager = transportPropertyManager;
|
||||||
this.uiCallback = uiCallback;
|
this.uiCallback = uiCallback;
|
||||||
plugins = new ConcurrentHashMap<TransportId, Plugin>();
|
plugins = new ConcurrentHashMap<>();
|
||||||
simplexPlugins = new CopyOnWriteArrayList<SimplexPlugin>();
|
simplexPlugins = new CopyOnWriteArrayList<>();
|
||||||
duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>();
|
duplexPlugins = new CopyOnWriteArrayList<>();
|
||||||
startLatches = new ConcurrentHashMap<TransportId, CountDownLatch>();
|
startLatches = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -156,17 +156,17 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<SimplexPlugin> getSimplexPlugins() {
|
public Collection<SimplexPlugin> getSimplexPlugins() {
|
||||||
return new ArrayList<SimplexPlugin>(simplexPlugins);
|
return new ArrayList<>(simplexPlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DuplexPlugin> getDuplexPlugins() {
|
public Collection<DuplexPlugin> getDuplexPlugins() {
|
||||||
return new ArrayList<DuplexPlugin>(duplexPlugins);
|
return new ArrayList<>(duplexPlugins);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<DuplexPlugin> getKeyAgreementPlugins() {
|
public Collection<DuplexPlugin> getKeyAgreementPlugins() {
|
||||||
List<DuplexPlugin> supported = new ArrayList<DuplexPlugin>();
|
List<DuplexPlugin> supported = new ArrayList<>();
|
||||||
for (DuplexPlugin d : duplexPlugins)
|
for (DuplexPlugin d : duplexPlugins)
|
||||||
if (d.supportsKeyAgreement()) supported.add(d);
|
if (d.supportsKeyAgreement()) supported.add(d);
|
||||||
return supported;
|
return supported;
|
||||||
@@ -283,6 +283,16 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportProperties getRemoteProperties(ContactId c) {
|
||||||
|
try {
|
||||||
|
return transportPropertyManager.getRemoteProperties(c, id);
|
||||||
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
return new TransportProperties();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeSettings(Settings s) {
|
public void mergeSettings(Settings s) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class Poller implements EventListener {
|
|||||||
this.random = random;
|
this.random = random;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
lock = new ReentrantLock();
|
lock = new ReentrantLock();
|
||||||
tasks = new HashMap<TransportId, PollTask>();
|
tasks = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -111,30 +111,24 @@ class Poller implements EventListener {
|
|||||||
connectToContact(c, (DuplexPlugin) p);
|
connectToContact(c, (DuplexPlugin) p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectToContact(final ContactId c, final SimplexPlugin p) {
|
private void connectToContact(ContactId c, SimplexPlugin p) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
TransportId t = p.getId();
|
||||||
public void run() {
|
if (!connectionRegistry.isConnected(c, t)) {
|
||||||
TransportId t = p.getId();
|
TransportConnectionWriter w = p.createWriter(c);
|
||||||
if (!connectionRegistry.isConnected(c, t)) {
|
if (w != null)
|
||||||
TransportConnectionWriter w = p.createWriter(c);
|
connectionManager.manageOutgoingConnection(c, t, w);
|
||||||
if (w != null)
|
|
||||||
connectionManager.manageOutgoingConnection(c, t, w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectToContact(final ContactId c, final DuplexPlugin p) {
|
private void connectToContact(ContactId c, DuplexPlugin p) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
TransportId t = p.getId();
|
||||||
public void run() {
|
if (!connectionRegistry.isConnected(c, t)) {
|
||||||
TransportId t = p.getId();
|
DuplexTransportConnection d = p.createConnection(c);
|
||||||
if (!connectionRegistry.isConnected(c, t)) {
|
if (d != null)
|
||||||
DuplexTransportConnection d = p.createConnection(c);
|
connectionManager.manageOutgoingConnection(c, t, d);
|
||||||
if (d != null)
|
|
||||||
connectionManager.manageOutgoingConnection(c, t, d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -159,14 +153,10 @@ class Poller implements EventListener {
|
|||||||
try {
|
try {
|
||||||
PollTask scheduled = tasks.get(t);
|
PollTask scheduled = tasks.get(t);
|
||||||
if (scheduled == null || due < scheduled.due) {
|
if (scheduled == null || due < scheduled.due) {
|
||||||
final PollTask task = new PollTask(p, due, randomiseNext);
|
PollTask task = new PollTask(p, due, randomiseNext);
|
||||||
tasks.put(t, task);
|
tasks.put(t, task);
|
||||||
scheduler.schedule(new Runnable() {
|
scheduler.schedule(
|
||||||
@Override
|
() -> ioExecutor.execute(task), delay, MILLISECONDS);
|
||||||
public void run() {
|
|
||||||
ioExecutor.execute(task);
|
|
||||||
}
|
|
||||||
}, delay, MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
@@ -174,7 +164,7 @@ class Poller implements EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@IoExecutor
|
@IoExecutor
|
||||||
private void poll(final Plugin p) {
|
private void poll(Plugin p) {
|
||||||
TransportId t = p.getId();
|
TransportId t = p.getId();
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t);
|
if (LOG.isLoggable(INFO)) LOG.info("Polling plugin " + t);
|
||||||
p.poll(connectionRegistry.getConnectedContacts(t));
|
p.poll(connectionRegistry.getConnectedContacts(t));
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ abstract class FilePlugin implements SimplexPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void createReaderFromFile(final File f) {
|
protected void createReaderFromFile(File f) {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
ioExecutor.execute(new ReaderCreator(f));
|
ioExecutor.execute(new ReaderCreator(f));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.briarproject.bramble.plugin.tcp;
|
package org.briarproject.bramble.plugin.tcp;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.FormatException;
|
import org.briarproject.bramble.api.FormatException;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
||||||
@@ -35,6 +34,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_LAN;
|
||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
||||||
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
||||||
|
|
||||||
@@ -45,7 +45,6 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
Logger.getLogger(LanTcpPlugin.class.getName());
|
Logger.getLogger(LanTcpPlugin.class.getName());
|
||||||
|
|
||||||
private static final int MAX_ADDRESSES = 4;
|
private static final int MAX_ADDRESSES = 4;
|
||||||
private static final String PROP_IP_PORTS = "ipPorts";
|
|
||||||
private static final String SEPARATOR = ",";
|
private static final String SEPARATOR = ",";
|
||||||
|
|
||||||
LanTcpPlugin(Executor ioExecutor, Backoff backoff,
|
LanTcpPlugin(Executor ioExecutor, Backoff backoff,
|
||||||
@@ -64,7 +63,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
TransportProperties p = callback.getLocalProperties();
|
TransportProperties p = callback.getLocalProperties();
|
||||||
String oldIpPorts = p.get(PROP_IP_PORTS);
|
String oldIpPorts = p.get(PROP_IP_PORTS);
|
||||||
List<InetSocketAddress> olds = parseSocketAddresses(oldIpPorts);
|
List<InetSocketAddress> olds = parseSocketAddresses(oldIpPorts);
|
||||||
List<InetSocketAddress> locals = new LinkedList<InetSocketAddress>();
|
List<InetSocketAddress> locals = new LinkedList<>();
|
||||||
for (InetAddress local : getLocalIpAddresses()) {
|
for (InetAddress local : getLocalIpAddresses()) {
|
||||||
if (isAcceptableAddress(local)) {
|
if (isAcceptableAddress(local)) {
|
||||||
// If this is the old address, try to use the same port
|
// If this is the old address, try to use the same port
|
||||||
@@ -83,7 +82,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
private List<InetSocketAddress> parseSocketAddresses(String ipPorts) {
|
private List<InetSocketAddress> parseSocketAddresses(String ipPorts) {
|
||||||
if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList();
|
if (StringUtils.isNullOrEmpty(ipPorts)) return Collections.emptyList();
|
||||||
String[] split = ipPorts.split(SEPARATOR);
|
String[] split = ipPorts.split(SEPARATOR);
|
||||||
List<InetSocketAddress> addresses = new ArrayList<InetSocketAddress>();
|
List<InetSocketAddress> addresses = new ArrayList<>();
|
||||||
for (String ipPort : split) {
|
for (String ipPort : split) {
|
||||||
InetSocketAddress a = parseSocketAddress(ipPort);
|
InetSocketAddress a = parseSocketAddress(ipPort);
|
||||||
if (a != null) addresses.add(a);
|
if (a != null) addresses.add(a);
|
||||||
@@ -96,7 +95,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
String ipPort = getIpPortString(a);
|
String ipPort = getIpPortString(a);
|
||||||
// Get the list of recently used addresses
|
// Get the list of recently used addresses
|
||||||
String setting = callback.getSettings().get(PREF_LAN_IP_PORTS);
|
String setting = callback.getSettings().get(PREF_LAN_IP_PORTS);
|
||||||
List<String> recent = new ArrayList<String>();
|
List<String> recent = new ArrayList<>();
|
||||||
if (!StringUtils.isNullOrEmpty(setting))
|
if (!StringUtils.isNullOrEmpty(setting))
|
||||||
Collections.addAll(recent, setting.split(SEPARATOR));
|
Collections.addAll(recent, setting.split(SEPARATOR));
|
||||||
// Is the address already in the list?
|
// Is the address already in the list?
|
||||||
@@ -112,7 +111,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
recent = recent.subList(0, MAX_ADDRESSES);
|
recent = recent.subList(0, MAX_ADDRESSES);
|
||||||
setting = StringUtils.join(recent, SEPARATOR);
|
setting = StringUtils.join(recent, SEPARATOR);
|
||||||
// Update the list of addresses shared with contacts
|
// Update the list of addresses shared with contacts
|
||||||
List<String> shared = new ArrayList<String>(recent);
|
List<String> shared = new ArrayList<>(recent);
|
||||||
Collections.sort(shared);
|
Collections.sort(shared);
|
||||||
String property = StringUtils.join(shared, SEPARATOR);
|
String property = StringUtils.join(shared, SEPARATOR);
|
||||||
TransportProperties properties = new TransportProperties();
|
TransportProperties properties = new TransportProperties();
|
||||||
@@ -126,9 +125,8 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<InetSocketAddress> getRemoteSocketAddresses(ContactId c) {
|
protected List<InetSocketAddress> getRemoteSocketAddresses(
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p) {
|
||||||
if (p == null) return Collections.emptyList();
|
|
||||||
return parseSocketAddresses(p.get(PROP_IP_PORTS));
|
return parseSocketAddresses(p.get(PROP_IP_PORTS));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,16 +260,12 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Callable<KeyAgreementConnection> listen() {
|
public Callable<KeyAgreementConnection> listen() {
|
||||||
return new Callable<KeyAgreementConnection>() {
|
return () -> {
|
||||||
@Override
|
Socket s = ss.accept();
|
||||||
public KeyAgreementConnection call() throws IOException {
|
if (LOG.isLoggable(INFO))
|
||||||
Socket s = ss.accept();
|
LOG.info(ID.getString() + ": Incoming connection");
|
||||||
if (LOG.isLoggable(INFO))
|
return new KeyAgreementConnection(
|
||||||
LOG.info(ID.getString() + ": Incoming connection");
|
new TcpTransportConnection(LanTcpPlugin.this, s), ID);
|
||||||
return new KeyAgreementConnection(
|
|
||||||
new TcpTransportConnection(LanTcpPlugin.this, s),
|
|
||||||
ID);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MappingResult map(final int port) {
|
public MappingResult map(int port) {
|
||||||
if (!started.getAndSet(true)) start();
|
if (!started.getAndSet(true)) start();
|
||||||
if (gateway == null) return null;
|
if (gateway == null) return null;
|
||||||
InetAddress internal = gateway.getLocalAddress();
|
InetAddress internal = gateway.getLocalAddress();
|
||||||
@@ -50,12 +50,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
succeeded = gateway.addPortMapping(port, port,
|
succeeded = gateway.addPortMapping(port, port,
|
||||||
getHostAddress(internal), "TCP", "TCP");
|
getHostAddress(internal), "TCP", "TCP");
|
||||||
if (succeeded) {
|
if (succeeded) {
|
||||||
shutdownManager.addShutdownHook(new Runnable() {
|
shutdownManager.addShutdownHook(() -> deleteMapping(port));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
deleteMapping(port);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
String externalString = gateway.getExternalIPAddress();
|
String externalString = gateway.getExternalIPAddress();
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
@@ -63,9 +58,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
"External address " + scrubInetAddress(externalString));
|
"External address " + scrubInetAddress(externalString));
|
||||||
if (externalString != null)
|
if (externalString != null)
|
||||||
external = InetAddress.getByName(externalString);
|
external = InetAddress.getByName(externalString);
|
||||||
} catch (IOException e) {
|
} catch (IOException | SAXException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
} catch (SAXException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
}
|
}
|
||||||
return new MappingResult(internal, external, port, succeeded);
|
return new MappingResult(internal, external, port, succeeded);
|
||||||
@@ -82,11 +75,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
GatewayDiscover d = new GatewayDiscover();
|
GatewayDiscover d = new GatewayDiscover();
|
||||||
try {
|
try {
|
||||||
d.discover();
|
d.discover();
|
||||||
} catch (IOException e) {
|
} catch (IOException | SAXException | ParserConfigurationException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
} catch (SAXException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
} catch (ParserConfigurationException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
}
|
}
|
||||||
gateway = d.getValidGateway();
|
gateway = d.getValidGateway();
|
||||||
@@ -97,9 +86,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
gateway.deletePortMapping(port, "TCP");
|
gateway.deletePortMapping(port, "TCP");
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Deleted mapping for port " + port);
|
LOG.info("Deleted mapping for port " + port);
|
||||||
} catch (IOException e) {
|
} catch (IOException | SAXException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
|
||||||
} catch (SAXException e) {
|
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -24,6 +25,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
@@ -66,11 +69,11 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
protected abstract void setLocalSocketAddress(InetSocketAddress a);
|
protected abstract void setLocalSocketAddress(InetSocketAddress a);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns zero or more socket addresses for connecting to the given
|
* Returns zero or more socket addresses for connecting to a contact with
|
||||||
* contact.
|
* the given transport properties.
|
||||||
*/
|
*/
|
||||||
protected abstract List<InetSocketAddress> getRemoteSocketAddresses(
|
protected abstract List<InetSocketAddress> getRemoteSocketAddresses(
|
||||||
ContactId c);
|
TransportProperties p);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if connections to the given address can be attempted.
|
* Returns true if connections to the given address can be attempted.
|
||||||
@@ -107,41 +110,37 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void bind() {
|
protected void bind() {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
if (!running) return;
|
||||||
public void run() {
|
ServerSocket ss = null;
|
||||||
if (!running) return;
|
for (InetSocketAddress addr : getLocalSocketAddresses()) {
|
||||||
ServerSocket ss = null;
|
try {
|
||||||
for (InetSocketAddress addr : getLocalSocketAddresses()) {
|
ss = new ServerSocket();
|
||||||
try {
|
ss.bind(addr);
|
||||||
ss = new ServerSocket();
|
break;
|
||||||
ss.bind(addr);
|
} catch (IOException e) {
|
||||||
break;
|
if (LOG.isLoggable(INFO))
|
||||||
} catch (IOException e) {
|
LOG.info("Failed to bind " + scrubSocketAddress(addr));
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Failed to bind " +
|
|
||||||
scrubSocketAddress(addr));
|
|
||||||
tryToClose(ss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ss == null || !ss.isBound()) {
|
|
||||||
LOG.info("Could not bind server socket");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!running) {
|
|
||||||
tryToClose(ss);
|
tryToClose(ss);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
socket = ss;
|
|
||||||
backoff.reset();
|
|
||||||
InetSocketAddress local =
|
|
||||||
(InetSocketAddress) ss.getLocalSocketAddress();
|
|
||||||
setLocalSocketAddress(local);
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Listening on " + scrubSocketAddress(local));
|
|
||||||
callback.transportEnabled();
|
|
||||||
acceptContactConnections();
|
|
||||||
}
|
}
|
||||||
|
if (ss == null || !ss.isBound()) {
|
||||||
|
LOG.info("Could not bind server socket");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!running) {
|
||||||
|
tryToClose(ss);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket = ss;
|
||||||
|
backoff.reset();
|
||||||
|
InetSocketAddress local =
|
||||||
|
(InetSocketAddress) ss.getLocalSocketAddress();
|
||||||
|
setLocalSocketAddress(local);
|
||||||
|
if (LOG.isLoggable(INFO))
|
||||||
|
LOG.info("Listening on " + scrubSocketAddress(local));
|
||||||
|
callback.transportEnabled();
|
||||||
|
acceptContactConnections();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,20 +206,21 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
public void poll(Collection<ContactId> connected) {
|
public void poll(Collection<ContactId> connected) {
|
||||||
if (!isRunning()) return;
|
if (!isRunning()) return;
|
||||||
backoff.increment();
|
backoff.increment();
|
||||||
// TODO: Pass properties to connectAndCallBack()
|
Map<ContactId, TransportProperties> remote =
|
||||||
for (ContactId c : callback.getRemoteProperties().keySet())
|
callback.getRemoteProperties();
|
||||||
if (!connected.contains(c)) connectAndCallBack(c);
|
for (Entry<ContactId, TransportProperties> e : remote.entrySet()) {
|
||||||
|
ContactId c = e.getKey();
|
||||||
|
if (!connected.contains(c)) connectAndCallBack(c, e.getValue());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectAndCallBack(final ContactId c) {
|
private void connectAndCallBack(ContactId c, TransportProperties p) {
|
||||||
ioExecutor.execute(new Runnable() {
|
ioExecutor.execute(() -> {
|
||||||
@Override
|
if (!isRunning()) return;
|
||||||
public void run() {
|
DuplexTransportConnection d = createConnection(p);
|
||||||
DuplexTransportConnection d = createConnection(c);
|
if (d != null) {
|
||||||
if (d != null) {
|
backoff.reset();
|
||||||
backoff.reset();
|
callback.outgoingConnectionCreated(c, d);
|
||||||
callback.outgoingConnectionCreated(c, d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -228,7 +228,12 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public DuplexTransportConnection createConnection(ContactId c) {
|
public DuplexTransportConnection createConnection(ContactId c) {
|
||||||
if (!isRunning()) return null;
|
if (!isRunning()) return null;
|
||||||
for (InetSocketAddress remote : getRemoteSocketAddresses(c)) {
|
return createConnection(callback.getRemoteProperties(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private DuplexTransportConnection createConnection(TransportProperties p) {
|
||||||
|
for (InetSocketAddress remote : getRemoteSocketAddresses(p)) {
|
||||||
if (!isConnectable(remote)) {
|
if (!isConnectable(remote)) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
SocketAddress local = socket.getLocalSocketAddress();
|
SocketAddress local = socket.getLocalSocketAddress();
|
||||||
@@ -304,7 +309,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<InetAddress> addrs = new ArrayList<InetAddress>();
|
List<InetAddress> addrs = new ArrayList<>();
|
||||||
for (NetworkInterface iface : ifaces)
|
for (NetworkInterface iface : ifaces)
|
||||||
addrs.addAll(Collections.list(iface.getInetAddresses()));
|
addrs.addAll(Collections.list(iface.getInetAddresses()));
|
||||||
return addrs;
|
return addrs;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package org.briarproject.bramble.plugin.tcp;
|
package org.briarproject.bramble.plugin.tcp;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.Backoff;
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
@@ -44,7 +43,7 @@ class WanTcpPlugin extends TcpPlugin {
|
|||||||
// Use the same address and port as last time if available
|
// Use the same address and port as last time if available
|
||||||
TransportProperties p = callback.getLocalProperties();
|
TransportProperties p = callback.getLocalProperties();
|
||||||
InetSocketAddress old = parseSocketAddress(p.get(PROP_IP_PORT));
|
InetSocketAddress old = parseSocketAddress(p.get(PROP_IP_PORT));
|
||||||
List<InetSocketAddress> addrs = new LinkedList<InetSocketAddress>();
|
List<InetSocketAddress> addrs = new LinkedList<>();
|
||||||
for (InetAddress a : getLocalIpAddresses()) {
|
for (InetAddress a : getLocalIpAddresses()) {
|
||||||
if (isAcceptableAddress(a)) {
|
if (isAcceptableAddress(a)) {
|
||||||
// If this is the old address, try to use the same port
|
// If this is the old address, try to use the same port
|
||||||
@@ -78,9 +77,8 @@ class WanTcpPlugin extends TcpPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected List<InetSocketAddress> getRemoteSocketAddresses(ContactId c) {
|
protected List<InetSocketAddress> getRemoteSocketAddresses(
|
||||||
TransportProperties p = callback.getRemoteProperties().get(c);
|
TransportProperties p) {
|
||||||
if (p == null) return Collections.emptyList();
|
|
||||||
InetSocketAddress parsed = parseSocketAddress(p.get(PROP_IP_PORT));
|
InetSocketAddress parsed = parseSocketAddress(p.get(PROP_IP_PORT));
|
||||||
if (parsed == null) return Collections.emptyList();
|
if (parsed == null) return Collections.emptyList();
|
||||||
return Collections.singletonList(parsed);
|
return Collections.singletonList(parsed);
|
||||||
|
|||||||
@@ -40,9 +40,12 @@ public class PropertiesModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
TransportPropertyManager getTransportPropertyManager(
|
TransportPropertyManager getTransportPropertyManager(
|
||||||
LifecycleManager lifecycleManager, ContactManager contactManager,
|
LifecycleManager lifecycleManager,
|
||||||
|
ValidationManager validationManager, ContactManager contactManager,
|
||||||
TransportPropertyManagerImpl transportPropertyManager) {
|
TransportPropertyManagerImpl transportPropertyManager) {
|
||||||
lifecycleManager.registerClient(transportPropertyManager);
|
lifecycleManager.registerClient(transportPropertyManager);
|
||||||
|
validationManager.registerIncomingMessageHook(CLIENT_ID,
|
||||||
|
transportPropertyManager);
|
||||||
contactManager.registerAddContactHook(transportPropertyManager);
|
contactManager.registerAddContactHook(transportPropertyManager);
|
||||||
contactManager.registerRemoveContactHook(transportPropertyManager);
|
contactManager.registerRemoveContactHook(transportPropertyManager);
|
||||||
return transportPropertyManager;
|
return transportPropertyManager;
|
||||||
|
|||||||
@@ -9,8 +9,10 @@ import org.briarproject.bramble.api.contact.ContactManager.AddContactHook;
|
|||||||
import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
|
import org.briarproject.bramble.api.contact.ContactManager.RemoveContactHook;
|
||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.data.MetadataParser;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.db.Metadata;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.TransportId;
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
@@ -19,8 +21,10 @@ import org.briarproject.bramble.api.properties.TransportPropertyManager;
|
|||||||
import org.briarproject.bramble.api.sync.Client;
|
import org.briarproject.bramble.api.sync.Client;
|
||||||
import org.briarproject.bramble.api.sync.Group;
|
import org.briarproject.bramble.api.sync.Group;
|
||||||
import org.briarproject.bramble.api.sync.GroupId;
|
import org.briarproject.bramble.api.sync.GroupId;
|
||||||
|
import org.briarproject.bramble.api.sync.InvalidMessageException;
|
||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -36,20 +40,22 @@ import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
|||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
class TransportPropertyManagerImpl implements TransportPropertyManager,
|
||||||
Client, AddContactHook, RemoveContactHook {
|
Client, AddContactHook, RemoveContactHook, IncomingMessageHook {
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final ClientHelper clientHelper;
|
private final ClientHelper clientHelper;
|
||||||
|
private final MetadataParser metadataParser;
|
||||||
private final ContactGroupFactory contactGroupFactory;
|
private final ContactGroupFactory contactGroupFactory;
|
||||||
private final Clock clock;
|
private final Clock clock;
|
||||||
private final Group localGroup;
|
private final Group localGroup;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
TransportPropertyManagerImpl(DatabaseComponent db,
|
TransportPropertyManagerImpl(DatabaseComponent db,
|
||||||
ClientHelper clientHelper, ContactGroupFactory contactGroupFactory,
|
ClientHelper clientHelper, MetadataParser metadataParser,
|
||||||
Clock clock) {
|
ContactGroupFactory contactGroupFactory, Clock clock) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.clientHelper = clientHelper;
|
this.clientHelper = clientHelper;
|
||||||
|
this.metadataParser = metadataParser;
|
||||||
this.contactGroupFactory = contactGroupFactory;
|
this.contactGroupFactory = contactGroupFactory;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID);
|
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID);
|
||||||
@@ -57,6 +63,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void createLocalState(Transaction txn) throws DbException {
|
public void createLocalState(Transaction txn) throws DbException {
|
||||||
|
if (db.containsGroup(txn, localGroup.getId())) return;
|
||||||
db.addGroup(txn, localGroup);
|
db.addGroup(txn, localGroup);
|
||||||
// Ensure we've set things up for any pre-existing contacts
|
// Ensure we've set things up for any pre-existing contacts
|
||||||
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
for (Contact c : db.getContacts(txn)) addingContact(txn, c);
|
||||||
@@ -84,6 +91,31 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
db.removeGroup(txn, getContactGroup(c));
|
db.removeGroup(txn, getContactGroup(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
|
||||||
|
throws DbException, InvalidMessageException {
|
||||||
|
try {
|
||||||
|
// Find the latest update for this transport, if any
|
||||||
|
BdfDictionary d = metadataParser.parse(meta);
|
||||||
|
TransportId t = new TransportId(d.getString("transportId"));
|
||||||
|
LatestUpdate latest = findLatest(txn, m.getGroupId(), t, false);
|
||||||
|
if (latest != null) {
|
||||||
|
if (d.getLong("version") > latest.version) {
|
||||||
|
// This update is newer - delete the previous update
|
||||||
|
db.deleteMessage(txn, latest.messageId);
|
||||||
|
db.deleteMessageMetadata(txn, latest.messageId);
|
||||||
|
} else {
|
||||||
|
// We've already received a newer update - delete this one
|
||||||
|
db.deleteMessage(txn, m.getId());
|
||||||
|
db.deleteMessageMetadata(txn, m.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (FormatException e) {
|
||||||
|
throw new InvalidMessageException(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addRemoteProperties(Transaction txn, ContactId c,
|
public void addRemoteProperties(Transaction txn, ContactId c,
|
||||||
Map<TransportId, TransportProperties> props) throws DbException {
|
Map<TransportId, TransportProperties> props) throws DbException {
|
||||||
@@ -98,7 +130,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
public Map<TransportId, TransportProperties> getLocalProperties()
|
public Map<TransportId, TransportProperties> getLocalProperties()
|
||||||
throws DbException {
|
throws DbException {
|
||||||
Map<TransportId, TransportProperties> local;
|
Map<TransportId, TransportProperties> local;
|
||||||
Transaction txn = db.startTransaction(true);
|
// TODO: Transaction can be read-only when code is simplified
|
||||||
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
local = getLocalProperties(txn);
|
local = getLocalProperties(txn);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -112,11 +145,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
public Map<TransportId, TransportProperties> getLocalProperties(
|
public Map<TransportId, TransportProperties> getLocalProperties(
|
||||||
Transaction txn) throws DbException {
|
Transaction txn) throws DbException {
|
||||||
try {
|
try {
|
||||||
Map<TransportId, TransportProperties> local =
|
Map<TransportId, TransportProperties> local = new HashMap<>();
|
||||||
new HashMap<TransportId, TransportProperties>();
|
|
||||||
// Find the latest local update for each transport
|
// Find the latest local update for each transport
|
||||||
Map<TransportId, LatestUpdate> latest = findLatest(txn,
|
Map<TransportId, LatestUpdate> latest = findLatestLocal(txn);
|
||||||
localGroup.getId(), true);
|
|
||||||
// Retrieve and parse the latest local properties
|
// Retrieve and parse the latest local properties
|
||||||
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
|
for (Entry<TransportId, LatestUpdate> e : latest.entrySet()) {
|
||||||
BdfList message = clientHelper.getMessageAsList(txn,
|
BdfList message = clientHelper.getMessageAsList(txn,
|
||||||
@@ -135,7 +166,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
try {
|
try {
|
||||||
TransportProperties p = null;
|
TransportProperties p = null;
|
||||||
Transaction txn = db.startTransaction(true);
|
// TODO: Transaction can be read-only when code is simplified
|
||||||
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
// Find the latest local update
|
// Find the latest local update
|
||||||
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
|
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
|
||||||
@@ -160,35 +192,53 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
@Override
|
@Override
|
||||||
public Map<ContactId, TransportProperties> getRemoteProperties(
|
public Map<ContactId, TransportProperties> getRemoteProperties(
|
||||||
TransportId t) throws DbException {
|
TransportId t) throws DbException {
|
||||||
|
Map<ContactId, TransportProperties> remote = new HashMap<>();
|
||||||
|
// TODO: Transaction can be read-only when code is simplified
|
||||||
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
Map<ContactId, TransportProperties> remote =
|
for (Contact c : db.getContacts(txn))
|
||||||
new HashMap<ContactId, TransportProperties>();
|
remote.put(c.getId(), getRemoteProperties(txn, c, t));
|
||||||
Transaction txn = db.startTransaction(true);
|
db.commitTransaction(txn);
|
||||||
try {
|
} finally {
|
||||||
for (Contact c : db.getContacts(txn)) {
|
db.endTransaction(txn);
|
||||||
// Don't return properties for inactive contacts
|
}
|
||||||
if (!c.isActive()) continue;
|
return remote;
|
||||||
Group g = getContactGroup(c);
|
}
|
||||||
// Find the latest remote update
|
|
||||||
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
|
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
|
||||||
if (latest != null) {
|
TransportId t) throws DbException {
|
||||||
// Retrieve and parse the latest remote properties
|
// Don't return properties for inactive contacts
|
||||||
BdfList message = clientHelper.getMessageAsList(txn,
|
if (!c.isActive()) return new TransportProperties();
|
||||||
latest.messageId);
|
Group g = getContactGroup(c);
|
||||||
if (message == null) throw new DbException();
|
try {
|
||||||
remote.put(c.getId(), parseProperties(message));
|
// Find the latest remote update
|
||||||
}
|
LatestUpdate latest = findLatest(txn, g.getId(), t, false);
|
||||||
}
|
if (latest == null) return new TransportProperties();
|
||||||
db.commitTransaction(txn);
|
// Retrieve and parse the latest remote properties
|
||||||
} finally {
|
BdfList message =
|
||||||
db.endTransaction(txn);
|
clientHelper.getMessageAsList(txn, latest.messageId);
|
||||||
}
|
if (message == null) throw new DbException();
|
||||||
return remote;
|
return parseProperties(message);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
|
||||||
|
throws DbException {
|
||||||
|
TransportProperties p;
|
||||||
|
// TODO: Transaction can be read-only when code is simplified
|
||||||
|
Transaction txn = db.startTransaction(false);
|
||||||
|
try {
|
||||||
|
p = getRemoteProperties(txn, db.getContact(txn, c), t);
|
||||||
|
db.commitTransaction(txn);
|
||||||
|
} finally {
|
||||||
|
db.endTransaction(txn);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
public void mergeLocalProperties(TransportId t, TransportProperties p)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
@@ -217,6 +267,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
long version = latest == null ? 1 : latest.version + 1;
|
long version = latest == null ? 1 : latest.version + 1;
|
||||||
storeMessage(txn, localGroup.getId(), t, merged, version,
|
storeMessage(txn, localGroup.getId(), t, merged, version,
|
||||||
true, false);
|
true, false);
|
||||||
|
// Delete the previous update, if any
|
||||||
|
if (latest != null)
|
||||||
|
db.removeMessage(txn, latest.messageId);
|
||||||
// Store the merged properties in each contact's group
|
// Store the merged properties in each contact's group
|
||||||
for (Contact c : db.getContacts(txn)) {
|
for (Contact c : db.getContacts(txn)) {
|
||||||
Group g = getContactGroup(c);
|
Group g = getContactGroup(c);
|
||||||
@@ -224,6 +277,9 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
version = latest == null ? 1 : latest.version + 1;
|
version = latest == null ? 1 : latest.version + 1;
|
||||||
storeMessage(txn, g.getId(), t, merged, version,
|
storeMessage(txn, g.getId(), t, merged, version,
|
||||||
true, true);
|
true, true);
|
||||||
|
// Delete the previous update, if any
|
||||||
|
if (latest != null)
|
||||||
|
db.removeMessage(txn, latest.messageId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -261,20 +317,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
return BdfList.of(t.getString(), version, p);
|
return BdfList.of(t.getString(), version, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<TransportId, LatestUpdate> findLatest(Transaction txn,
|
private Map<TransportId, LatestUpdate> findLatestLocal(Transaction txn)
|
||||||
GroupId g, boolean local) throws DbException, FormatException {
|
throws DbException, FormatException {
|
||||||
Map<TransportId, LatestUpdate> latestUpdates =
|
// TODO: This can be simplified before 1.0
|
||||||
new HashMap<TransportId, LatestUpdate>();
|
Map<TransportId, LatestUpdate> latestUpdates = new HashMap<>();
|
||||||
Map<MessageId, BdfDictionary> metadata =
|
Map<MessageId, BdfDictionary> metadata = clientHelper
|
||||||
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
.getMessageMetadataAsDictionary(txn, localGroup.getId());
|
||||||
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
|
for (Entry<MessageId, BdfDictionary> e : metadata.entrySet()) {
|
||||||
BdfDictionary meta = e.getValue();
|
BdfDictionary meta = e.getValue();
|
||||||
if (meta.getBoolean("local") == local) {
|
TransportId t = new TransportId(meta.getString("transportId"));
|
||||||
TransportId t = new TransportId(meta.getString("transportId"));
|
long version = meta.getLong("version");
|
||||||
long version = meta.getLong("version");
|
LatestUpdate latest = latestUpdates.get(t);
|
||||||
LatestUpdate latest = latestUpdates.get(t);
|
if (latest == null) {
|
||||||
if (latest == null || version > latest.version)
|
latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
|
||||||
latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
|
} else if (version > latest.version) {
|
||||||
|
// This update is newer - delete the previous one
|
||||||
|
db.removeMessage(txn, latest.messageId);
|
||||||
|
latestUpdates.put(t, new LatestUpdate(e.getKey(), version));
|
||||||
|
} else {
|
||||||
|
// We've already found a newer update - delete this one
|
||||||
|
db.removeMessage(txn, e.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return latestUpdates;
|
return latestUpdates;
|
||||||
@@ -283,6 +345,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
@Nullable
|
@Nullable
|
||||||
private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t,
|
private LatestUpdate findLatest(Transaction txn, GroupId g, TransportId t,
|
||||||
boolean local) throws DbException, FormatException {
|
boolean local) throws DbException, FormatException {
|
||||||
|
// TODO: This can be simplified before 1.0
|
||||||
LatestUpdate latest = null;
|
LatestUpdate latest = null;
|
||||||
Map<MessageId, BdfDictionary> metadata =
|
Map<MessageId, BdfDictionary> metadata =
|
||||||
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
clientHelper.getMessageMetadataAsDictionary(txn, g);
|
||||||
@@ -291,8 +354,26 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
|
|||||||
if (meta.getString("transportId").equals(t.getString())
|
if (meta.getString("transportId").equals(t.getString())
|
||||||
&& meta.getBoolean("local") == local) {
|
&& meta.getBoolean("local") == local) {
|
||||||
long version = meta.getLong("version");
|
long version = meta.getLong("version");
|
||||||
if (latest == null || version > latest.version)
|
if (latest == null) {
|
||||||
latest = new LatestUpdate(e.getKey(), version);
|
latest = new LatestUpdate(e.getKey(), version);
|
||||||
|
} else if (version > latest.version) {
|
||||||
|
// This update is newer - delete the previous one
|
||||||
|
if (local) {
|
||||||
|
db.removeMessage(txn, latest.messageId);
|
||||||
|
} else {
|
||||||
|
db.deleteMessage(txn, latest.messageId);
|
||||||
|
db.deleteMessageMetadata(txn, latest.messageId);
|
||||||
|
}
|
||||||
|
latest = new LatestUpdate(e.getKey(), version);
|
||||||
|
} else {
|
||||||
|
// We've already found a newer update - delete this one
|
||||||
|
if (local) {
|
||||||
|
db.removeMessage(txn, e.getKey());
|
||||||
|
} else {
|
||||||
|
db.deleteMessage(txn, e.getKey());
|
||||||
|
db.deleteMessageMetadata(txn, e.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return latest;
|
return latest;
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Receiver implements ReadHandler {
|
|||||||
Receiver(Clock clock, Sender sender) {
|
Receiver(Clock clock, Sender sender) {
|
||||||
this.sender = sender;
|
this.sender = sender;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
dataFrames = new TreeSet<Data>(new SequenceNumberComparator());
|
dataFrames = new TreeSet<>(new SequenceNumberComparator());
|
||||||
}
|
}
|
||||||
|
|
||||||
Data read() throws IOException, InterruptedException {
|
Data read() throws IOException, InterruptedException {
|
||||||
|
|||||||
@@ -42,48 +42,44 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
|
|||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.writeHandler = writeHandler;
|
this.writeHandler = writeHandler;
|
||||||
writes = new LinkedBlockingQueue<byte[]>();
|
writes = new LinkedBlockingQueue<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() {
|
public void start() {
|
||||||
SlipEncoder encoder = new SlipEncoder(this);
|
SlipEncoder encoder = new SlipEncoder(this);
|
||||||
final Sender sender = new Sender(clock, encoder);
|
Sender sender = new Sender(clock, encoder);
|
||||||
receiver = new Receiver(clock, sender);
|
receiver = new Receiver(clock, sender);
|
||||||
decoder = new SlipDecoder(receiver, Data.MAX_LENGTH);
|
decoder = new SlipDecoder(receiver, Data.MAX_LENGTH);
|
||||||
inputStream = new ReceiverInputStream(receiver);
|
inputStream = new ReceiverInputStream(receiver);
|
||||||
outputStream = new SenderOutputStream(sender);
|
outputStream = new SenderOutputStream(sender);
|
||||||
running = true;
|
running = true;
|
||||||
executor.execute(new Runnable() {
|
executor.execute(() -> {
|
||||||
@Override
|
long now = clock.currentTimeMillis();
|
||||||
public void run() {
|
long next = now + TICK_INTERVAL;
|
||||||
long now = clock.currentTimeMillis();
|
try {
|
||||||
long next = now + TICK_INTERVAL;
|
while (running) {
|
||||||
try {
|
byte[] b = null;
|
||||||
while (running) {
|
while (now < next && b == null) {
|
||||||
byte[] b = null;
|
b = writes.poll(next - now, MILLISECONDS);
|
||||||
while (now < next && b == null) {
|
if (!running) return;
|
||||||
b = writes.poll(next - now, MILLISECONDS);
|
now = clock.currentTimeMillis();
|
||||||
if (!running) return;
|
}
|
||||||
now = clock.currentTimeMillis();
|
if (b == null) {
|
||||||
}
|
sender.tick();
|
||||||
if (b == null) {
|
while (next <= now) next += TICK_INTERVAL;
|
||||||
sender.tick();
|
} else {
|
||||||
while (next <= now) next += TICK_INTERVAL;
|
if (b.length == 0) return; // Poison pill
|
||||||
} else {
|
writeHandler.handleWrite(b);
|
||||||
if (b.length == 0) return; // Poison pill
|
|
||||||
writeHandler.handleWrite(b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOG.warning("Interrupted while waiting to write");
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
running = false;
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
running = false;
|
|
||||||
}
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOG.warning("Interrupted while waiting to write");
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
running = false;
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
|
running = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class Sender {
|
|||||||
Sender(Clock clock, WriteHandler writeHandler) {
|
Sender(Clock clock, WriteHandler writeHandler) {
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
this.writeHandler = writeHandler;
|
this.writeHandler = writeHandler;
|
||||||
outstanding = new LinkedList<Outstanding>();
|
outstanding = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendAck(long sequenceNumber, int windowSize) throws IOException {
|
void sendAck(long sequenceNumber, int windowSize) throws IOException {
|
||||||
@@ -136,7 +136,7 @@ class Sender {
|
|||||||
if (now - o.lastTransmitted > rto) {
|
if (now - o.lastTransmitted > rto) {
|
||||||
it.remove();
|
it.remove();
|
||||||
if (retransmit == null)
|
if (retransmit == null)
|
||||||
retransmit = new ArrayList<Outstanding>();
|
retransmit = new ArrayList<>();
|
||||||
retransmit.add(o);
|
retransmit.add(o);
|
||||||
// Update the retransmission timeout
|
// Update the retransmission timeout
|
||||||
rto <<= 1;
|
rto <<= 1;
|
||||||
|
|||||||
@@ -54,12 +54,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(DuplexOutgoingSession.class.getName());
|
Logger.getLogger(DuplexOutgoingSession.class.getName());
|
||||||
|
|
||||||
private static final ThrowingRunnable<IOException> CLOSE =
|
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
|
||||||
new ThrowingRunnable<IOException>() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final Executor dbExecutor;
|
private final Executor dbExecutor;
|
||||||
@@ -83,7 +78,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
this.maxIdleTime = maxIdleTime;
|
this.maxIdleTime = maxIdleTime;
|
||||||
this.recordWriter = recordWriter;
|
this.recordWriter = recordWriter;
|
||||||
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
|
writerTasks = new LinkedBlockingQueue<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@IoExecutor
|
@IoExecutor
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class RecordReaderImpl implements RecordReader {
|
|||||||
private List<MessageId> readMessageIds() throws IOException {
|
private List<MessageId> readMessageIds() throws IOException {
|
||||||
if (payloadLength == 0) throw new FormatException();
|
if (payloadLength == 0) throw new FormatException();
|
||||||
if (payloadLength % UniqueId.LENGTH != 0) throw new FormatException();
|
if (payloadLength % UniqueId.LENGTH != 0) throw new FormatException();
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
for (int off = 0; off < payloadLength; off += UniqueId.LENGTH) {
|
for (int off = 0; off < payloadLength; off += UniqueId.LENGTH) {
|
||||||
byte[] id = new byte[UniqueId.LENGTH];
|
byte[] id = new byte[UniqueId.LENGTH];
|
||||||
System.arraycopy(payload, off, id, 0, UniqueId.LENGTH);
|
System.arraycopy(payload, off, id, 0, UniqueId.LENGTH);
|
||||||
|
|||||||
@@ -43,12 +43,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(SimplexOutgoingSession.class.getName());
|
Logger.getLogger(SimplexOutgoingSession.class.getName());
|
||||||
|
|
||||||
private static final ThrowingRunnable<IOException> CLOSE =
|
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
|
||||||
new ThrowingRunnable<IOException>() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
private final Executor dbExecutor;
|
private final Executor dbExecutor;
|
||||||
@@ -71,7 +66,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
this.maxLatency = maxLatency;
|
this.maxLatency = maxLatency;
|
||||||
this.recordWriter = recordWriter;
|
this.recordWriter = recordWriter;
|
||||||
outstandingQueries = new AtomicInteger(2); // One per type of record
|
outstandingQueries = new AtomicInteger(2); // One per type of record
|
||||||
writerTasks = new LinkedBlockingQueue<ThrowingRunnable<IOException>>();
|
writerTasks = new LinkedBlockingQueue<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@IoExecutor
|
@IoExecutor
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
this.dbExecutor = dbExecutor;
|
this.dbExecutor = dbExecutor;
|
||||||
this.validationExecutor = validationExecutor;
|
this.validationExecutor = validationExecutor;
|
||||||
this.messageFactory = messageFactory;
|
this.messageFactory = messageFactory;
|
||||||
validators = new ConcurrentHashMap<ClientId, MessageValidator>();
|
validators = new ConcurrentHashMap<>();
|
||||||
hooks = new ConcurrentHashMap<ClientId, IncomingMessageHook>();
|
hooks = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -93,19 +93,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
hooks.put(c, hook);
|
hooks.put(c, hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateOutstandingMessagesAsync(final ClientId c) {
|
private void validateOutstandingMessagesAsync(ClientId c) {
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> validateOutstandingMessages(c));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
validateOutstandingMessages(c);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void validateOutstandingMessages(ClientId c) {
|
private void validateOutstandingMessages(ClientId c) {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> unvalidated = new LinkedList<MessageId>();
|
Queue<MessageId> unvalidated = new LinkedList<>();
|
||||||
Transaction txn = db.startTransaction(true);
|
Transaction txn = db.startTransaction(true);
|
||||||
try {
|
try {
|
||||||
unvalidated.addAll(db.getMessagesToValidate(txn, c));
|
unvalidated.addAll(db.getMessagesToValidate(txn, c));
|
||||||
@@ -119,14 +114,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateNextMessageAsync(final Queue<MessageId> unvalidated) {
|
private void validateNextMessageAsync(Queue<MessageId> unvalidated) {
|
||||||
if (unvalidated.isEmpty()) return;
|
if (unvalidated.isEmpty()) return;
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> validateNextMessage(unvalidated));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
validateNextMessage(unvalidated);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -158,19 +148,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverOutstandingMessagesAsync(final ClientId c) {
|
private void deliverOutstandingMessagesAsync(ClientId c) {
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> deliverOutstandingMessages(c));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
deliverOutstandingMessages(c);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void deliverOutstandingMessages(ClientId c) {
|
private void deliverOutstandingMessages(ClientId c) {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> pending = new LinkedList<MessageId>();
|
Queue<MessageId> pending = new LinkedList<>();
|
||||||
Transaction txn = db.startTransaction(true);
|
Transaction txn = db.startTransaction(true);
|
||||||
try {
|
try {
|
||||||
pending.addAll(db.getPendingMessages(txn, c));
|
pending.addAll(db.getPendingMessages(txn, c));
|
||||||
@@ -184,15 +169,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deliverNextPendingMessageAsync(
|
private void deliverNextPendingMessageAsync(Queue<MessageId> pending) {
|
||||||
final Queue<MessageId> pending) {
|
|
||||||
if (pending.isEmpty()) return;
|
if (pending.isEmpty()) return;
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> deliverNextPendingMessage(pending));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
deliverNextPendingMessage(pending);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -229,8 +208,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
pending.addAll(getPendingDependents(txn, id));
|
pending.addAll(getPendingDependents(txn, id));
|
||||||
if (result.share) {
|
if (result.share) {
|
||||||
db.setMessageShared(txn, id);
|
db.setMessageShared(txn, id);
|
||||||
toShare = new LinkedList<MessageId>(
|
toShare = new LinkedList<>(states.keySet());
|
||||||
states.keySet());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidate = getDependentsToInvalidate(txn, id);
|
invalidate = getDependentsToInvalidate(txn, id);
|
||||||
@@ -255,13 +233,8 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateMessageAsync(final Message m, final Group g) {
|
private void validateMessageAsync(Message m, Group g) {
|
||||||
validationExecutor.execute(new Runnable() {
|
validationExecutor.execute(() -> validateMessage(m, g));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
validateMessage(m, g);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ValidationExecutor
|
@ValidationExecutor
|
||||||
@@ -277,21 +250,16 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
} catch (InvalidMessageException e) {
|
} catch (InvalidMessageException e) {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.log(INFO, e.toString(), e);
|
LOG.log(INFO, e.toString(), e);
|
||||||
Queue<MessageId> invalidate = new LinkedList<MessageId>();
|
Queue<MessageId> invalidate = new LinkedList<>();
|
||||||
invalidate.add(m.getId());
|
invalidate.add(m.getId());
|
||||||
invalidateNextMessageAsync(invalidate);
|
invalidateNextMessageAsync(invalidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeMessageContextAsync(final Message m, final ClientId c,
|
private void storeMessageContextAsync(Message m, ClientId c,
|
||||||
final MessageContext result) {
|
MessageContext result) {
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> storeMessageContext(m, c, result));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
storeMessageContext(m, c, result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -331,8 +299,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
pending = getPendingDependents(txn, id);
|
pending = getPendingDependents(txn, id);
|
||||||
if (result.share) {
|
if (result.share) {
|
||||||
db.setMessageShared(txn, id);
|
db.setMessageShared(txn, id);
|
||||||
toShare =
|
toShare = new LinkedList<>(dependencies);
|
||||||
new LinkedList<MessageId>(dependencies);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
invalidate = getDependentsToInvalidate(txn, id);
|
invalidate = getDependentsToInvalidate(txn, id);
|
||||||
@@ -378,7 +345,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
|
private Queue<MessageId> getPendingDependents(Transaction txn, MessageId m)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
Queue<MessageId> pending = new LinkedList<MessageId>();
|
Queue<MessageId> pending = new LinkedList<>();
|
||||||
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
||||||
for (Entry<MessageId, State> e : states.entrySet()) {
|
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||||
if (e.getValue() == PENDING) pending.add(e.getKey());
|
if (e.getValue() == PENDING) pending.add(e.getKey());
|
||||||
@@ -386,19 +353,14 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
return pending;
|
return pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shareOutstandingMessagesAsync(final ClientId c) {
|
private void shareOutstandingMessagesAsync(ClientId c) {
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> shareOutstandingMessages(c));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
shareOutstandingMessages(c);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void shareOutstandingMessages(ClientId c) {
|
private void shareOutstandingMessages(ClientId c) {
|
||||||
try {
|
try {
|
||||||
Queue<MessageId> toShare = new LinkedList<MessageId>();
|
Queue<MessageId> toShare = new LinkedList<>();
|
||||||
Transaction txn = db.startTransaction(true);
|
Transaction txn = db.startTransaction(true);
|
||||||
try {
|
try {
|
||||||
toShare.addAll(db.getMessagesToShare(txn, c));
|
toShare.addAll(db.getMessagesToShare(txn, c));
|
||||||
@@ -418,14 +380,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
* This method should only be called for messages that have all their
|
* This method should only be called for messages that have all their
|
||||||
* dependencies delivered and have been delivered themselves.
|
* dependencies delivered and have been delivered themselves.
|
||||||
*/
|
*/
|
||||||
private void shareNextMessageAsync(final Queue<MessageId> toShare) {
|
private void shareNextMessageAsync(Queue<MessageId> toShare) {
|
||||||
if (toShare.isEmpty()) return;
|
if (toShare.isEmpty()) return;
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> shareNextMessage(toShare));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
shareNextMessage(toShare);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -452,14 +409,9 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invalidateNextMessageAsync(final Queue<MessageId> invalidate) {
|
private void invalidateNextMessageAsync(Queue<MessageId> invalidate) {
|
||||||
if (invalidate.isEmpty()) return;
|
if (invalidate.isEmpty()) return;
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> invalidateNextMessage(invalidate));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
invalidateNextMessage(invalidate);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@@ -496,7 +448,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
|
private Queue<MessageId> getDependentsToInvalidate(Transaction txn,
|
||||||
MessageId m) throws DbException {
|
MessageId m) throws DbException {
|
||||||
Queue<MessageId> invalidate = new LinkedList<MessageId>();
|
Queue<MessageId> invalidate = new LinkedList<>();
|
||||||
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
Map<MessageId, State> states = db.getMessageDependents(txn, m);
|
||||||
for (Entry<MessageId, State> e : states.entrySet()) {
|
for (Entry<MessageId, State> e : states.entrySet()) {
|
||||||
if (e.getValue() != INVALID) invalidate.add(e.getKey());
|
if (e.getValue() != INVALID) invalidate.add(e.getKey());
|
||||||
@@ -514,17 +466,12 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadGroupAndValidateAsync(final Message m) {
|
private void loadGroupAndValidateAsync(Message m) {
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> loadGroupAndValidate(m));
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
loadGroupAndValidate(m);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
private void loadGroupAndValidate(final Message m) {
|
private void loadGroupAndValidate(Message m) {
|
||||||
try {
|
try {
|
||||||
Group g;
|
Group g;
|
||||||
Transaction txn = db.startTransaction(true);
|
Transaction txn = db.startTransaction(true);
|
||||||
|
|||||||
@@ -58,15 +58,14 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
this.pluginConfig = pluginConfig;
|
this.pluginConfig = pluginConfig;
|
||||||
this.transportKeyManagerFactory = transportKeyManagerFactory;
|
this.transportKeyManagerFactory = transportKeyManagerFactory;
|
||||||
// Use a ConcurrentHashMap as a thread-safe set
|
// Use a ConcurrentHashMap as a thread-safe set
|
||||||
activeContacts = new ConcurrentHashMap<ContactId, Boolean>();
|
activeContacts = new ConcurrentHashMap<>();
|
||||||
managers = new ConcurrentHashMap<TransportId, TransportKeyManager>();
|
managers = new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startService() throws ServiceException {
|
public void startService() throws ServiceException {
|
||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
Map<TransportId, Integer> transports =
|
Map<TransportId, Integer> transports = new HashMap<>();
|
||||||
new HashMap<TransportId, Integer>();
|
|
||||||
for (SimplexPluginFactory f : pluginConfig.getSimplexFactories())
|
for (SimplexPluginFactory f : pluginConfig.getSimplexFactories())
|
||||||
transports.put(f.getId(), f.getMaxLatency());
|
transports.put(f.getId(), f.getMaxLatency());
|
||||||
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
|
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories())
|
||||||
@@ -156,14 +155,10 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeContact(final ContactId c) {
|
private void removeContact(ContactId c) {
|
||||||
activeContacts.remove(c);
|
activeContacts.remove(c);
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> {
|
||||||
@Override
|
for (TransportKeyManager m : managers.values()) m.removeContact(c);
|
||||||
public void run() {
|
|
||||||
for (TransportKeyManager m : managers.values())
|
|
||||||
m.removeContact(c);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class ReorderingWindow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Long> getUnseen() {
|
List<Long> getUnseen() {
|
||||||
List<Long> unseen = new ArrayList<Long>(seen.length);
|
List<Long> unseen = new ArrayList<>(seen.length);
|
||||||
for (int i = 0; i < seen.length; i++)
|
for (int i = 0; i < seen.length; i++)
|
||||||
if (!seen[i]) unseen.add(base + i);
|
if (!seen[i]) unseen.add(base + i);
|
||||||
return unseen;
|
return unseen;
|
||||||
@@ -69,8 +69,8 @@ class ReorderingWindow {
|
|||||||
return new Change(added, removed);
|
return new Change(added, removed);
|
||||||
}
|
}
|
||||||
// Record the elements that will be added and removed
|
// Record the elements that will be added and removed
|
||||||
List<Long> added = new ArrayList<Long>(slide);
|
List<Long> added = new ArrayList<>(slide);
|
||||||
List<Long> removed = new ArrayList<Long>(slide);
|
List<Long> removed = new ArrayList<>(slide);
|
||||||
for (int i = 0; i < slide; i++) {
|
for (int i = 0; i < slide; i++) {
|
||||||
if (!seen[i]) removed.add(base + i);
|
if (!seen[i]) removed.add(base + i);
|
||||||
added.add(base + seen.length + i);
|
added.add(base + seen.length + i);
|
||||||
|
|||||||
@@ -65,9 +65,9 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
this.transportId = transportId;
|
this.transportId = transportId;
|
||||||
rotationPeriodLength = maxLatency + MAX_CLOCK_DIFFERENCE;
|
rotationPeriodLength = maxLatency + MAX_CLOCK_DIFFERENCE;
|
||||||
lock = new ReentrantLock();
|
lock = new ReentrantLock();
|
||||||
inContexts = new HashMap<Bytes, TagContext>();
|
inContexts = new HashMap<>();
|
||||||
outContexts = new HashMap<ContactId, MutableOutgoingKeys>();
|
outContexts = new HashMap<>();
|
||||||
keys = new HashMap<ContactId, MutableTransportKeys>();
|
keys = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -134,32 +134,22 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleKeyRotation(long now) {
|
private void scheduleKeyRotation(long now) {
|
||||||
Runnable task = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
rotateKeys();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
long delay = rotationPeriodLength - now % rotationPeriodLength;
|
long delay = rotationPeriodLength - now % rotationPeriodLength;
|
||||||
scheduler.schedule(task, delay, MILLISECONDS);
|
scheduler.schedule((Runnable) this::rotateKeys, delay, MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rotateKeys() {
|
private void rotateKeys() {
|
||||||
dbExecutor.execute(new Runnable() {
|
dbExecutor.execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
Transaction txn = db.startTransaction(false);
|
rotateKeys(txn);
|
||||||
try {
|
db.commitTransaction(txn);
|
||||||
rotateKeys(txn);
|
} finally {
|
||||||
db.commitTransaction(txn);
|
db.endTransaction(txn);
|
||||||
} finally {
|
|
||||||
db.endTransaction(txn);
|
|
||||||
}
|
|
||||||
} catch (DbException e) {
|
|
||||||
if (LOG.isLoggable(WARNING))
|
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
}
|
}
|
||||||
|
} catch (DbException e) {
|
||||||
|
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -272,8 +262,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
lock.lock();
|
lock.lock();
|
||||||
try {
|
try {
|
||||||
// Rotate the keys to the current rotation period
|
// Rotate the keys to the current rotation period
|
||||||
Map<ContactId, TransportKeys> snapshot =
|
Map<ContactId, TransportKeys> snapshot = new HashMap<>();
|
||||||
new HashMap<ContactId, TransportKeys>();
|
|
||||||
for (Entry<ContactId, MutableTransportKeys> e : keys.entrySet())
|
for (Entry<ContactId, MutableTransportKeys> e : keys.entrySet())
|
||||||
snapshot.put(e.getKey(), e.getValue().snapshot());
|
snapshot.put(e.getKey(), e.getValue().snapshot());
|
||||||
RotationResult rotationResult = rotateKeys(snapshot, now);
|
RotationResult rotationResult = rotateKeys(snapshot, now);
|
||||||
@@ -311,8 +300,8 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
private final Map<ContactId, TransportKeys> current, rotated;
|
private final Map<ContactId, TransportKeys> current, rotated;
|
||||||
|
|
||||||
private RotationResult() {
|
private RotationResult() {
|
||||||
current = new HashMap<ContactId, TransportKeys>();
|
current = new HashMap<>();
|
||||||
rotated = new HashMap<ContactId, TransportKeys>();
|
rotated = new HashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,16 +24,13 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
|||||||
Executor delegate = Executors.newSingleThreadExecutor();
|
Executor delegate = Executors.newSingleThreadExecutor();
|
||||||
// Allow all the tasks to be delegated straight away
|
// Allow all the tasks to be delegated straight away
|
||||||
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
|
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
|
||||||
final List<Integer> list = new Vector<Integer>();
|
List<Integer> list = new Vector<>();
|
||||||
final CountDownLatch latch = new CountDownLatch(TASKS);
|
CountDownLatch latch = new CountDownLatch(TASKS);
|
||||||
for (int i = 0; i < TASKS; i++) {
|
for (int i = 0; i < TASKS; i++) {
|
||||||
final int result = i;
|
int result = i;
|
||||||
polite.execute(new Runnable() {
|
polite.execute(() -> {
|
||||||
@Override
|
list.add(result);
|
||||||
public void run() {
|
latch.countDown();
|
||||||
list.add(result);
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Wait for all the tasks to finish
|
// Wait for all the tasks to finish
|
||||||
@@ -49,16 +46,13 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
|||||||
Executor delegate = Executors.newSingleThreadExecutor();
|
Executor delegate = Executors.newSingleThreadExecutor();
|
||||||
// Allow two tasks to be delegated at a time
|
// Allow two tasks to be delegated at a time
|
||||||
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 2);
|
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 2);
|
||||||
final List<Integer> list = new Vector<Integer>();
|
List<Integer> list = new Vector<>();
|
||||||
final CountDownLatch latch = new CountDownLatch(TASKS);
|
CountDownLatch latch = new CountDownLatch(TASKS);
|
||||||
for (int i = 0; i < TASKS; i++) {
|
for (int i = 0; i < TASKS; i++) {
|
||||||
final int result = i;
|
int result = i;
|
||||||
polite.execute(new Runnable() {
|
polite.execute(() -> {
|
||||||
@Override
|
list.add(result);
|
||||||
public void run() {
|
latch.countDown();
|
||||||
list.add(result);
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Wait for all the tasks to finish
|
// Wait for all the tasks to finish
|
||||||
@@ -73,23 +67,20 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
|||||||
Executor delegate = Executors.newCachedThreadPool();
|
Executor delegate = Executors.newCachedThreadPool();
|
||||||
// Allow all the tasks to be delegated straight away
|
// Allow all the tasks to be delegated straight away
|
||||||
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
|
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, TASKS * 2);
|
||||||
final List<Integer> list = new Vector<Integer>();
|
List<Integer> list = new Vector<>();
|
||||||
final CountDownLatch[] latches = new CountDownLatch[TASKS];
|
CountDownLatch[] latches = new CountDownLatch[TASKS];
|
||||||
for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1);
|
for (int i = 0; i < TASKS; i++) latches[i] = new CountDownLatch(1);
|
||||||
for (int i = 0; i < TASKS; i++) {
|
for (int i = 0; i < TASKS; i++) {
|
||||||
final int result = i;
|
int result = i;
|
||||||
polite.execute(new Runnable() {
|
polite.execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Each task waits for the next task, if any, to finish
|
||||||
try {
|
if (result < TASKS - 1) latches[result + 1].await();
|
||||||
// Each task waits for the next task, if any, to finish
|
list.add(result);
|
||||||
if (result < TASKS - 1) latches[result + 1].await();
|
} catch (InterruptedException e) {
|
||||||
list.add(result);
|
fail();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
latches[result].countDown();
|
|
||||||
}
|
}
|
||||||
|
latches[result].countDown();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Wait for all the tasks to finish
|
// Wait for all the tasks to finish
|
||||||
@@ -104,22 +95,19 @@ public class PoliteExecutorTest extends BrambleTestCase {
|
|||||||
Executor delegate = Executors.newCachedThreadPool();
|
Executor delegate = Executors.newCachedThreadPool();
|
||||||
// Allow one task to be delegated at a time
|
// Allow one task to be delegated at a time
|
||||||
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 1);
|
PoliteExecutor polite = new PoliteExecutor(TAG, delegate, 1);
|
||||||
final List<Integer> list = new Vector<Integer>();
|
List<Integer> list = new Vector<>();
|
||||||
final CountDownLatch latch = new CountDownLatch(TASKS);
|
CountDownLatch latch = new CountDownLatch(TASKS);
|
||||||
for (int i = 0; i < TASKS; i++) {
|
for (int i = 0; i < TASKS; i++) {
|
||||||
final int result = i;
|
int result = i;
|
||||||
polite.execute(new Runnable() {
|
polite.execute(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Each task runs faster than the previous task
|
||||||
try {
|
Thread.sleep(TASKS - result);
|
||||||
// Each task runs faster than the previous task
|
list.add(result);
|
||||||
Thread.sleep(TASKS - result);
|
} catch (InterruptedException e) {
|
||||||
list.add(result);
|
fail();
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
|
||||||
latch.countDown();
|
|
||||||
}
|
}
|
||||||
|
latch.countDown();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Wait for all the tasks to finish
|
// Wait for all the tasks to finish
|
||||||
|
|||||||
@@ -83,9 +83,9 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
|
|
||||||
@Test(expected = InvalidMessageException.class)
|
@Test(expected = InvalidMessageException.class)
|
||||||
public void testRejectsTooShortMessage() throws Exception {
|
public void testRejectsTooShortMessage() throws Exception {
|
||||||
final byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH];
|
byte[] invalidRaw = new byte[MESSAGE_HEADER_LENGTH];
|
||||||
// Use a mock message so the length of the raw message can be invalid
|
// Use a mock message so the length of the raw message can be invalid
|
||||||
final Message invalidMessage = context.mock(Message.class);
|
Message invalidMessage = context.mock(Message.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(invalidMessage).getTimestamp();
|
oneOf(invalidMessage).getTimestamp();
|
||||||
@@ -101,8 +101,8 @@ public class BdfMessageValidatorTest extends ValidatorTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAcceptsMinLengthMessage() throws Exception {
|
public void testAcceptsMinLengthMessage() throws Exception {
|
||||||
final byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1];
|
byte[] shortRaw = new byte[MESSAGE_HEADER_LENGTH + 1];
|
||||||
final Message shortMessage =
|
Message shortMessage =
|
||||||
new Message(messageId, groupId, timestamp, shortRaw);
|
new Message(messageId, groupId, timestamp, shortRaw);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.briarproject.bramble.api.sync.Message;
|
|||||||
import org.briarproject.bramble.api.sync.MessageFactory;
|
import org.briarproject.bramble.api.sync.MessageFactory;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -65,7 +65,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
new Message(messageId, groupId, timestamp, rawMessage);
|
new Message(messageId, groupId, timestamp, rawMessage);
|
||||||
private final Metadata metadata = new Metadata();
|
private final Metadata metadata = new Metadata();
|
||||||
private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
|
private final BdfList list = BdfList.of("Sign this!", getRandomBytes(42));
|
||||||
private final String label = TestUtils.getRandomString(5);
|
private final String label = StringUtils.getRandomString(5);
|
||||||
|
|
||||||
public ClientHelperImplTest() {
|
public ClientHelperImplTest() {
|
||||||
clientHelper =
|
clientHelper =
|
||||||
@@ -76,8 +76,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddLocalMessage() throws Exception {
|
public void testAddLocalMessage() throws Exception {
|
||||||
final boolean shared = true;
|
boolean shared = true;
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(false);
|
oneOf(db).startTransaction(false);
|
||||||
@@ -95,7 +95,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateMessage() throws Exception {
|
public void testCreateMessage() throws Exception {
|
||||||
final byte[] bytes = expectToByteArray(list);
|
byte[] bytes = expectToByteArray(list);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(messageFactory).createMessage(groupId, timestamp, bytes);
|
oneOf(messageFactory).createMessage(groupId, timestamp, bytes);
|
||||||
@@ -107,7 +107,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessageAsList() throws Exception {
|
public void testGetMessageAsList() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
expectToList(true);
|
expectToList(true);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
@@ -125,7 +125,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetGroupMetadataAsDictionary() throws Exception {
|
public void testGetGroupMetadataAsDictionary() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
@@ -145,7 +145,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessageMetadataAsDictionary() throws Exception {
|
public void testGetMessageMetadataAsDictionary() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
@@ -165,10 +165,9 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessageMetadataAsDictionaryMap() throws Exception {
|
public void testGetMessageMetadataAsDictionaryMap() throws Exception {
|
||||||
final Map<MessageId, BdfDictionary> map =
|
Map<MessageId, BdfDictionary> map = new HashMap<>();
|
||||||
new HashMap<MessageId, BdfDictionary>();
|
|
||||||
map.put(messageId, dictionary);
|
map.put(messageId, dictionary);
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
@@ -188,14 +187,13 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetMessageMetadataAsDictionaryQuery() throws Exception {
|
public void testGetMessageMetadataAsDictionaryQuery() throws Exception {
|
||||||
final Map<MessageId, BdfDictionary> map =
|
Map<MessageId, BdfDictionary> map = new HashMap<>();
|
||||||
new HashMap<MessageId, BdfDictionary>();
|
|
||||||
map.put(messageId, dictionary);
|
map.put(messageId, dictionary);
|
||||||
final BdfDictionary query =
|
BdfDictionary query =
|
||||||
BdfDictionary.of(new BdfEntry("query", "me"));
|
BdfDictionary.of(new BdfEntry("query", "me"));
|
||||||
final Metadata queryMetadata = new Metadata();
|
Metadata queryMetadata = new Metadata();
|
||||||
queryMetadata.put("query", getRandomBytes(42));
|
queryMetadata.put("query", getRandomBytes(42));
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
@@ -217,7 +215,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMergeGroupMetadata() throws Exception {
|
public void testMergeGroupMetadata() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(false);
|
oneOf(db).startTransaction(false);
|
||||||
@@ -235,7 +233,7 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMergeMessageMetadata() throws Exception {
|
public void testMergeMessageMetadata() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(false);
|
oneOf(db).startTransaction(false);
|
||||||
@@ -282,10 +280,10 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSign() throws Exception {
|
public void testSign() throws Exception {
|
||||||
final byte[] privateKey = getRandomBytes(42);
|
byte[] privateKey = getRandomBytes(42);
|
||||||
final byte[] signed = getRandomBytes(42);
|
byte[] signed = getRandomBytes(42);
|
||||||
|
|
||||||
final byte[] bytes = expectToByteArray(list);
|
byte[] bytes = expectToByteArray(list);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).sign(label, bytes, privateKey);
|
oneOf(cryptoComponent).sign(label, bytes, privateKey);
|
||||||
will(returnValue(signed));
|
will(returnValue(signed));
|
||||||
@@ -297,8 +295,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVerifySignature() throws Exception {
|
public void testVerifySignature() throws Exception {
|
||||||
final byte[] publicKey = getRandomBytes(42);
|
byte[] publicKey = getRandomBytes(42);
|
||||||
final byte[] bytes = expectToByteArray(list);
|
byte[] bytes = expectToByteArray(list);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
|
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
|
||||||
@@ -311,8 +309,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVerifyWrongSignature() throws Exception {
|
public void testVerifyWrongSignature() throws Exception {
|
||||||
final byte[] publicKey = getRandomBytes(42);
|
byte[] publicKey = getRandomBytes(42);
|
||||||
final byte[] bytes = expectToByteArray(list);
|
byte[] bytes = expectToByteArray(list);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
|
oneOf(cryptoComponent).verify(label, bytes, publicKey, rawMessage);
|
||||||
@@ -329,8 +327,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] expectToByteArray(final BdfList list) throws Exception {
|
private byte[] expectToByteArray(BdfList list) throws Exception {
|
||||||
final BdfWriter bdfWriter = context.mock(BdfWriter.class);
|
BdfWriter bdfWriter = context.mock(BdfWriter.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfWriterFactory)
|
oneOf(bdfWriterFactory)
|
||||||
@@ -341,8 +339,8 @@ public class ClientHelperImplTest extends BrambleTestCase {
|
|||||||
return new byte[0];
|
return new byte[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void expectToList(final boolean eof) throws Exception {
|
private void expectToList(boolean eof) throws Exception {
|
||||||
final BdfReader bdfReader = context.mock(BdfReader.class);
|
BdfReader bdfReader = context.mock(BdfReader.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(bdfReaderFactory)
|
oneOf(bdfReaderFactory)
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddContact() throws Exception {
|
public void testAddContact() throws Exception {
|
||||||
final SecretKey master = getSecretKey();
|
SecretKey master = getSecretKey();
|
||||||
final long timestamp = 42;
|
long timestamp = 42;
|
||||||
final boolean alice = true;
|
boolean alice = true;
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(false);
|
oneOf(db).startTransaction(false);
|
||||||
@@ -64,14 +64,13 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
oneOf(db).endTransaction(txn);
|
oneOf(db).endTransaction(txn);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
assertEquals(contactId, contactManager
|
assertEquals(contactId, contactManager.addContact(remote, local,
|
||||||
.addContact(remote, local, master, timestamp, alice, verified,
|
master, timestamp, alice, verified, active));
|
||||||
active));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetContact() throws Exception {
|
public void testGetContact() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -86,8 +85,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetContactByAuthor() throws Exception {
|
public void testGetContactByAuthor() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Collection<Contact> contacts = Collections.singleton(contact);
|
Collection<Contact> contacts = Collections.singleton(contact);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -102,7 +101,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test(expected = NoSuchContactException.class)
|
@Test(expected = NoSuchContactException.class)
|
||||||
public void testGetContactByUnknownAuthor() throws Exception {
|
public void testGetContactByUnknownAuthor() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -116,8 +115,8 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test(expected = NoSuchContactException.class)
|
@Test(expected = NoSuchContactException.class)
|
||||||
public void testGetContactByUnknownLocalAuthor() throws Exception {
|
public void testGetContactByUnknownLocalAuthor() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Collection<Contact> contacts = Collections.singleton(contact);
|
Collection<Contact> contacts = Collections.singleton(contact);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -132,10 +131,9 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testActiveContacts() throws Exception {
|
public void testActiveContacts() throws Exception {
|
||||||
Collection<Contact> activeContacts = Collections.singletonList(contact);
|
Collection<Contact> activeContacts = Collections.singletonList(contact);
|
||||||
final Collection<Contact> contacts =
|
Collection<Contact> contacts = new ArrayList<>(activeContacts);
|
||||||
new ArrayList<Contact>(activeContacts);
|
|
||||||
contacts.add(new Contact(new ContactId(3), remote, local, true, false));
|
contacts.add(new Contact(new ContactId(3), remote, local, true, false));
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -150,7 +148,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveContact() throws Exception {
|
public void testRemoveContact() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(false);
|
oneOf(db).startTransaction(false);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -166,7 +164,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSetContactActive() throws Exception {
|
public void testSetContactActive() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).setContactActive(txn, contactId, active);
|
oneOf(db).setContactActive(txn, contactId, active);
|
||||||
}});
|
}});
|
||||||
@@ -176,7 +174,7 @@ public class ContactManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testContactExists() throws Exception {
|
public void testContactExists() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class EllipticCurvePerformanceTest {
|
|||||||
ECPublicKeyParameters public2 =
|
ECPublicKeyParameters public2 =
|
||||||
(ECPublicKeyParameters) keyPair2.getPublic();
|
(ECPublicKeyParameters) keyPair2.getPublic();
|
||||||
// Time some ECDH key agreements
|
// Time some ECDH key agreements
|
||||||
List<Long> samples = new ArrayList<Long>();
|
List<Long> samples = new ArrayList<>();
|
||||||
for (int i = 0; i < SAMPLES; i++) {
|
for (int i = 0; i < SAMPLES; i++) {
|
||||||
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
|
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
|
||||||
long start = System.nanoTime();
|
long start = System.nanoTime();
|
||||||
@@ -79,7 +79,7 @@ public class EllipticCurvePerformanceTest {
|
|||||||
}
|
}
|
||||||
long agreementMedian = median(samples);
|
long agreementMedian = median(samples);
|
||||||
// Time some signatures
|
// Time some signatures
|
||||||
List<byte[]> signatures = new ArrayList<byte[]>();
|
List<byte[]> signatures = new ArrayList<>();
|
||||||
samples.clear();
|
samples.clear();
|
||||||
for (int i = 0; i < SAMPLES; i++) {
|
for (int i = 0; i < SAMPLES; i++) {
|
||||||
Digest digest = new Blake2sDigest();
|
Digest digest = new Blake2sDigest();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
|
|||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestSecureRandomProvider;
|
import org.briarproject.bramble.test.TestSecureRandomProvider;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -15,7 +16,7 @@ public class HashTest extends BrambleTestCase {
|
|||||||
|
|
||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
|
|
||||||
private final String label = TestUtils.getRandomString(42);
|
private final String label = StringUtils.getRandomString(42);
|
||||||
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
||||||
private final byte[] inputBytes1 = TestUtils.getRandomBytes(234);
|
private final byte[] inputBytes1 = TestUtils.getRandomBytes(234);
|
||||||
private final byte[] inputBytes2 = new byte[0];
|
private final byte[] inputBytes2 = new byte[0];
|
||||||
@@ -40,7 +41,7 @@ public class HashTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDifferentLabelsProduceDifferentHashes() {
|
public void testDifferentLabelsProduceDifferentHashes() {
|
||||||
String label2 = TestUtils.getRandomString(42);
|
String label2 = StringUtils.getRandomString(42);
|
||||||
byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
|
byte[] hash1 = crypto.hash(label, inputBytes, inputBytes1, inputBytes2);
|
||||||
byte[] hash2 =
|
byte[] hash2 =
|
||||||
crypto.hash(label2, inputBytes, inputBytes1, inputBytes2);
|
crypto.hash(label2, inputBytes, inputBytes1, inputBytes2);
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ public class KeyDerivationTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertAllDifferent(TransportKeys... transportKeys) {
|
private void assertAllDifferent(TransportKeys... transportKeys) {
|
||||||
List<SecretKey> secretKeys = new ArrayList<SecretKey>();
|
List<SecretKey> secretKeys = new ArrayList<>();
|
||||||
for (TransportKeys k : transportKeys) {
|
for (TransportKeys k : transportKeys) {
|
||||||
secretKeys.add(k.getPreviousIncomingKeys().getTagKey());
|
secretKeys.add(k.getPreviousIncomingKeys().getTagKey());
|
||||||
secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey());
|
secretKeys.add(k.getPreviousIncomingKeys().getHeaderKey());
|
||||||
@@ -160,7 +160,7 @@ public class KeyDerivationTest extends BrambleTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertAllDifferent(List<SecretKey> keys) {
|
private void assertAllDifferent(List<SecretKey> keys) {
|
||||||
Set<Bytes> set = new HashSet<Bytes>();
|
Set<Bytes> set = new HashSet<>();
|
||||||
for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes())));
|
for (SecretKey k : keys) assertTrue(set.add(new Bytes(k.getBytes())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.crypto.KeyPair;
|
|||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestSecureRandomProvider;
|
import org.briarproject.bramble.test.TestSecureRandomProvider;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -18,7 +19,7 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
private final CryptoComponent crypto;
|
private final CryptoComponent crypto;
|
||||||
|
|
||||||
private final byte[] publicKey, privateKey;
|
private final byte[] publicKey, privateKey;
|
||||||
private final String label = TestUtils.getRandomString(42);
|
private final String label = StringUtils.getRandomString(42);
|
||||||
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
private final byte[] inputBytes = TestUtils.getRandomBytes(123);
|
||||||
|
|
||||||
public SignatureTest() {
|
public SignatureTest() {
|
||||||
@@ -64,7 +65,7 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
public void testDifferentLabelsProduceDifferentSignatures()
|
public void testDifferentLabelsProduceDifferentSignatures()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
// Generate a second label
|
// Generate a second label
|
||||||
String label2 = TestUtils.getRandomString(42);
|
String label2 = StringUtils.getRandomString(42);
|
||||||
// Calculate the signature with different inputs
|
// Calculate the signature with different inputs
|
||||||
// the results should be different
|
// the results should be different
|
||||||
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig1 = crypto.sign(label, inputBytes, privateKey);
|
||||||
@@ -100,7 +101,7 @@ public class SignatureTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testDifferentLabelFailsVerification() throws Exception {
|
public void testDifferentLabelFailsVerification() throws Exception {
|
||||||
// Generate a second label
|
// Generate a second label
|
||||||
String label2 = TestUtils.getRandomString(42);
|
String label2 = StringUtils.getRandomString(42);
|
||||||
// calculate the signature with different label, should fail to verify
|
// calculate the signature with different label, should fail to verify
|
||||||
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
byte[] sig = crypto.sign(label, inputBytes, privateKey);
|
||||||
assertFalse(crypto.verify(label2, inputBytes, publicKey, sig));
|
assertFalse(crypto.verify(label2, inputBytes, publicKey, sig));
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class TagEncodingTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testKeyAffectsTag() throws Exception {
|
public void testKeyAffectsTag() throws Exception {
|
||||||
Set<Bytes> set = new HashSet<Bytes>();
|
Set<Bytes> set = new HashSet<>();
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
SecretKey tagKey = TestUtils.getSecretKey();
|
SecretKey tagKey = TestUtils.getSecretKey();
|
||||||
@@ -39,7 +39,7 @@ public class TagEncodingTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProtocolVersionAffectsTag() throws Exception {
|
public void testProtocolVersionAffectsTag() throws Exception {
|
||||||
Set<Bytes> set = new HashSet<Bytes>();
|
Set<Bytes> set = new HashSet<>();
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber);
|
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION + i, streamNumber);
|
||||||
@@ -49,7 +49,7 @@ public class TagEncodingTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStreamNumberAffectsTag() throws Exception {
|
public void testStreamNumberAffectsTag() throws Exception {
|
||||||
Set<Bytes> set = new HashSet<Bytes>();
|
Set<Bytes> set = new HashSet<>();
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
byte[] tag = new byte[TAG_LENGTH];
|
byte[] tag = new byte[TAG_LENGTH];
|
||||||
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i);
|
crypto.encodeTag(tag, tagKey, PROTOCOL_VERSION, streamNumber + i);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.FormatException;
|
|||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
import org.briarproject.bramble.api.data.BdfList;
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -159,7 +158,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadString8() throws Exception {
|
public void testReadString8() throws Exception {
|
||||||
String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
|
String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
|
||||||
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
||||||
// "foo", the empty string, and 127 random letters
|
// "foo", the empty string, and 127 random letters
|
||||||
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
||||||
@@ -181,7 +180,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSkipString8() throws Exception {
|
public void testSkipString8() throws Exception {
|
||||||
String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
|
String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
|
||||||
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
||||||
// "foo", the empty string, and 127 random letters
|
// "foo", the empty string, and 127 random letters
|
||||||
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
setContents("41" + "03" + "666F6F" + "41" + "00" +
|
||||||
@@ -194,9 +193,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadString16() throws Exception {
|
public void testReadString16() throws Exception {
|
||||||
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
String longest = TestUtils.getRandomString(Short.MAX_VALUE);
|
String longest = StringUtils.getRandomString(Short.MAX_VALUE);
|
||||||
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
||||||
// 128 random letters and 2^15 -1 random letters
|
// 128 random letters and 2^15 -1 random letters
|
||||||
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
||||||
@@ -207,7 +206,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testReadString16ChecksMaxLength() throws Exception {
|
public void testReadString16ChecksMaxLength() throws Exception {
|
||||||
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
// 128 random letters, twice
|
// 128 random letters, twice
|
||||||
setContents("42" + "0080" + shortHex + "42" + "0080" + shortHex);
|
setContents("42" + "0080" + shortHex + "42" + "0080" + shortHex);
|
||||||
@@ -218,9 +217,9 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSkipString16() throws Exception {
|
public void testSkipString16() throws Exception {
|
||||||
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
String longest = TestUtils.getRandomString(Short.MAX_VALUE);
|
String longest = StringUtils.getRandomString(Short.MAX_VALUE);
|
||||||
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
||||||
// 128 random letters and 2^15 - 1 random letters
|
// 128 random letters and 2^15 - 1 random letters
|
||||||
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
setContents("42" + "0080" + shortHex + "42" + "7FFF" + longHex);
|
||||||
@@ -231,7 +230,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReadString32() throws Exception {
|
public void testReadString32() throws Exception {
|
||||||
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
// 2^15 random letters
|
// 2^15 random letters
|
||||||
setContents("44" + "00008000" + shortHex);
|
setContents("44" + "00008000" + shortHex);
|
||||||
@@ -241,7 +240,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test(expected = FormatException.class)
|
@Test(expected = FormatException.class)
|
||||||
public void testReadString32ChecksMaxLength() throws Exception {
|
public void testReadString32ChecksMaxLength() throws Exception {
|
||||||
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
// 2^15 random letters, twice
|
// 2^15 random letters, twice
|
||||||
setContents("44" + "00008000" + shortHex +
|
setContents("44" + "00008000" + shortHex +
|
||||||
@@ -253,7 +252,7 @@ public class BdfReaderImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSkipString32() throws Exception {
|
public void testSkipString32() throws Exception {
|
||||||
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
// 2^15 random letters, twice
|
// 2^15 random letters, twice
|
||||||
setContents("44" + "00008000" + shortHex +
|
setContents("44" + "00008000" + shortHex +
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.briarproject.bramble.data;
|
package org.briarproject.bramble.data;
|
||||||
|
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -81,7 +80,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteString8() throws IOException {
|
public void testWriteString8() throws IOException {
|
||||||
String longest = TestUtils.getRandomString(Byte.MAX_VALUE);
|
String longest = StringUtils.getRandomString(Byte.MAX_VALUE);
|
||||||
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
||||||
w.writeString("foo bar baz bam ");
|
w.writeString("foo bar baz bam ");
|
||||||
w.writeString(longest);
|
w.writeString(longest);
|
||||||
@@ -93,9 +92,9 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteString16() throws IOException {
|
public void testWriteString16() throws IOException {
|
||||||
String shortest = TestUtils.getRandomString(Byte.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Byte.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
String longest = TestUtils.getRandomString(Short.MAX_VALUE);
|
String longest = StringUtils.getRandomString(Short.MAX_VALUE);
|
||||||
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
String longHex = StringUtils.toHexString(longest.getBytes("UTF-8"));
|
||||||
w.writeString(shortest);
|
w.writeString(shortest);
|
||||||
w.writeString(longest);
|
w.writeString(longest);
|
||||||
@@ -106,7 +105,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteString32() throws IOException {
|
public void testWriteString32() throws IOException {
|
||||||
String shortest = TestUtils.getRandomString(Short.MAX_VALUE + 1);
|
String shortest = StringUtils.getRandomString(Short.MAX_VALUE + 1);
|
||||||
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
String shortHex = StringUtils.toHexString(shortest.getBytes("UTF-8"));
|
||||||
w.writeString(shortest);
|
w.writeString(shortest);
|
||||||
// STRING_32 tag, length 2^15, UTF-8 bytes
|
// STRING_32 tag, length 2^15, UTF-8 bytes
|
||||||
@@ -155,7 +154,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteList() throws IOException {
|
public void testWriteList() throws IOException {
|
||||||
List<Object> l = new ArrayList<Object>();
|
List<Object> l = new ArrayList<>();
|
||||||
for (int i = 0; i < 3; i++) l.add(i);
|
for (int i = 0; i < 3; i++) l.add(i);
|
||||||
w.writeList(l);
|
w.writeList(l);
|
||||||
// LIST tag, elements as integers, END tag
|
// LIST tag, elements as integers, END tag
|
||||||
@@ -164,7 +163,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testListCanContainNull() throws IOException {
|
public void testListCanContainNull() throws IOException {
|
||||||
List<Object> l = new ArrayList<Object>();
|
List<Object> l = new ArrayList<>();
|
||||||
l.add(1);
|
l.add(1);
|
||||||
l.add(null);
|
l.add(null);
|
||||||
l.add(NULL_VALUE);
|
l.add(NULL_VALUE);
|
||||||
@@ -177,7 +176,7 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWriteDictionary() throws IOException {
|
public void testWriteDictionary() throws IOException {
|
||||||
// Use LinkedHashMap to get predictable iteration order
|
// Use LinkedHashMap to get predictable iteration order
|
||||||
Map<String, Object> m = new LinkedHashMap<String, Object>();
|
Map<String, Object> m = new LinkedHashMap<>();
|
||||||
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
|
for (int i = 0; i < 4; i++) m.put(String.valueOf(i), i);
|
||||||
w.writeDictionary(m);
|
w.writeDictionary(m);
|
||||||
// DICTIONARY tag, keys as strings and values as integers, END tag
|
// DICTIONARY tag, keys as strings and values as integers, END tag
|
||||||
@@ -216,12 +215,12 @@ public class BdfWriterImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testWriteNestedDictionariesAndLists() throws IOException {
|
public void testWriteNestedDictionariesAndLists() throws IOException {
|
||||||
Map<String, Object> inner = new LinkedHashMap<String, Object>();
|
Map<String, Object> inner = new LinkedHashMap<>();
|
||||||
inner.put("bar", new byte[0]);
|
inner.put("bar", new byte[0]);
|
||||||
List<Object> list = new ArrayList<Object>();
|
List<Object> list = new ArrayList<>();
|
||||||
list.add(1);
|
list.add(1);
|
||||||
list.add(inner);
|
list.add(inner);
|
||||||
Map<String, Object> outer = new LinkedHashMap<String, Object>();
|
Map<String, Object> outer = new LinkedHashMap<>();
|
||||||
outer.put("foo", list);
|
outer.put("foo", list);
|
||||||
w.writeDictionary(outer);
|
w.writeDictionary(outer);
|
||||||
// DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,
|
// DICTIONARY tag, "foo" as string, LIST tag, 1 as integer,
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testList() throws FormatException {
|
public void testList() throws FormatException {
|
||||||
List<Long> l = new ArrayList<Long>(4);
|
List<Long> l = new ArrayList<>(4);
|
||||||
l.add(42L);
|
l.add(42L);
|
||||||
l.add(1337L);
|
l.add(1337L);
|
||||||
l.add(Long.MIN_VALUE);
|
l.add(Long.MIN_VALUE);
|
||||||
@@ -114,7 +114,7 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDictionary() throws FormatException {
|
public void testDictionary() throws FormatException {
|
||||||
Map<String, Boolean> m = new HashMap<String, Boolean>();
|
Map<String, Boolean> m = new HashMap<>();
|
||||||
m.put("1", true);
|
m.put("1", true);
|
||||||
m.put("2", false);
|
m.put("2", false);
|
||||||
|
|
||||||
@@ -130,19 +130,19 @@ public class MetadataEncoderParserIntegrationTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComplexDictionary() throws FormatException {
|
public void testComplexDictionary() throws FormatException {
|
||||||
Map<String, List> m = new HashMap<String, List>();
|
Map<String, List> m = new HashMap<>();
|
||||||
List<String> one = new ArrayList<String>(3);
|
List<String> one = new ArrayList<>(3);
|
||||||
one.add("\uFDD0");
|
one.add("\uFDD0");
|
||||||
one.add("\uFDD1");
|
one.add("\uFDD1");
|
||||||
one.add("\uFDD2");
|
one.add("\uFDD2");
|
||||||
m.put("One", one);
|
m.put("One", one);
|
||||||
List<String> two = new ArrayList<String>(2);
|
List<String> two = new ArrayList<>(2);
|
||||||
two.add("\u0080");
|
two.add("\u0080");
|
||||||
two.add("\uD800\uDC00");
|
two.add("\uD800\uDC00");
|
||||||
m.put("Two", two);
|
m.put("Two", two);
|
||||||
d.put("test", m);
|
d.put("test", m);
|
||||||
|
|
||||||
Map<String, Boolean> m2 = new HashMap<String, Boolean>();
|
Map<String, Boolean> m2 = new HashMap<>();
|
||||||
m2.put("should be true", true);
|
m2.put("should be true", true);
|
||||||
d.put("another test", m2);
|
d.put("another test", m2);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -48,8 +49,8 @@ public class BasicH2Test extends BrambleTestCase {
|
|||||||
createTable(connection);
|
createTable(connection);
|
||||||
// Generate an ID and two names
|
// Generate an ID and two names
|
||||||
byte[] id = TestUtils.getRandomId();
|
byte[] id = TestUtils.getRandomId();
|
||||||
String oldName = TestUtils.getRandomString(50);
|
String oldName = StringUtils.getRandomString(50);
|
||||||
String newName = TestUtils.getRandomString(50);
|
String newName = StringUtils.getRandomString(50);
|
||||||
// Insert the ID and old name into the table
|
// Insert the ID and old name into the table
|
||||||
insertRow(id, oldName);
|
insertRow(id, oldName);
|
||||||
// Check that the old name can be retrieved using the ID
|
// Check that the old name can be retrieved using the ID
|
||||||
@@ -78,8 +79,8 @@ public class BasicH2Test extends BrambleTestCase {
|
|||||||
String[] newNames = new String[BATCH_SIZE];
|
String[] newNames = new String[BATCH_SIZE];
|
||||||
for (int i = 0; i < BATCH_SIZE; i++) {
|
for (int i = 0; i < BATCH_SIZE; i++) {
|
||||||
ids[i] = TestUtils.getRandomId();
|
ids[i] = TestUtils.getRandomId();
|
||||||
oldNames[i] = TestUtils.getRandomString(50);
|
oldNames[i] = StringUtils.getRandomString(50);
|
||||||
newNames[i] = TestUtils.getRandomString(50);
|
newNames[i] = StringUtils.getRandomString(50);
|
||||||
}
|
}
|
||||||
// Insert the IDs and old names into the table as a batch
|
// Insert the IDs and old names into the table as a batch
|
||||||
insertBatch(ids, oldNames);
|
insertBatch(ids, oldNames);
|
||||||
@@ -322,7 +323,7 @@ public class BasicH2Test extends BrambleTestCase {
|
|||||||
|
|
||||||
private List<String> getNames() throws SQLException {
|
private List<String> getNames() throws SQLException {
|
||||||
String sql = "SELECT name FROM foo ORDER BY uniqueId";
|
String sql = "SELECT name FROM foo ORDER BY uniqueId";
|
||||||
List<String> names = new ArrayList<String>();
|
List<String> names = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.prepareStatement(sql);
|
PreparedStatement ps = connection.prepareStatement(sql);
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
|
|||||||
import org.briarproject.bramble.api.transport.IncomingKeys;
|
import org.briarproject.bramble.api.transport.IncomingKeys;
|
||||||
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
import org.briarproject.bramble.api.transport.OutgoingKeys;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -73,7 +73,13 @@ import static org.junit.Assert.assertFalse;
|
|||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public class DatabaseComponentImplTest extends BrambleTestCase {
|
public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private final Database<Object> database = context.mock(Database.class);
|
||||||
|
private final ShutdownManager shutdown =
|
||||||
|
context.mock(ShutdownManager.class);
|
||||||
|
private final EventBus eventBus = context.mock(EventBus.class);
|
||||||
|
|
||||||
private final Object txn = new Object();
|
private final Object txn = new Object();
|
||||||
private final ClientId clientId;
|
private final ClientId clientId;
|
||||||
@@ -94,7 +100,7 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
private final Contact contact;
|
private final Contact contact;
|
||||||
|
|
||||||
public DatabaseComponentImplTest() {
|
public DatabaseComponentImplTest() {
|
||||||
clientId = new ClientId(TestUtils.getRandomString(5));
|
clientId = new ClientId(StringUtils.getRandomString(5));
|
||||||
groupId = new GroupId(TestUtils.getRandomId());
|
groupId = new GroupId(TestUtils.getRandomId());
|
||||||
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
||||||
group = new Group(groupId, clientId, descriptor);
|
group = new Group(groupId, clientId, descriptor);
|
||||||
@@ -119,18 +125,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
private DatabaseComponent createDatabaseComponent(Database<Object> database,
|
private DatabaseComponent createDatabaseComponent(Database<Object> database,
|
||||||
EventBus eventBus, ShutdownManager shutdown) {
|
EventBus eventBus, ShutdownManager shutdown) {
|
||||||
return new DatabaseComponentImpl<Object>(database, Object.class,
|
return new DatabaseComponentImpl<>(database, Object.class, eventBus,
|
||||||
eventBus, shutdown);
|
shutdown);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void testSimpleCalls() throws Exception {
|
public void testSimpleCalls() throws Exception {
|
||||||
final int shutdownHandle = 12345;
|
int shutdownHandle = 12345;
|
||||||
Mockery context = new Mockery();
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// open()
|
// open()
|
||||||
oneOf(database).open();
|
oneOf(database).open();
|
||||||
@@ -193,7 +194,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
// endTransaction()
|
// endTransaction()
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
// close()
|
// close()
|
||||||
oneOf(shutdown).removeShutdownHook(shutdownHandle);
|
|
||||||
oneOf(database).close();
|
oneOf(database).close();
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
@@ -220,18 +220,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
db.close();
|
db.close();
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocalMessagesAreNotStoredUnlessGroupExists()
|
public void testLocalMessagesAreNotStoredUnlessGroupExists()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -251,17 +244,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddLocalMessage() throws Exception {
|
public void testAddLocalMessage() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -293,18 +279,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVariousMethodsThrowExceptionIfContactIsMissing()
|
public void testVariousMethodsThrowExceptionIfContactIsMissing()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the contact is in the DB (which it's not)
|
// Check whether the contact is in the DB (which it's not)
|
||||||
exactly(18).of(database).startTransaction();
|
exactly(18).of(database).startTransaction();
|
||||||
@@ -499,18 +478,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVariousMethodsThrowExceptionIfLocalAuthorIsMissing()
|
public void testVariousMethodsThrowExceptionIfLocalAuthorIsMissing()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the pseudonym is in the DB (which it's not)
|
// Check whether the pseudonym is in the DB (which it's not)
|
||||||
exactly(3).of(database).startTransaction();
|
exactly(3).of(database).startTransaction();
|
||||||
@@ -551,18 +523,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVariousMethodsThrowExceptionIfGroupIsMissing()
|
public void testVariousMethodsThrowExceptionIfGroupIsMissing()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the group is in the DB (which it's not)
|
// Check whether the group is in the DB (which it's not)
|
||||||
exactly(8).of(database).startTransaction();
|
exactly(8).of(database).startTransaction();
|
||||||
@@ -656,18 +621,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVariousMethodsThrowExceptionIfMessageIsMissing()
|
public void testVariousMethodsThrowExceptionIfMessageIsMissing()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Check whether the message is in the DB (which it's not)
|
// Check whether the message is in the DB (which it's not)
|
||||||
exactly(11).of(database).startTransaction();
|
exactly(11).of(database).startTransaction();
|
||||||
@@ -791,18 +749,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testVariousMethodsThrowExceptionIfTransportIsMissing()
|
public void testVariousMethodsThrowExceptionIfTransportIsMissing()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// startTransaction()
|
// startTransaction()
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
@@ -889,19 +840,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateAck() throws Exception {
|
public void testGenerateAck() throws Exception {
|
||||||
final Collection<MessageId> messagesToAck = Arrays.asList(messageId,
|
Collection<MessageId> messagesToAck = Arrays.asList(messageId,
|
||||||
messageId1);
|
messageId1);
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -924,20 +868,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateBatch() throws Exception {
|
public void testGenerateBatch() throws Exception {
|
||||||
final byte[] raw1 = new byte[size];
|
byte[] raw1 = new byte[size];
|
||||||
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
||||||
final Collection<byte[]> messages = Arrays.asList(raw, raw1);
|
Collection<byte[]> messages = Arrays.asList(raw, raw1);
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -968,19 +905,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateOffer() throws Exception {
|
public void testGenerateOffer() throws Exception {
|
||||||
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1006,19 +936,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateRequest() throws Exception {
|
public void testGenerateRequest() throws Exception {
|
||||||
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1041,20 +964,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGenerateRequestedBatch() throws Exception {
|
public void testGenerateRequestedBatch() throws Exception {
|
||||||
final byte[] raw1 = new byte[size];
|
byte[] raw1 = new byte[size];
|
||||||
final Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
Collection<MessageId> ids = Arrays.asList(messageId, messageId1);
|
||||||
final Collection<byte[]> messages = Arrays.asList(raw, raw1);
|
Collection<byte[]> messages = Arrays.asList(raw, raw1);
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1086,17 +1002,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveAck() throws Exception {
|
public void testReceiveAck() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1119,17 +1028,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveMessage() throws Exception {
|
public void testReceiveMessage() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1174,17 +1076,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveDuplicateMessage() throws Exception {
|
public void testReceiveDuplicateMessage() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1211,17 +1106,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveMessageWithoutVisibleGroup() throws Exception {
|
public void testReceiveMessageWithoutVisibleGroup() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1241,20 +1129,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveOffer() throws Exception {
|
public void testReceiveOffer() throws Exception {
|
||||||
final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
||||||
final MessageId messageId3 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId3 = new MessageId(TestUtils.getRandomId());
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1295,17 +1176,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReceiveRequest() throws Exception {
|
public void testReceiveRequest() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1329,17 +1203,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChangingVisibilityCallsListeners() throws Exception {
|
public void testChangingVisibilityCallsListeners() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1369,18 +1236,11 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotChangingVisibilityDoesNotCallListeners()
|
public void testNotChangingVisibilityDoesNotCallListeners()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1402,20 +1262,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransportKeys() throws Exception {
|
public void testTransportKeys() throws Exception {
|
||||||
final TransportKeys transportKeys = createTransportKeys();
|
TransportKeys transportKeys = createTransportKeys();
|
||||||
final Map<ContactId, TransportKeys> keys = Collections.singletonMap(
|
Map<ContactId, TransportKeys> keys = Collections.singletonMap(
|
||||||
contactId, transportKeys);
|
contactId, transportKeys);
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// startTransaction()
|
// startTransaction()
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
@@ -1445,8 +1298,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransportKeys createTransportKeys() {
|
private TransportKeys createTransportKeys() {
|
||||||
@@ -1471,19 +1322,14 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMergeSettings() throws Exception {
|
public void testMergeSettings() throws Exception {
|
||||||
final Settings before = new Settings();
|
Settings before = new Settings();
|
||||||
before.put("foo", "bar");
|
before.put("foo", "bar");
|
||||||
before.put("baz", "bam");
|
before.put("baz", "bam");
|
||||||
final Settings update = new Settings();
|
Settings update = new Settings();
|
||||||
update.put("baz", "qux");
|
update.put("baz", "qux");
|
||||||
final Settings merged = new Settings();
|
Settings merged = new Settings();
|
||||||
merged.put("foo", "bar");
|
merged.put("foo", "bar");
|
||||||
merged.put("baz", "qux");
|
merged.put("baz", "qux");
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// startTransaction()
|
// startTransaction()
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
@@ -1513,8 +1359,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
@@ -1544,12 +1388,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
private void testCannotStartTransactionDuringTransaction(
|
private void testCannotStartTransactionDuringTransaction(
|
||||||
boolean firstTxnReadOnly, boolean secondTxnReadOnly)
|
boolean firstTxnReadOnly, boolean secondTxnReadOnly)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1559,22 +1397,12 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
shutdown);
|
shutdown);
|
||||||
|
|
||||||
assertNotNull(db.startTransaction(firstTxnReadOnly));
|
assertNotNull(db.startTransaction(firstTxnReadOnly));
|
||||||
try {
|
db.startTransaction(secondTxnReadOnly);
|
||||||
db.startTransaction(secondTxnReadOnly);
|
fail();
|
||||||
fail();
|
|
||||||
} finally {
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCannotAddLocalIdentityAsContact() throws Exception {
|
public void testCannotAddLocalIdentityAsContact() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1598,18 +1426,10 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCannotAddDuplicateContact() throws Exception {
|
public void testCannotAddDuplicateContact() throws Exception {
|
||||||
Mockery context = new Mockery();
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(database).startTransaction();
|
oneOf(database).startTransaction();
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
@@ -1635,19 +1455,13 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testMessageDependencies() throws Exception {
|
public void testMessageDependencies() throws Exception {
|
||||||
final int shutdownHandle = 12345;
|
int shutdownHandle = 12345;
|
||||||
Mockery context = new Mockery();
|
MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
||||||
final Database<Object> database = context.mock(Database.class);
|
|
||||||
final ShutdownManager shutdown = context.mock(ShutdownManager.class);
|
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
|
||||||
final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// open()
|
// open()
|
||||||
oneOf(database).open();
|
oneOf(database).open();
|
||||||
@@ -1692,7 +1506,6 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
// endTransaction()
|
// endTransaction()
|
||||||
oneOf(database).commitTransaction(txn);
|
oneOf(database).commitTransaction(txn);
|
||||||
// close()
|
// close()
|
||||||
oneOf(shutdown).removeShutdownHook(shutdownHandle);
|
|
||||||
oneOf(database).close();
|
oneOf(database).close();
|
||||||
}});
|
}});
|
||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
@@ -1702,7 +1515,7 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.addLocalMessage(transaction, message, metadata, true);
|
db.addLocalMessage(transaction, message, metadata, true);
|
||||||
Collection<MessageId> dependencies = new ArrayList<MessageId>(2);
|
Collection<MessageId> dependencies = new ArrayList<>(2);
|
||||||
dependencies.add(messageId1);
|
dependencies.add(messageId1);
|
||||||
dependencies.add(messageId2);
|
dependencies.add(messageId2);
|
||||||
db.addMessageDependencies(transaction, message, dependencies);
|
db.addMessageDependencies(transaction, message, dependencies);
|
||||||
@@ -1713,7 +1526,5 @@ public class DatabaseComponentImplTest extends BrambleTestCase {
|
|||||||
db.endTransaction(transaction);
|
db.endTransaction(transaction);
|
||||||
}
|
}
|
||||||
db.close();
|
db.close();
|
||||||
|
|
||||||
context.assertIsSatisfied();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import org.briarproject.bramble.system.SystemClock;
|
|||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestDatabaseConfig;
|
import org.briarproject.bramble.test.TestDatabaseConfig;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -84,7 +85,7 @@ public class H2DatabaseTest extends BrambleTestCase {
|
|||||||
|
|
||||||
public H2DatabaseTest() throws Exception {
|
public H2DatabaseTest() throws Exception {
|
||||||
groupId = new GroupId(TestUtils.getRandomId());
|
groupId = new GroupId(TestUtils.getRandomId());
|
||||||
clientId = new ClientId(TestUtils.getRandomString(5));
|
clientId = new ClientId(StringUtils.getRandomString(5));
|
||||||
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
||||||
group = new Group(groupId, clientId, descriptor);
|
group = new Group(groupId, clientId, descriptor);
|
||||||
AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
@@ -463,28 +464,25 @@ public class H2DatabaseTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCloseWaitsForCommit() throws Exception {
|
public void testCloseWaitsForCommit() throws Exception {
|
||||||
final CountDownLatch closing = new CountDownLatch(1);
|
CountDownLatch closing = new CountDownLatch(1);
|
||||||
final CountDownLatch closed = new CountDownLatch(1);
|
CountDownLatch closed = new CountDownLatch(1);
|
||||||
final AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
||||||
final AtomicBoolean error = new AtomicBoolean(false);
|
AtomicBoolean error = new AtomicBoolean(false);
|
||||||
final Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
|
|
||||||
// Start a transaction
|
// Start a transaction
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
// In another thread, close the database
|
// In another thread, close the database
|
||||||
Thread close = new Thread() {
|
Thread close = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
closing.countDown();
|
||||||
try {
|
db.close();
|
||||||
closing.countDown();
|
if (!transactionFinished.get()) error.set(true);
|
||||||
db.close();
|
closed.countDown();
|
||||||
if (!transactionFinished.get()) error.set(true);
|
} catch (Exception e) {
|
||||||
closed.countDown();
|
error.set(true);
|
||||||
} catch (Exception e) {
|
|
||||||
error.set(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
close.start();
|
close.start();
|
||||||
closing.await();
|
closing.await();
|
||||||
// Do whatever the transaction needs to do
|
// Do whatever the transaction needs to do
|
||||||
@@ -500,28 +498,25 @@ public class H2DatabaseTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCloseWaitsForAbort() throws Exception {
|
public void testCloseWaitsForAbort() throws Exception {
|
||||||
final CountDownLatch closing = new CountDownLatch(1);
|
CountDownLatch closing = new CountDownLatch(1);
|
||||||
final CountDownLatch closed = new CountDownLatch(1);
|
CountDownLatch closed = new CountDownLatch(1);
|
||||||
final AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
AtomicBoolean transactionFinished = new AtomicBoolean(false);
|
||||||
final AtomicBoolean error = new AtomicBoolean(false);
|
AtomicBoolean error = new AtomicBoolean(false);
|
||||||
final Database<Connection> db = open(false);
|
Database<Connection> db = open(false);
|
||||||
|
|
||||||
// Start a transaction
|
// Start a transaction
|
||||||
Connection txn = db.startTransaction();
|
Connection txn = db.startTransaction();
|
||||||
// In another thread, close the database
|
// In another thread, close the database
|
||||||
Thread close = new Thread() {
|
Thread close = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
closing.countDown();
|
||||||
try {
|
db.close();
|
||||||
closing.countDown();
|
if (!transactionFinished.get()) error.set(true);
|
||||||
db.close();
|
closed.countDown();
|
||||||
if (!transactionFinished.get()) error.set(true);
|
} catch (Exception e) {
|
||||||
closed.countDown();
|
error.set(true);
|
||||||
} catch (Exception e) {
|
|
||||||
error.set(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
close.start();
|
close.start();
|
||||||
closing.await();
|
closing.await();
|
||||||
// Do whatever the transaction needs to do
|
// Do whatever the transaction needs to do
|
||||||
@@ -869,7 +864,7 @@ public class H2DatabaseTest extends BrambleTestCase {
|
|||||||
assertEquals(0, db.countOfferedMessages(txn, contactId));
|
assertEquals(0, db.countOfferedMessages(txn, contactId));
|
||||||
|
|
||||||
// Add some offered messages and count them
|
// Add some offered messages and count them
|
||||||
List<MessageId> ids = new ArrayList<MessageId>();
|
List<MessageId> ids = new ArrayList<>();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
MessageId m = new MessageId(TestUtils.getRandomId());
|
MessageId m = new MessageId(TestUtils.getRandomId());
|
||||||
db.addOfferedMessage(txn, contactId, m);
|
db.addOfferedMessage(txn, contactId, m);
|
||||||
|
|||||||
@@ -17,56 +17,50 @@ public class LockFairnessTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testReadersCanShareTheLock() throws Exception {
|
public void testReadersCanShareTheLock() throws Exception {
|
||||||
// Use a fair lock
|
// Use a fair lock
|
||||||
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
|
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
|
||||||
final CountDownLatch firstReaderHasLock = new CountDownLatch(1);
|
CountDownLatch firstReaderHasLock = new CountDownLatch(1);
|
||||||
final CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
|
CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
|
||||||
final CountDownLatch secondReaderHasLock = new CountDownLatch(1);
|
CountDownLatch secondReaderHasLock = new CountDownLatch(1);
|
||||||
final CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
|
CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
|
||||||
// First reader
|
// First reader
|
||||||
Thread first = new Thread() {
|
Thread first = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Acquire the lock
|
||||||
|
lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
// Acquire the lock
|
// Allow the second reader to acquire the lock
|
||||||
lock.readLock().lock();
|
firstReaderHasLock.countDown();
|
||||||
try {
|
// Wait for the second reader to acquire the lock
|
||||||
// Allow the second reader to acquire the lock
|
assertTrue(secondReaderHasLock.await(10, SECONDS));
|
||||||
firstReaderHasLock.countDown();
|
} finally {
|
||||||
// Wait for the second reader to acquire the lock
|
// Release the lock
|
||||||
assertTrue(secondReaderHasLock.await(10, SECONDS));
|
lock.readLock().unlock();
|
||||||
} finally {
|
|
||||||
// Release the lock
|
|
||||||
lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
}
|
||||||
firstReaderHasFinished.countDown();
|
} catch (InterruptedException e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
};
|
firstReaderHasFinished.countDown();
|
||||||
|
});
|
||||||
first.start();
|
first.start();
|
||||||
// Second reader
|
// Second reader
|
||||||
Thread second = new Thread() {
|
Thread second = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Wait for the first reader to acquire the lock
|
||||||
|
assertTrue(firstReaderHasLock.await(10, SECONDS));
|
||||||
|
// Acquire the lock
|
||||||
|
lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
// Wait for the first reader to acquire the lock
|
// Allow the first reader to release the lock
|
||||||
assertTrue(firstReaderHasLock.await(10, SECONDS));
|
secondReaderHasLock.countDown();
|
||||||
// Acquire the lock
|
} finally {
|
||||||
lock.readLock().lock();
|
// Release the lock
|
||||||
try {
|
lock.readLock().unlock();
|
||||||
// Allow the first reader to release the lock
|
|
||||||
secondReaderHasLock.countDown();
|
|
||||||
} finally {
|
|
||||||
// Release the lock
|
|
||||||
lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
}
|
||||||
secondReaderHasFinished.countDown();
|
} catch (InterruptedException e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
};
|
secondReaderHasFinished.countDown();
|
||||||
|
});
|
||||||
second.start();
|
second.start();
|
||||||
// Wait for both readers to finish
|
// Wait for both readers to finish
|
||||||
assertTrue(firstReaderHasFinished.await(10, SECONDS));
|
assertTrue(firstReaderHasFinished.await(10, SECONDS));
|
||||||
@@ -76,86 +70,77 @@ public class LockFairnessTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testWritersDoNotStarve() throws Exception {
|
public void testWritersDoNotStarve() throws Exception {
|
||||||
// Use a fair lock
|
// Use a fair lock
|
||||||
final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
|
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
|
||||||
final CountDownLatch firstReaderHasLock = new CountDownLatch(1);
|
CountDownLatch firstReaderHasLock = new CountDownLatch(1);
|
||||||
final CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
|
CountDownLatch firstReaderHasFinished = new CountDownLatch(1);
|
||||||
final CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
|
CountDownLatch secondReaderHasFinished = new CountDownLatch(1);
|
||||||
final CountDownLatch writerHasFinished = new CountDownLatch(1);
|
CountDownLatch writerHasFinished = new CountDownLatch(1);
|
||||||
final AtomicBoolean secondReaderHasHeldLock = new AtomicBoolean(false);
|
AtomicBoolean secondReaderHasHeldLock = new AtomicBoolean(false);
|
||||||
final AtomicBoolean writerHasHeldLock = new AtomicBoolean(false);
|
AtomicBoolean writerHasHeldLock = new AtomicBoolean(false);
|
||||||
// First reader
|
// First reader
|
||||||
Thread first = new Thread() {
|
Thread first = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Acquire the lock
|
||||||
|
lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
// Acquire the lock
|
// Allow the other threads to acquire the lock
|
||||||
lock.readLock().lock();
|
firstReaderHasLock.countDown();
|
||||||
try {
|
// Wait for both other threads to wait for the lock
|
||||||
// Allow the other threads to acquire the lock
|
while (lock.getQueueLength() < 2) Thread.sleep(10);
|
||||||
firstReaderHasLock.countDown();
|
// No other thread should have acquired the lock
|
||||||
// Wait for both other threads to wait for the lock
|
assertFalse(secondReaderHasHeldLock.get());
|
||||||
while (lock.getQueueLength() < 2) Thread.sleep(10);
|
assertFalse(writerHasHeldLock.get());
|
||||||
// No other thread should have acquired the lock
|
} finally {
|
||||||
assertFalse(secondReaderHasHeldLock.get());
|
// Release the lock
|
||||||
assertFalse(writerHasHeldLock.get());
|
lock.readLock().unlock();
|
||||||
} finally {
|
|
||||||
// Release the lock
|
|
||||||
lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
}
|
||||||
firstReaderHasFinished.countDown();
|
} catch (InterruptedException e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
};
|
firstReaderHasFinished.countDown();
|
||||||
|
});
|
||||||
first.start();
|
first.start();
|
||||||
// Writer
|
// Writer
|
||||||
Thread writer = new Thread() {
|
Thread writer = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Wait for the first reader to acquire the lock
|
||||||
|
assertTrue(firstReaderHasLock.await(10, SECONDS));
|
||||||
|
// Acquire the lock
|
||||||
|
lock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
// Wait for the first reader to acquire the lock
|
writerHasHeldLock.set(true);
|
||||||
assertTrue(firstReaderHasLock.await(10, SECONDS));
|
// The second reader should not overtake the writer
|
||||||
// Acquire the lock
|
assertFalse(secondReaderHasHeldLock.get());
|
||||||
lock.writeLock().lock();
|
} finally {
|
||||||
try {
|
lock.writeLock().unlock();
|
||||||
writerHasHeldLock.set(true);
|
|
||||||
// The second reader should not overtake the writer
|
|
||||||
assertFalse(secondReaderHasHeldLock.get());
|
|
||||||
} finally {
|
|
||||||
lock.writeLock().unlock();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
}
|
||||||
writerHasFinished.countDown();
|
} catch (InterruptedException e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
};
|
writerHasFinished.countDown();
|
||||||
|
});
|
||||||
writer.start();
|
writer.start();
|
||||||
// Second reader
|
// Second reader
|
||||||
Thread second = new Thread() {
|
Thread second = new Thread(() -> {
|
||||||
@Override
|
try {
|
||||||
public void run() {
|
// Wait for the first reader to acquire the lock
|
||||||
|
assertTrue(firstReaderHasLock.await(10, SECONDS));
|
||||||
|
// Wait for the writer to wait for the lock
|
||||||
|
while (lock.getQueueLength() < 1) Thread.sleep(10);
|
||||||
|
// Acquire the lock
|
||||||
|
lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
// Wait for the first reader to acquire the lock
|
secondReaderHasHeldLock.set(true);
|
||||||
assertTrue(firstReaderHasLock.await(10, SECONDS));
|
// The second reader should not overtake the writer
|
||||||
// Wait for the writer to wait for the lock
|
assertTrue(writerHasHeldLock.get());
|
||||||
while (lock.getQueueLength() < 1) Thread.sleep(10);
|
} finally {
|
||||||
// Acquire the lock
|
lock.readLock().unlock();
|
||||||
lock.readLock().lock();
|
|
||||||
try {
|
|
||||||
secondReaderHasHeldLock.set(true);
|
|
||||||
// The second reader should not overtake the writer
|
|
||||||
assertTrue(writerHasHeldLock.get());
|
|
||||||
} finally {
|
|
||||||
lock.readLock().unlock();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail();
|
|
||||||
}
|
}
|
||||||
secondReaderHasFinished.countDown();
|
} catch (InterruptedException e) {
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
};
|
secondReaderHasFinished.countDown();
|
||||||
|
});
|
||||||
second.start();
|
second.start();
|
||||||
// Wait for all the threads to finish
|
// Wait for all the threads to finish
|
||||||
assertTrue(firstReaderHasFinished.await(10, SECONDS));
|
assertTrue(firstReaderHasFinished.await(10, SECONDS));
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.identity.IdentityManager;
|
|||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.test.BrambleMockTestCase;
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -31,8 +32,9 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
private final Transaction txn = new Transaction(null, false);
|
private final Transaction txn = new Transaction(null, false);
|
||||||
private final LocalAuthor localAuthor =
|
private final LocalAuthor localAuthor =
|
||||||
new LocalAuthor(new AuthorId(TestUtils.getRandomId()),
|
new LocalAuthor(new AuthorId(TestUtils.getRandomId()),
|
||||||
TestUtils.getRandomString(8), TestUtils.getRandomBytes(42),
|
StringUtils.getRandomString(8),
|
||||||
TestUtils.getRandomBytes(42), 0);
|
TestUtils.getRandomBytes(42), TestUtils.getRandomBytes(42),
|
||||||
|
0);
|
||||||
private final Collection<LocalAuthor> localAuthors =
|
private final Collection<LocalAuthor> localAuthors =
|
||||||
Collections.singletonList(localAuthor);
|
Collections.singletonList(localAuthor);
|
||||||
|
|
||||||
@@ -78,8 +80,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetAuthorStatus() throws DbException {
|
public void testGetAuthorStatus() throws DbException {
|
||||||
final AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
AuthorId authorId = new AuthorId(TestUtils.getRandomId());
|
||||||
final Collection<Contact> contacts = new ArrayList<Contact>();
|
Collection<Contact> contacts = new ArrayList<>();
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
@@ -93,7 +95,7 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
|
assertEquals(UNKNOWN, identityManager.getAuthorStatus(authorId));
|
||||||
|
|
||||||
// add one unverified contact
|
// add one unverified contact
|
||||||
Author author = new Author(authorId, TestUtils.getRandomString(8),
|
Author author = new Author(authorId, StringUtils.getRandomString(8),
|
||||||
TestUtils.getRandomBytes(42));
|
TestUtils.getRandomBytes(42));
|
||||||
Contact contact =
|
Contact contact =
|
||||||
new Contact(new ContactId(1), author, localAuthor.getId(),
|
new Contact(new ContactId(1), author, localAuthor.getId(),
|
||||||
@@ -123,8 +125,8 @@ public class IdentityManagerImplTest extends BrambleMockTestCase {
|
|||||||
identityManager.getAuthorStatus(localAuthor.getId()));
|
identityManager.getAuthorStatus(localAuthor.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAuthorStatusContext(final AuthorId authorId,
|
private void checkAuthorStatusContext(AuthorId authorId,
|
||||||
final Collection<Contact> contacts) throws DbException {
|
Collection<Contact> contacts) throws DbException {
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(db).startTransaction(true);
|
oneOf(db).startTransaction(true);
|
||||||
will(returnValue(txn));
|
will(returnValue(txn));
|
||||||
|
|||||||
@@ -65,11 +65,11 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testAliceProtocol() throws Exception {
|
public void testAliceProtocol() throws Exception {
|
||||||
// set up
|
// set up
|
||||||
final Payload theirPayload = new Payload(BOB_COMMIT, null);
|
Payload theirPayload = new Payload(BOB_COMMIT, null);
|
||||||
final Payload ourPayload = new Payload(ALICE_COMMIT, null);
|
Payload ourPayload = new Payload(ALICE_COMMIT, null);
|
||||||
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
||||||
final SecretKey sharedSecret = TestUtils.getSecretKey();
|
SecretKey sharedSecret = TestUtils.getSecretKey();
|
||||||
final SecretKey masterSecret = TestUtils.getSecretKey();
|
SecretKey masterSecret = TestUtils.getSecretKey();
|
||||||
|
|
||||||
KeyAgreementProtocol protocol =
|
KeyAgreementProtocol protocol =
|
||||||
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
||||||
@@ -129,11 +129,11 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testBobProtocol() throws Exception {
|
public void testBobProtocol() throws Exception {
|
||||||
// set up
|
// set up
|
||||||
final Payload theirPayload = new Payload(ALICE_COMMIT, null);
|
Payload theirPayload = new Payload(ALICE_COMMIT, null);
|
||||||
final Payload ourPayload = new Payload(BOB_COMMIT, null);
|
Payload ourPayload = new Payload(BOB_COMMIT, null);
|
||||||
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
||||||
final SecretKey sharedSecret = TestUtils.getSecretKey();
|
SecretKey sharedSecret = TestUtils.getSecretKey();
|
||||||
final SecretKey masterSecret = TestUtils.getSecretKey();
|
SecretKey masterSecret = TestUtils.getSecretKey();
|
||||||
|
|
||||||
KeyAgreementProtocol protocol =
|
KeyAgreementProtocol protocol =
|
||||||
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
||||||
@@ -192,9 +192,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
|
|||||||
@Test(expected = AbortException.class)
|
@Test(expected = AbortException.class)
|
||||||
public void testAliceProtocolAbortOnBadKey() throws Exception {
|
public void testAliceProtocolAbortOnBadKey() throws Exception {
|
||||||
// set up
|
// set up
|
||||||
final Payload theirPayload = new Payload(BOB_COMMIT, null);
|
Payload theirPayload = new Payload(BOB_COMMIT, null);
|
||||||
final Payload ourPayload = new Payload(ALICE_COMMIT, null);
|
Payload ourPayload = new Payload(ALICE_COMMIT, null);
|
||||||
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
||||||
|
|
||||||
KeyAgreementProtocol protocol =
|
KeyAgreementProtocol protocol =
|
||||||
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
||||||
@@ -233,9 +233,9 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
|
|||||||
@Test(expected = AbortException.class)
|
@Test(expected = AbortException.class)
|
||||||
public void testBobProtocolAbortOnBadKey() throws Exception {
|
public void testBobProtocolAbortOnBadKey() throws Exception {
|
||||||
// set up
|
// set up
|
||||||
final Payload theirPayload = new Payload(ALICE_COMMIT, null);
|
Payload theirPayload = new Payload(ALICE_COMMIT, null);
|
||||||
final Payload ourPayload = new Payload(BOB_COMMIT, null);
|
Payload ourPayload = new Payload(BOB_COMMIT, null);
|
||||||
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
||||||
|
|
||||||
KeyAgreementProtocol protocol =
|
KeyAgreementProtocol protocol =
|
||||||
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
||||||
@@ -270,10 +270,10 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
|
|||||||
@Test(expected = AbortException.class)
|
@Test(expected = AbortException.class)
|
||||||
public void testAliceProtocolAbortOnBadConfirm() throws Exception {
|
public void testAliceProtocolAbortOnBadConfirm() throws Exception {
|
||||||
// set up
|
// set up
|
||||||
final Payload theirPayload = new Payload(BOB_COMMIT, null);
|
Payload theirPayload = new Payload(BOB_COMMIT, null);
|
||||||
final Payload ourPayload = new Payload(ALICE_COMMIT, null);
|
Payload ourPayload = new Payload(ALICE_COMMIT, null);
|
||||||
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
||||||
final SecretKey sharedSecret = TestUtils.getSecretKey();
|
SecretKey sharedSecret = TestUtils.getSecretKey();
|
||||||
|
|
||||||
KeyAgreementProtocol protocol =
|
KeyAgreementProtocol protocol =
|
||||||
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
||||||
@@ -335,10 +335,10 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
|
|||||||
@Test(expected = AbortException.class)
|
@Test(expected = AbortException.class)
|
||||||
public void testBobProtocolAbortOnBadConfirm() throws Exception {
|
public void testBobProtocolAbortOnBadConfirm() throws Exception {
|
||||||
// set up
|
// set up
|
||||||
final Payload theirPayload = new Payload(ALICE_COMMIT, null);
|
Payload theirPayload = new Payload(ALICE_COMMIT, null);
|
||||||
final Payload ourPayload = new Payload(BOB_COMMIT, null);
|
Payload ourPayload = new Payload(BOB_COMMIT, null);
|
||||||
final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
|
||||||
final SecretKey sharedSecret = TestUtils.getSecretKey();
|
SecretKey sharedSecret = TestUtils.getSecretKey();
|
||||||
|
|
||||||
KeyAgreementProtocol protocol =
|
KeyAgreementProtocol protocol =
|
||||||
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
|
||||||
|
|||||||
@@ -15,13 +15,9 @@ public class ShutdownManagerImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testAddAndRemove() {
|
public void testAddAndRemove() {
|
||||||
ShutdownManager s = createShutdownManager();
|
ShutdownManager s = createShutdownManager();
|
||||||
Set<Integer> handles = new HashSet<Integer>();
|
Set<Integer> handles = new HashSet<>();
|
||||||
for (int i = 0; i < 100; i++) {
|
for (int i = 0; i < 100; i++) {
|
||||||
int handle = s.addShutdownHook(new Runnable() {
|
int handle = s.addShutdownHook(() -> {});
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// The handles should all be distinct
|
// The handles should all be distinct
|
||||||
assertTrue(handles.add(handle));
|
assertTrue(handles.add(handle));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class ConnectionRegistryImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testRegisterAndUnregister() {
|
public void testRegisterAndUnregister() {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
EventBus eventBus = context.mock(EventBus.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
exactly(5).of(eventBus).broadcast(with(any(
|
exactly(5).of(eventBus).broadcast(with(any(
|
||||||
ConnectionOpenedEvent.class)));
|
ConnectionOpenedEvent.class)));
|
||||||
|
|||||||
@@ -30,36 +30,36 @@ public class PluginManagerImplTest extends BrambleTestCase {
|
|||||||
Mockery context = new Mockery() {{
|
Mockery context = new Mockery() {{
|
||||||
setThreadingPolicy(new Synchroniser());
|
setThreadingPolicy(new Synchroniser());
|
||||||
}};
|
}};
|
||||||
final Executor ioExecutor = Executors.newSingleThreadExecutor();
|
Executor ioExecutor = Executors.newSingleThreadExecutor();
|
||||||
final EventBus eventBus = context.mock(EventBus.class);
|
EventBus eventBus = context.mock(EventBus.class);
|
||||||
final PluginConfig pluginConfig = context.mock(PluginConfig.class);
|
PluginConfig pluginConfig = context.mock(PluginConfig.class);
|
||||||
final ConnectionManager connectionManager =
|
ConnectionManager connectionManager =
|
||||||
context.mock(ConnectionManager.class);
|
context.mock(ConnectionManager.class);
|
||||||
final SettingsManager settingsManager =
|
SettingsManager settingsManager =
|
||||||
context.mock(SettingsManager.class);
|
context.mock(SettingsManager.class);
|
||||||
final TransportPropertyManager transportPropertyManager =
|
TransportPropertyManager transportPropertyManager =
|
||||||
context.mock(TransportPropertyManager.class);
|
context.mock(TransportPropertyManager.class);
|
||||||
final UiCallback uiCallback = context.mock(UiCallback.class);
|
UiCallback uiCallback = context.mock(UiCallback.class);
|
||||||
|
|
||||||
// Two simplex plugin factories: both create plugins, one fails to start
|
// Two simplex plugin factories: both create plugins, one fails to start
|
||||||
final SimplexPluginFactory simplexFactory =
|
SimplexPluginFactory simplexFactory =
|
||||||
context.mock(SimplexPluginFactory.class);
|
context.mock(SimplexPluginFactory.class);
|
||||||
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
|
SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
|
||||||
final TransportId simplexId = new TransportId("simplex");
|
TransportId simplexId = new TransportId("simplex");
|
||||||
final SimplexPluginFactory simplexFailFactory =
|
SimplexPluginFactory simplexFailFactory =
|
||||||
context.mock(SimplexPluginFactory.class, "simplexFailFactory");
|
context.mock(SimplexPluginFactory.class, "simplexFailFactory");
|
||||||
final SimplexPlugin simplexFailPlugin =
|
SimplexPlugin simplexFailPlugin =
|
||||||
context.mock(SimplexPlugin.class, "simplexFailPlugin");
|
context.mock(SimplexPlugin.class, "simplexFailPlugin");
|
||||||
final TransportId simplexFailId = new TransportId("simplex1");
|
TransportId simplexFailId = new TransportId("simplex1");
|
||||||
|
|
||||||
// Two duplex plugin factories: one creates a plugin, the other fails
|
// Two duplex plugin factories: one creates a plugin, the other fails
|
||||||
final DuplexPluginFactory duplexFactory =
|
DuplexPluginFactory duplexFactory =
|
||||||
context.mock(DuplexPluginFactory.class);
|
context.mock(DuplexPluginFactory.class);
|
||||||
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
|
DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
|
||||||
final TransportId duplexId = new TransportId("duplex");
|
TransportId duplexId = new TransportId("duplex");
|
||||||
final DuplexPluginFactory duplexFailFactory =
|
DuplexPluginFactory duplexFailFactory =
|
||||||
context.mock(DuplexPluginFactory.class, "duplexFailFactory");
|
context.mock(DuplexPluginFactory.class, "duplexFailFactory");
|
||||||
final TransportId duplexFailId = new TransportId("duplex1");
|
TransportId duplexFailId = new TransportId("duplex1");
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(simplexPlugin).getId();
|
allowing(simplexPlugin).getId();
|
||||||
|
|||||||
@@ -42,35 +42,35 @@ public class PollerTest extends BrambleTestCase {
|
|||||||
public void testConnectOnContactStatusChanged() throws Exception {
|
public void testConnectOnContactStatusChanged() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
final Executor ioExecutor = new ImmediateExecutor();
|
Executor ioExecutor = new ImmediateExecutor();
|
||||||
final ScheduledExecutorService scheduler =
|
ScheduledExecutorService scheduler =
|
||||||
context.mock(ScheduledExecutorService.class);
|
context.mock(ScheduledExecutorService.class);
|
||||||
final ConnectionManager connectionManager =
|
ConnectionManager connectionManager =
|
||||||
context.mock(ConnectionManager.class);
|
context.mock(ConnectionManager.class);
|
||||||
final ConnectionRegistry connectionRegistry =
|
ConnectionRegistry connectionRegistry =
|
||||||
context.mock(ConnectionRegistry.class);
|
context.mock(ConnectionRegistry.class);
|
||||||
final PluginManager pluginManager = context.mock(PluginManager.class);
|
PluginManager pluginManager = context.mock(PluginManager.class);
|
||||||
final SecureRandom random = context.mock(SecureRandom.class);
|
SecureRandom random = context.mock(SecureRandom.class);
|
||||||
final Clock clock = context.mock(Clock.class);
|
Clock clock = context.mock(Clock.class);
|
||||||
|
|
||||||
// Two simplex plugins: one supports polling, the other doesn't
|
// Two simplex plugins: one supports polling, the other doesn't
|
||||||
final SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
|
SimplexPlugin simplexPlugin = context.mock(SimplexPlugin.class);
|
||||||
final SimplexPlugin simplexPlugin1 =
|
SimplexPlugin simplexPlugin1 =
|
||||||
context.mock(SimplexPlugin.class, "simplexPlugin1");
|
context.mock(SimplexPlugin.class, "simplexPlugin1");
|
||||||
final TransportId simplexId1 = new TransportId("simplex1");
|
TransportId simplexId1 = new TransportId("simplex1");
|
||||||
final List<SimplexPlugin> simplexPlugins = Arrays.asList(simplexPlugin,
|
List<SimplexPlugin> simplexPlugins = Arrays.asList(simplexPlugin,
|
||||||
simplexPlugin1);
|
simplexPlugin1);
|
||||||
final TransportConnectionWriter simplexWriter =
|
TransportConnectionWriter simplexWriter =
|
||||||
context.mock(TransportConnectionWriter.class);
|
context.mock(TransportConnectionWriter.class);
|
||||||
|
|
||||||
// Two duplex plugins: one supports polling, the other doesn't
|
// Two duplex plugins: one supports polling, the other doesn't
|
||||||
final DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
|
DuplexPlugin duplexPlugin = context.mock(DuplexPlugin.class);
|
||||||
final TransportId duplexId = new TransportId("duplex");
|
TransportId duplexId = new TransportId("duplex");
|
||||||
final DuplexPlugin duplexPlugin1 =
|
DuplexPlugin duplexPlugin1 =
|
||||||
context.mock(DuplexPlugin.class, "duplexPlugin1");
|
context.mock(DuplexPlugin.class, "duplexPlugin1");
|
||||||
final List<DuplexPlugin> duplexPlugins = Arrays.asList(duplexPlugin,
|
List<DuplexPlugin> duplexPlugins = Arrays.asList(duplexPlugin,
|
||||||
duplexPlugin1);
|
duplexPlugin1);
|
||||||
final DuplexTransportConnection duplexConnection =
|
DuplexTransportConnection duplexConnection =
|
||||||
context.mock(DuplexTransportConnection.class);
|
context.mock(DuplexTransportConnection.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
@@ -129,20 +129,20 @@ public class PollerTest extends BrambleTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
final Executor ioExecutor = new ImmediateExecutor();
|
Executor ioExecutor = new ImmediateExecutor();
|
||||||
final ScheduledExecutorService scheduler =
|
ScheduledExecutorService scheduler =
|
||||||
context.mock(ScheduledExecutorService.class);
|
context.mock(ScheduledExecutorService.class);
|
||||||
final ConnectionManager connectionManager =
|
ConnectionManager connectionManager =
|
||||||
context.mock(ConnectionManager.class);
|
context.mock(ConnectionManager.class);
|
||||||
final ConnectionRegistry connectionRegistry =
|
ConnectionRegistry connectionRegistry =
|
||||||
context.mock(ConnectionRegistry.class);
|
context.mock(ConnectionRegistry.class);
|
||||||
final PluginManager pluginManager = context.mock(PluginManager.class);
|
PluginManager pluginManager = context.mock(PluginManager.class);
|
||||||
final SecureRandom random = context.mock(SecureRandom.class);
|
SecureRandom random = context.mock(SecureRandom.class);
|
||||||
final Clock clock = context.mock(Clock.class);
|
Clock clock = context.mock(Clock.class);
|
||||||
|
|
||||||
final DuplexPlugin plugin = context.mock(DuplexPlugin.class);
|
DuplexPlugin plugin = context.mock(DuplexPlugin.class);
|
||||||
final TransportId transportId = new TransportId("id");
|
TransportId transportId = new TransportId("id");
|
||||||
final DuplexTransportConnection duplexConnection =
|
DuplexTransportConnection duplexConnection =
|
||||||
context.mock(DuplexTransportConnection.class);
|
context.mock(DuplexTransportConnection.class);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
@@ -194,19 +194,19 @@ public class PollerTest extends BrambleTestCase {
|
|||||||
public void testRescheduleOnConnectionOpened() throws Exception {
|
public void testRescheduleOnConnectionOpened() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
final Executor ioExecutor = new ImmediateExecutor();
|
Executor ioExecutor = new ImmediateExecutor();
|
||||||
final ScheduledExecutorService scheduler =
|
ScheduledExecutorService scheduler =
|
||||||
context.mock(ScheduledExecutorService.class);
|
context.mock(ScheduledExecutorService.class);
|
||||||
final ConnectionManager connectionManager =
|
ConnectionManager connectionManager =
|
||||||
context.mock(ConnectionManager.class);
|
context.mock(ConnectionManager.class);
|
||||||
final ConnectionRegistry connectionRegistry =
|
ConnectionRegistry connectionRegistry =
|
||||||
context.mock(ConnectionRegistry.class);
|
context.mock(ConnectionRegistry.class);
|
||||||
final PluginManager pluginManager = context.mock(PluginManager.class);
|
PluginManager pluginManager = context.mock(PluginManager.class);
|
||||||
final SecureRandom random = context.mock(SecureRandom.class);
|
SecureRandom random = context.mock(SecureRandom.class);
|
||||||
final Clock clock = context.mock(Clock.class);
|
Clock clock = context.mock(Clock.class);
|
||||||
|
|
||||||
final DuplexPlugin plugin = context.mock(DuplexPlugin.class);
|
DuplexPlugin plugin = context.mock(DuplexPlugin.class);
|
||||||
final TransportId transportId = new TransportId("id");
|
TransportId transportId = new TransportId("id");
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(plugin).getId();
|
allowing(plugin).getId();
|
||||||
@@ -239,19 +239,19 @@ public class PollerTest extends BrambleTestCase {
|
|||||||
public void testRescheduleDoesNotReplaceEarlierTask() throws Exception {
|
public void testRescheduleDoesNotReplaceEarlierTask() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
final Executor ioExecutor = new ImmediateExecutor();
|
Executor ioExecutor = new ImmediateExecutor();
|
||||||
final ScheduledExecutorService scheduler =
|
ScheduledExecutorService scheduler =
|
||||||
context.mock(ScheduledExecutorService.class);
|
context.mock(ScheduledExecutorService.class);
|
||||||
final ConnectionManager connectionManager =
|
ConnectionManager connectionManager =
|
||||||
context.mock(ConnectionManager.class);
|
context.mock(ConnectionManager.class);
|
||||||
final ConnectionRegistry connectionRegistry =
|
ConnectionRegistry connectionRegistry =
|
||||||
context.mock(ConnectionRegistry.class);
|
context.mock(ConnectionRegistry.class);
|
||||||
final PluginManager pluginManager = context.mock(PluginManager.class);
|
PluginManager pluginManager = context.mock(PluginManager.class);
|
||||||
final SecureRandom random = context.mock(SecureRandom.class);
|
SecureRandom random = context.mock(SecureRandom.class);
|
||||||
final Clock clock = context.mock(Clock.class);
|
Clock clock = context.mock(Clock.class);
|
||||||
|
|
||||||
final DuplexPlugin plugin = context.mock(DuplexPlugin.class);
|
DuplexPlugin plugin = context.mock(DuplexPlugin.class);
|
||||||
final TransportId transportId = new TransportId("id");
|
TransportId transportId = new TransportId("id");
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(plugin).getId();
|
allowing(plugin).getId();
|
||||||
@@ -299,20 +299,20 @@ public class PollerTest extends BrambleTestCase {
|
|||||||
public void testPollOnTransportEnabled() throws Exception {
|
public void testPollOnTransportEnabled() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
context.setImposteriser(ClassImposteriser.INSTANCE);
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
final Executor ioExecutor = new ImmediateExecutor();
|
Executor ioExecutor = new ImmediateExecutor();
|
||||||
final ScheduledExecutorService scheduler =
|
ScheduledExecutorService scheduler =
|
||||||
context.mock(ScheduledExecutorService.class);
|
context.mock(ScheduledExecutorService.class);
|
||||||
final ConnectionManager connectionManager =
|
ConnectionManager connectionManager =
|
||||||
context.mock(ConnectionManager.class);
|
context.mock(ConnectionManager.class);
|
||||||
final ConnectionRegistry connectionRegistry =
|
ConnectionRegistry connectionRegistry =
|
||||||
context.mock(ConnectionRegistry.class);
|
context.mock(ConnectionRegistry.class);
|
||||||
final PluginManager pluginManager = context.mock(PluginManager.class);
|
PluginManager pluginManager = context.mock(PluginManager.class);
|
||||||
final SecureRandom random = context.mock(SecureRandom.class);
|
SecureRandom random = context.mock(SecureRandom.class);
|
||||||
final Clock clock = context.mock(Clock.class);
|
Clock clock = context.mock(Clock.class);
|
||||||
|
|
||||||
final Plugin plugin = context.mock(Plugin.class);
|
Plugin plugin = context.mock(Plugin.class);
|
||||||
final TransportId transportId = new TransportId("id");
|
TransportId transportId = new TransportId("id");
|
||||||
final List<ContactId> connected = Collections.singletonList(contactId);
|
List<ContactId> connected = Collections.singletonList(contactId);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
allowing(plugin).getId();
|
allowing(plugin).getId();
|
||||||
|
|||||||
@@ -145,11 +145,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
assertEquals(2, split.length);
|
assertEquals(2, split.length);
|
||||||
String addrString = split[0];
|
String addrString = split[0];
|
||||||
// Listen on the same interface as the plugin
|
// Listen on the same interface as the plugin
|
||||||
final ServerSocket ss = new ServerSocket();
|
ServerSocket ss = new ServerSocket();
|
||||||
ss.bind(new InetSocketAddress(addrString, 0), 10);
|
ss.bind(new InetSocketAddress(addrString, 0), 10);
|
||||||
int port = ss.getLocalPort();
|
int port = ss.getLocalPort();
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
final AtomicBoolean error = new AtomicBoolean(false);
|
AtomicBoolean error = new AtomicBoolean(false);
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -194,8 +194,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
|
plugin.createKeyAgreementListener(new byte[COMMIT_LENGTH]);
|
||||||
assertNotNull(kal);
|
assertNotNull(kal);
|
||||||
Callable<KeyAgreementConnection> c = kal.listen();
|
Callable<KeyAgreementConnection> c = kal.listen();
|
||||||
FutureTask<KeyAgreementConnection> f =
|
FutureTask<KeyAgreementConnection> f = new FutureTask<>(c);
|
||||||
new FutureTask<KeyAgreementConnection>(c);
|
|
||||||
new Thread(f).start();
|
new Thread(f).start();
|
||||||
// The plugin should have bound a socket and stored the port number
|
// The plugin should have bound a socket and stored the port number
|
||||||
BdfList descriptor = kal.getDescriptor();
|
BdfList descriptor = kal.getDescriptor();
|
||||||
@@ -240,10 +239,10 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
assertEquals(2, split.length);
|
assertEquals(2, split.length);
|
||||||
String addrString = split[0];
|
String addrString = split[0];
|
||||||
// Listen on the same interface as the plugin
|
// Listen on the same interface as the plugin
|
||||||
final ServerSocket ss = new ServerSocket();
|
ServerSocket ss = new ServerSocket();
|
||||||
ss.bind(new InetSocketAddress(addrString, 0), 10);
|
ss.bind(new InetSocketAddress(addrString, 0), 10);
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
final AtomicBoolean error = new AtomicBoolean(false);
|
AtomicBoolean error = new AtomicBoolean(false);
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -291,7 +290,7 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
private static class Callback implements DuplexPluginCallback {
|
private static class Callback implements DuplexPluginCallback {
|
||||||
|
|
||||||
private final Map<ContactId, TransportProperties> remote =
|
private final Map<ContactId, TransportProperties> remote =
|
||||||
new Hashtable<ContactId, TransportProperties>();
|
new Hashtable<>();
|
||||||
private final CountDownLatch propertiesLatch = new CountDownLatch(1);
|
private final CountDownLatch propertiesLatch = new CountDownLatch(1);
|
||||||
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
|
private final CountDownLatch connectionsLatch = new CountDownLatch(1);
|
||||||
private final TransportProperties local = new TransportProperties();
|
private final TransportProperties local = new TransportProperties();
|
||||||
@@ -311,6 +310,11 @@ public class LanTcpPluginTest extends BrambleTestCase {
|
|||||||
return remote;
|
return remote;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportProperties getRemoteProperties(ContactId c) {
|
||||||
|
return remote.get(c);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mergeSettings(Settings s) {
|
public void mergeSettings(Settings s) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,723 @@
|
|||||||
|
package org.briarproject.bramble.properties;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.client.ClientHelper;
|
||||||
|
import org.briarproject.bramble.api.client.ContactGroupFactory;
|
||||||
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
|
import org.briarproject.bramble.api.data.BdfEntry;
|
||||||
|
import org.briarproject.bramble.api.data.BdfList;
|
||||||
|
import org.briarproject.bramble.api.data.MetadataParser;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
|
import org.briarproject.bramble.api.db.Metadata;
|
||||||
|
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.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.plugin.TransportId;
|
||||||
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
|
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.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
|
import org.jmock.Expectations;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static 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.api.properties.TransportPropertyManager.CLIENT_ID;
|
||||||
|
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||||
|
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.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
|
public class TransportPropertyManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
|
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
|
||||||
|
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
|
||||||
|
private final MetadataParser metadataParser =
|
||||||
|
context.mock(MetadataParser.class);
|
||||||
|
private final ContactGroupFactory contactGroupFactory =
|
||||||
|
context.mock(ContactGroupFactory.class);
|
||||||
|
private final Clock clock = context.mock(Clock.class);
|
||||||
|
|
||||||
|
private final Group localGroup = getGroup();
|
||||||
|
private final LocalAuthor localAuthor = getLocalAuthor();
|
||||||
|
private final BdfDictionary fooPropertiesDict = BdfDictionary.of(
|
||||||
|
new BdfEntry("fooKey1", "fooValue1"),
|
||||||
|
new BdfEntry("fooKey2", "fooValue2")
|
||||||
|
);
|
||||||
|
private final BdfDictionary barPropertiesDict = BdfDictionary.of(
|
||||||
|
new BdfEntry("barKey1", "barValue1"),
|
||||||
|
new BdfEntry("barKey2", "barValue2")
|
||||||
|
);
|
||||||
|
private final TransportProperties fooProperties, barProperties;
|
||||||
|
|
||||||
|
private int nextContactId = 0;
|
||||||
|
|
||||||
|
public TransportPropertyManagerImplTest() throws Exception {
|
||||||
|
fooProperties = new TransportProperties();
|
||||||
|
for (String key : fooPropertiesDict.keySet())
|
||||||
|
fooProperties.put(key, fooPropertiesDict.getString(key));
|
||||||
|
barProperties = new TransportProperties();
|
||||||
|
for (String key : barPropertiesDict.keySet())
|
||||||
|
barProperties.put(key, barPropertiesDict.getString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private TransportPropertyManagerImpl createInstance() {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(contactGroupFactory).createLocalGroup(CLIENT_ID);
|
||||||
|
will(returnValue(localGroup));
|
||||||
|
}});
|
||||||
|
return new TransportPropertyManagerImpl(db, clientHelper,
|
||||||
|
metadataParser, contactGroupFactory, clock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatesGroupsAtStartup() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact1 = getContact(true);
|
||||||
|
Contact contact2 = getContact(true);
|
||||||
|
List<Contact> contacts = Arrays.asList(contact1, contact2);
|
||||||
|
Group contactGroup1 = getGroup(), contactGroup2 = getGroup();
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||||
|
will(returnValue(false));
|
||||||
|
oneOf(db).addGroup(txn, localGroup);
|
||||||
|
oneOf(db).getContacts(txn);
|
||||||
|
will(returnValue(contacts));
|
||||||
|
// The first contact's group has already been set up
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact1);
|
||||||
|
will(returnValue(contactGroup1));
|
||||||
|
oneOf(db).containsGroup(txn, contactGroup1.getId());
|
||||||
|
will(returnValue(true));
|
||||||
|
// The second contact's group hasn't been set up
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
|
||||||
|
will(returnValue(contactGroup2));
|
||||||
|
oneOf(db).containsGroup(txn, contactGroup2.getId());
|
||||||
|
will(returnValue(false));
|
||||||
|
oneOf(db).addGroup(txn, contactGroup2);
|
||||||
|
oneOf(db).setGroupVisibility(txn, contact2.getId(),
|
||||||
|
contactGroup2.getId(), SHARED);
|
||||||
|
}});
|
||||||
|
// Copy the latest local properties into the group
|
||||||
|
expectGetLocalProperties(txn);
|
||||||
|
expectStoreMessage(txn, contactGroup2.getId(), "foo", fooPropertiesDict,
|
||||||
|
1, true, true);
|
||||||
|
expectStoreMessage(txn, contactGroup2.getId(), "bar", barPropertiesDict,
|
||||||
|
1, true, true);
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.createLocalState(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotCreateGroupsAtStartupIfAlreadyCreated()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).containsGroup(txn, localGroup.getId());
|
||||||
|
will(returnValue(true));
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.createLocalState(txn);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatesContactGroupWhenAddingContact() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact(true);
|
||||||
|
Group contactGroup = getGroup();
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
// Create the group and share it with the contact
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||||
|
will(returnValue(contactGroup));
|
||||||
|
oneOf(db).containsGroup(txn, contactGroup.getId());
|
||||||
|
will(returnValue(false));
|
||||||
|
oneOf(db).addGroup(txn, contactGroup);
|
||||||
|
oneOf(db).setGroupVisibility(txn, contact.getId(),
|
||||||
|
contactGroup.getId(), SHARED);
|
||||||
|
}});
|
||||||
|
// Copy the latest local properties into the group
|
||||||
|
expectGetLocalProperties(txn);
|
||||||
|
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
|
||||||
|
1, true, true);
|
||||||
|
expectStoreMessage(txn, contactGroup.getId(), "bar", barPropertiesDict,
|
||||||
|
1, true, true);
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.addingContact(txn, contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemovesGroupWhenRemovingContact() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact(true);
|
||||||
|
Group contactGroup = getGroup();
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||||
|
will(returnValue(contactGroup));
|
||||||
|
oneOf(db).removeGroup(txn, contactGroup);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.removingContact(txn, contact);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotDeleteAnythingWhenFirstUpdateIsDelivered()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
GroupId contactGroupId = new GroupId(getRandomId());
|
||||||
|
long timestamp = 123456789;
|
||||||
|
Message message = getMessage(contactGroupId, timestamp);
|
||||||
|
Metadata meta = new Metadata();
|
||||||
|
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 2),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
);
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// A remote update for another transport should be ignored
|
||||||
|
MessageId barUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
// A local update for the same transport should be ignored
|
||||||
|
MessageId localUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(localUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
));
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(metadataParser).parse(meta);
|
||||||
|
will(returnValue(metaDictionary));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroupId);
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
assertFalse(t.incomingMessage(txn, message, meta));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeletesOlderUpdatesWhenUpdateIsDelivered()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
GroupId contactGroupId = new GroupId(getRandomId());
|
||||||
|
long timestamp = 123456789;
|
||||||
|
Message message = getMessage(contactGroupId, timestamp);
|
||||||
|
Metadata meta = new Metadata();
|
||||||
|
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 4),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
);
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// Old remote updates for the same transport should be deleted
|
||||||
|
MessageId fooVersion2 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion2, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 2),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
MessageId fooVersion1 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion1, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
MessageId fooVersion3 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion3, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 3),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(metadataParser).parse(meta);
|
||||||
|
will(returnValue(metaDictionary));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroupId);
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
// Versions 1-3 should be deleted
|
||||||
|
oneOf(db).deleteMessage(txn, fooVersion1);
|
||||||
|
oneOf(db).deleteMessageMetadata(txn, fooVersion1);
|
||||||
|
oneOf(db).deleteMessage(txn, fooVersion2);
|
||||||
|
oneOf(db).deleteMessageMetadata(txn, fooVersion2);
|
||||||
|
oneOf(db).deleteMessage(txn, fooVersion3);
|
||||||
|
oneOf(db).deleteMessageMetadata(txn, fooVersion3);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
assertFalse(t.incomingMessage(txn, message, meta));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeletesObsoleteUpdateWhenDelivered() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
GroupId contactGroupId = new GroupId(getRandomId());
|
||||||
|
long timestamp = 123456789;
|
||||||
|
Message message = getMessage(contactGroupId, timestamp);
|
||||||
|
Metadata meta = new Metadata();
|
||||||
|
BdfDictionary metaDictionary = BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 3),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
);
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// Old remote updates for the same transport should be deleted
|
||||||
|
MessageId fooVersion2 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion2, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 2),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
MessageId fooVersion1 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion1, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
// A newer remote update for the same transport should not be deleted
|
||||||
|
MessageId fooVersion4 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion4, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 4),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(metadataParser).parse(meta);
|
||||||
|
will(returnValue(metaDictionary));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroupId);
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
// Versions 1 and 2 should be deleted, version 4 should not
|
||||||
|
oneOf(db).deleteMessage(txn, fooVersion1);
|
||||||
|
oneOf(db).deleteMessageMetadata(txn, fooVersion1);
|
||||||
|
oneOf(db).deleteMessage(txn, fooVersion2);
|
||||||
|
oneOf(db).deleteMessageMetadata(txn, fooVersion2);
|
||||||
|
// The update being delivered (version 3) should be deleted
|
||||||
|
oneOf(db).deleteMessage(txn, message.getId());
|
||||||
|
oneOf(db).deleteMessageMetadata(txn, message.getId());
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
assertFalse(t.incomingMessage(txn, message, meta));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStoresRemotePropertiesWithVersion0() throws Exception {
|
||||||
|
Contact contact = getContact(true);
|
||||||
|
Group contactGroup = getGroup();
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Map<TransportId, TransportProperties> properties =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
properties.put(new TransportId("foo"), fooProperties);
|
||||||
|
properties.put(new TransportId("bar"), barProperties);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).getContact(txn, contact.getId());
|
||||||
|
will(returnValue(contact));
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||||
|
will(returnValue(contactGroup));
|
||||||
|
}});
|
||||||
|
expectStoreMessage(txn, contactGroup.getId(), "foo", fooPropertiesDict,
|
||||||
|
0, false, false);
|
||||||
|
expectStoreMessage(txn, contactGroup.getId(), "bar", barPropertiesDict,
|
||||||
|
0, false, false);
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.addRemoteProperties(txn, contact.getId(), properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturnsLatestLocalProperties() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
|
||||||
|
expectGetLocalProperties(txn);
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
Map<TransportId, TransportProperties> local = t.getLocalProperties(txn);
|
||||||
|
assertEquals(2, local.size());
|
||||||
|
assertEquals(fooProperties, local.get(new TransportId("foo")));
|
||||||
|
assertEquals(barProperties, local.get(new TransportId("bar")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturnsEmptyPropertiesIfNoLocalPropertiesAreFound()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// A local update for another transport should be ignored
|
||||||
|
MessageId barUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
));
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
assertEquals(0, t.getLocalProperties(new TransportId("foo")).size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturnsLocalProperties() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// A local update for another transport should be ignored
|
||||||
|
MessageId barUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(barUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
));
|
||||||
|
// A local update for the right transport should be returned
|
||||||
|
MessageId fooUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
));
|
||||||
|
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
|
||||||
|
will(returnValue(fooUpdate));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
assertEquals(fooProperties,
|
||||||
|
t.getLocalProperties(new TransportId("foo")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturnsRemotePropertiesOrEmptyProperties()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact1 = getContact(false);
|
||||||
|
Contact contact2 = getContact(true);
|
||||||
|
Contact contact3 = getContact(true);
|
||||||
|
List<Contact> contacts =
|
||||||
|
Arrays.asList(contact1, contact2, contact3);
|
||||||
|
Group contactGroup2 = getGroup();
|
||||||
|
Group contactGroup3 = getGroup();
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata3 =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// A remote update for another transport should be ignored
|
||||||
|
MessageId barUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata3.put(barUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
// A local update for the right transport should be ignored
|
||||||
|
MessageId localUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata3.put(localUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
));
|
||||||
|
// A remote update for the right transport should be returned
|
||||||
|
MessageId fooUpdateId = new MessageId(getRandomId());
|
||||||
|
messageMetadata3.put(fooUpdateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", false)
|
||||||
|
));
|
||||||
|
BdfList fooUpdate = BdfList.of("foo", 1, fooPropertiesDict);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
|
oneOf(db).getContacts(txn);
|
||||||
|
will(returnValue(contacts));
|
||||||
|
// First contact: skipped because not active
|
||||||
|
// Second contact: no updates
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact2);
|
||||||
|
will(returnValue(contactGroup2));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroup2.getId());
|
||||||
|
will(returnValue(Collections.emptyMap()));
|
||||||
|
// Third contact: returns an update
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact3);
|
||||||
|
will(returnValue(contactGroup3));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroup3.getId());
|
||||||
|
will(returnValue(messageMetadata3));
|
||||||
|
oneOf(clientHelper).getMessageAsList(txn, fooUpdateId);
|
||||||
|
will(returnValue(fooUpdate));
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
Map<ContactId, TransportProperties> properties =
|
||||||
|
t.getRemoteProperties(new TransportId("foo"));
|
||||||
|
assertEquals(3, properties.size());
|
||||||
|
assertEquals(0, properties.get(contact1.getId()).size());
|
||||||
|
assertEquals(0, properties.get(contact2.getId()).size());
|
||||||
|
assertEquals(fooProperties, properties.get(contact3.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMergingUnchangedPropertiesDoesNotCreateUpdate()
|
||||||
|
throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
MessageId updateId = new MessageId(getRandomId());
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
Collections.singletonMap(updateId, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
));
|
||||||
|
BdfList update = BdfList.of("foo", 1, fooPropertiesDict);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
|
// Merge the new properties with the existing properties
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
oneOf(clientHelper).getMessageAsList(txn, updateId);
|
||||||
|
will(returnValue(update));
|
||||||
|
// Properties are unchanged so we're done
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMergingNewPropertiesCreatesUpdate() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact(true);
|
||||||
|
Group contactGroup = getGroup();
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
|
// There are no existing properties to merge with
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(Collections.emptyMap()));
|
||||||
|
// Store the new properties in the local group, version 1
|
||||||
|
expectStoreMessage(txn, localGroup.getId(), "foo",
|
||||||
|
fooPropertiesDict, 1, true, false);
|
||||||
|
// Store the new properties in each contact's group, version 1
|
||||||
|
oneOf(db).getContacts(txn);
|
||||||
|
will(returnValue(Collections.singletonList(contact)));
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||||
|
will(returnValue(contactGroup));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(Collections.emptyMap()));
|
||||||
|
expectStoreMessage(txn, contactGroup.getId(), "foo",
|
||||||
|
fooPropertiesDict, 1, true, true);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMergingUpdatedPropertiesCreatesUpdate() throws Exception {
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
Contact contact = getContact(true);
|
||||||
|
Group contactGroup = getGroup();
|
||||||
|
BdfDictionary oldMetadata = BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 1),
|
||||||
|
new BdfEntry("local", true)
|
||||||
|
);
|
||||||
|
MessageId localGroupUpdateId = new MessageId(getRandomId());
|
||||||
|
Map<MessageId, BdfDictionary> localGroupMessageMetadata =
|
||||||
|
Collections.singletonMap(localGroupUpdateId, oldMetadata);
|
||||||
|
MessageId contactGroupUpdateId = new MessageId(getRandomId());
|
||||||
|
Map<MessageId, BdfDictionary> contactGroupMessageMetadata =
|
||||||
|
Collections.singletonMap(contactGroupUpdateId, oldMetadata);
|
||||||
|
BdfList oldUpdate = BdfList.of("foo", 1, BdfDictionary.of(
|
||||||
|
new BdfEntry("fooKey1", "oldFooValue1")
|
||||||
|
));
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(db).startTransaction(false);
|
||||||
|
will(returnValue(txn));
|
||||||
|
// Merge the new properties with the existing properties
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(localGroupMessageMetadata));
|
||||||
|
oneOf(clientHelper).getMessageAsList(txn, localGroupUpdateId);
|
||||||
|
will(returnValue(oldUpdate));
|
||||||
|
// Store the merged properties in the local group, version 2
|
||||||
|
expectStoreMessage(txn, localGroup.getId(), "foo",
|
||||||
|
fooPropertiesDict, 2, true, false);
|
||||||
|
// Delete the previous update
|
||||||
|
oneOf(db).removeMessage(txn, localGroupUpdateId);
|
||||||
|
// Store the merged properties in each contact's group, version 2
|
||||||
|
oneOf(db).getContacts(txn);
|
||||||
|
will(returnValue(Collections.singletonList(contact)));
|
||||||
|
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
|
||||||
|
will(returnValue(contactGroup));
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
contactGroup.getId());
|
||||||
|
will(returnValue(contactGroupMessageMetadata));
|
||||||
|
expectStoreMessage(txn, contactGroup.getId(), "foo",
|
||||||
|
fooPropertiesDict, 2, true, true);
|
||||||
|
// Delete the previous update
|
||||||
|
oneOf(db).removeMessage(txn, contactGroupUpdateId);
|
||||||
|
oneOf(db).commitTransaction(txn);
|
||||||
|
oneOf(db).endTransaction(txn);
|
||||||
|
}});
|
||||||
|
|
||||||
|
TransportPropertyManagerImpl t = createInstance();
|
||||||
|
t.mergeLocalProperties(new TransportId("foo"), fooProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Group getGroup() {
|
||||||
|
GroupId g = new GroupId(getRandomId());
|
||||||
|
byte[] descriptor = getRandomBytes(MAX_GROUP_DESCRIPTOR_LENGTH);
|
||||||
|
return new Group(g, CLIENT_ID, descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LocalAuthor getLocalAuthor() {
|
||||||
|
AuthorId id = new AuthorId(getRandomId());
|
||||||
|
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
|
||||||
|
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
byte[] privateKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
long created = System.currentTimeMillis();
|
||||||
|
return new LocalAuthor(id, name, publicKey, privateKey, created);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Contact getContact(boolean active) {
|
||||||
|
ContactId c = new ContactId(nextContactId++);
|
||||||
|
AuthorId a = new AuthorId(getRandomId());
|
||||||
|
String name = getRandomString(MAX_AUTHOR_NAME_LENGTH);
|
||||||
|
byte[] publicKey = getRandomBytes(MAX_PUBLIC_KEY_LENGTH);
|
||||||
|
return new Contact(c, new Author(a, name, publicKey),
|
||||||
|
localAuthor.getId(), true, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Message getMessage(GroupId g, long timestamp) {
|
||||||
|
MessageId messageId = new MessageId(getRandomId());
|
||||||
|
byte[] raw = getRandomBytes(MAX_MESSAGE_BODY_LENGTH);
|
||||||
|
return new Message(messageId, g, timestamp, raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectGetLocalProperties(Transaction txn)
|
||||||
|
throws Exception {
|
||||||
|
Map<MessageId, BdfDictionary> messageMetadata =
|
||||||
|
new LinkedHashMap<>();
|
||||||
|
// The only update for transport "foo" should be returned
|
||||||
|
MessageId fooVersion999 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(fooVersion999, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "foo"),
|
||||||
|
new BdfEntry("version", 999)
|
||||||
|
));
|
||||||
|
// An old update for transport "bar" should be deleted
|
||||||
|
MessageId barVersion2 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(barVersion2, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 2)
|
||||||
|
));
|
||||||
|
// An even older update for transport "bar" should be deleted
|
||||||
|
MessageId barVersion1 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(barVersion1, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 1)
|
||||||
|
));
|
||||||
|
// The latest update for transport "bar" should be returned
|
||||||
|
MessageId barVersion3 = new MessageId(getRandomId());
|
||||||
|
messageMetadata.put(barVersion3, BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", "bar"),
|
||||||
|
new BdfEntry("version", 3)
|
||||||
|
));
|
||||||
|
BdfList fooUpdate = BdfList.of("foo", 999, fooPropertiesDict);
|
||||||
|
BdfList barUpdate = BdfList.of("bar", 3, barPropertiesDict);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
// Find the latest local update for each transport
|
||||||
|
oneOf(clientHelper).getMessageMetadataAsDictionary(txn,
|
||||||
|
localGroup.getId());
|
||||||
|
will(returnValue(messageMetadata));
|
||||||
|
oneOf(db).removeMessage(txn, barVersion1);
|
||||||
|
oneOf(db).removeMessage(txn, barVersion2);
|
||||||
|
// Retrieve and parse the latest local properties
|
||||||
|
oneOf(clientHelper).getMessageAsList(txn, fooVersion999);
|
||||||
|
will(returnValue(fooUpdate));
|
||||||
|
oneOf(clientHelper).getMessageAsList(txn, barVersion3);
|
||||||
|
will(returnValue(barUpdate));
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expectStoreMessage(Transaction txn, GroupId g,
|
||||||
|
String transportId, BdfDictionary properties, long version,
|
||||||
|
boolean local, boolean shared) throws Exception {
|
||||||
|
long timestamp = 123456789;
|
||||||
|
BdfList body = BdfList.of(transportId, version, properties);
|
||||||
|
Message message = getMessage(g, timestamp);
|
||||||
|
BdfDictionary meta = BdfDictionary.of(
|
||||||
|
new BdfEntry("transportId", transportId),
|
||||||
|
new BdfEntry("version", version),
|
||||||
|
new BdfEntry("local", local)
|
||||||
|
);
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(clock).currentTimeMillis();
|
||||||
|
will(returnValue(timestamp));
|
||||||
|
oneOf(clientHelper).createMessage(g, timestamp, body);
|
||||||
|
will(returnValue(message));
|
||||||
|
oneOf(clientHelper).addLocalMessage(txn, message, meta, shared);
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import org.briarproject.bramble.api.sync.MessageId;
|
|||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ public class TransportPropertyValidatorTest extends BrambleTestCase {
|
|||||||
bdfDictionary = new BdfDictionary();
|
bdfDictionary = new BdfDictionary();
|
||||||
|
|
||||||
GroupId groupId = new GroupId(TestUtils.getRandomId());
|
GroupId groupId = new GroupId(TestUtils.getRandomId());
|
||||||
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
|
ClientId clientId = new ClientId(StringUtils.getRandomString(5));
|
||||||
byte[] descriptor = TestUtils.getRandomBytes(12);
|
byte[] descriptor = TestUtils.getRandomBytes(12);
|
||||||
group = new Group(groupId, clientId, descriptor);
|
group = new Group(groupId, clientId, descriptor);
|
||||||
|
|
||||||
@@ -85,7 +86,7 @@ public class TransportPropertyValidatorTest extends BrambleTestCase {
|
|||||||
public void testValidateLongTransportId() throws IOException {
|
public void testValidateLongTransportId() throws IOException {
|
||||||
|
|
||||||
String wrongTransportIdString =
|
String wrongTransportIdString =
|
||||||
TestUtils.getRandomString(MAX_TRANSPORT_ID_LENGTH + 1);
|
StringUtils.getRandomString(MAX_TRANSPORT_ID_LENGTH + 1);
|
||||||
BdfList body = BdfList.of(wrongTransportIdString, 4, bdfDictionary);
|
BdfList body = BdfList.of(wrongTransportIdString, 4, bdfDictionary);
|
||||||
tpv.validateMessage(message, group, body);
|
tpv.validateMessage(message, group, body);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ import org.briarproject.bramble.api.db.Transaction;
|
|||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.sync.Ack;
|
import org.briarproject.bramble.api.sync.Ack;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
|
import org.briarproject.bramble.api.sync.RecordWriter;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.ImmediateExecutor;
|
import org.briarproject.bramble.test.ImmediateExecutor;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
import org.briarproject.bramble.api.sync.RecordWriter;
|
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.jmock.Mockery;
|
import org.jmock.Mockery;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -44,10 +44,10 @@ public class SimplexOutgoingSessionTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNothingToSend() throws Exception {
|
public void testNothingToSend() throws Exception {
|
||||||
final SimplexOutgoingSession session = new SimplexOutgoingSession(db,
|
SimplexOutgoingSession session = new SimplexOutgoingSession(db,
|
||||||
dbExecutor, eventBus, contactId, maxLatency, recordWriter);
|
dbExecutor, eventBus, contactId, maxLatency, recordWriter);
|
||||||
final Transaction noAckTxn = new Transaction(null, false);
|
Transaction noAckTxn = new Transaction(null, false);
|
||||||
final Transaction noMsgTxn = new Transaction(null, false);
|
Transaction noMsgTxn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Add listener
|
// Add listener
|
||||||
@@ -80,14 +80,14 @@ public class SimplexOutgoingSessionTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSomethingToSend() throws Exception {
|
public void testSomethingToSend() throws Exception {
|
||||||
final Ack ack = new Ack(Collections.singletonList(messageId));
|
Ack ack = new Ack(Collections.singletonList(messageId));
|
||||||
final byte[] raw = new byte[1234];
|
byte[] raw = new byte[1234];
|
||||||
final SimplexOutgoingSession session = new SimplexOutgoingSession(db,
|
SimplexOutgoingSession session = new SimplexOutgoingSession(db,
|
||||||
dbExecutor, eventBus, contactId, maxLatency, recordWriter);
|
dbExecutor, eventBus, contactId, maxLatency, recordWriter);
|
||||||
final Transaction ackTxn = new Transaction(null, false);
|
Transaction ackTxn = new Transaction(null, false);
|
||||||
final Transaction noAckTxn = new Transaction(null, false);
|
Transaction noAckTxn = new Transaction(null, false);
|
||||||
final Transaction msgTxn = new Transaction(null, false);
|
Transaction msgTxn = new Transaction(null, false);
|
||||||
final Transaction noMsgTxn = new Transaction(null, false);
|
Transaction noMsgTxn = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Add listener
|
// Add listener
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
|||||||
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||||
import org.briarproject.bramble.test.BrambleTestCase;
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
@@ -78,7 +79,7 @@ public class SyncIntegrationTest extends BrambleTestCase {
|
|||||||
headerKey = TestUtils.getSecretKey();
|
headerKey = TestUtils.getSecretKey();
|
||||||
streamNumber = 123;
|
streamNumber = 123;
|
||||||
// Create a group
|
// Create a group
|
||||||
ClientId clientId = new ClientId(TestUtils.getRandomString(5));
|
ClientId clientId = new ClientId(StringUtils.getRandomString(5));
|
||||||
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
|
||||||
Group group = groupFactory.createGroup(clientId, descriptor);
|
Group group = groupFactory.createGroup(clientId, descriptor);
|
||||||
// Add two messages to the group
|
// Add two messages to the group
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.briarproject.bramble.test.BrambleMockTestCase;
|
|||||||
import org.briarproject.bramble.test.ImmediateExecutor;
|
import org.briarproject.bramble.test.ImmediateExecutor;
|
||||||
import org.briarproject.bramble.test.TestUtils;
|
import org.briarproject.bramble.test.TestUtils;
|
||||||
import org.briarproject.bramble.util.ByteUtils;
|
import org.briarproject.bramble.util.ByteUtils;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -51,7 +52,7 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
private final Executor dbExecutor = new ImmediateExecutor();
|
private final Executor dbExecutor = new ImmediateExecutor();
|
||||||
private final Executor validationExecutor = new ImmediateExecutor();
|
private final Executor validationExecutor = new ImmediateExecutor();
|
||||||
private final ClientId clientId =
|
private final ClientId clientId =
|
||||||
new ClientId(TestUtils.getRandomString(5));
|
new ClientId(StringUtils.getRandomString(5));
|
||||||
private final MessageId messageId = new MessageId(TestUtils.getRandomId());
|
private final MessageId messageId = new MessageId(TestUtils.getRandomId());
|
||||||
private final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
private final MessageId messageId1 = new MessageId(TestUtils.getRandomId());
|
||||||
private final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
private final MessageId messageId2 = new MessageId(TestUtils.getRandomId());
|
||||||
@@ -91,9 +92,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testStartAndStop() throws Exception {
|
public void testStartAndStop() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, true);
|
Transaction txn1 = new Transaction(null, true);
|
||||||
final Transaction txn2 = new Transaction(null, true);
|
Transaction txn2 = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// validateOutstandingMessages()
|
// validateOutstandingMessages()
|
||||||
@@ -125,13 +126,13 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMessagesAreValidatedAtStartup() throws Exception {
|
public void testMessagesAreValidatedAtStartup() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, true);
|
Transaction txn1 = new Transaction(null, true);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
final Transaction txn3 = new Transaction(null, true);
|
Transaction txn3 = new Transaction(null, true);
|
||||||
final Transaction txn4 = new Transaction(null, false);
|
Transaction txn4 = new Transaction(null, false);
|
||||||
final Transaction txn5 = new Transaction(null, true);
|
Transaction txn5 = new Transaction(null, true);
|
||||||
final Transaction txn6 = new Transaction(null, true);
|
Transaction txn6 = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Get messages to validate
|
// Get messages to validate
|
||||||
@@ -216,11 +217,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPendingMessagesAreDeliveredAtStartup() throws Exception {
|
public void testPendingMessagesAreDeliveredAtStartup() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, true);
|
Transaction txn1 = new Transaction(null, true);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
final Transaction txn3 = new Transaction(null, false);
|
Transaction txn3 = new Transaction(null, false);
|
||||||
final Transaction txn4 = new Transaction(null, true);
|
Transaction txn4 = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Get messages to validate
|
// Get messages to validate
|
||||||
@@ -302,11 +303,11 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMessagesAreSharedAtStartup() throws Exception {
|
public void testMessagesAreSharedAtStartup() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, true);
|
Transaction txn1 = new Transaction(null, true);
|
||||||
final Transaction txn2 = new Transaction(null, true);
|
Transaction txn2 = new Transaction(null, true);
|
||||||
final Transaction txn3 = new Transaction(null, false);
|
Transaction txn3 = new Transaction(null, false);
|
||||||
final Transaction txn4 = new Transaction(null, false);
|
Transaction txn4 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// No messages to validate
|
// No messages to validate
|
||||||
@@ -354,9 +355,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIncomingMessagesAreShared() throws Exception {
|
public void testIncomingMessagesAreShared() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -404,12 +405,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testValidationContinuesAfterNoSuchMessageException()
|
public void testValidationContinuesAfterNoSuchMessageException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, true);
|
Transaction txn1 = new Transaction(null, true);
|
||||||
final Transaction txn2 = new Transaction(null, true);
|
Transaction txn2 = new Transaction(null, true);
|
||||||
final Transaction txn3 = new Transaction(null, false);
|
Transaction txn3 = new Transaction(null, false);
|
||||||
final Transaction txn4 = new Transaction(null, true);
|
Transaction txn4 = new Transaction(null, true);
|
||||||
final Transaction txn5 = new Transaction(null, true);
|
Transaction txn5 = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Get messages to validate
|
// Get messages to validate
|
||||||
@@ -475,12 +476,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testValidationContinuesAfterNoSuchGroupException()
|
public void testValidationContinuesAfterNoSuchGroupException()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, true);
|
Transaction txn1 = new Transaction(null, true);
|
||||||
final Transaction txn2 = new Transaction(null, true);
|
Transaction txn2 = new Transaction(null, true);
|
||||||
final Transaction txn3 = new Transaction(null, false);
|
Transaction txn3 = new Transaction(null, false);
|
||||||
final Transaction txn4 = new Transaction(null, true);
|
Transaction txn4 = new Transaction(null, true);
|
||||||
final Transaction txn5 = new Transaction(null, true);
|
Transaction txn5 = new Transaction(null, true);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Get messages to validate
|
// Get messages to validate
|
||||||
@@ -550,8 +551,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNonLocalMessagesAreValidatedWhenAdded() throws Exception {
|
public void testNonLocalMessagesAreValidatedWhenAdded() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -590,8 +591,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMessagesWithUndeliveredDependenciesArePending()
|
public void testMessagesWithUndeliveredDependenciesArePending()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -623,8 +624,8 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMessagesWithDeliveredDependenciesGetDelivered()
|
public void testMessagesWithDeliveredDependenciesGetDelivered()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -662,9 +663,9 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMessagesWithInvalidDependenciesAreInvalid()
|
public void testMessagesWithInvalidDependenciesAreInvalid()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -715,19 +716,18 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRecursiveInvalidation() throws Exception {
|
public void testRecursiveInvalidation() throws Exception {
|
||||||
final MessageId messageId3 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId3 = new MessageId(TestUtils.getRandomId());
|
||||||
final MessageId messageId4 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId4 = new MessageId(TestUtils.getRandomId());
|
||||||
final Map<MessageId, State> twoDependents =
|
Map<MessageId, State> twoDependents = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<MessageId, State>();
|
|
||||||
twoDependents.put(messageId1, PENDING);
|
twoDependents.put(messageId1, PENDING);
|
||||||
twoDependents.put(messageId2, PENDING);
|
twoDependents.put(messageId2, PENDING);
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
final Transaction txn3 = new Transaction(null, false);
|
Transaction txn3 = new Transaction(null, false);
|
||||||
final Transaction txn4 = new Transaction(null, false);
|
Transaction txn4 = new Transaction(null, false);
|
||||||
final Transaction txn5 = new Transaction(null, false);
|
Transaction txn5 = new Transaction(null, false);
|
||||||
final Transaction txn6 = new Transaction(null, false);
|
Transaction txn6 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -819,27 +819,25 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPendingDependentsGetDelivered() throws Exception {
|
public void testPendingDependentsGetDelivered() throws Exception {
|
||||||
final MessageId messageId3 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId3 = new MessageId(TestUtils.getRandomId());
|
||||||
final MessageId messageId4 = new MessageId(TestUtils.getRandomId());
|
MessageId messageId4 = new MessageId(TestUtils.getRandomId());
|
||||||
final Message message3 = new Message(messageId3, groupId, timestamp,
|
Message message3 = new Message(messageId3, groupId, timestamp,
|
||||||
raw);
|
raw);
|
||||||
final Message message4 = new Message(messageId4, groupId, timestamp,
|
Message message4 = new Message(messageId4, groupId, timestamp,
|
||||||
raw);
|
raw);
|
||||||
final Map<MessageId, State> twoDependents =
|
Map<MessageId, State> twoDependents = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<MessageId, State>();
|
|
||||||
twoDependents.put(messageId1, PENDING);
|
twoDependents.put(messageId1, PENDING);
|
||||||
twoDependents.put(messageId2, PENDING);
|
twoDependents.put(messageId2, PENDING);
|
||||||
final Map<MessageId, State> twoDependencies =
|
Map<MessageId, State> twoDependencies = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<MessageId, State>();
|
|
||||||
twoDependencies.put(messageId1, DELIVERED);
|
twoDependencies.put(messageId1, DELIVERED);
|
||||||
twoDependencies.put(messageId2, DELIVERED);
|
twoDependencies.put(messageId2, DELIVERED);
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
final Transaction txn3 = new Transaction(null, false);
|
Transaction txn3 = new Transaction(null, false);
|
||||||
final Transaction txn4 = new Transaction(null, false);
|
Transaction txn4 = new Transaction(null, false);
|
||||||
final Transaction txn5 = new Transaction(null, false);
|
Transaction txn5 = new Transaction(null, false);
|
||||||
final Transaction txn6 = new Transaction(null, false);
|
Transaction txn6 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
@@ -978,13 +976,12 @@ public class ValidationManagerImplTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnlyReadyPendingDependentsGetDelivered() throws Exception {
|
public void testOnlyReadyPendingDependentsGetDelivered() throws Exception {
|
||||||
final Map<MessageId, State> twoDependencies =
|
Map<MessageId, State> twoDependencies = new LinkedHashMap<>();
|
||||||
new LinkedHashMap<MessageId, State>();
|
|
||||||
twoDependencies.put(messageId, DELIVERED);
|
twoDependencies.put(messageId, DELIVERED);
|
||||||
twoDependencies.put(messageId2, UNKNOWN);
|
twoDependencies.put(messageId2, UNKNOWN);
|
||||||
final Transaction txn = new Transaction(null, true);
|
Transaction txn = new Transaction(null, true);
|
||||||
final Transaction txn1 = new Transaction(null, false);
|
Transaction txn1 = new Transaction(null, false);
|
||||||
final Transaction txn2 = new Transaction(null, false);
|
Transaction txn2 = new Transaction(null, false);
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Load the group
|
// Load the group
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class LinuxSecureRandomSpiTest extends BrambleTestCase {
|
|||||||
System.err.println("WARNING: Skipping test, can't run on this OS");
|
System.err.println("WARNING: Skipping test, can't run on this OS");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set<Bytes> seeds = new HashSet<Bytes>();
|
Set<Bytes> seeds = new HashSet<>();
|
||||||
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi();
|
LinuxSecureRandomSpi engine = new LinuxSecureRandomSpi();
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
byte[] seed = engine.engineGenerateSeed(SEED_BYTES);
|
byte[] seed = engine.engineGenerateSeed(SEED_BYTES);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.briarproject.bramble.api.sync.GroupId;
|
|||||||
import org.briarproject.bramble.api.sync.Message;
|
import org.briarproject.bramble.api.sync.Message;
|
||||||
import org.briarproject.bramble.api.sync.MessageId;
|
import org.briarproject.bramble.api.sync.MessageId;
|
||||||
import org.briarproject.bramble.api.system.Clock;
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
public abstract class ValidatorTestCase extends BrambleMockTestCase {
|
public abstract class ValidatorTestCase extends BrambleMockTestCase {
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ public abstract class ValidatorTestCase extends BrambleMockTestCase {
|
|||||||
protected final Message message =
|
protected final Message message =
|
||||||
new Message(messageId, groupId, timestamp, raw);
|
new Message(messageId, groupId, timestamp, raw);
|
||||||
protected final ClientId clientId =
|
protected final ClientId clientId =
|
||||||
new ClientId(TestUtils.getRandomString(123));
|
new ClientId(StringUtils.getRandomString(123));
|
||||||
protected final byte[] descriptor = TestUtils.getRandomBytes(123);
|
protected final byte[] descriptor = TestUtils.getRandomBytes(123);
|
||||||
protected final Group group = new Group(groupId, clientId, descriptor);
|
protected final Group group = new Group(groupId, clientId, descriptor);
|
||||||
|
|
||||||
|
|||||||
@@ -58,21 +58,21 @@ public class KeyManagerImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void testStartService() throws Exception {
|
public void testStartService() throws Exception {
|
||||||
final Transaction txn = new Transaction(null, false);
|
Transaction txn = new Transaction(null, false);
|
||||||
AuthorId remoteAuthorId = new AuthorId(getRandomId());
|
AuthorId remoteAuthorId = new AuthorId(getRandomId());
|
||||||
Author remoteAuthor = new Author(remoteAuthorId, "author",
|
Author remoteAuthor = new Author(remoteAuthorId, "author",
|
||||||
getRandomBytes(42));
|
getRandomBytes(42));
|
||||||
AuthorId localAuthorId = new AuthorId(getRandomId());
|
AuthorId localAuthorId = new AuthorId(getRandomId());
|
||||||
final Collection<Contact> contacts = new ArrayList<Contact>();
|
Collection<Contact> contacts = new ArrayList<>();
|
||||||
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true,
|
contacts.add(new Contact(contactId, remoteAuthor, localAuthorId, true,
|
||||||
true));
|
true));
|
||||||
contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId,
|
contacts.add(new Contact(inactiveContactId, remoteAuthor, localAuthorId,
|
||||||
true, false));
|
true, false));
|
||||||
final SimplexPluginFactory pluginFactory =
|
SimplexPluginFactory pluginFactory =
|
||||||
context.mock(SimplexPluginFactory.class);
|
context.mock(SimplexPluginFactory.class);
|
||||||
final Collection<SimplexPluginFactory> factories = Collections
|
Collection<SimplexPluginFactory> factories = Collections
|
||||||
.singletonList(pluginFactory);
|
.singletonList(pluginFactory);
|
||||||
final int maxLatency = 1337;
|
int maxLatency = 1337;
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(pluginConfig).getSimplexFactories();
|
oneOf(pluginConfig).getSimplexFactories();
|
||||||
@@ -100,9 +100,9 @@ public class KeyManagerImplTest extends BrambleTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddContact() throws Exception {
|
public void testAddContact() throws Exception {
|
||||||
final SecretKey secretKey = getSecretKey();
|
SecretKey secretKey = getSecretKey();
|
||||||
final long timestamp = 42L;
|
long timestamp = 42L;
|
||||||
final boolean alice = true;
|
boolean alice = true;
|
||||||
|
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(transportKeyManager)
|
oneOf(transportKeyManager)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testEmptyFramesAreSkipped() throws Exception {
|
public void testEmptyFramesAreSkipped() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
||||||
will(returnValue(0)); // Empty frame
|
will(returnValue(0)); // Empty frame
|
||||||
@@ -37,7 +37,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testEmptyFramesAreSkippedWithBuffer() throws Exception {
|
public void testEmptyFramesAreSkippedWithBuffer() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
||||||
will(returnValue(0)); // Empty frame
|
will(returnValue(0)); // Empty frame
|
||||||
@@ -63,7 +63,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMultipleReadsPerFrame() throws Exception {
|
public void testMultipleReadsPerFrame() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
||||||
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame
|
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame
|
||||||
@@ -85,7 +85,7 @@ public class StreamReaderImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMultipleReadsPerFrameWithOffsets() throws Exception {
|
public void testMultipleReadsPerFrameWithOffsets() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
oneOf(decrypter).readFrame(with(any(byte[].class)));
|
||||||
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame
|
will(returnValue(MAX_PAYLOAD_LENGTH)); // Nice long frame
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testCloseWithoutWritingWritesFinalFrame() throws Exception {
|
public void testCloseWithoutWritingWritesFinalFrame() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Write an empty final frame
|
// Write an empty final frame
|
||||||
oneOf(encrypter).writeFrame(with(any(byte[].class)), with(0),
|
oneOf(encrypter).writeFrame(with(any(byte[].class)), with(0),
|
||||||
@@ -31,7 +31,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
|
|||||||
public void testFlushWithoutBufferedDataWritesFrameAndFlushes()
|
public void testFlushWithoutBufferedDataWritesFrameAndFlushes()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
||||||
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Write a non-final frame with an empty payload
|
// Write a non-final frame with an empty payload
|
||||||
@@ -58,7 +58,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
|
|||||||
public void testFlushWithBufferedDataWritesFrameAndFlushes()
|
public void testFlushWithBufferedDataWritesFrameAndFlushes()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
||||||
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Write a non-final frame with one payload byte
|
// Write a non-final frame with one payload byte
|
||||||
@@ -85,7 +85,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testSingleByteWritesWriteFullFrame() throws Exception {
|
public void testSingleByteWritesWriteFullFrame() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
||||||
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Write a full non-final frame
|
// Write a full non-final frame
|
||||||
@@ -109,7 +109,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testMultiByteWritesWriteFullFrames() throws Exception {
|
public void testMultiByteWritesWriteFullFrames() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
||||||
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Write two full non-final frames
|
// Write two full non-final frames
|
||||||
@@ -140,7 +140,7 @@ public class StreamWriterImplTest extends BrambleTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testLargeMultiByteWriteWritesFullFrames() throws Exception {
|
public void testLargeMultiByteWriteWritesFullFrames() throws Exception {
|
||||||
Mockery context = new Mockery();
|
Mockery context = new Mockery();
|
||||||
final StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
|
||||||
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
StreamWriterImpl w = new StreamWriterImpl(encrypter);
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// Write two full non-final frames
|
// Write two full non-final frames
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user