Compare commits

..

126 Commits

Author SHA1 Message Date
akwizgran
a438050e68 Merge branch '1081-share-app-via-wifi-hotspot' into offline-testing 2021-07-09 10:41:37 +01:00
Torsten Grote
4d0fe24722 Merge branch '1802-sync-via-removable-storage' into offline-testing
# Conflicts:
#	bramble-api/src/main/java/org/briarproject/bramble/api/FeatureFlags.java
#	bramble-core/build.gradle
#	bramble-core/src/test/java/org/briarproject/bramble/test/BrambleCoreIntegrationTestModule.java
#	bramble-core/witness.gradle
#	bramble-java/src/main/java/org/briarproject/bramble/plugin/tor/UnixTorPluginFactory.java
#	briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java
#	briar-android/src/main/java/org/briarproject/briar/android/AppModule.java
#	briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java
#	briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
#	briar-android/src/main/res/values/strings.xml
#	briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt
#	briar-headless/src/test/java/org/briarproject/briar/headless/HeadlessTestModule.kt
2021-07-07 15:36:08 -03:00
akwizgran
559b29e8b5 Merge branch '2080-improve-offline-sharing-texts' into '1081-share-app-via-wifi-hotspot'
Improve texts on offline hotspot for a better UX

See merge request briar/briar!1493
2021-07-07 10:59:40 +00:00
Torsten Grote
1b7b285862 Merge remote-tracking branch 'origin/1081-share-app-via-wifi-hotspot' into offline-testing 2021-07-06 17:15:23 -03:00
Torsten Grote
178810241f Merge branch '2031-increase-max-latency' into '1802-sync-via-removable-storage'
Increase max latency of removable drive plugin to 28 days

See merge request briar/briar!1503
2021-07-06 20:06:48 +00:00
Torsten Grote
61c601cb6d Merge branch '2103-check-transport-keys' into '1802-sync-via-removable-storage'
Check whether we have transport keys before trying to send data

See merge request briar/briar!1502
2021-07-06 19:56:24 +00:00
Torsten Grote
2002ad08ca Merge branch '2105-let-contacts-know-drive-not-supported' into '1802-sync-via-removable-storage'
Don't configure the removable drive plugin on API < 19

See merge request briar/briar!1501
2021-07-06 19:53:50 +00:00
akwizgran
d134a67ee9 Increase max latency of removable drive plugin to 28 days. 2021-07-06 17:33:00 +01:00
akwizgran
04cf8e16a9 Check whether we have transport keys before trying to send data. 2021-07-06 16:24:43 +01:00
akwizgran
227d345858 Don't configure the removable drive plugin on API < 19. 2021-07-06 16:13:48 +01:00
Torsten Grote
07ef73ab56 Merge branch '2102-clear-introduction-state' into '1802-sync-via-removable-storage'
Clear keys from session when moving to AWAIT_ACTIVATE state

See merge request briar/briar!1500
2021-07-06 12:26:05 +00:00
Torsten Grote
ea2b1ff4d8 Merge branch '2079-reject-old-timestamps' into '1802-sync-via-removable-storage'
Reject old timestamps when deriving rotation mode keys

See merge request briar/briar!1481
2021-07-06 12:22:42 +00:00
akwizgran
69fac86a0c Clear keys from session when moving to AWAIT_ACTIVATE state. 2021-07-05 18:02:22 +01:00
akwizgran
bd6b6c1cd6 Reject old timestamps when deriving rotation mode keys. 2021-07-05 16:35:32 +01:00
Torsten Grote
be6c868135 Merge branch '2101-dont-increment-attempt-twice' into '1081-share-app-via-wifi-hotspot'
Do not increment the attempt variable twice when requesting group info

See merge request briar/briar!1499
2021-07-05 11:44:51 +00:00
Torsten Grote
041a296666 Merge branch '2090-avoid-double-tap-on-start-sharing-button' into '1081-share-app-via-wifi-hotspot'
Do not allow the user to tap the start sharing button twice quickly

See merge request briar/briar!1495
2021-07-05 11:24:47 +00:00
Torsten Grote
00f03f6587 Merge branch '1981-upgrade-material-tap-target-prompt' into 'master'
Upgrade MaterialTapTargetPrompt library to fix NPE

Closes #1981

See merge request briar/briar!1498
2021-07-05 11:17:39 +00:00
Sebastian Kürten
276eeb1c20 Do not increment the attempt variable twice when requesting group info 2021-07-05 12:48:58 +02:00
akwizgran
c68bd699f1 Upgrade MaterialTapTargetPrompt library to fix NPE. 2021-07-05 10:06:53 +01:00
Sebastian Kürten
d46cfb757e Do not allow the user to tap the start sharing button twice quickly 2021-07-05 10:32:49 +02:00
Torsten Grote
d81c4e7982 Merge branch '2065-transfer-data-ui' into '1802-sync-via-removable-storage'
Implement UI of transfer data feature

See merge request briar/briar!1486
2021-07-02 18:07:57 +00:00
Torsten Grote
8c4d6ed5e4 Remove guidelines for percent based laout width 2021-07-02 14:53:10 -03:00
akwizgran
b21b319cb7 Use guidelines to set image sizes. 2021-07-02 14:53:10 -03:00
Torsten Grote
780f6e97b9 Check if the chosen contact supports removable drive transport
and show message if not
2021-07-02 14:53:10 -03:00
Torsten Grote
1756215183 Combine transfer data graphics to reduce layout complexity
and make scaling work better on smaller screens
2021-07-02 14:53:09 -03:00
Torsten Grote
7e3db6c6df Address review feedback for Transfer Data UI 2021-07-02 14:53:09 -03:00
Torsten Grote
1adf408ade Migrate all image file pickers to ActivityResultLauncher
startActivityForResult is deprecated and the new API is nicer. Also, we can use the same launcher types in various places.
2021-07-02 14:53:09 -03:00
Torsten Grote
d662ae49ee Try to force file chooser to show internal/external storage by default 2021-07-02 14:53:08 -03:00
Torsten Grote
7939c8b213 Calculate percentages for send progress bar 2021-07-02 14:53:08 -03:00
Torsten Grote
1899873da3 Remove manual initial state and oldTask state argument
The latter is now handled via a LiveEvent
2021-07-02 14:53:08 -03:00
Torsten Grote
5beffb21f1 Hide Transfer Data feature behind feature flag 2021-07-02 14:53:05 -03:00
Torsten Grote
0f9afda329 Check if there is data to send and show a message if not 2021-07-02 14:46:08 -03:00
Torsten Grote
c16663b530 Always inform new observers about current state 2021-07-02 14:46:07 -03:00
Torsten Grote
77767b45c9 Re-organize conversations overflow menu 2021-07-02 14:46:07 -03:00
Torsten Grote
79ae8fea8d Transfer Data UI 2021-07-02 14:46:06 -03:00
Daniel Lublin
7e3eb1201a Start of UI for transfer data feature 2021-07-02 14:46:04 -03:00
akwizgran
eb283d81c5 Merge branch '2069-transport-key-agreement-integration-tests' into '1802-sync-via-removable-storage'
Integration tests for transport key agreement client

See merge request briar/briar!1492
2021-07-02 11:11:06 +00:00
Torsten Grote
be3700d364 Remove FIXME in test since we won't fix it this way 2021-06-30 16:57:32 -03:00
Torsten Grote
ccec17f28a Also test that messages arrive and activate keys 2021-06-30 16:49:03 -03:00
Torsten Grote
e8428925ae Add two more tests to TransportKeyAgreementIntegrationTest 2021-06-30 16:49:03 -03:00
Torsten Grote
195123e669 Ensure that private key is not stored anymore 2021-06-30 16:49:02 -03:00
Torsten Grote
abe570e905 Add first integration test for TransportKeyAgreementManager 2021-06-30 16:49:02 -03:00
Torsten Grote
a93b1f18ac Refactor base of BriarIntegrationTest into BrambleIntegrationTest 2021-06-30 16:49:02 -03:00
Torsten Grote
e4bd6fdf95 Put FeatureFlags for tests into a TestFeatureFlagModule 2021-06-30 16:49:01 -03:00
Torsten Grote
793d81bd93 Merge branch '2093-inconsistency-when-navigating-back-to-intro' into '1081-share-app-via-wifi-hotspot'
Don't move to HotspotFragment on rotate when user navigated back to introduction

See merge request briar/briar!1494
2021-06-30 15:16:33 +00:00
Torsten Grote
be637cef65 Merge branch '2091-supported-property' into '1802-sync-via-removable-storage'
Add a transport property to signal support for removable drives

See merge request briar/briar!1496
2021-06-30 14:53:15 +00:00
Sebastian Kürten
9370062e41 Don't move to HotspotFragment on rotate when user navigated back to introduction 2021-06-30 12:07:30 +02:00
akwizgran
8c1f721015 Add method for checking whether contact supports transport. 2021-06-28 16:51:30 +01:00
akwizgran
22ea4ced0d Add transport property to indicate support for removable drives. 2021-06-28 16:51:30 +01:00
Sebastian Kürten
312d31b40e Improve texts on offline hotspot for a better UX 2021-06-28 15:09:40 +02:00
Torsten Grote
b15d42b0cd Merge branch '2087-fix-issue-when-hotspot-activity-and-viewmodel-get-destroyed' into '1081-share-app-via-wifi-hotspot'
Fix bug that occurs when HotspotActivity gets destroyed

See merge request briar/briar!1489
2021-06-25 19:52:56 +00:00
Torsten Grote
9274b8ef4a Merge branch '2084-aborted-introduction-sessions' into '1802-sync-via-removable-storage'
Allow aborted introduction sessions to be retried

See merge request briar/briar!1490
2021-06-23 16:05:31 +00:00
Torsten Grote
7ef4ea51b3 Merge branch '2061-check-clock-sanity-at-startup' into '1802-sync-via-removable-storage'
Check whether system clock is reasonable at startup

See merge request briar/briar!1491
2021-06-23 15:59:52 +00:00
akwizgran
e285f21d1c Check whether system clock is reasonable at startup. 2021-06-23 16:40:42 +01:00
Sebastian Kürten
160cef25af Fix bug that occurs when HotspotActivity gets destroyed
If HotspotActivity gets destroyed, so will be its viewmodel, resulting
in an undefined state when the activity gets created again. While the
fragments will be restored, the view model and hotspot/webserver state
will not. Fix this by resetting the UI to reflect the reset of hotspot
and webserver.
2021-06-23 17:23:59 +02:00
akwizgran
c0293a1327 Merge branch '2070-transport-key-agreement-validator-test' into '1802-sync-via-removable-storage'
Add unit test for transport key agreement validator

See merge request briar/briar!1488
2021-06-23 10:16:52 +00:00
Torsten Grote
035c639aa0 Add TransportKeyAgreementValidatorTest 2021-06-22 17:20:47 -03:00
Torsten Grote
29d31e79c3 Merge branch '2086-fix-margin-on-qr-cardview' into '1081-share-app-via-wifi-hotspot'
Fix background color of cardview for qr code

See merge request briar/briar!1487
2021-06-22 11:49:58 +00:00
Sebastian Kürten
7f7210becd Fix background color of cardview for qr code 2021-06-22 09:46:34 +02:00
akwizgran
ce74fcaab5 Store ID of message that triggered abort. 2021-06-21 16:22:51 +01:00
akwizgran
00407539d3 Bump version numbers for 1.3.5 release. 2021-06-18 11:17:35 +01:00
akwizgran
62014f4d01 Update translations. 2021-06-18 11:16:33 +01:00
akwizgran
e7dddda7e5 Merge branch 'tor-0.3.5.15' into 'master'
Upgrade Tor to 0.3.5.15

Closes #2075

See merge request briar/briar!1483
2021-06-17 12:21:01 +00:00
akwizgran
208ff6f3a5 Merge branch '2056-view-pager-crash' into 'master'
Migrate to ViewPager2 to fix weird ViewPager crash

Closes #2056

See merge request briar/briar!1484
2021-06-17 12:07:04 +00:00
akwizgran
4d31465191 Merge branch 'master' into 'tor-0.3.5.15'
# Conflicts:
#   bramble-java/build.gradle
2021-06-17 12:05:34 +00:00
Torsten Grote
cf987427e0 Migrate to ViewPager2 to fix weird ViewPager crash 2021-06-16 12:44:04 -03:00
akwizgran
b11b959fd3 Merge branch 'upgrade-libraries-1.3' into 'master'
Upgrade libraries after 1.3 release

See merge request briar/briar!1455
2021-06-16 13:52:04 +00:00
Torsten Grote
61f660ca1d Upgrade libraries before 1.3 release 2021-06-16 10:40:30 -03:00
akwizgran
6d44521016 Upgrade Tor to 0.3.5.15. 2021-06-16 11:16:10 +01:00
Torsten Grote
a5a1cdfabb Merge branch '2039-implement-hotspot-error-fragment' into '1081-share-app-via-wifi-hotspot'
Resolve "Implement HotspotErrorFragment"

See merge request briar/briar!1469
2021-06-14 20:23:18 +00:00
Sebastian Kürten
bfcb469d49 Use FragmentContainerView for displaying FallbackFragment 2021-06-14 17:14:50 +02:00
Sebastian Kürten
f8b645d2b1 Improve hotspot error fragment UI
* Use different highlighting for error message
* Improve margins in fragment_hotspot_save_apk.xml
* Address some review feedback
2021-06-14 17:14:35 +02:00
Sebastian Kürten
052eb03c9e Pass error message to feedback activity 2021-06-14 17:13:14 +02:00
Sebastian Kürten
83bf3f4ca7 Create FallbackFragment for alternative apk sharing method 2021-06-14 17:12:02 +02:00
Sebastian Kürten
f9181fa021 Log hotspot errors 2021-06-14 17:10:52 +02:00
Sebastian Kürten
79dae27c24 Wire feedback button to show feedback fragment 2021-06-14 17:10:46 +02:00
akwizgran
7289f5ba8a Merge branch '2059-no-such-group-exception' into 'master'
Check if group still exists before storing MessageId of thread position

Closes #2059

See merge request briar/briar!1477
2021-06-14 14:57:21 +00:00
Torsten Grote
b657c7f347 Ignore NoSuchGroupException when storing MessageId of thread position for removed group 2021-06-10 15:45:31 -03:00
Sebastian Kürten
8ef21637a9 Outline specific error fragment for hotspot 2021-06-09 18:53:59 +02:00
Sebastian Kürten
e3a1fca22e Let HotspotActivity implement BaseFragmentListener 2021-06-09 18:53:54 +02:00
Torsten Grote
ea9a2789ab Move hotspot help ActivityResultLauncher into method 2021-06-09 17:48:17 +02:00
Torsten Grote
cbdbd10cb3 Adapt hotspot buttons to latest design and add a nullability annotation 2021-06-09 17:48:17 +02:00
Torsten Grote
d6f985174a Make HotspotHelpFragment headlines bold 2021-06-09 17:48:17 +02:00
Torsten Grote
d184fbd3fe Handle returned Uri being null 2021-06-09 17:48:17 +02:00
Torsten Grote
ef623370b6 Save the APK as a hotspot fallback 2021-06-09 17:48:17 +02:00
Sebastian Kürten
5ac636d52d Add feature flag for sharing the app via offline hotspot 2021-06-09 17:48:17 +02:00
Sebastian Kürten
f1c71ec5a7 Recommend to undo settings to install apps from unknown sources 2021-06-09 17:48:16 +02:00
Torsten Grote
5cc280be61 Add missing hotspot nullability annotations 2021-06-09 17:48:16 +02:00
Torsten Grote
a5d8faef3c Move savedNetworkConfig into HotspotManager and use constructor injection 2021-06-09 17:48:16 +02:00
Torsten Grote
e22e9dcade Make hotspot SSID and passphrase persistent 2021-06-09 17:48:16 +02:00
Sebastian Kürten
7474ad8606 Use better filename for apk files shared via hotspot 2021-06-09 17:48:16 +02:00
Torsten Grote
1c3d90f7fc Show a snackbar when a peer connected to the hotspot 2021-06-09 17:48:16 +02:00
Torsten Grote
6f8d7167db Don't start hotspot while running and use proper ErrorFragment 2021-06-09 17:48:16 +02:00
Torsten Grote
99da50d37c Port code from Offline hotspot test app 2021-06-09 17:48:15 +02:00
Torsten Grote
15f5c8deee Fix hotspot notification on old APIs 2021-06-09 17:48:15 +02:00
Torsten Grote
7913cd322e Rename tab fragments
and remove redundant NonNull annotations
2021-06-09 17:48:15 +02:00
Torsten Grote
de8ad8f6f9 Show notification while hotspot is active 2021-06-09 17:48:15 +02:00
Torsten Grote
d0bc17e634 Add hotspot troubleshooting info 2021-06-09 17:48:15 +02:00
Torsten Grote
85433611a5 Add offline sharing entry point to Settings/Actions 2021-06-09 17:48:15 +02:00
Torsten Grote
ebd5879761 Let info screens scroll in case of insufficient space 2021-06-09 17:48:15 +02:00
Torsten Grote
b255ab07ae Implement info screens for offline app sharing 2021-06-09 17:48:14 +02:00
Torsten Grote
a86ba50dec Implement intro screen for offline app sharing 2021-06-09 17:48:09 +02:00
Torsten Grote
40865425c5 Merge branch 'fix-padding-of-contact-exchange-error' into 'master'
Fix missing padding for title in contact exchange error fragment

See merge request briar/briar!1478
2021-06-09 11:56:57 +00:00
Sebastian Kürten
f7249f5e84 Fix missing padding for title in contact exchange error fragment 2021-06-09 13:45:32 +02:00
Torsten Grote
cc04fb05c2 Merge branch '1971-tor-0.3.5.14' into 'master'
Upgrade Tor to 0.3.5.14

Closes #1971

