Compare commits

..

147 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
Sebastian Kürten
276eeb1c20 Do not increment the attempt variable twice when requesting group info 2021-07-05 12:48:58 +02: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
Torsten Grote
d4c1e132f7 Merge branch '2077-anything-to-send' into '1802-sync-via-removable-storage'
Add DB method for checking whether there's anything to send

See merge request briar/briar!1485
2021-06-17 13:30:31 +00:00
akwizgran
6b976df6a8 Add RemovableDriveManager method. 2021-06-17 13:01:33 +01:00
Torsten Grote
3e4db3b9da Merge branch '2045-flexible-sync' into '1802-sync-via-removable-storage'
Make retransmissions in the sync protocol more flexible

See merge request briar/briar!1482
2021-06-16 17:40:25 +00:00
akwizgran
0bf59eec20 Add comment explaining second client versioning message. 2021-06-16 16:26:29 +01:00
akwizgran
9f828a2222 Add DB method for checking whether there's anything to send 2021-06-16 16:25:11 +01:00
Torsten Grote
7be77b8c60 Merge branch '2038-transport-key-agreement-client' into '1802-sync-via-removable-storage'
Add transport key agreement client

See merge request briar/briar!1474
2021-06-16 12:28:00 +00:00
akwizgran
d5853e8403 Add integration test for eager retransmission. 2021-06-16 12:29:49 +01:00
akwizgran
32e9bf01ec Update DB method that gets total size of messages to send. 2021-06-16 12:29:49 +01:00
akwizgran
a5ce400341 Use eager retransmission if the transport is lossy and cheap. 2021-06-16 12:29:49 +01:00
akwizgran
a960bfb2c1 Add tests for eager retransmission. 2021-06-16 12:29:49 +01:00
akwizgran
847650f280 Replace inner classes with lambdas. 2021-06-16 12:29:49 +01:00
akwizgran
77a3199aac Update SimplexOutgoingSession to support sending unacked messages. 2021-06-16 12:29:49 +01:00
akwizgran
9a58b37ce2 Add database methods for sending unacked messages. 2021-06-16 12:29:49 +01:00
Torsten Grote
608e1eac6b Merge branch '2071-removable-drive-task-refactoring' into '1802-sync-via-removable-storage'
Refactor removable drive task management

See merge request briar/briar!1480
2021-06-15 12:23:27 +00:00
akwizgran
09de768e7e Merge branch '2038-key-manager-methods' into '1802-sync-via-removable-storage'
Key manager changes to support transport key agreement client

See merge request briar/briar!1473
2021-06-15 10:55:31 +00:00
akwizgran
faab80f0ea Hold lock while calling notifyObservers(). 2021-06-15 11:47:10 +01:00
akwizgran
07162cad8b Refactor removable drive tasks. 2021-06-15 11:44: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
ac0fc21e6e Merge branch '2038-db-methods' into '1802-sync-via-removable-storage'
New DB methods to support transport key agreement client

See merge request briar/briar!1472
2021-06-10 15:28:20 +00:00
akwizgran
dab736ce0e Merge branch '1802-defer-delivery' into '1802-sync-via-removable-storage'
Allow sync clients to defer delivery of messages

See merge request briar/briar!1471
2021-06-10 15:27:08 +00: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
bcbc96dc2d Merge branch '2037-create-removabledriveviewmodel' into '1802-sync-via-removable-storage'
Add RemovableDriveViewModel

See merge request briar/briar!1475
2021-06-09 11:32:10 +00:00
akwizgran
a72e92de24 Timestamp isn't needed for deriving root key. 2021-06-09 10:08:07 +01:00
Daniel Lublin
1ddcd6cfff Make pkg private 2021-06-08 20:31:23 +02:00
akwizgran
5dfd9e3546 Make tests more readable. 2021-06-08 17:13:18 +01:00
akwizgran
e05575b956 Add unit tests for addRotationKeys() methods. 2021-06-08 15:51:29 +01:00
Daniel Lublin
fd810f5c16 Move to new removabledrive package 2021-06-08 12:25:09 +02:00
Daniel Lublin
3f5e131250 Use US locale for now 2021-06-08 12:18:33 +02:00
Daniel Lublin
3ee516599d Add initial RemovableDriveViewModel 2021-06-07 13:17:50 +02:00
akwizgran
c703d90636 Remove unused remote timestamp from session. 2021-06-01 14:50:14 +01:00
akwizgran
e228b9fcbf Add transport key agreement client. 2021-06-01 14:18:02 +01:00
akwizgran
6e6cadd3ad Refactor KeyManager startup so managers are created earlier. 2021-06-01 14:17:12 +01:00
akwizgran
9cc8d44778 Add a key manager method for adding a single set of transport keys. 2021-06-01 11:34:27 +01:00
akwizgran
ee6f571c31 Add a DB method for checking whether transport keys exist. 2021-06-01 11:34:26 +01:00
akwizgran
2ac3bdd3ae Add database method for getting transports with keys. 2021-06-01 11:34:26 +01:00
akwizgran
e35ffe0cf0 Add javadocs for message states. 2021-06-01 11:33:06 +01:00
akwizgran
8a04d8edc4 Allow sync clients to defer delivery of messages. 2021-06-01 11:24:55 +01:00
akwizgran
a5fb3bb4a4 Merge branch '2016-2017-2018-removable-drive-reader-writer' into '1802-sync-via-removable-storage'
Create removable drive manager and reader/writer tasks

See merge request briar/briar!1458
2021-05-11 14:01:53 +00:00
akwizgran
eae329cdfa Refactor manager and tasks to remove reliance on files. 2021-05-11 12:19:16 +01:00
akwizgran
0ce0551f0d Update progress of writer task. 2021-05-11 12:19:16 +01:00
akwizgran
a198e7d08e Ensure that observers see the final state even if they're added late. 2021-05-11 12:19:16 +01:00
akwizgran
bca6f1506e Add integration test for syncing via removable drives. 2021-05-11 12:19:16 +01:00
akwizgran
e420201b00 Implement RemovableDriveWriterTask, except for progress updates. 2021-05-11 12:19:16 +01:00
akwizgran
03248d04e5 Fix typo in class names. 2021-05-11 12:19:16 +01:00
akwizgran
2c39b02644 Implement RemovableDriverReaderTask. 2021-05-11 12:19:16 +01:00
akwizgran
c9c6f3682c Add task factory. 2021-05-11 12:19:16 +01:00
akwizgran
8f4a0ef030 Add removable drive manager with placeholder task implementations. 2021-05-11 12:19:14 +01:00
akwizgran
5fe22bcd57 Merge branch '2035-android-removable-drive-plugin' into '1802-sync-via-removable-storage'
Add Android implementation of RemovableDrivePlugin

See merge request briar/briar!1457
2021-05-11 11:13:14 +00:00
akwizgran
b4880af7e2 Add Android implementation of RemovableDrivePlugin. 2021-05-10 14:19:24 +01:00
akwizgran
51d21bd669 Decouple RemovableDrivePlugin from FileConstants. 2021-05-10 13:48:12 +01:00
Torsten Grote
b8f3728a0d Merge branch '2015-removable-drive-plugin' into '1802-sync-via-removable-storage'
Create RemovableDrivePlugin

See merge request briar/briar!1454
2021-05-10 12:47:21 +00:00
akwizgran
bbfd4f137d Merge branch '2013-db-method-for-amount-of-data-to-sync' into '1802-sync-via-removable-storage'
Add DB method for getting amount of data to sync

See merge request briar/briar!1452
2021-05-10 12:00:11 +00:00
Daniel Lublin
7e3ca76dd1 Merge branch '2014-messages-sent-event' into '1802-sync-via-removable-storage'
Update MessagesSentEvent to include amount of data sent

