Compare commits

..

4 Commits

Author SHA1 Message Date
akwizgran
7345d5c22c Add WebP library for API 16. 2021-05-24 15:09:19 +01:00
akwizgran
b4a2725f03 Add workarounds for missing MIME type information on API 16. 2021-05-24 14:56:50 +01:00
akwizgran
a5972e26fe Use WebP for compressing images. 2021-05-21 12:43:50 +01:00
akwizgran
aabb0bfb4a Allow WebP images to be used as attachments and avatars. 2021-05-21 12:43:19 +01:00
445 changed files with 3749 additions and 17027 deletions

View File

@@ -33,7 +33,7 @@ test:
stage: test stage: test
script: script:
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom compileOfficialDebugAndroidTestSources compileScreenshotDebugAndroidTestSources check - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom check
rules: rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always when: always

View File

@@ -31,6 +31,15 @@
<option name="PACKAGES_TO_USE_STAR_IMPORTS"> <option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value /> <value />
</option> </option>
<option name="PACKAGES_IMPORT_LAYOUT">
<value>
<package name="" alias="false" withSubpackages="true" />
<package name="java" alias="false" withSubpackages="true" />
<package name="javax" alias="false" withSubpackages="true" />
<package name="kotlin" alias="false" withSubpackages="true" />
<package name="" alias="true" withSubpackages="true" />
</value>
</option>
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" /> <option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
@@ -188,9 +197,9 @@
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="kotlin"> <codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" /> <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<indentOptions> <option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="VARIABLE_ANNOTATION_WRAP" value="1" />
</indentOptions> <option name="ENUM_CONSTANTS_WRAP" value="1" />
</codeStyleSettings> </codeStyleSettings>
</code_scheme> </code_scheme>
</component> </component>

View File

@@ -1,32 +1,21 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.briar-android" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-android" />
</option>
<option name="taskNames">
<list>
<option value=":briar-android:testOfficialDebugUnitTest" />
<option value=":briar-android:testScreenshotDebugUnitTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2"> <method v="2">
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="GradleRunConfiguration" /> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="GradleRunConfiguration" /> <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-java" run_configuration_type="GradleRunConfiguration" /> <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="GradleRunConfiguration" /> <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 briar-api" run_configuration_type="GradleRunConfiguration" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="GradleRunConfiguration" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-api" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-headless" run_configuration_type="GradleRunConfiguration" /> <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-headless" run_configuration_type="AndroidJUnit" />
</method> </method>
</configuration> </configuration>
</component> </component>

View File

@@ -1,23 +1,14 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-android" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.bramble-android" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
</option> <method v="2">
<option name="taskNames"> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<list> </method>
<option value=":bramble-android:testDebugUnitTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-api" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.bramble-api" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
</option> <method v="2">
<option name="taskNames"> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<list> </method>
<option value=":bramble-api:animalSnifferMain" />
<option value=":bramble-api:animalSnifferTest" />
<option value=":bramble-api:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-core" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.bramble-core" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
</option> <method v="2">
<option name="taskNames"> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<list> </method>
<option value=":bramble-core:animalSnifferMain" />
<option value=":bramble-core:animalSnifferTest" />
<option value=":bramble-core:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,23 +1,15 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-java" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.bramble-java" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
<list /> <option name="PARAMETERS" value="" />
</option> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
<option name="taskNames"> <method v="2">
<list> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<option value=":bramble-java:test" /> </method>
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,24 +1,14 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-android" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.briar-android" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
</option> <method v="2">
<option name="taskNames"> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<list> </method>
<option value=":briar-android:testOfficialDebugUnitTest" />
<option value=":briar-android:testScreenshotDebugUnitTest" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-api" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in briar-api" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.briar-api" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-api" />
</option> <method v="2">
<option name="taskNames"> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<list> </method>
<option value=":briar-api:animalSnifferMain" />
<option value=":briar-api:animalSnifferTest" />
<option value=":briar-api:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,25 +1,14 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-core" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.briar-core" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="PARAMETERS" value="" />
<list /> <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
</option> <method v="2">
<option name="taskNames"> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<list> </method>
<option value=":briar-core:animalSnifferMain" />
<option value=":briar-core:animalSnifferTest" />
<option value=":briar-core:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,23 +1,15 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-headless" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="All tests in briar-headless" type="AndroidJUnit" factoryName="Android JUnit">
<ExternalSystemSettings> <module name="briar.briar-headless" />
<option name="executionName" /> <option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="externalSystemIdString" value="GRADLE" /> <option name="METHOD_NAME" value="" />
<option name="scriptParameters" value="" /> <option name="TEST_OBJECT" value="package" />
<option name="taskDescriptions"> <option name="VM_PARAMETERS" />
<list /> <option name="PARAMETERS" value="" />
</option> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-headless" />
<option name="taskNames"> <method v="2">
<list> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<option value=":briar-headless:test" /> </method>
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -1,28 +1,24 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="BridgeTest" type="GradleRunConfiguration" factoryName="Gradle"> <configuration default="false" name="BridgeTest" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
<ExternalSystemSettings> <module name="briar.bramble-java" />
<option name="env"> <useClassPathOnly />
<map> <extension name="coverage">
<entry key="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" /> <pattern>
</map> <option name="PATTERN" value="org.briarproject.bramble.plugin.tor.*" />
</option> <option name="ENABLED" value="true" />
<option name="executionName" /> </pattern>
<option name="externalProjectPath" value="$PROJECT_DIR$" /> </extension>
<option name="externalSystemIdString" value="GRADLE" /> <option name="PACKAGE_NAME" value="org.briarproject.bramble.plugin.tor" />
<option name="scriptParameters" value="--tests &quot;org.briarproject.bramble.plugin.tor.BridgeTest&quot;" /> <option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
<option name="taskDescriptions"> <option name="METHOD_NAME" value="" />
<list /> <option name="TEST_OBJECT" value="class" />
</option> <option name="PARAMETERS" value="" />
<option name="taskNames"> <option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
<list> <envs>
<option value=":bramble-java:test" /> <env name="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
</list> </envs>
</option> <method v="2">
<option name="vmOptions" value="" /> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
</ExternalSystemSettings> </method>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>

View File

@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.db" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.db.H2DatabasePerformanceTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -0,0 +1,14 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar.bramble-core" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.db" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.db.HyperSqlDatabasePerformanceTest" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="class" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -1,28 +1 @@
# Briar Briar is a messaging app designed for activists, journalists, and anyone else who needs a safe, easy and robust way to communicate. Unlike traditional messaging tools such as email, Twitter or Telegram, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices. If the Internet's down, Briar can sync via Bluetooth or Wi-Fi, keeping the information flowing in a crisis. If the Internet's up, Briar can sync via the Tor network, protecting users and their relationships from surveillance.
Briar is a messaging app designed for activists, journalists, and anyone else who needs a safe, easy and robust way to communicate.
Unlike traditional messaging tools such as email, Twitter or Telegram, Briar doesn't rely on a central server - messages are synchronized directly between the users' devices.
If the Internet's down, Briar can sync via Bluetooth or Wi-Fi, keeping information flowing in a crisis. If the Internet's up, Briar can sync via the Tor network, protecting users and their relationships from surveillance.
## Download Briar
[<img src="https://briarproject.org//img/fdroid_badge.png" width="240">](https://briarproject.org/fdroid)
[<img src="https://briarproject.org/img/google_play_badge_web_generic.png" width="240">](https://play.google.com/store/apps/details?id=org.briarproject.briar.android)
You can also [download the APK file](https://briarproject.org/apk) directly from
our site.
## Useful links
[briarproject.org](https://briarproject.org/)
[Source code](https://code.briarproject.org/briar/briar/tree/master)
[Manual](https://briarproject.org/manual/)
[Wiki](https://code.briarproject.org/briar/briar/-/wikis/home)
## Donate
[![Donate using Liberapay](https://briarproject.org/img/liberapay.svg)](https://liberapay.com/Briar/donate) [![Flattr this](https://briarproject.org/img/flattr-badge-large.png "Flattr this")](https://flattr.com/t/592836/)
Bitcoin and BCH: 1NZCKkUCtJV2U2Y9hDb9uq8S7ksFCFGR6K

View File

@@ -15,8 +15,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 30 targetSdkVersion 30
versionCode 10401 versionCode 10304
versionName "1.4.1" versionName "1.3.4"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -42,18 +42,18 @@ configurations {
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
tor "org.briarproject:tor-android:$tor_version" tor 'org.briarproject:tor-android:0.3.5.13@zip'
tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version@zip" tor 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a@zip'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'javax.annotation:jsr250-api:1.0'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation "junit:junit:$junit_version" testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:$jmock_version" testImplementation "org.jmock:jmock-legacy:2.8.2"
} }
def torBinariesDir = 'src/main/res/raw' def torBinariesDir = 'src/main/res/raw'

View File

@@ -5,15 +5,12 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -26,18 +23,14 @@ import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
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.Logger.getLogger;
import static org.briarproject.bramble.util.AndroidUtils.getPersistentLogDir;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir; import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.logFileOrDir; import static org.briarproject.bramble.util.LogUtils.logFileOrDir;
class AndroidAccountManager extends AccountManagerImpl class AndroidAccountManager extends AccountManagerImpl
implements AccountManager { implements AccountManager {
private static final Logger LOG = private static final Logger LOG =
getLogger(AndroidAccountManager.class.getName()); Logger.getLogger(AndroidAccountManager.class.getName());
/** /**
* Directories that shouldn't be deleted when deleting the user's account. * Directories that shouldn't be deleted when deleting the user's account.
@@ -47,22 +40,13 @@ class AndroidAccountManager extends AccountManagerImpl
protected final Context appContext; protected final Context appContext;
private final SharedPreferences prefs; private final SharedPreferences prefs;
private final PersistentLogManager logManager;
private final FeatureFlags featureFlags;
@Inject @Inject
AndroidAccountManager( AndroidAccountManager(DatabaseConfig databaseConfig,
DatabaseConfig databaseConfig, CryptoComponent crypto, IdentityManager identityManager,
CryptoComponent crypto, SharedPreferences prefs, Application app) {
IdentityManager identityManager,
SharedPreferences prefs,
PersistentLogManager logManager,
FeatureFlags featureFlags,
Application app) {
super(databaseConfig, crypto, identityManager); super(databaseConfig, crypto, identityManager);
this.prefs = prefs; this.prefs = prefs;
this.logManager = logManager;
this.featureFlags = featureFlags;
appContext = app.getApplicationContext(); appContext = app.getApplicationContext();
} }
@@ -90,9 +74,6 @@ class AndroidAccountManager extends AccountManagerImpl
LOG.info("Contents of account directory after deleting:"); LOG.info("Contents of account directory after deleting:");
logFileOrDir(LOG, INFO, getDataDir()); logFileOrDir(LOG, INFO, getDataDir());
} }
if (featureFlags.shouldEnablePersistentLogs()) {
replacePersistentLogger();
}
} }
} }
@@ -153,13 +134,4 @@ class AndroidAccountManager extends AccountManagerImpl
private void addIfNotNull(Set<File> files, @Nullable File file) { private void addIfNotNull(Set<File> files, @Nullable File file) {
if (file != null) files.add(file); if (file != null) files.add(file);
} }
private void replacePersistentLogger() {
File logDir = getPersistentLogDir(appContext);
try {
logManager.addLogHandler(logDir, getLogger(""));
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
} }

View File

@@ -87,7 +87,7 @@ class AndroidBluetoothPlugin extends
Clock clock, Clock clock,
Backoff backoff, Backoff backoff,
PluginCallback callback, PluginCallback callback,
long maxLatency, int maxLatency,
int maxIdleTime) { int maxIdleTime) {
super(connectionLimiter, connectionFactory, ioExecutor, super(connectionLimiter, connectionFactory, ioExecutor,
wakefulIoExecutor, secureRandom, backoff, callback, wakefulIoExecutor, secureRandom, backoff, callback,

View File

@@ -47,7 +47,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
@Inject @Inject
AndroidBluetoothPluginFactory(@IoExecutor Executor ioExecutor, public AndroidBluetoothPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor, @WakefulIoExecutor Executor wakefulIoExecutor,
AndroidExecutor androidExecutor, AndroidExecutor androidExecutor,
AndroidWakeLockManager wakeLockManager, AndroidWakeLockManager wakeLockManager,
@@ -75,7 +75,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }

View File

@@ -1,44 +0,0 @@
package org.briarproject.bramble.plugin.file;
import android.app.Application;
import android.net.Uri;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.PROP_URI;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@Immutable
@NotNullByDefault
class AndroidRemovableDrivePlugin extends RemovableDrivePlugin {
private final Application app;
AndroidRemovableDrivePlugin(Application app, PluginCallback callback,
long maxLatency) {
super(callback, maxLatency);
this.app = app;
}
@Override
InputStream openInputStream(TransportProperties p) throws IOException {
String uri = p.get(PROP_URI);
if (isNullOrEmpty(uri)) throw new IllegalArgumentException();
return app.getContentResolver().openInputStream(Uri.parse(uri));
}
@Override
OutputStream openOutputStream(TransportProperties p) throws IOException {
String uri = p.get(PROP_URI);
if (isNullOrEmpty(uri)) throw new IllegalArgumentException();
return app.getContentResolver().openOutputStream(Uri.parse(uri));
}
}

View File

@@ -1,47 +0,0 @@
package org.briarproject.bramble.plugin.file;
import android.app.Application;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static java.util.concurrent.TimeUnit.DAYS;
import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.ID;
@Immutable
@NotNullByDefault
public class AndroidRemovableDrivePluginFactory implements
SimplexPluginFactory {
private static final long MAX_LATENCY = DAYS.toMillis(28);
private final Application app;
@Inject
AndroidRemovableDrivePluginFactory(Application app) {
this.app = app;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public long getMaxLatency() {
return MAX_LATENCY;
}
@Nullable
@Override
public SimplexPlugin createPlugin(PluginCallback callback) {
return new AndroidRemovableDrivePlugin(app, callback, MAX_LATENCY);
}
}

View File

@@ -29,7 +29,6 @@ import java.net.UnknownHostException;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.net.SocketFactory; import javax.net.SocketFactory;
@@ -49,7 +48,6 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.IoUtils.tryToClose;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces;
@NotNullByDefault @NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin { class AndroidLanTcpPlugin extends LanTcpPlugin {
@@ -57,13 +55,6 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
private static final Logger LOG = private static final Logger LOG =
getLogger(AndroidLanTcpPlugin.class.getName()); getLogger(AndroidLanTcpPlugin.class.getName());
/**
* The interface name is used as a heuristic for deciding whether the
* device is providing a wifi access point.
*/
private static final Pattern AP_INTERFACE_NAME =
Pattern.compile("^(wlan|ap|p2p)[-0-9]");
private final Executor connectionStatusExecutor; private final Executor connectionStatusExecutor;
private final ConnectivityManager connectivityManager; private final ConnectivityManager connectivityManager;
@Nullable @Nullable
@@ -76,7 +67,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
Application app, Application app,
Backoff backoff, Backoff backoff,
PluginCallback callback, PluginCallback callback,
long maxLatency, int maxLatency,
int maxIdleTime, int maxIdleTime,
int connectionTimeout) { int connectionTimeout) {
super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency, super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency,
@@ -139,14 +130,17 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
if (info != null && info.getIpAddress() != 0) { if (info != null && info.getIpAddress() != 0) {
return new Pair<>(intToInetAddress(info.getIpAddress()), false); return new Pair<>(intToInetAddress(info.getIpAddress()), false);
} }
// If we're providing an access point, return its address List<InterfaceAddress> ifAddrs = getLocalInterfaceAddresses();
for (NetworkInterface iface : getNetworkInterfaces()) { // If we're providing a normal access point, return its address
if (AP_INTERFACE_NAME.matcher(iface.getName()).find()) { for (InterfaceAddress ifAddr : ifAddrs) {
for (InterfaceAddress ifAddr : iface.getInterfaceAddresses()) { if (isAndroidWifiApAddress(ifAddr)) {
if (isPossibleWifiApInterface(ifAddr)) { return new Pair<>(ifAddr.getAddress(), true);
return new Pair<>(ifAddr.getAddress(), true); }
} }
} // If we're providing a wifi direct access point, return its address
for (InterfaceAddress ifAddr : ifAddrs) {
if (isAndroidWifiDirectApAddress(ifAddr)) {
return new Pair<>(ifAddr.getAddress(), true);
} }
} }
// Not connected to wifi // Not connected to wifi
@@ -154,18 +148,33 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
} }
/** /**
* Returns true if the given address may belong to an interface providing * Returns true if the given address belongs to a network provided by an
* a wifi access point (including wifi direct legacy mode access points). * Android access point (including the access point's own address).
* <p> * <p>
* This method may return true for wifi client interfaces as well, but * The access point's address is usually 192.168.43.1, but at least one
* we've already checked for a wifi client connection above. * device (Honor 8A) may use other addresses in the range 192.168.43.0/24.
*/ */
private boolean isPossibleWifiApInterface(InterfaceAddress ifAddr) { private boolean isAndroidWifiApAddress(InterfaceAddress ifAddr) {
if (ifAddr.getNetworkPrefixLength() != 24) return false; if (ifAddr.getNetworkPrefixLength() != 24) return false;
byte[] ip = ifAddr.getAddress().getAddress(); byte[] ip = ifAddr.getAddress().getAddress();
return ip.length == 4 return ip.length == 4
&& ip[0] == (byte) 192 && ip[0] == (byte) 192
&& ip[1] == (byte) 168; && ip[1] == (byte) 168
&& ip[2] == (byte) 43;
}
/**
* Returns true if the given address belongs to a network provided by an
* Android wifi direct legacy mode access point (including the access
* point's own address).
*/
private boolean isAndroidWifiDirectApAddress(InterfaceAddress ifAddr) {
if (ifAddr.getNetworkPrefixLength() != 24) return false;
byte[] ip = ifAddr.getAddress().getAddress();
return ip.length == 4
&& ip[0] == (byte) 192
&& ip[1] == (byte) 168
&& ip[2] == (byte) 49;
} }
/** /**

View File

@@ -37,7 +37,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private final Application app; private final Application app;
@Inject @Inject
AndroidLanTcpPluginFactory(@IoExecutor Executor ioExecutor, public AndroidLanTcpPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor, @WakefulIoExecutor Executor wakefulIoExecutor,
EventBus eventBus, EventBus eventBus,
BackoffFactory backoffFactory, BackoffFactory backoffFactory,
@@ -55,7 +55,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }

View File

@@ -68,16 +68,14 @@ class AndroidTorPlugin extends TorPlugin {
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
long maxLatency, int maxLatency,
int maxIdleTime, int maxIdleTime,
File torDirectory, File torDirectory) {
int torSocksPort,
int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, maxLatency, torRendezvousCrypto, callback, architecture, maxLatency,
maxIdleTime, torDirectory, torSocksPort, torControlPort); maxIdleTime, torDirectory);
this.app = app; this.app = app;
wakeLock = wakeLockManager.createWakeLock("TorPlugin"); wakeLock = wakeLockManager.createWakeLock("TorPlugin");
String nativeLibDir = app.getApplicationInfo().nativeLibraryDir; String nativeLibDir = app.getApplicationInfo().nativeLibraryDir;

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.plugin.tor;
import android.app.Application; import android.app.Application;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
@@ -12,9 +11,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory; import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.TransportId; 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.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
@@ -59,12 +56,9 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private final AndroidWakeLockManager wakeLockManager; private final AndroidWakeLockManager wakeLockManager;
private final Clock clock; private final Clock clock;
private final File torDirectory; private final File torDirectory;
private int torSocksPort;
private int torControlPort;
private final CryptoComponent crypto;
@Inject @Inject
AndroidTorPluginFactory(@IoExecutor Executor ioExecutor, public AndroidTorPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor, @WakefulIoExecutor Executor wakefulIoExecutor,
Application app, Application app,
NetworkManager networkManager, NetworkManager networkManager,
@@ -77,10 +71,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
BatteryManager batteryManager, BatteryManager batteryManager,
AndroidWakeLockManager wakeLockManager, AndroidWakeLockManager wakeLockManager,
Clock clock, Clock clock,
@TorDirectory File torDirectory, @TorDirectory File torDirectory) {
@TorSocksPort int torSocksPort,
@TorControlPort int torControlPort,
CryptoComponent crypto) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor; this.wakefulIoExecutor = wakefulIoExecutor;
this.app = app; this.app = app;
@@ -95,9 +86,6 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.wakeLockManager = wakeLockManager; this.wakeLockManager = wakeLockManager;
this.clock = clock; this.clock = clock;
this.torDirectory = torDirectory; this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort;
this.crypto = crypto;
} }
@Override @Override
@@ -106,7 +94,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@@ -139,15 +127,13 @@ public class AndroidTorPluginFactory 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);
TorRendezvousCrypto torRendezvousCrypto = TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
new TorRendezvousCryptoImpl(crypto);
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor,
wakefulIoExecutor, app, networkManager, locationUtils, wakefulIoExecutor, app, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, wakeLockManager, circumventionProvider, batteryManager, wakeLockManager,
backoff, torRendezvousCrypto, callback, architecture, backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort, MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
torControlPort);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -111,19 +111,20 @@ public class AndroidUtils {
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE); return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
} }
public static File getTemporaryLogFile(Context ctx) { public static File getLogcatFile(Context ctx) {
return new File(ctx.getFilesDir(), STORED_LOGCAT); return new File(ctx.getFilesDir(), STORED_LOGCAT);
} }
public static File getPersistentLogDir(Context ctx) {
return ctx.getDir("log", MODE_PRIVATE);
}
/** /**
* Returns an array of supported content types for image attachments. * Returns an array of supported content types for image attachments.
*/ */
public static String[] getSupportedImageContentTypes() { public static String[] getSupportedImageContentTypes() {
return new String[] {"image/jpeg", "image/png", "image/gif"}; return new String[] {
"image/jpeg",
"image/png",
"image/gif",
"image/webp"
};
} }
@Nullable @Nullable

View File

@@ -4,11 +4,9 @@ import android.app.Application;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
@@ -17,9 +15,7 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.io.File; import java.io.File;
import java.util.logging.Logger;
import static android.content.Context.MODE_PRIVATE;
import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
@@ -31,10 +27,6 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
context.mock(SharedPreferences.class, "prefs"); context.mock(SharedPreferences.class, "prefs");
private final SharedPreferences defaultPrefs = private final SharedPreferences defaultPrefs =
context.mock(SharedPreferences.class, "defaultPrefs"); context.mock(SharedPreferences.class, "defaultPrefs");
private final PersistentLogManager logManager =
context.mock(PersistentLogManager.class);
private final FeatureFlags featureFlags =
context.mock(FeatureFlags.class);
private final DatabaseConfig databaseConfig = private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class); context.mock(DatabaseConfig.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class); private final CryptoComponent crypto = context.mock(CryptoComponent.class);
@@ -48,7 +40,6 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
private final File testDir = getTestDirectory(); private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key"); private final File keyDir = new File(testDir, "key");
private final File dbDir = new File(testDir, "db"); private final File dbDir = new File(testDir, "db");
private final File logDir = new File(testDir, "log");
private AndroidAccountManager accountManager; private AndroidAccountManager accountManager;
@@ -70,7 +61,7 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(app)); will(returnValue(app));
}}); }});
accountManager = new AndroidAccountManager(databaseConfig, crypto, accountManager = new AndroidAccountManager(databaseConfig, crypto,
identityManager, prefs, logManager, featureFlags, app) { identityManager, prefs, app) {
@Override @Override
SharedPreferences getDefaultSharedPreferences() { SharedPreferences getDefaultSharedPreferences() {
return defaultPrefs; return defaultPrefs;
@@ -118,17 +109,10 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
will(returnValue(cacheDir)); will(returnValue(cacheDir));
oneOf(app).getExternalCacheDir(); oneOf(app).getExternalCacheDir();
will(returnValue(externalCacheDir)); will(returnValue(externalCacheDir));
oneOf(featureFlags).shouldEnablePersistentLogs();
will(returnValue(true));
oneOf(app).getDir("log", MODE_PRIVATE);
will(returnValue(logDir));
oneOf(logManager).addLogHandler(with(logDir),
with(any(Logger.class)));
}}); }});
assertTrue(dbDir.mkdirs()); assertTrue(dbDir.mkdirs());
assertTrue(keyDir.mkdirs()); assertTrue(keyDir.mkdirs());
assertTrue(logDir.mkdirs());
assertTrue(codeCacheDir.mkdirs()); assertTrue(codeCacheDir.mkdirs());
assertTrue(codeCacheFile.createNewFile()); assertTrue(codeCacheFile.createNewFile());
assertTrue(libDir.mkdirs()); assertTrue(libDir.mkdirs());
@@ -146,7 +130,6 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertFalse(dbDir.exists()); assertFalse(dbDir.exists());
assertFalse(keyDir.exists()); assertFalse(keyDir.exists());
assertFalse(logDir.exists());
assertTrue(codeCacheDir.exists()); assertTrue(codeCacheDir.exists());
assertTrue(codeCacheFile.exists()); assertTrue(codeCacheFile.exists());
assertTrue(libDir.exists()); assertTrue(libDir.exists());