See merge request briar/briar!1470
2021-05-31 12:02:58 +00:00
akwizgran
58eb1d9e24 Upgrade Tor to 0.3.5.14. 2021-05-28 11:45:21 +01:00
akwizgran
76b7e6fecf Bump version numbers for 1.3.4 release. 2021-05-19 10:47:08 +01:00
akwizgran
980940a7cf Update translations. 2021-05-19 10:46:21 +01:00
akwizgran
9a021daae8 Merge branch '2043-blog-scrolling' into 'master'
Automatically scroll to our own blog posts

Closes #2043

See merge request briar/briar!1462
2021-05-19 09:35:10 +00:00
Torsten Grote
cc9904a454 Automatically scroll to our own blog posts 2021-05-18 15:39:22 -03:00
Torsten Grote
b0faab9395 Merge branch 'remove-failed-bridges' into 'master'
Remove three failed bridges

See merge request briar/briar!1460
2021-05-17 17:37:58 +00:00
akwizgran
f1198b47fd Remove three failed bridges. 2021-05-17 16:36:00 +01:00
akwizgran
37f2ab555f Update translations. 2021-05-17 16:26:22 +01:00
akwizgran
61ca2a391b Merge branch 'create-testdata-zero-values' into 'master'
Add button to zero values when creating test data

See merge request briar/briar!1447
2021-05-10 12:05:26 +00:00
akwizgran
88537b9323 Merge branch '2032-connect-via-bt-crash' into 'master'
Remove duplicate code due to merge mistake

Closes #2032

See merge request briar/briar!1456
2021-05-10 11:55:38 +00:00
Daniel Lublin
e6c004e8f6 Add button to zero values when creating test data 2021-05-10 13:46:49 +02:00
akwizgran
dc7290dab7 Remove duplicate code due to merge mistake. 2021-05-10 12:29:28 +01:00
akwizgran
9dff8bd64a Merge branch '2005-connect-via-bt-error' into 'master'
Connect via Bluetooth: Wait before showing an error Toast

See merge request briar/briar!1446
2021-05-06 13:14:32 +00:00
akwizgran
35c2f60129 Merge branch 'master' into '2005-connect-via-bt-error'
# Conflicts:
#   briar-android/src/main/java/org/briarproject/briar/android/conversation/BluetoothConnecter.java
2021-05-06 13:03:46 +00:00
akwizgran
471a2372c8 Merge branch '2027-pause-polling-when-doing-connect-via-bt' into 'master'
Disable polling while doing connect-via-BT

Closes #2027

See merge request briar/briar!1450
2021-05-06 12:59:38 +00:00
Daniel Lublin
fba028db03 Disable polling while doing connect-via-BT 2021-05-06 11:13:35 +02:00
Torsten Grote
c647c52638 Merge branch '2009-xiaomi-setup-screen' into 'master'
Show instructions for locking Briar to the Xiaomi recent apps list

Closes #2009

See merge request briar/briar!1451
2021-05-05 16:39:55 +00:00
akwizgran
cad5edcf86 Move input state methods to UiUtils. 2021-05-05 16:57:25 +01:00
akwizgran
38f70bb6be Add full stop. 2021-05-05 13:02:56 +01:00
akwizgran
33bdc81b3e Show instructions for locking Briar to the Xiaomi recent apps list. 2021-05-05 12:37:23 +01:00
Torsten Grote
552b9ef21a Wait for an incoming connection before showing an error Toast 2021-04-30 16:01:54 -03:00
239 changed files with 7501 additions and 1392 deletions

View File

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

View File

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

View File

@@ -75,7 +75,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -4,6 +4,7 @@ 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;
@@ -21,8 +22,9 @@ class AndroidRemovableDrivePlugin extends RemovableDrivePlugin {
private final Application app;
AndroidRemovableDrivePlugin(Application app, int maxLatency) {
super(maxLatency);
AndroidRemovableDrivePlugin(Application app, PluginCallback callback,
long maxLatency) {
super(callback, maxLatency);
this.app = app;
}

View File

@@ -35,13 +35,13 @@ public class AndroidRemovableDrivePluginFactory implements
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}
@Nullable
@Override
public SimplexPlugin createPlugin(PluginCallback callback) {
return new AndroidRemovableDrivePlugin(app, MAX_LATENCY);
return new AndroidRemovableDrivePlugin(app, callback, MAX_LATENCY);
}
}

View File

@@ -67,7 +67,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
Application app,
Backoff backoff,
PluginCallback callback,
int maxLatency,
long maxLatency,
int maxIdleTime,
int connectionTimeout) {
super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency,

View File

@@ -55,7 +55,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -68,7 +68,7 @@ class AndroidTorPlugin extends TorPlugin {
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback,
String architecture,
int maxLatency,
long maxLatency,
int maxIdleTime,
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,

View File

@@ -94,7 +94,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -10,17 +10,20 @@ import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Scanner;
import javax.annotation.Nullable;
import static android.content.Context.MODE_PRIVATE;
import static android.os.Build.VERSION.SDK_INT;
import static java.lang.Runtime.getRuntime;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
@@ -118,4 +121,17 @@ public class AndroidUtils {
public static String[] getSupportedImageContentTypes() {
return new String[] {"image/jpeg", "image/png", "image/gif"};
}
@Nullable
public static String getSystemProperty(String propName) {
try {
Process p = getRuntime().exec("getprop " + propName);
Scanner s = new Scanner(p.getInputStream());
String line = s.nextLine();
s.close();
return line;
} catch (SecurityException | IOException e) {
return null;
}
}
}

View File

@@ -1,42 +1,43 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.android.tools.analytics-library:protos:27.1.3:protos-27.1.3.jar:0d9e6cff60b318baac250b6f5bb076a8161103338bf2749cdf1db8a5a13a1f12',
'com.android.tools.analytics-library:shared:27.1.3:shared-27.1.3.jar:10d2a51d8f89ff4ac849888e5a9c60b10e879c30d78545ec1da4d3df7bd56ae4',
'com.android.tools.analytics-library:tracker:27.1.3:tracker-27.1.3.jar:589b355a2ba796cbc0a2b2295737de6661f078262e5f87cd6f540b8d011e5ebb',
'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:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
'com.android.tools.build:apksig:4.1.3:apksig-4.1.3.jar:a851980c678ff7a6785388b9a9e8cc094788ce3c4a985ad2b19c2028fd3c631a',
'com.android.tools.build:apkzlib:4.1.3:apkzlib-4.1.3.jar:475903065e7e83a8c1ba78d267c97a54dc5a04d768b535093850423d7b11f2c8',
'com.android.tools.build:builder-model:4.1.3:builder-model-4.1.3.jar:2624a1436c3ab39dd91d3ecf9409a594b0f89ea5cab255f2e9ff11f5ee03d274',
'com.android.tools.build:builder-test-api:4.1.3:builder-test-api-4.1.3.jar:3d2af66726b06b53b8d6d497efcee39ff9f77eb2f8d2cce38b31502383a40d2c',
'com.android.tools.build:builder:4.1.3:builder-4.1.3.jar:a40426cd6d68f6a722ef4950058c075e4547025e8c2fd78e732ad89f15176f84',
'com.android.tools.build:gradle-api:4.1.3:gradle-api-4.1.3.jar:11b1fb9de658bdcf9290b1c1517060d0c4d93f2b27975934989ca4ac890bc077',
'com.android.tools.build:manifest-merger:27.1.3:manifest-merger-27.1.3.jar:ce8d4009b1f1584777a7ffa1da3b0551dc316bc8e08112e442c352af70f46f2d',
'com.android.tools.ddms:ddmlib:27.1.3:ddmlib-27.1.3.jar:8f76e8236d2b9eebf26378746dad025c4c7c056a02e133dae4ddef47b283c710',
'com.android.tools.external.com-intellij:intellij-core:27.1.3:intellij-core-27.1.3.jar:652814fa099b4746fb6f10e19718e476952e8b5bac24e17d914f90650ad21808',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.3:kotlin-compiler-27.1.3.jar:8d7a78d5efd213c5e467e42bd205582aad73ffc77ee5dc18eb1361c9af72f125',
'com.android.tools.external.org-jetbrains:uast:27.1.3:uast-27.1.3.jar:aea53944a1ac6a05f12297b55290e8cbecfe54c4166260cfba4405823bfe1c78',
'com.android.tools.layoutlib:layoutlib-api:27.1.3:layoutlib-api-27.1.3.jar:23875ce0a8429f33a4e86cc358f658faa0ba9c576f5f05760e544b453d67d04b',
'com.android.tools.lint:lint-api:27.1.3:lint-api-27.1.3.jar:97666be32bcadacd944416ea334a9575ef8f4ad0c8f333151491ff4a7df43e1c',
'com.android.tools.lint:lint-checks:27.1.3:lint-checks-27.1.3.jar:b2d71ae84a31490fe9ff26c706163fe245b2aea98e3eb747214c1085df444708',
'com.android.tools.lint:lint-gradle-api:27.1.3:lint-gradle-api-27.1.3.jar:e54131c287a2954e6ed78a3351e5e10e35a1da2f09ac443bf44b705c71b63a4d',
'com.android.tools.lint:lint-gradle:27.1.3:lint-gradle-27.1.3.jar:6a79e48943649d63665db7b17dbaff7af93e94ab9b15072f1a4d90486294ee9f',
'com.android.tools.lint:lint-model:27.1.3:lint-model-27.1.3.jar:acb9e792db7000e38e3c3ca21a9b14f2de6549d7a3fc92a97ffba3d06345e5bf',
'com.android.tools.lint:lint:27.1.3:lint-27.1.3.jar:5a2e69d0901a3a476a5b2d5001de755868113145f5f6aa557750cfad5389a44b',
'com.android.tools:annotations:27.1.3:annotations-27.1.3.jar:904dd771883496d5dfc86619ab2555968ea4e8a29d7a5f4f7cae6fbf5429f8f5',
'com.android.tools:common:27.1.3:common-27.1.3.jar:17ab4728e3ea50f047dd5937f0faf35f2c5416962ed74891057087ddc328bf96',
'com.android.tools:dvlib:27.1.3:dvlib-27.1.3.jar:cead1c0c356cbe43e6855b0330fe09ef4bec2c72e22bdb4c6e7cf7e6b1dfbc37',
'com.android.tools:repository:27.1.3:repository-27.1.3.jar:99de1a178855b56b8cd91a56296f1e0a9399c445e6acc51f1d2927947cc472cb',
'com.android.tools:sdk-common:27.1.3:sdk-common-27.1.3.jar:b591e2aa0f1be600795f5c9e2bf81cba9b052bee452fc86c3362b5dd9e427a14',
'com.android.tools:sdklib:27.1.3:sdklib-27.1.3.jar:ad6c08a45fe2904d05656bdddf9f623fa5c1d16bbd7b8d6a270a0734136ae02e',
'com.android:signflinger:4.1.3:signflinger-4.1.3.jar:f3103b55ccdc8dd9ee2517eb26af93b904d41303726594372d0df59d51156e5c',
'com.android:zipflinger:4.1.3:zipflinger-4.1.3.jar:48569896c0497268308a8014c66eb0f2bace2b9e2fc9390f3012823fb86387d5',
'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.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'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.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',
@@ -50,7 +51,7 @@ dependencyVerification {
'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.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
@@ -62,21 +63,21 @@ dependencyVerification {
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'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.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'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.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'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: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: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:tor-android:0.3.5.13:tor-android-0.3.5.13.zip:e0978db136731dae07774b722970cdae1e462fb5adc82845dd80a7e2d87f356c',
'org.briarproject:tor-android:0.3.5.15:tor-android-0.3.5.15.jar:560c5070166300b396cb2f28d82d9f639ee1fb5479096a3cef67da56d39937ad',
'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.8.1:checker-qual-2.8.1.jar:9103499008bcecd4e948da29b17864abb64304e15706444ae209d17ebe0575df',
@@ -85,26 +86,31 @@ dependencyVerification {
'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
'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-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'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.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'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-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: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.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
]
}

View File

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

View File

@@ -12,4 +12,8 @@ public interface FeatureFlags {
boolean shouldEnableDisappearingMessages();
boolean shouldEnableConnectViaBluetooth();
boolean shouldEnableShareAppViaOfflineHotspot();
boolean shouldEnableTransferData();
}

View File

@@ -1,23 +1,19 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
/**
* A secret key used for encryption and/or authentication.
*/
public class SecretKey {
public class SecretKey extends Bytes {
/**
* The length of a secret key in bytes.
*/
public static final int LENGTH = 32;
private final byte[] key;
public SecretKey(byte[] key) {
super(key);
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.
*/
void addTransport(Transaction txn, TransportId t, int maxLatency)
void addTransport(Transaction txn, TransportId t, long maxLatency)
throws DbException;
/**
@@ -128,7 +128,7 @@ public interface DatabaseComponent extends TransactionManager {
* should be included
*/
boolean containsAnythingToSend(Transaction txn, ContactId c,
int maxLatency, boolean eager) throws DbException;
long maxLatency, boolean eager) throws DbException;
/**
* Returns true if the database contains the given contact for the given
@@ -200,7 +200,7 @@ public interface DatabaseComponent extends TransactionManager {
*/
@Nullable
Collection<Message> generateBatch(Transaction txn, ContactId c,
int maxLength, int maxLatency) throws DbException;
int maxLength, long maxLatency) throws DbException;
/**
* Returns a batch of messages for the given contact containing the
@@ -212,7 +212,7 @@ public interface DatabaseComponent extends TransactionManager {
* exception.
*/
Collection<Message> generateBatch(Transaction txn, ContactId c,
Collection<MessageId> ids, int maxLatency) throws DbException;
Collection<MessageId> ids, long maxLatency) throws DbException;
/**
* Returns an offer for the given contact for transmission over a
@@ -221,7 +221,7 @@ public interface DatabaseComponent extends TransactionManager {
*/
@Nullable
Offer generateOffer(Transaction txn, ContactId c, int maxMessages,
int maxLatency) throws DbException;
long maxLatency) throws DbException;
/**
* Returns a request for the given contact, or null if there are no
@@ -240,7 +240,7 @@ public interface DatabaseComponent extends TransactionManager {
*/
@Nullable
Collection<Message> generateRequestedBatch(Transaction txn, ContactId c,
int maxLength, int maxLatency) throws DbException;
int maxLength, long maxLatency) throws DbException;
/**
* Returns the contact with the given ID.

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.keyagreement.event;
import org.briarproject.bramble.api.event.Event;
/**
* An event that is broadcast when a BQP protocol completes.
* An event that is broadcast when a BQP protocol begins.
*/
public class KeyAgreementStartedEvent extends Event {
}

View File

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

View File

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

View File

@@ -0,0 +1,25 @@
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

@@ -15,7 +15,7 @@ public interface TransportConnectionWriter {
/**
* Returns the maximum latency of the transport in milliseconds.
*/
int getMaxLatency();
long getMaxLatency();
/**
* Returns the maximum idle time of the transport in milliseconds.

View File

@@ -70,7 +70,7 @@ public abstract class AbstractDuplexTransportConnection
private class Writer implements TransportConnectionWriter {
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return plugin.getMaxLatency();
}

View File

@@ -1,30 +1,11 @@
package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
import org.briarproject.bramble.api.plugin.PluginFactory;
/**
* Factory for creating a plugin for a duplex transport.
*/
@NotNullByDefault
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);
public interface DuplexPluginFactory extends PluginFactory<DuplexPlugin> {
}

View File

@@ -8,4 +8,5 @@ public interface RemovableDriveConstants {
String PROP_PATH = "path";
String PROP_URI = "uri";
String PROP_SUPPORTED = "supported";
}

View File

@@ -39,6 +39,12 @@ public interface RemovableDriveManager {
*/
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.
*/

View File

@@ -1,30 +1,11 @@
package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
import org.briarproject.bramble.api.plugin.PluginFactory;
/**
* Factory for creating a plugin for a simplex transport.
*/
@NotNullByDefault
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);
public interface SimplexPluginFactory extends PluginFactory<SimplexPlugin> {
}

View File

@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.UniqueId;
import java.util.List;
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;
public interface SyncConstants {
@@ -55,4 +56,9 @@ public interface SyncConstants {
* connections.
*/
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);
SyncSession createSimplexOutgoingSession(ContactId c, TransportId t,
int maxLatency, boolean eager, StreamWriter streamWriter);
long maxLatency, boolean eager, StreamWriter streamWriter);
SyncSession createDuplexOutgoingSession(ContactId c, TransportId t,
int maxLatency, int maxIdleTime, StreamWriter streamWriter,
long maxLatency, int maxIdleTime, StreamWriter streamWriter,
@Nullable Priority priority);
}

View File

@@ -6,6 +6,22 @@ package org.briarproject.bramble.api.system;
*/
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()
*/

View File

@@ -163,10 +163,15 @@ public class TestUtils {
public static Message getMessage(GroupId groupId) {
int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH);
return getMessage(groupId, bodyLength);
return getMessage(groupId, bodyLength, timestamp);
}
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());
byte[] body = getRandomBytes(bodyLength);
return new Message(id, groupId, timestamp, body);

View File

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

View File

@@ -17,16 +17,17 @@ dependencies {
implementation 'org.whispersystems:curve25519-java:0.5.0'
implementation 'org.briarproject:jtorctl:0.3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation 'net.jodah:concurrentunit:0.4.2'
testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-legacy:$jmock_version"
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24'
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
}

View File

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

View File