See merge request briar/briar!1453
2021-05-10 11:44:27 +00:00
akwizgran
524c8d26f8 Don't inject default RemovableDrivePluginFactory on Android. 2021-05-07 17:48:39 +01:00
akwizgran
7eccf7dac1 Decouple removable drive plugin from java.io.File for portability. 2021-05-07 17:36:10 +01:00
akwizgran
0bc06248ed Clean up plugin injection code, remove unused module. 2021-05-06 16:59:45 +01:00
akwizgran
c999f05cc7 Configure removable drive plugin for Android. 2021-05-06 16:59:45 +01:00
akwizgran
428269b312 Add removable drive plugin. 2021-05-06 16:59:45 +01:00
akwizgran
588e05ce83 Update MessagesSentEvent to include amount of data sent. 2021-05-06 16:20:15 +01:00
akwizgran
f7875c99b6 Add DB method for getting amount of data to sync. 2021-05-05 17:52:37 +01:00
269 changed files with 3122 additions and 6864 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -15,8 +15,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 30 targetSdkVersion 30
versionCode 10403 versionCode 10305
versionName "1.4.3" versionName "1.3.5"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -42,8 +42,8 @@ configurations {
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
tor "org.briarproject:tor-android:$tor_version" tor 'org.briarproject:tor-android:0.3.5.15'
tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version@zip" tor 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a@zip'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"

View File

@@ -20,7 +20,7 @@ import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.I
public class AndroidRemovableDrivePluginFactory implements public class AndroidRemovableDrivePluginFactory implements
SimplexPluginFactory { SimplexPluginFactory {
private static final long MAX_LATENCY = DAYS.toMillis(28); private static final int MAX_LATENCY = (int) DAYS.toMillis(14);
private final Application app; private final Application app;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -107,12 +107,6 @@ public interface ContactManager {
*/ */
String getHandshakeLink() throws DbException; String getHandshakeLink() throws DbException;
/**
* Returns the handshake link that needs to be sent to a contact we want
* to add.
*/
String getHandshakeLink(Transaction txn) throws DbException;
/** /**
* Creates a {@link PendingContact} from the given handshake link and * Creates a {@link PendingContact} from the given handshake link and
* alias, adds it to the database and returns it. * alias, adds it to the database and returns it.

View File

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

View File

@@ -471,14 +471,6 @@ public interface DatabaseComponent extends TransactionManager {
Map<MessageId, Integer> getUnackedMessagesToSend(Transaction txn, Map<MessageId, Integer> getUnackedMessagesToSend(Transaction txn,
ContactId c) throws DbException; ContactId c) throws DbException;
/**
* Reset the transmission count, expiry time and ETA of all messages that
* are eligible to be sent to the given contact. This includes messages that
* have already been sent and are not yet due for retransmission.
*/
void resetUnackedMessagesToSend(Transaction txn, ContactId c)
throws DbException;
/** /**
* Returns the total length, including headers, of all messages that are * Returns the total length, including headers, of all messages that are
* eligible to be sent to the given contact. This may include messages * eligible to be sent to the given contact. This may include messages

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,9 +14,9 @@ public interface RemovableDriveTask extends Runnable {
TransportProperties getTransportProperties(); TransportProperties getTransportProperties();
/** /**
* Adds an observer to the task. The observer will be notified on the * Adds an observer to the task. The observer will be notified of state
* event thread of the current state of the task and any subsequent state * changes on the event thread. If the task has already finished, the
* changes. * observer will be notified of its final state.
*/ */
void addObserver(Consumer<State> observer); void addObserver(Consumer<State> observer);

View File

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

View File

@@ -113,25 +113,9 @@ public interface KeyManager {
/** /**
* Looks up the given tag and returns a {@link StreamContext} for reading * Looks up the given tag and returns a {@link StreamContext} for reading
* from the corresponding stream, or null if an error occurs or the tag was * from the corresponding stream, or null if an error occurs or the tag was
* unexpected. Marks the tag as recognised and updates the reordering * unexpected.
* window.
*/ */
@Nullable @Nullable
StreamContext getStreamContext(TransportId t, byte[] tag) StreamContext getStreamContext(TransportId t, byte[] tag)
throws DbException; throws DbException;
/**
* Looks up the given tag and returns a {@link StreamContext} for reading
* from the corresponding stream, or null if an error occurs or the tag was
* unexpected. Only returns the StreamContext; does not mark the tag as
* recognised.
*/
@Nullable
StreamContext getStreamContextOnly(TransportId t, byte[] tag)
throws DbException;
/**
* Marks the tag as recognised and updates the reordering window.
*/
void markTagAsRecognised(TransportId t, byte[] tag) throws DbException;
} }

View File

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

View File

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

View File

@@ -10,8 +10,8 @@ dependencyVerification {
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0', '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.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.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249', 'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
@@ -21,7 +21,7 @@ dependencyVerification {
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', '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.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984', '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:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de', 'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
] ]
} }

View File

@@ -10,7 +10,7 @@ apply from: '../dagger.gradle'
dependencies { dependencies {
implementation project(path: ':bramble-api', configuration: 'default') implementation project(path: ':bramble-api', configuration: 'default')
implementation 'org.bouncycastle:bcprov-jdk15on:1.69' implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0' implementation 'net.i2p.crypto:eddsa:0.2.0'
@@ -32,14 +32,6 @@ dependencies {
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }
animalsniffer {
// Allow requireNonNull: Android desugaring rewrites it (so it's safe for us to use),
// and it gets used when passing method references instead of lambdas with Java 11.
// Note that this line allows *all* methods from java.util.Objects.
// That's the best that we can do with the configuration options that Animal Sniffer offers.
ignore 'java.util.Objects'
}
// needed to make test output available to bramble-java // needed to make test output available to bramble-java
configurations { configurations {
testOutput.extendsFrom(testCompile) testOutput.extendsFrom(testCompile)

View File

@@ -14,7 +14,6 @@ import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.io.IoModule; import org.briarproject.bramble.io.IoModule;
import org.briarproject.bramble.keyagreement.KeyAgreementModule; import org.briarproject.bramble.keyagreement.KeyAgreementModule;
import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.mailbox.MailboxModule;
import org.briarproject.bramble.plugin.PluginModule; import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.properties.PropertiesModule; import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.record.RecordModule; import org.briarproject.bramble.record.RecordModule;
@@ -44,7 +43,6 @@ import dagger.Module;
IoModule.class, IoModule.class,
KeyAgreementModule.class, KeyAgreementModule.class,
LifecycleModule.class, LifecycleModule.class,
MailboxModule.class,
PluginModule.class, PluginModule.class,
PropertiesModule.class, PropertiesModule.class,
RecordModule.class, RecordModule.class,

View File

@@ -121,12 +121,8 @@ class ContactManagerImpl implements ContactManager, EventListener {
@Override @Override
public String getHandshakeLink() throws DbException { public String getHandshakeLink() throws DbException {
return db.transactionWithResult(true, this::getHandshakeLink); KeyPair keyPair = db.transactionWithResult(true,
} identityManager::getHandshakeKeys);
@Override
public String getHandshakeLink(Transaction txn) throws DbException {
KeyPair keyPair = identityManager.getHandshakeKeys(txn);
return pendingContactFactory.createHandshakeLink(keyPair.getPublic()); return pendingContactFactory.createHandshakeLink(keyPair.getPublic());
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -757,13 +757,6 @@ interface Database<T> {
*/ */
void resetExpiryTime(T txn, ContactId c, MessageId m) throws DbException; void resetExpiryTime(T txn, ContactId c, MessageId m) throws DbException;
/**
* Resets the transmission count, expiry time and ETA of all messages that
* are eligible to be sent to the given contact. This includes messages that
* have already been sent and are not yet due for retransmission.
*/
void resetUnackedMessagesToSend(T txn, ContactId c) throws DbException;
/** /**
* Sets the cleanup timer duration for the given message. This does not * Sets the cleanup timer duration for the given message. This does not
* start the message's cleanup timer. * start the message's cleanup timer.
@@ -852,8 +845,8 @@ interface Database<T> {
* of the given message with respect to the given contact, using the latency * of the given message with respect to the given contact, using the latency
* of the transport over which it was sent. * of the transport over which it was sent.
*/ */
void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m, long maxLatency)
long maxLatency) throws DbException; throws DbException;
/** /**
* Stores the given transport keys, deleting any keys they have replaced. * Stores the given transport keys, deleting any keys they have replaced.

View File

@@ -750,15 +750,6 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
return db.getUnackedMessagesToSend(txn, c); return db.getUnackedMessagesToSend(txn, c);
} }
@Override
public void resetUnackedMessagesToSend(Transaction transaction, ContactId c)
throws DbException {
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
db.resetUnackedMessagesToSend(txn, c);
}
@Override @Override
public long getUnackedMessageBytesToSend(Transaction transaction, public long getUnackedMessageBytesToSend(Transaction transaction,
ContactId c) throws DbException { ContactId c) throws DbException {

View File

@@ -429,11 +429,8 @@ abstract class JdbcDatabase implements Database<Connection> {
compactAndClose(); compactAndClose();
logDuration(LOG, "Compacting database", start); logDuration(LOG, "Compacting database", start);
// Allow the next transaction to reopen the DB // Allow the next transaction to reopen the DB
connectionsLock.lock(); synchronized (connectionsLock) {
try {
closed = false; closed = false;
} finally {
connectionsLock.unlock();
} }
txn = startTransaction(); txn = startTransaction();
try { try {
@@ -2334,7 +2331,7 @@ abstract class JdbcDatabase implements Database<Connection> {
ps.setInt(2, DELIVERED.getValue()); ps.setInt(2, DELIVERED.getValue());
rs = ps.executeQuery(); rs = ps.executeQuery();
rs.next(); rs.next();
long total = rs.getLong(1); long total = rs.getInt(1);
rs.close(); rs.close();
ps.close(); ps.close();
return total; return total;
@@ -3293,29 +3290,6 @@ abstract class JdbcDatabase implements Database<Connection> {
} }
} }
@Override
public void resetUnackedMessagesToSend(Connection txn, ContactId c)
throws DbException {
PreparedStatement ps = null;
try {
String sql = "UPDATE statuses SET expiry = 0, txCount = 0, eta = 0"
+ " WHERE contactId = ? AND state = ?"
+ " AND groupShared = TRUE AND messageShared = TRUE"
+ " AND deleted = FALSE AND seen = FALSE";
ps = txn.prepareStatement(sql);
ps.setInt(1, c.getInt());
ps.setInt(2, DELIVERED.getValue());
int affected = ps.executeUpdate();
if (affected < 0) {
throw new DbStateException();
}
ps.close();
} catch (SQLException e) {
tryToClose(ps, LOG, WARNING);
throw new DbException(e);
}
}
@Override @Override
public void setCleanupTimerDuration(Connection txn, MessageId m, public void setCleanupTimerDuration(Connection txn, MessageId m,
long duration) throws DbException { long duration) throws DbException {

View File

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

View File

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

View File

@@ -28,9 +28,11 @@ import java.net.InterfaceAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -51,7 +53,7 @@ import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.IoUtils.tryToClose;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@@ -96,6 +98,7 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
/** /**
* Returns true if connections to the given address can be attempted. * Returns true if connections to the given address can be attempted.
*/ */
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
protected abstract boolean isConnectable(InterfaceAddress local, protected abstract boolean isConnectable(InterfaceAddress local,
InetSocketAddress remote); InetSocketAddress remote);
@@ -395,6 +398,17 @@ abstract class TcpPlugin implements DuplexPlugin, EventListener {
return addrs; return addrs;
} }
private List<NetworkInterface> getNetworkInterfaces() {
try {
Enumeration<NetworkInterface> ifaces =
NetworkInterface.getNetworkInterfaces();
return ifaces == null ? emptyList() : list(ifaces);
} catch (SocketException e) {
logException(LOG, WARNING, e);
return emptyList();
}
}
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof SettingsUpdatedEvent) { if (e instanceof SettingsUpdatedEvent) {

View File

@@ -1,71 +1,40 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List; import java.util.List;
@NotNullByDefault // TODO: Create a module for this so it doesn't have to be public
public interface CircumventionProvider {
enum BridgeType { public interface CircumventionProvider {
DEFAULT_OBFS4,
NON_DEFAULT_OBFS4,
MEEK
}
/** /**
* Countries where Tor is blocked, i.e. vanilla Tor connection won't work. * Countries where Tor is blocked, i.e. vanilla Tor connection won't work.
* <p> *
* See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 * See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
* and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki * and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
*/ */
String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE", "RU"}; String[] BLOCKED = {"CN", "IR", "EG", "BY", "TR", "SY", "VE"};
/** /**
* Countries where obfs4 or meek bridge connections are likely to work. * Countries where obfs4 or meek bridge connections are likely to work.
* Should be a subset of {@link #BLOCKED} and the union of * Should be a subset of {@link #BLOCKED}.
* {@link #DEFAULT_OBFS4_BRIDGES}, {@link #NON_DEFAULT_OBFS4_BRIDGES} and
* {@link #MEEK_BRIDGES}.
*/ */
String[] BRIDGES = {"CN", "IR", "EG", "BY", "TR", "SY", "VE", "RU"}; String[] BRIDGES = { "CN", "IR", "EG", "BY", "TR", "SY", "VE" };
/**
* Countries where default obfs4 bridges are likely to work.
* Should be a subset of {@link #BRIDGES}.
*/
String[] DEFAULT_OBFS4_BRIDGES = {"EG", "BY", "TR", "SY", "VE"};
/**
* Countries where non-default obfs4 bridges are likely to work.
* Should be a subset of {@link #BRIDGES}.
*/
String[] NON_DEFAULT_OBFS4_BRIDGES = {"RU"};
/** /**
* Countries where obfs4 bridges won't work and meek is needed. * Countries where obfs4 bridges won't work and meek is needed.
* Should be a subset of {@link #BRIDGES}. * Should be a subset of {@link #BRIDGES}.
*/ */
String[] MEEK_BRIDGES = {"CN", "IR"}; String[] NEEDS_MEEK = {"CN", "IR"};
/**
* Returns true if vanilla Tor connections are blocked in the given country.
*/
boolean isTorProbablyBlocked(String countryCode); boolean isTorProbablyBlocked(String countryCode);
/**
* Returns true if bridge connections of some type work in the given
* country.
*/
boolean doBridgesWork(String countryCode); boolean doBridgesWork(String countryCode);
/** boolean needsMeek(String countryCode);
* Returns the best type of bridge connection for the given country, or
* {@link #DEFAULT_OBFS4_BRIDGES} if no bridge type is known to work.
*/
BridgeType getBestBridgeType(String countryCode);
@IoExecutor @IoExecutor
List<String> getBridges(BridgeType type); List<String> getBridges(boolean meek);
} }

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@@ -10,31 +9,24 @@ import java.util.List;
import java.util.Scanner; import java.util.Scanner;
import java.util.Set; import java.util.Set;
import javax.annotation.concurrent.Immutable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.DEFAULT_OBFS4;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4;
@Immutable
@NotNullByDefault
class CircumventionProviderImpl implements CircumventionProvider { class CircumventionProviderImpl implements CircumventionProvider {
private final static String BRIDGE_FILE_NAME = "bridges"; private final static String BRIDGE_FILE_NAME = "bridges";
private static final Set<String> BLOCKED_IN_COUNTRIES = private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<>(asList(BLOCKED)); new HashSet<>(asList(BLOCKED));
private static final Set<String> BRIDGE_COUNTRIES = private static final Set<String> BRIDGES_WORK_IN_COUNTRIES =
new HashSet<>(asList(BRIDGES)); new HashSet<>(asList(BRIDGES));
private static final Set<String> DEFAULT_OBFS4_BRIDGE_COUNTRIES = private static final Set<String> BRIDGES_NEED_MEEK =
new HashSet<>(asList(DEFAULT_OBFS4_BRIDGES)); new HashSet<>(asList(NEEDS_MEEK));
private static final Set<String> NON_DEFAULT_OBFS4_BRIDGE_COUNTRIES =
new HashSet<>(asList(NON_DEFAULT_OBFS4_BRIDGES)); @Nullable
private static final Set<String> MEEK_COUNTRIES = private volatile List<String> bridges = null;
new HashSet<>(asList(MEEK_BRIDGES));
@Inject @Inject
CircumventionProviderImpl() { CircumventionProviderImpl() {
@@ -47,42 +39,33 @@ class CircumventionProviderImpl implements CircumventionProvider {
@Override @Override
public boolean doBridgesWork(String countryCode) { public boolean doBridgesWork(String countryCode) {
return BRIDGE_COUNTRIES.contains(countryCode); return BRIDGES_WORK_IN_COUNTRIES.contains(countryCode);
} }
@Override @Override
public BridgeType getBestBridgeType(String countryCode) { public boolean needsMeek(String countryCode) {
if (DEFAULT_OBFS4_BRIDGE_COUNTRIES.contains(countryCode)) { return BRIDGES_NEED_MEEK.contains(countryCode);
return DEFAULT_OBFS4;
} else if (NON_DEFAULT_OBFS4_BRIDGE_COUNTRIES.contains(countryCode)) {
return NON_DEFAULT_OBFS4;
} else if (MEEK_COUNTRIES.contains(countryCode)) {
return MEEK;
} else {
return DEFAULT_OBFS4;
}
} }
@Override @Override
@IoExecutor @IoExecutor
public List<String> getBridges(BridgeType type) { public List<String> getBridges(boolean useMeek) {
InputStream is = requireNonNull(getClass().getClassLoader() List<String> bridges = this.bridges;
.getResourceAsStream(BRIDGE_FILE_NAME)); if (bridges != null) return new ArrayList<>(bridges);
InputStream is = getClass().getClassLoader()
.getResourceAsStream(BRIDGE_FILE_NAME);
Scanner scanner = new Scanner(is); Scanner scanner = new Scanner(is);
List<String> bridges = new ArrayList<>(); bridges = new ArrayList<>();
while (scanner.hasNextLine()) { while (scanner.hasNextLine()) {
String line = scanner.nextLine(); String line = scanner.nextLine();
boolean isDefaultObfs4 = line.startsWith("d "); boolean isMeekBridge = line.startsWith("Bridge meek");
boolean isNonDefaultObfs4 = line.startsWith("n "); if (useMeek && !isMeekBridge || !useMeek && isMeekBridge) continue;
boolean isMeek = line.startsWith("m "); if (!line.startsWith("#")) bridges.add(line);
if ((type == DEFAULT_OBFS4 && isDefaultObfs4) ||
(type == NON_DEFAULT_OBFS4 && isNonDefaultObfs4) ||
(type == MEEK && isMeek)) {
bridges.add(line.substring(2));
}
} }
scanner.close(); scanner.close();
this.bridges = bridges;
return bridges; return bridges;
} }

View File

@@ -33,9 +33,7 @@ import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType;
import java.io.ByteArrayInputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@@ -46,7 +44,6 @@ import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -71,16 +68,20 @@ import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS; import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY; import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED; import static org.briarproject.bramble.api.plugin.Plugin.State.DISABLED;
import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING; import static org.briarproject.bramble.api.plugin.Plugin.State.ENABLING;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING; import static org.briarproject.bramble.api.plugin.Plugin.State.STARTING_STOPPING;
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_PLUGIN_ENABLE; import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_PLUGIN_ENABLE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_MOBILE; import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_MOBILE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_NETWORK; import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_NETWORK;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING; import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_PREF_TOR_ONLY_WHEN_CHARGING;
import static org.briarproject.bramble.api.plugin.TorConstants.HS_PRIVATE_KEY_V2;
import static org.briarproject.bramble.api.plugin.TorConstants.HS_PRIVATE_KEY_V3; import static org.briarproject.bramble.api.plugin.TorConstants.HS_PRIVATE_KEY_V3;
import static org.briarproject.bramble.api.plugin.TorConstants.HS_V3_CREATED;
import static org.briarproject.bramble.api.plugin.TorConstants.ID; import static org.briarproject.bramble.api.plugin.TorConstants.ID;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_MOBILE;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK;
@@ -89,11 +90,12 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_ONLY_WHEN_CHARGING;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT; import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V2;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3; import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY; import static org.briarproject.bramble.api.plugin.TorConstants.REASON_BATTERY;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED; import static org.briarproject.bramble.api.plugin.TorConstants.REASON_COUNTRY_BLOCKED;
import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA; import static org.briarproject.bramble.api.plugin.TorConstants.REASON_MOBILE_DATA;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK; import static org.briarproject.bramble.api.plugin.TorConstants.V3_MIGRATION_PERIOD_MS;
import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES; import static org.briarproject.bramble.plugin.tor.TorRendezvousCrypto.SEED_BYTES;
import static org.briarproject.bramble.util.IoUtils.copyAndClose; import static org.briarproject.bramble.util.IoUtils.copyAndClose;
import static org.briarproject.bramble.util.IoUtils.tryToClose; import static org.briarproject.bramble.util.IoUtils.tryToClose;
@@ -113,6 +115,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String OWNER = "__OwningControllerProcess"; private static final String OWNER = "__OwningControllerProcess";
private static final int COOKIE_TIMEOUT_MS = 3000; private static final int COOKIE_TIMEOUT_MS = 3000;
private static final int COOKIE_POLLING_INTERVAL_MS = 200; private static final int COOKIE_POLLING_INTERVAL_MS = 200;
private static final Pattern ONION_V2 = Pattern.compile("[a-z2-7]{16}");
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}"); private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
private final Executor ioExecutor, wakefulIoExecutor; private final Executor ioExecutor, wakefulIoExecutor;
@@ -129,11 +132,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final CircumventionProvider circumventionProvider; private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider; private final ResourceProvider resourceProvider;
private final long maxLatency; private final long maxLatency;
private final int maxIdleTime; private final int maxIdleTime, socketTimeout;
private final int socketTimeout;
private final File torDirectory, geoIpFile, configFile; private final File torDirectory, geoIpFile, configFile;
private final int torSocksPort;
private final int torControlPort;
private final File doneFile, cookieFile; private final File doneFile, cookieFile;
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
@@ -162,9 +162,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
String architecture, String architecture,
long maxLatency, long maxLatency,
int maxIdleTime, int maxIdleTime,
File torDirectory, File torDirectory) {
int torSocksPort,
int torControlPort) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor; this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager; this.networkManager = networkManager;
@@ -184,8 +182,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
socketTimeout = Integer.MAX_VALUE; socketTimeout = Integer.MAX_VALUE;
else socketTimeout = maxIdleTime * 2; else socketTimeout = maxIdleTime * 2;
this.torDirectory = torDirectory; this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort;
geoIpFile = new File(torDirectory, "geoip"); geoIpFile = new File(torDirectory, "geoip");
configFile = new File(torDirectory, "torrc"); configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done"); doneFile = new File(torDirectory, "done");
@@ -281,7 +277,6 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (LOG.isLoggable(INFO)) listFiles(torDirectory); if (LOG.isLoggable(INFO)) listFiles(torDirectory);
throw new PluginException(); throw new PluginException();
} }
//noinspection BusyWait
Thread.sleep(COOKIE_POLLING_INTERVAL_MS); Thread.sleep(COOKIE_POLLING_INTERVAL_MS);
} }
LOG.info("Auth cookie created"); LOG.info("Auth cookie created");
@@ -292,7 +287,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} }
try { try {
// Open a control connection and authenticate using the cookie file // Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", torControlPort); controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket); controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile)); controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed // Tell Tor to exit when the control connection is closed
@@ -395,24 +390,9 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return zin; return zin;
} }
private static void append(StringBuilder strb, String name, int value) {
strb.append(name);
strb.append(" ");
strb.append(value);
strb.append("\n");
}
private InputStream getConfigInputStream() { private InputStream getConfigInputStream() {
StringBuilder strb = new StringBuilder(); ClassLoader cl = getClass().getClassLoader();
append(strb, "ControlPort", torControlPort); return requireNonNull(cl.getResourceAsStream("torrc"));
append(strb, "CookieAuthentication", 1);
append(strb, "DisableNetwork", 1);
append(strb, "RunAsDaemon", 1);
append(strb, "SafeSocks", 1);
append(strb, "SocksPort", torSocksPort);
//noinspection CharsetObjectCanBeUsed
return new ByteArrayInputStream(
strb.toString().getBytes(Charset.forName("UTF-8")));
} }
private void listFiles(File f) { private void listFiles(File f) {
@@ -477,10 +457,54 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private void publishHiddenService(String port) { private void publishHiddenService(String port) {
if (!state.isTorRunning()) return; if (!state.isTorRunning()) return;
// TODO: Remove support for v2 hidden services after a reasonable
// migration period (migration started 2020-06-30)
String privKey2 = settings.get(HS_PRIVATE_KEY_V2);
String privKey3 = settings.get(HS_PRIVATE_KEY_V3); String privKey3 = settings.get(HS_PRIVATE_KEY_V3);
String v3Created = settings.get(HS_V3_CREATED);
// Publish a v2 hidden service if we've already created one, and
// either we've never published a v3 hidden service or we're still
// in the migration period since first publishing it
if (!isNullOrEmpty(privKey2)) {
long now = clock.currentTimeMillis();
long then = v3Created == null ? now : Long.parseLong(v3Created);
if (now - then >= V3_MIGRATION_PERIOD_MS) retireV2HiddenService();
else publishV2HiddenService(port, privKey2);
}
publishV3HiddenService(port, privKey3); publishV3HiddenService(port, privKey3);
} }
private void publishV2HiddenService(String port, String privKey) {
LOG.info("Creating v2 hidden service");
Map<Integer, String> portLines = singletonMap(80, "127.0.0.1:" + port);
Map<String, String> response;
try {
response = controlConnection.addOnion(privKey, portLines);
} catch (IOException e) {
logException(LOG, WARNING, e);
return;
}
if (!response.containsKey(HS_ADDRESS)) {
LOG.warning("Tor did not return a hidden service address");
return;
}
String onion2 = response.get(HS_ADDRESS);
if (LOG.isLoggable(INFO)) {
LOG.info("V2 hidden service " + scrubOnion(onion2));
}
// The hostname has already been published and the private key stored
}
private void retireV2HiddenService() {
LOG.info("Retiring v2 hidden service");
TransportProperties p = new TransportProperties();
p.put(PROP_ONION_V2, "");
callback.mergeLocalProperties(p);
Settings s = new Settings();
s.put(HS_PRIVATE_KEY_V2, "");
callback.mergeSettings(s);
}
private void publishV3HiddenService(String port, @Nullable String privKey) { private void publishV3HiddenService(String port, @Nullable String privKey) {
LOG.info("Creating v3 hidden service"); LOG.info("Creating v3 hidden service");
Map<Integer, String> portLines = singletonMap(80, "127.0.0.1:" + port); Map<Integer, String> portLines = singletonMap(80, "127.0.0.1:" + port);
@@ -517,6 +541,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
// Save the hidden service's private key for next time // Save the hidden service's private key for next time
Settings s = new Settings(); Settings s = new Settings();
s.put(HS_PRIVATE_KEY_V3, response.get(HS_PRIVKEY)); s.put(HS_PRIVATE_KEY_V3, response.get(HS_PRIVKEY));
s.put(HS_V3_CREATED, String.valueOf(clock.currentTimeMillis()));
callback.mergeSettings(s); callback.mergeSettings(s);
} }
} }
@@ -544,20 +569,20 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
controlConnection.setConf("DisableNetwork", enable ? "0" : "1"); controlConnection.setConf("DisableNetwork", enable ? "0" : "1");
} }
private void enableBridges(boolean enable, BridgeType bridgeType) private void enableBridges(boolean enable, boolean needsMeek)
throws IOException { throws IOException {
if (enable) { if (enable) {
Collection<String> conf = new ArrayList<>(); Collection<String> conf = new ArrayList<>();
conf.add("UseBridges 1"); conf.add("UseBridges 1");
File obfs4File = getObfs4ExecutableFile(); File obfs4File = getObfs4ExecutableFile();
if (bridgeType == MEEK) { if (needsMeek) {
conf.add("ClientTransportPlugin meek_lite exec " + conf.add("ClientTransportPlugin meek_lite exec " +
obfs4File.getAbsolutePath()); obfs4File.getAbsolutePath());
} else { } else {
conf.add("ClientTransportPlugin obfs4 exec " + conf.add("ClientTransportPlugin obfs4 exec " +
obfs4File.getAbsolutePath()); obfs4File.getAbsolutePath());
} }
conf.addAll(circumventionProvider.getBridges(bridgeType)); conf.addAll(circumventionProvider.getBridges(needsMeek));
controlConnection.setConf(conf); controlConnection.setConf(conf);
} else { } else {
controlConnection.setConf("UseBridges", "0"); controlConnection.setConf("UseBridges", "0");
@@ -623,30 +648,49 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public DuplexTransportConnection createConnection(TransportProperties p) { public DuplexTransportConnection createConnection(TransportProperties p) {
if (getState() != ACTIVE) return null; if (getState() != ACTIVE) return null;
// TODO: Remove support for v2 hidden services after a reasonable
// migration period (migration started 2020-06-30)
String bestOnion = null, version = null;
String onion2 = p.get(PROP_ONION_V2);
String onion3 = p.get(PROP_ONION_V3); String onion3 = p.get(PROP_ONION_V3);
if (onion3 != null && !ONION_V3.matcher(onion3).matches()) { if (!isNullOrEmpty(onion2)) {
// Don't scrub the address so we can find the problem if (ONION_V2.matcher(onion2).matches()) {
if (LOG.isLoggable(INFO)) { bestOnion = onion2;
LOG.info("Invalid v3 hostname: " + onion3); version = "v2";
} else {
// Don't scrub the address so we can find the problem
if (LOG.isLoggable(INFO))
LOG.info("Invalid v2 hostname: " + onion2);
} }
onion3 = null;
} }
if (onion3 == null) return null; if (!isNullOrEmpty(onion3)) {
if (ONION_V3.matcher(onion3).matches()) {
bestOnion = onion3;
version = "v3";
} else {
// Don't scrub the address so we can find the problem
if (LOG.isLoggable(INFO))
LOG.info("Invalid v3 hostname: " + onion3);
}
}
if (bestOnion == null) return null;
Socket s = null; Socket s = null;
try { try {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("Connecting to v3 " + scrubOnion(onion3)); LOG.info("Connecting to " + version + " "
+ scrubOnion(bestOnion));
} }
s = torSocketFactory.createSocket(onion3 + ".onion", 80); s = torSocketFactory.createSocket(bestOnion + ".onion", 80);
s.setSoTimeout(socketTimeout); s.setSoTimeout(socketTimeout);
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("Connected to v3 " + scrubOnion(onion3)); LOG.info("Connected to " + version + " "
+ scrubOnion(bestOnion));
} }
return new TorTransportConnection(this, s); return new TorTransportConnection(this, s);
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(INFO)) { if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to v3 " LOG.info("Could not connect to " + version + " "
+ scrubOnion(onion3) + ": " + e.toString()); + scrubOnion(bestOnion) + ": " + e.toString());
} }
tryToClose(s, LOG, WARNING); tryToClose(s, LOG, WARNING);
return null; return null;
@@ -846,9 +890,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
int reasonsDisabled = 0; int reasonsDisabled = 0;
boolean enableNetwork = false, enableBridges = false; boolean enableNetwork = false, enableBridges = false;
boolean enableConnectionPadding = false; boolean useMeek = false, enableConnectionPadding = false;
BridgeType bridgeType =
circumventionProvider.getBestBridgeType(country);
if (!online) { if (!online) {
LOG.info("Disabling network, device is offline"); LOG.info("Disabling network, device is offline");
@@ -877,10 +919,14 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
enableNetwork = true; enableNetwork = true;
if (network == PREF_TOR_NETWORK_WITH_BRIDGES || if (network == PREF_TOR_NETWORK_WITH_BRIDGES ||
(automatic && bridgesWork)) { (automatic && bridgesWork)) {
if (ipv6Only) bridgeType = MEEK; if (ipv6Only ||
enableBridges = true; circumventionProvider.needsMeek(country)) {
if (LOG.isLoggable(INFO)) { LOG.info("Using meek bridges");
LOG.info("Using bridge type " + bridgeType); enableBridges = true;
useMeek = true;
} else {
LOG.info("Using obfs4 bridges");
enableBridges = true;
} }
} else { } else {
LOG.info("Not using bridges"); LOG.info("Not using bridges");
@@ -898,7 +944,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
try { try {
if (enableNetwork) { if (enableNetwork) {
enableBridges(enableBridges, bridgeType); enableBridges(enableBridges, useMeek);
enableConnectionPadding(enableConnectionPadding); enableConnectionPadding(enableConnectionPadding);
useIpv6(ipv6Only); useIpv6(ipv6Only);
} }
@@ -938,17 +984,17 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Nullable @Nullable
private ServerSocket serverSocket = null; private ServerSocket serverSocket = null;
private synchronized void setStarted() { synchronized void setStarted() {
started = true; started = true;
callback.pluginStateChanged(getState()); callback.pluginStateChanged(getState());
} }
private synchronized boolean isTorRunning() { synchronized boolean isTorRunning() {
return started && !stopped; return started && !stopped;
} }
@Nullable @Nullable
private synchronized ServerSocket setStopped() { synchronized ServerSocket setStopped() {
stopped = true; stopped = true;
ServerSocket ss = serverSocket; ServerSocket ss = serverSocket;
serverSocket = null; serverSocket = null;
@@ -956,44 +1002,44 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return ss; return ss;
} }
private synchronized void setBootstrapped() { synchronized void setBootstrapped() {
bootstrapped = true; bootstrapped = true;
callback.pluginStateChanged(getState()); callback.pluginStateChanged(getState());
} }
private synchronized boolean getAndSetCircuitBuilt() { synchronized boolean getAndSetCircuitBuilt() {
boolean firstCircuit = !circuitBuilt; boolean firstCircuit = !circuitBuilt;
circuitBuilt = true; circuitBuilt = true;
callback.pluginStateChanged(getState()); callback.pluginStateChanged(getState());
return firstCircuit; return firstCircuit;
} }
private synchronized void enableNetwork(boolean enable) { synchronized void enableNetwork(boolean enable) {
networkInitialised = true; networkInitialised = true;
networkEnabled = enable; networkEnabled = enable;
if (!enable) circuitBuilt = false; if (!enable) circuitBuilt = false;
callback.pluginStateChanged(getState()); callback.pluginStateChanged(getState());
} }
private synchronized void setReasonsDisabled(int reasonsDisabled) { synchronized void setReasonsDisabled(int reasonsDisabled) {
settingsChecked = true; settingsChecked = true;
this.reasonsDisabled = reasonsDisabled; this.reasonsDisabled = reasonsDisabled;
callback.pluginStateChanged(getState()); callback.pluginStateChanged(getState());
} }
// Doesn't affect getState() // Doesn't affect getState()
private synchronized boolean setServerSocket(ServerSocket ss) { synchronized boolean setServerSocket(ServerSocket ss) {
if (stopped || serverSocket != null) return false; if (stopped || serverSocket != null) return false;
serverSocket = ss; serverSocket = ss;
return true; return true;
} }
// Doesn't affect getState() // Doesn't affect getState()
private synchronized void clearServerSocket(ServerSocket ss) { synchronized void clearServerSocket(ServerSocket ss) {
if (serverSocket == ss) serverSocket = null; if (serverSocket == ss) serverSocket = null;
} }
private synchronized State getState() { synchronized State getState() {
if (!started || stopped || !settingsChecked) { if (!started || stopped || !settingsChecked) {
return STARTING_STOPPING; return STARTING_STOPPING;
} }
@@ -1003,7 +1049,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return bootstrapped && circuitBuilt ? ACTIVE : ENABLING; return bootstrapped && circuitBuilt ? ACTIVE : ENABLING;
} }
private synchronized int getReasonsDisabled() { synchronized int getReasonsDisabled() {
return getState() == DISABLED ? reasonsDisabled : 0; return getState() == DISABLED ? reasonsDisabled : 0;
} }
} }

View File

@@ -4,26 +4,39 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable; import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec; import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import org.bouncycastle.util.encoders.Base64; import org.briarproject.bramble.util.Base32;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.SHA3Digest;
import org.spongycastle.util.encoders.Base64;
import java.nio.charset.Charset; import java.nio.charset.Charset;
class TorRendezvousCryptoImpl implements TorRendezvousCrypto { import static java.lang.System.arraycopy;
public class TorRendezvousCryptoImpl implements TorRendezvousCrypto {
private static final EdDSANamedCurveSpec CURVE_SPEC = private static final EdDSANamedCurveSpec CURVE_SPEC =
EdDSANamedCurveTable.getByName("Ed25519"); EdDSANamedCurveTable.getByName("Ed25519");
private final CryptoComponent crypto; private static final byte HS_PROTOCOL_VERSION = 3;
private static final int CHECKSUM_BYTES = 2;
TorRendezvousCryptoImpl(CryptoComponent crypto) {
this.crypto = crypto;
}
@Override @Override
public String getOnionAddress(byte[] seed) { public String getOnionAddress(byte[] seed) {
EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC); EdDSAPrivateKeySpec spec = new EdDSAPrivateKeySpec(seed, CURVE_SPEC);
return crypto.encodeOnionAddress(spec.getA().toByteArray()); byte[] publicKey = spec.getA().toByteArray();
Digest digest = new SHA3Digest(256);
byte[] label = ".onion checksum".getBytes(Charset.forName("US-ASCII"));
digest.update(label, 0, label.length);
digest.update(publicKey, 0, publicKey.length);
digest.update(HS_PROTOCOL_VERSION);
byte[] checksum = new byte[digest.getDigestSize()];
digest.doFinal(checksum, 0);
byte[] address = new byte[publicKey.length + CHECKSUM_BYTES + 1];
arraycopy(publicKey, 0, address, 0, publicKey.length);
arraycopy(checksum, 0, address, publicKey.length, CHECKSUM_BYTES);
address[address.length - 1] = HS_PROTOCOL_VERSION;
return Base32.encode(address).toLowerCase();
} }
@Override @Override

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.rendezvous; package org.briarproject.bramble.rendezvous;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource; import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
import org.spongycastle.crypto.engines.Salsa20Engine;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;

View File

@@ -37,10 +37,4 @@ class SettingsManagerImpl implements SettingsManager {
public void mergeSettings(Settings s, String namespace) throws DbException { public void mergeSettings(Settings s, String namespace) throws DbException {
db.transaction(false, txn -> db.mergeSettings(txn, s, namespace)); db.transaction(false, txn -> db.mergeSettings(txn, s, namespace));
} }
@Override
public void mergeSettings(Transaction txn, Settings s, String namespace)
throws DbException {
db.mergeSettings(txn, s, namespace);
}
} }

View File

@@ -1,7 +1,5 @@
package org.briarproject.bramble.socks; package org.briarproject.bramble.socks;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import javax.net.SocketFactory; import javax.net.SocketFactory;
@@ -11,14 +9,15 @@ import dagger.Provides;
import static org.briarproject.bramble.api.plugin.TorConstants.CONNECT_TO_PROXY_TIMEOUT; import static org.briarproject.bramble.api.plugin.TorConstants.CONNECT_TO_PROXY_TIMEOUT;
import static org.briarproject.bramble.api.plugin.TorConstants.EXTRA_SOCKET_TIMEOUT; import static org.briarproject.bramble.api.plugin.TorConstants.EXTRA_SOCKET_TIMEOUT;
import static org.briarproject.bramble.api.plugin.TorConstants.SOCKS_PORT;
@Module @Module
public class SocksModule { public class SocksModule {
@Provides @Provides
SocketFactory provideTorSocketFactory(@TorSocksPort int torSocksPort) { SocketFactory provideTorSocketFactory() {
InetSocketAddress proxy = new InetSocketAddress("127.0.0.1", InetSocketAddress proxy = new InetSocketAddress("127.0.0.1",
torSocksPort); SOCKS_PORT);
return new SocksSocketFactory(proxy, CONNECT_TO_PROXY_TIMEOUT, return new SocksSocketFactory(proxy, CONNECT_TO_PROXY_TIMEOUT,
EXTRA_SOCKET_TIMEOUT); EXTRA_SOCKET_TIMEOUT);
} }

View File

@@ -215,23 +215,6 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
m.getStreamContext(txn, tag))); m.getStreamContext(txn, tag)));
} }
@Override
public StreamContext getStreamContextOnly(TransportId t, byte[] tag)
throws DbException {
return withManager(t, m ->
db.transactionWithNullableResult(false, txn ->
m.getStreamContextOnly(txn, tag)));
}
@Override
public void markTagAsRecognised(TransportId t, byte[] tag)
throws DbException {
withManager(t, m -> {
db.transaction(false, txn -> m.markTagAsRecognised(txn, tag));
return null;
});
}
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
if (e instanceof ContactRemovedEvent) { if (e instanceof ContactRemovedEvent) {

View File

@@ -48,9 +48,4 @@ interface TransportKeyManager {
StreamContext getStreamContext(Transaction txn, byte[] tag) StreamContext getStreamContext(Transaction txn, byte[] tag)
throws DbException; throws DbException;
@Nullable
StreamContext getStreamContextOnly(Transaction txn, byte[] tag);
void markTagAsRecognised(Transaction txn, byte[] tag) throws DbException;
} }

View File

@@ -393,82 +393,56 @@ class TransportKeyManagerImpl implements TransportKeyManager {
throws DbException { throws DbException {
lock.lock(); lock.lock();
try { try {
StreamContext ctx = streamContextFromTag(tag); // Look up the incoming keys for the tag
if (ctx == null) return null; TagContext tagCtx = inContexts.remove(new Bytes(tag));
markTagAsRecognised(txn, tag); if (tagCtx == null) return null;
MutableIncomingKeys inKeys = tagCtx.inKeys;
// Create a stream context
StreamContext ctx = new StreamContext(tagCtx.contactId,
tagCtx.pendingContactId, transportId,
inKeys.getTagKey(), inKeys.getHeaderKey(),
tagCtx.streamNumber, tagCtx.handshakeMode);
// Update the reordering window
ReorderingWindow window = inKeys.getWindow();
Change change = window.setSeen(tagCtx.streamNumber);
// Add tags for any stream numbers added to the window
for (long streamNumber : change.getAdded()) {
byte[] addTag = new byte[TAG_LENGTH];
transportCrypto.encodeTag(addTag, inKeys.getTagKey(),
PROTOCOL_VERSION, streamNumber);
TagContext tagCtx1 = new TagContext(tagCtx.keySetId,
tagCtx.contactId, tagCtx.pendingContactId, inKeys,
streamNumber, tagCtx.handshakeMode);
inContexts.put(new Bytes(addTag), tagCtx1);
}
// Remove tags for any stream numbers removed from the window
for (long streamNumber : change.getRemoved()) {
if (streamNumber == tagCtx.streamNumber) continue;
byte[] removeTag = new byte[TAG_LENGTH];
transportCrypto.encodeTag(removeTag, inKeys.getTagKey(),
PROTOCOL_VERSION, streamNumber);
inContexts.remove(new Bytes(removeTag));
}
// Write the window back to the DB
db.setReorderingWindow(txn, tagCtx.keySetId, transportId,
inKeys.getTimePeriod(), window.getBase(),
window.getBitmap());
// If the outgoing keys are inactive, activate them
MutableTransportKeySet ks = keys.get(tagCtx.keySetId);
MutableOutgoingKeys outKeys =
ks.getKeys().getCurrentOutgoingKeys();
if (!outKeys.isActive()) {
LOG.info("Activating outgoing keys");
outKeys.activate();
considerReplacingOutgoingKeys(ks);
db.setTransportKeysActive(txn, transportId, tagCtx.keySetId);
}
return ctx; return ctx;
} finally { } finally {
lock.unlock(); lock.unlock();
} }
} }
@Override
public StreamContext getStreamContextOnly(Transaction txn, byte[] tag) {
lock.lock();
try {
return streamContextFromTag(tag);
} finally {
lock.unlock();
}
}
@GuardedBy("lock")
@Nullable
private StreamContext streamContextFromTag(byte[] tag) {
// Look up the incoming keys for the tag
TagContext tagCtx = inContexts.get(new Bytes(tag));
if (tagCtx == null) return null;
MutableIncomingKeys inKeys = tagCtx.inKeys;
// Create a stream context
return new StreamContext(tagCtx.contactId,
tagCtx.pendingContactId, transportId,
inKeys.getTagKey(), inKeys.getHeaderKey(),
tagCtx.streamNumber, tagCtx.handshakeMode);
}
@Override
public void markTagAsRecognised(Transaction txn, byte[] tag)
throws DbException {
TagContext tagCtx = inContexts.remove(new Bytes(tag));
if (tagCtx == null) return;
MutableIncomingKeys inKeys = tagCtx.inKeys;
// Update the reordering window
ReorderingWindow window = inKeys.getWindow();
Change change = window.setSeen(tagCtx.streamNumber);
// Add tags for any stream numbers added to the window
for (long streamNumber : change.getAdded()) {
byte[] addTag = new byte[TAG_LENGTH];
transportCrypto.encodeTag(addTag, inKeys.getTagKey(),
PROTOCOL_VERSION, streamNumber);
TagContext tagCtx1 = new TagContext(tagCtx.keySetId,
tagCtx.contactId, tagCtx.pendingContactId, inKeys,
streamNumber, tagCtx.handshakeMode);
inContexts.put(new Bytes(addTag), tagCtx1);
}
// Remove tags for any stream numbers removed from the window
for (long streamNumber : change.getRemoved()) {
if (streamNumber == tagCtx.streamNumber) continue;
byte[] removeTag = new byte[TAG_LENGTH];
transportCrypto.encodeTag(removeTag, inKeys.getTagKey(),
PROTOCOL_VERSION, streamNumber);
inContexts.remove(new Bytes(removeTag));
}
// Write the window back to the DB
db.setReorderingWindow(txn, tagCtx.keySetId, transportId,
inKeys.getTimePeriod(), window.getBase(),
window.getBitmap());
// If the outgoing keys are inactive, activate them
MutableTransportKeySet ks = keys.get(tagCtx.keySetId);
MutableOutgoingKeys outKeys =
ks.getKeys().getCurrentOutgoingKeys();
if (!outKeys.isActive()) {
LOG.info("Activating outgoing keys");
outKeys.activate();
considerReplacingOutgoingKeys(ks);
db.setTransportKeysActive(txn, transportId, tagCtx.keySetId);
}
}
@DatabaseExecutor @DatabaseExecutor
@Wakeful @Wakeful
private void updateKeys(Transaction txn) throws DbException { private void updateKeys(Transaction txn) throws DbException {

View File

@@ -1,17 +1,10 @@
d Bridge obfs4 38.229.1.78:80 C8CBDB2464FC9804A69531437BCF2BE31FDD2EE4 cert=Hmyfd2ev46gGY7NoVxA9ngrPF2zCZtzskRTzoWXbxNkzeVnGFPWmrTtILRyqCTjHR+s9dg iat-mode=1 Bridge obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
d 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
d Bridge obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0 Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0
d Bridge obfs4 85.31.186.26:443 91A6354697E6B02A386312F68D82CF86824D3606 cert=PBwr+S8JTVZo6MPdHnkTwXJPILWADLqfMGoVvhZClMq/Urndyd42BwX9YFJHZnBB3H0XCw iat-mode=0 Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0
d Bridge obfs4 193.11.166.194:27015 2D82C2E354D531A68469ADF7F878FA6060C6BACA cert=4TLQPJrTSaDffMK7Nbao6LC7G9OW/NHkUwIdjLSS3KYf0Nv4/nQiiI8dY2TcsQx01NniOg iat-mode=0 Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0
d Bridge obfs4 193.11.166.194:27020 86AC7B8D430DAC4117E9F42C9EAED18133863AAF cert=0LDeJH4JzMDtkJJrFphJCiPqKx7loozKN7VNfuukMGfHO0Z8OGdzHVkhVAOfo1mUdv9cMg iat-mode=0 Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0
d Bridge obfs4 193.11.166.194:27025 1AE2C08904527FEA90C4C4F8C1083EA59FBC6FAF cert=ItvYZzW5tn6v3G4UnQa6Qz04Npro6e81AP70YujmK/KXwDFPTs3aHXcHp4n8Vt6w/bv8cA iat-mode=0 Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0
d Bridge obfs4 209.148.46.65:443 74FAD13168806246602538555B5521A0383A1875 cert=ssH+9rP8dG2NLDN2XuFw63hIO/9MNNinLmxQDpVa+7kTOa9/m+tGWT1SmSYpQ9uTBGa6Hw iat-mode=0 Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
d Bridge obfs4 146.57.248.225:22 10A6CD36A537FCE513A322361547444B393989F0 cert=K1gDtDAIcUfeLqbstggjIw2rtgIKqdIhUlHp82XRqNSq/mtAjp1BIC9vHKJ2FAEpGssTPw iat-mode=0 Bridge obfs4 78.46.188.239:37356 5A2D2F4158D0453E00C7C176978D3F41D69C45DB cert=3c0SwxpOisbohNxEc4tb875RVW8eOu1opRTVXJhafaKA/PNNtI7ElQIVOVZg1AdL5bxGCw iat-mode=0
d Bridge obfs4 45.145.95.6:27015 C5B7CD6946FF10C5B3E89691A7D3F2C122D2117C cert=TD7PbUO0/0k6xYHMPW3vJxICfkMZNdkRrb63Zhl5j9dW3iRGiCx0A7mPhe5T2EDzQ35+Zw iat-mode=0 Bridge meek_lite 192.0.2.2:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com
d Bridge obfs4 51.222.13.177:80 5EDAC3B810E12B01F6FD8050D2FD3E277B289A08 cert=2uplIpLQ0q9+0qMFrK5pkaYRDOe460LL9WHBvatgkuRr/SL31wBOEupaMMJ6koRE6Ld0ew iat-mode=0
d Bridge obfs4 185.100.85.3:443 5B403DFE34F4872EB027059CECAE30B0C864B3A2 cert=bWUdFUe8io9U6JkSLoGAvSAUDcB779/shovCYmYAQb/pW/iEAMZtO/lCd94OokOF909TPA iat-mode=2
n Bridge obfs4 46.226.107.197:10300 A38FD6BDFD902882F5F5B9B7CCC95602A20B0BC4 cert=t8tA9q2AeGlmp/dO6oW9bkY5RqqmvqjArCEM9wjJoDnk6XtnaejkF0JTA7VamdyOzcvuBg iat-mode=0
n Bridge obfs4 74.104.165.202:9002 EF432018A6AA5D970B2F84E39CD30A147030141C cert=PhppfUusY85dHGvWtGTybZ1fED4DtbHmALkNMIOIYrAz1B4xN7/2a5gyiZe1epju1BOHVg iat-mode=0
n Bridge obfs4 23.88.49.56:443 1CDA1660823AE2565D7F50DE8EB99DFDDE96074B cert=4bwNXedHutVD0ZqCm6ph90Vik9dRY4n9qnBHiLiqQOSsIvui4iHwuMFQK6oqiK8tyhVcDw iat-mode=0
n Bridge obfs4 185.65.206.101:443 8A3E001D4C5105ED41060597DEEB21FF19CDC4D3 cert=Nd6XZ+f00sGKL1u6USmyvfqR34HN/pt7jEVbgMpXPF/yyGaLBiXRH/x0SIjX5TceYnd+Dg iat-mode=0
m Bridge meek_lite 192.0.2.2:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com

View File

@@ -0,0 +1,6 @@
ControlPort 59051
CookieAuthentication 1
DisableNetwork 1
RunAsDaemon 1
SafeSocks 1
SocksPort 59050

View File

@@ -24,10 +24,11 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageFactory; import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.DbExpectations; import org.briarproject.bramble.test.DbExpectations;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@@ -52,8 +53,9 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
public class ClientHelperImplTest extends BrambleMockTestCase { public class ClientHelperImplTest extends BrambleTestCase {
private final Mockery context = new Mockery();
private final DatabaseComponent db = context.mock(DatabaseComponent.class); private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final MessageFactory messageFactory = private final MessageFactory messageFactory =
context.mock(MessageFactory.class); context.mock(MessageFactory.class);
@@ -98,6 +100,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
clientHelper.addLocalMessage(message, dictionary, shared); clientHelper.addLocalMessage(message, dictionary, shared);
context.assertIsSatisfied();
} }
@Test @Test
@@ -109,6 +112,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
clientHelper.createMessage(groupId, timestamp, list); clientHelper.createMessage(groupId, timestamp, list);
context.assertIsSatisfied();
} }
@Test @Test
@@ -123,6 +127,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
clientHelper.getMessageAsList(messageId); clientHelper.getMessageAsList(messageId);
context.assertIsSatisfied();
} }
@Test @Test
@@ -139,6 +144,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertEquals(dictionary, assertEquals(dictionary,
clientHelper.getGroupMetadataAsDictionary(groupId)); clientHelper.getGroupMetadataAsDictionary(groupId));
context.assertIsSatisfied();
} }
@Test @Test
@@ -155,6 +161,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertEquals(dictionary, assertEquals(dictionary,
clientHelper.getMessageMetadataAsDictionary(messageId)); clientHelper.getMessageMetadataAsDictionary(messageId));
context.assertIsSatisfied();
} }
@Test @Test
@@ -172,6 +179,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId)); assertEquals(map, clientHelper.getMessageMetadataAsDictionary(groupId));
context.assertIsSatisfied();
} }
@Test @Test
@@ -196,6 +204,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertEquals(map, assertEquals(map,
clientHelper.getMessageMetadataAsDictionary(groupId, query)); clientHelper.getMessageMetadataAsDictionary(groupId, query));
context.assertIsSatisfied();
} }
@Test @Test
@@ -210,6 +219,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
clientHelper.mergeGroupMetadata(groupId, dictionary); clientHelper.mergeGroupMetadata(groupId, dictionary);
context.assertIsSatisfied();
} }
@Test @Test
@@ -224,6 +234,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
clientHelper.mergeMessageMetadata(messageId, dictionary); clientHelper.mergeMessageMetadata(messageId, dictionary);
context.assertIsSatisfied();
} }
@Test @Test
@@ -231,6 +242,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
byte[] bytes = expectToByteArray(list); byte[] bytes = expectToByteArray(list);
assertArrayEquals(bytes, clientHelper.toByteArray(list)); assertArrayEquals(bytes, clientHelper.toByteArray(list));
context.assertIsSatisfied();
} }
@Test @Test
@@ -238,6 +250,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
expectToList(true); expectToList(true);
assertEquals(list, clientHelper.toList(getRandomBytes(123))); assertEquals(list, clientHelper.toList(getRandomBytes(123)));
context.assertIsSatisfied();
} }
@Test @Test
@@ -249,6 +262,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
fail(); fail();
} catch (FormatException e) { } catch (FormatException e) {
// expected // expected
context.assertIsSatisfied();
} }
} }
@@ -265,6 +279,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
assertArrayEquals(signature, assertArrayEquals(signature,
clientHelper.sign(label, list, privateKey)); clientHelper.sign(label, list, privateKey));
context.assertIsSatisfied();
} }
@Test @Test
@@ -280,6 +295,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
}}); }});
clientHelper.verifySignature(signature, label, list, publicKey); clientHelper.verifySignature(signature, label, list, publicKey);
context.assertIsSatisfied();
} }
@Test @Test
@@ -299,6 +315,7 @@ public class ClientHelperImplTest extends BrambleMockTestCase {
fail(); fail();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
// expected // expected
context.assertIsSatisfied();
} }
} }