View File

@@ -1,161 +1,110 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:30.0.3:protos-30.0.3.jar:f62b89dcd9de719c6a7b7e15fb1dd20e45b57222e675cf633607bd0ed6bca7e7', 'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
'com.android.tools.analytics-library:shared:30.0.3:shared-30.0.3.jar:05aa9ba3cc890354108521fdf99802565aae5dd6ca44a6ac8bb8d594d1c1cd15', 'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
'com.android.tools.analytics-library:tracker:30.0.3:tracker-30.0.3.jar:5d0ef35bf6733e96210b5085a2a202152921bf834d345959dce1ca3369b528df', 'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca', 'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
'com.android.tools.build:apksig:7.0.3:apksig-7.0.3.jar:012337a2803c9a30dfc41dcbc6450686ee9e5f582549f7f126479f743a343ec9', 'com.android.tools.build:apksig:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
'com.android.tools.build:apkzlib:7.0.3:apkzlib-7.0.3.jar:b31e53174c92db83c5cc6e7dac6734ea4e907a72e452c2bf1818dfd082c59397', 'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
'com.android.tools.build:builder-model:7.0.3:builder-model-7.0.3.jar:483f99d7494a5bed027e1e8d29111384cf535d4842f0be5a79805bd44bb68d4e', 'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
'com.android.tools.build:builder-test-api:7.0.3:builder-test-api-7.0.3.jar:f6de4bc2cef545e8367bf82d7c733829c7be3b0b3b8b09fd8c58f2150e59ab46', 'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
'com.android.tools.build:builder:7.0.3:builder-7.0.3.jar:c6952da0094b094c2ba0fe84c675622097c5d9b9f9beb53485b860320540cf1d', 'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
'com.android.tools.build:manifest-merger:30.0.3:manifest-merger-30.0.3.jar:72b346ba6318b4b6260e6e49df4bea5da2e12329ab6c2beb2269c49a9f51f178', 'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
'com.android.tools.ddms:ddmlib:30.0.3:ddmlib-30.0.3.jar:7a914a68ab93393657297234e2f37b22410ae9a433cba692ce8c727c9607e3bb', 'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
'com.android.tools.external.com-intellij:intellij-core:30.0.3:intellij-core-30.0.3.jar:1ebe858d3f58eeaa8c06507f8ac0f1c7051e6c61f35a70f3c3967d5734d3abc5', 'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
'com.android.tools.external.com-intellij:kotlin-compiler:30.0.3:kotlin-compiler-30.0.3.jar:ed00e441f427cb4e0d418287b9da30b12b7f735f9af32e6b5d3dc960b6a742fc', 'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
'com.android.tools.external.org-jetbrains:uast:30.0.3:uast-30.0.3.jar:a77801bee6ff509910e459525c9c34d7f04b066ade123547f16f1917548eadea', 'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
'com.android.tools.layoutlib:layoutlib-api:30.0.3:layoutlib-api-30.0.3.jar:4caa87e9ca2e11315f650d576cd59fec1793373bc3fca3f6d53c029e7534e7c4', 'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
'com.android.tools.lint:lint-api:30.0.3:lint-api-30.0.3.jar:bcecbd2f752a6560096a9029a47d1de6bd788a51bab505c5ebfba6a18524b983', 'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
'com.android.tools.lint:lint-checks:30.0.3:lint-checks-30.0.3.jar:25a7cd42dc3ad502337f131fb8b7e873c53301db0a67b1c64dd4ae7a8eb66cec', 'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
'com.android.tools.lint:lint-gradle:30.0.3:lint-gradle-30.0.3.jar:94544d6147a809bf2fd3440e51f28a4e42e547d74aab53eefd74938cdad42c26', 'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
'com.android.tools.lint:lint-model:30.0.3:lint-model-30.0.3.jar:0b940a7f575c2ff5cbd038260f41dde686a93c672213881ead3ce8af3513b396', 'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
'com.android.tools.lint:lint:30.0.3:lint-30.0.3.jar:ee4f11001e0c7e3b776e0d67399ad354b19b0f168822ec2b7db47c0910ed227d', 'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
'com.android.tools:annotations:30.0.3:annotations-30.0.3.jar:5c1944982fda8555855c4f5422fabf0dc8e2306e1f5460e9ad82dae71316bc31', 'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
'com.android.tools:common:30.0.3:common-30.0.3.jar:8751efaaf2c2ddd1f0a37526c794347def6a3057ca9fc510307c13a6cf0d036f', 'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
'com.android.tools:dvlib:30.0.3:dvlib-30.0.3.jar:5affafcec390041e5afd64cb924153f5e474db47ee8ccc2f555b495083141233', 'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
'com.android.tools:repository:30.0.3:repository-30.0.3.jar:0a40c6f16c506903ce2c609affd8228aceda73a69d93dfa42d4f02b8491449f6', 'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
'com.android.tools:sdk-common:30.0.3:sdk-common-30.0.3.jar:b45570a380360236ffee0f6bb593d66b673bad3834dfe0d6c9871fa7188ee0eb', 'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
'com.android.tools:sdklib:30.0.3:sdklib-30.0.3.jar:7088f20a414fab170a21e457825e14ebe099f753558e02c8acc12c67eb412162', 'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
'com.android:signflinger:7.0.3:signflinger-7.0.3.jar:903a4536db3e96b4e1e1dc1e400eb0b91bf7866d9b39cd7ec94d75dde158f152', 'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
'com.android:zipflinger:7.0.3:zipflinger-7.0.3.jar:fd209c960a3eff7a339e6fcba07d5e9ef4604d1633c69ab2df987460d9804140', 'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
'com.beust:jcommander:1.78:jcommander-1.78.jar:7891debb84b5f83e9bd57593ebece3399abbe0fd938cf306b3534c57913b9615', 'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
'com.github.javaparser:javaparser-core:3.17.0:javaparser-core-3.17.0.jar:23f5c982e1c7771423d37d52c774e8d2e80fd7ea7305ebe448797a96f67e6fca', 'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f', 'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e', 'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8', 'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4', 'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb', 'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a', 'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'com.google.errorprone:error_prone_annotations:2.3.4:error_prone_annotations-2.3.4.jar:baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c', 'com.google.errorprone:error_prone_annotations:2.3.2:error_prone_annotations-2.3.2.jar:357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30', 'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e', 'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26', 'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7', 'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'com.google.guava:guava:30.1-jre:guava-30.1-jre.jar:e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa', 'com.google.guava:guava:28.1-jre:guava-28.1-jre.jar:30beb8b8527bd07c6e747e77f1a92122c2f29d57ce347461a4a55eb26e382da4',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6', 'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b', 'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd', 'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9', 'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439', 'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291', 'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0', 'com.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.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef', 'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511', 'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
'com.thoughtworks.qdox:qdox:1.12.1:qdox-1.12.1.jar:21fba22f830e9268f07cf4ab2d99e8181abbdcb0cb91ee0228eb3cb918dcdd1d',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569', 'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
'commons-io:commons-io:2.4:commons-io-2.4.jar:cc6a41dc3eaacc9e440a6bd0d2890b20d36b4ee408fe2d67122f328bb6e01581',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636', 'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'info.picocli:picocli:4.5.2:picocli-4.5.2.jar:b4395e9a67932616efd2245d984bf5fcd453c2c5049558c3ce959ac2af4d3fac', 'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071', 'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f', 'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'jline:jline:2.14.6:jline-2.14.6.jar:97d1acaac82409be42e622d7a54d3ae9d08517e8aefdea3d2ba9791150c2f02d', 'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5', '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', 'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant-antlr:1.10.9:ant-antlr-1.10.9.jar:7623dc9d0f20ea713290c6bf1a23f4c059447aef7ff9f5b2be75960f3f028d2e', 'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.ant:ant-junit:1.10.9:ant-junit-1.10.9.jar:960bdc8827954d62206ba42d0a68a7ee4476175ba47bb113e17e77cce7394630', 'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.ant:ant-launcher:1.10.9:ant-launcher-1.10.9.jar:fcce891f57f3be72149ff96ac2a80574165b3e0839866b95d24528f3027d50c1',
'org.apache.ant:ant:1.10.9:ant-1.10.9.jar:0715478af585ea80a18985613ebecdc7922122d45b2c3c970ff9b352cddb75fc',
'org.apache.commons:commons-compress:1.20:commons-compress-1.20.jar:0aeb625c948c697ea7b205156e112363b59ed5e2551212cd4e460bdb72c7c06e',
'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7', 'org.apache.httpcomponents:httpclient:4.5.6:httpclient-4.5.6.jar:c03f813195e7a80e3608d0ddd8da80b21696a4c92a6a2298865bf149071551c7',
'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd', 'org.apache.httpcomponents:httpcore:4.4.10:httpcore-4.4.10.jar:78ba1096561957db1b55200a159b648876430342d15d461277e62360da19f6fd',
'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e', 'org.apache.httpcomponents:httpmime:4.5.6:httpmime-4.5.6.jar:0b2b1102c18d3c7e05a77214b9b7501a6f6056174ae5604e0e256776eda7553e',
'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:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', 'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82', 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82',
'org.briarproject:tor-android:0.3.5.17:tor-android-0.3.5.17.jar:1888afc10a26b93d00a010ea27bf0b1b162a6d524688b08b98d70d14dc363b54', 'org.briarproject:tor-android:0.3.5.13:tor-android-0.3.5.13.zip:e0978db136731dae07774b722970cdae1e462fb5adc82845dd80a7e2d87f356c',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a', 'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4', 'org.checkerframework:checker-qual:2.8.1:checker-qual-2.8.1.jar:9103499008bcecd4e948da29b17864abb64304e15706444ae209d17ebe0575df',
'org.codehaus.groovy:groovy-ant:3.0.7:groovy-ant-3.0.7.jar:6ed2ba82813d128f7050c24142e87b3dc2ad8b504786280eb03e81f0cf6a5793', 'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
'org.codehaus.groovy:groovy-astbuilder:3.0.7:groovy-astbuilder-3.0.7.jar:b290451eb1583666e906c41f7d14747b4cc96363c99c478b244634fd5dfc9013',
'org.codehaus.groovy:groovy-cli-picocli:3.0.7:groovy-cli-picocli-3.0.7.jar:71b4bd11fb30a9c7b5618e22122c9c5141958fb27f4dcf0068b6f715088f6916',
'org.codehaus.groovy:groovy-console:3.0.7:groovy-console-3.0.7.jar:0541b358b6b8e5363215026736168fccfec1d91bac678d066fa77349eeeaa5dd',
'org.codehaus.groovy:groovy-datetime:3.0.7:groovy-datetime-3.0.7.jar:b9823d14b1a4f94236ae2f8a471701aab17e093e1b33402b91550b5c8dd88f04',
'org.codehaus.groovy:groovy-docgenerator:3.0.7:groovy-docgenerator-3.0.7.jar:bf53f7a11c9eb1e278e1b8ed2714c741bcf781235c803ad3ba1555f2614573f3',
'org.codehaus.groovy:groovy-groovydoc:3.0.7:groovy-groovydoc-3.0.7.jar:86b24dfc23c005066ab83927cdb54177f06c9531773f2e2d2ecc9a131f7c2677',
'org.codehaus.groovy:groovy-groovysh:3.0.7:groovy-groovysh-3.0.7.jar:5c40e78cbc09726aedd1c75fab112d245d665d6294870f9119e6cd3013ed14ab',
'org.codehaus.groovy:groovy-jmx:3.0.7:groovy-jmx-3.0.7.jar:0a89f3007884eb156751937d93382038b83d39c7c2f0ab156ebf251a7251f2ab',
'org.codehaus.groovy:groovy-json:3.0.7:groovy-json-3.0.7.jar:df1f0ee475e3fc93a6a0d17548294e160cca5de6d9d36817a7be1fbe650de03b',
'org.codehaus.groovy:groovy-jsr223:3.0.7:groovy-jsr223-3.0.7.jar:1dbd969595332416193baa660fbb45743d19696eaa25fe98e591a2739e13517e',
'org.codehaus.groovy:groovy-macro:3.0.7:groovy-macro-3.0.7.jar:c6cc06df526b39e2c359e2435f0071594c5a1c7babafaa6c184fdd8fa931531f',
'org.codehaus.groovy:groovy-nio:3.0.7:groovy-nio-3.0.7.jar:db54c577882b294cd8c975ec5451596441baf54781319c61627dca0e0c2361ef',
'org.codehaus.groovy:groovy-servlet:3.0.7:groovy-servlet-3.0.7.jar:5b6a909bf501c209adfb6205b9e740649609074455fd979bf9da4853e6ff9a39',
'org.codehaus.groovy:groovy-sql:3.0.7:groovy-sql-3.0.7.jar:252bb6c74e1a9f41756ad4fbd3b0d2eddc93bb61109961dd1952a37bf2d57a64',
'org.codehaus.groovy:groovy-swing:3.0.7:groovy-swing-3.0.7.jar:bd942032d9328d54c6679c49a41f6caa0d4a0039ebe598493b8a647730d98cff',
'org.codehaus.groovy:groovy-templates:3.0.7:groovy-templates-3.0.7.jar:f119e07f650ef186ae5a4b944f9e30915b14311bad47c94a6b32de8d4f69bc80',
'org.codehaus.groovy:groovy-test-junit5:3.0.7:groovy-test-junit5-3.0.7.jar:c16eeea07b8e396891e266d7ba9388b24ac804237ffdd9a792b0d08969bad014',
'org.codehaus.groovy:groovy-test:3.0.7:groovy-test-3.0.7.jar:f71afd7c25d43017f89ea47e6de6daec971d159047dae083c1513a8422d44b90',
'org.codehaus.groovy:groovy-testng:3.0.7:groovy-testng-3.0.7.jar:713d5f2231bbb5712aefd362151b9ffd884aeb7ef2e773315cc54259cbdd063d',
'org.codehaus.groovy:groovy-xml:3.0.7:groovy-xml-3.0.7.jar:8a62e7c9ddece3e82676c4bef2f2c100f459602cd1fb6a14e94187bf863e97ff',
'org.codehaus.groovy:groovy:3.0.7:groovy-3.0.7.jar:51d1777e8dd1f00e60ea56e00d8a354ff5aab1f00fc8464ae8d39d71867e401f',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b', 'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe', 'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jacoco:org.jacoco.agent:0.8.3:org.jacoco.agent-0.8.3.jar:522deb254ee16a04cc8341cc8f335f5cb7232982994d961b9cf3a0454709209f', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jacoco:org.jacoco.ant:0.8.3:org.jacoco.ant-0.8.3.jar:735844e1ae15f9b875b42a27ac5cb61cc26e106d9e839e5d1c6756709b424ce0', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jacoco:org.jacoco.core:0.8.3:org.jacoco.core-0.8.3.jar:0818437bc060a0c7cc798148f22b713702aae2771aba104444407697d578f1ea', 'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jacoco:org.jacoco.report:0.8.3:org.jacoco.report-0.8.3.jar:aae08fa4ff043c807b8876cdb2d8705eb8449a55efce461baa6c09da245088c1', 'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
'org.jetbrains.kotlin:kotlin-reflect:1.4.32:kotlin-reflect-1.4.32.jar:dbf19e9cdaa9c3c170f3f6f6ce3922f38dfc1d7fa1cab5b7c23a19da8b5eec5b',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.32:kotlin-stdlib-common-1.4.32.jar:e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32:kotlin-stdlib-jdk7-1.4.32.jar:5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32:kotlin-stdlib-jdk8-1.4.32.jar:adc43e54757b106e0cd7b3b7aa257dff471b61efdabe067fc02b2f57e2396262',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.32:kotlin-stdlib-1.4.32.jar:13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd', 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be', 'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
'org.junit.jupiter:junit-jupiter-api:5.7.0:junit-jupiter-api-5.7.0.jar:b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182', 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.junit.jupiter:junit-jupiter-engine:5.7.0:junit-jupiter-engine-5.7.0.jar:dfa26af94644ac2612dde6625852fcb550a0d21caa243257de54cba738ba87af',
'org.junit.platform:junit-platform-commons:1.7.0:junit-platform-commons-1.7.0.jar:5330ee87cc7586e6e25175a34e9251624ff12ff525269d3415d0b4ca519b6fea',
'org.junit.platform:junit-platform-engine:1.7.0:junit-platform-engine-1.7.0.jar:75f21a20dc594afdc875736725b408cec6d0344874d29f34b2dd3075500236f2',
'org.junit.platform:junit-platform-launcher:1.7.0:junit-platform-launcher-1.7.0.jar:fbdc748fde4c4279fe1d3c607447cb3b7ccd45d7338fc574f8a894ddf2d16818',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2',
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474', 'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d', 'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c', 'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145', 'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf', 'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.testng:testng:7.3.0:testng-7.3.0.jar:63727488f9717d57f0d0a0fee5a1fc10a2be9cfcff2ec3a7187656d663c0774e',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
] ]
} }

