mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Compare commits
242 Commits
bluetooth-
...
ci-debuggi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b02d89967e | ||
|
|
65ce049737 | ||
|
|
335c360ef8 | ||
|
|
fc26aaa168 | ||
|
|
88224793c1 | ||
|
|
0bf74f6a69 | ||
|
|
4286621b02 | ||
|
|
b3e3b970ab | ||
|
|
ef10a08165 | ||
|
|
094e1f8b65 | ||
|
|
8b58bdb289 | ||
|
|
7f61061f15 | ||
|
|
cd127670bb | ||
|
|
a9b412be40 | ||
|
|
413360db09 | ||
|
|
e5112ae9ee | ||
|
|
f399ce9290 | ||
|
|
30e036c672 | ||
|
|
2896700e50 | ||
|
|
987baba3bc | ||
|
|
03191ff08f | ||
|
|
42031631dd | ||
|
|
64e30844b8 | ||
|
|
30a070dd13 | ||
|
|
4f18303a1f | ||
|
|
5c500fb740 | ||
|
|
4d63272c04 | ||
|
|
16b09b9380 | ||
|
|
a1599df712 | ||
|
|
afa3c3a70e | ||
|
|
0f37a43415 | ||
|
|
ef1d5d3233 | ||
|
|
feab825865 | ||
|
|
5d2c96f916 | ||
|
|
02ff37b187 | ||
|
|
6863727646 | ||
|
|
087d6e9931 | ||
|
|
d79f1b667a | ||
|
|
633f5a8bd7 | ||
|
|
90cb9a2fae | ||
|
|
fc86319e13 | ||
|
|
af1ed292ae | ||
|
|
5393127400 | ||
|
|
0e6c374d0e | ||
|
|
52efbcac8a | ||
|
|
acf6a45004 | ||
|
|
7ffcace228 | ||
|
|
e157fdfc7b | ||
|
|
f8a8c0d8b8 | ||
|
|
f53aeef0d6 | ||
|
|
f812acb00b | ||
|
|
004467e84e | ||
|
|
34c0a83e36 | ||
|
|
fd0dad8936 | ||
|
|
32420a0781 | ||
|
|
b6c85c8bf6 | ||
|
|
4163731ec3 | ||
|
|
8e732d880f | ||
|
|
0b2594a693 | ||
|
|
7e009ceaf2 | ||
|
|
b238b28ef9 | ||
|
|
edb8e8f9d0 | ||
|
|
cc6041e90c | ||
|
|
3ff6462899 | ||
|
|
6f7d0c6f77 | ||
|
|
412381f37e | ||
|
|
05fbb87c06 | ||
|
|
daf5db470f | ||
|
|
be2d695150 | ||
|
|
d0c2c03057 | ||
|
|
db11e0101a | ||
|
|
25b8932cde | ||
|
|
0d658513ba | ||
|
|
732bf6d4ec | ||
|
|
53762e7c93 | ||
|
|
5a145c9eb2 | ||
|
|
d8ce1d75ca | ||
|
|
77b2fa8acb | ||
|
|
f9d5873385 | ||
|
|
1de6c863df | ||
|
|
8c5c66fa9a | ||
|
|
82f939ecd4 | ||
|
|
1a5c02f8a9 | ||
|
|
16d56535ca | ||
|
|
dcd6fda046 | ||
|
|
2535445831 | ||
|
|
c0d5a3a5ea | ||
|
|
c1789a8e52 | ||
|
|
2a0ecc3f80 | ||
|
|
b176ec5844 | ||
|
|
f8df6b88ee | ||
|
|
55d8f853db | ||
|
|
004853a09b | ||
|
|
d815dd6ec9 | ||
|
|
f243ed39ab | ||
|
|
4aed0632b8 | ||
|
|
1860db10b4 | ||
|
|
cf4efbeef3 | ||
|
|
099e8ef4d5 | ||
|
|
05152eef0e | ||
|
|
481de00f90 | ||
|
|
277d045469 | ||
|
|
287f3760cd | ||
|
|
58d09d0742 | ||
|
|
14353653c7 | ||
|
|
adbfa26364 | ||
|
|
abaefacb69 | ||
|
|
6ca0339da2 | ||
|
|
4a9977fa58 | ||
|
|
f9d8c720ec | ||
|
|
1edf2bfa75 | ||
|
|
233af69909 | ||
|
|
6f6ba38de1 | ||
|
|
f9495b49d6 | ||
|
|
cb29c9bf32 | ||
|
|
8283760e8a | ||
|
|
e300245f8d | ||
|
|
81cbb7e843 | ||
|
|
bc0e529d89 | ||
|
|
c6b6bc307e | ||
|
|
b200dd9323 | ||
|
|
881d8034cb | ||
|
|
1bee58e70d | ||
|
|
ede33d9278 | ||
|
|
ce6293b1d3 | ||
|
|
912dd0eb4a | ||
|
|
06197295f8 | ||
|
|
6a163c0358 | ||
|
|
aa6b5511c2 | ||
|
|
1cbd76bbc9 | ||
|
|
ba4a4aea59 | ||
|
|
391e869d29 | ||
|
|
8925d6f5d7 | ||
|
|
afa9b6193a | ||
|
|
1bcedea34a | ||
|
|
0f16ac57f3 | ||
|
|
7ecac1867e | ||
|
|
331c09a02a | ||
|
|
7e05a49bda | ||
|
|
eac1f9ed74 | ||
|
|
d16aa9e2a4 | ||
|
|
cc72d146a0 | ||
|
|
bff23480d7 | ||
|
|
e435578f3b | ||
|
|
33b9539a72 | ||
|
|
a114d4db15 | ||
|
|
73b7879c64 | ||
|
|
e622a518ac | ||
|
|
28ea3d014a | ||
|
|
457d77ca51 | ||
|
|
581c67f5fd | ||
|
|
1dcb9aa1d0 | ||
|
|
d97dcfff30 | ||
|
|
e166d9dd15 | ||
|
|
2e002d132c | ||
|
|
da629df630 | ||
|
|
135372ebee | ||
|
|
b083122d72 | ||
|
|
649433a506 | ||
|
|
eff3a69734 | ||
|
|
62de50af76 | ||
|
|
1f9def8418 | ||
|
|
1e80069980 | ||
|
|
bfde71c151 | ||
|
|
bce0a3150b | ||
|
|
ee59b9b3ad | ||
|
|
55918a88b2 | ||
|
|
679c1c3719 | ||
|
|
21f33d6cfb | ||
|
|
912b1b5b1d | ||
|
|
0ad20037ae | ||
|
|
62d893f7b1 | ||
|
|
497213e56d | ||
|
|
f5c0d0b2cb | ||
|
|
f4131d6f32 | ||
|
|
06deba4bd4 | ||
|
|
26643e491b | ||
|
|
6ef4130f8f | ||
|
|
ba5b2f601b | ||
|
|
5be672f0e7 | ||
|
|
fa525564c0 | ||
|
|
dee0ca238b | ||
|
|
3c6b43b2bd | ||
|
|
dcacae0729 | ||
|
|
aefc5c519e | ||
|
|
7225adf24e | ||
|
|
30228cf025 | ||
|
|
99e2b7eaab | ||
|
|
2f7d5b869c | ||
|
|
d5d6db6723 | ||
|
|
b026031d66 | ||
|
|
abe14f19e6 | ||
|
|
fa17549972 | ||
|
|
0d2a91289f | ||
|
|
2e22318b27 | ||
|
|
11f0bd1ae0 | ||
|
|
e2d636e274 | ||
|
|
f41b76c567 | ||
|
|
08931e64cb | ||
|
|
ccee1febbc | ||
|
|
7bfc1c3579 | ||
|
|
2dc94a95ed | ||
|
|
a47a1cf442 | ||
|
|
4adb27a1ce | ||
|
|
841c31ebce | ||
|
|
d6810cf87f | ||
|
|
7a2df3d6cb | ||
|
|
0c65ff4783 | ||
|
|
8b10b7ed23 | ||
|
|
9743255ce9 | ||
|
|
8c64734ff1 | ||
|
|
c845dfc7f4 | ||
|
|
a8a02b9e45 | ||
|
|
6703be1c32 | ||
|
|
fc99dedb53 | ||
|
|
65a461a0db | ||
|
|
a44a68f231 | ||
|
|
4ac6baa23d | ||
|
|
4cde50b7f5 | ||
|
|
da40eca80b | ||
|
|
fa267d38af | ||
|
|
ba20fbeb47 | ||
|
|
196df05df9 | ||
|
|
44f07c8d76 | ||
|
|
d7f39af6d1 | ||
|
|
4f732c3997 | ||
|
|
74cfd313ab | ||
|
|
c089a099f0 | ||
|
|
98a0d09899 | ||
|
|
18c4195115 | ||
|
|
d4a9c41cf5 | ||
|
|
8bc28f99c1 | ||
|
|
1834146ad0 | ||
|
|
624e03a2c9 | ||
|
|
a24e0482c9 | ||
|
|
695b543ba9 | ||
|
|
75e910e1d9 | ||
|
|
8fc8333451 | ||
|
|
c2154c81f4 | ||
|
|
5cd5fc7e43 | ||
|
|
abd9db70b9 | ||
|
|
5e679e7a10 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -23,5 +23,6 @@ local.properties
|
|||||||
!.idea/codeStyles
|
!.idea/codeStyles
|
||||||
.gradle
|
.gradle
|
||||||
build/
|
build/
|
||||||
|
captures
|
||||||
*.iml
|
*.iml
|
||||||
projectFilesBackup/
|
projectFilesBackup/
|
||||||
@@ -11,8 +11,8 @@ test:
|
|||||||
- .gradle/caches
|
- .gradle/caches
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- ./gradlew --no-daemon animalSnifferMain animalSnifferTest
|
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
|
||||||
- ./gradlew --no-daemon test
|
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom test
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
# these file change every time but should not be cached
|
# these file change every time but should not be cached
|
||||||
@@ -21,11 +21,7 @@ test:
|
|||||||
|
|
||||||
|
|
||||||
test_reproducible:
|
test_reproducible:
|
||||||
image: briar/reproducer:latest
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cd /opt/briar-reproducer
|
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
|
||||||
- ./reproduce.py ${CI_COMMIT_REF_NAME}
|
|
||||||
|
|
||||||
only:
|
only:
|
||||||
- tags
|
- tags
|
||||||
|
|||||||
1
.idea/runConfigurations/All_tests.xml
generated
1
.idea/runConfigurations/All_tests.xml
generated
@@ -21,6 +21,7 @@
|
|||||||
<method>
|
<method>
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="AndroidJUnit" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-j2se" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-j2se" run_configuration_type="AndroidJUnit" />
|
||||||
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
|
||||||
</method>
|
</method>
|
||||||
|
|||||||
23
.idea/runConfigurations/All_tests_in_bramble_android.xml
generated
Normal file
23
.idea/runConfigurations/All_tests_in_bramble_android.xml
generated
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
|
||||||
|
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||||
|
<module name="bramble-android" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||||
|
<option name="ALTERNATIVE_JRE_PATH" />
|
||||||
|
<option name="PACKAGE_NAME" value="" />
|
||||||
|
<option name="MAIN_CLASS_NAME" value="" />
|
||||||
|
<option name="METHOD_NAME" value="" />
|
||||||
|
<option name="TEST_OBJECT" value="package" />
|
||||||
|
<option name="VM_PARAMETERS" value="-ea" />
|
||||||
|
<option name="PARAMETERS" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
|
||||||
|
<option name="ENV_VARIABLES" />
|
||||||
|
<option name="PASS_PARENT_ENVS" value="true" />
|
||||||
|
<option name="TEST_SEARCH_SCOPE">
|
||||||
|
<value defaultName="singleModule" />
|
||||||
|
</option>
|
||||||
|
<envs />
|
||||||
|
<patterns />
|
||||||
|
<method />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
|
apply from: 'witness.gradle'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdkVersion 27
|
||||||
@@ -8,9 +9,11 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 26
|
targetSdkVersion 26
|
||||||
versionCode 10005
|
versionCode 10013
|
||||||
versionName "1.0.5"
|
versionName "1.0.13"
|
||||||
consumerProguardFiles 'proguard-rules.txt'
|
consumerProguardFiles 'proguard-rules.txt'
|
||||||
|
|
||||||
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -25,92 +28,25 @@ configurations {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-core', configuration: 'default')
|
implementation project(path: ':bramble-core', configuration: 'default')
|
||||||
implementation 'org.briarproject:jtorctl:0.3'
|
tor 'org.briarproject:tor-android:0.2.9.16@zip'
|
||||||
tor 'org.briarproject:tor-android:0.2.9.15@zip'
|
|
||||||
|
|
||||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||||
}
|
|
||||||
|
|
||||||
dependencyVerification {
|
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||||
verify = [
|
testImplementation 'junit:junit:4.12'
|
||||||
'com.android.tools.analytics-library:protos:26.1.2:protos-26.1.2.jar:52672a0b42b572a06aecc3535d5068eb46c0e15d129b9f1085d3c16a1da5cdbb',
|
testImplementation "org.jmock:jmock:2.8.2"
|
||||||
'com.android.tools.analytics-library:shared:26.1.2:shared-26.1.2.jar:5c7e0eda18c6f87feeb83628c707e8aaa3298b41fb72e38efe31ad1675f9e8e9',
|
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||||
'com.android.tools.analytics-library:tracker:26.1.2:tracker-26.1.2.jar:06f97aa0adf44ffb06f8681c6a79d9be153a08f61d21eddc42b8d3db96df4282',
|
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||||
'com.android.tools.build:apksig:3.1.2:apksig-3.1.2.jar:40696a4559124d1d57873d208857eee059d48859239d569c7d18374ac644a8be',
|
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||||
'com.android.tools.build:builder-model:3.1.2:builder-model-3.1.2.jar:d49bfa2a135c9562b6ca7aa4342036cfa1582c7074c2d1d93d1dae8b3a134e17',
|
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||||
'com.android.tools.build:builder-test-api:3.1.2:builder-test-api-3.1.2.jar:dfe2a50b740d41b11189101062434d4283d18647e89a492ad51710c719363e9f',
|
|
||||||
'com.android.tools.build:builder:3.1.2:builder-3.1.2.jar:b60f825a42e2efe8433619fbc759f3d9effecab718279048d36881188ceb1d14',
|
androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||||
'com.android.tools.build:gradle-api:3.1.2:gradle-api-3.1.2.jar:e58bcc5b893e4583ab0f5c8ef89c4dbcce202b405a9d7fcc116d21e5357d4893',
|
androidTestImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||||
'com.android.tools.build:manifest-merger:26.1.2:manifest-merger-26.1.2.jar:9c61c27ea5266573107b954acf1216d398f4d7e7ae6fad6409d6b2b767eb091c',
|
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||||
'com.android.tools.ddms:ddmlib:26.1.2:ddmlib-26.1.2.jar:18a2a5fbef36882f07d03c2b9e59eba05cf8248177bf5cbff736e4b582804c44',
|
androidTestAnnotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
'com.android.tools.external.com-intellij:intellij-core:26.1.2:intellij-core-26.1.2.jar:37c5acf279f1ae3e85b1a5be3c9f15f43bde7b08f978eefefffb9c4035760c52',
|
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
||||||
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.2:kotlin-compiler-26.1.2.jar:152df0bee7580326c77316b669a9d96e3b09efb1d45f545dce4147271b0b8944',
|
|
||||||
'com.android.tools.external.org-jetbrains:uast:26.1.2:uast-26.1.2.jar:02d39582206d3f5fc0a6cb18bfd9e8b9f9c1acb805ec6dac08b4e3a56849d279',
|
|
||||||
'com.android.tools.layoutlib:layoutlib-api:26.1.2:layoutlib-api-26.1.2.jar:20220039fcc7d799f928153beff862e704457c0f55ab44258f3745ebeb662b4f',
|
|
||||||
'com.android.tools.lint:lint-api:26.1.2:lint-api-26.1.2.jar:e1d5b62b870a7c566e9877a6b96b27784a4d713f8caa07fdcb4705d47a40a1d9',
|
|
||||||
'com.android.tools.lint:lint-checks:26.1.2:lint-checks-26.1.2.jar:211e2afd58504372385d71b1e5be982c2b5121ab6fee1c04ddabeb75a8729e07',
|
|
||||||
'com.android.tools.lint:lint-gradle-api:26.1.2:lint-gradle-api-26.1.2.jar:71284f2a8b03c3e55c94511c9eb36f8184fbb85324325fc6b78abf5183f03d90',
|
|
||||||
'com.android.tools.lint:lint-gradle:26.1.2:lint-gradle-26.1.2.jar:855f0c82b7fc690df1b7319c0774f7517f7f8f5dd4eee1f6077dcf50e07c6240',
|
|
||||||
'com.android.tools.lint:lint-kotlin:26.1.2:lint-kotlin-26.1.2.jar:1e591f70bcbbc11569720a9bbcca2bc1f3d4f789f01f40f642848d920643d484',
|
|
||||||
'com.android.tools.lint:lint:26.1.2:lint-26.1.2.jar:93736c62e9f1976998c2b4aa716aea0734cdb162d05502f4af7292654aedb182',
|
|
||||||
'com.android.tools:annotations:26.1.2:annotations-26.1.2.jar:72773dcaf5c4ccca828e3c8467f1b78a8a00b3cc5f8ad1aab88fcf9379928018',
|
|
||||||
'com.android.tools:common:26.1.2:common-26.1.2.jar:ea4320f0c17dcbc4491896bb705c4d25ec08bd62ef02ab0579fe154e75e788e6',
|
|
||||||
'com.android.tools:dvlib:26.1.2:dvlib-26.1.2.jar:1187aa4fb666595c96c4deb6bc0e0f4b7e396bde9f6243330b49a232946130ea',
|
|
||||||
'com.android.tools:repository:26.1.2:repository-26.1.2.jar:8b86e512ad6d32bd76989451eefe2b271f5efce6d4d65ecb173afaf14606e01a',
|
|
||||||
'com.android.tools:sdk-common:26.1.2:sdk-common-26.1.2.jar:23584720a60a21cdcb5b1ec10269e3013789d6805d153cc696c39ec7ce251896',
|
|
||||||
'com.android.tools:sdklib:26.1.2:sdklib-26.1.2.jar:d3870fafc59ab8efa70d3f9649f40ee299c8ec5b58377b06e8853d7272a5bf4e',
|
|
||||||
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
|
||||||
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
|
|
||||||
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
|
||||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
|
||||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
|
||||||
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
|
||||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
|
||||||
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
|
|
||||||
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
|
||||||
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
|
||||||
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
|
||||||
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
|
|
||||||
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
|
||||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
|
||||||
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
|
||||||
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
|
|
||||||
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
|
|
||||||
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
|
|
||||||
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
|
||||||
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
|
||||||
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
|
||||||
'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2',
|
|
||||||
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
|
|
||||||
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
|
|
||||||
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
|
|
||||||
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
|
|
||||||
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
|
|
||||||
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
|
|
||||||
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
|
||||||
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
|
||||||
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
|
|
||||||
'org.briarproject:tor-android:0.2.9.15:tor-android-0.2.9.15.zip:34a6474ee219ffa52e0f3393e917dda6ed03d320b02247d4fa5075aa4094ee6d',
|
|
||||||
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
|
||||||
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
|
||||||
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
|
||||||
'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70',
|
|
||||||
'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea',
|
|
||||||
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
|
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
|
|
||||||
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
|
|
||||||
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
|
||||||
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
|
||||||
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
|
|
||||||
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
|
|
||||||
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
|
|
||||||
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
|
|
||||||
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
|
|
||||||
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
@@ -119,3 +55,8 @@ project.afterEvaluate {
|
|||||||
into 'src/main/res/raw'
|
into 'src/main/res/raw'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test) {
|
||||||
|
// Use entropy-gathering device specified on command line, if any
|
||||||
|
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
|
import org.briarproject.bramble.test.BrambleAndroidIntegrationTestComponent;
|
||||||
|
import org.briarproject.bramble.test.BrambleTestCase;
|
||||||
|
import org.briarproject.bramble.test.DaggerBrambleAndroidIntegrationTestComponent;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
|
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||||
|
import static java.util.Collections.singletonList;
|
||||||
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class BridgeTest extends BrambleTestCase {
|
||||||
|
|
||||||
|
private final static long TIMEOUT = SECONDS.toMillis(23);
|
||||||
|
|
||||||
|
private final static Logger LOG =
|
||||||
|
Logger.getLogger(BridgeTest.class.getName());
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
NetworkManager networkManager;
|
||||||
|
@Inject
|
||||||
|
ResourceProvider resourceProvider;
|
||||||
|
@Inject
|
||||||
|
CircumventionProvider circumventionProvider;
|
||||||
|
@Inject
|
||||||
|
EventBus eventBus;
|
||||||
|
@Inject
|
||||||
|
BackoffFactory backoffFactory;
|
||||||
|
@Inject
|
||||||
|
Clock clock;
|
||||||
|
|
||||||
|
private final Context appContext =
|
||||||
|
getTargetContext().getApplicationContext();
|
||||||
|
|
||||||
|
private List<String> bridges;
|
||||||
|
private AndroidTorPluginFactory factory;
|
||||||
|
|
||||||
|
private volatile String currentBridge = null;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
BrambleAndroidIntegrationTestComponent component =
|
||||||
|
DaggerBrambleAndroidIntegrationTestComponent.builder().build();
|
||||||
|
component.inject(this);
|
||||||
|
|
||||||
|
Executor ioExecutor = Executors.newCachedThreadPool();
|
||||||
|
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
|
||||||
|
LocationUtils locationUtils = () -> "US";
|
||||||
|
SocketFactory torSocketFactory = SocketFactory.getDefault();
|
||||||
|
|
||||||
|
bridges = circumventionProvider.getBridges();
|
||||||
|
CircumventionProvider bridgeProvider = new CircumventionProvider() {
|
||||||
|
@Override
|
||||||
|
public boolean isTorProbablyBlocked(String countryCode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doBridgesWork(String countryCode) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getBridges() {
|
||||||
|
return singletonList(currentBridge);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
factory = new AndroidTorPluginFactory(ioExecutor, scheduler, appContext,
|
||||||
|
networkManager, locationUtils, eventBus, torSocketFactory,
|
||||||
|
backoffFactory, resourceProvider, bridgeProvider, clock);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBridges() throws Exception {
|
||||||
|
assertTrue(bridges.size() > 0);
|
||||||
|
|
||||||
|
for (String bridge : bridges) testBridge(bridge);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void testBridge(String bridge) throws Exception {
|
||||||
|
DuplexPlugin duplexPlugin =
|
||||||
|
factory.createPlugin(new TorPluginCallBack());
|
||||||
|
assertNotNull(duplexPlugin);
|
||||||
|
AndroidTorPlugin plugin = (AndroidTorPlugin) duplexPlugin;
|
||||||
|
|
||||||
|
currentBridge = bridge;
|
||||||
|
LOG.warning("Testing " + bridge);
|
||||||
|
try {
|
||||||
|
plugin.start();
|
||||||
|
long start = clock.currentTimeMillis();
|
||||||
|
while (clock.currentTimeMillis() - start < TIMEOUT) {
|
||||||
|
if (plugin.isRunning()) return;
|
||||||
|
clock.sleep(500);
|
||||||
|
}
|
||||||
|
if (!plugin.isRunning()) {
|
||||||
|
fail("Could not connect to Tor within timeout.");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
plugin.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
||||||
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public class TorPluginCallBack implements DuplexPluginCallback {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incomingConnectionCreated(DuplexTransportConnection d) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void outgoingConnectionCreated(ContactId c,
|
||||||
|
DuplexTransportConnection d) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Settings getSettings() {
|
||||||
|
return new Settings();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransportProperties getLocalProperties() {
|
||||||
|
return new TransportProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mergeSettings(Settings s) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mergeLocalProperties(TransportProperties p) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transportEnabled() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transportDisabled() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package org.briarproject.bramble.test;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
class ApplicationModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Application provideApplication() {
|
||||||
|
return (Application) getTargetContext().getApplicationContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.briarproject.bramble.test;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.BrambleAndroidModule;
|
||||||
|
import org.briarproject.bramble.event.EventModule;
|
||||||
|
import org.briarproject.bramble.plugin.PluginModule;
|
||||||
|
import org.briarproject.bramble.plugin.tor.BridgeTest;
|
||||||
|
import org.briarproject.bramble.system.SystemModule;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Component;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Component(modules = {
|
||||||
|
BrambleAndroidModule.class,
|
||||||
|
TestLifecycleModule.class,
|
||||||
|
ApplicationModule.class,
|
||||||
|
PluginModule.class, // needed for BackoffFactory
|
||||||
|
EventModule.class,
|
||||||
|
SystemModule.class,
|
||||||
|
})
|
||||||
|
public interface BrambleAndroidIntegrationTestComponent {
|
||||||
|
|
||||||
|
void inject(BridgeTest init);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,14 +2,13 @@
|
|||||||
package="org.briarproject.bramble"
|
package="org.briarproject.bramble"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.bluetooth"/>
|
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
<uses-permission android:name="android.permission.BLUETOOTH"/>
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||||
<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.WAKE_LOCK"/>
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package org.briarproject.bramble;
|
package org.briarproject.bramble;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.network.AndroidNetworkModule;
|
||||||
|
import org.briarproject.bramble.plugin.tor.CircumventionModule;
|
||||||
import org.briarproject.bramble.system.AndroidSystemModule;
|
import org.briarproject.bramble.system.AndroidSystemModule;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
|
|
||||||
@Module(includes = {
|
@Module(includes = {
|
||||||
AndroidSystemModule.class
|
AndroidNetworkModule.class,
|
||||||
|
AndroidSystemModule.class,
|
||||||
|
CircumventionModule.class
|
||||||
})
|
})
|
||||||
public class BrambleAndroidModule {
|
public class BrambleAndroidModule {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package org.briarproject.bramble.account;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.account.AccountManager;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
class AndroidAccountManager extends AccountManagerImpl
|
||||||
|
implements AccountManager {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(AndroidAccountManager.class.getName());
|
||||||
|
|
||||||
|
private static final String PREF_DB_KEY = "key";
|
||||||
|
|
||||||
|
protected final Context appContext;
|
||||||
|
private final SharedPreferences prefs;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AndroidAccountManager(DatabaseConfig databaseConfig,
|
||||||
|
CryptoComponent crypto, IdentityManager identityManager,
|
||||||
|
SharedPreferences prefs, Application app) {
|
||||||
|
super(databaseConfig, crypto, identityManager);
|
||||||
|
this.prefs = prefs;
|
||||||
|
appContext = app.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
protected String loadEncryptedDatabaseKey() {
|
||||||
|
String key = getDatabaseKeyFromPreferences();
|
||||||
|
if (key == null) key = super.loadEncryptedDatabaseKey();
|
||||||
|
else migrateDatabaseKeyToFile(key);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
@Nullable
|
||||||
|
private String getDatabaseKeyFromPreferences() {
|
||||||
|
String key = prefs.getString(PREF_DB_KEY, null);
|
||||||
|
if (key == null) LOG.info("No database key in preferences");
|
||||||
|
else LOG.info("Found database key in preferences");
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
private void migrateDatabaseKeyToFile(String key) {
|
||||||
|
if (storeEncryptedDatabaseKey(key)) {
|
||||||
|
if (prefs.edit().remove(PREF_DB_KEY).commit())
|
||||||
|
LOG.info("Database key migrated to file");
|
||||||
|
else LOG.warning("Database key not removed from preferences");
|
||||||
|
} else {
|
||||||
|
LOG.warning("Database key not migrated to file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAccount() {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
super.deleteAccount();
|
||||||
|
SharedPreferences defaultPrefs = getDefaultSharedPreferences();
|
||||||
|
deleteAppData(prefs, defaultPrefs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package access for testing
|
||||||
|
SharedPreferences getDefaultSharedPreferences() {
|
||||||
|
return PreferenceManager.getDefaultSharedPreferences(appContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
private void deleteAppData(SharedPreferences... clear) {
|
||||||
|
// Clear and commit shared preferences
|
||||||
|
for (SharedPreferences prefs : clear) {
|
||||||
|
if (!prefs.edit().clear().commit())
|
||||||
|
LOG.warning("Could not clear shared preferences");
|
||||||
|
}
|
||||||
|
// Delete files, except lib and shared_prefs directories
|
||||||
|
File dataDir = new File(appContext.getApplicationInfo().dataDir);
|
||||||
|
File[] children = dataDir.listFiles();
|
||||||
|
if (children == null) {
|
||||||
|
LOG.warning("Could not list files in app data dir");
|
||||||
|
} else {
|
||||||
|
for (File child : children) {
|
||||||
|
String name = child.getName();
|
||||||
|
if (!name.equals("lib") && !name.equals("shared_prefs")) {
|
||||||
|
IoUtils.deleteFileOrDir(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Recreate the cache dir as some OpenGL drivers expect it to exist
|
||||||
|
if (!new File(dataDir, "cache").mkdir())
|
||||||
|
LOG.warning("Could not recreate cache dir");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
package org.briarproject.bramble.network;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.Service;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkStatus;
|
||||||
|
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.system.Scheduler;
|
||||||
|
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static android.content.Context.CONNECTIVITY_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.TYPE_WIFI;
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
|
||||||
|
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||||
|
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
class AndroidNetworkManager implements NetworkManager, Service {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(AndroidNetworkManager.class.getName());
|
||||||
|
|
||||||
|
// See android.net.wifi.WifiManager
|
||||||
|
private static final String WIFI_AP_STATE_CHANGED_ACTION =
|
||||||
|
"android.net.wifi.WIFI_AP_STATE_CHANGED";
|
||||||
|
|
||||||
|
private final ScheduledExecutorService scheduler;
|
||||||
|
private final EventBus eventBus;
|
||||||
|
private final Context appContext;
|
||||||
|
private final AtomicReference<Future<?>> connectivityCheck =
|
||||||
|
new AtomicReference<>();
|
||||||
|
private final AtomicBoolean used = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
private volatile BroadcastReceiver networkStateReceiver = null;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AndroidNetworkManager(@Scheduler ScheduledExecutorService scheduler,
|
||||||
|
EventBus eventBus, Application app) {
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
this.eventBus = eventBus;
|
||||||
|
this.appContext = app.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startService() {
|
||||||
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
|
// Register to receive network status events
|
||||||
|
networkStateReceiver = new NetworkStateReceiver();
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(CONNECTIVITY_ACTION);
|
||||||
|
filter.addAction(ACTION_SCREEN_ON);
|
||||||
|
filter.addAction(ACTION_SCREEN_OFF);
|
||||||
|
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
|
||||||
|
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
|
||||||
|
appContext.registerReceiver(networkStateReceiver, filter);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stopService() {
|
||||||
|
if (networkStateReceiver != null)
|
||||||
|
appContext.unregisterReceiver(networkStateReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NetworkStatus getNetworkStatus() {
|
||||||
|
ConnectivityManager cm = (ConnectivityManager)
|
||||||
|
appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||||
|
if (cm == null) throw new AssertionError();
|
||||||
|
NetworkInfo net = cm.getActiveNetworkInfo();
|
||||||
|
boolean connected = net != null && net.isConnected();
|
||||||
|
boolean wifi = connected && net.getType() == TYPE_WIFI;
|
||||||
|
return new NetworkStatus(connected, wifi);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateConnectionStatus() {
|
||||||
|
eventBus.broadcast(new NetworkStatusEvent(getNetworkStatus()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleConnectionStatusUpdate(int delay, TimeUnit unit) {
|
||||||
|
Future<?> newConnectivityCheck =
|
||||||
|
scheduler.schedule(this::updateConnectionStatus, delay, unit);
|
||||||
|
Future<?> oldConnectivityCheck =
|
||||||
|
connectivityCheck.getAndSet(newConnectivityCheck);
|
||||||
|
if (oldConnectivityCheck != null) oldConnectivityCheck.cancel(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class NetworkStateReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context ctx, Intent i) {
|
||||||
|
String action = i.getAction();
|
||||||
|
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
|
||||||
|
updateConnectionStatus();
|
||||||
|
if (isSleepOrDozeEvent(action)) {
|
||||||
|
// Allow time for the network to be enabled or disabled
|
||||||
|
scheduleConnectionStatusUpdate(1, MINUTES);
|
||||||
|
} else if (isApEvent(action)) {
|
||||||
|
// The state change may be broadcast before the AP address is
|
||||||
|
// visible, so delay handling the event
|
||||||
|
scheduleConnectionStatusUpdate(5, SECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSleepOrDozeEvent(@Nullable String action) {
|
||||||
|
boolean isSleep = ACTION_SCREEN_ON.equals(action) ||
|
||||||
|
ACTION_SCREEN_OFF.equals(action);
|
||||||
|
boolean isDoze = SDK_INT >= 23 &&
|
||||||
|
ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action);
|
||||||
|
return isSleep || isDoze;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isApEvent(@Nullable String action) {
|
||||||
|
return WIFI_AP_STATE_CHANGED_ACTION.equals(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.briarproject.bramble.network;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class AndroidNetworkModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,
|
||||||
|
AndroidNetworkManager networkManager) {
|
||||||
|
lifecycleManager.registerService(networkManager);
|
||||||
|
return networkManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
|
|||||||
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
|
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
|
||||||
import static android.bluetooth.BluetoothAdapter.STATE_ON;
|
import static android.bluetooth.BluetoothAdapter.STATE_ON;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -145,7 +146,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
try {
|
try {
|
||||||
if (ss != null) ss.close();
|
if (ss != null) ss.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,7 +186,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
|
|||||||
try {
|
try {
|
||||||
if (c != null) c.close();
|
if (c != null) c.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package org.briarproject.bramble.plugin.tcp;
|
package org.briarproject.bramble.plugin.tcp;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkInfo;
|
import android.net.NetworkInfo;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.PoliteExecutor;
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
|
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
|
||||||
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.duplex.DuplexPluginCallback;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
@@ -20,7 +21,6 @@ import java.net.Socket;
|
|||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
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.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -28,21 +28,13 @@ import javax.net.SocketFactory;
|
|||||||
|
|
||||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||||
import static android.content.Context.WIFI_SERVICE;
|
import static android.content.Context.WIFI_SERVICE;
|
||||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
|
||||||
import static android.net.ConnectivityManager.TYPE_WIFI;
|
import static android.net.ConnectivityManager.TYPE_WIFI;
|
||||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
import static java.util.Collections.emptyList;
|
import static java.util.Collections.emptyList;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class AndroidLanTcpPlugin extends LanTcpPlugin {
|
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
|
||||||
|
|
||||||
// See android.net.wifi.WifiManager
|
|
||||||
private static final String WIFI_AP_STATE_CHANGED_ACTION =
|
|
||||||
"android.net.wifi.WIFI_AP_STATE_CHANGED";
|
|
||||||
private static final int WIFI_AP_STATE_ENABLED = 13;
|
|
||||||
|
|
||||||
private static final byte[] WIFI_AP_ADDRESS_BYTES =
|
private static final byte[] WIFI_AP_ADDRESS_BYTES =
|
||||||
{(byte) 192, (byte) 168, 43, 1};
|
{(byte) 192, (byte) 168, 43, 1};
|
||||||
@@ -60,22 +52,20 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ScheduledExecutorService scheduler;
|
private final Executor connectionStatusExecutor;
|
||||||
private final Context appContext;
|
|
||||||
private final ConnectivityManager connectivityManager;
|
private final ConnectivityManager connectivityManager;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final WifiManager wifiManager;
|
private final WifiManager wifiManager;
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private volatile BroadcastReceiver networkStateReceiver = null;
|
|
||||||
private volatile SocketFactory socketFactory;
|
private volatile SocketFactory socketFactory;
|
||||||
|
|
||||||
AndroidLanTcpPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
|
AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
|
||||||
Backoff backoff, Context appContext, DuplexPluginCallback callback,
|
Backoff backoff, DuplexPluginCallback callback, int maxLatency,
|
||||||
int maxLatency, int maxIdleTime) {
|
int maxIdleTime) {
|
||||||
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
|
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime);
|
||||||
this.scheduler = scheduler;
|
// Don't execute more than one connection status check at a time
|
||||||
this.appContext = appContext;
|
connectionStatusExecutor =
|
||||||
|
new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1);
|
||||||
ConnectivityManager connectivityManager = (ConnectivityManager)
|
ConnectivityManager connectivityManager = (ConnectivityManager)
|
||||||
appContext.getSystemService(CONNECTIVITY_SERVICE);
|
appContext.getSystemService(CONNECTIVITY_SERVICE);
|
||||||
if (connectivityManager == null) throw new AssertionError();
|
if (connectivityManager == null) throw new AssertionError();
|
||||||
@@ -89,19 +79,12 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
public void start() {
|
public void start() {
|
||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
running = true;
|
running = true;
|
||||||
// Register to receive network status events
|
updateConnectionStatus();
|
||||||
networkStateReceiver = new NetworkStateReceiver();
|
|
||||||
IntentFilter filter = new IntentFilter();
|
|
||||||
filter.addAction(CONNECTIVITY_ACTION);
|
|
||||||
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
|
|
||||||
appContext.registerReceiver(networkStateReceiver, filter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
if (networkStateReceiver != null)
|
|
||||||
appContext.unregisterReceiver(networkStateReceiver);
|
|
||||||
tryToClose(socket);
|
tryToClose(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,7 +103,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
return singletonList(intToInetAddress(info.getIpAddress()));
|
return singletonList(intToInetAddress(info.getIpAddress()));
|
||||||
// If we're running an access point, return its address
|
// If we're running an access point, return its address
|
||||||
if (super.getLocalIpAddresses().contains(WIFI_AP_ADDRESS))
|
if (super.getLocalIpAddresses().contains(WIFI_AP_ADDRESS))
|
||||||
return singletonList(WIFI_AP_ADDRESS);
|
return singletonList(WIFI_AP_ADDRESS);
|
||||||
// No suitable addresses
|
// No suitable addresses
|
||||||
return emptyList();
|
return emptyList();
|
||||||
}
|
}
|
||||||
@@ -152,21 +135,13 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
return SocketFactory.getDefault();
|
return SocketFactory.getDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class NetworkStateReceiver extends BroadcastReceiver {
|
@Override
|
||||||
|
public void eventOccurred(Event e) {
|
||||||
|
if (e instanceof NetworkStatusEvent) updateConnectionStatus();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
private void updateConnectionStatus() {
|
||||||
public void onReceive(Context ctx, Intent i) {
|
connectionStatusExecutor.execute(() -> {
|
||||||
if (!running) return;
|
|
||||||
if (isApEnabledEvent(i)) {
|
|
||||||
// The state change may be broadcast before the AP address is
|
|
||||||
// visible, so delay handling the event
|
|
||||||
scheduler.schedule(this::handleConnectivityChange, 1, SECONDS);
|
|
||||||
} else {
|
|
||||||
handleConnectivityChange();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleConnectivityChange() {
|
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
Collection<InetAddress> addrs = getLocalIpAddresses();
|
Collection<InetAddress> addrs = getLocalIpAddresses();
|
||||||
if (addrs.contains(WIFI_AP_ADDRESS)) {
|
if (addrs.contains(WIFI_AP_ADDRESS)) {
|
||||||
@@ -186,11 +161,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
|
|||||||
socketFactory = getSocketFactory();
|
socketFactory = getSocketFactory();
|
||||||
if (socket == null || socket.isClosed()) bind();
|
if (socket == null || socket.isClosed()) bind();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
private boolean isApEnabledEvent(Intent i) {
|
|
||||||
return WIFI_AP_STATE_CHANGED_ACTION.equals(i.getAction()) &&
|
|
||||||
i.getIntExtra(EXTRA_WIFI_STATE, 0) == WIFI_AP_STATE_ENABLED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.plugin.tcp;
|
|||||||
|
|
||||||
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;
|
||||||
@@ -11,7 +12,6 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
|||||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
@@ -28,15 +28,14 @@ public class AndroidLanTcpPluginFactory 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 EventBus eventBus;
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
|
||||||
public AndroidLanTcpPluginFactory(Executor ioExecutor,
|
public AndroidLanTcpPluginFactory(Executor ioExecutor, EventBus eventBus,
|
||||||
ScheduledExecutorService scheduler, BackoffFactory backoffFactory,
|
BackoffFactory backoffFactory, Context appContext) {
|
||||||
Context appContext) {
|
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.scheduler = scheduler;
|
this.eventBus = eventBus;
|
||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
}
|
}
|
||||||
@@ -55,7 +54,9 @@ public class AndroidLanTcpPluginFactory 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 AndroidLanTcpPlugin(ioExecutor, scheduler, backoff,
|
AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor,
|
||||||
appContext, callback, MAX_LATENCY, MAX_IDLE_TIME);
|
appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME);
|
||||||
|
eventBus.addListener(plugin);
|
||||||
|
return plugin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.plugin.Backoff;
|
||||||
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
|
import org.briarproject.bramble.util.RenewableWakeLock;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
|
||||||
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
|
import static android.content.Context.MODE_PRIVATE;
|
||||||
|
import static android.content.Context.POWER_SERVICE;
|
||||||
|
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
|
||||||
|
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
class AndroidTorPlugin extends TorPlugin {
|
||||||
|
|
||||||
|
// This tag may prevent Huawei's power manager from killing us
|
||||||
|
private static final String WAKE_LOCK_TAG = "LocationManagerService";
|
||||||
|
|
||||||
|
private final Context appContext;
|
||||||
|
private final RenewableWakeLock wakeLock;
|
||||||
|
|
||||||
|
AndroidTorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
|
||||||
|
Context appContext, NetworkManager networkManager,
|
||||||
|
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||||
|
Clock clock, ResourceProvider resourceProvider,
|
||||||
|
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||||
|
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||||
|
int maxIdleTime) {
|
||||||
|
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
|
||||||
|
clock, resourceProvider, circumventionProvider, backoff,
|
||||||
|
callback, architecture, maxLatency, maxIdleTime,
|
||||||
|
appContext.getDir("tor", MODE_PRIVATE));
|
||||||
|
this.appContext = appContext;
|
||||||
|
PowerManager pm = (PowerManager)
|
||||||
|
appContext.getSystemService(POWER_SERVICE);
|
||||||
|
assert pm != null;
|
||||||
|
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
|
||||||
|
WAKE_LOCK_TAG, 1, MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getProcessId() {
|
||||||
|
return android.os.Process.myPid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected long getLastUpdateTime() {
|
||||||
|
try {
|
||||||
|
PackageManager pm = appContext.getPackageManager();
|
||||||
|
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
|
||||||
|
return pi.lastUpdateTime;
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enableNetwork(boolean enable) throws IOException {
|
||||||
|
if (!running) return;
|
||||||
|
if (enable) wakeLock.acquire();
|
||||||
|
super.enableNetwork(enable);
|
||||||
|
if (!enable) wakeLock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
super.stop();
|
||||||
|
wakeLock.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
import org.briarproject.bramble.api.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;
|
||||||
@@ -12,7 +13,9 @@ 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.DuplexPluginFactory;
|
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
import org.briarproject.bramble.util.AndroidUtils;
|
import org.briarproject.bramble.util.AndroidUtils;
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -24,10 +27,10 @@ import javax.net.SocketFactory;
|
|||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class TorPluginFactory implements DuplexPluginFactory {
|
public class AndroidTorPluginFactory implements DuplexPluginFactory {
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(TorPluginFactory.class.getName());
|
Logger.getLogger(AndroidTorPluginFactory.class.getName());
|
||||||
|
|
||||||
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
|
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
|
||||||
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
|
||||||
@@ -38,22 +41,32 @@ public class TorPluginFactory implements DuplexPluginFactory {
|
|||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
private final ScheduledExecutorService scheduler;
|
private final ScheduledExecutorService scheduler;
|
||||||
private final Context appContext;
|
private final Context appContext;
|
||||||
|
private final NetworkManager networkManager;
|
||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
private final EventBus eventBus;
|
private final EventBus eventBus;
|
||||||
private final SocketFactory torSocketFactory;
|
private final SocketFactory torSocketFactory;
|
||||||
private final BackoffFactory backoffFactory;
|
private final BackoffFactory backoffFactory;
|
||||||
|
private final ResourceProvider resourceProvider;
|
||||||
|
private final CircumventionProvider circumventionProvider;
|
||||||
|
private final Clock clock;
|
||||||
|
|
||||||
public TorPluginFactory(Executor ioExecutor,
|
public AndroidTorPluginFactory(Executor ioExecutor,
|
||||||
ScheduledExecutorService scheduler, Context appContext,
|
ScheduledExecutorService scheduler, Context appContext,
|
||||||
LocationUtils locationUtils, EventBus eventBus,
|
NetworkManager networkManager, LocationUtils locationUtils,
|
||||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory) {
|
EventBus eventBus, SocketFactory torSocketFactory,
|
||||||
|
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
|
||||||
|
CircumventionProvider circumventionProvider, Clock clock) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.scheduler = scheduler;
|
this.scheduler = scheduler;
|
||||||
this.appContext = appContext;
|
this.appContext = appContext;
|
||||||
|
this.networkManager = networkManager;
|
||||||
this.locationUtils = locationUtils;
|
this.locationUtils = locationUtils;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.torSocketFactory = torSocketFactory;
|
this.torSocketFactory = torSocketFactory;
|
||||||
this.backoffFactory = backoffFactory;
|
this.backoffFactory = backoffFactory;
|
||||||
|
this.resourceProvider = resourceProvider;
|
||||||
|
this.circumventionProvider = circumventionProvider;
|
||||||
|
this.clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -89,9 +102,10 @@ 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, scheduler, appContext,
|
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
|
||||||
locationUtils, torSocketFactory, backoff, callback,
|
appContext, networkManager, locationUtils, torSocketFactory,
|
||||||
architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
clock, resourceProvider, circumventionProvider, backoff,
|
||||||
|
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
|
||||||
eventBus.addListener(plugin);
|
eventBus.addListener(plugin);
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package org.briarproject.bramble.plugin.tor;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
class TorNetworkMetadata {
|
|
||||||
|
|
||||||
// See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
|
||||||
// and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
|
|
||||||
// TODO: get a more complete list
|
|
||||||
private static final Set<String> BLOCKED_IN_COUNTRIES =
|
|
||||||
new HashSet<>(Arrays.asList("CN", "IR", "SY", "ZZ"));
|
|
||||||
|
|
||||||
static boolean isTorProbablyBlocked(String countryCode) {
|
|
||||||
return BLOCKED_IN_COUNTRIES.contains(countryCode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package org.briarproject.bramble.system;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
class AndroidResourceProvider implements ResourceProvider {
|
||||||
|
|
||||||
|
private final Context appContext;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AndroidResourceProvider(Application app) {
|
||||||
|
this.appContext = app.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getResourceInputStream(String name) {
|
||||||
|
Resources res = appContext.getResources();
|
||||||
|
int resId = res.getIdentifier(name, "raw", appContext.getPackageName());
|
||||||
|
return res.openRawResource(resId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
package org.briarproject.bramble.system;
|
package org.briarproject.bramble.system;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
|
|
||||||
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.ResourceProvider;
|
||||||
import org.briarproject.bramble.api.system.SecureRandomProvider;
|
import org.briarproject.bramble.api.system.SecureRandomProvider;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
@@ -16,18 +15,26 @@ public class AndroidSystemModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
SecureRandomProvider provideSecureRandomProvider(Application app) {
|
SecureRandomProvider provideSecureRandomProvider(
|
||||||
return new AndroidSecureRandomProvider(app);
|
AndroidSecureRandomProvider provider) {
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
LocationUtils provideLocationUtils(Application app) {
|
LocationUtils provideLocationUtils(AndroidLocationUtils locationUtils) {
|
||||||
return new AndroidLocationUtils(app);
|
return locationUtils;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
AndroidExecutor provideAndroidExecutor(Application app) {
|
AndroidExecutor provideAndroidExecutor(
|
||||||
return new AndroidExecutorImpl(app);
|
AndroidExecutorImpl androidExecutor) {
|
||||||
|
return androidExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.briarproject.bramble.util;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
@@ -58,30 +57,6 @@ public class AndroidUtils {
|
|||||||
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
|
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void deleteAppData(Context ctx, SharedPreferences... clear) {
|
|
||||||
// Clear and commit shared preferences
|
|
||||||
for (SharedPreferences prefs : clear) {
|
|
||||||
if (!prefs.edit().clear().commit())
|
|
||||||
LOG.warning("Could not clear shared preferences");
|
|
||||||
}
|
|
||||||
// Delete files, except lib and shared_prefs directories
|
|
||||||
File dataDir = new File(ctx.getApplicationInfo().dataDir);
|
|
||||||
File[] children = dataDir.listFiles();
|
|
||||||
if (children == null) {
|
|
||||||
LOG.warning("Could not list files in app data dir");
|
|
||||||
} else {
|
|
||||||
for (File child : children) {
|
|
||||||
String name = child.getName();
|
|
||||||
if (!name.equals("lib") && !name.equals("shared_prefs")) {
|
|
||||||
IoUtils.deleteFileOrDir(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Recreate the cache dir as some OpenGL drivers expect it to exist
|
|
||||||
if (!new File(dataDir, "cache").mkdir())
|
|
||||||
LOG.warning("Could not recreate cache dir");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static File getReportDir(Context ctx) {
|
public static File getReportDir(Context ctx) {
|
||||||
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
|
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package org.briarproject.bramble.util;
|
||||||
|
|
||||||
|
import android.os.PowerManager;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
|
|
||||||
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
|
import static java.util.logging.Level.INFO;
|
||||||
|
|
||||||
|
@ThreadSafe
|
||||||
|
@NotNullByDefault
|
||||||
|
public class RenewableWakeLock {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(RenewableWakeLock.class.getName());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically release the lock this many milliseconds after it's due
|
||||||
|
* to have been replaced and released.
|
||||||
|
*/
|
||||||
|
private static final int SAFETY_MARGIN_MS = 10_000;
|
||||||
|
|
||||||
|
private final PowerManager powerManager;
|
||||||
|
private final ScheduledExecutorService scheduler;
|
||||||
|
private final int levelAndFlags;
|
||||||
|
private final String tag;
|
||||||
|
private final long durationMs;
|
||||||
|
private final Runnable renewTask;
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
@Nullable
|
||||||
|
private PowerManager.WakeLock wakeLock; // Locking: lock
|
||||||
|
@Nullable
|
||||||
|
private ScheduledFuture future; // Locking: lock
|
||||||
|
|
||||||
|
public RenewableWakeLock(PowerManager powerManager,
|
||||||
|
ScheduledExecutorService scheduler, int levelAndFlags, String tag,
|
||||||
|
long duration, TimeUnit timeUnit) {
|
||||||
|
this.powerManager = powerManager;
|
||||||
|
this.scheduler = scheduler;
|
||||||
|
this.levelAndFlags = levelAndFlags;
|
||||||
|
this.tag = tag;
|
||||||
|
durationMs = MILLISECONDS.convert(duration, timeUnit);
|
||||||
|
renewTask = this::renew;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void acquire() {
|
||||||
|
if (LOG.isLoggable(INFO)) LOG.info("Acquiring wake lock " + tag);
|
||||||
|
synchronized (lock) {
|
||||||
|
if (wakeLock != null) {
|
||||||
|
LOG.info("Already acquired");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
|
||||||
|
wakeLock.setReferenceCounted(false);
|
||||||
|
wakeLock.acquire(durationMs + SAFETY_MARGIN_MS);
|
||||||
|
future = scheduler.schedule(renewTask, durationMs, MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renew() {
|
||||||
|
if (LOG.isLoggable(INFO)) LOG.info("Renewing wake lock " + tag);
|
||||||
|
synchronized (lock) {
|
||||||
|
if (wakeLock == null) {
|
||||||
|
LOG.info("Already released");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PowerManager.WakeLock oldWakeLock = wakeLock;
|
||||||
|
wakeLock = powerManager.newWakeLock(levelAndFlags, tag);
|
||||||
|
wakeLock.setReferenceCounted(false);
|
||||||
|
wakeLock.acquire(durationMs + SAFETY_MARGIN_MS);
|
||||||
|
oldWakeLock.release();
|
||||||
|
future = scheduler.schedule(renewTask, durationMs, MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void release() {
|
||||||
|
if (LOG.isLoggable(INFO)) LOG.info("Releasing wake lock " + tag);
|
||||||
|
synchronized (lock) {
|
||||||
|
if (wakeLock == null) {
|
||||||
|
LOG.info("Already released");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (future == null) throw new AssertionError();
|
||||||
|
future.cancel(false);
|
||||||
|
future = null;
|
||||||
|
wakeLock.release();
|
||||||
|
wakeLock = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
8
bramble-android/src/main/res/raw/bridges
Normal file
8
bramble-android/src/main/res/raw/bridges
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
|
||||||
|
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
|
||||||
|
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
|
||||||
|
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
|
||||||
|
Bridge 195.91.239.8:9001 BA83F62551545655BBEBBFF353A45438D73FD45A
|
||||||
|
Bridge 185.165.184.217:6429 64CC94BEC51254E4409AD059192833854CCB95F0
|
||||||
|
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
|
||||||
|
Bridge 95.85.40.163:9001 40057BE9CF76B6C5BDBE713753468BE0A990DE9C
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
package org.briarproject.bramble.account;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
|
import org.jmock.Expectations;
|
||||||
|
import org.jmock.lib.legacy.ClassImposteriser;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
|
|
||||||
|
public class AndroidAccountManagerTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
|
private final SharedPreferences prefs =
|
||||||
|
context.mock(SharedPreferences.class, "prefs");
|
||||||
|
private final SharedPreferences defaultPrefs =
|
||||||
|
context.mock(SharedPreferences.class, "defaultPrefs");
|
||||||
|
private final DatabaseConfig databaseConfig =
|
||||||
|
context.mock(DatabaseConfig.class);
|
||||||
|
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
|
||||||
|
private final IdentityManager identityManager =
|
||||||
|
context.mock(IdentityManager.class);
|
||||||
|
private final SharedPreferences.Editor
|
||||||
|
editor = context.mock(SharedPreferences.Editor.class);
|
||||||
|
private final Application app;
|
||||||
|
private final ApplicationInfo applicationInfo;
|
||||||
|
|
||||||
|
private final String encryptedKeyHex = toHexString(getRandomBytes(123));
|
||||||
|
private final File testDir = getTestDirectory();
|
||||||
|
private final File keyDir = new File(testDir, "key");
|
||||||
|
private final File keyFile = new File(keyDir, "db.key");
|
||||||
|
private final File keyBackupFile = new File(keyDir, "db.key.bak");
|
||||||
|
private final File dbDir = new File(testDir, "db");
|
||||||
|
|
||||||
|
private AndroidAccountManager accountManager;
|
||||||
|
|
||||||
|
public AndroidAccountManagerTest() {
|
||||||
|
context.setImposteriser(ClassImposteriser.INSTANCE);
|
||||||
|
app = context.mock(Application.class);
|
||||||
|
applicationInfo = new ApplicationInfo();
|
||||||
|
applicationInfo.dataDir = testDir.getAbsolutePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
allowing(databaseConfig).getDatabaseDirectory();
|
||||||
|
will(returnValue(dbDir));
|
||||||
|
allowing(databaseConfig).getDatabaseKeyDirectory();
|
||||||
|
will(returnValue(keyDir));
|
||||||
|
allowing(app).getApplicationContext();
|
||||||
|
will(returnValue(app));
|
||||||
|
}});
|
||||||
|
accountManager = new AndroidAccountManager(databaseConfig, crypto,
|
||||||
|
identityManager, prefs, app) {
|
||||||
|
@Override
|
||||||
|
SharedPreferences getDefaultSharedPreferences() {
|
||||||
|
return defaultPrefs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDbKeyIsMigratedFromPreferencesToFile() {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(prefs).getString("key", null);
|
||||||
|
will(returnValue(encryptedKeyHex));
|
||||||
|
oneOf(prefs).edit();
|
||||||
|
will(returnValue(editor));
|
||||||
|
oneOf(editor).remove("key");
|
||||||
|
will(returnValue(editor));
|
||||||
|
oneOf(editor).commit();
|
||||||
|
will(returnValue(true));
|
||||||
|
}});
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex,
|
||||||
|
accountManager.loadEncryptedDatabaseKey());
|
||||||
|
|
||||||
|
assertTrue(keyFile.exists());
|
||||||
|
assertTrue(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteAccountClearsSharedPrefsAndDeletesFiles()
|
||||||
|
throws Exception {
|
||||||
|
// Directories 'lib' and 'shared_prefs' should be spared
|
||||||
|
File libDir = new File(testDir, "lib");
|
||||||
|
File libFile = new File(libDir, "file");
|
||||||
|
File sharedPrefsDir = new File(testDir, "shared_prefs");
|
||||||
|
File sharedPrefsFile = new File(sharedPrefsDir, "file");
|
||||||
|
// Directory 'cache' should be emptied
|
||||||
|
File cacheDir = new File(testDir, "cache");
|
||||||
|
File cacheFile = new File(cacheDir, "file");
|
||||||
|
// Other directories should be deleted
|
||||||
|
File potatoDir = new File(testDir, ".potato");
|
||||||
|
File potatoFile = new File(potatoDir, "file");
|
||||||
|
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(prefs).edit();
|
||||||
|
will(returnValue(editor));
|
||||||
|
oneOf(editor).clear();
|
||||||
|
will(returnValue(editor));
|
||||||
|
oneOf(editor).commit();
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(defaultPrefs).edit();
|
||||||
|
will(returnValue(editor));
|
||||||
|
oneOf(editor).clear();
|
||||||
|
will(returnValue(editor));
|
||||||
|
oneOf(editor).commit();
|
||||||
|
will(returnValue(true));
|
||||||
|
oneOf(app).getApplicationInfo();
|
||||||
|
will(returnValue(applicationInfo));
|
||||||
|
}});
|
||||||
|
|
||||||
|
assertTrue(dbDir.mkdirs());
|
||||||
|
assertTrue(keyDir.mkdirs());
|
||||||
|
assertTrue(libDir.mkdirs());
|
||||||
|
assertTrue(libFile.createNewFile());
|
||||||
|
assertTrue(sharedPrefsDir.mkdirs());
|
||||||
|
assertTrue(sharedPrefsFile.createNewFile());
|
||||||
|
assertTrue(cacheDir.mkdirs());
|
||||||
|
assertTrue(cacheFile.createNewFile());
|
||||||
|
assertTrue(potatoDir.mkdirs());
|
||||||
|
assertTrue(potatoFile.createNewFile());
|
||||||
|
|
||||||
|
accountManager.deleteAccount();
|
||||||
|
|
||||||
|
assertFalse(dbDir.exists());
|
||||||
|
assertFalse(keyDir.exists());
|
||||||
|
assertTrue(libDir.exists());
|
||||||
|
assertTrue(libFile.exists());
|
||||||
|
assertTrue(sharedPrefsDir.exists());
|
||||||
|
assertTrue(sharedPrefsFile.exists());
|
||||||
|
assertTrue(cacheDir.exists());
|
||||||
|
assertFalse(cacheFile.exists());
|
||||||
|
assertFalse(potatoDir.exists());
|
||||||
|
assertFalse(potatoFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
deleteTestDirectory(testDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
94
bramble-android/witness.gradle
Normal file
94
bramble-android/witness.gradle
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
dependencyVerification {
|
||||||
|
verify = [
|
||||||
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
|
'com.android.support.test:monitor:1.0.2:monitor-1.0.2.aar:38ef4fa98a32dc55550ff49bb36a583e178b3a9b830fcb8dcc27bfc4254bc2bc',
|
||||||
|
'com.android.support.test:runner:1.0.2:runner-1.0.2.aar:f04b9ae342975ba1cb3e4a06e13426e3e6b8a73faa45acba604493d83c9a4f00',
|
||||||
|
'com.android.support:support-annotations:27.1.1:support-annotations-27.1.1.jar:3365960206c3d2b09e845f555e7f88f8effc8d2f00b369e66c4be384029299cf',
|
||||||
|
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
|
||||||
|
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
|
||||||
|
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
|
||||||
|
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
|
||||||
|
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
|
||||||
|
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
|
||||||
|
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
|
||||||
|
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
|
||||||
|
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
|
||||||
|
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
|
||||||
|
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
|
||||||
|
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
|
||||||
|
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
|
||||||
|
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
|
||||||
|
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
|
||||||
|
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
|
||||||
|
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
|
||||||
|
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
|
||||||
|
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
|
||||||
|
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
|
||||||
|
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
|
||||||
|
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
|
||||||
|
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
|
||||||
|
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
|
||||||
|
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
|
||||||
|
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
|
||||||
|
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
|
||||||
|
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
|
||||||
|
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
||||||
|
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
||||||
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
|
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
|
||||||
|
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
||||||
|
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
|
||||||
|
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
|
||||||
|
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
|
||||||
|
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
|
||||||
|
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
|
||||||
|
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
||||||
|
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||||
|
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
|
||||||
|
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
|
||||||
|
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
|
||||||
|
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
|
||||||
|
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
|
||||||
|
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
|
||||||
|
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
|
||||||
|
'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2',
|
||||||
|
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
|
||||||
|
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
|
||||||
|
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
|
||||||
|
'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.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
|
||||||
|
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
|
||||||
|
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
|
||||||
|
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
|
||||||
|
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
|
||||||
|
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
|
||||||
|
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
|
||||||
|
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
|
||||||
|
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
|
||||||
|
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
|
||||||
|
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
|
||||||
|
'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70',
|
||||||
|
'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea',
|
||||||
|
'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.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
|
||||||
|
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
|
||||||
|
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
|
||||||
|
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
|
||||||
|
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
|
||||||
|
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
|
||||||
|
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
|
||||||
|
'org.jmock:jmock-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.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
|
||||||
|
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
|
||||||
|
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
|
||||||
|
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
|
||||||
|
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
|
||||||
|
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
|
||||||
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
|
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ targetCompatibility = 1.8
|
|||||||
|
|
||||||
apply plugin: 'ru.vyarus.animalsniffer'
|
apply plugin: 'ru.vyarus.animalsniffer'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
|
apply from: 'witness.gradle'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "com.google.dagger:dagger:2.0.2"
|
implementation "com.google.dagger:dagger:2.0.2"
|
||||||
@@ -19,31 +20,6 @@ dependencies {
|
|||||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
|
||||||
verify = [
|
|
||||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
|
||||||
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
|
||||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
|
||||||
'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.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
|
|
||||||
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
|
|
||||||
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
|
|
||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
|
||||||
'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-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
|
||||||
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// needed to make test output available to bramble-core and briar-core
|
// needed to make test output available to bramble-core and briar-core
|
||||||
configurations {
|
configurations {
|
||||||
testOutput.extendsFrom(testCompile)
|
testOutput.extendsFrom(testCompile)
|
||||||
@@ -55,3 +31,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
|
|||||||
artifacts {
|
artifacts {
|
||||||
testOutput jarTest
|
testOutput jarTest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test) {
|
||||||
|
// Use entropy-gathering device specified on command line, if any
|
||||||
|
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package org.briarproject.bramble.api.account;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface AccountManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the manager has the database key. This will be false
|
||||||
|
* before {@link #createAccount(String, String)} or {@link #signIn(String)}
|
||||||
|
* has been called, and true after {@link #createAccount(String, String)}
|
||||||
|
* or {@link #signIn(String)} has returned true, until the process exits.
|
||||||
|
*/
|
||||||
|
boolean hasDatabaseKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the database key if the manager has it. This will be null
|
||||||
|
* before {@link #createAccount(String, String)} or {@link #signIn(String)}
|
||||||
|
* has been called, and non-null after
|
||||||
|
* {@link #createAccount(String, String)} or {@link #signIn(String)} has
|
||||||
|
* returned true, until the process exits.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
SecretKey getDatabaseKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the encrypted database key can be loaded from disk, and
|
||||||
|
* the database directory exists and is a directory.
|
||||||
|
*/
|
||||||
|
boolean accountExists();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an identity with the given name and registers it with the
|
||||||
|
* {@link IdentityManager}. Creates a database key, encrypts it with the
|
||||||
|
* given password and stores it on disk.
|
||||||
|
* <p/>
|
||||||
|
* This method does not create the database directory, so
|
||||||
|
* {@link #accountExists()} will continue to return false until the
|
||||||
|
* database directory is created.
|
||||||
|
*/
|
||||||
|
boolean createAccount(String name, String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all account state from disk. {@link #accountExists()} will
|
||||||
|
* return false after this method returns.
|
||||||
|
*/
|
||||||
|
void deleteAccount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the encrypted database key from disk and decrypts it with the
|
||||||
|
* given password.
|
||||||
|
*
|
||||||
|
* @return true if the database key was successfully loaded and decrypted.
|
||||||
|
*/
|
||||||
|
boolean signIn(String password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the encrypted database key from disk, decrypts it with the old
|
||||||
|
* password, encrypts it with the new password, and stores it on disk,
|
||||||
|
* replacing the old key.
|
||||||
|
*
|
||||||
|
* @return true if the database key was successfully loaded, re-encrypted
|
||||||
|
* and stored.
|
||||||
|
*/
|
||||||
|
boolean changePassword(String oldPassword, String newPassword);
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ public interface ContactManager {
|
|||||||
/**
|
/**
|
||||||
* Registers a hook to be called whenever a contact is added or removed.
|
* Registers a hook to be called whenever a contact is added or removed.
|
||||||
* This method should be called before
|
* This method should be called before
|
||||||
* {@link LifecycleManager#startServices(String)}.
|
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerContactHook(ContactHook hook);
|
void registerContactHook(ContactHook hook);
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.identity.Author;
|
import org.briarproject.bramble.api.identity.Author;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
@@ -44,7 +45,8 @@ public interface DatabaseComponent {
|
|||||||
* @throws DataTooOldException if the data uses an older schema than the
|
* @throws DataTooOldException if the data uses an older schema than the
|
||||||
* current code and cannot be migrated
|
* current code and cannot be migrated
|
||||||
*/
|
*/
|
||||||
boolean open(@Nullable MigrationListener listener) throws DbException;
|
boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waits for any open transactions to finish and closes the database.
|
* Waits for any open transactions to finish and closes the database.
|
||||||
@@ -267,7 +269,7 @@ public interface DatabaseComponent {
|
|||||||
* Read-only.
|
* Read-only.
|
||||||
*/
|
*/
|
||||||
Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
|
Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IDs of any messages that need to be validated.
|
* Returns the IDs of any messages that need to be validated.
|
||||||
@@ -487,7 +489,7 @@ public interface DatabaseComponent {
|
|||||||
* Removes the given transport keys from the database.
|
* Removes the given transport keys from the database.
|
||||||
*/
|
*/
|
||||||
void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
|
void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks the given contact as verified.
|
* Marks the given contact as verified.
|
||||||
@@ -534,7 +536,7 @@ public interface DatabaseComponent {
|
|||||||
* Marks the given transport keys as usable for outgoing streams.
|
* Marks the given transport keys as usable for outgoing streams.
|
||||||
*/
|
*/
|
||||||
void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
|
void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the given transport keys, deleting any keys they have replaced.
|
* Stores the given transport keys, deleting any keys they have replaced.
|
||||||
|
|||||||
@@ -1,30 +1,15 @@
|
|||||||
package org.briarproject.bramble.api.db;
|
package org.briarproject.bramble.api.db;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public interface DatabaseConfig {
|
public interface DatabaseConfig {
|
||||||
|
|
||||||
boolean databaseExists();
|
|
||||||
|
|
||||||
File getDatabaseDirectory();
|
File getDatabaseDirectory();
|
||||||
|
|
||||||
File getDatabaseKeyDirectory();
|
File getDatabaseKeyDirectory();
|
||||||
|
|
||||||
void setEncryptionKey(SecretKey key);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
SecretKey getEncryptionKey();
|
|
||||||
|
|
||||||
void setLocalAuthorName(String nickname);
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
String getLocalAuthorName();
|
|
||||||
|
|
||||||
long getMaxSize();
|
long getMaxSize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.api.identity;
|
package org.briarproject.bramble.api.identity;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoExecutor;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.identity.Author.Status;
|
import org.briarproject.bramble.api.identity.Author.Status;
|
||||||
@@ -9,29 +10,40 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
public interface IdentityManager {
|
public interface IdentityManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores the local pseudonym.
|
* Creates a local identity with the given name.
|
||||||
*/
|
*/
|
||||||
void registerLocalAuthor(LocalAuthor a) throws DbException;
|
@CryptoExecutor
|
||||||
|
LocalAuthor createLocalAuthor(String name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cached main local identity, non-blocking, or loads it from
|
* Registers the given local identity with the manager. The identity is
|
||||||
* the db, blocking
|
* not stored until {@link #storeLocalAuthor()} is called.
|
||||||
|
*/
|
||||||
|
void registerLocalAuthor(LocalAuthor a);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the local identity registered with
|
||||||
|
* {@link #registerLocalAuthor(LocalAuthor)}, if any.
|
||||||
|
*/
|
||||||
|
void storeLocalAuthor() throws DbException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the cached local identity or loads it from the database.
|
||||||
*/
|
*/
|
||||||
LocalAuthor getLocalAuthor() throws DbException;
|
LocalAuthor getLocalAuthor() throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the cached main local identity, non-blocking, or loads it from
|
* Returns the cached local identity or loads it from the database.
|
||||||
* the db, blocking, within the given Transaction.
|
|
||||||
*/
|
*/
|
||||||
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
|
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the trust-level status of the author
|
* Returns the {@link Status} of the given author.
|
||||||
*/
|
*/
|
||||||
Status getAuthorStatus(AuthorId a) throws DbException;
|
Status getAuthorStatus(AuthorId a) throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the trust-level status of the author
|
* Returns the {@link Status} of the given author.
|
||||||
*/
|
*/
|
||||||
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
|
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,6 @@ public interface KeyAgreementConstants {
|
|||||||
*/
|
*/
|
||||||
byte PROTOCOL_VERSION = 4;
|
byte PROTOCOL_VERSION = 4;
|
||||||
|
|
||||||
/**
|
|
||||||
* The length of the record header in bytes.
|
|
||||||
*/
|
|
||||||
int RECORD_HEADER_LENGTH = 4;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The offset of the payload length in the record header, in bytes.
|
|
||||||
*/
|
|
||||||
int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The length of the BQP key commitment in bytes.
|
* The length of the BQP key commitment in bytes.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation for injecting the executor for long-running IO tasks. Also used
|
* Annotation for injecting the executor for long-running IO tasks. Also used
|
||||||
* for annotating methods that should run on the UI executor.
|
* for annotating methods that should run on the IO executor.
|
||||||
* <p>
|
* <p>
|
||||||
* The contract of this executor is that tasks may be run concurrently, and
|
* The contract of this executor is that tasks may be run concurrently, and
|
||||||
* submitting a task will never block. Tasks may run indefinitely. Tasks
|
* submitting a task will never block. Tasks may run indefinitely. Tasks
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package org.briarproject.bramble.api.lifecycle;
|
package org.briarproject.bramble.api.lifecycle;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.sync.Client;
|
import org.briarproject.bramble.api.sync.Client;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the lifecycle of the app, starting {@link Client Clients}, starting
|
* Manages the lifecycle of the app, starting {@link Client Clients}, starting
|
||||||
* and stopping {@link Service Services}, shutting down
|
* and stopping {@link Service Services}, shutting down
|
||||||
@@ -18,7 +17,7 @@ import javax.annotation.Nullable;
|
|||||||
public interface LifecycleManager {
|
public interface LifecycleManager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The result of calling {@link #startServices(String)}.
|
* The result of calling {@link #startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
enum StartResult {
|
enum StartResult {
|
||||||
ALREADY_RUNNING,
|
ALREADY_RUNNING,
|
||||||
@@ -44,28 +43,27 @@ public interface LifecycleManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a {@link Service} to be started and stopped. This method
|
* Registers a {@link Service} to be started and stopped. This method
|
||||||
* should be called before {@link #startServices(String)}.
|
* should be called before {@link #startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerService(Service s);
|
void registerService(Service s);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a {@link Client} to be started. This method should be called
|
* Registers a {@link Client} to be started. This method should be called
|
||||||
* before {@link #startServices(String)}.
|
* before {@link #startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerClient(Client c);
|
void registerClient(Client c);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an {@link ExecutorService} to be shut down. This method
|
* Registers an {@link ExecutorService} to be shut down. This method
|
||||||
* should be called before {@link #startServices(String)}.
|
* should be called before {@link #startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerForShutdown(ExecutorService e);
|
void registerForShutdown(ExecutorService e);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the {@link DatabaseComponent}, optionally creates a local author
|
* Opens the {@link DatabaseComponent} using the given key and starts any
|
||||||
* with the provided nickname, and starts any registered
|
* registered {@link Client Clients} and {@link Service Services}.
|
||||||
* {@link Client Clients} and {@link Service Services}.
|
|
||||||
*/
|
*/
|
||||||
StartResult startServices(@Nullable String nickname);
|
StartResult startServices(SecretKey dbKey);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops any registered {@link Service Services}, shuts down any
|
* Stops any registered {@link Service Services}, shuts down any
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.briarproject.bramble.api.network;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface NetworkManager {
|
||||||
|
|
||||||
|
NetworkStatus getNetworkStatus();
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package org.briarproject.bramble.api.network;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
public class NetworkStatus {
|
||||||
|
|
||||||
|
private final boolean connected, wifi;
|
||||||
|
|
||||||
|
public NetworkStatus(boolean connected, boolean wifi) {
|
||||||
|
this.connected = connected;
|
||||||
|
this.wifi = wifi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWifi() {
|
||||||
|
return wifi;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package org.briarproject.bramble.api.network.event;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.event.Event;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkStatus;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
@NotNullByDefault
|
||||||
|
public class NetworkStatusEvent extends Event {
|
||||||
|
|
||||||
|
private final NetworkStatus status;
|
||||||
|
|
||||||
|
public NetworkStatusEvent(NetworkStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetworkStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ public interface TorConstants {
|
|||||||
|
|
||||||
String PREF_TOR_NETWORK = "network";
|
String PREF_TOR_NETWORK = "network";
|
||||||
String PREF_TOR_PORT = "port";
|
String PREF_TOR_PORT = "port";
|
||||||
|
String PREF_TOR_DISABLE_BLOCKED = "disableWhenBlocked";
|
||||||
|
|
||||||
int PREF_TOR_NETWORK_NEVER = 0;
|
int PREF_TOR_NETWORK_NEVER = 0;
|
||||||
int PREF_TOR_NETWORK_WIFI = 1;
|
int PREF_TOR_NETWORK_WIFI = 1;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.api.sync;
|
package org.briarproject.bramble.api.sync;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Metadata;
|
import org.briarproject.bramble.api.db.Metadata;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
@@ -35,7 +36,8 @@ public interface ValidationManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the message validator for the given client. This method
|
* Registers the message validator for the given client. This method
|
||||||
* should be called before {@link LifecycleManager#startServices(String)}.
|
* should be called before
|
||||||
|
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerMessageValidator(ClientId c, int majorVersion,
|
void registerMessageValidator(ClientId c, int majorVersion,
|
||||||
MessageValidator v);
|
MessageValidator v);
|
||||||
@@ -44,7 +46,7 @@ public interface ValidationManager {
|
|||||||
* Registers the incoming message hook for the given client. The hook will
|
* Registers the incoming message hook for the given client. The hook will
|
||||||
* be called once for each incoming message that passes validation. This
|
* be called once for each incoming message that passes validation. This
|
||||||
* method should be called before
|
* method should be called before
|
||||||
* {@link LifecycleManager#startServices(String)}.
|
* {@link LifecycleManager#startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerIncomingMessageHook(ClientId c, int majorVersion,
|
void registerIncomingMessageHook(ClientId c, int majorVersion,
|
||||||
IncomingMessageHook hook);
|
IncomingMessageHook hook);
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.briarproject.bramble.api.system;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
|
public interface ResourceProvider {
|
||||||
|
|
||||||
|
InputStream getResourceInputStream(String name);
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.api.versioning;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
@@ -25,7 +26,7 @@ public interface ClientVersioningManager {
|
|||||||
/**
|
/**
|
||||||
* Registers a client that will be advertised to contacts. The hook will
|
* Registers a client that will be advertised to contacts. The hook will
|
||||||
* be called when the visibility of the client changes. This method should
|
* be called when the visibility of the client changes. This method should
|
||||||
* be called before {@link LifecycleManager#startServices(String)}.
|
* be called before {@link LifecycleManager#startServices(SecretKey)}.
|
||||||
*/
|
*/
|
||||||
void registerClient(ClientId clientId, int majorVersion, int minorVersion,
|
void registerClient(ClientId clientId, int majorVersion, int minorVersion,
|
||||||
ClientVersioningHook hook);
|
ClientVersioningHook hook);
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package org.briarproject.bramble.util;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.FINE;
|
||||||
|
|
||||||
|
public class LogUtils {
|
||||||
|
|
||||||
|
private static final int NANOS_PER_MILLI = 1000 * 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the elapsed time in milliseconds since some arbitrary
|
||||||
|
* starting time. This is only useful for measuring elapsed time.
|
||||||
|
*/
|
||||||
|
public static long now() {
|
||||||
|
return System.nanoTime() / NANOS_PER_MILLI;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs the duration of a task.
|
||||||
|
* @param logger the logger to use
|
||||||
|
* @param task a description of the task
|
||||||
|
* @param start the start time of the task, as returned by {@link #now()}
|
||||||
|
*/
|
||||||
|
public static void logDuration(Logger logger, String task, long start) {
|
||||||
|
if (logger.isLoggable(FINE)) {
|
||||||
|
long duration = now() - start;
|
||||||
|
logger.fine(task + " took " + duration + " ms");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logException(Logger logger, Level level, Throwable t) {
|
||||||
|
if (logger.isLoggable(level)) logger.log(level, t.toString(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
bramble-api/witness.gradle
Normal file
24
bramble-api/witness.gradle
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
dependencyVerification {
|
||||||
|
verify = [
|
||||||
|
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
||||||
|
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
|
||||||
|
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
||||||
|
'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.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
|
||||||
|
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
|
||||||
|
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
|
||||||
|
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
||||||
|
'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-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
||||||
|
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ apply plugin: 'ru.vyarus.animalsniffer'
|
|||||||
apply plugin: 'net.ltgt.apt'
|
apply plugin: 'net.ltgt.apt'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'witness'
|
apply plugin: 'witness'
|
||||||
|
apply from: 'witness.gradle'
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(path: ':bramble-api', configuration: 'default')
|
implementation project(path: ':bramble-api', configuration: 'default')
|
||||||
@@ -14,6 +15,7 @@ dependencies {
|
|||||||
implementation 'org.bitlet:weupnp:0.1.4'
|
implementation 'org.bitlet:weupnp:0.1.4'
|
||||||
implementation 'net.i2p.crypto:eddsa:0.2.0'
|
implementation 'net.i2p.crypto:eddsa:0.2.0'
|
||||||
implementation 'org.whispersystems:curve25519-java:0.4.1'
|
implementation 'org.whispersystems:curve25519-java:0.4.1'
|
||||||
|
implementation 'org.briarproject:jtorctl:0.3'
|
||||||
|
|
||||||
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
apt 'com.google.dagger:dagger-compiler:2.0.2'
|
||||||
|
|
||||||
@@ -31,39 +33,6 @@ dependencies {
|
|||||||
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyVerification {
|
|
||||||
verify = [
|
|
||||||
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
|
|
||||||
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
|
|
||||||
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
|
|
||||||
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
|
|
||||||
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
|
|
||||||
'com.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',
|
|
||||||
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
|
|
||||||
'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.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
|
|
||||||
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
|
|
||||||
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
|
|
||||||
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
|
|
||||||
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
|
|
||||||
'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
|
|
||||||
'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-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
|
|
||||||
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
|
|
||||||
'org.whispersystems:curve25519-java:0.4.1:curve25519-java-0.4.1.jar:7dd659d8822c06c3aea1a47f18fac9e5761e29cab8100030b877db445005f03e',
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
// needed to make test output available to bramble-j2se
|
// needed to make test output available to bramble-j2se
|
||||||
configurations {
|
configurations {
|
||||||
testOutput.extendsFrom(testCompile)
|
testOutput.extendsFrom(testCompile)
|
||||||
@@ -75,3 +44,8 @@ task jarTest(type: Jar, dependsOn: testClasses) {
|
|||||||
artifacts {
|
artifacts {
|
||||||
testOutput jarTest
|
testOutput jarTest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(Test) {
|
||||||
|
// Use entropy-gathering device specified on command line, if any
|
||||||
|
systemProperty 'java.security.egd', System.getProperty('java.security.egd')
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.concurrent.GuardedBy;
|
import javax.annotation.concurrent.GuardedBy;
|
||||||
|
|
||||||
import static java.util.logging.Level.FINE;
|
import static java.util.logging.Level.FINE;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Executor} that delegates its tasks to another {@link Executor}
|
* An {@link Executor} that delegates its tasks to another {@link Executor}
|
||||||
@@ -20,8 +20,6 @@ import static java.util.logging.Level.FINE;
|
|||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class PoliteExecutor implements Executor {
|
public class PoliteExecutor implements Executor {
|
||||||
|
|
||||||
private static final Level LOG_LEVEL = FINE;
|
|
||||||
|
|
||||||
private final Object lock = new Object();
|
private final Object lock = new Object();
|
||||||
@GuardedBy("lock")
|
@GuardedBy("lock")
|
||||||
private final Queue<Runnable> queue = new LinkedList<>();
|
private final Queue<Runnable> queue = new LinkedList<>();
|
||||||
@@ -49,11 +47,11 @@ public class PoliteExecutor implements Executor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable r) {
|
public void execute(Runnable r) {
|
||||||
long submitted = System.currentTimeMillis();
|
long submitted = now();
|
||||||
Runnable wrapped = () -> {
|
Runnable wrapped = () -> {
|
||||||
if (log.isLoggable(LOG_LEVEL)) {
|
if (log.isLoggable(FINE)) {
|
||||||
long queued = System.currentTimeMillis() - submitted;
|
long queued = now() - submitted;
|
||||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
log.fine("Queue time " + queued + " ms");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
r.run();
|
r.run();
|
||||||
|
|||||||
@@ -6,16 +6,14 @@ import java.util.concurrent.BlockingQueue;
|
|||||||
import java.util.concurrent.RejectedExecutionHandler;
|
import java.util.concurrent.RejectedExecutionHandler;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.FINE;
|
import static java.util.logging.Level.FINE;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class TimeLoggingExecutor extends ThreadPoolExecutor {
|
public class TimeLoggingExecutor extends ThreadPoolExecutor {
|
||||||
|
|
||||||
private static final Level LOG_LEVEL = FINE;
|
|
||||||
|
|
||||||
private final Logger log;
|
private final Logger log;
|
||||||
|
|
||||||
public TimeLoggingExecutor(String tag, int corePoolSize, int maxPoolSize,
|
public TimeLoggingExecutor(String tag, int corePoolSize, int maxPoolSize,
|
||||||
@@ -29,15 +27,15 @@ public class TimeLoggingExecutor extends ThreadPoolExecutor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Runnable r) {
|
public void execute(Runnable r) {
|
||||||
if (log.isLoggable(LOG_LEVEL)) {
|
if (log.isLoggable(FINE)) {
|
||||||
long submitted = System.currentTimeMillis();
|
long submitted = now();
|
||||||
super.execute(() -> {
|
super.execute(() -> {
|
||||||
long started = System.currentTimeMillis();
|
long started = now();
|
||||||
long queued = started - submitted;
|
long queued = started - submitted;
|
||||||
log.log(LOG_LEVEL, "Queue time " + queued + " ms");
|
log.fine("Queue time " + queued + " ms");
|
||||||
r.run();
|
r.run();
|
||||||
long executing = System.currentTimeMillis() - started;
|
long executing = now() - started;
|
||||||
log.log(LOG_LEVEL, "Execution time " + executing + " ms");
|
log.fine("Execution time " + executing + " ms");
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
super.execute(r);
|
super.execute(r);
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
package org.briarproject.bramble.account;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.account.AccountManager;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.fromHexString;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
class AccountManagerImpl implements AccountManager {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(AccountManagerImpl.class.getName());
|
||||||
|
|
||||||
|
private static final String DB_KEY_FILENAME = "db.key";
|
||||||
|
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
|
||||||
|
|
||||||
|
private final DatabaseConfig databaseConfig;
|
||||||
|
private final CryptoComponent crypto;
|
||||||
|
private final IdentityManager identityManager;
|
||||||
|
private final File dbKeyFile, dbKeyBackupFile;
|
||||||
|
|
||||||
|
final Object stateChangeLock = new Object();
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private volatile SecretKey databaseKey = null;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AccountManagerImpl(DatabaseConfig databaseConfig, CryptoComponent crypto,
|
||||||
|
IdentityManager identityManager) {
|
||||||
|
this.databaseConfig = databaseConfig;
|
||||||
|
this.crypto = crypto;
|
||||||
|
this.identityManager = identityManager;
|
||||||
|
File keyDir = databaseConfig.getDatabaseKeyDirectory();
|
||||||
|
dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
|
||||||
|
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDatabaseKey() {
|
||||||
|
return databaseKey != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public SecretKey getDatabaseKey() {
|
||||||
|
return databaseKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
@Nullable
|
||||||
|
protected String loadEncryptedDatabaseKey() {
|
||||||
|
String key = readDbKeyFromFile(dbKeyFile);
|
||||||
|
if (key == null) {
|
||||||
|
LOG.info("No database key in primary file");
|
||||||
|
key = readDbKeyFromFile(dbKeyBackupFile);
|
||||||
|
if (key == null) LOG.info("No database key in backup file");
|
||||||
|
else LOG.warning("Found database key in backup file");
|
||||||
|
} else {
|
||||||
|
LOG.info("Found database key in primary file");
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
@Nullable
|
||||||
|
private String readDbKeyFromFile(File f) {
|
||||||
|
if (!f.exists()) {
|
||||||
|
LOG.info("Key file does not exist");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||||
|
new FileInputStream(f), "UTF-8"));
|
||||||
|
String key = reader.readLine();
|
||||||
|
reader.close();
|
||||||
|
return key;
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
protected boolean storeEncryptedDatabaseKey(String hex) {
|
||||||
|
LOG.info("Storing database key in file");
|
||||||
|
// Create the directory if necessary
|
||||||
|
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
|
||||||
|
LOG.info("Created database key directory");
|
||||||
|
// If only the backup file exists, rename it so we don't overwrite it
|
||||||
|
if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) {
|
||||||
|
if (dbKeyBackupFile.renameTo(dbKeyFile))
|
||||||
|
LOG.info("Renamed old backup");
|
||||||
|
else LOG.warning("Failed to rename old backup");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// Write to the backup file
|
||||||
|
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||||
|
LOG.info("Stored database key in backup file");
|
||||||
|
// Delete the old primary file, if it exists
|
||||||
|
if (dbKeyFile.exists()) {
|
||||||
|
if (dbKeyFile.delete()) LOG.info("Deleted primary file");
|
||||||
|
else LOG.warning("Failed to delete primary file");
|
||||||
|
}
|
||||||
|
// The backup file becomes the new primary
|
||||||
|
if (dbKeyBackupFile.renameTo(dbKeyFile)) {
|
||||||
|
LOG.info("Renamed backup file to primary");
|
||||||
|
} else {
|
||||||
|
LOG.warning("Failed to rename backup file to primary");
|
||||||
|
return false; // Don't overwrite our only copy
|
||||||
|
}
|
||||||
|
// Write a second copy to the backup file
|
||||||
|
writeDbKeyToFile(hex, dbKeyBackupFile);
|
||||||
|
LOG.info("Stored second copy of database key in backup file");
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
private void writeDbKeyToFile(String key, File f) throws IOException {
|
||||||
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
|
out.write(key.getBytes("UTF-8"));
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accountExists() {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
return loadEncryptedDatabaseKey() != null
|
||||||
|
&& databaseConfig.getDatabaseDirectory().isDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createAccount(String name, String password) {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
LocalAuthor localAuthor = identityManager.createLocalAuthor(name);
|
||||||
|
identityManager.registerLocalAuthor(localAuthor);
|
||||||
|
SecretKey key = crypto.generateSecretKey();
|
||||||
|
if (!encryptAndStoreDatabaseKey(key, password)) return false;
|
||||||
|
databaseKey = key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
private boolean encryptAndStoreDatabaseKey(SecretKey key, String password) {
|
||||||
|
byte[] plaintext = key.getBytes();
|
||||||
|
byte[] ciphertext = crypto.encryptWithPassword(plaintext, password);
|
||||||
|
return storeEncryptedDatabaseKey(toHexString(ciphertext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteAccount() {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
LOG.info("Deleting account");
|
||||||
|
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseKeyDirectory());
|
||||||
|
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean signIn(String password) {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
SecretKey key = loadAndDecryptDatabaseKey(password);
|
||||||
|
if (key == null) return false;
|
||||||
|
databaseKey = key;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locking: stateChangeLock
|
||||||
|
@Nullable
|
||||||
|
private SecretKey loadAndDecryptDatabaseKey(String password) {
|
||||||
|
String hex = loadEncryptedDatabaseKey();
|
||||||
|
if (hex == null) {
|
||||||
|
LOG.warning("Failed to load encrypted database key");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
byte[] ciphertext = fromHexString(hex);
|
||||||
|
byte[] plaintext = crypto.decryptWithPassword(ciphertext, password);
|
||||||
|
if (plaintext == null) {
|
||||||
|
LOG.info("Failed to decrypt database key");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new SecretKey(plaintext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean changePassword(String oldPassword, String newPassword) {
|
||||||
|
synchronized (stateChangeLock) {
|
||||||
|
SecretKey key = loadAndDecryptDatabaseKey(oldPassword);
|
||||||
|
return key != null && encryptAndStoreDatabaseKey(key, newPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package org.briarproject.bramble.account;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.account.AccountManager;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class AccountModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
AccountManager provideAccountManager(AccountManagerImpl accountManager) {
|
||||||
|
return accountManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,6 +46,7 @@ import javax.inject.Inject;
|
|||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
|
import static org.briarproject.bramble.api.contact.RecordTypes.CONTACT_INFO;
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
|
||||||
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
import static org.briarproject.bramble.util.ValidationUtils.checkSize;
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
in = conn.getReader().getInputStream();
|
in = conn.getReader().getInputStream();
|
||||||
out = conn.getWriter().getOutputStream();
|
out = conn.getWriter().getOutputStream();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
listener.contactExchangeFailed();
|
listener.contactExchangeFailed();
|
||||||
tryToClose(conn);
|
tryToClose(conn);
|
||||||
return;
|
return;
|
||||||
@@ -133,7 +134,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
try {
|
try {
|
||||||
localProperties = transportPropertyManager.getLocalProperties();
|
localProperties = transportPropertyManager.getLocalProperties();
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
listener.contactExchangeFailed();
|
listener.contactExchangeFailed();
|
||||||
tryToClose(conn);
|
tryToClose(conn);
|
||||||
return;
|
return;
|
||||||
@@ -194,7 +195,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
LOG.info("End of stream");
|
LOG.info("End of stream");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
listener.contactExchangeFailed();
|
listener.contactExchangeFailed();
|
||||||
tryToClose(conn);
|
tryToClose(conn);
|
||||||
return;
|
return;
|
||||||
@@ -222,11 +223,11 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
LOG.info("Pseudonym exchange succeeded");
|
LOG.info("Pseudonym exchange succeeded");
|
||||||
listener.contactExchangeSucceeded(remoteInfo.author);
|
listener.contactExchangeSucceeded(remoteInfo.author);
|
||||||
} catch (ContactExistsException e) {
|
} catch (ContactExistsException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
tryToClose(conn);
|
tryToClose(conn);
|
||||||
listener.duplicateContact(remoteInfo.author);
|
listener.duplicateContact(remoteInfo.author);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
tryToClose(conn);
|
tryToClose(conn);
|
||||||
listener.contactExchangeFailed();
|
listener.contactExchangeFailed();
|
||||||
}
|
}
|
||||||
@@ -307,7 +308,7 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
|
|||||||
conn.getReader().dispose(true, true);
|
conn.getReader().dispose(true, true);
|
||||||
conn.getWriter().dispose(true);
|
conn.getWriter().dispose(true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
import static org.briarproject.bramble.util.ByteUtils.INT_32_BYTES;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class CryptoComponentImpl implements CryptoComponent {
|
class CryptoComponentImpl implements CryptoComponent {
|
||||||
@@ -127,16 +129,14 @@ class CryptoComponentImpl implements CryptoComponent {
|
|||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
if (!(pub instanceof Curve25519PublicKey))
|
if (!(pub instanceof Curve25519PublicKey))
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
long now = System.currentTimeMillis();
|
long start = now();
|
||||||
byte[] secret = curve25519.calculateAgreement(pub.getEncoded(),
|
byte[] secret = curve25519.calculateAgreement(pub.getEncoded(),
|
||||||
priv.getEncoded());
|
priv.getEncoded());
|
||||||
// If the shared secret is all zeroes, the public key is invalid
|
// If the shared secret is all zeroes, the public key is invalid
|
||||||
byte allZero = 0;
|
byte allZero = 0;
|
||||||
for (byte b : secret) allZero |= b;
|
for (byte b : secret) allZero |= b;
|
||||||
if (allZero == 0) throw new GeneralSecurityException();
|
if (allZero == 0) throw new GeneralSecurityException();
|
||||||
long duration = System.currentTimeMillis() - now;
|
logDuration(LOG, "Deriving shared secret", start);
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Deriving shared secret took " + duration + " ms");
|
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import java.util.logging.Logger;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
class ScryptKdf implements PasswordBasedKdf {
|
class ScryptKdf implements PasswordBasedKdf {
|
||||||
|
|
||||||
@@ -50,13 +52,11 @@ class ScryptKdf implements PasswordBasedKdf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SecretKey deriveKey(String password, byte[] salt, int cost) {
|
public SecretKey deriveKey(String password, byte[] salt, int cost) {
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
byte[] passwordBytes = StringUtils.toUtf8(password);
|
byte[] passwordBytes = StringUtils.toUtf8(password);
|
||||||
SecretKey k = new SecretKey(SCrypt.generate(passwordBytes, salt, cost,
|
SecretKey k = new SecretKey(SCrypt.generate(passwordBytes, salt, cost,
|
||||||
BLOCK_SIZE, PARALLELIZATION, SecretKey.LENGTH));
|
BLOCK_SIZE, PARALLELIZATION, SecretKey.LENGTH));
|
||||||
long duration = System.currentTimeMillis() - start;
|
logDuration(LOG, "Deriving key from password", start);
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Deriving key from password took " + duration + " ms");
|
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key parser that uses the encoding defined in "SEC 1: Elliptic Curve
|
* A key parser that uses the encoding defined in "SEC 1: Elliptic Curve
|
||||||
@@ -48,7 +49,7 @@ class Sec1KeyParser implements KeyParser {
|
|||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
// The validation procedure comes from SEC 1, section 3.2.2.1. Note
|
// The validation procedure comes from SEC 1, section 3.2.2.1. Note
|
||||||
// that SEC 1 parameter names are used below, not RFC 5639 names
|
// that SEC 1 parameter names are used below, not RFC 5639 names
|
||||||
long now = System.currentTimeMillis();
|
long start = now();
|
||||||
if (encodedKey.length != publicKeyBytes)
|
if (encodedKey.length != publicKeyBytes)
|
||||||
throw new GeneralSecurityException();
|
throw new GeneralSecurityException();
|
||||||
// The first byte must be 0x04
|
// The first byte must be 0x04
|
||||||
@@ -80,16 +81,14 @@ class Sec1KeyParser implements KeyParser {
|
|||||||
// Construct a public key from the point (x, y) and the params
|
// Construct a public key from the point (x, y) and the params
|
||||||
ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params);
|
ECPublicKeyParameters k = new ECPublicKeyParameters(pub, params);
|
||||||
PublicKey p = new Sec1PublicKey(k);
|
PublicKey p = new Sec1PublicKey(k);
|
||||||
long duration = System.currentTimeMillis() - now;
|
logDuration(LOG, "Parsing public key", start);
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Parsing public key took " + duration + " ms");
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PrivateKey parsePrivateKey(byte[] encodedKey)
|
public PrivateKey parsePrivateKey(byte[] encodedKey)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException {
|
||||||
long now = System.currentTimeMillis();
|
long start = now();
|
||||||
if (encodedKey.length != privateKeyBytes)
|
if (encodedKey.length != privateKeyBytes)
|
||||||
throw new GeneralSecurityException();
|
throw new GeneralSecurityException();
|
||||||
BigInteger d = new BigInteger(1, encodedKey); // Positive signum
|
BigInteger d = new BigInteger(1, encodedKey); // Positive signum
|
||||||
@@ -99,9 +98,7 @@ class Sec1KeyParser implements KeyParser {
|
|||||||
// Construct a private key from the private value and the params
|
// Construct a private key from the private value and the params
|
||||||
ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params);
|
ECPrivateKeyParameters k = new ECPrivateKeyParameters(d, params);
|
||||||
PrivateKey p = new Sec1PrivateKey(k, keyBits);
|
PrivateKey p = new Sec1PrivateKey(k, keyBits);
|
||||||
long duration = System.currentTimeMillis() - now;
|
logDuration(LOG, "Parsing private key", start);
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Parsing private key took " + duration + " ms");
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.briarproject.bramble.db;
|
|||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
@@ -48,7 +49,8 @@ interface Database<T> {
|
|||||||
* @throws DataTooOldException if the data uses an older schema than the
|
* @throws DataTooOldException if the data uses an older schema than the
|
||||||
* current code and cannot be migrated
|
* current code and cannot be migrated
|
||||||
*/
|
*/
|
||||||
boolean open(@Nullable MigrationListener listener) throws DbException;
|
boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||||
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prevents new transactions from starting, waits for all current
|
* Prevents new transactions from starting, waits for all current
|
||||||
@@ -641,7 +643,7 @@ interface Database<T> {
|
|||||||
* Marks the given transport keys as usable for outgoing streams.
|
* Marks the given transport keys as usable for outgoing streams.
|
||||||
*/
|
*/
|
||||||
void setTransportKeysActive(T txn, TransportId t, KeySetId k)
|
void setTransportKeysActive(T txn, TransportId t, KeySetId k)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the transmission count and expiry time of the given message
|
* Updates the transmission count and expiry time of the given message
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.event.ContactAddedEvent;
|
|||||||
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent;
|
||||||
import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
|
import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.ContactExistsException;
|
import org.briarproject.bramble.api.db.ContactExistsException;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
@@ -68,13 +69,15 @@ import javax.annotation.Nullable;
|
|||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.FINE;
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
|
||||||
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -101,14 +104,14 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean open(@Nullable MigrationListener listener)
|
public boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
boolean reopened = db.open(listener);
|
boolean reopened = db.open(key, listener);
|
||||||
shutdown.addShutdownHook(() -> {
|
shutdown.addShutdownHook(() -> {
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return reopened;
|
return reopened;
|
||||||
@@ -125,13 +128,13 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
|
|||||||
// Don't allow reentrant locking
|
// Don't allow reentrant locking
|
||||||
if (lock.getReadHoldCount() > 0) throw new IllegalStateException();
|
if (lock.getReadHoldCount() > 0) throw new IllegalStateException();
|
||||||
if (lock.getWriteHoldCount() > 0) throw new IllegalStateException();
|
if (lock.getWriteHoldCount() > 0) throw new IllegalStateException();
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
if (readOnly) lock.readLock().lock();
|
if (readOnly) {
|
||||||
else lock.writeLock().lock();
|
lock.readLock().lock();
|
||||||
if (LOG.isLoggable(FINE)) {
|
logDuration(LOG, "Waiting for read lock", start);
|
||||||
long duration = System.currentTimeMillis() - start;
|
} else {
|
||||||
if (readOnly) LOG.fine("Waited " + duration + " ms for read lock");
|
lock.writeLock().lock();
|
||||||
else LOG.fine("Waited " + duration + " ms for write lock");
|
logDuration(LOG, "Waiting for write lock", start);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return new Transaction(db.startTransaction(), readOnly);
|
return new Transaction(db.startTransaction(), readOnly);
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ class H2Database extends JdbcDatabase {
|
|||||||
private final DatabaseConfig config;
|
private final DatabaseConfig config;
|
||||||
private final String url;
|
private final String url;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private volatile SecretKey key = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
H2Database(DatabaseConfig config, Clock clock) {
|
H2Database(DatabaseConfig config, Clock clock) {
|
||||||
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||||
@@ -44,11 +47,11 @@ class H2Database extends JdbcDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean open(@Nullable MigrationListener listener)
|
public boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||||
throws DbException {
|
throws DbException {
|
||||||
boolean reopen = config.databaseExists();
|
this.key = key;
|
||||||
if (!reopen) config.getDatabaseDirectory().mkdirs();
|
boolean reopen = !config.getDatabaseDirectory().mkdirs();
|
||||||
super.open("org.h2.Driver", reopen, listener);
|
super.open("org.h2.Driver", reopen, key, listener);
|
||||||
return reopen;
|
return reopen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +66,7 @@ class H2Database extends JdbcDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getFreeSpace() throws DbException {
|
public long getFreeSpace() {
|
||||||
File dir = config.getDatabaseDirectory();
|
File dir = config.getDatabaseDirectory();
|
||||||
long maxSize = config.getMaxSize();
|
long maxSize = config.getMaxSize();
|
||||||
long free = dir.getFreeSpace();
|
long free = dir.getFreeSpace();
|
||||||
@@ -88,7 +91,7 @@ class H2Database extends JdbcDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Connection createConnection() throws SQLException {
|
protected Connection createConnection() throws SQLException {
|
||||||
SecretKey key = config.getEncryptionKey();
|
SecretKey key = this.key;
|
||||||
if (key == null) throw new IllegalStateException();
|
if (key == null) throw new IllegalStateException();
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.setProperty("user", "user");
|
props.setProperty("user", "user");
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
private final DatabaseConfig config;
|
private final DatabaseConfig config;
|
||||||
private final String url;
|
private final String url;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private volatile SecretKey key = null;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
HyperSqlDatabase(DatabaseConfig config, Clock clock) {
|
HyperSqlDatabase(DatabaseConfig config, Clock clock) {
|
||||||
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
|
||||||
@@ -46,10 +49,11 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean open(@Nullable MigrationListener listener) throws DbException {
|
public boolean open(SecretKey key, @Nullable MigrationListener listener)
|
||||||
boolean reopen = config.databaseExists();
|
throws DbException {
|
||||||
if (!reopen) config.getDatabaseDirectory().mkdirs();
|
this.key = key;
|
||||||
super.open("org.hsqldb.jdbc.JDBCDriver", reopen, listener);
|
boolean reopen = !config.getDatabaseDirectory().mkdirs();
|
||||||
|
super.open("org.hsqldb.jdbc.JDBCDriver", reopen, key, listener);
|
||||||
return reopen;
|
return reopen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +97,7 @@ class HyperSqlDatabase extends JdbcDatabase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Connection createConnection() throws SQLException {
|
protected Connection createConnection() throws SQLException {
|
||||||
SecretKey key = config.getEncryptionKey();
|
SecretKey key = this.key;
|
||||||
if (key == null) throw new IllegalStateException();
|
if (key == null) throw new IllegalStateException();
|
||||||
String hex = StringUtils.toHexString(key.getBytes());
|
String hex = StringUtils.toHexString(key.getBytes());
|
||||||
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
return DriverManager.getConnection(url + ";crypt_key=" + hex);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
|
|||||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||||
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
import static org.briarproject.bramble.db.ExponentialBackoff.calculateExpiry;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic database implementation that can be used with any JDBC-compatible
|
* A generic database implementation that can be used with any JDBC-compatible
|
||||||
@@ -327,7 +328,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void open(String driverClass, boolean reopen,
|
protected void open(String driverClass, boolean reopen, SecretKey key,
|
||||||
@Nullable MigrationListener listener) throws DbException {
|
@Nullable MigrationListener listener) throws DbException {
|
||||||
// Load the JDBC driver
|
// Load the JDBC driver
|
||||||
try {
|
try {
|
||||||
@@ -404,7 +405,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
try {
|
try {
|
||||||
if (rs != null) rs.close();
|
if (rs != null) rs.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +413,7 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
try {
|
try {
|
||||||
if (s != null) s.close();
|
if (s != null) s.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,12 +510,11 @@ abstract class JdbcDatabase implements Database<Connection> {
|
|||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
// Try to close the connection
|
// Try to close the connection
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
try {
|
try {
|
||||||
txn.close();
|
txn.close();
|
||||||
} catch (SQLException e1) {
|
} catch (SQLException e1) {
|
||||||
if (LOG.isLoggable(WARNING))
|
logException(LOG, WARNING, e1);
|
||||||
LOG.log(WARNING, e1.toString(), e1);
|
|
||||||
}
|
}
|
||||||
// Whatever happens, allow the database to close
|
// Whatever happens, allow the database to close
|
||||||
connectionsLock.lock();
|
connectionsLock.lock();
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
class Migration38_39 implements Migration<Connection> {
|
class Migration38_39 implements Migration<Connection> {
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ class Migration38_39 implements Migration<Connection> {
|
|||||||
try {
|
try {
|
||||||
if (s != null) s.close();
|
if (s != null) s.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package org.briarproject.bramble.identity;
|
package org.briarproject.bramble.identity;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.contact.Contact;
|
import org.briarproject.bramble.api.contact.Contact;
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.KeyPair;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.identity.Author.Status;
|
import org.briarproject.bramble.api.identity.Author.Status;
|
||||||
|
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
import org.briarproject.bramble.api.identity.AuthorId;
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
@@ -21,6 +24,8 @@ import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
|
|||||||
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
|
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
|
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
|
||||||
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
|
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -30,25 +35,51 @@ class IdentityManagerImpl implements IdentityManager {
|
|||||||
Logger.getLogger(IdentityManagerImpl.class.getName());
|
Logger.getLogger(IdentityManagerImpl.class.getName());
|
||||||
|
|
||||||
private final DatabaseComponent db;
|
private final DatabaseComponent db;
|
||||||
|
private final CryptoComponent crypto;
|
||||||
|
private final AuthorFactory authorFactory;
|
||||||
|
|
||||||
// The local author is immutable so we can cache it
|
// The local author is immutable so we can cache it
|
||||||
@Nullable
|
@Nullable
|
||||||
private volatile LocalAuthor cachedAuthor;
|
private volatile LocalAuthor cachedAuthor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
IdentityManagerImpl(DatabaseComponent db) {
|
IdentityManagerImpl(DatabaseComponent db, CryptoComponent crypto,
|
||||||
|
AuthorFactory authorFactory) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
|
this.crypto = crypto;
|
||||||
|
this.authorFactory = authorFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerLocalAuthor(LocalAuthor localAuthor)
|
public LocalAuthor createLocalAuthor(String name) {
|
||||||
throws DbException {
|
long start = now();
|
||||||
|
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
||||||
|
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||||
|
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
||||||
|
LocalAuthor localAuthor = authorFactory.createLocalAuthor(name,
|
||||||
|
publicKey, privateKey);
|
||||||
|
logDuration(LOG, "Creating local author", start);
|
||||||
|
return localAuthor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerLocalAuthor(LocalAuthor a) {
|
||||||
|
cachedAuthor = a;
|
||||||
|
LOG.info("Local author registered");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void storeLocalAuthor() throws DbException {
|
||||||
|
LocalAuthor cached = cachedAuthor;
|
||||||
|
if (cached == null) {
|
||||||
|
LOG.info("No local author to store");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.addLocalAuthor(txn, localAuthor);
|
db.addLocalAuthor(txn, cached);
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
cachedAuthor = localAuthor;
|
LOG.info("Local author stored");
|
||||||
LOG.info("Local author registered");
|
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import javax.annotation.Nullable;
|
|||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT;
|
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.CONNECTION_TIMEOUT;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class KeyAgreementConnector {
|
class KeyAgreementConnector {
|
||||||
@@ -134,7 +135,7 @@ class KeyAgreementConnector {
|
|||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
return null;
|
return null;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
stopListening();
|
stopListening();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -120,13 +121,11 @@ class KeyAgreementTaskImpl extends Thread implements KeyAgreementTask,
|
|||||||
// Broadcast result to caller
|
// Broadcast result to caller
|
||||||
eventBus.broadcast(new KeyAgreementFinishedEvent(result));
|
eventBus.broadcast(new KeyAgreementFinishedEvent(result));
|
||||||
} catch (AbortException e) {
|
} catch (AbortException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
logException(LOG, WARNING, e);
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
// Notify caller that the protocol was aborted
|
// Notify caller that the protocol was aborted
|
||||||
eventBus.broadcast(new KeyAgreementAbortedEvent(e.receivedAbort));
|
eventBus.broadcast(new KeyAgreementAbortedEvent(e.receivedAbort));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
logException(LOG, WARNING, e);
|
||||||
LOG.log(WARNING, e.toString(), e);
|
|
||||||
// Notify caller that the connection failed
|
// Notify caller that the connection failed
|
||||||
eventBus.broadcast(new KeyAgreementFailedEvent());
|
eventBus.broadcast(new KeyAgreementFailedEvent());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.PR
|
|||||||
import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT;
|
import static org.briarproject.bramble.api.keyagreement.RecordTypes.ABORT;
|
||||||
import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM;
|
import static org.briarproject.bramble.api.keyagreement.RecordTypes.CONFIRM;
|
||||||
import static org.briarproject.bramble.api.keyagreement.RecordTypes.KEY;
|
import static org.briarproject.bramble.api.keyagreement.RecordTypes.KEY;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the sending and receiving of BQP records.
|
* Handles the sending and receiving of BQP records.
|
||||||
@@ -72,7 +73,7 @@ class KeyAgreementTransport {
|
|||||||
try {
|
try {
|
||||||
writeRecord(ABORT, new byte[0]);
|
writeRecord(ABORT, new byte[0]);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
exception = true;
|
exception = true;
|
||||||
}
|
}
|
||||||
tryToClose(exception);
|
tryToClose(exception);
|
||||||
@@ -83,7 +84,7 @@ class KeyAgreementTransport {
|
|||||||
kac.getConnection().getReader().dispose(exception, true);
|
kac.getConnection().getReader().dispose(exception, true);
|
||||||
kac.getConnection().getWriter().dispose(exception);
|
kac.getConnection().getWriter().dispose(exception);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.briarproject.bramble.lifecycle;
|
package org.briarproject.bramble.lifecycle;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.crypto.KeyPair;
|
|
||||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||||
@@ -9,9 +8,7 @@ import org.briarproject.bramble.api.db.DbException;
|
|||||||
import org.briarproject.bramble.api.db.MigrationListener;
|
import org.briarproject.bramble.api.db.MigrationListener;
|
||||||
import org.briarproject.bramble.api.db.Transaction;
|
import org.briarproject.bramble.api.db.Transaction;
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
import org.briarproject.bramble.api.event.EventBus;
|
||||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.lifecycle.Service;
|
import org.briarproject.bramble.api.lifecycle.Service;
|
||||||
import org.briarproject.bramble.api.lifecycle.ServiceException;
|
import org.briarproject.bramble.api.lifecycle.ServiceException;
|
||||||
@@ -26,10 +23,10 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.FINE;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
|
||||||
@@ -43,6 +40,9 @@ import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResul
|
|||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DB_ERROR;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DB_ERROR;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -56,8 +56,6 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
private final List<Service> services;
|
private final List<Service> services;
|
||||||
private final List<Client> clients;
|
private final List<Client> clients;
|
||||||
private final List<ExecutorService> executors;
|
private final List<ExecutorService> executors;
|
||||||
private final CryptoComponent crypto;
|
|
||||||
private final AuthorFactory authorFactory;
|
|
||||||
private final IdentityManager identityManager;
|
private final IdentityManager identityManager;
|
||||||
private final Semaphore startStopSemaphore = new Semaphore(1);
|
private final Semaphore startStopSemaphore = new Semaphore(1);
|
||||||
private final CountDownLatch dbLatch = new CountDownLatch(1);
|
private final CountDownLatch dbLatch = new CountDownLatch(1);
|
||||||
@@ -68,12 +66,9 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
|
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
|
||||||
CryptoComponent crypto, AuthorFactory authorFactory,
|
|
||||||
IdentityManager identityManager) {
|
IdentityManager identityManager) {
|
||||||
this.db = db;
|
this.db = db;
|
||||||
this.eventBus = eventBus;
|
this.eventBus = eventBus;
|
||||||
this.crypto = crypto;
|
|
||||||
this.authorFactory = authorFactory;
|
|
||||||
this.identityManager = identityManager;
|
this.identityManager = identityManager;
|
||||||
services = new CopyOnWriteArrayList<>();
|
services = new CopyOnWriteArrayList<>();
|
||||||
clients = new CopyOnWriteArrayList<>();
|
clients = new CopyOnWriteArrayList<>();
|
||||||
@@ -100,48 +95,20 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
executors.add(e);
|
executors.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalAuthor createLocalAuthor(String nickname) {
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
KeyPair keyPair = crypto.generateSignatureKeyPair();
|
|
||||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
|
||||||
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
|
||||||
LocalAuthor localAuthor = authorFactory
|
|
||||||
.createLocalAuthor(nickname, publicKey, privateKey);
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Creating local author took " + duration + " ms");
|
|
||||||
return localAuthor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerLocalAuthor(LocalAuthor author) throws DbException {
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
identityManager.registerLocalAuthor(author);
|
|
||||||
long duration = System.currentTimeMillis() - now;
|
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Registering local author took " + duration + " ms");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StartResult startServices(@Nullable String nickname) {
|
public StartResult startServices(SecretKey dbKey) {
|
||||||
if (!startStopSemaphore.tryAcquire()) {
|
if (!startStopSemaphore.tryAcquire()) {
|
||||||
LOG.info("Already starting or stopping");
|
LOG.info("Already starting or stopping");
|
||||||
return ALREADY_RUNNING;
|
return ALREADY_RUNNING;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
LOG.info("Starting services");
|
LOG.info("Starting services");
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
|
|
||||||
boolean reopened = db.open(this);
|
boolean reopened = db.open(dbKey, this);
|
||||||
long duration = System.currentTimeMillis() - start;
|
if (reopened) logDuration(LOG, "Reopening database", start);
|
||||||
if (LOG.isLoggable(INFO)) {
|
else logDuration(LOG, "Creating database", start);
|
||||||
if (reopened)
|
identityManager.storeLocalAuthor();
|
||||||
LOG.info("Reopening database took " + duration + " ms");
|
|
||||||
else LOG.info("Creating database took " + duration + " ms");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nickname != null) {
|
|
||||||
registerLocalAuthor(createLocalAuthor(nickname));
|
|
||||||
}
|
|
||||||
|
|
||||||
state = STARTING_SERVICES;
|
state = STARTING_SERVICES;
|
||||||
dbLatch.countDown();
|
dbLatch.countDown();
|
||||||
@@ -150,13 +117,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
Transaction txn = db.startTransaction(false);
|
Transaction txn = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
for (Client c : clients) {
|
for (Client c : clients) {
|
||||||
start = System.currentTimeMillis();
|
start = now();
|
||||||
c.createLocalState(txn);
|
c.createLocalState(txn);
|
||||||
duration = System.currentTimeMillis() - start;
|
if (LOG.isLoggable(FINE)) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
logDuration(LOG, "Starting client "
|
||||||
LOG.info("Starting client "
|
+ c.getClass().getSimpleName(), start);
|
||||||
+ c.getClass().getSimpleName()
|
|
||||||
+ " took " + duration + " ms");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.commitTransaction(txn);
|
db.commitTransaction(txn);
|
||||||
@@ -164,12 +129,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
for (Service s : services) {
|
for (Service s : services) {
|
||||||
start = System.currentTimeMillis();
|
start = now();
|
||||||
s.startService();
|
s.startService();
|
||||||
duration = System.currentTimeMillis() - start;
|
if (LOG.isLoggable(FINE)) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
logDuration(LOG, "Starting service "
|
||||||
LOG.info("Starting service " + s.getClass().getSimpleName()
|
+ s.getClass().getSimpleName(), start);
|
||||||
+ " took " + duration + " ms");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,16 +142,16 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
eventBus.broadcast(new LifecycleEvent(RUNNING));
|
eventBus.broadcast(new LifecycleEvent(RUNNING));
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
} catch (DataTooOldException e) {
|
} catch (DataTooOldException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return DATA_TOO_OLD_ERROR;
|
return DATA_TOO_OLD_ERROR;
|
||||||
} catch (DataTooNewException e) {
|
} catch (DataTooNewException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return DATA_TOO_NEW_ERROR;
|
return DATA_TOO_NEW_ERROR;
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return DB_ERROR;
|
return DB_ERROR;
|
||||||
} catch (ServiceException e) {
|
} catch (ServiceException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return SERVICE_ERROR;
|
return SERVICE_ERROR;
|
||||||
} finally {
|
} finally {
|
||||||
startStopSemaphore.release();
|
startStopSemaphore.release();
|
||||||
@@ -213,29 +177,26 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
|
|||||||
state = STOPPING;
|
state = STOPPING;
|
||||||
eventBus.broadcast(new LifecycleEvent(STOPPING));
|
eventBus.broadcast(new LifecycleEvent(STOPPING));
|
||||||
for (Service s : services) {
|
for (Service s : services) {
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
s.stopService();
|
s.stopService();
|
||||||
long duration = System.currentTimeMillis() - start;
|
if (LOG.isLoggable(FINE)) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
logDuration(LOG, "Stopping service "
|
||||||
LOG.info("Stopping service " + s.getClass().getSimpleName()
|
+ s.getClass().getSimpleName(), start);
|
||||||
+ " took " + duration + " ms");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (ExecutorService e : executors) {
|
for (ExecutorService e : executors) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(FINE)) {
|
||||||
LOG.info("Stopping executor "
|
LOG.fine("Stopping executor "
|
||||||
+ e.getClass().getSimpleName());
|
+ e.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
e.shutdownNow();
|
e.shutdownNow();
|
||||||
}
|
}
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
db.close();
|
db.close();
|
||||||
long duration = System.currentTimeMillis() - start;
|
logDuration(LOG, "Closing database", start);
|
||||||
if (LOG.isLoggable(INFO))
|
|
||||||
LOG.info("Closing database took " + duration + " ms");
|
|
||||||
shutdownLatch.countDown();
|
shutdownLatch.countDown();
|
||||||
} catch (DbException | ServiceException e) {
|
} catch (DbException | ServiceException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
} finally {
|
} finally {
|
||||||
startStopSemaphore.release();
|
startStopSemaphore.release();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
package org.briarproject.bramble.lifecycle;
|
package org.briarproject.bramble.lifecycle;
|
||||||
|
|
||||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
|
||||||
import org.briarproject.bramble.api.db.DatabaseComponent;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
|
||||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
|
||||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
|
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
|
||||||
@@ -54,11 +49,9 @@ public class LifecycleModule {
|
|||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
LifecycleManager provideLifecycleManager(DatabaseComponent db,
|
LifecycleManager provideLifecycleManager(
|
||||||
EventBus eventBus, CryptoComponent crypto,
|
LifecycleManagerImpl lifecycleManager) {
|
||||||
AuthorFactory authorFactory, IdentityManager identityManager) {
|
return lifecycleManager;
|
||||||
return new LifecycleManagerImpl(db, eventBus, crypto, authorFactory,
|
|
||||||
identityManager);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
class ConnectionManagerImpl implements ConnectionManager {
|
class ConnectionManagerImpl implements ConnectionManager {
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
byte[] tag = readTag(reader);
|
byte[] tag = readTag(reader);
|
||||||
ctx = keyManager.getStreamContext(transportId, tag);
|
ctx = keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException | DbException e) {
|
} catch (IOException | DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeReader(true, false);
|
disposeReader(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -151,7 +152,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
createIncomingSession(ctx, reader).run();
|
createIncomingSession(ctx, reader).run();
|
||||||
disposeReader(false, true);
|
disposeReader(false, true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeReader(true, true);
|
disposeReader(true, true);
|
||||||
} finally {
|
} finally {
|
||||||
connectionRegistry.unregisterConnection(contactId, transportId,
|
connectionRegistry.unregisterConnection(contactId, transportId,
|
||||||
@@ -163,7 +164,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
reader.dispose(exception, recognised);
|
reader.dispose(exception, recognised);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,7 +189,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
ctx = keyManager.getStreamContext(contactId, transportId);
|
ctx = keyManager.getStreamContext(contactId, transportId);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeWriter(true);
|
disposeWriter(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -204,7 +205,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
createSimplexOutgoingSession(ctx, writer).run();
|
createSimplexOutgoingSession(ctx, writer).run();
|
||||||
disposeWriter(false);
|
disposeWriter(false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeWriter(true);
|
disposeWriter(true);
|
||||||
} finally {
|
} finally {
|
||||||
connectionRegistry.unregisterConnection(contactId, transportId,
|
connectionRegistry.unregisterConnection(contactId, transportId,
|
||||||
@@ -216,7 +217,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
writer.dispose(exception);
|
writer.dispose(exception);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -246,7 +247,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
byte[] tag = readTag(reader);
|
byte[] tag = readTag(reader);
|
||||||
ctx = keyManager.getStreamContext(transportId, tag);
|
ctx = keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException | DbException e) {
|
} catch (IOException | DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeReader(true, false);
|
disposeReader(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -265,7 +266,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
incomingSession.run();
|
incomingSession.run();
|
||||||
disposeReader(false, true);
|
disposeReader(false, true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeReader(true, true);
|
disposeReader(true, true);
|
||||||
} finally {
|
} finally {
|
||||||
connectionRegistry.unregisterConnection(contactId, transportId,
|
connectionRegistry.unregisterConnection(contactId, transportId,
|
||||||
@@ -279,7 +280,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
ctx = keyManager.getStreamContext(contactId, transportId);
|
ctx = keyManager.getStreamContext(contactId, transportId);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeWriter(true);
|
disposeWriter(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -294,7 +295,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
outgoingSession.run();
|
outgoingSession.run();
|
||||||
disposeWriter(false);
|
disposeWriter(false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeWriter(true);
|
disposeWriter(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,7 +306,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
reader.dispose(exception, recognised);
|
reader.dispose(exception, recognised);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,7 +318,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
writer.dispose(exception);
|
writer.dispose(exception);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,7 +348,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
ctx = keyManager.getStreamContext(contactId, transportId);
|
ctx = keyManager.getStreamContext(contactId, transportId);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeWriter(true);
|
disposeWriter(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -364,7 +365,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
outgoingSession.run();
|
outgoingSession.run();
|
||||||
disposeWriter(false);
|
disposeWriter(false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeWriter(true);
|
disposeWriter(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +377,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
byte[] tag = readTag(reader);
|
byte[] tag = readTag(reader);
|
||||||
ctx = keyManager.getStreamContext(transportId, tag);
|
ctx = keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException | DbException e) {
|
} catch (IOException | DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeReader(true, false);
|
disposeReader(true, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -400,7 +401,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
incomingSession.run();
|
incomingSession.run();
|
||||||
disposeReader(false, true);
|
disposeReader(false, true);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
disposeReader(true, true);
|
disposeReader(true, true);
|
||||||
} finally {
|
} finally {
|
||||||
connectionRegistry.unregisterConnection(contactId, transportId,
|
connectionRegistry.unregisterConnection(contactId, transportId,
|
||||||
@@ -414,7 +415,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
reader.dispose(exception, recognised);
|
reader.dispose(exception, recognised);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,7 +427,7 @@ class ConnectionManagerImpl implements ConnectionManager {
|
|||||||
try {
|
try {
|
||||||
writer.dispose(exception);
|
writer.dispose(exception);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,8 +49,12 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.logging.Level.FINE;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -205,17 +209,16 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
plugin.start();
|
plugin.start();
|
||||||
long duration = System.currentTimeMillis() - start;
|
if (LOG.isLoggable(FINE)) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
logDuration(LOG, "Starting plugin " + plugin.getId(),
|
||||||
LOG.info("Starting plugin " + plugin.getId() + " took " +
|
start);
|
||||||
duration + " ms");
|
|
||||||
}
|
}
|
||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
if (LOG.isLoggable(WARNING)) {
|
if (LOG.isLoggable(WARNING)) {
|
||||||
LOG.warning("Plugin " + plugin.getId() + " did not start");
|
LOG.warning("Plugin " + plugin.getId() + " did not start");
|
||||||
LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
startLatch.countDown();
|
startLatch.countDown();
|
||||||
@@ -243,12 +246,11 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
// Wait for the plugin to finish starting
|
// Wait for the plugin to finish starting
|
||||||
startLatch.await();
|
startLatch.await();
|
||||||
// Stop the plugin
|
// Stop the plugin
|
||||||
long start = System.currentTimeMillis();
|
long start = now();
|
||||||
plugin.stop();
|
plugin.stop();
|
||||||
long duration = System.currentTimeMillis() - start;
|
if (LOG.isLoggable(FINE)) {
|
||||||
if (LOG.isLoggable(INFO)) {
|
logDuration(LOG, "Stopping plugin " + plugin.getId(),
|
||||||
LOG.info("Stopping plugin " + plugin.getId()
|
start);
|
||||||
+ " took " + duration + " ms");
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.warning("Interrupted while waiting for plugin to stop");
|
LOG.warning("Interrupted while waiting for plugin to stop");
|
||||||
@@ -256,7 +258,7 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
} catch (PluginException e) {
|
} catch (PluginException e) {
|
||||||
if (LOG.isLoggable(WARNING)) {
|
if (LOG.isLoggable(WARNING)) {
|
||||||
LOG.warning("Plugin " + plugin.getId() + " did not stop");
|
LOG.warning("Plugin " + plugin.getId() + " did not stop");
|
||||||
LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
stopLatch.countDown();
|
stopLatch.countDown();
|
||||||
@@ -278,7 +280,7 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
try {
|
try {
|
||||||
return settingsManager.getSettings(id.getString());
|
return settingsManager.getSettings(id.getString());
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return new Settings();
|
return new Settings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -288,7 +290,7 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
try {
|
try {
|
||||||
return transportPropertyManager.getLocalProperties(id);
|
return transportPropertyManager.getLocalProperties(id);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return new TransportProperties();
|
return new TransportProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -298,7 +300,7 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
try {
|
try {
|
||||||
settingsManager.mergeSettings(s, id.getString());
|
settingsManager.mergeSettings(s, id.getString());
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,7 +309,7 @@ class PluginManagerImpl implements PluginManager, Service {
|
|||||||
try {
|
try {
|
||||||
transportPropertyManager.mergeLocalProperties(id, p);
|
transportPropertyManager.mergeLocalProperties(id, p);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -134,7 +135,7 @@ class Poller implements EventListener {
|
|||||||
if (w != null)
|
if (w != null)
|
||||||
connectionManager.manageOutgoingConnection(c, t, w);
|
connectionManager.manageOutgoingConnection(c, t, w);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -150,7 +151,7 @@ class Poller implements EventListener {
|
|||||||
if (d != null)
|
if (d != null)
|
||||||
connectionManager.manageOutgoingConnection(c, t, d);
|
connectionManager.manageOutgoingConnection(c, t, d);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -211,7 +212,7 @@ class Poller implements EventListener {
|
|||||||
remote.keySet().removeAll(connected);
|
remote.keySet().removeAll(connected);
|
||||||
if (!remote.isEmpty()) p.poll(remote);
|
if (!remote.isEmpty()) p.poll(remote);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@@ -92,7 +93,7 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
|
|||||||
conn.getWriter().dispose(false);
|
conn.getWriter().dispose(false);
|
||||||
conn.getReader().dispose(false, false);
|
conn.getReader().dispose(false, false);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PREF_BT_ENA
|
|||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
|
||||||
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -169,7 +170,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
try {
|
try {
|
||||||
ss = openServerSocket(contactConnectionsUuid);
|
ss = openServerSocket(contactConnectionsUuid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isRunning() || !shouldAllowContactConnections()) {
|
if (!isRunning() || !shouldAllowContactConnections()) {
|
||||||
@@ -336,7 +337,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
|
|||||||
try {
|
try {
|
||||||
ss = openServerSocket(uuid);
|
ss = openServerSocket(uuid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!isRunning()) {
|
if (!isRunning()) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.plugin.FileConstants.PROP_PATH;
|
import static org.briarproject.bramble.api.plugin.FileConstants.PROP_PATH;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -51,7 +52,7 @@ abstract class FilePlugin implements SimplexPlugin {
|
|||||||
FileInputStream in = new FileInputStream(file);
|
FileInputStream in = new FileInputStream(file);
|
||||||
return new FileTransportReader(file, in, this);
|
return new FileTransportReader(file, in, this);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ abstract class FilePlugin implements SimplexPlugin {
|
|||||||
FileOutputStream out = new FileOutputStream(file);
|
FileOutputStream out = new FileOutputStream(file);
|
||||||
return new FileTransportWriter(file, out, this);
|
return new FileTransportWriter(file, out, this);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.io.InputStream;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class FileTransportReader implements TransportConnectionReader {
|
class FileTransportReader implements TransportConnectionReader {
|
||||||
@@ -36,7 +37,7 @@ class FileTransportReader implements TransportConnectionReader {
|
|||||||
try {
|
try {
|
||||||
in.close();
|
in.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
plugin.readerFinished(file, exception, recognised);
|
plugin.readerFinished(file, exception, recognised);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.io.OutputStream;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
class FileTransportWriter implements TransportConnectionWriter {
|
class FileTransportWriter implements TransportConnectionWriter {
|
||||||
@@ -46,7 +47,7 @@ class FileTransportWriter implements TransportConnectionWriter {
|
|||||||
try {
|
try {
|
||||||
out.close();
|
out.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
plugin.writerFinished(file, exception);
|
plugin.writerFinished(file, exception);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
|||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
|
||||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
|
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -295,7 +296,7 @@ class LanTcpPlugin extends TcpPlugin {
|
|||||||
try {
|
try {
|
||||||
ss.close();
|
ss.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubInetAddress;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@@ -59,7 +60,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
if (externalString != null)
|
if (externalString != null)
|
||||||
external = InetAddress.getByName(externalString);
|
external = InetAddress.getByName(externalString);
|
||||||
} catch (IOException | SAXException e) {
|
} catch (IOException | SAXException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
return new MappingResult(internal, external, port, succeeded);
|
return new MappingResult(internal, external, port, succeeded);
|
||||||
}
|
}
|
||||||
@@ -76,7 +77,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
try {
|
try {
|
||||||
d.discover();
|
d.discover();
|
||||||
} catch (IOException | SAXException | ParserConfigurationException e) {
|
} catch (IOException | SAXException | ParserConfigurationException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
gateway = d.getValidGateway();
|
gateway = d.getValidGateway();
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ class PortMapperImpl implements PortMapper {
|
|||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Deleted mapping for port " + port);
|
LOG.info("Deleted mapping for port " + port);
|
||||||
} catch (IOException | SAXException e) {
|
} catch (IOException | SAXException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import javax.annotation.Nullable;
|
|||||||
|
|
||||||
import static java.util.logging.Level.INFO;
|
import static java.util.logging.Level.INFO;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -152,7 +153,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
try {
|
try {
|
||||||
if (ss != null) ss.close();
|
if (ss != null) ss.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
} finally {
|
} finally {
|
||||||
callback.transportDisabled();
|
callback.transportDisabled();
|
||||||
}
|
}
|
||||||
@@ -306,7 +307,7 @@ abstract class TcpPlugin implements DuplexPlugin {
|
|||||||
try {
|
try {
|
||||||
ifaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
ifaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
List<InetAddress> addrs = new ArrayList<>();
|
List<InetAddress> addrs = new ArrayList<>();
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class CircumventionModule {
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
CircumventionProvider provideCircumventionProvider(
|
||||||
|
CircumventionProviderImpl provider) {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
// TODO: Create a module for this so it doesn't have to be public
|
||||||
|
|
||||||
|
public interface CircumventionProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Countries where Tor is blocked, i.e. vanilla Tor connection won't work.
|
||||||
|
*
|
||||||
|
* See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
||||||
|
* and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
|
||||||
|
*/
|
||||||
|
String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE"};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Countries where vanilla bridge connection are likely to work.
|
||||||
|
* Should be a subset of {@link #BLOCKED}.
|
||||||
|
*/
|
||||||
|
String[] BRIDGES = { "EG", "BY", "TR", "SY", "VE" };
|
||||||
|
|
||||||
|
boolean isTorProbablyBlocked(String countryCode);
|
||||||
|
|
||||||
|
boolean doBridgesWork(String countryCode);
|
||||||
|
|
||||||
|
@IoExecutor
|
||||||
|
List<String> getBridges();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Scanner;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
|
||||||
|
class CircumventionProviderImpl implements CircumventionProvider {
|
||||||
|
|
||||||
|
private final static String BRIDGE_FILE_NAME = "bridges";
|
||||||
|
|
||||||
|
private static final Set<String> BLOCKED_IN_COUNTRIES =
|
||||||
|
new HashSet<>(asList(BLOCKED));
|
||||||
|
private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
|
||||||
|
new HashSet<>(asList(BRIDGES));
|
||||||
|
|
||||||
|
private final ResourceProvider resourceProvider;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private volatile List<String> bridges = null;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CircumventionProviderImpl(ResourceProvider resourceProvider) {
|
||||||
|
this.resourceProvider = resourceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTorProbablyBlocked(String countryCode) {
|
||||||
|
return BLOCKED_IN_COUNTRIES.contains(countryCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doBridgesWork(String countryCode) {
|
||||||
|
return BRIDGES_WORK_IN_COUNTRIES.contains(countryCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@IoExecutor
|
||||||
|
public List<String> getBridges() {
|
||||||
|
List<String> bridges = this.bridges;
|
||||||
|
if (bridges != null) return new ArrayList<>(bridges);
|
||||||
|
|
||||||
|
InputStream is =
|
||||||
|
resourceProvider.getResourceInputStream(BRIDGE_FILE_NAME);
|
||||||
|
Scanner scanner = new Scanner(is);
|
||||||
|
|
||||||
|
bridges = new ArrayList<>();
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine();
|
||||||
|
if (!line.startsWith("#")) bridges.add(line);
|
||||||
|
}
|
||||||
|
scanner.close();
|
||||||
|
this.bridges = bridges;
|
||||||
|
return bridges;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,18 +1,5 @@
|
|||||||
package org.briarproject.bramble.plugin.tor;
|
package org.briarproject.bramble.plugin.tor;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.content.pm.PackageInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.os.FileObserver;
|
|
||||||
import android.os.PowerManager;
|
|
||||||
|
|
||||||
import net.freehaven.tor.control.EventHandler;
|
import net.freehaven.tor.control.EventHandler;
|
||||||
import net.freehaven.tor.control.TorControlConnection;
|
import net.freehaven.tor.control.TorControlConnection;
|
||||||
|
|
||||||
@@ -22,6 +9,9 @@ import org.briarproject.bramble.api.data.BdfList;
|
|||||||
import org.briarproject.bramble.api.event.Event;
|
import org.briarproject.bramble.api.event.Event;
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
import org.briarproject.bramble.api.event.EventListener;
|
||||||
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkManager;
|
||||||
|
import org.briarproject.bramble.api.network.NetworkStatus;
|
||||||
|
import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.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;
|
||||||
@@ -34,7 +24,9 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
|
|||||||
import org.briarproject.bramble.api.properties.TransportProperties;
|
import org.briarproject.bramble.api.properties.TransportProperties;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
||||||
|
import org.briarproject.bramble.api.system.Clock;
|
||||||
import org.briarproject.bramble.api.system.LocationUtils;
|
import org.briarproject.bramble.api.system.LocationUtils;
|
||||||
|
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||||
import org.briarproject.bramble.util.IoUtils;
|
import org.briarproject.bramble.util.IoUtils;
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
@@ -49,18 +41,16 @@ import java.io.OutputStream;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
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.Map.Entry;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
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.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;
|
||||||
@@ -68,78 +58,76 @@ import java.util.zip.ZipInputStream;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
|
||||||
import static android.content.Context.MODE_PRIVATE;
|
|
||||||
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.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 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;
|
||||||
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
|
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
|
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
|
import static org.briarproject.bramble.api.plugin.TorConstants.ID;
|
||||||
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_DISABLE_BLOCKED;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
|
||||||
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS;
|
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_ALWAYS;
|
||||||
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.api.plugin.TorConstants.PROP_ONION;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
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 {
|
abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
Logger.getLogger(TorPlugin.class.getName());
|
||||||
|
|
||||||
private static final String[] EVENTS = {
|
private static final String[] EVENTS = {
|
||||||
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
"CIRC", "ORCONN", "HS_DESC", "NOTICE", "WARN", "ERR"
|
||||||
};
|
};
|
||||||
private static final String OWNER = "__OwningControllerProcess";
|
private static final String OWNER = "__OwningControllerProcess";
|
||||||
private static final int COOKIE_TIMEOUT = 3000; // Milliseconds
|
private static final int COOKIE_TIMEOUT_MS = 3000;
|
||||||
|
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
|
||||||
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
|
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
|
||||||
private static final Logger LOG =
|
|
||||||
Logger.getLogger(TorPlugin.class.getName());
|
|
||||||
|
|
||||||
private final Executor ioExecutor, connectionStatusExecutor;
|
private final Executor ioExecutor, connectionStatusExecutor;
|
||||||
private final ScheduledExecutorService scheduler;
|
private final NetworkManager networkManager;
|
||||||
private final Context appContext;
|
|
||||||
private final LocationUtils locationUtils;
|
private final LocationUtils locationUtils;
|
||||||
private final SocketFactory torSocketFactory;
|
private final SocketFactory torSocketFactory;
|
||||||
|
private final Clock clock;
|
||||||
private final Backoff backoff;
|
private final Backoff backoff;
|
||||||
private final DuplexPluginCallback callback;
|
private final DuplexPluginCallback callback;
|
||||||
private final String architecture;
|
private final String architecture;
|
||||||
|
private final CircumventionProvider circumventionProvider;
|
||||||
|
private final ResourceProvider resourceProvider;
|
||||||
private final int maxLatency, maxIdleTime, socketTimeout;
|
private final int maxLatency, maxIdleTime, socketTimeout;
|
||||||
private final ConnectionStatus connectionStatus;
|
|
||||||
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 ConnectionStatus connectionStatus;
|
||||||
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 ServerSocket socket = null;
|
private volatile ServerSocket socket = null;
|
||||||
private volatile Socket controlSocket = null;
|
private volatile Socket controlSocket = null;
|
||||||
private volatile TorControlConnection controlConnection = null;
|
private volatile TorControlConnection controlConnection = null;
|
||||||
private volatile BroadcastReceiver networkStateReceiver = null;
|
|
||||||
|
|
||||||
TorPlugin(Executor ioExecutor, ScheduledExecutorService scheduler,
|
protected volatile boolean running = false;
|
||||||
Context appContext, LocationUtils locationUtils,
|
|
||||||
SocketFactory torSocketFactory, Backoff backoff,
|
protected abstract int getProcessId();
|
||||||
DuplexPluginCallback callback, String architecture,
|
|
||||||
int maxLatency, int maxIdleTime) {
|
protected abstract long getLastUpdateTime();
|
||||||
|
|
||||||
|
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
|
||||||
|
LocationUtils locationUtils, SocketFactory torSocketFactory,
|
||||||
|
Clock clock, ResourceProvider resourceProvider,
|
||||||
|
CircumventionProvider circumventionProvider, Backoff backoff,
|
||||||
|
DuplexPluginCallback callback, String architecture, int maxLatency,
|
||||||
|
int maxIdleTime, File torDirectory) {
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.scheduler = scheduler;
|
this.networkManager = networkManager;
|
||||||
this.appContext = appContext;
|
|
||||||
this.locationUtils = locationUtils;
|
this.locationUtils = locationUtils;
|
||||||
this.torSocketFactory = torSocketFactory;
|
this.torSocketFactory = torSocketFactory;
|
||||||
|
this.clock = clock;
|
||||||
|
this.resourceProvider = resourceProvider;
|
||||||
|
this.circumventionProvider = circumventionProvider;
|
||||||
this.backoff = backoff;
|
this.backoff = backoff;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.architecture = architecture;
|
this.architecture = architecture;
|
||||||
@@ -148,21 +136,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (maxIdleTime > Integer.MAX_VALUE / 2)
|
if (maxIdleTime > Integer.MAX_VALUE / 2)
|
||||||
socketTimeout = Integer.MAX_VALUE;
|
socketTimeout = Integer.MAX_VALUE;
|
||||||
else socketTimeout = maxIdleTime * 2;
|
else socketTimeout = maxIdleTime * 2;
|
||||||
connectionStatus = new ConnectionStatus();
|
this.torDirectory = torDirectory;
|
||||||
torDirectory = appContext.getDir("tor", MODE_PRIVATE);
|
|
||||||
torFile = new File(torDirectory, "tor");
|
torFile = new File(torDirectory, "tor");
|
||||||
geoIpFile = new File(torDirectory, "geoip");
|
geoIpFile = new File(torDirectory, "geoip");
|
||||||
configFile = new File(torDirectory, "torrc");
|
configFile = new File(torDirectory, "torrc");
|
||||||
doneFile = new File(torDirectory, "done");
|
doneFile = new File(torDirectory, "done");
|
||||||
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
|
||||||
Object o = appContext.getSystemService(POWER_SERVICE);
|
connectionStatus = new ConnectionStatus();
|
||||||
PowerManager pm = (PowerManager) o;
|
|
||||||
// This tag will prevent Huawei's powermanager from killing us.
|
|
||||||
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, "LocationManagerService");
|
|
||||||
wakeLock.setReferenceCounted(false);
|
|
||||||
// Don't execute more than one connection status check at a time
|
// Don't execute more than one connection status check at a time
|
||||||
connectionStatusExecutor = new PoliteExecutor("TorPlugin",
|
connectionStatusExecutor =
|
||||||
ioExecutor, 1);
|
new PoliteExecutor("TorPlugin", ioExecutor, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -185,21 +168,13 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (used.getAndSet(true)) throw new IllegalStateException();
|
if (used.getAndSet(true)) throw new IllegalStateException();
|
||||||
// Install or update the assets if necessary
|
// Install or update the assets if necessary
|
||||||
if (!assetsAreUpToDate()) installAssets();
|
if (!assetsAreUpToDate()) installAssets();
|
||||||
LOG.info("Starting Tor");
|
if (cookieFile.exists() && !cookieFile.delete())
|
||||||
// Watch for the auth cookie file being updated
|
LOG.warning("Old auth cookie not deleted");
|
||||||
try {
|
|
||||||
cookieFile.getParentFile().mkdirs();
|
|
||||||
cookieFile.createNewFile();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new PluginException(e);
|
|
||||||
}
|
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
FileObserver obs = new WriteObserver(cookieFile, latch);
|
|
||||||
obs.startWatching();
|
|
||||||
// Start a new Tor process
|
// Start a new Tor process
|
||||||
|
LOG.info("Starting Tor");
|
||||||
String torPath = torFile.getAbsolutePath();
|
String torPath = torFile.getAbsolutePath();
|
||||||
String configPath = configFile.getAbsolutePath();
|
String configPath = configFile.getAbsolutePath();
|
||||||
String pid = String.valueOf(android.os.Process.myPid());
|
String pid = String.valueOf(getProcessId());
|
||||||
Process torProcess;
|
Process torProcess;
|
||||||
ProcessBuilder pb =
|
ProcessBuilder pb =
|
||||||
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
|
new ProcessBuilder(torPath, "-f", configPath, OWNER, pid);
|
||||||
@@ -235,11 +210,16 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
throw new PluginException();
|
throw new PluginException();
|
||||||
}
|
}
|
||||||
// Wait for the auth cookie file to be created/updated
|
// Wait for the auth cookie file to be created/updated
|
||||||
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) {
|
long start = clock.currentTimeMillis();
|
||||||
LOG.warning("Auth cookie not created");
|
while (cookieFile.length() < 32) {
|
||||||
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
|
if (clock.currentTimeMillis() - start > COOKIE_TIMEOUT_MS) {
|
||||||
throw new PluginException();
|
LOG.warning("Auth cookie not created");
|
||||||
|
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
|
||||||
|
throw new PluginException();
|
||||||
|
}
|
||||||
|
Thread.sleep(COOKIE_POLLING_INTERVAL_MS);
|
||||||
}
|
}
|
||||||
|
LOG.info("Auth cookie created");
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LOG.warning("Interrupted while starting Tor");
|
LOG.warning("Interrupted while starting Tor");
|
||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
@@ -266,26 +246,14 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new PluginException(e);
|
throw new PluginException(e);
|
||||||
}
|
}
|
||||||
// Register to receive network status events
|
// Check whether we're online
|
||||||
networkStateReceiver = new NetworkStateReceiver();
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
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);
|
|
||||||
// Bind a server socket to receive incoming hidden service connections
|
// Bind a server socket to receive incoming hidden service connections
|
||||||
bind();
|
bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean assetsAreUpToDate() {
|
private boolean assetsAreUpToDate() {
|
||||||
try {
|
return doneFile.lastModified() > getLastUpdateTime();
|
||||||
PackageManager pm = appContext.getPackageManager();
|
|
||||||
PackageInfo pi = pm.getPackageInfo(appContext.getPackageName(), 0);
|
|
||||||
return doneFile.lastModified() > pi.lastUpdateTime;
|
|
||||||
} catch (NameNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void installAssets() throws PluginException {
|
private void installAssets() throws PluginException {
|
||||||
@@ -318,36 +286,29 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
private InputStream getTorInputStream() throws IOException {
|
private InputStream getTorInputStream() throws IOException {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Installing Tor binary for " + architecture);
|
LOG.info("Installing Tor binary for " + architecture);
|
||||||
int resId = getResourceId("tor_" + architecture);
|
InputStream in =
|
||||||
InputStream in = appContext.getResources().openRawResource(resId);
|
resourceProvider.getResourceInputStream("tor_" + architecture);
|
||||||
ZipInputStream zin = new ZipInputStream(in);
|
ZipInputStream zin = new ZipInputStream(in);
|
||||||
if (zin.getNextEntry() == null) throw new IOException();
|
if (zin.getNextEntry() == null) throw new IOException();
|
||||||
return zin;
|
return zin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getGeoIpInputStream() throws IOException {
|
private InputStream getGeoIpInputStream() throws IOException {
|
||||||
int resId = getResourceId("geoip");
|
InputStream in = resourceProvider.getResourceInputStream("geoip");
|
||||||
InputStream in = appContext.getResources().openRawResource(resId);
|
|
||||||
ZipInputStream zin = new ZipInputStream(in);
|
ZipInputStream zin = new ZipInputStream(in);
|
||||||
if (zin.getNextEntry() == null) throw new IOException();
|
if (zin.getNextEntry() == null) throw new IOException();
|
||||||
return zin;
|
return zin;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputStream getConfigInputStream() {
|
private InputStream getConfigInputStream() {
|
||||||
int resId = getResourceId("torrc");
|
return resourceProvider.getResourceInputStream("torrc");
|
||||||
return appContext.getResources().openRawResource(resId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getResourceId(String filename) {
|
|
||||||
Resources res = appContext.getResources();
|
|
||||||
return res.getIdentifier(filename, "raw", appContext.getPackageName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToClose(@Nullable Closeable c) {
|
private void tryToClose(@Nullable Closeable c) {
|
||||||
try {
|
try {
|
||||||
if (c != null) c.close();
|
if (c != null) c.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +316,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
try {
|
try {
|
||||||
if (s != null) s.close();
|
if (s != null) s.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,7 +325,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
File[] children = f.listFiles();
|
File[] children = f.listFiles();
|
||||||
if (children != null) for (File child : children) listFiles(child);
|
if (children != null) for (File child : children) listFiles(child);
|
||||||
} else {
|
} else {
|
||||||
LOG.info(f.getAbsolutePath());
|
LOG.info(f.getAbsolutePath() + " " + f.length());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +358,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
ss = new ServerSocket();
|
ss = new ServerSocket();
|
||||||
ss.bind(new InetSocketAddress("127.0.0.1", port));
|
ss.bind(new InetSocketAddress("127.0.0.1", port));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
tryToClose(ss);
|
tryToClose(ss);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -423,7 +384,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
try {
|
try {
|
||||||
if (ss != null) ss.close();
|
if (ss != null) ss.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
} finally {
|
} finally {
|
||||||
callback.transportDisabled();
|
callback.transportDisabled();
|
||||||
}
|
}
|
||||||
@@ -442,7 +403,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
response = controlConnection.addOnion(portLines);
|
response = controlConnection.addOnion(portLines);
|
||||||
else response = controlConnection.addOnion(privKey, portLines);
|
else response = controlConnection.addOnion(privKey, portLines);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!response.containsKey(HS_ADDRESS)) {
|
if (!response.containsKey(HS_ADDRESS)) {
|
||||||
@@ -486,14 +447,21 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableNetwork(boolean enable) throws IOException {
|
protected void enableNetwork(boolean enable) throws IOException {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
if (enable) wakeLock.acquire();
|
|
||||||
connectionStatus.enableNetwork(enable);
|
connectionStatus.enableNetwork(enable);
|
||||||
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
|
controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
|
||||||
if (!enable) {
|
if (!enable) callback.transportDisabled();
|
||||||
callback.transportDisabled();
|
}
|
||||||
wakeLock.release();
|
|
||||||
|
private void enableBridges(boolean enable) throws IOException {
|
||||||
|
if (enable) {
|
||||||
|
Collection<String> conf = new ArrayList<>();
|
||||||
|
conf.add("UseBridges 1");
|
||||||
|
conf.addAll(circumventionProvider.getBridges());
|
||||||
|
controlConnection.setConf(conf);
|
||||||
|
} else {
|
||||||
|
controlConnection.setConf("UseBridges", "0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,8 +469,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
running = false;
|
running = false;
|
||||||
tryToClose(socket);
|
tryToClose(socket);
|
||||||
if (networkStateReceiver != null)
|
|
||||||
appContext.unregisterReceiver(networkStateReceiver);
|
|
||||||
if (controlSocket != null && controlConnection != null) {
|
if (controlSocket != null && controlConnection != null) {
|
||||||
try {
|
try {
|
||||||
LOG.info("Stopping Tor");
|
LOG.info("Stopping Tor");
|
||||||
@@ -510,10 +476,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
controlConnection.shutdownTor("TERM");
|
controlConnection.shutdownTor("TERM");
|
||||||
controlSocket.close();
|
controlSocket.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wakeLock.release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -564,7 +529,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
try {
|
try {
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
LOG.info("Connecting to " + scrubOnion(onion));
|
LOG.info("Connecting to " + scrubOnion(onion));
|
||||||
controlConnection.forgetHiddenService(onion);
|
|
||||||
s = torSocketFactory.createSocket(onion + ".onion", 80);
|
s = torSocketFactory.createSocket(onion + ".onion", 80);
|
||||||
s.setSoTimeout(socketTimeout);
|
s.setSoTimeout(socketTimeout);
|
||||||
if (LOG.isLoggable(INFO))
|
if (LOG.isLoggable(INFO))
|
||||||
@@ -613,8 +577,10 @@ 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"))
|
if (status.equals("CLOSED") || status.equals("FAILED")) {
|
||||||
updateConnectionStatus(); // Check whether we've lost connectivity
|
// Check whether we've lost connectivity
|
||||||
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -641,46 +607,31 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
LOG.info("Descriptor uploaded");
|
LOG.info("Descriptor uploaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class WriteObserver extends FileObserver {
|
|
||||||
|
|
||||||
private final CountDownLatch latch;
|
|
||||||
|
|
||||||
private WriteObserver(File file, CountDownLatch latch) {
|
|
||||||
super(file.getAbsolutePath(), CLOSE_WRITE);
|
|
||||||
this.latch = latch;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEvent(int event, @Nullable String path) {
|
|
||||||
stopWatching();
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (e instanceof SettingsUpdatedEvent) {
|
if (e instanceof SettingsUpdatedEvent) {
|
||||||
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
|
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
|
||||||
if (s.getNamespace().equals(ID.getString())) {
|
if (s.getNamespace().equals(ID.getString())) {
|
||||||
LOG.info("Tor settings updated");
|
LOG.info("Tor settings updated");
|
||||||
updateConnectionStatus();
|
updateConnectionStatus(networkManager.getNetworkStatus());
|
||||||
}
|
}
|
||||||
|
} else if (e instanceof NetworkStatusEvent) {
|
||||||
|
updateConnectionStatus(((NetworkStatusEvent) e).getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateConnectionStatus() {
|
private void updateConnectionStatus(NetworkStatus status) {
|
||||||
connectionStatusExecutor.execute(() -> {
|
connectionStatusExecutor.execute(() -> {
|
||||||
if (!running) return;
|
if (!running) return;
|
||||||
Object o = appContext.getSystemService(CONNECTIVITY_SERVICE);
|
boolean online = status.isConnected();
|
||||||
ConnectivityManager cm = (ConnectivityManager) o;
|
boolean wifi = status.isWifi();
|
||||||
NetworkInfo net = cm.getActiveNetworkInfo();
|
|
||||||
boolean online = net != null && net.isConnected();
|
|
||||||
boolean wifi = online && net.getType() == TYPE_WIFI;
|
|
||||||
String country = locationUtils.getCurrentCountry();
|
String country = locationUtils.getCurrentCountry();
|
||||||
boolean blocked = TorNetworkMetadata.isTorProbablyBlocked(
|
boolean blocked =
|
||||||
country);
|
circumventionProvider.isTorProbablyBlocked(country);
|
||||||
Settings s = callback.getSettings();
|
Settings s = callback.getSettings();
|
||||||
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
|
int network = s.getInt(PREF_TOR_NETWORK, PREF_TOR_NETWORK_ALWAYS);
|
||||||
|
boolean disableWhenBlocked =
|
||||||
|
s.getBoolean(PREF_TOR_DISABLE_BLOCKED, true);
|
||||||
|
|
||||||
if (LOG.isLoggable(INFO)) {
|
if (LOG.isLoggable(INFO)) {
|
||||||
LOG.info("Online: " + online + ", wifi: " + wifi);
|
LOG.info("Online: " + online + ", wifi: " + wifi);
|
||||||
@@ -692,46 +643,34 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (!online) {
|
if (!online) {
|
||||||
LOG.info("Disabling network, device is offline");
|
LOG.info("Disabling network, device is offline");
|
||||||
enableNetwork(false);
|
enableNetwork(false);
|
||||||
} else if (blocked) {
|
|
||||||
LOG.info("Disabling network, country is blocked");
|
|
||||||
enableNetwork(false);
|
|
||||||
} else if (network == PREF_TOR_NETWORK_NEVER
|
} else if (network == PREF_TOR_NETWORK_NEVER
|
||||||
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
|
|| (network == PREF_TOR_NETWORK_WIFI && !wifi)) {
|
||||||
LOG.info("Disabling network due to data setting");
|
LOG.info("Disabling network due to data setting");
|
||||||
enableNetwork(false);
|
enableNetwork(false);
|
||||||
|
} else if (blocked) {
|
||||||
|
if (circumventionProvider.doBridgesWork(country)) {
|
||||||
|
LOG.info("Enabling network, using bridges");
|
||||||
|
enableBridges(true);
|
||||||
|
enableNetwork(true);
|
||||||
|
} else if (disableWhenBlocked) {
|
||||||
|
LOG.info("Disabling network, country is blocked");
|
||||||
|
enableNetwork(false);
|
||||||
|
} else {
|
||||||
|
LOG.info("Enabling network but country is blocked");
|
||||||
|
enableBridges(false);
|
||||||
|
enableNetwork(true);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG.info("Enabling network");
|
LOG.info("Enabling network");
|
||||||
|
enableBridges(false);
|
||||||
enableNetwork(true);
|
enableNetwork(true);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, 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 {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context ctx, Intent i) {
|
|
||||||
if (!running) return;
|
|
||||||
String action = i.getAction();
|
|
||||||
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
|
|
||||||
updateConnectionStatus();
|
|
||||||
if (ACTION_SCREEN_ON.equals(action)
|
|
||||||
|| ACTION_SCREEN_OFF.equals(action)) {
|
|
||||||
scheduleConnectionStatusUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ConnectionStatus {
|
private static class ConnectionStatus {
|
||||||
|
|
||||||
// All of the following are locking: this
|
// All of the following are locking: this
|
||||||
@@ -16,6 +16,7 @@ import java.util.logging.Logger;
|
|||||||
|
|
||||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
@@ -78,7 +79,7 @@ class ReliabilityLayerImpl implements ReliabilityLayer, WriteHandler {
|
|||||||
Thread.currentThread().interrupt();
|
Thread.currentThread().interrupt();
|
||||||
running = false;
|
running = false;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
running = false;
|
running = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import javax.inject.Inject;
|
|||||||
import javax.net.SocketFactory;
|
import javax.net.SocketFactory;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -132,7 +133,7 @@ class DevReporterImpl implements DevReporter, EventListener {
|
|||||||
try {
|
try {
|
||||||
if (c != null) c.close();
|
if (c != null) c.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ class DevReporterImpl implements DevReporter, EventListener {
|
|||||||
try {
|
try {
|
||||||
if (s != null) s.close();
|
if (s != null) s.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
||||||
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
|
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
|
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An outgoing {@link SyncSession} suitable for duplex transports. The session
|
* An outgoing {@link SyncSession} suitable for duplex transports. The session
|
||||||
@@ -240,7 +241,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
LOG.info("Generated ack: " + (a != null));
|
LOG.info("Generated ack: " + (a != null));
|
||||||
if (a != null) writerTasks.add(new WriteAck(a));
|
if (a != null) writerTasks.add(new WriteAck(a));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -287,7 +288,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
LOG.info("Generated batch: " + (b != null));
|
LOG.info("Generated batch: " + (b != null));
|
||||||
if (b != null) writerTasks.add(new WriteBatch(b));
|
if (b != null) writerTasks.add(new WriteBatch(b));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,7 +335,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
LOG.info("Generated offer: " + (o != null));
|
LOG.info("Generated offer: " + (o != null));
|
||||||
if (o != null) writerTasks.add(new WriteOffer(o));
|
if (o != null) writerTasks.add(new WriteOffer(o));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,7 +380,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
LOG.info("Generated request: " + (r != null));
|
LOG.info("Generated request: " + (r != null));
|
||||||
if (r != null) writerTasks.add(new WriteRequest(r));
|
if (r != null) writerTasks.add(new WriteRequest(r));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import javax.annotation.concurrent.ThreadSafe;
|
|||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An incoming {@link SyncSession}.
|
* An incoming {@link SyncSession}.
|
||||||
@@ -127,7 +128,7 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +154,7 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,7 +180,7 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +206,7 @@ class IncomingSession implements SyncSession, EventListener {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STOPPING;
|
||||||
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
|
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
|
||||||
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
|
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_IDS;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An outgoing {@link SyncSession} suitable for simplex transports. The session
|
* An outgoing {@link SyncSession} suitable for simplex transports. The session
|
||||||
@@ -139,7 +140,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
if (a == null) decrementOutstandingQueries();
|
if (a == null) decrementOutstandingQueries();
|
||||||
else writerTasks.add(new WriteAck(a));
|
else writerTasks.add(new WriteAck(a));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,7 +185,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
|
|||||||
if (b == null) decrementOutstandingQueries();
|
if (b == null) decrementOutstandingQueries();
|
||||||
else writerTasks.add(new WriteBatch(b));
|
else writerTasks.add(new WriteBatch(b));
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void readRecord() throws IOException {
|
private void readRecord() throws IOException {
|
||||||
assert nextRecord == null;
|
if (nextRecord != null) throw new AssertionError();
|
||||||
while (true) {
|
while (true) {
|
||||||
nextRecord = reader.readRecord();
|
nextRecord = reader.readRecord();
|
||||||
// Check the protocol version
|
// Check the protocol version
|
||||||
@@ -62,7 +62,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private byte getNextRecordType() {
|
private byte getNextRecordType() {
|
||||||
assert nextRecord != null;
|
if (nextRecord == null) throw new AssertionError();
|
||||||
return nextRecord.getRecordType();
|
return nextRecord.getRecordType();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<MessageId> readMessageIds() throws IOException {
|
private List<MessageId> readMessageIds() throws IOException {
|
||||||
assert nextRecord != null;
|
if (nextRecord == null) throw new AssertionError();
|
||||||
byte[] payload = nextRecord.getPayload();
|
byte[] payload = nextRecord.getPayload();
|
||||||
if (payload.length == 0) throw new FormatException();
|
if (payload.length == 0) throw new FormatException();
|
||||||
if (payload.length % UniqueId.LENGTH != 0) throw new FormatException();
|
if (payload.length % UniqueId.LENGTH != 0) throw new FormatException();
|
||||||
@@ -122,7 +122,7 @@ class SyncRecordReaderImpl implements SyncRecordReader {
|
|||||||
@Override
|
@Override
|
||||||
public Message readMessage() throws IOException {
|
public Message readMessage() throws IOException {
|
||||||
if (!hasMessage()) throw new FormatException();
|
if (!hasMessage()) throw new FormatException();
|
||||||
assert nextRecord != null;
|
if (nextRecord == null) throw new AssertionError();
|
||||||
byte[] payload = nextRecord.getPayload();
|
byte[] payload = nextRecord.getPayload();
|
||||||
if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException();
|
if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException();
|
||||||
// Validate timestamp
|
// Validate timestamp
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import static java.util.logging.Level.WARNING;
|
|||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.INVALID;
|
||||||
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
import static org.briarproject.bramble.api.sync.ValidationManager.State.PENDING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -110,7 +111,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
validateNextMessageAsync(unvalidated);
|
validateNextMessageAsync(unvalidated);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +145,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
LOG.info("Group removed before validation");
|
LOG.info("Group removed before validation");
|
||||||
validateNextMessageAsync(unvalidated);
|
validateNextMessageAsync(unvalidated);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +166,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
deliverNextPendingMessageAsync(pending);
|
deliverNextPendingMessageAsync(pending);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +232,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
LOG.info("Group removed before delivery");
|
LOG.info("Group removed before delivery");
|
||||||
deliverNextPendingMessageAsync(pending);
|
deliverNextPendingMessageAsync(pending);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,8 +253,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
storeMessageContextAsync(m, g.getClientId(),
|
storeMessageContextAsync(m, g.getClientId(),
|
||||||
g.getMajorVersion(), context);
|
g.getMajorVersion(), context);
|
||||||
} catch (InvalidMessageException e) {
|
} catch (InvalidMessageException e) {
|
||||||
if (LOG.isLoggable(INFO))
|
logException(LOG, INFO, e);
|
||||||
LOG.log(INFO, e.toString(), e);
|
|
||||||
Queue<MessageId> invalidate = new LinkedList<>();
|
Queue<MessageId> invalidate = new LinkedList<>();
|
||||||
invalidate.add(m.getId());
|
invalidate.add(m.getId());
|
||||||
invalidateNextMessageAsync(invalidate);
|
invalidateNextMessageAsync(invalidate);
|
||||||
@@ -326,7 +326,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
} catch (NoSuchGroupException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
LOG.info("Group removed during validation");
|
LOG.info("Group removed during validation");
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
}
|
}
|
||||||
shareNextMessageAsync(toShare);
|
shareNextMessageAsync(toShare);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,7 +412,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
LOG.info("Group removed before sharing");
|
LOG.info("Group removed before sharing");
|
||||||
shareNextMessageAsync(toShare);
|
shareNextMessageAsync(toShare);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
LOG.info("Message removed before invalidation");
|
LOG.info("Message removed before invalidation");
|
||||||
invalidateNextMessageAsync(invalidate);
|
invalidateNextMessageAsync(invalidate);
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +492,7 @@ class ValidationManagerImpl implements ValidationManager, Service,
|
|||||||
} catch (NoSuchGroupException e) {
|
} catch (NoSuchGroupException e) {
|
||||||
LOG.info("Group removed before validation");
|
LOG.info("Group removed before validation");
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.logging.Logger;
|
|||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -49,7 +50,7 @@ class LinuxSecureRandomProvider extends AbstractSecureRandomProvider {
|
|||||||
out.close();
|
out.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// On some devices /dev/urandom isn't writable - this isn't fatal
|
// On some devices /dev/urandom isn't writable - this isn't fatal
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.security.SecureRandomSpi;
|
|||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
public class LinuxSecureRandomSpi extends SecureRandomSpi {
|
public class LinuxSecureRandomSpi extends SecureRandomSpi {
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ public class LinuxSecureRandomSpi extends SecureRandomSpi {
|
|||||||
out.close();
|
out.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// On some devices /dev/urandom isn't writable - this isn't fatal
|
// On some devices /dev/urandom isn't writable - this isn't fatal
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOC
|
|||||||
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
import static org.briarproject.bramble.api.transport.TransportConstants.PROTOCOL_VERSION;
|
||||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||||
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
import static org.briarproject.bramble.util.ByteUtils.MAX_32_BIT_UNSIGNED;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -169,7 +170,7 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
db.endTransaction(txn);
|
db.endTransaction(txn);
|
||||||
}
|
}
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
|
logException(LOG, WARNING, e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,341 @@
|
|||||||
|
package org.briarproject.bramble.account;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
|
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||||
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
|
import org.briarproject.bramble.test.BrambleMockTestCase;
|
||||||
|
import org.jmock.Expectations;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertFalse;
|
||||||
|
import static junit.framework.Assert.assertNull;
|
||||||
|
import static junit.framework.Assert.assertTrue;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.toHexString;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
public class AccountManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
|
private final DatabaseConfig databaseConfig =
|
||||||
|
context.mock(DatabaseConfig.class);
|
||||||
|
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
|
||||||
|
private final IdentityManager identityManager =
|
||||||
|
context.mock(IdentityManager.class);
|
||||||
|
|
||||||
|
private final SecretKey key = getSecretKey();
|
||||||
|
private final byte[] encryptedKey = getRandomBytes(123);
|
||||||
|
private final String encryptedKeyHex = toHexString(encryptedKey);
|
||||||
|
private final byte[] newEncryptedKey = getRandomBytes(123);
|
||||||
|
private final String newEncryptedKeyHex = toHexString(newEncryptedKey);
|
||||||
|
private final LocalAuthor localAuthor = getLocalAuthor();
|
||||||
|
private final String authorName = localAuthor.getName();
|
||||||
|
private final String password = getRandomString(10);
|
||||||
|
private final String newPassword = getRandomString(10);
|
||||||
|
private final File testDir = getTestDirectory();
|
||||||
|
private final File dbDir = new File(testDir, "db");
|
||||||
|
private final File keyDir = new File(testDir, "key");
|
||||||
|
private final File keyFile = new File(keyDir, "db.key");
|
||||||
|
private final File keyBackupFile = new File(keyDir, "db.key.bak");
|
||||||
|
|
||||||
|
private AccountManagerImpl accountManager;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
allowing(databaseConfig).getDatabaseDirectory();
|
||||||
|
will(returnValue(dbDir));
|
||||||
|
allowing(databaseConfig).getDatabaseKeyDirectory();
|
||||||
|
will(returnValue(keyDir));
|
||||||
|
}});
|
||||||
|
|
||||||
|
accountManager =
|
||||||
|
new AccountManagerImpl(databaseConfig, crypto, identityManager);
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignInReturnsFalseIfDbKeyCannotBeLoaded() {
|
||||||
|
assertFalse(accountManager.signIn(password));
|
||||||
|
assertFalse(accountManager.hasDatabaseKey());
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignInReturnsFalseIfPasswordIsWrong() throws Exception {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(crypto).decryptWithPassword(encryptedKey, password);
|
||||||
|
will(returnValue(null));
|
||||||
|
}});
|
||||||
|
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
|
||||||
|
assertFalse(accountManager.signIn(password));
|
||||||
|
assertFalse(accountManager.hasDatabaseKey());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSignInReturnsTrueIfPasswordIsRight() throws Exception {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(crypto).decryptWithPassword(encryptedKey, password);
|
||||||
|
will(returnValue(key.getBytes()));
|
||||||
|
}});
|
||||||
|
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
|
||||||
|
assertTrue(accountManager.signIn(password));
|
||||||
|
assertTrue(accountManager.hasDatabaseKey());
|
||||||
|
SecretKey decrypted = accountManager.getDatabaseKey();
|
||||||
|
assertNotNull(decrypted);
|
||||||
|
assertArrayEquals(key.getBytes(), decrypted.getBytes());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex,
|
||||||
|
accountManager.loadEncryptedDatabaseKey());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDbKeyIsLoadedFromBackupFile() throws Exception {
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex,
|
||||||
|
accountManager.loadEncryptedDatabaseKey());
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDbKeyIsNullIfNotFound() {
|
||||||
|
assertNull(accountManager.loadEncryptedDatabaseKey());
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStoringDbKeyOverwritesPrimary() throws Exception {
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
|
||||||
|
assertTrue(accountManager.storeEncryptedDatabaseKey(
|
||||||
|
newEncryptedKeyHex));
|
||||||
|
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStoringDbKeyOverwritesBackup() throws Exception {
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
|
||||||
|
assertTrue(accountManager.storeEncryptedDatabaseKey(
|
||||||
|
newEncryptedKeyHex));
|
||||||
|
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccountExistsReturnsFalseIfDbKeyCannotBeLoaded() {
|
||||||
|
assertFalse(accountManager.accountExists());
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccountExistsReturnsFalseIfDbDirectoryDoesNotExist()
|
||||||
|
throws Exception {
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertFalse(dbDir.exists());
|
||||||
|
|
||||||
|
assertFalse(accountManager.accountExists());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
assertFalse(dbDir.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccountExistsReturnsFalseIfDbDirectoryIsNotDirectory()
|
||||||
|
throws Exception {
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertTrue(dbDir.createNewFile());
|
||||||
|
assertFalse(dbDir.isDirectory());
|
||||||
|
|
||||||
|
assertFalse(accountManager.accountExists());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
assertTrue(dbDir.exists());
|
||||||
|
assertFalse(dbDir.isDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAccountExistsReturnsTrueIfDbDirectoryIsDirectory()
|
||||||
|
throws Exception {
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertTrue(dbDir.mkdirs());
|
||||||
|
assertTrue(dbDir.isDirectory());
|
||||||
|
|
||||||
|
assertTrue(accountManager.accountExists());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
assertTrue(dbDir.exists());
|
||||||
|
assertTrue(dbDir.isDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateAccountStoresDbKey() throws Exception {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(identityManager).createLocalAuthor(authorName);
|
||||||
|
will(returnValue(localAuthor));
|
||||||
|
oneOf(identityManager).registerLocalAuthor(localAuthor);
|
||||||
|
oneOf(crypto).generateSecretKey();
|
||||||
|
will(returnValue(key));
|
||||||
|
oneOf(crypto).encryptWithPassword(key.getBytes(), password);
|
||||||
|
will(returnValue(encryptedKey));
|
||||||
|
}});
|
||||||
|
|
||||||
|
assertFalse(accountManager.hasDatabaseKey());
|
||||||
|
|
||||||
|
assertTrue(accountManager.createAccount(authorName, password));
|
||||||
|
|
||||||
|
assertTrue(accountManager.hasDatabaseKey());
|
||||||
|
SecretKey dbKey = accountManager.getDatabaseKey();
|
||||||
|
assertNotNull(dbKey);
|
||||||
|
assertArrayEquals(key.getBytes(), dbKey.getBytes());
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangePasswordReturnsFalseIfDbKeyCannotBeLoaded() {
|
||||||
|
assertFalse(accountManager.changePassword(password, newPassword));
|
||||||
|
|
||||||
|
assertFalse(keyFile.exists());
|
||||||
|
assertFalse(keyBackupFile.exists());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangePasswordReturnsFalseIfPasswordIsWrong()
|
||||||
|
throws Exception {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(crypto).decryptWithPassword(encryptedKey, password);
|
||||||
|
will(returnValue(null));
|
||||||
|
}});
|
||||||
|
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertFalse(accountManager.changePassword(password, newPassword));
|
||||||
|
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testChangePasswordReturnsTrueIfPasswordIsRight()
|
||||||
|
throws Exception {
|
||||||
|
context.checking(new Expectations() {{
|
||||||
|
oneOf(crypto).decryptWithPassword(encryptedKey, password);
|
||||||
|
will(returnValue(key.getBytes()));
|
||||||
|
oneOf(crypto).encryptWithPassword(key.getBytes(), newPassword);
|
||||||
|
will(returnValue(newEncryptedKey));
|
||||||
|
}});
|
||||||
|
|
||||||
|
storeDatabaseKey(keyFile, encryptedKeyHex);
|
||||||
|
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
|
||||||
|
|
||||||
|
assertTrue(accountManager.changePassword(password, newPassword));
|
||||||
|
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyFile));
|
||||||
|
assertEquals(newEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void storeDatabaseKey(File f, String hex) throws IOException {
|
||||||
|
f.getParentFile().mkdirs();
|
||||||
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
|
out.write(hex.getBytes("UTF-8"));
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String loadDatabaseKey(File f) throws IOException {
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||||
|
new FileInputStream(f), "UTF-8"));
|
||||||
|
String hex = reader.readLine();
|
||||||
|
reader.close();
|
||||||
|
return hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
deleteTestDirectory(testDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -89,6 +89,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
context.mock(ShutdownManager.class);
|
context.mock(ShutdownManager.class);
|
||||||
private final EventBus eventBus = context.mock(EventBus.class);
|
private final EventBus eventBus = context.mock(EventBus.class);
|
||||||
|
|
||||||
|
private final SecretKey key = getSecretKey();
|
||||||
private final Object txn = new Object();
|
private final Object txn = new Object();
|
||||||
private final ClientId clientId;
|
private final ClientId clientId;
|
||||||
private final int majorVersion;
|
private final int majorVersion;
|
||||||
@@ -141,7 +142,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
int shutdownHandle = 12345;
|
int shutdownHandle = 12345;
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// open()
|
// open()
|
||||||
oneOf(database).open(null);
|
oneOf(database).open(key, null);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
||||||
will(returnValue(shutdownHandle));
|
will(returnValue(shutdownHandle));
|
||||||
@@ -208,7 +209,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
shutdown);
|
shutdown);
|
||||||
|
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.addLocalAuthor(transaction, localAuthor);
|
db.addLocalAuthor(transaction, localAuthor);
|
||||||
@@ -1602,7 +1603,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
MessageId messageId2 = new MessageId(getRandomId());
|
MessageId messageId2 = new MessageId(getRandomId());
|
||||||
context.checking(new Expectations() {{
|
context.checking(new Expectations() {{
|
||||||
// open()
|
// open()
|
||||||
oneOf(database).open(null);
|
oneOf(database).open(key, null);
|
||||||
will(returnValue(false));
|
will(returnValue(false));
|
||||||
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
oneOf(shutdown).addShutdownHook(with(any(Runnable.class)));
|
||||||
will(returnValue(shutdownHandle));
|
will(returnValue(shutdownHandle));
|
||||||
@@ -1646,7 +1647,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
|
|||||||
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
DatabaseComponent db = createDatabaseComponent(database, eventBus,
|
||||||
shutdown);
|
shutdown);
|
||||||
|
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
Transaction transaction = db.startTransaction(false);
|
Transaction transaction = db.startTransaction(false);
|
||||||
try {
|
try {
|
||||||
db.addLocalMessage(transaction, message, metadata, true);
|
db.addLocalMessage(transaction, message, metadata, true);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.bramble.db;
|
package org.briarproject.bramble.db;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||||
import org.briarproject.bramble.api.db.DataTooNewException;
|
import org.briarproject.bramble.api.db.DataTooNewException;
|
||||||
import org.briarproject.bramble.api.db.DataTooOldException;
|
import org.briarproject.bramble.api.db.DataTooOldException;
|
||||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||||
@@ -26,6 +27,7 @@ import static java.util.Collections.singletonList;
|
|||||||
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE;
|
||||||
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY;
|
||||||
import static org.briarproject.bramble.db.JdbcDatabase.CODE_SCHEMA_VERSION;
|
import static org.briarproject.bramble.db.JdbcDatabase.CODE_SCHEMA_VERSION;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -43,6 +45,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
protected final DatabaseConfig config =
|
protected final DatabaseConfig config =
|
||||||
new TestDatabaseConfig(testDir, 1024 * 1024);
|
new TestDatabaseConfig(testDir, 1024 * 1024);
|
||||||
|
protected final SecretKey key = getSecretKey();
|
||||||
protected final Clock clock = new SystemClock();
|
protected final Clock clock = new SystemClock();
|
||||||
|
|
||||||
abstract Database<Connection> createDatabase(
|
abstract Database<Connection> createDatabase(
|
||||||
@@ -62,7 +65,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
public void testDoesNotRunMigrationsWhenCreatingDatabase()
|
public void testDoesNotRunMigrationsWhenCreatingDatabase()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
Database<Connection> db = createDatabase(singletonList(migration));
|
Database<Connection> db = createDatabase(singletonList(migration));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
@@ -72,14 +75,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
// Override the data schema version
|
// Override the data schema version
|
||||||
setDataSchemaVersion(db, -1);
|
setDataSchemaVersion(db, -1);
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - an exception should be thrown
|
// Reopen the DB - an exception should be thrown
|
||||||
db = createDatabase(asList(migration, migration1));
|
db = createDatabase(asList(migration, migration1));
|
||||||
db.open(null);
|
db.open(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -87,12 +90,12 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - migrations should not be run
|
// Reopen the DB - migrations should not be run
|
||||||
db = createDatabase(asList(migration, migration1));
|
db = createDatabase(asList(migration, migration1));
|
||||||
assertTrue(db.open(null));
|
assertTrue(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
@@ -101,14 +104,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
public void testThrowsExceptionIfDataIsNewerThanCode() throws Exception {
|
public void testThrowsExceptionIfDataIsNewerThanCode() throws Exception {
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
// Override the data schema version
|
// Override the data schema version
|
||||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION + 1);
|
setDataSchemaVersion(db, CODE_SCHEMA_VERSION + 1);
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - an exception should be thrown
|
// Reopen the DB - an exception should be thrown
|
||||||
db = createDatabase(asList(migration, migration1));
|
db = createDatabase(asList(migration, migration1));
|
||||||
db.open(null);
|
db.open(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = DataTooOldException.class)
|
@Test(expected = DataTooOldException.class)
|
||||||
@@ -116,13 +119,13 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(emptyList());
|
Database<Connection> db = createDatabase(emptyList());
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1);
|
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1);
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - an exception should be thrown
|
// Reopen the DB - an exception should be thrown
|
||||||
db = createDatabase(emptyList());
|
db = createDatabase(emptyList());
|
||||||
db.open(null);
|
db.open(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = DataTooOldException.class)
|
@Test(expected = DataTooOldException.class)
|
||||||
@@ -141,14 +144,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
// Override the data schema version
|
// Override the data schema version
|
||||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 3);
|
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 3);
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - an exception should be thrown
|
// Reopen the DB - an exception should be thrown
|
||||||
db = createDatabase(asList(migration, migration1));
|
db = createDatabase(asList(migration, migration1));
|
||||||
db.open(null);
|
db.open(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -170,14 +173,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
// Override the data schema version
|
// Override the data schema version
|
||||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - the first migration should be run
|
// Reopen the DB - the first migration should be run
|
||||||
db = createDatabase(asList(migration, migration1));
|
db = createDatabase(asList(migration, migration1));
|
||||||
assertTrue(db.open(null));
|
assertTrue(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
@@ -202,14 +205,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase {
|
|||||||
|
|
||||||
// Open the DB for the first time
|
// Open the DB for the first time
|
||||||
Database<Connection> db = createDatabase(asList(migration, migration1));
|
Database<Connection> db = createDatabase(asList(migration, migration1));
|
||||||
assertFalse(db.open(null));
|
assertFalse(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
// Override the data schema version
|
// Override the data schema version
|
||||||
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2);
|
||||||
db.close();
|
db.close();
|
||||||
// Reopen the DB - both migrations should be run
|
// Reopen the DB - both migrations should be run
|
||||||
db = createDatabase(asList(migration, migration1));
|
db = createDatabase(asList(migration, migration1));
|
||||||
assertTrue(db.open(null));
|
assertTrue(db.open(key, null));
|
||||||
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db));
|
||||||
db.close();
|
db.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.List;
|
|||||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getMean;
|
import static org.briarproject.bramble.test.TestUtils.getMean;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getMedian;
|
import static org.briarproject.bramble.test.TestUtils.getMedian;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getStandardDeviation;
|
import static org.briarproject.bramble.test.TestUtils.getStandardDeviation;
|
||||||
import static org.briarproject.bramble.test.UTest.Z_CRITICAL_0_01;
|
import static org.briarproject.bramble.test.UTest.Z_CRITICAL_0_01;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ public abstract class DatabasePerformanceComparisonTest
|
|||||||
throws DbException {
|
throws DbException {
|
||||||
Database<Connection> db = createDatabase(conditionA,
|
Database<Connection> db = createDatabase(conditionA,
|
||||||
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
||||||
db.open(null);
|
db.open(getSecretKey(), null);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import java.sql.Connection;
|
|||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
|
|
||||||
public abstract class DatabaseTraceTest extends DatabasePerformanceTest {
|
public abstract class DatabaseTraceTest extends DatabasePerformanceTest {
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ public abstract class DatabaseTraceTest extends DatabasePerformanceTest {
|
|||||||
private Database<Connection> openDatabase() throws DbException {
|
private Database<Connection> openDatabase() throws DbException {
|
||||||
Database<Connection> db = createDatabase(
|
Database<Connection> db = createDatabase(
|
||||||
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
||||||
db.open(null);
|
db.open(getSecretKey(), null);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import java.util.List;
|
|||||||
public class H2MigrationTest extends DatabaseMigrationTest {
|
public class H2MigrationTest extends DatabaseMigrationTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
Database<Connection> createDatabase(List<Migration<Connection>> migrations)
|
Database<Connection> createDatabase(
|
||||||
throws Exception {
|
List<Migration<Connection>> migrations) {
|
||||||
return new H2Database(config, clock) {
|
return new H2Database(config, clock) {
|
||||||
@Override
|
@Override
|
||||||
List<Migration<Connection>> getMigrations() {
|
List<Migration<Connection>> getMigrations() {
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import static org.briarproject.bramble.test.TestUtils.getLocalAuthor;
|
|||||||
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
import static org.briarproject.bramble.test.TestUtils.getRandomId;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
@@ -79,7 +80,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
private static final int ONE_MEGABYTE = 1024 * 1024;
|
private static final int ONE_MEGABYTE = 1024 * 1024;
|
||||||
private static final int MAX_SIZE = 5 * ONE_MEGABYTE;
|
private static final int MAX_SIZE = 5 * ONE_MEGABYTE;
|
||||||
|
|
||||||
private final File testDir = TestUtils.getTestDirectory();
|
private final SecretKey key = getSecretKey();
|
||||||
|
private final File testDir = getTestDirectory();
|
||||||
private final GroupId groupId;
|
private final GroupId groupId;
|
||||||
private final ClientId clientId;
|
private final ClientId clientId;
|
||||||
private final int majorVersion;
|
private final int majorVersion;
|
||||||
@@ -96,7 +98,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
private final KeySetId keySetId, keySetId1;
|
private final KeySetId keySetId, keySetId1;
|
||||||
private final Random random = new Random();
|
private final Random random = new Random();
|
||||||
|
|
||||||
JdbcDatabaseTest() throws Exception {
|
JdbcDatabaseTest() {
|
||||||
clientId = getClientId();
|
clientId = getClientId();
|
||||||
majorVersion = 123;
|
majorVersion = 123;
|
||||||
group = getGroup(clientId, majorVersion);
|
group = getGroup(clientId, majorVersion);
|
||||||
@@ -1819,7 +1821,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
|
|||||||
Database<Connection> db = createDatabase(
|
Database<Connection> db = createDatabase(
|
||||||
new TestDatabaseConfig(testDir, MAX_SIZE), clock);
|
new TestDatabaseConfig(testDir, MAX_SIZE), clock);
|
||||||
if (!resume) TestUtils.deleteTestDirectory(testDir);
|
if (!resume) TestUtils.deleteTestDirectory(testDir);
|
||||||
db.open(null);
|
db.open(key, null);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.List;
|
|||||||
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getMean;
|
import static org.briarproject.bramble.test.TestUtils.getMean;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getMedian;
|
import static org.briarproject.bramble.test.TestUtils.getMedian;
|
||||||
|
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getStandardDeviation;
|
import static org.briarproject.bramble.test.TestUtils.getStandardDeviation;
|
||||||
|
|
||||||
public abstract class SingleDatabasePerformanceTest
|
public abstract class SingleDatabasePerformanceTest
|
||||||
@@ -40,7 +41,7 @@ public abstract class SingleDatabasePerformanceTest
|
|||||||
private Database<Connection> openDatabase() throws DbException {
|
private Database<Connection> openDatabase() throws DbException {
|
||||||
Database<Connection> db = createDatabase(
|
Database<Connection> db = createDatabase(
|
||||||
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock());
|
||||||
db.open(null);
|
db.open(getSecretKey(), null);
|
||||||
return db;
|
return db;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user