@@ -47,6 +47,7 @@ import javax.inject.Inject;
import static java.util.logging.Logger.getLogger;
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.ContactExchangeRecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.util.ValidationUtils.checkLength;
@@ -184,6 +185,10 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
// The agreed timestamp is the minimum of the peers' timestamps
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
Contact contact = addContact(p, remoteInfo.author, localAuthor,

View File

@@ -145,7 +145,7 @@ interface Database<T> {
/**
* Stores a transport.
*/
void addTransport(T txn, TransportId t, int maxLatency)
void addTransport(T txn, TransportId t, long maxLatency)
throws DbException;
/**
@@ -171,7 +171,7 @@ interface Database<T> {
* @param eager True if messages that are not yet due for retransmission
* should be included
*/
boolean containsAnythingToSend(T txn, ContactId c, int maxLatency,
boolean containsAnythingToSend(T txn, ContactId c, long maxLatency,
boolean eager) throws DbException;
/**
@@ -483,7 +483,7 @@ interface Database<T> {
* Read-only.
*/
Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
int maxMessages, int maxLatency) throws DbException;
int maxMessages, long maxLatency) throws DbException;
/**
* Returns the IDs of some messages that are eligible to be requested from
@@ -505,13 +505,13 @@ interface Database<T> {
* Read-only.
*/
Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength,
int maxLatency) throws DbException;
long 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, int)} this
* 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/>
@@ -604,7 +604,7 @@ interface Database<T> {
* Read-only.
*/
Collection<MessageId> getRequestedMessagesToSend(T txn, ContactId c,
int maxLength, int maxLatency) throws DbException;
int maxLength, long maxLatency) throws DbException;
/**
* Returns all settings in the given namespace.
@@ -845,7 +845,7 @@ interface Database<T> {
* of the given message with respect to the given contact, using the latency
* of the transport over which it was sent.
*/
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, int maxLatency)
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, long maxLatency)
throws DbException;
/**

View File

@@ -310,7 +310,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override
public void addTransport(Transaction transaction, TransportId t,
int maxLatency) throws DbException {
long maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsTransport(txn, t))
@@ -343,7 +343,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override
public boolean containsAnythingToSend(Transaction transaction, ContactId c,
int maxLatency, boolean eager) throws DbException {
long maxLatency, boolean eager) throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
@@ -424,7 +424,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable
@Override
public Collection<Message> generateBatch(Transaction transaction,
ContactId c, int maxLength, int maxLatency) throws DbException {
ContactId c, int maxLength, long maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
@@ -447,7 +447,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override
public Collection<Message> generateBatch(Transaction transaction,
ContactId c, Collection<MessageId> ids, int maxLatency)
ContactId c, Collection<MessageId> ids, long maxLatency)
throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
@@ -474,7 +474,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable
@Override
public Offer generateOffer(Transaction transaction, ContactId c,
int maxMessages, int maxLatency) throws DbException {
int maxMessages, long maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
@@ -505,7 +505,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Nullable
@Override
public Collection<Message> generateRequestedBatch(Transaction transaction,
ContactId c, int maxLength, int maxLatency) throws DbException {
ContactId c, int maxLength, long maxLatency) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))

View File

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

View File

@@ -102,7 +102,7 @@ import static org.briarproject.bramble.util.LogUtils.now;
abstract class JdbcDatabase implements Database<Connection> {
// Package access for testing
static final int CODE_SCHEMA_VERSION = 48;
static final int CODE_SCHEMA_VERSION = 49;
// Time period offsets for incoming transport keys
private static final int OFFSET_PREV = -1;
@@ -267,7 +267,7 @@ abstract class JdbcDatabase implements Database<Connection> {
private static final String CREATE_TRANSPORTS =
"CREATE TABLE transports"
+ " (transportId _STRING NOT NULL,"
+ " maxLatency INT NOT NULL,"
+ " maxLatency BIGINT NOT NULL,"
+ " PRIMARY KEY (transportId))";
private static final String CREATE_PENDING_CONTACTS =
@@ -498,7 +498,8 @@ abstract class JdbcDatabase implements Database<Connection> {
new Migration44_45(),
new Migration45_46(),
new Migration46_47(dbTypes),
new Migration47_48()
new Migration47_48(),
new Migration48_49()
);
}
@@ -1006,7 +1007,7 @@ abstract class JdbcDatabase implements Database<Connection> {
}
@Override
public void addTransport(Connection txn, TransportId t, int maxLatency)
public void addTransport(Connection txn, TransportId t, long maxLatency)
throws DbException {
PreparedStatement ps = null;
try {
@@ -1129,7 +1130,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override
public boolean containsAnythingToSend(Connection txn, ContactId c,
int maxLatency, boolean eager) throws DbException {
long maxLatency, boolean eager) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {
@@ -2188,7 +2189,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override
public Collection<MessageId> getMessagesToOffer(Connection txn,
ContactId c, int maxMessages, int maxLatency) throws DbException {
ContactId c, int maxMessages, long maxLatency) throws DbException {
long now = clock.currentTimeMillis();
long eta = now + maxLatency;
PreparedStatement ps = null;
@@ -2247,7 +2248,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override
public Collection<MessageId> getMessagesToSend(Connection txn, ContactId c,
int maxLength, int maxLatency) throws DbException {
int maxLength, long maxLatency) throws DbException {
long now = clock.currentTimeMillis();
long eta = now + maxLatency;
PreparedStatement ps = null;
@@ -2546,7 +2547,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override
public Collection<MessageId> getRequestedMessagesToSend(Connection txn,
ContactId c, int maxLength, int maxLatency) throws DbException {
ContactId c, int maxLength, long maxLatency) throws DbException {
long now = clock.currentTimeMillis();
long eta = now + maxLatency;
PreparedStatement ps = null;
@@ -3617,7 +3618,7 @@ abstract class JdbcDatabase implements Database<Connection> {
@Override
public void updateExpiryTimeAndEta(Connection txn, ContactId c, MessageId m,
int maxLatency) throws DbException {
long maxLatency) throws DbException {
PreparedStatement ps = null;
ResultSet rs = null;
try {

View File

@@ -0,0 +1,41 @@
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,6 +12,7 @@ import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -34,11 +35,14 @@ 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.STOPPING;
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_OLD_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.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.logException;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -52,6 +56,7 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private final DatabaseComponent db;
private final EventBus eventBus;
private final Clock clock;
private final List<Service> services;
private final List<OpenDatabaseHook> openDatabaseHooks;
private final List<ExecutorService> executors;
@@ -63,9 +68,11 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
private volatile LifecycleState state = STARTING;
@Inject
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus) {
LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus,
Clock clock) {
this.db = db;
this.eventBus = eventBus;
this.clock = clock;
services = new CopyOnWriteArrayList<>();
openDatabaseHooks = new CopyOnWriteArrayList<>();
executors = new CopyOnWriteArrayList<>();
@@ -99,6 +106,13 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
LOG.info("Already starting or stopping");
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 {
LOG.info("Opening database");
long start = now();

View File

@@ -79,7 +79,8 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
private final SecureRandom secureRandom;
private final Backoff backoff;
private final PluginCallback callback;
private final int maxLatency, maxIdleTime;
private final long maxLatency;
private final int maxIdleTime;
private final AtomicBoolean used = new AtomicBoolean(false);
private final AtomicBoolean everConnected = new AtomicBoolean(false);
@@ -121,7 +122,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
SecureRandom secureRandom,
Backoff backoff,
PluginCallback callback,
int maxLatency,
long maxLatency,
int maxIdleTime) {
this.connectionLimiter = connectionLimiter;
this.connectionFactory = connectionFactory;
@@ -158,7 +159,7 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return maxLatency;
}
@@ -473,6 +474,16 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
return discoverSemaphore.availablePermits() == 0;
}
@Override
public void disablePolling() {
connectionLimiter.startLimiting();
}
@Override
public void enablePolling() {
connectionLimiter.endLimiting();
}
@Override
public DuplexTransportConnection discoverAndConnectForSetup(String uuid) {
DuplexTransportConnection conn = discoverAndConnect(uuid);
@@ -501,9 +512,9 @@ abstract class AbstractBluetoothPlugin<S, SS> implements BluetoothPlugin,
if (s.getNamespace().equals(ID.getString()))
ioExecutor.execute(() -> onSettingsUpdated(s.getSettings()));
} else if (e instanceof KeyAgreementListeningEvent) {
ioExecutor.execute(connectionLimiter::keyAgreementStarted);
connectionLimiter.startLimiting();
} else if (e instanceof KeyAgreementStoppedListeningEvent) {
ioExecutor.execute(connectionLimiter::keyAgreementEnded);
connectionLimiter.endLimiting();
} else if (e instanceof RemoteTransportPropertiesUpdatedEvent) {
RemoteTransportPropertiesUpdatedEvent r =
(RemoteTransportPropertiesUpdatedEvent) e;

View File

@@ -7,14 +7,15 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
interface BluetoothConnectionLimiter {
/**
* Informs the limiter that key agreement has started.
* Tells the limiter to not allow regular polling connections (because we
* are about to do key agreement, or connect via BT for setup).
*/
void keyAgreementStarted();
void startLimiting();
/**
* Informs the limiter that key agreement has ended.
* Tells the limiter to no longer limit regular polling connections.
*/
void keyAgreementEnded();
void endLimiting();
/**
* Returns true if a contact connection can be opened. This method does not

View File

@@ -30,34 +30,37 @@ class BluetoothConnectionLimiterImpl implements BluetoothConnectionLimiter {
private final List<DuplexTransportConnection> connections =
new LinkedList<>();
@GuardedBy("lock")
private boolean keyAgreementInProgress = false;
private int limitingInProgress = 0;
BluetoothConnectionLimiterImpl(EventBus eventBus) {
this.eventBus = eventBus;
}
@Override
public void keyAgreementStarted() {
public void startLimiting() {
synchronized (lock) {
keyAgreementInProgress = true;
limitingInProgress++;
}
LOG.info("Key agreement started");
LOG.info("Limiting started");
eventBus.broadcast(new CloseSyncConnectionsEvent(ID));
}
@Override
public void keyAgreementEnded() {
public void endLimiting() {
synchronized (lock) {
keyAgreementInProgress = false;
limitingInProgress--;
if (limitingInProgress < 0) {
throw new IllegalStateException();
}
}
LOG.info("Key agreement ended");
LOG.info("Limiting ended");
}
@Override
public boolean canOpenContactConnection() {
synchronized (lock) {
if (keyAgreementInProgress) {
LOG.info("Can't open contact connection during key agreement");
if (limitingInProgress > 0) {
LOG.info("Can't open contact connection while limiting");
return false;
} else {
LOG.info("Can open contact connection");

View File

@@ -11,6 +11,10 @@ public interface BluetoothPlugin extends DuplexPlugin {
boolean isDiscovering();
void disablePolling();
void enablePolling();
@Nullable
DuplexTransportConnection discoverAndConnectForSetup(String uuid);

View File

@@ -3,6 +3,7 @@ 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;
@@ -17,10 +18,12 @@ 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
@@ -30,7 +33,8 @@ abstract class AbstractRemovableDrivePlugin implements SimplexPlugin {
private static final Logger LOG =
getLogger(AbstractRemovableDrivePlugin.class.getName());
private final int maxLatency;
private final long maxLatency;
private final PluginCallback callback;
abstract InputStream openInputStream(TransportProperties p)
throws IOException;
@@ -38,7 +42,8 @@ abstract class AbstractRemovableDrivePlugin implements SimplexPlugin {
abstract OutputStream openOutputStream(TransportProperties p)
throws IOException;
AbstractRemovableDrivePlugin(int maxLatency) {
AbstractRemovableDrivePlugin(PluginCallback callback, long maxLatency) {
this.callback = callback;
this.maxLatency = maxLatency;
}
@@ -48,7 +53,7 @@ abstract class AbstractRemovableDrivePlugin implements SimplexPlugin {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return maxLatency;
}
@@ -60,6 +65,8 @@ abstract class AbstractRemovableDrivePlugin implements SimplexPlugin {
@Override
public void start() {
callback.mergeLocalProperties(
new TransportProperties(singletonMap(PROP_SUPPORTED, "true")));
}
@Override

View File

@@ -27,20 +27,20 @@ abstract class FilePlugin implements SimplexPlugin {
getLogger(FilePlugin.class.getName());
protected final PluginCallback callback;
protected final int maxLatency;
protected final long maxLatency;
protected abstract void writerFinished(File f, boolean exception);
protected abstract void readerFinished(File f, boolean exception,
boolean recognised);
FilePlugin(PluginCallback callback, int maxLatency) {
FilePlugin(PluginCallback callback, long maxLatency) {
this.callback = callback;
this.maxLatency = maxLatency;
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return maxLatency;
}

View File

@@ -27,7 +27,7 @@ class FileTransportWriter implements TransportConnectionWriter {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return plugin.getMaxLatency();
}

View File

@@ -8,6 +8,8 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.file.RemovableDriveManager;
import org.briarproject.bramble.api.plugin.file.RemovableDriveTask;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.transport.KeyManager;
import java.util.concurrent.Executor;
@@ -16,6 +18,8 @@ import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
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.plugin.file.RemovableDrivePluginFactory.MAX_LATENCY;
@ThreadSafe
@@ -25,19 +29,29 @@ class RemovableDriveManagerImpl
private final Executor ioExecutor;
private final DatabaseComponent db;
private final KeyManager keyManager;
private final TransportPropertyManager transportPropertyManager;
private final RemovableDriveTaskFactory taskFactory;
private final Object lock = new Object();
@GuardedBy("lock")
@Nullable
private RemovableDriveTask reader = null;
@GuardedBy("lock")
@Nullable
private RemovableDriveTask writer = null;
@Inject
RemovableDriveManagerImpl(@IoExecutor Executor ioExecutor,
DatabaseComponent db, RemovableDriveTaskFactory taskFactory) {
RemovableDriveManagerImpl(
@IoExecutor Executor ioExecutor,
DatabaseComponent db,
KeyManager keyManager,
TransportPropertyManager transportPropertyManager,
RemovableDriveTaskFactory taskFactory) {
this.ioExecutor = ioExecutor;
this.db = db;
this.keyManager = keyManager;
this.transportPropertyManager = transportPropertyManager;
this.taskFactory = taskFactory;
}
@@ -80,6 +94,15 @@ class RemovableDriveManagerImpl
return created;
}
@Override
public boolean isTransportSupportedByContact(ContactId c)
throws DbException {
if (!keyManager.canSendOutgoingStreams(c, ID)) return false;
TransportProperties p =
transportPropertyManager.getRemoteProperties(c, ID);
return "true".equals(p.get(PROP_SUPPORTED));
}
@Override
public boolean isWriterTaskNeeded(ContactId c) throws DbException {
return db.transactionWithResult(true, txn ->

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.plugin.file;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.FileInputStream;
@@ -18,8 +19,8 @@ import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@NotNullByDefault
class RemovableDrivePlugin extends AbstractRemovableDrivePlugin {
RemovableDrivePlugin(int maxLatency) {
super(maxLatency);
RemovableDrivePlugin(PluginCallback callback, long maxLatency) {
super(callback, maxLatency);
}
@Override

View File

@@ -17,7 +17,7 @@ import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.I
@NotNullByDefault
public class RemovableDrivePluginFactory implements SimplexPluginFactory {
static final int MAX_LATENCY = (int) DAYS.toMillis(14);
static final long MAX_LATENCY = DAYS.toMillis(28);
@Inject
RemovableDrivePluginFactory() {
@@ -29,13 +29,13 @@ public class RemovableDrivePluginFactory implements SimplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}
@Nullable
@Override
public SimplexPlugin createPlugin(PluginCallback callback) {
return new RemovableDrivePlugin(MAX_LATENCY);
return new RemovableDrivePlugin(callback, MAX_LATENCY);
}
}

View File

@@ -63,8 +63,6 @@ abstract class RemovableDriveTaskImpl implements RemovableDriveTask {
synchronized (lock) {
observers.add(o);
state = this.state;
}
if (state.isFinished()) {
eventExecutor.execute(() -> o.accept(state));
}
}

View File

@@ -96,7 +96,7 @@ class RemovableDriveWriterTask extends RemovableDriveTaskImpl
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return delegate.getMaxLatency();
}

View File

@@ -26,7 +26,7 @@ class TransportOutputStreamWriter implements TransportConnectionWriter {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return plugin.getMaxLatency();
}

View File

@@ -92,7 +92,7 @@ class LanTcpPlugin extends TcpPlugin {
Executor wakefulIoExecutor,
Backoff backoff,
PluginCallback callback,
int maxLatency,
long maxLatency,
int maxIdleTime,
int connectionTimeout) {
super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency,

View File

@@ -50,7 +50,7 @@ public class LanTcpPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -69,8 +69,8 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
protected final Executor ioExecutor, wakefulIoExecutor, bindExecutor;
protected final Backoff backoff;
protected final PluginCallback callback;
protected final int maxLatency, maxIdleTime;
protected final int connectionTimeout, socketTimeout;
protected final long maxLatency;
protected final int maxIdleTime, connectionTimeout, socketTimeout;
protected final AtomicBoolean used = new AtomicBoolean(false);
protected final PluginState state = new PluginState();
@@ -111,7 +111,7 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
Executor wakefulIoExecutor,
Backoff backoff,
PluginCallback callback,
int maxLatency,
long maxLatency,
int maxIdleTime,
int connectionTimeout) {
this.ioExecutor = ioExecutor;
@@ -129,7 +129,7 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return maxLatency;
}

View File

@@ -35,7 +35,7 @@ class WanTcpPlugin extends TcpPlugin {
Backoff backoff,
PortMapper portMapper,
PluginCallback callback,
int maxLatency,
long maxLatency,
int maxIdleTime,
int connectionTimeout) {
super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency,

View File

@@ -54,7 +54,7 @@ public class WanTcpPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -131,7 +131,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final String architecture;
private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider;
private final int maxLatency, maxIdleTime, socketTimeout;
private final long maxLatency;
private final int maxIdleTime, socketTimeout;
private final File torDirectory, geoIpFile, configFile;
private final File doneFile, cookieFile;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -159,7 +160,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback,
String architecture,
int maxLatency,
long maxLatency,
int maxIdleTime,
File torDirectory) {
this.ioExecutor = ioExecutor;
@@ -204,7 +205,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return maxLatency;
}

View File

@@ -77,7 +77,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
private final Clock clock;
private final ContactId contactId;
private final TransportId transportId;
private final int maxLatency, maxIdleTime;
private final long maxLatency, maxIdleTime;
private final StreamWriter streamWriter;
private final SyncRecordWriter recordWriter;
@Nullable
@@ -95,7 +95,7 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
DuplexOutgoingSession(DatabaseComponent db, Executor dbExecutor,
EventBus eventBus, Clock clock, ContactId contactId,
TransportId transportId, int maxLatency, int maxIdleTime,
TransportId transportId, long maxLatency, int maxIdleTime,
StreamWriter streamWriter, SyncRecordWriter recordWriter,
@Nullable Priority priority) {
this.db = db;

View File

@@ -65,7 +65,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
private final EventBus eventBus;
private final ContactId contactId;
private final TransportId transportId;
private final int maxLatency;
private final long maxLatency;
private final boolean eager;
private final StreamWriter streamWriter;
private final SyncRecordWriter recordWriter;
@@ -76,7 +76,7 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
SimplexOutgoingSession(DatabaseComponent db, Executor dbExecutor,
EventBus eventBus, ContactId contactId, TransportId transportId,
int maxLatency, boolean eager, StreamWriter streamWriter,
long maxLatency, boolean eager, StreamWriter streamWriter,
SyncRecordWriter recordWriter) {
this.db = db;
this.dbExecutor = dbExecutor;

View File

@@ -60,7 +60,7 @@ class SyncSessionFactoryImpl implements SyncSessionFactory {
@Override
public SyncSession createSimplexOutgoingSession(ContactId c, TransportId t,
int maxLatency, boolean eager, StreamWriter streamWriter) {
long maxLatency, boolean eager, StreamWriter streamWriter) {
OutputStream out = streamWriter.getOutputStream();
SyncRecordWriter recordWriter =
recordWriterFactory.createRecordWriter(out);
@@ -70,7 +70,7 @@ class SyncSessionFactoryImpl implements SyncSessionFactory {
@Override
public SyncSession createDuplexOutgoingSession(ContactId c, TransportId t,
int maxLatency, int maxIdleTime, StreamWriter streamWriter,
long maxLatency, int maxIdleTime, StreamWriter streamWriter,
@Nullable Priority priority) {
OutputStream out = streamWriter.getOutputStream();
SyncRecordWriter recordWriter =

View File

@@ -19,9 +19,8 @@ import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.lifecycle.ServiceException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.PluginFactory;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.StreamContext;
@@ -40,6 +39,7 @@ import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_TRANSPORT_LATENCY;
@ThreadSafe
@NotNullByDefault
@@ -67,12 +67,12 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
this.pluginConfig = pluginConfig;
this.transportCrypto = transportCrypto;
managers = new ConcurrentHashMap<>();
for (SimplexPluginFactory f : pluginConfig.getSimplexFactories()) {
for (PluginFactory<?> f : pluginConfig.getSimplexFactories()) {
TransportKeyManager m = transportKeyManagerFactory.
createTransportKeyManager(f.getId(), f.getMaxLatency());
managers.put(f.getId(), m);
}
for (DuplexPluginFactory f : pluginConfig.getDuplexFactories()) {
for (PluginFactory<?> f : pluginConfig.getDuplexFactories()) {
TransportKeyManager m = transportKeyManagerFactory.
createTransportKeyManager(f.getId(), f.getMaxLatency());
managers.put(f.getId(), m);
@@ -84,15 +84,11 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
if (used.getAndSet(true)) throw new IllegalStateException();
try {
db.transaction(false, txn -> {
for (SimplexPluginFactory f :
pluginConfig.getSimplexFactories()) {
db.addTransport(txn, f.getId(), f.getMaxLatency());
managers.get(f.getId()).start(txn);
for (PluginFactory<?> f : pluginConfig.getSimplexFactories()) {
addTransport(txn, f);
}
for (DuplexPluginFactory f :
pluginConfig.getDuplexFactories()) {
db.addTransport(txn, f.getId(), f.getMaxLatency());
managers.get(f.getId()).start(txn);
for (PluginFactory<?> f : pluginConfig.getDuplexFactories()) {
addTransport(txn, f);
}
});
} catch (DbException e) {
@@ -100,6 +96,16 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
}
}
private void addTransport(Transaction txn, PluginFactory<?> f)
throws DbException {
long maxLatency = f.getMaxLatency();
if (maxLatency > MAX_TRANSPORT_LATENCY) {
throw new IllegalStateException();
}
db.addTransport(txn, f.getId(), maxLatency);
managers.get(f.getId()).start(txn);
}
@Override
public void stopService() {
}

View File

@@ -22,9 +22,8 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.PluginFactory;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
import org.briarproject.bramble.api.sync.GroupId;
@@ -110,11 +109,11 @@ class TransportKeyAgreementManagerImpl extends BdfIncomingMessageHook
this.sessionParser = sessionParser;
this.crypto = crypto;
transports = new ArrayList<>();
for (DuplexPluginFactory duplex : config.getDuplexFactories()) {
transports.add(duplex.getId());
for (PluginFactory<?> f : config.getDuplexFactories()) {
transports.add(f.getId());
}
for (SimplexPluginFactory simplex : config.getSimplexFactories()) {
transports.add(simplex.getId());
for (PluginFactory<?> f : config.getSimplexFactories()) {
transports.add(f.getId());
}
localGroup = contactGroupFactory.createLocalGroup(CLIENT_ID,
MAJOR_VERSION);

View File

@@ -19,6 +19,7 @@ import javax.annotation.concurrent.Immutable;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
import static org.briarproject.bramble.api.system.Clock.MIN_REASONABLE_TIME_MS;
import static org.briarproject.bramble.transport.agreement.MessageType.ACTIVATE;
import static org.briarproject.bramble.transport.agreement.MessageType.KEY;
import static org.briarproject.bramble.transport.agreement.TransportKeyAgreementConstants.MSG_KEY_PUBLIC_KEY;
@@ -42,13 +43,14 @@ class TransportKeyAgreementValidator extends BdfMessageValidator {
protected BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws FormatException {
MessageType type = MessageType.fromValue(body.getLong(0).intValue());
if (type == KEY) return validateKeyMessage(body);
if (type == KEY) return validateKeyMessage(m.getTimestamp(), body);
else if (type == ACTIVATE) return validateActivateMessage(body);
else throw new AssertionError();
}
private BdfMessageContext validateKeyMessage(BdfList body)
private BdfMessageContext validateKeyMessage(long timestamp, BdfList body)
throws FormatException {
if (timestamp < MIN_REASONABLE_TIME_MS) throw new FormatException();
// Message type, transport ID, public key
checkSize(body, 3);
String transportId = body.getString(1);

View File

@@ -1,6 +1,3 @@
Bridge obfs4 192.95.36.142:443 CDF2E852BF539B82BD10E27E9115A31734E378C2 cert=qUVQ0srL1JI/vO6V6m/24anYXiJD3QP2HgzUKQtQ7GRqqUvs7P+tG43RtAqdhLOALP7DJQ iat-mode=1
Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1
Bridge obfs4 38.229.33.83:80 0BAC39417268B96B9F514E7F63FA6FBA1A788955 cert=VwEFpk9F/UN9JED7XpG1XOjm/O8ZCXK80oPecgWnNDZDv5pdkhq1OpbAH0wNqOT6H6BmRQ iat-mode=1
Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0
Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0

View File

@@ -120,7 +120,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase {
private final MessageId messageId, messageId1;
private final Metadata metadata;
private final TransportId transportId;
private final int maxLatency;
private final long maxLatency;
private final ContactId contactId;
private final Contact contact;
private final KeySetId keySetId;

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.db;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_TRANSPORT_LATENCY;
import static org.junit.Assert.assertEquals;
public class ExponentialBackoffTest extends BrambleTestCase {
@@ -36,28 +37,28 @@ public class ExponentialBackoffTest extends BrambleTestCase {
@Test
public void testTransmissionCountOverflow() {
int maxLatency = Integer.MAX_VALUE; // RTT will not overflow
long maxLatency = MAX_TRANSPORT_LATENCY; // RTT will not overflow
long expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 0);
assertEquals(Integer.MAX_VALUE * 2L, expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 31);
assertEquals(Integer.MAX_VALUE * (2L << 31), expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 32);
assertEquals(MAX_TRANSPORT_LATENCY * 2L, expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 27);
assertEquals(MAX_TRANSPORT_LATENCY * (2L << 27), expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 28);
assertEquals(Long.MAX_VALUE, expiry); // Overflow caught
expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 33);
expiry = ExponentialBackoff.calculateExpiry(0, maxLatency, 29);
assertEquals(Long.MAX_VALUE, expiry); // Overflow caught
}
@Test
public void testCurrentTimeOverflow() {
int maxLatency = Integer.MAX_VALUE; // RTT will not overflow
long now = Long.MAX_VALUE - (Integer.MAX_VALUE * (2L << 31));
long maxLatency = MAX_TRANSPORT_LATENCY; // RTT will not overflow
long now = Long.MAX_VALUE - (MAX_TRANSPORT_LATENCY * (2L << 27));
long expiry = ExponentialBackoff.calculateExpiry(now, maxLatency, 0);
assertEquals(now + Integer.MAX_VALUE * 2L, expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(now - 1, maxLatency, 31);
assertEquals(now + MAX_TRANSPORT_LATENCY * 2L, expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(now - 1, maxLatency, 27);
assertEquals(Long.MAX_VALUE - 1, expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(now, maxLatency, 31);
expiry = ExponentialBackoff.calculateExpiry(now, maxLatency, 27);
assertEquals(Long.MAX_VALUE, expiry); // No overflow
expiry = ExponentialBackoff.calculateExpiry(now + 1, maxLatency, 32);
expiry = ExponentialBackoff.calculateExpiry(now + 1, maxLatency, 27);
assertEquals(Long.MAX_VALUE, expiry); // Overflow caught
}
}

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.OpenDatabaseHook;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.junit.Before;
@@ -14,7 +15,10 @@ import org.junit.Test;
import java.util.concurrent.atomic.AtomicBoolean;
import static junit.framework.TestCase.assertTrue;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.CLOCK_ERROR;
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.test.TestUtils.getSecretKey;
import static org.junit.Assert.assertEquals;
@@ -22,6 +26,7 @@ public class LifecycleManagerImplTest extends BrambleMockTestCase {
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final EventBus eventBus = context.mock(EventBus.class);
private final Clock clock = context.mock(Clock.class);
private final SecretKey dbKey = getSecretKey();
@@ -29,16 +34,19 @@ public class LifecycleManagerImplTest extends BrambleMockTestCase {
@Before
public void setUp() {
lifecycleManager = new LifecycleManagerImpl(db, eventBus);
lifecycleManager = new LifecycleManagerImpl(db, eventBus, clock);
}
@Test
public void testOpenDatabaseHooksAreCalledAtStartup() throws Exception {
long now = System.currentTimeMillis();
Transaction txn = new Transaction(null, false);
AtomicBoolean called = new AtomicBoolean(false);
OpenDatabaseHook hook = transaction -> called.set(true);
context.checking(new DbExpectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(db).open(dbKey, lifecycleManager);
will(returnValue(false));
oneOf(db).transaction(with(false), withDbRunnable(txn));
@@ -51,4 +59,26 @@ public class LifecycleManagerImplTest extends BrambleMockTestCase {
assertEquals(SUCCESS, lifecycleManager.startServices(dbKey));
assertTrue(called.get());
}
@Test
public void testStartupFailsIfClockIsUnreasonablyBehind() {
context.checking(new DbExpectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(MIN_REASONABLE_TIME_MS - 1));
}});
assertEquals(CLOCK_ERROR, lifecycleManager.startServices(dbKey));
}
@Test
public void testStartupFailsIfClockIsUnreasonablyAhead() {
context.checking(new DbExpectations() {{
oneOf(clock).currentTimeMillis();
will(returnValue(MAX_REASONABLE_TIME_MS + 1));
}});
assertEquals(CLOCK_ERROR, lifecycleManager.startServices(dbKey));
}
}

View File

@@ -12,6 +12,7 @@ import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule;
import org.briarproject.bramble.system.TimeTravelModule;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.bramble.test.TestFeatureFlagModule;
import org.briarproject.bramble.test.TestSecureRandomModule;
import javax.inject.Singleton;
@@ -25,6 +26,7 @@ import dagger.Component;
DefaultEventExecutorModule.class,
DefaultWakefulIoExecutorModule.class,
TestDatabaseConfigModule.class,
TestFeatureFlagModule.class,
RemovableDriveIntegrationTestModule.class,
RemovableDriveModule.class,
TestSecureRandomModule.class,

View File

@@ -1,6 +1,5 @@
package org.briarproject.bramble.plugin.file;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TransportId;
@@ -52,30 +51,4 @@ class RemovableDriveIntegrationTestModule {
};
return pluginConfig;
}
@Provides
FeatureFlags provideFeatureFlags() {
return new FeatureFlags() {
@Override
public boolean shouldEnableImageAttachments() {
return true;
}
@Override
public boolean shouldEnableProfilePictures() {
return true;
}
@Override
public boolean shouldEnableDisappearingMessages() {
return true;
}
@Override
public boolean shouldEnableConnectViaBluetooth() {
return true;
}
};
}
}

View File

@@ -1,48 +1,22 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.bramble.battery.DefaultBatteryManagerModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.system.DefaultWakefulIoExecutorModule;
import org.briarproject.bramble.system.TimeTravelModule;
import dagger.Module;
import dagger.Provides;
@Module(includes = {
DefaultBatteryManagerModule.class,
DefaultEventExecutorModule.class,
DefaultWakefulIoExecutorModule.class,
TestDatabaseConfigModule.class,
TestFeatureFlagModule.class,
TestPluginConfigModule.class,
TestSecureRandomModule.class,
TimeTravelModule.class
})
public class BrambleCoreIntegrationTestModule {
@Provides
FeatureFlags provideFeatureFlags() {
return new FeatureFlags() {
@Override
public boolean shouldEnableImageAttachments() {
return true;
}
@Override
public boolean shouldEnableProfilePictures() {
return true;
}
@Override
public boolean shouldEnableDisappearingMessages() {
return true;
}
@Override
public boolean shouldEnableConnectViaBluetooth() {
return true;
}
};
}
}

View File

@@ -0,0 +1,336 @@
package org.briarproject.bramble.test;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.BdfStringUtils;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.event.MessageStateChangedEvent;
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
import org.junit.After;
import org.junit.Before;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
import static org.briarproject.bramble.api.sync.validation.MessageState.INVALID;
import static org.briarproject.bramble.api.sync.validation.MessageState.PENDING;
import static org.briarproject.bramble.test.TestPluginConfigModule.SIMPLEX_TRANSPORT_ID;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public abstract class BrambleIntegrationTest<C extends BrambleIntegrationTestComponent>
extends BrambleTestCase {
private static final Logger LOG =
getLogger(BrambleIntegrationTest.class.getName());
private static final boolean DEBUG = false;
protected final static int TIMEOUT = 15000;
// objects accessed from background threads need to be volatile
private volatile Waiter validationWaiter;
private volatile Waiter deliveryWaiter;
private volatile Waiter ackWaiter;
private volatile boolean expectAck = false;
private final Semaphore messageSemaphore = new Semaphore(0);
private final AtomicInteger deliveryCounter = new AtomicInteger(0);
private final AtomicInteger validationCounter = new AtomicInteger(0);
private final AtomicInteger ackCounter = new AtomicInteger(0);
protected final File testDir = TestUtils.getTestDirectory();
@Before
public void setUp() throws Exception {
assertTrue(testDir.mkdirs());
// initialize waiters fresh for each test
validationWaiter = new Waiter();
deliveryWaiter = new Waiter();
ackWaiter = new Waiter();
deliveryCounter.set(0);
validationCounter.set(0);
ackCounter.set(0);
}
@After
public void tearDown() throws Exception {
TestUtils.deleteTestDirectory(testDir);
}
protected void addEventListener(C c) {
c.getEventBus().addListener(new Listener(c));
}
private class Listener implements EventListener {
private final ClientHelper clientHelper;
private final Executor executor;
private Listener(C c) {
clientHelper = c.getClientHelper();
executor = newSingleThreadExecutor();
}
@Override
public void eventOccurred(Event e) {
if (e instanceof MessageStateChangedEvent) {
MessageStateChangedEvent event = (MessageStateChangedEvent) e;
if (!event.isLocal()) {
if (event.getState() == DELIVERED) {
LOG.info("Delivered new message "
+ event.getMessageId());
deliveryCounter.addAndGet(1);
loadAndLogMessage(event.getMessageId());
deliveryWaiter.resume();
} else if (event.getState() == INVALID ||
event.getState() == PENDING) {
LOG.info("Validated new " + event.getState().name() +
" message " + event.getMessageId());
validationCounter.addAndGet(1);
loadAndLogMessage(event.getMessageId());
validationWaiter.resume();
}
}
} else if (e instanceof MessagesAckedEvent && expectAck) {
MessagesAckedEvent event = (MessagesAckedEvent) e;
ackCounter.addAndGet(event.getMessageIds().size());
for (MessageId m : event.getMessageIds()) {
loadAndLogMessage(m);
ackWaiter.resume();
}
}
}
private void loadAndLogMessage(MessageId id) {
executor.execute(() -> {
if (DEBUG) {
try {
BdfList body = clientHelper.getMessageAsList(id);
LOG.info("Contents of " + id + ":\n"
+ BdfStringUtils.toString(body));
} catch (DbException | FormatException e) {
logException(LOG, WARNING, e);
}
}
messageSemaphore.release();
});
}
}
protected void syncMessage(BrambleIntegrationTestComponent fromComponent,
BrambleIntegrationTestComponent toComponent, ContactId toId,
TransportId transportId, int num, boolean valid) throws Exception {
syncMessage(fromComponent, toComponent, toId, transportId, num, 0,
valid ? 0 : num, valid ? num : 0);
}
protected void syncMessage(BrambleIntegrationTestComponent fromComponent,
BrambleIntegrationTestComponent toComponent, ContactId toId,
int num, boolean valid) throws Exception {
syncMessage(fromComponent, toComponent, toId, num, 0, valid ? 0 : num,
valid ? num : 0);
}
protected void syncMessage(BrambleIntegrationTestComponent fromComponent,
BrambleIntegrationTestComponent toComponent, ContactId toId,
int numNew, int numDupes, int numPendingOrInvalid, int numDelivered)
throws Exception {
syncMessage(fromComponent, toComponent, toId, SIMPLEX_TRANSPORT_ID,
numNew, numDupes, numPendingOrInvalid, numDelivered);
}
protected void syncMessage(BrambleIntegrationTestComponent fromComponent,
BrambleIntegrationTestComponent toComponent, ContactId toId,
TransportId transportId, int numNew, int numDupes,
int numPendingOrInvalid, int numDelivered) throws Exception {
// Debug output
String from =
fromComponent.getIdentityManager().getLocalAuthor().getName();
String to = toComponent.getIdentityManager().getLocalAuthor().getName();
LOG.info("TEST: Sending " + (numNew + numDupes) + " message(s) from "
+ from + " to " + to);
// Listen for messages being sent
waitForEvents(fromComponent);
SendListener sendListener = new SendListener();
fromComponent.getEventBus().addListener(sendListener);
// Write the messages to a transport stream
ByteArrayOutputStream out = new ByteArrayOutputStream();
TestTransportConnectionWriter writer =
new TestTransportConnectionWriter(out, false);
fromComponent.getConnectionManager().manageOutgoingConnection(toId,
transportId, writer);
writer.getDisposedLatch().await(TIMEOUT, MILLISECONDS);
// Check that the expected number of messages were sent
waitForEvents(fromComponent);
fromComponent.getEventBus().removeListener(sendListener);
assertEquals("Messages sent", numNew + numDupes,
sendListener.sent.size());
// Read the messages from the transport stream
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
TestTransportConnectionReader reader =
new TestTransportConnectionReader(in);
toComponent.getConnectionManager().manageIncomingConnection(
transportId, reader);
if (numPendingOrInvalid > 0) {
validationWaiter.await(TIMEOUT, numPendingOrInvalid);
}
assertEquals("Messages validated", numPendingOrInvalid,
validationCounter.getAndSet(0));
if (numDelivered > 0) {
deliveryWaiter.await(TIMEOUT, numDelivered);
}
assertEquals("Messages delivered", numDelivered,
deliveryCounter.getAndSet(0));
try {
messageSemaphore.tryAcquire(numNew, TIMEOUT, MILLISECONDS);
} catch (InterruptedException e) {
LOG.info("Interrupted while waiting for messages");
Thread.currentThread().interrupt();
fail();
}
}
protected void awaitPendingMessageDelivery(int num)
throws TimeoutException {
deliveryWaiter.await(TIMEOUT, num);
assertEquals("Messages delivered", num, deliveryCounter.getAndSet(0));
try {
messageSemaphore.tryAcquire(num, TIMEOUT, MILLISECONDS);
} catch (InterruptedException e) {
LOG.info("Interrupted while waiting for messages");
Thread.currentThread().interrupt();
fail();
}
}
protected void sendAcks(BrambleIntegrationTestComponent fromComponent,
BrambleIntegrationTestComponent toComponent, ContactId toId,
int num) throws Exception {
// Debug output
String from =
fromComponent.getIdentityManager().getLocalAuthor().getName();
String to = toComponent.getIdentityManager().getLocalAuthor().getName();
LOG.info("TEST: Sending " + num + " ACKs from " + from + " to " + to);
expectAck = true;
// Listen for messages being sent (none should be sent)
waitForEvents(fromComponent);
SendListener sendListener = new SendListener();
fromComponent.getEventBus().addListener(sendListener);
// start outgoing connection
ByteArrayOutputStream out = new ByteArrayOutputStream();
TestTransportConnectionWriter writer =
new TestTransportConnectionWriter(out, false);
fromComponent.getConnectionManager().manageOutgoingConnection(toId,
SIMPLEX_TRANSPORT_ID, writer);
writer.getDisposedLatch().await(TIMEOUT, MILLISECONDS);
// Check that no messages were sent
waitForEvents(fromComponent);
fromComponent.getEventBus().removeListener(sendListener);
assertEquals("Messages sent", 0, sendListener.sent.size());
// handle incoming connection
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
TestTransportConnectionReader reader =
new TestTransportConnectionReader(in);
toComponent.getConnectionManager().manageIncomingConnection(
SIMPLEX_TRANSPORT_ID, reader);
ackWaiter.await(TIMEOUT, num);
assertEquals("ACKs delivered", num, ackCounter.getAndSet(0));
assertEquals("No messages delivered", 0, deliveryCounter.get());
try {
messageSemaphore.tryAcquire(num, TIMEOUT, MILLISECONDS);
} catch (InterruptedException e) {
LOG.info("Interrupted while waiting for messages");
Thread.currentThread().interrupt();
fail();
} finally {
expectAck = false;
}
}
/**
* Broadcasts a marker event and waits for it to be delivered, which
* indicates that all previously broadcast events have been delivered.
*/
public static void waitForEvents(BrambleIntegrationTestComponent component)
throws Exception {
CountDownLatch latch = new CountDownLatch(1);
MarkerEvent marker = new MarkerEvent();
EventBus eventBus = component.getEventBus();
eventBus.addListener(new EventListener() {
@Override
public void eventOccurred(@Nonnull Event e) {
if (e == marker) {
latch.countDown();
eventBus.removeListener(this);
}
}
});
eventBus.broadcast(marker);
if (!latch.await(1, MINUTES)) fail();
}
private static class MarkerEvent extends Event {
}
private static class SendListener implements EventListener {
private final Set<MessageId> sent = new HashSet<>();
@Override
public void eventOccurred(Event e) {
if (e instanceof MessagesSentEvent) {
sent.addAll(((MessagesSentEvent) e).getMessageIds());
}
}
}
}

