Compare commits

..

140 Commits

Author SHA1 Message Date
akwizgran
0e51ddb767 Bumped expiry date to 1 May 2017. 2017-02-27 09:29:24 +00:00
Torsten Grote
36f02b36d9 Update expiry and translations 2017-02-01 11:17:53 -02:00
akwizgran
2fb11fba2a Merge branch '877-save-invitation-outcome-to-invitation-message-and-make-available-to-ui' into 'master'
Store invitation outcome in metadata and make it available to the UI

This MR is based on !479 and should only be merged after that one has been merged as well.

It stores the invitation outcome in the message metadata  and includes it in the `canBeOpened()` calculation for private groups and sharables.

Closes #877

See merge request !480
2017-01-06 16:06:19 +00:00
akwizgran
1d11857e75 Merge branch '476-blog-sharing-protocol-modifies-state-external-to-session' into 'master'
Migrate blog sharing to new sharing client infrastructure

This MR contains a second small commit that fixes #816 and adds a test for it.

Closes #476, #701

See merge request !479
2017-01-06 16:04:17 +00:00
Torsten Grote
04508a7431 Store invitation outcome in metadata
and include in canBeOpened calculation for private groups and sharables.
2017-01-06 13:29:21 -02:00
Torsten Grote
5653c6d650 Address review comments 2017-01-06 13:25:13 -02:00
Torsten Grote
ab100ad19b Properly remove the blog when deleting a contact and inform all peers
Fixes #816
2017-01-06 13:01:37 -02:00
Torsten Grote
c13eafef14 Migrate blog sharing to new sharing client infrastructure 2017-01-06 13:01:34 -02:00
akwizgran
d5443e9651 Merge branch '889-select-navdrawer-item-when-coming-from-notification' into 'master'
Check the blog item in NavDrawer when opening a blog via notification