View File

@@ -1,9 +1,9 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import org.junit.Test; import org.junit.Test;
import org.spongycastle.crypto.digests.Blake2bDigest;
import java.util.Random; import java.util.Random;

View File

@@ -0,0 +1,115 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
import java.math.BigInteger;
import java.security.SecureRandom;
import static org.junit.Assert.assertEquals;
public class EllipticCurveMultiplicationTest extends BrambleTestCase {
@Test
public void testMultiplierProducesSameResultsAsDefault() throws Exception {
// Instantiate the default implementation of the curve
X9ECParameters defaultX9Parameters =
TeleTrusTNamedCurves.getByName("brainpoolp256r1");
ECCurve defaultCurve = defaultX9Parameters.getCurve();
ECPoint defaultG = defaultX9Parameters.getG();
BigInteger defaultN = defaultX9Parameters.getN();
BigInteger defaultH = defaultX9Parameters.getH();
ECDomainParameters defaultParameters = new ECDomainParameters(
defaultCurve, defaultG, defaultN, defaultH);
// Instantiate an implementation using the Montgomery ladder multiplier
ECDomainParameters montgomeryParameters =
constantTime(defaultParameters);
// Generate two key pairs with each set of parameters, using the same
// deterministic PRNG for both sets of parameters
byte[] seed = new byte[32];
new SecureRandom().nextBytes(seed);
// Montgomery ladder multiplier
SecureRandom random = new PseudoSecureRandom(seed);
ECKeyGenerationParameters montgomeryGeneratorParams =
new ECKeyGenerationParameters(montgomeryParameters, random);
ECKeyPairGenerator montgomeryGenerator = new ECKeyPairGenerator();
montgomeryGenerator.init(montgomeryGeneratorParams);
AsymmetricCipherKeyPair montgomeryKeyPair1 =
montgomeryGenerator.generateKeyPair();
ECPrivateKeyParameters montgomeryPrivate1 =
(ECPrivateKeyParameters) montgomeryKeyPair1.getPrivate();
ECPublicKeyParameters montgomeryPublic1 =
(ECPublicKeyParameters) montgomeryKeyPair1.getPublic();
AsymmetricCipherKeyPair montgomeryKeyPair2 =
montgomeryGenerator.generateKeyPair();
ECPrivateKeyParameters montgomeryPrivate2 =
(ECPrivateKeyParameters) montgomeryKeyPair2.getPrivate();
ECPublicKeyParameters montgomeryPublic2 =
(ECPublicKeyParameters) montgomeryKeyPair2.getPublic();
// Default multiplier
random = new PseudoSecureRandom(seed);
ECKeyGenerationParameters defaultGeneratorParams =
new ECKeyGenerationParameters(defaultParameters, random);
ECKeyPairGenerator defaultGenerator = new ECKeyPairGenerator();
defaultGenerator.init(defaultGeneratorParams);
AsymmetricCipherKeyPair defaultKeyPair1 =
defaultGenerator.generateKeyPair();
ECPrivateKeyParameters defaultPrivate1 =
(ECPrivateKeyParameters) defaultKeyPair1.getPrivate();
ECPublicKeyParameters defaultPublic1 =
(ECPublicKeyParameters) defaultKeyPair1.getPublic();
AsymmetricCipherKeyPair defaultKeyPair2 =
defaultGenerator.generateKeyPair();
ECPrivateKeyParameters defaultPrivate2 =
(ECPrivateKeyParameters) defaultKeyPair2.getPrivate();
ECPublicKeyParameters defaultPublic2 =
(ECPublicKeyParameters) defaultKeyPair2.getPublic();
// The key pairs generated with both sets of parameters should be equal
assertEquals(montgomeryPrivate1.getD(), defaultPrivate1.getD());
assertEquals(montgomeryPublic1.getQ(), defaultPublic1.getQ());
assertEquals(montgomeryPrivate2.getD(), defaultPrivate2.getD());
assertEquals(montgomeryPublic2.getQ(), defaultPublic2.getQ());
// OK, all of the above was just sanity checks - now for the test!
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
agreement.init(montgomeryPrivate1);
BigInteger sharedSecretMontgomeryMontgomery =
agreement.calculateAgreement(montgomeryPublic2);
agreement.init(montgomeryPrivate1);
BigInteger sharedSecretMontgomeryDefault =
agreement.calculateAgreement(defaultPublic2);
agreement.init(defaultPrivate1);
BigInteger sharedSecretDefaultMontgomery =
agreement.calculateAgreement(montgomeryPublic2);
agreement.init(defaultPrivate1);
BigInteger sharedSecretDefaultDefault =
agreement.calculateAgreement(defaultPublic2);
// Shared secrets calculated with different multipliers should be equal
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretMontgomeryDefault);
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretDefaultMontgomery);
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretDefaultDefault);
}
private static ECDomainParameters constantTime(ECDomainParameters in) {
ECCurve curve = in.getCurve().configure().setMultiplier(
new MontgomeryLadderMultiplier()).create();
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
ECPoint g = curve.createPoint(x, y);
return new ECDomainParameters(curve, g, in.getN(), in.getH());
}
}

