Compare commits

...

296 Commits

Author SHA1 Message Date
akwizgran
56c1fef4db Count 7 bits at a time. 2018-12-13 10:58:19 +00:00
akwizgran
c2f96580b8 Add utility methods for variable-length integers. 2018-12-05 11:31:34 +00:00
akwizgran
a5c9e7c74d Merge branch '1242-display-image-attachments-fullscreen' into 'master'
Add ImageActivity to show image attachment in full-screen

See merge request briar/briar!999
2018-11-30 18:04:55 +00:00
Torsten Grote
8a4a343147 [android] Move image to the top if it is overlapping the toolbar 2018-11-30 15:53:38 -02:00
Torsten Grote
7b22d3b84d [android] Address review issues for image fullscreen view 2018-11-28 17:26:01 -02:00
Torsten Grote
c8fa23273f [android] support pull down to dismiss pattern for ImageActivity 2018-11-28 17:26:01 -02:00
Torsten Grote
fbe5df8938 [android] Add ImageActivity to show images in full-screen 2018-11-28 17:26:01 -02:00
akwizgran
008cf95741 Merge branch '1467-conversation-scrolling' into 'master'
Only scroll conversation list to bottom, when already at bottom

Closes #1467

See merge request briar/briar!1000
2018-11-27 09:32:05 +00:00
Torsten Grote
3eb066a836 [android] Use new IoUtils to close InputStreams 2018-11-26 16:28:06 -02:00
Torsten Grote
674b29af25 [android] static constant all caps 2018-11-26 16:23:51 -02:00
Torsten Grote
b8ca5ab557 [android] Only scroll conversation list to bottom, when already at bottom
Closes #1467
2018-11-26 16:23:17 -02:00
Torsten Grote
6e17709f46 Merge branch 'try-to-close' into 'master'
Move tryToClose() methods into utility classes

See merge request briar/briar!1002
2018-11-26 18:22:24 +00:00
akwizgran
726d90145c Merge branch '1242-display-image-attachments' into 'master'
[android] display image attachments for conversation messages

See merge request briar/briar!997
2018-11-26 17:19:37 +00:00
Torsten Grote
165211eb9b Merge branch '1259-headless-mac-os' into 'master'
Enable headless app to start on MacOS

See merge request briar/briar!1003
2018-11-26 12:01:27 +00:00
akwizgran
868c61e5d6 Move tryToClose() methods into utility classes. 2018-11-23 15:02:27 +00:00
Torsten Grote
798bb6d4f7 [android] scale thumbnails to minimum size, don't upscale to maximum size 2018-11-23 11:25:18 -02:00
akwizgran
bc352a2dc6 Enable Tor on Mac OS once binaries are available. 2018-11-23 13:07:12 +00:00
akwizgran
ce7d6d3db5 Code cleanup. 2018-11-23 12:56:34 +00:00
akwizgran
61276c81d2 Make it possible to start the headless app on MacOS.
The app is still non-functional because we don't have a Tor plugin.
2018-11-23 12:52:40 +00:00
Torsten Grote
c09abdb088 Merge branch 'location-permission-sdk-23' into 'master'
Change location permission to uses-permission-sdk-23

See merge request briar/briar!1001
2018-11-22 12:03:07 +00:00
akwizgran
45a11badd5 Change location permission to uses-permission-sdk-23. 2018-11-20 16:16:47 +00:00
Torsten Grote
152ac3df43 [android] improve bitmap transformation hashKey and DiskCacheKey 2018-11-20 11:49:21 -02:00
Torsten Grote
dd5ad86db8 [android] Use DataFetcherFactory to create data fetchers and allow cancelling loads 2018-11-20 11:49:21 -02:00
Torsten Grote
10e9fb308d [android] Display Image Attachements: Address first round of review comments 2018-11-19 20:35:07 -02:00
Torsten Grote
de8e95692a [android] support RTL languages when rounding thumbnail corners 2018-11-19 20:35:07 -02:00
Torsten Grote
d6b52cf4ec [android] Use our own BitmapTransformation for rounded image corners 2018-11-19 20:35:07 -02:00
Torsten Grote
8a839fb5e4 [android] display image attachments for conversation messages 2018-11-19 20:35:07 -02:00
akwizgran
fbf8642edb Merge branch '1464-message-status-mixed' into 'master'
[core] fix wrong order of message status flags in conversation headers

Closes #1464

See merge request briar/briar!998
2018-11-16 13:44:39 +00:00
Torsten Grote
ade6a14342 Merge branch 'validation-refactoring' into 'master'
Reorganise validation code

See merge request briar/briar!991
2018-11-15 17:18:15 +00:00
Torsten Grote
d500ff81c3 Merge branch 'require-non-null' into 'master'
Add static requireNonNull() method

See merge request briar/briar!996
2018-11-15 16:50:16 +00:00
Torsten Grote
3053e3cfa7 [core] fix wrong order of message status flags in conversation headers 2018-11-15 14:39:05 -02:00
akwizgran
6964a67ca3 Add static requireNonNull() method. 2018-11-15 11:13:15 +00:00
Torsten Grote
f4b06e1fb3 Merge branch 'load-latest-message-eagerly' into 'master'
Load latest message eagerly

See merge request briar/briar!995
2018-11-14 16:01:59 +00:00
akwizgran
4db075d643 Only consider the latest item for preloading. 2018-11-14 15:13:25 +00:00
akwizgran
78a8ae6b8e Sort headers and eagerly load text of latest message. 2018-11-14 15:01:54 +00:00
Torsten Grote
7866037d02 Merge branch '1460-introduction-request-text' into 'master'
Show correct text when an existing contact is introduced

Closes #1460

See merge request briar/briar!994
2018-11-14 11:23:26 +00:00
akwizgran
35716051fb Show correct text when an existing contact is introduced. 2018-11-14 11:05:46 +00:00
Torsten Grote
6cafea836f Merge branch 'eager-singletons' into 'master'
Singletons that call registration methods must be eager

See merge request briar/briar!993
2018-11-13 18:03:28 +00:00
akwizgran
bd0fd229c6 Merge branch '1242-attachment-input-stream' into 'master'
Attachments will use InputStream rather than ByteBuffer

See merge request briar/briar!992
2018-11-13 17:41:39 +00:00
akwizgran
ea05a5c703 Singletons that call registration methods must be eager. 2018-11-13 17:40:06 +00:00
akwizgran
4103eaf639 Reorganise validation code (no functional changes). 2018-11-13 17:16:47 +00:00
Torsten Grote
753a25bc2a [core] Attachments will use InputStream rather than ByteBuffer 2018-11-13 15:12:34 -02:00
akwizgran
8f4c3c4528 Bump version numbers for 1.1.5 release. 2018-11-13 13:01:01 +00:00
akwizgran
636a7dfe72 Update translations. 2018-11-13 12:59:51 +00:00
akwizgran
08e99edd42 Merge branch 'unpack-tor-binaries' into 'master'
Always unpack and include latest Tor binaries

See merge request briar/briar!987
2018-11-13 12:56:47 +00:00
akwizgran
e28bc475df Merge branch '1242-optional-message-text' into 'master'
Add support for private messages without text

See merge request briar/briar!990
2018-11-13 10:47:52 +00:00
Torsten Grote
88276a4d44 Add support for private messages without text 2018-11-12 18:11:03 -02:00
akwizgran
f9987c89df Merge branch 'disable-tor-connection-padding' into 'master'
Disable Tor's connection padding

See merge request briar/briar!989
2018-11-12 14:03:22 +00:00
Torsten Grote
2c8cb8301f Merge branch '1455-stream-context-may-be-null' into 'master'
Stream context may be null

Closes #1455

See merge request briar/briar!988
2018-11-12 12:50:01 +00:00
akwizgran
c00ee80f0f Update test expectations. 2018-11-12 12:20:04 +00:00
akwizgran
3bfedfdc3d Add action for nullable DB callables. 2018-11-12 12:16:42 +00:00
akwizgran
ecb63d1acb Add interface for DB tasks will nullable results. 2018-11-12 12:13:26 +00:00
akwizgran
b24914408d Stream context may be null. 2018-11-12 11:31:59 +00:00
akwizgran
5ede63edd5 Always unpack and include latest Tor binaries. 2018-11-08 17:48:26 +00:00
akwizgran
4e523c5fbc Merge branch '1242-display-image-attachments' into 'master'
[android] refactor conversation items and view holders

See merge request briar/briar!984
2018-11-08 16:08:58 +00:00
akwizgran
cf79ed5633 IntentFilter may not be thread-safe. 2018-11-08 14:54:53 +00:00
akwizgran
0a0a6a6369 Disable Tor's connection padding on mobile data or battery. 2018-11-08 14:50:36 +00:00
akwizgran
4784980e7b No need to broadcast network status at startup. 2018-11-08 14:50:36 +00:00
akwizgran
3bfa5e2081 [android] Move ConversationListener to top level. 2018-11-08 10:27:36 -02:00
akwizgran
f2b09deac4 [android] Remove type parameter from view holders. 2018-11-08 10:27:29 -02:00
Torsten Grote
ad4729b2f9 [android] refactor conversation items and view holders
This is a preparation for image support.
2018-11-08 10:27:29 -02:00
akwizgran
50cc0a6815 Merge branch '1452-websocket-authentication' into 'master'
[headless] change websocket authentication from basic auth to token message

Closes #1452

See merge request briar/briar!986
2018-11-08 12:26:53 +00:00
Torsten Grote
32c8ac6576 [headless] change websocket authentication from basic auth to token message 2018-11-08 10:15:17 -02:00
akwizgran
c12422d949 Merge branch '1434-android-conversation-package' into 'master'
Move conversation classes into their own package

See merge request briar/briar!978
2018-11-08 11:01:36 +00:00
akwizgran
3841713c18 Merge branch 'upgrade_roboletric_to_401' into 'master'
Upgrade robolectric to 4.0.1

See merge request briar/briar!980
2018-11-08 11:00:08 +00:00
akwizgran
79232eb558 Merge branch 'headless-fixes' into 'master'
Headless fixes

See merge request briar/briar!985
2018-11-08 10:55:28 +00:00
Torsten Grote
d02b30e751 Merge branch 'use-transactional-db-api' into 'master'
Use transactional database API in Bramble

See merge request briar/briar!974
2018-11-07 19:06:26 +00:00
akwizgran
043662a092 Code cleanup. 2018-11-07 18:31:07 +00:00
Torsten Grote
efc85fb88f [headless] don't use putAll for a single field 2018-11-07 15:24:20 -03:00
Torsten Grote
8b3983ef9e [headless] only offload to DatabaseExecutor when needed
when receiving a new conversation message
2018-11-07 15:24:20 -03:00
Torsten Grote
6766fb76b2 [headless] upgrade javalin and mockk 2018-11-07 15:18:46 -03:00
Torsten Grote
7f74bd1c38 [headless] Use --user for websocket example request
The authentication token can contain slashes.
When used as part of the URL, the URL becomes invalid.
Therefore, using curl's user parameter is preferrable.
2018-11-07 15:18:46 -03:00
akwizgran
951ee30b95 Update tests. 2018-11-07 18:18:30 +00:00
akwizgran
c386a0f5eb Replace Maybe with nullable transaction method. 2018-11-07 18:18:30 +00:00
akwizgran
52c778dce3 Reformat code. 2018-11-07 18:18:27 +00:00
akwizgran
e846a13f50 Use transactional database API in Bramble. 2018-11-07 18:14:10 +00:00
akwizgran
23e9b119d1 Merge branch '1434-message-attachments' into 'master'
Add attachment API for sending/retreiving private messages

See merge request briar/briar!976
2018-11-07 18:08:36 +00:00
akwizgran
e6f380296f Merge branch '1451-briar-headless-test-other-modules' into 'master'
[headless] Limit tests in Android Studio to headless package

Closes #1451

See merge request briar/briar!983
2018-11-07 17:47:37 +00:00
Torsten Grote
794fb9686b [headless] Limit tests in Android Studio to headless package 2018-11-07 13:46:49 -03:00
Torsten Grote
bb22b9db10 Merge branch 'remove-hamcrest-dependencies' into 'master'
Remove redundant dependency declarations

See merge request briar/briar!981
2018-11-07 16:37:30 +00:00
Julian Dehm
d4f015d054 Upgrade robolectric to 4.0.1 2018-11-07 17:11:21 +01:00
akwizgran
41e5d8900c Remove redundant dependency declarations. 2018-11-07 16:10:39 +00:00
Torsten Grote
c3cb966009 [android] move conversation classes into their own package 2018-11-07 11:48:20 -03:00
Torsten Grote
f964d1ef07 Fix receivers of ConversationMessageReceivedEvent
These were only listening to private message events, ignoring all others
2018-11-07 11:34:11 -03:00
Torsten Grote
cccaeeda6c [core] Add API to add messages with attachments 2018-11-07 11:34:11 -03:00
Torsten Grote
483106e00c [core] Add MessagingManager#getAttachment() 2018-11-07 11:34:11 -03:00
Torsten Grote
934f14ef31 [core] Add attachment support to private messages 2018-11-07 11:34:09 -03:00
Torsten Grote
e3abff5ad8 Refactor PrivateMessageHeader to ConversationMessageHeader base-class
This is preparation for adding attachments to private messages
2018-11-07 11:33:37 -03:00
Torsten Grote
391732b239 Merge branch 'change-contact-name' into 'master'
Change button text to match name of action

See merge request briar/briar!979
2018-11-07 12:11:22 +00:00
akwizgran
4738bfdd85 Ignore missing translations. 2018-11-07 10:43:13 +00:00
akwizgran
be1ca89309 Change button text to match name of action. 2018-11-07 10:40:59 +00:00
Torsten Grote
866be99179 Merge branch '41-alias-frontend' into 'master'
Add UI for changing contact aliases

Closes #41

See merge request briar/briar!965
2018-11-06 18:09:47 +00:00
akwizgran
48822e2133 Merge branch '1381-introduction-test-fails' into 'master'
Fix non-determinism of Introduction integration tests

Closes #1381

See merge request briar/briar!970
2018-11-06 18:00:48 +00:00
Torsten Grote
6883c5caa9 [android] address last contact aliases review issues 2018-11-06 14:57:39 -03:00
Torsten Grote
8b709969ab [android] pass ContactId via ViewModel to AliasDialogFragment 2018-11-06 13:42:51 -03:00
Torsten Grote
fe94b65b3b [android] Fix double loading of conversation messages when rotating screen 2018-11-06 13:42:51 -03:00
akwizgran
f54df1d787 Reduce visibility, remove unnecessary rethrow. 2018-11-06 13:42:51 -03:00
akwizgran
a7e826ccf5 Remove qualification from java.lang.Runnable. 2018-11-06 13:42:51 -03:00
akwizgran
845eb3262b Use expression lambda. 2018-11-06 13:42:51 -03:00
akwizgran
0a46ad439f Check whether activity is null. 2018-11-06 13:42:51 -03:00
akwizgran
d14d93ea35 Require observed data to be non-null. 2018-11-06 13:42:51 -03:00
akwizgran
12a1cf8f8b Reuse Observer interface. 2018-11-06 13:42:51 -03:00
akwizgran
fb2ab861db Fix some lint warnings. 2018-11-06 13:42:51 -03:00
Torsten Grote
aa15b68d24 [android] Reload conversation when contact name changes 2018-11-06 13:42:51 -03:00
Torsten Grote
7059f376f1 [android] Add UI for changing contact alias
This introduces the first ViewModel to share state between the
ConversationActivity and the AliasDialogFragment.
2018-11-06 13:42:51 -03:00
akwizgran
9313c191c1 Merge branch 'ui-fixes' into 'master'
Small UI fixes

See merge request briar/briar!975
2018-11-05 10:40:09 +00:00
akwizgran
7746364ae9 Merge branch '1437-reversed-emoji' into 'master'
[android] Add new emojis to the beginning of the list of recently used ones

Closes #1437

See merge request briar/briar!977
2018-11-05 10:27:03 +00:00
Torsten Grote
7429857b28 [android] Add new emojis to the beginning of the list of recently used ones
Otherwise the list will be reversed with most recently used at the end.
2018-11-04 11:08:05 -03:00
Torsten Grote
4db64f51a8 [android] Use same color for all messages in private groups 2018-11-02 15:59:49 -03:00
Torsten Grote
78172038ef [android] Always center selectable contacts vertically 2018-11-02 15:38:01 -03:00
Torsten Grote
7d0c418877 [android] Align short incoming messages on the left 2018-11-02 15:37:16 -03:00
Torsten Grote
5ae4f8f6cb [core] Fix non-determism in GroupInvitationIntegrationTest 2018-11-02 14:08:42 -03:00
Torsten Grote
45dd10db9d [core] Fix non-determinism in introduction integration tests 2018-11-02 14:08:42 -03:00
Torsten Grote
5cc8c268ca [core] Re-add message counter and put debug output behind flag 2018-11-02 14:08:42 -03:00
akwizgran
93a6bf2f52 Add logging to debug test failures. 2018-11-02 12:48:23 -03:00
akwizgran
852dd46a1b Utility class for converting BDF to strings.
(cherry picked from commit 9e94917)
2018-11-02 12:48:23 -03:00
Torsten Grote
4a42e767d3 [core] Add a detector for message delivery non-determinism 2018-11-02 12:48:13 -03:00
akwizgran
8547b4dc91 Merge branch 'upgrade-dagger' into 'master'
Upgrade dagger

See merge request briar/briar!973
2018-11-01 14:17:35 +00:00
akwizgran
f6c8a8cec7 Move dagger.gradle to project root. 2018-11-01 14:05:46 +00:00
Torsten Grote
db8796049e gradle: Factor out dagger apt code into its own file 2018-11-01 10:45:59 -03:00
Torsten Grote
e1f31ad381 Remove gradle-apt-plugin since it isn't stricly needed anymore
Reference: 6b2ee87fbf/README.md
2018-10-31 16:01:57 -03:00
Torsten Grote
3a15e47ddd Upgrade Dagger to latest version 2018-10-31 15:57:21 -03:00
Torsten Grote
cf616905d6 Merge branch 'introduction-manager-skip-session-parsing' into 'master'
Avoid some unnecessary session parsing when retrieving introduction messages

See merge request briar/briar!972
2018-10-31 16:36:59 +00:00
akwizgran
d3f774f339 Avoid some unnecessary session parsing. 2018-10-31 16:18:33 +00:00
akwizgran
6c7c488892 Merge branch '41-alias-frontend-base' into 'master'
[android] Show contact aliases in UI

See merge request briar/briar!971
2018-10-31 16:16:38 +00:00
Torsten Grote
3fe7aae97e Contact aliases: address review comments 2018-10-31 13:06:19 -03:00
Torsten Grote
ecf417c93b [android] Show contact alias in remaining places 2018-10-31 13:06:19 -03:00
Torsten Grote
c1785c5b13 [android] Show contact alias in contact lists 2018-10-31 13:06:19 -03:00
Torsten Grote
fb2c321a3d [android] Show contact alias inside private groups and their memberlist 2018-10-31 13:06:19 -03:00
Torsten Grote
6e3adc0874 Show alias for introduction notices in private conversation 2018-10-31 13:06:19 -03:00
Torsten Grote
cdbe2a00f5 [android] Show alias for creator of private group in list of private groups 2018-10-31 11:40:17 -03:00
Torsten Grote
a51dc7e0d5 [android] Show Author alias in AuthorView 2018-10-31 11:40:15 -03:00
Torsten Grote
0ee7465429 Merge branch '41-alias-author-info' into 'master'
Refactor Author.Status into dedicated AuthorInfo class and add alias

See merge request briar/briar!968
2018-10-30 19:33:39 +00:00
Torsten Grote
7c202189a2 [bramble] Implement equals() and hashCode() for AuthorView 2018-10-30 15:21:09 -03:00
akwizgran
da3b2c1591 Merge branch '41-alias-backend' into 'master'
Add backend support for contact aliases

See merge request briar/briar!963
2018-10-30 16:43:52 +00:00
Torsten Grote
6c5e8ce4cf Rename remaining occurrences of status to authorInfo 2018-10-30 13:40:04 -03:00
Torsten Grote
ca700d8d23 [bramble] address review comments 2018-10-30 13:32:56 -03:00
akwizgran
db11dad61e Merge branch 'clean-tor-binaries' into 'master'
Delete Tor binaries when cleaning

See merge request briar/briar!969
2018-10-30 13:59:21 +00:00
akwizgran
69e7366226 Merge branch '1433-illegal-characters' into 'master'
Handle illegal byte sequences safely in BdfReaderImpl

