Compare commits

...

561 Commits

Author SHA1 Message Date
Sebastian Kürten e8e07414e7 Add feature flag for introductions 2022-01-06 15:37:18 +01:00
Sebastian Kürten 707802c459 Add feature flags for private groups, forums and blogs 2022-01-06 15:35:37 +01:00
akwizgran 65be2d2b26 Merge branch 'transactional-attachment-reader' into 'master'
Transactional version of AttachmentReader#getAttachment()

See merge request briar/briar!1570
2021-12-23 17:05:32 +00:00
Sebastian Kürten d2a39da3e0 Transactional version of AttachmentReader#getAttachment() 2021-12-20 13:55:08 +01:00
akwizgran d13e4c976e Merge branch 'fix-string-substitutions' into 'master'
Fix multiple substitutions specified in non-positional format

See merge request briar/briar!1568
2021-12-17 11:23:03 +00:00
akwizgran 20b52804bf Merge branch 'add-pending-contact-transactional' into 'master'
Transactional versions of some more API calls

See merge request briar/briar!1561
2021-12-16 16:38:15 +00:00
ialokim 5b27eb354c transactional versions of addPendingContact, getPendingContacts, getConversationId and respondToIntroduction 2021-12-16 17:21:57 +01:00
Torsten Grote c340071469 Merge branch 'jmock-java-11' into 'master'
Replace ClassImposteriser with ByteBuddyClassImposteriser

See merge request briar/briar!1569
2021-12-15 16:34:04 +00:00
akwizgran 506e274dff Merge branch '2242-migrate-okhttp' into 'master'
Migrate OkHttp to bramble-core

Closes #2242

See merge request briar/briar!1562
2021-12-15 16:04:33 +00:00
Torsten Grote 423356fdda Add missing bouncycastle dependency to witness 2021-12-15 10:48:55 -03:00
Torsten Grote 043a173828 Migrate OkHttp to bramble-core 2021-12-15 10:46:48 -03:00
akwizgran f0501bbfab Merge branch '1483-peer-session-crash' into 'master'
Do not create PeerSession for groups we created

Closes #1483

See merge request briar/briar!1344
2021-12-15 12:37:46 +00:00
akwizgran 5cafde7b14 Merge branch 'test-deps' into 'master'
Upgrade briar-android unit test dependencies

See merge request briar/briar!1567
2021-12-15 12:34:54 +00:00
akwizgran 5117dbad7e Merge branch 'bouncycastle-java8' into 'master'
Switch to bouncycastle dependency for Java 1.8 to prevent Java 15 class warnings of multi-jar

See merge request briar/briar!1566
2021-12-15 10:39:38 +00:00
Torsten Grote 3a22388495 Fix multiple substitutions specified in non-positional format
The build warnings might persist until translations have been updated
2021-12-14 16:51:52 -03:00
Torsten Grote 1d4de46dfd Upgrade briar-android unit test dependencies 2021-12-14 16:22:11 -03:00
Torsten Grote d805069dfe Switch to bouncycastle dependency for Java 1.8 to prevent Java 15 class warnings of multi-jar 2021-12-14 15:42:10 -03:00
akwizgran 74cb2a6ce5 Merge branch 'readme-reproducible' into 'master'
Add a section about reproducible builds to the readme

See merge request briar/briar!1565
2021-12-14 13:23:46 +00:00
Torsten Grote 2880a4adac Add a section about reproducible builds to the readme 2021-12-14 10:00:20 -03:00
akwizgran e032e0ccd5 Bump version numbers for 1.4.3 release. 2021-12-13 16:58:13 +00:00
Torsten Grote 38a07e1d54 Merge branch 'fix-headless-jar-build-on-java-11' into 'master'
Fix headless jar build on Java 11, add to CI pipeline

See merge request briar/briar!1563
2021-12-13 16:22:43 +00:00
akwizgran 07b35db4d4 Fix headless jar build on Java 11, add to CI pipeline. 2021-12-13 15:38:17 +00:00
akwizgran 3b03db9f43 Bump version numbers for 1.4.2 release. 2021-12-13 15:17:34 +00:00
akwizgran de3a74eedf Update translations. 2021-12-13 15:16:17 +00:00
akwizgran 5a39f9730f Merge branch 'non-default-bridges' into 'master'
Use non-default obfs4 bridges in Russia

See merge request briar/briar!1556
2021-12-13 13:34:19 +00:00
akwizgran bdf02bbc6c Increase test timeout because meek bridge is super slow. 2021-12-13 12:53:42 +00:00
akwizgran d5b2ebdb23 Include meek bridge in test and mark it as essential. 2021-12-13 11:56:52 +00:00
Torsten Grote 98bb8d4af1 Merge branch 'fix-database-locking' into 'master'
Use ReentrantLock as a lock (not a monitor) when marking DB as open.

See merge request briar/briar!1549
2021-12-13 11:48:28 +00:00
akwizgran 75cc19e578 Remove failing non-default bridge. 2021-12-13 11:47:03 +00:00
akwizgran aad87e6e98 Update default bridges from upstream. 2021-12-13 11:46:43 +00:00
akwizgran dad895c30d Merge branch '2225-error-handling-for-mailbox-downloads' into 'master'
Add methods to get StreamContext from tag, and mark it as recognised

Closes #2225

See merge request briar/briar!1560
2021-12-10 14:45:34 +00:00
Daniel Lublin f8b3d79813 Add methods to get StreamContext from tag, and mark it as recognised
Separate methods are needed to be able to restart reading from a stream
in the case of errors. Tag should be marked as recognised only after
successfully reading the stream.

Closes #2225
2021-12-10 15:23:30 +01:00
akwizgran 0a98566298 Merge branch '2190-mailbox-reset-retransmission-times' into 'master'
Resolve "Method for resetting retransmission times"

Closes #2190

See merge request briar/briar!1559
2021-12-09 12:11:54 +00:00
Daniel Lublin 93a03d7e15 Reset using a single db query 2021-12-09 12:55:01 +01:00
Daniel Lublin 3eb3dbde09 Add database method to reset retransmission times
Will be used to ensure messages are not stranded on a Mailbox, when such
is added, removed, or otherwise changed.

Closes #2190.
2021-12-09 11:10:50 +01:00
akwizgran fd56176450 Merge branch 'desktop-98-transactional' into 'master'
Add transactional versions of some API calls for Briar Desktop

See merge request briar/briar!1557
2021-12-08 11:08:47 +00:00
ialokim d29812f055 add transactional versions of some API calls 2021-12-07 20:39:55 +01:00
akwizgran 403601b9f2 Merge branch '2088-fix-error-with-null-group' into 'master'
Offline hotspot: don't crash if group is null

Closes #2088

See merge request briar/briar!1552
2021-12-07 15:20:35 +00:00
akwizgran 992215b78a Merge branch '2230-tracking-uploads' into 'master'
Add MailboxSettingsManager methods for tracking pending uploads

Closes #2230

See merge request briar/briar!1558
2021-12-07 15:12:24 +00:00
Torsten Grote 658ca8de21 Add MailboxSettingsManager methods for tracking pending uploads 2021-12-07 10:07:54 -03:00
akwizgran e0e2c0cc89 Add unit test. 2021-12-07 10:33:16 +00:00
akwizgran 114d80ad43 Use non-default obfs4 bridges in Russia. 2021-12-06 18:11:16 +00:00
Torsten Grote 8d5803098b Merge branch 'network-usage-metrics' into 'master'
Include network usage metrics in crash reports and feedback

See merge request briar/briar!1555
2021-11-30 18:08:07 +00:00
akwizgran a9ed9da822 Include network usage metrics in crash reports and feedback. 2021-11-30 14:12:45 +00:00
akwizgran 1d04bbcb4f Merge branch '1607-share-http-client-instance' into 'master'
Use a single OkHttpClient instance for all RSS fetches

Closes #1607

See merge request briar/briar!1536
2021-11-23 11:51:23 +00:00
akwizgran 43b0d1d543 Merge branch 'gradle-7-3' into 'master'
Upgrade gradle to v7.3

See merge request briar/briar!1553
2021-11-23 11:43:47 +00:00
Sebastian Kürten 1bfd9e4eb0 Upgrade gradle to v7.3 2021-11-23 10:13:11 +01:00
Sebastian Kürten 2295db4361 Offline hotspot: don't crash if group is null 2021-11-22 17:26:01 +01:00
akwizgran 8fca06e040 Merge branch 'gradle-7' into 'master'
Upgrade gradle and android plugin to v7

See merge request briar/briar!1551
2021-11-22 15:36:30 +00:00
akwizgran 3f7c9af3a9 Create the HTTP client lazily and allow it to be garbage collected. 2021-11-22 12:01:51 +00:00
akwizgran 93178d2f28 Merge branch '2171-store-time-of-last-connection-to-own-mailbox' into 'master'
Store time of last attempted and successful connections to own mailbox

Closes #2171

See merge request briar/briar!1547
2021-11-22 11:09:37 +00:00
akwizgran 2755d3f470 Merge branch '2169-store-own-mailbox-properties' into 'master'
Add mailbox settings manager

Closes #2169

See merge request briar/briar!1546
2021-11-22 11:09:03 +00:00
Torsten Grote 7efc3ca78f Fix AuthorView using the wrong constant 2021-11-19 15:11:23 -03:00
Torsten Grote d6767a62b9 Upgrade gradle and android plugin to v7 2021-11-19 14:55:16 -03:00
Torsten Grote 2821460648 Merge branch 'use-synchroniser-for-mock-tests' into 'master'
Use Synchroniser for all mock tests

See merge request briar/briar!1550
2021-11-18 13:37:16 +00:00
akwizgran 7aa1073bf5 Replace ClassImposteriser with ByteBuddyClassImposteriser.
This may avoid problems with ClassImposteriser when using Java 11. See
https://github.com/jmock-developers/jmock-library/releases/tag/2.10.0
2021-11-18 13:28:08 +00:00
akwizgran 3ff7349b40 Set threading policy for the one test that does things differently. 2021-11-18 13:27:38 +00:00
akwizgran 22593722a7 Convert remaining tests to use BrambleMockTestCase. 2021-11-18 12:56:39 +00:00
akwizgran e91ad962cb Use Synchroniser for all mock tests.
Android Studio tries to collect the output of failed tests on a different thread, which results in an exception when using Mockery's default threading policy, causing the tests to appear as incomplete rather than failed.
2021-11-18 11:32:33 +00:00
akwizgran 53d9a9b43b Merge branch '2153-tor-0.3.5.17' into 'master'
Upgrade Tor to 0.3.5.17 and remove v2 onion code

Closes #1280 and #2153

See merge request briar/briar!1548
2021-11-17 15:40:44 +00:00
akwizgran 6c702bad0a Use ReentrantLock as a lock (not a monitor) when marking DB as open. 2021-11-17 15:03:58 +00:00
Torsten Grote 0dc2aba22f Remove old v2 onion code from TorPlugin 2021-11-17 10:54:49 -03:00
Torsten Grote 5a8b822e08 Upgrade Tor to 0.3.5.17 2021-11-17 09:46:49 -03:00
akwizgran 8ac6b0155b Store time of last attempted and successful connections to mailbox. 2021-11-17 10:49:00 +00:00
akwizgran 372810f48e Add mailbox settings manager. 2021-11-16 12:53:17 +00:00
akwizgran 1b4ab4f945 Merge branch '2167-decode-qr-code-for-pairing-with-mailbox' into 'master'
Create initial MailboxPairViewModel that decodes QR code

Closes #2167

See merge request briar/briar!1544
2021-11-16 12:15:26 +00:00
Daniel Lublin 407ddad0a8 Make it package private 2021-11-15 12:59:57 +01:00
Daniel Lublin 77a986318e Add MailboxPairViewModel that decodes Mailbox QR code 2021-11-15 12:59:56 +01:00
Daniel Lublin 1809be4656 Factor out onion address encoder to CryptoComponent 2021-11-15 12:59:56 +01:00
Daniel Lublin 6d1a0a5792 Refactor qrcode and its camera classes to separate package 2021-11-15 12:59:56 +01:00
akwizgran 85dc27ed77 Merge branch 'message-tracked-event' into 'master'
Implement and use new message tracked event

See merge request briar/briar!1541
2021-11-12 11:35:59 +00:00
ialokim 3f8df34f5c use new event to update contacts view model 2021-11-11 20:56:13 +01:00
ialokim eb08781460 broadcast event when a conversation message is tracked 2021-11-11 20:56:02 +01:00
akwizgran 8a4fe7ca49 Fix missing import. 2021-11-04 11:08:15 +00:00
akwizgran e688448537 Merge branch 'dynamic-tor-ports' into 'master'
Make Tor ports configurable at runtime

See merge request briar/briar!1537
2021-11-04 11:00:09 +00:00
Sebastian Kürten e0f36ade92 Address review feedback 2021-11-03 16:32:17 +01:00
akwizgran 6517f3f2d0 Bump version numbers for 1.4.1 release. 2021-11-03 15:08:52 +00:00
akwizgran 70d5150faf Fix placeholder in Icelandic translation. 2021-11-03 15:08:05 +00:00
Sebastian Kürten a1f9e80e12 Inject Tor ports via annotated int parameters 2021-11-03 15:43:01 +01:00
akwizgran 770c87c723 Bump version numbers for 1.4.0 release. 2021-11-03 14:38:32 +00:00
akwizgran 2b5446759f Update translations. 2021-11-03 14:37:34 +00:00
Torsten Grote edccb9ae14 Merge branch '1081-fix-typo' into 'master'
Fix a typo: without Internet connection -> without an Internet connection

See merge request briar/briar!1540
2021-11-03 14:33:43 +00:00
Torsten Grote 1337fc46b3 Merge branch 'feature-flags-for-hotspot-and-removable-drives' into 'master'
Enable removable drives and sharing app offline in release builds

See merge request briar/briar!1542
2021-11-02 12:09:36 +00:00
akwizgran ed26dc0b2b Enable removable drives and sharing app offline in release builds. 2021-11-02 11:18:54 +00:00
akwizgran bf9fe6a146 Fix a typo: without Internet connection -> without an Internet connection. 2021-10-29 13:01:26 +01:00
akwizgran 448ea114f3 Merge branch 'suggest-restarting-hotspot-phone' into 'master'
Add restarting hotspot phone to troubleshooting

See merge request briar/briar!1534
2021-10-29 11:53:52 +00:00
akwizgran abc523fae3 Merge branch '2011-hotspot-graphic' into 'master'
Add feature graphic for app sharing feature

Closes #2011

See merge request briar/briar!1538
2021-10-29 11:45:21 +00:00
Daniel Lublin 6de5f424b8 Add restarting hotspot phone to troubleshooting 2021-10-21 10:03:48 +02:00
Torsten Grote 703559102a Add feature graphic for app sharing feature 2021-10-19 14:02:57 -03:00
Torsten Grote 4acc5f4d8c Merge branch 'gradle-run-configurations' into 'master'
Convert AS run configurations for tests to Gradle

See merge request briar/briar!1535
2021-10-18 13:31:59 +00:00
Sebastian Kürten bf091ef854 Use different Tor ports for regular and debug builds 2021-10-16 14:45:14 +02:00
Sebastian Kürten d4656df384 Make Tor ports configurable at runtime
Instead of using hard-coded values 59050 and 59051 for the Tor socks and
control ports, provide them via a TorPorts interface. This makes it possible
to pass the ports to a TorPortsImpl in modules. Hence it is possible to
configure the Tor port for different types of builds or via command line
options in case of briar headless or other clients using the core code.
2021-10-16 14:41:29 +02:00
akwizgran e79abeff2e Use a single OkHttpClient instance for all RSS fetches. 2021-09-30 14:09:15 +01:00
akwizgran 4a4d8f4ccf Convert AS run configurations for tests to Gradle. 2021-09-24 14:02:41 +01:00
akwizgran 807677532c Bump version numbers for 1.3.8 release. 2021-08-31 15:38:11 +01:00
Torsten Grote 7e9d64b6ad Merge branch 'fix-headless-build' into 'master'
Remove jar signatures to avoid SecurityException when repacking headless jar

See merge request briar/briar!1532
2021-08-31 14:37:13 +00:00
akwizgran f963c4cfdd Remove jar signatures to avoid SecurityException when repacking headless jar. 2021-08-31 15:02:43 +01:00
akwizgran 7388da410f Bump version numbers for 1.3.7 release. 2021-08-31 14:16:43 +01:00
akwizgran 3635c35923 Update translations. 2021-08-31 14:15:47 +01:00
akwizgran 7c1399c326 Merge branch 'simpler-hotspot-name-pass' into 'master'
Limit hotspot name and password to only lowercase letters (on 29+)

See merge request briar/briar!1520
2021-08-31 13:10:02 +00:00
akwizgran c002cc2e73 Merge branch 'enable-connect-via-bluetooth' into 'master'
Enable connect via Bluetooth feature in release builds

See merge request briar/briar!1531
2021-08-31 13:07:59 +00:00
Torsten Grote f3273260bb Fix Kotlin coding style 2021-08-31 14:32:36 +02:00
Torsten Grote abf99f0219 Merge branch '2148-shrink-hotspot-qr-codes' into 'master'
Shrink QR code to avoid scrolling

Closes #2148

See merge request briar/briar!1528
2021-08-31 12:21:16 +00:00
Torsten Grote 7405ed7196 Merge branch '2076-revise-transfer-data-explanation' into 'master'
Revise removable drive ui after usability testing

Closes #2076

See merge request briar/briar!1530
2021-08-31 12:11:11 +00:00
Daniel Lublin b53203581c Enable scrollbar for hotspot scrollviews 2021-08-31 12:10:40 +02:00
Daniel Lublin d522942bdd Enable scrollbar for scrollview 2021-08-31 12:02:39 +02:00
Daniel Lublin 802015d995 Shrink QR code to avoid scrolling 2021-08-31 09:09:10 +02:00
Daniel Lublin c36352f2b8 Rename feature for user 2021-08-31 09:08:42 +02:00
Daniel Lublin 21a2f91521 Revise transfer data wording, adding explanation in fullscreen dialog 2021-08-31 09:08:40 +02:00
akwizgran d8267ce559 Update code style settings. 2021-08-30 15:22:34 +01:00
akwizgran 8f887c609f Enable connect via Bluetooth feature in release builds. 2021-08-30 15:17:53 +01:00
akwizgran b077e5f94f Update translations. 2021-08-30 15:03:57 +01:00
akwizgran 2b61b01b4e Merge branch '2151-bluetooth-connect-ui' into 'master'
Add simple UI for Connect via Bluetooth feature

Closes #2151 and #1821

See merge request briar/briar!1524
2021-08-30 13:58:26 +00:00
Torsten Grote 822a58c8a6 Replace final Bluetooth connection fragments with toasts 2021-08-30 15:34:37 +02:00
Daniel Lublin 09b065f46e Limit hotspot name and password to only lowercase letters (on 29+) 2021-08-23 10:44:42 +02:00
Torsten Grote be9255029b Merge branch '2149-hotspot-detection' into 'master'
Use interface name to decide whether we're providing a wifi hotspot

Closes #2149

See merge request briar/briar!1521
2021-08-20 14:55:06 +00:00
Torsten Grote f596811997 Merge branch '2144-graphics-size' into 'master'
Use fixed sizes and consistent layout for "hero icons"

Closes #2144

See merge request briar/briar!1525
2021-08-20 07:43:29 +00:00
Torsten Grote 1be8ac6e14 Add simple UI for Connect via Bluetooth feature 2021-08-20 09:11:35 +02:00
akwizgran 571ec2257e Remove full stop from string that's now used as a title. 2021-08-19 13:03:52 +01:00
akwizgran 7fb2faba45 Automatically scroll HotspotIntroFragment. 2021-08-19 13:00:54 +01:00
akwizgran a390bf1c4f Use consistent layout style for all screens with "hero icons". 2021-08-19 12:27:03 +01:00
akwizgran 9d031fa796 Use fixed dp sizes for graphics. 2021-08-17 13:04:45 +01:00
akwizgran d678043f8e Merge branch '2152-rss-icon' into 'master'
Resolve "RSS icon doesn't appear on older devices"

Closes #2152

See merge request briar/briar!1523
2021-08-17 09:36:56 +00:00
Torsten Grote b11147265d Merge branch '1724-replace-spongy-castle-with-bouncy-castle' into 'master'
Replace Spongy Castle with Bouncy Castle

Closes #1724

See merge request briar/briar!1522
2021-08-17 07:46:04 +00:00
Torsten Grote 2fe052d77e Fix blog post padding on Android 4 2021-08-17 09:43:04 +02:00
Torsten Grote 8e91322869 Upgrade CircleImageView dependency 2021-08-17 09:25:51 +02:00
Torsten Grote 1de5779e2c Fix RSS icon not showing on API < 19 2021-08-17 09:25:39 +02:00
akwizgran 99b2c8af69 Upgrade Bouncy Castle to 1.69, drop Montgomery ladder tests. 2021-08-16 15:52:33 +01:00
akwizgran b1cc4fe006 Replace Spongy Castle with Bouncy Castle. 2021-08-16 15:38:36 +01:00
akwizgran d65afc519a Factor out shared code. 2021-08-16 12:00:42 +01:00
akwizgran 32cbdff532 Use interface name to decide whether we're providing a wifi hotspot. 2021-08-16 11:55:41 +01:00
akwizgran 48292d2e47 Merge branch '2144-transfer-data-graphics' into 'master'
Fix images when sending or receiving data

Closes #2144

See merge request briar/briar!1517
2021-08-11 10:27:24 +00:00
akwizgran 89bd9ee653 Merge branch 'animal-sniffer-11' into 'master'
Fix animal sniffer when run with Java 11

See merge request briar/briar!1516
2021-08-11 10:26:29 +00:00
akwizgran 61aa3a839d Merge branch '2026-ux-offline-sharing' into 'master'
Adjust after UX testing

Closes #2026

See merge request briar/briar!1518
2021-08-11 10:24:29 +00:00
Daniel Lublin e38e9b943d Squeeze items to free more vertical space for qr code 2021-08-10 17:12:26 +02:00
Daniel Lublin 4eb5c2ac10 Revise share-offline screen wording; always show connected peers counter 2021-08-10 17:02:20 +02:00
Torsten Grote ebaa3271dd Merge branch 'ssid-password-white-background' into 'master'
Use white background for hotspot name and password