View File

@@ -3,26 +3,30 @@ package org.briarproject.bramble.crypto;
import net.i2p.crypto.eddsa.EdDSASecurityProvider; import net.i2p.crypto.eddsa.EdDSASecurityProvider;
import net.i2p.crypto.eddsa.KeyPairGenerator; import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.bouncycastle.asn1.sec.SECNamedCurves; import org.spongycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters; import org.spongycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement; import org.spongycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.Digest; import org.spongycastle.crypto.Digest;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement; import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.digests.Blake2bDigest; import org.spongycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom; import org.spongycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSADigestSigner; import org.spongycastle.crypto.signers.DSADigestSigner;
import org.bouncycastle.crypto.signers.DSAKCalculator; import org.spongycastle.crypto.signers.DSAKCalculator;
import org.bouncycastle.crypto.signers.ECDSASigner; import org.spongycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator; import org.spongycastle.crypto.signers.HMacDSAKCalculator;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
import org.whispersystems.curve25519.Curve25519; import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair; import org.whispersystems.curve25519.Curve25519KeyPair;
import java.math.BigInteger;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.Provider; import java.security.Provider;
@@ -51,12 +55,14 @@ public class EllipticCurvePerformanceTest {
for (String name : SEC_NAMES) { for (String name : SEC_NAMES) {
ECDomainParameters params = ECDomainParameters params =
convertParams(SECNamedCurves.getByName(name)); convertParams(SECNamedCurves.getByName(name));
runTest(name, params); runTest(name + " default", params);
runTest(name + " constant", constantTime(params));
} }
for (String name : BRAINPOOL_NAMES) { for (String name : BRAINPOOL_NAMES) {
ECDomainParameters params = ECDomainParameters params =
convertParams(TeleTrusTNamedCurves.getByName(name)); convertParams(TeleTrusTNamedCurves.getByName(name));
runTest(name, params); runTest(name + " default", params);
runTest(name + " constant", constantTime(params));
} }
runCurve25519Test(); runCurve25519Test();
runEd25519Test(); runEd25519Test();
@@ -187,4 +193,13 @@ public class EllipticCurvePerformanceTest {
return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(), return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(),
in.getH()); in.getH());
} }
private static ECDomainParameters constantTime(ECDomainParameters in) {
ECCurve curve = in.getCurve().configure().setMultiplier(
new MontgomeryLadderMultiplier()).create();
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
ECPoint g = curve.createPoint(x, y);
return new ECDomainParameters(curve, g, in.getN(), in.getH());
}
} }

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.CryptoException;
import org.briarproject.bramble.api.crypto.KeyPair; import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PrivateKey; import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey; import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test; import org.junit.Test;
import org.spongycastle.crypto.CryptoException;
import java.security.SecureRandom; import java.security.SecureRandom;

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.crypto; package org.briarproject.bramble.crypto;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.spongycastle.crypto.engines.Salsa20Engine;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import javax.annotation.concurrent.NotThreadSafe; import javax.annotation.concurrent.NotThreadSafe;

View File

@@ -2197,55 +2197,6 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase {
db.close(); db.close();
} }
@Test
public void testResetRetransmissionTimes() throws Exception {
long now = System.currentTimeMillis();
AtomicLong time = new AtomicLong(now);
Database<Connection> db =
open(false, new TestMessageFactory(), new SettableClock(time));
Connection txn = db.startTransaction();
// Add a contact, a shared group and a shared message
db.addIdentity(txn, identity);
assertEquals(contactId,
db.addContact(txn, author, localAuthor.getId(), null, true));
db.addGroup(txn, group);
db.addGroupVisibility(txn, contactId, groupId, true);
db.addMessage(txn, message, DELIVERED, true, false, null);
// Time: now
// Retrieve the message from the database
Collection<MessageId> ids = db.getMessagesToSend(txn, contactId,
ONE_MEGABYTE, MAX_LATENCY);
assertEquals(singletonList(messageId), ids);
// Time: now
// Mark the message as sent
db.updateExpiryTimeAndEta(txn, contactId, messageId, MAX_LATENCY);
// The message should expire after 2 * MAX_LATENCY
assertEquals(now + MAX_LATENCY * 2, db.getNextSendTime(txn, contactId));
// Time: now + MAX_LATENCY * 2 - 1
// The message should not yet be sendable
time.set(now + MAX_LATENCY * 2 - 1);
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
assertTrue(ids.isEmpty());
// Reset the retransmission times
db.resetUnackedMessagesToSend(txn, contactId);
// The message should have infinitely short expiry
assertEquals(0, db.getNextSendTime(txn, contactId));
// The message should be sendable
ids = db.getMessagesToSend(txn, contactId, ONE_MEGABYTE, MAX_LATENCY);
assertFalse(ids.isEmpty());
db.commitTransaction(txn);
db.close();
}
@Test @Test
public void testCompactionTime() throws Exception { public void testCompactionTime() throws Exception {
MessageFactory messageFactory = new TestMessageFactory(); MessageFactory messageFactory = new TestMessageFactory();

View File

@@ -12,7 +12,6 @@ import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.auto.Mock; import org.jmock.auto.Mock;
import org.jmock.integration.junit4.JUnitRuleMockery; import org.jmock.integration.junit4.JUnitRuleMockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.jmock.lib.legacy.ClassImposteriser; import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@@ -36,7 +35,6 @@ public class KeyAgreementProtocolTest extends BrambleTestCase {
public JUnitRuleMockery context = new JUnitRuleMockery() {{ public JUnitRuleMockery context = new JUnitRuleMockery() {{
// So we can mock concrete classes like KeyAgreementTransport // So we can mock concrete classes like KeyAgreementTransport
setImposteriser(ClassImposteriser.INSTANCE); setImposteriser(ClassImposteriser.INSTANCE);
setThreadingPolicy(new Synchroniser());
}}; }};
private final PublicKey alicePubKey = getAgreementPublicKey(); private final PublicKey alicePubKey = getAgreementPublicKey();

View File

@@ -1,225 +0,0 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.Test;
import java.util.Random;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_ATTEMPTS;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_ATTEMPT;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_SUCCESS;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_ONION;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_TOKEN;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_NAMESPACE;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_UPLOADS_NAMESPACE;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
private final SettingsManager settingsManager =
context.mock(SettingsManager.class);
private final MailboxSettingsManager manager =
new MailboxSettingsManagerImpl(settingsManager);
private final Random random = new Random();
private final String onion = getRandomString(64);
private final String token = getRandomString(64);
private final ContactId contactId1 = new ContactId(random.nextInt());
private final ContactId contactId2 = new ContactId(random.nextInt());
private final ContactId contactId3 = new ContactId(random.nextInt());
private final long now = System.currentTimeMillis();
private final long lastAttempt = now - 1234;
private final long lastSuccess = now - 2345;
private final int attempts = 123;
@Test
public void testReturnsNullPropertiesIfSettingsAreEmpty() throws Exception {
Transaction txn = new Transaction(null, true);
Settings emptySettings = new Settings();
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(emptySettings));
}});
assertNull(manager.getOwnMailboxProperties(txn));
}
@Test
public void testReturnsProperties() throws Exception {
Transaction txn = new Transaction(null, true);
Settings settings = new Settings();
settings.put(SETTINGS_KEY_ONION, onion);
settings.put(SETTINGS_KEY_TOKEN, token);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(settings));
}});
MailboxProperties properties = manager.getOwnMailboxProperties(txn);
assertNotNull(properties);
assertEquals(onion, properties.getOnionAddress());
assertEquals(token, properties.getAuthToken());
assertTrue(properties.isOwner());
}
@Test
public void testStoresProperties() throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.put(SETTINGS_KEY_ONION, onion);
expectedSettings.put(SETTINGS_KEY_TOKEN, token);
MailboxProperties properties =
new MailboxProperties(onion, token, true);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.setOwnMailboxProperties(txn, properties);
}
@Test
public void testReturnsDefaultStatusIfSettingsAreEmpty() throws Exception {
Transaction txn = new Transaction(null, true);
Settings emptySettings = new Settings();
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(emptySettings));
}});
MailboxStatus status = manager.getOwnMailboxStatus(txn);
assertEquals(-1, status.getTimeOfLastAttempt());
assertEquals(-1, status.getTimeOfLastSuccess());
assertEquals(0, status.getAttemptsSinceSuccess());
}
@Test
public void testReturnsStatus() throws Exception {
Transaction txn = new Transaction(null, true);
Settings settings = new Settings();
settings.putLong(SETTINGS_KEY_LAST_ATTEMPT, lastAttempt);
settings.putLong(SETTINGS_KEY_LAST_SUCCESS, lastSuccess);
settings.putInt(SETTINGS_KEY_ATTEMPTS, attempts);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(settings));
}});
MailboxStatus status = manager.getOwnMailboxStatus(txn);
assertEquals(lastAttempt, status.getTimeOfLastAttempt());
assertEquals(lastSuccess, status.getTimeOfLastSuccess());
assertEquals(attempts, status.getAttemptsSinceSuccess());
}
@Test
public void testRecordsSuccess() throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, 0);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordSuccessfulConnection(txn, now);
}
@Test
public void testRecordsFailureOnFirstAttempt() throws Exception {
testRecordsFailure(new Settings(), 0);
}
@Test
public void testRecordsFailureOnLaterAttempt() throws Exception {
Settings oldSettings = new Settings();
oldSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, lastAttempt);
oldSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, lastSuccess);
oldSettings.putInt(SETTINGS_KEY_ATTEMPTS, attempts);
testRecordsFailure(oldSettings, attempts);
}
private void testRecordsFailure(Settings oldSettings, int oldAttempts)
throws Exception {
Transaction txn = new Transaction(null, false);
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, oldAttempts + 1);
context.checking(new Expectations() {{
oneOf(settingsManager).getSettings(txn, SETTINGS_NAMESPACE);
will(returnValue(oldSettings));
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordFailedConnectionAttempt(txn, now);
}
@Test
public void testGettingPendingUploads() throws Exception {
Transaction txn = new Transaction(null, true);
Settings settings = new Settings();
settings.put(String.valueOf(contactId1.getInt()), onion);
settings.put(String.valueOf(contactId2.getInt()), token);
settings.put(String.valueOf(contactId3.getInt()), "");
context.checking(new Expectations() {{
exactly(4).of(settingsManager)
.getSettings(txn, SETTINGS_UPLOADS_NAMESPACE);
will(returnValue(settings));
}});
String filename1 = manager.getPendingUpload(txn, contactId1);
assertEquals(onion, filename1);
String filename2 = manager.getPendingUpload(txn, contactId2);
assertEquals(token, filename2);
String filename3 = manager.getPendingUpload(txn, contactId3);
assertNull(filename3);
String filename4 =
manager.getPendingUpload(txn, new ContactId(random.nextInt()));
assertNull(filename4);
}
@Test
public void testSettingPendingUploads() throws Exception {
Transaction txn = new Transaction(null, false);
// setting a pending upload stores expected settings
Settings expectedSettings1 = new Settings();
expectedSettings1.put(String.valueOf(contactId1.getInt()), onion);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings1,
SETTINGS_UPLOADS_NAMESPACE);
}});
manager.setPendingUpload(txn, contactId1, onion);
// nulling a pending upload empties stored settings
Settings expectedSettings2 = new Settings();
expectedSettings2.put(String.valueOf(contactId2.getInt()), "");
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings2,
SETTINGS_UPLOADS_NAMESPACE);
}});
manager.setPendingUpload(txn, contactId2, null);
}
}

View File

@@ -12,8 +12,10 @@ import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.properties.TransportPropertyManager; import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.settings.SettingsManager; import org.briarproject.bramble.api.settings.SettingsManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.concurrent.Synchroniser;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays; import java.util.Arrays;
@@ -22,10 +24,13 @@ import java.util.concurrent.Executors;
import static org.briarproject.bramble.test.TestUtils.getTransportId; import static org.briarproject.bramble.test.TestUtils.getTransportId;
public class PluginManagerImplTest extends BrambleMockTestCase { public class PluginManagerImplTest extends BrambleTestCase {
@Test @Test
public void testStartAndStop() throws Exception { public void testStartAndStop() throws Exception {
Mockery context = new Mockery() {{
setThreadingPolicy(new Synchroniser());
}};
Executor ioExecutor = Executors.newSingleThreadExecutor(); Executor ioExecutor = Executors.newSingleThreadExecutor();
EventBus eventBus = context.mock(EventBus.class); EventBus eventBus = context.mock(EventBus.class);
PluginConfig pluginConfig = context.mock(PluginConfig.class); PluginConfig pluginConfig = context.mock(PluginConfig.class);
@@ -111,5 +116,7 @@ public class PluginManagerImplTest extends BrambleMockTestCase {
// Two plugins should be started and stopped // Two plugins should be started and stopped
p.startService(); p.startService();
p.stopService(); p.stopService();
context.assertIsSatisfied();
} }
} }

View File

@@ -1,68 +0,0 @@
package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BLOCKED;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BRIDGES;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.DEFAULT_OBFS4;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.DEFAULT_OBFS4_BRIDGES;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.MEEK_BRIDGES;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.NON_DEFAULT_OBFS4_BRIDGES;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class CircumventionProviderTest extends BrambleTestCase {
private final CircumventionProvider provider =
new CircumventionProviderImpl();
@Test
public void testInvariants() {
Set<String> blocked = new HashSet<>(asList(BLOCKED));
Set<String> bridges = new HashSet<>(asList(BRIDGES));
Set<String> defaultObfs4Bridges =
new HashSet<>(asList(DEFAULT_OBFS4_BRIDGES));
Set<String> nonDefaultObfs4Bridges =
new HashSet<>(asList(NON_DEFAULT_OBFS4_BRIDGES));
Set<String> meekBridges = new HashSet<>(asList(MEEK_BRIDGES));
// BRIDGES should be a subset of BLOCKED
assertTrue(blocked.containsAll(bridges));
// BRIDGES should be the union of the bridge type sets
Set<String> union = new HashSet<>(defaultObfs4Bridges);
union.addAll(nonDefaultObfs4Bridges);
union.addAll(meekBridges);
assertEquals(bridges, union);
// The bridge type sets should not overlap
assertEmptyIntersection(defaultObfs4Bridges, nonDefaultObfs4Bridges);
assertEmptyIntersection(defaultObfs4Bridges, meekBridges);
assertEmptyIntersection(nonDefaultObfs4Bridges, meekBridges);
}
@Test
public void testGetBestBridgeType() {
for (String country : DEFAULT_OBFS4_BRIDGES) {
assertEquals(DEFAULT_OBFS4, provider.getBestBridgeType(country));
}
for (String country : NON_DEFAULT_OBFS4_BRIDGES) {
assertEquals(NON_DEFAULT_OBFS4,
provider.getBestBridgeType(country));
}
for (String country : MEEK_BRIDGES) {
assertEquals(MEEK, provider.getBestBridgeType(country));
}
assertEquals(DEFAULT_OBFS4, provider.getBestBridgeType("ZZ"));
}
private <T> void assertEmptyIntersection(Set<T> a, Set<T> b) {
Set<T> intersection = new HashSet<>(a);
intersection.retainAll(b);
assertTrue(intersection.isEmpty());
}
}

View File

@@ -24,6 +24,21 @@ public class TestFeatureFlagModule {
public boolean shouldEnableDisappearingMessages() { public boolean shouldEnableDisappearingMessages() {
return true; return true;
} }
@Override
public boolean shouldEnableConnectViaBluetooth() {
return true;
}
@Override
public boolean shouldEnableShareAppViaOfflineHotspot() {
return true;
}
@Override
public boolean shouldEnableTransferData() {
return true;
}
}; };
} }
} }

View File