Closes #1433

See merge request briar/briar!967
2018-10-30 13:58:36 +00:00
akwizgran
90b7b4e67f Merge branch '1416-obfs4' into 'master'
Add obfs4proxy and switch to obfs4 bridges

Closes #1417

See merge request briar/briar!964
2018-10-30 13:58:13 +00:00
akwizgran
d29812a42b Delete Tor binaries when cleaning. 2018-10-30 13:06:06 +00:00
Torsten Grote
baf64e1129 [bramble] Add transactionless method for retrieving AuthorInfo to ContactManager 2018-10-29 18:16:34 -03:00
Torsten Grote
88adfabe09 Refactor Author.Status into dedicated AuthorInfo class and add alias 2018-10-29 17:23:45 -03:00
akwizgran
6565172e10 Bump version numbers for 1.1.4 release. 2018-10-29 17:31:09 +00:00
akwizgran
7447468ce5 Update translations. 2018-10-29 17:30:04 +00:00
akwizgran
2db2a1a208 Replace a slow bridge with a faster one. 2018-10-29 17:25:12 +00:00
akwizgran
0d7e4feaf2 Throw AssertionError to make intent clearer. 2018-10-29 17:02:07 +00:00
akwizgran
eb3983f6b2 Use safe ASCII decoding in ModemImpl. 2018-10-29 16:48:18 +00:00
akwizgran
e2ce49c30e Use safe UTF-8 decoding in BdfReaderImpl. 2018-10-29 16:47:55 +00:00
akwizgran
adc6fb2fd5 Add fuzzing test for illegal UTF-8 byte sequences. 2018-10-29 16:44:02 +00:00
Torsten Grote
969150bff0 [bramble] Factor out database type placeholder replacement
to make it available in database schema migrations
2018-10-29 12:50:08 -03:00
Torsten Grote
8fc622f85d [bramble] Add support for contact aliases
Foundation for #41
2018-10-29 12:50:08 -03:00
akwizgran
22eed91019 Merge branch 'javalin-access-manager' into 'master'
[headless] Set up access manager before starting server

See merge request briar/briar!966
2018-10-29 15:35:48 +00:00
akwizgran
fcb88ed58c Merge branch '1147-bluetooth-discovery' into 'master'
Support Bluetooth discovery for adding contacts

See merge request briar/briar!954
2018-10-29 14:35:17 +00:00
Torsten Grote
0d940fc7d7 [headless] Set up access manager before starting server
This became necesary to due an upstream change we missed when bumping
the dependency:

ab19ff91b7
2018-10-29 11:20:48 -03:00
Torsten Grote
ca6dc33cdd Add obfs4 proxy and switch to obfs4 bridges 2018-10-25 09:38:44 -03:00
akwizgran
53da13794f Merge branch '1422-activity-log' into 'master'
Log when activities start and stop

See merge request briar/briar!959
2018-10-24 16:00:52 +00:00
akwizgran
2ab03f48cc Merge branch '1256-remove-contact' into 'master'
briar-headless: Add endpoint for removing a contact

See merge request briar/briar!962
2018-10-24 15:59:39 +00:00
Torsten Grote
436f45554d [briar-headless] update dependencies 2018-10-24 12:41:29 -03:00
Torsten Grote
51209b5eec briar-headless: Add endpoint for removing a contact 2018-10-24 12:12:33 -03:00
akwizgran
822597b4c6 Merge branch '1373-mirror-icons' into 'master'
Fix RTL icon mirroring in DevReportActivity

Closes #1373

See merge request briar/briar!960
2018-10-24 14:05:06 +00:00
akwizgran
7c01bc59c0 Merge branch '1252-dark-theme-system-default' into 'master'
Remove system default theme option on API < 28

Closes #1252

See merge request briar/briar!961
2018-10-24 13:52:20 +00:00
Torsten Grote
825d342f9b Remove system default theme option on API < 27
Closes #1252
2018-10-24 10:40:43 -03:00
Torsten Grote
34955fecbb Fix RTL icon mirroring in DevReportActivity
For some reason, the toolbar icon has a wrong layout direction,
so the autoMirrored attribute doesn't take any effect.
2018-10-22 16:53:17 -03:00
Torsten Grote
5c28b60a6b Log when activities start and stop
Remove BriarRecyclerView log messages
2018-10-22 14:11:36 -03:00
akwizgran
389b2b5b8e Merge branch '1423-check-lifecycle-state' into 'master'
Check lifecycle state before changing fragment

Closes #1423

See merge request briar/briar!958
2018-10-22 14:27:30 +00:00
Torsten Grote
78abfa3698 Check lifecycle state before changing fragment 2018-10-19 16:40:00 -03:00
akwizgran
9c4fb4fd34 Remove unused string. 2018-10-18 17:22:54 +01:00
akwizgran
3d6a336f6d Refactor permissions code, add comments, fix corner cases. 2018-10-18 17:16:49 +01:00
akwizgran
e47d41596a Merge branch '1254-inject-object-mapper' into 'master'
briar-headless: Inject a singleton ObjectMapper for JSON parsing

See merge request briar/briar!957
2018-10-18 15:40:20 +00:00
Torsten Grote
8cf54bcedb briar-headless: Inject a singleton ObjectMapper for JSON parsing 2018-10-18 09:55:34 -03:00
akwizgran
89d5145665 Bump version numbers for 1.1.3 release. 2018-10-17 17:51:11 +01:00
Torsten Grote
0706498b03 Merge branch 'upgrade-android-gradle-plugin' into 'master'
Upgrade Android Gradle plugin to 3.2.1.

See merge request briar/briar!956
2018-10-17 16:36:24 +00:00
akwizgran
b296500e7a Update translations. 2018-10-17 12:41:24 +01:00
akwizgran
60a8b03344 Upgrade Android Gradle plugin to 3.2.1. 2018-10-17 12:34:13 +01:00
Torsten Grote
ae16a93522 Merge branch 'compact-at-startup' into 'master'
Compact the database at startup

See merge request briar/briar!955
2018-10-16 16:02:40 +00:00
Torsten Grote
c9a2ff71ae Merge branch 'tor-v3-hidden-service-addresses' into 'master'
Add support for v3 hidden service addresses

See merge request briar/briar!952
2018-10-16 15:55:34 +00:00
akwizgran
16f4c60a56 Add test for compaction time. 2018-10-16 11:39:06 +01:00
akwizgran
76121eb871 Always compact the DB if migrations have been applied. 2018-10-16 11:24:47 +01:00
akwizgran
47c91a96ae Compact the database at startup. 2018-10-16 11:13:37 +01:00
akwizgran
14befb957b Add support for v3 hidden service addresses. 2018-10-16 10:15:18 +01:00
akwizgran
4b7a81177c Static imports. 2018-10-15 14:46:40 +01:00
Torsten Grote
b464fe1653 Merge branch 'message-terminology' into 'master'
Use "text" to refer to message text

See merge request briar/briar!948
2018-10-15 13:22:31 +00:00
akwizgran
09c6f09805 Merge branch '1420-tor-status-update' into 'master'
Disable TorPlugin before applying changed settings

Closes #1420

See merge request briar/briar!953
2018-10-15 12:54:41 +00:00
Torsten Grote
a93093182d Disable TorPlugin before applying changed settings
The is necessary for two reasons:

1. Since Tor 0.3.4.8, it doesn't reconnect when changing the value of
   UseBridges via the control connection without also resetting
   DisableNetwork
2. The TorPlugin needs to set itself to a disconnected state for the UI
   to properly reflect this new state

Fixes #1420
2018-10-15 09:43:12 -03:00
akwizgran
9515e93857 Cancel discovery after 10 seconds and try to connect. 2018-10-15 11:04:46 +01:00
akwizgran
efe15df940 Remove static import of R's fields. 2018-10-15 11:04:46 +01:00
akwizgran
de611857cf Discover BT devices if no address is provided. 2018-10-15 11:04:46 +01:00
akwizgran
8935ec2c2e Don't wait for state change if BT is already discoverable. 2018-10-15 11:04:45 +01:00
akwizgran
bd00fb1c04 Ask for coarse location permission before adding a contact. 2018-10-15 11:04:45 +01:00
akwizgran
3192015cfd Ask for Bluetooth discoverability before adding a contact. 2018-10-15 11:04:45 +01:00
Torsten Grote
e776ee02b0 Merge branch 'tor-0.3.4.8' into 'master'
Upgrade Tor to 0.3.4.8

See merge request briar/briar!951
2018-10-11 22:44:45 +00:00
akwizgran
c0553ec11f Upgrade Linux Tor binaries to 0.3.4.8. 2018-10-11 15:05:39 +01:00
akwizgran
75a871a2f8 Upgrade Android Tor binaries to 0.3.4.8. 2018-10-11 14:38:18 +01:00
akwizgran
d6d3d5acef Merge branch '1240-no-empty-messages' into 'master'
Don't allow empty message bodies

See merge request briar/briar!949
2018-10-10 14:52:34 +00:00
Torsten Grote
a361a2613c Merge branch 'test-configurations' into 'master'
Update test configurations for Android Studio 3.2

See merge request briar/briar!950
2018-10-10 12:38:19 +00:00
akwizgran
b68dbd6a75 Merge branch 'upgrade-dependencies' into 'master'
Upgrade some of the things

See merge request briar/briar!935
2018-10-10 11:42:45 +00:00
akwizgran
f1e89a3ff4 Don't allow empty message bodies. 2018-10-10 10:57:41 +01:00
akwizgran
056c23167d Update test configurations for Android Studio 3.2. 2018-10-10 10:43:07 +01:00
akwizgran
79d5612645 Use "text" to refer to message text. 2018-10-10 10:40:30 +01:00
akwizgran
a030f92275 Merge branch 'headless' into 'master'
Add Briar headless client that exposes a REST API

See merge request briar/briar!931
2018-10-09 15:43:31 +00:00
Torsten Grote
b3615b4a77 briar-headless: Last round of review comments 2018-10-09 12:19:21 -03:00
akwizgran
8a15fb242a Merge branch 'briar-integration-test-transaction' into 'master'
Remove custom DB transaction code from BriarIntegrationTest

See merge request briar/briar!946
2018-10-09 14:16:23 +00:00
Torsten Grote
e3686186ee Fix closing server with ^C 2018-10-08 18:40:21 -03:00
akwizgran
18ae388137 Merge branch '1395-low-memory-crash' into 'master'
Don't use non-AppCompat theme for AppCompat activities

Closes #1395

See merge request briar/briar!947
2018-10-08 12:03:20 +00:00
Torsten Grote
775031e893 Don't use non-AppCompat theme for AppCompat activities
Fixes #1395
2018-10-05 16:50:11 -03:00
Torsten Grote
9f91b91a4f Remove custom DB transaction code from BriarIntegrationTest 2018-10-05 15:41:29 -03:00
Torsten Grote
280f3ba1fc briar-headless: POST text as JSON in body instead of form parameter 2018-10-05 15:23:31 -03:00
Torsten Grote
66619fd3a4 briar-headless: Next round of review comments 2018-10-05 15:23:31 -03:00
akwizgran
c7eb0cbb6d Include body of private request if present. 2018-10-05 15:23:31 -03:00
akwizgran
1617a95bb9 Only include "body" for headers that can have bodies. 2018-10-05 15:23:31 -03:00
Torsten Grote
6f54718756 Use short type labels in JSON API instead of long Java-like namespaces 2018-10-05 15:23:31 -03:00
Torsten Grote
ea749f2128 Minor improvements to JsonDict output classes 2018-10-05 15:23:31 -03:00
akwizgran
b4b0d3daa6 Allow null values in JsonDict. 2018-10-05 15:23:31 -03:00
akwizgran
609c90f57e Convert Map#put() to assignment. 2018-10-05 15:23:31 -03:00
akwizgran
5cf68fa134 Use JsonDict for blog post headers. 2018-10-05 15:23:31 -03:00
akwizgran
61c9c6b8eb Add visitor to dispatch output() dynamically. 2018-10-05 15:23:31 -03:00
akwizgran
e97608da40 Add test to show that static dispatch won't work. 2018-10-05 15:23:31 -03:00
akwizgran
0bb80b1a15 Add JsonDict class for JSON output. 2018-10-05 15:23:31 -03:00
akwizgran
bda52ea548 Use maps for JSON output. 2018-10-05 15:23:31 -03:00
Torsten Grote
cf033dc29d briar-headless: Address second round of review comments 2018-10-05 15:23:31 -03:00
Torsten Grote
c12cedc371 briar-headless: Address first round of review comments 2018-10-05 15:23:31 -03:00
Torsten Grote
4b5e9bd64f Ensure the use SecureRandom when creating authentication token 2018-10-05 15:23:31 -03:00
Torsten Grote
8d55911dab Add unit test for WebSocketController
Also move the controller into an event package
2018-10-05 15:23:31 -03:00
Torsten Grote
e381f83512 Last code cleanup before submitting merge request 2018-10-05 15:23:31 -03:00
Torsten Grote
e4c7f13832 Add a README.md with API documentation
Also fix some smaller issues found during writing the documentation
2018-10-05 15:23:31 -03:00
Torsten Grote
b089a204d3 Add support for websocket authentication via basic auth
The token should be used as username and the password left empty
2018-10-05 15:23:31 -03:00
Torsten Grote
85fcb34997 Add briar-headless Android Studio run configuration 2018-10-05 15:23:31 -03:00
Torsten Grote
d6d132a9cf Add Bearer Authentication to REST API 2018-10-05 15:23:31 -03:00
Torsten Grote
98d1ea7730 briar-headless: Add more controller tests
Current controller line coverage: 100%
2018-10-05 15:23:31 -03:00
Torsten Grote
159fd34c0c Use Conversation Manager for message retrieval 2018-10-05 15:23:31 -03:00
Torsten Grote
9e7a387ea4 Turn output classes into Kotlin data classes 2018-10-05 15:23:31 -03:00
Torsten Grote
138e520e6c briar-headless: Add command line arguments 2018-10-05 15:23:31 -03:00
Torsten Grote
5783c1dfd8 briar-headless: Add a websocket controller for private message events
Also version API URLs
2018-10-05 15:23:31 -03:00
Torsten Grote
348968018a Migrate REST classes to Kotlin and upgrade Javalin 2018-10-05 15:23:31 -03:00
Torsten Grote
33c509cd1f briar-headless: Add Kotlin and first unit test for blogs with Mockk 2018-10-05 15:23:31 -03:00
Torsten Grote
bea77151bd briar-headless: Add API to list all contacts 2018-10-05 15:23:31 -03:00
Torsten Grote
787e62345f Add simple MessagingController 2018-10-05 15:23:31 -03:00
Torsten Grote
48f6a3b91f Add Tor plugin to headless client and introduce new ConfigurationManager 2018-10-05 15:23:31 -03:00
Torsten Grote
a798e25bf2 Save app data always in $HOME/.briar for now 2018-10-05 15:23:31 -03:00
Torsten Grote
31e4045cf7 Try to shutdown cleanly when server stops or SIGINT is received 2018-10-05 15:23:31 -03:00
Torsten Grote
5334a8c9ca Add basic support for listing and writing blog posts 2018-10-05 15:23:31 -03:00
Torsten Grote
d11f1d2805 Add a poor man's argument to explicitly turn on verbose logging 2018-10-05 15:23:31 -03:00
Torsten Grote
0d1ebddcd2 Allow account creation and reading password from STDIN 2018-10-05 15:23:31 -03:00
Torsten Grote
6c296c1348 Proof-of-Concept Headless Client 2018-10-05 15:23:31 -03:00
akwizgran
87701e5f07 Merge branch 'transactional-db' into 'master'
Transactional DB interface

See merge request briar/briar!945
2018-10-05 15:19:40 +00:00
Torsten Grote
3aae01d152 Merge branch 'panic-app-list' into 'master'
Update list of panic button apps after installing app

Closes #1392

See merge request briar/briar!940
2018-10-05 14:18:44 +00:00
akwizgran
bc298ba68a Remove unnecessary final modifiers. 2018-10-05 09:34:41 +01:00
akwizgran
2623eaa149 Remove unnecessary throwing variants. 2018-10-05 09:32:01 +01:00
akwizgran
7359b6942a Use transactional DB interface for ForumManagerImpl. 2018-10-04 15:59:10 +01:00
akwizgran
3bcc532b4b Add transactional DB interface. 2018-10-04 15:56:21 +01:00
akwizgran
4d08c69779 Revert spurious changes to run configurations. 2018-10-03 13:08:00 +01:00
Torsten Grote
a6cd8937f7 Remove space reserved for icons from preferences
Works around https://issuetracker.google.com/issues/111907042

Might be replacable with a solution from
https://issuetracker.google.com/issues/111907042 in the future.
2018-10-03 12:58:49 +01:00
akwizgran
e8566906ef Update gradle-witness to exclude android.jar from dependencies. 2018-10-03 12:48:29 +01:00
akwizgran
929102ed60 Upgrade build tools to 28.0.3. 2018-10-03 12:48:29 +01:00
akwizgran
3b871f5932 Update ProGuard rules for new OkHttp version. 2018-10-03 12:48:29 +01:00
akwizgran
b972d1fc13 Update ACRA usage for new version. 2018-10-03 12:48:28 +01:00
akwizgran
ccbeee60a7 Upgrade Rome, OkHttp and jsoup libraries. 2018-10-03 12:48:28 +01:00
akwizgran
074b10e177 Upgrade JNA library. 2018-10-03 12:48:28 +01:00
akwizgran
031516ccce Upgrade curve25519-java library. 2018-10-03 12:48:28 +01:00
akwizgran
7d2f1abb94 Upgrade Gradle APT and Animal Sniffer plugins. 2018-10-03 12:48:28 +01:00
akwizgran
00b9c76bb8 Upgrade ACRA. 2018-10-03 12:48:28 +01:00
akwizgran
4d9fab85cb Upgrade zxing, material tap target libraries. 2018-10-03 12:48:28 +01:00
akwizgran
bd2514a299 Upgrade support library to 28.0.0. 2018-10-03 12:48:27 +01:00
akwizgran
e795efc7fc Bump compileSdkVersion for bramble-android. 2018-10-03 12:48:27 +01:00
akwizgran
6691d2164f Upgrade Gradle Android plugin and build tools. 2018-10-03 12:48:27 +01:00
Administrator
a384450c36 Merge branch '1373-format-numbers' into 'master'
Format numbers in locale as well (not all languages use the same)

See merge request briar/briar!943
2018-10-03 11:41:56 +00:00
akwizgran
b375e9873c Merge branch '1409-localize-crash-screen' into 'master'
Localize crash screen in language defined in settings

Closes #1409

See merge request briar/briar!944
2018-10-03 07:53:41 +00:00
Torsten Grote
cb30c3885a Localize crash screen in language defined in settings 2018-10-02 17:56:33 -03:00
Torsten Grote
6ee81eb24c Format numbers in locale as well (not all languages use the same)
Done according to
https://developer.android.com/training/basics/supporting-devices/languages#FormatNumbers
2018-10-02 17:31:23 -03:00
Torsten Grote
c14ebe82ce Merge branch '1365-keep-screen-on' into 'master'
Keep screen on while QR code viewfinder is open

See merge request briar/briar!942
2018-10-02 11:20:46 +00:00
Torsten Grote
00e9f894b1 Merge branch 'remove-tor-patch' into 'master'
Remove unused patches

See merge request briar/briar!941
2018-10-02 11:13:06 +00:00
akwizgran
499c586a59 Keep screen on while scanning QR code. 2018-10-02 12:03:29 +01:00
akwizgran
64f9ce7306 Remove unused patches. 2018-10-02 11:49:29 +01:00
akwizgran
39478a7914 Bump version numbers for 1.1.2 release. 2018-10-01 14:58:45 +01:00
akwizgran
112e71a9cb Bump version numbers for 1.0.2 release. 2018-10-01 14:56:08 +01:00
akwizgran
5650bef310 Update translations. 2018-10-01 14:56:08 +01:00
akwizgran
2a87171c49 Merge branch 'manual-screenshots' into 'master'
Create Screenshot of Conversation for Manual

Closes #1377

See merge request briar/briar!910
2018-10-01 13:41:05 +00:00
akwizgran
071d961ed1 Remove debug logging. 2018-09-28 11:31:22 +01:00
akwizgran
cb9efc5fec Fix lint warnings. 2018-09-28 11:28:47 +01:00
akwizgran
f9e292f734 Update panic app list after installing app. 2018-09-28 11:27:08 +01:00
akwizgran
15cb5409e7 Merge branch '1352-panic-ripple-fdroid' into 'master'
Fix Panic Button bugs