See merge request briar/briar!1519
2021-08-10 11:24:47 +00:00
akwizgran adb6b4fba5 Use white background for hotspot name and password. 2021-08-10 11:26:23 +01:00
Torsten Grote 917a470559 Upgrade animal sniffer plugin 2021-08-09 15:39:18 +02:00
Torsten Grote a188e41134 Fix animal sniffer when run with Java 11 2021-08-09 15:38:14 +02:00
Torsten Grote b9ba813b23 Fix images when sending or receiving data 2021-08-09 14:26:49 +02:00
akwizgran b7d46b9340 Merge branch '1081-share-app-via-wifi-hotspot' into 'master'
Share app via Wi-Fi hotspot

Closes #1081

See merge request briar/briar!1515
2021-08-04 12:09:08 +00:00
Sebastian Kürten 60aaa4a7c1 HotspotManager: set channel to null after closing it consistently 2021-08-04 12:35:59 +02:00
Sebastian Kürten d411b99030 Improve handling of HotspotState's field 'consumed' 2021-08-04 12:35:33 +02:00
Torsten Grote acacb59114 Address review feedback for feature branch 2021-08-03 09:33:59 +02:00
akwizgran 2e07e79e4c Merge branch 'fix-screenshot-tests' into 'master'
Fix screenshot tests

See merge request briar/briar!1514
2021-07-28 12:37:53 +00:00
akwizgran e9dbceefe8 Merge branch '2117-hotspot-password' into '1081-share-app-via-wifi-hotspot'
hotspot: remove 5 and S, as well as i and l

See merge request briar/briar!1513
2021-07-28 12:36:07 +00:00
Torsten Grote 8cdb314170 Fix screenshot tests 2021-07-27 15:09:10 +02:00
Torsten Grote 39d3f47e19 hotspot: remove 5 and S, as well as i, l and 1 2021-07-27 13:39:28 +02:00
Torsten Grote 522474ac15 Merge branch '2100-refactor-condition-managers' into '1081-share-app-via-wifi-hotspot'
Split ConditionManager into API-specific versions

See merge request briar/briar!1512
2021-07-26 13:49:20 +00:00
akwizgran ed6c4ba634 Merge branch 'master' into 'master'
Create a better formatted and more informant README.md

See merge request briar/briar!1504
2021-07-26 10:34:46 +00:00
akwizgran 49562cbd79 Merge branch 'log-uncaught-exceptions' into 'master'
Log uncaught exceptions on debug builds

See merge request briar/briar!1497
2021-07-23 10:45:27 +00:00
Sebastian Kürten 6337b86266 Rename ConditionManager classes 2021-07-21 16:29:23 +02:00
Sebastian Kürten 93eadb88f3 Apply review feedback 2021-07-21 16:13:44 +02:00
Sebastian Kürten 46e391645c Reduce visibility of a field and two methods 2021-07-21 13:30:20 +02:00
Sebastian Kürten 355c487ec9 Split ConditionManager into API-specific versions
* On API 29+ we need the location permission to start the hotspot, while
  on lower API levels, we don't. In order to handle permissions and
  other conditions in a clear manner depending the API level of the
  device the app is running on, have separate extensions of the base
  ConditionManager class.