There are three scenarios where the selected item in the NavDrawer changes:
1. The user selects an item -> the item is checked automatically.
2. The user pressed back -> already handled in onBackPressed (needs to be extended with #606)
3. The user touched a notification -> handled by this commit.
   
Signed-off-by: goapunk <noobie@goapunks.net>

Closes #889

See merge request !481
2017-01-06 14:59:21 +00:00
akwizgran
d5f9a3280d Merge branch 'briar-recycler-view-log' into 'master'
Stop periodic list update only once

When testing the forum unread code, I noticed the recycler view is detaching twice. Once because the stop method is called and once because the view detaches from the window. Wouldn't it be safe to null the refresher when the updates are stopped?

See merge request !478
2017-01-06 14:15:48 +00:00
goapunk
09b2ecaecf Check the corresponding NavDrawer item when coming from a notification
Signed-off-by: goapunk <noobie@goapunks.net>
2017-01-06 15:12:40 +01:00
Torsten Grote
dc6a6f27ab Fix MessageTreeImplTest 2017-01-04 16:27:49 -02:00
Torsten Grote
8d9ddeeeee Stop periodic list update only once 2017-01-04 11:15:19 -02:00
Torsten Grote
baed2b8483 Merge branch '879-remove-thread-collapsing-unread-count' into 'master'
Remove code for collapsing threads and for reply count

Besides removing lots of code, this MR also improves the encapsulation between adapter and view holders.

Closes #478, #502, #526, #682,  #683,  #835,  #836

See merge request !477
2017-01-04 13:00:16 +00:00
Torsten Grote
b3d3230549 Remove code for collapsing threads and for reply count 2017-01-04 10:58:31 -02:00
akwizgran
deb8787668 Merge branch '879-threaded-unread-messages' into 'master'
Threaded Unread Handling

![unread](/uploads/457c3bc36c897d683ff8161b4f3a344c/unread.mp4)

This leaves in the collapsing code for now and just hides the UI element for collapsing. The code can be removed in a second pass to simplify the adapter.

Closes #879

See merge request !476
2017-01-04 11:12:24 +00:00
Torsten Grote
7034ea28f3 Merge branch '475-new-sharing-client' into 'master'
New Forum Sharing Client

This is very similar to how the private group invitations work and I am sure there's still some tiny bugs that I didn't catch.

All existing integration tests either pass or have been modified to pass.

Once this has been merged, the code should be usable for blog sharing as well.

Closes #475

See merge request !467
2017-01-03 19:30:48 +00:00
Torsten Grote
51b78cf9b1 Address review comments for new sharing client 2017-01-03 17:25:45 -02:00
Torsten Grote
b4c669243b Add UnreadMessageButton to threaded conversations 2017-01-03 13:25:31 -02:00
Torsten Grote
694e662028 New Forum Sharing Client 2017-01-03 11:23:02 -02:00
Torsten Grote
409e0fb5a5 ForumSharingValidator 2017-01-03 11:23:00 -02:00
Torsten Grote
279f4d668a Add new UnreadMessageButton class 2017-01-02 16:30:00 -02:00
akwizgran
d2608e28ac Merge branch '881-forumactivitytest-fails-due-to-custom-toolbar' into 'master'
Fix ForumActivityTest and get rid of redundant theme definition

Closes #881

See merge request !474
2017-01-02 14:22:27 +00:00
akwizgran
8cf02c5f0e Merge branch '851-refresher-memory-leak' into 'master'
Fix memory leaks caused by periodic view refreshing tasks

This branch implements @goapunk's suggested solution to #851. Credit goes to @ernir for finding the bug and the initial solution, and @goapunk for the improved solution - I just did a quick implementation so we can get this fixed as quickly as possible.

Closes #851

See merge request !473
2017-01-02 14:10:32 +00:00
Torsten Grote
c5df2100da Fix ForumActivityTest and get rid of redundant theme definition 2017-01-02 11:57:45 -02:00
akwizgran
a6999a8197 Merge branch '710-conversationactivity-uses-uninitialised-field-as-format-string-argument' into 'master'
Make sure contact name is initialized when needed

This uses a Listenable Future and unfortunately requires 4 basically identical methods to handle the incoming events. Any suggestions for improving that are welcome.

Closes #710

See merge request !472
2017-01-02 11:11:41 +00:00
akwizgran
da89f11419 Merge branch '882-feedmanagerimpl-logs-rss-feed-urls' into 'master'
Do not log information from RSS feeds

Closes #882

See merge request !475
2017-01-02 10:52:04 +00:00
Torsten Grote
a9663875f4 Update expiry date and translations 2016-12-30 12:13:43 -02:00
Torsten Grote
804966ede6 Do not log information from RSS feeds 2016-12-29 13:07:18 -02:00
Torsten Grote
f0f22b42e5 Make sure contact name is initialized when needed 2016-12-29 12:29:32 -02:00
akwizgran
59316ae3c4 Fix memory leaks caused by periodic view refreshing tasks. 2016-12-28 15:23:21 +00:00
Torsten Grote
460b524e4b Merge branch 'record-reading-tests' into 'master'
Unit tests for record readers

I thought we should have some tests for the new logic that skips unrecognised record types.

See merge request !471
2016-12-21 17:14:16 +00:00
akwizgran
48e949c9f8 Merge branch '742-use-unique-request-ids-across-the-app' into 'master'
Use unique request codes across the app

Closes #742

See merge request !470
2016-12-21 15:33:03 +00:00
Torsten Grote
924398c829 Use unique request codes across the app 2016-12-21 12:52:11 -02:00
akwizgran
8619b044ce Merge branch '469-handle-background-errors' into 'master'
Add a handleDbException() method to BaseActivity

This adds a `handleDbException()` method to BaseActivity and a corresponding method for fragments that calls through to the activity.
For now, the method just finishes the activity
and NavDrawerActivity overrides it to do nothing,
and all the error places marked with TODO that finish the activity call the method instead.

That gives us zero functional improvement over the status quo,
but it allows us to change the default behaviour easily,
and then we can start thinking about which cases should have non-default behaviour.

First part of #469

See merge request !469
2016-12-21 14:46:53 +00:00
akwizgran
3c3731a562 Merge branch '876-group-invitation-not-marked-unavailable' into 'master'
Mark invitation unavailable to answer when creator dissolved the group after the invitation.

Closes #876

See merge request !468
2016-12-21 14:43:38 +00:00
akwizgran
b54984b542 Unit tests for RecordReaderImpl. 2016-12-21 14:39:56 +00:00
akwizgran
2390f767f5 Unit tests for KeyAgreementTransport. 2016-12-21 14:08:21 +00:00
Torsten Grote
0a9840997f This adds a handleDbException() method to BaseActivity
and a corresponding method for fragments that calls through to the activity.
For now, the method just finishes the activity
and NavDrawerActivity overrides it to do nothing,
and all the error places marked with TODO that finish the activity call the method instead.

That gives us zero functional improvement over the status quo,
but it allows us to change the default behaviour easily,
and then we can start thinking about which cases should have non-default behaviour.
2016-12-21 12:06:20 -02:00
Torsten Grote
6a94785d9a Mark invitation unavailable to answer when creator dissolved the group
after the invitation.

Closes #876
2016-12-21 11:24:08 -02:00
akwizgran
79fc41477c Merge branch '628-bring-protocols-into-line-with-spec' into 'master'
Bring protocols in line with spec

Closes #628

See merge request !465
2016-12-21 12:52:43 +00:00
Torsten Grote
efb89adf41 Merge branch '793-show-open-button-after-accepting-invitations' into 'master'
Show open button in private conversation after accepting invitations

To keep the implementation simple, the Open button does appear where the Accept button had been previously.

In order to make the Open button functional, I had to make the `GroupId` of the invitation target available to the UI. Most code in this MR is due to that.

![device-2016-12-13-105228](/uploads/d0f27fc02f1411596458d9203a0810d2/device-2016-12-13-105228.png)

Closes #793

See merge request !457
2016-12-20 14:07:13 +00:00
Torsten Grote
c04580e321 Don't open unsubscribed shareables 2016-12-20 12:00:01 -02:00
Torsten Grote
2ef9b8f4b6 Show open button in private conversation after accepting invitations 2016-12-20 08:47:27 -02:00
akwizgran
d63d15329c Merge branch '814-enable-QrScanner-after-QrCode-was-created' into 'master'
Ignore QR code results until local QR code is created

* Make scanning only possible after we are "ready" (= our QrCode was created and set).

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #814

See merge request !454
2016-12-19 19:28:14 +00:00
Torsten Grote
5345db0b6b Address review comments 2016-12-19 11:15:53 -02:00
Torsten Grote
501980d8fe Bring protocols in line with spec 2016-12-19 10:26:48 -02:00
akwizgran
cc5c000278 Merge branch '738-older-devices-show-overflow-icon-on-some-screens-but-not-others' into 'master'
Also show overflow icon on devices with menu key by using Toolbar

Closes #738

See merge request !463
2016-12-16 11:58:18 +00:00
akwizgran
3ce0131b8c Merge branch '828-update-briar-logo-in-app' into 'master'
Update all logos

The launcher icons are now in mipmap folders which is the recommended practice, because on a low-res device, the high res drawables are stripped from the app. This is bad when the user decides to show the app icons really big on the launcher and the high-res drawables are not available anymore.

The old launcher icon seemed to have some sort of 3D effect.
![device-2016-12-13-134037](/uploads/84db532df3821ad74ba57719f0763b7b/device-2016-12-13-134037.png)

Navigation Drawer Old:
![device-2016-12-13-124112](/uploads/465b817d2e0bbbd50b461ea32686c933/device-2016-12-13-124112.png)
Navigation Drawer New:
![device-2016-12-13-132428](/uploads/3c3530bfc515525dd8f66abfa52d1142/device-2016-12-13-132428.png)

Closes #828

See merge request !459
2016-12-15 23:25:40 +00:00
akwizgran
008e4f760a Merge branch '795-use-different-notification-icons-for-different-features' into 'master'
Use different notification icons for different features

![device-2016-12-13-151008](/uploads/2c9aa33c230738b5ea20a76ac5e3b214/device-2016-12-13-151008.png)
![device-2016-12-13-150954](/uploads/85acd46fc6afd3aebcc1fcd015b041d7/device-2016-12-13-150954.png)

Closes #795

See merge request !460
2016-12-15 23:16:36 +00:00
akwizgran
fc44268b22 Removed translations of unused strings. 2016-12-15 23:12:24 +00:00
akwizgran
de0a7c75ed Merge branch '697-include-commit-id-in-crash-reports-and-feedback' into 'master'
Include Commit ID in crash reports and feedback

Closes #697

See merge request !461
2016-12-15 23:06:24 +00:00
Torsten Grote
1c6be2fb78 Include Commit ID in crash reports and feedback 2016-12-15 15:40:52 -02:00
Torsten Grote
09b0a8b161 Use different notification icons for different features
and use the primary color for the notification.
2016-12-15 15:29:48 -02:00
Torsten Grote
a6d053a0ea Update all logos 2016-12-15 15:19:38 -02:00
akwizgran
e7a26c42a4 Merge branch '285-plugins-should-throw-exceptions-for-startup-errors' into 'master'
Plugins throw exceptions for startup errors

Please review carefully as I don't know much about the code I have touched here.

Closes #285

See merge request !462
2016-12-15 14:33:35 +00:00
akwizgran
bb5fc35e17 Removed translations of unused strings. 2016-12-15 10:56:04 +00:00
Torsten Grote
ea4e2f09c8 Revert dagger update 2016-12-14 16:52:38 -02:00
Torsten Grote
ffc9fdbb92 Plugins throw exceptions for startup errors 2016-12-14 16:35:23 -02:00
akwizgran
074f5c2faf Fix imports in HashTest. 2016-12-14 17:09:15 +00:00
goapunk
7666b210e4 Ignore results from the QrScanner if task is not ready
* Ignore results until the KeyAgreementTask is ready and returned the local payload

Signed-off-by: goapunk <noobie@goapunks.net>
2016-12-14 17:28:01 +01:00
akwizgran
ab3fcb6219 Merge branch 'add-crypto-hash-test' into 'master'
Add Unit tests for CryptoComponent#hash()

See merge request !464
2016-12-14 16:14:18 +00:00
akwizgran
b7e35ff780 Merge branch '778-move-unit-tests-into-their-respective-modules' into 'master'
Move all unit tests to their modules and remove briar-tests

There are now tests in these modules:
* bramble-api
* bramble-core
* bramble-j2se
* briar-core
* briar-android

In order to run all -core tests together, the following AS run configuration can be used:
![Screenshot_2016-12-12_16-37-53](/uploads/8c706406f015ecd9e2371ebc28e6b34c/Screenshot_2016-12-12_16-37-53.png)

Closes #778

See merge request !456
2016-12-14 15:57:45 +00:00
akwizgran
3c2428449d Moved test utility classes into test package. 2016-12-14 15:42:52 +00:00
Torsten Grote
25a4caec2a Add Unit tests for CryptoComponent#hash() 2016-12-14 13:15:44 -02:00
Torsten Grote
db71472501 Also show overflow icon on devices with menu key by using Toolbar 2016-12-14 11:17:04 -02:00
Torsten Grote
1081a08ea9 Move all unit tests to their modules and remove briar-tests 2016-12-13 17:22:24 -02:00
akwizgran
32be148c7a Merge branch '646-shared-with-subtitle-groups' into 'master'
Add sharing information to private group ActionBar subtitle

![device-2016-12-12-114533](/uploads/b31fc37643ef6e817a80a4ddd767fe98/device-2016-12-12-114533.png)

Closes #646

See merge request !455
2016-12-13 18:01:48 +00:00
Torsten Grote
78000375df Merge branch '155-notification-icon' into 'master'
Make notification icon less similar to superuser icon

Closes #155

See merge request !458
2016-12-13 17:24:05 +00:00
akwizgran
66f8978bb6 Make notification icon less similar to superuser icon. 2016-12-13 17:20:48 +00:00
Torsten Grote
45b5040254 Add sharing information to private group ActionBar subtitle 2016-12-12 13:55:35 -02:00
Torsten Grote
378a8f0a10 Merge branch '813-add-online-status-and-creator-information-to-group-memberlist' into 'master'
Add creator and online information to group member list

![device-2016-12-06-102258](/uploads/90e19a6ca31aaf91c6ebf3ea8e218b3f/device-2016-12-06-102258.png)
![device-2016-12-06-110113](/uploads/3fd62f7cdfe75419a07262356d27b952/device-2016-12-06-110113.png)

Closes #813

See merge request !448
2016-12-12 15:36:02 +00:00
Torsten Grote
562866494b Add creator and online information to group member list 2016-12-12 13:33:23 -02:00
akwizgran
c9cb085a0a Merge branch '777-move-integration-tests-into-their-respective-modules' into 'master'
Move integration tests to their proper packages

Closes #777

See merge request !453
2016-12-12 15:08:26 +00:00
Torsten Grote
97d4c68f43 Move integration tests to their proper packages 2016-12-12 10:27:41 -02:00
Torsten Grote
4226ba40c2 Merge branch '570-consistent-use-of-animations' into 'master'
Make animations more consistent

![animations6](/uploads/0ac694d3561515e04fbb9032d31f183c/animations6.mp4)

Closes #570, #621

See merge request !439
2016-12-09 16:49:26 +00:00
Torsten Grote
3df3d19a07 Address review comments 2016-12-09 14:40:20 -02:00
Torsten Grote
e3dcc62509 Use back transition when backing out of creating private group 2016-12-09 14:22:05 -02:00
Torsten Grote
db3c3eee44 Move OnBlogPostClickListener from activity to fragment 2016-12-09 14:22:03 -02:00
Torsten Grote
5a522d64df Don't show splash screen when signed in
This also removes the BriarFragmentActivity that was only really used by
the NavDrawerActivity.
2016-12-09 14:14:47 -02:00
Torsten Grote
68b216d580 Make animations more consistent 2016-12-09 14:13:18 -02:00
Torsten Grote
d5c6fcc85b Fix merge accident after renaming event 2016-12-09 14:12:27 -02:00
Torsten Grote
a099104d08 Merge branch '646-shared-with-subtitle-forums' into 'master'
Add sharing info to ForumActivity action bar subtitle

This indirectly does also most of the work for adding the same information to private groups. However, completing this is blocked by !448.

![device-2016-12-07-152915](/uploads/5bb42f2e78a87931b0307e7597ba72c5/device-2016-12-07-152915.png)

Second part of #646

See merge request !451
2016-12-09 16:06:21 +00:00
akwizgran
787b3399f7 Merge branch '646-shared-with-subtitle' into 'master'
Add blog sharing information to toolbar subtitle

This MR introduces a new `SharingController` which is supposed to be used in activities that show blogs, groups and forums. Feedback on this approach is welcome before this is used to add "Shared with" support to other parts of the UI.

The toolbar subtitle shows information about how many contacts the current shareable is shared with and how many of those are online.

So far this is implemented for blogs:

![device-2016-12-05-180207](/uploads/13afb4c7c5d10ad29c414865ee02670d/device-2016-12-05-180207.png)

One part of #646

See merge request !447
2016-12-09 16:04:04 +00:00
Torsten Grote
4e159bbb1f Add sharing info to ForumActivity action bar subtitle 2016-12-09 14:02:42 -02:00
Torsten Grote
7c6232db9d Address review comments (rename event, fix annotations, final field) 2016-12-09 13:54:39 -02:00
Torsten Grote
6cf1480d2d Merge branch '766-unit-tests-for-peer-protocol-engine' into 'master'
Add unit tests for PeerProtocolEngine

Although not all classes have unit tests, this

Closes #766

See merge request !450
2016-12-08 16:14:34 +00:00
Torsten Grote
2679e6932f Add unit tests for PeerProtocolEngine 2016-12-08 14:13:00 -02:00
akwizgran
17e149e517 Merge branch '766-unit-tests-for-invitee-protocol-engine' into 'master'
Add unit tests for InviteeProtocolEngine

Next part of #766

See merge request !444
2016-12-08 15:42:05 +00:00
Torsten Grote
d04dda1566 Add sharing information to toolbar subtitle of blogs
The toolbar subtitle shows information about how many contacts the
current blog is shared with and how many of those are online.
2016-12-07 15:16:44 -02:00
Torsten Grote
5588855667 Fix intent of some CreatorProtocolEngine unit tests 2016-12-07 15:07:01 -02:00
Torsten Grote
7df6abbcbe Merge branch '810-fix-sharing-status-screens' into 'master'
Fix Sharing Status screens

* Remove distinction between "shared with" and "shared by"
* Show all contacts a blog is shared with
* Show online status of contacts in sharing screen

![device-2016-12-05-142949](/uploads/703fbd2d52815374e57edd89f754bf6c/device-2016-12-05-142949.png)

Closes #810

See merge request !445
2016-12-07 16:52:29 +00:00
Torsten Grote
001f5faeaa Two small review details: comment and initializing boolean 2016-12-07 14:49:57 -02:00
Torsten Grote
ba1a19d236 Address review issues 2016-12-07 14:31:24 -02:00
Torsten Grote
b7ce7de42a Add unit tests for InviteeProtocolEngine 2016-12-07 14:31:23 -02:00
akwizgran
3f6a8f9341 Merge branch '808-introduction-client-logs-contact-names' into 'master'
Remove verbose logging from introduction client

Closes #808

See merge request !449
2016-12-07 15:49:14 +00:00
akwizgran
9495163016 Merge branch 'onboarding-dialog-style' into 'master'
Introduce Dialog Theme for Onboarding

Currently onboarding dialogs and confirmation dialogs look the same. This MR introduces a new dialog theme for onboarding dialogs that looks like the tap target onboarding, so that the user can immediately spot the purpose of the dialog.

![device-2016-12-06-085539](/uploads/6d75b17c0f20028bb7ffac65e6fba03a/device-2016-12-06-085539.png)

See merge request !446
2016-12-07 15:47:12 +00:00
Torsten Grote
7f5a5d40dc Remove verbose logging from introduction client 2016-12-06 15:36:54 -02:00
Torsten Grote
98dd8ec7f7 Fix Sharing Status screens
* Remove distinction between "shared with" and "shared by"
* Show all contacts a blog is shared with
* Show online status of contacts in sharing screen
2016-12-06 10:53:50 -02:00
akwizgran
27c2ee8d89 Merge branch '548-require-a-label-for-hashing' into 'master'
Require a label for hashing

* Add a string label argument to `CryptoComponent#hash()`
* Convert `DoubleDigest` from implementing `MessageDigest`
  to implementing `org.spongycastle.crypto.Digest`
  (we need to keep `DoubleDigest` for `FortunaGenerator`)
* Convert all other uses of `MessageDigest` to `CryptoComponent#hash()`
* Remove `CryptoComponent#getMessageDigest()`, `MessageDigest` and `DigestWrapper`

Closes #548

See merge request !442
2016-12-06 11:07:58 +00:00
Torsten Grote
b98ab93e77 Merge branch '283-die-bluetooth-die' into 'master'
Ensure key agreement tasks finish if they ignore interrupts

The problem here was that `BluetoothSocket#connect()` was throwing an IOException when the task was interrupted - the task treated this like any other connection failure and retried, so the task never finished.

The fix is to check whether the timeout has expired before retrying, so the task eventually finishes even if it ignores the original interrupt.

Closes #283

See merge request !443
2016-12-06 11:02:19 +00:00
Torsten Grote
81337fe7ad Introduce Dialog Theme for Onboarding 2016-12-05 14:54:39 -02:00
akwizgran
cdd234dfe3 Ensure key agreement tasks finish if they ignore interrupts. 2016-12-05 12:38:45 +00:00
Torsten Grote
062ed4ef4b Require a label for hashing
* Add a string label argument to CryptoComponent#hash()
* Convert DoubleDigest from implementing MessageDigest
  to implementing org.spongycastle.crypto.Digest
  (we need to keep DoubleDigest for FortunaGenerator)
* Convert all other uses of MessageDigest to CryptoComponent#hash()
* Remove CryptoComponent#getMessageDigest(), MessageDigest and DigestWrapper
2016-12-05 09:57:18 -02:00
akwizgran
9c22ea8434 Merge branch '766-unit-tests-for-creator-protocol-engine' into 'master'
Add unit tests for CreatorProtocolEngine

See merge request !441
2016-12-05 09:59:40 +00:00
Torsten Grote
9458b185f8 Add unit test for CreatorProtocolEngine 2016-12-02 10:57:00 -02:00
akwizgran
c2b06536ad Merge branch 'identity-manager-unit-tests' into 'master'
Add missing IdentityManager unit tests

See merge request !440
2016-12-02 10:35:15 +00:00
akwizgran
878b52ef2c Merge branch '771-create-bramble-modules' 2016-12-01 21:48:03 +00:00
Torsten Grote
a9ddb0019e Add missing IdentityManager unit tests 2016-12-01 13:21:09 -02:00
akwizgran
2d7cb7b279 Updated Transifex config. 2016-12-01 10:19:24 +00:00
akwizgran
f25d33b0c8 Move stray resources to the right place. 2016-12-01 10:18:42 +00:00
akwizgran
906dd1bd06 Added .gitignore files for new modules. 2016-12-01 10:08:46 +00:00
akwizgran
ad6016d428 Updated java.library.path. 2016-11-30 18:10:49 +00:00
akwizgran
f6d23b4d1a Merge branch '705-blog-pager-race-conditions' into 'master'
Remove blog pagers

I set out to fix potential race conditions in the blog pagers (the screens you reach by tapping the body of a blog post, that allow you to swipe left and right through the posts in the combined feed or a single blog). The race conditions here are similar to those addressed by !356, but the adapters don't inherit from BriarAdapter so they need to be fixed separately.

While I was looking into this I found a few minor problems with the pagers:
* The feed pager wasn't responding to events - this was fixed in !398
* The feed pager finishes NavDrawerActivity when any blog is removed
* The feed isn't updated when a blog is added (this applies to the list view as well as the pager)
* Posts aren't removed from the feed pager when a blog is removed

The last problem is quite serious - the feed pager's adapter contains posts that are no longer in the DB, so they'll fail to load. To fix that problem, the adapter needs to be cleared in onStop() and repopulated in onStart(). This is the same approach we use for other adapters where items can be removed from the underlying dataset. Unfortunately, FragmentStatePagerAdapter has some odd behaviour when you clear and repopulate it:

1. When reselecting the previously selected item after clearing and repopulating the adapter, the item slides into view instead of just appearing, which makes it look like you've accidentally swiped.
2. Items are sometimes duplicated when clearing and repopulating the adapter, so swiping left or right shows another copy of the same post.

These problems only seem to happen if the adapter is cleared - adding new posts works fine on master, although I think there might be some luck involved - FragmentStatePagerAdapter doesn't seem to be designed to support items changing positions.

I spent a lot of time trying to resolve these problems before concluding that maybe it wasn't worth it, and we should just remove the pagers. That's what's currently implemented in this branch. Tapping the body of a post will show the full-length post, but you won't be able to swipe left or right.

The swiping functionality was nice to have, so if you have ideas for fixing the bugs I'd love to hear them. But I'd rather remove this functionality than keep it in a buggy state with no plan for how to fix it.

Closes #705

See merge request !400
2016-11-30 11:21:03 +00:00
akwizgran
aa064e853a Merge branch '760-integration-tests-for-private-group-invitation-protocol' into 'master'
Add integration tests for GroupInvitationManager

This MR is based on !433. It adds some integration tests for the private group invitation protocol. One of those tests fails at the moment.

It does not yet cover all corner cases, so it does not fully address #760, but addresses a part of it. Suggestions for more scenarios to test are welcome.

[Wording changed to prevent #760 from being closed automatically based on the description.]

See merge request !434
2016-11-30 11:19:05 +00:00
akwizgran
8a139eaf5d Tightened up test expectations. 2016-11-30 11:17:57 +00:00
akwizgran
d51f73151f Fixed a bug in the group invitation protocol, added tests. 2016-11-30 11:12:04 +00:00
akwizgran
6c90204c6e Fixed a broken unit test. 2016-11-30 11:07:30 +00:00
akwizgran
f8266d8a02 Tightened up some tests. 2016-11-30 10:23:43 +00:00
akwizgran
f245b04726 Fixed a failing test. 2016-11-30 10:23:43 +00:00
Torsten Grote
67d9f3a7c2 Add integration tests for GroupInvitationManager 2016-11-30 10:23:35 +00:00
akwizgran
24d68c4f5b Merge branch '727-refactor-integration-tests' into 'master'
Refactor Integration Tests

This is quite a massive MR (currently 1763 additions and 3482 deletions). However, there's not so much happening. The only thing I did was moving redundant code from the various protocol integration tests to the `BriarIntegrationTest` class.

All integration tests are still passing.

Closes #727

See merge request !433
2016-11-29 18:28:11 +00:00
akwizgran
edbd7f4eeb Addressed review comments. 2016-11-29 18:27:19 +00:00
akwizgran
2f7830e73f Merge branch '766-unit-tests-for-group-validators' into 'master'
Add unit tests for group validators

Part of #766

See merge request !436
2016-11-29 18:13:43 +00:00
akwizgran
a82fdca3d4 Added more private group invitation validation tests. 2016-11-29 18:12:32 +00:00
akwizgran
050111a994 Added some more private group validation tests, found a bug. 2016-11-29 17:46:46 +00:00
akwizgran
a22d1d811f Merge branch '766-unit-tests-for-group-invitation-client' into 'master'
Add unit tests for group invitation client

Part of #766

See merge request !429
2016-11-29 11:51:17 +00:00
akwizgran
90124e00ca Addressed review comments. 2016-11-29 11:50:20 +00:00
akwizgran
04323856de Merge branch '782-wrong-item-selected-in-navdrawer-onBackPressed' into 'master'
Fix Contacts Item always beeing selected if Back is pressed in the NavMenu

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #782

See merge request !438
2016-11-28 17:07:24 +00:00
goapunk
cfcd36f21a Fix Contacts Item always beeing selected if Back is pressed in the NavMenu
Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-28 16:29:41 +01:00
Ernir Erlingsson
2b9ccb4c42 Merge branch '782-wrong-item-selected-in-navdrawer-onBackPressed' into 'master'
Select the correct MenuItem when Back is pressed in NawDrawer

Signed-off-by: goapunk <noobie@goapunks.net>

Closes #782

See merge request !437
2016-11-28 08:37:53 +00:00
Ernir Erlingsson
6436e6688d Merge branch '477-private-messaging-text-bubble-and-header-overlap' into 'master'
Bring back the toolbar shadow

![device-2016-11-21-180111](/uploads/7cd5e6a1e7a4b79b6d7cf81377b148a0/device-2016-11-21-180111.png)

Closes #477

See merge request !431
2016-11-27 21:55:24 +00:00
Torsten Grote
8c7a532e2e Update translations before user testing 2016-11-27 13:38:26 -02:00
goapunk
47171f3e18 Select the correct MenuItem when Back is pressed in NawDrawer
Signed-off-by: goapunk <noobie@goapunks.net>
2016-11-26 23:09:07 +01:00
Torsten Grote
b37a7531ca Add unit tests for group validators 2016-11-23 18:53:03 -02:00
Torsten Grote
2850763ec6 Refactor Integration Tests 2016-11-22 13:31:58 -02:00
Torsten Grote
e69139bc24 Bring back the toolbar shadow 2016-11-21 18:32:29 -02:00
Torsten Grote
b0b932a01c Add unit tests for group invitation client 2016-11-21 16:57:28 -02:00
akwizgran
2837bde774 Removed blog post pagers 2016-11-11 13:38:04 +00:00
akwizgran
411549dc0a Code cleanup, use correct fragment class. 2016-11-11 13:37:32 +00:00
1560 changed files with 32404 additions and 25553 deletions

2
.gitignore vendored
View File

@@ -21,3 +21,5 @@ local.properties
.gradle
build/
*.iml
.gitignore
src/test/

View File

@@ -1,5 +1,5 @@
bin
gen
build
local.properties
.settings
src/main/res/raw/*.zip

View File

@@ -0,0 +1,104 @@
import de.undercouch.gradle.tasks.download.Download
import de.undercouch.gradle.tasks.download.Verify
apply plugin: 'com.android.library'
apply plugin: 'witness'
apply plugin: 'de.undercouch.download'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
minSdkVersion 14
targetSdkVersion 22
versionCode 1
versionName "1.0"
consumerProguardFiles 'proguard-rules.txt'
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
dependencies {
compile project(':bramble-core')
compile fileTree(dir: 'libs', include: ['*.jar'])
provided 'javax.annotation:jsr250-api:1.0'
}
def torBinaryDir = 'src/main/res/raw'
task downloadTorGeoIp(type: Download) {
src 'https://briarproject.org/build/geoip-2015-12-01.zip'
dest "$torBinaryDir/geoip.zip"
onlyIfNewer true
}
task downloadTorBinaryArm(type: Download) {
src 'https://briarproject.org/build/tor-0.2.7.6-arm.zip'
dest "$torBinaryDir/tor_arm.zip"
onlyIfNewer true
}
task downloadTorBinaryArmPie(type: Download) {
src 'https://briarproject.org/build/tor-0.2.7.6-arm-pie.zip'
dest "$torBinaryDir/tor_arm_pie.zip"
onlyIfNewer true
}
task downloadTorBinaryX86(type: Download) {
src 'https://briarproject.org/build/tor-0.2.7.6-x86.zip'
dest "$torBinaryDir/tor_x86.zip"
onlyIfNewer true
}
task downloadTorBinaryX86Pie(type: Download) {
src 'https://briarproject.org/build/tor-0.2.7.6-x86-pie.zip'
dest "$torBinaryDir/tor_x86_pie.zip"
onlyIfNewer true
}
task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
src "$torBinaryDir/geoip.zip"
algorithm 'SHA-256'
checksum '9bcdaf0a7ba0933735328d8ec466c25c25dbb459efc2bce9e55c774eabea5162'
}
task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
src "$torBinaryDir/tor_arm.zip"
algorithm 'SHA-256'
checksum '83272962eda701cd5d74d2418651c4ff0f0b1dff51f558a292d1a1c42bf12146'
}
task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
src "$torBinaryDir/tor_arm_pie.zip"
algorithm 'SHA-256'
checksum 'd0300d1e45de11ebb24ed62b9c492be9c2e88590b7822195ab38c7a76ffcf646'
}
task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
src "$torBinaryDir/tor_x86.zip"
algorithm 'SHA-256'
checksum 'b8813d97b01ee1b9c9a4233c1b9bbe9f9f6b494ae6f9cbd84de8a3911911615e'
}
task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
src "$torBinaryDir/tor_x86_pie.zip"
algorithm 'SHA-256'
checksum '9c66e765aa196dc089951a1b2140cc8290305c2fcbf365121f99e01a233baf4e'
}
project.afterEvaluate {
preBuild.dependsOn {
[
'verifyTorGeoIp',
'verifyTorBinaryArm',
'verifyTorBinaryArmPie',
'verifyTorBinaryX86',
'verifyTorBinaryX86Pie'
]
}
}

View File

@@ -0,0 +1,15 @@
-keep,includedescriptorclasses class org.briarproject.** { *; }
-keep class org.h2.** { *; }
-dontwarn org.h2.**
-dontnote org.h2.**
-keep class dagger.** { *; }
-dontwarn dagger.**
-dontnote dagger.**
-dontwarn sun.misc.Unsafe
-dontnote com.google.common.**
# UPnP library isn't used
-dontwarn org.bitlet.weupnp.**

View File

@@ -0,0 +1,24 @@
<manifest
package="org.briarproject.bramble"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.bluetooth"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<!-- Since API 23, this is needed to add contacts via Bluetooth -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<application
android:allowBackup="false"
android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>

View File

@@ -0,0 +1,13 @@
package org.briarproject.bramble;
import org.briarproject.bramble.plugin.AndroidPluginModule;
import org.briarproject.bramble.system.AndroidSystemModule;
import dagger.Module;
@Module(includes = {
AndroidPluginModule.class,
AndroidSystemModule.class
})
public class BrambleAndroidModule {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.android.api;
package org.briarproject.bramble.api.system;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

View File

@@ -1,20 +1,21 @@
package org.briarproject.plugins;
package org.briarproject.bramble.plugin;
import android.app.Application;
import android.content.Context;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.lifecycle.IoExecutor;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.PluginConfig;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.system.LocationUtils;
import org.briarproject.plugins.droidtooth.DroidtoothPluginFactory;
import org.briarproject.plugins.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.plugins.tor.TorPluginFactory;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.IoExecutor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import org.briarproject.bramble.api.reporting.DevReporter;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.plugin.droidtooth.DroidtoothPluginFactory;
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
import org.briarproject.bramble.plugin.tor.TorPluginFactory;
import java.security.SecureRandom;
import java.util.Arrays;
@@ -28,10 +29,10 @@ import dagger.Module;
import dagger.Provides;
@Module
public class AndroidPluginsModule {
public class AndroidPluginModule {
@Provides
public PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
AndroidExecutor androidExecutor, SecureRandom random,
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
Application app, LocationUtils locationUtils, DevReporter reporter,
@@ -46,7 +47,8 @@ public class AndroidPluginsModule {
backoffFactory, appContext);
final Collection<DuplexPluginFactory> duplex =
Arrays.asList(bluetooth, tor, lan);
return new PluginConfig() {
@NotNullByDefault
PluginConfig pluginConfig = new PluginConfig() {
@Override
public Collection<DuplexPluginFactory> getDuplexFactories() {
@@ -58,5 +60,6 @@ public class AndroidPluginsModule {
return Collections.emptyList();
}
};
return pluginConfig;
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.plugins.droidtooth;
package org.briarproject.bramble.plugin.droidtooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -9,23 +9,24 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.FormatException;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.keyagreement.KeyAgreementConnection;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.properties.TransportProperties;
import org.briarproject.util.StringUtils;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.PseudoRandom;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementConnection;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TransportId;
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.api.system.AndroidExecutor;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.IOException;
@@ -64,12 +65,12 @@ 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.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
import static org.briarproject.api.plugins.BluetoothConstants.ID;
import static org.briarproject.api.plugins.BluetoothConstants.PROP_ADDRESS;
import static org.briarproject.api.plugins.BluetoothConstants.PROP_UUID;
import static org.briarproject.api.plugins.BluetoothConstants.UUID_BYTES;
import static org.briarproject.util.PrivacyUtils.scrubMacAddress;
import static org.briarproject.bramble.api.keyagreement.KeyAgreementConstants.TRANSPORT_ID_BLUETOOTH;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
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.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
@@ -128,7 +129,7 @@ class DroidtoothPlugin implements DuplexPlugin {
}
@Override
public boolean start() throws IOException {
public void start() throws PluginException {
if (used.getAndSet(true)) throw new IllegalStateException();
// BluetoothAdapter.getDefaultAdapter() must be called on a thread
// with a message queue, so submit it to the AndroidExecutor
@@ -142,13 +143,14 @@ class DroidtoothPlugin implements DuplexPlugin {
}).get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IOException("Interrupted while getting BluetoothAdapter");
LOG.warning("Interrupted while getting BluetoothAdapter");
throw new PluginException(e);
} catch (ExecutionException e) {
throw new IOException(e);
throw new PluginException(e);
}
if (adapter == null) {
LOG.info("Bluetooth is not supported");
return false;
throw new PluginException();
}
running = true;
// Listen for changes to the Bluetooth state
@@ -170,7 +172,6 @@ class DroidtoothPlugin implements DuplexPlugin {
LOG.info("Not enabling Bluetooth");
}
}
return true;
}
private void bind() {
@@ -341,8 +342,10 @@ class DroidtoothPlugin implements DuplexPlugin {
LOG.info("Connected to " + scrubMacAddress(address));
return s;
} catch (IOException e) {
if (LOG.isLoggable(INFO))
LOG.info("Failed to connect to " + scrubMacAddress(address));
if (LOG.isLoggable(INFO)) {
LOG.info("Failed to connect to " + scrubMacAddress(address)
+ ": " + e);
}
tryToClose(s);
return null;
}
@@ -588,9 +591,10 @@ class DroidtoothPlugin implements DuplexPlugin {
finished.countDown();
} else if (action.equals(FOUND)) {
BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
if (LOG.isLoggable(INFO))
if (LOG.isLoggable(INFO)) {
LOG.info("Discovered device: " +
scrubMacAddress(d.getAddress()));
}
addresses.add(d.getAddress());
}
}

View File

@@ -1,20 +1,25 @@
package org.briarproject.plugins.droidtooth;
package org.briarproject.bramble.plugin.droidtooth;
import android.content.Context;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.api.TransportId;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.TransportId;
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 java.security.SecureRandom;
import java.util.concurrent.Executor;
import static org.briarproject.api.plugins.BluetoothConstants.ID;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
@Immutable
@NotNullByDefault
public class DroidtoothPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds

View File

@@ -1,14 +1,16 @@
package org.briarproject.plugins.droidtooth;
package org.briarproject.bramble.plugin.droidtooth;
import android.bluetooth.BluetoothSocket;
import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@NotNullByDefault
class DroidtoothTransportConnection extends AbstractDuplexTransportConnection {
private final BluetoothSocket socket;

View File

@@ -1,4 +1,4 @@
package org.briarproject.plugins.tcp;
package org.briarproject.bramble.plugin.tcp;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -7,9 +7,9 @@ import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -39,14 +39,13 @@ class AndroidLanTcpPlugin extends LanTcpPlugin {
}
@Override
public boolean start() {
public void start() {
if (used.getAndSet(true)) throw new IllegalStateException();
running = true;
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
IntentFilter filter = new IntentFilter(CONNECTIVITY_ACTION);
appContext.registerReceiver(networkStateReceiver, filter);
return true;
}
@Override

View File

@@ -1,18 +1,23 @@
package org.briarproject.plugins.tcp;
package org.briarproject.bramble.plugin.tcp;
import android.content.Context;
import org.briarproject.api.TransportId;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.TransportId;
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 java.util.concurrent.Executor;
import static org.briarproject.api.plugins.LanTcpConstants.ID;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
@Immutable
@NotNullByDefault
public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds

View File

@@ -1,18 +1,18 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class TorNetworkMetadata {
class TorNetworkMetadata {
// See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
// and https://trac.torproject.org/projects/tor/wiki/doc/OONI/censorshipwiki
// TODO: get a more complete list
private static final Set<String> BLOCKED_IN_COUNTRIES =
new HashSet<String>(Arrays.asList("CN", "IR", "SY", "ZZ"));
new HashSet<>(Arrays.asList("CN", "IR", "SY", "ZZ"));
public static boolean isTorProbablyBlocked(String countryCode) {
static boolean isTorProbablyBlocked(String countryCode) {
return BLOCKED_IN_COUNTRIES.contains(countryCode);
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -7,6 +7,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.FileObserver;
@@ -15,27 +16,29 @@ import android.os.PowerManager;
import net.freehaven.tor.control.EventHandler;
import net.freehaven.tor.control.TorControlConnection;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.PseudoRandom;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.SettingsUpdatedEvent;
import org.briarproject.api.keyagreement.KeyAgreementListener;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.TorConstants;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.api.properties.TransportProperties;
import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.settings.Settings;
import org.briarproject.api.system.LocationUtils;
import org.briarproject.util.IoUtils;
import org.briarproject.util.StringUtils;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.crypto.PseudoRandom;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
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.api.reporting.DevReporter;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.IoUtils;
import org.briarproject.bramble.util.StringUtils;
import java.io.Closeable;
import java.io.EOFException;
@@ -75,10 +78,11 @@ import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static net.freehaven.tor.control.TorControlCommands.HS_ADDRESS;
import static net.freehaven.tor.control.TorControlCommands.HS_PRIVKEY;
import static org.briarproject.api.plugins.TorConstants.CONTROL_PORT;
import static org.briarproject.util.PrivacyUtils.scrubOnion;
import static org.briarproject.bramble.api.plugin.TorConstants.CONTROL_PORT;
import static org.briarproject.bramble.util.PrivacyUtils.scrubOnion;
@NotNullByDefault
@MethodsNotNullByDefault
@ParametersNotNullByDefault
class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private static final String PROP_ONION = "onion";
@@ -107,13 +111,9 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
private final AtomicBoolean used = new AtomicBoolean(false);
private volatile boolean running = false;
@Nullable
private volatile ServerSocket socket = null;
@Nullable
private volatile Socket controlSocket = null;
@Nullable
private volatile TorControlConnection controlConnection = null;
@Nullable
private volatile BroadcastReceiver networkStateReceiver = null;
TorPlugin(Executor ioExecutor, Context appContext,
@@ -163,14 +163,18 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public boolean start() throws IOException {
public void start() throws PluginException {
if (used.getAndSet(true)) throw new IllegalStateException();
// Install or update the assets if necessary
if (!assetsAreUpToDate()) installAssets();
LOG.info("Starting Tor");
// Watch for the auth cookie file being updated
cookieFile.getParentFile().mkdirs();
cookieFile.createNewFile();
try {
cookieFile.getParentFile().mkdirs();
cookieFile.createNewFile();
} catch (IOException e) {
throw new PluginException(e);
}
CountDownLatch latch = new CountDownLatch(1);
FileObserver obs = new WriteObserver(cookieFile, latch);
obs.startWatching();
@@ -183,8 +187,8 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
Process torProcess;
try {
torProcess = Runtime.getRuntime().exec(cmd, env, torDirectory);
} catch (SecurityException e) {
throw new IOException(e);
} catch (SecurityException | IOException e) {
throw new PluginException(e);
}
// Log the process's standard output until it detaches
if (LOG.isLoggable(INFO)) {
@@ -198,35 +202,39 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
if (exit != 0) {
if (LOG.isLoggable(WARNING))
LOG.warning("Tor exited with value " + exit);
return false;
throw new PluginException();
}
// Wait for the auth cookie file to be created/updated
if (!latch.await(COOKIE_TIMEOUT, MILLISECONDS)) {
LOG.warning("Auth cookie not created");
if (LOG.isLoggable(INFO)) listFiles(torDirectory);
return false;
throw new PluginException();
}
} catch (InterruptedException e) {
LOG.warning("Interrupted while starting Tor");
Thread.currentThread().interrupt();
return false;
throw new PluginException();
}
// Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
running = true;
// Register to receive events from the Tor process
controlConnection.setEventHandler(this);
controlConnection.setEvents(Arrays.asList(EVENTS));
// Check whether Tor has already bootstrapped
String phase = controlConnection.getInfo("status/bootstrap-phase");
if (phase != null && phase.contains("PROGRESS=100")) {
LOG.info("Tor has already bootstrapped");
connectionStatus.setBootstrapped();
try {
// Open a control connection and authenticate using the cookie file
controlSocket = new Socket("127.0.0.1", CONTROL_PORT);
controlConnection = new TorControlConnection(controlSocket);
controlConnection.authenticate(read(cookieFile));
// Tell Tor to exit when the control connection is closed
controlConnection.takeOwnership();
controlConnection.resetConf(Collections.singletonList(OWNER));
running = true;
// Register to receive events from the Tor process
controlConnection.setEventHandler(this);
controlConnection.setEvents(Arrays.asList(EVENTS));
// Check whether Tor has already bootstrapped
String phase = controlConnection.getInfo("status/bootstrap-phase");
if (phase != null && phase.contains("PROGRESS=100")) {
LOG.info("Tor has already bootstrapped");
connectionStatus.setBootstrapped();
}
} catch (IOException e) {
throw new PluginException(e);
}
// Register to receive network status events
networkStateReceiver = new NetworkStateReceiver();
@@ -234,7 +242,6 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
appContext.registerReceiver(networkStateReceiver, filter);
// Bind a server socket to receive incoming hidden service connections
bind();
return true;
}
private boolean assetsAreUpToDate() {
@@ -247,7 +254,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
}
private void installAssets() throws IOException {
private void installAssets() throws PluginException {
InputStream in = null;
OutputStream out = null;
try {
@@ -270,30 +277,36 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
} catch (IOException e) {
tryToClose(in);
tryToClose(out);
throw e;
throw new PluginException(e);
}
}
private InputStream getTorInputStream() throws IOException {
if (LOG.isLoggable(INFO))
LOG.info("Installing Tor binary for " + architecture);
String filename = "tor-" + architecture + ".zip";
InputStream in = appContext.getResources().getAssets().open(filename);
int resId = getResourceId("tor_" + architecture);
InputStream in = appContext.getResources().openRawResource(resId);
ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException();
return zin;
}
private InputStream getGeoIpInputStream() throws IOException {
String filename = "geoip.zip";
InputStream in = appContext.getResources().getAssets().open(filename);
int resId = getResourceId("geoip");
InputStream in = appContext.getResources().openRawResource(resId);
ZipInputStream zin = new ZipInputStream(in);
if (zin.getNextEntry() == null) throw new IOException();
return zin;
}
private InputStream getConfigInputStream() throws IOException {
return appContext.getResources().getAssets().open("torrc");
int resId = getResourceId("torrc");
return appContext.getResources().openRawResource(resId);
}
private int getResourceId(String filename) {
Resources res = appContext.getResources();
return res.getIdentifier(filename, "raw", appContext.getPackageName());
}
private void tryToClose(@Nullable Closeable c) {
@@ -471,7 +484,7 @@ class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
}
@Override
public void stop() throws IOException {
public void stop() throws PluginException {
running = false;
tryToClose(socket);
if (networkStateReceiver != null)

View File

@@ -1,25 +1,29 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import android.content.Context;
import android.os.Build;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.plugins.Backoff;
import org.briarproject.api.plugins.BackoffFactory;
import org.briarproject.api.plugins.TorConstants;
import org.briarproject.api.plugins.duplex.DuplexPlugin;
import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
import org.briarproject.api.reporting.DevReporter;
import org.briarproject.api.system.LocationUtils;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId;
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.reporting.DevReporter;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.util.AndroidUtils;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import javax.net.SocketFactory;
@Immutable
@NotNullByDefault
public class TorPluginFactory implements DuplexPluginFactory {
private static final Logger LOG =
@@ -81,7 +85,7 @@ public class TorPluginFactory implements DuplexPluginFactory {
return null;
}
// Use position-independent executable for SDK >= 16
if (Build.VERSION.SDK_INT >= 16) architecture += "-pie";
if (Build.VERSION.SDK_INT >= 16) architecture += "_pie";
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE);

View File

@@ -1,13 +1,15 @@
package org.briarproject.plugins.tor;
package org.briarproject.bramble.plugin.tor;
import org.briarproject.api.plugins.Plugin;
import org.briarproject.api.plugins.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
@NotNullByDefault
class TorTransportConnection extends AbstractDuplexTransportConnection {
private final Socket socket;

View File

@@ -1,10 +1,10 @@
package org.briarproject.system;
package org.briarproject.bramble.system;
import android.app.Application;
import android.os.Handler;
import android.os.Looper;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidExecutor;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;

View File

@@ -1,4 +1,4 @@
package org.briarproject.system;
package org.briarproject.bramble.system;
import android.annotation.SuppressLint;
import android.app.Application;
@@ -6,7 +6,8 @@ import android.content.Context;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import org.briarproject.api.system.LocationUtils;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.LocationUtils;
import java.util.Locale;
import java.util.logging.Logger;
@@ -15,6 +16,7 @@ import javax.inject.Inject;
import static android.content.Context.TELEPHONY_SERVICE;
@NotNullByDefault
class AndroidLocationUtils implements LocationUtils {
private static final Logger LOG =
@@ -23,7 +25,7 @@ class AndroidLocationUtils implements LocationUtils {
private final Context appContext;
@Inject
public AndroidLocationUtils(Application app) {
AndroidLocationUtils(Application app) {
appContext = app.getApplicationContext();
}
@@ -44,6 +46,7 @@ class AndroidLocationUtils implements LocationUtils {
* some reason - both that class and {@code Context.COUNTRY_CODE} are
* annotated {@code @hide}.
*/
@Override
@SuppressLint("DefaultLocale")
public String getCurrentCountry() {
String countryCode = getCountryFromPhoneNetwork();

View File

@@ -1,4 +1,4 @@
package org.briarproject.system;
package org.briarproject.bramble.system;
import android.app.Application;
import android.content.ContentResolver;
@@ -6,13 +6,18 @@ import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.annotation.concurrent.Immutable;
import javax.inject.Inject;
import static android.provider.Settings.Secure.ANDROID_ID;
@Immutable
@NotNullByDefault
class AndroidSeedProvider extends LinuxSeedProvider {
private final Context appContext;

View File

@@ -0,0 +1,33 @@
package org.briarproject.bramble.system;
import android.app.Application;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.SeedProvider;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AndroidSystemModule {
@Provides
@Singleton
SeedProvider provideSeedProvider(Application app) {
return new AndroidSeedProvider(app);
}
@Provides
LocationUtils provideLocationUtils(Application app) {
return new AndroidLocationUtils(app);
}
@Provides
@Singleton
AndroidExecutor provideAndroidExecutor(Application app) {
return new AndroidExecutorImpl(app);
}
}

View File

@@ -0,0 +1,70 @@
package org.briarproject.bramble.util;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.Build;
import android.provider.Settings;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static android.content.Context.MODE_PRIVATE;
public class AndroidUtils {
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
private static final String FAKE_BLUETOOTH_ADDRESS = "02:00:00:00:00:00";
private static final String STORED_REPORTS = "dev-reports";
@SuppressWarnings("deprecation")
public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>();
if (Build.VERSION.SDK_INT >= 21) {
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS));
} else {
abis.add(Build.CPU_ABI);
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
}
return abis;
}
public static String getBluetoothAddress(Context ctx,
BluetoothAdapter adapter) {
// Return the adapter's address if it's valid and not fake
String address = adapter.getAddress();
if (isValidBluetoothAddress(address)) return address;
// Return the address from settings if it's valid and not fake
address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address");
if (isValidBluetoothAddress(address)) return address;
// Let the caller know we can't find the address
return "";
}
private static boolean isValidBluetoothAddress(String address) {
return !StringUtils.isNullOrEmpty(address)
&& BluetoothAdapter.checkBluetoothAddress(address)
&& !address.equals(FAKE_BLUETOOTH_ADDRESS);
}
public static void deleteAppData(Context ctx) {
File dataDir = new File(ctx.getApplicationInfo().dataDir);
File[] children = dataDir.listFiles();
if (children != null) {
for (File child : children) {
if (!child.getName().equals("lib"))
IoUtils.deleteFileOrDir(child);
}
}
// Recreate the cache dir as some OpenGL drivers expect it to exist
new File(dataDir, "cache").mkdir();
}
public static File getReportDir(Context ctx) {
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
}
}

View File

@@ -0,0 +1,3 @@
<resources>
<string name="app_name">Bramble</string>
</resources>

41
bramble-api/build.gradle Normal file
View File

@@ -0,0 +1,41 @@
apply plugin: 'java'
sourceCompatibility = 1.6
targetCompatibility = 1.6
apply plugin: 'witness'
dependencies {
compile "com.google.dagger:dagger:2.0.2"
compile 'com.google.dagger:dagger-compiler:2.0.2'
compile 'com.google.code.findbugs:jsr305:3.0.1'
testCompile 'junit:junit:4.12'
testCompile "org.jmock:jmock:2.8.1"
testCompile "org.jmock:jmock-junit4:2.8.1"
testCompile "org.jmock:jmock-legacy:2.8.1"
testCompile "org.hamcrest:hamcrest-library:1.3"
testCompile "org.hamcrest:hamcrest-core:1.3"
}
dependencyVerification {
verify = [
'com.google.dagger:dagger:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9',
'com.google.dagger:dagger-compiler:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3',
'com.google.code.findbugs:jsr305:c885ce34249682bc0236b4a7d56efcc12048e6135a5baf7a9cde8ad8cda13fcd',
'javax.inject:javax.inject:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'com.google.dagger:dagger-producers:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b',
'com.google.guava:guava:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99',
]
}
// needed to make test output available to bramble-core and briar-core
configurations {
testOutput.extendsFrom(testCompile)
}
task jarTest(type: Jar, dependsOn: testClasses) {
from sourceSets.test.output
classifier = 'test'
}
artifacts {
testOutput jarTest
}

View File

@@ -1,11 +1,17 @@
package org.briarproject.api;
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Arrays;
import java.util.Comparator;
import javax.annotation.concurrent.ThreadSafe;
/**
* A wrapper around a byte array, to allow it to be stored in maps etc.
*/
@ThreadSafe
@NotNullByDefault
public class Bytes implements Comparable<Bytes> {
public static final BytesComparator COMPARATOR = new BytesComparator();

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api;
import java.io.IOException;
/**
* An exception that indicates an unrecoverable formatting error.
*/
public class FormatException extends IOException {
}

View File

@@ -1,12 +1,10 @@
package org.briarproject.api;
package org.briarproject.bramble.api;
import java.util.Hashtable;
import java.util.Map;
public abstract class StringMap extends Hashtable<String, String> {
private static final long serialVersionUID = 2497176435908100448L;
protected StringMap(Map<String, String> m) {
super(m);
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
@NotNullByDefault
public abstract class UniqueId extends Bytes {
/**
* The length of a unique identifier in bytes.
*/
public static final int LENGTH = 32;
protected UniqueId(byte[] id) {
super(id);
if (id.length != LENGTH) throw new IllegalArgumentException();
}
}

View File

@@ -1,8 +1,8 @@
package org.briarproject.api.clients;
package org.briarproject.bramble.api.client;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.MessageId;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import java.util.Collection;
import java.util.Collections;

View File

@@ -0,0 +1,66 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.data.MetadataEncoder;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
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.system.Clock;
import java.util.logging.Logger;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
import static org.briarproject.bramble.api.transport.TransportConstants.MAX_CLOCK_DIFFERENCE;
@Immutable
@NotNullByDefault
public abstract class BdfMessageValidator implements MessageValidator {
protected static final Logger LOG =
Logger.getLogger(BdfMessageValidator.class.getName());
protected final ClientHelper clientHelper;
protected final MetadataEncoder metadataEncoder;
protected final Clock clock;
protected BdfMessageValidator(ClientHelper clientHelper,
MetadataEncoder metadataEncoder, Clock clock) {
this.clientHelper = clientHelper;
this.metadataEncoder = metadataEncoder;
this.clock = clock;
}
protected abstract BdfMessageContext validateMessage(Message m, Group g,
BdfList body) throws InvalidMessageException, FormatException;
@Override
public MessageContext validateMessage(Message m, Group g)
throws InvalidMessageException {
// Reject the message if it's too far in the future
long now = clock.currentTimeMillis();
if (m.getTimestamp() - now > MAX_CLOCK_DIFFERENCE) {
throw new InvalidMessageException(
"Timestamp is too far in the future");
}
byte[] raw = m.getRaw();
if (raw.length <= MESSAGE_HEADER_LENGTH) {
throw new InvalidMessageException("Message is too short");
}
try {
BdfList body = clientHelper.toList(raw, MESSAGE_HEADER_LENGTH,
raw.length - MESSAGE_HEADER_LENGTH);
BdfMessageContext result = validateMessage(m, g, body);
Metadata meta = metadataEncoder.encode(result.getDictionary());
return new MessageContext(meta, result.getDependencies());
} catch (FormatException e) {
throw new InvalidMessageException(e);
}
}
}

View File

@@ -1,14 +1,14 @@
package org.briarproject.api.clients;
package org.briarproject.bramble.api.client;
import org.briarproject.api.FormatException;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.nullsafety.NotNullByDefault;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import java.security.GeneralSecurityException;
import java.util.Map;
@@ -48,7 +48,8 @@ public interface ClientHelper {
BdfDictionary getGroupMetadataAsDictionary(Transaction txn, GroupId g)
throws DbException, FormatException;
BdfDictionary getMessageMetadataAsDictionary(MessageId m) throws DbException,
BdfDictionary getMessageMetadataAsDictionary(MessageId m)
throws DbException,
FormatException;
BdfDictionary getMessageMetadataAsDictionary(Transaction txn, MessageId m)

View File

@@ -0,0 +1,29 @@
package org.briarproject.bramble.api.client;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
@NotNullByDefault
public interface ContactGroupFactory {
/**
* Creates a group that is not shared with any contacts.
*/
Group createLocalGroup(ClientId clientId);
/**
* Creates a group for the given client to share with the given contact.
*/
Group createContactGroup(ClientId clientId, Contact contact);
/**
* Creates a group for the given client to share between the given authors
* identified by their AuthorIds.
*/
Group createContactGroup(ClientId clientId, AuthorId authorId1,
AuthorId authorId2);
}

View File

@@ -1,8 +1,13 @@
package org.briarproject.api.contact;
package org.briarproject.bramble.api.contact;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class Contact {
private final ContactId id;

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface ContactExchangeListener {
void contactExchangeSucceeded(Author remoteAuthor);
/**
* The exchange failed because the contact already exists.
*/
void duplicateContact(Author remoteAuthor);
/**
* A general failure.
*/
void contactExchangeFailed();
}

View File

@@ -0,0 +1,22 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
/**
* A task for conducting a contact information exchange with a remote peer.
*/
@NotNullByDefault
public interface ContactExchangeTask {
/**
* Exchanges contact information with a remote peer.
*/
void startExchange(ContactExchangeListener listener,
LocalAuthor localAuthor, SecretKey masterSecret,
DuplexTransportConnection conn, TransportId transportId,
boolean alice);
}

View File

@@ -1,9 +1,15 @@
package org.briarproject.api.contact;
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* Type-safe wrapper for an integer that uniquely identifies a contact within
* the scope of a single node.
*/
@Immutable
@NotNullByDefault
public class ContactId {
private final int id;

View File

@@ -0,0 +1,104 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
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.nullsafety.NotNullByDefault;
import java.util.Collection;
@NotNullByDefault
public interface ContactManager {
/**
* Registers a hook to be called whenever a contact is added.
*/
void registerAddContactHook(AddContactHook hook);
/**
* Registers a hook to be called whenever a contact is removed.
*/
void registerRemoveContactHook(RemoveContactHook hook);
/**
* Stores a contact within the given transaction associated with the given
* local and remote pseudonyms, and returns an ID for the contact.
*/
ContactId addContact(Transaction txn, Author remote, AuthorId local,
SecretKey master, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact.
*/
ContactId addContact(Author remote, AuthorId local,
SecretKey master, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException;
/**
* Returns the contact with the given ID.
*/
Contact getContact(ContactId c) throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
*/
Contact getContact(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
/**
* Returns the contact with the given remoteAuthorId
* that was added by the LocalAuthor with the given localAuthorId
*
* @throws org.briarproject.bramble.api.db.NoSuchContactException
*/
Contact getContact(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
/**
* Returns all active contacts.
*/
Collection<Contact> getActiveContacts() throws DbException;
/**
* Removes a contact and all associated state.
*/
void removeContact(ContactId c) throws DbException;
/**
* Removes a contact and all associated state.
*/
void removeContact(Transaction txn, ContactId c) throws DbException;
/**
* Marks a contact as active or inactive.
*/
void setContactActive(Transaction txn, ContactId c, boolean active)
throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException;
/**
* Return true if a contact with this name and public key already exists
*/
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException;
interface AddContactHook {
void addingContact(Transaction txn, Contact c) throws DbException;
}
interface RemoveContactHook {
void removingContact(Transaction txn, Contact c) throws DbException;
}
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is added.
*/
@Immutable
@NotNullByDefault
public class ContactAddedEvent extends Event {
private final ContactId contactId;
private final boolean active;
public ContactAddedEvent(ContactId contactId, boolean active) {
this.contactId = contactId;
this.active = active;
}
public ContactId getContactId() {
return contactId;
}
public boolean isActive() {
return active;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is removed.
*/
@Immutable
@NotNullByDefault
public class ContactRemovedEvent extends Event {
private final ContactId contactId;
public ContactRemovedEvent(ContactId contactId) {
this.contactId = contactId;
}
public ContactId getContactId() {
return contactId;
}
}

View File

@@ -0,0 +1,31 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is marked active or inactive.
*/
@Immutable
@NotNullByDefault
public class ContactStatusChangedEvent extends Event {
private final ContactId contactId;
private final boolean active;
public ContactStatusChangedEvent(ContactId contactId, boolean active) {
this.contactId = contactId;
this.active = active;
}
public ContactId getContactId() {
return contactId;
}
public boolean isActive() {
return active;
}
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a contact is verified.
*/
@Immutable
@NotNullByDefault
public class ContactVerifiedEvent extends Event {
private final ContactId contactId;
public ContactVerifiedEvent(ContactId contactId) {
this.contactId = contactId;
}
public ContactId getContactId() {
return contactId;
}
}

View File

@@ -1,7 +1,7 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.api.TransportId;
import org.briarproject.api.transport.TransportKeys;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.TransportKeys;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
@@ -10,8 +10,6 @@ public interface CryptoComponent {
SecretKey generateSecretKey();
MessageDigest getMessageDigest();
PseudoRandom getPseudoRandom(int seed1, int seed2);
SecureRandom getSecureRandom();
@@ -164,8 +162,17 @@ public interface CryptoComponent {
/**
* Returns the hash of the given inputs. The inputs are unambiguously
* combined by prefixing each input with its length.
*
* @param label A label specific to this hash to ensure that hashes
* calculated for distinct purposes don't collide.
*/
byte[] hash(byte[]... inputs);
byte[] hash(String label, byte[]... inputs);
/**
* Returns the length of hashes produced by
* the {@link CryptoComponent#hash(String, byte[]...)} method.
*/
int getHashLength();
/**
* Returns a message authentication code with the given key over the

View File

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

View File

@@ -1,6 +1,14 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
/** A key pair consisting of a {@link PublicKey} and a {@link PrivateKey). */
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* A key pair consisting of a {@link PublicKey} and a {@link PrivateKey).
*/
@Immutable
@NotNullByDefault
public class KeyPair {
private final PublicKey publicKey;

View File

@@ -1,7 +1,10 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
@NotNullByDefault
public interface KeyParser {
PublicKey parsePublicKey(byte[] encodedKey) throws GeneralSecurityException;

View File

@@ -1,5 +1,8 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface PasswordStrengthEstimator {
float NONE = 0;

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* The private half of a public/private {@link KeyPair}.
*/
@NotNullByDefault
public interface PrivateKey {
/**
* Returns the encoded representation of this key.
*/
byte[] getEncoded();
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* A deterministic pseudo-random number generator.
*/
@NotNullByDefault
public interface PseudoRandom {
byte[] nextBytes(int bytes);
}

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* The public half of a public/private {@link KeyPair}.
*/
@NotNullByDefault
public interface PublicKey {
/**
* Returns the encoded representation of this key.
*/
byte[] getEncoded();
}

View File

@@ -1,9 +1,14 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
/** A secret key used for encryption and/or authentication. */
/**
* A secret key used for encryption and/or authentication.
*/
public class SecretKey {
public static final int LENGTH = 32; // Bytes
/**
* The length of a secret key in bytes.
*/
public static final int LENGTH = 32;
private final byte[] key;

View File

@@ -1,13 +1,17 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface StreamDecrypter {
/**
* Reads a frame, decrypts its payload into the given buffer and returns
* the payload length, or -1 if no more frames can be read from the stream.
* @throws java.io.IOException if an error occurs while reading the frame,
*
* @throws IOException if an error occurs while reading the frame,
* or if authenticated decryption fails.
*/
int readFrame(byte[] payload) throws IOException;

View File

@@ -1,12 +1,16 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamContext;
import java.io.InputStream;
import org.briarproject.api.transport.StreamContext;
@NotNullByDefault
public interface StreamDecrypterFactory {
/** Creates a {@link StreamDecrypter} for decrypting a transport stream. */
/**
* Creates a {@link StreamDecrypter} for decrypting a transport stream.
*/
StreamDecrypter createStreamDecrypter(InputStream in, StreamContext ctx);
/**

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface StreamEncrypter {
/**
* Encrypts the given frame and writes it to the stream.
*/
void writeFrame(byte[] payload, int payloadLength, int paddingLength,
boolean finalFrame) throws IOException;
/**
* Flushes the stream.
*/
void flush() throws IOException;
}

View File

@@ -1,12 +1,16 @@
package org.briarproject.api.crypto;
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamContext;
import java.io.OutputStream;
import org.briarproject.api.transport.StreamContext;
@NotNullByDefault
public interface StreamEncrypterFactory {
/** Creates a {@link StreamEncrypter} for encrypting a transport stream. */
/**
* Creates a {@link StreamEncrypter} for encrypting a transport stream.
*/
StreamEncrypter createStreamEncrypter(OutputStream out, StreamContext ctx);
/**

View File

@@ -1,7 +1,7 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.api.Bytes;
import org.briarproject.api.FormatException;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;

View File

@@ -1,7 +1,13 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Map.Entry;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class BdfEntry implements Entry<String, Object>, Comparable<BdfEntry> {
private final String key;

View File

@@ -1,14 +1,15 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.api.Bytes;
import org.briarproject.api.FormatException;
import org.jetbrains.annotations.Nullable;
import org.briarproject.bramble.api.Bytes;
import org.briarproject.bramble.api.FormatException;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
import javax.annotation.Nullable;
import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE;
public class BdfList extends Vector<Object> {

View File

@@ -1,49 +1,75 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface BdfReader {
int DEFAULT_NESTED_LIMIT = 5;
boolean eof() throws IOException;
void close() throws IOException;
boolean hasNull() throws IOException;
void readNull() throws IOException;
void skipNull() throws IOException;
boolean hasBoolean() throws IOException;
boolean readBoolean() throws IOException;
void skipBoolean() throws IOException;
boolean hasLong() throws IOException;
long readLong() throws IOException;
void skipLong() throws IOException;
boolean hasDouble() throws IOException;
double readDouble() throws IOException;
void skipDouble() throws IOException;
boolean hasString() throws IOException;
String readString(int maxLength) throws IOException;
void skipString() throws IOException;
boolean hasRaw() throws IOException;
byte[] readRaw(int maxLength) throws IOException;
void skipRaw() throws IOException;
boolean hasList() throws IOException;
BdfList readList() throws IOException;
void readListStart() throws IOException;
boolean hasListEnd() throws IOException;
void readListEnd() throws IOException;
void skipList() throws IOException;
boolean hasDictionary() throws IOException;
BdfDictionary readDictionary() throws IOException;
void readDictionaryStart() throws IOException;
boolean hasDictionaryEnd() throws IOException;
void readDictionaryEnd() throws IOException;
void skipDictionary() throws IOException;
}

View File

@@ -1,7 +1,10 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.InputStream;
@NotNullByDefault
public interface BdfReaderFactory {
BdfReader createReader(InputStream in);

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.data;
package org.briarproject.bramble.api.data;
import java.io.IOException;
import java.util.Collection;
@@ -7,20 +7,30 @@ import java.util.Map;
public interface BdfWriter {
void flush() throws IOException;
void close() throws IOException;
void writeNull() throws IOException;
void writeBoolean(boolean b) throws IOException;
void writeLong(long l) throws IOException;
void writeDouble(double d) throws IOException;
void writeString(String s) throws IOException;
void writeRaw(byte[] b) throws IOException;
void writeList(Collection<?> c) throws IOException;
void writeListStart() throws IOException;
void writeListEnd() throws IOException;
void writeDictionary(Map<?, ?> m) throws IOException;
void writeDictionaryStart() throws IOException;
void writeDictionaryEnd() throws IOException;
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.OutputStream;
@NotNullByDefault
public interface BdfWriterFactory {
BdfWriter createWriter(OutputStream out);
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface MetadataEncoder {
Metadata encode(BdfDictionary d) throws FormatException;
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface MetadataParser {
BdfDictionary parse(Metadata m) throws FormatException;
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.bramble.api.data;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.IOException;
@NotNullByDefault
public interface ObjectReader<T> {
T readObject(BdfReader r) throws IOException;
}

View File

@@ -1,9 +1,8 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a duplicate contact is added to the database. This exception may
* occur due to concurrent updates and does not indicate a database error.
*/
public class ContactExistsException extends DbException {
}

View File

@@ -1,34 +1,38 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.settings.Settings;
import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.Group.Visibility;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.MessageStatus;
import org.briarproject.api.sync.Offer;
import org.briarproject.api.sync.Request;
import org.briarproject.api.transport.TransportKeys;
import org.jetbrains.annotations.Nullable;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.settings.Settings;
import org.briarproject.bramble.api.sync.Ack;
import org.briarproject.bramble.api.sync.ClientId;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.Group.Visibility;
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.Offer;
import org.briarproject.bramble.api.sync.Request;
import org.briarproject.bramble.api.sync.ValidationManager;
import org.briarproject.bramble.api.transport.TransportKeys;
import java.util.Collection;
import java.util.Map;
import static org.briarproject.api.sync.ValidationManager.State;
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.
*/
@NotNullByDefault
public interface DatabaseComponent {
/**
@@ -330,10 +334,10 @@ public interface DatabaseComponent {
/**
* Returns the IDs and states of all dependencies of the given message.
* Missing dependencies have the state {@link
* org.briarproject.api.sync.ValidationManager.State UNKNOWN}.
* Dependencies in other groups have the state {@link
* org.briarproject.api.sync.ValidationManager.State INVALID}.
* Missing dependencies have the state
* {@link ValidationManager.State UNKNOWN}.
* Dependencies in other groups have the state
* {@link ValidationManager.State INVALID}.
* Note that these states are not set on the dependencies themselves; the
* returned states should only be taken in the context of the given message.
* <p/>

View File

@@ -1,9 +1,13 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File;
import javax.annotation.Nullable;
@NotNullByDefault
public interface DatabaseConfig {
boolean databaseExists();
@@ -12,10 +16,12 @@ public interface DatabaseConfig {
void setEncryptionKey(SecretKey key);
@Nullable
SecretKey getEncryptionKey();
void setLocalAuthorName(String nickname);
@Nullable
String getLocalAuthorName();
long getMaxSize();

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@@ -20,6 +20,7 @@ import static java.lang.annotation.RetentionPolicy.RUNTIME;
* discarded.
*/
@Qualifier
@Target({ FIELD, METHOD, PARAMETER })
@Target({FIELD, METHOD, PARAMETER})
@Retention(RUNTIME)
public @interface DatabaseExecutor {}
public @interface DatabaseExecutor {
}

View File

@@ -1,8 +1,7 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted and the database is closed.
*/
public class DbClosedException extends DbException {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
public class DbException extends Exception {

View File

@@ -1,7 +1,10 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import java.util.Hashtable;
import javax.annotation.concurrent.ThreadSafe;
@ThreadSafe
public class Metadata extends Hashtable<String, byte[]> {
/**

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a contact that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchContactException extends DbException {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a group that is not in the
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
* indicate a database error.
*/
public class NoSuchGroupException extends DbException {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a pseudonym that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchLocalAuthorException extends DbException {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a message that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchMessageException extends DbException {
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
/**
* Thrown when a database operation is attempted for a transport that is not in
@@ -6,5 +6,4 @@ package org.briarproject.api.db;
* not indicate a database error.
*/
public class NoSuchTransportException extends DbException {
}

View File

@@ -1,14 +1,17 @@
package org.briarproject.api.db;
package org.briarproject.bramble.api.db;
import org.briarproject.api.event.Event;
import org.briarproject.bramble.api.event.Event;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.concurrent.NotThreadSafe;
/**
* A wrapper around a database transaction. Transactions are not thread-safe.
*/
@NotThreadSafe
public class Transaction {
private final Object txn;

View File

@@ -0,0 +1,7 @@
package org.briarproject.bramble.api.event;
/**
* An abstract superclass for events.
*/
public abstract class Event {
}

View File

@@ -0,0 +1,22 @@
package org.briarproject.bramble.api.event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface EventBus {
/**
* Adds a listener to be notified when events occur.
*/
void addListener(EventListener l);
/**
* Removes a listener.
*/
void removeListener(EventListener l);
/**
* Notifies all listeners of an event.
*/
void broadcast(Event e);
}

View File

@@ -0,0 +1,16 @@
package org.briarproject.bramble.api.event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* An interface for receiving notifications when events occur.
*/
@NotNullByDefault
public interface EventListener {
/**
* Called when an event is broadcast. Implementations of this method must
* not block.
*/
void eventOccurred(Event e);
}

View File

@@ -1,11 +1,19 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.UnsupportedEncodingException;
/** A pseudonym for a user. */
import javax.annotation.concurrent.Immutable;
/**
* A pseudonym for a user.
*/
@Immutable
@NotNullByDefault
public class Author {
public enum Status { ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES }
public enum Status {ANONYMOUS, UNKNOWN, UNVERIFIED, VERIFIED, OURSELVES}
private final AuthorId id;
private final String name;
@@ -25,17 +33,23 @@ public class Author {
this.publicKey = publicKey;
}
/** Returns the author's unique identifier. */
/**
* Returns the author's unique identifier.
*/
public AuthorId getId() {
return id;
}
/** Returns the author's name. */
/**
* Returns the author's name.
*/
public String getName() {
return name;
}
/** Returns the public key used to verify the pseudonym's signatures. */
/**
* Returns the public key used to verify the pseudonym's signatures.
*/
public byte[] getPublicKey() {
return publicKey;
}

View File

@@ -1,8 +1,10 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
public interface AuthorConstants {
/** The maximum length of an author's name in UTF-8 bytes. */
/**
* The maximum length of an author's name in UTF-8 bytes.
*/
int MAX_AUTHOR_NAME_LENGTH = 50;
/**

View File

@@ -1,5 +1,8 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface AuthorFactory {
Author createAuthor(String name, byte[] publicKey);

View File

@@ -1,20 +1,22 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
import org.briarproject.api.UniqueId;
import org.briarproject.bramble.api.UniqueId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.nio.charset.Charset;
import javax.annotation.concurrent.ThreadSafe;
/**
* Type-safe wrapper for a byte array that uniquely identifies an
* {@link org.briarproject.api.identity.Author Author}.
* {@link Author}.
*/
@ThreadSafe
@NotNullByDefault
public class AuthorId extends UniqueId {
/**
* Label for hashing authors to calculate their identities.
*/
public static final byte[] LABEL =
"AUTHOR_ID".getBytes(Charset.forName("US-ASCII"));
public static final String LABEL = "org.briarproject.bramble.AUTHOR_ID";
public AuthorId(byte[] id) {
super(id);

View File

@@ -0,0 +1,38 @@
package org.briarproject.bramble.api.identity;
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
public interface IdentityManager {
/**
* Stores the local pseudonym.
*/
void registerLocalAuthor(LocalAuthor a) throws DbException;
/**
* Returns the cached main local identity, non-blocking, or loads it from
* the db, blocking
*/
LocalAuthor getLocalAuthor() throws DbException;
/**
* Returns the cached main local identity, non-blocking, or loads it from
* the db, blocking, within the given Transaction.
*/
LocalAuthor getLocalAuthor(Transaction txn) throws DbException;
/**
* Returns the trust-level status of the author
*/
Status getAuthorStatus(AuthorId a) throws DbException;
/**
* Returns the trust-level status of the author
*/
Status getAuthorStatus(Transaction txn, AuthorId a) throws DbException;
}

View File

@@ -1,6 +1,14 @@
package org.briarproject.api.identity;
package org.briarproject.bramble.api.identity;
/** A pseudonym for the local user. */
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* A pseudonym for the local user.
*/
@Immutable
@NotNullByDefault
public class LocalAuthor extends Author {
private final byte[] privateKey;
@@ -13,7 +21,9 @@ public class LocalAuthor extends Author {
this.created = created;
}
/** Returns the private key used to generate the pseudonym's signatures. */
/**
* Returns the private key used to generate the pseudonym's signatures.
*/
public byte[] getPrivateKey() {
return privateKey;
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.identity.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a local pseudonym is added.
*/
@Immutable
@NotNullByDefault
public class LocalAuthorAddedEvent extends Event {
private final AuthorId authorId;
public LocalAuthorAddedEvent(AuthorId authorId) {
this.authorId = authorId;
}
public AuthorId getAuthorId() {
return authorId;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.identity.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a local pseudonym is removed.
*/
@Immutable
@NotNullByDefault
public class LocalAuthorRemovedEvent extends Event {
private final AuthorId authorId;
public LocalAuthorRemovedEvent(AuthorId authorId) {
this.authorId = authorId;
}
public AuthorId getAuthorId() {
return authorId;
}
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.bramble.api.invitation;
public interface InvitationConstants {
/**
* The connection timeout in milliseconds.
*/
long CONNECTION_TIMEOUT = 60 * 1000;
/**
* The confirmation timeout in milliseconds.
*/
long CONFIRMATION_TIMEOUT = 60 * 1000;
/**
* The number of bits in an invitation or confirmation code. Codes must fit
* into six decimal digits.
*/
int CODE_BITS = 19;
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.api.invitation;
package org.briarproject.bramble.api.invitation;
/**
* An interface for receiving updates about the state of an

View File

@@ -1,5 +1,15 @@
package org.briarproject.api.invitation;
package org.briarproject.bramble.api.invitation;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
/**
* A snapshot of the state of an {@link InvitationTask}.
*/
@Immutable
@NotNullByDefault
public class InvitationState {
private final int localInvitationCode, remoteInvitationCode;
@@ -7,13 +17,14 @@ public class InvitationState {
private final boolean connected, connectionFailed;
private final boolean localCompared, remoteCompared;
private final boolean localMatched, remoteMatched;
@Nullable
private final String contactName;
public InvitationState(int localInvitationCode, int remoteInvitationCode,
int localConfirmationCode, int remoteConfirmationCode,
boolean connected, boolean connectionFailed, boolean localCompared,
boolean remoteCompared, boolean localMatched,
boolean remoteMatched, String contactName) {
boolean remoteMatched, @Nullable String contactName) {
this.localInvitationCode = localInvitationCode;
this.remoteInvitationCode = remoteInvitationCode;
this.localConfirmationCode = localConfirmationCode;
@@ -67,6 +78,7 @@ public class InvitationState {
return remoteMatched;
}
@Nullable
public String getContactName() {
return contactName;
}

View File

@@ -1,6 +1,11 @@
package org.briarproject.api.invitation;
package org.briarproject.bramble.api.invitation;
/** A task for exchanging invitations with a remote peer. */
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* A task for exchanging invitations with a remote peer.
*/
@NotNullByDefault
public interface InvitationTask {
/**
@@ -9,10 +14,14 @@ public interface InvitationTask {
*/
InvitationState addListener(InvitationListener l);
/** Removes the given listener. */
/**
* Removes the given listener.
*/
void removeListener(InvitationListener l);
/** Asynchronously starts the connection process. */
/**
* Asynchronously starts the connection process.
*/
void connect();
/**

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.invitation;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* Creates tasks for exchanging invitations with remote peers.
*/
@NotNullByDefault
public interface InvitationTaskFactory {
/**
* Creates a task using the given local and remote invitation codes.
*/
InvitationTask createTask(int localCode, int remoteCode);
}

View File

@@ -1,9 +1,15 @@
package org.briarproject.api.keyagreement;
package org.briarproject.bramble.api.keyagreement;
import org.briarproject.api.TransportId;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class KeyAgreementConnection {
private final DuplexTransportConnection conn;
private final TransportId id;

View File

@@ -0,0 +1,36 @@
package org.briarproject.bramble.api.keyagreement;
public interface KeyAgreementConstants {
/**
* The current version of the BQP protocol.
*/
byte PROTOCOL_VERSION = 2;
/**
* The length of the record header in bytes.
*/
int RECORD_HEADER_LENGTH = 4;
/**
* The offset of the payload length in the record header, in bytes.
*/
int RECORD_HEADER_PAYLOAD_LENGTH_OFFSET = 2;
/**
* The length of the BQP key commitment in bytes.
*/
int COMMIT_LENGTH = 16;
long CONNECTION_TIMEOUT = 20 * 1000; // Milliseconds
/**
* The transport identifier for Bluetooth.
*/
int TRANSPORT_ID_BLUETOOTH = 0;
/**
* The transport identifier for LAN.
*/
int TRANSPORT_ID_LAN = 1;
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.api.keyagreement;
package org.briarproject.bramble.api.keyagreement;
import org.briarproject.api.data.BdfList;
import org.briarproject.bramble.api.data.BdfList;
import java.util.concurrent.Callable;

View File

@@ -1,8 +1,8 @@
package org.briarproject.api.keyagreement;
package org.briarproject.bramble.api.keyagreement;
import org.briarproject.api.TransportId;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
public class KeyAgreementResult {

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