View File

@@ -0,0 +1,30 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.connection.ConnectionManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class
})
public interface BrambleIntegrationTestComponent
extends BrambleCoreIntegrationTestEagerSingletons {
IdentityManager getIdentityManager();
EventBus getEventBus();
ConnectionManager getConnectionManager();
ClientHelper getClientHelper();
}

View File

@@ -0,0 +1,44 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.FeatureFlags;
import dagger.Module;
import dagger.Provides;
@Module
public class TestFeatureFlagModule {
@Provides
FeatureFlags provideFeatureFlags() {
return new FeatureFlags() {
@Override
public boolean shouldEnableImageAttachments() {
return true;
}
@Override
public boolean shouldEnableProfilePictures() {
return true;
}
@Override
public boolean shouldEnableDisappearingMessages() {
return true;
}
@Override
public boolean shouldEnableConnectViaBluetooth() {
return true;
}
@Override
public boolean shouldEnableShareAppViaOfflineHotspot() {
return true;
}
@Override
public boolean shouldEnableTransferData() {
return true;
}
};
}
}

View File

@@ -27,18 +27,30 @@ public class TestPluginConfigModule {
public static final TransportId SIMPLEX_TRANSPORT_ID = getTransportId();
public static final TransportId DUPLEX_TRANSPORT_ID = getTransportId();
public static final int MAX_LATENCY = 30_000; // 30 seconds
private static final int MAX_LATENCY = 30_000; // 30 seconds
private final TransportId simplexTransportId, duplexTransportId;
public TestPluginConfigModule() {
this(SIMPLEX_TRANSPORT_ID, DUPLEX_TRANSPORT_ID);
}
public TestPluginConfigModule(TransportId simplexTransportId,
TransportId duplexTransportId) {
this.simplexTransportId = simplexTransportId;
this.duplexTransportId = duplexTransportId;
}
@NotNullByDefault
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
@Override
public TransportId getId() {
return SIMPLEX_TRANSPORT_ID;
return simplexTransportId;
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}
@@ -54,11 +66,11 @@ public class TestPluginConfigModule {
@Override
public TransportId getId() {
return DUPLEX_TRANSPORT_ID;
return duplexTransportId;
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}
@@ -70,7 +82,7 @@ public class TestPluginConfigModule {
};
@Provides
PluginConfig providePluginConfig() {
public PluginConfig providePluginConfig() {
@NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() {

View File

@@ -29,7 +29,7 @@ public class TestTransportConnectionWriter
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return 30_000;
}

View File

@@ -81,7 +81,7 @@ public class KeyManagerImplTest extends BrambleMockTestCase {
context.mock(SimplexPluginFactory.class);
Collection<SimplexPluginFactory> factories =
singletonList(pluginFactory);
int maxLatency = 1337;
long maxLatency = 1337;
context.checking(new Expectations() {{
allowing(pluginConfig).getSimplexFactories();

View File

@@ -0,0 +1,418 @@
package org.briarproject.bramble.transport.agreement;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Identity;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.BrambleIntegrationTest;
import org.briarproject.bramble.test.TestDatabaseConfigModule;
import org.briarproject.bramble.test.TestPluginConfigModule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.util.Map;
import static org.briarproject.bramble.api.transport.agreement.TransportKeyAgreementManager.CLIENT_ID;
import static org.briarproject.bramble.api.transport.agreement.TransportKeyAgreementManager.MAJOR_VERSION;
import static org.briarproject.bramble.test.TestPluginConfigModule.DUPLEX_TRANSPORT_ID;
import static org.briarproject.bramble.test.TestPluginConfigModule.SIMPLEX_TRANSPORT_ID;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.transport.agreement.TransportKeyAgreementConstants.MSG_KEY_IS_SESSION;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class TransportKeyAgreementIntegrationTest
extends BrambleIntegrationTest<TransportKeyAgreementTestComponent> {
private final File aliceDir = new File(testDir, "alice");
private final File bobDir = new File(testDir, "bob");
private final SecretKey masterKey = getSecretKey();
private final long timestamp = System.currentTimeMillis();
private final TransportId newTransportId =
new TransportId(getRandomString(8));
private TransportKeyAgreementTestComponent alice, bob;
private Identity aliceIdentity, bobIdentity;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
// Create the devices
alice = createComponent(aliceDir, false);
bob = createComponent(bobDir, false);
// Create identities
aliceIdentity = alice.getIdentityManager().createIdentity("Alice");
bobIdentity = bob.getIdentityManager().createIdentity("Bob");
// Start both lifecycles
startLifecycle(alice, aliceIdentity);
startLifecycle(bob, bobIdentity);
}
private TransportKeyAgreementTestComponent createComponent(
File dir, boolean useNewTransport) {
TestPluginConfigModule pluginConfigModule = useNewTransport ?
new TestPluginConfigModule(SIMPLEX_TRANSPORT_ID, newTransportId)
: new TestPluginConfigModule();
TransportKeyAgreementTestComponent c =
DaggerTransportKeyAgreementTestComponent.builder()
.testDatabaseConfigModule(
new TestDatabaseConfigModule(dir))
.testPluginConfigModule(pluginConfigModule)
.build();
BrambleCoreIntegrationTestEagerSingletons.Helper
.injectEagerSingletons(c);
return c;
}
private void startLifecycle(
TransportKeyAgreementTestComponent device,
Identity identity) throws Exception {
// Listen to message related events first to not miss early ones
addEventListener(device);
// Register identity before starting lifecycle
device.getIdentityManager().registerIdentity(identity);
// Start the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.startServices(masterKey); // re-using masterKey here
lifecycleManager.waitForStartup();
}
@After
@Override
public void tearDown() throws Exception {
tearDown(alice);
tearDown(bob);
super.tearDown();
}
private void tearDown(TransportKeyAgreementTestComponent device)
throws Exception {
// Stop the lifecycle manager
LifecycleManager lifecycleManager = device.getLifecycleManager();
lifecycleManager.stopServices();
lifecycleManager.waitForShutdown();
}
@Test
public void testBothAddTransportAtTheSameTime() throws Exception {
// Alice and Bob add each other.
Pair<ContactId, ContactId> contactIds = addContacts(true);
ContactId aliceId = contactIds.getFirst();
ContactId bobId = contactIds.getSecond();
// Alice and Bob restart and come back with the new transport.
alice = restartWithNewTransport(alice, aliceDir, aliceIdentity);
bob = restartWithNewTransport(bob, bobDir, bobIdentity);
// They can still send via the old simplex,
// but not via the new duplex transport
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
assertFalse(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, SIMPLEX_TRANSPORT_ID));
assertFalse(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Bobs has started a session and sends KEY message to Alice
syncMessage(bob, alice, aliceId, 1, true);
// Alice now and sends her own KEY as well as her ACTIVATE message.
syncMessage(alice, bob, bobId, 2, true);
// Bob can already send over the new transport while Alice still can't.
assertFalse(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Now Bob sends his ACTIVATE message to Alice.
syncMessage(bob, alice, aliceId, 1, true);
// Now Alice can also send over the new transport.
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Ensure that private key is not stored anymore.
assertLocalKeyPairIsNull(alice, bobId);
assertLocalKeyPairIsNull(bob, aliceId);
// Messages can be send over the new transport in both directions.
assertTransportMessageArrives(alice, bob, bobId, newTransportId);
assertTransportMessageArrives(bob, alice, aliceId, newTransportId);
}
@Test
public void testAliceAddsTransportBeforeBob() throws Exception {
// Alice and Bob add each other.
Pair<ContactId, ContactId> contactIds = addContacts(true);
ContactId aliceId = contactIds.getFirst();
ContactId bobId = contactIds.getSecond();
// Alice restarts and comes back with the new transport.
alice = restartWithNewTransport(alice, aliceDir, aliceIdentity);
// Alice can still send via the old simplex,
// but not via the new duplex transport
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
assertFalse(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
// Alice has started a session and sends KEY message to Bob
// which he can't read, as he doesn't support the new transport, yet.
syncMessage(alice, bob, bobId, 1, false);
// Bob restarts and comes back with the new transport.
bob = restartWithNewTransport(bob, bobDir, bobIdentity);
// Alice's pending KEY message now gets delivered async, so wait for it
awaitPendingMessageDelivery(1);
// Bob now sends his own KEY as well as his ACTIVATE message.
syncMessage(bob, alice, aliceId, 2, true);
// Alice can already send over the new transport while Bob still can't.
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertFalse(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Now Alice sends her ACTIVATE message to Bob.
syncMessage(alice, bob, bobId, 1, true);
// Now Bob can also send over the new transport.
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Ensure that private key is not stored anymore.
assertLocalKeyPairIsNull(alice, bobId);
assertLocalKeyPairIsNull(bob, aliceId);
// Messages can be send over the new transport in both directions.
assertTransportMessageArrives(alice, bob, bobId, newTransportId);
assertTransportMessageArrives(bob, alice, aliceId, newTransportId);
}
@Test
public void testAliceAlreadyHasTransportWhenAddingBob() throws Exception {
// Alice restarts and comes back with the new transport.
alice = restartWithNewTransport(alice, aliceDir, aliceIdentity);
// Alice and Bob add each other.
Pair<ContactId, ContactId> contactIds = addContacts(false);
ContactId aliceId = contactIds.getFirst();
ContactId bobId = contactIds.getSecond();
// Alice can still send via the old simplex,
// but not via the new duplex transport
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
// Normally, Alice should not be able to send streams already.
// However, she does already derive keys for the transport.
// The UI checks RemovableDriveManager#isTransportSupportedByContact()
// in practice to prevent sending streams that Bob can't decrypt.
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
// Bob restarts and comes back with the new transport.
bob = restartWithNewTransport(bob, bobDir, bobIdentity);
// Bob sends his own KEY message.
syncMessage(bob, alice, aliceId, 1, true);
// Alice can already send over the new transport while Bob still can't.
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertFalse(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Now Alice sends her KEY and her ACTIVATE message to Bob.
syncMessage(alice, bob, bobId, 2, true);
// Now Bob can also send over the new transport.
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Ensure that private key is not stored anymore.
assertLocalKeyPairIsNull(alice, bobId);
assertLocalKeyPairIsNull(bob, aliceId);
// Bobs still sends his ACTIVATE message.
syncMessage(bob, alice, aliceId, 1, true);
// Messages can be send over the new transport in both directions.
assertTransportMessageArrives(alice, bob, bobId, newTransportId);
assertTransportMessageArrives(bob, alice, aliceId, newTransportId);
}
@Test
public void testAliceActivatesKeysByIncomingMessage() throws Exception {
// Alice and Bob add each other.
Pair<ContactId, ContactId> contactIds = addContacts(true);
ContactId aliceId = contactIds.getFirst();
ContactId bobId = contactIds.getSecond();
// Alice and Bob restart and come back with the new transport.
alice = restartWithNewTransport(alice, aliceDir, aliceIdentity);
bob = restartWithNewTransport(bob, bobDir, bobIdentity);
// They can still send via the old simplex,
// but not via the new duplex transport
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
assertFalse(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, SIMPLEX_TRANSPORT_ID));
assertFalse(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Bobs has started a session and sends KEY message to Alice
syncMessage(bob, alice, aliceId, 1, true);
// Alice now and sends her own KEY as well as her ACTIVATE message.
syncMessage(alice, bob, bobId, 2, true);
// Bob can already send over the new transport while Alice still can't.
assertFalse(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, newTransportId));
// Bob's database mysteriously loses the ACTIVATE message,
// so it won't be send to Alice.
Contact contact = bob.getContactManager().getContact(aliceId);
Group group = getContactGroup(bob, contact);
Map<MessageId, BdfDictionary> map = bob.getClientHelper()
.getMessageMetadataAsDictionary(group.getId());
DatabaseComponent db = bob.getDatabaseComponent();
for (Map.Entry<MessageId, BdfDictionary> e : map.entrySet()) {
if (e.getValue().getBoolean(MSG_KEY_IS_SESSION)) continue;
db.transaction(false, txn -> db.removeMessage(txn, e.getKey()));
}
// Bob sends a message to Alice
assertTransportMessageArrives(bob, alice, aliceId, newTransportId);
// Now without receiving the ACTIVATE, Alice can already send to Bob
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, newTransportId));
assertTransportMessageArrives(alice, bob, bobId, newTransportId);
}
private Pair<ContactId, ContactId> addContacts(
boolean assertOldDuplexSending) throws Exception {
ContactId bobId = addContact(alice, bob, true);
ContactId aliceId = addContact(bob, alice, false);
// Alice and Bob can send messages via the default test transports
if (assertOldDuplexSending) {
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, SIMPLEX_TRANSPORT_ID));
assertTrue(alice.getKeyManager()
.canSendOutgoingStreams(bobId, DUPLEX_TRANSPORT_ID));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, SIMPLEX_TRANSPORT_ID));
assertTrue(bob.getKeyManager()
.canSendOutgoingStreams(aliceId, DUPLEX_TRANSPORT_ID));
}
// Sync initial client versioning updates
syncMessage(alice, bob, bobId, 1, true);
syncMessage(bob, alice, aliceId, 1, true);
syncMessage(alice, bob, bobId, 1, true);
sendAcks(bob, alice, aliceId, 1);
return new Pair<>(aliceId, bobId);
}
private ContactId addContact(
TransportKeyAgreementTestComponent device,
TransportKeyAgreementTestComponent remote,
boolean alice) throws Exception {
// Get remote Author
Author remoteAuthor = remote.getIdentityManager().getLocalAuthor();
// Get ID of LocalAuthor
IdentityManager identityManager = device.getIdentityManager();
AuthorId localAuthorId = identityManager.getLocalAuthor().getId();
// Add the other user as a contact
ContactManager contactManager = device.getContactManager();
return contactManager.addContact(remoteAuthor, localAuthorId, masterKey,
timestamp, alice, true, true);
}
private TransportKeyAgreementTestComponent restartWithNewTransport(
TransportKeyAgreementTestComponent device, File dir,
Identity identity) throws Exception {
tearDown(device);
TransportKeyAgreementTestComponent newDevice =
createComponent(dir, true);
startLifecycle(newDevice, identity);
return newDevice;
}
/**
* Asserts that the local key pair (specifically the private key) is removed
* from the session as intended when leaving the AWAIT_KEY state.
* If it remained on disk after the keys had been activated
* then we'd lose forward secrecy.
*/
private void assertLocalKeyPairIsNull(
TransportKeyAgreementTestComponent device, ContactId contactId)
throws Exception {
Contact contact = device.getContactManager().getContact(contactId);
Group group = getContactGroup(device, contact);
Map<MessageId, BdfDictionary> map = device.getClientHelper()
.getMessageMetadataAsDictionary(group.getId());
for (Map.Entry<MessageId, BdfDictionary> e : map.entrySet()) {
if (!e.getValue().getBoolean(MSG_KEY_IS_SESSION)) continue;
Session s = device.getSessionParser().parseSession(e.getValue());
assertNull(s.getLocalKeyPair());
}
}
private Group getContactGroup(TransportKeyAgreementTestComponent device,
Contact c) {
return device.getContactGroupFactory().createContactGroup(CLIENT_ID,
MAJOR_VERSION, c);
}
private void assertTransportMessageArrives(
TransportKeyAgreementTestComponent from,
TransportKeyAgreementTestComponent to, ContactId toId,
TransportId transportId) throws Exception {
TransportProperties p = new TransportProperties();
p.putBoolean("foo", true);
from.getTransportPropertyManager().mergeLocalProperties(transportId, p);
syncMessage(from, to, toId, transportId, 1, true);
}
}

View File

@@ -0,0 +1,40 @@
package org.briarproject.bramble.transport.agreement;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.transport.KeyManager;
import org.briarproject.bramble.test.BrambleCoreIntegrationTestModule;
import org.briarproject.bramble.test.BrambleIntegrationTestComponent;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
BrambleCoreIntegrationTestModule.class,
BrambleCoreModule.class
})
interface TransportKeyAgreementTestComponent
extends BrambleIntegrationTestComponent {
KeyManager getKeyManager();
TransportKeyAgreementManagerImpl getTransportKeyAgreementManager();
ContactManager getContactManager();
LifecycleManager getLifecycleManager();
ContactGroupFactory getContactGroupFactory();
SessionParser getSessionParser();
TransportPropertyManager getTransportPropertyManager();
DatabaseComponent getDatabaseComponent();
}

View File

@@ -0,0 +1,301 @@
package org.briarproject.bramble.transport.agreement;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.BdfMessageContext;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.Test;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.crypto.CryptoConstants.MAX_AGREEMENT_PUBLIC_KEY_BYTES;
import static org.briarproject.bramble.api.plugin.TransportId.MAX_TRANSPORT_ID_LENGTH;
import static org.briarproject.bramble.api.system.Clock.MIN_REASONABLE_TIME_MS;
import static org.briarproject.bramble.api.versioning.ClientVersioningManager.CLIENT_ID;
import static org.briarproject.bramble.api.versioning.ClientVersioningManager.MAJOR_VERSION;
import static org.briarproject.bramble.test.TestUtils.getGroup;
import static org.briarproject.bramble.test.TestUtils.getMessage;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.transport.agreement.MessageType.ACTIVATE;
import static org.briarproject.bramble.transport.agreement.MessageType.KEY;
import static org.briarproject.bramble.transport.agreement.TransportKeyAgreementConstants.MSG_KEY_PUBLIC_KEY;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class TransportKeyAgreementValidatorTest extends BrambleMockTestCase {
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final MetadataEncoder metadataEncoder =
context.mock(MetadataEncoder.class);
private final Clock clock = context.mock(Clock.class);
private final MessageEncoder messageEncoder =
context.mock(MessageEncoder.class);
private final TransportKeyAgreementValidator validator =
new TransportKeyAgreementValidator(clientHelper, metadataEncoder,
clock, messageEncoder);
private final Group group = getGroup(CLIENT_ID, MAJOR_VERSION);
private final Message message = getMessage(group.getId());
@Test(expected = FormatException.class)
public void testRejectsEmptyMessage() throws Exception {
BdfList body = BdfList.of();
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsNullType() throws Exception {
BdfList body = BdfList.of((Object) null);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsNonLongType() throws Exception {
BdfList body = BdfList.of("123");
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsUnknownLongType() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue() + 1);
validator.validateMessage(message, group, body);
}
@Test
public void testAcceptsKeyMsg() throws Exception {
TransportId transportId = new TransportId(getRandomString(1));
context.checking(new Expectations() {{
oneOf(messageEncoder)
.encodeMessageMetadata(transportId, KEY, false);
will(returnValue(new BdfDictionary()));
}});
byte[] publicKey = getRandomBytes(1);
BdfList body =
BdfList.of(KEY.getValue(), transportId.getString(), publicKey);
BdfMessageContext msgCtx =
validator.validateMessage(message, group, body);
assertEquals(emptyList(), msgCtx.getDependencies());
BdfDictionary d = msgCtx.getDictionary();
assertArrayEquals(publicKey, d.getRaw(MSG_KEY_PUBLIC_KEY));
}
@Test
public void testAcceptsKeyMsgMaxLengths() throws Exception {
TransportId transportId =
new TransportId(getRandomString(MAX_TRANSPORT_ID_LENGTH));
context.checking(new Expectations() {{
oneOf(messageEncoder)
.encodeMessageMetadata(transportId, KEY, false);
will(returnValue(new BdfDictionary()));
}});
byte[] publicKey = getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES);
BdfList body =
BdfList.of(KEY.getValue(), transportId.getString(), publicKey);
BdfMessageContext msgCtx =
validator.validateMessage(message, group, body);
assertEquals(emptyList(), msgCtx.getDependencies());
BdfDictionary d = msgCtx.getDictionary();
assertArrayEquals(publicKey, d.getRaw(MSG_KEY_PUBLIC_KEY));
}
@Test
public void testAcceptsMinTimestampKeyMsg() throws Exception {
Message message =
getMessage(group.getId(), 1234, MIN_REASONABLE_TIME_MS);
TransportId transportId = new TransportId(getRandomString(1));
context.checking(new Expectations() {{
oneOf(messageEncoder)
.encodeMessageMetadata(transportId, KEY, false);
will(returnValue(new BdfDictionary()));
}});
byte[] publicKey = getRandomBytes(1);
BdfList body =
BdfList.of(KEY.getValue(), transportId.getString(), publicKey);
BdfMessageContext msgCtx =
validator.validateMessage(message, group, body);
assertEquals(emptyList(), msgCtx.getDependencies());
BdfDictionary d = msgCtx.getDictionary();
assertArrayEquals(publicKey, d.getRaw(MSG_KEY_PUBLIC_KEY));
}
@Test(expected = FormatException.class)
public void testRejectsTooLongKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(), getRandomString(1),
getRandomBytes(1), 1);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooShortKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(), getRandomString(1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsEmptyTransportIdKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(), "", getRandomBytes(1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooLongTransportIdKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(),
getRandomString(MAX_TRANSPORT_ID_LENGTH + 1),
getRandomBytes(1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsNonStringTransportIdKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(),
getRandomBytes(MAX_TRANSPORT_ID_LENGTH),
getRandomBytes(1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsEmptyPublicKeyKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(),
getRandomString(1),
getRandomBytes(0));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooLongPublicKeyKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(),
getRandomString(1),
getRandomBytes(MAX_AGREEMENT_PUBLIC_KEY_BYTES + 1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsNonBytesPublicKeyKeyMsg() throws Exception {
BdfList body = BdfList.of(KEY.getValue(),
getRandomString(1),
getRandomString(MAX_AGREEMENT_PUBLIC_KEY_BYTES));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooOldTimestampKeyMsg() throws Exception {
Message message =
getMessage(group.getId(), 1234, MIN_REASONABLE_TIME_MS - 1);
BdfList body = BdfList.of(KEY.getValue(), getRandomString(1),
getRandomBytes(1));
validator.validateMessage(message, group, body);
}
@Test
public void testAcceptsActivateMsg() throws Exception {
TransportId transportId = new TransportId(getRandomString(1));
BdfDictionary meta = new BdfDictionary();
context.checking(new Expectations() {{
oneOf(messageEncoder)
.encodeMessageMetadata(transportId, ACTIVATE, false);
will(returnValue(meta));
}});
MessageId msgId = new MessageId(getRandomBytes(MessageId.LENGTH));
BdfList body = BdfList.of(ACTIVATE.getValue(), transportId.getString(),
msgId.getBytes());
BdfMessageContext msgCtx =
validator.validateMessage(message, group, body);
assertEquals(singletonList(msgId), msgCtx.getDependencies());
assertEquals(meta, msgCtx.getDictionary());
}
@Test
public void testAcceptsActivateMsgMaxTransportIdLength() throws Exception {
TransportId transportId =
new TransportId(getRandomString(MAX_TRANSPORT_ID_LENGTH));
BdfDictionary meta = new BdfDictionary();
context.checking(new Expectations() {{
oneOf(messageEncoder)
.encodeMessageMetadata(transportId, ACTIVATE, false);
will(returnValue(meta));
}});
MessageId msgId = new MessageId(getRandomBytes(MessageId.LENGTH));
BdfList body = BdfList.of(ACTIVATE.getValue(), transportId.getString(),
msgId.getBytes());
BdfMessageContext msgCtx =
validator.validateMessage(message, group, body);
assertEquals(singletonList(msgId), msgCtx.getDependencies());
assertEquals(meta, msgCtx.getDictionary());
}
@Test(expected = FormatException.class)
public void testRejectsTooLongActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(), getRandomString(1),
getRandomBytes(MessageId.LENGTH), 1);
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooShortActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(), getRandomString(1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsEmptyTransportIdActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(), "",
getRandomBytes(MessageId.LENGTH));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsNonStringTransportIdActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(), 123,
getRandomBytes(MessageId.LENGTH));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooLongTransportIdActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(),
getRandomString(MAX_TRANSPORT_ID_LENGTH + 1),
getRandomBytes(MessageId.LENGTH));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooShortMsgIdActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(),
getRandomString(1),
getRandomBytes(MessageId.LENGTH - 1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsTooLongMsgIdActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(),
getRandomString(1),
getRandomBytes(MessageId.LENGTH + 1));
validator.validateMessage(message, group, body);
}
@Test(expected = FormatException.class)
public void testRejectsNonByteMsgIdActivateMsg() throws Exception {
BdfList body = BdfList.of(ACTIVATE.getValue(),
getRandomString(1),
getRandomString(MessageId.LENGTH));
validator.validateMessage(message, group, body);
}
}

View File

@@ -1,11 +1,12 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'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.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'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',
@@ -15,15 +16,16 @@ dependencyVerification {
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.jodah:concurrentunit:0.4.2:concurrentunit-0.4.2.jar:5583078e1acf91734939e985bc9e7ee947b0e93a8eef679da6bb07bbeb47ced3',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
@@ -32,16 +34,22 @@ dependencyVerification {
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.hsqldb:hsqldb:2.3.5:hsqldb-2.3.5.jar:6676a6977ac98997a80f827ddbd3fe8ca1e0853dad1492512135fd1a222ccfad',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'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.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
]
}

View File

@@ -14,21 +14,22 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
implementation fileTree(dir: 'libs', include: '*.jar')
implementation 'net.java.dev.jna:jna:4.5.2'
implementation 'net.java.dev.jna:jna-platform:4.5.2'
tor 'org.briarproject:tor:0.3.5.13-1@zip'
def jna_version = '4.5.2'
implementation "net.java.dev.jna:jna:$jna_version"
implementation "net.java.dev.jna:jna-platform:$jna_version"
tor 'org.briarproject:tor:0.3.5.15'
tor 'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-legacy:$jmock_version"
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24'
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
}
def torBinariesDir = 'src/main/resources'

View File

@@ -41,7 +41,7 @@ class JavaBluetoothPlugin extends
SecureRandom secureRandom,
Backoff backoff,
PluginCallback callback,
int maxLatency,
long maxLatency,
int maxIdleTime) {
super(connectionManager, connectionFactory, ioExecutor,
wakefulIoExecutor, secureRandom, backoff, callback,

View File

@@ -58,7 +58,7 @@ public class JavaBluetoothPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -50,14 +50,14 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
private final ModemFactory modemFactory;
private final SerialPortList serialPortList;
private final PluginCallback callback;
private final int maxLatency;
private final long maxLatency;
private final AtomicBoolean used = new AtomicBoolean(false);
private final PluginState state = new PluginState();
private volatile Modem modem = null;
ModemPlugin(ModemFactory modemFactory, SerialPortList serialPortList,
PluginCallback callback, int maxLatency) {
PluginCallback callback, long maxLatency) {
this.modemFactory = modemFactory;
this.serialPortList = serialPortList;
this.callback = callback;
@@ -70,7 +70,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return maxLatency;
}

View File

@@ -36,7 +36,7 @@ public class ModemPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -33,7 +33,7 @@ abstract class JavaTorPlugin extends TorPlugin {
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback,
String architecture,
int maxLatency,
long maxLatency,
int maxIdleTime,
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,

View File

@@ -33,7 +33,7 @@ class UnixTorPlugin extends JavaTorPlugin {
TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback,
String architecture,
int maxLatency,
long maxLatency,
int maxIdleTime,
File torDirectory) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,

View File

@@ -16,6 +16,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.WakefulIoExecutor;
import java.io.File;
import java.util.concurrent.Executor;
@@ -56,7 +57,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
@Inject
UnixTorPluginFactory(@IoExecutor Executor ioExecutor,
@IoExecutor Executor wakefulIoExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor,
NetworkManager networkManager,
LocationUtils locationUtils,
EventBus eventBus,
@@ -87,7 +88,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
}
@Override
public int getMaxLatency() {
public long getMaxLatency() {
return MAX_LATENCY;
}

View File

@@ -1,11 +1,12 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'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.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'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',
@@ -13,28 +14,34 @@ dependencyVerification {
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'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.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'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:4.5.2:jna-platform-4.5.2.jar:f1d00c167d8921c6e23c626ef9f1c3ae0be473c95c68ffa012bc7ae55a87e2d6',
'net.java.dev.jna:jna:4.5.2:jna-4.5.2.jar:0c8eb7acf67261656d79005191debaba3b6bf5dd60a43735a245429381dbecff',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766',
'org.briarproject:tor:0.3.5.13-1:tor-0.3.5.13-1.zip:ef35c16bf8dc1f4c75ed71d9f55e4514f383d124ec96b859aca647c990927c99',
'org.briarproject:tor:0.3.5.15:tor-0.3.5.15.jar:2ff5b5a3b5eaa97d699629ad24ba9584b3199d0ffdb1ea7d8a02de3016b80e7a',
'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.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.20:kotlin-stdlib-common-1.4.20.jar:a7112c9b3cefee418286c9c9372f7af992bd1e6e030691d52f60cb36dbec8320',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'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.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
]
}

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="155" height="155"
viewBox="0 0 155 158.05972" fill="none" version="1.1" id="svg24"
sodipodi:docname="transfer_data.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<defs id="defs11" />
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1"
objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="982"
id="namedview9" showgrid="false" inkscape:zoom="1.4523073" inkscape:cx="8.2820655"
inkscape:cy="-28.56208" inkscape:window-x="1920" inkscape:window-y="72"
inkscape:window-maximized="0" inkscape:current-layer="svg24" />
<metadata id="metadata30">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g id="g844" transform="translate(0,3.0301033)">
<path id="path2" style="fill:#82c91e"
d="m 34.888672,24.835938 c -0.929975,-0.02143 -1.778628,0.612487 -1.994141,1.554687 -0.2463,1.0768 0.427106,2.148231 1.503907,2.394531 l 5.339843,1.222656 c -6.856612,4.77068 -12.781629,10.788147 -17.445312,17.767579 -5.4771,8.1968 -9.072016,17.49215 -10.541016,27.21875 -0.217,1.4367 0.827383,2.738037 2.271485,2.898437 1.4442,0.1604 2.74109,-0.880406 2.96289,-2.316406 1.3729,-8.8885 4.672941,-17.381253 9.681641,-24.876953 4.280712,-6.40624 9.717062,-11.928555 16.003906,-16.316407 l -1.271484,5.558594 c -0.2463,1.0768 0.427106,2.150185 1.503906,2.396485 1.0767,0.2463 2.150184,-0.427207 2.396484,-1.503907 l 2.076172,-9.080078 c 0.167435,-0.732007 0.107609,-1.457562 -0.109375,-2.123047 -0.03323,-0.347577 -0.135561,-0.692647 -0.314453,-1.017578 -0.353538,-0.6421 -0.935043,-1.078378 -1.585937,-1.257812 -0.310286,-0.16723 -0.63775,-0.310162 -0.998047,-0.392578 l -9.078125,-2.076172 c -0.134588,-0.03079 -0.269491,-0.04772 -0.402344,-0.05078 z m 76.982418,2.876953 c -0.836,0.0548 -1.63328,0.526718 -2.08203,1.316406 -0.717,1.2635 -0.27106,2.863965 0.96094,3.634765 8.143,5.095901 14.99795,12.028813 20.00195,20.257813 4.93587,8.11686 7.91993,17.252829 8.7461,26.689453 l -4.25,-3.394531 c -0.863,-0.6893 -2.12055,-0.548547 -2.81055,0.314453 -0.689,0.8631 -0.54855,2.121147 0.31445,2.810547 l 7.27735,5.8125 c 1.726,1.3788 4.24209,1.097194 5.62109,-0.628906 l 5.8125,-7.277344 c 0.69,-0.863 0.54855,-2.121147 -0.31445,-2.810547 -0.863,-0.6894 -2.12155,-0.548647 -2.81055,0.314453 l -3.58984,4.494141 c -0.8855,-10.27436 -4.12841,-20.220841 -9.50196,-29.056641 -5.469,-8.9943 -12.97353,-16.564369 -21.89453,-22.105469 -0.46312,-0.287512 -0.97886,-0.40397 -1.48047,-0.371093 z M 45.191406,137.83008 c -0.851573,0.0281 -1.670687,0.44648 -2.164062,1.20898 -0.7895,1.219 -0.44326,2.85471 0.80664,3.59571 9.034,5.356 19.211344,8.51779 29.714844,9.21679 10.5035,0.699 21.011881,-1.08626 30.675782,-5.19726 1.337,-0.569 1.89734,-2.14303 1.27734,-3.45703 -0.621,-1.313 -2.18834,-1.86969 -3.52734,-1.30469 -8.852401,3.73 -18.466473,5.34798 -28.076172,4.70898 -9.609701,-0.64 -18.922925,-3.51767 -27.203126,-8.38867 -0.469612,-0.27637 -0.992962,-0.39966 -1.503906,-0.38281 z" />
<path id="path8" style="fill:#8a9cb3"
d="M 68.474609,0 C 66.724209,0 65.046294,0.6958487 63.808594,1.9335938 62.570894,3.1713338 61.875,4.8491794 61.875,6.5996094 V 46.199219 c 0,1.7504 0.695894,3.430267 1.933594,4.667969 1.2377,1.237698 2.915615,1.933593 4.666015,1.933593 h 19.800782 c 1.7504,0 3.428315,-0.695895 4.666015,-1.933593 1.2377,-1.237702 1.933594,-2.917569 1.933594,-4.667969 V 6.5996094 c 0,-1.75043 -0.695894,-3.4282757 -1.933594,-4.6660156 C 91.703706,0.6958487 90.025791,0 88.275391,0 Z m 0,3.3007812 h 19.800782 c 0.8752,0 1.715084,0.3459738 2.333984,0.9648438 0.6188,0.61887 0.964844,1.4587744 0.964844,2.3339844 V 46.199219 c 0,0.8752 -0.346044,1.715084 -0.964844,2.333984 C 89.990475,49.152003 89.150591,49.5 88.275391,49.5 H 68.474609 c -0.8752,0 -1.715084,-0.347997 -2.333984,-0.966797 -0.6188,-0.6189 -0.964844,-1.458784 -0.964844,-2.333984 V 6.5996094 c 0,-0.87521 0.346044,-1.7151144 0.964844,-2.3339844 0.6189,-0.61887 1.458784,-0.9648437 2.333984,-0.9648438 z M 11.25,97 0,108.40039 v 22.79883 C 0,133.28922 1.6875,135 3.75,135 h 22.5 c 2.0625,0 3.75,-1.71078 3.75,-3.80078 V 100.80078 C 30,98.710782 28.3125,97 26.25,97 Z M 131,100.59961 c -0.796,0 -1.55909,0.31591 -2.12109,0.87891 -0.563,0.562 -0.87891,1.32509 -0.87891,2.12109 v 13.5 c -0.796,0 -1.55909,0.31591 -2.12109,0.87891 -0.563,0.562 -0.87891,1.32509 -0.87891,2.12109 v 16.5 h 3 v -16.5 h 24 v 16.5 h 3 v -16.5 c 0,-0.796 -0.31591,-1.55909 -0.87891,-2.12109 -0.562,-0.563 -1.32509,-0.87891 -2.12109,-0.87891 v -13.5 c 0,-0.796 -0.31591,-1.55909 -0.87891,-2.12109 -0.562,-0.563 -1.32509,-0.87891 -2.12109,-0.87891 z M 12.806641,100.80078 H 26.25 v 30.39844 H 3.75 V 109.97656 Z M 131,103.59961 h 18 v 13.5 H 131 Z M 9.375,106.5 v 7.59961 h 3.75 V 106.5 Z m 5.625,0 v 7.59961 h 3.75 V 106.5 Z m 5.625,0 v 7.59961 h 3.75 V 106.5 Z" />
</g>
<path
d="m 78.375,46.2 c 0.8752,0 1.7146,-0.3477 2.3335,-0.9666 0.6188,-0.6188 0.9665,-1.4582 0.9665,-2.3334 0,-0.8752 -0.3477,-1.7146 -0.9665,-2.3335 C 80.0896,39.9477 79.2502,39.6 78.375,39.6 c -0.8752,0 -1.7146,0.3477 -2.3334,0.9665 -0.6189,0.6189 -0.9666,1.4583 -0.9666,2.3335 0,0.8752 0.3477,1.7146 0.9666,2.3334 0.6188,0.6189 1.4582,0.9666 2.3334,0.9666 z"
fill="#8a9cb3" id="path10" />
<path d="m 134,109.6 h 4.5 v 3 H 134 Z" fill="#8a9cb3" id="path14" />
<path d="m 141.5,109.6 h 4.5 v 3 h -4.5 z" fill="#8a9cb3" id="path16" />
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="120" height="52"
viewBox="0 0 120 52" fill="none" version="1.1" id="svg24"
sodipodi:docname="transfer_data_receive.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<defs id="defs11" />
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1"
objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="982"
id="namedview9" showgrid="false" inkscape:zoom="4.1077454" inkscape:cx="81.48675"
inkscape:cy="18.42645" inkscape:window-x="1920" inkscape:window-y="72"
inkscape:window-maximized="0" inkscape:current-layer="svg24" inkscape:document-rotation="0"
fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" />
<metadata id="metadata30">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<path id="path8"
style="fill:#8a9cb3;stroke:none;stroke-width:0.749281;stroke-miterlimit:4;stroke-dasharray:none"
d="m 15.97512,14.267003 c -0.596207,0 -1.167798,0.237677 -1.588736,0.659365 -0.421693,0.42094 -0.659371,0.992537 -0.659371,1.588743 v 10.111264 c -0.596207,0 -1.16631,0.236178 -1.58725,0.657875 -0.421682,0.420938 -0.659361,0.992529 -0.659361,1.588736 v 12.35937 h 2.246611 v -12.35937 h 17.977398 v 12.359369 h 2.24662 V 28.872986 c 0,-0.596207 -0.23619,-1.167798 -0.65788,-1.588737 -0.42094,-0.421697 -0.99253,-0.657875 -1.58874,-0.657875 V 16.515111 c 0,-0.596206 -0.23768,-1.167804 -0.65937,-1.588743 -0.42094,-0.421688 -0.99252,-0.659365 -1.58873,-0.659365 z m 0,2.248108 H 29.456311 V 26.626375 H 15.97512 Z m 2.24662,2.224241 v 2.246609 h 3.369915 v -2.246609 z m 5.618031,0 v 2.246609 h 3.36993 v -2.246609 z"
sodipodi:nodetypes="scsccsccccccsccscssccccccccccccccc" />
<path
d="m 47.827564,24.463076 v 3.073847 h 18.443085 l -8.45308,8.453081 2.182432,2.182432 12.172435,-12.172438 -12.172435,-12.172434 -2.182432,2.182431 8.45308,8.45308 z"
id="path895" style="fill:#82c91e;fill-opacity:1;stroke:none;stroke-width:1.53692" />
<path id="path8-3"
style="fill:#8a9cb3;stroke:none;stroke-width:0.985186;stroke-miterlimit:4;stroke-dasharray:none"
d="M 93.999021,5.9999999e-8 C 92.275189,5.9999999e-8 90.624219,0.68560941 89.405306,1.9045678 88.186391,3.1235212 87.500737,4.7763832 87.500737,6.5002454 V 45.497793 c 0,1.723833 0.685654,3.378723 1.904569,4.597639 C 90.624219,51.314343 92.275189,52 93.999021,52 h 19.500739 c 1.72383,0 3.37676,-0.685657 4.59567,-1.904568 C 119.31435,48.876515 120,47.221626 120,45.497793 V 6.5002454 C 120,4.7763832 119.31435,3.1235212 118.09543,1.9045678 116.87652,0.68560941 115.22359,5.9999999e-8 113.49976,5.9999999e-8 Z m 0,3.252084740000001 h 19.500739 c 0.86192,0 1.68931,0.339865 2.29881,0.9493417 0.60941,0.6094767 0.95131,1.4368929 0.95131,2.2988189 V 45.497793 c 0,0.861917 -0.3419,1.689315 -0.95131,2.29882 -0.6095,0.609408 -1.43689,0.953264 -2.29881,0.953264 H 93.999021 c -0.861916,0 -1.687352,-0.343856 -2.296858,-0.953264 -0.609407,-0.609505 -0.951304,-1.436903 -0.951304,-2.29882 V 6.5002454 c 0,-0.861926 0.341897,-1.6893422 0.951304,-2.2988189 0.609506,-0.6094767 1.434942,-0.9493417 2.296858,-0.9493417 z m 9.750369,32.7640582 c -0.86191,0 -1.68745,0.341895 -2.29686,0.951303 -0.6095,0.609506 -0.95326,1.436904 -0.95326,2.298819 0,0.861916 0.34376,1.687452 0.95326,2.29686 0.60941,0.609507 1.43495,0.951302 2.29686,0.951302 0.86192,0 1.68931,-0.341797 2.29882,-0.951302 0.6094,-0.609408 0.9513,-1.434942 0.9513,-2.29686 0,-0.861915 -0.3419,-1.689311 -0.9513,-2.298819 -0.60951,-0.609408 -1.4369,-0.951303 -2.29882,-0.951303 z"
sodipodi:nodetypes="sssssssscsssssscsscsscsscsssscssscs" />
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="120" height="52"
viewBox="0 0 120 52" fill="none" version="1.1" id="svg24"
sodipodi:docname="transfer_data_send.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<defs id="defs11" />
<sodipodi:namedview pagecolor="#ffffff" bordercolor="#666666" borderopacity="1"
objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="982"
id="namedview9" showgrid="false" inkscape:zoom="4.1077454" inkscape:cx="35.020218"
inkscape:cy="26.319497" inkscape:window-x="1920" inkscape:window-y="72"
inkscape:window-maximized="1" inkscape:current-layer="svg24" inkscape:document-rotation="0"
fit-margin-top="0" fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0"
lock-margins="true" />
<metadata id="metadata30">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<path id="path8"
style="fill:#8a9cb3;stroke:none;stroke-width:0.749281;stroke-miterlimit:4;stroke-dasharray:none"
d="m 91.223138,12.30985 c -0.596207,0 -1.167798,0.237677 -1.588736,0.659365 -0.421693,0.42094 -0.659371,0.992537 -0.659371,1.588743 v 10.111264 c -0.596207,0 -1.16631,0.236178 -1.58725,0.657875 -0.421682,0.420938 -0.659361,0.992529 -0.659361,1.588736 v 12.35937 h 2.246611 v -12.35937 h 17.977399 v 12.359369 h 2.24662 V 26.915833 c 0,-0.596207 -0.23619,-1.167798 -0.65788,-1.588737 -0.42094,-0.421697 -0.99253,-0.657875 -1.58874,-0.657875 V 14.557958 c 0,-0.596206 -0.23768,-1.167804 -0.65937,-1.588743 -0.42094,-0.421688 -0.99252,-0.659365 -1.58873,-0.659365 z m 0,2.248108 H 104.70433 V 24.669222 H 91.223138 Z m 2.24662,2.224241 v 2.246609 h 3.369915 v -2.246609 z m 5.618031,0 v 2.246609 h 3.369931 v -2.246609 z"
sodipodi:nodetypes="scsccsccccccsccscssccccccccccccccc" />
<path
d="m 47.827564,24.463076 v 3.073847 h 18.443085 l -8.45308,8.453081 2.182432,2.182432 12.172435,-12.172438 -12.172435,-12.172434 -2.182432,2.182431 8.45308,8.45308 z"
id="path895" style="fill:#82c91e;fill-opacity:1;stroke:none;stroke-width:1.53692" />
<path id="path8-3"
style="fill:#8a9cb3;stroke:none;stroke-width:0.985186;stroke-miterlimit:4;stroke-dasharray:none"
d="M 6.4982841,0 C 4.7744519,0 3.1234817,0.68560936 1.9045686,1.9045677 0.68565358,3.1235212 0,4.7763832 0,6.5002454 V 45.497793 c 0,1.723832 0.68565358,3.378724 1.9045686,4.597639 C 3.1234817,51.314343 4.7744519,52 6.4982841,52 H 25.999019 c 1.723832,0 3.376764,-0.685657 4.595677,-1.904568 1.218914,-1.218917 1.904569,-2.873807 1.904568,-4.597639 V 6.5002454 c 0,-1.7238622 -0.685654,-3.3767242 -1.904568,-4.5956777 C 29.375783,0.68560936 27.722851,0 25.999019,0 Z m 0,3.2520847 H 25.999019 c 0.861916,0 1.689313,0.339865 2.29882,0.9493418 0.609407,0.6094767 0.951302,1.4368929 0.951302,2.2988189 V 45.497793 c 0,0.861916 -0.341895,1.689315 -0.951302,2.29882 -0.609507,0.609408 -1.436904,0.953264 -2.29882,0.953264 H 6.4982841 c -0.8619161,0 -1.6873525,-0.343856 -2.2968577,-0.953264 C 3.5920186,47.187108 3.2501219,46.359709 3.2501219,45.497793 V 6.5002454 c 0,-0.861926 0.3418967,-1.6893422 0.9513045,-2.2988189 C 4.8109316,3.5919497 5.636368,3.2520847 6.4982841,3.2520847 Z M 16.248652,36.016144 c -0.861916,0 -1.68745,0.341895 -2.296859,0.951302 -0.609506,0.609506 -0.953264,1.436905 -0.953264,2.29882 0,0.861916 0.343758,1.687452 0.953264,2.29686 0.609409,0.609507 1.434943,0.951302 2.296859,0.951302 0.861916,0 1.689312,-0.341797 2.298819,-0.951302 0.609408,-0.609408 0.951303,-1.434942 0.951303,-2.29686 0,-0.861915 -0.341895,-1.689311 -0.951303,-2.29882 -0.609507,-0.609407 -1.436903,-0.951302 -2.298819,-0.951302 z"
sodipodi:nodetypes="sssssssscsssssscsscsscsscsssscssscs" />
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -26,8 +26,8 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
versionCode 10303
versionName "1.3.3"
versionCode 10305
versionName "1.3.5"
applicationId "org.briarproject.briar.android"
vectorDrawables.useSupportLibrary = true
@@ -100,19 +100,19 @@ dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
implementation project(':bramble-android')
implementation 'androidx.fragment:fragment:1.3.0'
implementation 'androidx.fragment:fragment:1.3.4'
implementation 'androidx.preference:preference:1.1.1'
implementation 'androidx.exifinterface:exifinterface:1.3.1'
implementation 'androidx.exifinterface:exifinterface:1.3.2'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0-rc03'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.recyclerview:recyclerview-selection:1.1.0'
implementation 'info.guardianproject.panic:panic:1.0'
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
implementation 'de.hdodenhof:circleimageview:3.0.1'
implementation 'com.google.zxing:core:3.3.3' // newer version need minSdk 24
implementation 'uk.co.samuelwall:material-tap-target-prompt:3.0.0'
implementation 'uk.co.samuelwall:material-tap-target-prompt:3.3.0'
implementation 'com.vanniktech:emoji-google:0.6.0' // newer versions need minSdk 21
implementation 'com.github.kobakei:MaterialFabSpeedDial:1.2.1'
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
@@ -121,28 +121,28 @@ dependencies {
exclude group: 'com.android.support'
exclude module: 'disklrucache' // when there's no disk cache, we can't accidentally use it
}
implementation 'org.nanohttpd:nanohttpd:2.3.1'
annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
annotationProcessor "com.github.bumptech.glide:compiler:$glideVersion"
compileOnly 'javax.annotation:jsr250-api:1.0'
def espressoVersion = '3.3.0'
def jmockVersion = '2.8.2'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
testImplementation 'androidx.test:runner:1.3.0'
testImplementation 'androidx.test.ext:junit:1.1.2'
testImplementation 'androidx.fragment:fragment-testing:1.2.5'
testImplementation 'androidx.fragment:fragment-testing:1.3.4'
testImplementation "androidx.arch.core:core-testing:2.1.0"
testImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
testImplementation 'org.robolectric:robolectric:4.3.1'
testImplementation 'org.mockito:mockito-core:3.1.0'
testImplementation 'junit:junit:4.13.1'
testImplementation "org.jmock:jmock:$jmockVersion"
testImplementation "org.jmock:jmock-junit4:$jmockVersion"
testImplementation "org.jmock:jmock-legacy:$jmockVersion"
testAnnotationProcessor "com.google.dagger:dagger-compiler:2.24"
testImplementation 'org.mockito:mockito-core:3.9.0'
testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-legacy:$jmock_version"
testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
androidTestImplementation project(path: ':bramble-api', configuration: 'testOutput')
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
@@ -151,9 +151,9 @@ dependencies {
androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestUtil 'androidx.test:orchestrator:1.3.0'
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.24"
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
androidTestImplementation 'junit:junit:4.13.1'
androidTestImplementation "junit:junit:$junit_version"
androidTestScreenshotImplementation 'tools.fastlane:screengrab:2.0.0'
androidTestScreenshotImplementation 'com.jraska:falcon:2.1.1'
androidTestScreenshotImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'

View File

@@ -18,6 +18,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.CAMERA" />
@@ -104,8 +105,7 @@
<activity
android:name="org.briarproject.briar.android.account.SetupActivity"
android:label="@string/setup_title"
android:windowSoftInputMode="adjustResize|stateAlwaysVisible" />
android:label="@string/setup_title" />
<activity
android:name="org.briarproject.briar.android.splash.SplashScreenActivity"
@@ -437,11 +437,25 @@
android:value="org.briarproject.briar.android.navdrawer.NavDrawerActivity" />
</activity>
<activity
android:name="org.briarproject.briar.android.removabledrive.RemovableDriveActivity"
android:label="@string/removable_drive_menu_title"
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
</activity>
<activity
android:name=".android.contact.add.remote.PendingContactListActivity"
android:label="@string/pending_contact_requests"
android:theme="@style/BriarTheme" />
<activity
android:name=".android.hotspot.HotspotActivity"
android:label="@string/hotspot_title"
android:theme="@style/BriarTheme" />
</application>
<queries>

View File

@@ -0,0 +1,103 @@
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
background-color: #F2F2F2;
font-family: Roboto,Arial,Helvetica,sans-serif;
font-size: 14px;
margin: 0;
height: 100%;
}
div#top {
background-color: #FFFFFF;
padding: 16px;
}
div#bottom {
padding: 16px 32px;
margin-top: 12px;
}
a.button {
background-color: #82C91E;
width: 100%;
display: block;
box-sizing: border-box;
padding: 12px 32px !important;
border: 1px solid transparent;
border-radius: 2px;
color: #000000 !important;
cursor: pointer;
font-weight: 500;
text-decoration: none;
text-transform: uppercase;
text-align: center;
margin: 20px auto 20px auto;
}
ol {
list-style: none;
counter-reset: briar-counter;
padding-left: 40px;
}
ol li {
counter-increment: briar-counter;
margin-bottom: 2em;
}
ol li::before {
content: counter(briar-counter);
background-color: #82C91E;
color: #000000 !important;
font-weight: bold;
border-radius: 70px;
width: 24px;
height: 24px;
line-height: 24px;
text-align: center;
position: absolute;
left: 32px;
}
</style>
</head>
<body>
<div id="top">
<svg style="width:156px;height:47px;" viewBox="0 0 778 235">
<path style="fill:#87c214"
d="m 64.900391,0 c -9.7,0 -17.701172,7.9992183 -17.701172,17.699219 v 22.5 h 43.601562 v -22.5 C 90.800781,7.9992183 82.899219,0 73.199219,0 Z m 96.999999,0 c -9.7,0 -17.70117,7.9992183 -17.70117,17.699219 V 137.19922 h 43.60156 V 17.699219 C 187.80078,7.9992183 179.89922,0 170.19922,0 Z M 47.199219,97.800781 V 217.30078 c 0,9.7 7.901172,17.69922 17.701172,17.69922 h 8.298828 c 9.7,0 17.701172,-7.99922 17.701172,-17.69922 V 97.800781 Z m 97.000001,96.999999 v 22.5 c 0,9.7 8.00117,17.69922 17.70117,17.69922 h 8.29883 c 9.7,0 17.70117,-7.99922 17.70117,-17.69922 v -22.5 z"/>
<path style="fill:#95d220"
d="M 17.699219,47.199219 C 7.9992186,47.199219 0,55.100391 0,64.900391 v 8.298828 c 0,9.7 7.8992186,17.701172 17.699219,17.701172 H 137.19922 V 47.199219 Z m 177.101561,0 v 43.701172 h 22.5 c 9.7,0 17.69922,-7.901172 17.69922,-17.701172 v -8.298828 c 0,-9.8 -7.99922,-17.701172 -17.69922,-17.701172 z M 17.699219,144.19922 C 7.9992186,144.19922 0,152.10039 0,161.90039 v 8.29883 c 0,9.7 7.8992186,17.70117 17.699219,17.70117 h 22.5 v -43.70117 z m 80.101562,0 v 43.70117 H 217.30078 c 9.7,0 17.69922,-8.00117 17.69922,-17.70117 v -8.29883 c 0,-9.8 -7.99922,-17.70117 -17.69922,-17.70117 z"/>
<path d="M 301,60.564864 V 174.43514 h 53.31362 c 25.13729,0 38.31622,-12.58548 38.31622,-32.27441 0,-12.78766 -5.88,-22.32687 -17.63776,-27.60431 v -0.20217 c 8.91968,-5.48043 12.77339,-12.38249 12.77339,-23.140374 0,-16.238294 -11.14945,-30.648991 -34.66495,-30.648991 z m 110.68683,0 V 174.43514 h 13.37598 v -45.67022 l -1.41529,-1.41926 h 26.95811 c 15.00127,0 23.51842,5.27428 28.99185,17.04704 l 14.1887,30.04244 h 15.00139 l -16.82503,-35.52128 c -3.64896,-7.91617 -9.52848,-12.99064 -14.79921,-15.22341 v -0.20216 c 12.36593,-3.24765 22.70429,-14.41228 22.70429,-29.229734 0,-22.530633 -17.43208,-33.693671 -38.31224,-33.693671 z m 111.08726,0 V 174.43514 h 13.37992 V 60.564864 Z m 78.65821,0 -50.07469,113.870276 h 14.59701 l 12.16287,-27.40213 -0.60656,-1.41926 h 62.2336 l -0.60655,1.41926 12.16286,27.40213 h 14.59701 L 615.62098,60.564864 Z m 79.463,0 V 174.43514 h 13.37994 v -45.67022 l -1.41927,-1.41926 h 26.96209 c 15.00128,0 23.51842,5.27428 28.99185,17.04704 l 14.1887,30.04244 H 778 l -16.82503,-35.52128 c -3.64895,-7.91617 -9.52851,-12.99064 -14.79921,-15.22341 v -0.20216 c 12.36591,-3.24765 22.70427,-14.41228 22.70427,-29.229734 0,-22.530633 -17.43209,-33.693671 -38.31223,-33.693671 z M 312.96068,73.147961 h 38.72057 c 14.59584,0 22.29593,5.887175 22.29593,18.065895 0,10.148944 -6.07834,18.268094 -22.29593,18.268094 h -38.72057 l 1.41927,-1.41927 V 74.571187 Z m 110.68684,0 h 37.90786 c 13.78495,0 24.32519,5.684988 24.52791,20.908395 0,12.178724 -9.52687,20.702244 -25.94718,20.702244 h -36.48859 l 1.41529,-1.41927 V 74.571187 Z m 269.00626,0 h 37.90788 c 13.98769,0 24.53187,5.684988 24.53187,20.908395 0,12.178724 -9.52688,20.702244 -25.94718,20.702244 h -36.49257 l 1.41927,-1.41927 V 74.571187 Z m -83.92693,1.423226 h 0.20615 l 3.44509,11.366019 20.06794,45.670224 1.41924,1.41926 h -50.07071 l 1.41926,-1.41926 20.06793,-45.670224 z M 312.96068,122.06505 h 41.35294 c 16.82575,0 24.53189,7.71398 24.53189,20.09568 0,12.58468 -7.09797,19.69131 -24.53189,19.69131 h -41.35294 l 1.41927,-1.42322 v -36.94055 z"/>
</svg>
<h2 id="download_title">Download Briar 1.2.20</h2>
<span id="download_intro">Someone nearby shared Briar with you.</span>
<a href="/app.apk" class="button">
<svg aria-hidden="true"
style="width:24px;height:24px;margin-right:6px;vertical-align:middle;"
viewBox="0 0 24 24">
<path fill="currentColor" d="M5,20H19V18H5M19,9H15V3H9V9H5L12,16L19,9Z"/>
</svg>
<span id="download_button">Download Briar</span>
</a>
<span id="download_outro">After the download is complete, open the downloaded file and install it.</span>
</div>
<div id="bottom">
<h3 id="troubleshooting_title">Troubleshooting</h3>
<ol>
<li id="troubleshooting_1">If you can't download the app, try it with a different web
browser app.
</li>
<li id="troubleshooting_2">Ensure that your browser is allowed to download apps directly by
giving it the permission or enabling the installation of apps from "Unknown Sources" in
system settings.
</li>
</ol>
</div>
</body>
</html>

View File

@@ -36,8 +36,16 @@ import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.attachment.AttachmentModule;
import org.briarproject.briar.android.attachment.media.MediaModule;
import org.briarproject.briar.android.conversation.glide.BriarModelLoader;
import org.briarproject.briar.android.hotspot.AbstractTabsFragment;
import org.briarproject.briar.android.hotspot.FallbackFragment;
import org.briarproject.briar.android.hotspot.HotspotIntroFragment;
import org.briarproject.briar.android.hotspot.ManualHotspotFragment;
import org.briarproject.briar.android.hotspot.QrHotspotFragment;
import org.briarproject.briar.android.logging.CachingLogHandler;
import org.briarproject.briar.android.login.SignInReminderReceiver;
import org.briarproject.briar.android.removabledrive.ChooserFragment;
import org.briarproject.briar.android.removabledrive.ReceiveFragment;
import org.briarproject.briar.android.removabledrive.SendFragment;
import org.briarproject.briar.android.settings.ConnectionsFragment;
import org.briarproject.briar.android.settings.NotificationsFragment;
import org.briarproject.briar.android.settings.SecurityFragment;
@@ -212,4 +220,20 @@ public interface AndroidComponent
void inject(SecurityFragment securityFragment);
void inject(NotificationsFragment notificationsFragment);
void inject(HotspotIntroFragment hotspotIntroFragment);
void inject(AbstractTabsFragment abstractTabsFragment);
void inject(QrHotspotFragment qrHotspotFragment);
void inject(ManualHotspotFragment manualHotspotFragment);
void inject(FallbackFragment fallbackFragment);
void inject(ChooserFragment chooserFragment);
void inject(SendFragment sendFragment);
void inject(ReceiveFragment receiveFragment);
}