* Take special care to handle situations gracefully where the Wifi is
  disabled and the user tries to start the hotspot. We cannot simply
  rely on Wifi being enabled as a sufficient condition that allows us to
  start the hotspot. We need to wait for WifiP2p to be available. While
  it is tricky to obtain that state (it involves registering a broadcast
  receiver for the WIFI_P2P_STATE_CHANGED_ACTION broadcast, keeping
  track of changes there and even then things are still ugly. It can
  happen that WifiP2p is available *before* Wifi is. Also it can happen
  that WifiP2p never becomes available because some other application
  has already opened a hotspot. Instead of checking that state, we now
  just try (and retry repeatedly after a delay) to start the hotspot
  (and the WifiP2p framework) hoping that is becomes availabe within a
  reasonable amount of time after Wifi has been detected to be on.
  Currently we try 5 times with a delay of 1 second.
* Improve the behavior of disabling and re-enabling the 'start hotspot'
  button, so that it becomes impossible to double-tap it, but still
  making sure that the button get re-enabled as soon as the UI is back
  in a state where the user should be able to tap the button again.
2021-07-21 13:30:14 +02:00
Torsten Grote d1c0f1b2f6 Merge branch '2109-assertion-in-rssfeedviewmodel' into 'master'
Fix assertion caused by system-initiated process death

Closes #2109

See merge request briar/briar!1510
2021-07-20 13:03:27 +00:00
akwizgran 445ef0818c Bump version numbers for 1.3.6 release. 2021-07-14 13:12:16 +01:00
akwizgran 8af743db71 Update translations. 2021-07-14 13:11:30 +01:00
akwizgran 806fce8c34 Keep the screen on while the hotspot is running. 2021-07-14 14:04:33 +02:00
Sebastian Kürten f9494d71de Improve texts on offline hotspot for a better UX 2021-07-14 14:04:30 +02:00
Sebastian Kürten df38187288 Do not increment the attempt variable twice when requesting group info 2021-07-14 14:04:12 +02:00
Sebastian Kürten b8009c35f1 Do not allow the user to tap the start sharing button twice quickly 2021-07-14 14:04:11 +02:00
Sebastian Kürten 1306761f4a Don't move to HotspotFragment on rotate when user navigated back to introduction 2021-07-14 14:04:11 +02:00
Sebastian Kürten 703ff9835d 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-07-14 14:04:11 +02:00
Sebastian Kürten 4abaeed32f Fix background color of cardview for qr code 2021-07-14 14:04:10 +02:00
Sebastian Kürten 9192ee32cf Use FragmentContainerView for displaying FallbackFragment 2021-07-14 14:04:09 +02:00
Sebastian Kürten aecd204efe Improve hotspot error fragment UI
* Use different highlighting for error message
* Improve margins in fragment_hotspot_save_apk.xml
* Address some review feedback
2021-07-14 14:04:09 +02:00
Sebastian Kürten 03cb1010e2 Pass error message to feedback activity 2021-07-14 14:04:07 +02:00
Sebastian Kürten 30063f5fbf Create FallbackFragment for alternative apk sharing method 2021-07-14 14:04:05 +02:00
Sebastian Kürten 0fb52a7f53 Log hotspot errors 2021-07-14 14:03:58 +02:00
Sebastian Kürten 094024eb4f Wire feedback button to show feedback fragment 2021-07-14 14:03:58 +02:00
Sebastian Kürten e39c99fd6c Outline specific error fragment for hotspot 2021-07-14 14:03:57 +02:00
Sebastian Kürten 6cd70e0e7f Let HotspotActivity implement BaseFragmentListener 2021-07-14 14:03:57 +02:00
Torsten Grote d646635b1f Move hotspot help ActivityResultLauncher into method 2021-07-14 14:03:57 +02:00
Torsten Grote a534ec2b50 Adapt hotspot buttons to latest design and add a nullability annotation 2021-07-14 14:03:56 +02:00
Torsten Grote a23de6172f Make HotspotHelpFragment headlines bold 2021-07-14 14:03:56 +02:00
Torsten Grote ff2dd33435 Handle returned Uri being null 2021-07-14 14:03:54 +02:00
Torsten Grote d5d0a03638 Save the APK as a hotspot fallback 2021-07-14 14:03:50 +02:00
Sebastian Kürten 344fff4a7a Add feature flag for sharing the app via offline hotspot 2021-07-14 14:03:13 +02:00
Sebastian Kürten f9749fda80 Recommend to undo settings to install apps from unknown sources 2021-07-14 13:53:21 +02:00
Torsten Grote aabba3a6c8 Add missing hotspot nullability annotations 2021-07-14 13:53:20 +02:00
Torsten Grote 673f530c14 Move savedNetworkConfig into HotspotManager and use constructor injection 2021-07-14 13:53:20 +02:00
Torsten Grote 36a1478661 Make hotspot SSID and passphrase persistent 2021-07-14 13:53:19 +02:00
Sebastian Kürten 1c056160e1 Use better filename for apk files shared via hotspot 2021-07-14 13:53:19 +02:00
Torsten Grote ab6b83d4fa Show a snackbar when a peer connected to the hotspot 2021-07-14 13:53:17 +02:00
Torsten Grote a6c33d300c Don't start hotspot while running and use proper ErrorFragment 2021-07-14 13:53:16 +02:00
Torsten Grote 28d87dd153 Port code from Offline hotspot test app 2021-07-14 13:53:12 +02:00
Torsten Grote 16b79e0482 Fix hotspot notification on old APIs 2021-07-14 13:53:03 +02:00
Torsten Grote 3eee144c6c Rename tab fragments
and remove redundant NonNull annotations
2021-07-14 13:52:58 +02:00
Torsten Grote 1b7007d4ef Show notification while hotspot is active 2021-07-14 13:52:42 +02:00
Torsten Grote 19a5c2f79f Add hotspot troubleshooting info 2021-07-14 13:39:11 +02:00
Torsten Grote 8c163d8f10 Add offline sharing entry point to Settings/Actions 2021-07-14 13:39:10 +02:00
Torsten Grote c3cd32b12c Let info screens scroll in case of insufficient space 2021-07-14 13:39:09 +02:00
Torsten Grote 7c8aa5bc21 Implement info screens for offline app sharing 2021-07-14 13:39:05 +02:00
Torsten Grote 54b239f45e Implement intro screen for offline app sharing 2021-07-14 13:38:41 +02:00
Torsten Grote 97bd977108 Merge branch '1802-sync-via-removable-storage' into 'master'
Transfer data securely via removable storage

See merge request briar/briar!1511
2021-07-14 11:23:50 +00:00
akwizgran aaba9f2417 Don't configure plugin unless feature flag is enabled. 2021-07-14 11:48:48 +01:00
akwizgran 6a909b6c5c Rename method, as it no longer involves a notification. 2021-07-13 15:55:29 +01:00
akwizgran 4ef92f1c39 Remove redundant UiUtils method. 2021-07-13 15:49:33 +01:00
akwizgran 8f392b4599 Use getLong() to avoid remote possibility of overflow. 2021-07-13 12:04:09 +01:00
akwizgran f556bc7249 Update javadoc for RemovableDriveTask. 2021-07-13 11:50:17 +01:00
akwizgran e48886c95a Update max latency of AndroidRemovableDrivePlugin to 28 days. 2021-07-13 11:44:32 +01:00
Daniel Lublin e2879cd664 Fix assertion caused by system-initiated process death 2021-07-13 11:31:51 +02:00
akwizgran c3977e9276 Add comment reminding us to remove obsolete notification channel ID. 2021-07-13 10:30:17 +02:00
akwizgran b93803060e Remove unused strings. 2021-07-13 10:30:17 +02:00
akwizgran 4498187721 Suggest upgrading if the app fails to start. 2021-07-13 10:30:16 +02:00
akwizgran 8666fe45b1 Show startup failure activity immediately, without a notification. 2021-07-13 10:30:15 +02:00
akwizgran cd12447c2e Include RemovableDriveModule in UI tests. 2021-07-13 10:30:14 +02:00
Torsten Grote 0a79cc882a Handle the don't keep activities option when using transfer data feature 2021-07-13 10:30:13 +02:00
akwizgran 7f80b5d660 Update text explaining that contact doesn't support removable drives. 2021-07-13 10:30:13 +02:00
akwizgran 92f58e9465 Increase max latency of removable drive plugin to 28 days. 2021-07-13 10:30:12 +02:00
akwizgran 387f7f1545 Check whether we have transport keys before trying to send data. 2021-07-13 10:30:12 +02:00
akwizgran 65e0845376 Don't configure the removable drive plugin on API < 19. 2021-07-13 10:30:11 +02:00
akwizgran 97bb695373 Clear keys from session when moving to AWAIT_ACTIVATE state. 2021-07-13 10:30:11 +02:00
akwizgran d8230afae3 Reject old timestamps when deriving rotation mode keys. 2021-07-13 10:30:11 +02:00
Torsten Grote 07afb955f7 Remove guidelines for percent based laout width 2021-07-13 10:30:10 +02:00
akwizgran a57d668fc9 Use guidelines to set image sizes. 2021-07-13 10:30:10 +02:00
Torsten Grote 765dbcc111 Check if the chosen contact supports removable drive transport
and show message if not
2021-07-13 10:30:09 +02:00
Torsten Grote ccb4f88b89 Combine transfer data graphics to reduce layout complexity
and make scaling work better on smaller screens
2021-07-13 10:30:09 +02:00
Torsten Grote eee9e1a488 Address review feedback for Transfer Data UI 2021-07-13 10:30:08 +02:00
Torsten Grote f832f663c9 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-13 10:30:07 +02:00
Torsten Grote 032f56ad67 Try to force file chooser to show internal/external storage by default 2021-07-13 10:30:07 +02:00
Torsten Grote 3f2ac528c1 Calculate percentages for send progress bar 2021-07-13 10:30:06 +02:00
Torsten Grote d174757ef0 Remove manual initial state and oldTask state argument
The latter is now handled via a LiveEvent
2021-07-13 10:30:06 +02:00
Torsten Grote f457a5e831 Hide Transfer Data feature behind feature flag 2021-07-13 10:30:06 +02:00
Torsten Grote ab2fe58d2f Check if there is data to send and show a message if not 2021-07-13 10:30:05 +02:00
Torsten Grote fe1c384aeb Always inform new observers about current state 2021-07-13 10:30:05 +02:00
Torsten Grote 4c327e9874 Re-organize conversations overflow menu 2021-07-13 10:30:04 +02:00
Torsten Grote 928b951c25 Transfer Data UI 2021-07-13 10:30:04 +02:00
Daniel Lublin ecba2a51d8 Start of UI for transfer data feature 2021-07-13 10:30:03 +02:00
Torsten Grote 9668f62c6a Remove FIXME in test since we won't fix it this way 2021-07-13 10:30:02 +02:00
Torsten Grote dc3ba3d8f0 Also test that messages arrive and activate keys 2021-07-13 10:30:01 +02:00
Torsten Grote 3f6f970d36 Add two more tests to TransportKeyAgreementIntegrationTest 2021-07-13 10:30:01 +02:00
Torsten Grote 768356d8e2 Ensure that private key is not stored anymore 2021-07-13 10:30:00 +02:00
Torsten Grote 65110090de Add first integration test for TransportKeyAgreementManager 2021-07-13 10:29:59 +02:00
Torsten Grote f5cab63052 Add first integration test for TransportKeyAgreementManager 2021-07-13 10:29:56 +02:00
Torsten Grote 399d8adb3b Refactor base of BriarIntegrationTest into BrambleIntegrationTest 2021-07-13 10:27:17 +02:00
Torsten Grote b40055686b Put FeatureFlags for tests into a TestFeatureFlagModule 2021-07-13 10:26:27 +02:00
akwizgran 2dcecb2a46 Add method for checking whether contact supports transport. 2021-07-13 10:26:27 +02:00
akwizgran 0cc118c849 Add transport property to indicate support for removable drives. 2021-07-13 10:26:26 +02:00
akwizgran b1148ebc83 Store ID of message that triggered abort. 2021-07-13 10:26:26 +02:00
akwizgran 802f64e309 Check whether system clock is reasonable at startup. 2021-07-13 10:26:26 +02:00
Torsten Grote 80749fec09 Add TransportKeyAgreementValidatorTest 2021-07-13 10:26:25 +02:00
akwizgran 1f1ea8f3ed Add RemovableDriveManager method. 2021-07-13 10:26:25 +02:00
akwizgran 796cbcaf4b Add DB method for checking whether there's anything to send 2021-07-13 10:26:24 +02:00
akwizgran 4cf5242aa5 Add comment explaining second client versioning message. 2021-07-13 10:26:24 +02:00
akwizgran 8921f10ffd Add integration test for eager retransmission. 2021-07-13 10:26:24 +02:00
akwizgran b60c129acf Update DB method that gets total size of messages to send. 2021-07-13 10:26:23 +02:00
akwizgran 852413b36a Use eager retransmission if the transport is lossy and cheap. 2021-07-13 10:26:23 +02:00
akwizgran a39b367477 Add tests for eager retransmission. 2021-07-13 10:26:22 +02:00
akwizgran 8be274dc4d Replace inner classes with lambdas. 2021-07-13 10:26:22 +02:00
akwizgran 9ac72296c7 Update SimplexOutgoingSession to support sending unacked messages. 2021-07-13 10:26:21 +02:00
akwizgran 1405f5954a Add database methods for sending unacked messages. 2021-07-13 10:26:21 +02:00
akwizgran f406de6b0c Timestamp isn't needed for deriving root key. 2021-07-13 10:26:20 +02:00
akwizgran 0df57c82cb Make tests more readable. 2021-07-13 10:26:20 +02:00
akwizgran 4853bcd724 Remove unused remote timestamp from session. 2021-07-13 10:26:20 +02:00
akwizgran 37e95d4ce6 Add transport key agreement client. 2021-07-13 10:26:19 +02:00
akwizgran 23acd186f7 Hold lock while calling notifyObservers(). 2021-07-13 10:26:19 +02:00
akwizgran 5e98bd0b53 Refactor removable drive tasks. 2021-07-13 10:26:18 +02:00
akwizgran d7238312b1 Add unit tests for addRotationKeys() methods. 2021-07-13 10:26:18 +02:00
akwizgran ec40da4353 Refactor KeyManager startup so managers are created earlier. 2021-07-13 10:26:18 +02:00
akwizgran 204ad8913f Add a key manager method for adding a single set of transport keys. 2021-07-13 10:26:17 +02:00
akwizgran c0f5023b63 Add a DB method for checking whether transport keys exist. 2021-07-13 10:26:17 +02:00
akwizgran b3c105bfa7 Add database method for getting transports with keys. 2021-07-13 10:26:16 +02:00
akwizgran 68acbe5c7d Add javadocs for message states. 2021-07-13 10:26:16 +02:00
akwizgran 12245d960c Allow sync clients to defer delivery of messages. 2021-07-13 10:26:16 +02:00
Daniel Lublin f82c2517fb Make pkg private 2021-07-13 10:26:15 +02:00
Daniel Lublin fa49da68a4 Move to new removabledrive package 2021-07-13 10:26:15 +02:00
Daniel Lublin cffbfdf6f2 Use US locale for now 2021-07-13 10:26:14 +02:00
Daniel Lublin cd126279ac Add initial RemovableDriveViewModel 2021-07-13 10:26:14 +02:00
akwizgran bedd6f9a6e Refactor manager and tasks to remove reliance on files. 2021-07-13 10:26:13 +02:00
akwizgran 10e0c8d876 Update progress of writer task. 2021-07-13 10:26:13 +02:00
akwizgran dc2ad48a7f Ensure that observers see the final state even if they're added late. 2021-07-13 10:26:13 +02:00
akwizgran c010dd9401 Add integration test for syncing via removable drives. 2021-07-13 10:26:12 +02:00
akwizgran 270ef76057 Implement RemovableDriveWriterTask, except for progress updates. 2021-07-13 10:26:12 +02:00
akwizgran 9d47f27293 Fix typo in class names. 2021-07-13 10:26:11 +02:00
akwizgran f0687a082a Implement RemovableDriverReaderTask. 2021-07-13 10:26:11 +02:00
akwizgran edebde2bf4 Add task factory. 2021-07-13 10:26:11 +02:00
akwizgran 71ce74c633 Add removable drive manager with placeholder task implementations. 2021-07-13 10:26:10 +02:00
akwizgran 2dd5239b9d Add Android implementation of RemovableDrivePlugin. 2021-07-13 10:26:10 +02:00
akwizgran f0145eb8e6 Decouple RemovableDrivePlugin from FileConstants. 2021-07-13 10:26:09 +02:00
akwizgran 556ed8fe16 Don't inject default RemovableDrivePluginFactory on Android. 2021-07-13 10:26:08 +02:00
akwizgran ed753fd354 Decouple removable drive plugin from java.io.File for portability. 2021-07-13 10:26:08 +02:00
akwizgran 4ecc5e4367 Clean up plugin injection code, remove unused module. 2021-07-13 10:26:02 +02:00
akwizgran b4ae480d93 Configure removable drive plugin for Android. 2021-07-13 10:25:23 +02:00
akwizgran 9a563e0cdd Add removable drive plugin. 2021-07-13 10:25:23 +02:00
akwizgran c5d6ee6782 Add DB method for getting amount of data to sync. 2021-07-13 10:25:22 +02:00
akwizgran f7fdf7745e Update MessagesSentEvent to include amount of data sent. 2021-07-13 10:25:21 +02:00
akwizgran a48b60a24a Update translations. 2021-07-12 10:18:31 +01:00
Ben Armstead 520f06020c Correct typo 2021-07-08 15:14:30 +00:00
Ben Armstead f96b60c0d0 Create a better formatted and more informant README.md 2021-07-08 13:16:37 +00:00
Torsten Grote 00f03f6587 Merge branch '1981-upgrade-material-tap-target-prompt' into 'master'
Upgrade MaterialTapTargetPrompt library to fix NPE

Closes #1981

See merge request briar/briar!1498
2021-07-05 11:17:39 +00:00
akwizgran c68bd699f1 Upgrade MaterialTapTargetPrompt library to fix NPE. 2021-07-05 10:06:53 +01:00
akwizgran e5f78cdc1e Log uncaught exceptions on debug builds. 2021-06-30 10:44:15 +01:00
akwizgran 00407539d3 Bump version numbers for 1.3.5 release. 2021-06-18 11:17:35 +01:00
akwizgran 62014f4d01 Update translations. 2021-06-18 11:16:33 +01:00
akwizgran e7dddda7e5 Merge branch 'tor-0.3.5.15' into 'master'
Upgrade Tor to 0.3.5.15

Closes #2075

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

Closes #2056

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

See merge request briar/briar!1455
2021-06-16 13:52:04 +00:00
Torsten Grote 61f660ca1d Upgrade libraries before 1.3 release 2021-06-16 10:40:30 -03:00
akwizgran 6d44521016 Upgrade Tor to 0.3.5.15. 2021-06-16 11:16:10 +01:00
akwizgran 7289f5ba8a Merge branch '2059-no-such-group-exception' into 'master'
Check if group still exists before storing MessageId of thread position

Closes #2059

See merge request briar/briar!1477
2021-06-14 14:57:21 +00:00
Torsten Grote b657c7f347 Ignore NoSuchGroupException when storing MessageId of thread position for removed group 2021-06-10 15:45:31 -03:00
Torsten Grote 40865425c5 Merge branch 'fix-padding-of-contact-exchange-error' into 'master'
Fix missing padding for title in contact exchange error fragment

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

Closes #1971

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

Closes #2043

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

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

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

Closes #2032

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

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

Closes #2027

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

Closes #2009

See merge request briar/briar!1451
2021-05-05 16:39:55 +00:00
akwizgran cad5edcf86 Move input state methods to UiUtils. 2021-05-05 16:57:25 +01:00
akwizgran 38f70bb6be Add full stop. 2021-05-05 13:02:56 +01:00
akwizgran 33bdc81b3e Show instructions for locking Briar to the Xiaomi recent apps list. 2021-05-05 12:37:23 +01:00
Torsten Grote 21fd7f5eed Merge branch 'allow-one-unreachable-bridge' into 'master'
Allow BridgeTest to pass if one bridge is unreachable

See merge request briar/briar!1449
2021-05-04 12:31:38 +00:00
akwizgran 6354e91b55 Allow BridgeTest to pass if one bridge is unreachable. 2021-05-04 13:13:57 +01:00
Torsten Grote 8123c06348 Merge branch '2012-update-bubbles-after-removing-messages' into 'master'
Update disappearing message bubbles after removing messages

Closes #2012

See merge request briar/briar!1448
2021-05-03 16:57:04 +00:00
akwizgran 663c648337 Update disappearing message bubbles after removing messages. 2021-05-03 15:16:11 +01:00
akwizgran bee4e94987 Bump version numbers for 1.3.3 release. 2021-05-03 13:55:39 +01:00
akwizgran c44bdc8762 Update translations. 2021-05-03 13:38:14 +01:00
Torsten Grote 423ecf71d8 Merge branch '1894-viewmodel-for-rssfeed-activities' into 'master'
Introduce ViewModel for RssFeed*Activity

Closes #1894

See merge request briar/briar!1366
2021-05-03 12:35:32 +00:00
Daniel Lublin 73c7882cc0 Introduce RssFeedViewModel
Furnishing the RssFeed function as a single activity with fragments for
Manage and Import.
2021-05-03 09:40:40 +02:00
Torsten Grote 552b9ef21a Wait for an incoming connection before showing an error Toast 2021-04-30 16:01:54 -03:00
Torsten Grote 683af1ec3a Merge branch '1827-target-api-30' into 'master'
Raise target API level to 30, upgrade build tools to 30.0.3

Closes #1827

See merge request briar/briar!1445
2021-04-30 17:44:49 +00:00
akwizgran 77ed15311c Raise target API level to 30, upgrade build tools to 30.0.3. 2021-04-30 14:51:49 +01:00
akwizgran 3d72557618 Merge branch '1962-connect-via-bt-backend' into 'master'
Implement connect via Bluetooth backend

Closes #1962

See merge request briar/briar!1412
2021-04-27 12:27:55 +00:00
Daniel Lublin e2a11d42f8 Implement backend for connect via bluetooth 2021-04-27 14:15:10 +02:00
akwizgran 0f5ea6ae66 Merge branch 'translation-update-script' into 'master'
Add script to update Android app translations

See merge request briar/briar!1442
2021-04-27 11:09:24 +00:00
akwizgran 5b2c9b85f9 Merge branch 'prevent-double-pipelines' into 'master'
Avoid duplicate CI pipelines running at the same time

See merge request briar/briar!1443
2021-04-27 11:08:13 +00:00
Torsten Grote 94921230d9 Avoid duplicate CI pipelines running at the same time
Docs:
https://docs.gitlab.com/ee/ci/yaml/README.html#switch-between-branch-pipelines-and-merge-request-pipelines
https://docs.gitlab.com/ee/ci/yaml/README.html#avoid-duplicate-pipelines
2021-04-26 15:37:16 -03:00
Torsten Grote 34788356e6 Add script to update Android app translations
add German and Spanish (incl. video) play store listing
2021-04-26 15:14:06 -03:00
akwizgran 2f719d7f2c Bump version numbers for 1.3.2 release. 2021-04-26 13:50:35 +01:00
akwizgran eb2e8d75f4 Enable features for 1.3 release. 2021-04-26 13:45:53 +01:00
akwizgran 338d288290 Update translations. 2021-04-26 13:43:33 +01:00
Torsten Grote 03fe1a2d2c Merge branch '1743-huawei-app-launch' into 'master'
Add button for opening Huawei battery settings during setup

See merge request briar/briar!1441
2021-04-23 13:54:55 +00:00
akwizgran ade48c7bea Merge branch 'fastlane-metadata-upload' into 'master'
Update Google play listing and language mappings

See merge request briar/briar!1440
2021-04-23 13:43:10 +00:00
akwizgran 4a8d89e2bb Add button for opening Huawei battery settings during setup. 2021-04-23 14:25:24 +01:00
Torsten Grote 0fed1681ed Google play listing now available in:
* Persian
* Galician
* Lithuanian
* Turkish
* Chinese (Simplified)
2021-04-23 10:22:27 -03:00
akwizgran 93ad483066 Merge branch 'fastlane-metadata-upload' into 'master'
Update Play Store listing and add Catalan translation

See merge request briar/briar!1439
2021-04-23 10:10:08 +00:00
Torsten Grote d995e73996 Update Play Store listing and add Catalan translation 2021-04-22 14:06:37 -03:00
Torsten Grote 1d271bab18 Merge branch '1914-create-viewmodels-directly-after-injection' into 'master'
Create ViewModels directly after injection

Closes #1914

See merge request briar/briar!1432
2021-04-22 14:59:05 +00:00
Torsten Grote a9d2aa9366 Merge branch '1883-resource-ids-will-be-non-final' into 'master'
Replace switch statements with resource ids with if-then-else

Closes #1883

See merge request briar/briar!1438
2021-04-22 13:34:35 +00:00
Sebastian Kürten 2a48d43e5b Create ViewModels directly after injection 2021-04-22 15:31:55 +02:00
Sebastian Kürten 0a4e23118a Replace switch statements with resource ids with if-then-else 2021-04-22 15:19:11 +02:00
akwizgran 528a15962f Merge branch 'fastlane-metadata' into 'master'
Make Google Play descriptions translatable

See merge request briar/briar!1437
2021-04-22 13:00:13 +00:00
Torsten Grote 0a0cc4e79c Extend full description 2021-04-22 09:50:16 -03:00
Torsten Grote 2b3ba42d70 Make Google Play descriptions translable 2021-04-21 13:35:10 -03:00
akwizgran 9465331ece Merge branch '1999-bluetooth-killed-activity-fix' into 'master'
Reset plugin assignments when starting AddNearbyContactIntroFragment

Closes #1999

See merge request briar/briar!1434
2021-04-21 15:57:17 +00:00
akwizgran b0d86bef3e Merge branch 'scheduled-tests' into 'master'
Run bridge tests in scheduled nightly tests (and fix merge pipelines)

See merge request briar/briar!1431
2021-04-21 13:55:48 +00:00
Torsten Grote a28a2360f1 Merge branch 'remove-redundant-casts' into 'master'
Remove a few redundant casts

See merge request briar/briar!1436
2021-04-21 12:52:04 +00:00
Torsten Grote f7a957150e Tweak CI rules for optional tests
so they are not needed for merge requests
2021-04-21 09:49:11 -03:00
Torsten Grote 67bd065bc3 Allow manual emulator tests in all situations 2021-04-21 09:48:59 -03:00
Torsten Grote 5a3a12767c Increase SetupActivity timeout in PromoVideoTest as the current one doesn't seem to be sufficient 2021-04-21 09:48:58 -03:00
Torsten Grote 2f86bc312c Catch UnableToTakeScreenshotException to make CI more stable 2021-04-21 09:48:58 -03:00
Torsten Grote f0fcadfaf4 Also run optional bridge test with schedules 2021-04-21 09:48:57 -03:00
akwizgran a9d88c849a Merge branch '1961-connect-via-bt-ui' into 'master'
Simple version of Connect via Bluetooth UI

See merge request briar/briar!1398
2021-04-21 11:57:53 +00:00
Sebastian Kürten 7397efca80 Remove a few redundant casts 2021-04-21 13:53:53 +02:00
Torsten Grote 17bd6f9a33 Merge branch '1778-onboarding-tap-target' into 'master'
Wait for layout before showing onboarding tap target

Closes #1778

See merge request briar/briar!1435
2021-04-21 11:45:19 +00:00
akwizgran 2d4e7a9fb0 Wait for layout before showing onboarding tap target. 2021-04-21 12:20:21 +01:00
Torsten Grote 0266da993d Reset plugin assignments when starting AddNearbyContactIntroFragment 2021-04-20 14:38:58 -03:00
Torsten Grote ea5280713f Address review feedback for Connect via Bluetooth UI 2021-04-20 14:24:05 -03:00
Torsten Grote 0b89d29c7d Reset BluetoothPlugin reference
When it is assigned before we are signed-in in (like when returning to a killed activity), it would be null and without a reset, we would consider Bluetooth to not be supported.
2021-04-20 14:23:07 -03:00
Torsten Grote 688bac77a8 Use a feature flag to hide connect via Bluetooth option 2021-04-19 11:36:35 -03:00
Torsten Grote c736bf7c06 Move Connect via Bluetooth UI into DialogFragment
so it can stay active when leaving the context to enable location or permissions
2021-04-19 11:08:02 -03:00
Torsten Grote 539730f8ec Show dialog when permission was denied for good 2021-04-19 11:07:21 -03:00
Torsten Grote a9c4669c75 Simple version of Connect via Bluetooth UI 2021-04-19 11:07:20 -03:00
Torsten Grote 4c11f93ee2 Merge branch '1973-make-use-of-handle-exception' into 'master'
Make more use of DbViewModel#handleException()

Closes #1973

See merge request briar/briar!1427
2021-04-16 17:29:20 +00:00
Torsten Grote d3dbcfd62d Recreate plausible private group sharing sessions when re-adding contact from group 2021-04-15 14:46:22 -03:00
Torsten Grote c4c70f5ac2 Do not create PeerSession for groups we created
This needs a CreatorSession which gets created on-demand.
2021-04-15 14:44:58 -03:00
Sebastian Kürten f8dba6fd7f Add static version of DbViewModel#handleException() in UiUtils 2021-04-15 19:34:14 +02:00
Sebastian Kürten 419247074f Make more use of DbViewModel#handleException() 2021-04-15 17:53:53 +02:00
akwizgran 2ddb7b5b64 Merge branch '1944-update-contact-list-when-changing-aliases' into 'master'
Broadcast ContactAliasChangedEvent to update contact list

Closes #1944

See merge request briar/briar!1425
2021-04-15 15:35:46 +00:00
akwizgran c14b59661e Merge branch 'fix-settings-test' into 'master'
Fix SettingsActivityScreenshotTest and enable scheduled emulator tests

See merge request briar/briar!1429
2021-04-15 15:30:31 +00:00
akwizgran d70d27e665 Merge branch '804-self-destructing-messages' into 'master'
Merge 'Self-destruct timer for messages' to master

Closes #1863

See merge request briar/briar!1396
2021-04-15 15:24:19 +00:00
akwizgran 8991762b0c Final code review nitpicks. 2021-04-15 16:12:38 +01:00
akwizgran 2fc6741c99 Remove redundant method. 2021-04-15 16:03:01 +01:00
akwizgran 1075af73f2 Change default timer duration to 7 days. 2021-04-15 11:54:48 +01:00
Torsten Grote 8671229f76 Merge branch '1672-speed-dial-crash' into 'master'
Close the speed dial to prevent a crash

Closes #1672

See merge request briar/briar!1430
2021-04-14 17:22:06 +00:00
akwizgran 0fb67583ff Close the speed dial to prevent a crash. 2021-04-14 18:10:39 +01:00
Torsten Grote 2fc0fd17a2 Fix SettingsActivityScreenshotTest 2021-04-14 11:43:31 -03:00
Torsten Grote f185860213 Allow emulator tests to run also on a schedule
Also do 1 retry in case of failure
2021-04-14 10:57:49 -03:00
akwizgran 8ffcdbfc21 Merge branch 'sort-blogposts' into 'master'
Sort the loaded posts, like FeedViewModel already does

See merge request briar/briar!1428
2021-04-14 10:14:34 +00:00
Daniel Lublin 6a38e2cca8 Sort the loaded posts, like FeedViewModel already does 2021-04-14 12:02:02 +02:00
Sebastian Kürten 10d9d78ca8 Broadcast ContactAliasChangedEvent to update contact list 2021-04-14 07:43:50 +02:00
Torsten Grote 03a68038e7 Merge branch 'v3-address-for-feedback-and-crash-reports' into 'master'
Use a v3 hidden service for receiving feedback and crash reports

See merge request briar/briar!1426
2021-04-13 17:01:58 +00:00
akwizgran fabefcdf4b Use a v3 hidden service for receiving feedback and crash reports. 2021-04-13 17:50:36 +01:00
Sebastian Kürten 9e4d8ecddf Make introducees send auto-declines even if reponse already received 2021-04-13 08:49:04 -03:00
Sebastian Kürten 1dffbfd8dc Add two tests for auto-declines happening after response already received 2021-04-13 08:49:04 -03:00
Sebastian Kürten 950db5a87a Assert that IntroductionManager return true for canIntroduce() 2021-04-13 08:49:04 -03:00
Sebastian Kürten 21348d5557 IntroductionManager: don't throw IllegalArgumentException when deleting invisible msgs 2021-04-13 08:49:03 -03:00
Sebastian Kürten eb1a089437 Revert changes to AbstractProtocolEngine
This reverts parts of commit 5d143f8b33adc07d990627036b806a2becea7074.
2021-04-13 08:49:03 -03:00
Sebastian Kürten 17fc81ab7a Re-add integration test that goes through two full introduction cycles 2021-04-13 08:49:03 -03:00
Torsten Grote 1c54fd1101 Don't auto-delete invisible forwarded responses on sender side
They will be visible for the recipient, so send with timer
2021-04-13 08:49:02 -03:00
Sebastian Kürten 263bce38cd Create new test that reproduces #1975 2021-04-13 08:49:02 -03:00
Sebastian Kürten a923c1151c Move setReadFlag() from ConversationClient to ConversationManager 2021-04-13 08:49:02 -03:00
Sebastian Kürten 0bf10a827f Implement auto-declining for self-destructed introductions 2021-04-13 08:49:01 -03:00
Daniel Lublin 49850e4198 Make sure invitation accept msg is linking to shareable 2021-04-13 08:49:01 -03:00
Daniel Lublin 95b437b311 Add test for invitee responding after sharer deleted invitation 2021-04-13 08:49:00 -03:00
Daniel Lublin 7006f765a6 Keep members in subclasses and use getters 2021-04-13 08:49:00 -03:00
Daniel Lublin ec3360400c Assert that expected event is broadcasted 2021-04-13 08:49:00 -03:00
Daniel Lublin 5c41d09c52 Remember when invitation was auto-declined due to deletion
And render differently
2021-04-13 08:48:59 -03:00
Daniel Lublin a7590956fd Auto-decline/auto-delete Forum & Blog sharing invitations/responses 2021-04-13 08:48:59 -03:00
Torsten Grote a581960121 Don't show notification for own auto-decline responses 2021-04-13 08:48:58 -03:00
Torsten Grote dc57a0b925 Use AtomicReference in TestEventListener to store event 2021-04-13 08:48:58 -03:00
Torsten Grote d6082162ab Add a way to check for expected events
and use it for private group auto-declines
2021-04-13 08:48:58 -03:00
Torsten Grote 1801afdbb7 Update support for disappearing messages in real time 2021-04-13 08:48:57 -03:00
akwizgran 458add0c9c Don't advertise support for messaging features that are disabled by flags. 2021-04-13 08:48:57 -03:00
akwizgran f2374eb141 Count sent messages in integration tests. 2021-04-13 08:48:56 -03:00
Torsten Grote 5db5897793 Use stored session metadata instead of fetching it again 2021-04-13 08:48:56 -03:00
Torsten Grote f3d628afa7 Render automatic declines differently in the UI
and show them as they happen via an Event
2021-04-13 08:48:55 -03:00
Torsten Grote 4d3482e40e Remember when declines were automatic due to deletion
so they can be shown differently for sender
2021-04-13 08:48:55 -03:00
Torsten Grote a8cff454ec Add integration tests for auto-deletion of private group invitations and responses 2021-04-13 08:48:55 -03:00
Torsten Grote f66cae4749 Factor out auto-delete integration test code
so we can re-use it in other tests
2021-04-13 08:48:54 -03:00
Torsten Grote aded1daf92 Auto-delete PrivateGroup invitations and responses as well 2021-04-13 08:48:54 -03:00
Torsten Grote aa1ba0d950 Turn 'Learn more' link into a button to have a larger tap area
and a selectable background
2021-04-13 08:48:53 -03:00
Torsten Grote 071010e438 Turn ConversationSettingsLearnMoreDialog into a generic Onboarding fragment 2021-04-13 08:48:53 -03:00
Torsten Grote f6d8e364d6 Update auto-delete onboarding text 2021-04-13 08:48:53 -03:00
akwizgran f1453ed4c4 Show disabled menu item if we support feature but contact doesn't. 2021-04-13 08:48:52 -03:00
akwizgran 3a2146cb03 Don't advertise support for disappearing messages unless flag is enabled. 2021-04-13 08:48:52 -03:00
akwizgran 24eb76de20 Hide disappearing messages menu item unless feature flag is enabled. 2021-04-13 08:48:51 -03:00
akwizgran 693478e0a5 Add feature flag for self-destructing messages. 2021-04-13 08:48:51 -03:00
Torsten Grote bf6be5c5a7 Replace all messages when re-loading
to ensure that messages deleted in the meantime get removed
2021-04-13 08:48:51 -03:00
Torsten Grote a12a639cd3 Remove auto-deleted messages immediately from conversation 2021-04-13 08:48:50 -03:00
Torsten Grote ef37428714 Replace MessagesCleanedUpEvent with ConversationMessagesDeletedEvent 2021-04-13 08:48:50 -03:00
akwizgran 644afe8995 Wait for events to be delivered before continuing with test. 2021-04-13 08:48:50 -03:00
akwizgran c66c428124 Log how long it takes to deliver private messages and attachments. 2021-04-13 08:48:49 -03:00
akwizgran db5b2ea9b6 Remove redundant call to getAutoDeleteTimer(). 2021-04-13 08:48:49 -03:00
akwizgran d84603bce2 Check group counts in AutoDeleteIntegrationTest. 2021-04-13 08:48:48 -03:00
akwizgran b128370299 Include legacy messages when recalculating group count. 2021-04-13 08:48:48 -03:00
akwizgran 240e619248 Delete private messages when their timers expire (needs UI support). 2021-04-13 08:48:48 -03:00
akwizgran c89bde08db Move ConversationManagerImpl to conversation package. 2021-04-13 08:48:47 -03:00
akwizgran 3ecd1c62b8 Set default timer duration to 1 minute for testing. 2021-04-13 08:48:47 -03:00
akwizgran e3c5497283 Update javadoc to explain that a new timer can be set. 2021-04-13 08:48:46 -03:00
akwizgran 4bd8ee8ccf Pass message IDs to cleanup hooks in batches. 2021-04-13 08:48:46 -03:00
akwizgran 43b437af92 Group messages by group ID when fetching them from database. 2021-04-13 08:48:46 -03:00
akwizgran 56e0d62597 Throw an exception if no cleanup hook was registered. 2021-04-13 08:48:45 -03:00
akwizgran d10e5f025d Remove copypasta. 2021-04-13 08:48:45 -03:00
akwizgran b1a80691db Add comment to explain that starting timer may be a no-op. 2021-04-13 08:48:44 -03:00
akwizgran 049aa61e85 Stop the timer if no hook has been registered. 2021-04-13 08:48:44 -03:00
akwizgran 7026361234 Add javadocs for CleanupManager and CleanupHook. 2021-04-13 08:48:44 -03:00
akwizgran 5e30dc5bf4 Simplify deadline comparison logic. 2021-04-13 08:48:43 -03:00
akwizgran 024bfc8ec8 Stop the cleanup timer if the hook returns false. 2021-04-13 08:48:42 -03:00
akwizgran 04e5e8e4d0 Add cleanup manager. 2021-04-13 08:48:38 -03:00
akwizgran 7c5d47733f Query message IDs rather than metadata when only IDs are needed. 2021-04-13 08:46:11 -03:00
Torsten Grote b24f2a1818 Add support for showing auto-delete timers in minutes 2021-04-13 08:46:11 -03:00
Torsten Grote ee6664ce9d Show actual auto-delete timer duration in UI
(only days and hours for now)
2021-04-13 08:46:11 -03:00
Torsten Grote ab434946b5 Show outgoing message status icon in same color as time 2021-04-13 08:46:10 -03:00
Torsten Grote 35e431eb99 Fix bomb icon color
in incoming image messages without text (on old phones)
2021-04-13 08:46:10 -03:00
Torsten Grote aa8cddf509 Get rid of SENDING state and publish new live data in order on UiThread 2021-04-13 08:46:10 -03:00
Torsten Grote c9ede0bfc1 Return LiveData when sending message 2021-04-13 08:46:09 -03:00
Torsten Grote 6ec9a0f2b2 Show warning dialog when auto-delete timer has changed since starting to compose message 2021-04-13 08:46:09 -03:00
Torsten Grote 2f86112801 Add "Tap to learn more" to message bubbles for timer changes 2021-04-13 08:46:09 -03:00
akwizgran c032befe6f Provide clock for UI tests. 2021-04-13 08:46:08 -03:00
akwizgran 55eccde031 Add some comments. 2021-04-13 08:46:08 -03:00
akwizgran 5716820439 Sync acks for initial messages when setting up integration tests. 2021-04-13 08:46:08 -03:00
akwizgran 17d433dd9b Allow time travel in integration tests. 2021-04-13 08:46:07 -03:00
akwizgran 000812bf6d Inject DefaultTaskSchedulerModule.EagerSingletons at startup in headless app. 2021-04-13 08:46:07 -03:00
akwizgran 5e2187a877 Refactor integration tests to allow clock to be replaced. 2021-04-13 08:46:06 -03:00
Sebastian Kürten e10b6334f5 Introduce conversation settings screen 2021-04-13 08:46:06 -03:00
Torsten Grote baa0341727 Create group invitation with read-write transaction
because the AutoDeleteManager needs to change the DB
and otherwise crashes.

Closes #1863
2021-04-13 08:46:06 -03:00
Torsten Grote 814b2b2582 Make view state of text send UI easier to reason about
and fix bugs with bomb badge and hint display
2021-04-13 08:46:05 -03:00
Torsten Grote 56705bde74 Show bomb badge in same style as send button 2021-04-13 08:46:05 -03:00
Torsten Grote dceb38b777 Show a bomb badge on the send button when disappearing messages is active 2021-04-13 08:46:05 -03:00
Torsten Grote 9947a6aa1b Use a different hint in conversation when message will disappear
and keep the hint updated when the auto-delete timer changes
2021-04-13 08:46:04 -03:00
Torsten Grote 7a3be374c8 Broadcast event when auto delete timer is mirrored 2021-04-13 08:46:04 -03:00
Torsten Grote 4ea3ce0e3c Remove mirrored timer texts
as we can't detect reliably if a timer setting was mirrored or manually changed.

Also remove item update optimization from adapter as this can cause issues when items already exist.
2021-04-13 08:46:04 -03:00
Torsten Grote 923185b3f4 Show timer change notices in private conversations 2021-04-13 08:46:03 -03:00
Torsten Grote d91e6c6c1a Allow setting a self-destruct timer
This is a rough prototype of #1837 meant to make testing the UI easier.
2021-04-13 08:46:03 -03:00
akwizgran 1c93a79448 Use Collections.sort() to satisfy Animal Sniffer. 2021-04-13 08:46:03 -03:00
akwizgran e12ad0cd79 Add integration tests for timer mirroring. 2021-04-13 08:46:02 -03:00
akwizgran 8d6bd29b93 Add method for UI and tests to get current timer. 2021-04-13 08:46:02 -03:00
akwizgran f941a73999 Update integration tests. 2021-04-13 08:46:02 -03:00
akwizgran c3057141d8 Don't receive auto-delete timer from remote accept message as introducee. 2021-04-13 08:46:01 -03:00
akwizgran 49080cb64c Hook up incoming messages to the auto-delete manager. 2021-04-13 08:46:01 -03:00
akwizgran 27dbe23914 Mirror the remote auto-delete timer. 2021-04-13 08:46:01 -03:00
akwizgran d7a2de5817 Add integration tests for auto-delete timer. 2021-04-13 08:46:00 -03:00
akwizgran 0328aa0630 Forwarded accept messages aren't visible to the introducee. 2021-04-13 08:46:00 -03:00
akwizgran b6cf302131 Only use conversation timestamp for messages that will be visible in conversation. 2021-04-13 08:46:00 -03:00
akwizgran e2a894acd3 Get timestamp for abort message in same way as other messages. 2021-04-13 08:45:59 -03:00
akwizgran 00ed6d9bb8 Look up auto-delete timer when creating private group invitation. 2021-04-13 08:45:59 -03:00
akwizgran c9a9734368 Use the right timestamp when signing private group invitation. 2021-04-13 08:45:58 -03:00
akwizgran efc56a8724 Provide TransactionManager. 2021-04-13 08:45:58 -03:00
akwizgran 6e6923b108 Look up conversation timestamp when creating group invitation messages. 2021-04-13 08:45:58 -03:00
akwizgran f459beccdb Move lookup of latest conversation timestamp to core for blog and forum sharing. 2021-04-13 08:45:57 -03:00
akwizgran 751c5a3245 Move lookup of latest conversation timestamp to core. 2021-04-13 08:45:57 -03:00
akwizgran 8488499da6 Add transactional variant of getGroupCount(). 2021-04-13 08:45:57 -03:00
akwizgran 96a7e3c425 Send current minor version of messaging client to contacts. 2021-04-13 08:45:56 -03:00
Torsten Grote 0dcf510466 Show bomb icon for messages with auto-destruct timer 2021-04-13 08:45:56 -03:00
akwizgran 0427b12d52 Check that timer argument is legal before storing. 2021-04-13 08:45:56 -03:00
akwizgran 9256c66fcc Add unit tests for AutoDeleteManagerImpl. 2021-04-13 08:45:55 -03:00
akwizgran 706f4e1c4c Implement AutoDeleteManager. 2021-04-13 08:45:55 -03:00
akwizgran 96debcd616 Add dummy implementation of AutoDeleteManager. 2021-04-13 08:45:54 -03:00
akwizgran 07f20e1e0d Refactor auto-delete code from Bramble to Briar. 2021-04-13 08:45:54 -03:00
akwizgran fee2e503bd Rewrap lines. 2021-04-13 08:45:54 -03:00
akwizgran f9f260bbc1 Factor out methods for storing and retrieving contact ID. 2021-04-13 08:45:53 -03:00
akwizgran 61718192ee Factor out method for validating auto-delete timers. 2021-04-13 08:45:53 -03:00
akwizgran 27893f9cdd Update comments. 2021-04-13 08:45:53 -03:00
akwizgran 9b0b80ef04 Add unit tests for validating auto-delete timer. 2021-04-13 08:45:52 -03:00
akwizgran 3e1c2df4b1 Update private group invitation client to include self-destruct timers. 2021-04-13 08:45:52 -03:00
akwizgran fa745410cc Update blog and forum sharing clients to include self-destruct timers. 2021-04-13 08:45:51 -03:00
akwizgran a427624e8d Update message parsing and encoding to include auto-delete timer. 2021-04-13 08:45:51 -03:00
akwizgran 3798ca1e17 Update introduction validator to support auto-delete timers. 2021-04-13 08:45:51 -03:00
akwizgran 113120b3ab Add constant for NO_AUTO_DELETE_TIMER, address review comments. 2021-04-13 08:45:50 -03:00
akwizgran b10ca5b77f Add unit tests for private message validation. 2021-04-13 08:45:50 -03:00
akwizgran f10e3d756a Fix comments in PrivateMessageValidator. 2021-04-13 08:45:50 -03:00
akwizgran 9608b974ec Add integration test for auto-delete timer in private messages. 2021-04-13 08:45:49 -03:00
akwizgran 3b6cc9c633 Add auto-deletion timer to private messages. 2021-04-13 08:45:47 -03:00
akwizgran 5305dd62d1 Merge branch '1872-key-agreement' into 'master'
Finish migrating KeyAgreementActivity to ViewModel

Closes #1982 and #1872

See merge request briar/briar!1357
2021-04-12 13:19:51 +00:00
akwizgran a066190c60 Merge branch '57-detect-db-durability-failures' into 'master'
Implement dirty flag to detect durability failures

Closes #57

See merge request briar/briar!1424
2021-04-12 13:17:28 +00:00
akwizgran cdae8b35f5 Another small refactoring to make control flow easier to understand. 2021-04-12 10:06:49 -03:00
Torsten Grote 6ee57315dd Prevent NPE when onQrCodeDecoded() is called after we stop to listen 2021-04-12 10:06:48 -03:00
Sebastian Kürten 64f682146d Integrate merge request feedback 2021-04-12 13:04:42 +02:00
akwizgran 36525fbe9d Merge branch 'promo-video' into 'master'
Instrumentation test for tutorial video and sign-in

Closes #1967

See merge request briar/briar!1423
2021-04-12 10:46:03 +00:00
Torsten Grote 8f628f2d45 Fix PromoVideoTest for CI 2021-04-09 15:24:13 -03:00
Torsten Grote 5e84e5b8b6 Stop listening to key agreement connections when leaving fragment
Also don't liberate screen orientation when backing out of adding a contact nearby
2021-04-09 15:20:39 -03:00
Torsten Grote a64878bd00 Also reset payload flags when resetting AddNearbyContact state 2021-04-08 14:21:17 -03:00
Torsten Grote c53fc5eaa3 Add inspection profile to repo
so we can all share the same inspection profile and benefit from its warnings
2021-04-08 13:55:26 -03:00
akwizgran 212751c835 Return a value instead of passing a runnable argument. 2021-04-08 17:11:07 +01:00
akwizgran fe1c6acebb Remove workaround for Android issue #190966. 2021-04-08 17:03:28 +01:00
Sebastian Kürten ce47bfe018 Write tests for the dirty flag 2021-04-08 12:24:23 +02:00
Torsten Grote 0ee4ade404 One more round of addressing AddNearbyContact review feedback 2021-04-07 16:18:18 -03:00
Sebastian Kürten e99df2b69e Log dirty flag when opening database 2021-04-06 20:19:28 +02:00
Sebastian Kürten db84d07c38 Store a dirty flag in the database 2021-04-06 19:45:26 +02:00
Torsten Grote db610cfb4c Run only tests from android package on emulator
Otherwise, it re-runs bramble tests for some reason
2021-04-01 17:12:04 -03:00
Torsten Grote 5b52417d20 Check if Bluetooth is supported before requesting discoverability 2021-04-01 15:36:55 -03:00
Torsten Grote 8a768cf933 Add a test for sign-in
This requires an account to exist before as we can't restart our lifecycle.
So we don't automatically clear app data after each test, but rather need to delete an existing account manually before each test.
2021-04-01 14:31:34 -03:00
Torsten Grote 8a3dd5472b Make a screenshot when test fails to help with debugging 2021-03-31 13:36:55 -03:00
Torsten Grote f971533a5b Add a way to detect if code runs as instrumentation test
and disable some dialogs to make tests easier to write
2021-03-31 13:36:55 -03:00
Torsten Grote a12166c13b Use Android Test Orchestrator to have a clean state for each test
fixes flaky/broken espresso tests
2021-03-31 13:36:54 -03:00
Torsten Grote 51624a31e3 Add a first PromoVideoTest 2021-03-31 13:36:54 -03:00
Torsten Grote cdc632e1af Don't show screen filter and expiry warnings in screenshot tests 2021-03-30 16:56:03 -03:00
Torsten Grote 31f87f647e Create an OverlayView so we can show taps in espresso tests 2021-03-30 16:56:03 -03:00
Torsten Grote dcd37f71d1 Turn splash screen duration into a resource variable
so screenshot tests can define a different duration
2021-03-30 16:56:03 -03:00
Torsten Grote 4ca286b28e Allow to decide whether test contacts should have alias 2021-03-30 16:56:02 -03:00
Torsten Grote 4f3e4b019a Request user to turn on location for adding contact nearby on API 28+ 2021-03-29 11:30:17 -03:00
Torsten Grote 1d44305e34 Catch exception when calling Camera#getParameters()
Fixes #1982
2021-03-24 15:23:16 -03:00
Torsten Grote a37af592cd Use new ActivityResultLauncher to request permissions for AddNearbyContact 2021-03-24 15:03:53 -03:00
Torsten Grote 7f486eef4c Refactor more code into AddNearbyContactViewModel
thus concentrating the logic there needing less back and forth with the activity
2021-03-23 18:09:57 -03:00
Torsten Grote bcc0442add Merge activities for adding contact nearby
and rename related classes to consolidate names
2021-03-17 14:05:15 -03:00
Torsten Grote 700f6e05bf Factor out permission related code from KeyAgreementActivity to AddNearbyContactPermissionManager 2021-03-17 14:02:54 -03:00
Torsten Grote d8327d6de2 Re-set orientation lock when fragment is left 2021-03-17 14:02:54 -03:00
Torsten Grote 5a55b3d7e3 Move Plugin related code from activity to ViewModel 2021-03-17 14:02:54 -03:00
Torsten Grote bed87ed439 Move backend comms and logic out of KeyAgreementFragment
into ViewModel
2021-03-17 14:02:53 -03:00
Torsten Grote 6d1f1c7852 Get rid of KeyAgreementEventListener
and communicate via ViewModel
2021-03-17 14:02:53 -03:00
Torsten Grote f6b3bde724 Introduce ContactExchangeResult
to include all result information in LiveData
2021-03-17 14:02:53 -03:00
Torsten Grote 94ec22bef8 Move keyagreement package into contact.add.nearby
and fix some small warnings in the process
2021-03-17 14:02:50 -03:00
764 changed files with 34413 additions and 8168 deletions
+1
View File
@@ -18,6 +18,7 @@ local.properties
# Android Studio # Android Studio
.idea/* .idea/*
!.idea/inspectionProfiles/
!.idea/runConfigurations/ !.idea/runConfigurations/
!.idea/codeStyleSettings.xml !.idea/codeStyleSettings.xml
!.idea/codeStyles !.idea/codeStyles
+39 -7
View File
@@ -5,6 +5,15 @@ stages:
- optional_tests - optional_tests
- check_reproducibility - check_reproducibility
workflow:
# when to create a CI pipeline
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never # avoids duplicate jobs for branch and MR
- if: '$CI_COMMIT_BRANCH'
- if: '$CI_COMMIT_TAG'
.base-test: .base-test:
before_script: before_script:
- set -e - set -e
@@ -24,7 +33,12 @@ 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 check - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom :briar-headless:linuxJars
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom compileOfficialDebugAndroidTestSources compileScreenshotDebugAndroidTestSources check
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
when: always
- when: always
android test: android test:
extends: .base-test extends: .base-test
@@ -34,17 +48,31 @@ android test:
# start emulator first, so it can fail early # start emulator first, so it can fail early
- start-emulator.sh - start-emulator.sh
# run normal and screenshot tests together (exclude Large tests) # run normal and screenshot tests together (exclude Large tests)
- ./gradlew -Djava.security.egd=file:/dev/urandom connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.notAnnotation=androidx.test.filters.LargeTest - ./gradlew -Djava.security.egd=file:/dev/urandom connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.package=org.briarproject.briar.android -Pandroid.testInstrumentationRunnerArguments.notAnnotation=androidx.test.filters.LargeTest
after_script:
- adb pull /sdcard/Pictures/screenshots
artifacts: artifacts:
name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}" name: "${CI_PROJECT_PATH}_${CI_JOB_STAGE}_${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}"
paths: paths:
- kernel.log - kernel.log
- logcat.txt - logcat.txt
- briar-android/build/reports/androidTests/connected/flavors/*
- screenshots
expire_in: 3 days expire_in: 3 days
when: on_failure when: on_failure
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
- briar-android/**/*
when: manual when: manual
except: allow_failure: true
- tags - if: '$CI_COMMIT_TAG == null'
when: manual
allow_failure: true
retry:
max: 1
tags: tags:
- kvm - kvm
@@ -75,11 +103,15 @@ test_reproducible:
- rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock - rm -f $GRADLE_USER_HOME/caches/modules-2/modules-2.lock
- rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/ - rm -fr $GRADLE_USER_HOME/caches/*/plugin-resolution/
manual_tests: bridge test:
extends: .optional_tests extends: .optional_tests
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: on_success
allow_failure: true
- if: '$CI_COMMIT_TAG == null'
when: manual when: manual
except: allow_failure: true
- tags
pre_release_tests: pre_release_tests:
extends: .optional_tests extends: .optional_tests
+3 -12
View File
@@ -31,15 +31,6 @@
<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" />
@@ -197,9 +188,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" />
<option name="PARAMETER_ANNOTATION_WRAP" value="1" /> <indentOptions>
<option name="VARIABLE_ANNOTATION_WRAP" value="1" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="ENUM_CONSTANTS_WRAP" value="1" /> </indentOptions>
</codeStyleSettings> </codeStyleSettings>
</code_scheme> </code_scheme>
</component> </component>
+1
View File
@@ -7,6 +7,7 @@
<w>encrypter</w> <w>encrypter</w>
<w>identicon</w> <w>identicon</w>
<w>introducee</w> <w>introducee</w>
<w>introducees</w>
<w>introducer</w> <w>introducer</w>
<w>onboarding</w> <w>onboarding</w>
</words> </words>
+14
View File
@@ -0,0 +1,14 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="MissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoreObjectMethods" value="true" />
<option name="ignoreAnonymousClassMethods" value="false" />
</inspection_tool>
<inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="true" />
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="true" />
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="true" />
</inspection_tool>
</profile>
</component>
+27 -16
View File
@@ -1,21 +1,32 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.briar-android" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-android" /> <list />
</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="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" 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-core" 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-java" 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 bramble-android" 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-api" 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-core" 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="GradleRunConfiguration" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-headless" run_configuration_type="AndroidJUnit" />
</method> </method>
</configuration> </configuration>
</component> </component>
+20 -11
View File
@@ -1,14 +1,23 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in bramble-android" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.bramble-android" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" /> <list />
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="taskNames">
</method> <list>
<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>
+22 -11
View File
@@ -1,14 +1,25 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in bramble-api" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.bramble-api" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" /> <list />
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="taskNames">
</method> <list>
<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>
+22 -11
View File
@@ -1,14 +1,25 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in bramble-core" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.bramble-core" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" /> <list />
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="taskNames">
</method> <list>
<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>
+20 -12
View File
@@ -1,15 +1,23 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in bramble-java" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.bramble-java" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" /> <option name="taskDescriptions">
<option name="PARAMETERS" value="" /> <list />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" /> </option>
<method v="2"> <option name="taskNames">
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <list>
</method> <option value=":bramble-java:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>
+21 -11
View File
@@ -1,14 +1,24 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in briar-android" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.briar-android" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" /> <list />
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="taskNames">
</method> <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" />
</configuration> </configuration>
</component> </component>
+22 -11
View File
@@ -1,14 +1,25 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-api" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in briar-api" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.briar-api" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-api" /> <list />
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="taskNames">
</method> <list>
<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>
+22 -11
View File
@@ -1,14 +1,25 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in briar-core" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.briar-core" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="PARAMETERS" value="" /> <option name="taskDescriptions">
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" /> <list />
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="taskNames">
</method> <list>
<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>
+20 -12
View File
@@ -1,15 +1,23 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-headless" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests in briar-headless" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.briar-headless" /> <ExternalSystemSettings>
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" /> <option name="executionName" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="METHOD_NAME" value="" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="TEST_OBJECT" value="package" /> <option name="scriptParameters" value="" />
<option name="VM_PARAMETERS" /> <option name="taskDescriptions">
<option name="PARAMETERS" value="" /> <list />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-headless" /> </option>
<method v="2"> <option name="taskNames">
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <list>
</method> <option value=":briar-headless:test" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>
+25 -21
View File
@@ -1,24 +1,28 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="BridgeTest" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true"> <configuration default="false" name="BridgeTest" type="GradleRunConfiguration" factoryName="Gradle">
<module name="briar.bramble-java" /> <ExternalSystemSettings>
<useClassPathOnly /> <option name="env">
<extension name="coverage"> <map>
<pattern> <entry key="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" />
<option name="PATTERN" value="org.briarproject.bramble.plugin.tor.*" /> </map>
<option name="ENABLED" value="true" /> </option>
</pattern> <option name="executionName" />
</extension> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="PACKAGE_NAME" value="org.briarproject.bramble.plugin.tor" /> <option name="externalSystemIdString" value="GRADLE" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.bramble.plugin.tor.BridgeTest" /> <option name="scriptParameters" value="--tests &quot;org.briarproject.bramble.plugin.tor.BridgeTest&quot;" />
<option name="METHOD_NAME" value="" /> <option name="taskDescriptions">
<option name="TEST_OBJECT" value="class" /> <list />
<option name="PARAMETERS" value="" /> </option>
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" /> <option name="taskNames">
<envs> <list>
<env name="OPTIONAL_TESTS" value="org.briarproject.bramble.plugin.tor.BridgeTest" /> <option value=":bramble-java:test" />
</envs> </list>
<method v="2"> </option>
<option name="Android.Gradle.BeforeRunTask" enabled="true" /> <option name="vmOptions" value="" />
</method> </ExternalSystemSettings>
<ExternalSystemDebugServerProcess>false</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration> </configuration>
</component> </component>
-14
View File
@@ -1,14 +0,0 @@
<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>
-14
View File
@@ -1,14 +0,0 @@
<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>
+37 -1
View File
@@ -1 +1,37 @@
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
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)
## Reproducible builds
We provide [docker images](https://code.briarproject.org/briar/briar-reproducer#briar-reproducer)
to ease the task of verifying that the published APK binaries
include nothing but our publicly available source code.
You can either use those images or use them as a blueprint to build your own environment
for reproduction.
## 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
+11 -11
View File
@@ -6,7 +6,7 @@ apply from: 'witness.gradle'
android { android {
compileSdkVersion 30 compileSdkVersion 30
buildToolsVersion '30.0.2' buildToolsVersion '30.0.3'
packagingOptions { packagingOptions {
doNotStrip '**/*.so' doNotStrip '**/*.so'
@@ -14,9 +14,9 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 30
versionCode 10220 versionCode 10403
versionName "1.2.20" versionName "1.4.3"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -42,18 +42,18 @@ configurations {
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
tor 'org.briarproject:tor-android:0.3.5.13@zip' tor "org.briarproject:tor-android:$tor_version"
tor 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a@zip' tor "org.briarproject:obfs4proxy-android:$obfs4proxy_version@zip"
annotationProcessor 'com.google.dagger:dagger-compiler:2.24' annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'javax.annotation:jsr250-api:1.0'
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'junit:junit:4.12' testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock:2.8.2" testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-junit4:2.8.2" testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-legacy:2.8.2" testImplementation "org.jmock:jmock-imposters:$jmock_version"
} }
def torBinariesDir = 'src/main/res/raw' def torBinariesDir = 'src/main/res/raw'
@@ -59,8 +59,8 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
class AndroidBluetoothPlugin class AndroidBluetoothPlugin extends
extends BluetoothPlugin<BluetoothSocket, BluetoothServerSocket> { AbstractBluetoothPlugin<BluetoothSocket, BluetoothServerSocket> {
private static final Logger LOG = private static final Logger LOG =
getLogger(AndroidBluetoothPlugin.class.getName()); getLogger(AndroidBluetoothPlugin.class.getName());
@@ -75,6 +75,7 @@ class AndroidBluetoothPlugin
// Non-null if the plugin started successfully // Non-null if the plugin started successfully
private volatile BluetoothAdapter adapter = null; private volatile BluetoothAdapter adapter = null;
private volatile boolean stopDiscoverAndConnect;
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
BluetoothConnectionFactory<BluetoothSocket> connectionFactory, BluetoothConnectionFactory<BluetoothSocket> connectionFactory,
@@ -86,7 +87,7 @@ class AndroidBluetoothPlugin
Clock clock, Clock clock,
Backoff backoff, Backoff backoff,
PluginCallback callback, PluginCallback callback,
int maxLatency, long maxLatency,
int maxIdleTime) { int maxIdleTime) {
super(connectionLimiter, connectionFactory, ioExecutor, super(connectionLimiter, connectionFactory, ioExecutor,
wakefulIoExecutor, secureRandom, backoff, callback, wakefulIoExecutor, secureRandom, backoff, callback,
@@ -187,7 +188,16 @@ class AndroidBluetoothPlugin
@Nullable @Nullable
DuplexTransportConnection discoverAndConnect(String uuid) { DuplexTransportConnection discoverAndConnect(String uuid) {
if (adapter == null) return null; if (adapter == null) return null;
if (!discoverSemaphore.tryAcquire()) {
LOG.info("Discover already running");
return null;
}
try {
stopDiscoverAndConnect = false;
for (String address : discoverDevices()) { for (String address : discoverDevices()) {
if (stopDiscoverAndConnect) {
break;
}
try { try {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubMacAddress(address)); LOG.info("Connecting to " + scrubMacAddress(address));
@@ -199,10 +209,19 @@ class AndroidBluetoothPlugin
} }
} }
} }
} finally {
discoverSemaphore.release();
}
LOG.info("Could not connect to any devices"); LOG.info("Could not connect to any devices");
return null; return null;
} }
@Override
public void stopDiscoverAndConnect() {
stopDiscoverAndConnect = true;
adapter.cancelDiscovery();
}
private Collection<String> discoverDevices() { private Collection<String> discoverDevices() {
List<String> addresses = new ArrayList<>(); List<String> addresses = new ArrayList<>();
BlockingQueue<Intent> intents = new LinkedBlockingQueue<>(); BlockingQueue<Intent> intents = new LinkedBlockingQueue<>();
@@ -47,7 +47,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
@Inject @Inject
public AndroidBluetoothPluginFactory(@IoExecutor Executor ioExecutor, AndroidBluetoothPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor, @WakefulIoExecutor Executor wakefulIoExecutor,
AndroidExecutor androidExecutor, AndroidExecutor androidExecutor,
AndroidWakeLockManager wakeLockManager, AndroidWakeLockManager wakeLockManager,
@@ -75,7 +75,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public int getMaxLatency() { public long getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@@ -0,0 +1,44 @@
package org.briarproject.bramble.plugin.file;
import android.app.Application;
import android.net.Uri;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.PROP_URI;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@Immutable
@NotNullByDefault
class AndroidRemovableDrivePlugin extends RemovableDrivePlugin {
private final Application app;
AndroidRemovableDrivePlugin(Application app, PluginCallback callback,
long maxLatency) {
super(callback, maxLatency);
this.app = app;
}
@Override
InputStream openInputStream(TransportProperties p) throws IOException {
String uri = p.get(PROP_URI);
if (isNullOrEmpty(uri)) throw new IllegalArgumentException();
return app.getContentResolver().openInputStream(Uri.parse(uri));
}
@Override
OutputStream openOutputStream(TransportProperties p) throws IOException {
String uri = p.get(PROP_URI);
if (isNullOrEmpty(uri)) throw new IllegalArgumentException();
return app.getContentResolver().openOutputStream(Uri.parse(uri));
}
}
@@ -0,0 +1,47 @@
package org.briarproject.bramble.plugin.file;
import android.app.Application;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static java.util.concurrent.TimeUnit.DAYS;
import static org.briarproject.bramble.api.plugin.file.RemovableDriveConstants.ID;
@Immutable
@NotNullByDefault
public class AndroidRemovableDrivePluginFactory implements
SimplexPluginFactory {
private static final long MAX_LATENCY = DAYS.toMillis(28);
private final Application app;
@Inject
AndroidRemovableDrivePluginFactory(Application app) {
this.app = app;
}
@Override
public TransportId getId() {
return ID;
}
@Override
public long getMaxLatency() {
return MAX_LATENCY;
}
@Nullable
@Override
public SimplexPlugin createPlugin(PluginCallback callback) {
return new AndroidRemovableDrivePlugin(app, callback, MAX_LATENCY);
}
}
@@ -29,6 +29,7 @@ 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;
@@ -48,6 +49,7 @@ 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 {
@@ -55,6 +57,13 @@ 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
@@ -67,7 +76,7 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
Application app, Application app,
Backoff backoff, Backoff backoff,
PluginCallback callback, PluginCallback callback,
int maxLatency, long maxLatency,
int maxIdleTime, int maxIdleTime,
int connectionTimeout) { int connectionTimeout) {
super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency, super(ioExecutor, wakefulIoExecutor, backoff, callback, maxLatency,
@@ -130,17 +139,14 @@ 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);
} }
List<InterfaceAddress> ifAddrs = getLocalInterfaceAddresses(); // If we're providing an access point, return its address
// If we're providing a normal access point, return its address for (NetworkInterface iface : getNetworkInterfaces()) {
for (InterfaceAddress ifAddr : ifAddrs) { if (AP_INTERFACE_NAME.matcher(iface.getName()).find()) {
if (isAndroidWifiApAddress(ifAddr)) { for (InterfaceAddress ifAddr : iface.getInterfaceAddresses()) {
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
@@ -148,33 +154,18 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
} }
/** /**
* Returns true if the given address belongs to a network provided by an * Returns true if the given address may belong to an interface providing
* Android access point (including the access point's own address). * a wifi access point (including wifi direct legacy mode access points).
* <p> * <p>
* The access point's address is usually 192.168.43.1, but at least one * This method may return true for wifi client interfaces as well, but
* device (Honor 8A) may use other addresses in the range 192.168.43.0/24. * we've already checked for a wifi client connection above.
*/ */
private boolean isAndroidWifiApAddress(InterfaceAddress ifAddr) { private boolean isPossibleWifiApInterface(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;
} }
/** /**
@@ -37,7 +37,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private final Application app; private final Application app;
@Inject @Inject
public AndroidLanTcpPluginFactory(@IoExecutor Executor ioExecutor, AndroidLanTcpPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor, @WakefulIoExecutor Executor wakefulIoExecutor,
EventBus eventBus, EventBus eventBus,
BackoffFactory backoffFactory, BackoffFactory backoffFactory,
@@ -55,7 +55,7 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public int getMaxLatency() { public long getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@@ -68,14 +68,16 @@ class AndroidTorPlugin extends TorPlugin {
TorRendezvousCrypto torRendezvousCrypto, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, PluginCallback callback,
String architecture, String architecture,
int 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); maxIdleTime, torDirectory, torSocksPort, torControlPort);
this.app = app; this.app = app;
wakeLock = wakeLockManager.createWakeLock("TorPlugin"); wakeLock = wakeLockManager.createWakeLock("TorPlugin");
String nativeLibDir = app.getApplicationInfo().nativeLibraryDir; String nativeLibDir = app.getApplicationInfo().nativeLibraryDir;
@@ -3,6 +3,7 @@ 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;
@@ -11,7 +12,9 @@ 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;
@@ -56,9 +59,12 @@ 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
public AndroidTorPluginFactory(@IoExecutor Executor ioExecutor, AndroidTorPluginFactory(@IoExecutor Executor ioExecutor,
@WakefulIoExecutor Executor wakefulIoExecutor, @WakefulIoExecutor Executor wakefulIoExecutor,
Application app, Application app,
NetworkManager networkManager, NetworkManager networkManager,
@@ -71,7 +77,10 @@ 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;
@@ -86,6 +95,9 @@ 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
@@ -94,7 +106,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public int getMaxLatency() { public long getMaxLatency() {
return MAX_LATENCY; return MAX_LATENCY;
} }
@@ -127,13 +139,15 @@ 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 = new TorRendezvousCryptoImpl(); TorRendezvousCrypto torRendezvousCrypto =
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); MAX_LATENCY, MAX_IDLE_TIME, torDirectory, torSocksPort,
torControlPort);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }
@@ -10,17 +10,20 @@ import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Scanner;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.lang.Runtime.getRuntime;
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.api.nullsafety.NullSafety.requireNonNull;
@@ -118,4 +121,17 @@ public class AndroidUtils {
public static String[] getSupportedImageContentTypes() { public static String[] getSupportedImageContentTypes() {
return new String[] {"image/jpeg", "image/png", "image/gif"}; return new String[] {"image/jpeg", "image/png", "image/gif"};
} }
@Nullable
public static String getSystemProperty(String propName) {
try {
Process p = getRuntime().exec("getprop " + propName);
Scanner s = new Scanner(p.getInputStream());
String line = s.nextLine();
s.close();
return line;
} catch (SecurityException | IOException e) {
return null;
}
}
} }
@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations; import org.jmock.Expectations;
import org.jmock.lib.legacy.ClassImposteriser; import org.jmock.imposters.ByteBuddyClassImposteriser;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -44,7 +44,7 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
private AndroidAccountManager accountManager; private AndroidAccountManager accountManager;
public AndroidAccountManagerTest() { public AndroidAccountManagerTest() {
context.setImposteriser(ClassImposteriser.INSTANCE); context.setImposteriser(ByteBuddyClassImposteriser.INSTANCE);
app = context.mock(Application.class); app = context.mock(Application.class);
applicationInfo = new ApplicationInfo(); applicationInfo = new ApplicationInfo();
applicationInfo.dataDir = testDir.getAbsolutePath(); applicationInfo.dataDir = testDir.getAbsolutePath();
+119 -68
View File
@@ -1,110 +1,161 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861', 'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4', 'com.android.tools.analytics-library:protos:30.0.3:protos-30.0.3.jar:f62b89dcd9de719c6a7b7e15fb1dd20e45b57222e675cf633607bd0ed6bca7e7',
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366', 'com.android.tools.analytics-library:shared:30.0.3:shared-30.0.3.jar:05aa9ba3cc890354108521fdf99802565aae5dd6ca44a6ac8bb8d594d1c1cd15',
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9', 'com.android.tools.analytics-library:tracker:30.0.3:tracker-30.0.3.jar:5d0ef35bf6733e96210b5085a2a202152921bf834d345959dce1ca3369b528df',
'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:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72', 'com.android.tools.build:apksig:7.0.3:apksig-7.0.3.jar:012337a2803c9a30dfc41dcbc6450686ee9e5f582549f7f126479f743a343ec9',
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127', 'com.android.tools.build:apkzlib:7.0.3:apkzlib-7.0.3.jar:b31e53174c92db83c5cc6e7dac6734ea4e907a72e452c2bf1818dfd082c59397',
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd', 'com.android.tools.build:builder-model:7.0.3:builder-model-7.0.3.jar:483f99d7494a5bed027e1e8d29111384cf535d4842f0be5a79805bd44bb68d4e',
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a', 'com.android.tools.build:builder-test-api:7.0.3:builder-test-api-7.0.3.jar:f6de4bc2cef545e8367bf82d7c733829c7be3b0b3b8b09fd8c58f2150e59ab46',
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d', 'com.android.tools.build:builder:7.0.3:builder-7.0.3.jar:c6952da0094b094c2ba0fe84c675622097c5d9b9f9beb53485b860320540cf1d',
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358', 'com.android.tools.build:manifest-merger:30.0.3:manifest-merger-30.0.3.jar:72b346ba6318b4b6260e6e49df4bea5da2e12329ab6c2beb2269c49a9f51f178',
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b', 'com.android.tools.ddms:ddmlib:30.0.3:ddmlib-30.0.3.jar:7a914a68ab93393657297234e2f37b22410ae9a433cba692ce8c727c9607e3bb',
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a', 'com.android.tools.external.com-intellij:intellij-core:30.0.3:intellij-core-30.0.3.jar:1ebe858d3f58eeaa8c06507f8ac0f1c7051e6c61f35a70f3c3967d5734d3abc5',
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6', 'com.android.tools.external.com-intellij:kotlin-compiler:30.0.3:kotlin-compiler-30.0.3.jar:ed00e441f427cb4e0d418287b9da30b12b7f735f9af32e6b5d3dc960b6a742fc',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8', 'com.android.tools.external.org-jetbrains:uast:30.0.3:uast-30.0.3.jar:a77801bee6ff509910e459525c9c34d7f04b066ade123547f16f1917548eadea',
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714', 'com.android.tools.layoutlib:layoutlib-api:30.0.3:layoutlib-api-30.0.3.jar:4caa87e9ca2e11315f650d576cd59fec1793373bc3fca3f6d53c029e7534e7c4',
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c', 'com.android.tools.lint:lint-api:30.0.3:lint-api-30.0.3.jar:bcecbd2f752a6560096a9029a47d1de6bd788a51bab505c5ebfba6a18524b983',
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b', 'com.android.tools.lint:lint-checks:30.0.3:lint-checks-30.0.3.jar:25a7cd42dc3ad502337f131fb8b7e873c53301db0a67b1c64dd4ae7a8eb66cec',
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61', 'com.android.tools.lint:lint-gradle:30.0.3:lint-gradle-30.0.3.jar:94544d6147a809bf2fd3440e51f28a4e42e547d74aab53eefd74938cdad42c26',
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d', 'com.android.tools.lint:lint-model:30.0.3:lint-model-30.0.3.jar:0b940a7f575c2ff5cbd038260f41dde686a93c672213881ead3ce8af3513b396',
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756', 'com.android.tools.lint:lint:30.0.3:lint-30.0.3.jar:ee4f11001e0c7e3b776e0d67399ad354b19b0f168822ec2b7db47c0910ed227d',
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d', 'com.android.tools:annotations:30.0.3:annotations-30.0.3.jar:5c1944982fda8555855c4f5422fabf0dc8e2306e1f5460e9ad82dae71316bc31',
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81', 'com.android.tools:common:30.0.3:common-30.0.3.jar:8751efaaf2c2ddd1f0a37526c794347def6a3057ca9fc510307c13a6cf0d036f',
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1', 'com.android.tools:dvlib:30.0.3:dvlib-30.0.3.jar:5affafcec390041e5afd64cb924153f5e474db47ee8ccc2f555b495083141233',
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c', 'com.android.tools:repository:30.0.3:repository-30.0.3.jar:0a40c6f16c506903ce2c609affd8228aceda73a69d93dfa42d4f02b8491449f6',
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f', 'com.android.tools:sdk-common:30.0.3:sdk-common-30.0.3.jar:b45570a380360236ffee0f6bb593d66b673bad3834dfe0d6c9871fa7188ee0eb',
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d', 'com.android.tools:sdklib:30.0.3:sdklib-30.0.3.jar:7088f20a414fab170a21e457825e14ebe099f753558e02c8acc12c67eb412162',
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c', 'com.android:signflinger:7.0.3:signflinger-7.0.3.jar:903a4536db3e96b4e1e1dc1e400eb0b91bf7866d9b39cd7ec94d75dde158f152',
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250', 'com.android:zipflinger:7.0.3:zipflinger-7.0.3.jar:fd209c960a3eff7a339e6fcba07d5e9ef4604d1633c69ab2df987460d9804140',
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60', 'com.beust:jcommander:1.78:jcommander-1.78.jar:7891debb84b5f83e9bd57593ebece3399abbe0fd938cf306b3534c57913b9615',
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446', 'com.github.javaparser:javaparser-core:3.17.0:javaparser-core-3.17.0.jar:23f5c982e1c7771423d37d52c774e8d2e80fd7ea7305ebe448797a96f67e6fca',
'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.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81', 'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f', 'com.google.dagger:dagger-compiler:2.33:dagger-compiler-2.33.jar:aa8a0d8370c578fd6999802d0d90b9829377a46d2c1141e11b8f737970e7155e',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a', 'com.google.dagger:dagger-producers:2.33:dagger-producers-2.33.jar:5897f0b6eef799c2adfe3ccacc58c0fb374d58acb063c3ebe5366c38a8bce5c8',
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718', 'com.google.dagger:dagger-spi:2.33:dagger-spi-2.33.jar:e2dcab2221b8afb9556ef0a1c83b0bd5f42552e254322a257330f754cdbbb9d4',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64', '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.2:error_prone_annotations-2.3.2.jar:357cd6cfb067c969226c442451502aee13800a24e950fdfde77bcdb4565a668d', 'com.google.errorprone:error_prone_annotations:2.3.4:error_prone_annotations-2.3.4.jar:baf7d6ea97ce606c53e11b6854ba5f2ce7ef5c24dddf0afa18d1260bd25b002c',
'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:28.1-jre:guava-28.1-jre.jar:30beb8b8527bd07c6e747e77f1a92122c2f29d57ce347461a4a55eb26e382da4', 'com.google.guava:guava:30.1-jre:guava-30.1-jre.jar:e6dd072f9d3fe02a4600688380bd422bdac184caf6fe2418cfdd0934f09432aa',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99', 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6', 'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b', 'com.google.j2objc:j2objc-annotations:1.3:j2objc-annotations-1.3.jar:21af30c92267bd6122c0e0b4d20cccb6641a37eaf956c6540ec471d584e64a7b',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd', 'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9', 'com.google.protobuf:protobuf-java:3.10.0:protobuf-java-3.10.0.jar:161d7d61a8cb3970891c299578702fd079646e032329d6c2cabf998d191437c9',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439', 'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90', 'com.squareup:javapoet:1.13.0:javapoet-1.13.0.jar:4c7517e848a71b36d069d12bb3bf46a70fd4cda3105d822b0ed2e19c00b69291',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0', 'com.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.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf', 'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec', 'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
'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',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c', 'info.picocli:picocli:4.5.2:picocli-4.5.2.jar:b4395e9a67932616efd2245d984bf5fcd453c2c5049558c3ce959ac2af4d3fac',
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393', 'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
'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',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06', 'jline:jline:2.14.6:jline-2.14.6.jar:97d1acaac82409be42e622d7a54d3ae9d08517e8aefdea3d2ba9791150c2f02d',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd', 'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5', 'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2', 'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d', 'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8', '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.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca', 'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', 'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82', 'org.briarproject:obfs4proxy-android:0.0.12-dev-40245c4a:obfs4proxy-android-0.0.12-dev-40245c4a.zip:8ab05a8f8391be2cb5ab2b665c281a06d9e3a756bd0f95a40a36ca927866ea82',
'org.briarproject:tor-android:0.3.5.13:tor-android-0.3.5.13.zip:e0978db136731dae07774b722970cdae1e462fb5adc82845dd80a7e2d87f356c', 'org.briarproject:tor-android:0.3.5.17:tor-android-0.3.5.17.jar:1888afc10a26b93d00a010ea27bf0b1b162a6d524688b08b98d70d14dc363b54',
'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:2.8.1:checker-qual-2.8.1.jar:9103499008bcecd4e948da29b17864abb64304e15706444ae209d17ebe0575df', 'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4',
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0', 'org.codehaus.groovy:groovy-ant:3.0.7:groovy-ant-3.0.7.jar:6ed2ba82813d128f7050c24142e87b3dc2ad8b504786280eb03e81f0cf6a5793',
'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.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d', 'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f', 'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c', 'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40', 'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4', 'org.jacoco:org.jacoco.agent:0.8.3:org.jacoco.agent-0.8.3.jar:522deb254ee16a04cc8341cc8f335f5cb7232982994d961b9cf3a0454709209f',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95', 'org.jacoco:org.jacoco.ant:0.8.3:org.jacoco.ant-0.8.3.jar:735844e1ae15f9b875b42a27ac5cb61cc26e106d9e839e5d1c6756709b424ce0',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b', 'org.jacoco:org.jacoco.core:0.8.3:org.jacoco.core-0.8.3.jar:0818437bc060a0c7cc798148f22b713702aae2771aba104444407697d578f1ea',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7', '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.32:kotlin-stdlib-common-1.4.32.jar:e1ff6f55ee9e7591dcc633f7757bac25a7edb1cc7f738b37ec652f10f66a4145',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.32:kotlin-stdlib-jdk7-1.4.32.jar:5f801e75ca27d8791c14b07943c608da27620d910a8093022af57f543d5d98b6',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.32:kotlin-stdlib-jdk8-1.4.32.jar:adc43e54757b106e0cd7b3b7aa257dff471b61efdabe067fc02b2f57e2396262',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.20:kotlin-stdlib-1.4.20.jar:b8ab1da5cdc89cb084d41e1f28f20a42bd431538642a5741c52bbfae3fa3e656',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.32:kotlin-stdlib-1.4.32.jar:13e9fd3e69dc7230ce0fc873a92a4e5d521d179bcf1bef75a6705baac3bfecba',
'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.1.0:kotlinx-metadata-jvm-0.1.0.jar:9753bb39efef35957c5c15df9a3cb769aabf2cdfa74b47afcb7760e5146be3b5',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c', 'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b', 'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760', 'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16', 'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77', 'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80', 'org.junit.jupiter:junit-jupiter-api:5.7.0:junit-jupiter-api-5.7.0.jar:b03f78e0daeed2d77a0af9bcd662b4cdb9693f7ee72e01a539b508b84c63d182',
'org.junit.jupiter:junit-jupiter-engine:5.7.0:junit-jupiter-engine-5.7.0.jar:dfa26af94644ac2612dde6625852fcb550a0d21caa243257de54cba738ba87af',
'org.junit.platform:junit-platform-commons:1.7.0:junit-platform-commons-1.7.0.jar:5330ee87cc7586e6e25175a34e9251624ff12ff525269d3415d0b4ca519b6fea',
'org.junit.platform:junit-platform-engine:1.7.0:junit-platform-engine-1.7.0.jar:75f21a20dc594afdc875736725b408cec6d0344874d29f34b2dd3075500236f2',
'org.junit.platform:junit-platform-launcher:1.7.0:junit-platform-launcher-1.7.0.jar:fbdc748fde4c4279fe1d3c607447cb3b7ccd45d7338fc574f8a894ddf2d16818',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.opentest4j:opentest4j:1.2.0:opentest4j-1.2.0.jar:58812de60898d976fb81ef3b62da05c6604c18fd4a249f5044282479fc286af2',
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474', 'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d', 'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c', 'org.ow2.asm:asm-tree:7.0:asm-tree-7.0.jar:cfd7a0874f9de36a999c127feeadfbfe6e04d4a71ee954d7af3d853f0be48a6c',
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145', 'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf', 'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.testng:testng:7.3.0:testng-7.3.0.jar:63727488f9717d57f0d0a0fee5a1fc10a2be9cfcff2ec3a7187656d663c0774e',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
] ]
} }
+4 -5
View File
@@ -7,13 +7,12 @@ apply plugin: 'witness'
apply from: 'witness.gradle' apply from: 'witness.gradle'
dependencies { dependencies {
implementation "com.google.dagger:dagger:2.24" implementation "com.google.dagger:dagger:$dagger_version"
implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation 'junit:junit:4.12' testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock:2.8.2" testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-junit4:2.8.2" testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-legacy:2.8.2"
signature 'org.codehaus.mojo.signature:java16:1.1@signature' signature 'org.codehaus.mojo.signature:java16:1.1@signature'
} }
@@ -0,0 +1,9 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Consumer<T> {
void accept(T t);
}
@@ -9,4 +9,13 @@ public interface FeatureFlags {
boolean shouldEnableProfilePictures(); boolean shouldEnableProfilePictures();
boolean shouldEnableDisappearingMessages();
boolean shouldEnableIntroductionsInCore();
boolean shouldEnablePrivateGroupsInCore();
boolean shouldEnableForumsInCore();
boolean shouldEnableBlogsInCore();
} }
@@ -0,0 +1,35 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.lang.ref.WeakReference;
import javax.annotation.concurrent.GuardedBy;
import javax.inject.Provider;
/**
* A {@link Provider} that keeps a {@link WeakReference} to the last provided
* instance and provides the same instance again until the instance is garbage
* collected.
*/
@NotNullByDefault
public abstract class WeakSingletonProvider<T> implements Provider<T> {
private final Object lock = new Object();
@GuardedBy("lock")
private WeakReference<T> ref = new WeakReference<>(null);
@Override
public T get() {
synchronized (lock) {
T instance = ref.get();
if (instance == null) {
instance = createInstance();
ref = new WeakReference<>(instance);
}
return instance;
}
}
public abstract T createInstance();
}
@@ -0,0 +1,29 @@
package org.briarproject.bramble.api.cleanup;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import java.util.Collection;
/**
* An interface for registering a hook with the {@link CleanupManager}
* that will be called when a message's cleanup deadline is reached.
*/
@NotNullByDefault
public interface CleanupHook {
/**
* Called when the cleanup deadlines of one or more messages are reached.
* <p>
* The callee is not required to delete the messages, but the hook won't be
* called again for these messages unless another cleanup timer is set (see
* {@link DatabaseComponent#setCleanupTimerDuration(Transaction, MessageId, long)}
* and {@link DatabaseComponent#startCleanupTimer(Transaction, MessageId)}).
*/
void deleteMessages(Transaction txn, GroupId g,
Collection<MessageId> messageIds) throws DbException;
}
@@ -0,0 +1,42 @@
package org.briarproject.bramble.api.cleanup;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.MessageId;
/**
* The CleanupManager is responsible for tracking the cleanup deadlines of
* messages and passing them to their respective
* {@link CleanupHook CleanupHooks} when the deadlines are reached.
* <p>
* The CleanupManager responds to
* {@link CleanupTimerStartedEvent CleanupTimerStartedEvents} broadcast by the
* {@link DatabaseComponent}.
* <p>
* See {@link DatabaseComponent#setCleanupTimerDuration(Transaction, MessageId, long)},
* {@link DatabaseComponent#startCleanupTimer(Transaction, MessageId)},
* {@link DatabaseComponent#stopCleanupTimer(Transaction, MessageId)}.
*/
@NotNullByDefault
public interface CleanupManager {
/**
* When scheduling a cleanup task we overshoot the deadline by this many
* milliseconds to reduce the number of tasks that need to be scheduled
* when messages have cleanup deadlines that are close together.
*/
long BATCH_DELAY_MS = 1000;
/**
* Registers a hook to be called when messages are due for cleanup.
* This method should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerCleanupHook(ClientId c, int majorVersion,
CleanupHook hook);
}
@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.cleanup.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a message's cleanup timer is started.
*/
@Immutable
@NotNullByDefault
public class CleanupTimerStartedEvent extends Event {
private final MessageId messageId;
private final long cleanupDeadline;
public CleanupTimerStartedEvent(MessageId messageId,
long cleanupDeadline) {
this.messageId = messageId;
this.cleanupDeadline = cleanupDeadline;
}
public MessageId getMessageId() {
return messageId;
}
public long getCleanupDeadline() {
return cleanupDeadline;
}
}
@@ -32,28 +32,31 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
/** /**
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* <p>
* If an unexpected exception occurs while handling data that is assumed
* to be valid (e.g. locally created metadata), it may be sensible to
* rethrow the unexpected exception as a DbException so that delivery is
* attempted again at next startup. This will allow delivery to succeed if
* the unexpected exception was caused by a bug that has subsequently been
* fixed.
* *
* @param txn A read-write transaction * @param txn A read-write transaction
* @return Whether or not this message should be shared * @throws DbException if a database error occurs while delivering the
* @throws DbException Should only be used for real database errors. * message. Delivery will be attempted again at next startup. Throwing
* If this is thrown, delivery will be attempted again at next startup, * this exception has the same effect as returning
* whereas if a FormatException is thrown, the message will be permanently * {@link DeliveryAction#DEFER}.
* invalidated. * @throws FormatException if the message is invalid in the context of its
* @throws FormatException Use this for any non-database error * dependencies. The message and any dependents will be marked as invalid
* that occurs while handling remotely created data. * and deleted along with their metadata. Throwing this exception has the
* This includes errors that occur while handling locally created data * same effect as returning {@link DeliveryAction#REJECT}.
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Never rethrow DbException as FormatException!
*/ */
protected abstract boolean incomingMessage(Transaction txn, Message m, protected abstract DeliveryAction incomingMessage(Transaction txn,
BdfList body, BdfDictionary meta) throws DbException, Message m, BdfList body, BdfDictionary meta)
FormatException; throws DbException, FormatException;
@Override @Override
public boolean incomingMessage(Transaction txn, Message m, Metadata meta) public DeliveryAction incomingMessage(Transaction txn, Message m,
throws DbException, InvalidMessageException { Metadata meta) throws DbException, InvalidMessageException {
try { try {
BdfList body = clientHelper.toList(m); BdfList body = clientHelper.toList(m);
BdfDictionary metaDictionary = metadataParser.parse(meta); BdfDictionary metaDictionary = metadataParser.parse(meta);
@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.client; package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
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.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
@@ -16,6 +17,7 @@ import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.Map; import java.util.Map;
@NotNullByDefault @NotNullByDefault
@@ -50,9 +52,11 @@ public interface ClientHelper {
BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g) BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g)
throws DbException, FormatException; throws DbException, FormatException;
Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
BdfDictionary query) throws DbException, FormatException;
BdfDictionary getMessageMetadataAsDictionary(MessageId m) BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException, throws DbException, FormatException;
FormatException;
BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m) BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m)
throws DbException, FormatException; throws DbException, FormatException;
@@ -119,4 +123,17 @@ public interface ClientHelper {
Map<TransportId, TransportProperties> parseAndValidateTransportPropertiesMap( Map<TransportId, TransportProperties> parseAndValidateTransportPropertiesMap(
BdfDictionary properties) throws FormatException; BdfDictionary properties) throws FormatException;
/**
* Retrieves the contact ID from the group metadata of the given contact
* group.
*/
ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException;
/**
* Stores the given contact ID in the group metadata of the given contact
* group.
*/
void setContactId(Transaction txn, GroupId contactGroupId, ContactId c)
throws DbException;
} }
@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.client;
public interface ContactGroupConstants {
/**
* Group metadata key for associating a contact ID with a contact group.
*/
String GROUP_KEY_CONTACT_ID = "contactId";
}
@@ -107,6 +107,32 @@ 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
* alias, adds it to the database and returns it.
*
* @param link The handshake link received from the pending contact
* @param alias The alias the user has given this pending contact
* @throws UnsupportedVersionException If the link uses a format version
* that is not supported
* @throws FormatException If the link is invalid
* @throws GeneralSecurityException If the pending contact's handshake
* public key is invalid
* @throws ContactExistsException If a contact with the same handshake
* public key already exists
* @throws PendingContactExistsException If a pending contact with the same
* handshake public key already exists
*/
PendingContact addPendingContact(Transaction txn, String link, String alias)
throws DbException, FormatException, GeneralSecurityException,
ContactExistsException, PendingContactExistsException;
/** /**
* 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.
@@ -140,6 +166,13 @@ public interface ContactManager {
Collection<Pair<PendingContact, PendingContactState>> getPendingContacts() Collection<Pair<PendingContact, PendingContactState>> getPendingContacts()
throws DbException; throws DbException;
/**
* Returns a list of {@link PendingContact PendingContacts} and their
* {@link PendingContactState states}.
*/
Collection<Pair<PendingContact, PendingContactState>> getPendingContacts(Transaction txn)
throws DbException;
/** /**
* Removes a {@link PendingContact}. * Removes a {@link PendingContact}.
*/ */
@@ -0,0 +1,35 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when the alias for a contact changed.
*/
@Immutable
@NotNullByDefault
public class ContactAliasChangedEvent extends Event {
private final ContactId contactId;
@Nullable
private final String alias;
public ContactAliasChangedEvent(ContactId contactId,
@Nullable String alias) {
this.contactId = contactId;
this.alias = alias;
}
public ContactId getContactId() {
return contactId;
}
@Nullable
public String getAlias() {
return alias;
}
}
@@ -170,4 +170,11 @@ 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);
} }
@@ -1,23 +1,19 @@
package org.briarproject.bramble.api.crypto; package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.Bytes;
/** /**
* A secret key used for encryption and/or authentication. * A secret key used for encryption and/or authentication.
*/ */
public class SecretKey { public class SecretKey extends Bytes {
/** /**
* The length of a secret key in bytes. * The length of a secret key in bytes.
*/ */
public static final int LENGTH = 32; public static final int LENGTH = 32;
private final byte[] key;
public SecretKey(byte[] key) { public SecretKey(byte[] key) {
super(key);
if (key.length != LENGTH) throw new IllegalArgumentException(); if (key.length != LENGTH) throw new IllegalArgumentException();
this.key = key;
}
public byte[] getBytes() {
return key;
} }
} }
@@ -41,6 +41,18 @@ import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface DatabaseComponent extends TransactionManager { public interface DatabaseComponent extends TransactionManager {
/**
* Return value for {@link #getNextCleanupDeadline(Transaction)} if
* no messages are scheduled to be deleted.
*/
long NO_CLEANUP_DEADLINE = -1;
/**
* Return value for {@link #startCleanupTimer(Transaction, MessageId)}
* if the cleanup timer was not started.
*/
long TIMER_NOT_STARTED = -1;
/** /**
* Opens the database and returns true if the database already existed. * Opens the database and returns true if the database already existed.
* *
@@ -89,7 +101,7 @@ public interface DatabaseComponent extends TransactionManager {
/** /**
* Stores a transport. * Stores a transport.
*/ */
void addTransport(Transaction txn, TransportId t, int maxLatency) void addTransport(Transaction txn, TransportId t, long maxLatency)
throws DbException; throws DbException;
/** /**
@@ -106,6 +118,18 @@ public interface DatabaseComponent extends TransactionManager {
KeySetId addTransportKeys(Transaction txn, PendingContactId p, KeySetId addTransportKeys(Transaction txn, PendingContactId p,
TransportKeys k) throws DbException; TransportKeys k) throws DbException;
/**
* Returns true if there are any acks or messages to send to the given
* contact over a transport with the given maximum latency.
* <p/>
* Read-only.
*
* @param eager True if messages that are not yet due for retransmission
* should be included
*/
boolean containsAnythingToSend(Transaction txn, ContactId c,
long maxLatency, boolean eager) throws DbException;
/** /**
* Returns true if the database contains the given contact for the given * Returns true if the database contains the given contact for the given
* local pseudonym. * local pseudonym.
@@ -138,6 +162,16 @@ public interface DatabaseComponent extends TransactionManager {
boolean containsPendingContact(Transaction txn, PendingContactId p) boolean containsPendingContact(Transaction txn, PendingContactId p)
throws DbException; throws DbException;
/**
* Returns true if the database contains keys for communicating with the
* given contact over the given transport. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
boolean containsTransportKeys(Transaction txn, ContactId c, TransportId t)
throws DbException;
/** /**
* Deletes the message with the given ID. Unlike * Deletes the message with the given ID. Unlike
* {@link #removeMessage(Transaction, MessageId)}, the message ID, * {@link #removeMessage(Transaction, MessageId)}, the message ID,
@@ -166,7 +200,19 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
@Nullable @Nullable
Collection<Message> generateBatch(Transaction txn, ContactId c, Collection<Message> generateBatch(Transaction txn, ContactId c,
int maxLength, int maxLatency) throws DbException; int maxLength, long maxLatency) throws DbException;
/**
* Returns a batch of messages for the given contact containing the
* messages with the given IDs, for transmission over a transport with
* the given maximum latency.
* <p/>
* If any of the given messages are not in the database or are not visible
* to the contact, they are omitted from the batch without throwing an
* exception.
*/
Collection<Message> generateBatch(Transaction txn, ContactId c,
Collection<MessageId> ids, long maxLatency) throws DbException;
/** /**
* Returns an offer for the given contact for transmission over a * Returns an offer for the given contact for transmission over a
@@ -175,7 +221,7 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
@Nullable @Nullable
Offer generateOffer(Transaction txn, ContactId c, int maxMessages, Offer generateOffer(Transaction txn, ContactId c, int maxMessages,
int maxLatency) throws DbException; long maxLatency) throws DbException;
/** /**
* Returns a request for the given contact, or null if there are no * Returns a request for the given contact, or null if there are no
@@ -194,7 +240,7 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
@Nullable @Nullable
Collection<Message> generateRequestedBatch(Transaction txn, ContactId c, Collection<Message> generateRequestedBatch(Transaction txn, ContactId c,
int maxLength, int maxLatency) throws DbException; int maxLength, long maxLatency) throws DbException;
/** /**
* Returns the contact with the given ID. * Returns the contact with the given ID.
@@ -288,6 +334,16 @@ public interface DatabaseComponent extends TransactionManager {
Collection<MessageId> getMessageIds(Transaction txn, GroupId g) Collection<MessageId> getMessageIds(Transaction txn, GroupId g)
throws DbException; throws DbException;
/**
* Returns the IDs of any delivered messages in the given group with
* metadata that matches all entries in the given query. If the query is
* empty, the IDs of all delivered messages are returned.
* <p/>
* Read-only.
*/
Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
Metadata query) throws DbException;
/** /**
* Returns the IDs of any messages that need to be validated. * Returns the IDs of any messages that need to be validated.
* <p/> * <p/>
@@ -314,6 +370,15 @@ public interface DatabaseComponent extends TransactionManager {
Collection<MessageId> getMessagesToShare(Transaction txn) Collection<MessageId> getMessagesToShare(Transaction txn)
throws DbException; throws DbException;
/**
* Returns the IDs of any messages of any messages that are due for
* deletion, along with their group IDs.
* <p/>
* Read-only.
*/
Map<GroupId, Collection<MessageId>> getMessagesToDelete(Transaction txn)
throws DbException;
/** /**
* Returns the metadata for all delivered messages in the given group. * Returns the metadata for all delivered messages in the given group.
* <p/> * <p/>
@@ -395,6 +460,44 @@ public interface DatabaseComponent extends TransactionManager {
MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m) MessageStatus getMessageStatus(Transaction txn, ContactId c, MessageId m)
throws DbException; throws DbException;
/**
* Returns the IDs of all messages that are eligible to be sent to the
* given contact, together with their raw lengths. This may include
* messages that have already been sent and are not yet due for
* retransmission.
* <p/>
* Read-only.
*/
Map<MessageId, Integer> getUnackedMessagesToSend(Transaction txn,
ContactId c) throws DbException;
/**
* 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
* eligible to be sent to the given contact. This may include messages
* that have already been sent and are not yet due for retransmission.
* <p/>
* Read-only.
*/
long getUnackedMessageBytesToSend(Transaction txn, ContactId c)
throws DbException;
/**
* Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be deleted, or {@link #NO_CLEANUP_DEADLINE}
* if no messages are scheduled to be deleted.
* <p/>
* Read-only.
*/
long getNextCleanupDeadline(Transaction txn) throws DbException;
/* /*
* Returns the next time (in milliseconds since the Unix epoch) when a * Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be sent to the given contact. The returned value may * message is due to be sent to the given contact. The returned value may
@@ -443,6 +546,16 @@ public interface DatabaseComponent extends TransactionManager {
Collection<TransportKeySet> getTransportKeys(Transaction txn, TransportId t) Collection<TransportKeySet> getTransportKeys(Transaction txn, TransportId t)
throws DbException; throws DbException;
/**
* Returns the contact IDs and transport IDs for which the DB contains
* at least one set of transport keys. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
Map<ContactId, Collection<TransportId>> getTransportsWithKeys(
Transaction txn) throws DbException;
/** /**
* Increments the outgoing stream counter for the given transport keys. * Increments the outgoing stream counter for the given transport keys.
*/ */
@@ -535,6 +648,13 @@ public interface DatabaseComponent extends TransactionManager {
void removeTransportKeys(Transaction txn, TransportId t, KeySetId k) void removeTransportKeys(Transaction txn, TransportId t, KeySetId k)
throws DbException; throws DbException;
/**
* Sets the cleanup timer duration for the given message. This does not
* start the message's cleanup timer.
*/
void setCleanupTimerDuration(Transaction txn, MessageId m, long duration)
throws DbException;
/** /**
* Marks the given contact as verified. * Marks the given contact as verified.
*/ */
@@ -557,6 +677,12 @@ public interface DatabaseComponent extends TransactionManager {
*/ */
void setMessagePermanent(Transaction txn, MessageId m) throws DbException; void setMessagePermanent(Transaction txn, MessageId m) throws DbException;
/**
* Marks the given message as not shared. This method is only meant for
* testing.
*/
void setMessageNotShared(Transaction txn, MessageId m) throws DbException;
/** /**
* Marks the given message as shared. * Marks the given message as shared.
*/ */
@@ -599,6 +725,22 @@ public interface DatabaseComponent extends TransactionManager {
void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k) void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k)
throws DbException; throws DbException;
/**
* Starts the cleanup timer for the given message, if a timer duration
* has been set and the timer has not already been started.
*
* @return The cleanup deadline, or {@link #TIMER_NOT_STARTED} if no
* timer duration has been set for this message or its timer has already
* been started.
*/
long startCleanupTimer(Transaction txn, MessageId m) throws DbException;
/**
* Stops the cleanup timer for the given message, if the timer has been
* started.
*/
void stopCleanupTimer(Transaction txn, MessageId m) throws DbException;
/** /**
* Stores the given transport keys, deleting any keys they have replaced. * Stores the given transport keys, deleting any keys they have replaced.
*/ */
@@ -57,6 +57,7 @@ public class Author implements Nameable {
/** /**
* Returns the author's name. * Returns the author's name.
*/ */
@Override
public String getName() { public String getName() {
return name; return name;
} }
@@ -3,7 +3,7 @@ package org.briarproject.bramble.api.keyagreement.event;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
/** /**
* An event that is broadcast when a BQP protocol completes. * An event that is broadcast when a BQP protocol begins.
*/ */
public class KeyAgreementStartedEvent extends Event { public class KeyAgreementStartedEvent extends Event {
} }
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.Wakeful; import org.briarproject.bramble.api.system.Wakeful;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -22,6 +23,7 @@ public interface LifecycleManager {
*/ */
enum StartResult { enum StartResult {
ALREADY_RUNNING, ALREADY_RUNNING,
CLOCK_ERROR,
DB_ERROR, DB_ERROR,
DATA_TOO_OLD_ERROR, DATA_TOO_OLD_ERROR,
DATA_TOO_NEW_ERROR, DATA_TOO_NEW_ERROR,
@@ -65,6 +67,10 @@ public interface LifecycleManager {
/** /**
* Opens the {@link DatabaseComponent} using the given key and starts any * Opens the {@link DatabaseComponent} using the given key and starts any
* registered {@link Service Services}. * registered {@link Service Services}.
*
* @return {@link StartResult#CLOCK_ERROR} if the system clock is earlier
* than {@link Clock#MIN_REASONABLE_TIME_MS} or later than
* {@link Clock#MAX_REASONABLE_TIME_MS}.
*/ */
@Wakeful @Wakeful
StartResult startServices(SecretKey dbKey); StartResult startServices(SecretKey dbKey);
@@ -0,0 +1,32 @@
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;
}
}
@@ -0,0 +1,33 @@
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;
}
@@ -0,0 +1,59 @@
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;
}
}
@@ -61,7 +61,7 @@ public interface Plugin {
/** /**
* Returns the transport's maximum latency in milliseconds. * Returns the transport's maximum latency in milliseconds.
*/ */
int getMaxLatency(); long getMaxLatency();
/** /**
* Returns the transport's maximum idle time in milliseconds. * Returns the transport's maximum idle time in milliseconds.
@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface PluginFactory<P extends Plugin> {
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/**
* Returns the maximum latency of the transport in milliseconds.
*/
long getMaxLatency();
/**
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
P createPlugin(PluginCallback callback);
}
@@ -1,17 +1,14 @@
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 SOCKS_PORT = 59050; int DEFAULT_SOCKS_PORT = 59050;
int CONTROL_PORT = 59051; int DEFAULT_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
@@ -21,14 +18,7 @@ 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;
@@ -0,0 +1,20 @@
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 {
}
@@ -0,0 +1,20 @@
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 {
}
@@ -15,13 +15,18 @@ public interface TransportConnectionWriter {
/** /**
* Returns the maximum latency of the transport in milliseconds. * Returns the maximum latency of the transport in milliseconds.
*/ */
int getMaxLatency(); long getMaxLatency();
/** /**
* Returns the maximum idle time of the transport in milliseconds. * Returns the maximum idle time of the transport in milliseconds.
*/ */
int getMaxIdleTime(); int getMaxIdleTime();
/**
* Returns true if the transport is lossy and cheap.
*/
boolean isLossyAndCheap();
/** /**
* Returns an output stream for writing to the transport connection. * Returns an output stream for writing to the transport connection.
*/ */
@@ -70,7 +70,7 @@ public abstract class AbstractDuplexTransportConnection
private class Writer implements TransportConnectionWriter { private class Writer implements TransportConnectionWriter {
@Override @Override
public int getMaxLatency() { public long getMaxLatency() {
return plugin.getMaxLatency(); return plugin.getMaxLatency();
} }
@@ -79,6 +79,11 @@ public abstract class AbstractDuplexTransportConnection
return plugin.getMaxIdleTime(); return plugin.getMaxIdleTime();
} }
@Override
public boolean isLossyAndCheap() {
return false;
}
@Override @Override
public OutputStream getOutputStream() throws IOException { public OutputStream getOutputStream() throws IOException {
return AbstractDuplexTransportConnection.this.getOutputStream(); return AbstractDuplexTransportConnection.this.getOutputStream();
@@ -1,30 +1,11 @@
package org.briarproject.bramble.api.plugin.duplex; package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginFactory;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
/** /**
* Factory for creating a plugin for a duplex transport. * Factory for creating a plugin for a duplex transport.
*/ */
@NotNullByDefault @NotNullByDefault
public interface DuplexPluginFactory { public interface DuplexPluginFactory extends PluginFactory<DuplexPlugin> {
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/**
* Returns the maximum latency of the transport in milliseconds.
*/
int getMaxLatency();
/**
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
DuplexPlugin createPlugin(PluginCallback callback);
} }
@@ -1,4 +1,4 @@
package org.briarproject.bramble.api.plugin; package org.briarproject.bramble.api.plugin.file;
public interface FileConstants { public interface FileConstants {
@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.plugin.file;
import org.briarproject.bramble.api.plugin.TransportId;
public interface RemovableDriveConstants {
TransportId ID = new TransportId("org.briarproject.bramble.drive");
String PROP_PATH = "path";
String PROP_URI = "uri";
String PROP_SUPPORTED = "supported";
}
@@ -0,0 +1,52 @@
package org.briarproject.bramble.api.plugin.file;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties;
import javax.annotation.Nullable;
@NotNullByDefault
public interface RemovableDriveManager {
/**
* Returns the currently running reader task, or null if no reader task
* is running.
*/
@Nullable
RemovableDriveTask getCurrentReaderTask();
/**
* Returns the currently running writer task, or null if no writer task
* is running.
*/
@Nullable
RemovableDriveTask getCurrentWriterTask();
/**
* Starts and returns a reader task, reading from a stream described by
* the given transport properties. If a reader task is already running,
* it will be returned and the argument will be ignored.
*/
RemovableDriveTask startReaderTask(TransportProperties p);
/**
* Starts and returns a writer task for the given contact, writing to
* a stream described by the given transport properties. If a writer task
* is already running, it will be returned and the arguments will be
* ignored.
*/
RemovableDriveTask startWriterTask(ContactId c, TransportProperties p);
/**
* Returns true if the given contact has indicated support for the
* removable drive transport.
*/
boolean isTransportSupportedByContact(ContactId c) throws DbException;
/**
* Returns true if there is anything to send to the given contact.
*/
boolean isWriterTaskNeeded(ContactId c) throws DbException;
}
@@ -0,0 +1,65 @@
package org.briarproject.bramble.api.plugin.file;
import org.briarproject.bramble.api.Consumer;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties;
@NotNullByDefault
public interface RemovableDriveTask extends Runnable {
/**
* Returns the {@link TransportProperties} that were used for creating
* this task.
*/
TransportProperties getTransportProperties();
/**
* Adds an observer to the task. The observer will be notified on the
* event thread of the current state of the task and any subsequent state
* changes.
*/
void addObserver(Consumer<State> observer);
/**
* Removes an observer from the task.
*/
void removeObserver(Consumer<State> observer);
class State {
private final long done, total;
private final boolean finished, success;
public State(long done, long total, boolean finished, boolean success) {
this.done = done;
this.total = total;
this.finished = finished;
this.success = success;
}
/**
* Returns the total length in bytes of the messages read or written
* so far, or zero if the total is unknown.
*/
public long getDone() {
return done;
}
/**
* Returns the total length in bytes of the messages that will have
* been read or written when the task is complete, or zero if the
* total is unknown.
*/
public long getTotal() {
return total;
}
public boolean isFinished() {
return finished;
}
public boolean isSuccess() {
return success;
}
}
}
@@ -15,6 +15,12 @@ import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface SimplexPlugin extends Plugin { public interface SimplexPlugin extends Plugin {
/**
* Returns true if the transport is likely to lose streams and the cost of
* transmitting redundant copies of data is cheap.
*/
boolean isLossyAndCheap();
/** /**
* Attempts to create and return a reader for the given transport * Attempts to create and return a reader for the given transport
* properties. Returns null if a reader cannot be created. * properties. Returns null if a reader cannot be created.
@@ -1,30 +1,11 @@
package org.briarproject.bramble.api.plugin.simplex; package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback; import org.briarproject.bramble.api.plugin.PluginFactory;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable;
/** /**
* Factory for creating a plugin for a simplex transport. * Factory for creating a plugin for a simplex transport.
*/ */
@NotNullByDefault @NotNullByDefault
public interface SimplexPluginFactory { public interface SimplexPluginFactory extends PluginFactory<SimplexPlugin> {
/**
* Returns the plugin's transport identifier.
*/
TransportId getId();
/**
* Returns the maximum latency of the transport in milliseconds.
*/
int getMaxLatency();
/**
* Creates and returns a plugin, or null if no plugin can be created.
*/
@Nullable
SimplexPlugin createPlugin(PluginCallback callback);
} }
@@ -21,5 +21,6 @@ public interface ReportingConstants {
* Hidden service address for reporting crashes and feedback to the * Hidden service address for reporting crashes and feedback to the
* developers. * developers.
*/ */
String DEV_ONION_ADDRESS = "cwqmubyvnig3wag3.onion"; String DEV_ONION_ADDRESS =
"b2nkt5doeamvdmjzfz7g42hk5vdtlnktlgzhel2bgjcc4v4jhnx2qrqd.onion";
} }
@@ -22,4 +22,11 @@ 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;
} }
@@ -5,6 +5,7 @@ import org.briarproject.bramble.api.UniqueId;
import java.util.List; import java.util.List;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.concurrent.TimeUnit.DAYS;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
public interface SyncConstants { public interface SyncConstants {
@@ -55,4 +56,9 @@ public interface SyncConstants {
* connections. * connections.
*/ */
int PRIORITY_NONCE_BYTES = 16; int PRIORITY_NONCE_BYTES = 16;
/**
* The maximum allowed latency for any transport, in milliseconds.
*/
long MAX_TRANSPORT_LATENCY = DAYS.toMillis(365);
} }
@@ -16,9 +16,9 @@ public interface SyncSessionFactory {
PriorityHandler handler); PriorityHandler handler);
SyncSession createSimplexOutgoingSession(ContactId c, TransportId t, SyncSession createSimplexOutgoingSession(ContactId c, TransportId t,
int maxLatency, StreamWriter streamWriter); long maxLatency, boolean eager, StreamWriter streamWriter);
SyncSession createDuplexOutgoingSession(ContactId c, TransportId t, SyncSession createDuplexOutgoingSession(ContactId c, TransportId t,
int maxLatency, int maxIdleTime, StreamWriter streamWriter, long maxLatency, int maxIdleTime, StreamWriter streamWriter,
@Nullable Priority priority); @Nullable Priority priority);
} }
@@ -18,11 +18,13 @@ public class MessagesSentEvent extends Event {
private final ContactId contactId; private final ContactId contactId;
private final Collection<MessageId> messageIds; private final Collection<MessageId> messageIds;
private final long totalLength;
public MessagesSentEvent(ContactId contactId, public MessagesSentEvent(ContactId contactId,
Collection<MessageId> messageIds) { Collection<MessageId> messageIds, long totalLength) {
this.contactId = contactId; this.contactId = contactId;
this.messageIds = messageIds; this.messageIds = messageIds;
this.totalLength = totalLength;
} }
public ContactId getContactId() { public ContactId getContactId() {
@@ -32,4 +34,8 @@ public class MessagesSentEvent extends Event {
public Collection<MessageId> getMessageIds() { public Collection<MessageId> getMessageIds() {
return messageIds; return messageIds;
} }
public long getTotalLength() {
return totalLength;
}
} }
@@ -10,23 +10,54 @@ public interface IncomingMessageHook {
/** /**
* Called once for each incoming message that passes validation. * Called once for each incoming message that passes validation.
* <p>
* If an unexpected exception occurs while handling data that is assumed
* to be valid (e.g. locally created metadata), it may be sensible to
* rethrow the unexpected exception as a DbException so that delivery is
* attempted again at next startup. This will allow delivery to succeed if
* the unexpected exception was caused by a bug that has subsequently been
* fixed.
* *
* @param txn A read-write transaction * @param txn A read-write transaction
* @return Whether or not this message should be shared * @throws DbException if a database error occurs while delivering the
* @throws DbException Should only be used for real database errors. * message. Delivery will be attempted again at next startup. Throwing
* If this is thrown, delivery will be attempted again at next startup, * this exception has the same effect as returning
* whereas if an InvalidMessageException is thrown, * {@link DeliveryAction#DEFER}.
* the message will be permanently invalidated. * @throws InvalidMessageException if the message is invalid in the context
* @throws InvalidMessageException for any non-database error * of its dependencies. The message and any dependents will be marked as
* that occurs while handling remotely created data. * invalid and deleted along with their metadata. Throwing this exception
* This includes errors that occur while handling locally created data * has the same effect as returning {@link DeliveryAction#REJECT}.
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as InvalidMessageException!
*/ */
boolean incomingMessage(Transaction txn, Message m, Metadata meta) DeliveryAction incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException; throws DbException, InvalidMessageException;
enum DeliveryAction {
/**
* The message and any dependent messages will be moved to the
* {@link MessageState#INVALID INVALID state} and deleted, along with
* their metadata.
*/
REJECT,
/**
* The message will be moved to the
* {@link MessageState#PENDING PENDING state}. Delivery will be
* attempted again at next startup.
*/
DEFER,
/**
* The message will be moved to the
* {@link MessageState#DELIVERED DELIVERED state} and shared.
*/
ACCEPT_SHARE,
/**
* The message will be moved to the
* {@link MessageState#DELIVERED DELIVERED state} and will not be
* shared.
*/
ACCEPT_DO_NOT_SHARE
}
} }
@@ -1,8 +1,33 @@
package org.briarproject.bramble.api.sync.validation; package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook.DeliveryAction;
public enum MessageState { public enum MessageState {
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3); /**
* A remote message that has not yet been validated.
*/
UNKNOWN(0),
/**
* A remote message that has failed validation, has been
* {@link DeliveryAction#REJECT rejected} by the local sync client, or
* depends on another message that has failed validation or been rejected.
*/
INVALID(1),
/**
* A remote message that has passed validation and is awaiting delivery to
* the local sync client. The message will not be delivered until all its
* dependencies have been validated and delivered.
*/
PENDING(2),
/**
* A local message, or a remote message that has passed validation and
* been delivered to the local sync client.
*/
DELIVERED(3);
private final int value; private final int value;
@@ -6,6 +6,22 @@ package org.briarproject.bramble.api.system;
*/ */
public interface Clock { public interface Clock {
/**
* The minimum reasonable value for the system clock, in milliseconds
* since the Unix epoch.
* <p/>
* 1 Jan 2021, 00:00:00 UTC
*/
long MIN_REASONABLE_TIME_MS = 1_609_459_200_000L;
/**
* The maximum reasonable value for the system clock, in milliseconds
* since the Unix epoch.
* <p/>
* 1 Jan 2121, 00:00:00 UTC
*/
long MAX_REASONABLE_TIME_MS = 4_765_132_800_000L;
/** /**
* @see System#currentTimeMillis() * @see System#currentTimeMillis()
*/ */
@@ -22,8 +22,24 @@ public interface KeyManager {
/** /**
* Derives and stores a set of rotation mode transport keys for * Derives and stores a set of rotation mode transport keys for
* communicating with the given contact over each transport and returns the * communicating with the given contact over the given transport and
* key set IDs. * returns the key set ID, or null if the transport is not supported.
* <p/>
* {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned.
*
* @param alice True if the local party is Alice
* @param active Whether the derived keys can be used for outgoing streams
*/
@Nullable
KeySetId addRotationKeys(Transaction txn, ContactId c, TransportId t,
SecretKey rootKey, long timestamp, boolean alice,
boolean active) throws DbException;
/**
* Derives and stores a set of rotation mode transport keys for
* communicating with the given contact over each supported transport and
* returns the key set IDs.
* <p/> * <p/>
* {@link StreamContext StreamContexts} for the contact can be created * {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned. * after this method has returned.
@@ -97,9 +113,25 @@ 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. * unexpected. Marks the tag as recognised and updates the reordering
* 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;
} }
@@ -0,0 +1,24 @@
package org.briarproject.bramble.api.transport.agreement;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
@NotNullByDefault
public interface TransportKeyAgreementManager {
/**
* The unique ID of the transport key agreement client.
*/
ClientId CLIENT_ID =
new ClientId("org.briarproject.bramble.transport.agreement");
/**
* The current major version of the transport key agreement client.
*/
int MAJOR_VERSION = 0;
/**
* The current minor version of the transport key agreement client.
*/
int MINOR_VERSION = 0;
}
@@ -0,0 +1,34 @@
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();
}
}
}
@@ -6,7 +6,9 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault @NotNullByDefault
public class ValidationUtils { public class ValidationUtils {
@@ -64,4 +66,9 @@ public class ValidationUtils {
if (dictionary != null && dictionary.size() != size) if (dictionary != null && dictionary.size() != size)
throw new FormatException(); throw new FormatException();
} }
public static void checkRange(@Nullable Long l, long min, long max)
throws FormatException {
if (l != null && (l < min || l > max)) throw new FormatException();
}
} }
@@ -1,12 +1,17 @@
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();
@@ -163,10 +163,15 @@ public class TestUtils {
public static Message getMessage(GroupId groupId) { public static Message getMessage(GroupId groupId) {
int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH); int bodyLength = 1 + random.nextInt(MAX_MESSAGE_BODY_LENGTH);
return getMessage(groupId, bodyLength); return getMessage(groupId, bodyLength, timestamp);
} }
public static Message getMessage(GroupId groupId, int bodyLength) { public static Message getMessage(GroupId groupId, int bodyLength) {
return getMessage(groupId, bodyLength, timestamp);
}
public static Message getMessage(GroupId groupId, int bodyLength,
long timestamp) {
MessageId id = new MessageId(getRandomId()); MessageId id = new MessageId(getRandomId());
byte[] body = getRandomBytes(bodyLength); byte[] body = getRandomBytes(bodyLength);
return new Message(id, groupId, timestamp, body); return new Message(id, groupId, timestamp, body);
@@ -0,0 +1,8 @@
package org.briarproject.bramble.test;
public interface TimeTravel {
void setCurrentTimeMillis(long now) throws InterruptedException;
void addCurrentTimeMillis(long add) throws InterruptedException;
}
+20 -17
View File
@@ -1,24 +1,27 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861', 'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64', 'com.google.dagger:dagger:2.33:dagger-2.33.jar:d8798c5b8cf6b125234e33af5c6293bb9f2208ce29b57924c35b8c0be7b6bdcb',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.13.2:junit-4.13.2.jar:8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d', 'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8', 'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', 'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.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.16:animal-sniffer-ant-tasks-1.16.jar:890040976fbe2d584619a6a61b1fd2e925b3b5eb342a85eb2762c467c0d64e90', 'org.codehaus.mojo:animal-sniffer-ant-tasks:1.20:animal-sniffer-ant-tasks-1.20.jar:bb7d2498144118311d968bb08ff6fae3fc535fb1cb9cca8b8e9ea65b189422ac',
'org.codehaus.mojo:animal-sniffer:1.16:animal-sniffer-1.16.jar:72be8bcc226ba43b937c722a08a07852bfa1b11400089265d5df0ee7b38b1d52', 'org.codehaus.mojo:animal-sniffer:1.20:animal-sniffer-1.20.jar:80c422523c38db91260c6d78e5ee4b012862ab61cc55020c9e243dd7b5c62249',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', 'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c', 'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c', 'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b', 'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760', 'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16', 'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80', 'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.ow2.asm:asm-all:5.2:asm-all-5.2.jar:7fbffbc1db3422e2101689fd88df8384b15817b52b9b2b267b9f6d2511dc198d', 'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220', 'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'org.ow2.asm:asm:9.1:asm-9.1.jar:cda4de455fab48ff0bcb7c48b4639447d4de859a7afc30a094a986f0936beba2',
] ]
} }
+20 -7
View File
@@ -10,27 +10,40 @@ apply from: '../dagger.gradle'
dependencies { dependencies {
implementation project(path: ':bramble-api', configuration: 'default') implementation project(path: ':bramble-api', configuration: 'default')
implementation 'com.madgag.spongycastle:core:1.58.0.0' implementation 'org.bouncycastle:bcprov-jdk15to18:1.70'
//noinspection GradleDependency
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6 implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation 'org.bitlet:weupnp:0.1.4' implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0' implementation 'net.i2p.crypto:eddsa:0.2.0'
implementation 'org.whispersystems:curve25519-java:0.5.0' implementation 'org.whispersystems:curve25519-java:0.5.0'
implementation 'org.briarproject:jtorctl:0.3' implementation 'org.briarproject:jtorctl:0.3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.24' //noinspection GradleDependency
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
annotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
testImplementation project(path: ':bramble-api', configuration: 'testOutput') testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6 testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
testImplementation 'junit:junit:4.12' testImplementation 'net.jodah:concurrentunit:0.4.2'
testImplementation "org.jmock:jmock:2.8.2" testImplementation "junit:junit:$junit_version"
testImplementation "org.jmock:jmock-junit4:2.8.2" testImplementation "org.jmock:jmock:$jmock_version"
testImplementation "org.jmock:jmock-legacy:2.8.2" testImplementation "org.jmock:jmock-junit4:$jmock_version"
testImplementation "org.jmock:jmock-imposters:$jmock_version"
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.24' testAnnotationProcessor "com.google.dagger:dagger-compiler:$dagger_version"
signature 'org.codehaus.mojo.signature:java16:1.1@signature' 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)
@@ -1,5 +1,6 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.cleanup.CleanupModule;
import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.contact.ContactModule;
import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoExecutorModule;
import org.briarproject.bramble.db.DatabaseExecutorModule; import org.briarproject.bramble.db.DatabaseExecutorModule;
@@ -10,10 +11,13 @@ import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.rendezvous.RendezvousModule; import org.briarproject.bramble.rendezvous.RendezvousModule;
import org.briarproject.bramble.sync.validation.ValidationModule; import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.transport.TransportModule; import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.transport.agreement.TransportKeyAgreementModule;
import org.briarproject.bramble.versioning.VersioningModule; import org.briarproject.bramble.versioning.VersioningModule;
public interface BrambleCoreEagerSingletons { public interface BrambleCoreEagerSingletons {
void inject(CleanupModule.EagerSingletons init);
void inject(ContactModule.EagerSingletons init); void inject(ContactModule.EagerSingletons init);
void inject(CryptoExecutorModule.EagerSingletons init); void inject(CryptoExecutorModule.EagerSingletons init);
@@ -30,6 +34,8 @@ public interface BrambleCoreEagerSingletons {
void inject(RendezvousModule.EagerSingletons init); void inject(RendezvousModule.EagerSingletons init);
void inject(TransportKeyAgreementModule.EagerSingletons init);
void inject(TransportModule.EagerSingletons init); void inject(TransportModule.EagerSingletons init);
void inject(ValidationModule.EagerSingletons init); void inject(ValidationModule.EagerSingletons init);
@@ -39,6 +45,7 @@ public interface BrambleCoreEagerSingletons {
class Helper { class Helper {
public static void injectEagerSingletons(BrambleCoreEagerSingletons c) { public static void injectEagerSingletons(BrambleCoreEagerSingletons c) {
c.inject(new CleanupModule.EagerSingletons());
c.inject(new ContactModule.EagerSingletons()); c.inject(new ContactModule.EagerSingletons());
c.inject(new CryptoExecutorModule.EagerSingletons()); c.inject(new CryptoExecutorModule.EagerSingletons());
c.inject(new DatabaseExecutorModule.EagerSingletons()); c.inject(new DatabaseExecutorModule.EagerSingletons());
@@ -47,6 +54,7 @@ public interface BrambleCoreEagerSingletons {
c.inject(new RendezvousModule.EagerSingletons()); c.inject(new RendezvousModule.EagerSingletons());
c.inject(new PluginModule.EagerSingletons()); c.inject(new PluginModule.EagerSingletons());
c.inject(new PropertiesModule.EagerSingletons()); c.inject(new PropertiesModule.EagerSingletons());
c.inject(new TransportKeyAgreementModule.EagerSingletons());
c.inject(new TransportModule.EagerSingletons()); c.inject(new TransportModule.EagerSingletons());
c.inject(new ValidationModule.EagerSingletons()); c.inject(new ValidationModule.EagerSingletons());
c.inject(new VersioningModule.EagerSingletons()); c.inject(new VersioningModule.EagerSingletons());
@@ -1,5 +1,6 @@
package org.briarproject.bramble; package org.briarproject.bramble;
import org.briarproject.bramble.cleanup.CleanupModule;
import org.briarproject.bramble.client.ClientModule; import org.briarproject.bramble.client.ClientModule;
import org.briarproject.bramble.connection.ConnectionModule; import org.briarproject.bramble.connection.ConnectionModule;
import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.contact.ContactModule;
@@ -13,6 +14,7 @@ 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;
@@ -21,15 +23,15 @@ import org.briarproject.bramble.rendezvous.RendezvousModule;
import org.briarproject.bramble.settings.SettingsModule; import org.briarproject.bramble.settings.SettingsModule;
import org.briarproject.bramble.sync.SyncModule; import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule; import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.system.ClockModule;
import org.briarproject.bramble.transport.TransportModule; import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.transport.agreement.TransportKeyAgreementModule;
import org.briarproject.bramble.versioning.VersioningModule; import org.briarproject.bramble.versioning.VersioningModule;
import dagger.Module; import dagger.Module;
@Module(includes = { @Module(includes = {
CleanupModule.class,
ClientModule.class, ClientModule.class,
ClockModule.class,
ConnectionModule.class, ConnectionModule.class,
ContactModule.class, ContactModule.class,
CryptoModule.class, CryptoModule.class,
@@ -42,6 +44,7 @@ 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,
@@ -49,6 +52,7 @@ import dagger.Module;
RendezvousModule.class, RendezvousModule.class,
SettingsModule.class, SettingsModule.class,
SyncModule.class, SyncModule.class,
TransportKeyAgreementModule.class,
TransportModule.class, TransportModule.class,
ValidationModule.class, ValidationModule.class,
VersioningModule.class VersioningModule.class
@@ -0,0 +1,159 @@
package org.briarproject.bramble.cleanup;
import org.briarproject.bramble.api.cleanup.CleanupHook;
import org.briarproject.bramble.api.cleanup.CleanupManager;
import org.briarproject.bramble.api.cleanup.event.CleanupTimerStartedEvent;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.Service;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.TaskScheduler;
import org.briarproject.bramble.api.versioning.ClientMajorVersion;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static java.lang.Math.max;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.db.DatabaseComponent.NO_CLEANUP_DEADLINE;
import static org.briarproject.bramble.util.LogUtils.logException;
@ThreadSafe
@NotNullByDefault
class CleanupManagerImpl implements CleanupManager, Service, EventListener {
private static final Logger LOG =
getLogger(CleanupManagerImpl.class.getName());
private final Executor dbExecutor;
private final DatabaseComponent db;
private final TaskScheduler taskScheduler;
private final Clock clock;
private final Map<ClientMajorVersion, CleanupHook> hooks =
new ConcurrentHashMap<>();
private final Object lock = new Object();
@GuardedBy("lock")
private final Set<CleanupTask> pending = new HashSet<>();
@Inject
CleanupManagerImpl(@DatabaseExecutor Executor dbExecutor,
DatabaseComponent db, TaskScheduler taskScheduler, Clock clock) {
this.dbExecutor = dbExecutor;
this.db = db;
this.taskScheduler = taskScheduler;
this.clock = clock;
}
@Override
public void registerCleanupHook(ClientId c, int majorVersion,
CleanupHook hook) {
hooks.put(new ClientMajorVersion(c, majorVersion), hook);
}
@Override
public void startService() {
maybeScheduleTask(clock.currentTimeMillis());
}
@Override
public void stopService() {
}
@Override
public void eventOccurred(Event e) {
if (e instanceof CleanupTimerStartedEvent) {
CleanupTimerStartedEvent a = (CleanupTimerStartedEvent) e;
maybeScheduleTask(a.getCleanupDeadline());
}
}
private void maybeScheduleTask(long deadline) {
synchronized (lock) {
for (CleanupTask task : pending) {
if (task.deadline <= deadline) return;
}
CleanupTask task = new CleanupTask(deadline);
pending.add(task);
scheduleTask(task);
}
}
private void scheduleTask(CleanupTask task) {
long now = clock.currentTimeMillis();
long delay = max(0, task.deadline - now + BATCH_DELAY_MS);
if (LOG.isLoggable(INFO)) {
LOG.info("Scheduling cleanup task in " + delay + " ms");
}
taskScheduler.schedule(() -> deleteMessagesAndScheduleNextTask(task),
dbExecutor, delay, MILLISECONDS);
}
private void deleteMessagesAndScheduleNextTask(CleanupTask task) {
try {
synchronized (lock) {
pending.remove(task);
}
long deadline = db.transactionWithResult(false, txn -> {
deleteMessages(txn);
return db.getNextCleanupDeadline(txn);
});
if (deadline != NO_CLEANUP_DEADLINE) {
maybeScheduleTask(deadline);
}
} catch (DbException e) {
logException(LOG, WARNING, e);
}
}
private void deleteMessages(Transaction txn) throws DbException {
Map<GroupId, Collection<MessageId>> ids = db.getMessagesToDelete(txn);
for (Entry<GroupId, Collection<MessageId>> e : ids.entrySet()) {
GroupId groupId = e.getKey();
Collection<MessageId> messageIds = e.getValue();
if (LOG.isLoggable(INFO)) {
LOG.info(messageIds.size() + " messages to delete");
}
for (MessageId m : messageIds) db.stopCleanupTimer(txn, m);
Group group = db.getGroup(txn, groupId);
ClientMajorVersion cv = new ClientMajorVersion(group.getClientId(),
group.getMajorVersion());
CleanupHook hook = hooks.get(cv);
if (hook == null) {
throw new IllegalStateException("No cleanup hook for " + cv);
}
hook.deleteMessages(txn, groupId, messageIds);
}
}
private static class CleanupTask {
private final long deadline;
private CleanupTask(long deadline) {
this.deadline = deadline;
}
}
}
@@ -0,0 +1,29 @@
package org.briarproject.bramble.cleanup;
import org.briarproject.bramble.api.cleanup.CleanupManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class CleanupModule {
public static class EagerSingletons {
@Inject
CleanupManager cleanupManager;
}
@Provides
@Singleton
CleanupManager provideCleanupManager(LifecycleManager lifecycleManager,
EventBus eventBus, CleanupManagerImpl cleanupManager) {
lifecycleManager.registerService(cleanupManager);
eventBus.addListener(cleanupManager);
return cleanupManager;
}
}
@@ -2,11 +2,13 @@ package org.briarproject.bramble.client;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper; import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.CryptoComponent; import org.briarproject.bramble.api.crypto.CryptoComponent;
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.data.BdfDictionary; import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.BdfReader; import org.briarproject.bramble.api.data.BdfReader;
import org.briarproject.bramble.api.data.BdfReaderFactory; import org.briarproject.bramble.api.data.BdfReaderFactory;
@@ -32,6 +34,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
@@ -39,6 +42,7 @@ import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static org.briarproject.bramble.api.client.ContactGroupConstants.GROUP_KEY_CONTACT_ID;
import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION; import static org.briarproject.bramble.api.identity.Author.FORMAT_VERSION;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
@@ -151,6 +155,12 @@ class ClientHelperImpl implements ClientHelper {
return metadataParser.parse(metadata); return metadataParser.parse(metadata);
} }
@Override
public Collection<MessageId> getMessageIds(Transaction txn, GroupId g,
BdfDictionary query) throws DbException, FormatException {
return db.getMessageIds(txn, g, metadataEncoder.encode(query));
}
@Override @Override
public BdfDictionary getMessageMetadataAsDictionary(MessageId m) public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException, FormatException { throws DbException, FormatException {
@@ -389,4 +399,27 @@ class ClientHelperImpl implements ClientHelper {
return tpMap; return tpMap;
} }
@Override
public ContactId getContactId(Transaction txn, GroupId contactGroupId)
throws DbException {
try {
BdfDictionary meta =
getGroupMetadataAsDictionary(txn, contactGroupId);
return new ContactId(meta.getLong(GROUP_KEY_CONTACT_ID).intValue());
} catch (FormatException e) {
throw new DbException(e); // Invalid group metadata
}
}
@Override
public void setContactId(Transaction txn, GroupId contactGroupId,
ContactId c) throws DbException {
BdfDictionary meta = BdfDictionary.of(
new BdfEntry(GROUP_KEY_CONTACT_ID, c.getInt()));
try {
mergeGroupMetadata(txn, contactGroupId, meta);
} catch (FormatException e) {
throw new AssertionError(e);
}
}
} }
@@ -45,7 +45,6 @@ abstract class Connection {
@Nullable @Nullable
StreamContext recogniseTag(TransportConnectionReader reader, StreamContext recogniseTag(TransportConnectionReader reader,
TransportId transportId) { TransportId transportId) {
StreamContext ctx;
try { try {
byte[] tag = readTag(reader.getInputStream()); byte[] tag = readTag(reader.getInputStream());
return keyManager.getStreamContext(transportId, tag); return keyManager.getStreamContext(transportId, tag);
@@ -71,8 +71,10 @@ class OutgoingSimplexSyncConnection extends SyncConnection implements Runnable {
StreamWriter streamWriter = streamWriterFactory.createStreamWriter( StreamWriter streamWriter = streamWriterFactory.createStreamWriter(
w.getOutputStream(), ctx); w.getOutputStream(), ctx);
ContactId c = requireNonNull(ctx.getContactId()); ContactId c = requireNonNull(ctx.getContactId());
// Use eager retransmission if the transport is lossy and cheap
return syncSessionFactory.createSimplexOutgoingSession(c, return syncSessionFactory.createSimplexOutgoingSession(c,
ctx.getTransportId(), w.getMaxLatency(), streamWriter); ctx.getTransportId(), w.getMaxLatency(), w.isLossyAndCheap(),
streamWriter);
} }
} }
@@ -47,6 +47,7 @@ import javax.inject.Inject;
import static java.util.logging.Logger.getLogger; import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.bramble.api.system.Clock.MIN_REASONABLE_TIME_MS;
import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION; import static org.briarproject.bramble.contact.ContactExchangeConstants.PROTOCOL_VERSION;
import static org.briarproject.bramble.contact.ContactExchangeRecordTypes.CONTACT_INFO; import static org.briarproject.bramble.contact.ContactExchangeRecordTypes.CONTACT_INFO;
import static org.briarproject.bramble.util.ValidationUtils.checkLength; import static org.briarproject.bramble.util.ValidationUtils.checkLength;
@@ -184,6 +185,10 @@ class ContactExchangeManagerImpl implements ContactExchangeManager {
// The agreed timestamp is the minimum of the peers' timestamps // The agreed timestamp is the minimum of the peers' timestamps
long timestamp = Math.min(localTimestamp, remoteInfo.timestamp); long timestamp = Math.min(localTimestamp, remoteInfo.timestamp);
if (timestamp < MIN_REASONABLE_TIME_MS) {
LOG.warning("Timestamp is too old");
throw new FormatException();
}
// Add the contact // Add the contact
Contact contact = addContact(p, remoteInfo.author, localAuthor, Contact contact = addContact(p, remoteInfo.author, localAuthor,
@@ -121,28 +121,39 @@ class ContactManagerImpl implements ContactManager, EventListener {
@Override @Override
public String getHandshakeLink() throws DbException { public String getHandshakeLink() throws DbException {
KeyPair keyPair = db.transactionWithResult(true, return db.transactionWithResult(true, this::getHandshakeLink);
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());
} }
@Override @Override
public PendingContact addPendingContact(String link, String alias) public PendingContact addPendingContact(Transaction txn, String link, String alias)
throws DbException, FormatException, GeneralSecurityException { throws DbException, FormatException, GeneralSecurityException {
PendingContact p = PendingContact p =
pendingContactFactory.createPendingContact(link, alias); pendingContactFactory.createPendingContact(link, alias);
Transaction txn = db.startTransaction(false);
try {
AuthorId local = identityManager.getLocalAuthor(txn).getId(); AuthorId local = identityManager.getLocalAuthor(txn).getId();
db.addPendingContact(txn, p, local); db.addPendingContact(txn, p, local);
KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn); KeyPair ourKeyPair = identityManager.getHandshakeKeys(txn);
keyManager.addPendingContact(txn, p.getId(), p.getPublicKey(), keyManager.addPendingContact(txn, p.getId(), p.getPublicKey(),
ourKeyPair); ourKeyPair);
return p;
}
@Override
public PendingContact addPendingContact(String link, String alias)
throws DbException, FormatException, GeneralSecurityException {
Transaction txn = db.startTransaction(false);
try {
PendingContact p = addPendingContact(txn, link, alias);
db.commitTransaction(txn); db.commitTransaction(txn);
return p;
} finally { } finally {
db.endTransaction(txn); db.endTransaction(txn);
} }
return p;
} }
@Override @Override
@@ -154,8 +165,13 @@ class ContactManagerImpl implements ContactManager, EventListener {
@Override @Override
public Collection<Pair<PendingContact, PendingContactState>> getPendingContacts() public Collection<Pair<PendingContact, PendingContactState>> getPendingContacts()
throws DbException { throws DbException {
Collection<PendingContact> pendingContacts = return db.transactionWithResult(true, this::getPendingContacts);
db.transactionWithResult(true, db::getPendingContacts); }
@Override
public Collection<Pair<PendingContact, PendingContactState>> getPendingContacts(Transaction txn)
throws DbException {
Collection<PendingContact> pendingContacts = db.getPendingContacts(txn);
List<Pair<PendingContact, PendingContactState>> pairs = List<Pair<PendingContact, PendingContactState>> pairs =
new ArrayList<>(pendingContacts.size()); new ArrayList<>(pendingContacts.size());
for (PendingContact p : pendingContacts) { for (PendingContact p : pendingContacts) {
@@ -4,6 +4,10 @@ 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;
@@ -18,14 +22,13 @@ 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;
@@ -58,6 +61,8 @@ 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;
@@ -442,4 +447,21 @@ 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();
}
} }
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -1,5 +1,7 @@
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;
@@ -9,8 +11,6 @@ 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;
@@ -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;
@@ -68,6 +68,13 @@ interface Database<T> {
*/ */
void close() throws DbException; void close() throws DbException;
/**
* Returns true if the dirty flag was set while opening the database,
* indicating that the database has not been shut down properly the last
* time it was closed and some data could be lost.
*/
boolean wasDirtyOnInitialisation();
/** /**
* Starts a new transaction and returns an object representing it. * Starts a new transaction and returns an object representing it.
*/ */
@@ -138,7 +145,7 @@ interface Database<T> {
/** /**
* Stores a transport. * Stores a transport.
*/ */
void addTransport(T txn, TransportId t, int maxLatency) void addTransport(T txn, TransportId t, long maxLatency)
throws DbException; throws DbException;
/** /**
@@ -155,6 +162,18 @@ interface Database<T> {
KeySetId addTransportKeys(T txn, PendingContactId p, TransportKeys k) KeySetId addTransportKeys(T txn, PendingContactId p, TransportKeys k)
throws DbException; throws DbException;
/**
* Returns true if there are any acks or messages to send to the given
* contact over a transport with the given maximum latency.
* <p/>
* Read-only.
*
* @param eager True if messages that are not yet due for retransmission
* should be included
*/
boolean containsAnythingToSend(T txn, ContactId c, long maxLatency,
boolean eager) throws DbException;
/** /**
* Returns true if the database contains the given contact for the given * Returns true if the database contains the given contact for the given
* local pseudonym. * local pseudonym.
@@ -208,6 +227,16 @@ interface Database<T> {
*/ */
boolean containsTransport(T txn, TransportId t) throws DbException; boolean containsTransport(T txn, TransportId t) throws DbException;
/**
* Returns true if the database contains keys for communicating with the
* given contact over the given transport. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
boolean containsTransportKeys(T txn, ContactId c, TransportId t)
throws DbException;
/** /**
* Returns true if the database contains the given message, the message is * Returns true if the database contains the given message, the message is
* shared, and the visibility of the message's group to the given contact * shared, and the visibility of the message's group to the given contact
@@ -454,7 +483,7 @@ interface Database<T> {
* Read-only. * Read-only.
*/ */
Collection<MessageId> getMessagesToOffer(T txn, ContactId c, Collection<MessageId> getMessagesToOffer(T txn, ContactId c,
int maxMessages, int maxLatency) throws DbException; int maxMessages, long maxLatency) throws DbException;
/** /**
* Returns the IDs of some messages that are eligible to be requested from * Returns the IDs of some messages that are eligible to be requested from
@@ -469,10 +498,36 @@ interface Database<T> {
* Returns the IDs of some messages that are eligible to be sent to the * Returns the IDs of some messages that are eligible to be sent to the
* given contact, up to the given total length. * given contact, up to the given total length.
* <p/> * <p/>
* Unlike {@link #getUnackedMessagesToSend(Object, ContactId)} this method
* does not return messages that have already been sent unless they are
* due for retransmission.
* <p/>
* Read-only. * Read-only.
*/ */
Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength, Collection<MessageId> getMessagesToSend(T txn, ContactId c, int maxLength,
int maxLatency) throws DbException; long maxLatency) throws DbException;
/**
* Returns the IDs of all messages that are eligible to be sent to the
* given contact, together with their raw lengths.
* <p/>
* Unlike {@link #getMessagesToSend(Object, ContactId, int, long)} this
* method may return messages that have already been sent and are not yet
* due for retransmission.
* <p/>
* Read-only.
*/
Map<MessageId, Integer> getUnackedMessagesToSend(T txn, ContactId c)
throws DbException;
/**
* Returns the total length, including headers, of all messages that are
* eligible to be sent to the given contact. This may include messages
* that have already been sent and are not yet due for retransmission.
* <p/>
* Read-only.
*/
long getUnackedMessageBytesToSend(T txn, ContactId c) throws DbException;
/** /**
* Returns the IDs of any messages that need to be validated. * Returns the IDs of any messages that need to be validated.
@@ -497,6 +552,25 @@ interface Database<T> {
*/ */
Collection<MessageId> getMessagesToShare(T txn) throws DbException; Collection<MessageId> getMessagesToShare(T txn) throws DbException;
/**
* Returns the IDs of any messages of any messages that are due for
* deletion, along with their group IDs.
* <p/>
* Read-only.
*/
Map<GroupId, Collection<MessageId>> getMessagesToDelete(T txn)
throws DbException;
/**
* Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be deleted, or
* {@link DatabaseComponent#NO_CLEANUP_DEADLINE} if no messages are
* scheduled to be deleted.
* <p/>
* Read-only.
*/
long getNextCleanupDeadline(T txn) throws DbException;
/** /**
* Returns the next time (in milliseconds since the Unix epoch) when a * Returns the next time (in milliseconds since the Unix epoch) when a
* message is due to be sent to the given contact. The returned value may * message is due to be sent to the given contact. The returned value may
@@ -530,7 +604,7 @@ interface Database<T> {
* Read-only. * Read-only.
*/ */
Collection<MessageId> getRequestedMessagesToSend(T txn, ContactId c, Collection<MessageId> getRequestedMessagesToSend(T txn, ContactId c,
int maxLength, int maxLatency) throws DbException; int maxLength, long maxLatency) throws DbException;
/** /**
* Returns all settings in the given namespace. * Returns all settings in the given namespace.
@@ -554,6 +628,16 @@ interface Database<T> {
Collection<TransportKeySet> getTransportKeys(T txn, TransportId t) Collection<TransportKeySet> getTransportKeys(T txn, TransportId t)
throws DbException; throws DbException;
/**
* Returns the contact IDs and transport IDs for which the DB contains
* at least one set of transport keys. Handshake mode and rotation mode
* keys are included, whether activated or not.
* <p/>
* Read-only.
*/
Map<ContactId, Collection<TransportId>> getTransportsWithKeys(T txn)
throws DbException;
/** /**
* Increments the outgoing stream counter for the given transport keys. * Increments the outgoing stream counter for the given transport keys.
*/ */
@@ -606,8 +690,10 @@ interface Database<T> {
/** /**
* Marks a message as having been seen by the given contact. * Marks a message as having been seen by the given contact.
*
* @return True if the message was not already marked as seen.
*/ */
void raiseSeenFlag(T txn, ContactId c, MessageId m) throws DbException; boolean raiseSeenFlag(T txn, ContactId c, MessageId m) throws DbException;
/** /**
* Removes a contact from the database. * Removes a contact from the database.
@@ -671,6 +757,20 @@ 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
* start the message's cleanup timer.
*/
void setCleanupTimerDuration(T txn, MessageId m, long duration)
throws DbException;
/** /**
* Marks the given contact as verified. * Marks the given contact as verified.
*/ */
@@ -701,9 +801,10 @@ interface Database<T> {
void setMessagePermanent(T txn, MessageId m) throws DbException; void setMessagePermanent(T txn, MessageId m) throws DbException;
/** /**
* Marks the given message as shared. * Marks the given message as shared or not.
*/ */
void setMessageShared(T txn, MessageId m) throws DbException; void setMessageShared(T txn, MessageId m, boolean shared)
throws DbException;
/** /**
* Sets the validation and delivery state of the given message. * Sets the validation and delivery state of the given message.
@@ -730,13 +831,29 @@ interface Database<T> {
void setTransportKeysActive(T txn, TransportId t, KeySetId k) void setTransportKeysActive(T txn, TransportId t, KeySetId k)
throws DbException; throws DbException;
/**
* Starts the cleanup timer for the given message, if a timer duration
* has been set and the timer has not already been started.
*
* @return The cleanup deadline, or
* {@link DatabaseComponent#TIMER_NOT_STARTED} if no timer duration has
* been set for this message or its timer has already been started.
*/
long startCleanupTimer(T txn, MessageId m) throws DbException;
/**
* Stops the cleanup timer for the given message, if the timer has been
* started.
*/
void stopCleanupTimer(T txn, MessageId m) throws DbException;
/** /**
* Updates the transmission count, expiry time and estimated time of arrival * Updates the transmission count, expiry time and estimated time of arrival
* 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, int maxLatency) void updateExpiryTimeAndEta(T txn, ContactId c, MessageId m,
throws DbException; long maxLatency) throws DbException;
/** /**
* Stores the given transport keys, deleting any keys they have replaced. * Stores the given transport keys, deleting any keys they have replaced.

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