View File

@@ -7,13 +7,13 @@ apply plugin: 'witness'
apply from: 'witness.gradle' apply from: 'witness.gradle'
dependencies { dependencies {
implementation "com.google.dagger:dagger:$dagger_version" implementation "com.google.dagger:dagger:2.24"
implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation "junit:junit:$junit_version" testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:$jmock_version" testImplementation "org.jmock:jmock-legacy:2.8.2"
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }

View File

@@ -1,9 +0,0 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Consumer<T> {
void accept(T t);
}

View File

@@ -11,5 +11,5 @@ public interface FeatureFlags {
boolean shouldEnableDisappearingMessages(); boolean shouldEnableDisappearingMessages();
boolean shouldEnablePersistentLogs(); boolean shouldEnableConnectViaBluetooth();
} }

View File

@@ -1,16 +1,8 @@
package org.briarproject.bramble.api; package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import static org.briarproject.bramble.util.StringUtils.fromHexString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@NotNullByDefault
public abstract class StringMap extends Hashtable<String, String> { public abstract class StringMap extends Hashtable<String, String> {
protected StringMap(Map<String, String> m) { protected StringMap(Map<String, String> m) {
@@ -60,19 +52,4 @@ public abstract class StringMap extends Hashtable<String, String> {
public void putLong(String key, long value) { public void putLong(String key, long value) {
put(key, String.valueOf(value)); put(key, String.valueOf(value));
} }
@Nullable
public byte[] getBytes(String key) {
String s = get(key);
if (s == null) return null;
try {
return fromHexString(s);
} catch (IllegalArgumentException e) {
return null;
}
}
public void putBytes(String key, byte[] value) {
put(key, toHexString(value));
}
} }

View File

@@ -32,31 +32,28 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
/** /**
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* <p>
* If an unexpected exception occurs while handling data that is assumed
* to be valid (e.g. locally created metadata), it may be sensible to
* rethrow the unexpected exception as a DbException so that delivery is
* attempted again at next startup. This will allow delivery to succeed if
* the unexpected exception was caused by a bug that has subsequently been
* fixed.
* *
* @param txn A read-write transaction * @param txn A read-write transaction
* @throws DbException if a database error occurs while delivering the * @return Whether or not this message should be shared
* message. Delivery will be attempted again at next startup. Throwing * @throws DbException Should only be used for real database errors.
* this exception has the same effect as returning * If this is thrown, delivery will be attempted again at next startup,
* {@link DeliveryAction#DEFER}. * whereas if a FormatException is thrown, the message will be permanently
* @throws FormatException if the message is invalid in the context of its * invalidated.
* dependencies. The message and any dependents will be marked as invalid * @throws FormatException Use this for any non-database error
* and deleted along with their metadata. Throwing this exception has the * that occurs while handling remotely created data.
* same effect as returning {@link DeliveryAction#REJECT}. * This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Never rethrow DbException as FormatException!
*/ */
protected abstract DeliveryAction incomingMessage(Transaction txn, protected abstract boolean incomingMessage(Transaction txn, Message m,
Message m, BdfList body, BdfDictionary meta) BdfList body, BdfDictionary meta) throws DbException,
throws DbException, FormatException; FormatException;
@Override @Override
public DeliveryAction incomingMessage(Transaction txn, Message m, public boolean incomingMessage(Transaction txn, Message m, Metadata meta)
Metadata meta) throws DbException, InvalidMessageException { throws DbException, InvalidMessageException {
try { try {
BdfList body = clientHelper.toList(m); BdfList body = clientHelper.toList(m);
BdfDictionary metaDictionary = metadataParser.parse(meta); BdfDictionary metaDictionary = metadataParser.parse(meta);

View File

@@ -128,7 +128,7 @@ public interface ClientHelper {
* group. * group.
*/ */
ContactId getContactId(Transaction txn, GroupId contactGroupId) ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException; throws DbException, FormatException;
/** /**
* Stores the given contact ID in the group metadata of the given contact * Stores the given contact ID in the group metadata of the given contact

View File

@@ -170,11 +170,4 @@ public interface CryptoComponent {
* length. The line terminator is CRLF. * length. The line terminator is CRLF.
*/ */
String asciiArmour(byte[] b, int lineLength); String asciiArmour(byte[] b, int lineLength);
/**
* Encode the onion/hidden service address given its public key. As
* specified here: https://gitweb.torproject.org/torspec.git/tree/rend-spec-v3.txt?id=29245fd5#n2135
*/
String encodeOnionAddress(byte[] publicKey);
} }

View File

@@ -1,19 +1,23 @@
package org.briarproject.bramble.api.crypto; package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
/** /**
* A secret key used for encryption and/or authentication. * A secret key used for encryption and/or authentication.
*/ */
public class SecretKey extends Bytes { public class SecretKey {
/** /**
* The length of a secret key in bytes. * The length of a secret key in bytes.
*/ */
public static final int LENGTH = 32; public static final int LENGTH = 32;
private final byte[] key;
public SecretKey(byte[] key) { public SecretKey(byte[] key) {
super(key);
if (key.length != LENGTH) throw new IllegalArgumentException(); if (key.length != LENGTH) throw new IllegalArgumentException();
this.key = key;
}
public byte[] getBytes() {
return key;
} }
} }

View File

@@ -101,7 +101,7 @@ public interface DatabaseComponent extends TransactionManager {
/** /**
* Stores a transport. * Stores a transport.
*/ */
void addTransport(Transaction txn, TransportId t, long maxLatency) void addTransport(Transaction txn, TransportId t, int maxLatency)
throws DbException; throws DbException;
/** /**
@@ -118,18 +118,6 @@ public interface DatabaseComponent extends TransactionManager {
KeySetId addTransportKeys(Transaction txn, PendingContactId p, KeySetId addTransportKeys(Transaction txn, PendingContactId p,
TransportKeys k) throws DbException; TransportKeys k) throws DbException;
/**
* Returns true if there are any acks or messages to send to the given
* contact over a transport with the given maximum latency.
* <p/>
* Read-only.
*
* @param eager True if messages that are not yet due for retransmission
* should be included
*/
boolean containsAnythingToSend(Transaction txn, ContactId c,
long maxLatency, boolean eager) throws DbException;
/** /**
* Returns true if the database contains the given contact for the given * Returns true if the database contains the given contact for the given
* local pseudonym. * local pseudonym.
@@ -162,16 +150,6 @@ public interface DatabaseComponent extends TransactionManager {
boolean containsPendingContact(Transaction txn, PendingContactId p) boolean containsPendingContact(Transaction txn, PendingContactId p)
throws DbException; throws DbException;
/**
* Returns true if the database contains keys for communicating with the
* given contact over the given transport. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
boolean containsTransportKeys(Transaction txn, ContactId c, TransportId t)
throws DbException;
/** /**
* Deletes the message with the given ID. Unlike * Deletes the message with the given ID. Unlike
* {@link #removeMessage(Transaction, MessageId)}, the message ID, * {@link #removeMessage(Transaction, MessageId)}, the message ID,
@@ -200,19 +178,7 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
@Nullable @Nullable
Collection<Message> generateBatch(Transaction txn, ContactId c, Collection<Message> generateBatch(Transaction txn, ContactId c,
int maxLength, long maxLatency) throws DbException; int maxLength, int maxLatency) throws DbException;
/**
* Returns a batch of messages for the given contact containing the
* messages with the given IDs, for transmission over a transport with
* the given maximum latency.
* <p/>
* If any of the given messages are not in the database or are not visible
* to the contact, they are omitted from the batch without throwing an
* exception.
*/
Collection<Message> generateBatch(Transaction txn, ContactId c,
Collection<MessageId> ids, long maxLatency) throws DbException;
/** /**
* Returns an offer for the given contact for transmission over a * Returns an offer for the given contact for transmission over a
@@ -221,7 +187,7 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
@Nullable @Nullable
Offer generateOffer(Transaction txn, ContactId c, int maxMessages, Offer generateOffer(Transaction txn, ContactId c, int maxMessages,
long maxLatency) throws DbException; int maxLatency) throws DbException;
/** /**
* Returns a request for the given contact, or null if there are no * Returns a request for the given contact, or null if there are no
@@ -240,7 +206,7 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
@Nullable @Nullable
Collection<Message> generateRequestedBatch(Transaction txn, ContactId c, Collection<Message> generateRequestedBatch(Transaction txn, ContactId c,
int maxLength, long maxLatency) throws DbException; int maxLength, int maxLatency) throws DbException;
/** /**
* Returns the contact with the given ID. * Returns the contact with the given ID.
@@ -460,27 +426,6 @@ public interface DatabaseComponent extends TransactionManager {
MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m) MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m)
throws DbException; throws DbException;
/**
* Returns the IDs of all messages that are eligible to be sent to the
* given contact, together with their raw lengths. This may include
* messages that have already been sent and are not yet due for
* retransmission.
* <p/>
* Read-only.
*/
Map<MessageId, Integer> getUnackedMessagesToSend(Transaction txn,
ContactId c) throws DbException;
/**
* Returns the total length, including headers, of all messages that are
* eligible to be sent to the given contact. This may include messages
* that have already been sent and are not yet due for retransmission.
* <p/>
* Read-only.
*/
long getUnackedMessageBytesToSend(Transaction txn, ContactId c)
throws DbException;
/** /**
* Returns the next time (in milliseconds since the Unix epoch) when a * Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be deleted, or {@link #NO_CLEANUP_DEADLINE} * message is due to be deleted, or {@link #NO_CLEANUP_DEADLINE}
@@ -538,16 +483,6 @@ public interface DatabaseComponent extends TransactionManager {
Collection<TransportKeySet> getTransportKeys(Transaction txn, TransportId t) Collection<TransportKeySet> getTransportKeys(Transaction txn, TransportId t)
throws DbException; throws DbException;
/**
* Returns the contact IDs and transport IDs for which the DB contains
* at least one set of transport keys. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
Map<ContactId, Collection<TransportId>> getTransportsWithKeys(
Transaction txn) throws DbException;
/** /**
* Increments the outgoing stream counter for the given transport keys. * Increments the outgoing stream counter for the given transport keys.
*/ */

View File

@@ -5,7 +5,6 @@ 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.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.Wakeful; import org.briarproject.bramble.api.system.Wakeful;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -23,7 +22,6 @@ public interface LifecycleManager {
*/ */
enum StartResult { enum StartResult {
ALREADY_RUNNING, ALREADY_RUNNING,
CLOCK_ERROR,
DB_ERROR, DB_ERROR,
DATA_TOO_OLD_ERROR, DATA_TOO_OLD_ERROR,
DATA_TOO_NEW_ERROR, DATA_TOO_NEW_ERROR,
@@ -67,10 +65,6 @@ public interface LifecycleManager {
/** /**
* Opens the {@link DatabaseComponent} using the given key and starts any * Opens the {@link DatabaseComponent} using the given key and starts any
* registered {@link Service Services}. * registered {@link Service Services}.
*
* @return {@link StartResult#CLOCK_ERROR} if the system clock is earlier
* than {@link Clock#MIN_REASONABLE_TIME_MS} or later than
* {@link Clock#MAX_REASONABLE_TIME_MS}.
*/ */
@Wakeful @Wakeful
StartResult startServices(SecretKey dbKey); StartResult startServices(SecretKey dbKey);

View File

@@ -1,46 +0,0 @@
package org.briarproject.bramble.api.logging;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.logging.Handler;
import java.util.logging.Logger;
@NotNullByDefault
public interface PersistentLogManager {
/**
* The namespace of the (@link Settings) where the log key is stored.
*/
String LOG_SETTINGS_NAMESPACE = "log";
/**
* The {@link Settings} key under which the log key is stored.
*/
String LOG_KEY_KEY = "logKey";
/**
* Creates and returns a persistent log handler that stores its logs in
* the given directory.
*/
Handler createLogHandler(File dir) throws IOException;
/**
* Creates a persistent log handler that stores its logs in the given
* directory and adds the handler to the given logger, replacing any
* existing persistent log handler.
*/
void addLogHandler(File dir, Logger logger) throws IOException;
/**
* Returns a {@link Scanner} for reading the persistent log entries stored
* in the given directory.
*
* @param old True if the previous session's log should be loaded, or false
* if the current session's log should be loaded
*/
Scanner getPersistentLog(File dir, boolean old) throws IOException;
}

View File

@@ -1,32 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class MailboxProperties {
private final String onionAddress, authToken;
private final boolean owner;
public MailboxProperties(String onionAddress, String authToken,
boolean owner) {
this.onionAddress = onionAddress;
this.authToken = authToken;
this.owner = owner;
}
public String getOnionAddress() {
return onionAddress;
}
public String getAuthToken() {
return authToken;
}
public boolean isOwner() {
return owner;
}
}

View File

@@ -1,26 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface MailboxSettingsManager {
@Nullable
MailboxProperties getOwnMailboxProperties(Transaction txn)
throws DbException;
void setOwnMailboxProperties(Transaction txn, MailboxProperties p)
throws DbException;
MailboxStatus getOwnMailboxStatus(Transaction txn) throws DbException;
void recordSuccessfulConnection(Transaction txn, long now)
throws DbException;
void recordFailedConnectionAttempt(Transaction txn, long now)
throws DbException;
}

View File

@@ -1,59 +0,0 @@
package org.briarproject.bramble.api.mailbox;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class MailboxStatus {
private final long lastAttempt, lastSuccess;
private final int attemptsSinceSuccess;
public MailboxStatus(long lastAttempt, long lastSuccess,
int attemptsSinceSuccess) {
this.lastAttempt = lastAttempt;
this.lastSuccess = lastSuccess;
this.attemptsSinceSuccess = attemptsSinceSuccess;
}
/**
* Returns the time of the last attempt to connect to the mailbox, in
* milliseconds since the Unix epoch, or -1 if no attempt has been made.
* <p>
* If an attempt is in progress and has not yet succeeded or failed then
* this method returns the time of the previous attempt, or -1 if the
* current attempt is the first.
*/
public long getTimeOfLastAttempt() {
return lastAttempt;
}
/**
* Returns the time of the last successful attempt to connect to the
* mailbox, in milliseconds since the Unix epoch, or -1 if no attempt has
* succeeded.
* <p>
* If the last attempt was successful then this method returns the same
* value as {@link #getTimeOfLastAttempt()}. If an attempt is in progress
* and has not yet succeeded or failed then this method returns the time
* of the previous successful connection, or -1 if no attempt has
* succeeded.
*/
public long getTimeOfLastSuccess() {
return lastSuccess;
}
/**
* Returns the number of attempts to connect to the mailbox that have
* failed since the last attempt succeeded, or the number of attempts that
* have been made, if no attempt has ever succeeded.
* <p>
* If an attempt is in progress and has not yet succeeded or failed then
* it is not included in this count.
*/
public int getAttemptsSinceSuccess() {
return attemptsSinceSuccess;
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.api.plugin.file; package org.briarproject.bramble.api.plugin;
public interface FileConstants { public interface FileConstants {

View File

@@ -61,7 +61,7 @@ public interface Plugin {
/** /**
* Returns the transport's maximum latency in milliseconds. * Returns the transport's maximum latency in milliseconds.
*/ */
long getMaxLatency(); int getMaxLatency();
/** /**
* Returns the transport's maximum idle time in milliseconds. * Returns the transport's maximum idle time in milliseconds.

View File

@@ -1,25 +0,0 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface PluginFactory<P extends Plugin> {
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/**
* Returns the maximum latency of the transport in milliseconds.
*/
long getMaxLatency();
/**
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
P createPlugin(PluginCallback callback);
}

View File

@@ -1,14 +1,17 @@
package org.briarproject.bramble.api.plugin; package org.briarproject.bramble.api.plugin;
import static java.util.concurrent.TimeUnit.DAYS;
public interface TorConstants { public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor"); TransportId ID = new TransportId("org.briarproject.bramble.tor");
// Transport properties // Transport properties
String PROP_ONION_V2 = "onion";
String PROP_ONION_V3 = "onion3"; String PROP_ONION_V3 = "onion3";
int DEFAULT_SOCKS_PORT = 59050; int SOCKS_PORT = 59050;
int DEFAULT_CONTROL_PORT = 59051; int CONTROL_PORT = 59051;
int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds int CONNECT_TO_PROXY_TIMEOUT = 5000; // Milliseconds
int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds int EXTRA_SOCKET_TIMEOUT = 30000; // Milliseconds
@@ -18,7 +21,14 @@ public interface TorConstants {
String PREF_TOR_PORT = "port"; String PREF_TOR_PORT = "port";
String PREF_TOR_MOBILE = "useMobileData"; String PREF_TOR_MOBILE = "useMobileData";
String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging"; String PREF_TOR_ONLY_WHEN_CHARGING = "onlyWhenCharging";
String HS_PRIVATE_KEY_V2 = "onionPrivKey";
String HS_PRIVATE_KEY_V3 = "onionPrivKey3"; String HS_PRIVATE_KEY_V3 = "onionPrivKey3";
String HS_V3_CREATED = "onionPrivKey3Created";
/**
* How long to publish a v3 hidden service before retiring the v2 service.
*/
long V3_MIGRATION_PERIOD_MS = DAYS.toMillis(180);
// Values for PREF_TOR_NETWORK // Values for PREF_TOR_NETWORK
int PREF_TOR_NETWORK_AUTOMATIC = 0; int PREF_TOR_NETWORK_AUTOMATIC = 0;

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.plugin;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the control port for the Tor plugin.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface TorControlPort {
}

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.plugin;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Annotation for injecting the socks port for the Tor plugin.
*/
@Qualifier
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface TorSocksPort {
}

View File

@@ -15,18 +15,13 @@ public interface TransportConnectionWriter {
/** /**
* Returns the maximum latency of the transport in milliseconds. * Returns the maximum latency of the transport in milliseconds.
*/ */
long getMaxLatency(); int getMaxLatency();
/** /**
* Returns the maximum idle time of the transport in milliseconds. * Returns the maximum idle time of the transport in milliseconds.
*/ */
int getMaxIdleTime(); int getMaxIdleTime();
/**
* Returns true if the transport is lossy and cheap.
*/
boolean isLossyAndCheap();
/** /**
* Returns an output stream for writing to the transport connection. * Returns an output stream for writing to the transport connection.
*/ */

View File

@@ -70,7 +70,7 @@ public abstract class AbstractDuplexTransportConnection
private class Writer implements TransportConnectionWriter { private class Writer implements TransportConnectionWriter {
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return plugin.getMaxLatency(); return plugin.getMaxLatency();
} }
@@ -79,11 +79,6 @@ public abstract class AbstractDuplexTransportConnection
return plugin.getMaxIdleTime(); return plugin.getMaxIdleTime();
} }
@Override
public boolean isLossyAndCheap() {
return false;
}
@Override @Override
public OutputStream getOutputStream() throws IOException { public OutputStream getOutputStream() throws IOException {
return AbstractDuplexTransportConnection.this.getOutputStream(); return AbstractDuplexTransportConnection.this.getOutputStream();

View File

@@ -1,11 +1,30 @@
package org.briarproject.bramble.api.plugin.duplex; package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginFactory; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
/** /**
* Factory for creating a plugin for a duplex transport. * Factory for creating a plugin for a duplex transport.
*/ */
@NotNullByDefault @NotNullByDefault
public interface DuplexPluginFactory extends PluginFactory<DuplexPlugin> { public interface DuplexPluginFactory {
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/**
* Returns the maximum latency of the transport in milliseconds.
*/
int getMaxLatency();
/**
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
DuplexPlugin createPlugin(PluginCallback callback);
} }

View File

@@ -1,12 +0,0 @@
package org.briarproject.bramble.api.plugin.file;
import org.briarproject.bramble.api.plugin.TransportId;
public interface RemovableDriveConstants {
TransportId ID = new TransportId("org.briarproject.bramble.drive");
String PROP_PATH = "path";
String PROP_URI = "uri";
String PROP_SUPPORTED = "supported";
}

View File

@@ -1,52 +0,0 @@
package org.briarproject.bramble.api.plugin.file;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties;
import javax.annotation.Nullable;
@NotNullByDefault
public interface RemovableDriveManager {
/**
* Returns the currently running reader task, or null if no reader task
* is running.
*/
@Nullable
RemovableDriveTask getCurrentReaderTask();
/**
* Returns the currently running writer task, or null if no writer task
* is running.
*/
@Nullable
RemovableDriveTask getCurrentWriterTask();
/**
* Starts and returns a reader task, reading from a stream described by
* the given transport properties. If a reader task is already running,
* it will be returned and the argument will be ignored.
*/
RemovableDriveTask startReaderTask(TransportProperties p);
/**
* Starts and returns a writer task for the given contact, writing to
* a stream described by the given transport properties. If a writer task
* is already running, it will be returned and the arguments will be
* ignored.
*/
RemovableDriveTask startWriterTask(ContactId c, TransportProperties p);
/**
* Returns true if the given contact has indicated support for the
* removable drive transport.
*/
boolean isTransportSupportedByContact(ContactId c) throws DbException;
/**
* Returns true if there is anything to send to the given contact.
*/
boolean isWriterTaskNeeded(ContactId c) throws DbException;
}

View File

@@ -1,65 +0,0 @@
package org.briarproject.bramble.api.plugin.file;
import org.briarproject.bramble.api.Consumer;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties;
@NotNullByDefault
public interface RemovableDriveTask extends Runnable {
/**
* Returns the {@link TransportProperties} that were used for creating
* this task.
*/
TransportProperties getTransportProperties();
/**
* Adds an observer to the task. The observer will be notified on the
* event thread of the current state of the task and any subsequent state
* changes.
*/
void addObserver(Consumer<State> observer);
/**
* Removes an observer from the task.
*/
void removeObserver(Consumer<State> observer);
class State {
private final long done, total;
private final boolean finished, success;
public State(long done, long total, boolean finished, boolean success) {
this.done = done;
this.total = total;
this.finished = finished;
this.success = success;
}
/**
* Returns the total length in bytes of the messages read or written
* so far, or zero if the total is unknown.
*/
public long getDone() {
return done;
}
/**
* Returns the total length in bytes of the messages that will have
* been read or written when the task is complete, or zero if the
* total is unknown.
*/
public long getTotal() {
return total;
}
public boolean isFinished() {
return finished;
}
public boolean isSuccess() {
return success;
}
}
}

View File

@@ -15,12 +15,6 @@ import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface SimplexPlugin extends Plugin { public interface SimplexPlugin extends Plugin {
/**
* Returns true if the transport is likely to lose streams and the cost of
* transmitting redundant copies of data is cheap.
*/
boolean isLossyAndCheap();
/** /**
* Attempts to create and return a reader for the given transport * Attempts to create and return a reader for the given transport
* properties. Returns null if a reader cannot be created. * properties. Returns null if a reader cannot be created.

View File

@@ -1,11 +1,30 @@
package org.briarproject.bramble.api.plugin.simplex; package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginFactory; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
/** /**
* Factory for creating a plugin for a simplex transport. * Factory for creating a plugin for a simplex transport.
*/ */
@NotNullByDefault @NotNullByDefault
public interface SimplexPluginFactory extends PluginFactory<SimplexPlugin> { public interface SimplexPluginFactory {
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/**
* Returns the maximum latency of the transport in milliseconds.
*/
int getMaxLatency();
/**
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
SimplexPlugin createPlugin(PluginCallback callback);
} }

View File

@@ -8,24 +8,11 @@ import java.io.File;
@NotNullByDefault @NotNullByDefault
public interface DevConfig { public interface DevConfig {
/**
* Returns the public key for encrypting feedback and crash reports.
*/
PublicKey getDevPublicKey(); PublicKey getDevPublicKey();
/**
* Returns the onion address for submitting feedback and crash reports.
*/
String getDevOnionAddress(); String getDevOnionAddress();
/**
* Returns the directory for storing unsent feedback and crash reports.
*/
File getReportDir(); File getReportDir();
/** File getLogcatFile();
* Returns the temporary file for passing the encrypted app log from the
* main process to the crash reporter process.
*/
File getTemporaryLogFile();
} }

View File

@@ -22,11 +22,4 @@ public interface SettingsManager {
* namespace. * namespace.
*/ */
void mergeSettings(Settings s, String namespace) throws DbException; void mergeSettings(Settings s, String namespace) throws DbException;
/**
* Merges the given settings with any existing settings in the given
* namespace.
*/
void mergeSettings(Transaction txn, Settings s, String namespace)
throws DbException;
} }

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.UniqueId;
import java.util.List; import java.util.List;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.DAYS;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
public interface SyncConstants { public interface SyncConstants {
@@ -56,9 +55,4 @@ public interface SyncConstants {
* connections. * connections.
*/ */
int PRIORITY_NONCE_BYTES = 16; int PRIORITY_NONCE_BYTES = 16;
/**
* The maximum allowed latency for any transport, in milliseconds.
*/
long MAX_TRANSPORT_LATENCY = DAYS.toMillis(365);
} }

View File

@@ -16,9 +16,9 @@ public interface SyncSessionFactory {
PriorityHandler handler); PriorityHandler handler);
SyncSession createSimplexOutgoingSession(ContactId c, TransportId t, SyncSession createSimplexOutgoingSession(ContactId c, TransportId t,
long maxLatency, boolean eager, StreamWriter streamWriter); int maxLatency, StreamWriter streamWriter);
SyncSession createDuplexOutgoingSession(ContactId c, TransportId t, SyncSession createDuplexOutgoingSession(ContactId c, TransportId t,
long maxLatency, int maxIdleTime, StreamWriter streamWriter, int maxLatency, int maxIdleTime, StreamWriter streamWriter,
@Nullable Priority priority); @Nullable Priority priority);
} }

View File

@@ -18,13 +18,11 @@ public class MessagesSentEvent extends Event {
private final ContactId contactId; private final ContactId contactId;
private final Collection<MessageId> messageIds; private final Collection<MessageId> messageIds;
private final long totalLength;
public MessagesSentEvent(ContactId contactId, public MessagesSentEvent(ContactId contactId,
Collection<MessageId> messageIds, long totalLength) { Collection<MessageId> messageIds) {
this.contactId = contactId; this.contactId = contactId;
this.messageIds = messageIds; this.messageIds = messageIds;
this.totalLength = totalLength;
} }
public ContactId getContactId() { public ContactId getContactId() {
@@ -34,8 +32,4 @@ public class MessagesSentEvent extends Event {
public Collection<MessageId> getMessageIds() { public Collection<MessageId> getMessageIds() {
return messageIds; return messageIds;
} }
public long getTotalLength() {
return totalLength;
}
} }

View File

@@ -10,54 +10,23 @@ public interface IncomingMessageHook {
/** /**
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* <p>
* If an unexpected exception occurs while handling data that is assumed
* to be valid (e.g. locally created metadata), it may be sensible to
* rethrow the unexpected exception as a DbException so that delivery is
* attempted again at next startup. This will allow delivery to succeed if
* the unexpected exception was caused by a bug that has subsequently been
* fixed.
* *
* @param txn A read-write transaction * @param txn A read-write transaction
* @throws DbException if a database error occurs while delivering the * @return Whether or not this message should be shared
* message. Delivery will be attempted again at next startup. Throwing * @throws DbException Should only be used for real database errors.
* this exception has the same effect as returning * If this is thrown, delivery will be attempted again at next startup,
* {@link DeliveryAction#DEFER}. * whereas if an InvalidMessageException is thrown,
* @throws InvalidMessageException if the message is invalid in the context * the message will be permanently invalidated.
* of its dependencies. The message and any dependents will be marked as * @throws InvalidMessageException for any non-database error
* invalid and deleted along with their metadata. Throwing this exception * that occurs while handling remotely created data.
* has the same effect as returning {@link DeliveryAction#REJECT}. * This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as InvalidMessageException!
*/ */
DeliveryAction incomingMessage(Transaction txn, Message m, Metadata meta) boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException; throws DbException, InvalidMessageException;
enum DeliveryAction {
/**
* The message and any dependent messages will be moved to the
* {@link MessageState#INVALID INVALID state} and deleted, along with
* their metadata.
*/
REJECT,
/**
* The message will be moved to the
* {@link MessageState#PENDING PENDING state}. Delivery will be
* attempted again at next startup.
*/
DEFER,
/**
* The message will be moved to the
* {@link MessageState#DELIVERED DELIVERED state} and shared.
*/
ACCEPT_SHARE,
/**
* The message will be moved to the
* {@link MessageState#DELIVERED DELIVERED state} and will not be
* shared.
*/
ACCEPT_DO_NOT_SHARE
}
} }

View File

@@ -1,33 +1,8 @@
package org.briarproject.bramble.api.sync.validation; package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction;
public enum MessageState { public enum MessageState {
/** UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
* A remote message that has not yet been validated.
*/
UNKNOWN(0),
/**
* A remote message that has failed validation, has been
* {@link DeliveryAction#REJECT rejected} by the local sync client, or
* depends on another message that has failed validation or been rejected.
*/
INVALID(1),
/**
* A remote message that has passed validation and is awaiting delivery to
* the local sync client. The message will not be delivered until all its
* dependencies have been validated and delivered.
*/
PENDING(2),
/**
* A local message, or a remote message that has passed validation and
* been delivered to the local sync client.
*/
DELIVERED(3);
private final int value; private final int value;

View File

@@ -6,22 +6,6 @@ package org.briarproject.bramble.api.system;
*/ */
public interface Clock { public interface Clock {
/**
* The minimum reasonable value for the system clock, in milliseconds
* since the Unix epoch.
* <p/>
* 1 Jan 2021, 00:00:00 UTC
*/
long MIN_REASONABLE_TIME_MS = 1_609_459_200_000L;
/**
* The maximum reasonable value for the system clock, in milliseconds
* since the Unix epoch.
* <p/>
* 1 Jan 2121, 00:00:00 UTC
*/
long MAX_REASONABLE_TIME_MS = 4_765_132_800_000L;
/** /**
* @see System#currentTimeMillis() * @see System#currentTimeMillis()
*/ */

View File

@@ -22,24 +22,8 @@ public interface KeyManager {
/** /**
* Derives and stores a set of rotation mode transport keys for * Derives and stores a set of rotation mode transport keys for
* communicating with the given contact over the given transport and * communicating with the given contact over each transport and returns the
* returns the key set ID, or null if the transport is not supported. * key set IDs.
* <p/>
* {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned.
*
* @param alice True if the local party is Alice
* @param active Whether the derived keys can be used for outgoing streams
*/
@Nullable
KeySetId addRotationKeys(Transaction txn, ContactId c, TransportId t,
SecretKey rootKey, long timestamp, boolean alice,
boolean active) throws DbException;
/**
* Derives and stores a set of rotation mode transport keys for
* communicating with the given contact over each supported transport and
* returns the key set IDs.
* <p/> * <p/>
* {@link StreamContext StreamContexts} for the contact can be created * {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned. * after this method has returned.

View File

@@ -1,24 +0,0 @@
package org.briarproject.bramble.api.transport.agreement;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
@NotNullByDefault
public interface TransportKeyAgreementManager {
/**
* The unique ID of the transport key agreement client.
*/
ClientId CLIENT_ID =
new ClientId("org.briarproject.bramble.transport.agreement");
/**
* The current major version of the transport key agreement client.
*/
int MAJOR_VERSION = 0;
/**
* The current minor version of the transport key agreement client.
*/
int MINOR_VERSION = 0;
}

View File

@@ -1,10 +1,7 @@
package org.briarproject.bramble.util; package org.briarproject.bramble.util;
import java.io.File; import java.io.File;
import java.util.Collection;
import java.util.logging.Formatter;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger; import java.util.logging.Logger;
import static java.util.logging.Level.FINE; import static java.util.logging.Level.FINE;
@@ -60,13 +57,4 @@ public class LogUtils {
String type) { String type) {
logger.log(level, type + " " + f.getAbsolutePath() + " " + f.length()); logger.log(level, type + " " + f.getAbsolutePath() + " " + f.length());
} }
public static String formatLog(Formatter formatter,
Collection<LogRecord> logRecords) {
StringBuilder sb = new StringBuilder();
for (LogRecord record : logRecords) {
sb.append(formatter.format(record)).append('\n');
}
return sb.toString();
}
} }

View File

@@ -1,34 +0,0 @@
package org.briarproject.bramble.util;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Logger;
import static java.util.Collections.emptyList;
import static java.util.Collections.list;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
public class NetworkUtils {
private static final Logger LOG = getLogger(NetworkUtils.class.getName());
public static List<NetworkInterface> getNetworkInterfaces() {
try {
Enumeration<NetworkInterface> ifaces =
NetworkInterface.getNetworkInterfaces();
// Despite what the docs say, the return value can be null
//noinspection ConstantConditions
return ifaces == null ? emptyList() : list(ifaces);
} catch (SocketException e) {
logException(LOG, WARNING, e);
return emptyList();
}
}
}

View File

@@ -1,17 +1,12 @@
package org.briarproject.bramble.test; package org.briarproject.bramble.test;
import org.jmock.Mockery; import org.jmock.Mockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.junit.After; import org.junit.After;
public abstract class BrambleMockTestCase extends BrambleTestCase { public abstract class BrambleMockTestCase extends BrambleTestCase {
protected final Mockery context = new Mockery(); protected final Mockery context = new Mockery();
public BrambleMockTestCase() {
context.setThreadingPolicy(new Synchroniser());
}
@After @After
public void checkExpectations() { public void checkExpectations() {
context.assertIsSatisfied(); context.assertIsSatisfied();

View File

@@ -163,15 +163,10 @@ public class TestUtils {
public static Message getMessage(GroupId groupId) { public static Message getMessage(GroupId groupId) {
int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH); int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH);
return getMessage(groupId, bodyLength, timestamp); return getMessage(groupId, bodyLength);
} }
public static Message getMessage(GroupId groupId, int bodyLength) { public static Message getMessage(GroupId groupId, int bodyLength) {
return getMessage(groupId, bodyLength, timestamp);
}
public static Message getMessage(GroupId groupId, int bodyLength,
long timestamp) {
MessageId id = new MessageId(getRandomId()); MessageId id = new MessageId(getRandomId());
byte[] body = getRandomBytes(bodyLength); byte[] body = getRandomBytes(bodyLength);
return new Message(id, groupId, timestamp, body); return new Message(id, groupId, timestamp, body);

View File

@@ -1,27 +1,24 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb', 'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0', 'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', '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.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249', 'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09', 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b', 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd', 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be', 'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984', 'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
] ]
} }

View File

@@ -10,36 +10,27 @@ apply from: '../dagger.gradle'
dependencies { dependencies {
implementation project(path: ':bramble-api', configuration: 'default') implementation project(path: ':bramble-api', configuration: 'default')
implementation 'org.bouncycastle:bcprov-jdk15on:1.69' implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
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.5.0' implementation 'org.whispersystems:curve25519-java:0.5.0'
implementation 'org.briarproject:jtorctl:0.3' implementation 'org.briarproject:jtorctl:0.3'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6 testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
testImplementation 'net.jodah:concurrentunit:0.4.2' testImplementation 'junit:junit:4.12'
testImplementation "junit:junit:$junit_version" testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock:$jmock_version" testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-junit4:$jmock_version" testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.jmock:jmock-legacy:$jmock_version"
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24'
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }
animalsniffer {
// Allow requireNonNull: Android desugaring rewrites it (so it's safe for us to use),
// and it gets used when passing method references instead of lambdas with Java 11.
// Note that this line allows *all* methods from java.util.Objects.
// That's the best that we can do with the configuration options that Animal Sniffer offers.
ignore 'java.util.Objects'
}
// needed to make test output available to bramble-java // needed to make test output available to bramble-java
configurations { configurations {
testOutput.extendsFrom(testCompile) testOutput.extendsFrom(testCompile)

View File

@@ -11,7 +11,6 @@ import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.rendezvous.RendezvousModule; import org.briarproject.bramble.rendezvous.RendezvousModule;
import org.briarproject.bramble.sync.validation.ValidationModule; import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.transport.TransportModule; import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.transport.agreement.TransportKeyAgreementModule;
import org.briarproject.bramble.versioning.VersioningModule; import org.briarproject.bramble.versioning.VersioningModule;
public interface BrambleCoreEagerSingletons { public interface BrambleCoreEagerSingletons {
@@ -34,8 +33,6 @@ public interface BrambleCoreEagerSingletons {
void inject(RendezvousModule.EagerSingletons init); void inject(RendezvousModule.EagerSingletons init);
void inject(TransportKeyAgreementModule.EagerSingletons init);
void inject(TransportModule.EagerSingletons init); void inject(TransportModule.EagerSingletons init);
void inject(ValidationModule.EagerSingletons init); void inject(ValidationModule.EagerSingletons init);
@@ -54,7 +51,6 @@ public interface BrambleCoreEagerSingletons {
c.inject(new RendezvousModule.EagerSingletons()); c.inject(new RendezvousModule.EagerSingletons());
c.inject(new PluginModule.EagerSingletons()); c.inject(new PluginModule.EagerSingletons());
c.inject(new PropertiesModule.EagerSingletons()); c.inject(new PropertiesModule.EagerSingletons());
c.inject(new TransportKeyAgreementModule.EagerSingletons());
c.inject(new TransportModule.EagerSingletons()); c.inject(new TransportModule.EagerSingletons());
c.inject(new ValidationModule.EagerSingletons()); c.inject(new ValidationModule.EagerSingletons());
c.inject(new VersioningModule.EagerSingletons()); c.inject(new VersioningModule.EagerSingletons());

View File

@@ -14,8 +14,6 @@ import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.io.IoModule; import org.briarproject.bramble.io.IoModule;
import org.briarproject.bramble.keyagreement.KeyAgreementModule; import org.briarproject.bramble.keyagreement.KeyAgreementModule;
import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.logging.LoggingModule;
import org.briarproject.bramble.mailbox.MailboxModule;
import org.briarproject.bramble.plugin.PluginModule; import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.properties.PropertiesModule; import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.record.RecordModule; import org.briarproject.bramble.record.RecordModule;
@@ -25,7 +23,6 @@ import org.briarproject.bramble.settings.SettingsModule;
import org.briarproject.bramble.sync.SyncModule; import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule; import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.transport.TransportModule; import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.transport.agreement.TransportKeyAgreementModule;
import org.briarproject.bramble.versioning.VersioningModule; import org.briarproject.bramble.versioning.VersioningModule;
import dagger.Module; import dagger.Module;
@@ -45,8 +42,6 @@ import dagger.Module;
IoModule.class, IoModule.class,
KeyAgreementModule.class, KeyAgreementModule.class,
LifecycleModule.class, LifecycleModule.class,
LoggingModule.class,
MailboxModule.class,
PluginModule.class, PluginModule.class,
PropertiesModule.class, PropertiesModule.class,
RecordModule.class, RecordModule.class,
@@ -54,7 +49,6 @@ import dagger.Module;
RendezvousModule.class, RendezvousModule.class,
SettingsModule.class, SettingsModule.class,
SyncModule.class, SyncModule.class,
TransportKeyAgreementModule.class,
TransportModule.class, TransportModule.class,
ValidationModule.class, ValidationModule.class,
VersioningModule.class VersioningModule.class

View File

@@ -45,6 +45,7 @@ abstract class Connection {
@Nullable @Nullable
StreamContext recogniseTag(TransportConnectionReader reader, StreamContext recogniseTag(TransportConnectionReader reader,
TransportId transportId) { TransportId transportId) {
StreamContext ctx;
try { try {
byte[] tag = readTag(reader.getInputStream()); byte[] tag = readTag(reader.getInputStream());
return keyManager.getStreamContext(transportId, tag); return keyManager.getStreamContext(transportId, tag);

View File

@@ -71,10 +71,8 @@ class OutgoingSimplexSyncConnection extends SyncConnection implements Runnable {
StreamWriter streamWriter = streamWriterFactory.createStreamWriter( StreamWriter streamWriter = streamWriterFactory.createStreamWriter(
w.getOutputStream(), ctx); w.getOutputStream(), ctx);
ContactId c = requireNonNull(ctx.getContactId()); ContactId c = requireNonNull(ctx.getContactId());
// Use eager retransmission if the transport is lossy and cheap
return syncSessionFactory.createSimplexOutgoingSession(c, return syncSessionFactory.createSimplexOutgoingSession(c,
ctx.getTransportId(), w.getMaxLatency(), w.isLossyAndCheap(), ctx.getTransportId(), w.getMaxLatency(), streamWriter);
streamWriter);
} }
} }

View File

@@ -47,7 +47,6 @@ import javax.inject.Inject;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
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.api.system.Clock.MIN_REASONABLE_TIME_MS;
import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.contact.ContactExchangeRecordTypes.CONTACT_INFO; import static org.briarproject.bramble.contact.ContactExchangeRecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
@@ -185,10 +184,6 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
// The agreed timestamp is the minimum of the peers' timestamps // The agreed timestamp is the minimum of the peers' timestamps
long timestamp = Math.min(localTimestamp, remoteInfo.timestamp); long timestamp = Math.min(localTimestamp, remoteInfo.timestamp);
if (timestamp < MIN_REASONABLE_TIME_MS) {
LOG.warning("Timestamp is too old");
throw new FormatException();
}
// Add the contact // Add the contact
Contact contact = addContact(p, remoteInfo.author, localAuthor, Contact contact = addContact(p, remoteInfo.author, localAuthor,

View File

@@ -4,10 +4,6 @@ import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.EdDSAPublicKey; import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.KeyPairGenerator; import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.briarproject.bramble.api.crypto.AgreementPrivateKey; import org.briarproject.bramble.api.crypto.AgreementPrivateKey;
import org.briarproject.bramble.api.crypto.AgreementPublicKey; import org.briarproject.bramble.api.crypto.AgreementPublicKey;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -22,13 +18,14 @@ import org.briarproject.bramble.api.crypto.SignaturePrivateKey;
import org.briarproject.bramble.api.crypto.SignaturePublicKey; import org.briarproject.bramble.api.crypto.SignaturePublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.Base32;
import org.briarproject.bramble.util.ByteUtils; import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.CryptoException;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.whispersystems.curve25519.Curve25519; import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair; import org.whispersystems.curve25519.Curve25519KeyPair;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Provider; import java.security.Provider;
@@ -61,8 +58,6 @@ class CryptoComponentImpl implements CryptoComponent {
private static final int PBKDF_SALT_BYTES = 32; // 256 bits private static final int PBKDF_SALT_BYTES = 32; // 256 bits
private static final byte PBKDF_FORMAT_SCRYPT = 0; private static final byte PBKDF_FORMAT_SCRYPT = 0;
private static final byte PBKDF_FORMAT_SCRYPT_STRENGTHENED = 1; private static final byte PBKDF_FORMAT_SCRYPT_STRENGTHENED = 1;
private static final byte ONION_HS_PROTOCOL_VERSION = 3;
private static final int ONION_CHECKSUM_BYTES = 2;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final PasswordBasedKdf passwordBasedKdf; private final PasswordBasedKdf passwordBasedKdf;
@@ -447,21 +442,4 @@ class CryptoComponentImpl implements CryptoComponent {
public String asciiArmour(byte[] b, int lineLength) { public String asciiArmour(byte[] b, int lineLength) {
return AsciiArmour.wrap(b, lineLength); return AsciiArmour.wrap(b, lineLength);
} }
@Override
public String encodeOnionAddress(byte[] publicKey) {
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update(ONION_HS_PROTOCOL_VERSION);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + ONION_CHECKSUM_BYTES + 1];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, ONION_CHECKSUM_BYTES);
address[address.length - 1] = ONION_HS_PROTOCOL_VERSION;
return Base32.encode(address).toLowerCase();
}
} }

View File

@@ -1,38 +1,38 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.KeyEncoder;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.engines.AESLightEngine;
import org.bouncycastle.crypto.engines.IESEngine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.IESWithCipherParameters;
import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.KeyParser; import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.BasicAgreement;
import org.spongycastle.crypto.BlockCipher;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.CryptoException;
import org.spongycastle.crypto.DerivationFunction;
import org.spongycastle.crypto.KeyEncoder;
import org.spongycastle.crypto.Mac;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.engines.AESLightEngine;
import org.spongycastle.crypto.engines.IESEngine;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator;
import org.spongycastle.crypto.generators.KDF2BytesGenerator;
import org.spongycastle.crypto.macs.HMac;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.AsymmetricKeyParameter;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.crypto.params.IESWithCipherParameters;
import org.spongycastle.crypto.parsers.ECIESPublicKeyParser;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.generators.SCrypt;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.generators.SCrypt;
import java.util.logging.Logger; import java.util.logging.Logger;

View File

@@ -1,14 +1,14 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.briarproject.bramble.api.crypto.KeyParser; import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;

View File

@@ -1,8 +1,8 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;

View File

@@ -1,8 +1,8 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;

View File

@@ -1,7 +1,5 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
@@ -11,6 +9,8 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.IncomingKeys; import org.briarproject.bramble.api.transport.IncomingKeys;
import org.briarproject.bramble.api.transport.OutgoingKeys; import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;

View File

@@ -1,13 +1,13 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.engines.XSalsa20Engine;
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.Poly1305;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.DataLengthException;
import org.spongycastle.crypto.engines.XSalsa20Engine;
import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
import org.spongycastle.crypto.macs.Poly1305;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;

View File

@@ -145,7 +145,7 @@ interface Database<T> {
/** /**
* Stores a transport. * Stores a transport.
*/ */
void addTransport(T txn, TransportId t, long maxLatency) void addTransport(T txn, TransportId t, int maxLatency)
throws DbException; throws DbException;
/** /**
@@ -162,18 +162,6 @@ interface Database<T> {
KeySetId addTransportKeys(T txn, PendingContactId p, TransportKeys k) KeySetId addTransportKeys(T txn, PendingContactId p, TransportKeys k)
throws DbException; throws DbException;
/**
* Returns true if there are any acks or messages to send to the given
* contact over a transport with the given maximum latency.
* <p/>
* Read-only.
*
* @param eager True if messages that are not yet due for retransmission
* should be included
*/
boolean containsAnythingToSend(T txn, ContactId c, long maxLatency,
boolean eager) throws DbException;
/** /**
* Returns true if the database contains the given contact for the given * Returns true if the database contains the given contact for the given
* local pseudonym. * local pseudonym.
@@ -227,16 +215,6 @@ interface Database<T> {
*/ */
boolean containsTransport(T txn, TransportId t) throws DbException; boolean containsTransport(T txn, TransportId t) throws DbException;
/**
* Returns true if the database contains keys for communicating with the
* given contact over the given transport. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
boolean containsTransportKeys(T txn, ContactId c, TransportId t)
throws DbException;
/** /**
* Returns true if the database contains the given message, the message is * Returns true if the database contains the given message, the message is
* shared, and the visibility of the message's group to the given contact * shared, and the visibility of the message's group to the given contact
@@ -483,7 +461,7 @@ interface Database<T> {
* Read-only. * Read-only.
*/ */
Collection<MessageId> getMessagesToOffer(T txn, ContactId c, Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
int maxMessages, long maxLatency) throws DbException; int maxMessages, int maxLatency) throws DbException;
/** /**
* Returns the IDs of some messages that are eligible to be requested from * Returns the IDs of some messages that are eligible to be requested from
@@ -498,36 +476,10 @@ interface Database<T> {
* Returns the IDs of some messages that are eligible to be sent to the * Returns the IDs of some messages that are eligible to be sent to the
* given contact, up to the given total length. * given contact, up to the given total length.
* <p/> * <p/>
* Unlike {@link #getUnackedMessagesToSend(Object, ContactId)} this method
* does not return messages that have already been sent unless they are
* due for retransmission.
* <p/>
* Read-only. * Read-only.
*/ */
Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength, Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength,
long maxLatency) throws DbException; int maxLatency) throws DbException;
/**
* Returns the IDs of all messages that are eligible to be sent to the
* given contact, together with their raw lengths.
* <p/>
* Unlike {@link #getMessagesToSend(Object, ContactId, int, long)} this
* method may return messages that have already been sent and are not yet
* due for retransmission.
* <p/>
* Read-only.
*/
Map<MessageId, Integer> getUnackedMessagesToSend(T txn, ContactId c)
throws DbException;
/**
* Returns the total length, including headers, of all messages that are
* eligible to be sent to the given contact. This may include messages
* that have already been sent and are not yet due for retransmission.
* <p/>
* Read-only.
*/
long getUnackedMessageBytesToSend(T txn, ContactId c) throws DbException;
/** /**
* Returns the IDs of any messages that need to be validated. * Returns the IDs of any messages that need to be validated.
@@ -604,7 +556,7 @@ interface Database<T> {
* Read-only. * Read-only.
*/ */
Collection<MessageId> getRequestedMessagesToSend(T txn, ContactId c, Collection<MessageId> getRequestedMessagesToSend(T txn, ContactId c,
int maxLength, long maxLatency) throws DbException; int maxLength, int maxLatency) throws DbException;
/** /**
* Returns all settings in the given namespace. * Returns all settings in the given namespace.
@@ -628,16 +580,6 @@ interface Database<T> {
Collection<TransportKeySet> getTransportKeys(T txn, TransportId t) Collection<TransportKeySet> getTransportKeys(T txn, TransportId t)
throws DbException; throws DbException;
/**
* Returns the contact IDs and transport IDs for which the DB contains
* at least one set of transport keys. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
Map<ContactId, Collection<TransportId>> getTransportsWithKeys(T txn)
throws DbException;
/** /**
* Increments the outgoing stream counter for the given transport keys. * Increments the outgoing stream counter for the given transport keys.
*/ */
@@ -845,7 +787,7 @@ interface Database<T> {
* of the given message with respect to the given contact, using the latency * of the given message with respect to the given contact, using the latency
* of the transport over which it was sent. * of the transport over which it was sent.
*/ */
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, long maxLatency) void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, int maxLatency)
throws DbException; throws DbException;
/** /**

View File

@@ -310,7 +310,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override @Override
public void addTransport(Transaction transaction, TransportId t, public void addTransport(Transaction transaction, TransportId t,
long maxLatency) throws DbException { int maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsTransport(txn, t)) if (!db.containsTransport(txn, t))
@@ -341,15 +341,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.addTransportKeys(txn, p, k); return db.addTransportKeys(txn, p, k);
} }
@Override
public boolean containsAnythingToSend(Transaction transaction, ContactId c,
long maxLatency, boolean eager) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
return db.containsAnythingToSend(txn, c, maxLatency, eager);
}
@Override @Override
public boolean containsContact(Transaction transaction, AuthorId remote, public boolean containsContact(Transaction transaction, AuthorId remote,
AuthorId local) throws DbException { AuthorId local) throws DbException {
@@ -380,13 +371,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.containsPendingContact(txn, p); return db.containsPendingContact(txn, p);
} }
@Override
public boolean containsTransportKeys(Transaction transaction, ContactId c,
TransportId t) throws DbException {
T txn = unbox(transaction);
return db.containsTransportKeys(txn, c, t);
}
@Override @Override
public void deleteMessage(Transaction transaction, MessageId m) public void deleteMessage(Transaction transaction, MessageId m)
throws DbException { throws DbException {
@@ -424,57 +408,28 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable @Nullable
@Override @Override
public Collection<Message> generateBatch(Transaction transaction, public Collection<Message> generateBatch(Transaction transaction,
ContactId c, int maxLength, long maxLatency) throws DbException { ContactId c, int maxLength, int maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> ids = Collection<MessageId> ids =
db.getMessagesToSend(txn, c, maxLength, maxLatency); db.getMessagesToSend(txn, c, maxLength, maxLatency);
long totalLength = 0;
List<Message> messages = new ArrayList<>(ids.size()); List<Message> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) { for (MessageId m : ids) {
Message message = db.getMessage(txn, m); messages.add(db.getMessage(txn, m));
totalLength += message.getRawLength();
messages.add(message);
db.updateExpiryTimeAndEta(txn, c, m, maxLatency); db.updateExpiryTimeAndEta(txn, c, m, maxLatency);
} }
if (ids.isEmpty()) return null; if (ids.isEmpty()) return null;
db.lowerRequestedFlag(txn, c, ids); db.lowerRequestedFlag(txn, c, ids);
transaction.attach(new MessagesSentEvent(c, ids, totalLength)); transaction.attach(new MessagesSentEvent(c, ids));
return messages;
}
@Override
public Collection<Message> generateBatch(Transaction transaction,
ContactId c, Collection<MessageId> ids, long maxLatency)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
long totalLength = 0;
List<Message> messages = new ArrayList<>(ids.size());
List<MessageId> sentIds = new ArrayList<>(ids.size());
for (MessageId m : ids) {
if (db.containsVisibleMessage(txn, c, m)) {
Message message = db.getMessage(txn, m);
totalLength += message.getRawLength();
messages.add(message);
sentIds.add(m);
db.updateExpiryTimeAndEta(txn, c, m, maxLatency);
}
}
if (messages.isEmpty()) return messages;
db.lowerRequestedFlag(txn, c, sentIds);
transaction.attach(new MessagesSentEvent(c, sentIds, totalLength));
return messages; return messages;
} }
@Nullable @Nullable
@Override @Override
public Offer generateOffer(Transaction transaction, ContactId c, public Offer generateOffer(Transaction transaction, ContactId c,
int maxMessages, long maxLatency) throws DbException { int maxMessages, int maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
@@ -505,24 +460,21 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable @Nullable
@Override @Override
public Collection<Message> generateRequestedBatch(Transaction transaction, public Collection<Message> generateRequestedBatch(Transaction transaction,
ContactId c, int maxLength, long maxLatency) throws DbException { ContactId c, int maxLength, int maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException(); if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction); T txn = unbox(transaction);
if (!db.containsContact(txn, c)) if (!db.containsContact(txn, c))
throw new NoSuchContactException(); throw new NoSuchContactException();
Collection<MessageId> ids = Collection<MessageId> ids =
db.getRequestedMessagesToSend(txn, c, maxLength, maxLatency); db.getRequestedMessagesToSend(txn, c, maxLength, maxLatency);
long totalLength = 0;
List<Message> messages = new ArrayList<>(ids.size()); List<Message> messages = new ArrayList<>(ids.size());
for (MessageId m : ids) { for (MessageId m : ids) {
Message message = db.getMessage(txn, m); messages.add(db.getMessage(txn, m));
totalLength += message.getRawLength();
messages.add(message);
db.updateExpiryTimeAndEta(txn, c, m, maxLatency); db.updateExpiryTimeAndEta(txn, c, m, maxLatency);
} }
if (ids.isEmpty()) return null; if (ids.isEmpty()) return null;
db.lowerRequestedFlag(txn, c, ids); db.lowerRequestedFlag(txn, c, ids);
transaction.attach(new MessagesSentEvent(c, ids, totalLength)); transaction.attach(new MessagesSentEvent(c, ids));
return messages; return messages;
} }
@@ -740,25 +692,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return status; return status;
} }
@Override
public Map<MessageId, Integer> getUnackedMessagesToSend(
Transaction transaction,
ContactId c) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
return db.getUnackedMessagesToSend(txn, c);
}
@Override
public long getUnackedMessageBytesToSend(Transaction transaction,
ContactId c) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
return db.getUnackedMessageBytesToSend(txn, c);
}
@Override @Override
public Map<MessageId, MessageState> getMessageDependencies( public Map<MessageId, MessageState> getMessageDependencies(
Transaction transaction, MessageId m) throws DbException { Transaction transaction, MessageId m) throws DbException {
@@ -832,13 +765,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getTransportKeys(txn, t); return db.getTransportKeys(txn, t);
} }
@Override
public Map<ContactId, Collection<TransportId>> getTransportsWithKeys(
Transaction transaction) throws DbException {
T txn = unbox(transaction);
return db.getTransportsWithKeys(txn);
}
@Override @Override
public void incrementStreamCounter(Transaction transaction, TransportId t, public void incrementStreamCounter(Transaction transaction, TransportId t,
KeySetId k) throws DbException { KeySetId k) throws DbException {

View File

@@ -1,7 +1,5 @@
package org.briarproject.bramble.db; package org.briarproject.bramble.db;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_TRANSPORT_LATENCY;
class ExponentialBackoff { class ExponentialBackoff {
/** /**
@@ -13,11 +11,9 @@ class ExponentialBackoff {
* transmissions increases exponentially. If the expiry time would * transmissions increases exponentially. If the expiry time would
* be greater than Long.MAX_VALUE, Long.MAX_VALUE is returned. * be greater than Long.MAX_VALUE, Long.MAX_VALUE is returned.
*/ */
static long calculateExpiry(long now, long maxLatency, int txCount) { static long calculateExpiry(long now, int maxLatency, int txCount) {
if (now < 0) throw new IllegalArgumentException(); if (now < 0) throw new IllegalArgumentException();
if (maxLatency <= 0 || maxLatency > MAX_TRANSPORT_LATENCY) { if (maxLatency <= 0) throw new IllegalArgumentException();
throw new IllegalArgumentException();
}
if (txCount < 0) throw new IllegalArgumentException(); if (txCount < 0) throw new IllegalArgumentException();
// The maximum round-trip time is twice the maximum latency // The maximum round-trip time is twice the maximum latency
long roundTrip = maxLatency * 2L; long roundTrip = maxLatency * 2L;

View File

@@ -51,7 +51,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -102,7 +101,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
abstract class JdbcDatabase implements Database<Connection> { abstract class JdbcDatabase implements Database<Connection> {
// Package access for testing // Package access for testing
static final int CODE_SCHEMA_VERSION = 49; static final int CODE_SCHEMA_VERSION = 48;
// Time period offsets for incoming transport keys // Time period offsets for incoming transport keys
private static final int OFFSET_PREV = -1; private static final int OFFSET_PREV = -1;
@@ -267,7 +266,7 @@ abstract class JdbcDatabase implements Database<Connection> {
private static final String CREATE_TRANSPORTS = private static final String CREATE_TRANSPORTS =
"CREATE TABLE transports" "CREATE TABLE transports"
+ " (transportId _STRING NOT NULL," + " (transportId _STRING NOT NULL,"
+ " maxLatency BIGINT NOT NULL," + " maxLatency INT NOT NULL,"
+ " PRIMARY KEY (transportId))"; + " PRIMARY KEY (transportId))";
private static final String CREATE_PENDING_CONTACTS = private static final String CREATE_PENDING_CONTACTS =
@@ -345,11 +344,6 @@ abstract class JdbcDatabase implements Database<Connection> {
"CREATE INDEX IF NOT EXISTS statusesByContactIdTimestamp" "CREATE INDEX IF NOT EXISTS statusesByContactIdTimestamp"
+ " ON statuses (contactId, timestamp)"; + " ON statuses (contactId, timestamp)";
private static final String
INDEX_STATUSES_BY_CONTACT_ID_TX_COUNT_TIMESTAMP =
"CREATE INDEX IF NOT EXISTS statusesByContactIdTxCountTimestamp"
+ " ON statuses (contactId, txCount, timestamp)";
private static final String INDEX_MESSAGES_BY_CLEANUP_DEADLINE = private static final String INDEX_MESSAGES_BY_CLEANUP_DEADLINE =
"CREATE INDEX IF NOT EXISTS messagesByCleanupDeadline" "CREATE INDEX IF NOT EXISTS messagesByCleanupDeadline"
+ " ON messages (cleanupDeadline)"; + " ON messages (cleanupDeadline)";
@@ -498,8 +492,7 @@ abstract class JdbcDatabase implements Database<Connection> {
new Migration44_45(), new Migration44_45(),
new Migration45_46(), new Migration45_46(),
new Migration46_47(dbTypes), new Migration46_47(dbTypes),
new Migration47_48(), new Migration47_48()
new Migration48_49()
); );
} }
@@ -577,7 +570,6 @@ abstract class JdbcDatabase implements Database<Connection> {
s.executeUpdate(INDEX_MESSAGE_DEPENDENCIES_BY_DEPENDENCY_ID); s.executeUpdate(INDEX_MESSAGE_DEPENDENCIES_BY_DEPENDENCY_ID);
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_GROUP_ID); s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_GROUP_ID);
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP); s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TIMESTAMP);
s.executeUpdate(INDEX_STATUSES_BY_CONTACT_ID_TX_COUNT_TIMESTAMP);
s.executeUpdate(INDEX_MESSAGES_BY_CLEANUP_DEADLINE); s.executeUpdate(INDEX_MESSAGES_BY_CLEANUP_DEADLINE);
s.close(); s.close();
} catch (SQLException e) { } catch (SQLException e) {
@@ -1007,7 +999,7 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
@Override @Override
public void addTransport(Connection txn, TransportId t, long maxLatency) public void addTransport(Connection txn, TransportId t, int maxLatency)
throws DbException { throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
try { try {
@@ -1128,55 +1120,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public boolean containsAnythingToSend(Connection txn, ContactId c,
long maxLatency, boolean eager) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT NULL FROM statuses"
+ " WHERE contactId = ? AND ack = TRUE";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
rs = ps.executeQuery();
boolean acksToSend = rs.next();
rs.close();
ps.close();
if (acksToSend) return true;
if (eager) {
sql = "SELECT NULL from statuses"
+ " WHERE contactId = ? AND state = ?"
+ " AND groupShared = TRUE AND messageShared = TRUE"
+ " AND deleted = FALSE AND seen = FALSE";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, DELIVERED.getValue());
} else {
long now = clock.currentTimeMillis();
long eta = now + maxLatency;
sql = "SELECT NULL FROM statuses"
+ " WHERE contactId = ? AND state = ?"
+ " AND groupShared = TRUE AND messageShared = TRUE"
+ " AND deleted = FALSE AND seen = FALSE"
+ " AND (expiry <= ? OR eta > ?)";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, DELIVERED.getValue());
ps.setLong(3, now);
ps.setLong(4, eta);
}
rs = ps.executeQuery();
boolean messagesToSend = rs.next();
rs.close();
ps.close();
return messagesToSend;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public boolean containsContact(Connection txn, AuthorId remote, public boolean containsContact(Connection txn, AuthorId remote,
AuthorId local) throws DbException { AuthorId local) throws DbException {
@@ -1334,29 +1277,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public boolean containsTransportKeys(Connection txn, ContactId c,
TransportId t) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT NULL FROM outgoingKeys"
+ " WHERE contactId = ? AND transportId = ?";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setString(2, t.getString());
rs = ps.executeQuery();
boolean found = rs.next();
rs.close();
ps.close();
return found;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public boolean containsVisibleMessage(Connection txn, ContactId c, public boolean containsVisibleMessage(Connection txn, ContactId c,
MessageId m) throws DbException { MessageId m) throws DbException {
@@ -2189,7 +2109,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override @Override
public Collection<MessageId> getMessagesToOffer(Connection txn, public Collection<MessageId> getMessagesToOffer(Connection txn,
ContactId c, int maxMessages, long maxLatency) throws DbException { ContactId c, int maxMessages, int maxLatency) throws DbException {
long now = clock.currentTimeMillis(); long now = clock.currentTimeMillis();
long eta = now + maxLatency; long eta = now + maxLatency;
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -2248,7 +2168,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override @Override
public Collection<MessageId> getMessagesToSend(Connection txn, ContactId c, public Collection<MessageId> getMessagesToSend(Connection txn, ContactId c,
int maxLength, long maxLatency) throws DbException { int maxLength, int maxLatency) throws DbException {
long now = clock.currentTimeMillis(); long now = clock.currentTimeMillis();
long eta = now + maxLatency; long eta = now + maxLatency;
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -2285,63 +2205,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public Map<MessageId, Integer> getUnackedMessagesToSend(Connection txn,
ContactId c) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT length, messageId FROM statuses"
+ " WHERE contactId = ? AND state = ?"
+ " AND groupShared = TRUE AND messageShared = TRUE"
+ " AND deleted = FALSE AND seen = FALSE"
+ " ORDER BY txCount, timestamp";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, DELIVERED.getValue());
rs = ps.executeQuery();
Map<MessageId, Integer> results = new LinkedHashMap<>();
while (rs.next()) {
int length = rs.getInt(1);
MessageId id = new MessageId(rs.getBytes(2));
results.put(id, length);
}
rs.close();
ps.close();
return results;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public long getUnackedMessageBytesToSend(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT SUM(length) FROM statuses"
+ " WHERE contactId = ? AND state = ?"
+ " AND groupShared = TRUE AND messageShared = TRUE"
+ " AND deleted = FALSE AND seen = FALSE";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, DELIVERED.getValue());
rs = ps.executeQuery();
rs.next();
long total = rs.getLong(1);
rs.close();
ps.close();
return total;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public Collection<MessageId> getMessagesToValidate(Connection txn) public Collection<MessageId> getMessagesToValidate(Connection txn)
throws DbException { throws DbException {
@@ -2547,7 +2410,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override @Override
public Collection<MessageId> getRequestedMessagesToSend(Connection txn, public Collection<MessageId> getRequestedMessagesToSend(Connection txn,
ContactId c, int maxLength, long maxLatency) throws DbException { ContactId c, int maxLength, int maxLatency) throws DbException {
long now = clock.currentTimeMillis(); long now = clock.currentTimeMillis();
long eta = now + maxLatency; long eta = now + maxLatency;
PreparedStatement ps = null; PreparedStatement ps = null;
@@ -2711,38 +2574,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public Map<ContactId, Collection<TransportId>> getTransportsWithKeys(
Connection txn) throws DbException {
Statement s = null;
ResultSet rs = null;
try {
String sql = "SELECT DISTINCT contactId, transportId"
+ " FROM outgoingKeys";
s = txn.createStatement();
rs = s.executeQuery(sql);
Map<ContactId, Collection<TransportId>> ids = new HashMap<>();
while (rs.next()) {
ContactId c = new ContactId(rs.getInt(1));
TransportId t = new TransportId(rs.getString(2));
Collection<TransportId> transportIds = ids.get(c);
if (transportIds == null) {
transportIds = new ArrayList<>();
ids.put(c, transportIds);
}
transportIds.add(t);
}
rs.close();
s.close();
return ids;
} catch (SQLException e) {
tryToClose(rs, LOG, WARNING);
tryToClose(s, LOG, WARNING);
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public void incrementStreamCounter(Connection txn, TransportId t, public void incrementStreamCounter(Connection txn, TransportId t,
KeySetId k) throws DbException { KeySetId k) throws DbException {
@@ -3618,7 +3449,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override @Override
public void updateExpiryTimeAndEta(Connection txn, ContactId c, MessageId m, public void updateExpiryTimeAndEta(Connection txn, ContactId c, MessageId m,
long maxLatency) throws DbException { int maxLatency) throws DbException {
PreparedStatement ps = null; PreparedStatement ps = null;
ResultSet rs = null; ResultSet rs = null;
try { try {

View File

@@ -1,41 +0,0 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DbException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration48_49 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration48_49.class.getName());
@Override
public int getStartVersion() {
return 48;
}
@Override
public int getEndVersion() {
return 49;
}
@Override
public void migrate(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
s.execute("ALTER TABLE transports"
+ " ALTER COLUMN maxLatency"
+ " SET DATA TYPE BIGINT");
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
}

View File

@@ -12,7 +12,6 @@ import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException; import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
@@ -35,14 +34,11 @@ import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleS
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING_SERVICES;
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.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.CLOCK_ERROR;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DATA_TOO_NEW_ERROR; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DATA_TOO_NEW_ERROR;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DATA_TOO_OLD_ERROR; import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DATA_TOO_OLD_ERROR;
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.api.system.Clock.MAX_REASONABLE_TIME_MS;
import static org.briarproject.bramble.api.system.Clock.MIN_REASONABLE_TIME_MS;
import static org.briarproject.bramble.util.LogUtils.logDuration; import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.LogUtils.now; import static org.briarproject.bramble.util.LogUtils.now;
@@ -56,7 +52,6 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private final DatabaseComponent db; private final DatabaseComponent db;
private final EventBus eventBus; private final EventBus eventBus;
private final Clock clock;
private final List<Service> services; private final List<Service> services;
private final List<OpenDatabaseHook> openDatabaseHooks; private final List<OpenDatabaseHook> openDatabaseHooks;
private final List<ExecutorService> executors; private final List<ExecutorService> executors;
@@ -68,11 +63,9 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private volatile LifecycleState state = STARTING; private volatile LifecycleState state = STARTING;
@Inject @Inject
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus, LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus) {
Clock clock) {
this.db = db; this.db = db;
this.eventBus = eventBus; this.eventBus = eventBus;
this.clock = clock;
services = new CopyOnWriteArrayList<>(); services = new CopyOnWriteArrayList<>();
openDatabaseHooks = new CopyOnWriteArrayList<>(); openDatabaseHooks = new CopyOnWriteArrayList<>();
executors = new CopyOnWriteArrayList<>(); executors = new CopyOnWriteArrayList<>();
@@ -106,13 +99,6 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
LOG.info("Already starting or stopping"); LOG.info("Already starting or stopping");
return ALREADY_RUNNING; return ALREADY_RUNNING;
} }
long now = clock.currentTimeMillis();
if (now < MIN_REASONABLE_TIME_MS || now > MAX_REASONABLE_TIME_MS) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("System clock is unreasonable: " + now);
}
return CLOCK_ERROR;
}
try { try {
LOG.info("Opening database"); LOG.info("Opening database");
long start = now(); long start = now();

View File

@@ -1,44 +0,0 @@
package org.briarproject.bramble.logging;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.system.TaskScheduler;
import java.io.OutputStream;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import java.util.logging.StreamHandler;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
class FlushingStreamHandler extends StreamHandler {
private static final int FLUSH_DELAY_MS = 5_000;
private final TaskScheduler scheduler;
private final Executor ioExecutor;
private final AtomicBoolean flushScheduled = new AtomicBoolean(false);
FlushingStreamHandler(TaskScheduler scheduler,
Executor ioExecutor, OutputStream out, Formatter formatter) {
super(out, formatter);
this.scheduler = scheduler;
this.ioExecutor = ioExecutor;
}
@Override
public void publish(LogRecord record) {
super.publish(record);
if (!flushScheduled.getAndSet(true)) {
scheduler.schedule(this::scheduledFlush, ioExecutor,
FLUSH_DELAY_MS, MILLISECONDS);
}
}
@IoExecutor
private void scheduledFlush() {
flushScheduled.set(false);
flush();
}
}

View File

@@ -1,29 +0,0 @@
package org.briarproject.bramble.logging;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import java.util.logging.Formatter;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class LoggingModule {
@Provides
Formatter provideFormatter() {
return new BriefLogFormatter();
}
@Provides
@Singleton
PersistentLogManager providePersistentLogManager(
LifecycleManager lifecycleManager,
PersistentLogManagerImpl persistentLogManager) {
lifecycleManager.registerOpenDatabaseHook(persistentLogManager);
return persistentLogManager;
}
}

View File

@@ -1,176 +0,0 @@
package org.briarproject.bramble.logging;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.ShutdownManager;
import org.briarproject.bramble.api.logging.PersistentLogManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.transport.StreamReaderFactory;
import org.briarproject.bramble.api.transport.StreamWriter;
import org.briarproject.bramble.api.transport.StreamWriterFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
class PersistentLogManagerImpl implements PersistentLogManager,
OpenDatabaseHook {
private static final Logger LOG =
getLogger(PersistentLogManagerImpl.class.getName());
private static final String LOG_FILE = "briar.log";
private static final String OLD_LOG_FILE = "briar.log.old";
private final TaskScheduler scheduler;
private final Executor ioExecutor;
private final ShutdownManager shutdownManager;
private final DatabaseComponent db;
private final StreamReaderFactory streamReaderFactory;
private final StreamWriterFactory streamWriterFactory;
private final Formatter formatter;
private final SecretKey logKey;
private final AtomicReference<Integer> shutdownHookHandle =
new AtomicReference<>();
@Nullable
private volatile SecretKey oldLogKey = null;
@Inject
PersistentLogManagerImpl(
TaskScheduler scheduler,
@IoExecutor Executor ioExecutor,
ShutdownManager shutdownManager,
DatabaseComponent db,
StreamReaderFactory streamReaderFactory,
StreamWriterFactory streamWriterFactory,
Formatter formatter,
CryptoComponent crypto) {
this.scheduler = scheduler;
this.ioExecutor = ioExecutor;
this.shutdownManager = shutdownManager;
this.db = db;
this.streamReaderFactory = streamReaderFactory;
this.streamWriterFactory = streamWriterFactory;
this.formatter = formatter;
logKey = crypto.generateSecretKey();
}
@Override
public void onDatabaseOpened(Transaction txn) throws DbException {
Settings s = db.getSettings(txn, LOG_SETTINGS_NAMESPACE);
// Load the old log key, if any
byte[] oldKeyBytes = s.getBytes(LOG_KEY_KEY);
if (oldKeyBytes != null && oldKeyBytes.length == SecretKey.LENGTH) {
LOG.info("Loaded old log key");
oldLogKey = new SecretKey(oldKeyBytes);
}
// Store the current log key
s.putBytes(LOG_KEY_KEY, logKey.getBytes());
db.mergeSettings(txn, s, LOG_SETTINGS_NAMESPACE);
}
@Override
public Handler createLogHandler(File dir) throws IOException {
File logFile = new File(dir, LOG_FILE);
File oldLogFile = new File(dir, OLD_LOG_FILE);
if (oldLogFile.exists() && !oldLogFile.delete())
LOG.warning("Failed to delete old log file");
if (logFile.exists() && !logFile.renameTo(oldLogFile))
LOG.warning("Failed to rename log file");
try {
OutputStream out = new FileOutputStream(logFile);
StreamWriter writer =
streamWriterFactory.createLogStreamWriter(out, logKey);
StreamHandler handler = new FlushingStreamHandler(scheduler,
ioExecutor, writer.getOutputStream(), formatter);
// Flush the log and terminate the stream at shutdown
Runnable shutdownHook = () -> {
LOG.info("Shutting down");
handler.flush();
try {
writer.sendEndOfStream();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
};
int handle = shutdownManager.addShutdownHook(shutdownHook);
// If a previous handler registered a shutdown hook, remove it
Integer oldHandle = shutdownHookHandle.getAndSet(handle);
if (oldHandle != null) {
shutdownManager.removeShutdownHook(oldHandle);
}
return handler;
} catch (SecurityException e) {
throw new IOException(e);
}
}
@Override
public void addLogHandler(File dir, Logger logger) throws IOException {
for (Handler h : logger.getHandlers()) {
if (h instanceof FlushingStreamHandler) logger.removeHandler(h);
}
logger.addHandler(createLogHandler(dir));
}
@Override
public Scanner getPersistentLog(File dir, boolean old)
throws IOException {
if (old) {
SecretKey oldLogKey = this.oldLogKey;
if (oldLogKey == null) {
LOG.info("Old log key has not been loaded");
return emptyScanner();
}
return getPersistentLog(new File(dir, OLD_LOG_FILE), oldLogKey);
} else {
return getPersistentLog(new File(dir, LOG_FILE), logKey);
}
}
private Scanner getPersistentLog(File logFile, SecretKey key)
throws IOException {
if (logFile.exists()) {
LOG.info("Reading log file");
InputStream in = new FileInputStream(logFile);
return new Scanner(streamReaderFactory.createLogStreamReader(in,
key));
} else {
LOG.info("Log file does not exist");
return emptyScanner();
}
}
private Scanner emptyScanner() {
return new Scanner(new ByteArrayInputStream(new byte[0]));
}
}

View File

@@ -1,16 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import dagger.Module;
import dagger.Provides;
@Module
public class MailboxModule {
@Provides
MailboxSettingsManager provideMailboxSettingsManager(
MailboxSettingsManagerImpl mailboxSettingsManager) {
return mailboxSettingsManager;
}
}

View File

@@ -1,86 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@Immutable
@NotNullByDefault
class MailboxSettingsManagerImpl implements MailboxSettingsManager {
// Package access for testing
static final String SETTINGS_NAMESPACE = "mailbox";
static final String SETTINGS_KEY_ONION = "onion";
static final String SETTINGS_KEY_TOKEN = "token";
static final String SETTINGS_KEY_LAST_ATTEMPT = "lastAttempt";
static final String SETTINGS_KEY_LAST_SUCCESS = "lastSuccess";
static final String SETTINGS_KEY_ATTEMPTS = "attempts";
private final SettingsManager settingsManager;
@Inject
MailboxSettingsManagerImpl(SettingsManager settingsManager) {
this.settingsManager = settingsManager;
}
@Override
public MailboxProperties getOwnMailboxProperties(Transaction txn)
throws DbException {
Settings s = settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
String onion = s.get(SETTINGS_KEY_ONION);
String token = s.get(SETTINGS_KEY_TOKEN);
if (isNullOrEmpty(onion) || isNullOrEmpty(token)) return null;
return new MailboxProperties(onion, token, true);
}
@Override
public void setOwnMailboxProperties(Transaction txn, MailboxProperties p)
throws DbException {
Settings s = new Settings();
s.put(SETTINGS_KEY_ONION, p.getOnionAddress());
s.put(SETTINGS_KEY_TOKEN, p.getAuthToken());
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
}
@Override
public MailboxStatus getOwnMailboxStatus(Transaction txn)
throws DbException {
Settings s = settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
long lastAttempt = s.getLong(SETTINGS_KEY_LAST_ATTEMPT, -1);
long lastSuccess = s.getLong(SETTINGS_KEY_LAST_SUCCESS, -1);
int attempts = s.getInt(SETTINGS_KEY_ATTEMPTS, 0);
return new MailboxStatus(lastAttempt, lastSuccess, attempts);
}
@Override
public void recordSuccessfulConnection(Transaction txn, long now)
throws DbException {
Settings s = new Settings();
s.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
s.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
s.putInt(SETTINGS_KEY_ATTEMPTS, 0);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
}
@Override
public void recordFailedConnectionAttempt(Transaction txn, long now)
throws DbException {
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
int attempts = oldSettings.getInt(SETTINGS_KEY_ATTEMPTS, 0);
Settings newSettings = new Settings();
newSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
newSettings.putInt(SETTINGS_KEY_ATTEMPTS, attempts + 1);
settingsManager.mergeSettings(txn, newSettings, SETTINGS_NAMESPACE);
}
}

View File

@@ -79,8 +79,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final Backoff backoff; private final Backoff backoff;
private final PluginCallback callback; private final PluginCallback callback;
private final long maxLatency; private final int maxLatency, maxIdleTime;
private final int maxIdleTime;
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
private final AtomicBoolean everConnected = new AtomicBoolean(false); private final AtomicBoolean everConnected = new AtomicBoolean(false);
@@ -122,7 +121,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
SecureRandom secureRandom, SecureRandom secureRandom,
Backoff backoff, Backoff backoff,
PluginCallback callback, PluginCallback callback,
long maxLatency, int maxLatency,
int maxIdleTime) { int maxIdleTime) {
this.connectionLimiter = connectionLimiter; this.connectionLimiter = connectionLimiter;
this.connectionFactory = connectionFactory; this.connectionFactory = connectionFactory;
@@ -159,7 +158,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
} }
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return maxLatency; return maxLatency;
} }

View File

@@ -1,126 +0,0 @@
package org.briarproject.bramble.plugin.file;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import static java.util.Collections.singletonMap;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.ID;
import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.PROP_SUPPORTED;
import static org.briarproject.bramble.util.LogUtils.logException;
@Immutable
@NotNullByDefault
abstract class AbstractRemovableDrivePlugin implements SimplexPlugin {
private static final Logger LOG =
getLogger(AbstractRemovableDrivePlugin.class.getName());
private final long maxLatency;
private final PluginCallback callback;
abstract InputStream openInputStream(TransportProperties p)
throws IOException;
abstract OutputStream openOutputStream(TransportProperties p)
throws IOException;
AbstractRemovableDrivePlugin(PluginCallback callback, long maxLatency) {
this.callback = callback;
this.maxLatency = maxLatency;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public long getMaxLatency() {
return maxLatency;
}
@Override
public int getMaxIdleTime() {
// Unused for simplex transports
throw new UnsupportedOperationException();
}
@Override
public void start() {
callback.mergeLocalProperties(
new TransportProperties(singletonMap(PROP_SUPPORTED, "true")));
}
@Override
public void stop() {
}
@Override
public State getState() {
return ACTIVE;
}
@Override
public int getReasonsDisabled() {
return 0;
}
@Override
public boolean shouldPoll() {
return false;
}
@Override
public int getPollingInterval() {
throw new UnsupportedOperationException();
}
@Override
public void poll(
Collection<Pair<TransportProperties, ConnectionHandler>> properties) {
throw new UnsupportedOperationException();
}
@Override
public boolean isLossyAndCheap() {
return true;
}
@Override
public TransportConnectionReader createReader(TransportProperties p) {
try {
return new TransportInputStreamReader(openInputStream(p));
} catch (IOException e) {
logException(LOG, WARNING, e);
return null;
}
}
@Override
public TransportConnectionWriter createWriter(TransportProperties p) {
try {
return new TransportOutputStreamWriter(this, openOutputStream(p));
} catch (IOException e) {
logException(LOG, WARNING, e);
return null;
}
}
}

View File

@@ -15,8 +15,8 @@ import java.util.logging.Logger;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.FileConstants.PROP_PATH;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.file.FileConstants.PROP_PATH;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@@ -27,20 +27,20 @@ abstract class FilePlugin implements SimplexPlugin {
getLogger(FilePlugin.class.getName()); getLogger(FilePlugin.class.getName());
protected final PluginCallback callback; protected final PluginCallback callback;
protected final long maxLatency; protected final int maxLatency;
protected abstract void writerFinished(File f, boolean exception); protected abstract void writerFinished(File f, boolean exception);
protected abstract void readerFinished(File f, boolean exception, protected abstract void readerFinished(File f, boolean exception,
boolean recognised); boolean recognised);
FilePlugin(PluginCallback callback, long maxLatency) { FilePlugin(PluginCallback callback, int maxLatency) {
this.callback = callback; this.callback = callback;
this.maxLatency = maxLatency; this.maxLatency = maxLatency;
} }
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return maxLatency; return maxLatency;
} }

View File

@@ -27,7 +27,7 @@ class FileTransportWriter implements TransportConnectionWriter {
} }
@Override @Override
public long getMaxLatency() { public int getMaxLatency() {
return plugin.getMaxLatency(); return plugin.getMaxLatency();
} }
@@ -36,11 +36,6 @@ class FileTransportWriter implements TransportConnectionWriter {
return plugin.getMaxIdleTime(); return plugin.getMaxIdleTime();
} }
@Override
public boolean isLossyAndCheap() {
return plugin.isLossyAndCheap();
}
@Override @Override
public OutputStream getOutputStream() { public OutputStream getOutputStream() {
return out; return out;

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