Closes #1109 and #1352

See merge request briar/briar!937
2018-09-28 09:57:18 +00:00
akwizgran
fd07dc006d Update comment. 2018-09-28 09:55:47 +01:00
akwizgran
cc87c4e37d Merge branch '1391-start-end-api15' into 'master'
RTL language layout fixes

Closes #1391

See merge request briar/briar!938
2018-09-28 08:45:17 +00:00
akwizgran
4a10e876f6 Merge branch '1389-notice-shadows' into 'master'
Fix notice shadows

Closes #1389

See merge request briar/briar!939
2018-09-28 08:43:06 +00:00
Torsten Grote
fad0057c4a Fix notice shadows 2018-09-27 20:32:13 -03:00
Torsten Grote
5aabfcea9a Unmirror checkboxes in RTL layouts 2018-09-27 19:09:08 -03:00
Torsten Grote
f7d928c774 Fix start/end margins for API 15
Fixes #1391
2018-09-27 19:07:13 -03:00
Torsten Grote
bd983d9796 Remove non-functional uninstall panic action
Fixes #1109
2018-09-27 18:37:57 -03:00
Torsten Grote
de8d1b7d96 Allow sign out by trusted non-paired panic apps 2018-09-27 18:25:31 -03:00
Torsten Grote
9155f62d0b Remove Amnesty International's key and add F-Droid Ripple key instead
Fixes #1352
2018-09-27 18:17:14 -03:00
Torsten Grote
c2b7f85b8e Remove code from TestDataCreator that breaks encapsulation 2018-09-24 12:37:11 -03:00
Torsten Grote
ae81eb3737 Throw AssertionError when creating an account while a database key is in memory 2018-09-24 12:37:11 -03:00
Torsten Grote
60d949c342 Refactor tests so that all test data is created in the first test 2018-09-24 12:37:11 -03:00
Torsten Grote
1c90e64894 Split up UI and Screenshot tests
Closes #1377
2018-09-24 12:37:06 -03:00
Torsten Grote
f0e2d5281f Create Screenshot of Conversation for Manual 2018-09-24 12:34:26 -03:00
555 changed files with 12228 additions and 6171 deletions

View File

@@ -36,6 +36,9 @@
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
</JavaCodeStyleSettings>
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
@@ -257,5 +260,11 @@
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<option name="PARAMETER_ANNOTATION_WRAP" value="1" />
<option name="VARIABLE_ANNOTATION_WRAP" value="1" />
<option name="ENUM_CONSTANTS_WRAP" value="1" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All in briar-headless" type="AndroidJUnit" factoryName="Android JUnit" nameIsGenerated="true">
<module name="briar-headless" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-headless" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<patterns />
<method />
</configuration>
</component>

View File

@@ -24,6 +24,7 @@
<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-java" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All in briar-headless" run_configuration_type="AndroidJUnit" />
</method>
</configuration>
</component>
</component>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-android" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-android" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-api" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-api" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-api" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-core" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-core" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in bramble-java" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-java" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea -Djava.library.path=libs" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bramble-java" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-android" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="briar-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-core" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="briar-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-core" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="H2 Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -1,6 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="HyperSQL Performance Test" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="bramble-core" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
@@ -11,12 +10,10 @@
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="ENV_VARIABLES" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method />
</configuration>

View File

@@ -0,0 +1,17 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="briar-headless" type="JetRunConfigurationType" factoryName="Kotlin" singleton="true">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="VM_PARAMETERS" value="" />
<option name="PROGRAM_PARAMETERS" value="-v" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PASS_PARENT_ENVS" value="true" />
<option name="MAIN_CLASS_NAME" value="org.briarproject.briar.headless.MainKt" />
<option name="WORKING_DIRECTORY" value="" />
<module name="briar-headless" />
<envs />
<method>
<option name="Gradle.BeforeRunTask" enabled="true" tasks="jar" externalProjectPath="$PROJECT_DIR$/briar-headless" vmOptions="" scriptParameters="" />
</method>
</configuration>
</component>

View File

@@ -1,16 +1,18 @@
import com.android.build.gradle.tasks.MergeResources
apply plugin: 'com.android.library'
apply plugin: 'witness'
apply from: 'witness.gradle'
android {
compileSdkVersion 27
buildToolsVersion '27.0.3'
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 10101
versionName "1.1.1"
versionCode 10105
versionName "1.1.5"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -28,9 +30,10 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
tor 'org.briarproject:tor-android:0.2.9.16@zip'
tor 'org.briarproject:tor-android:0.3.4.8@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.7@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
compileOnly 'javax.annotation:jsr250-api:1.0'
@@ -39,13 +42,29 @@ dependencies {
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
}
project.afterEvaluate {
copy {
from configurations.tor.collect { zipTree(it) }
into 'src/main/res/raw'
def torBinariesDir = 'src/main/res/raw'
task cleanTorBinaries {
doLast {
delete fileTree(torBinariesDir) { include '*.zip' }
}
}
clean.dependsOn cleanTorBinaries
task unpackTorBinaries {
doLast {
copy {
from configurations.tor.collect { zipTree(it) }
into torBinariesDir
}
}
dependsOn cleanTorBinaries
}
tasks.withType(MergeResources) {
inputs.dir torBinariesDir
dependsOn unpackTorBinaries
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble;
import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.network.AndroidNetworkModule;
public interface BrambleAndroidEagerSingletons {
void inject(AndroidBatteryModule.EagerSingletons init);
void inject(AndroidNetworkModule.EagerSingletons init);
}

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble;
import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.network.AndroidNetworkModule;
import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.system.AndroidSystemModule;
@@ -7,10 +8,15 @@ import org.briarproject.bramble.system.AndroidSystemModule;
import dagger.Module;
@Module(includes = {
AndroidBatteryModule.class,
AndroidNetworkModule.class,
AndroidSystemModule.class,
CircumventionModule.class
})
public class BrambleAndroidModule {
public static void initEagerSingletons(BrambleAndroidEagerSingletons c) {
c.inject(new AndroidBatteryModule.EagerSingletons());
c.inject(new AndroidNetworkModule.EagerSingletons());
}
}

View File

@@ -0,0 +1,84 @@
package org.briarproject.bramble.battery;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.Service;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.inject.Inject;
import static android.content.Intent.ACTION_BATTERY_CHANGED;
import static android.content.Intent.ACTION_POWER_CONNECTED;
import static android.content.Intent.ACTION_POWER_DISCONNECTED;
import static android.os.BatteryManager.BATTERY_STATUS_CHARGING;
import static android.os.BatteryManager.BATTERY_STATUS_FULL;
import static android.os.BatteryManager.EXTRA_STATUS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Logger.getLogger;
class AndroidBatteryManager implements BatteryManager, Service {
private static final Logger LOG =
getLogger(AndroidBatteryManager.class.getName());
private final Context appContext;
private final EventBus eventBus;
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile BroadcastReceiver batteryReceiver = null;
@Inject
AndroidBatteryManager(Application app, EventBus eventBus) {
this.appContext = app.getApplicationContext();
this.eventBus = eventBus;
}
@Override
public boolean isCharging() {
// Get the sticky intent for ACTION_BATTERY_CHANGED
IntentFilter filter = new IntentFilter(ACTION_BATTERY_CHANGED);
Intent i = appContext.registerReceiver(null, filter);
if (i == null) return false;
int status = i.getIntExtra(EXTRA_STATUS, -1);
return status == BATTERY_STATUS_CHARGING ||
status == BATTERY_STATUS_FULL;
}
@Override
public void startService() {
if (used.getAndSet(true)) throw new IllegalStateException();
batteryReceiver = new BatteryReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_POWER_CONNECTED);
filter.addAction(ACTION_POWER_DISCONNECTED);
appContext.registerReceiver(batteryReceiver, filter);
}
@Override
public void stopService() {
if (batteryReceiver != null)
appContext.unregisterReceiver(batteryReceiver);
}
private class BatteryReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context ctx, Intent i) {
String action = i.getAction();
if (LOG.isLoggable(INFO)) LOG.info("Received broadcast " + action);
if (ACTION_POWER_CONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(true));
else if (ACTION_POWER_DISCONNECTED.equals(action))
eventBus.broadcast(new BatteryEvent(false));
}
}
}

View File

@@ -0,0 +1,27 @@
package org.briarproject.bramble.battery;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidBatteryModule {
public static class EagerSingletons {
@Inject
BatteryManager batteryManager;
}
@Provides
@Singleton
BatteryManager provideBatteryManager(LifecycleManager lifecycleManager,
AndroidBatteryManager batteryManager) {
lifecycleManager.registerService(batteryManager);
return batteryManager;
}
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.network;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.network.NetworkManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
@@ -11,6 +12,11 @@ import dagger.Provides;
@Module
public class AndroidNetworkModule {
public static class EagerSingletons {
@Inject
NetworkManager networkManager;
}
@Provides
@Singleton
NetworkManager provideNetworkManager(LifecycleManager lifecycleManager,

View File

@@ -16,18 +16,27 @@ import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.IoUtils;
import java.io.Closeable;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_FINISHED;
import static android.bluetooth.BluetoothAdapter.ACTION_DISCOVERY_STARTED;
import static android.bluetooth.BluetoothAdapter.ACTION_SCAN_MODE_CHANGED;
import static android.bluetooth.BluetoothAdapter.ACTION_STATE_CHANGED;
import static android.bluetooth.BluetoothAdapter.EXTRA_SCAN_MODE;
@@ -37,8 +46,12 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERA
import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -47,8 +60,11 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private static final Logger LOG =
Logger.getLogger(AndroidBluetoothPlugin.class.getName());
private static final int MAX_DISCOVERY_MS = 10_000;
private final AndroidExecutor androidExecutor;
private final Context appContext;
private final Clock clock;
private volatile boolean wasEnabledByUs = false;
private volatile BluetoothStateReceiver receiver = null;
@@ -58,12 +74,13 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, AndroidExecutor androidExecutor,
Context appContext, SecureRandom secureRandom, Backoff backoff,
DuplexPluginCallback callback, int maxLatency) {
Context appContext, SecureRandom secureRandom, Clock clock,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback,
maxLatency);
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.clock = clock;
}
@Override
@@ -143,11 +160,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
@Override
void tryToClose(@Nullable BluetoothServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
IoUtils.tryToClose(ss, LOG, WARNING);
}
@Override
@@ -177,17 +190,77 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
s.connect();
return wrapSocket(s);
} catch (IOException e) {
tryToClose(s);
IoUtils.tryToClose(s, LOG, WARNING);
throw e;
}
}
private void tryToClose(@Nullable Closeable c) {
try {
if (c != null) c.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
@Override
@Nullable
DuplexTransportConnection discoverAndConnect(String uuid) {
if (adapter == null) return null;
for (String address : discoverDevices()) {
try {
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubMacAddress(address));
return connectTo(address, uuid);
} catch (IOException e) {
if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to "
+ scrubMacAddress(address));
}
}
}
LOG.info("Could not connect to any devices");
return null;
}
private Collection<String> discoverDevices() {
List<String> addresses = new ArrayList<>();
BlockingQueue<Intent> intents = new LinkedBlockingQueue<>();
DiscoveryReceiver receiver = new DiscoveryReceiver(intents);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DISCOVERY_STARTED);
filter.addAction(ACTION_DISCOVERY_FINISHED);
filter.addAction(ACTION_FOUND);
appContext.registerReceiver(receiver, filter);
try {
if (adapter.startDiscovery()) {
long now = clock.currentTimeMillis();
long end = now + MAX_DISCOVERY_MS;
while (now < end) {
Intent i = intents.poll(end - now, MILLISECONDS);
if (i == null) break;
String action = i.getAction();
if (ACTION_DISCOVERY_STARTED.equals(action)) {
LOG.info("Discovery started");
} else if (ACTION_DISCOVERY_FINISHED.equals(action)) {
LOG.info("Discovery finished");
break;
} else if (ACTION_FOUND.equals(action)) {
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
String address = d.getAddress();
if (LOG.isLoggable(INFO))
LOG.info("Discovered " + scrubMacAddress(address));
if (!addresses.contains(address))
addresses.add(address);
}
now = clock.currentTimeMillis();
}
} else {
LOG.info("Could not start discovery");
}
} catch (InterruptedException e) {
LOG.info("Interrupted while discovering devices");
Thread.currentThread().interrupt();
} finally {
LOG.info("Cancelling discovery");
adapter.cancelDiscovery();
appContext.unregisterReceiver(receiver);
}
// Shuffle the addresses so we don't always try the same one first
Collections.shuffle(addresses);
return addresses;
}
private class BluetoothStateReceiver extends BroadcastReceiver {
@@ -207,4 +280,18 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
}
}
}
private static class DiscoveryReceiver extends BroadcastReceiver {
private final BlockingQueue<Intent> intents;
private DiscoveryReceiver(BlockingQueue<Intent> intents) {
this.intents = intents;
}
@Override
public void onReceive(Context ctx, Intent intent) {
intents.add(intent);
}
}
}

View File