@@ -1,17 +1,19 @@
package org.briarproject.bramble.transport; package org.briarproject.bramble.transport;
import org.briarproject.bramble.api.crypto.StreamDecrypter; import org.briarproject.bramble.api.crypto.StreamDecrypter;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class StreamReaderImplTest extends BrambleMockTestCase { public class StreamReaderImplTest extends BrambleTestCase {
@Test @Test
public void testEmptyFramesAreSkipped() throws Exception { public void testEmptyFramesAreSkipped() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -28,11 +30,13 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
assertEquals(0, r.read()); // Read another byte assertEquals(0, r.read()); // Read another byte
assertEquals(-1, r.read()); // Skip the second empty frame, reach EOF assertEquals(-1, r.read()); // Skip the second empty frame, reach EOF
assertEquals(-1, r.read()); // Still at EOF assertEquals(-1, r.read()); // Still at EOF
context.assertIsSatisfied();
r.close(); r.close();
} }
@Test @Test
public void testEmptyFramesAreSkippedWithBuffer() throws Exception { public void testEmptyFramesAreSkippedWithBuffer() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -52,11 +56,13 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
assertEquals(-1, r.read(buf)); assertEquals(-1, r.read(buf));
// Still at EOF // Still at EOF
assertEquals(-1, r.read(buf)); assertEquals(-1, r.read(buf));
context.assertIsSatisfied();
r.close(); r.close();
} }
@Test @Test
public void testMultipleReadsPerFrame() throws Exception { public void testMultipleReadsPerFrame() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -72,11 +78,13 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
assertEquals(MAX_PAYLOAD_LENGTH / 2, r.read(buf)); assertEquals(MAX_PAYLOAD_LENGTH / 2, r.read(buf));
// Reach EOF // Reach EOF
assertEquals(-1, r.read(buf, 0, buf.length)); assertEquals(-1, r.read(buf, 0, buf.length));
context.assertIsSatisfied();
r.close(); r.close();
} }
@Test @Test
public void testMultipleReadsPerFrameWithOffsets() throws Exception { public void testMultipleReadsPerFrameWithOffsets() throws Exception {
Mockery context = new Mockery();
StreamDecrypter decrypter = context.mock(StreamDecrypter.class); StreamDecrypter decrypter = context.mock(StreamDecrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(decrypter).readFrame(with(any(byte[].class))); oneOf(decrypter).readFrame(with(any(byte[].class)));
@@ -94,6 +102,7 @@ public class StreamReaderImplTest extends BrambleMockTestCase {
MAX_PAYLOAD_LENGTH / 2)); MAX_PAYLOAD_LENGTH / 2));
// Reach EOF // Reach EOF
assertEquals(-1, r.read(buf, 0, buf.length)); assertEquals(-1, r.read(buf, 0, buf.length));
context.assertIsSatisfied();
r.close(); r.close();
} }
} }

View File

@@ -1,17 +1,19 @@
package org.briarproject.bramble.transport; package org.briarproject.bramble.transport;
import org.briarproject.bramble.api.crypto.StreamEncrypter; import org.briarproject.bramble.api.crypto.StreamEncrypter;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test; import org.junit.Test;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH; import static org.briarproject.bramble.api.transport.TransportConstants.MAX_PAYLOAD_LENGTH;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
public class StreamWriterImplTest extends BrambleMockTestCase { public class StreamWriterImplTest extends BrambleTestCase {
@Test @Test
public void testCloseWithoutWritingWritesFinalFrame() throws Exception { public void testCloseWithoutWritingWritesFinalFrame() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
// Write an empty final frame // Write an empty final frame
@@ -22,11 +24,13 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
}}); }});
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
w.close(); w.close();
context.assertIsSatisfied();
} }
@Test @Test
public void testFlushWithoutBufferedDataWritesFrameAndFlushes() public void testFlushWithoutBufferedDataWritesFrameAndFlushes()
throws Exception { throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -47,11 +51,13 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush(); oneOf(encrypter).flush();
}}); }});
w.close(); w.close();
context.assertIsSatisfied();
} }
@Test @Test
public void testFlushWithBufferedDataWritesFrameAndFlushes() public void testFlushWithBufferedDataWritesFrameAndFlushes()
throws Exception { throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -73,10 +79,12 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush(); oneOf(encrypter).flush();
}}); }});
w.close(); w.close();
context.assertIsSatisfied();
} }
@Test @Test
public void testSingleByteWritesWriteFullFrame() throws Exception { public void testSingleByteWritesWriteFullFrame() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -95,10 +103,12 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush(); oneOf(encrypter).flush();
}}); }});
w.close(); w.close();
context.assertIsSatisfied();
} }
@Test @Test
public void testMultiByteWritesWriteFullFrames() throws Exception { public void testMultiByteWritesWriteFullFrames() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -124,10 +134,12 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
oneOf(encrypter).flush(); oneOf(encrypter).flush();
}}); }});
w.close(); w.close();
context.assertIsSatisfied();
} }
@Test @Test
public void testLargeMultiByteWriteWritesFullFrames() throws Exception { public void testLargeMultiByteWriteWritesFullFrames() throws Exception {
Mockery context = new Mockery();
StreamEncrypter encrypter = context.mock(StreamEncrypter.class); StreamEncrypter encrypter = context.mock(StreamEncrypter.class);
StreamWriterImpl w = new StreamWriterImpl(encrypter); StreamWriterImpl w = new StreamWriterImpl(encrypter);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
@@ -145,5 +157,6 @@ public class StreamWriterImplTest extends BrambleMockTestCase {
w.write(b); w.write(b);
// There should be one byte left in the buffer // There should be one byte left in the buffer
w.close(); w.close();
context.assertIsSatisfied();
} }
} }

View File