View File

@@ -30,6 +30,7 @@ import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.R;
import org.briarproject.briar.android.conversation.ConversationActivity;
import org.briarproject.briar.android.forum.ForumActivity;
import org.briarproject.briar.android.hotspot.HotspotActivity;
import org.briarproject.briar.android.login.SignInReminderReceiver;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
@@ -63,9 +64,11 @@ import static android.app.Notification.DEFAULT_SOUND;
import static android.app.Notification.DEFAULT_VIBRATE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.PendingIntent.getActivity;
import static android.content.Context.NOTIFICATION_SERVICE;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.os.Build.VERSION.SDK_INT;
import static androidx.core.app.NotificationCompat.CATEGORY_MESSAGE;
import static androidx.core.app.NotificationCompat.CATEGORY_SERVICE;
@@ -274,7 +277,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
b.setWhen(0); // Don't show the time
b.setOngoing(true);
Intent i = new Intent(appContext, SplashScreenActivity.class);
b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0));
b.setContentIntent(getActivity(appContext, 0, i, 0));
if (SDK_INT >= 21) {
b.setCategory(CATEGORY_SERVICE);
b.setVisibility(VISIBILITY_SECRET);
@@ -619,13 +622,11 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
public void showSignInNotification() {
if (blockSignInReminder) return;
if (SDK_INT >= 26) {
NotificationChannel channel =
new NotificationChannel(REMINDER_CHANNEL_ID, appContext
.getString(
R.string.reminder_notification_channel_title),
IMPORTANCE_LOW);
channel.setLockscreenVisibility(
NotificationCompat.VISIBILITY_SECRET);
NotificationChannel channel = new NotificationChannel(
REMINDER_CHANNEL_ID, appContext
.getString(R.string.reminder_notification_channel_title),
IMPORTANCE_LOW);
channel.setLockscreenVisibility(VISIBILITY_SECRET);
notificationManager.createNotificationChannel(channel);
}
@@ -652,7 +653,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
Intent i = new Intent(appContext, SplashScreenActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
b.setContentIntent(PendingIntent.getActivity(appContext, 0, i, 0));
b.setContentIntent(getActivity(appContext, 0, i, 0));
notificationManager.notify(REMINDER_NOTIFICATION_ID, b.build());
}
@@ -720,4 +721,40 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
public void unblockAllBlogPostNotifications() {
androidExecutor.runOnUiThread((Runnable) () -> blockBlogs = false);
}
@Override
public void showHotspotNotification() {
if (SDK_INT >= 26) {
String channelTitle = appContext
.getString(R.string.hotspot_notification_channel_title);
NotificationChannel channel = new NotificationChannel(
HOTSPOT_CHANNEL_ID, channelTitle, IMPORTANCE_LOW);
channel.setLockscreenVisibility(VISIBILITY_SECRET);
notificationManager.createNotificationChannel(channel);
}
BriarNotificationBuilder b =
new BriarNotificationBuilder(appContext, HOTSPOT_CHANNEL_ID);
b.setSmallIcon(R.drawable.notification_hotspot);
b.setColorRes(R.color.briar_brand_green);
b.setContentTitle(
appContext.getText(R.string.hotspot_notification_title));
b.setNotificationCategory(CATEGORY_SERVICE);
b.setOngoing(true);
b.setShowWhen(true);
String actionTitle =
appContext.getString(R.string.hotspot_button_stop_sharing);
Intent i = new Intent(appContext, HotspotActivity.class);
i.addFlags(FLAG_ACTIVITY_SINGLE_TOP);
i.setAction(ACTION_STOP_HOTSPOT);
PendingIntent actionIntent = getActivity(appContext, 0, i, 0);
int icon = SDK_INT >= 21 ? R.drawable.ic_portable_wifi_off : 0;
b.addAction(icon, actionTitle, actionIntent);
notificationManager.notify(HOTSPOT_NOTIFICATION_ID, b.build());
}
@Override
public void clearHotspotNotification() {
notificationManager.cancel(HOTSPOT_NOTIFICATION_ID);
}
}

View File

@@ -25,7 +25,6 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.reporting.DevConfig;
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
import org.briarproject.bramble.plugin.file.AndroidRemovableDrivePluginFactory;
import org.briarproject.bramble.plugin.file.RemovableDriveModule;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
import org.briarproject.bramble.util.AndroidUtils;
@@ -37,12 +36,14 @@ import org.briarproject.briar.android.blog.BlogModule;
import org.briarproject.briar.android.contact.ContactListModule;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactModule;
import org.briarproject.briar.android.forum.ForumModule;
import org.briarproject.briar.android.hotspot.HotspotModule;
import org.briarproject.briar.android.introduction.IntroductionModule;
import org.briarproject.briar.android.logging.LoggingModule;
import org.briarproject.briar.android.login.LoginModule;
import org.briarproject.briar.android.navdrawer.NavDrawerModule;
import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
import org.briarproject.briar.android.privategroup.list.GroupListModule;
import org.briarproject.briar.android.removabledrive.TransferDataModule;
import org.briarproject.briar.android.reporting.DevReportModule;
import org.briarproject.briar.android.settings.SettingsModule;
import org.briarproject.briar.android.sharing.SharingModule;
@@ -69,6 +70,7 @@ import dagger.Provides;
import static android.content.Context.MODE_PRIVATE;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap;
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
@@ -93,7 +95,8 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
GroupListModule.class,
GroupConversationModule.class,
SharingModule.class,
RemovableDriveModule.class
HotspotModule.class,
TransferDataModule.class,
})
public class AppModule {
@@ -165,7 +168,7 @@ public class AppModule {
@Override
public Collection<SimplexPluginFactory> getSimplexFactories() {
return singletonList(drive);
return SDK_INT >= 19 ? singletonList(drive) : emptyList();
}
@Override
@@ -307,6 +310,16 @@ public class AppModule {
public boolean shouldEnableConnectViaBluetooth() {
return IS_DEBUG_BUILD;
}
@Override
public boolean shouldEnableTransferData() {
return IS_DEBUG_BUILD;
}
@Override
public boolean shouldEnableShareAppViaOfflineHotspot() {
return IS_DEBUG_BUILD;
}
};
}
}

View File

@@ -51,26 +51,27 @@ public class StartupFailureActivity extends BaseActivity implements
}
// show proper error message
String errorMsg;
int errorRes;
switch (result) {
case CLOCK_ERROR:
errorRes = R.string.startup_failed_clock_error;
break;
case DATA_TOO_OLD_ERROR:
errorMsg =
getString(R.string.startup_failed_data_too_old_error);
errorRes = R.string.startup_failed_data_too_old_error;
break;
case DATA_TOO_NEW_ERROR:
errorMsg =
getString(R.string.startup_failed_data_too_new_error);
errorRes = R.string.startup_failed_data_too_new_error;
break;
case DB_ERROR:
errorMsg = getString(R.string.startup_failed_db_error);
errorRes = R.string.startup_failed_db_error;
break;
case SERVICE_ERROR:
errorMsg = getString(R.string.startup_failed_service_error);
errorRes = R.string.startup_failed_service_error;
break;
default:
throw new IllegalArgumentException();
}
showInitialFragment(ErrorFragment.newInstance(errorMsg));
showInitialFragment(ErrorFragment.newInstance(getString(errorRes)));
}
@Override

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