@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock;
import java.security.SecureRandom;
import java.util.concurrent.Executor;
@@ -33,17 +34,19 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private final Context appContext;
private final SecureRandom secureRandom;
private final EventBus eventBus;
private final Clock clock;
private final BackoffFactory backoffFactory;
public AndroidBluetoothPluginFactory(Executor ioExecutor,
AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom, EventBus eventBus,
SecureRandom secureRandom, EventBus eventBus, Clock clock,
BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor;
this.androidExecutor = androidExecutor;
this.appContext = appContext;
this.secureRandom = secureRandom;
this.eventBus = eventBus;
this.clock = clock;
this.backoffFactory = backoffFactory;
}
@@ -65,7 +68,7 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
connectionLimiter, ioExecutor, androidExecutor, appContext,
secureRandom, backoff, callback, MAX_LATENCY);
secureRandom, clock, backoff, callback, MAX_LATENCY);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -6,6 +6,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.PowerManager;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
@@ -41,17 +42,18 @@ class AndroidTorPlugin extends TorPlugin {
Context appContext, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Backoff backoff,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, backoff,
callback, architecture, maxLatency, maxIdleTime,
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext;
PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE);
assert pm != null;
if (pm == null) throw new AssertionError();
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
WAKE_LOCK_TAG, 1, MINUTES);
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.os.Build;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -48,6 +49,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
private final BackoffFactory backoffFactory;
private final ResourceProvider resourceProvider;
private final CircumventionProvider circumventionProvider;
private final BatteryManager batteryManager;
private final Clock clock;
public AndroidTorPluginFactory(Executor ioExecutor,
@@ -55,7 +57,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
NetworkManager networkManager, LocationUtils locationUtils,
EventBus eventBus, SocketFactory torSocketFactory,
BackoffFactory backoffFactory, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Clock clock) {
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Clock clock) {
this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.appContext = appContext;
@@ -66,6 +69,7 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
this.backoffFactory = backoffFactory;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager;
this.clock = clock;
}
@@ -104,8 +108,8 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
appContext, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, backoff,
callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin);
return plugin;
}

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.system;
import android.annotation.SuppressLint;
import android.app.Application;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -26,7 +27,7 @@ import static android.provider.Settings.Secure.ANDROID_ID;
@Immutable
@NotNullByDefault
class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
private static final int SEED_LENGTH = 32;
@@ -37,6 +38,7 @@ class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
appContext = app.getApplicationContext();
}
@SuppressLint("HardwareIds")
@Override
protected void writeToEntropyPool(DataOutputStream out) throws IOException {
super.writeToEntropyPool(out);
@@ -49,12 +51,14 @@ class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
String id = Settings.Secure.getString(contentResolver, ANDROID_ID);
if (id != null) out.writeUTF(id);
Parcel parcel = Parcel.obtain();
WifiManager wm =
(WifiManager) appContext.getSystemService(WIFI_SERVICE);
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs)
parcel.writeParcelable(config, 0);
WifiManager wm = (WifiManager) appContext.getApplicationContext()
.getSystemService(WIFI_SERVICE);
if (wm != null) {
List<WifiConfiguration> configs = wm.getConfiguredNetworks();
if (configs != null) {
for (WifiConfiguration config : configs)
parcel.writeParcelable(config, 0);
}
}
BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
if (bt != null) {
@@ -77,13 +81,13 @@ class AndroidSecureRandomProvider extends LinuxSecureRandomProvider {
// Based on https://android-developers.googleblog.com/2013/08/some-securerandom-thoughts.html
private void applyOpenSslFix() {
byte[] seed = new LinuxSecureRandomSpi().engineGenerateSeed(
byte[] seed = new UnixSecureRandomSpi().engineGenerateSeed(
SEED_LENGTH);
try {
// Seed the OpenSSL PRNG
Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_seed", byte[].class)
.invoke(null, seed);
.invoke(null, (Object) seed);
// Mix the output of the Linux PRNG into the OpenSSL PRNG
int bytesRead = (Integer) Class.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")

View File

@@ -11,15 +11,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.logging.Logger;
import static android.content.Context.MODE_PRIVATE;
import static android.os.Build.VERSION.SDK_INT;
public class AndroidUtils {
private static final Logger LOG =
Logger.getLogger(AndroidUtils.class.getName());
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
@@ -28,7 +25,7 @@ public class AndroidUtils {
@SuppressWarnings("deprecation")
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 21) {
if (SDK_INT >= 21) {
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
} else {
abis.add(Build.CPU_ABI);

View File

@@ -1,50 +1,57 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:26.1.3:protos-26.1.3.jar:818c9f256f141d9dafec03a1aa2b94d240b2c140acfd7ee31a8b3e6c2b9479e3',
'com.android.tools.analytics-library:shared:26.1.3:shared-26.1.3.jar:7110706c7ada96c8b6f5ca80c478291bc7899d46277de2c48527e045442401a3',
'com.android.tools.analytics-library:tracker:26.1.3:tracker-26.1.3.jar:4155424bf2ce4872da83332579a1707252bc66cbd77c5144fdc4483d0f2e1418',
'com.android.tools.build:apksig:3.1.3:apksig-3.1.3.jar:7e1f8e675a6e768e5b56405e41d6c3cc05befe62e601b04177de1029902c9c89',
'com.android.tools.build:builder-model:3.1.3:builder-model-3.1.3.jar:06ad1c422d679fc698451479cb40ba863849d67bfd1de23f6d2c16d78b024b0b',
'com.android.tools.build:builder-test-api:3.1.3:builder-test-api-3.1.3.jar:4d989f780436794f0f8b2f50e9e079b786571eac90f26c208ab2ae6d4012f389',
'com.android.tools.build:builder:3.1.3:builder-3.1.3.jar:8a1092012c89d0ec1ee2eff09c5708c71ef4482a6862df8d3a44a67fccace01c',
'com.android.tools.build:gradle-api:3.1.3:gradle-api-3.1.3.jar:01e4df521456aef66514336f1d492346730dd1fb8f6433a89f62da834941ed72',
'com.android.tools.build:manifest-merger:26.1.3:manifest-merger-26.1.3.jar:1e4fc7e932adb4607082409800e5e6fccb42e6c5360ae5990094bf522f3ada55',
'com.android.tools.ddms:ddmlib:26.1.3:ddmlib-26.1.3.jar:c54931cd68df5d1ea2923b3b320eae47cd2307a5a916bb8674c0acf93cd1d3cd',
'com.android.tools.external.com-intellij:intellij-core:26.1.3:intellij-core-26.1.3.jar:af67f5535fef2e1a28b1007a4acb8c5deb6a1e33b8afe7b11d012c9e778ebcec',
'com.android.tools.external.com-intellij:kotlin-compiler:26.1.3:kotlin-compiler-26.1.3.jar:c746d2859dc11cc05c84b692b3498d3a621e0929511f8440ee009c6557838fd4',
'com.android.tools.external.org-jetbrains:uast:26.1.3:uast-26.1.3.jar:3f3f6651d0c7685a77ecb22e9c82d6b49fdf24322c17360768dc530678f43265',
'com.android.tools.layoutlib:layoutlib-api:26.1.3:layoutlib-api-26.1.3.jar:10bc73ce706c45629872d6a999dbe12116df64e24f47ff93b7b13121ff57b4b0',
'com.android.tools.lint:lint-api:26.1.3:lint-api-26.1.3.jar:6f97323f9af8deda86278717885b5c927f3766757db89709f52d11d42b6fb751',
'com.android.tools.lint:lint-checks:26.1.3:lint-checks-26.1.3.jar:73c3d53784c9ce3e6d5968506581918e0179645d20809927ca4a001dd766b001',
'com.android.tools.lint:lint-gradle-api:26.1.3:lint-gradle-api-26.1.3.jar:7ca3c4866ec21dc21d53a9d86f752b77ace6f6c610a0c9dc877313856c733d9d',
'com.android.tools.lint:lint-gradle:26.1.3:lint-gradle-26.1.3.jar:db0c354b8f4b6f6637e31f91c564785a59ff896325331fcbc3de7458e0b6c067',
'com.android.tools.lint:lint-kotlin:26.1.3:lint-kotlin-26.1.3.jar:94e2b0f4565a241561cfb8fc1222bb3f132a3b98d2a90421dbb72ee8358e7d68',
'com.android.tools.lint:lint:26.1.3:lint-26.1.3.jar:8d5f32c989c6d191d712e90ad3ca2d1c409313599551d04d834caa44d26c78df',
'com.android.tools:annotations:26.1.3:annotations-26.1.3.jar:c950430b24ac5d58fc97e7283b8f0115f99587e76e08b4e1e2aaa780f2d77323',
'com.android.tools:common:26.1.3:common-26.1.3.jar:7c31a90581a148ab219f615a59667f0dded7fa39b248529784474da3c2274ef2',
'com.android.tools:dvlib:26.1.3:dvlib-26.1.3.jar:0cae87906f53d3f1088366a916ed180a7312b6d9919b90797f238875c8492855',
'com.android.tools:repository:26.1.3:repository-26.1.3.jar:52d4539cc68db91b261e2a33b2c8206b26e05539078758dc28cfb3854adb4f59',
'com.android.tools:sdk-common:26.1.3:sdk-common-26.1.3.jar:1948603ca9ff22c7ebb3178000bffa3a9dd2ca1cc5cb0c793cae08468b8fcfc1',
'com.android.tools:sdklib:26.1.3:sdklib-26.1.3.jar:4adcfaad9514607098d2c51503c39811112d3050f4d1e744c01c7f08f591032b',
'com.android.tools.analytics-library:protos:26.2.1:protos-26.2.1.jar:2f371f5b1f551e85ab08be4d6a2873471b3d44afd1ebf6aa3298f3b796bf691f',
'com.android.tools.analytics-library:shared:26.2.1:shared-26.2.1.jar:4c1e4e705fa4d45f23aaea230557f6508155012d9c296337787c1d7b26a97f5a',
'com.android.tools.analytics-library:tracker:26.2.1:tracker-26.2.1.jar:4a624ecc976539f755ddb0bb8dfc2dd3d08326cfec59a098dbd70f701ca7fb75',
'com.android.tools.build:aapt2:3.2.1-4818971:aapt2-3.2.1-4818971-linux.jar:f431b6f96c91a2c155144b091a9c97d9805c589fe8efc9c930b6cd346cb60a1e',
'com.android.tools.build:apksig:3.2.1:apksig-3.2.1.jar:2b46f2feffea66037aab29e4261b2433c190194a6ef97b958511eb157f2ccba5',
'com.android.tools.build:apkzlib:3.2.1:apkzlib-3.2.1.jar:c39ad0313905932431fe81c8899c2cf39a4d92ad6c4edcaa4b25432f461452aa',
'com.android.tools.build:builder-model:3.2.1:builder-model-3.2.1.jar:a9f68e6abcec122f9cb5ad352d3f05a3eb03acbcdca95e4d25c16310c2c965ff',
'com.android.tools.build:builder-test-api:3.2.1:builder-test-api-3.2.1.jar:533ac6c2b5884bb54967a33791f2628dfdfac7981af39417a333b43d4379b6be',
'com.android.tools.build:builder:3.2.1:builder-3.2.1.jar:aedcbfd115dbe91d09b4113e66ef50589b558d0aa3b2f133b1d867c9b87fae83',
'com.android.tools.build:gradle-api:3.2.1:gradle-api-3.2.1.jar:57cf0ac5ac1dca8afdb3f62b94265e776e7dcfa641cc3844fb53a05193de208d',
'com.android.tools.build:manifest-merger:26.2.1:manifest-merger-26.2.1.jar:8830573263361035d38cfdcb51e2db94029c93865b21334f5fbf8a27984281a6',
'com.android.tools.ddms:ddmlib:26.2.1:ddmlib-26.2.1.jar:a4bf0a29a19980bf27269465cc782064656750b77c26728f82f9e148b705218b',
'com.android.tools.external.com-intellij:intellij-core:26.2.1:intellij-core-26.2.1.jar:4925ad1892c2687cb1a63427d440ef519c8c59215fefe0dc5d541d5d411fcafe',
'com.android.tools.external.com-intellij:kotlin-compiler:26.2.1:kotlin-compiler-26.2.1.jar:daa064fd708f340ee25fb9823c4c74104ac77f1370b76d907eb9ae6daec0a2ae',
'com.android.tools.external.org-jetbrains:uast:26.2.1:uast-26.2.1.jar:f10f7258d2ab9189562cc0f9ad838c0378fdba439229173390a99de02ebac75b',
'com.android.tools.layoutlib:layoutlib-api:26.2.1:layoutlib-api-26.2.1.jar:ddbf4fca123733fa011595b1cc1f4ac2937ed327b60990711fafc33c775c2ade',
'com.android.tools.lint:lint-api:26.2.1:lint-api-26.2.1.jar:3b57e739de567b98bc9ab56c2c0ee66fc026b4adf5843e8f9804ca0666a6f66e',
'com.android.tools.lint:lint-checks:26.2.1:lint-checks-26.2.1.jar:c86f4cc9aaee722ee4ad70062f7b5af91e9b041914af27adc09f545ab0fb3bc6',
'com.android.tools.lint:lint-gradle-api:26.2.1:lint-gradle-api-26.2.1.jar:2283e7af32e301565f2a797e531f0fc8c648077d457afb3ffdddbee638976c2f',
'com.android.tools.lint:lint-gradle:26.2.1:lint-gradle-26.2.1.jar:8fd90b2f3ec788cbb9801c07ab3e1ea2255aa31a6093157d7ea0ff13d0315ecb',
'com.android.tools.lint:lint-kotlin:26.2.1:lint-kotlin-26.2.1.jar:7a6a5d2b18f69cf1b900d857c2632b4c683713c533295933b8b759f8cab4a877',
'com.android.tools.lint:lint:26.2.1:lint-26.2.1.jar:7848b82ae988b90dee259ae7c7e86e05cbf52db6cd21c8bbd38ce7df08f3f8c5',
'com.android.tools:annotations:26.2.1:annotations-26.2.1.jar:7391c6a1e080174b96e64ceb078dadd31ce4d8a2d2fee0ec65be202126f90f24',
'com.android.tools:common:26.2.1:common-26.2.1.jar:a50aab2d6411ff68f4004a87c7e93d87d8e980a0ec3b352246549897ea2d78e5',
'com.android.tools:dvlib:26.2.1:dvlib-26.2.1.jar:72a83bf2839b1df9b1fbf67ba45d1bfb9f966cd774da4320c762b2be8f1688aa',
'com.android.tools:repository:26.2.1:repository-26.2.1.jar:fa74dae09103faef703df38550ad8fa244c5b6d1bf90d6198be932292b3d9cc1',
'com.android.tools:sdk-common:26.2.1:sdk-common-26.2.1.jar:759d4b292ca69a35cf961fca377b54158fc6c88108978006999442e80a011cf4',
'com.android.tools:sdklib:26.2.1:sdklib-26.2.1.jar:248df7ad5eac4aeb6f96c394c76760de4b7b89ac056e54d0c21a739368b91b45',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed',
'com.google.code.gson:gson:2.7:gson-2.7.jar:2d43eb5ea9e133d2ee2405cc14f5ee08951b8361302fdd93494a3a997b508d32',
'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825',
'com.google.dagger:dagger-compiler:2.19:dagger-compiler-2.19.jar:27a4b202a2de908182edb261f8c0a264e08e5e4733d7514bc7fbf0d31da5c0fc',
'com.google.dagger:dagger-producers:2.19:dagger-producers-2.19.jar:a17663abe0fc38b676026950907d4c5f5e2bf338375415861eaff6e3bdb0b768',
'com.google.dagger:dagger-spi:2.19:dagger-spi-2.19.jar:e7a6379d82c841f6aac2866948ad1eed716528707814602842a8d844ce04e2e1',
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
'com.google.errorprone:error_prone_annotations:2.0.18:error_prone_annotations-2.0.18.jar:cb4cfad870bf563a07199f3ebea5763f0dec440fcda0b318640b1feaa788656b',
'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
'com.google.guava:guava:22.0:guava-22.0.jar:1158e94c7de4da480873f0b4ab4a1da14c0d23d4b1902cc94a58a6f0f9ab579e',
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8',
'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.guava:guava:23.0:guava-23.0.jar:7baa80df284117e5b945b19b98d367a85ea7b7801bd358ff657946c3bd1b6596',
'com.google.guava:guava:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:40ceb7157feb263949e0f503fe5f71689333a621021aa20ce0d0acee3badaa0f',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:2.21:istack-commons-runtime-2.21.jar:c33e67a0807095f02a0e2da139412dd7c4f9cc1a4c054b3e434f96831ba950f4',
'com.sun.xml.fastinfoset:FastInfoset:1.2.13:FastInfoset-1.2.13.jar:27a77db909f3c2833c0b1a37c55af1db06045118ad2eed96ce567b6632bce038',
'commons-codec:commons-codec:1.6:commons-codec-1.6.jar:54b34e941b8e1414bd3e40d736efd3481772dc26db3296f6aa45cec9f6203d86',
'commons-logging:commons-logging:1.1.1:commons-logging-1.1.1.jar:ce6f913cad1f0db3aad70186d65c5bc7ffcc9a99e3fe8e0b137312819f7c362f',
'commons-codec:commons-codec:1.9:commons-codec-1.9.jar:ad19d2601c3abf0b946b5c3a4113e226a8c1e3305e395b90013b78dd94a723ce',
'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',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
@@ -55,13 +62,15 @@ dependencyVerification {
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8',
'org.apache.commons:commons-compress:1.12:commons-compress-1.12.jar:2c1542faf343185b7cab9c3d55c8ae5471d6d095d3887a4adefdbdf2984dc0b6',
'org.apache.httpcomponents:httpclient:4.2.6:httpclient-4.2.6.jar:362e9324ee7c697e21279e20077b52737ddef3f1b2c1a7abe5ad34b465145550',
'org.apache.httpcomponents:httpcore:4.2.5:httpcore-4.2.5.jar:e5e82da4cc66c8d917bbf743e3c0752efe8522735e7fc9dbddb65bccea81cfe9',
'org.apache.httpcomponents:httpmime:4.1:httpmime-4.1.jar:31629566148e8a47688ae43b420abc3ecd783ed15b33bebc00824bf24c9b15aa',
'org.apache.httpcomponents:httpclient:4.5.2:httpclient-4.5.2.jar:0dffc621400d6c632f55787d996b8aeca36b30746a716e079a985f24d8074057',
'org.apache.httpcomponents:httpcore:4.4.5:httpcore-4.4.5.jar:64d5453874cab7e40a7065cb01a9a9ca1053845a9786b478878b679e0580cec3',
'org.apache.httpcomponents:httpmime:4.5.2:httpmime-4.5.2.jar:231a3f7e4962053db2be8461d5422e68fc458a3a7dd7d8ada803a348e21f8f07',
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
'org.briarproject:obfs4proxy-android:0.0.7:obfs4proxy-android-0.0.7.zip:abdfb5d889d848de9bf214f9276abbf454808a505b870819eccc9a9e985bf617',
'org.briarproject:tor-android:0.3.4.8:tor-android-0.3.4.8.zip:989a0352d9d8d8172cd6c2137654e165e5d2beb10ed1211bab3814e224ad1926',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
@@ -70,9 +79,10 @@ dependencyVerification {
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jetbrains.kotlin:kotlin-reflect:1.2.0:kotlin-reflect-1.2.0.jar:4f48a872bad6e4d9c053f4ad610d11e4012ad7e58dc19a03dd5eb811f36069dd',
'org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0:kotlin-stdlib-jre7-1.2.0.jar:c7a20fb951d437797afe8980aff6c1e5a03f310c661ba58ba1d4fa90cb0f2926',
'org.jetbrains.kotlin:kotlin-stdlib-jre8:1.2.0:kotlin-stdlib-jre8-1.2.0.jar:633524eee6ef1941f7cb1dab7ee3927b0a221ceee9047aeb5515f4cbb990c82a',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.0:kotlin-stdlib-1.2.0.jar:05cfd9f5ac0b41910703a8925f7211a495909b27a2ffdd1c5106f1689aeafcd4',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.71:kotlin-stdlib-common-1.2.71.jar:63999687ff2fce8a592dd180ffbbf8f1d21c26b4044c55cdc74ff3cf3b3cf328',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.71:kotlin-stdlib-jdk7-1.2.71.jar:b136bd61b240e07d4d92ce00d3bd1dbf584400a7bf5f220c2f3cd22446858082',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.71:kotlin-stdlib-jdk8-1.2.71.jar:ac3c8abf47790b64b4f7e2509a53f0c145e061ac1612a597520535d199946ea9',
'org.jetbrains.kotlin:kotlin-stdlib:1.2.71:kotlin-stdlib-1.2.71.jar:4c895c270b87f5fec2a2796e1d89c15407ee821de961527c28588bb46afbc68b',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',
@@ -81,11 +91,11 @@ dependencyVerification {
'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16',
'org.jvnet.staxex:stax-ex:1.7.7:stax-ex-1.7.7.jar:a31ff7d77163c0deb09e7fee59ad35ae44c2cee2cc8552a116ccd1583d813fb4',
'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80',
'org.ow2.asm:asm-analysis:5.1:asm-analysis-5.1.jar:a34658f5c5de4b573eef21131cc32cc25f7b66407944f312b28ec2e56abb1fa9',
'org.ow2.asm:asm-commons:5.1:asm-commons-5.1.jar:97b3786e1f55e74bddf8ad102bf50e33bbcbc1f6b7fd7b36f0bbbb25cd4981be',
'org.ow2.asm:asm-tree:5.1:asm-tree-5.1.jar:c0de2bbc4cb8297419659813ecd4ed1d077ed1dd5c1f5544cc5143e493e84c10',
'org.ow2.asm:asm-util:5.1:asm-util-5.1.jar:ee032c39ae5e3cd099148fbba9a2124f9ed613e5cb93e03ee0fa8808ce364040',
'org.ow2.asm:asm-analysis:6.0:asm-analysis-6.0.jar:2f1a6387219c3a6cc4856481f221b03bd9f2408a326d416af09af5d6f608c1f4',
'org.ow2.asm:asm-commons:6.0:asm-commons-6.0.jar:f1bce5c648a96a017bdcd01fe5d59af9845297fd7b79b81c015a6fbbd9719abf',
'org.ow2.asm:asm-tree:6.0:asm-tree-6.0.jar:887998fb69727c8759e4d253f856822801e33f9fd4caa566b3ac58ee92106215',
'org.ow2.asm:asm-util:6.0:asm-util-6.0.jar:356afebdb0f870175262e5188f8709a3b17aa2a5a6a4b0340b04d4b449bca5f6',
'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220',
'org.ow2.asm:asm:5.1:asm-5.1.jar:d2da399a9967c69f0a21739256fa79d284222c223082cacadc17372244764b54',
'org.ow2.asm:asm:6.0:asm-6.0.jar:dd8971c74a4e697899a8e95caae4ea8760ea6c486dc6b97b1795e75760420461',
]
}

View File

@@ -7,15 +7,13 @@ apply plugin: 'witness'
apply from: 'witness.gradle'
dependencies {
implementation "com.google.dagger:dagger:2.0.2"
implementation "com.google.dagger:dagger:2.19"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation 'junit:junit:4.12'
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class Pair<A, B> {
private final A first;
private final B second;
public Pair(A first, B second) {
this.first = first;
this.second = second;
}
public A getFirst() {
return first;
}
public B getSecond() {
return second;
}
}

View File

@@ -38,4 +38,18 @@ public abstract class StringMap extends Hashtable<String, String> {
public void putInt(String key, int value) {
put(key, String.valueOf(value));
}
public long getLong(String key, long defaultValue) {
String s = get(key);
if (s == null) return defaultValue;
try {
return Long.valueOf(s);
} catch (NumberFormatException e) {
return defaultValue;
}
}
public void putLong(String key, long value) {
put(key, String.valueOf(value));
}
}

View File

@@ -0,0 +1,6 @@
package org.briarproject.bramble.api.battery;
public interface BatteryManager {
boolean isCharging();
}

View File

@@ -0,0 +1,19 @@
package org.briarproject.bramble.api.battery.event;
import org.briarproject.bramble.api.event.Event;
/**
* An event that is broadcast when the device starts or stops charging.
*/
public class BatteryEvent extends Event {
private final boolean charging;
public BatteryEvent(boolean charging) {
this.charging = charging;
}
public boolean isCharging() {
return charging;
}
}

View File

@@ -1,7 +1,6 @@
package org.briarproject.briar.client;
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataParser;
@@ -12,7 +11,7 @@ import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
import javax.annotation.concurrent.Immutable;
@@ -62,5 +61,4 @@ public abstract class BdfIncomingMessageHook implements IncomingMessageHook {
throw new InvalidMessageException(e);
}
}
}

View File

@@ -9,7 +9,7 @@ import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageContext;
import org.briarproject.bramble.api.sync.ValidationManager.MessageValidator;
import org.briarproject.bramble.api.sync.validation.MessageValidator;
import org.briarproject.bramble.api.system.Clock;
import java.util.logging.Logger;
@@ -48,12 +48,8 @@ public abstract class BdfMessageValidator implements MessageValidator {
throw new InvalidMessageException(
"Timestamp is too far in the future");
}
byte[] body = m.getBody();
if (body.length == 0) {
throw new InvalidMessageException("Message is too short");
}
try {
BdfList bodyList = clientHelper.toList(body);
BdfList bodyList = clientHelper.toList(m.getBody());
BdfMessageContext result = validateMessage(m, g, bodyList);
Metadata meta = metadataEncoder.encode(result.getDictionary());
return new MessageContext(meta, result.getDependencies());

View File

@@ -4,8 +4,12 @@ import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@Immutable
@NotNullByDefault
public class Contact {
@@ -13,13 +17,21 @@ public class Contact {
private final ContactId id;
private final Author author;
private final AuthorId localAuthorId;
@Nullable
private final String alias;
private final boolean verified, active;
public Contact(ContactId id, Author author, AuthorId localAuthorId,
boolean verified, boolean active) {
@Nullable String alias, boolean verified, boolean active) {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
}
this.id = id;
this.author = author;
this.localAuthorId = localAuthorId;
this.alias = alias;
this.verified = verified;
this.active = active;
}
@@ -36,6 +48,11 @@ public class Contact {
return localAuthorId;
}
@Nullable
public String getAlias() {
return alias;
}
public boolean isVerified() {
return verified;
}

View File

@@ -5,11 +5,14 @@ import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
import javax.annotation.Nullable;
@NotNullByDefault
public interface ContactManager {
@@ -93,6 +96,18 @@ public interface ContactManager {
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(ContactId c, @Nullable String alias)
throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
@@ -105,6 +120,16 @@ public interface ContactManager {
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(AuthorId a) throws DbException;
/**
* Returns the {@link AuthorInfo} for the given author.
*/
AuthorInfo getAuthorInfo(Transaction txn, AuthorId a) throws DbException;
interface ContactHook {
void addingContact(Transaction txn, Contact c) throws DbException;

View File

@@ -0,0 +1,71 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.bramble.util.StringUtils.toHexString;
@NotNullByDefault
public class BdfStringUtils {
public static String toString(@Nullable Object o) throws FormatException {
return toString(o, 0);
}
private static String toString(@Nullable Object o, int indent)
throws FormatException {
if (o == null || o == NULL_VALUE) return "null";
if (o instanceof Boolean) return o.toString();
if (o instanceof Number) return o.toString();
if (o instanceof String) return "\"" + o + "\"";
if (o instanceof Bytes)
return "x" + toHexString(((Bytes) o).getBytes());
if (o instanceof byte[])
return "x" + toHexString((byte[]) o);
if (o instanceof List) {
List<?> list = (List) o;
StringBuilder sb = new StringBuilder();
sb.append("[\n");
int i = 0, size = list.size();
for (Object e : list) {
indent(sb, indent + 1);
sb.append(toString(e, indent + 1));
if (i++ < size - 1) sb.append(',');
sb.append('\n');
}
indent(sb, indent);
sb.append(']');
return sb.toString();
}
if (o instanceof Map) {
Map<?, ?> map = (Map) o;
StringBuilder sb = new StringBuilder();
sb.append("{\n");
int i = 0, size = map.size();
for (Entry e : map.entrySet()) {
indent(sb, indent + 1);
sb.append(toString(e.getKey(), indent + 1));
sb.append(": ");
sb.append(toString(e.getValue(), indent + 1));
if (i++ < size - 1) sb.append(',');
sb.append('\n');
}
indent(sb, indent);
sb.append('}');
return sb.toString();
}
throw new FormatException();
}
private static void indent(StringBuilder sb, int indent) {
for (int i = 0; i < indent; i++) sb.append('\t');
}
}

View File

@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.validation.MessageState;
import org.briarproject.bramble.api.transport.KeySet;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
@@ -28,8 +29,6 @@ import java.util.Map;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.sync.ValidationManager.State;
/**
* Encapsulates the database implementation and exposes high-level operations
* to other components.
@@ -76,6 +75,27 @@ public interface DatabaseComponent {
*/
void endTransaction(Transaction txn);
/**
* Runs the given task within a transaction.
*/
<E extends Exception> void transaction(boolean readOnly,
DbRunnable<E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task.
*/
<R, E extends Exception> R transactionWithResult(boolean readOnly,
DbCallable<R, E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task, which may be null.
*/
@Nullable
<R, E extends Exception> R transactionWithNullableResult(boolean readOnly,
NullableDbCallable<R, E> task) throws DbException, E;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
@@ -353,12 +373,12 @@ public interface DatabaseComponent {
/**
* Returns the IDs and states of all dependencies of the given message.
* For missing dependencies and dependencies in other groups, the state
* {@link State UNKNOWN} is returned.
* {@link MessageState UNKNOWN} is returned.
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependencies(Transaction txn, MessageId m)
throws DbException;
Map<MessageId, MessageState> getMessageDependencies(Transaction txn,
MessageId m) throws DbException;
/**
* Returns the IDs and states of all dependents of the given message.
@@ -367,15 +387,16 @@ public interface DatabaseComponent {
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependents(Transaction txn, MessageId m)
throws DbException;
Map<MessageId, MessageState> getMessageDependents(Transaction txn,
MessageId m) throws DbException;
/**
* Gets the validation and delivery state of the given message.
* <p/>
* Read-only.
*/
State getMessageState(Transaction txn, MessageId m) throws DbException;
MessageState getMessageState(Transaction txn, MessageId m)
throws DbException;
/**
* Returns the status of the given delivered message with respect to the
@@ -502,6 +523,12 @@ public interface DatabaseComponent {
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for the contact or unsets it if alias is null.
*/
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets the given group's visibility to the given contact.
*/
@@ -516,7 +543,7 @@ public interface DatabaseComponent {
/**
* Sets the validation and delivery state of the given message.
*/
void setMessageState(Transaction txn, MessageId m, State state)
void setMessageState(Transaction txn, MessageId m, MessageState state)
throws DbException;
/**

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface DbCallable<R, E extends Exception> {
R call(Transaction txn) throws DbException, E;
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface DbRunnable<E extends Exception> {
void run(Transaction txn) throws DbException, E;
}

View File

@@ -6,6 +6,10 @@ public interface MigrationListener {
* This is called when a migration is started while opening the database.
* It will be called once for each migration being applied.
*/
void onMigrationRun();
void onDatabaseMigration();
/**
* This is called when compaction is started while opening the database.
*/
void onDatabaseCompaction();
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface NullableDbCallable<R, E extends Exception> {
@Nullable
R call(Transaction txn) throws DbException, E;
}

View File

@@ -16,10 +16,6 @@ import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_K
@NotNullByDefault
public class Author implements Nameable {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES
}
/**
* The current version of the author structure.
*/

View File

@@ -0,0 +1,56 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class AuthorInfo {
public enum Status {
NONE, ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES;
public boolean isContact() {
return this == UNVERIFIED || this == VERIFIED;
}
}
private final Status status;
@Nullable
private final String alias;
public AuthorInfo(Status status, @Nullable String alias) {
this.status = status;
this.alias = alias;
}
public AuthorInfo(Status status) {
this(status, null);
}
public Status getStatus() {
return status;
}
@Nullable
public String getAlias() {
return alias;
}
@Override
public int hashCode() {
int hashCode = status.ordinal();
if (alias != null) hashCode += alias.hashCode();
return hashCode;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof AuthorInfo)) return false;
AuthorInfo info = (AuthorInfo) o;
return status == info.status &&
(alias == null ? info.alias == null : alias.equals(info.alias));
}
}

View File

@@ -3,7 +3,6 @@ package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author.Status;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
@@ -37,14 +36,4 @@ public interface IdentityManager {
*/
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/**
* Returns the {@link Status} of the given author.
*/
Status getAuthorStatus(AuthorId a) throws DbException;
/**
* Returns the {@link Status} of the given author.
*/
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
}

View File

@@ -21,7 +21,7 @@ public interface KeyAgreementConstants {
/**
* The connection timeout in milliseconds.
*/
long CONNECTION_TIMEOUT = 20 * 1000;
long CONNECTION_TIMEOUT = 60_000;
/**
* The transport identifier for Bluetooth.

View File

@@ -34,7 +34,8 @@ public interface LifecycleManager {
*/
enum LifecycleState {
STARTING, MIGRATING_DATABASE, STARTING_SERVICES, RUNNING, STOPPING;
STARTING, MIGRATING_DATABASE, COMPACTING_DATABASE, STARTING_SERVICES,
RUNNING, STOPPING;
public boolean isAfter(LifecycleState state) {
return ordinal() > state.ordinal();

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.nullsafety;
import javax.annotation.Nullable;
@NotNullByDefault
public class NullSafety {
/**
* Stand-in for `Objects.requireNonNull()`.
*/
public static <T> T requireNonNull(@Nullable T t) {
if (t == null) throw new NullPointerException();
return t;
}
}

View File

@@ -4,7 +4,8 @@ public interface TorConstants {
TransportId ID = new TransportId("org.briarproject.bramble.tor");
String PROP_ONION = "onion";
String PROP_ONION_V2 = "onion";
String PROP_ONION_V3 = "onion3";
int SOCKS_PORT = 59050;
int CONTROL_PORT = 59051;

View File

@@ -16,6 +16,7 @@ public class Message {
private final byte[] body;
public Message(MessageId id, GroupId groupId, long timestamp, byte[] body) {
if (body.length == 0) throw new IllegalArgumentException();
if (body.length > MAX_MESSAGE_BODY_LENGTH)
throw new IllegalArgumentException();
this.id = id;

View File

@@ -1,87 +0,0 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* Responsible for managing message validators and passing them messages to
* validate.
*/
@NotNullByDefault
public interface ValidationManager {
enum State {
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
private final int value;
State(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static State fromValue(int value) {
for (State s : values()) if (s.value == value) return s;
throw new IllegalArgumentException();
}
}
/**
* Registers the message validator for the given client. This method
* should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerMessageValidator(ClientId c, int majorVersion,
MessageValidator v);
/**
* Registers the incoming message hook for the given client. The hook will
* be called once for each incoming message that passes validation. This
* method should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerIncomingMessageHook(ClientId c, int majorVersion,
IncomingMessageHook hook);
interface MessageValidator {
/**
* Validates the given message and returns its metadata and
* dependencies.
*/
MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException;
}
interface IncomingMessageHook {
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if an InvalidMessageException is thrown,
* the message will be permanently invalidated.
* @throws InvalidMessageException for any non-database error
* that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as InvalidMessageException!
*/
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException;
}
}

View File

@@ -3,11 +3,10 @@ package org.briarproject.bramble.api.sync.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.validation.MessageState;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.sync.ValidationManager.State;
/**
* An event that is broadcast when a message state changed.
*/
@@ -17,10 +16,10 @@ public class MessageStateChangedEvent extends Event {
private final MessageId messageId;
private final boolean local;
private final State state;
private final MessageState state;
public MessageStateChangedEvent(MessageId messageId, boolean local,
State state) {
MessageState state) {
this.messageId = messageId;
this.local = local;
this.state = state;
@@ -34,7 +33,7 @@ public class MessageStateChangedEvent extends Event {
return local;
}
public State getState() {
public MessageState getState() {
return state;
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
public interface IncomingMessageHook {
/**
* Called once for each incoming message that passes validation.
*
* @return whether or not this message should be shared
* @throws DbException Should only be used for real database errors.
* If this is thrown, delivery will be attempted again at next startup,
* whereas if an InvalidMessageException is thrown,
* the message will be permanently invalidated.
* @throws InvalidMessageException for any non-database error
* that occurs while handling remotely created data.
* This includes errors that occur while handling locally created data
* in a context controlled by remotely created data
* (for example, parsing the metadata of a dependency
* of an incoming message).
* Throwing this will delete the incoming message and its metadata
* marking it as invalid in the database.
* Never rethrow DbException as InvalidMessageException!
*/
boolean incomingMessage(Transaction txn, Message m, Metadata meta)
throws DbException, InvalidMessageException;
}

View File

@@ -0,0 +1,21 @@
package org.briarproject.bramble.api.sync.validation;
public enum MessageState {
UNKNOWN(0), INVALID(1), PENDING(2), DELIVERED(3);
private final int value;
MessageState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static MessageState fromValue(int value) {
for (MessageState s : values()) if (s.value == value) return s;
throw new IllegalArgumentException();
}
}

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageContext;
public interface MessageValidator {
/**
* Validates the given message and returns its metadata and
* dependencies.
*/
MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException;
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.sync.validation;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
/**
* Responsible for managing message validators and passing them messages to
* validate.
*/
@NotNullByDefault
public interface ValidationManager {
/**
* Registers the {@link MessageValidator} for the given client. This method
* should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerMessageValidator(ClientId c, int majorVersion,
MessageValidator v);
/**
* Registers the {@link IncomingMessageHook} for the given client. The hook
* will be called once for each incoming message that passes validation.
* This method should be called before
* {@link LifecycleManager#startServices(SecretKey)}.
*/
void registerIncomingMessageHook(ClientId c, int majorVersion,
IncomingMessageHook hook);
}

View File

@@ -1,5 +1,7 @@
package org.briarproject.bramble.util;
import org.briarproject.bramble.api.FormatException;
public class ByteUtils {
/**
@@ -12,15 +14,26 @@ public class ByteUtils {
*/
public static final long MAX_32_BIT_UNSIGNED = 4294967295L; // 2^32 - 1
/** The number of bytes needed to encode a 16-bit integer. */
/**
* The number of bytes needed to encode a 16-bit integer.
*/
public static final int INT_16_BYTES = 2;
/** The number of bytes needed to encode a 32-bit integer. */
/**
* The number of bytes needed to encode a 32-bit integer.
*/
public static final int INT_32_BYTES = 4;
/** The number of bytes needed to encode a 64-bit integer. */
/**
* The number of bytes needed to encode a 64-bit integer.
*/
public static final int INT_64_BYTES = 8;
/**
* The maximum number of bytes needed to encode a variable-length integer.
*/
public static final int MAX_VARINT_BYTES = 9;
public static void writeUint16(int src, byte[] dest, int offset) {
if (src < 0) throw new IllegalArgumentException();
if (src > MAX_16_BIT_UNSIGNED) throw new IllegalArgumentException();
@@ -55,6 +68,42 @@ public class ByteUtils {
dest[offset + 7] = (byte) (src & 0xFF);
}
/**
* Returns the number of bytes needed to represent 'src' as a
* variable-length integer.
* <p>
* 'src' must not be negative.
*/
public static int getVarIntBytes(long src) {
if (src < 0) throw new IllegalArgumentException();
int len = 1;
while ((src >>= 7) > 0) len++;
return len;
}
/**
* Writes 'src' to 'dest' as a variable-length integer, starting at
* 'offset', and returns the number of bytes written.
* <p>
* `src` must not be negative.
*/
public static int writeVarInt(long src, byte[] dest, int offset) {
if (src < 0) throw new IllegalArgumentException();
int len = getVarIntBytes(src);
if (dest.length < offset + len) throw new IllegalArgumentException();
// Work backwards from the end
int end = offset + len - 1;
for (int i = end; i >= offset; i--) {
// Encode 7 bits
dest[i] = (byte) (src & 0x7F);
// Raise the continuation flag, except for the last byte
if (i < end) dest[i] |= (byte) 0x80;
// Shift out the bits that were encoded
src >>= 7;
}
return len;
}
public static int readUint16(byte[] src, int offset) {
if (src.length < offset + INT_16_BYTES)
throw new IllegalArgumentException();
@@ -83,14 +132,46 @@ public class ByteUtils {
| (src[offset + 7] & 0xFFL);
}
public static int readUint(byte[] src, int bits) {
if (src.length << 3 < bits) throw new IllegalArgumentException();
int dest = 0;
for (int i = 0; i < bits; i++) {
if ((src[i >> 3] & 128 >> (i & 7)) != 0) dest |= 1 << bits - i - 1;
/**
* Returns the length in bytes of a variable-length integer encoded in
* 'src' starting at 'offset'.
*
* @throws FormatException if there is not a valid variable-length integer
* at the specified position.
*/
public static int getVarIntBytes(byte[] src, int offset)
throws FormatException {
if (src.length < offset) throw new IllegalArgumentException();
for (int i = 0; i < MAX_VARINT_BYTES && offset + i < src.length; i++) {
// If the continuation flag is lowered, this is the last byte
if ((src[offset + i] & 0x80) == 0) return i + 1;
}
if (dest < 0) throw new AssertionError();
if (dest >= 1 << bits) throw new AssertionError();
return dest;
// We've read 9 bytes or reached the end of the input without finding
// the last byte
throw new FormatException();
}
/**
* Reads a variable-length integer from 'src' starting at 'offset' and
* returns it.
*
* @throws FormatException if there is not a valid variable-length integer
* at the specified position.
*/
public static long readVarInt(byte[] src, int offset)
throws FormatException {
if (src.length < offset) throw new IllegalArgumentException();
long dest = 0;
for (int i = 0; i < MAX_VARINT_BYTES && offset + i < src.length; i++) {
// Decode 7 bits
dest |= src[offset + i] & 0x7F;
// If the continuation flag is lowered, this is the last byte
if ((src[offset + i] & 0x80) == 0) return dest;
// Make room for the next 7 bits
dest <<= 7;
}
// We've read 9 bytes or reached the end of the input without finding
// the last byte
throw new FormatException();
}
}

View File

@@ -8,12 +8,15 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
public class IoUtils {
@@ -54,16 +57,35 @@ public class IoUtils {
out.flush();
out.close();
} catch (IOException e) {
tryToClose(in);
tryToClose(out);
tryToClose(in, LOG, WARNING);
tryToClose(out, LOG, WARNING);
}
}
private static void tryToClose(@Nullable Closeable c) {
public static void tryToClose(@Nullable Closeable c, Logger logger,
Level level) {
try {
if (c != null) c.close();
} catch (IOException e) {
// We did our best
logException(logger, level, e);
}
}
public static void tryToClose(@Nullable Socket s, Logger logger,
Level level) {
try {
if (s != null) s.close();
} catch (IOException e) {
logException(logger, level, e);
}
}
public static void tryToClose(@Nullable ServerSocket ss, Logger logger,
Level level) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
logException(logger, level, e);
}
}

View File

@@ -10,8 +10,6 @@ public class OsUtils {
@Nullable
private static final String os = System.getProperty("os.name");
@Nullable
private static final String version = System.getProperty("os.version");
@Nullable
private static final String vendor = System.getProperty("java.vendor");
public static boolean isWindows() {

View File

@@ -47,7 +47,7 @@ public class StringUtils {
try {
return s.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
throw new AssertionError(e);
}
}
@@ -63,7 +63,7 @@ public class StringUtils {
try {
return decoder.decode(buffer).toString();
} catch (CharacterCodingException e) {
throw new RuntimeException(e);
throw new AssertionError(e);
}
}

View File

@@ -0,0 +1,42 @@
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.NONE;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
public class AuthorInfoTest extends BrambleTestCase {
@Test
public void testEquals() {
assertEquals(
new AuthorInfo(NONE),
new AuthorInfo(NONE, null)
);
assertEquals(
new AuthorInfo(NONE, "test"),
new AuthorInfo(NONE, "test")
);
assertNotEquals(
new AuthorInfo(NONE),
new AuthorInfo(VERIFIED)
);
assertNotEquals(
new AuthorInfo(NONE, "test"),
new AuthorInfo(NONE)
);
assertNotEquals(
new AuthorInfo(NONE),
new AuthorInfo(NONE, "test")
);
assertNotEquals(
new AuthorInfo(NONE, "a"),
new AuthorInfo(NONE, "b")
);
}
}

View File

@@ -0,0 +1,24 @@
package org.briarproject.bramble.test;
import org.briarproject.bramble.api.system.Clock;
import java.util.concurrent.atomic.AtomicLong;
public class SettableClock implements Clock {
private final AtomicLong time;
public SettableClock(AtomicLong time) {
this.time = time;
}
@Override
public long currentTimeMillis() {
return time.get();
}
@Override
public void sleep(long milliseconds) throws InterruptedException {
Thread.sleep(milliseconds);
}
}

View File

@@ -2,7 +2,7 @@ dependencyVerification {
verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.dagger:dagger:2.19:dagger-2.19.jar:514b6f1e0727c6572e1d65cb27e4ae668b7aeaeb93a29515182965265b609939',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',

View File

@@ -3,10 +3,10 @@ sourceCompatibility = 1.8
targetCompatibility = 1.8
apply plugin: 'ru.vyarus.animalsniffer'
apply plugin: 'net.ltgt.apt'
apply plugin: 'idea'
apply plugin: 'witness'
apply from: 'witness.gradle'
apply from: '../dagger.gradle'
dependencies {
implementation project(path: ':bramble-api', configuration: 'default')
@@ -14,10 +14,10 @@ dependencies {
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0'
implementation 'org.whispersystems:curve25519-java:0.4.1'
implementation 'org.whispersystems:curve25519-java:0.5.0'
implementation 'org.briarproject:jtorctl:0.3'
apt 'com.google.dagger:dagger-compiler:2.0.2'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
testImplementation 'org.hsqldb:hsqldb:2.3.5' // The last version that supports Java 1.6
@@ -25,10 +25,8 @@ dependencies {
testImplementation "org.jmock:jmock:2.8.2"
testImplementation "org.jmock:jmock-junit4:2.8.2"
testImplementation "org.jmock:jmock-legacy:2.8.2"
testImplementation "org.hamcrest:hamcrest-library:1.3"
testImplementation "org.hamcrest:hamcrest-core:1.3"
testApt 'com.google.dagger:dagger-compiler:2.0.2'
testAnnotationProcessor 'com.google.dagger:dagger-compiler:2.19'
signature 'org.codehaus.mojo.signature:java16:1.1@signature'
}

View File

@@ -8,7 +8,7 @@ import org.briarproject.bramble.lifecycle.LifecycleModule;
import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.properties.PropertiesModule;
import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.versioning.VersioningModule;
@@ -31,11 +31,11 @@ public interface BrambleCoreEagerSingletons {
void inject(ReportingModule.EagerSingletons init);
void inject(SyncModule.EagerSingletons init);
void inject(SystemModule.EagerSingletons init);
void inject(TransportModule.EagerSingletons init);
void inject(ValidationModule.EagerSingletons init);
void inject(VersioningModule.EagerSingletons init);
}

View File

@@ -19,6 +19,7 @@ import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.settings.SettingsModule;
import org.briarproject.bramble.socks.SocksModule;
import org.briarproject.bramble.sync.SyncModule;
import org.briarproject.bramble.sync.validation.ValidationModule;
import org.briarproject.bramble.system.SystemModule;
import org.briarproject.bramble.transport.TransportModule;
import org.briarproject.bramble.versioning.VersioningModule;
@@ -47,6 +48,7 @@ import dagger.Module;
SyncModule.class,
SystemModule.class,
TransportModule.class,
ValidationModule.class,
VersioningModule.class
})
public class BrambleCoreModule {
@@ -60,9 +62,9 @@ public class BrambleCoreModule {
c.inject(new PluginModule.EagerSingletons());
c.inject(new PropertiesModule.EagerSingletons());
c.inject(new ReportingModule.EagerSingletons());
c.inject(new SyncModule.EagerSingletons());
c.inject(new SystemModule.EagerSingletons());
c.inject(new TransportModule.EagerSingletons());
c.inject(new ValidationModule.EagerSingletons());
c.inject(new VersioningModule.EagerSingletons());
}
}

View File

@@ -159,7 +159,8 @@ class AccountManagerImpl implements AccountManager {
@Override
public boolean createAccount(String name, String password) {
synchronized (stateChangeLock) {
// TODO don't allow creating another account if one already exists
if (hasDatabaseKey())
throw new AssertionError("Already have a database key");
LocalAuthor localAuthor = identityManager.createLocalAuthor(name);
identityManager.registerLocalAuthor(localAuthor);
SecretKey key = crypto.generateSecretKey();
@@ -182,6 +183,7 @@ class AccountManagerImpl implements AccountManager {
LOG.info("Deleting account");
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseKeyDirectory());
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory());
databaseKey = null;
}
}

View File

@@ -0,0 +1,19 @@
package org.briarproject.bramble.battery;
import org.briarproject.bramble.api.battery.BatteryManager;
import dagger.Module;
import dagger.Provides;
/**
* Provides a default implementation of {@link BatteryManager} for systems
* without batteries.
*/
@Module
public class DefaultBatteryManagerModule {
@Provides
BatteryManager provideBatteryManager() {
return () -> false;
}
}

View File

@@ -82,13 +82,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public void addLocalMessage(Message m, BdfDictionary metadata,
boolean shared) throws DbException, FormatException {
Transaction txn = db.startTransaction(false);
try {
addLocalMessage(txn, m, metadata, shared);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> addLocalMessage(txn, m, metadata, shared));
}
@Override
@@ -113,15 +107,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public Message getMessage(MessageId m) throws DbException {
Message message;
Transaction txn = db.startTransaction(true);
try {
message = getMessage(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return message;
return db.transactionWithResult(true, txn -> getMessage(txn, m));
}
@Override
@@ -132,15 +118,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfList getMessageAsList(MessageId m) throws DbException,
FormatException {
BdfList list;
Transaction txn = db.startTransaction(true);
try {
list = getMessageAsList(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return list;
return db.transactionWithResult(true, txn -> getMessageAsList(txn, m));
}
@Override
@@ -152,15 +130,8 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfDictionary getGroupMetadataAsDictionary(GroupId g)
throws DbException, FormatException {
BdfDictionary dictionary;
Transaction txn = db.startTransaction(true);
try {
dictionary = getGroupMetadataAsDictionary(txn, g);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return dictionary;
return db.transactionWithResult(true, txn ->
getGroupMetadataAsDictionary(txn, g));
}
@Override
@@ -173,15 +144,8 @@ class ClientHelperImpl implements ClientHelper {
@Override
public BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException, FormatException {
BdfDictionary dictionary;
Transaction txn = db.startTransaction(true);
try {
dictionary = getMessageMetadataAsDictionary(txn, m);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return dictionary;
return db.transactionWithResult(true, txn ->
getMessageMetadataAsDictionary(txn, m));
}
@Override
@@ -194,15 +158,8 @@ class ClientHelperImpl implements ClientHelper {
@Override
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
GroupId g) throws DbException, FormatException {
Map<MessageId, BdfDictionary> map;
Transaction txn = db.startTransaction(true);
try {
map = getMessageMetadataAsDictionary(txn, g);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return map;
return db.transactionWithResult(true, txn ->
getMessageMetadataAsDictionary(txn, g));
}
@Override
@@ -219,15 +176,8 @@ class ClientHelperImpl implements ClientHelper {
public Map<MessageId, BdfDictionary> getMessageMetadataAsDictionary(
GroupId g, BdfDictionary query) throws DbException,
FormatException {
Map<MessageId, BdfDictionary> map;
Transaction txn = db.startTransaction(true);
try {
map = getMessageMetadataAsDictionary(txn, g, query);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return map;
return db.transactionWithResult(true, txn ->
getMessageMetadataAsDictionary(txn, g, query));
}
@Override
@@ -245,13 +195,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public void mergeGroupMetadata(GroupId g, BdfDictionary metadata)
throws DbException, FormatException {
Transaction txn = db.startTransaction(false);
try {
mergeGroupMetadata(txn, g, metadata);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> mergeGroupMetadata(txn, g, metadata));
}
@Override
@@ -263,13 +207,7 @@ class ClientHelperImpl implements ClientHelper {
@Override
public void mergeMessageMetadata(MessageId m, BdfDictionary metadata)
throws DbException, FormatException {
Transaction txn = db.startTransaction(false);
try {
mergeMessageMetadata(txn, m, metadata);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> mergeMessageMetadata(txn, m, metadata));
}
@Override

View File

@@ -13,7 +13,6 @@ import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.ContactExistsException;
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.identity.Author;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
@@ -158,7 +157,8 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
streamWriterFactory.createContactExchangeStreamWriter(out,
alice ? aliceHeaderKey : bobHeaderKey);
RecordWriter recordWriter =
recordWriterFactory.createRecordWriter(streamWriter.getOutputStream());
recordWriterFactory
.createRecordWriter(streamWriter.getOutputStream());
// Derive the nonces to be signed
byte[] aliceNonce = crypto.mac(ALICE_NONCE_LABEL, masterSecret,
@@ -287,19 +287,14 @@ class ContactExchangeTaskImpl extends Thread implements ContactExchangeTask {
private ContactId addContact(Author remoteAuthor, long timestamp,
Map<TransportId, TransportProperties> remoteProperties)
throws DbException {
ContactId contactId;
Transaction txn = db.startTransaction(false);
try {
contactId = contactManager.addContact(txn, remoteAuthor,
return db.transactionWithResult(false, txn -> {
ContactId contactId = contactManager.addContact(txn, remoteAuthor,
localAuthor.getId(), masterSecret, timestamp, alice,
true, true);
transportPropertyManager.addRemoteProperties(txn, contactId,
remoteProperties);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return contactId;
return contactId;
});
}
private void tryToClose(DuplexTransportConnection conn) {

View File

@@ -10,6 +10,9 @@ import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.KeyManager;
@@ -18,21 +21,32 @@ import java.util.Collection;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.AuthorInfo.Status.VERIFIED;
import static org.briarproject.bramble.util.StringUtils.toUtf8;
@ThreadSafe
@NotNullByDefault
class ContactManagerImpl implements ContactManager {
private final DatabaseComponent db;
private final KeyManager keyManager;
private final IdentityManager identityManager;
private final List<ContactHook> hooks;
@Inject
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager) {
ContactManagerImpl(DatabaseComponent db, KeyManager keyManager,
IdentityManager identityManager) {
this.db = db;
this.keyManager = keyManager;
this.identityManager = identityManager;
hooks = new CopyOnWriteArrayList<>();
}
@@ -65,42 +79,21 @@ class ContactManagerImpl implements ContactManager {
public ContactId addContact(Author remote, AuthorId local, SecretKey master,
long timestamp, boolean alice, boolean verified, boolean active)
throws DbException {
ContactId c;
Transaction txn = db.startTransaction(false);
try {
c = addContact(txn, remote, local, master, timestamp, alice,
verified, active);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return c;
return db.transactionWithResult(false, txn ->
addContact(txn, remote, local, master, timestamp, alice,
verified, active));
}
@Override
public Contact getContact(ContactId c) throws DbException {
Contact contact;
Transaction txn = db.startTransaction(true);
try {
contact = db.getContact(txn, c);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return contact;
return db.transactionWithResult(true, txn -> db.getContact(txn, c));
}
@Override
public Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException {
Transaction txn = db.startTransaction(true);
try {
Contact c = getContact(txn, remoteAuthorId, localAuthorId);
db.commitTransaction(txn);
return c;
} finally {
db.endTransaction(txn);
}
return db.transactionWithResult(true, txn ->
getContact(txn, remoteAuthorId, localAuthorId));
}
@Override
@@ -118,14 +111,8 @@ class ContactManagerImpl implements ContactManager {
@Override
public Collection<Contact> getActiveContacts() throws DbException {
Collection<Contact> contacts;
Transaction txn = db.startTransaction(true);
try {
contacts = db.getContacts(txn);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Collection<Contact> contacts =
db.transactionWithResult(true, db::getContacts);
List<Contact> active = new ArrayList<>(contacts.size());
for (Contact c : contacts) if (c.isActive()) active.add(c);
return active;
@@ -133,13 +120,7 @@ class ContactManagerImpl implements ContactManager {
@Override
public void removeContact(ContactId c) throws DbException {
Transaction txn = db.startTransaction(false);
try {
removeContact(txn, c);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> removeContact(txn, c));
}
@Override
@@ -148,6 +129,23 @@ class ContactManagerImpl implements ContactManager {
db.setContactActive(txn, c, active);
}
@Override
public void setContactAlias(Transaction txn, ContactId c,
@Nullable String alias) throws DbException {
if (alias != null) {
int aliasLength = toUtf8(alias).length;
if (aliasLength == 0 || aliasLength > MAX_AUTHOR_NAME_LENGTH)
throw new IllegalArgumentException();
}
db.setContactAlias(txn, c, alias);
}
@Override
public void setContactAlias(ContactId c, @Nullable String alias)
throws DbException {
db.transaction(false, txn -> setContactAlias(txn, c, alias));
}
@Override
public boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
@@ -157,15 +155,8 @@ class ContactManagerImpl implements ContactManager {
@Override
public boolean contactExists(AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException {
boolean exists;
Transaction txn = db.startTransaction(true);
try {
exists = contactExists(txn, remoteAuthorId, localAuthorId);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return exists;
return db.transactionWithResult(true, txn ->
contactExists(txn, remoteAuthorId, localAuthorId));
}
@Override
@@ -176,4 +167,23 @@ class ContactManagerImpl implements ContactManager {
db.removeContact(txn, c);
}
@Override
public AuthorInfo getAuthorInfo(AuthorId a) throws DbException {
return db.transactionWithResult(true, txn -> getAuthorInfo(txn, a));
}
@Override
public AuthorInfo getAuthorInfo(Transaction txn, AuthorId authorId)
throws DbException {
LocalAuthor localAuthor = identityManager.getLocalAuthor(txn);
if (localAuthor.getId().equals(authorId))
return new AuthorInfo(OURSELVES);
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
if (contacts.isEmpty()) return new AuthorInfo(UNKNOWN);
if (contacts.size() > 1) throw new AssertionError();
Contact c = contacts.iterator().next();
if (c.isVerified()) return new AuthorInfo(VERIFIED, c.getAlias());
else return new AuthorInfo(UNVERIFIED, c.getAlias());
}
}

View File

@@ -29,6 +29,7 @@ import static org.briarproject.bramble.data.Types.STRING_16;
import static org.briarproject.bramble.data.Types.STRING_32;
import static org.briarproject.bramble.data.Types.STRING_8;
import static org.briarproject.bramble.data.Types.TRUE;
import static org.briarproject.bramble.util.StringUtils.fromUtf8;
@NotThreadSafe
@NotNullByDefault
@@ -253,7 +254,7 @@ class BdfReaderImpl implements BdfReader {
if (length < 0 || length > maxBufferSize) throw new FormatException();
if (length == 0) return "";
readIntoBuffer(length);
return new String(buf, 0, length, "UTF-8");
return fromUtf8(buf, 0, length);
}
private int readStringLength() throws IOException {

View File

@@ -22,7 +22,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.ValidationManager.State;
import org.briarproject.bramble.api.sync.validation.MessageState;
import org.briarproject.bramble.api.transport.KeySet;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
@@ -106,7 +106,7 @@ interface Database<T> {
* @param sender the contact from whom the message was received, or null
* if the message was created locally.
*/
void addMessage(T txn, Message m, State state, boolean shared,
void addMessage(T txn, Message m, MessageState state, boolean shared,
@Nullable ContactId sender) throws DbException;
/**
@@ -114,7 +114,7 @@ interface Database<T> {
* in the given state.
*/
void addMessageDependency(T txn, Message dependent, MessageId dependency,
State dependentState) throws DbException;
MessageState dependentState) throws DbException;
/**
* Records that a message has been offered by the given contact.
@@ -310,11 +310,11 @@ interface Database<T> {
/**
* Returns the IDs and states of all dependencies of the given message.
* For missing dependencies and dependencies in other groups, the state
* {@link State UNKNOWN} is returned.
* {@link MessageState UNKNOWN} is returned.
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependencies(T txn, MessageId m)
Map<MessageId, MessageState> getMessageDependencies(T txn, MessageId m)
throws DbException;
/**
@@ -324,7 +324,7 @@ interface Database<T> {
* <p/>
* Read-only.
*/
Map<MessageId, State> getMessageDependents(T txn, MessageId m)
Map<MessageId, MessageState> getMessageDependents(T txn, MessageId m)
throws DbException;
/**
@@ -383,7 +383,7 @@ interface Database<T> {
* <p/>
* Read-only.
*/
State getMessageState(T txn, MessageId m) throws DbException;
MessageState getMessageState(T txn, MessageId m) throws DbException;
/**
* Returns the status of all delivered messages in the given group with
@@ -616,6 +616,12 @@ interface Database<T> {
void setContactActive(T txn, ContactId c, boolean active)
throws DbException;
/**
* Sets an alias name for a contact.
*/
void setContactAlias(T txn, ContactId c, @Nullable String alias)
throws DbException;
/**
* Sets the given group's visibility to the given contact to either
* {@link Visibility VISIBLE} or {@link Visibility SHARED}.
@@ -631,7 +637,8 @@ interface Database<T> {
/**
* Sets the validation and delivery state of the given message.
*/
void setMessageState(T txn, MessageId m, State state) throws DbException;
void setMessageState(T txn, MessageId m, MessageState state)
throws DbException;
/**
* Sets the reordering window for the given key set and transport in the

View File

@@ -9,7 +9,9 @@ import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbCallable;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.DbRunnable;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.db.NoSuchContactException;
@@ -17,6 +19,7 @@ import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.NoSuchLocalAuthorException;
import org.briarproject.bramble.api.db.NoSuchMessageException;
import org.briarproject.bramble.api.db.NoSuchTransportException;
import org.briarproject.bramble.api.db.NullableDbCallable;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
@@ -40,7 +43,6 @@ import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.MessageStatus;
import org.briarproject.bramble.api.sync.Offer;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.ValidationManager.State;
import org.briarproject.bramble.api.sync.event.GroupAddedEvent;
import org.briarproject.bramble.api.sync.event.GroupRemovedEvent;
import org.briarproject.bramble.api.sync.event.GroupVisibilityUpdatedEvent;
@@ -52,6 +54,7 @@ import org.briarproject.bramble.api.sync.event.MessageToAckEvent;
import org.briarproject.bramble.api.sync.event.MessageToRequestEvent;
import org.briarproject.bramble.api.sync.event.MessagesAckedEvent;
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
import org.briarproject.bramble.api.sync.validation.MessageState;
import org.briarproject.bramble.api.transport.KeySet;
import org.briarproject.bramble.api.transport.KeySetId;
import org.briarproject.bramble.api.transport.TransportKeys;
@@ -72,8 +75,8 @@ import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.sync.Group.Visibility.INVISIBLE;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.DELIVERED;
import static org.briarproject.bramble.api.sync.ValidationManager.State.UNKNOWN;
import static org.briarproject.bramble.api.sync.validation.MessageState.DELIVERED;
import static org.briarproject.bramble.api.sync.validation.MessageState.UNKNOWN;
import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.logException;
@@ -166,6 +169,45 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
}
@Override
public <E extends Exception> void transaction(boolean readOnly,
DbRunnable<E> task) throws DbException, E {
Transaction txn = startTransaction(readOnly);
try {
task.run(txn);
commitTransaction(txn);
} finally {
endTransaction(txn);
}
}
@Override
public <R, E extends Exception> R transactionWithResult(boolean readOnly,
DbCallable<R, E> task) throws DbException, E {
Transaction txn = startTransaction(readOnly);
try {
R result = task.call(txn);
commitTransaction(txn);
return result;
} finally {
endTransaction(txn);
}
}
@Override
public <R, E extends Exception> R transactionWithNullableResult(
boolean readOnly, NullableDbCallable<R, E> task)
throws DbException, E {
Transaction txn = startTransaction(readOnly);
try {
R result = task.call(txn);
commitTransaction(txn);
return result;
} finally {
endTransaction(txn);
}
}
private T unbox(Transaction transaction) {
if (transaction.isCommitted()) throw new IllegalStateException();
return txnClass.cast(transaction.unbox());
@@ -537,7 +579,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public State getMessageState(Transaction transaction, MessageId m)
public MessageState getMessageState(Transaction transaction, MessageId m)
throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
@@ -577,8 +619,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public Map<MessageId, State> getMessageDependencies(Transaction transaction,
MessageId m) throws DbException {
public Map<MessageId, MessageState> getMessageDependencies(
Transaction transaction, MessageId m) throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
@@ -586,8 +628,8 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
}
@Override
public Map<MessageId, State> getMessageDependents(Transaction transaction,
MessageId m) throws DbException {
public Map<MessageId, MessageState> getMessageDependents(
Transaction transaction, MessageId m) throws DbException {
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
throw new NoSuchMessageException();
@@ -832,6 +874,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
transaction.attach(new ContactStatusChangedEvent(c, active));
}
@Override
public void setContactAlias(Transaction transaction, ContactId c,
@Nullable String alias) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsContact(txn, c))
throw new NoSuchContactException();
db.setContactAlias(txn, c, alias);
}
@Override
public void setGroupVisibility(Transaction transaction, ContactId c,
GroupId g, Visibility v) throws DbException {
@@ -866,7 +918,7 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
@Override
public void setMessageState(Transaction transaction, MessageId m,
State state) throws DbException {
MessageState state) throws DbException {
if (transaction.isReadOnly()) throw new IllegalArgumentException();
T txn = unbox(transaction);
if (!db.containsMessage(txn, m))
@@ -883,10 +935,10 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
T txn = unbox(transaction);
if (!db.containsMessage(txn, dependent.getId()))
throw new NoSuchMessageException();
State dependentState = db.getMessageState(txn, dependent.getId());
MessageState dependentState =
db.getMessageState(txn, dependent.getId());
for (MessageId dependency : dependencies) {
db.addMessageDependency(txn, dependent, dependency,
dependentState);
db.addMessageDependency(txn, dependent, dependency, dependentState);
}
}

View File

@@ -2,6 +2,8 @@ package org.briarproject.bramble.db;
import org.briarproject.bramble.api.settings.Settings;
import static java.util.concurrent.TimeUnit.DAYS;
interface DatabaseConstants {
/**
@@ -23,4 +25,16 @@ interface DatabaseConstants {
*/
String SCHEMA_VERSION_KEY = "schemaVersion";
/**
* The {@link Settings} key under which the time of the last database
* compaction is stored.
*/
String LAST_COMPACTED_KEY = "lastCompacted";
/**
* The maximum time between database compactions in milliseconds. When the
* database is opened it will be compacted if more than this amount of time
* has passed since the last compaction.
*/
long MAX_COMPACTION_INTERVAL_MS = DAYS.toMillis(30);
}

View File

@@ -0,0 +1,34 @@
package org.briarproject.bramble.db;
class DatabaseTypes {
private final String hashType, secretType, binaryType;
private final String counterType, stringType;
public DatabaseTypes(String hashType, String secretType, String binaryType,
String counterType, String stringType) {
this.hashType = hashType;
this.secretType = secretType;
this.binaryType = binaryType;
this.counterType = counterType;
this.stringType = stringType;
}
/**
* Replaces database type placeholders in a statement with the actual types.
* These placeholders are currently supported:
* <li> _HASH
* <li> _SECRET
* <li> _BINARY
* <li> _COUNTER
* <li> _STRING
*/
String replaceTypes(String s) {
s = s.replaceAll("_HASH", hashType);
s = s.replaceAll("_SECRET", secretType);
s = s.replaceAll("_BINARY", binaryType);
s = s.replaceAll("_COUNTER", counterType);
s = s.replaceAll("_STRING", stringType);
return s;
}
}

View File

@@ -13,22 +13,32 @@ import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
/**
* Contains all the H2-specific code for the database.
*/
@NotNullByDefault
class H2Database extends JdbcDatabase {
private static final Logger LOG = getLogger(H2Database.class.getName());
private static final String HASH_TYPE = "BINARY(32)";
private static final String SECRET_TYPE = "BINARY(32)";
private static final String BINARY_TYPE = "BINARY";
private static final String COUNTER_TYPE = "INT NOT NULL AUTO_INCREMENT";
private static final String STRING_TYPE = "VARCHAR";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE);
private final DatabaseConfig config;
private final String url;
@@ -39,8 +49,7 @@ class H2Database extends JdbcDatabase {
@Inject
H2Database(DatabaseConfig config, MessageFactory messageFactory,
Clock clock) {
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
messageFactory, clock);
super(dbTypes, messageFactory, clock);
this.config = config;
File dir = config.getDatabaseDirectory();
String path = new File(dir, "db").getAbsolutePath();
@@ -106,4 +115,22 @@ class H2Database extends JdbcDatabase {
String getUrl() {
return url;
}
@Override
protected void compactAndClose() throws DbException {
Connection c = null;
Statement s = null;
try {
c = createConnection();
closeAllConnections();
s = c.createStatement();
s.execute("SHUTDOWN COMPACT");
s.close();
c.close();
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
tryToClose(c, LOG, WARNING);
throw new DbException(e);
}
}
}

View File

@@ -14,22 +14,32 @@ import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
/**
* Contains all the HSQLDB-specific code for the database.
*/
@NotNullByDefault
class HyperSqlDatabase extends JdbcDatabase {
private static final Logger LOG =
getLogger(HyperSqlDatabase.class.getName());
private static final String HASH_TYPE = "BINARY(32)";
private static final String SECRET_TYPE = "BINARY(32)";
private static final String BINARY_TYPE = "BINARY";
private static final String COUNTER_TYPE =
"INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY(START WITH 1)";
private static final String STRING_TYPE = "VARCHAR";
private static final DatabaseTypes dbTypes = new DatabaseTypes(HASH_TYPE,
SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE);
private final DatabaseConfig config;
private final String url;
@@ -40,8 +50,7 @@ class HyperSqlDatabase extends JdbcDatabase {
@Inject
HyperSqlDatabase(DatabaseConfig config, MessageFactory messageFactory,
Clock clock) {
super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE,
messageFactory, clock);
super(dbTypes, messageFactory, clock);
this.config = config;
File dir = config.getDatabaseDirectory();
String path = new File(dir, "db").getAbsolutePath();
@@ -61,20 +70,24 @@ class HyperSqlDatabase extends JdbcDatabase {
@Override
public void close() throws DbException {
Connection c = null;
Statement s = null;
try {
super.closeAllConnections();
Connection c = createConnection();
Statement s = c.createStatement();
c = createConnection();
s = c.createStatement();
s.executeQuery("SHUTDOWN");
s.close();
c.close();
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
tryToClose(c, LOG, WARNING);
throw new DbException(e);
}
}
@Override
public long getFreeSpace() throws DbException {
public long getFreeSpace() {
File dir = config.getDatabaseDirectory();
long maxSize = config.getMaxSize();
long free = dir.getFreeSpace();
@@ -104,4 +117,22 @@ class HyperSqlDatabase extends JdbcDatabase {
String hex = StringUtils.toHexString(key.getBytes());
return DriverManager.getConnection(url + ";crypt_key=" + hex);
}
@Override
protected void compactAndClose() throws DbException {
Connection c = null;
Statement s = null;
try {
super.closeAllConnections();
c = createConnection();
s = c.createStatement();
s.executeQuery("SHUTDOWN COMPACT");
s.close();
c.close();
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
tryToClose(c, LOG, WARNING);
throw new DbException(e);
}
}
}

View File

@@ -0,0 +1,42 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
class JdbcUtils {
static void tryToClose(@Nullable ResultSet rs, Logger logger, Level level) {
try {
if (rs != null) rs.close();
} catch (SQLException e) {
logException(logger, level, e);
}
}
static void tryToClose(@Nullable Statement s, Logger logger, Level level) {
try {
if (s != null) s.close();
} catch (SQLException e) {
logException(logger, level, e);
}
}
static void tryToClose(@Nullable Connection c, Logger logger, Level level) {
try {
if (c != null) c.close();
} catch (SQLException e) {
logException(logger, level, e);
}
}
}

View File

@@ -7,10 +7,8 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration38_39 implements Migration<Connection> {
@@ -40,16 +38,8 @@ class Migration38_39 implements Migration<Connection> {
+ " ALTER COLUMN contactId"
+ " SET NOT NULL");
} catch (SQLException e) {
tryToClose(s);
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
private void tryToClose(@Nullable Statement s) {
try {
if (s != null) s.close();
} catch (SQLException e) {
logException(LOG, WARNING, e);
}
}
}

View File

@@ -7,10 +7,8 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration39_40 implements Migration<Connection> {
@@ -39,16 +37,8 @@ class Migration39_40 implements Migration<Connection> {
+ " ALTER COLUMN eta"
+ " SET NOT NULL");
} catch (SQLException e) {
tryToClose(s);
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
private void tryToClose(@Nullable Statement s) {
try {
if (s != null) s.close();
} catch (SQLException e) {
logException(LOG, WARNING, e);
}
}
}

View File

@@ -0,0 +1,46 @@
package org.briarproject.bramble.db;
import org.briarproject.bramble.api.db.DbException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.db.JdbcUtils.tryToClose;
class Migration40_41 implements Migration<Connection> {
private static final Logger LOG = getLogger(Migration40_41.class.getName());
private final DatabaseTypes dbTypes;
public Migration40_41(DatabaseTypes databaseTypes) {
this.dbTypes = databaseTypes;
}
@Override
public int getStartVersion() {
return 40;
}
@Override
public int getEndVersion() {
return 41;
}
@Override
public void migrate(Connection txn) throws DbException {
Statement s = null;
try {
s = txn.createStatement();
s.execute("ALTER TABLE contacts"
+ dbTypes.replaceTypes(" ADD alias _STRING"));
} catch (SQLException e) {
tryToClose(s, LOG, WARNING);
throw new DbException(e);
}
}
}

View File

@@ -1,29 +1,21 @@
package org.briarproject.bramble.identity;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author.Status;
import org.briarproject.bramble.api.identity.AuthorFactory;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
import javax.inject.Inject;
import static org.briarproject.bramble.api.identity.Author.Status.OURSELVES;
import static org.briarproject.bramble.api.identity.Author.Status.UNKNOWN;
import static org.briarproject.bramble.api.identity.Author.Status.UNVERIFIED;
import static org.briarproject.bramble.api.identity.Author.Status.VERIFIED;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@@ -75,27 +67,16 @@ class IdentityManagerImpl implements IdentityManager {
LOG.info("No local author to store");
return;
}
Transaction txn = db.startTransaction(false);
try {
db.addLocalAuthor(txn, cached);
db.commitTransaction(txn);
LOG.info("Local author stored");
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> db.addLocalAuthor(txn, cached));
LOG.info("Local author stored");
}
@Override
public LocalAuthor getLocalAuthor() throws DbException {
if (cachedAuthor == null) {
Transaction txn = db.startTransaction(true);
try {
cachedAuthor = loadLocalAuthor(txn);
LOG.info("Local author loaded");
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
cachedAuthor =
db.transactionWithResult(true, this::loadLocalAuthor);
LOG.info("Local author loaded");
}
LocalAuthor cached = cachedAuthor;
if (cached == null) throw new AssertionError();
@@ -118,26 +99,4 @@ class IdentityManagerImpl implements IdentityManager {
return db.getLocalAuthors(txn).iterator().next();
}
@Override
public Status getAuthorStatus(AuthorId authorId) throws DbException {
Transaction txn = db.startTransaction(true);
try {
return getAuthorStatus(txn, authorId);
} finally {
db.endTransaction(txn);
}
}
@Override
public Status getAuthorStatus(Transaction txn, AuthorId authorId)
throws DbException {
if (getLocalAuthor(txn).getId().equals(authorId)) return OURSELVES;
Collection<Contact> contacts = db.getContactsByAuthorId(txn, authorId);
if (contacts.isEmpty()) return UNKNOWN;
for (Contact c : contacts) {
if (c.isVerified()) return VERIFIED;
}
return UNVERIFIED;
}
}

View File

@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.db.DataTooOldException;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.MigrationListener;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
@@ -29,6 +28,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.FINE;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.COMPACTING_DATABASE;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.MIGRATING_DATABASE;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.STARTING;
@@ -114,20 +114,16 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
dbLatch.countDown();
eventBus.broadcast(new LifecycleEvent(STARTING_SERVICES));
Transaction txn = db.startTransaction(false);
try {
db.transaction(false, txn -> {
for (Client c : clients) {
start = now();
long start1 = now();
c.createLocalState(txn);
if (LOG.isLoggable(FINE)) {
logDuration(LOG, "Starting client "
+ c.getClass().getSimpleName(), start);
+ c.getClass().getSimpleName(), start1);
}
}
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
});
for (Service s : services) {
start = now();
s.startService();
@@ -159,11 +155,17 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener {
}
@Override
public void onMigrationRun() {
public void onDatabaseMigration() {
state = MIGRATING_DATABASE;
eventBus.broadcast(new LifecycleEvent(MIGRATING_DATABASE));
}
@Override
public void onDatabaseCompaction() {
state = COMPACTING_DATABASE;
eventBus.broadcast(new LifecycleEvent(COMPACTING_DATABASE));
}
@Override
public void stopServices() {
try {

View File

@@ -23,7 +23,6 @@ import org.briarproject.bramble.api.plugin.event.EnableBluetoothEvent;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
import java.security.SecureRandom;
@@ -46,6 +45,9 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_UUID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.UUID_BYTES;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
import static org.briarproject.bramble.util.StringUtils.macToBytes;
import static org.briarproject.bramble.util.StringUtils.macToString;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -96,6 +98,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
abstract DuplexTransportConnection connectTo(String address, String uuid)
throws IOException;
@Nullable
abstract DuplexTransportConnection discoverAndConnect(String uuid);
BluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, SecureRandom secureRandom,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) {
@@ -193,7 +198,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
address = getBluetoothAddress();
if (LOG.isLoggable(INFO))
LOG.info("Local address " + scrubMacAddress(address));
if (!StringUtils.isNullOrEmpty(address)) {
if (!isNullOrEmpty(address)) {
p.put(PROP_ADDRESS, address);
changed = true;
}
@@ -256,9 +261,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
// Try to connect to known devices in parallel
for (Entry<ContactId, TransportProperties> e : contacts.entrySet()) {
String address = e.getValue().get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) continue;
if (isNullOrEmpty(address)) continue;
String uuid = e.getValue().get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) continue;
if (isNullOrEmpty(uuid)) continue;
ContactId c = e.getKey();
ioExecutor.execute(() -> {
if (!isRunning() || !shouldAllowContactConnections()) return;
@@ -309,9 +314,9 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
if (!isRunning() || !shouldAllowContactConnections()) return null;
if (!connectionLimiter.canOpenContactConnection()) return null;
String address = p.get(PROP_ADDRESS);
if (StringUtils.isNullOrEmpty(address)) return null;
if (isNullOrEmpty(address)) return null;
String uuid = p.get(PROP_UUID);
if (StringUtils.isNullOrEmpty(uuid)) return null;
if (isNullOrEmpty(uuid)) return null;
DuplexTransportConnection conn = connect(address, uuid);
if (conn == null) return null;
// TODO: Why don't we reset the backoff here?
@@ -326,9 +331,6 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
@Override
public KeyAgreementListener createKeyAgreementListener(byte[] commitment) {
if (!isRunning()) return null;
// There's no point listening if we can't discover our own address
String address = getBluetoothAddress();
if (address == null) return null;
// No truncation necessary because COMMIT_LENGTH = 16
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
if (LOG.isLoggable(INFO)) LOG.info("Key agreement UUID " + uuid);
@@ -346,7 +348,8 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
}
BdfList descriptor = new BdfList();
descriptor.add(TRANSPORT_ID_BLUETOOTH);
descriptor.add(StringUtils.macToBytes(address));
String address = getBluetoothAddress();
if (address != null) descriptor.add(macToBytes(address));
return new BluetoothKeyAgreementListener(descriptor, ss);
}
@@ -354,18 +357,25 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
public DuplexTransportConnection createKeyAgreementConnection(
byte[] commitment, BdfList descriptor) {
if (!isRunning()) return null;
String address;
try {
address = parseAddress(descriptor);
} catch (FormatException e) {
LOG.info("Invalid address in key agreement descriptor");
return null;
}
// No truncation necessary because COMMIT_LENGTH = 16
String uuid = UUID.nameUUIDFromBytes(commitment).toString();
if (LOG.isLoggable(INFO))
LOG.info("Connecting to key agreement UUID " + uuid);
DuplexTransportConnection conn = connect(address, uuid);
DuplexTransportConnection conn;
if (descriptor.size() == 1) {
if (LOG.isLoggable(INFO))
LOG.info("Discovering address for key agreement UUID " + uuid);
conn = discoverAndConnect(uuid);
} else {
String address;
try {
address = parseAddress(descriptor);
} catch (FormatException e) {
LOG.info("Invalid address in key agreement descriptor");
return null;
}
if (LOG.isLoggable(INFO))
LOG.info("Connecting to key agreement UUID " + uuid);
conn = connect(address, uuid);
}
if (conn != null) connectionLimiter.keyAgreementConnectionOpened(conn);
return conn;
}
@@ -373,7 +383,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
private String parseAddress(BdfList descriptor) throws FormatException {
byte[] mac = descriptor.getRaw(1);
if (mac.length != 6) throw new FormatException();
return StringUtils.macToString(mac);
return macToString(mac);
}
@Override

View File

@@ -4,12 +4,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
@NotNullByDefault
class FileTransportReader implements TransportConnectionReader {
@@ -34,11 +33,7 @@ class FileTransportReader implements TransportConnectionReader {
@Override
public void dispose(boolean exception, boolean recognised) {
try {
in.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
tryToClose(in, LOG, WARNING);
plugin.readerFinished(file, exception, recognised);
}
}

View File

@@ -4,12 +4,11 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
@NotNullByDefault
class FileTransportWriter implements TransportConnectionWriter {
@@ -44,11 +43,7 @@ class FileTransportWriter implements TransportConnectionWriter {
@Override
public void dispose(boolean exception) {
try {
out.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
tryToClose(out, LOG, WARNING);
plugin.writerFinished(file, exception);
}
}

View File

@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
@@ -35,7 +36,6 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PREF_LAN_IP_PORTS;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.PROP_IP_PORTS;
import static org.briarproject.bramble.util.ByteUtils.MAX_16_BIT_UNSIGNED;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubSocketAddress;
@NotNullByDefault
@@ -293,11 +293,7 @@ class LanTcpPlugin extends TcpPlugin {
@Override
public void close() {
try {
ss.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
IoUtils.tryToClose(ss, LOG, WARNING);
}
}

View File

@@ -11,6 +11,7 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.IOException;
@@ -153,13 +154,8 @@ abstract class TcpPlugin implements DuplexPlugin {
}
protected void tryToClose(@Nullable ServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
} finally {
callback.transportDisabled();
}
IoUtils.tryToClose(ss, LOG, WARNING);
callback.transportDisabled();
}
String getIpPortString(InetSocketAddress a) {

View File

@@ -4,6 +4,8 @@ import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.TorControlConnection;
import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.battery.event.BatteryEvent;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.event.Event;
@@ -28,9 +30,7 @@ import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
@@ -70,9 +70,11 @@ import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_NEVER;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_NETWORK_WITH_BRIDGES;
import static org.briarproject.bramble.api.plugin.TorConstants.PREF_TOR_PORT;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V2;
import static org.briarproject.bramble.api.plugin.TorConstants.PROP_ONION_V3;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -87,20 +89,22 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String OWNER = "__OwningControllerProcess";
private static final int COOKIE_TIMEOUT_MS = 3000;
private static final int COOKIE_POLLING_INTERVAL_MS = 200;
private static final Pattern ONION = Pattern.compile("[a-z2-7]{16}");
private static final Pattern ONION_V2 = Pattern.compile("[a-z2-7]{16}");
private static final Pattern ONION_V3 = Pattern.compile("[a-z2-7]{56}");
private final Executor ioExecutor, connectionStatusExecutor;
private final NetworkManager networkManager;
private final LocationUtils locationUtils;
private final SocketFactory torSocketFactory;
private final Clock clock;
private final BatteryManager batteryManager;
private final Backoff backoff;
private final DuplexPluginCallback callback;
private final String architecture;
private final CircumventionProvider circumventionProvider;
private final ResourceProvider resourceProvider;
private final int maxLatency, maxIdleTime, socketTimeout;
private final File torDirectory, torFile, geoIpFile, configFile;
private final File torDirectory, torFile, geoIpFile, obfs4File, configFile;
private final File doneFile, cookieFile;
private final ConnectionStatus connectionStatus;
private final AtomicBoolean used = new AtomicBoolean(false);
@@ -119,7 +123,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
TorPlugin(Executor ioExecutor, NetworkManager networkManager,
LocationUtils locationUtils, SocketFactory torSocketFactory,
Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, Backoff backoff,
CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency,
int maxIdleTime, File torDirectory) {
this.ioExecutor = ioExecutor;
@@ -129,6 +134,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
this.clock = clock;
this.resourceProvider = resourceProvider;
this.circumventionProvider = circumventionProvider;
this.batteryManager = batteryManager;
this.backoff = backoff;
this.callback = callback;
this.architecture = architecture;
@@ -140,6 +146,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
this.torDirectory = torDirectory;
torFile = new File(torDirectory, "tor");
geoIpFile = new File(torDirectory, "geoip");
obfs4File = new File(torDirectory, "obfs4proxy");
configFile = new File(torDirectory, "torrc");
doneFile = new File(torDirectory, "done");
cookieFile = new File(torDirectory, ".tor/control_auth_cookie");
@@ -258,7 +265,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
throw new PluginException(e);
}
// Check whether we're online
updateConnectionStatus(networkManager.getNetworkStatus());
updateConnectionStatus(networkManager.getNetworkStatus(),
batteryManager.isCharging());
// Bind a server socket to receive incoming hidden service connections
bind();
}
@@ -282,14 +290,20 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
in = getGeoIpInputStream();
out = new FileOutputStream(geoIpFile);
IoUtils.copyAndClose(in, out);
// Unzip the Obfs4 proxy to the filesystem
in = getObfs4InputStream();
out = new FileOutputStream(obfs4File);
IoUtils.copyAndClose(in, out);
// Make the Obfs4 proxy executable
if (!obfs4File.setExecutable(true, true)) throw new IOException();
// Copy the config file to the filesystem
in = getConfigInputStream();
out = new FileOutputStream(configFile);
IoUtils.copyAndClose(in, out);
doneFile.createNewFile();
} catch (IOException e) {
tryToClose(in);
tryToClose(out);
IoUtils.tryToClose(in, LOG, WARNING);
IoUtils.tryToClose(out, LOG, WARNING);
throw new PluginException(e);
}
}
@@ -312,26 +326,20 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return zin;
}
private InputStream getObfs4InputStream() throws IOException {
if (LOG.isLoggable(INFO))
LOG.info("Installing obfs4proxy binary for " + architecture);
InputStream in = resourceProvider
.getResourceInputStream("obfs4proxy_" + architecture, ".zip");
ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException();
return zin;
}
private InputStream getConfigInputStream() {
return getClass().getClassLoader().getResourceAsStream("torrc");
}
private void tryToClose(@Nullable Closeable c) {
try {
if (c != null) c.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
private void tryToClose(@Nullable Socket s) {
try {
if (s != null) s.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
private void listFiles(File f) {
if (f.isDirectory()) {
File[] children = f.listFiles();
@@ -353,7 +361,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
return b;
} finally {
tryToClose(in);
IoUtils.tryToClose(in, LOG, WARNING);
}
}
@@ -362,7 +370,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
// If there's already a port number stored in config, reuse it
String portString = settings.get(PREF_TOR_PORT);
int port;
if (StringUtils.isNullOrEmpty(portString)) port = 0;
if (isNullOrEmpty(portString)) port = 0;
else port = Integer.parseInt(portString);
// Bind a server socket to receive connections from Tor
ServerSocket ss = null;
@@ -393,13 +401,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
private void tryToClose(@Nullable ServerSocket ss) {
try {
if (ss != null) ss.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
} finally {
callback.transportDisabled();
}
IoUtils.tryToClose(ss, LOG, WARNING);
callback.transportDisabled();
}
private void publishHiddenService(String port) {
@@ -427,11 +430,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
return;
}
// Publish the hidden service's onion hostname in transport properties
String hostname = response.get(HS_ADDRESS);
String onion2 = response.get(HS_ADDRESS);
if (LOG.isLoggable(INFO))
LOG.info("Hidden service " + scrubOnion(hostname));
LOG.info("Hidden service " + scrubOnion(onion2));
TransportProperties p = new TransportProperties();
p.put(PROP_ONION, hostname);
p.put(PROP_ONION_V2, onion2);
callback.mergeLocalProperties(p);
if (privKey == null) {
// Save the hidden service's private key for next time
@@ -470,6 +473,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (enable) {
Collection<String> conf = new ArrayList<>();
conf.add("UseBridges 1");
conf.add("ClientTransportPlugin obfs4 exec " +
obfs4File.getAbsolutePath());
conf.addAll(circumventionProvider.getBridges());
controlConnection.setConf(conf);
} else {
@@ -530,28 +535,43 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override
public DuplexTransportConnection createConnection(TransportProperties p) {
if (!isRunning()) return null;
String onion = p.get(PROP_ONION);
if (StringUtils.isNullOrEmpty(onion)) return null;
if (!ONION.matcher(onion).matches()) {
// not scrubbing this address, so we are able to find the problem
if (LOG.isLoggable(INFO)) LOG.info("Invalid hostname: " + onion);
return null;
String bestOnion = null;
String onion2 = p.get(PROP_ONION_V2);
String onion3 = p.get(PROP_ONION_V3);
if (!isNullOrEmpty(onion2)) {
if (ONION_V2.matcher(onion2).matches()) {
bestOnion = onion2;
} else {
// Don't scrub the address so we can find the problem
if (LOG.isLoggable(INFO))
LOG.info("Invalid v2 hostname: " + onion2);
}
}
if (!isNullOrEmpty(onion3)) {
if (ONION_V3.matcher(onion3).matches()) {
bestOnion = onion3;
} else {
// Don't scrub the address so we can find the problem
if (LOG.isLoggable(INFO))
LOG.info("Invalid v3 hostname: " + onion3);
}
}
if (bestOnion == null) return null;
Socket s = null;
try {
if (LOG.isLoggable(INFO))
LOG.info("Connecting to " + scrubOnion(onion));
s = torSocketFactory.createSocket(onion + ".onion", 80);
LOG.info("Connecting to " + scrubOnion(bestOnion));
s = torSocketFactory.createSocket(bestOnion + ".onion", 80);
s.setSoTimeout(socketTimeout);
if (LOG.isLoggable(INFO))
LOG.info("Connected to " + scrubOnion(onion));
LOG.info("Connected to " + scrubOnion(bestOnion));
return new TorTransportConnection(this, s);
} catch (IOException e) {
if (LOG.isLoggable(INFO)) {
LOG.info("Could not connect to " + scrubOnion(onion) + ": " +
e.toString());
LOG.info("Could not connect to " + scrubOnion(bestOnion)
+ ": " + e.toString());
}
tryToClose(s);
IoUtils.tryToClose(s, LOG, WARNING);
return null;
}
}
@@ -592,7 +612,8 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
LOG.info("OR connection " + status + " " + orName);
if (status.equals("CLOSED") || status.equals("FAILED")) {
// Check whether we've lost connectivity
updateConnectionStatus(networkManager.getNetworkStatus());
updateConnectionStatus(networkManager.getNetworkStatus(),
batteryManager.isCharging());
}
}
@@ -627,14 +648,33 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (s.getNamespace().equals(ID.getString())) {
LOG.info("Tor settings updated");
settings = s.getSettings();
updateConnectionStatus(networkManager.getNetworkStatus());
// Works around a bug introduced in Tor 0.3.4.8. Could be
// replaced with callback.transportDisabled() when fixed.
disableNetwork();
updateConnectionStatus(networkManager.getNetworkStatus(),
batteryManager.isCharging());
}
} else if (e instanceof NetworkStatusEvent) {
updateConnectionStatus(((NetworkStatusEvent) e).getStatus());
updateConnectionStatus(((NetworkStatusEvent) e).getStatus(),
batteryManager.isCharging());
} else if (e instanceof BatteryEvent) {
updateConnectionStatus(networkManager.getNetworkStatus(),
((BatteryEvent) e).isCharging());
}
}
private void updateConnectionStatus(NetworkStatus status) {
private void disableNetwork() {
connectionStatusExecutor.execute(() -> {
try {
enableNetwork(false);
} catch (IOException ex) {
logException(LOG, WARNING, ex);
}
});
}
private void updateConnectionStatus(NetworkStatus status,
boolean charging) {
connectionStatusExecutor.execute(() -> {
if (!running) return;
boolean online = status.isConnected();
@@ -652,6 +692,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
LOG.info("Online: " + online + ", wifi: " + wifi);
if ("".equals(country)) LOG.info("Country code unknown");
else LOG.info("Country code: " + country);
LOG.info("Charging: " + charging);
}
try {
@@ -675,12 +716,24 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
enableBridges(false);
enableNetwork(true);
}
if (online && wifi && charging) {
LOG.info("Enabling connection padding");
enableConnectionPadding(true);
} else {
LOG.info("Disabling connection padding");
enableConnectionPadding(false);
}
} catch (IOException e) {
logException(LOG, WARNING, e);
}
});
}
private void enableConnectionPadding(boolean enable) throws IOException {
if (!running) return;
controlConnection.setConf("ConnectionPadding", enable ? "1" : "0");
}
// TODO remove when sufficient time has passed. Added 2018-08-15
private void migrateSettings() {
Settings sOld = callback.getSettings();

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.properties.TransportPropertyManager;
import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.sync.validation.ValidationManager;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersioningManager;

View File

@@ -24,7 +24,7 @@ import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.InvalidMessageException;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.api.sync.ValidationManager.IncomingMessageHook;
import org.briarproject.bramble.api.sync.validation.IncomingMessageHook;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.versioning.ClientVersioningManager;
import org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook;
@@ -142,15 +142,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public Map<TransportId, TransportProperties> getLocalProperties()
throws DbException {
Map<TransportId, TransportProperties> local;
Transaction txn = db.startTransaction(true);
try {
local = getLocalProperties(txn);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return local;
return db.transactionWithResult(true, this::getLocalProperties);
}
@Override
@@ -176,9 +168,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
public TransportProperties getLocalProperties(TransportId t)
throws DbException {
try {
TransportProperties p = null;
Transaction txn = db.startTransaction(true);
try {
return db.transactionWithResult(true, txn -> {
TransportProperties p = null;
// Find the latest local update
LatestUpdate latest = findLatest(txn, localGroup.getId(), t,
true);
@@ -188,11 +179,8 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
latest.messageId);
p = parseProperties(message);
}
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return p == null ? new TransportProperties() : p;
return p == null ? new TransportProperties() : p;
});
} catch (FormatException e) {
throw new DbException(e);
}
@@ -201,16 +189,12 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public Map<ContactId, TransportProperties> getRemoteProperties(
TransportId t) throws DbException {
Map<ContactId, TransportProperties> remote = new HashMap<>();
Transaction txn = db.startTransaction(true);
try {
return db.transactionWithResult(true, txn -> {
Map<ContactId, TransportProperties> remote = new HashMap<>();
for (Contact c : db.getContacts(txn))
remote.put(c.getId(), getRemoteProperties(txn, c, t));
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return remote;
return remote;
});
}
private TransportProperties getRemoteProperties(Transaction txn, Contact c,
@@ -234,23 +218,15 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
@Override
public TransportProperties getRemoteProperties(ContactId c, TransportId t)
throws DbException {
TransportProperties p;
Transaction txn = db.startTransaction(true);
try {
p = getRemoteProperties(txn, db.getContact(txn, c), t);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return p;
return db.transactionWithResult(true, txn ->
getRemoteProperties(txn, db.getContact(txn, c), t));
}
@Override
public void mergeLocalProperties(TransportId t, TransportProperties p)
throws DbException {
try {
Transaction txn = db.startTransaction(false);
try {
db.transaction(false, txn -> {
// Merge the new properties with any existing properties
TransportProperties merged;
boolean changed;
@@ -287,10 +263,7 @@ class TransportPropertyManagerImpl implements TransportPropertyManager,
db.removeMessage(txn, latest.messageId);
}
}
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
});
} catch (FormatException e) {
throw new DbException(e);
}

View File

@@ -12,7 +12,6 @@ import org.briarproject.bramble.api.reporting.DevReporter;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -26,13 +25,12 @@ import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import javax.net.SocketFactory;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
@Immutable
@NotNullByDefault
@@ -66,7 +64,7 @@ class DevReporterImpl implements DevReporter, EventListener {
s.setSoTimeout(SOCKET_TIMEOUT);
return s;
} catch (IOException e) {
tryToClose(s);
tryToClose(s, LOG, WARNING);
throw e;
}
}
@@ -88,8 +86,7 @@ class DevReporterImpl implements DevReporter, EventListener {
writer.append(armoured);
writer.flush();
} finally {
if (writer != null)
writer.close();
tryToClose(writer, LOG, WARNING);
}
}
@@ -121,27 +118,11 @@ class DevReporterImpl implements DevReporter, EventListener {
f.delete();
} catch (IOException e) {
LOG.log(WARNING, "Failed to send reports", e);
tryToClose(out);
tryToClose(in);
tryToClose(out, LOG, WARNING);
tryToClose(in, LOG, WARNING);
return;
}
}
LOG.info("Reports sent");
}
private void tryToClose(@Nullable Closeable c) {
try {
if (c != null) c.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
private void tryToClose(@Nullable Socket s) {
try {
if (s != null) s.close();
} catch (IOException e) {
logException(LOG, WARNING, e);
}
}
}

View File

@@ -23,15 +23,8 @@ class SettingsManagerImpl implements SettingsManager {
@Override
public Settings getSettings(String namespace) throws DbException {
Settings s;
Transaction txn = db.startTransaction(true);
try {
s = db.getSettings(txn, namespace);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return s;
return db.transactionWithResult(true, txn ->
db.getSettings(txn, namespace));
}
@Override
@@ -42,12 +35,6 @@ class SettingsManagerImpl implements SettingsManager {
@Override
public void mergeSettings(Settings s, String namespace) throws DbException {
Transaction txn = db.startTransaction(false);
try {
db.mergeSettings(txn, s, namespace);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn -> db.mergeSettings(txn, s, namespace));
}
}

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
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.EventBus;
import org.briarproject.bramble.api.event.EventListener;
@@ -230,14 +229,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
if (interrupted) return;
if (!generateAckQueued.getAndSet(false)) throw new AssertionError();
try {
Ack a;
Transaction txn = db.startTransaction(false);
try {
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Ack a = db.transactionWithNullableResult(false, txn ->
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
if (LOG.isLoggable(INFO))
LOG.info("Generated ack: " + (a != null));
if (a != null) writerTasks.add(new WriteAck(a));
@@ -275,16 +268,15 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
if (!generateBatchQueued.getAndSet(false))
throw new AssertionError();
try {
Collection<Message> b;
Transaction txn = db.startTransaction(false);
try {
b = db.generateRequestedBatch(txn, contactId,
MAX_RECORD_PAYLOAD_BYTES, maxLatency);
setNextSendTime(db.getNextSendTime(txn, contactId));
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Collection<Message> b =
db.transactionWithNullableResult(false, txn -> {
Collection<Message> batch =
db.generateRequestedBatch(txn, contactId,
MAX_RECORD_PAYLOAD_BYTES,
maxLatency);
setNextSendTime(db.getNextSendTime(txn, contactId));
return batch;
});
if (LOG.isLoggable(INFO))
LOG.info("Generated batch: " + (b != null));
if (b != null) writerTasks.add(new WriteBatch(b));
@@ -322,16 +314,12 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
if (!generateOfferQueued.getAndSet(false))
throw new AssertionError();
try {
Offer o;
Transaction txn = db.startTransaction(false);
try {
o = db.generateOffer(txn, contactId, MAX_MESSAGE_IDS,
maxLatency);
Offer o = db.transactionWithNullableResult(false, txn -> {
Offer offer = db.generateOffer(txn, contactId,
MAX_MESSAGE_IDS, maxLatency);
setNextSendTime(db.getNextSendTime(txn, contactId));
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
return offer;
});
if (LOG.isLoggable(INFO))
LOG.info("Generated offer: " + (o != null));
if (o != null) writerTasks.add(new WriteOffer(o));
@@ -369,14 +357,8 @@ class DuplexOutgoingSession implements SyncSession, EventListener {
if (!generateRequestQueued.getAndSet(false))
throw new AssertionError();
try {
Request r;
Transaction txn = db.startTransaction(false);
try {
r = db.generateRequest(txn, contactId, MAX_MESSAGE_IDS);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Request r = db.transactionWithNullableResult(false, txn ->
db.generateRequest(txn, contactId, MAX_MESSAGE_IDS));
if (LOG.isLoggable(INFO))
LOG.info("Generated request: " + (r != null));
if (r != null) writerTasks.add(new WriteRequest(r));

View File

@@ -6,7 +6,6 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
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.EventBus;
import org.briarproject.bramble.api.event.EventListener;
@@ -120,13 +119,8 @@ class IncomingSession implements SyncSession, EventListener {
@Override
public void run() {
try {
Transaction txn = db.startTransaction(false);
try {
db.receiveAck(txn, contactId, ack);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn ->
db.receiveAck(txn, contactId, ack));
} catch (DbException e) {
logException(LOG, WARNING, e);
interrupt();
@@ -146,13 +140,8 @@ class IncomingSession implements SyncSession, EventListener {
@Override
public void run() {
try {
Transaction txn = db.startTransaction(false);
try {
db.receiveMessage(txn, contactId, message);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn ->
db.receiveMessage(txn, contactId, message));
} catch (DbException e) {
logException(LOG, WARNING, e);
interrupt();
@@ -172,13 +161,8 @@ class IncomingSession implements SyncSession, EventListener {
@Override
public void run() {
try {
Transaction txn = db.startTransaction(false);
try {
db.receiveOffer(txn, contactId, offer);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn ->
db.receiveOffer(txn, contactId, offer));
} catch (DbException e) {
logException(LOG, WARNING, e);
interrupt();
@@ -198,13 +182,8 @@ class IncomingSession implements SyncSession, EventListener {
@Override
public void run() {
try {
Transaction txn = db.startTransaction(false);
try {
db.receiveRequest(txn, contactId, request);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
db.transaction(false, txn ->
db.receiveRequest(txn, contactId, request));
} catch (DbException e) {
logException(LOG, WARNING, e);
interrupt();

View File

@@ -36,6 +36,7 @@ class MessageFactoryImpl implements MessageFactory {
@Override
public Message createMessage(GroupId g, long timestamp, byte[] body) {
if (body.length == 0) throw new IllegalArgumentException();
if (body.length > MAX_MESSAGE_BODY_LENGTH)
throw new IllegalArgumentException();
MessageId id = getMessageId(g, timestamp, body);
@@ -54,7 +55,7 @@ class MessageFactoryImpl implements MessageFactory {
@Override
public Message createMessage(byte[] raw) {
if (raw.length < MESSAGE_HEADER_LENGTH)
if (raw.length <= MESSAGE_HEADER_LENGTH)
throw new IllegalArgumentException();
if (raw.length > MAX_MESSAGE_LENGTH)
throw new IllegalArgumentException();

View File

@@ -5,7 +5,6 @@ import org.briarproject.bramble.api.contact.event.ContactRemovedEvent;
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.EventBus;
import org.briarproject.bramble.api.event.EventListener;
@@ -47,7 +46,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
private static final Logger LOG =
Logger.getLogger(SimplexOutgoingSession.class.getName());
private static final ThrowingRunnable<IOException> CLOSE = () -> {};
private static final ThrowingRunnable<IOException> CLOSE = () -> {
};
private final DatabaseComponent db;
private final Executor dbExecutor;
@@ -128,14 +128,8 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
public void run() {
if (interrupted) return;
try {
Ack a;
Transaction txn = db.startTransaction(false);
try {
a = db.generateAck(txn, contactId, MAX_MESSAGE_IDS);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Ack a = db.transactionWithNullableResult(false, txn ->
db.generateAck(txn, contactId, MAX_MESSAGE_IDS));
if (LOG.isLoggable(INFO))
LOG.info("Generated ack: " + (a != null));
if (a == null) decrementOutstandingQueries();
@@ -172,15 +166,10 @@ class SimplexOutgoingSession implements SyncSession, EventListener {
public void run() {
if (interrupted) return;
try {
Collection<Message> b;
Transaction txn = db.startTransaction(false);
try {
b = db.generateBatch(txn, contactId,
MAX_RECORD_PAYLOAD_BYTES, maxLatency);
db.commitTransaction(txn);
} finally {
db.endTransaction(txn);
}
Collection<Message> b =
db.transactionWithNullableResult(false, txn ->
db.generateBatch(txn, contactId,
MAX_RECORD_PAYLOAD_BYTES, maxLatency));
if (LOG.isLoggable(INFO))
LOG.info("Generated batch: " + (b != null));
if (b == null) decrementOutstandingQueries();

View File

@@ -1,23 +1,11 @@
package org.briarproject.bramble.sync;
import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.sync.GroupFactory;
import org.briarproject.bramble.api.sync.MessageFactory;
import org.briarproject.bramble.api.sync.SyncRecordReaderFactory;
import org.briarproject.bramble.api.sync.SyncRecordWriterFactory;
import org.briarproject.bramble.api.sync.SyncSessionFactory;
import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.system.Clock;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
import dagger.Module;
@@ -26,29 +14,14 @@ import dagger.Provides;
@Module
public class SyncModule {
public static class EagerSingletons {
@Inject
ValidationManager validationManager;
}
/**
* The maximum number of validation tasks to delegate to the crypto
* executor concurrently.
* <p>
* The number of available processors can change during the lifetime of the
* JVM, so this is just a reasonable guess.
*/
private static final int MAX_CONCURRENT_VALIDATION_TASKS =
Math.max(1, Runtime.getRuntime().availableProcessors() - 1);
@Provides
GroupFactory provideGroupFactory(CryptoComponent crypto) {
return new GroupFactoryImpl(crypto);
GroupFactory provideGroupFactory(GroupFactoryImpl groupFactory) {
return groupFactory;
}
@Provides
MessageFactory provideMessageFactory(CryptoComponent crypto) {
return new MessageFactoryImpl(crypto);
MessageFactory provideMessageFactory(MessageFactoryImpl messageFactory) {
return messageFactory;
}
@Provides
@@ -65,30 +38,8 @@ public class SyncModule {
@Provides
@Singleton
SyncSessionFactory provideSyncSessionFactory(DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor, EventBus eventBus,
Clock clock, SyncRecordReaderFactory recordReaderFactory,
SyncRecordWriterFactory recordWriterFactory) {
return new SyncSessionFactoryImpl(db, dbExecutor, eventBus, clock,
recordReaderFactory, recordWriterFactory);
}
@Provides
@Singleton
ValidationManager provideValidationManager(
LifecycleManager lifecycleManager, EventBus eventBus,
ValidationManagerImpl validationManager) {
lifecycleManager.registerService(validationManager);
eventBus.addListener(validationManager);
return validationManager;
}
@Provides
@Singleton
@ValidationExecutor
Executor provideValidationExecutor(
@CryptoExecutor Executor cryptoExecutor) {
return new PoliteExecutor("ValidationExecutor", cryptoExecutor,
MAX_CONCURRENT_VALIDATION_TASKS);
SyncSessionFactory provideSyncSessionFactory(
SyncSessionFactoryImpl syncSessionFactory) {
return syncSessionFactory;
}
}

View File

@@ -124,7 +124,8 @@ class SyncRecordReaderImpl implements SyncRecordReader {
if (!hasMessage()) throw new FormatException();
if (nextRecord == null) throw new AssertionError();
byte[] payload = nextRecord.getPayload();
if (payload.length < MESSAGE_HEADER_LENGTH) throw new FormatException();
if (payload.length <= MESSAGE_HEADER_LENGTH)
throw new FormatException();
// Validate timestamp
long timestamp = ByteUtils.readUint64(payload, UniqueId.LENGTH);
if (timestamp < 0) throw new FormatException();

View File

@@ -1,4 +1,4 @@
package org.briarproject.bramble.sync;
package org.briarproject.bramble.sync.validation;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

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