@@ -393,76 +393,6 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase {
assertNull(transportKeyManager.getStreamContext(txn, tag)); assertNull(transportKeyManager.getStreamContext(txn, tag));
} }
@Test
public void testGetStreamContextOnlyAndMarkTag() throws Exception {
boolean alice = random.nextBoolean();
TransportKeys transportKeys = createTransportKeys(1000, 0, true);
Transaction txn = new Transaction(null, false);
// Keep a copy of the tags
List<byte[]> tags = new ArrayList<>();
context.checking(new Expectations() {{
oneOf(transportCrypto).deriveRotationKeys(transportId, rootKey,
1000, alice, true);
will(returnValue(transportKeys));
// Get the current time (the start of time period 1000)
oneOf(clock).currentTimeMillis();
will(returnValue(timePeriodLength * 1000));
// Encode the tags (3 sets)
for (long i = 0; i < REORDERING_WINDOW_SIZE; i++) {
exactly(3).of(transportCrypto).encodeTag(
with(any(byte[].class)), with(tagKey),
with(PROTOCOL_VERSION), with(i));
will(new EncodeTagAction(tags));
}
// Updated the transport keys (the keys are unaffected)
oneOf(transportCrypto).updateTransportKeys(transportKeys, 1000);
will(returnValue(transportKeys));
// Save the keys
oneOf(db).addTransportKeys(txn, contactId, transportKeys);
will(returnValue(keySetId));
// Encode a new tag after sliding the window
oneOf(transportCrypto).encodeTag(with(any(byte[].class)),
with(tagKey), with(PROTOCOL_VERSION),
with((long) REORDERING_WINDOW_SIZE));
will(new EncodeTagAction(tags));
// Save the reordering window (previous time period, base 1)
oneOf(db).setReorderingWindow(txn, keySetId, transportId, 999,
1, new byte[REORDERING_WINDOW_SIZE / 8]);
}});
// The timestamp is at the start of time period 1000
long timestamp = timePeriodLength * 1000;
assertEquals(keySetId, transportKeyManager.addRotationKeys(
txn, contactId, rootKey, timestamp, alice, true));
assertTrue(transportKeyManager.canSendOutgoingStreams(contactId));
// Use the first tag (previous time period, stream number 0)
assertEquals(REORDERING_WINDOW_SIZE * 3, tags.size());
byte[] tag = tags.get(0);
// Repeated request should return same stream context
StreamContext ctx = transportKeyManager.getStreamContextOnly(txn, tag);
assertNotNull(ctx);
assertEquals(contactId, ctx.getContactId());
assertEquals(transportId, ctx.getTransportId());
assertEquals(tagKey, ctx.getTagKey());
assertEquals(headerKey, ctx.getHeaderKey());
assertEquals(0L, ctx.getStreamNumber());
ctx = transportKeyManager.getStreamContextOnly(txn, tag);
assertNotNull(ctx);
assertEquals(contactId, ctx.getContactId());
assertEquals(transportId, ctx.getTransportId());
assertEquals(tagKey, ctx.getTagKey());
assertEquals(headerKey, ctx.getHeaderKey());
assertEquals(0L, ctx.getStreamNumber());
// Then mark tag as recognised
transportKeyManager.markTagAsRecognised(txn, tag);
// Another tag should have been encoded
assertEquals(REORDERING_WINDOW_SIZE * 3 + 1, tags.size());
// Finally ensure the used tag is not recognised again
assertNull(transportKeyManager.getStreamContextOnly(txn, tag));
}
@Test @Test
public void testKeysAreUpdatedToCurrentPeriod() throws Exception { public void testKeysAreUpdatedToCurrentPeriod() throws Exception {
TransportKeys transportKeys = createTransportKeys(1000, 0, true); TransportKeys transportKeys = createTransportKeys(1000, 0, true);

View File

@@ -15,6 +15,7 @@ dependencyVerification {
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6', 'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c', '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.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291', '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.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
@@ -26,14 +27,13 @@ dependencyVerification {
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', '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.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15on:1.69:bcprov-jdk15on-1.69.jar:e469bd39f936999f256002631003ff022a22951da9d5bd9789c7abfa9763a292',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864', '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', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a', 'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619', 'org.codehaus.mojo.signature:java16:1.1:java16-1.1.signature:53799223a2c98dba2d0add810bed76315460df285c69e4f397ae6098f87dd619',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90',
'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249', 'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9', 'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21', 'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
@@ -48,8 +48,8 @@ dependencyVerification {
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04', '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.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984', '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:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de', 'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d', 'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
] ]
} }

View File

@@ -17,8 +17,8 @@ dependencies {
def jna_version = '4.5.2' def jna_version = '4.5.2'
implementation "net.java.dev.jna:jna:$jna_version" implementation "net.java.dev.jna:jna:$jna_version"
implementation "net.java.dev.jna:jna-platform:$jna_version" implementation "net.java.dev.jna:jna-platform:$jna_version"
tor "org.briarproject:tor:$tor_version" tor 'org.briarproject:tor:0.3.5.15'
tor "org.briarproject:obfs4proxy:$obfs4proxy_version@zip" tor 'org.briarproject:obfs4proxy:0.0.12-dev-40245c4a@zip'
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version" annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"

View File

@@ -9,15 +9,16 @@ import java.net.Inet4Address;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface; import java.net.NetworkInterface;
import java.net.SocketException; import java.net.SocketException;
import java.util.Enumeration;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import static java.net.NetworkInterface.getNetworkInterfaces;
import static java.util.Collections.list; import static java.util.Collections.list;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.NetworkUtils.getNetworkInterfaces;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -34,14 +35,19 @@ class JavaNetworkManager implements NetworkManager {
public NetworkStatus getNetworkStatus() { public NetworkStatus getNetworkStatus() {
boolean connected = false, hasIpv4 = false, hasIpv6Unicast = false; boolean connected = false, hasIpv4 = false, hasIpv6Unicast = false;
try { try {
for (NetworkInterface i : getNetworkInterfaces()) { Enumeration<NetworkInterface> interfaces = getNetworkInterfaces();
if (i.isLoopback() || !i.isUp()) continue; if (interfaces == null) {
for (InetAddress addr : list(i.getInetAddresses())) { LOG.info("No network interfaces");
connected = true; } else {
if (addr instanceof Inet4Address) { for (NetworkInterface i : list(interfaces)) {
hasIpv4 = true; if (i.isLoopback() || !i.isUp()) continue;
} else if (!addr.isMulticastAddress()) { for (InetAddress addr : list(i.getInetAddresses())) {
hasIpv6Unicast = true; connected = true;
if (addr instanceof Inet4Address) {
hasIpv4 = true;
} else if (!addr.isMulticastAddress()) {
hasIpv6Unicast = true;
}
} }
} }
} }

View File

@@ -35,15 +35,12 @@ abstract class JavaTorPlugin extends TorPlugin {
String architecture, String architecture,
long maxLatency, long maxLatency,
int maxIdleTime, int maxIdleTime,
File torDirectory, File torDirectory) {
int torSocksPort,
int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort, maxLatency, maxIdleTime, torDirectory);
torControlPort);
} }
@Override @Override

View File

@@ -35,15 +35,12 @@ class UnixTorPlugin extends JavaTorPlugin {
String architecture, String architecture,
long maxLatency, long maxLatency,
int maxIdleTime, int maxIdleTime,
File torDirectory, File torDirectory) {
int torSocksPort,
int torControlPort) {
super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils, super(ioExecutor, wakefulIoExecutor, networkManager, locationUtils,
torSocketFactory, clock, resourceProvider, torSocketFactory, clock, resourceProvider,
circumventionProvider, batteryManager, backoff, circumventionProvider, batteryManager, backoff,
torRendezvousCrypto, callback, architecture, torRendezvousCrypto, callback, architecture,
maxLatency, maxIdleTime, torDirectory, torSocksPort, maxLatency, maxIdleTime, torDirectory);
torControlPort);
} }
@Override @Override

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
@@ -10,9 +9,7 @@ import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory; import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
@@ -57,9 +54,6 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
private final BatteryManager batteryManager; private final BatteryManager batteryManager;
private final Clock clock; private final Clock clock;
private final File torDirectory; private final File torDirectory;
private int torSocksPort;
private int torControlPort;
private final CryptoComponent crypto;
@Inject @Inject
UnixTorPluginFactory(@IoExecutor Executor ioExecutor, UnixTorPluginFactory(@IoExecutor Executor ioExecutor,
@@ -73,10 +67,7 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, BatteryManager batteryManager,
Clock clock, Clock clock,
@TorDirectory File torDirectory, @TorDirectory File torDirectory) {
@TorSocksPort int torSocksPort,
@TorControlPort int torControlPort,
CryptoComponent crypto) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.wakefulIoExecutor = wakefulIoExecutor; this.wakefulIoExecutor = wakefulIoExecutor;
this.networkManager = networkManager; this.networkManager = networkManager;
@@ -89,9 +80,6 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
this.batteryManager = batteryManager; this.batteryManager = batteryManager;
this.clock = clock; this.clock = clock;
this.torDirectory = torDirectory; this.torDirectory = torDirectory;
this.torSocksPort = torSocksPort;
this.torControlPort = torControlPort;
this.crypto = crypto;
} }
@Override @Override
@@ -132,14 +120,12 @@ public class UnixTorPluginFactory implements DuplexPluginFactory {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
new TorRendezvousCryptoImpl(crypto);
UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, wakefulIoExecutor, UnixTorPlugin plugin = new UnixTorPlugin(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, torSocketFactory, clock, networkManager, locationUtils, torSocketFactory, clock,
resourceProvider, circumventionProvider, batteryManager, resourceProvider, circumventionProvider, batteryManager,
backoff, torRendezvousCrypto, callback, architecture, backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort, MAX_LATENCY, MAX_IDLE_TIME, torDirectory);
torControlPort);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -2,18 +2,15 @@ package org.briarproject.bramble.plugin.tor;
import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons; import org.briarproject.bramble.BrambleCoreIntegrationTestEagerSingletons;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor; import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.WakefulIoExecutor; import org.briarproject.bramble.api.system.WakefulIoExecutor;
import org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType;
import org.briarproject.bramble.test.BrambleJavaIntegrationTestComponent; import org.briarproject.bramble.test.BrambleJavaIntegrationTestComponent;
import org.briarproject.bramble.test.BrambleTestCase; import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.test.DaggerBrambleJavaIntegrationTestComponent; import org.briarproject.bramble.test.DaggerBrambleJavaIntegrationTestComponent;
@@ -36,14 +33,9 @@ import javax.inject.Inject;
import javax.net.SocketFactory; import javax.net.SocketFactory;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_SOCKS_PORT;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.DEFAULT_OBFS4;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.MEEK;
import static org.briarproject.bramble.plugin.tor.CircumventionProvider.BridgeType.NON_DEFAULT_OBFS4;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled; import static org.briarproject.bramble.test.TestUtils.isOptionalTestEnabled;
@@ -62,21 +54,14 @@ public class BridgeTest extends BrambleTestCase {
.injectEagerSingletons(component); .injectEagerSingletons(component);
// Share a failure counter among all the test instances // Share a failure counter among all the test instances
AtomicInteger failures = new AtomicInteger(0); AtomicInteger failures = new AtomicInteger(0);
CircumventionProvider provider = component.getCircumventionProvider(); List<String> bridges =
List<Params> states = new ArrayList<>(); component.getCircumventionProvider().getBridges(false);
for (String bridge : provider.getBridges(DEFAULT_OBFS4)) { List<Params> states = new ArrayList<>(bridges.size());
states.add(new Params(bridge, DEFAULT_OBFS4, failures, false)); for (String bridge : bridges) states.add(new Params(bridge, failures));
}
for (String bridge : provider.getBridges(NON_DEFAULT_OBFS4)) {
states.add(new Params(bridge, NON_DEFAULT_OBFS4, failures, false));
}
for (String bridge : provider.getBridges(MEEK)) {
states.add(new Params(bridge, MEEK, failures, true));
}
return states; return states;
} }
private final static long TIMEOUT = MINUTES.toMillis(5); private final static long TIMEOUT = SECONDS.toMillis(60);
private final static int NUM_FAILURES_ALLOWED = 1; private final static int NUM_FAILURES_ALLOWED = 1;
private final static Logger LOG = getLogger(BridgeTest.class.getName()); private final static Logger LOG = getLogger(BridgeTest.class.getName());
@@ -101,16 +86,16 @@ public class BridgeTest extends BrambleTestCase {
BackoffFactory backoffFactory; BackoffFactory backoffFactory;
@Inject @Inject
Clock clock; Clock clock;
@Inject
CryptoComponent crypto;
private final File torDir = getTestDirectory(); private final File torDir = getTestDirectory();
private final Params params; private final String bridge;
private final AtomicInteger failures;
private UnixTorPluginFactory factory; private UnixTorPluginFactory factory;
public BridgeTest(Params params) { public BridgeTest(Params params) {
this.params = params; bridge = params.bridge;
failures = params.failures;
} }
@Before @Before
@@ -130,7 +115,6 @@ public class BridgeTest extends BrambleTestCase {
LocationUtils locationUtils = () -> "US"; LocationUtils locationUtils = () -> "US";
SocketFactory torSocketFactory = SocketFactory.getDefault(); SocketFactory torSocketFactory = SocketFactory.getDefault();
@NotNullByDefault
CircumventionProvider bridgeProvider = new CircumventionProvider() { CircumventionProvider bridgeProvider = new CircumventionProvider() {
@Override @Override
public boolean isTorProbablyBlocked(String countryCode) { public boolean isTorProbablyBlocked(String countryCode) {
@@ -143,20 +127,19 @@ public class BridgeTest extends BrambleTestCase {
} }
@Override @Override
public BridgeType getBestBridgeType(String countryCode) { public boolean needsMeek(String countryCode) {
return params.bridgeType; return false;
} }
@Override @Override
public List<String> getBridges(BridgeType bridgeType) { public List<String> getBridges(boolean useMeek) {
return singletonList(params.bridge); return singletonList(bridge);
} }
}; };
factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor, factory = new UnixTorPluginFactory(ioExecutor, wakefulIoExecutor,
networkManager, locationUtils, eventBus, torSocketFactory, networkManager, locationUtils, eventBus, torSocketFactory,
backoffFactory, resourceProvider, bridgeProvider, backoffFactory, resourceProvider, bridgeProvider,
batteryManager, clock, torDir, DEFAULT_SOCKS_PORT, batteryManager, clock, torDir);
DEFAULT_CONTROL_PORT, crypto);
} }
@After @After
@@ -171,7 +154,7 @@ public class BridgeTest extends BrambleTestCase {
assertNotNull(duplexPlugin); assertNotNull(duplexPlugin);
UnixTorPlugin plugin = (UnixTorPlugin) duplexPlugin; UnixTorPlugin plugin = (UnixTorPlugin) duplexPlugin;
LOG.warning("Testing " + params.bridge); LOG.warning("Testing " + bridge);
try { try {
plugin.start(); plugin.start();
long start = clock.currentTimeMillis(); long start = clock.currentTimeMillis();
@@ -181,11 +164,8 @@ public class BridgeTest extends BrambleTestCase {
} }
if (plugin.getState() != ACTIVE) { if (plugin.getState() != ACTIVE) {
LOG.warning("Could not connect to Tor within timeout"); LOG.warning("Could not connect to Tor within timeout");
if (params.failures.incrementAndGet() > NUM_FAILURES_ALLOWED) { if (failures.incrementAndGet() > NUM_FAILURES_ALLOWED) {
fail(params.failures.get() + " bridges are unreachable"); fail(failures.get() + " bridges are unreachable");
}
if (params.mustSucceed) {
fail("essential bridge is unreachable");
} }
} }
} finally { } finally {
@@ -196,16 +176,11 @@ public class BridgeTest extends BrambleTestCase {
private static class Params { private static class Params {
private final String bridge; private final String bridge;
private final BridgeType bridgeType;
private final AtomicInteger failures; private final AtomicInteger failures;
private final boolean mustSucceed;
private Params(String bridge, BridgeType bridgeType, private Params(String bridge, AtomicInteger failures) {
AtomicInteger failures, boolean mustSucceed) {
this.bridge = bridge; this.bridge = bridge;
this.bridgeType = bridgeType;
this.failures = failures; this.failures = failures;
this.mustSucceed = mustSucceed;
} }
} }
} }

View File

@@ -25,7 +25,7 @@ dependencyVerification {
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047', '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:obfs4proxy:0.0.12-dev-40245c4a:obfs4proxy-0.0.12-dev-40245c4a.zip:172029e7058b3a83ac93ac4991a44bf76e16ce8d46f558f5836d57da3cb3a766',
'org.briarproject:tor:0.3.5.17:tor-0.3.5.17.jar:ce0e1f4d8f14878e61b23a35a452bc0f2a8e3117ced5a74773cd78475fa7af39', '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-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a', 'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',

View File

@@ -1,28 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?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#" <svg
xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="500" height="175" viewBox="0 0 500 175" xmlns:cc="http://creativecommons.org/ns#"
id="svg2" version="1.1" sodipodi:docname="bluetooth.svg" inkscape:version="1.0.2 (e86c870879, 2021-01-15)"> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
<sodipodi:namedview xmlns:svg="http://www.w3.org/2000/svg"
pagecolor="#ffffff" xmlns="http://www.w3.org/2000/svg"
bordercolor="#666666" width="499.24374"
borderopacity="1" height="175.49413"
objecttolerance="10" viewBox="0 0 499.24373 175.49413"
gridtolerance="10" id="svg2"
guidetolerance="10" version="1.1">
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="892"
id="namedview10"
showgrid="false"
inkscape:zoom="0.93337848"
inkscape:cx="-49.861215"
inkscape:cy="137.66042"
inkscape:window-x="0"
inkscape:window-y="144"
inkscape:window-maximized="0"
inkscape:current-layer="svg2" />
<defs <defs
id="defs4" /> id="defs4" />
<metadata <metadata
@@ -39,23 +26,22 @@
</metadata> </metadata>
<path <path
id="path4201" id="path4201"
d="m 459.80937,167.15983 -4.32657,-4.3343 -7.06956,-2.42737 c -3.88825,-1.33505 -8.72285,-2.99587 -10.74354,-3.6907 l -3.674,-1.26333 3.524,-0.1726 c 8.24183,-0.40367 12.98778,-4.00671 14.33634,-10.88389 0.79628,-4.06078 1.12887,-17.29805 0.83016,-33.04122 -0.15338,-8.08375 -0.16617,-15.41641 -0.0284,-16.29481 0.13775,-0.8784 0.53527,-2.42011 0.88339,-3.42602 1.22247,-3.53243 0.33996,-11.90828 -1.8577,-17.63146 -0.34848,-0.9075 -1.93434,-4.215 -3.52415,-7.35 -4.15849,-8.2003 -4.50458,-8.94188 -4.89292,-10.4841 -0.45865,-1.82145 -0.21161,-5.43531 0.4625,-6.7659 0.66625,-1.31505 2.15695,-2.91616 3.24622,-3.48662 1.29885,-0.68024 2.61568,0.12202 4.6864,2.85512 3.42153,4.51599 14.00135,19.44095 15.73191,22.19301 3.74551,5.95636 5.95558,11.16496 7.9722,18.78849 0.6547,2.475 1.88525,6.9975 2.73456,10.05 0.84931,3.0525 2.71404,10.15792 4.14385,15.78983 l 2.59964,10.23983 4.65,5.19319 c 2.5575,2.85626 5.7975,6.46371 7.2,8.01657 1.4025,1.55286 2.55,2.97543 2.55,3.16127 0,0.33546 -34.49955,29.29931 -34.89913,29.29931 -0.11475,0 -2.15559,-1.95044 -4.5352,-4.3343 z M 365.9443,150.77206 c -1.25762,-0.62844 -2.20557,-1.3788 -2.91402,-2.30663 -2.08931,-2.73629 -1.95034,2.36868 -1.86433,-68.48249 l 0.0777,-64.03881 0.66066,-1.23494 c 1.0152,-1.89767 1.99201,-2.91087 3.73952,-3.87887 l 1.59982,-0.88619 37.78387,-0.0796 c 42.45592,-0.0894 39.40239,-0.2483 42.11646,2.19188 0.87544,0.78709 1.75715,1.95946 2.18393,2.90385 0.71264,1.57698 0.71613,1.63839 0.80561,14.20405 l 0.0899,12.62022 -1.79817,-0.13007 c -1.42577,-0.10313 -2.08143,0.007 -3.16601,0.5321 -2.01294,0.97445 -3.93993,2.89871 -5.11476,5.10753 l -1.03717,1.95 -0.007,-12.825 -0.007,-12.825 h -33.6 -33.6 v 51.3 51.3 h 33.59873 33.59874 l 0.0763,-34.425 c 0.073,-32.96021 0.0982,-34.36117 0.59098,-32.925 0.28309,0.825 1.80562,3.9975 3.3834,7.05 5.49252,10.62624 5.40494,9.86009 5.39597,47.20335 -0.007,27.62122 -0.12358,29.95084 -1.66204,33.10906 -1.07144,2.19949 -2.71143,3.71042 -5.05823,4.66019 l -1.67381,0.6774 -36.1677,0.0797 -36.16769,0.0797 -1.864,-0.93145 z m 42.39939,-5.03813 c 2.87119,-1.30885 4.45771,-3.6784 4.43003,-6.61652 -0.0388,-4.11587 -3.1088,-7.22328 -7.1364,-7.22328 -2.11956,0 -3.56727,0.60889 -5.16364,2.17177 -2.24518,2.19807 -2.75398,5.43897 -1.30101,8.28704 0.71312,1.39782 2.52137,3.00905 3.96214,3.53045 1.49707,0.54176 3.84003,0.47454 5.20888,-0.14946 z" d="m 459.80937,171.15983 -4.32657,-4.3343 -7.06956,-2.42737 c -3.88825,-1.33505 -8.72285,-2.99587 -10.74354,-3.6907 l -3.674,-1.26333 3.524,-0.1726 c 8.24183,-0.40367 12.98778,-4.00671 14.33634,-10.88389 0.79628,-4.06078 1.12887,-17.29805 0.83016,-33.04122 -0.15338,-8.08375 -0.16617,-15.41641 -0.0284,-16.29481 0.13775,-0.8784 0.53527,-2.42011 0.88339,-3.42602 1.22247,-3.53243 0.33996,-11.90828 -1.8577,-17.63146 -0.34848,-0.9075 -1.93434,-4.215 -3.52415,-7.35 -4.15849,-8.2003 -4.50458,-8.94188 -4.89292,-10.4841 -0.45865,-1.82145 -0.21161,-5.43531 0.4625,-6.7659 0.66625,-1.31505 2.15695,-2.91616 3.24622,-3.48662 1.29885,-0.68024 2.61568,0.12202 4.6864,2.85512 3.42153,4.51599 14.00135,19.44095 15.73191,22.19301 3.74551,5.95636 5.95558,11.16496 7.9722,18.78849 0.6547,2.475 1.88525,6.9975 2.73456,10.05 0.84931,3.0525 2.71404,10.15792 4.14385,15.78983 l 2.59964,10.23983 4.65,5.19319 c 2.5575,2.85626 5.7975,6.46371 7.2,8.01657 1.4025,1.55286 2.55,2.97543 2.55,3.16127 0,0.33546 -34.49955,29.29931 -34.89913,29.29931 -0.11475,0 -2.15559,-1.95044 -4.5352,-4.3343 z M 365.9443,154.77206 c -1.25762,-0.62844 -2.20557,-1.3788 -2.91402,-2.30663 -2.08931,-2.73629 -1.95034,2.36868 -1.86433,-68.48249 l 0.0777,-64.03881 0.66066,-1.23494 c 1.0152,-1.89767 1.99201,-2.91087 3.73952,-3.87887 l 1.59982,-0.88619 37.78387,-0.0796 c 42.45592,-0.0894 39.40239,-0.2483 42.11646,2.19188 0.87544,0.78709 1.75715,1.95946 2.18393,2.90385 0.71264,1.57698 0.71613,1.63839 0.80561,14.20405 l 0.0899,12.62022 -1.79817,-0.13007 c -1.42577,-0.10313 -2.08143,0.007 -3.16601,0.5321 -2.01294,0.97445 -3.93993,2.89871 -5.11476,5.10753 l -1.03717,1.95 -0.007,-12.825 -0.007,-12.825 -33.6,0 -33.6,0 0,51.3 0,51.3 33.59873,0 33.59874,0 0.0763,-34.425 c 0.073,-32.96021 0.0982,-34.36117 0.59098,-32.925 0.28309,0.825 1.80562,3.9975 3.3834,7.05 5.49252,10.62624 5.40494,9.86009 5.39597,47.20335 -0.007,27.62122 -0.12358,29.95084 -1.66204,33.10906 -1.07144,2.19949 -2.71143,3.71042 -5.05823,4.66019 l -1.67381,0.6774 -36.1677,0.0797 -36.16769,0.0797 -1.864,-0.93145 z m 42.39939,-5.03813 c 2.87119,-1.30885 4.45771,-3.6784 4.43003,-6.61652 -0.0388,-4.11587 -3.1088,-7.22328 -7.1364,-7.22328 -2.11956,0 -3.56727,0.60889 -5.16364,2.17177 -2.24518,2.19807 -2.75398,5.43897 -1.30101,8.28704 0.71312,1.39782 2.52137,3.00905 3.96214,3.53045 1.49707,0.54176 3.84003,0.47454 5.20888,-0.14946 z"
style="fill:#000000;stroke:none" /> style="fill:#000000" />
<path <path
id="path4201-1" id="path4201-1"
d="m 39.434334,167.15983 4.32657,-4.3343 7.06956,-2.42737 c 3.88825,-1.33505 8.72285,-2.99587 10.74354,-3.6907 l 3.674,-1.26333 -3.524,-0.1726 c -8.24183,-0.40367 -12.98778,-4.00671 -14.33634,-10.88389 -0.79628,-4.06078 -1.12887,-17.29805 -0.83016,-33.04122 0.15338,-8.08375 0.16617,-15.41641 0.0284,-16.29481 -0.13775,-0.8784 -0.53527,-2.42011 -0.88339,-3.42602 -1.22247,-3.53243 -0.33996,-11.90828 1.8577,-17.63146 0.34848,-0.9075 1.93434,-4.215 3.52415,-7.35 4.15849,-8.2003 4.50458,-8.94188 4.89292,-10.4841 0.45865,-1.82145 0.21161,-5.43531 -0.4625,-6.7659 -0.66625,-1.31505 -2.15695,-2.91616 -3.24622,-3.48662 -1.29885,-0.68024 -2.61568,0.12202 -4.6864,2.85512 -3.42153,4.51599 -14.00135,19.44095 -15.73191,22.19301 -3.74551,5.95636 -5.955584,11.16496 -7.972204,18.78849 -0.6547,2.475 -1.88525,6.9975 -2.73456,10.05 -0.84931,3.0525 -2.71404,10.15792 -4.14385,15.78983 L 14.4,125.82379 9.75,131.01698 c -2.5575,2.85626 -5.7975,6.46371 -7.2,8.01657 -1.4025,1.55286 -2.55,2.97543 -2.55,3.16127 0,0.33546 34.499554,29.29931 34.899134,29.29931 0.11475,0 2.15559,-1.95044 4.53519,-4.3343 z m 93.865056,-16.38777 c 1.25762,-0.62844 2.20557,-1.3788 2.91402,-2.30663 2.08931,-2.73629 1.95034,2.36868 1.86433,-68.48249 l -0.0777,-64.03881 -0.66066,-1.23494 c -1.0152,-1.89767 -1.99201,-2.91087 -3.73952,-3.87887 L 132.00004,9.94413 94.216184,9.86453 c -42.45592,-0.0894 -39.40239,-0.2483 -42.11646,2.19188 -0.87544,0.78709 -1.75715,1.95946 -2.18393,2.90385 -0.71264,1.57698 -0.71613,1.63839 -0.80561,14.20405 l -0.0899,12.62022 1.79817,-0.13007 c 1.42577,-0.10313 2.08143,0.007 3.16601,0.5321 2.01294,0.97445 3.93993,2.89871 5.11476,5.10753 l 1.03717,1.95 0.007,-12.825 0.007,-12.825 h 33.6 33.599986 v 51.3 51.3 H 93.751664 60.152924 l -0.0763,-34.425 c -0.073,-32.96021 -0.0982,-34.36117 -0.59098,-32.925 -0.28309,0.825 -1.80562,3.9975 -3.3834,7.05 -5.49252,10.62624 -5.40494,9.86009 -5.39597,47.20335 0.007,27.62122 0.12358,29.95084 1.66204,33.10906 1.07144,2.19949 2.71143,3.71042 5.05823,4.66019 l 1.67381,0.6774 36.1677,0.0797 36.167676,0.0797 1.864,-0.93145 z m -42.399376,-5.03813 c -2.87119,-1.30885 -4.45771,-3.6784 -4.43003,-6.61652 0.0388,-4.11587 3.1088,-7.22328 7.1364,-7.22328 2.11956,0 3.56727,0.60889 5.16364,2.17177 2.245176,2.19807 2.753976,5.43897 1.301006,8.28704 -0.713116,1.39782 -2.521366,3.00905 -3.962136,3.53045 -1.49707,0.54176 -3.84003,0.47454 -5.20888,-0.14946 z" d="m 39.434334,171.15983 4.32657,-4.3343 7.06956,-2.42737 c 3.88825,-1.33505 8.72285,-2.99587 10.74354,-3.6907 l 3.674,-1.26333 -3.524,-0.1726 c -8.24183,-0.40367 -12.98778,-4.00671 -14.33634,-10.88389 -0.79628,-4.06078 -1.12887,-17.29805 -0.83016,-33.04122 0.15338,-8.08375 0.16617,-15.41641 0.0284,-16.29481 -0.13775,-0.8784 -0.53527,-2.42011 -0.88339,-3.42602 -1.22247,-3.53243 -0.33996,-11.90828 1.8577,-17.63146 0.34848,-0.9075 1.93434,-4.215 3.52415,-7.35 4.15849,-8.2003 4.50458,-8.94188 4.89292,-10.4841 0.45865,-1.82145 0.21161,-5.43531 -0.4625,-6.7659 -0.66625,-1.31505 -2.15695,-2.91616 -3.24622,-3.48662 -1.29885,-0.68024 -2.61568,0.12202 -4.6864,2.85512 -3.42153,4.51599 -14.00135,19.44095 -15.73191,22.19301 -3.74551,5.95636 -5.955584,11.16496 -7.972204,18.78849 -0.6547,2.475 -1.88525,6.9975 -2.73456,10.05 -0.84931,3.0525 -2.71404,10.15792 -4.14385,15.78983 L 14.4,129.82379 9.75,135.01698 c -2.5575,2.85626 -5.7975,6.46371 -7.2,8.01657 -1.4025,1.55286 -2.55,2.97543 -2.55,3.16127 0,0.33546 34.499554,29.29931 34.899134,29.29931 0.11475,0 2.15559,-1.95044 4.53519,-4.3343 z m 93.865056,-16.38777 c 1.25762,-0.62844 2.20557,-1.3788 2.91402,-2.30663 2.08931,-2.73629 1.95034,2.36868 1.86433,-68.48249 l -0.0777,-64.03881 -0.66066,-1.23494 c -1.0152,-1.89767 -1.99201,-2.91087 -3.73952,-3.87887 l -1.59982,-0.88619 -37.783856,-0.0796 c -42.45592,-0.0894 -39.40239,-0.2483 -42.11646,2.19188 -0.87544,0.78709 -1.75715,1.95946 -2.18393,2.90385 -0.71264,1.57698 -0.71613,1.63839 -0.80561,14.20405 l -0.0899,12.62022 1.79817,-0.13007 c 1.42577,-0.10313 2.08143,0.007 3.16601,0.5321 2.01294,0.97445 3.93993,2.89871 5.11476,5.10753 l 1.03717,1.95 0.007,-12.825 0.007,-12.825 33.6,0 33.599986,0 0,51.3 0,51.3 -33.598716,0 -33.59874,0 -0.0763,-34.425 c -0.073,-32.96021 -0.0982,-34.36117 -0.59098,-32.925 -0.28309,0.825 -1.80562,3.9975 -3.3834,7.05 -5.49252,10.62624 -5.40494,9.86009 -5.39597,47.20335 0.007,27.62122 0.12358,29.95084 1.66204,33.10906 1.07144,2.19949 2.71143,3.71042 5.05823,4.66019 l 1.67381,0.6774 36.1677,0.0797 36.167676,0.0797 1.864,-0.93145 z m -42.399376,-5.03813 c -2.87119,-1.30885 -4.45771,-3.6784 -4.43003,-6.61652 0.0388,-4.11587 3.1088,-7.22328 7.1364,-7.22328 2.11956,0 3.56727,0.60889 5.16364,2.17177 2.245176,2.19807 2.753976,5.43897 1.301006,8.28704 -0.713116,1.39782 -2.521366,3.00905 -3.962136,3.53045 -1.49707,0.54176 -3.84003,0.47454 -5.20888,-0.14946 z"
style="fill:#000000;stroke:none" /> style="fill:#000000" />
<path <path
id="rect4270" id="rect4270"
d="m 247.25369,71.97921 h 4.73637 c 13.16497,0 23.76348,10.598514 23.76348,23.763485 v 32.174615 c 0,13.16497 -10.59851,23.76348 -23.76348,23.76348 h -4.73637 c -13.16497,0 -23.76349,-10.59851 -23.76349,-23.76348 V 95.742695 c 0,-13.164971 10.59852,-23.763485 23.76349,-23.763485 z" d="m 247.25369,75.97921 4.73637,0 c 13.16497,0 23.76348,10.598514 23.76348,23.763485 l 0,32.174615 c 0,13.16497 -10.59851,23.76348 -23.76348,23.76348 l -4.73637,0 c -13.16497,0 -23.76349,-10.59851 -23.76349,-23.76348 l 0,-32.174615 c 0,-13.164971 10.59852,-23.763485 23.76349,-23.763485 z"
style="fill:#0a3d91;stroke:none" /> style="fill:#0a3d91" />
<path
id="path4272"
d="m 236.31105,102.92749 24.90674,25.07007 -12.00423,14.53574 0,-51.936691 12.00423,13.882451 -24.90674,24.41678"
style="fill:none;stroke:#ffffff;stroke-width:4.32805729" />
<path <path
id="path4844" id="path4844"
d="m 143.67921,23.5571 c -1.59043,2.623831 0.18153,5.574737 2.78461,6.642714 2.69504,1.572445 6.1706,4.987176 9.14793,2.232151 2.23313,-2.039515 0.60129,-5.727894 -2.04109,-6.67035 -3.06433,-1.676733 -6.55172,-5.514807 -9.89145,-2.204515 z M 351.7046,23.12937 c -2.76779,1.960623 -7.06819,2.694997 -8.37782,6.042717 -0.64195,2.73095 1.93572,4.99255 4.58419,4.426453 3.2021,-1.637914 7.05658,-2.8424 9.17849,-5.94769 0.56931,-2.60435 -1.49324,-5.35066 -4.26769,-4.745697 -0.41558,-0.107679 -0.76003,0.03505 -1.11717,0.224217 z m -26.76172,13.17187 c -2.93431,1.708015 -7.32039,1.922759 -8.93076,5.153004 -0.90775,2.654328 1.43202,5.159236 4.12365,4.861044 3.35587,-1.304271 7.31954,-2.112696 9.73662,-5.002268 0.81368,-2.537666 -0.97658,-5.469583 -3.79644,-5.128908 -0.4035,-0.14574 -0.75969,-0.03824 -1.13307,0.117128 z m -155.23633,2.46289 c -1.21948,2.711869 0.75683,5.460507 3.4437,6.14538 2.85847,1.080772 6.66937,4.11785 9.31224,1.23392 2.3151,-2.03652 0.33929,-5.835383 -2.40983,-6.41823 -3.32833,-1.175814 -7.38479,-4.713633 -10.34611,-0.96107 z m 127.27344,7.61719 c -3.12289,1.309174 -7.49226,0.970678 -9.49244,3.970097 -1.23184,2.518748 0.7727,5.298264 3.48037,5.339749 3.48706,-0.907308 7.56742,-1.1128 10.30314,-3.739116 1.11397,-2.422222 -0.31199,-5.546068 -3.1516,-5.551016 -0.3827,-0.195662 -0.75023,-0.126964 -1.13947,-0.01971 z m -97.49023,1.54492 c -2.22858,1.461838 -2.68005,4.865948 -0.27553,6.376909 2.5869,1.470583 5.91459,1.954941 8.83971,2.495346 2.78485,0.332188 4.74603,-2.479173 3.89118,-5.048668 -2.04264,-3.279676 -6.47206,-2.73364 -9.71704,-4.089227 -0.91277,0.08855 -1.82555,0.177093 -2.73832,0.26564 z m 68.51367,4.50782 c -3.27623,0.788856 -7.46081,-0.187875 -9.93635,2.381992 -1.64972,2.268076 -0.15709,5.353662 2.50432,5.86185 3.61172,-0.292365 7.71764,0.09072 10.84009,-2.093962 1.46245,-2.227649 0.52336,-5.531725 -2.28478,-5.959415 -0.34949,-0.249225 -0.72211,-0.239347 -1.12328,-0.190465 z m -39.44922,1.41796 c -1.93309,1.83595 -1.76537,5.266611 0.87081,6.321491 2.80857,0.988807 6.17065,0.846733 9.1444,0.861366 2.79909,-0.172766 4.22635,-3.289835 2.92376,-5.664738 -2.60365,-2.851635 -6.84699,-1.541752 -10.29251,-2.269899 -0.88215,0.250593 -1.76431,0.501187 -2.64646,0.75178 z" d="m 143.67921,27.5571 c -1.59043,2.623831 0.18153,5.574737 2.78461,6.642714 2.69504,1.572445 6.1706,4.987176 9.14793,2.232151 2.23313,-2.039515 0.60129,-5.727894 -2.04109,-6.67035 -3.06433,-1.676733 -6.55172,-5.514807 -9.89145,-2.204515 z M 351.7046,27.12937 c -2.76779,1.960623 -7.06819,2.694997 -8.37782,6.042717 -0.64195,2.73095 1.93572,4.99255 4.58419,4.426453 3.2021,-1.637914 7.05658,-2.8424 9.17849,-5.94769 0.56931,-2.60435 -1.49324,-5.35066 -4.26769,-4.745697 -0.41558,-0.107679 -0.76003,0.03505 -1.11717,0.224217 z m -26.76172,13.17187 c -2.93431,1.708015 -7.32039,1.922759 -8.93076,5.153004 -0.90775,2.654328 1.43202,5.159236 4.12365,4.861044 3.35587,-1.304271 7.31954,-2.112696 9.73662,-5.002268 0.81368,-2.537666 -0.97658,-5.469583 -3.79644,-5.128908 -0.4035,-0.14574 -0.75969,-0.03824 -1.13307,0.117128 z m -155.23633,2.46289 c -1.21948,2.711869 0.75683,5.460507 3.4437,6.14538 2.85847,1.080772 6.66937,4.11785 9.31224,1.23392 2.3151,-2.03652 0.33929,-5.835383 -2.40983,-6.41823 -3.32833,-1.175814 -7.38479,-4.713633 -10.34611,-0.96107 z m 127.27344,7.61719 c -3.12289,1.309174 -7.49226,0.970678 -9.49244,3.970097 -1.23184,2.518748 0.7727,5.298264 3.48037,5.339749 3.48706,-0.907308 7.56742,-1.1128 10.30314,-3.739116 1.11397,-2.422222 -0.31199,-5.546068 -3.1516,-5.551016 -0.3827,-0.195662 -0.75023,-0.126964 -1.13947,-0.01971 z m -97.49023,1.54492 c -2.22858,1.461838 -2.68005,4.865948 -0.27553,6.376909 2.5869,1.470583 5.91459,1.954941 8.83971,2.495346 2.78485,0.332188 4.74603,-2.479173 3.89118,-5.048668 -2.04264,-3.279676 -6.47206,-2.73364 -9.71704,-4.089227 -0.91277,0.08855 -1.82555,0.177093 -2.73832,0.26564 z m 68.51367,4.50782 c -3.27623,0.788856 -7.46081,-0.187875 -9.93635,2.381992 -1.64972,2.268076 -0.15709,5.353662 2.50432,5.86185 3.61172,-0.292365 7.71764,0.09072 10.84009,-2.093962 1.46245,-2.227649 0.52336,-5.531725 -2.28478,-5.959415 -0.34949,-0.249225 -0.72211,-0.239347 -1.12328,-0.190465 z m -39.44922,1.41796 c -1.93309,1.83595 -1.76537,5.266611 0.87081,6.321491 2.80857,0.988807 6.17065,0.846733 9.1444,0.861366 2.79909,-0.172766 4.22635,-3.289835 2.92376,-5.664738 -2.60365,-2.851635 -6.84699,-1.541752 -10.29251,-2.269899 -0.88215,0.250593 -1.76431,0.501187 -2.64646,0.75178 z"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0a3d91;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.55;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:7.55, 22.65;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#0a3d91;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:7.55000019;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:7.55, 22.65;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
d="m 252.50083,112.08988 11.6563,-11.45156 -17.12592,-19.790888 0.0193,25.792048 -9.14185,-9.24454 -3.12531,3.09064 11.5214,11.58063 -11.49773,11.30756 c 3.03061,3.05593 0,0 3.03061,3.05593 l 9.18921,-8.97308 c 0.0443,4.73517 0.004,27.16515 0.004,27.16515 l 17.10224,-20.77257 z m -1.07721,-19.570428 6.79869,7.863838 -6.79869,6.63278 z m -0.0237,40.027828 0.0237,-15.39623 6.89338,6.9879 z"
id="path1536"
style="display:inline;opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.254891"
sodipodi:nodetypes="ccccccccccccccccccccc" />
</svg> </svg>

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,83 +0,0 @@
<?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="256" height="204"
viewBox="0 0 256 204" fill="none" version="1.1" id="svg42" sodipodi:docname="share_app.svg"
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
<metadata id="metadata48">
<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>
<defs id="defs46" />
<sodipodi:namedview pagecolor="#000000" bordercolor="#666666" borderopacity="1"
objecttolerance="10" gridtolerance="10" guidetolerance="10" inkscape:pageopacity="0"
inkscape:pageshadow="2" inkscape:window-width="1920" inkscape:window-height="964"
id="namedview44" showgrid="false" inkscape:zoom="2.4705882" inkscape:cx="123.34752"
inkscape:cy="83.759737" inkscape:window-x="1920" inkscape:window-y="72"
inkscape:window-maximized="0" inkscape:current-layer="svg42" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M41.583 100.841H22.1807V102.841H52.7503V136.663H54.7503V102.841H68.0341C70.9241 102.841 73.267 105.184 73.267 108.074C73.267 112.068 76.5053 115.307 80.4999 115.307H92.727V113.307H80.4999C77.6098 113.307 75.267 110.964 75.267 108.074C75.267 104.079 72.0287 100.841 68.0341 100.841H43.583V63.6593H41.583V100.841Z"
fill="#657D99" id="path2" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M122.611 86.0596V46.2531H124.611V86.0596H122.611Z" fill="#657D99" id="path4" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M119.754 179.928L119.754 142.682L121.754 142.682L121.754 179.928L119.754 179.928Z"
fill="#657D99" id="path6" />
<path opacity="0.5" fill-rule="evenodd" clip-rule="evenodd"
d="M195.251 100.841V86.5962H193.251V113.826H148.362V115.826H194.251C198.125 115.826 201.301 118.969 201.301 122.826V127.044H203.301V122.826C203.301 118.186 199.75 114.378 195.251 113.881V102.841H233.052V100.841H195.251Z"
fill="#657D99" id="path8" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M32.1213 57.4112L32.8875 55.5637C33.5961 55.8576 34.3747 56.0208 35.1966 56.0208H37.0795V58.0208H35.1966C34.1072 58.0208 33.0686 57.804 32.1213 57.4112ZM48.3769 58.0208V56.0208H50.2598C51.0816 56.0208 51.8602 55.8576 52.5689 55.5637L53.335 57.4112C52.3877 57.804 51.3491 58.0208 50.2598 58.0208H48.3769ZM58.2935 36.8067H56.2935V34.9238C56.2935 34.102 56.1303 33.3234 55.8364 32.6147L57.6839 31.8486C58.0767 32.7959 58.2935 33.8345 58.2935 34.9238V36.8067ZM37.0795 26.8901H35.1966C34.1072 26.8901 33.0686 27.1069 32.1213 27.4997L32.8875 29.3472C33.5961 29.0533 34.3747 28.8901 35.1966 28.8901H37.0795V26.8901ZM27.1628 48.1042H29.1628V49.9871C29.1628 50.8089 29.326 51.5875 29.6199 52.2962L27.7724 53.0623C27.3796 52.115 27.1628 51.0764 27.1628 49.9871V48.1042ZM27.1628 44.3384H29.1628V40.5725H27.1628V44.3384ZM27.1628 36.8067H29.1628V34.9238C29.1628 34.102 29.326 33.3234 29.6199 32.6147L27.7724 31.8486C27.3796 32.7959 27.1628 33.8345 27.1628 34.9238V36.8067ZM40.8453 26.8901V28.8901H44.6111V26.8901H40.8453ZM48.3769 26.8901V28.8901H50.2598C51.0816 28.8901 51.8602 29.0533 52.5689 29.3472L53.335 27.4997C52.3877 27.1069 51.3491 26.8901 50.2598 26.8901H48.3769ZM58.2935 40.5725H56.2935V44.3383H58.2935V40.5725ZM58.2935 48.1042H56.2935V49.9871C56.2935 50.8089 56.1303 51.5875 55.8364 52.2962L57.6839 53.0623C58.0767 52.115 58.2935 51.0764 58.2935 49.9871V48.1042ZM44.6111 58.0208V56.0208H40.8453V58.0208H44.6111Z"
fill="#657D99" id="path10" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M112.487 40.4256L112.875 38.4636C113.41 38.5694 113.964 38.6251 114.533 38.6251H116.99V40.6251H114.533C113.833 40.6251 113.149 40.5565 112.487 40.4256ZM131.733 40.6251V38.6251H134.191C134.76 38.6251 135.314 38.5694 135.848 38.4636L136.237 40.4256C135.575 40.5565 134.891 40.6251 134.191 40.6251H131.733ZM140.016 38.8593L138.903 37.1973C139.829 36.5774 140.627 35.7797 141.247 34.8536L142.909 35.9663C142.143 37.1095 141.159 38.0939 140.016 38.8593ZM144.674 12.9411H142.674V10.4839C142.674 9.91475 142.619 9.36059 142.513 8.82599L144.475 8.43785C144.606 9.0996 144.674 9.78374 144.674 10.4839V12.9411ZM142.909 4.65889L141.247 5.77152C140.627 4.84548 139.829 4.04776 138.903 3.42779L140.016 1.76585C141.159 2.53126 142.143 3.5156 142.909 4.65889ZM116.99 0H114.533C113.833 0 113.149 0.0686375 112.487 0.199551L112.875 2.16153C113.41 2.05577 113.964 2 114.533 2H116.99V0ZM108.708 1.76585L109.821 3.42779C108.895 4.04776 108.097 4.84548 107.477 5.77152L105.815 4.65888C106.581 3.5156 107.565 2.53126 108.708 1.76585ZM104.049 27.6841H106.049V30.1412C106.049 30.7104 106.105 31.2645 106.211 31.7992L104.249 32.1873C104.118 31.5255 104.049 30.8414 104.049 30.1412V27.6841ZM105.815 35.9663L107.477 34.8536C108.097 35.7797 108.895 36.5774 109.821 37.1973L108.708 38.8593C107.565 38.0939 106.581 37.1095 105.815 35.9663ZM104.049 22.7697H106.049V17.8554H104.049V22.7697ZM104.049 12.9411H106.049V10.4839C106.049 9.91475 106.105 9.36059 106.211 8.82598L104.249 8.43785C104.118 9.09959 104.049 9.78374 104.049 10.4839V12.9411ZM121.905 0V2H126.819V0H121.905ZM131.733 0V2H134.191C134.76 2 135.314 2.05577 135.848 2.16153L136.237 0.199552C135.575 0.0686377 134.891 0 134.191 0H131.733ZM144.674 17.8554H142.674V22.7697H144.674V17.8554ZM144.674 27.6841H142.674V30.1412C142.674 30.7104 142.619 31.2645 142.513 31.7992L144.475 32.1873C144.606 31.5255 144.674 30.8414 144.674 30.1412V27.6841ZM126.819 40.6251V38.6251H121.905V40.6251H126.819Z"
fill="#657D99" id="path12" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M183.397 81.9904L184.163 80.1429C184.902 80.4493 185.714 80.6194 186.57 80.6194H188.513V82.6194H186.57C185.446 82.6194 184.375 82.3957 183.397 81.9904ZM200.171 82.6194V80.6194H202.114C202.97 80.6194 203.782 80.4493 204.521 80.1429L205.287 81.9904C204.309 82.3957 203.238 82.6194 202.114 82.6194H200.171ZM210.403 60.7295H208.403V58.7866C208.403 57.9301 208.233 57.1184 207.927 56.3795L209.774 55.6134C210.18 56.5908 210.403 57.6626 210.403 58.7866V60.7295ZM188.513 50.4969H186.57C185.446 50.4969 184.375 50.7207 183.397 51.126L184.163 52.9734C184.902 52.667 185.714 52.4969 186.57 52.4969H188.513V50.4969ZM178.281 72.3869H180.281V74.3297C180.281 75.1863 180.451 75.998 180.757 76.7368L178.91 77.5029C178.504 76.5255 178.281 75.4538 178.281 74.3297V72.3869ZM178.281 68.5011H180.281V64.6153H178.281V68.5011ZM178.281 60.7295H180.281V58.7866C180.281 57.9301 180.451 57.1184 180.757 56.3795L178.91 55.6134C178.504 56.5908 178.281 57.6626 178.281 58.7866V60.7295ZM192.399 50.4969V52.4969H196.285V50.4969H192.399ZM200.171 50.4969V52.4969H202.114C202.97 52.4969 203.782 52.667 204.521 52.9734L205.287 51.126C204.309 50.7207 203.238 50.4969 202.114 50.4969H200.171ZM210.403 64.6153H208.403V68.5011H210.403V64.6153ZM210.403 72.3869H208.403V74.3297C208.403 75.1863 208.233 75.998 207.927 76.7368L209.774 77.5029C210.18 76.5255 210.403 75.4538 210.403 74.3297V72.3869ZM196.285 82.6194V80.6194H192.399V82.6194H196.285Z"
fill="#657D99" id="path14" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M188.271 180.562L188.659 178.6C189.316 178.73 189.996 178.798 190.694 178.798H192.633V180.798H190.694C189.865 180.798 189.055 180.717 188.271 180.562ZM212.029 180.798V178.798H213.968C214.666 178.798 215.346 178.73 216.003 178.6L216.391 180.562C215.607 180.717 214.797 180.798 213.968 180.798H212.029ZM220.865 178.708L219.753 177.046C220.889 176.285 221.868 175.306 222.629 174.17L224.291 175.282C223.384 176.636 222.219 177.801 220.865 178.708ZM226.381 147.05H224.381V145.111C224.381 144.413 224.313 143.733 224.183 143.077L226.145 142.688C226.3 143.472 226.381 144.282 226.381 145.111V147.05ZM224.291 138.214L222.629 139.327C221.868 138.19 220.889 137.211 219.753 136.451L220.865 134.789C222.219 135.695 223.384 136.86 224.291 138.214ZM192.633 132.698H190.694C189.865 132.698 189.055 132.779 188.271 132.934L188.659 134.896C189.316 134.766 189.996 134.698 190.694 134.698H192.633V132.698ZM183.797 134.789L184.91 136.451C183.773 137.211 182.794 138.19 182.033 139.327L180.372 138.214C181.278 136.86 182.443 135.695 183.797 134.789ZM178.281 166.446H180.281V168.385C180.281 169.083 180.349 169.763 180.479 170.42L178.517 170.808C178.362 170.024 178.281 169.214 178.281 168.385V166.446ZM180.372 175.282L182.033 174.17C182.794 175.306 183.773 176.285 184.91 177.046L183.797 178.708C182.443 177.801 181.278 176.636 180.372 175.282ZM178.281 162.567H180.281V158.688H178.281V162.567ZM178.281 154.809H180.281V150.93H178.281V154.809ZM178.281 147.05H180.281V145.111C180.281 144.413 180.349 143.733 180.479 143.077L178.517 142.688C178.362 143.472 178.281 144.282 178.281 145.111V147.05ZM196.512 132.698V134.698H200.392V132.698H196.512ZM204.271 132.698V134.698H208.15V132.698H204.271ZM212.029 132.698V134.698H213.968C214.666 134.698 215.346 134.766 216.003 134.896L216.391 132.934C215.607 132.779 214.797 132.698 213.968 132.698H212.029ZM226.381 150.93H224.381V154.809H226.381V150.93ZM226.381 158.688H224.381V162.567H226.381V158.688ZM226.381 166.446H224.381V168.385C224.381 169.083 224.313 169.763 224.183 170.42L226.145 170.808C226.3 170.024 226.381 169.214 226.381 168.385V166.446ZM208.15 180.798V178.798H204.271V180.798H208.15ZM200.392 180.798V178.798H196.512V180.798H200.392Z"
fill="#657D99" id="path16" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M40.3891 175.457L41.1552 173.609C41.9338 173.932 42.7892 174.111 43.6915 174.111H45.7134V176.111H43.6915C42.5217 176.111 41.4063 175.878 40.3891 175.457ZM57.8451 176.111V174.111H59.8671C60.7693 174.111 61.6247 173.932 62.4033 173.609L63.1694 175.457C62.1522 175.878 61.0368 176.111 59.8671 176.111H57.8451ZM68.4941 153.33H66.4941V151.309C66.4941 150.406 66.3149 149.551 65.992 148.772L67.8395 148.006C68.2613 149.023 68.4941 150.139 68.4941 151.309V153.33ZM45.7134 142.682H43.6915C42.5217 142.682 41.4063 142.914 40.3891 143.336L41.1552 145.184C41.9338 144.861 42.7892 144.682 43.6915 144.682H45.7134V142.682ZM35.0645 165.462H37.0645V167.484C37.0645 168.386 37.2437 169.242 37.5665 170.02L35.7191 170.786C35.2973 169.769 35.0645 168.654 35.0645 167.484V165.462ZM35.0645 161.418H37.0645V157.374H35.0645V161.418ZM35.0645 153.33H37.0645V151.309C37.0645 150.406 37.2437 149.551 37.5665 148.772L35.7191 148.006C35.2973 149.023 35.0645 150.139 35.0645 151.309V153.33ZM49.7573 142.682V144.682H53.8012V142.682H49.7573ZM57.8451 142.682V144.682H59.8671C60.7693 144.682 61.6247 144.861 62.4033 145.184L63.1694 143.336C62.1522 142.914 61.0368 142.682 59.8671 142.682H57.8451ZM68.4941 157.374H66.4941V161.418H68.4941V157.374ZM68.4941 165.462H66.4941V167.484C66.4941 168.386 66.3149 169.242 65.992 170.02L67.8395 170.786C68.2613 169.769 68.4941 168.654 68.4941 167.484V165.462ZM53.8012 176.111V174.111H49.7573V176.111H53.8012Z"
fill="#657D99" id="path18" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M2.84 110.802L3.60611 108.954C3.91005 109.081 4.24493 109.151 4.60133 109.151H6.75821V111.151H4.60133C3.97743 111.151 3.38253 111.027 2.84 110.802ZM11.072 111.151V109.151H13.2288C13.5852 109.151 13.9201 109.081 14.2241 108.954L14.9902 110.802C14.4476 111.027 13.8527 111.151 13.2288 111.151H11.072ZM17.8302 100.079H15.8302V97.9223C15.8302 97.5659 15.7596 97.231 15.6336 96.927L17.481 96.1609C17.706 96.7035 17.8302 97.2984 17.8302 97.9223V100.079ZM6.75821 93.3209H4.60133C3.97743 93.3209 3.38253 93.4451 2.84 93.6701L3.60611 95.5175C3.91005 95.3915 4.24493 95.3209 4.60133 95.3209H6.75821V93.3209ZM0 104.393H2V106.55C2 106.906 2.07056 107.241 2.1966 107.545L0.349152 108.311C0.124172 107.769 0 107.174 0 106.55V104.393ZM0 100.079H2V97.9223C2 97.5659 2.07056 97.231 2.1966 96.927L0.349152 96.1609C0.124172 96.7035 0 97.2984 0 97.9223V100.079ZM11.072 93.3209V95.3209H13.2288C13.5852 95.3209 13.9201 95.3915 14.2241 95.5175L14.9902 93.6701C14.4476 93.4451 13.8527 93.3209 13.2288 93.3209H11.072ZM17.8302 104.393H15.8302V106.55C15.8302 106.906 15.7596 107.241 15.6336 107.545L17.481 108.311C17.706 107.769 17.8302 107.174 17.8302 106.55V104.393Z"
fill="#657D99" id="path20" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M114.745 202.969L115.511 201.122C115.815 201.248 116.149 201.318 116.506 201.318H118.663V203.318H116.506C115.882 203.318 115.287 203.194 114.745 202.969ZM122.977 203.318V201.318H125.133C125.49 201.318 125.825 201.248 126.129 201.122L126.895 202.969C126.352 203.194 125.757 203.318 125.133 203.318H122.977ZM129.735 192.246H127.735V190.09C127.735 189.733 127.664 189.398 127.538 189.094L129.386 188.328C129.611 188.871 129.735 189.466 129.735 190.09V192.246ZM118.663 185.488H116.506C115.882 185.488 115.287 185.612 114.745 185.837L115.511 187.685C115.815 187.559 116.149 187.488 116.506 187.488H118.663V185.488ZM111.905 196.56H113.905V198.717C113.905 199.074 113.975 199.408 114.101 199.712L112.254 200.478C112.029 199.936 111.905 199.341 111.905 198.717V196.56ZM111.905 192.246H113.905V190.09C113.905 189.733 113.975 189.398 114.101 189.094L112.254 188.328C112.029 188.871 111.905 189.466 111.905 190.09V192.246ZM122.977 185.488V187.488H125.133C125.49 187.488 125.825 187.559 126.129 187.685L126.895 185.837C126.352 185.612 125.757 185.488 125.133 185.488H122.977ZM129.735 196.56H127.735V198.717C127.735 199.074 127.664 199.408 127.538 199.712L129.386 200.478C129.611 199.936 129.735 199.341 129.735 198.717V196.56Z"
fill="#657D99" id="path22" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M240.444 110.802L241.21 108.954C241.514 109.081 241.849 109.151 242.205 109.151H244.362V111.151H242.205C241.581 111.151 240.987 111.027 240.444 110.802ZM248.676 111.151V109.151H250.833C251.189 109.151 251.524 109.081 251.828 108.954L252.594 110.802C252.052 111.027 251.457 111.151 250.833 111.151H248.676ZM255.434 100.079H253.434V97.9223C253.434 97.5659 253.364 97.231 253.238 96.927L255.085 96.1609C255.31 96.7035 255.434 97.2984 255.434 97.9223V100.079ZM244.362 93.3209H242.205C241.581 93.3209 240.987 93.4451 240.444 93.6701L241.21 95.5175C241.514 95.3915 241.849 95.3209 242.205 95.3209H244.362V93.3209ZM237.604 104.393H239.604V106.55C239.604 106.906 239.675 107.241 239.801 107.545L237.953 108.311C237.728 107.769 237.604 107.174 237.604 106.55V104.393ZM237.604 100.079H239.604V97.9223C239.604 97.5659 239.675 97.231 239.801 96.927L237.953 96.1609C237.728 96.7035 237.604 97.2984 237.604 97.9223V100.079ZM248.676 93.3209V95.3209H250.833C251.189 95.3209 251.524 95.3915 251.828 95.5175L252.594 93.6701C252.052 93.4451 251.457 93.3209 250.833 93.3209H248.676ZM255.434 104.393H253.434V106.55C253.434 106.906 253.364 107.241 253.238 107.545L255.085 108.311C255.31 107.769 255.434 107.174 255.434 106.55V104.393Z"
fill="#657D99" id="path24" />
<path
d="M108.75 109.808V129.511C108.75 131.11 110.052 132.429 111.668 132.429H113.036C114.636 132.429 115.955 131.11 115.955 129.511V109.808H108.75V109.808Z"
fill="#87C214" id="path26" />
<path
d="M115.938 100.312V96.6023C115.938 95.003 114.636 93.684 113.036 93.684H111.668C110.069 93.684 108.75 95.003 108.75 96.6023V100.312H115.938V100.312Z"
fill="#87C214" id="path28" />
<path
d="M131.931 116.305V96.6023C131.931 95.003 130.628 93.684 129.029 93.684H127.66C126.061 93.684 124.742 95.003 124.742 96.6023V116.305H131.931V116.305Z"
fill="#87C214" id="path30" />
<path
d="M124.742 125.801V129.511C124.742 131.11 126.061 132.429 127.66 132.429H129.029C130.628 132.429 131.947 131.11 131.947 129.511V125.801H124.742Z"
fill="#87C214" id="path32" />
<path
d="M107.595 117.459H103.886C102.286 117.459 100.967 118.761 100.967 120.377V121.746C100.967 123.345 102.27 124.664 103.886 124.664H107.595V117.459Z"
fill="#95D220" id="path34" />
<path
d="M136.795 117.459H117.092V124.664H136.795C138.394 124.664 139.713 123.345 139.713 121.746V120.377C139.713 118.761 138.394 117.459 136.795 117.459Z"
fill="#95D220" id="path36" />
<path
d="M123.588 101.466H103.886C102.286 101.466 100.967 102.769 100.967 104.385V105.753C100.967 107.352 102.27 108.671 103.886 108.671H123.588V101.466Z"
fill="#95D220" id="path38" />
<path
d="M136.795 101.466H133.085V108.671H136.795C138.394 108.671 139.713 107.369 139.713 105.753V104.384C139.713 102.769 138.394 101.466 136.795 101.466Z"
fill="#95D220" id="path40" />
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -26,8 +26,8 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 30 targetSdkVersion 30
versionCode 10403 versionCode 10305
versionName "1.4.3" versionName "1.3.5"
applicationId "org.briarproject.briar.android" applicationId "org.briarproject.briar.android"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@@ -110,7 +110,7 @@ dependencies {
implementation 'info.guardianproject.panic:panic:1.0' implementation 'info.guardianproject.panic:panic:1.0'
implementation 'info.guardianproject.trustedintents:trustedintents:0.2' implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
implementation 'de.hdodenhof:circleimageview:3.1.0' implementation 'de.hdodenhof:circleimageview:3.0.1'
implementation 'com.google.zxing:core:3.3.3' // newer version need minSdk 24 implementation 'com.google.zxing:core:3.3.3' // newer version need minSdk 24
implementation 'uk.co.samuelwall:material-tap-target-prompt:3.3.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.vanniktech:emoji-google:0.6.0' // newer versions need minSdk 21

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.android;
import org.briarproject.bramble.BrambleAndroidModule; import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.bramble.plugin.file.RemovableDriveModule;
import org.briarproject.bramble.system.ClockModule; import org.briarproject.bramble.system.ClockModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.account.SignInTestCreateAccount; import org.briarproject.briar.android.account.SignInTestCreateAccount;
@@ -22,7 +21,6 @@ import dagger.Component;
AttachmentModule.class, AttachmentModule.class,
ClockModule.class, ClockModule.class,
MediaModule.class, MediaModule.class,
RemovableDriveModule.class,
BriarCoreModule.class, BriarCoreModule.class,
BrambleAndroidModule.class, BrambleAndroidModule.class,
BriarAccountModule.class, BriarAccountModule.class,

View File

@@ -3,7 +3,6 @@ package org.briarproject.briar.android;
import org.briarproject.bramble.BrambleAndroidModule; import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.account.BriarAccountModule; import org.briarproject.bramble.account.BriarAccountModule;
import org.briarproject.bramble.plugin.file.RemovableDriveModule;
import org.briarproject.bramble.system.ClockModule; import org.briarproject.bramble.system.ClockModule;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.attachment.AttachmentModule; import org.briarproject.briar.android.attachment.AttachmentModule;
@@ -21,7 +20,6 @@ import dagger.Component;
AttachmentModule.class, AttachmentModule.class,
ClockModule.class, ClockModule.class,
MediaModule.class, MediaModule.class,
RemovableDriveModule.class,
BriarCoreModule.class, BriarCoreModule.class,
BrambleAndroidModule.class, BrambleAndroidModule.class,
BriarAccountModule.class, BriarAccountModule.class,

View File

@@ -344,13 +344,7 @@
<activity <activity
android:name="org.briarproject.briar.android.StartupFailureActivity" android:name="org.briarproject.briar.android.StartupFailureActivity"
android:excludeFromRecents="true" android:label="@string/startup_failed_activity_title" />
android:exported="false"
android:finishOnTaskLaunch="true"
android:label="@string/startup_failed_activity_title"
android:launchMode="singleInstance"
android:process=":briar_startup_failure"
android:windowSoftInputMode="adjustResize|stateHidden" />
<activity <activity
android:name="org.briarproject.briar.android.settings.SettingsActivity" android:name="org.briarproject.briar.android.settings.SettingsActivity"
@@ -462,17 +456,6 @@
android:label="@string/hotspot_title" android:label="@string/hotspot_title"
android:theme="@style/BriarTheme" /> android:theme="@style/BriarTheme" />
<activity
android:name=".android.contact.connect.ConnectViaBluetoothActivity"
android:exported="false"
android:label="@string/connect_via_bluetooth_title"
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity"
android:theme="@style/BriarTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
</activity>
</application> </application>
<queries> <queries>

View File

@@ -92,9 +92,9 @@
<li id="troubleshooting_1">If you can't download the app, try it with a different web <li id="troubleshooting_1">If you can't download the app, try it with a different web
browser app. browser app.
</li> </li>
<li id="troubleshooting_2">To install the downloaded app, <li id="troubleshooting_2">Ensure that your browser is allowed to download apps directly by
you might need to allow your browser to install unknown apps. giving it the permission or enabling the installation of apps from "Unknown Sources" in
We recommend to undo that after successful installation. system settings.
</li> </li>
</ol> </ol>
</div> </div>

View File

@@ -35,7 +35,6 @@ import org.briarproject.briar.BriarCoreEagerSingletons;
import org.briarproject.briar.BriarCoreModule; import org.briarproject.briar.BriarCoreModule;
import org.briarproject.briar.android.attachment.AttachmentModule; import org.briarproject.briar.android.attachment.AttachmentModule;
import org.briarproject.briar.android.attachment.media.MediaModule; import org.briarproject.briar.android.attachment.media.MediaModule;
import org.briarproject.briar.android.contact.connect.BluetoothIntroFragment;
import org.briarproject.briar.android.conversation.glide.BriarModelLoader; import org.briarproject.briar.android.conversation.glide.BriarModelLoader;
import org.briarproject.briar.android.hotspot.AbstractTabsFragment; import org.briarproject.briar.android.hotspot.AbstractTabsFragment;
import org.briarproject.briar.android.hotspot.FallbackFragment; import org.briarproject.briar.android.hotspot.FallbackFragment;
@@ -237,6 +236,4 @@ public interface AndroidComponent
void inject(SendFragment sendFragment); void inject(SendFragment sendFragment);
void inject(ReceiveFragment receiveFragment); void inject(ReceiveFragment receiveFragment);
void inject(BluetoothIntroFragment bluetoothIntroFragment);
} }

View File

@@ -18,9 +18,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BluetoothConstants; import org.briarproject.bramble.api.plugin.BluetoothConstants;
import org.briarproject.bramble.api.plugin.LanTcpConstants; import org.briarproject.bramble.api.plugin.LanTcpConstants;
import org.briarproject.bramble.api.plugin.PluginConfig; import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TorControlPort;
import org.briarproject.bramble.api.plugin.TorDirectory; import org.briarproject.bramble.api.plugin.TorDirectory;
import org.briarproject.bramble.api.plugin.TorSocksPort;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
@@ -37,13 +35,11 @@ import org.briarproject.briar.android.account.SetupModule;
import org.briarproject.briar.android.blog.BlogModule; import org.briarproject.briar.android.blog.BlogModule;
import org.briarproject.briar.android.contact.ContactListModule; import org.briarproject.briar.android.contact.ContactListModule;
import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactModule; import org.briarproject.briar.android.contact.add.nearby.AddNearbyContactModule;
import org.briarproject.briar.android.contact.connect.ConnectViaBluetoothModule;
import org.briarproject.briar.android.forum.ForumModule; import org.briarproject.briar.android.forum.ForumModule;
import org.briarproject.briar.android.hotspot.HotspotModule; import org.briarproject.briar.android.hotspot.HotspotModule;
import org.briarproject.briar.android.introduction.IntroductionModule; import org.briarproject.briar.android.introduction.IntroductionModule;
import org.briarproject.briar.android.logging.LoggingModule; import org.briarproject.briar.android.logging.LoggingModule;
import org.briarproject.briar.android.login.LoginModule; import org.briarproject.briar.android.login.LoginModule;
import org.briarproject.briar.android.mailbox.MailboxModule;
import org.briarproject.briar.android.navdrawer.NavDrawerModule; import org.briarproject.briar.android.navdrawer.NavDrawerModule;
import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule; import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
import org.briarproject.briar.android.privategroup.list.GroupListModule; import org.briarproject.briar.android.privategroup.list.GroupListModule;
@@ -56,7 +52,6 @@ import org.briarproject.briar.android.viewmodel.ViewModelModule;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog; import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.LockManager; import org.briarproject.briar.api.android.LockManager;
import org.briarproject.briar.api.android.NetworkUsageMetrics;
import org.briarproject.briar.api.android.ScreenFilterMonitor; import org.briarproject.briar.api.android.ScreenFilterMonitor;
import org.briarproject.briar.api.test.TestAvatarCreator; import org.briarproject.briar.api.test.TestAvatarCreator;
@@ -78,8 +73,6 @@ import static java.util.Arrays.asList;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_CONTROL_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.DEFAULT_SOCKS_PORT;
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS; import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX; import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
@@ -96,7 +89,6 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
DevReportModule.class, DevReportModule.class,
ContactListModule.class, ContactListModule.class,
IntroductionModule.class, IntroductionModule.class,
ConnectViaBluetoothModule.class,
// below need to be within same scope as ViewModelProvider.Factory // below need to be within same scope as ViewModelProvider.Factory
BlogModule.class, BlogModule.class,
ForumModule.class, ForumModule.class,
@@ -105,7 +97,6 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
SharingModule.class, SharingModule.class,
HotspotModule.class, HotspotModule.class,
TransferDataModule.class, TransferDataModule.class,
MailboxModule.class,
}) })
public class AppModule { public class AppModule {
@@ -115,7 +106,7 @@ public class AppModule {
@Inject @Inject
ScreenFilterMonitor screenFilterMonitor; ScreenFilterMonitor screenFilterMonitor;
@Inject @Inject
NetworkUsageMetrics networkUsageMetrics; NetworkUsageLogger networkUsageLogger;
@Inject @Inject
DozeWatchdog dozeWatchdog; DozeWatchdog dozeWatchdog;
@Inject @Inject
@@ -162,34 +153,11 @@ public class AppModule {
return app.getDir("tor", MODE_PRIVATE); return app.getDir("tor", MODE_PRIVATE);
} }
@Provides
@Singleton
@TorSocksPort
int provideTorSocksPort() {
if (!IS_DEBUG_BUILD) {
return DEFAULT_SOCKS_PORT;
} else {
return DEFAULT_SOCKS_PORT + 2;
}
}
@Provides
@Singleton
@TorControlPort
int provideTorControlPort() {
if (!IS_DEBUG_BUILD) {
return DEFAULT_CONTROL_PORT;
} else {
return DEFAULT_CONTROL_PORT + 2;
}
}
@Provides @Provides
@Singleton @Singleton
PluginConfig providePluginConfig(AndroidBluetoothPluginFactory bluetooth, PluginConfig providePluginConfig(AndroidBluetoothPluginFactory bluetooth,
AndroidTorPluginFactory tor, AndroidLanTcpPluginFactory lan, AndroidTorPluginFactory tor, AndroidLanTcpPluginFactory lan,
AndroidRemovableDrivePluginFactory drive, AndroidRemovableDrivePluginFactory drive) {
FeatureFlags featureFlags) {
@NotNullByDefault @NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() { PluginConfig pluginConfig = new PluginConfig() {
@@ -200,8 +168,7 @@ public class AppModule {
@Override @Override
public Collection<SimplexPluginFactory> getSimplexFactories() { public Collection<SimplexPluginFactory> getSimplexFactories() {
if (SDK_INT >= 19) return singletonList(drive); return SDK_INT >= 19 ? singletonList(drive) : emptyList();
else return emptyList();
} }
@Override @Override
@@ -288,12 +255,11 @@ public class AppModule {
} }
@Provides @Provides
@Singleton NetworkUsageLogger provideNetworkUsageLogger(
NetworkUsageMetrics provideNetworkUsageMetrics(
LifecycleManager lifecycleManager) { LifecycleManager lifecycleManager) {
NetworkUsageMetrics networkUsageMetrics = new NetworkUsageMetricsImpl(); NetworkUsageLogger networkUsageLogger = new NetworkUsageLogger();
lifecycleManager.registerService(networkUsageMetrics); lifecycleManager.registerService(networkUsageLogger);
return networkUsageMetrics; return networkUsageLogger;
} }
@Provides @Provides
@@ -339,6 +305,21 @@ public class AppModule {
public boolean shouldEnableDisappearingMessages() { public boolean shouldEnableDisappearingMessages() {
return true; return true;
} }
@Override
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

@@ -3,6 +3,7 @@ package org.briarproject.briar.android;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
import android.app.NotificationManager; import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service; import android.app.Service;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.ComponentName; import android.content.ComponentName;
@@ -33,7 +34,11 @@ import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.inject.Inject; import javax.inject.Inject;
import androidx.core.app.NotificationCompat;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_LOW; import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
@@ -50,6 +55,7 @@ import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResul
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY; import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_NOTIFICATION_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_OLD_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_OLD_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_NOTIFICATION_ID; import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_NOTIFICATION_ID;
@@ -60,6 +66,8 @@ public class BriarService extends Service {
public static String EXTRA_START_RESULT = public static String EXTRA_START_RESULT =
"org.briarproject.briar.START_RESULT"; "org.briarproject.briar.START_RESULT";
public static String EXTRA_NOTIFICATION_ID =
"org.briarproject.briar.FAILURE_NOTIFICATION_ID";
public static String EXTRA_STARTUP_FAILED = public static String EXTRA_STARTUP_FAILED =
"org.briarproject.briar.STARTUP_FAILED"; "org.briarproject.briar.STARTUP_FAILED";
@@ -127,11 +135,12 @@ public class BriarService extends Service {
ongoingChannel.setLockscreenVisibility(VISIBILITY_SECRET); ongoingChannel.setLockscreenVisibility(VISIBILITY_SECRET);
ongoingChannel.setShowBadge(false); ongoingChannel.setShowBadge(false);
nm.createNotificationChannel(ongoingChannel); nm.createNotificationChannel(ongoingChannel);
// Delete the unused channel previously used for startup NotificationChannel failureChannel = new NotificationChannel(
// failure notifications FAILURE_CHANNEL_ID,
// TODO: Remove this ID after a reasonable upgrade period getString(R.string.startup_failed_notification_title),
// (added 2021-07-12) IMPORTANCE_DEFAULT);
nm.deleteNotificationChannel(FAILURE_CHANNEL_ID); failureChannel.setLockscreenVisibility(VISIBILITY_SECRET);
nm.createNotificationChannel(failureChannel);
} }
Notification foregroundNotification = Notification foregroundNotification =
notificationManager.getForegroundNotification(); notificationManager.getForegroundNotification();
@@ -147,7 +156,7 @@ public class BriarService extends Service {
} else { } else {
if (LOG.isLoggable(WARNING)) if (LOG.isLoggable(WARNING))
LOG.warning("Startup failed: " + result); LOG.warning("Startup failed: " + result);
showStartupFailure(result); showStartupFailureNotification(result);
stopSelf(); stopSelf();
} }
}, "LifecycleStartup"); }, "LifecycleStartup");
@@ -173,13 +182,29 @@ public class BriarService extends Service {
Localizer.getInstance().setLocale(this); Localizer.getInstance().setLocale(this);
} }
private void showStartupFailure(StartResult result) { private void showStartupFailureNotification(StartResult result) {
androidExecutor.runOnUiThread(() -> { androidExecutor.runOnUiThread(() -> {
// Bring the entry activity to the front to clear the back stack NotificationCompat.Builder b = new NotificationCompat.Builder(
Intent i = new Intent(BriarService.this, ENTRY_ACTIVITY); BriarService.this, FAILURE_CHANNEL_ID);
b.setSmallIcon(android.R.drawable.stat_notify_error);
b.setContentTitle(getText(
R.string.startup_failed_notification_title));
b.setContentText(getText(
R.string.startup_failed_notification_text));
Intent i = new Intent(BriarService.this,
StartupFailureActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
i.putExtra(EXTRA_START_RESULT, result);
i.putExtra(EXTRA_NOTIFICATION_ID, FAILURE_NOTIFICATION_ID);
b.setContentIntent(PendingIntent.getActivity(BriarService.this,
0, i, FLAG_UPDATE_CURRENT));
NotificationManager nm = (NotificationManager)
requireNonNull(getSystemService(NOTIFICATION_SERVICE));
nm.notify(FAILURE_NOTIFICATION_ID, b.build());
// Bring the dashboard to the front to clear the back stack
i = new Intent(BriarService.this, ENTRY_ACTIVITY);
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP); i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP);
i.putExtra(EXTRA_STARTUP_FAILED, true); i.putExtra(EXTRA_STARTUP_FAILED, true);
i.putExtra(EXTRA_START_RESULT, result);
startActivity(i); startActivity(i);
}); });
} }

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