Compare commits

..

604 Commits

Author SHA1 Message Date
akwizgran
2bf3736b2d Avoid using the deprecated NetworkInfo API. 2020-06-29 15:54:16 +01:00
Torsten Grote
443043ae09 Merge branch 'plugin-toggles' into 'master'
Merge plugin-toggles feature branch

See merge request briar/briar!1255
2020-06-29 13:07:52 +00:00
akwizgran
a03953563f Show appropriate text for answered introduction requests. 2020-06-26 17:37:17 +01:00
akwizgran
033fd2d3b4 Update comments about migration periods, since this isn't merged yet. 2020-06-26 17:37:16 +01:00
akwizgran
011d8e1df7 Remove unused strings. 2020-06-26 17:37:16 +01:00
akwizgran
ef5e2dad72 Make inner class just a holder for resources. 2020-06-26 17:37:16 +01:00
akwizgran
f35e87c8ad Remove unused code, fix a null safety bug. 2020-06-26 17:37:16 +01:00
akwizgran
e4940a046a Move transport toggles back to the settings screen. 2020-06-26 17:37:16 +01:00
akwizgran
0a666df164 Correctly handle connectivity events on IPv6-only networks. 2020-06-26 17:37:16 +01:00
akwizgran
6fb4b95b18 Don't allow list elements to be null. 2020-06-26 17:37:16 +01:00
akwizgran
5567982fb4 Use IPv6 for key agreement if IPv4 isn't available. 2020-06-26 17:37:16 +01:00
akwizgran
25e50ceb10 Try to detect our address on an IPv6-only wifi network. 2020-06-26 17:37:16 +01:00
akwizgran
1495daf977 Remove redundant address checks.
Remote addresses are checked for acceptability before connecting.
2020-06-26 17:37:16 +01:00
akwizgran
badc6da649 Accept any link-local IPv6 address.
This allows IPv6 to be used when providing an access point.
2020-06-26 17:37:16 +01:00
akwizgran
e065d45d16 Recognise unusual AP addresses. 2020-06-26 17:37:16 +01:00
akwizgran
d0c53f1310 Only bind to the SLAAC address of the wifi interface.
This is just a precaution - on all devices I've tested, the wifi
interface is the only one with a SLAAC address.
2020-06-26 17:37:16 +01:00
akwizgran
e1084ffadd Support IPv6 SLAAC addresses. 2020-06-26 17:37:15 +01:00
akwizgran
2bd2f67693 Interrupt sync sessions when transport becomes inactive.
This ensures connections are closed when the user disables a transport.
2020-06-26 17:37:12 +01:00
akwizgran
c2b0a4b8d1 Remove unnecessary plugin lookup. 2020-06-26 17:34:38 +01:00
akwizgran
ee19d2f574 Use tinted icon for plugin settings dialog. 2020-06-26 17:34:38 +01:00
akwizgran
e9ec5734e2 Show dialog from controller. 2020-06-26 17:34:38 +01:00
akwizgran
7b1c6f3fdd Add icon, title to Change Settings dialog. 2020-06-26 17:34:38 +01:00
akwizgran
d689cf776c Change Tor settings after asking for confirmation. 2020-06-26 17:34:38 +01:00
akwizgran
f0fd1844dd Transition from one constraint set to another. 2020-06-26 17:34:38 +01:00
akwizgran
d16a301fc4 Make entire collapsed view clickable. 2020-06-26 17:34:38 +01:00
akwizgran
3ab88181eb Put the transport toggles in an expandable view (no animations). 2020-06-26 17:34:37 +01:00
akwizgran
802e599f09 Add STARTING_STOPPING state, use flags for reasons disabled. 2020-06-26 17:34:37 +01:00
akwizgran
a6bd59d3c9 Close small gap between setStarted() and setDisabledBySettings(). 2020-06-26 17:34:37 +01:00
akwizgran
b04b724028 Don't show Tor in the enabling state if it's disabled by settings. 2020-06-26 17:34:37 +01:00
akwizgran
71b0408fe6 Remove "don't connect" option from Tor network setting.
This has been replaced by the enable/disable setting and no longer
works.
2020-06-26 17:34:37 +01:00
Torsten Grote
2d38bd5734 [android] Scroll down when nav drawer chevron is pressed 2020-06-26 17:34:37 +01:00
Torsten Grote
ff5da8404a [android] remove unused strings 2020-06-26 17:34:37 +01:00
Torsten Grote
75615a4e7f [android] make transport plugin toggles functional 2020-06-26 17:34:37 +01:00
Torsten Grote
96e32ad64e [android] Add transport plugin toggles to NavDrawer 2020-06-26 17:34:37 +01:00
Torsten Grote
0fec5d7783 [bramble] Add method for enabling/disabling plugins to PluginManager 2020-06-26 17:34:37 +01:00
akwizgran
ee74b3774b Remove another redundant call to pluginStateChanged(). 2020-06-26 17:34:37 +01:00
akwizgran
c783a2f352 Enable LAN plugin before showing QR code. 2020-06-26 17:34:37 +01:00
akwizgran
77aa5401f3 Remove redundant call to pluginStateChanged(). 2020-06-26 17:34:37 +01:00
akwizgran
99686f5316 Use XML to specify dependencies between settings. 2020-06-26 17:34:37 +01:00
akwizgran
f5b4f6e071 Clean up logic for enabling/disabling settings. 2020-06-26 17:34:36 +01:00
akwizgran
a2de841e6a Don't remove old settings yet.
This avoids an unlikely race condition at startup, where the user opens
the settings screen before the Tor plugin has migrated the settings.
2020-06-26 17:34:36 +01:00
akwizgran
1f94c2d4e8 Enable LAN plugin in unit test. 2020-06-26 17:34:36 +01:00
akwizgran
413ce29c0c Enable BT plugin before showing QR code. 2020-06-26 17:34:36 +01:00
akwizgran
c67f758c90 Small code cleanups in key agreement UI. 2020-06-26 17:34:36 +01:00
akwizgran
339524500b Make REASON_USER into a generic reason code. 2020-06-26 17:34:36 +01:00
akwizgran
03811f78fa Add toggle setting for LAN plugin. 2020-06-26 17:34:36 +01:00
akwizgran
fc86c46456 Update semantics of Bluetooth setting.
The setting now enables/disables the plugin, not just contact
connections. The key agreement UI will need to be updated to change the
setting if the user agrees to use Bluetooth.
2020-06-26 17:34:36 +01:00
akwizgran
7ae86d70af Convert Bluetooth setting to a switch. 2020-06-26 17:34:36 +01:00
akwizgran
63e3c661a3 Add toggle setting for Tor plugin. 2020-06-26 17:34:36 +01:00
akwizgran
4f54bd90fb Remove redundant casts. 2020-06-26 17:34:36 +01:00
akwizgran
706c03aa8b Skip fetching RSS feeds if Tor is not active. 2020-06-26 17:34:36 +01:00
akwizgran
c42a987927 Use amber icon when enabling transports. 2020-06-26 17:34:36 +01:00
akwizgran
297dbe0b16 Only update bridge and padding settings if network is enabled. 2020-06-26 17:34:35 +01:00
akwizgran
4130662e1f Notify callback of state changes while holding lock. 2020-06-26 17:34:35 +01:00
akwizgran
c08bdf96cd Update javadocs for lock-safe methods. 2020-06-26 17:34:35 +01:00
akwizgran
8bb534564f Remove redundant logging. 2020-06-26 17:34:35 +01:00
akwizgran
5e60a717fc Remove debug logging. 2020-06-26 17:34:35 +01:00
akwizgran
dd1509350c Close server socket when BT is disabled. 2020-06-26 17:34:35 +01:00
akwizgran
465ba3d337 Remove unnecessary inner class, state checks. 2020-06-26 17:34:35 +01:00
akwizgran
7561c5039e Reset backoff before notifying of new state.
The new state may cause the poller to poll the
plugin. Let's avoid a race between updating and
querying the polling interval.
2020-06-26 17:34:35 +01:00
akwizgran
242d6f8a0e Move to enabling state earlier in Tor startup. 2020-06-26 17:34:35 +01:00
akwizgran
c554847b54 Add TransportStateEvent, rename existing events. 2020-06-26 17:34:35 +01:00
akwizgran
d30b250389 Ensure server socket is closed. 2020-06-26 17:34:35 +01:00
akwizgran
ecea2c587d Add method for getting reason why plugin is disabled. 2020-06-26 17:34:35 +01:00
akwizgran
43a91e2e57 Fix test expectations. 2020-06-26 17:34:35 +01:00
akwizgran
ea288b998b Rename available/unavailable states. 2020-06-26 17:34:34 +01:00
akwizgran
48dc598ca3 Update tests. 2020-06-26 17:34:34 +01:00
akwizgran
e2d63ac6a4 If adapter is disabled, forget that we enabled it. 2020-06-26 17:34:34 +01:00
akwizgran
afc85cdf52 Check that server sockets are closed as expected. 2020-06-26 17:34:34 +01:00
akwizgran
b2a1ea84f8 Provide more information about plugin states. 2020-06-26 17:34:32 +01:00
akwizgran
fcc26c093b Avoid NPE if there's no TelephonyManager. 2020-06-26 17:33:54 +01:00
Torsten Grote
5a741bf13b Merge branch '1712-bluetooth-connection-wake-lock' into 'master'
Hold a wake lock while Bluetooth connections are open

See merge request briar/briar!1251
2020-06-26 16:11:36 +00:00
akwizgran
5dc460851b Remove redundant logging. 2020-06-26 15:33:37 +01:00
akwizgran
b805514f70 Use renewable wake lock, try to guess a "safe" tag. 2020-06-26 14:58:06 +01:00
akwizgran
69d94c9f29 Hold a wake lock while Bluetooth connections are open. 2020-06-26 14:58:06 +01:00
Torsten Grote
53d4b7a0df Merge branch '1712-simple-connection-limiter' into 'master'
Simple connection limiter that closes connections cleanly

Closes #1712

See merge request briar/briar!1254
2020-06-26 11:36:21 +00:00
akwizgran
648f26542c Simple connection limiter that closes connections cleanly. 2020-06-26 10:57:08 +01:00
akwizgran
dcb5f95934 Merge branch '1712-prefer-lan-to-bluetooth' into 'master'
Close redundant connections

See merge request briar/briar!1249
2020-06-26 09:46:24 +00:00
akwizgran
730d553b0a Fix screenshot test (again). 2020-06-26 10:38:04 +01:00
akwizgran
7736a3b6fc Use separate methods for registering incoming and outgoing connections. 2020-06-26 09:59:03 +01:00
akwizgran
95f427863d Remove transport preferences for briar-headless. 2020-06-25 17:46:22 +01:00
Torsten Grote
ff8a422638 Merge branch '1712-connection-manager-refactoring' into 'master'
Connection manager refactoring

See merge request briar/briar!1248
2020-06-25 14:21:49 +00:00
akwizgran
78d7fc2106 Fix bug in reporting of connection state, add regression tests. 2020-06-02 12:00:06 +01:00
akwizgran
cc943be540 Update javadoc. 2020-06-01 15:30:30 +01:00
akwizgran
6eb77465f6 Don't try to reconnect if the connection was closed cleanly. 2020-06-01 14:49:55 +01:00
akwizgran
35d1b406f7 Refactor transport preferences. 2020-06-01 14:49:55 +01:00
akwizgran
2add63657e Inner class can be static. 2020-06-01 14:49:55 +01:00
akwizgran
d3751fbead Don't interrupt connections until priority is set.
This maintains compatibility with older peers that don't know about
priorities or transport preferences and will try to replace any
connections we close.
2020-06-01 14:49:55 +01:00
akwizgran
4aaa8c3b93 Don't poll if already connected via a better transport. 2020-05-25 17:47:33 +01:00
akwizgran
5b04527c54 Fix screenshot test. 2020-05-25 17:47:33 +01:00
akwizgran
7d6b65913a Combine connection chooser with connection registry. 2020-05-25 16:42:01 +01:00
akwizgran
36747acac1 Extract better and worse transports from preferences. 2020-05-25 14:47:34 +01:00
akwizgran
e8dbc00712 Refactor connection registry implementation. 2020-05-25 14:33:35 +01:00
akwizgran
d3d7212b08 Add registry method for deciding which contacts to poll. 2020-05-13 17:55:05 +01:00
akwizgran
2919657b4a Add unit tests for connection chooser. 2020-05-13 15:56:07 +01:00
akwizgran
0c338b362e Add InterruptibleConnection interface for easier testing. 2020-05-13 15:43:07 +01:00
akwizgran
8dd993dd9d Interrupt connections outside the lock. 2020-05-13 10:24:27 +01:00
akwizgran
1b2b50d91b Exchange priority records and close redundant connections. 2020-05-12 21:36:58 +01:00
akwizgran
ee9c771045 Add priority record for choosing between redundant connections. 2020-05-12 21:36:58 +01:00
akwizgran
9e6d67f13d Handle interrupts that occur before the outgoing session starts. 2020-05-12 21:36:57 +01:00
akwizgran
710b6d18ce Fix import in screenshot test. 2020-05-12 21:36:45 +01:00
akwizgran
dd4aa67643 Refactor connection creation back into manager. 2020-05-12 21:27:43 +01:00
akwizgran
79482d5e3a Move connection management to its own package. 2020-05-12 17:36:35 +01:00
akwizgran
ee0bf7218c Move some duplicated code into utility methods. 2020-05-12 17:25:55 +01:00
akwizgran
c1101c7fe1 Factor inner classes out of ConnectionManagerImpl. 2020-05-12 17:08:04 +01:00
Torsten Grote
708452713d Merge branch '1712-detect-dead-bluetooth-connections' into 'master'
Detect and close dead Bluetooth connections

See merge request briar/briar!1246
2020-05-11 15:55:07 +00:00
akwizgran
c80d3196af Use milliseconds for timing. 2020-05-11 15:42:23 +01:00
Torsten Grote
d1c2eb89a1 Merge branch '1712-fix-double-connection-counting' into 'master'
Don't count Bluetooth connections twice

See merge request briar/briar!1245
2020-05-11 14:06:30 +00:00
akwizgran
c4273d22ed Delegate all other methods to wrapped InputStream. 2020-05-08 16:22:46 +01:00
akwizgran
21f3a9f3c7 Add javadoc. 2020-05-08 16:22:46 +01:00
akwizgran
0281eec0da Add unit test for TimeoutInputStream. 2020-05-08 16:22:46 +01:00
akwizgran
d3fd309609 Only check timeouts when we have some streams to monitor. 2020-05-08 16:22:46 +01:00
akwizgran
f2f278c393 Add timeout monitor for Bluetooth connections. 2020-05-08 16:22:46 +01:00
akwizgran
e204d5a996 Don't count connections twice. 2020-05-08 15:17:27 +01:00
akwizgran
876efee1a8 Use keepalives to detect dead connections. 2020-05-08 14:21:41 +01:00
akwizgran
8fd9a40ffb Merge branch 'discover-bt-address-from-incoming-connection' into 'master'
Discover remote Bluetooth address from connection

See merge request briar/briar!1244
2020-04-29 15:31:30 +00:00
akwizgran
fb918457d4 Use constants for metadata keys. 2020-04-29 15:37:21 +01:00
akwizgran
b5fe55faf3 Validate remote address. 2020-04-29 15:28:27 +01:00
akwizgran
7320099494 Also store properties discovered from outgoing connections.
This is useful when adding a Bluetooth address is discovered while
adding a contact.
2020-04-28 17:56:01 +01:00
akwizgran
346bec94e8 Discover contacts' BT addresses from incoming connections. 2020-04-28 17:45:17 +01:00
akwizgran
856ec61759 Merge branch '1722-lastChatActivity' into 'master'
Include last private chat activity in list of contacts

Closes #1722

See merge request briar/briar!1242
2020-04-27 09:20:08 +00:00
Torsten Grote
f61e2b399e [headless] Fix unit tests by passing only timestamp into OutputContact 2020-04-20 09:44:51 -03:00
Nico Alt
6135f9152f Include last private chat activity in list of contacts
Fixes #1722.
2020-04-08 12:00:00 +00:00
Torsten Grote
84584d4d3c Merge branch 'tor-0.3.5.10' into 'master'
Upgrade Tor to version 0.3.5.10

Closes #1714

See merge request briar/briar!1241
2020-03-31 13:14:21 +00:00
akwizgran
17239810c8 Upgrade Tor to version 0.3.5.10. 2020-03-25 17:09:12 +00:00
Torsten Grote
9eee58657e Merge branch '1696-keystore-crash' into 'master'
Show a dialog instead of crashing if a hardware-backed key can't be loaded

Closes #1696

See merge request briar/briar!1233
2020-03-12 12:12:42 +00:00
Torsten Grote
76425455b8 Merge branch 'logging-for-account-bugs' into 'master'
Add logging to track down account bugs

See merge request briar/briar!1239
2020-03-11 14:18:50 +00:00
akwizgran
9ea7140a7f Add logging to track down account bugs. 2020-03-11 14:06:48 +00:00
akwizgran
bde9800c89 Add annotation for visibility. 2020-03-11 13:54:01 +00:00
Torsten Grote
4e5b6ed3e0 Merge branch '1367-db-race' into 'master'
Don't infer anything from existence of (possibly empty) DB directory

Closes #1528 and #1367

See merge request briar/briar!1238
2020-03-10 14:59:06 +00:00
akwizgran
77d037f061 Update javadocs. 2020-03-10 11:27:54 +00:00
Torsten Grote
676f5faef4 Merge branch 'fix-wifi-connectivity-misreporting' into 'master'
Fix misreporting of wifi status in LAN plugin

See merge request briar/briar!1237
2020-03-06 16:52:20 +00:00
akwizgran
8e21068465 Fix misreporting of wifi status in LAN plugin. 2020-03-06 13:35:06 +00:00
akwizgran
4a68e5347d Merge branch '1582-fix-climbing-snackbar' into 'master'
Fix climbing snackbar

Closes #1582

See merge request briar/briar!1223
2020-03-03 14:42:20 +00:00
Torsten Grote
27dd383496 Merge branch '1371-protect-code-cache-directory' into 'master'
Protect cache and code_cache directories when deleting account

Closes #1545 and #1371

See merge request briar/briar!1231
2020-02-26 14:03:39 +00:00
akwizgran
ed50582e27 Show a dialog if the DB key can't be decrypted due to a keystore error. 2020-02-25 15:00:49 +00:00
akwizgran
1546a05568 Catch exception if hardware-backed key can't be loaded. 2020-02-25 12:28:21 +00:00
akwizgran
4bdf966e67 Test that code_cache directory isn't deleted. 2020-02-25 11:23:07 +00:00
akwizgran
e1e67f3b2e Clear the cache directory but don't delete it. 2020-02-25 11:18:50 +00:00
akwizgran
1d63b16ff1 Don't delete the code_cache directory when deleting account.
This seems to avoid the disappearing account bug when installing a new
version.
2020-02-25 10:14:31 +00:00
akwizgran
618ab1f1ec Don't infer anything from existence of (possibly empty) DB directory. 2020-02-24 17:51:59 +00:00
Torsten Grote
421f0ebfa5 Merge branch 'network-prefix-length' into 'master'
Use network prefix length to determine which addresses are connectable

Closes #1178

See merge request briar/briar!1230
2020-02-19 13:11:24 +00:00
akwizgran
61db5d1b04 Make bit-twiddling code more readable. 2020-02-19 09:52:13 +00:00
akwizgran
b3d4012527 Use network prefix length to determine which addresses are connectable. 2020-02-18 11:22:29 +00:00
Torsten Grote
60172331ee Merge branch 'ipv4-link-local' into 'master'
Add support for IPv4 link-local addresses

See merge request briar/briar!1229
2020-02-17 12:42:01 +00:00
akwizgran
076debdc4b Merge branch '1328-reuse-port' into 'master'
Choose port in advance when providing wifi access point

Closes #1328

See merge request briar/briar!1228
2020-02-17 12:37:29 +00:00
akwizgran
ed13cbca6a Add support for IPv4 link-local addresses. 2020-02-17 11:42:13 +00:00
akwizgran
49cb1d0612 Choose port in advance when providing wifi access point. 2020-02-14 16:56:00 +00:00
akwizgran
eb562f8f6b Bump version numbers for 1.2.7 release. 2020-02-14 09:51:14 +00:00
Torsten Grote
d9b3ee7f77 Merge branch '1707-fragment-listeners' into 'master'
Don't overwrite listener references with null during fragment changes

Closes #1707, #1706, #1704, and #1697

See merge request briar/briar!1227
2020-02-13 17:47:09 +00:00
akwizgran
c206b46e28 Don't overwrite listener references with null during fragment changes. 2020-02-13 15:58:26 +00:00
akwizgran
62ef64db11 Bump version numbers for 1.2.6 release. 2020-02-13 11:33:18 +00:00
akwizgran
c2e83dd21d Update translations. 2020-02-13 11:32:19 +00:00
akwizgran
48048dd2fd Merge branch '1483-crash-logging' into 'master'
Log the role we find when failing to parse creator session

See merge request briar/briar!1225
2020-02-12 17:26:32 +00:00
akwizgran
17335811ec Merge branch '1699-no-browser' into 'master'
Check if browser intent resolves before starting

Closes #1699

See merge request briar/briar!1226
2020-02-12 14:48:58 +00:00
Torsten Grote
9946fe806a [android] check if browser intent resolves before starting
This prevents a crash on systems without a browser
2020-02-12 10:43:59 -03:00
Torsten Grote
748d249771 [core] log the role when failing to parse creator session 2020-02-12 09:31:16 -03:00
akwizgran
68d6b4b2ac Merge branch '1665-recyclerview-selection' into 'master'
Upgrade recyclerview and selection library to fix crashes

Closes #1665

See merge request briar/briar!1224
2020-02-12 11:24:22 +00:00
Torsten Grote
cf48efae34 [android] upgrade recyclerview and selection library 2020-02-12 08:02:25 -03:00
akwizgran
287be6aa3f Merge branch '1695-show-no-internet-snackbar-when-tor-disabled' into 'master'
Show "No Internet" snackbar when Tor plugin is not active

Closes #1695

See merge request briar/briar!1222
2020-02-11 17:28:05 +00:00
Torsten Grote
1e4ad67ffc [android] Fix climbing snackbar
Use a fresh snackbar for pending contacts each time it needs to be
shown. Don't re-use the old instance and clear it in onStop().
2020-02-11 13:25:15 -03:00
Torsten Grote
c976dd02ae [android] Show "No Internet" snackbar when Tor plugin is not active 2020-02-11 12:59:28 -03:00
Torsten Grote
c4761c3bb2 Merge branch 'ignore-ble-for-bt-discovery' into 'master'
Ignore BLE-only devices during BT discovery

See merge request briar/briar!1221
2020-02-07 13:18:53 +00:00
Torsten Grote
0ff182b5af Merge branch 'message-tree-thread-safety' into 'master'
Ensure MessageTreeImpl#contains() is thread-safe

See merge request briar/briar!1213
2020-01-23 11:02:55 +00:00
akwizgran
b904b6ea51 Ensure MessageTreeImpl#contains() is thread-safe. 2020-01-23 10:14:35 +00:00
akwizgran
aad92e3f32 Bump version numbers for 1.2.5 release. 2020-01-20 17:28:04 +00:00
akwizgran
f816132ac2 Update translations. 2020-01-20 17:27:11 +00:00
akwizgran
0dcfa5826f Merge branch 'nav-drawer-banner' into 'master'
Hide banner of navigation drawer when not enough screen heigth available

See merge request briar/briar!1208
2020-01-15 13:35:59 +00:00
Torsten Grote
792892d933 Hide banner of navigation drawer when not enough screen heigth available 2020-01-15 09:22:50 -03:00
Torsten Grote
ab9ade9a0b Merge branch '1182-hardware-backed-key' into 'master'
Encrypt DB key with hardware-backed key when available

Closes #1182

See merge request briar/briar!1207
2020-01-15 11:32:33 +00:00
akwizgran
c61c9bbc02 Refactor Android-specific code out of bramble-core. 2020-01-10 17:41:10 +00:00
akwizgran
f650b2236e Catch any Exception when generating stored key. 2020-01-10 16:15:56 +00:00
akwizgran
72a391b506 Break out of loop after generating key. 2020-01-10 12:22:47 +00:00
akwizgran
f76d08c19a Use StrongBox on API 28+ if available. 2020-01-09 15:18:58 +00:00
akwizgran
fc6b596241 Remove unnecessary key purpose. 2020-01-09 15:03:46 +00:00
akwizgran
c11d09a885 Re-encrypt the DB key with the stored key. 2020-01-09 14:45:32 +00:00
akwizgran
d7b05dcba0 Add javadocs. 2020-01-09 14:45:32 +00:00
akwizgran
4d3c1b4fd2 Use Android keystore for encrypting DB key.
Only for new accounts on API 23+.
2020-01-09 14:45:32 +00:00
akwizgran
8a6e886d09 Remove DB key migration code. 2020-01-09 11:22:39 +00:00
Torsten Grote
69093d6786 Merge branch '1636-compression-failure' into 'master'
Fix PNG compression on some phones

Closes #1636

See merge request briar/briar!1183
2020-01-08 16:06:39 +00:00
akwizgran
120fcf550d Merge branch 'undefined' into 'master'
Android TV leanback banner

See merge request briar/briar!1199
2020-01-08 16:00:30 +00:00
akwizgran
5af7bbb24d Merge branch 'master' into '1636-compression-failure'
# Conflicts:
#   bramble-android/src/main/java/org/briarproject/bramble/util/AndroidUtils.java
2020-01-08 15:27:01 +00:00
Torsten Grote
dd3c909b31 Merge branch 'bt-address-reflection' into 'master'
Use reflection to get local Bluetooth address

See merge request briar/briar!1202
2020-01-08 14:05:01 +00:00
Torsten Grote
4f1e9067e3 Merge branch '68-enable-private-message-deletion-in-release-builds' into 'master'
Enable private message deletion in release builds

See merge request briar/briar!1206
2020-01-08 14:00:03 +00:00
akwizgran
9305532079 Enable private message deletion in release builds. 2020-01-07 12:43:10 +00:00
akwizgran
bbcdd9418c Revert breaking change to Korean translation. 2020-01-07 12:35:25 +00:00
akwizgran
373ca0e0ea Update translations. 2020-01-07 11:30:21 +00:00
akwizgran
e4af161db5 Merge branch 'fix-test-sensitivity-to-arrival-order' into 'master'
Fix sensitivity of integration tests to message arrival order

See merge request briar/briar!1205
2019-12-20 12:12:36 +00:00
akwizgran
9b37cb19f4 Reset counters before each test. 2019-12-19 17:55:56 +00:00
akwizgran
016178045f Make integration tests less sensitive to sync order. 2019-12-19 17:45:32 +00:00
akwizgran
dae08b2af4 Merge branch '1677-note-alias-key' into 'master'
Add warning about alias key to headless contacts response documentation

See merge request briar/briar!1204
2019-12-17 12:26:16 +00:00
Nico Alt
3bc349e426 Add warning about alias key to headless contacts response documentation
Quick fix for https://code.briarproject.org/briar/briar/issues/1677.
2019-12-16 15:30:02 +01:00
akwizgran
bd478c5074 Ignore BLE-only devices during BT discovery. 2019-12-12 17:24:09 +00:00
akwizgran
26144c18d8 Download test assets, fix expectations. 2019-12-12 14:25:40 +00:00
akwizgran
ace1d38966 Disable PngSuite test by default.
Results are device-dependent and outside our
control.
2019-12-12 14:25:40 +00:00
akwizgran
24a63b08c0 Add transparent PNG. 2019-12-12 14:25:40 +00:00
akwizgran
44411ab224 Simplify code. 2019-12-12 14:25:40 +00:00
akwizgran
6d742c554f Test that PngSuite corrupt test images fail. 2019-12-12 14:25:40 +00:00
akwizgran
1e2ccd96a7 Remove support for GIF attachments on API < 24. 2019-12-12 14:25:40 +00:00
Torsten Grote
1000512c5b [android] Add PngSuite images to compression test 2019-12-12 14:25:37 +00:00
Torsten Grote
c7a0f794c8 [android] Fix PNG compression with different BitmapConfig
Source: https://stackoverflow.com/a/6140360
2019-12-12 10:04:49 +00:00
Torsten Grote
62970cce30 [android] add instrumentation test for image compression 2019-12-12 10:04:44 +00:00
Torsten Grote
6a31274b76 Merge branch 'remove-default-methods' into 'master'
Replace default methods with helper classes

See merge request briar/briar!1203
2019-12-11 16:44:59 +00:00
akwizgran
5962d3c763 Replace default methods with helper classes.
This is a workaround for AbstractMethodErrors
thrown by on-device tests.
2019-12-11 16:28:19 +00:00
Torsten Grote
6f38e70ad2 Merge branch 'tor-0.3.5.9' into 'master'
Upgrade Tor to 0.3.5.9

See merge request briar/briar!1201
2019-12-11 13:10:43 +00:00
akwizgran
61324b1cb0 Catch SecurityException.
This isn't currently thrown, but future versions
of Android might throw it.
2019-12-11 12:03:37 +00:00
akwizgran
d1e21877b3 Use reflection to get local Bluetooth address.
This is expected to work on Android 8 but not 8.1+.
2019-12-11 11:48:53 +00:00
akwizgran
61293c0747 Upgrade Tor to 0.3.5.9. 2019-12-11 09:43:24 +00:00
Torsten Grote
5ba64577bd Merge branch '68-tweak-deletion-error-messages' into 'master'
Tweak the error dialog when message deletion fails

See merge request briar/briar!1200
2019-12-10 16:56:48 +00:00
akwizgran
3486cc8fcc Tweak the error dialog when message deletion fails. 2019-12-10 16:05:03 +00:00
akwizgran
a1357c22b2 Fix checksum for jackson-annotations.
See https://issues.sonatype.org/browse/OSSRH-51881
2019-12-10 13:44:30 +00:00
akwizgran
86693abd66 Merge branch '1656-explain-deletion-failures' into 'master'
Better explain why messages could not be deleted

Closes #1656

See merge request briar/briar!1197
2019-12-10 12:38:07 +00:00
Torsten Grote
0edb2b7b6e [core] Add JavaDoc for MessageRetreiver of IntroductionManager
for message deletion
2019-12-10 09:02:43 -03:00
akwizgran
ffc2c5d900 Merge branch 'javalin-3.5' into 'master'
Upgrade headless to Javalin 3.5

See merge request briar/briar!1162
2019-12-10 10:11:55 +00:00
Hugh Isaacs II
6380133fcd Update briar-android/src/main/AndroidManifest.xml, briar-android/src/main/res/mipmap-xhdpi/tv_banner.png files 2019-12-02 16:29:25 +00:00
Hugh Isaacs II
1ae4062f01 Android TV leanback banner 2019-12-02 16:13:15 +00:00
Torsten Grote
9ebe49b85d [headless] Let websocket upgrade requests pass in AccessManager
This is because JavaScript in browsers apparently can not add Authentication
headers to websocket requests, so we use a dedicated authentication message there.

In Javalin 3, the AccessManager also handles websocket requests.
We need to let those pass to support JavaScript.
2019-11-14 14:13:54 -03:00
Torsten Grote
6f153f14c7 [headless] upgrade to Javalin 3.5 2019-11-14 14:13:54 -03:00
Torsten Grote
5aeee9af8b [core] address review comments for message deletion explanation 2019-11-14 14:05:28 -03:00
akwizgran
52feabecbe Merge branch 'disable-google-tracking' into 'master'
Disable instrumentation test analytics

See merge request briar/briar!1198
2019-11-14 14:07:50 +00:00
Torsten Grote
53fb3f78c1 [android] disable instrumentation test analytics 2019-11-13 14:12:07 -03:00
Torsten Grote
ae0fa351b6 Better explain why messages could not be deleted
This also fixes a bug in the IntroductionManager that would allow to
delete only part of a session's visible messages.
2019-11-11 13:09:51 -03:00
akwizgran
11c43dc7f4 Merge branch '1628-multi-select' into 'master'
Multi-select conversion messages (to delete)

Closes #1628

See merge request briar/briar!1179
2019-11-08 13:05:09 +00:00
Torsten Grote
497ab38be1 [android] highlight selected messages with accent color 2019-11-08 09:54:04 -03:00
Torsten Grote
ddcb412fcd [core] remove notice about removing support for old message type 2019-11-07 15:31:24 -03:00
Torsten Grote
71243ce561 [android] prevent empty state message from showing up briefly when clearing list 2019-11-07 15:30:25 -03:00
Torsten Grote
5c900c443d [core] also support private messages in legacy format for selective deletion 2019-11-07 14:39:50 -03:00
Torsten Grote
97dd9b901d [android] hook up UI to ConversationManager to actually delete messages 2019-11-07 14:39:50 -03:00
Torsten Grote
9ce327a40c [android] highlight selected conversation messages in UI 2019-11-07 14:39:50 -03:00
Torsten Grote
a9b9a8c5f8 [android] allow to select multiple conversation messages 2019-11-07 14:39:49 -03:00
akwizgran
ed66a470cc Merge branch '1643-controller-leaks' into 'master'
Fix controller memory leaks

Closes #1643

See merge request briar/briar!1184
2019-11-07 16:33:18 +00:00
akwizgran
405c243313 Merge branch '1243-attachment-close-button-color' into 'master'
Change image preview close button color to accent color

See merge request briar/briar!1182
2019-11-07 16:23:24 +00:00
Torsten Grote
034e76dd5c [android] Fix controller memory leaks 2019-11-07 12:57:41 -03:00
Torsten Grote
73417a42d6 [android] change image preview close button color to accent color
This was suggested in #1243.
2019-11-07 12:56:52 -03:00
akwizgran
9d72fca2a7 Merge branch 'AndroidX' into 'master'
AndroidX Migration

See merge request briar/briar!1176
2019-11-07 15:40:19 +00:00
akwizgran
b4e0d3b982 Merge branch '1653-npe-settings-fragment' into 'master'
Don't try to display settings before they are fully loaded

Closes #1653

See merge request briar/briar!1194
2019-11-07 15:29:55 +00:00
Torsten Grote
088ca01eb3 [android] re-include BrambleCoreModule since issue caused by it also exists on master 2019-11-07 12:20:03 -03:00
Torsten Grote
83ed6f90d7 [core] downgrade okhttp to 3.12.x series to support our minSdk level 2019-11-07 11:49:45 -03:00
Torsten Grote
ab7b287082 [android] downgrade zxing to 3.3.3 because newer versions need minSdk 24 2019-11-07 10:44:08 -03:00
Torsten Grote
4fe41bfde7 Merge branch 'remove-beta-build-flag' into 'master'
Remove beta build flag

Closes #1527

See merge request briar/briar!1196
2019-11-06 17:53:02 +00:00
Torsten Grote
2e65122e9d Merge branch 'client-versioning-events' into 'master'
Update image attachment UI when new client version is received from contact

Closes #1638

See merge request briar/briar!1195
2019-11-06 17:52:43 +00:00
akwizgran
ee180defce Remove expiry update code, fix references to Briar 1.0. 2019-11-06 14:21:52 +00:00
akwizgran
7ee0febf0c Use TimeUnit to make durations more readable. 2019-11-06 14:21:52 +00:00
akwizgran
216f0598f9 Remove ancient flag for beta builds. 2019-11-06 14:20:11 +00:00
akwizgran
27cba75a50 Fix test expectations. 2019-11-06 14:17:16 +00:00
akwizgran
b3bc5e69b5 Use client versioning event to update UI. 2019-11-06 13:58:11 +00:00
akwizgran
ee1fd2ad8a Broadcast events for client versioning updates. 2019-11-06 13:58:11 +00:00
akwizgran
a844526dae Refactor ClientVersion to bramble-api. 2019-11-06 13:58:06 +00:00
Torsten Grote
cb5a9bdff8 [android] don't try to display settings before they are fully loaded 2019-11-06 09:21:28 -03:00
akwizgran
75dfa80541 Bump version numbers for 1.2.4 release. 2019-11-06 09:58:00 +00:00
akwizgran
41b59fbcfe Merge branch '1610-pending-contacts-offline-snackbar' into 'master'
Don't show offline snackbar when there's no pending contacts

Closes #1610

See merge request briar/briar!1193
2019-11-06 09:50:39 +00:00
akwizgran
98a4f5def1 Merge branch '1654-notification-channel-unavailable' into 'master'
Fail gracefully when ACTION_CHANNEL_NOTIFICATION_SETTINGS is not available

Closes #1654

See merge request briar/briar!1192
2019-11-06 09:49:21 +00:00
akwizgran
aeefa35f38 Merge branch '1454-theme-system-crash' into 'master'
Prevent crash when user has set theme to system default on unsupported API level

Closes #1454

See merge request briar/briar!1191
2019-11-06 09:46:48 +00:00
akwizgran
4e7f33edfd Merge branch '1483-group-invite-not-allowed' into 'master'
Make sure group actions can only be made by the correct role

See merge request briar/briar!1190
2019-11-06 09:45:28 +00:00
akwizgran
f1e957ffed Merge branch '1655-no-bluetooth-activity' into 'master'
Check if REQUEST_BLUETOOTH_DISCOVERABLE is available before launching

Closes #1655

See merge request briar/briar!1189
2019-11-06 09:42:00 +00:00
akwizgran
9e3fed6bc0 Merge branch '1651-no-ringtone-picker' into 'master'
Check if ringtone picker is available before launching it

Closes #1485 and #1651

See merge request briar/briar!1188
2019-11-06 09:40:30 +00:00
Torsten Grote
bf9a39cc6c [android] don't show offline snackbar when there's no pending contacts
If the pending contact list is opened concurrently
with the last pending contact being removed (unlikely but possible)
then the "no internet connection" snackbar would be shown
even though the app is connected to Tor.
2019-11-05 15:35:10 -03:00
Torsten Grote
72aa5397f8 [android] fail gracefully when ACTION_CHANNEL_NOTIFICATION_SETTINGS is not available 2019-11-05 15:17:10 -03:00
Torsten Grote
21eaab3259 [android] prevent crash when user has set theme to system default
on an API level that does not support it.
2019-11-05 14:57:25 -03:00
Torsten Grote
92d595da35 [android] make sure group actions can only be made by the correct role 2019-11-05 14:46:10 -03:00
Torsten Grote
5e85566fc3 [android] check if REQUEST_BLUETOOTH_DISCOVERABLE is available before launching 2019-11-05 12:54:02 -03:00
Torsten Grote
1574bf35fc [android] do not use file:// Uris for notification sounds
This causes a FileUriExposedException otherwise.

Closes #1485
2019-11-05 12:31:25 -03:00
Torsten Grote
533e01e881 [android] check if ringtone picker is available before launching
Also refuse file:// Uri as they cause a FileUriExposedException as in #1485
2019-11-05 12:03:00 -03:00
Torsten Grote
0103835601 [android] upgrade design library to fix memory leak 2019-11-01 14:12:24 -03:00
Torsten Grote
dc1183b4cc [android] Apply updated Android XML layout formatting 2019-11-01 11:47:35 -03:00
Torsten Grote
044e1ebe73 [android] Fix theme of DevReportActivity after AndroidX migration 2019-11-01 11:47:34 -03:00
Torsten Grote
494e51ef07 Optimize imports after AndroidX migration 2019-11-01 11:47:33 -03:00
Torsten Grote
1be078d181 Change CI config so that it finds more breakages
Previously we did not run lint and did not try to compile the
AndroidTest instrumentation tests.
2019-11-01 11:44:37 -03:00
Torsten Grote
98eb78c7bc [android] fix instrumentation tests after AndroidX migration 2019-11-01 11:44:36 -03:00
Torsten Grote
9d31a0a536 [android] Fix robolectric test after AndroidX migration 2019-11-01 11:44:36 -03:00
Torsten Grote
a592c05146 AndroidX migration and library updates 2019-11-01 11:44:36 -03:00
akwizgran
383367f0c8 Merge branch 'remove-remove-contacts-feature-flag' into 'master'
Remove contacts feature flag

See merge request briar/briar!1185
2019-11-01 14:29:37 +00:00
Torsten Grote
ca052ea7dd update translations 2019-11-01 11:12:26 -03:00
Torsten Grote
5147f6b7e6 Remove RemoteContacts feature flag in preparation of 1.2 release 2019-11-01 11:09:43 -03:00
akwizgran
84a8ff1dd8 Merge branch '1629-delete-message-subset' into 'master'
Support for deleting a subset of all conversation messages

Closes #1629

See merge request briar/briar!1180
2019-10-28 16:52:41 +00:00
Torsten Grote
6c489fbea3 [core] also delete attachments when deleting select messages 2019-10-28 10:22:04 -03:00
Torsten Grote
c7200910c9 [core] address feedback for selective conversation message deletion 2019-10-28 09:45:41 -03:00
akwizgran
663e5c4b46 Merge branch '1405-emoji-keyboard' into 'master'
Always show keyboard when clicking text input field

Closes #1405

See merge request briar/briar!1181
2019-10-28 12:16:15 +00:00
Torsten Grote
529eaceec7 [android] show keyboard when clicking text input field 2019-10-22 12:43:35 -03:00
Torsten Grote
f516dbe34f [core] add method to ConversationManager for deleting a set of messages 2019-10-22 11:18:10 -03:00
Torsten Grote
5b515d7e18 [core] implement subset conversation message deletion for IntroductionManager 2019-10-22 11:18:10 -03:00
Torsten Grote
ef04a26cfc [core] implement subset conversation message deletion for GroupInvitationManager 2019-10-22 11:18:09 -03:00
Torsten Grote
2e6fe42074 [core] implement subset conversation message deletion for SharingManager 2019-10-22 11:18:09 -03:00
Torsten Grote
124e2f99b0 [core] Add method to ConversationClient for deleting a set of messages
This also implements the method for MessagingManager
(including integration tests) and adds no-op implementations for other
clients.
2019-10-22 11:18:09 -03:00
Torsten Grote
190a6bff96 [core] Add method to ConversationClient that returns a set of MessageIds it is responsible for 2019-10-22 11:18:08 -03:00
Torsten Grote
01df141c08 Merge branch '843-landscape-keyboard' into 'master'
Raise target API version to 28 and fix soft keyboard issues

Closes #1505

See merge request briar/briar!1043
2019-10-21 12:38:38 +00:00
Torsten Grote
d7c9bf80de Merge branch 'xml-formatting-settings' into 'master'
Update XML code style settings

See merge request briar/briar!1178
2019-10-18 16:51:30 +00:00
akwizgran
3a5e51e248 Update XML code style settings. 2019-10-18 17:38:41 +01:00
akwizgran
a76e3dcec1 Fix bug with enter key when rotating screen. 2019-10-18 14:03:01 +01:00
akwizgran
0fdc7199ed Hide keyboard when contact alias dialog is closed. 2019-10-18 14:03:01 +01:00
akwizgran
248f482fee Use requestFocus tag for RSS import. 2019-10-18 14:03:00 +01:00
akwizgran
4196d046a3 Use stateAlwaysVisible for consistent behaviour. 2019-10-18 14:03:00 +01:00
akwizgran
722ebb22f6 Use requestFocus tag to request initial focus. 2019-10-18 13:45:48 +01:00
akwizgran
a4f561ca1a Request focus when showing soft keyboard. 2019-10-18 13:45:48 +01:00
akwizgran
c7db0bf6fa Remove unused listener implementation. 2019-10-18 13:45:47 +01:00
akwizgran
ca6f458551 Always hide keyboard when importing RSS feed. 2019-10-18 13:45:47 +01:00
akwizgran
c85990408a Remove redundant requestFocus() call. 2019-10-18 13:45:47 +01:00
akwizgran
3ed0204170 Clean up soft input modes. 2019-10-18 13:45:46 +01:00
akwizgran
e2b3340734 Remove redundant methods for showing/hiding keyboard. 2019-10-18 13:45:45 +01:00
akwizgran
78aac8de52 Replace EditText with TextInputEditText. 2019-10-18 13:45:45 +01:00
akwizgran
971ae3a20e Raise target API level to 28. 2019-10-18 13:45:44 +01:00
Torsten Grote
622e7a775a [android] Soft keyboard fixes
1. Manually request focus for input fields and show keyboard

This is needed when targetting API 28 which doesn't give focus anymore
automatically like it used to be.

Closes #1505

2. Remember keyboard states across screen rotations

This also upgrades the emoji library and gets rid of the
KeyboardAwareLinearLayout that is still a relict from the time when we
were using Signal's emoji implementation.

3. Move soft keyboard showing/hiding into UiUtils
2019-10-18 13:44:44 +01:00
akwizgran
103e8482b0 Merge branch 'codeStylesAS3.5' into 'master'
Android Studio 3.5 changed our codeStyles

See merge request briar/briar!1177
2019-10-17 16:56:13 +00:00
Torsten Grote
ddcfc11012 Android Studio 3.5 changed our codeStyles 2019-10-17 13:33:51 -03:00
akwizgran
ab2e40abde Merge branch '1565-duplicate-remote-contacts' into 'master'
UX for handling duplicate handshake links

Closes #1565

See merge request briar/briar!1173
2019-10-16 16:16:08 +00:00
Torsten Grote
1ddceaadd6 Always replace pending contacts no matter their state when link is re-entered 2019-10-16 13:06:21 -03:00
akwizgran
7a644f7d8b Merge branch '1210-fix-list-duplicates' into 'master'
[android] Fix duplicate items in lists

Closes #1210

See merge request briar/briar!1174
2019-10-16 14:32:49 +00:00
Torsten Grote
397afbfec0 Address review comments for detecting duplicate (pending) contacts 2019-10-16 11:15:14 -03:00
Torsten Grote
0d4cb05ac0 [android] fix possible duplicates in list
When doing reloads of list items such as when adding test contacts,
we loaded different versions of those items and added them to the list.
According to the documentation
https://developer.android.com/reference/android/support/v7/util/SortedList.html#add
> If the sorting criteria of the item is changed,
> SortedList won't be able to find its duplicate in the list
> which will result in having a duplicate of the Item in the list.

For the contact list at least, new contacts caused reloads of the entire list
and new messages caused the contacts to be sorted differently.
Thus we ended up with duplicate contacts in the list.

This commit fixes this by replacing the contacts in the list instead of adding them.
It applies the same fix to forums and private groups
which use the same logic and are thus also affected.

Fixes #1210
2019-10-15 16:25:10 -03:00
Torsten Grote
aa0937e6aa [android] Show dialog when (pending) contact already exists
If two different people sent the same link, show warning dialog to the
user to prevent a social attack trying to discover contact
relationships.
2019-10-15 14:47:42 -03:00
Torsten Grote
4bf8d4c0e7 [bramble] add method for getting pending contact state 2019-10-15 14:46:37 -03:00
Torsten Grote
75fcd28071 [bramble] throw exceptions when adding pending contact which exists 2019-10-15 10:32:52 -03:00
Torsten Grote
5f29ab3b40 [bramble-core] Add DB method for getting contact by handshake key 2019-10-15 10:12:59 -03:00
Torsten Grote
f45d00e23c Update translations, add Bosnian and Swahili 2019-10-14 15:11:44 -03:00
akwizgran
2b589c2da6 Merge branch 'tor64' into 'master'
Add support for 64-bit Tor binaries

Closes #1506

See merge request briar/briar!1161
2019-10-14 16:33:53 +00:00
akwizgran
67d15ec82e Merge branch '1633-min-api-16' into 'master'
[android] Raise minimum API level to 16

Closes #1633

See merge request briar/briar!1171
2019-10-14 15:37:43 +00:00
akwizgran
2d44d749ba Merge branch '1627-test-fix' into 'master'
Fix group sharing message deletion test

See merge request briar/briar!1168
2019-10-14 15:36:12 +00:00
Torsten Grote
6ef86c5638 Merge branch 'remove-tor-settings-migration' into 'master'
Remove old migration code for Tor settings

See merge request briar/briar!1172
2019-10-14 15:28:24 +00:00
akwizgran
131f9b9696 Remove old migration code for Tor settings. 2019-10-14 16:00:43 +01:00
akwizgran
a876d4cfb7 Remove a couple of redundant comments. 2019-10-14 15:59:14 +01:00
akwizgran
fafcacf808 Remove a couple more API version checks. 2019-10-14 15:56:44 +01:00
akwizgran
7a0d990f0b Don't include non-PIE binaries in APK.
This shouldn't be merged before raising the minimum
API version to 16.
2019-10-14 15:49:37 +01:00
Torsten Grote
234bdf686e [android] Raise minimum API level to 16 2019-10-14 11:49:06 -03:00
akwizgran
edb9da107f Merge branch '1632-allow-resharing-shareable' into 'master'
Allow sharer to re-share a shareable again after leaving

Closes #1632

See merge request briar/briar!1169
2019-10-14 14:29:38 +00:00
Torsten Grote
d1d4914c6a Merge branch '1582-restore-recycler-view-behaviour' into 'master'
Restore custom layout behaviour for handling snackbar

Closes #1582

See merge request briar/briar!1170
2019-10-14 14:26:01 +00:00
Torsten Grote
9261d23bba [core] allow sharer to re-share a shareable again after leaving 2019-10-14 11:13:01 -03:00
akwizgran
f4febe90c9 Restore custom layout behaviour for handling snackbar. 2019-10-14 14:45:23 +01:00
Torsten Grote
ecd766b204 [core] Fix group sharing message deletion test 2019-10-14 09:40:52 -03:00
akwizgran
ca4fc2dc26 Merge branch '1627-delete-completed-privategroup-sessions' into 'master'
Delete conversation messages belonging to completed private group sessions

Closes #1627

See merge request briar/briar!1167
2019-10-14 11:57:27 +00:00
akwizgran
c3ddcdffe0 Merge branch '1627-delete-completed-sharing-sessions' into 'master'
Delete conversation messages belonging to completed sharing sessions

See merge request briar/briar!1164
2019-10-14 11:45:30 +00:00
Torsten Grote
2e37619357 [android] use new obfs4 release with only pie builds and fixed arm64 2019-10-10 10:01:15 -03:00
Torsten Grote
c247d745df [bramble-android] add support for 64-bit Tor binaries 2019-10-10 09:29:24 -03:00
akwizgran
3a4de3d2cb Merge branch '68-fix-message-tracker' into 'master'
Fix MessageTracker group counts after deleting messages

See merge request briar/briar!1166
2019-10-10 08:54:45 +00:00
Torsten Grote
04f1036dbf [android] Change non-deletion message to refer to ongoing sessions 2019-10-09 17:21:41 -03:00
Torsten Grote
9736f9d31f [core] allow messages from private group sessions with responses get deleted 2019-10-09 17:21:41 -03:00
Torsten Grote
440d5239b1 [core] track GroupCount properly when deleting messages from SharingManager 2019-10-09 13:32:41 -03:00
Torsten Grote
e4a8b10b94 [core] allow messages from shareable sessions with responses get deleted 2019-10-09 13:22:37 -03:00
Torsten Grote
41676065c5 [core] Fix MessageTracker group counts after deleting messages 2019-10-09 13:19:43 -03:00
Torsten Grote
1fcc83a0d0 Merge branch 'feature-flag-message-deletion' into 'master'
Add feature flag for private message deletion

See merge request briar/briar!1165
2019-10-09 15:56:17 +00:00
akwizgran
249b85cd26 Add feature flag for private message deletion. 2019-10-09 16:22:04 +01:00
akwizgran
a23e0699d8 Merge branch '1627-delete-completed-introduction-sessions' into 'master'
Delete conversation messages belonging to completed introduction sessions

See merge request briar/briar!1163
2019-10-09 12:39:05 +00:00
Torsten Grote
e3e47dae48 [core] throw AssertionError if SessionId is missing
Also remove stale comment
2019-10-09 08:27:33 -03:00
Torsten Grote
9660ff2fff [core] delete conversation messages belonging to completed introduction sessions
A session is completed if it returned to the START state
and if all sent messages have been ACKed by the receiver.

The session's metadata is kept in case the user restarts the session
by doing another introduction.
2019-10-09 08:24:16 -03:00
akwizgran
ea810c817b Merge branch '1626-delete-all-messages-ui' into 'master'
Add conversation menu action to delete all messages

Closes #1626

See merge request briar/briar!1159
2019-10-07 16:56:44 +00:00
Torsten Grote
876d50975e [android] fix typo s/can not/cannot/ 2019-10-07 12:08:18 -03:00
akwizgran
bf5bdc52b4 Merge branch '1577-headless-readme-improvements' into 'master'
Clarify minor things in headless readme

Closes #1577

See merge request briar/briar!1157
2019-10-07 14:55:17 +00:00
akwizgran
29320c410e Merge branch '1625-conversation-client-message-deletion' into 'master'
Add ConversationManager method for deleting all messages

Closes #1625

See merge request briar/briar!1158
2019-10-07 14:44:41 +00:00
Nico Alt
d41472a18c Clarify minor things in headless readme
Based on answers received in #1577, I tried to clarify outstanding
questions I had about the Briar Headless API.

Fixes #1577.
2019-10-07 16:35:21 +02:00
akwizgran
c411065255 Merge branch '1582-pending-contacts-snackbar-fab' into 'master'
Use snackbar-aware behaviour for FAB.

Closes #1582

See merge request briar/briar!1156
2019-10-07 13:48:01 +00:00
Torsten Grote
3ac5646355 [briar-android] Add conversation menu action to delete all messages 2019-10-03 15:24:36 -03:00
Torsten Grote
c46fdce277 Add ConversationManager method for deleting all messages
Note that this does not yet delete special conversation messages
such as invitations or introductions and their responses.
2019-10-03 14:47:12 -03:00
akwizgran
643ef593e1 Use dodgeInsetEdges to make room for the snackbar. 2019-10-02 12:16:24 +01:00
akwizgran
eda17449be Merge branch '1582-pending-contacts-snackbar' into 'master'
Prevent pending contacts snackbar from covering contact list

See merge request briar/briar!1152
2019-10-01 12:18:11 +00:00
Torsten Grote
28f82a1507 Use snackbar-aware behaviour for FAB. 2019-10-01 13:01:44 +01:00
Torsten Grote
8734825346 [android] prevent pending contacts snackbar from covering contact list 2019-10-01 08:53:14 -03:00
akwizgran
640f3d63b0 Merge branch '1583-remote-contacts-small-screens' into 'master'
Make Remote Contact layouts work on small screens

Closes #1583

See merge request briar/briar!1155
2019-09-27 14:58:43 +00:00
akwizgran
b1dfd867f0 Bump version numbers for 1.1.9 release. 2019-07-03 12:16:52 +01:00
Torsten Grote
ff76900d74 Merge branch '1609-trimmed-text-length' into 'master'
Use trimmed length when deciding whether text is empty

Closes #1609

See merge request briar/briar!1153
2019-07-01 16:25:15 +00:00
Torsten Grote
945fdb8ee4 [android] Make Remote Contact layouts work on small screens 2019-07-01 17:56:28 +02:00
Torsten Grote
53fe3e1592 Merge branch '1428-android-debug-logging' into 'master'
Enable debug logging for debug and beta builds

Closes #1428

See merge request briar/briar!1154
2019-07-01 14:34:06 +00:00
akwizgran
be76c5b7db Add safety annotations. 2019-07-01 14:38:28 +01:00
akwizgran
909e946e58 Enable debug logging for debug and beta builds. 2019-07-01 14:34:51 +01:00
akwizgran
408d9ddee4 Rename directory for traditional Chinese translation. 2019-07-01 10:14:08 +01:00
akwizgran
0e5027e725 Update list of translations. 2019-07-01 01:35:52 +01:00
akwizgran
2d4c97a69e Update translations, add new translations. 2019-07-01 01:26:27 +01:00
akwizgran
7d62ae5fa8 Use trimmed length when deciding whether text is empty. 2019-07-01 01:13:24 +01:00
Torsten Grote
bd616853cf Merge branch '1607-upgrade-rome' into 'master'
Upgrade Rome to fix memory allocation bug

Closes #1607

See merge request briar/briar!1151
2019-06-28 14:17:46 +00:00
akwizgran
32e1d6c748 Upgrade Rome to fix memory allocation bug. 2019-06-28 15:09:09 +01:00
akwizgran
6b022afa67 Bump version numbers for 1.1.8 release. 2019-06-28 14:48:00 +01:00
akwizgran
e8b454b25b Update translations. 2019-06-28 14:47:03 +01:00
Torsten Grote
54c05b5ffe Merge branch '1606-bump-client-minor-version' into 'master'
Bump client minor version to avoid triggering crash

Closes #1606

See merge request briar/briar!1150
2019-06-28 13:28:37 +00:00
akwizgran
d145a082f5 Bump client minor version to avoid triggering crash. 2019-06-28 14:07:28 +01:00
akwizgran
4fd012c31a Merge branch 'compress-images' into 'master'
Compress images

See merge request briar/briar!1147
2019-06-26 14:21:24 +00:00
akwizgran
95d06770bf Rename 'scale' to 'inSampleSize' for clarity. 2019-06-26 14:36:40 +01:00
akwizgran
428247b7b2 Initialise result LiveData before starting task. 2019-06-26 14:31:40 +01:00
akwizgran
a921361a56 Inject ImageSizeCalculator. 2019-06-26 12:40:28 +01:00
akwizgran
fe7dfa721e Compress image attachments. 2019-06-25 16:55:09 +01:00
akwizgran
92eb06a9e9 Refactor attachment creation to use injection. 2019-06-25 16:29:54 +01:00
Torsten Grote
5beed1a748 Merge branch '1594-preview-fails-to-load' into 'master'
Use a fresh LiveData for each attachment creation task

Closes #1594

See merge request briar/briar!1144
2019-06-20 14:05:43 +00:00
Torsten Grote
774047d856 Merge branch '1585-check-attachment-content-type' into 'master'
Improve handling of missing attachments in UI

See merge request briar/briar!1142
2019-06-20 14:04:02 +00:00
Torsten Grote
fc28e7aa88 Merge branch 'nickname-nitpicks' into 'master'
Nickname nitpicks

See merge request briar/briar!1143
2019-06-20 13:41:25 +00:00
Torsten Grote
78459499b2 Merge branch '1593-qr-code-assertion-error' into 'master'
Keep enum methods used by ZXing

Closes #1593

See merge request briar/briar!1146
2019-06-19 23:45:49 +00:00
akwizgran
c2973608d7 Keep enum methods used by ZXing. 2019-06-19 16:36:39 +01:00
akwizgran
be1c33cb42 Use a fresh LiveData for each attachment creation task. 2019-06-19 13:43:04 +01:00
akwizgran
c955466bda Load missing attachments when they arrive. 2019-06-19 12:47:18 +01:00
akwizgran
593a0c4632 Improve handling of missing and invalid attachments. 2019-06-19 11:23:57 +01:00
akwizgran
ed20b2d8d6 Use attachment header to retrieve attachment. 2019-06-19 10:57:13 +01:00
akwizgran
34583e6d2d Merge branch '1054-crash-scroll' into 'master'
Improve crash screen and reporter

Closes #1426, #1061, #1390, #1012, and #1054

See merge request briar/briar!1049
2019-06-18 16:47:02 +00:00
Torsten Grote
ea5a862242 [android] Fix send button in ReportForm's action bar 2019-06-18 13:28:28 -03:00
akwizgran
9ab9e02f8a Trim whitespace from nicknames (useful for auto-complete). 2019-06-18 17:24:08 +01:00
akwizgran
3f70ae3c8c Use same input type for nicknames everywhere. 2019-06-18 17:19:39 +01:00
Torsten Grote
3f60098099 [android] don't cancel crash reports after sending them 2019-06-18 12:21:04 -03:00
Torsten Grote
e965021e3d [android] don't clear task when submitting feedback, only after crash 2019-06-18 12:21:04 -03:00
Torsten Grote
7d9380d3d6 [android] go to homescreen after pressing back in crash reporter
Fixes #1390
2019-06-18 12:21:04 -03:00
Torsten Grote
3c8c0e579e [android] point ACRA to correct BuildConfig class
Fixes #1061
2019-06-18 12:21:03 -03:00
Torsten Grote
bd2bbe9268 [android] don't show JSON in feedback/crash report
use key-value pairs instead

Closes #1426
2019-06-18 12:21:03 -03:00
Torsten Grote
89d24b1753 [android] Make entire report form scrollable, not only the hidden data 2019-06-18 12:21:03 -03:00
Torsten Grote
861dbe20b1 [android] Fix crash screen buttons to the bottom of the screen
and resize crash icon to the available screen space
2019-06-18 12:21:02 -03:00
Torsten Grote
197800de8b [android] split crash report screen into two fragments 2019-06-18 12:21:02 -03:00
Torsten Grote
07e824ad68 [android] Make crash screen scrollable and add icon 2019-06-18 12:21:01 -03:00
Torsten Grote
d210215bd1 Merge branch '1585-new-messaging-client' into 'master'
Add support for image attachments to messaging client

Closes #1585

See merge request briar/briar!1133
2019-06-18 14:55:40 +00:00
akwizgran
00705447ec Use feature flag to decide which version to advertise. 2019-06-18 13:39:01 +01:00
akwizgran
9095ccef85 Filter attachment URIs in controller. 2019-06-18 13:10:52 +01:00
akwizgran
3196204094 Send legacy private messages from headless app. 2019-06-18 13:03:50 +01:00
akwizgran
2bae639105 Upgrade messaging client to support attachments. 2019-06-18 13:03:49 +01:00
akwizgran
f73d298752 Merge branch 'inject-feature-flags' into 'master'
Use injection to provide feature flags

See merge request briar/briar!1140
2019-06-18 11:51:09 +00:00
Torsten Grote
bc3a443276 Merge branch '1590-create-private-messages-on-ui-thread' into 'master'
Move private message creation off the crypto executor

Closes #1590

See merge request briar/briar!1141
2019-06-18 11:22:45 +00:00
akwizgran
2a29d33303 Move private message creation off the crypto executor. 2019-06-18 12:14:10 +01:00
akwizgran
30e0be9f43 Merge branch '1580-show-snackbar' into 'master'
Show snackbar when there is no internet connection

Closes #1580

See merge request briar/briar!1139
2019-06-18 09:54:34 +00:00
akwizgran
3828d16971 Use injection to provide feature flags. 2019-06-18 10:52:21 +01:00
akwizgran
a54eb64eb5 Merge branch '1468-reject-unsupported-images' into 'master'
Reject unsupported images

Closes #1468

See merge request briar/briar!1038
2019-06-17 16:39:26 +00:00
Torsten Grote
ad2d3e70d6 [android] address thread-safety issues of attachment creation 2019-06-17 13:22:38 -03:00
Torsten Grote
1f91842c52 [android] re-use the same LiveData for AttachmentResults 2019-06-17 13:11:16 -03:00
Torsten Grote
c07a0a2fd7 [android] address review comments for rejecting unsupported images 2019-06-17 13:11:16 -03:00
Torsten Grote
4ee4905e06 [android] migrate added conversation header to new LiveEvent 2019-06-17 13:11:16 -03:00
Torsten Grote
67b7517f2b [android] refactor AttachmentCreator to return a single LiveData 2019-06-17 13:11:16 -03:00
Torsten Grote
cd3174a643 [android] Fix view recycling issue of image previews 2019-06-17 13:11:15 -03:00
Torsten Grote
9d9bc4ca84 [android] Let AttachmentCreator return same LiveData after configuration changes 2019-06-17 13:11:15 -03:00
Torsten Grote
7358091699 [android] Address first round of review comments for attachments 2019-06-17 13:11:15 -03:00
Torsten Grote
11eefaedcf Refactor attachment creation 2019-06-17 13:11:14 -03:00
Torsten Grote
bb5a6c0241 [android] Add assertions to TextAttachmentController 2019-06-17 13:11:14 -03:00
Torsten Grote
70d29af2ba [android] Allow sending message with attachments before previews are loaded 2019-06-17 13:11:14 -03:00
Torsten Grote
baedb14e2b [android] allow attaching only of images with supported mime type 2019-06-17 13:11:13 -03:00
Torsten Grote
2796926709 [android] Load image preview from database instead of content Uri 2019-06-17 13:11:13 -03:00
Torsten Grote
fc6275b037 [android] reject invalid mime types for image attachments 2019-06-17 13:11:13 -03:00
Torsten Grote
f76f9be4ed Reject attachments that exceed the allowed size
Closes #1468
2019-06-17 13:11:13 -03:00
Torsten Grote
6167ba5c46 [android] move unsent attachment cache logic into AttachmentController 2019-06-17 13:11:12 -03:00
Torsten Grote
55f4600a69 [android] Create attachments before showing previews 2019-06-17 13:11:12 -03:00
Torsten Grote
c73801c7e8 [android] Show snackbar when there is no internet connection 2019-06-17 10:11:02 -03:00
Torsten Grote
249e1e28fe Merge branch '1580-offline-state' into 'master'
Add offline state for pending contacts

Closes #1580

See merge request briar/briar!1138
2019-06-17 13:10:41 +00:00
akwizgran
f0cea28aeb Don't show a message for the offline state. 2019-06-17 13:45:22 +01:00
Torsten Grote
32e8ea9888 Merge branch '1565-strings-duplicate-handshake-links' into 'master'
Add strings for duplicate pending contacts

See merge request briar/briar!1137
2019-06-17 12:29:22 +00:00
akwizgran
5a1caed89f Rename endpoints field. 2019-06-17 13:22:36 +01:00
akwizgran
22f5c42fc1 Resolve merge conflicts.
# Conflicts:
#   briar-android/src/main/res/values/strings.xml
2019-06-17 12:13:19 +00:00
akwizgran
aab46040a5 Add comments for translators. 2019-06-17 13:12:11 +01:00
akwizgran
18fd238aa1 Merge branch '1580-strings-offline-state' into 'master'
Add string for pending contact offline state

See merge request briar/briar!1136
2019-06-17 11:12:50 +00:00
akwizgran
3a837b3c5a Resolve merge conflicts.
# Conflicts:
#   briar-android/src/main/res/values/strings.xml
2019-06-17 11:04:11 +00:00
akwizgran
ac2597865c Merge branch '1587-version-negotiation' into 'master'
Add version negotiation to sync protocol

Closes #1587

See merge request briar/briar!1134
2019-06-17 10:54:39 +00:00
akwizgran
4a67cf3ce7 Don't cache default state when adding pending contact.
This can overwrite the initial state broadcast by the
rendezvous poller.
2019-06-17 10:22:08 +01:00
Torsten Grote
a5041e651e Merge branch '1230-strings-adding-contact-slow' into 'master'
Add strings for warning when adding a contact is slow

See merge request briar/briar!1135
2019-06-15 13:37:13 +00:00
akwizgran
b0e97d787f Add offline state for pending contacts. 2019-06-15 12:27:24 +01:00
akwizgran
0d8af780a3 Add strings for duplicate pending contacts. 2019-06-15 11:31:18 +01:00
akwizgran
9c20e6b333 Add string for pending contact offline state. 2019-06-15 11:04:22 +01:00
akwizgran
ab14976c96 Add strings for warning when adding a contact is slow. 2019-06-15 11:01:09 +01:00
akwizgran
ec3f821ba6 Update test expectations. 2019-06-13 17:17:50 +01:00
akwizgran
1d546da781 Store sync versions received from contacts. 2019-06-13 17:07:12 +01:00
akwizgran
f2c951b70b Add DB methods for getting and setting sync versions. 2019-06-13 17:06:57 +01:00
akwizgran
1e259c100d Add sync versions column to contacts table. 2019-06-13 16:35:48 +01:00
akwizgran
3636aeba9a Use HyperSQL-compatible syntax in migration. 2019-06-13 16:34:20 +01:00
akwizgran
132e20a6ce Send versions record at start of each session. 2019-06-13 16:16:02 +01:00
akwizgran
c228e5c219 Add versions record to sync protocol. 2019-06-13 16:16:02 +01:00
akwizgran
ae1d1fc5a7 Add thread safety and null safety annotations. 2019-06-13 16:16:01 +01:00
Torsten Grote
37f02a40e9 Merge branch '1585-temporary-messages' into 'master'
Add support for temporary messages

See merge request briar/briar!1132
2019-06-12 15:39:02 +00:00
akwizgran
3c8b8c39e1 Turn commonly used variables into fields. 2019-06-12 16:29:24 +01:00
akwizgran
8f839e2c30 Remove temporary messages at startup. 2019-06-12 15:21:48 +01:00
akwizgran
da4b63f20f Clean up ValidationManagerImplTest. 2019-06-12 15:17:13 +01:00
akwizgran
cd40e771d2 Allow messages to be marked as temporary. 2019-06-12 15:11:10 +01:00
Torsten Grote
dd7accfa95 Merge branch '1576-db-before-signing-in' into 'master'
Retry database tasks after signing in

Closes #1576

See merge request briar/briar!1131
2019-06-10 16:33:47 +00:00
akwizgran
1cf993484d Avoid unnecessary reloads. 2019-06-10 17:24:58 +01:00
akwizgran
e810785fe2 Retry database tasks after signing in. 2019-06-10 15:51:20 +01:00
akwizgran
7ec826ccb7 Merge branch '1562-intent-router' into 'master'
Receive external intents through NavDrawerActivity

Closes #1562

See merge request briar/briar!1128
2019-06-10 14:20:06 +00:00
Torsten Grote
4a4abd7efa Merge branch '1232-polling-events' into 'master'
Show "connecting" state for pending contacts

See merge request briar/briar!1129
2019-06-10 13:11:06 +00:00
Torsten Grote
dc2e42e1f2 [android] don't check getIntent() for null as it should be non-null now 2019-06-10 07:39:49 -03:00
Torsten Grote
1c4d277771 Don't route intents for MANAGE_NETWORK_USAGE settings
This is because we require a special permission to launch this intent
and we prefer requiring this permission to having the NavDrawerActivity
added to the back stack.

This commit also re-adds the deprecated USE_FINGERPRINT permission as
Android Studio would show an error otherwise.
2019-06-10 07:39:48 -03:00
Torsten Grote
fb10ba5855 [android] Receive external intents through NavDrawerActivity
This ensures that our main activity is on the task stack below the
activity opened by an external intent. So when the user navigates back,
they always get back to the main activity.
2019-06-10 07:39:48 -03:00
Torsten Grote
f31b85acdb Merge branch '1564-tor-rendezvous-crypto' into 'master'
Publish hidden service for connecting to pending contact

Closes #1564

See merge request briar/briar!1125
2019-06-09 14:24:40 +00:00
akwizgran
6519706599 Merge branch '1579-remove-pending-contacts-button' into 'master'
Show less obstrusive remove button for pending contacts

Closes #1579

See merge request briar/briar!1130
2019-06-08 09:44:35 +00:00
Torsten Grote
76741bc2ba [android] show less obstrusive remove button for pending contacts
This uses the same button as the RSS feed items
2019-06-07 11:09:34 -03:00
akwizgran
60eefbf3e0 Use named constants. 2019-06-07 11:54:44 +01:00
akwizgran
a4a45efd43 Broadcast event when polling newly added contact. 2019-06-07 11:48:53 +01:00
akwizgran
208ae6a4b6 Show recently polled pending contacts as "connecting". 2019-06-07 11:42:48 +01:00
akwizgran
fe1df6dafa Move pending contact events to rendezvous poller. 2019-06-07 11:42:48 +01:00
akwizgran
15d9ff1ebd Rename "connected" state to "connecting". 2019-06-07 11:42:10 +01:00
akwizgran
dc741e988c Shorter description for "waiting for connection" state. 2019-06-07 11:42:10 +01:00
Torsten Grote
6665235768 Merge branch '1232-pending-contact-states' into 'master'
Add ContactManager support for pending contact states

See merge request briar/briar!1122
2019-06-06 21:31:43 +00:00
akwizgran
ba19716e0f Don't broadcast disabled event whenever we close a socket. 2019-06-06 16:42:26 +01:00
akwizgran
41deff1bf3 Suppress redundant enabled/disabled events. 2019-06-06 16:42:26 +01:00
akwizgran
1ec3fa3ade Implement Tor rendezvous crypto. 2019-06-06 16:42:26 +01:00
akwizgran
64ae99bbce Handle corner cases such as removal during rendezvous. 2019-06-06 16:40:55 +01:00
akwizgran
ed1cefa144 Use concurrent map for pending contact states. 2019-06-06 16:40:54 +01:00
akwizgran
23354d6568 Use predicates to match events. 2019-06-06 16:40:54 +01:00
akwizgran
1aa579a44f Add unit tests for pending contact state. 2019-06-06 16:40:54 +01:00
akwizgran
98191fb059 Add ContactManager support for pending contact states. 2019-06-06 16:40:54 +01:00
Torsten Grote
b9283ea654 Merge branch '1232-rendezvous-poller-expiry' into 'master'
Use periodic poll task for expiry

See merge request briar/briar!1127
2019-06-06 15:12:08 +00:00
akwizgran
71b1f99b56 Use regular poll task for expiry. 2019-06-06 13:45:00 +01:00
Torsten Grote
2982a874d4 Merge branch '1232-rendezvous-poller-cleanup' into 'master'
Small cleanups for rendezvous poller

See merge request briar/briar!1126
2019-06-06 12:04:08 +00:00
akwizgran
ea228164dc Check that poller instance isn't reused. 2019-06-06 12:11:31 +01:00
akwizgran
4b5ad9ace4 Make test expectations modular. 2019-06-06 12:11:31 +01:00
Torsten Grote
a94ffd413c Merge branch '1232-transfer-pending-contact-alias' into 'master'
Transfer pending contact alias to contact

See merge request briar/briar!1124
2019-06-05 17:11:48 +00:00
Torsten Grote
1f921753fd Merge branch '1567-rendezvous-poller' into 'master'
Create poller for rendezvous connections

Closes #1567

See merge request briar/briar!1121
2019-06-05 17:08:31 +00:00
Torsten Grote
157b64e643 Merge branch 'pending-contacts-crash' into 'master'
Don't call setValue() on a background thread

See merge request briar/briar!1123
2019-06-05 16:57:04 +00:00
akwizgran
6f285c5b0a Transfer pending contact alias to contact. 2019-06-05 17:48:02 +01:00
akwizgran
bf39c30d24 Don't call setValue() on a background thread. 2019-06-05 17:45:12 +01:00
akwizgran
7439e5579f Let plugins know if we're Alice or Bob. 2019-06-05 11:23:56 +01:00
akwizgran
4452dacc94 Make RendezvousCrypto package-private. 2019-06-05 11:01:28 +01:00
akwizgran
0579157010 Include protocol version in rendezvous key derivation. 2019-06-05 10:59:21 +01:00
akwizgran
3dbd0b80aa Make rendezvous constants package-private. 2019-06-05 10:58:12 +01:00
akwizgran
3863df3c1f Poll pending contact immediately when added. 2019-06-05 10:44:08 +01:00
akwizgran
08a5b8393f Add unit test for starting rendezvous poller. 2019-06-05 10:44:07 +01:00
akwizgran
92dea21c67 Run commit actions in unit tests. 2019-06-05 10:44:07 +01:00
akwizgran
82a52638cf Derive rendezvous key from static master key. 2019-06-05 10:44:07 +01:00
akwizgran
a38113e862 Add rendezvous poller. 2019-06-05 10:44:07 +01:00
akwizgran
7fd8ad65be Make RendezvousEndpoint closeable. 2019-06-05 10:44:06 +01:00
akwizgran
ce9c7cb32a Add requireNull() utility method. 2019-06-05 10:44:06 +01:00
akwizgran
5d2252ebda Add method for deriving rendezvous key. 2019-06-05 10:44:06 +01:00
akwizgran
3820d7413c Rename rendezvous handler to endpoint. 2019-06-05 10:44:06 +01:00
akwizgran
ab90e1de04 Pass incoming connection handler to plugins. 2019-06-05 10:44:05 +01:00
Torsten Grote
a650d812fa Merge branch '1571-connection-manager-pending-contacts' into 'master'
Add rendezvous connection support to connection manager

Closes #1571

See merge request briar/briar!1120
2019-06-04 14:08:05 +00:00
akwizgran
c536782e01 Remove redundant use of IO executor. 2019-06-04 14:23:47 +01:00
akwizgran
9ffd1ec2c2 Unregister connection if sending stream header fails. 2019-06-04 14:20:57 +01:00
Torsten Grote
1c56068bf1 Merge branch '1232-handshake-manager' into 'master'
Implement handshake protocol

See merge request briar/briar!1118
2019-06-04 11:49:11 +00:00
Torsten Grote
d2290e2037 Merge branch '1560-forum-sharing-integration-test' into 'master'
Fix race conditions in ForumSharingIntegrationTest

Closes #1560

See merge request briar/briar!1119
2019-06-04 11:47:49 +00:00
akwizgran
0951508af7 Define PROOF_BYTES as MAC_BYTES. 2019-06-04 12:38:21 +01:00
akwizgran
34a5b69100 Reuse TransportCrypto#isAlice(). 2019-06-04 12:21:17 +01:00
akwizgran
d939fe80bd Explicitly check length of proof of ownership. 2019-06-04 12:17:10 +01:00
akwizgran
4ea8a4732c Fix race conditions in ForumSharingIntegrationTest. 2019-06-04 11:57:39 +01:00
Torsten Grote
da67cae4ce Merge branch 'test-sync-at-higher-level' into 'master'
Test sync at a higher level

See merge request briar/briar!1116
2019-06-04 10:37:31 +00:00
akwizgran
d3c7ecdef4 Use static comparison method. 2019-06-03 18:02:19 +01:00
akwizgran
4d8e0baeb4 Rewrap a line. 2019-06-03 17:58:31 +01:00
akwizgran
0b764a01dd Use larger buffer in test connections to prevent deadlock. 2019-06-03 17:55:35 +01:00
akwizgran
f95bb9b28e Add integration test for new connection manager methods. 2019-06-03 17:55:35 +01:00
akwizgran
8f21e07840 Add rendezvous connection support to connection manager. 2019-06-03 17:52:43 +01:00
akwizgran
eed8d25120 Decouple HandshakeManager from ContactExchangeManager. 2019-06-03 17:44:38 +01:00
Torsten Grote
265a43f5ff Merge branch 'use-real-executors-in-integration-tests' into 'master'
Use BrambleCoreModule in integration tests

See merge request briar/briar!1115
2019-06-03 14:48:53 +00:00
akwizgran
89cbdc824c Add integration test for handshaking with pending contact. 2019-06-03 15:36:28 +01:00
akwizgran
4640651714 Add integration test for converting pending contacts. 2019-06-03 15:36:27 +01:00
akwizgran
af8b7f1130 Implement getHandshakeLink(). 2019-06-03 15:36:27 +01:00
akwizgran
643270e247 Add integration test for ContactExchangeManager. 2019-06-03 15:36:24 +01:00
akwizgran
24f1b7eeca Implement handshake manager. 2019-06-03 15:35:53 +01:00
akwizgran
60155f146a Add contact exchange method for pending contacts. 2019-06-03 15:35:53 +01:00
akwizgran
7c3f2c0bed Add test implementation of DuplexTransportConnection. 2019-06-03 15:35:00 +01:00
akwizgran
85a1fd2caa Convert BriarIntegrationTest to use test reader and writer. 2019-06-03 15:34:59 +01:00
akwizgran
f8d240a320 Test stream reading and writing at a higher level. 2019-06-03 15:34:59 +01:00
akwizgran
5860c723de Remove unused test module. 2019-06-03 15:34:59 +01:00
akwizgran
33d35148d8 Run briar-headless tests when running all tests. 2019-06-03 15:34:17 +01:00
akwizgran
0e55b06c0a Provide SOCKS module for headless app, remove reporting. 2019-06-03 15:34:17 +01:00
akwizgran
d964f06de1 Use default methods for easier maintenance. 2019-06-03 15:34:16 +01:00
akwizgran
100e17b242 Use BrambleCoreModule in integration tests. 2019-06-03 15:34:16 +01:00
akwizgran
7bf86d9c53 Use real executors in integration tests. 2019-06-03 15:34:16 +01:00
Torsten Grote
8fc5c21354 Merge branch '1570-derive-handshake-root-key' into 'master'
Add contact manager and key manager methods for converting a pending contact

Closes #1570

See merge request briar/briar!1114
2019-06-03 14:33:21 +00:00
akwizgran
fe83a59d2a Add comment about tag reuse. 2019-06-03 12:48:14 +01:00
akwizgran
1b8692a216 Add longer explanation of 'verified' flag. 2019-06-03 12:40:49 +01:00
akwizgran
57a70f411b Update ContactManager javadocs. 2019-05-31 11:59:00 +01:00
akwizgran
b2d2b1765a Fix pending contact flag. Hooray for unit tests. 2019-05-30 17:37:09 +01:00
akwizgran
430b530ca5 Derive handshake root key when converting pending contact. 2019-05-30 17:27:07 +01:00
akwizgran
4a2936c685 Optionally include handshake public key for new contact. 2019-05-30 16:36:25 +01:00
Torsten Grote
d3c7c54797 Merge branch '1561-wait-for-delivery-in-integration-test' into 'master'
Wait for message delivery in integration test

Closes #1561

See merge request briar/briar!1113
2019-05-30 15:25:08 +00:00
akwizgran
83dc52572d Remove keys when pending contacts are removed. 2019-05-30 16:20:57 +01:00
akwizgran
810d45d6b9 Derive handshake root key when adding a pending contact. 2019-05-30 15:48:26 +01:00
akwizgran
9b4f60088f Add methods for deriving static master and root keys. 2019-05-30 14:31:12 +01:00
akwizgran
b222107044 Add static method for comparing byte arrays. 2019-05-30 14:30:16 +01:00
akwizgran
d0495b7c00 Wait for transport properties as well as client versions. 2019-05-30 13:55:16 +01:00
akwizgran
ee874947d0 Wait for message delivery in integration test. 2019-05-30 11:51:16 +01:00
akwizgran
d38176faea Merge branch '1571-connection-manager-cleanup' into 'master'
Clean up connection manager, ready for pending contacts

See merge request briar/briar!1109
2019-05-29 15:16:35 +00:00
Torsten Grote
2a00f94e23 Merge branch '1571-connection-registry-pending-contacts' into 'master'
Add support for pending contacts to connection registry

See merge request briar/briar!1111
2019-05-28 14:36:42 +00:00
akwizgran
8bd4278ae5 Add support for pending contacts to connection registry. 2019-05-28 14:33:03 +01:00
akwizgran
829a6df567 Remove redundant assignment. 2019-05-28 14:15:47 +01:00
akwizgran
aa0c3118a0 Interrupt outgoing session on read error. 2019-05-28 10:45:55 +01:00
Torsten Grote
015f5005d0 Merge branch '1232-get-pending-contact' into 'master'
Add method to get a pending contact

See merge request briar/briar!1110
2019-05-27 17:51:59 +00:00
Torsten Grote
91c5ec6f18 Merge branch '1232-triple-dh' into 'master'
Implement triple Diffie-Hellman key agreement

See merge request briar/briar!1108
2019-05-27 17:49:05 +00:00
Torsten Grote
cd9cc375ff Merge branch '1570-convert-pending-contact' into 'master'
Add database methods for converting a pending contact

Closes #1570

See merge request briar/briar!1107
2019-05-27 17:45:26 +00:00
akwizgran
819deca93c Update javadoc. 2019-05-27 17:54:23 +01:00
akwizgran
79632908d4 Add method to get a pending contact. 2019-05-27 17:44:57 +01:00
akwizgran
f979d44c96 Update REST API docs. 2019-05-27 17:43:23 +01:00
akwizgran
44d2526997 Add triple Diffie-Hellman key agreement. 2019-05-27 15:03:58 +01:00
akwizgran
14e604e21e Add 'verified' flag to ContactAddedEvent. 2019-05-27 11:40:28 +01:00
akwizgran
677728b9ae Add database methods for converting a pending contact. 2019-05-27 11:19:21 +01:00
akwizgran
84060a57da Merge branch 'unsupported-handshake-link' into 'master'
Add error message for unsupported handshake link version

See merge request briar/briar!1091
2019-05-26 14:36:24 +00:00
Torsten Grote
4a92625a7b Merge branch 'contact-exchange-refactoring' into 'master'
Contact exchange refactoring

See merge request briar/briar!1106
2019-05-24 17:33:21 +00:00
Torsten Grote
bea526d64d [android] tweak wording for unsupported link version 2019-05-24 14:31:04 -03:00
akwizgran
717b2d176e Clean up connection manager, ready for pending contacts. 2019-05-24 18:08:06 +01:00
Torsten Grote
cff5e53d09 Merge branch 'record-reader-predicates' into 'master'
Use predicates to specify records to accept or ignore

See merge request briar/briar!1105
2019-05-24 16:16:24 +00:00
akwizgran
221687c9d7 Merge branch 'startup-fix' into 'master'
Show OpenDatabaseFragment right after signing in

See merge request briar/briar!1099
2019-05-24 15:06:41 +00:00
akwizgran
953fccba16 Update PendingContactListener to use PendingContactItem. 2019-05-24 15:57:24 +01:00
akwizgran
eca82e2888 Merge branch '1554-remove-pending-contacts' into 'master'
Allow pending contacts to be removed at any time

Closes #1554

See merge request briar/briar!1098
2019-05-24 14:49:48 +00:00
Torsten Grote
ad93100e99 Merge branch '35-transaction-manager' into 'master'
Extract TransactionManager from DatabaseComponent

See merge request briar/briar!1104
2019-05-24 13:20:35 +00:00
akwizgran
d80c77f466 Try to close connection if contact exchange fails. 2019-05-24 13:14:53 +01:00
akwizgran
a6376af7c2 Extract TransactionManager from DatabaseComponent. 2019-05-24 12:44:23 +01:00
akwizgran
f1e5c2dd66 Return a contact, encapsulate contact exchange crypto. 2019-05-24 11:42:30 +01:00
akwizgran
5be0e928c4 Replace events with return value and exceptions. 2019-05-24 10:53:43 +01:00
akwizgran
bcc899eebf Attach information to ContactExistsException. 2019-05-24 10:53:43 +01:00
akwizgran
9ea91cbb3e Move background work into view model. 2019-05-24 10:51:38 +01:00
akwizgran
da54712ae1 Refactor ContactExchangeTask into reusable manager. 2019-05-24 10:51:38 +01:00
akwizgran
f459115b19 Run contact exchange task on IO executor. 2019-05-24 10:51:38 +01:00
akwizgran
cc49648e37 Use predicates to specify records to accept or ignore. 2019-05-24 10:51:27 +01:00
Torsten Grote
9ce71088e2 Merge branch '1564-rendezvous-plugin-api' into 'master'
Add rendezvous API to transport plugins

See merge request briar/briar!1103
2019-05-22 16:58:31 +00:00
Torsten Grote
0f3e6d9736 Merge branch '1567-remove-pending-contact-state-from-db' into 'master'
Remove pending contact state from DB

See merge request briar/briar!1102
2019-05-22 16:56:59 +00:00
akwizgran
de97cce119 Address review comments. 2019-05-22 17:46:17 +01:00
akwizgran
a82d20564a Update names in RendezvousModule. 2019-05-22 16:13:49 +01:00
akwizgran
967f068637 Add initial API for rendezvous plugins. 2019-05-22 15:26:28 +01:00
akwizgran
90c33133c3 Code cleanup. 2019-05-22 15:22:35 +01:00
akwizgran
01ef367864 Remove pending contact state from the database. 2019-05-22 11:25:05 +01:00
Torsten Grote
da5d442c91 Merge branch '1232-poller-refactoring' into 'master'
Pass a connection handler to plugins when polling

See merge request briar/briar!1101
2019-05-21 13:33:53 +00:00
akwizgran
ead7570ec5 Add javadoc. 2019-05-21 14:27:27 +01:00
akwizgran
43b2f9da1c Static import. 2019-05-17 15:46:37 +01:00
akwizgran
668433dd62 Pass a connection handler to plugins when polling. 2019-05-17 14:07:54 +01:00
akwizgran
a0772852de Decouple poller from plugin manager. 2019-05-17 13:59:30 +01:00
Torsten Grote
f0bd18c4d6 [android] show OpenDatabaseFragment right after signing in 2019-05-16 15:22:56 -03:00
akwizgran
99000d8eab Merge branch 'repro-check-on-success' into 'master'
Only check reproducibility when normal tests pass

See merge request briar/briar!1100
2019-05-16 16:58:33 +00:00
Torsten Grote
0b48afb692 Only check reproducibility when normal tests pass 2019-05-16 13:48:25 -03:00
Torsten Grote
299ad07222 [android] Allow pending contacts to be removed at any time 2019-05-16 12:54:42 -03:00
Torsten Grote
19ec98b607 [android] use exception instead of string resource in LiveResult 2019-05-13 13:21:58 -03:00
Torsten Grote
ec7fdb3f72 [android] Pass the entire link to the backend, so newer version have a chance to arrive 2019-05-13 12:00:18 -03:00
Torsten Grote
be8aba347d [android] Add error message for unsupported handshake link version 2019-05-13 12:00:18 -03:00
997 changed files with 29528 additions and 11481 deletions

View File

@@ -1,6 +1,11 @@
image: briar/ci-image-android:latest image: briar/ci-image-android:latest
stages:
- test
- check_reproducibility
test: test:
stage: test
before_script: before_script:
- set -e - set -e
- export GRADLE_USER_HOME=$PWD/.gradle - export GRADLE_USER_HOME=$PWD/.gradle
@@ -12,7 +17,7 @@ test:
script: script:
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom animalSnifferMain animalSnifferTest
- ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom test - ./gradlew --no-daemon -Djava.security.egd=file:/dev/urandom check compileOfficialDebugAndroidTestSources compileScreenshotDebugAndroidTestSources
after_script: after_script:
# these file change every time but should not be cached # these file change every time but should not be cached
@@ -21,6 +26,7 @@ test:
test_reproducible: test_reproducible:
stage: check_reproducibility
script: script:
- "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline" - "curl -X POST -F token=${RELEASE_CHECK_TOKEN} -F ref=master -F variables[RELEASE_TAG]=${CI_COMMIT_REF_NAME} https://code.briarproject.org/api/v4/projects/61/trigger/pipeline"
only: only:

View File

@@ -1,16 +1,10 @@
<component name="ProjectCodeStyleConfiguration"> <component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173"> <code_scheme name="Project" version="173">
<option name="RIGHT_MARGIN" value="100" />
<AndroidXmlCodeStyleSettings> <AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" /> <option name="ARRANGEMENT_SETTINGS_MIGRATED_TO_191" value="true" />
</AndroidXmlCodeStyleSettings> </AndroidXmlCodeStyleSettings>
<JavaCodeStyleSettings> <JavaCodeStyleSettings>
<option name="ANNOTATION_PARAMETER_WRAP" value="1" /> <option name="ANNOTATION_PARAMETER_WRAP" value="1" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE"> <option name="IMPORT_LAYOUT_TABLE">
<value> <value>
<package name="android" withSubpackages="true" static="false" /> <package name="android" withSubpackages="true" static="false" />
@@ -77,7 +71,6 @@
</indentOptions> </indentOptions>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="XML"> <codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="true" /> <option name="USE_TAB_CHARACTER" value="true" />
@@ -90,7 +83,8 @@
<match> <match>
<AND> <AND>
<NAME>xmlns:android</NAME> <NAME>xmlns:android</NAME>
<XML_NAMESPACE>Namespace:</XML_NAMESPACE> <XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
</rule> </rule>
@@ -100,7 +94,8 @@
<match> <match>
<AND> <AND>
<NAME>xmlns:.*</NAME> <NAME>xmlns:.*</NAME>
<XML_NAMESPACE>Namespace:</XML_NAMESPACE> <XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
<order>BY_NAME</order> <order>BY_NAME</order>
@@ -111,6 +106,7 @@
<match> <match>
<AND> <AND>
<NAME>.*:id</NAME> <NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@@ -121,6 +117,7 @@
<match> <match>
<AND> <AND>
<NAME>.*:name</NAME> <NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@@ -131,6 +128,7 @@
<match> <match>
<AND> <AND>
<NAME>name</NAME> <NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@@ -141,6 +139,7 @@
<match> <match>
<AND> <AND>
<NAME>style</NAME> <NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@@ -151,6 +150,7 @@
<match> <match>
<AND> <AND>
<NAME>.*</NAME> <NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE> <XML_NAMESPACE>^$</XML_NAMESPACE>
</AND> </AND>
</match> </match>
@@ -161,64 +161,12 @@
<rule> <rule>
<match> <match>
<AND> <AND>
<NAME>.*:layout_width</NAME> <NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE> <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND> </AND>
</match> </match>
</rule> <order>ANDROID_ATTRIBUTE_ORDER</order>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule> </rule>
</section> </section>
<section> <section>
@@ -226,6 +174,7 @@
<match> <match>
<AND> <AND>
<NAME>.*</NAME> <NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE> <XML_NAMESPACE>.*</XML_NAMESPACE>
</AND> </AND>
</match> </match>

View File

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

View File

@@ -1,30 +1,20 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests" type="AndroidJUnit" factoryName="Android JUnit"> <configuration default="false" name="All tests" type="AndroidJUnit" factoryName="Android JUnit">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<module name="briar-android" /> <module name="briar-android" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
<option name="ALTERNATIVE_JRE_PATH" />
<option name="PACKAGE_NAME" value="" /> <option name="PACKAGE_NAME" value="" />
<option name="MAIN_CLASS_NAME" value="" /> <option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" /> <option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" /> <option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" value="-ea" />
<option name="PARAMETERS" value="" /> <option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/briar-android" /> <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-android" />
<option name="ENV_VARIABLES" /> <method v="2">
<option name="PASS_PARENT_ENVS" value="true" /> <option name="Android.Gradle.BeforeRunTask" enabled="true" />
<option name="TEST_SEARCH_SCOPE">
<value defaultName="singleModule" />
</option>
<envs />
<patterns />
<method>
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="AndroidJUnit" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-api" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="AndroidJUnit" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-android" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in bramble-java" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-core" run_configuration_type="AndroidJUnit" />
<option name="RunConfigurationTask" enabled="true" run_configuration_name="All in briar-headless" run_configuration_type="AndroidJUnit" /> <option name="RunConfigurationTask" enabled="true" run_configuration_name="All tests in briar-headless" run_configuration_type="AndroidJUnit" />
</method> </method>
</configuration> </configuration>
</component> </component>

View File

@@ -0,0 +1,15 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="All tests in briar-headless" type="AndroidJUnit" factoryName="Android JUnit">
<module name="briar-headless" />
<option name="PACKAGE_NAME" value="org.briarproject.briar.headless" />
<option name="MAIN_CLASS_NAME" value="" />
<option name="METHOD_NAME" value="" />
<option name="TEST_OBJECT" value="package" />
<option name="VM_PARAMETERS" />
<option name="PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/briar-headless" />
<method v="2">
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
</method>
</configuration>
</component>

View File

@@ -5,23 +5,31 @@ apply plugin: 'witness'
apply from: 'witness.gradle' apply from: 'witness.gradle'
android { android {
compileSdkVersion 28 compileSdkVersion 29
buildToolsVersion '28.0.3' buildToolsVersion '29.0.2'
defaultConfig { defaultConfig {
minSdkVersion 14 minSdkVersion 16
targetSdkVersion 26 targetSdkVersion 28
versionCode 10107 versionCode 10207
versionName "1.1.7" versionName "1.2.7"
consumerProguardFiles 'proguard-rules.txt' consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
} }
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
lintOptions {
// FIXME
warning "LintError"
warning "InvalidPackage"
warning "MissingPermission"
warning "InlinedApi", "ObsoleteSdkInt", "Override", "NewApi", "UnusedAttribute"
}
} }
configurations { configurations {
@@ -30,10 +38,10 @@ configurations {
dependencies { dependencies {
implementation project(path: ':bramble-core', configuration: 'default') implementation project(path: ':bramble-core', configuration: 'default')
tor 'org.briarproject:tor-android:0.3.5.8@zip' tor 'org.briarproject:tor-android:0.3.5.10@zip'
tor 'org.briarproject:obfs4proxy-android:0.0.9@zip' tor 'org.briarproject:obfs4proxy-android:0.0.11-2@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.22.1' annotationProcessor 'com.google.dagger:dagger-compiler:2.24'
compileOnly 'javax.annotation:jsr250-api:1.0' compileOnly 'javax.annotation:jsr250-api:1.0'
@@ -59,6 +67,8 @@ task unpackTorBinaries {
copy { copy {
from configurations.tor.collect { zipTree(it) } from configurations.tor.collect { zipTree(it) }
into torBinariesDir into torBinariesDir
// TODO: Remove after next Tor upgrade, which won't include non-PIE binaries
include 'geoip.zip', '*_pie.zip'
} }
} }
dependsOn cleanTorBinaries dependsOn cleanTorBinaries

View File

@@ -2,10 +2,23 @@ package org.briarproject.bramble;
import org.briarproject.bramble.battery.AndroidBatteryModule; import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.network.AndroidNetworkModule; import org.briarproject.bramble.network.AndroidNetworkModule;
import org.briarproject.bramble.reporting.ReportingModule;
public interface BrambleAndroidEagerSingletons { public interface BrambleAndroidEagerSingletons {
void inject(AndroidBatteryModule.EagerSingletons init); void inject(AndroidBatteryModule.EagerSingletons init);
void inject(AndroidNetworkModule.EagerSingletons init); void inject(AndroidNetworkModule.EagerSingletons init);
void inject(ReportingModule.EagerSingletons init);
class Helper {
public static void injectEagerSingletons(
BrambleAndroidEagerSingletons c) {
c.inject(new AndroidBatteryModule.EagerSingletons());
c.inject(new AndroidNetworkModule.EagerSingletons());
c.inject(new ReportingModule.EagerSingletons());
}
}
} }

View File

@@ -3,6 +3,8 @@ package org.briarproject.bramble;
import org.briarproject.bramble.battery.AndroidBatteryModule; import org.briarproject.bramble.battery.AndroidBatteryModule;
import org.briarproject.bramble.network.AndroidNetworkModule; import org.briarproject.bramble.network.AndroidNetworkModule;
import org.briarproject.bramble.plugin.tor.CircumventionModule; import org.briarproject.bramble.plugin.tor.CircumventionModule;
import org.briarproject.bramble.reporting.ReportingModule;
import org.briarproject.bramble.socks.SocksModule;
import org.briarproject.bramble.system.AndroidSystemModule; import org.briarproject.bramble.system.AndroidSystemModule;
import dagger.Module; import dagger.Module;
@@ -11,12 +13,9 @@ import dagger.Module;
AndroidBatteryModule.class, AndroidBatteryModule.class,
AndroidNetworkModule.class, AndroidNetworkModule.class,
AndroidSystemModule.class, AndroidSystemModule.class,
CircumventionModule.class CircumventionModule.class,
ReportingModule.class,
SocksModule.class
}) })
public class BrambleAndroidModule { public class BrambleAndroidModule {
public static void initEagerSingletons(BrambleAndroidEagerSingletons c) {
c.inject(new AndroidBatteryModule.EagerSingletons());
c.inject(new AndroidNetworkModule.EagerSingletons());
}
} }

View File

@@ -12,13 +12,16 @@ import org.briarproject.bramble.api.identity.IdentityManager;
import java.io.File; import java.io.File;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.inject.Inject; import javax.inject.Inject;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir; import static org.briarproject.bramble.util.IoUtils.deleteFileOrDir;
import static org.briarproject.bramble.util.LogUtils.logFileOrDir; import static org.briarproject.bramble.util.LogUtils.logFileOrDir;
@@ -29,7 +32,11 @@ class AndroidAccountManager extends AccountManagerImpl
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(AndroidAccountManager.class.getName()); Logger.getLogger(AndroidAccountManager.class.getName());
private static final String PREF_DB_KEY = "key"; /**
* Directories that shouldn't be deleted when deleting the user's account.
*/
private static final List<String> PROTECTED_DIR_NAMES =
asList("cache", "code_cache", "lib", "shared_prefs");
protected final Context appContext; protected final Context appContext;
private final SharedPreferences prefs; private final SharedPreferences prefs;
@@ -53,36 +60,6 @@ class AndroidAccountManager extends AccountManagerImpl
return exists; return exists;
} }
// Locking: stateChangeLock
@Override
@Nullable
protected String loadEncryptedDatabaseKey() {
String key = getDatabaseKeyFromPreferences();
if (key == null) key = super.loadEncryptedDatabaseKey();
else migrateDatabaseKeyToFile(key);
return key;
}
// Locking: stateChangeLock
@Nullable
private String getDatabaseKeyFromPreferences() {
String key = prefs.getString(PREF_DB_KEY, null);
if (key == null) LOG.info("No database key in preferences");
else LOG.info("Found database key in preferences");
return key;
}
// Locking: stateChangeLock
private void migrateDatabaseKeyToFile(String key) {
if (storeEncryptedDatabaseKey(key)) {
if (prefs.edit().remove(PREF_DB_KEY).commit())
LOG.info("Database key migrated to file");
else LOG.warning("Database key not removed from preferences");
} else {
LOG.warning("Database key not migrated to file");
}
}
@Override @Override
public void deleteAccount() { public void deleteAccount() {
synchronized (stateChangeLock) { synchronized (stateChangeLock) {
@@ -105,14 +82,14 @@ class AndroidAccountManager extends AccountManagerImpl
return PreferenceManager.getDefaultSharedPreferences(appContext); return PreferenceManager.getDefaultSharedPreferences(appContext);
} }
// Locking: stateChangeLock @GuardedBy("stateChangeLock")
private void deleteAppData(SharedPreferences... clear) { private void deleteAppData(SharedPreferences... clear) {
// Clear and commit shared preferences // Clear and commit shared preferences
for (SharedPreferences prefs : clear) { for (SharedPreferences prefs : clear) {
if (!prefs.edit().clear().commit()) if (!prefs.edit().clear().commit())
LOG.warning("Could not clear shared preferences"); LOG.warning("Could not clear shared preferences");
} }
// Delete files, except lib and shared_prefs directories // Delete files, except protected directories
Set<File> files = new HashSet<>(); Set<File> files = new HashSet<>();
File dataDir = getDataDir(); File dataDir = getDataDir();
@Nullable @Nullable
@@ -121,14 +98,12 @@ class AndroidAccountManager extends AccountManagerImpl
LOG.warning("Could not list files in app data dir"); LOG.warning("Could not list files in app data dir");
} else { } else {
for (File file : fileArray) { for (File file : fileArray) {
String name = file.getName(); if (!PROTECTED_DIR_NAMES.contains(file.getName())) {
if (!name.equals("lib") && !name.equals("shared_prefs")) {
files.add(file); files.add(file);
} }
} }
} }
files.add(appContext.getFilesDir()); files.add(appContext.getFilesDir());
files.add(appContext.getCacheDir());
addIfNotNull(files, appContext.getExternalCacheDir()); addIfNotNull(files, appContext.getExternalCacheDir());
if (SDK_INT >= 19) { if (SDK_INT >= 19) {
for (File file : appContext.getExternalCacheDirs()) { for (File file : appContext.getExternalCacheDirs()) {
@@ -140,12 +115,16 @@ class AndroidAccountManager extends AccountManagerImpl
addIfNotNull(files, file); addIfNotNull(files, file);
} }
} }
// Clear the cache directory but don't delete it
File cacheDir = appContext.getCacheDir();
File[] children = cacheDir.listFiles();
if (children != null) files.addAll(asList(children));
for (File file : files) { for (File file : files) {
if (LOG.isLoggable(INFO)) {
LOG.info("Deleting " + file.getAbsolutePath());
}
deleteFileOrDir(file); deleteFileOrDir(file);
} }
// Recreate the cache dir as some OpenGL drivers expect it to exist
if (!new File(dataDir, "cache").mkdirs())
LOG.warning("Could not recreate cache dir");
} }
private File getDataDir() { private File getDataDir() {

View File

@@ -6,6 +6,8 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
@@ -32,11 +34,15 @@ import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON; import static android.content.Intent.ACTION_SCREEN_ON;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.wifi.p2p.WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED; import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -51,7 +57,8 @@ class AndroidNetworkManager implements NetworkManager, Service {
private final ScheduledExecutorService scheduler; private final ScheduledExecutorService scheduler;
private final EventBus eventBus; private final EventBus eventBus;
private final Context appContext; private final Application app;
private final ConnectivityManager connectivityManager;
private final AtomicReference<Future<?>> connectivityCheck = private final AtomicReference<Future<?>> connectivityCheck =
new AtomicReference<>(); new AtomicReference<>();
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
@@ -63,7 +70,9 @@ class AndroidNetworkManager implements NetworkManager, Service {
EventBus eventBus, Application app) { EventBus eventBus, Application app) {
this.scheduler = scheduler; this.scheduler = scheduler;
this.eventBus = eventBus; this.eventBus = eventBus;
this.appContext = app.getApplicationContext(); this.app = app;
connectivityManager = (ConnectivityManager)
requireNonNull(app.getSystemService(CONNECTIVITY_SERVICE));
} }
@Override @Override
@@ -76,26 +85,35 @@ class AndroidNetworkManager implements NetworkManager, Service {
filter.addAction(ACTION_SCREEN_ON); filter.addAction(ACTION_SCREEN_ON);
filter.addAction(ACTION_SCREEN_OFF); filter.addAction(ACTION_SCREEN_OFF);
filter.addAction(WIFI_AP_STATE_CHANGED_ACTION); filter.addAction(WIFI_AP_STATE_CHANGED_ACTION);
filter.addAction(WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED); if (SDK_INT >= 23) filter.addAction(ACTION_DEVICE_IDLE_MODE_CHANGED);
appContext.registerReceiver(networkStateReceiver, filter); app.registerReceiver(networkStateReceiver, filter);
} }
@Override @Override
public void stopService() { public void stopService() {
if (networkStateReceiver != null) if (networkStateReceiver != null) {
appContext.unregisterReceiver(networkStateReceiver); app.unregisterReceiver(networkStateReceiver);
}
} }
@Override @Override
public NetworkStatus getNetworkStatus() { public NetworkStatus getNetworkStatus() {
ConnectivityManager cm = (ConnectivityManager) if (SDK_INT >= 23) {
appContext.getSystemService(CONNECTIVITY_SERVICE); Network net = connectivityManager.getActiveNetwork();
if (cm == null) throw new AssertionError(); if (net == null) return new NetworkStatus(false, false);
NetworkInfo net = cm.getActiveNetworkInfo(); NetworkCapabilities caps =
boolean connected = net != null && net.isConnected(); connectivityManager.getNetworkCapabilities(net);
boolean wifi = connected && net.getType() == TYPE_WIFI; if (caps == null) return new NetworkStatus(false, false);
return new NetworkStatus(connected, wifi); boolean connected = caps.hasCapability(NET_CAPABILITY_INTERNET);
boolean wifi = caps.hasTransport(TRANSPORT_WIFI);
return new NetworkStatus(connected, wifi);
} else {
NetworkInfo net = connectivityManager.getActiveNetworkInfo();
boolean connected = net != null && net.isConnected();
boolean wifi = connected && net.getType() == TYPE_WIFI;
return new NetworkStatus(connected, wifi);
}
} }
private void updateConnectionStatus() { private void updateConnectionStatus() {
@@ -136,7 +154,8 @@ class AndroidNetworkManager implements NetworkManager, Service {
} }
private boolean isApEvent(@Nullable String action) { private boolean isApEvent(@Nullable String action) {
return WIFI_AP_STATE_CHANGED_ACTION.equals(action); return WIFI_AP_STATE_CHANGED_ACTION.equals(action) ||
WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action);
} }
} }
} }

View File

@@ -9,11 +9,12 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import org.briarproject.bramble.api.io.TimeoutMonitor;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.PluginException; import org.briarproject.bramble.api.plugin.PluginException;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
@@ -24,13 +25,13 @@ import java.io.IOException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -47,10 +48,14 @@ import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE;
import static android.bluetooth.BluetoothAdapter.STATE_OFF; import static android.bluetooth.BluetoothAdapter.STATE_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_ON; import static android.bluetooth.BluetoothAdapter.STATE_ON;
import static android.bluetooth.BluetoothDevice.ACTION_FOUND; import static android.bluetooth.BluetoothDevice.ACTION_FOUND;
import static android.bluetooth.BluetoothDevice.DEVICE_TYPE_LE;
import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE; import static android.bluetooth.BluetoothDevice.EXTRA_DEVICE;
import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.shuffle;
import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.logging.Level.INFO; import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING; import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress; import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@@ -58,10 +63,11 @@ import static org.briarproject.bramble.util.PrivacyUtils.scrubMacAddress;
class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> { class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(AndroidBluetoothPlugin.class.getName()); getLogger(AndroidBluetoothPlugin.class.getName());
private static final int MAX_DISCOVERY_MS = 10_000; private static final int MAX_DISCOVERY_MS = 10_000;
private final ScheduledExecutorService scheduler;
private final AndroidExecutor androidExecutor; private final AndroidExecutor androidExecutor;
private final Context appContext; private final Context appContext;
private final Clock clock; private final Clock clock;
@@ -73,11 +79,14 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
private volatile BluetoothAdapter adapter = null; private volatile BluetoothAdapter adapter = null;
AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter, AndroidBluetoothPlugin(BluetoothConnectionLimiter connectionLimiter,
Executor ioExecutor, AndroidExecutor androidExecutor, TimeoutMonitor timeoutMonitor, Executor ioExecutor,
Context appContext, SecureRandom secureRandom, Clock clock, SecureRandom secureRandom, ScheduledExecutorService scheduler,
Backoff backoff, DuplexPluginCallback callback, int maxLatency) { AndroidExecutor androidExecutor, Context appContext, Clock clock,
super(connectionLimiter, ioExecutor, secureRandom, backoff, callback, Backoff backoff, PluginCallback callback, int maxLatency,
maxLatency); int maxIdleTime) {
super(connectionLimiter, timeoutMonitor, ioExecutor, secureRandom,
backoff, callback, maxLatency, maxIdleTime);
this.scheduler = scheduler;
this.androidExecutor = androidExecutor; this.androidExecutor = androidExecutor;
this.appContext = appContext; this.appContext = appContext;
this.clock = clock; this.clock = clock;
@@ -145,6 +154,12 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
wasEnabledByUs = true; wasEnabledByUs = true;
} }
@Override
void onAdapterDisabled() {
super.onAdapterDisabled();
wasEnabledByUs = false;
}
@Override @Override
@Nullable @Nullable
String getBluetoothAddress() { String getBluetoothAddress() {
@@ -169,9 +184,10 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
return wrapSocket(ss.accept()); return wrapSocket(ss.accept());
} }
private DuplexTransportConnection wrapSocket(BluetoothSocket s) { private DuplexTransportConnection wrapSocket(BluetoothSocket s)
return new AndroidBluetoothTransportConnection(this, throws IOException {
connectionLimiter, s); return new AndroidBluetoothTransportConnection(this, connectionLimiter,
timeoutMonitor, appContext, scheduler, s);
} }
@Override @Override
@@ -239,11 +255,15 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
break; break;
} else if (ACTION_FOUND.equals(action)) { } else if (ACTION_FOUND.equals(action)) {
BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE); BluetoothDevice d = i.getParcelableExtra(EXTRA_DEVICE);
String address = d.getAddress(); // Ignore Bluetooth LE devices
if (LOG.isLoggable(INFO)) if (SDK_INT < 18 || d.getType() != DEVICE_TYPE_LE) {
LOG.info("Discovered " + scrubMacAddress(address)); String address = d.getAddress();
if (!addresses.contains(address)) if (LOG.isLoggable(INFO))
addresses.add(address); LOG.info("Discovered " +
scrubMacAddress(address));
if (!addresses.contains(address))
addresses.add(address);
}
} }
now = clock.currentTimeMillis(); now = clock.currentTimeMillis();
} }
@@ -259,7 +279,7 @@ class AndroidBluetoothPlugin extends BluetoothPlugin<BluetoothServerSocket> {
appContext.unregisterReceiver(receiver); appContext.unregisterReceiver(receiver);
} }
// Shuffle the addresses so we don't always try the same one first // Shuffle the addresses so we don't always try the same one first
Collections.shuffle(addresses); shuffle(addresses);
return addresses; return addresses;
} }

View File

@@ -3,18 +3,20 @@ package org.briarproject.bramble.plugin.bluetooth;
import android.content.Context; import android.content.Context;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.io.TimeoutMonitor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
@@ -25,28 +27,34 @@ import static org.briarproject.bramble.api.plugin.BluetoothConstants.ID;
public class AndroidBluetoothPluginFactory implements DuplexPluginFactory { public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_LATENCY = 30 * 1000; // 30 seconds
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
private final ScheduledExecutorService scheduler;
private final AndroidExecutor androidExecutor; private final AndroidExecutor androidExecutor;
private final Context appContext; private final Context appContext;
private final SecureRandom secureRandom; private final SecureRandom secureRandom;
private final EventBus eventBus; private final EventBus eventBus;
private final Clock clock; private final Clock clock;
private final TimeoutMonitor timeoutMonitor;
private final BackoffFactory backoffFactory; private final BackoffFactory backoffFactory;
public AndroidBluetoothPluginFactory(Executor ioExecutor, public AndroidBluetoothPluginFactory(Executor ioExecutor,
ScheduledExecutorService scheduler,
AndroidExecutor androidExecutor, Context appContext, AndroidExecutor androidExecutor, Context appContext,
SecureRandom secureRandom, EventBus eventBus, Clock clock, SecureRandom secureRandom, EventBus eventBus, Clock clock,
BackoffFactory backoffFactory) { TimeoutMonitor timeoutMonitor, BackoffFactory backoffFactory) {
this.ioExecutor = ioExecutor; this.ioExecutor = ioExecutor;
this.scheduler = scheduler;
this.androidExecutor = androidExecutor; this.androidExecutor = androidExecutor;
this.appContext = appContext; this.appContext = appContext;
this.secureRandom = secureRandom; this.secureRandom = secureRandom;
this.eventBus = eventBus; this.eventBus = eventBus;
this.clock = clock; this.clock = clock;
this.timeoutMonitor = timeoutMonitor;
this.backoffFactory = backoffFactory; this.backoffFactory = backoffFactory;
} }
@@ -61,14 +69,15 @@ public class AndroidBluetoothPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
BluetoothConnectionLimiter connectionLimiter = BluetoothConnectionLimiter connectionLimiter =
new BluetoothConnectionLimiterImpl(); new BluetoothConnectionLimiterImpl(eventBus);
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin( AndroidBluetoothPlugin plugin = new AndroidBluetoothPlugin(
connectionLimiter, ioExecutor, androidExecutor, appContext, connectionLimiter, timeoutMonitor, ioExecutor, secureRandom,
secureRandom, clock, backoff, callback, MAX_LATENCY); scheduler, androidExecutor, appContext, clock, backoff,
callback, MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -1,33 +1,60 @@
package org.briarproject.bramble.plugin.bluetooth; package org.briarproject.bramble.plugin.bluetooth;
import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.os.PowerManager;
import org.briarproject.bramble.api.io.TimeoutMonitor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection; import org.briarproject.bramble.api.plugin.duplex.AbstractDuplexTransportConnection;
import org.briarproject.bramble.util.RenewableWakeLock;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.concurrent.ScheduledExecutorService;
import static android.content.Context.POWER_SERVICE;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MINUTES;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
import static org.briarproject.bramble.api.plugin.BluetoothConstants.PROP_ADDRESS;
import static org.briarproject.bramble.util.AndroidUtils.getWakeLockTag;
import static org.briarproject.bramble.util.AndroidUtils.isValidBluetoothAddress;
@NotNullByDefault @NotNullByDefault
class AndroidBluetoothTransportConnection class AndroidBluetoothTransportConnection
extends AbstractDuplexTransportConnection { extends AbstractDuplexTransportConnection {
private final BluetoothConnectionLimiter connectionManager; private final BluetoothConnectionLimiter connectionLimiter;
private final RenewableWakeLock wakeLock;
private final BluetoothSocket socket; private final BluetoothSocket socket;
private final InputStream in;
AndroidBluetoothTransportConnection(Plugin plugin, AndroidBluetoothTransportConnection(Plugin plugin,
BluetoothConnectionLimiter connectionManager, BluetoothConnectionLimiter connectionLimiter,
BluetoothSocket socket) { TimeoutMonitor timeoutMonitor, Context appContext,
ScheduledExecutorService scheduler, BluetoothSocket socket)
throws IOException {
super(plugin); super(plugin);
this.connectionManager = connectionManager; this.connectionLimiter = connectionLimiter;
this.socket = socket; this.socket = socket;
in = timeoutMonitor.createTimeoutInputStream(
socket.getInputStream(), plugin.getMaxIdleTime() * 2);
PowerManager powerManager = (PowerManager)
requireNonNull(appContext.getSystemService(POWER_SERVICE));
String tag = getWakeLockTag(appContext);
wakeLock = new RenewableWakeLock(powerManager, scheduler,
PARTIAL_WAKE_LOCK, tag, 1, MINUTES);
wakeLock.acquire();
String address = socket.getRemoteDevice().getAddress();
if (isValidBluetoothAddress(address)) remote.put(PROP_ADDRESS, address);
} }
@Override @Override
protected InputStream getInputStream() throws IOException { protected InputStream getInputStream() {
return socket.getInputStream(); return in;
} }
@Override @Override
@@ -40,7 +67,8 @@ class AndroidBluetoothTransportConnection
try { try {
socket.close(); socket.close();
} finally { } finally {
connectionManager.connectionClosed(this); wakeLock.release();
connectionLimiter.connectionClosed(this);
} }
} }
} }

View File

@@ -1,25 +1,32 @@
package org.briarproject.bramble.plugin.tcp; package org.briarproject.bramble.plugin.tcp;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network; import android.net.Network;
import android.net.NetworkInfo; import android.net.NetworkCapabilities;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import org.briarproject.bramble.PoliteExecutor; import org.briarproject.bramble.PoliteExecutor;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.network.event.NetworkStatusEvent; import org.briarproject.bramble.api.network.event.NetworkStatusEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.settings.Settings;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.net.Socket; import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Collection; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -28,29 +35,23 @@ import javax.net.SocketFactory;
import static android.content.Context.CONNECTIVITY_SERVICE; import static android.content.Context.CONNECTIVITY_SERVICE;
import static android.content.Context.WIFI_SERVICE; import static android.content.Context.WIFI_SERVICE;
import static android.net.ConnectivityManager.TYPE_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static java.util.Collections.list;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE;
import static org.briarproject.bramble.api.plugin.Plugin.State.INACTIVE;
import static org.briarproject.bramble.util.IoUtils.tryToClose;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault @NotNullByDefault
class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener { class AndroidLanTcpPlugin extends LanTcpPlugin {
private static final byte[] WIFI_AP_ADDRESS_BYTES =
{(byte) 192, (byte) 168, 43, 1};
private static final InetAddress WIFI_AP_ADDRESS;
private static final Logger LOG = private static final Logger LOG =
Logger.getLogger(AndroidLanTcpPlugin.class.getName()); getLogger(AndroidLanTcpPlugin.class.getName());
static {
try {
WIFI_AP_ADDRESS = InetAddress.getByAddress(WIFI_AP_ADDRESS_BYTES);
} catch (UnknownHostException e) {
// Should only be thrown if the address has an illegal length
throw new AssertionError(e);
}
}
private final Executor connectionStatusExecutor; private final Executor connectionStatusExecutor;
private final ConnectivityManager connectivityManager; private final ConnectivityManager connectivityManager;
@@ -60,9 +61,10 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private volatile SocketFactory socketFactory; private volatile SocketFactory socketFactory;
AndroidLanTcpPlugin(Executor ioExecutor, Context appContext, AndroidLanTcpPlugin(Executor ioExecutor, Context appContext,
Backoff backoff, DuplexPluginCallback callback, int maxLatency, Backoff backoff, PluginCallback callback, int maxLatency,
int maxIdleTime) { int maxIdleTime, int connectionTimeout) {
super(ioExecutor, backoff, callback, maxLatency, maxIdleTime); super(ioExecutor, backoff, callback, maxLatency, maxIdleTime,
connectionTimeout);
// Don't execute more than one connection status check at a time // Don't execute more than one connection status check at a time
connectionStatusExecutor = connectionStatusExecutor =
new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1); new PoliteExecutor("AndroidLanTcpPlugin", ioExecutor, 1);
@@ -78,34 +80,137 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
@Override @Override
public void start() { public void start() {
if (used.getAndSet(true)) throw new IllegalStateException(); if (used.getAndSet(true)) throw new IllegalStateException();
running = true; initialisePortProperty();
Settings settings = callback.getSettings();
state.setStarted(settings.getBoolean(PREF_PLUGIN_ENABLE, false));
updateConnectionStatus(); updateConnectionStatus();
} }
@Override
public void stop() {
running = false;
tryToClose(socket);
}
@Override @Override
protected Socket createSocket() throws IOException { protected Socket createSocket() throws IOException {
return socketFactory.createSocket(); return socketFactory.createSocket();
} }
@Override @Override
protected Collection<InetAddress> getLocalIpAddresses() { protected List<InetAddress> getUsableLocalInetAddresses(boolean ipv4) {
// If the device doesn't have wifi, don't open any sockets InetAddress addr = getWifiAddress(ipv4);
if (wifiManager == null) return emptyList(); return addr == null ? emptyList() : singletonList(addr);
// If we're connected to a wifi network, use that network }
@Nullable
private InetAddress getWifiAddress(boolean ipv4) {
Pair<InetAddress, Boolean> wifi = getWifiIpv4Address();
if (ipv4) return wifi == null ? null : wifi.getFirst();
// If there's no wifi IPv4 address, we might be a client on an
// IPv6-only wifi network. We can only detect this on API 21+
if (wifi == null) {
return SDK_INT >= 21 ? getWifiClientIpv6Address() : null;
}
// Use the wifi IPv4 address to determine which interface's IPv6
// address we should return (if the interface has a suitable address)
return getIpv6AddressForInterface(wifi.getFirst());
}
/**
* Returns a {@link Pair} where the first element is the IPv4 address of
* the wifi interface and the second element is true if this device is
* providing an access point, or false if this device is a client. Returns
* null if this device isn't connected to wifi as an access point or client.
*/
@Nullable
private Pair<InetAddress, Boolean> getWifiIpv4Address() {
if (wifiManager == null) return null;
// If we're connected to a wifi network, return its address
WifiInfo info = wifiManager.getConnectionInfo(); WifiInfo info = wifiManager.getConnectionInfo();
if (info != null && info.getIpAddress() != 0) if (info != null && info.getIpAddress() != 0) {
return singletonList(intToInetAddress(info.getIpAddress())); return new Pair<>(intToInetAddress(info.getIpAddress()), false);
// If we're running an access point, return its address }
if (super.getLocalIpAddresses().contains(WIFI_AP_ADDRESS)) List<InterfaceAddress> ifAddrs = getLocalInterfaceAddresses();
return singletonList(WIFI_AP_ADDRESS); // If we're providing a normal access point, return its address
// No suitable addresses for (InterfaceAddress ifAddr : ifAddrs) {
return emptyList(); if (isAndroidWifiApAddress(ifAddr)) {
return new Pair<>(ifAddr.getAddress(), true);
}
}
// If we're providing a wifi direct access point, return its address
for (InterfaceAddress ifAddr : ifAddrs) {
if (isAndroidWifiDirectApAddress(ifAddr)) {
return new Pair<>(ifAddr.getAddress(), true);
}
}
// Not connected to wifi
return null;
}
/**
* Returns true if the given address belongs to a network provided by an
* Android access point (including the access point's own address).
* <p>
* The access point's address is usually 192.168.43.1, but at least one
* device (Honor 8A) may use other addresses in the range 192.168.43.0/24.
*/
private boolean isAndroidWifiApAddress(InterfaceAddress ifAddr) {
if (ifAddr.getNetworkPrefixLength() != 24) return false;
byte[] ip = ifAddr.getAddress().getAddress();
return ip.length == 4
&& ip[0] == (byte) 192
&& ip[1] == (byte) 168
&& ip[2] == (byte) 43;
}
/**
* Returns true if the given address belongs to a network provided by an
* Android wifi direct legacy mode access point (including the access
* point's own address).
*/
private boolean isAndroidWifiDirectApAddress(InterfaceAddress ifAddr) {
if (ifAddr.getNetworkPrefixLength() != 24) return false;
byte[] ip = ifAddr.getAddress().getAddress();
return ip.length == 4
&& ip[0] == (byte) 192
&& ip[1] == (byte) 168
&& ip[2] == (byte) 49;
}
/**
* Returns a link-local IPv6 address for the wifi client interface, or null
* if there's no such interface or it doesn't have a suitable address.
*/
@TargetApi(21)
@Nullable
private InetAddress getWifiClientIpv6Address() {
for (Network net : connectivityManager.getAllNetworks()) {
NetworkCapabilities caps =
connectivityManager.getNetworkCapabilities(net);
if (caps == null || !caps.hasTransport(TRANSPORT_WIFI)) continue;
LinkProperties props = connectivityManager.getLinkProperties(net);
if (props == null) continue;
for (LinkAddress linkAddress : props.getLinkAddresses()) {
InetAddress addr = linkAddress.getAddress();
if (isIpv6LinkLocalAddress(addr)) return addr;
}
}
return null;
}
/**
* Returns a link-local IPv6 address for the interface with the given IPv4
* address, or null if the interface doesn't have a suitable address.
*/
@Nullable
private InetAddress getIpv6AddressForInterface(InetAddress ipv4) {
try {
NetworkInterface iface = NetworkInterface.getByInetAddress(ipv4);
if (iface == null) return null;
for (InetAddress addr : list(iface.getInetAddresses())) {
if (isIpv6LinkLocalAddress(addr)) return addr;
}
// No suitable address
return null;
} catch (SocketException e) {
logException(LOG, WARNING, e);
return null;
}
} }
private InetAddress intToInetAddress(int ip) { private InetAddress intToInetAddress(int ip) {
@@ -127,9 +232,11 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
private SocketFactory getSocketFactory() { private SocketFactory getSocketFactory() {
if (SDK_INT < 21) return SocketFactory.getDefault(); if (SDK_INT < 21) return SocketFactory.getDefault();
for (Network net : connectivityManager.getAllNetworks()) { for (Network net : connectivityManager.getAllNetworks()) {
NetworkInfo info = connectivityManager.getNetworkInfo(net); NetworkCapabilities caps =
if (info != null && info.getType() == TYPE_WIFI) connectivityManager.getNetworkCapabilities(net);
if (caps != null && caps.hasTransport(TRANSPORT_WIFI)) {
return net.getSocketFactory(); return net.getSocketFactory();
}
} }
LOG.warning("Could not find suitable socket factory"); LOG.warning("Could not find suitable socket factory");
return SocketFactory.getDefault(); return SocketFactory.getDefault();
@@ -137,30 +244,59 @@ class AndroidLanTcpPlugin extends LanTcpPlugin implements EventListener {
@Override @Override
public void eventOccurred(Event e) { public void eventOccurred(Event e) {
super.eventOccurred(e);
if (e instanceof NetworkStatusEvent) updateConnectionStatus(); if (e instanceof NetworkStatusEvent) updateConnectionStatus();
} }
private void updateConnectionStatus() { private void updateConnectionStatus() {
connectionStatusExecutor.execute(() -> { connectionStatusExecutor.execute(() -> {
if (!running) return; State s = getState();
Collection<InetAddress> addrs = getLocalIpAddresses(); if (s != ACTIVE && s != INACTIVE) return;
if (addrs.contains(WIFI_AP_ADDRESS)) { Pair<InetAddress, Boolean> wifi = getPreferredWifiAddress();
if (wifi == null) {
LOG.info("Not connected to wifi");
socketFactory = SocketFactory.getDefault();
// Server sockets may not have been closed automatically when
// interface was taken down. If any sockets are open, closing
// them here will cause the sockets to be cleared and the state
// to be updated in acceptContactConnections()
if (s == ACTIVE) {
LOG.info("Closing server sockets");
tryToClose(state.getServerSocket(true), LOG, WARNING);
tryToClose(state.getServerSocket(false), LOG, WARNING);
}
} else if (wifi.getSecond()) {
LOG.info("Providing wifi hotspot"); LOG.info("Providing wifi hotspot");
// There's no corresponding Network object and thus no way // There's no corresponding Network object and thus no way
// to get a suitable socket factory, so we won't be able to // to get a suitable socket factory, so we won't be able to
// make outgoing connections on API 21+ if another network // make outgoing connections on API 21+ if another network
// has internet access // has internet access
socketFactory = SocketFactory.getDefault(); socketFactory = SocketFactory.getDefault();
if (socket == null || socket.isClosed()) bind(); if (s == INACTIVE) bind();
} else if (addrs.isEmpty()) {
LOG.info("Not connected to wifi");
socketFactory = SocketFactory.getDefault();
tryToClose(socket);
} else { } else {
LOG.info("Connected to wifi"); LOG.info("Connected to wifi");
socketFactory = getSocketFactory(); socketFactory = getSocketFactory();
if (socket == null || socket.isClosed()) bind(); if (s == INACTIVE) bind();
} }
}); });
} }
/**
* Returns a {@link Pair} where the first element is an IP address (IPv4 if
* available, otherwise IPv6) of the wifi interface and the second element
* is true if this device is providing an access point, or false if this
* device is a client. Returns null if this device isn't connected to wifi
* as an access point or client.
*/
@Nullable
private Pair<InetAddress, Boolean> getPreferredWifiAddress() {
Pair<InetAddress, Boolean> wifi = getWifiIpv4Address();
// If there's no wifi IPv4 address, we might be a client on an
// IPv6-only wifi network. We can only detect this on API 21+
if (wifi == null && SDK_INT >= 21) {
InetAddress ipv6 = getWifiClientIpv6Address();
if (ipv6 != null) return new Pair<>(ipv6, false);
}
return wifi;
}
} }

View File

@@ -6,9 +6,9 @@ import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -21,10 +21,11 @@ import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
@NotNullByDefault @NotNullByDefault
public class AndroidLanTcpPluginFactory implements DuplexPluginFactory { public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
private static final int MAX_LATENCY = 30 * 1000; // 30 seconds private static final int MAX_LATENCY = 30_000; // 30 seconds
private static final int MAX_IDLE_TIME = 30 * 1000; // 30 seconds private static final int MAX_IDLE_TIME = 30_000; // 30 seconds
private static final int MIN_POLLING_INTERVAL = 60 * 1000; // 1 minute private static final int CONNECTION_TIMEOUT = 3_000; // 3 seconds
private static final int MAX_POLLING_INTERVAL = 10 * 60 * 1000; // 10 mins private static final int MIN_POLLING_INTERVAL = 60_000; // 1 minute
private static final int MAX_POLLING_INTERVAL = 600_000; // 10 mins
private static final double BACKOFF_BASE = 1.2; private static final double BACKOFF_BASE = 1.2;
private final Executor ioExecutor; private final Executor ioExecutor;
@@ -51,11 +52,12 @@ public class AndroidLanTcpPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor, AndroidLanTcpPlugin plugin = new AndroidLanTcpPlugin(ioExecutor,
appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME); appContext, backoff, callback, MAX_LATENCY, MAX_IDLE_TIME,
CONNECTION_TIMEOUT);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -11,7 +11,7 @@ import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback; import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.ResourceProvider;
@@ -27,6 +27,7 @@ import static android.content.Context.MODE_PRIVATE;
import static android.content.Context.POWER_SERVICE; import static android.content.Context.POWER_SERVICE;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK; import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.MINUTES;
import static org.briarproject.bramble.util.AndroidUtils.getWakeLockTag;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
@@ -41,18 +42,19 @@ class AndroidTorPlugin extends TorPlugin {
Clock clock, ResourceProvider resourceProvider, Clock clock, ResourceProvider resourceProvider,
CircumventionProvider circumventionProvider, CircumventionProvider circumventionProvider,
BatteryManager batteryManager, Backoff backoff, BatteryManager batteryManager, Backoff backoff,
DuplexPluginCallback callback, String architecture, int maxLatency, TorRendezvousCrypto torRendezvousCrypto,
PluginCallback callback, String architecture, int maxLatency,
int maxIdleTime) { int maxIdleTime) {
super(ioExecutor, networkManager, locationUtils, torSocketFactory, super(ioExecutor, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager, clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, maxLatency, maxIdleTime, backoff, torRendezvousCrypto, callback, architecture, maxLatency, maxIdleTime,
appContext.getDir("tor", MODE_PRIVATE)); appContext.getDir("tor", MODE_PRIVATE));
this.appContext = appContext; this.appContext = appContext;
PowerManager pm = (PowerManager) PowerManager pm = (PowerManager)
appContext.getSystemService(POWER_SERVICE); appContext.getSystemService(POWER_SERVICE);
if (pm == null) throw new AssertionError(); if (pm == null) throw new AssertionError();
wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK, wakeLock = new RenewableWakeLock(pm, scheduler, PARTIAL_WAKE_LOCK,
getWakeLockTag(), 1, MINUTES); getWakeLockTag(appContext), 1, MINUTES);
} }
@Override @Override
@@ -73,7 +75,6 @@ class AndroidTorPlugin extends TorPlugin {
@Override @Override
protected void enableNetwork(boolean enable) throws IOException { protected void enableNetwork(boolean enable) throws IOException {
if (!running) return;
if (enable) wakeLock.acquire(); if (enable) wakeLock.acquire();
super.enableNetwork(enable); super.enableNetwork(enable);
if (!enable) wakeLock.release(); if (!enable) wakeLock.release();
@@ -84,17 +85,4 @@ class AndroidTorPlugin extends TorPlugin {
super.stop(); super.stop();
wakeLock.release(); wakeLock.release();
} }
private String getWakeLockTag() {
PackageManager pm = appContext.getPackageManager();
for (PackageInfo info : pm.getInstalledPackages(0)) {
String name = info.packageName.toLowerCase();
if (name.startsWith("com.huawei.powergenie")) {
return "LocationManagerService";
} else if (name.startsWith("com.evenwell.powermonitor")) {
return "AudioIn";
}
}
return getClass().getSimpleName();
}
} }

View File

@@ -1,7 +1,6 @@
package org.briarproject.bramble.plugin.tor; package org.briarproject.bramble.plugin.tor;
import android.content.Context; import android.content.Context;
import android.os.Build;
import org.briarproject.bramble.api.battery.BatteryManager; import org.briarproject.bramble.api.battery.BatteryManager;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
@@ -9,10 +8,10 @@ import org.briarproject.bramble.api.network.NetworkManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Backoff; import org.briarproject.bramble.api.plugin.Backoff;
import org.briarproject.bramble.api.plugin.BackoffFactory; import org.briarproject.bramble.api.plugin.BackoffFactory;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.plugin.TorConstants;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin; import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginCallback;
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.system.Clock; import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
@@ -84,14 +83,20 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
} }
@Override @Override
public DuplexPlugin createPlugin(DuplexPluginCallback callback) { public DuplexPlugin createPlugin(PluginCallback callback) {
// Check that we have a Tor binary for this architecture // Check that we have a Tor binary for this architecture
String architecture = null; String architecture = null;
for (String abi : AndroidUtils.getSupportedArchitectures()) { for (String abi : AndroidUtils.getSupportedArchitectures()) {
if (abi.startsWith("x86")) { if (abi.startsWith("x86_64")) {
architecture = "x86_64";
break;
} else if (abi.startsWith("x86")) {
architecture = "x86"; architecture = "x86";
break; break;
} else if (abi.startsWith("arm64")) {
architecture = "arm64";
break;
} else if (abi.startsWith("armeabi")) { } else if (abi.startsWith("armeabi")) {
architecture = "arm"; architecture = "arm";
break; break;
@@ -101,15 +106,17 @@ public class AndroidTorPluginFactory implements DuplexPluginFactory {
LOG.info("Tor is not supported on this architecture"); LOG.info("Tor is not supported on this architecture");
return null; return null;
} }
// Use position-independent executable for SDK >= 16 // Use position-independent executable
if (Build.VERSION.SDK_INT >= 16) architecture += "_pie"; architecture += "_pie";
Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL, Backoff backoff = backoffFactory.createBackoff(MIN_POLLING_INTERVAL,
MAX_POLLING_INTERVAL, BACKOFF_BASE); MAX_POLLING_INTERVAL, BACKOFF_BASE);
TorRendezvousCrypto torRendezvousCrypto = new TorRendezvousCryptoImpl();
AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler, AndroidTorPlugin plugin = new AndroidTorPlugin(ioExecutor, scheduler,
appContext, networkManager, locationUtils, torSocketFactory, appContext, networkManager, locationUtils, torSocketFactory,
clock, resourceProvider, circumventionProvider, batteryManager, clock, resourceProvider, circumventionProvider, batteryManager,
backoff, callback, architecture, MAX_LATENCY, MAX_IDLE_TIME); backoff, torRendezvousCrypto, callback, architecture,
MAX_LATENCY, MAX_IDLE_TIME);
eventBus.addListener(plugin); eventBus.addListener(plugin);
return plugin; return plugin;
} }

View File

@@ -61,12 +61,12 @@ class AndroidLocationUtils implements LocationUtils {
private String getCountryFromPhoneNetwork() { private String getCountryFromPhoneNetwork() {
Object o = appContext.getSystemService(TELEPHONY_SERVICE); Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o; TelephonyManager tm = (TelephonyManager) o;
return tm.getNetworkCountryIso(); return tm == null ? "" : tm.getNetworkCountryIso();
} }
private String getCountryFromSimCard() { private String getCountryFromSimCard() {
Object o = appContext.getSystemService(TELEPHONY_SERVICE); Object o = appContext.getSystemService(TELEPHONY_SERVICE);
TelephonyManager tm = (TelephonyManager) o; TelephonyManager tm = (TelephonyManager) o;
return tm.getSimCountryIso(); return tm == null ? "" : tm.getSimCountryIso();
} }
} }

View File

@@ -23,6 +23,7 @@ import javax.annotation.concurrent.Immutable;
import javax.inject.Inject; import javax.inject.Inject;
import static android.content.Context.WIFI_SERVICE; import static android.content.Context.WIFI_SERVICE;
import static android.os.Build.VERSION.SDK_INT;
import static android.provider.Settings.Secure.ANDROID_ID; import static android.provider.Settings.Secure.ANDROID_ID;
@Immutable @Immutable
@@ -74,8 +75,7 @@ class AndroidSecureRandomProvider extends UnixSecureRandomProvider {
// Silence strict mode // Silence strict mode
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskWrites(); StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskWrites();
super.writeSeed(); super.writeSeed();
if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT <= 18) if (SDK_INT <= 18) applyOpenSslFix();
applyOpenSslFix();
StrictMode.setThreadPolicy(tp); StrictMode.setThreadPolicy(tp);
} }

View File

@@ -3,18 +3,30 @@ package org.briarproject.bramble.util;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build; import android.os.Build;
import android.provider.Settings; import android.provider.Settings;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File; import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import javax.annotation.Nullable;
import static android.content.Context.MODE_PRIVATE; import static android.content.Context.MODE_PRIVATE;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import static java.util.Arrays.asList;
import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull;
@NotNullByDefault
public class AndroidUtils { public class AndroidUtils {
// Fake Bluetooth address returned by BluetoothAdapter on API 23 and later // Fake Bluetooth address returned by BluetoothAdapter on API 23 and later
@@ -22,11 +34,10 @@ public class AndroidUtils {
private static final String STORED_REPORTS = "dev-reports"; private static final String STORED_REPORTS = "dev-reports";
@SuppressWarnings("deprecation")
public static Collection<String> getSupportedArchitectures() { public static Collection<String> getSupportedArchitectures() {
List<String> abis = new ArrayList<>(); List<String> abis = new ArrayList<>();
if (SDK_INT >= 21) { if (SDK_INT >= 21) {
abis.addAll(Arrays.asList(Build.SUPPORTED_ABIS)); abis.addAll(asList(Build.SUPPORTED_ABIS));
} else { } else {
abis.add(Build.CPU_ABI); abis.add(Build.CPU_ABI);
if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2); if (Build.CPU_ABI2 != null) abis.add(Build.CPU_ABI2);
@@ -36,25 +47,89 @@ public class AndroidUtils {
public static String getBluetoothAddress(Context ctx, public static String getBluetoothAddress(Context ctx,
BluetoothAdapter adapter) { BluetoothAdapter adapter) {
return getBluetoothAddressAndMethod(ctx, adapter).getFirst();
}
public static Pair<String, String> getBluetoothAddressAndMethod(Context ctx,
BluetoothAdapter adapter) {
// Return the adapter's address if it's valid and not fake // Return the adapter's address if it's valid and not fake
@SuppressLint("HardwareIds") @SuppressLint("HardwareIds")
String address = adapter.getAddress(); String address = adapter.getAddress();
if (isValidBluetoothAddress(address)) return address; if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "adapter");
}
// Return the address from settings if it's valid and not fake // Return the address from settings if it's valid and not fake
address = Settings.Secure.getString(ctx.getContentResolver(), address = Settings.Secure.getString(ctx.getContentResolver(),
"bluetooth_address"); "bluetooth_address");
if (isValidBluetoothAddress(address)) return address; if (isValidBluetoothAddress(address)) {
return new Pair<>(address, "settings");
}
// Try to get the address via reflection
address = getBluetoothAddressByReflection(adapter);
if (isValidBluetoothAddress(address)) {
return new Pair<>(requireNonNull(address), "reflection");
}
// Let the caller know we can't find the address // Let the caller know we can't find the address
return ""; return new Pair<>("", "");
} }
private static boolean isValidBluetoothAddress(String address) { public static boolean isValidBluetoothAddress(@Nullable String address) {
return !StringUtils.isNullOrEmpty(address) return !StringUtils.isNullOrEmpty(address)
&& BluetoothAdapter.checkBluetoothAddress(address) && BluetoothAdapter.checkBluetoothAddress(address)
&& !address.equals(FAKE_BLUETOOTH_ADDRESS); && !address.equals(FAKE_BLUETOOTH_ADDRESS);
} }
@Nullable
private static String getBluetoothAddressByReflection(
BluetoothAdapter adapter) {
try {
Field mServiceField =
adapter.getClass().getDeclaredField("mService");
mServiceField.setAccessible(true);
Object mService = mServiceField.get(adapter);
// mService may be null when Bluetooth is disabled
if (mService == null) throw new NoSuchFieldException();
Method getAddressMethod =
mService.getClass().getMethod("getAddress");
return (String) getAddressMethod.invoke(mService);
} catch (NoSuchFieldException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} catch (NoSuchMethodException e) {
return null;
} catch (InvocationTargetException e) {
return null;
} catch (SecurityException e) {
return null;
}
}
public static File getReportDir(Context ctx) { public static File getReportDir(Context ctx) {
return ctx.getDir(STORED_REPORTS, MODE_PRIVATE); return ctx.getDir(STORED_REPORTS, MODE_PRIVATE);
} }
/**
* Returns an array of supported content types for image attachments.
* GIFs can't be compressed on API < 24 so they're not supported.
* <p>
* TODO: Remove this restriction when large message support is added
*/
public static String[] getSupportedImageContentTypes() {
if (SDK_INT < 24) return new String[] {"image/jpeg", "image/png"};
else return new String[] {"image/jpeg", "image/png", "image/gif"};
}
public static String getWakeLockTag(Context ctx) {
PackageManager pm = ctx.getPackageManager();
for (PackageInfo info : pm.getInstalledPackages(0)) {
String name = info.packageName.toLowerCase();
if (name.startsWith("com.huawei.powergenie")) {
return "LocationManagerService";
} else if (name.startsWith("com.evenwell.powermonitor")) {
return "AudioIn";
}
}
return ctx.getPackageName();
}
} }

View File

@@ -16,13 +16,10 @@ import org.junit.Test;
import java.io.File; import java.io.File;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.StringUtils.toHexString;
public class AndroidAccountManagerTest extends BrambleMockTestCase { public class AndroidAccountManagerTest extends BrambleMockTestCase {
@@ -40,11 +37,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
private final Application app; private final Application app;
private final ApplicationInfo applicationInfo; private final ApplicationInfo applicationInfo;
private final String encryptedKeyHex = toHexString(getRandomBytes(123));
private final File testDir = getTestDirectory(); private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key"); private final File keyDir = new File(testDir, "key");
private final File keyFile = new File(keyDir, "db.key");
private final File keyBackupFile = new File(keyDir, "db.key.bak");
private final File dbDir = new File(testDir, "db"); private final File dbDir = new File(testDir, "db");
private AndroidAccountManager accountManager; private AndroidAccountManager accountManager;
@@ -75,33 +69,12 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
}; };
} }
@Test
public void testDbKeyIsMigratedFromPreferencesToFile() {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(encryptedKeyHex));
oneOf(prefs).edit();
will(returnValue(editor));
oneOf(editor).remove("key");
will(returnValue(editor));
oneOf(editor).commit();
will(returnValue(true));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(encryptedKeyHex,
accountManager.loadEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
}
@Test @Test
public void testDeleteAccountClearsSharedPrefsAndDeletesFiles() public void testDeleteAccountClearsSharedPrefsAndDeletesFiles()
throws Exception { throws Exception {
// Directories 'lib' and 'shared_prefs' should be spared // Directories 'code_cache', 'lib' and 'shared_prefs' should be spared
File codeCacheDir = new File(testDir, "code_cache");
File codeCacheFile = new File(codeCacheDir, "file");
File libDir = new File(testDir, "lib"); File libDir = new File(testDir, "lib");
File libFile = new File(libDir, "file"); File libFile = new File(libDir, "file");
File sharedPrefsDir = new File(testDir, "shared_prefs"); File sharedPrefsDir = new File(testDir, "shared_prefs");
@@ -140,6 +113,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertTrue(dbDir.mkdirs()); assertTrue(dbDir.mkdirs());
assertTrue(keyDir.mkdirs()); assertTrue(keyDir.mkdirs());
assertTrue(codeCacheDir.mkdirs());
assertTrue(codeCacheFile.createNewFile());
assertTrue(libDir.mkdirs()); assertTrue(libDir.mkdirs());
assertTrue(libFile.createNewFile()); assertTrue(libFile.createNewFile());
assertTrue(sharedPrefsDir.mkdirs()); assertTrue(sharedPrefsDir.mkdirs());
@@ -155,6 +130,8 @@ public class AndroidAccountManagerTest extends BrambleMockTestCase {
assertFalse(dbDir.exists()); assertFalse(dbDir.exists());
assertFalse(keyDir.exists()); assertFalse(keyDir.exists());
assertTrue(codeCacheDir.exists());
assertTrue(codeCacheFile.exists());
assertTrue(libDir.exists()); assertTrue(libDir.exists());
assertTrue(libFile.exists()); assertTrue(libFile.exists());
assertTrue(sharedPrefsDir.exists()); assertTrue(sharedPrefsDir.exists());

View File

@@ -1,44 +1,46 @@
dependencyVerification { dependencyVerification {
verify = [ verify = [
'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861', 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861',
'com.android.tools.analytics-library:protos:26.4.0:protos-26.4.0.jar:ad760915586797d39319f402837b378bff3bb4ed583e3e0c48c965631fb2135f', 'com.android.tools.analytics-library:protos:26.5.1:protos-26.5.1.jar:8dde1130725461fe827f2a343d353f2b51e8870661fc860d7d5ebddb097ead4e',
'com.android.tools.analytics-library:shared:26.4.0:shared-26.4.0.jar:1332106a905d48909c81268c9e414946de3e83487db394c6073b0a9b5c3d0ed2', 'com.android.tools.analytics-library:shared:26.5.1:shared-26.5.1.jar:ccc2f3b00ec17b11401610ba68553544fc8fc517120e84439ac6eb86b875e18d',
'com.android.tools.analytics-library:tracker:26.4.0:tracker-26.4.0.jar:d0020cfbfd4cd75935f2972d6a24089840d4a10df6f3ef2a796093217dd37796', 'com.android.tools.analytics-library:tracker:26.5.1:tracker-26.5.1.jar:3a76984c0fe2e847ca7a8b35b4780ef0447a9d1666946cb8e60466318e0ab5ae',
'com.android.tools.build:apksig:3.4.0:apksig-3.4.0.jar:91d5a1866139c69756280355a6f61b4d619d0516841580114f45a10f2177327e', 'com.android.tools.build:aapt2-proto:0.4.0:aapt2-proto-0.4.0.jar:fac0435e08898f89eeeb9ca236bea707155ff816c12205ced285ad53604133ca',
'com.android.tools.build:apkzlib:3.4.0:apkzlib-3.4.0.jar:8653c85f5fdf1dde840e8b8af7396aeb79c34b66e541b5860059616006535592', 'com.android.tools.build:apksig:3.5.1:apksig-3.5.1.jar:1fd33e7f009a2a0da766cfeec4211a09f548034b015c289a66d75dd8a9302f4a',
'com.android.tools.build:builder-model:3.4.0:builder-model-3.4.0.jar:a88f138124a9f016a70bcb4760359a502f65c7deed56507ee4014f4dd9ea853b', 'com.android.tools.build:apkzlib:3.5.1:apkzlib-3.5.1.jar:9f330167cbe973b7db407692f74f4f6453b7ffa5f2048934b06280c2ceee60fa',
'com.android.tools.build:builder-test-api:3.4.0:builder-test-api-3.4.0.jar:31089ab1ec19ca7687a010867d2f3807513c805b8226979706f4247b5d4df26f', 'com.android.tools.build:builder-model:3.5.1:builder-model-3.5.1.jar:39ea3c82b76b6e0c9f9fa88d93e0edc1dd4a0f1dfae0ef6fbf2d451da47e5450',
'com.android.tools.build:builder:3.4.0:builder-3.4.0.jar:476221b5203a7f50089bf185ed95000a34b6f5020ef0a17815afd58606922679', 'com.android.tools.build:builder-test-api:3.5.1:builder-test-api-3.5.1.jar:a1b59305584cbcaa078fdc9cfb80871012755b822dd32e8da19add6f7bbcb762',
'com.android.tools.build:gradle-api:3.4.0:gradle-api-3.4.0.jar:215eca38f6719213c2f492b4d622cdd11676c66c9871f8a2aed0c66d00175628', 'com.android.tools.build:builder:3.5.1:builder-3.5.1.jar:e3a8d382434c5f60990730c4719fc814e85a898a33a1e96c1df8d627d3c6eea6',
'com.android.tools.build:manifest-merger:26.4.0:manifest-merger-26.4.0.jar:29e45e690dedd165035e97c21c2ca94d0bd4ec16b6b210daa26669a582b6f220', 'com.android.tools.build:gradle-api:3.5.1:gradle-api-3.5.1.jar:be9b41859bace11998f66b04ed944f87e413f3ad6da3c4665587699da125addc',
'com.android.tools.ddms:ddmlib:26.4.0:ddmlib-26.4.0.jar:93f56fe4630c3166adbd6c51d7bb602d96abb91b07ba5b1165fdcd071e88c940', 'com.android.tools.build:manifest-merger:26.5.1:manifest-merger-26.5.1.jar:dcad9ecb967251f4d750f55a4204a2b400e8fbfe5cb930a1d0d5dbe10ae8bdfc',
'com.android.tools.external.com-intellij:intellij-core:26.4.0:intellij-core-26.4.0.jar:30cb0e879d4424de9677a50b537fb628636b4a50f5470af5e52437980c41421f', 'com.android.tools.ddms:ddmlib:26.5.1:ddmlib-26.5.1.jar:b081aef2a4ed3f4d47cae4cdb128469735f25a114e026d37123bf9ffdec742a8',
'com.android.tools.external.com-intellij:kotlin-compiler:26.4.0:kotlin-compiler-26.4.0.jar:dd1fe225c31a0e012dc025336363a5b783e2c5c20ffb69e77f8f57e89420d998', 'com.android.tools.external.com-intellij:intellij-core:26.5.1:intellij-core-26.5.1.jar:20eced30adc124805bd93488d9cd9d3e33e6bf7b48e9fe5a703d4983f894d450',
'com.android.tools.external.org-jetbrains:uast:26.4.0:uast-26.4.0.jar:f25f3285b775a983327583ff6584dea54e447813ef69e0ce08b05a45b5f4aab0', 'com.android.tools.external.com-intellij:kotlin-compiler:26.5.1:kotlin-compiler-26.5.1.jar:5aed762dd54875b77ae7018d97c05756ff0c5b9fd02ec595dd396ccd14cc22cb',
'com.android.tools.layoutlib:layoutlib-api:26.4.0:layoutlib-api-26.4.0.jar:52128f5cf293b224072be361919bfd416e59480ab7264ddcdbbf046b0d7a12e3', 'com.android.tools.external.org-jetbrains:uast:26.5.1:uast-26.5.1.jar:4bc8653d6c0943f40fee963a149e36c6baa45683d2530968a13f5007e3c40740',
'com.android.tools.lint:lint-api:26.4.0:lint-api-26.4.0.jar:fdb8fca8ae4c254f438338d03d72605e00ed106f2d5550405af41ca1c8509401', 'com.android.tools.layoutlib:layoutlib-api:26.5.1:layoutlib-api-26.5.1.jar:88732f11396c427273e515d23042e35633f4fe4295528a99b866aa2adf0efd9c',
'com.android.tools.lint:lint-checks:26.4.0:lint-checks-26.4.0.jar:4ff52d40488cd3e22b9c6b2eb67784e0c3269d0b42ef9d17689cd75a7b2bceb4', 'com.android.tools.lint:lint-api:26.5.1:lint-api-26.5.1.jar:ec33fcd72bfaf70dd841e03fbfd93f109c2e575aec146067c606689c3972f0de',
'com.android.tools.lint:lint-gradle-api:26.4.0:lint-gradle-api-26.4.0.jar:714b7a85c7d2aa10daeab16e969fe7530c659d0728a7f24021da456870418d0f', 'com.android.tools.lint:lint-checks:26.5.1:lint-checks-26.5.1.jar:a1b9607d484aaae7a71dcecdc76f8003d8239af226c776894a2cf63f9e6c60d7',
'com.android.tools.lint:lint-gradle:26.4.0:lint-gradle-26.4.0.jar:b8c130d273f522388734457e1b96790f41528fcec6fda9e8eaa4e4d95a07cfbb', 'com.android.tools.lint:lint-gradle-api:26.5.1:lint-gradle-api-26.5.1.jar:82453fd98a8394cc84ed995c04d2cd744abd1d6589403427ba7eef53115406f3',
'com.android.tools.lint:lint:26.4.0:lint-26.4.0.jar:83aa062fb0405b60ed358d858c8c2955e1bae44a455b498068c6a60988755f00', 'com.android.tools.lint:lint-gradle:26.5.1:lint-gradle-26.5.1.jar:59465b56cf7db77c656d5f8195d721c3d48b6bdd0502d774de335bfe4baff00b',
'com.android.tools:annotations:26.4.0:annotations-26.4.0.jar:a7955b8e19c3a2a861d6faa43a58b7c0d46ea9112188ee3e235c6f9f439ecc1a', 'com.android.tools.lint:lint:26.5.1:lint-26.5.1.jar:336e4b04ec6f8b0f25879131b7a7862d77df83a1879ee5b71be26128755f8e2e',
'com.android.tools:common:26.4.0:common-26.4.0.jar:ea40b94b3c1284ea7700f011388e2906a8363a66abd902891722b3c557984852', 'com.android.tools:annotations:26.5.1:annotations-26.5.1.jar:2c43c82f8c59d8f7a61e3239e1a2dc9f69dc342ec09af9b7c9f69b25337c0b6e',
'com.android.tools:dvlib:26.4.0:dvlib-26.4.0.jar:23af89c535b01ba36ceed1b6b309b672814eba624e643cd7dedf0519edad50cc', 'com.android.tools:common:26.5.1:common-26.5.1.jar:eccfa54486ed54c4e3123cc42195d023bd0dd21bcd2f0e4868e8c6fc70f8ef6b',
'com.android.tools:repository:26.4.0:repository-26.4.0.jar:3d1763ab46199374dc6d94129bba11c70f1d5857e2c81a3ac4898abca40b176b', 'com.android.tools:dvlib:26.5.1:dvlib-26.5.1.jar:46f93ad498b4756e7d867d2fe38c38890a80e7407a4ae459e4a8c8d5c5aeacfe',
'com.android.tools:sdk-common:26.4.0:sdk-common-26.4.0.jar:78a522525b30ffc6b7bf1299c831d24ce385f68a9f4878f8f752e9baefa31b0f', 'com.android.tools:repository:26.5.1:repository-26.5.1.jar:2b3ee791aa4c3e8ce60498c161a27ca7228816fc630eed4d9f25f2f36a106dce',
'com.android.tools:sdklib:26.4.0:sdklib-26.4.0.jar:b854c23892013a326d761cf071c72cf3e038ed0469d10f4a356829fa56e4c132', 'com.android.tools:sdk-common:26.5.1:sdk-common-26.5.1.jar:365f749676c3574676fd465177c8a492f340816db2b520d6ed114d3b6e77bea7',
'com.google.code.findbugs:jsr305:1.3.9:jsr305-1.3.9.jar:905721a0eea90a81534abb7ee6ef4ea2e5e645fa1def0a5cd88402df1b46c9ed', 'com.android.tools:sdklib:26.5.1:sdklib-26.5.1.jar:007da104afb27c8c682a1628023fe9ec438249c8d15ef0fd6624c5bb8e23b696',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7', 'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.0:gson-2.8.0.jar:c6221763bd79c4f1c3dc7f750b5f29a0bb38b367b81314c4f71896e340c40825', 'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.dagger:dagger-compiler:2.22.1:dagger-compiler-2.22.1.jar:e5f28302cbe70a79d3620cddebfb8ec0736814f3980ffe1e673bfe3342f507d3', 'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.22.1:dagger-producers-2.22.1.jar:f834a0082014213a68ff06a0f048d750178d02196c58b0b15beb367d32b97e35', 'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.22.1:dagger-spi-2.22.1.jar:4b0b922793b3bcb91b99fabb75dba77c68afd7ae4c5f0c4fd6ba681f0a291c7d', 'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
'com.google.dagger:dagger:2.22.1:dagger-2.22.1.jar:329d4340f24c4f5717af016c097e90668bfea2a5376e6aa9964b01cef3fd241a', 'com.google.dagger:dagger:2.24:dagger-2.24.jar:550a6e46a6dfcdf1d764887b6090cea94f783327e50e5c73754f18facfc70b64',
'com.google.errorprone:error_prone_annotations:2.1.3:error_prone_annotations-2.1.3.jar:03d0329547c13da9e17c634d1049ea2ead093925e290567e1a364fd6b1fc7ff8', 'com.google.errorprone:error_prone_annotations:2.2.0:error_prone_annotations-2.2.0.jar:6ebd22ca1b9d8ec06d41de8d64e0596981d9607b42035f9ed374f9de271a481a',
'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30', 'com.google.errorprone:javac-shaded:9-dev-r4023-3:javac-shaded-9-dev-r4023-3.jar:65bfccf60986c47fbc17c9ebab0be626afc41741e0a6ec7109e0768817a36f30',
'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e', 'com.google.googlejavaformat:google-java-format:1.5:google-java-format-1.5.jar:aa19ad7850fb85178aa22f2fddb163b84d6ce4d0035872f30d4408195ca1144e',
'com.google.guava:guava:25.0-jre:guava-25.0-jre.jar:3fd4341776428c7e0e5c18a7c10de129475b69ab9d30aeafbb5c277bb6074fa9', 'com.google.guava:failureaccess:1.0.1:failureaccess-1.0.1.jar:a171ee4c734dd2da837e4b16be9df4661afab72a41adaf31eb84dfdaf936ca26',
'com.google.guava:guava:26.0-jre:guava-26.0-jre.jar:a0e9cabad665bc20bcd2b01f108e5fc03f756e13aea80abaadb9f407033bea2c', 'com.google.guava:guava:27.0.1-jre:guava-27.0.1-jre.jar:e1c814fd04492a27c38e0317eabeaa1b3e950ec8010239e400fe90ad6c9107b4',
'com.google.guava:guava:27.1-jre:guava-27.1-jre.jar:4a5aa70cc968a4d137e599ad37553e5cfeed2265e8c193476d7119036c536fe7',
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6', 'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd', 'com.google.jimfs:jimfs:1.1:jimfs-1.1.jar:c4828e28d7c0a930af9387510b3bada7daa5c04d7c25a75c7b8b081f1c257ddd',
'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4', 'com.google.protobuf:protobuf-java:3.4.0:protobuf-java-3.4.0.jar:dce7e66b32456a1b1198da0caff3a8acb71548658391e798c79369241e6490a4',
@@ -55,6 +57,7 @@ dependencyVerification {
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2', 'javax.xml.bind:jaxb-api:2.2.12-b140109.1041:jaxb-api-2.2.12-b140109.1041.jar:b5e60cd8b7b5ff01ce4a74c5dd008f4fbd14ced3495d0b47b85cfedc182211f2',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5', 'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2', 'net.sf.kxml:kxml2:2.3.0:kxml2-2.3.0.jar:f264dd9f79a1fde10ce5ecc53221eff24be4c9331c830b7d52f2f08a7b633de2',
'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d', 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d',
@@ -66,22 +69,22 @@ dependencyVerification {
'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca', 'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349', 'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:obfs4proxy-android:0.0.9:obfs4proxy-android-0.0.9.zip:9b7e9181535ea8d8bbe8ae6338e08cf4c5fc1e357a779393e0ce49586d459ae0', 'org.briarproject:obfs4proxy-android:0.0.11-2:obfs4proxy-android-0.0.11-2.zip:57e55cbe87aa2aac210fdbb6cd8cdeafe15f825406a08ebf77a8b787aa2c6a8a',
'org.briarproject:tor-android:0.3.5.8:tor-android-0.3.5.8.zip:42a13a6f185be1a62f42e3f30ce66a3c099ac5ec890a65e7593111b65b44a54a', 'org.briarproject:tor-android:0.3.5.10:tor-android-0.3.5.10.zip:edd83bf557fcff2105eaa0bdb3f607a6852ebe7360920929ae3039dd5f4774c5',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d', 'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a', 'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0', 'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d', 'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa', 'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',
'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70', 'org.glassfish.jaxb:jaxb-runtime:2.2.11:jaxb-runtime-2.2.11.jar:a874f2351cfba8e2946be3002d10c18a6da8f21b52ba2acf52f2b85d5520ed70',
'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea', 'org.glassfish.jaxb:txw2:2.2.11:txw2-2.2.11.jar:272a3ccad45a4511351920cd2a8633c53cab8d5220c7a92954da5526bb5eafea',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c', 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.jetbrains.kotlin:kotlin-reflect:1.3.21:kotlin-reflect-1.3.21.jar:a3065c822633191e0a3e3ee12a29bec234fc4b2864a6bb87ef48cce3e9e0c26a', 'org.jetbrains.kotlin:kotlin-reflect:1.3.50:kotlin-reflect-1.3.50.jar:64583199ea5a54aefd1bd1595288925f784226ee562d1dd279011c6075b3d7a4',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.21:kotlin-stdlib-common-1.3.21.jar:cea61f7b611895e64f58569a9757fc0ab0d582f107211e1930e0ce2a0add52a7', 'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50:kotlin-stdlib-common-1.3.50.jar:8ce678e88e4ba018b66dacecf952471e4d7dfee156a8a819760a5a5ff29d323c',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21:kotlin-stdlib-jdk7-1.3.21.jar:a87875604fd42140da6938ae4d35ee61081f4482536efc6d2615b8b626a198af', 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.50:kotlin-stdlib-jdk7-1.3.50.jar:9a026639e76212f8d57b86d55b075394c2e009f1979110751d34c05c5f75d57b',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.21:kotlin-stdlib-jdk8-1.3.21.jar:5823ed66ac122a1c55442ebca5a209a843ccd87f562edc31a787f3d2e47f74d4', 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.50:kotlin-stdlib-jdk8-1.3.50.jar:1b351fb6e09c14b55525c74c1f4cf48942eae43c348b7bc764a5e6e423d4da0c',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.21:kotlin-stdlib-1.3.21.jar:38ba2370d9f06f50433e06b2ca775b94473c2e2785f410926079ab793c72b034', 'org.jetbrains.kotlin:kotlin-stdlib:1.3.50:kotlin-stdlib-1.3.50.jar:e6f05746ee0366d0b52825a090fac474dcf44082c9083bbb205bd16976488d6c',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7', 'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c', 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c',

View File

@@ -7,7 +7,7 @@ apply plugin: 'witness'
apply from: 'witness.gradle' apply from: 'witness.gradle'
dependencies { dependencies {
implementation "com.google.dagger:dagger:2.22.1" implementation "com.google.dagger:dagger:2.24"
implementation 'com.google.code.findbugs:jsr305:3.0.2' implementation 'com.google.code.findbugs:jsr305:3.0.2'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'

View File

@@ -4,7 +4,6 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils; import org.briarproject.bramble.util.StringUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
@@ -16,8 +15,6 @@ import javax.annotation.concurrent.ThreadSafe;
@NotNullByDefault @NotNullByDefault
public class Bytes implements Comparable<Bytes> { public class Bytes implements Comparable<Bytes> {
public static final BytesComparator COMPARATOR = new BytesComparator();
private final byte[] bytes; private final byte[] bytes;
private int hashCode = -1; private int hashCode = -1;
@@ -45,14 +42,7 @@ public class Bytes implements Comparable<Bytes> {
@Override @Override
public int compareTo(Bytes other) { public int compareTo(Bytes other) {
byte[] aBytes = bytes, bBytes = other.bytes; return compare(bytes, other.bytes);
int length = Math.min(aBytes.length, bBytes.length);
for (int i = 0; i < length; i++) {
int aUnsigned = aBytes[i] & 0xFF, bUnsigned = bBytes[i] & 0xFF;
if (aUnsigned < bUnsigned) return -1;
if (aUnsigned > bUnsigned) return 1;
}
return aBytes.length - bBytes.length;
} }
@Override @Override
@@ -61,11 +51,13 @@ public class Bytes implements Comparable<Bytes> {
"(" + StringUtils.toHexString(getBytes()) + ")"; "(" + StringUtils.toHexString(getBytes()) + ")";
} }
public static class BytesComparator implements Comparator<Bytes> { public static int compare(byte[] a, byte[] b) {
int length = Math.min(a.length, b.length);
@Override for (int i = 0; i < length; i++) {
public int compare(Bytes a, Bytes b) { int aUnsigned = a[i] & 0xFF, bUnsigned = b[i] & 0xFF;
return a.compareTo(b); if (aUnsigned < bUnsigned) return -1;
if (aUnsigned > bUnsigned) return 1;
} }
return a.length - b.length;
} }
} }

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api;
/**
* Interface for specifying which features are enabled in a build.
*/
public interface FeatureFlags {
boolean shouldEnableImageAttachments();
}

View File

@@ -0,0 +1,9 @@
package org.briarproject.bramble.api;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public interface Predicate<T> {
boolean test(T t);
}

View File

@@ -1,5 +1,6 @@
package org.briarproject.bramble.api.account; package org.briarproject.bramble.api.account;
import org.briarproject.bramble.api.crypto.DecryptionException;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -13,7 +14,8 @@ public interface AccountManager {
* Returns true if the manager has the database key. This will be false * Returns true if the manager has the database key. This will be false
* before {@link #createAccount(String, String)} or {@link #signIn(String)} * before {@link #createAccount(String, String)} or {@link #signIn(String)}
* has been called, and true after {@link #createAccount(String, String)} * has been called, and true after {@link #createAccount(String, String)}
* or {@link #signIn(String)} has returned true, until the process exits. * or {@link #signIn(String)} has returned true, until
* {@link #deleteAccount()} is called or the process exits.
*/ */
boolean hasDatabaseKey(); boolean hasDatabaseKey();
@@ -22,25 +24,22 @@ public interface AccountManager {
* before {@link #createAccount(String, String)} or {@link #signIn(String)} * before {@link #createAccount(String, String)} or {@link #signIn(String)}
* has been called, and non-null after * has been called, and non-null after
* {@link #createAccount(String, String)} or {@link #signIn(String)} has * {@link #createAccount(String, String)} or {@link #signIn(String)} has
* returned true, until the process exits. * returned true, until {@link #deleteAccount()} is called or the process
* exits.
*/ */
@Nullable @Nullable
SecretKey getDatabaseKey(); SecretKey getDatabaseKey();
/** /**
* Returns true if the encrypted database key can be loaded from disk, and * Returns true if the encrypted database key can be loaded from disk.
* the database directory exists and is a directory.
*/ */
boolean accountExists(); boolean accountExists();
/** /**
* Creates an identity with the given name and registers it with the * Creates an identity with the given name and registers it with the
* {@link IdentityManager}. Creates a database key, encrypts it with the * {@link IdentityManager}. Creates a database key, encrypts it with the
* given password and stores it on disk. * given password and stores it on disk. {@link #accountExists()} will
* <p/> * return true after this method returns true.
* This method does not create the database directory, so
* {@link #accountExists()} will continue to return false until the
* database directory is created.
*/ */
boolean createAccount(String name, String password); boolean createAccount(String name, String password);
@@ -54,17 +53,19 @@ public interface AccountManager {
* Loads the encrypted database key from disk and decrypts it with the * Loads the encrypted database key from disk and decrypts it with the
* given password. * given password.
* *
* @return true if the database key was successfully loaded and decrypted. * @throws DecryptionException If the database key could not be loaded and
* decrypted.
*/ */
boolean signIn(String password); void signIn(String password) throws DecryptionException;
/** /**
* Loads the encrypted database key from disk, decrypts it with the old * Loads the encrypted database key from disk, decrypts it with the old
* password, encrypts it with the new password, and stores it on disk, * password, encrypts it with the new password, and stores it on disk,
* replacing the old key. * replacing the old key.
* *
* @return true if the database key was successfully loaded, re-encrypted * @throws DecryptionException If the database key could not be loaded and
* and stored. * decrypted.
*/ */
boolean changePassword(String oldPassword, String newPassword); void changePassword(String oldPassword, String newPassword)
throws DecryptionException;
} }

View File

@@ -25,7 +25,10 @@ public interface ClientHelper {
throws DbException, FormatException; throws DbException, FormatException;
void addLocalMessage(Transaction txn, Message m, BdfDictionary metadata, void addLocalMessage(Transaction txn, Message m, BdfDictionary metadata,
boolean shared) throws DbException, FormatException; boolean shared, boolean temporary)
throws DbException, FormatException;
Message createMessage(GroupId g, long timestamp, byte[] body);
Message createMessage(GroupId g, long timestamp, BdfList body) Message createMessage(GroupId g, long timestamp, BdfList body)
throws FormatException; throws FormatException;
@@ -108,7 +111,7 @@ public interface ClientHelper {
Author parseAndValidateAuthor(BdfList author) throws FormatException; Author parseAndValidateAuthor(BdfList author) throws FormatException;
PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes) PublicKey parseAndValidateAgreementPublicKey(byte[] publicKeyBytes)
throws FormatException; throws FormatException;
TransportProperties parseAndValidateTransportProperties( TransportProperties parseAndValidateTransportProperties(
BdfDictionary properties) throws FormatException; BdfDictionary properties) throws FormatException;

View File

@@ -0,0 +1,49 @@
package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
@NotNullByDefault
public interface ConnectionManager {
/**
* Manages an incoming connection from a contact over a simplex transport.
*/
void manageIncomingConnection(TransportId t, TransportConnectionReader r);
/**
* Manages an incoming connection from a contact over a duplex transport.
*/
void manageIncomingConnection(TransportId t, DuplexTransportConnection d);
/**
* Manages an incoming handshake connection from a pending contact over a
* duplex transport.
*/
void manageIncomingConnection(PendingContactId p, TransportId t,
DuplexTransportConnection d);
/**
* Manages an outgoing connection to a contact over a simplex transport.
*/
void manageOutgoingConnection(ContactId c, TransportId t,
TransportConnectionWriter w);
/**
* Manages an outgoing connection to a contact over a duplex transport.
*/
void manageOutgoingConnection(ContactId c, TransportId t,
DuplexTransportConnection d);
/**
* Manages an outgoing handshake connection to a pending contact over a
* duplex transport.
*/
void manageOutgoingConnection(PendingContactId p, TransportId t,
DuplexTransportConnection d);
}

View File

@@ -0,0 +1,130 @@
package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginConfig;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.plugin.event.ConnectionClosedEvent;
import org.briarproject.bramble.api.plugin.event.ConnectionOpenedEvent;
import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent;
import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent;
import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionClosedEvent;
import org.briarproject.bramble.api.rendezvous.event.RendezvousConnectionOpenedEvent;
import org.briarproject.bramble.api.sync.Priority;
import java.util.Collection;
/**
* Keeps track of which contacts are currently connected by which transports.
*/
@NotNullByDefault
public interface ConnectionRegistry {
/**
* Registers an incoming connection from the given contact over the given
* transport. The connection's {@link Priority priority} can be set later
* via {@link #setPriority(ContactId, TransportId, InterruptibleConnection,
* Priority)} if a priority record is received from the contact.
* <p>
* Broadcasts {@link ConnectionOpenedEvent}. Also broadcasts
* {@link ContactConnectedEvent} if this is the only connection with the
* contact.
*/
void registerIncomingConnection(ContactId c, TransportId t,
InterruptibleConnection conn);
/**
* Registers an outgoing connection to the given contact over the given
* transport.
* <p>
* Broadcasts {@link ConnectionOpenedEvent}. Also broadcasts
* {@link ContactConnectedEvent} if this is the only connection with the
* contact.
* <p>
* If the registry has any "better" connections with the given contact, the
* given connection will be interrupted. If the registry has any "worse"
* connections with the given contact, those connections will be
* interrupted.
* <p>
* Connection A is considered "better" than connection B if both
* connections have had their priorities set, and either A's transport is
* {@link PluginConfig#getTransportPreferences() preferred} to B's, or
* they use the same transport and A has higher {@link Priority priority}
* than B.
* <p>
* For backward compatibility, connections without priorities are not
* considered better or worse than other connections.
*/
void registerOutgoingConnection(ContactId c, TransportId t,
InterruptibleConnection conn, Priority priority);
/**
* Unregisters a connection with the given contact over the given transport.
* <p>
* Broadcasts {@link ConnectionClosedEvent}. Also broadcasts
* {@link ContactDisconnectedEvent} if this is the only connection with
* the contact.
*/
void unregisterConnection(ContactId c, TransportId t,
InterruptibleConnection conn, boolean incoming, boolean exception);
/**
* Sets the {@link Priority priority} of a connection that was previously
* registered via {@link #registerIncomingConnection(ContactId, TransportId,
* InterruptibleConnection)}.
* <p>
* If the registry has any "better" connections with the given contact, the
* given connection will be interrupted. If the registry has any "worse"
* connections with the given contact, those connections will be
* interrupted.
* <p>
* Connection A is considered "better" than connection B if both
* connections have had their priorities set, and either A's transport is
* {@link PluginConfig#getTransportPreferences() preferred} to B's, or
* they use the same transport and A has higher {@link Priority priority}
* than B.
* <p>
* For backward compatibility, connections without priorities are not
* considered better or worse than other connections.
*/
void setPriority(ContactId c, TransportId t, InterruptibleConnection conn,
Priority priority);
/**
* Returns any contacts that are connected via the given transport.
*/
Collection<ContactId> getConnectedContacts(TransportId t);
/**
* Returns any contacts that are connected via the given transport or any
* {@link PluginConfig#getTransportPreferences() better} transport.
*/
Collection<ContactId> getConnectedOrBetterContacts(TransportId t);
/**
* Returns true if the given contact is connected via the given transport.
*/
boolean isConnected(ContactId c, TransportId t);
/**
* Returns true if the given contact is connected via any transport.
*/
boolean isConnected(ContactId c);
/**
* Registers a connection with the given pending contact. Broadcasts
* {@link RendezvousConnectionOpenedEvent} if this is the only connection
* with the pending contact.
*
* @return True if this is the only connection with the pending contact,
* false if it is redundant and should be closed
*/
boolean registerConnection(PendingContactId p);
/**
* Unregisters a connection with the given pending contact. Broadcasts
* {@link RendezvousConnectionClosedEvent}.
*/
void unregisterConnection(PendingContactId p, boolean success);
}

View File

@@ -0,0 +1,19 @@
package org.briarproject.bramble.api.connection;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* A duplex sync connection that can be closed by interrupting its outgoing
* sync session.
*/
@NotNullByDefault
public interface InterruptibleConnection {
/**
* Interrupts the connection's outgoing sync session. If the underlying
* transport connection is alive and the remote peer is cooperative, this
* should result in both sync sessions ending and the connection being
* cleanly closed.
*/
void interruptOutgoingSession();
}

View File

@@ -0,0 +1,37 @@
package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import java.io.IOException;
@NotNullByDefault
public interface ContactExchangeManager {
/**
* Exchanges contact information with a remote peer and adds the peer
* as a contact.
*
* @param alice Whether the local peer takes the role of Alice
* @return The newly added contact
* @throws ContactExistsException If the contact already exists
*/
Contact exchangeContacts(DuplexTransportConnection conn,
SecretKey masterKey, boolean alice, boolean verified)
throws IOException, DbException;
/**
* Exchanges contact information with a remote peer and adds the peer
* as a contact, replacing the given pending contact.
*
* @param alice Whether the local peer takes the role of Alice
* @return The newly added contact
* @throws ContactExistsException If the contact already exists
*/
Contact exchangeContacts(PendingContactId p, DuplexTransportConnection conn,
SecretKey masterKey, boolean alice, boolean verified)
throws IOException, DbException;
}

View File

@@ -1,10 +1,13 @@
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.FormatException; import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.UnsupportedVersionException; import org.briarproject.bramble.api.UnsupportedVersionException;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.ContactExistsException;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchContactException; import org.briarproject.bramble.api.db.NoSuchContactException;
import org.briarproject.bramble.api.db.PendingContactExistsException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.AuthorId;
@@ -12,6 +15,7 @@ import org.briarproject.bramble.api.identity.AuthorInfo;
import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.security.GeneralSecurityException;
import java.util.Collection; import java.util.Collection;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -28,28 +32,71 @@ public interface ContactManager {
/** /**
* Stores a contact associated with the given local and remote pseudonyms, * Stores a contact associated with the given local and remote pseudonyms,
* derives and stores transport keys for each transport, and returns an ID * derives and stores rotation mode transport keys for each transport, and
* for the contact. * returns an ID for the contact.
* *
* @param alice true if the local party is Alice * @param rootKey The root key for a set of rotation mode transport keys
* @param timestamp The timestamp for deriving rotation mode transport
* keys from the root key
* @param alice True if the local party is Alice
* @param verified True if the contact's identity has been verified, which
* is true if the contact was added in person or false if the contact was
* introduced or added remotely
* @param active True if the rotation mode transport keys can be used for
* outgoing streams
*/ */
ContactId addContact(Transaction txn, Author remote, AuthorId local, ContactId addContact(Transaction txn, Author remote, AuthorId local,
SecretKey rootKey, long timestamp, boolean alice, boolean verified, SecretKey rootKey, long timestamp, boolean alice, boolean verified,
boolean active) throws DbException; boolean active) throws DbException;
/**
* Stores a contact associated with the given local and remote pseudonyms,
* replacing the given pending contact, derives and stores handshake mode
* and rotation mode transport keys for each transport, and returns an ID
* for the contact.
*
* @param rootKey The root key for a set of rotation mode transport keys
* @param timestamp The timestamp for deriving rotation mode transport
* keys from the root key
* @param alice True if the local party is Alice
* @param verified True if the contact's identity has been verified, which
* is true if the contact was added in person or false if the contact was
* introduced or added remotely
* @param active True if the rotation mode transport keys can be used for
* outgoing streams
* @throws GeneralSecurityException If the pending contact's handshake
* public key is invalid
*/
ContactId addContact(Transaction txn, PendingContactId p, Author remote,
AuthorId local, SecretKey rootKey, long timestamp, boolean alice,
boolean verified, boolean active)
throws DbException, GeneralSecurityException;
/** /**
* Stores a contact associated with the given local and remote pseudonyms * Stores a contact associated with the given local and remote pseudonyms
* and returns an ID for the contact. * and returns an ID for the contact.
*
* @param verified True if the contact's identity has been verified, which
* is true if the contact was added in person or false if the contact was
* introduced or added remotely
*/ */
ContactId addContact(Transaction txn, Author remote, AuthorId local, ContactId addContact(Transaction txn, Author remote, AuthorId local,
boolean verified) throws DbException; boolean verified) throws DbException;
/** /**
* Stores a contact associated with the given local and remote pseudonyms, * Stores a contact associated with the given local and remote pseudonyms,
* derives and stores transport keys for each transport, and returns an ID * derives and stores rotation mode transport keys for each transport, and
* for the contact. * returns an ID for the contact.
* *
* @param alice true if the local party is Alice * @param rootKey The root key for a set of rotation mode transport keys
* @param timestamp The timestamp for deriving rotation mode transport
* keys from the root key
* @param alice True if the local party is Alice
* @param verified True if the contact's identity has been verified, which
* is true if the contact was added in person or false if the contact was
* introduced or added remotely
* @param active True if the rotation mode transport keys can be used for
* outgoing streams
*/ */
ContactId addContact(Author remote, AuthorId local, SecretKey rootKey, ContactId addContact(Author remote, AuthorId local, SecretKey rootKey,
long timestamp, boolean alice, boolean verified, boolean active) long timestamp, boolean alice, boolean verified, boolean active)
@@ -65,20 +112,34 @@ public interface ContactManager {
* Creates a {@link PendingContact} from the given handshake link and * Creates a {@link PendingContact} from the given handshake link and
* alias, adds it to the database and returns it. * alias, adds it to the database and returns it.
* *
* @param link The handshake link received from the contact we want to add * @param link The handshake link received from the pending contact
* @param alias The alias the user has given this contact * @param alias The alias the user has given this pending contact
* @return A PendingContact representing the contact to be added
* @throws UnsupportedVersionException If the link uses a format version * @throws UnsupportedVersionException If the link uses a format version
* that is not supported * that is not supported
* @throws FormatException If the link is invalid * @throws FormatException If the link is invalid
* @throws GeneralSecurityException If the pending contact's handshake
* public key is invalid
* @throws ContactExistsException If a contact with the same handshake
* public key already exists
* @throws PendingContactExistsException If a pending contact with the same
* handshake public key already exists
*/ */
PendingContact addPendingContact(String link, String alias) PendingContact addPendingContact(String link, String alias)
throws DbException, FormatException; throws DbException, FormatException, GeneralSecurityException,
ContactExistsException, PendingContactExistsException;
/** /**
* Returns a list of {@link PendingContact}s. * Returns the pending contact with the given ID.
*/ */
Collection<PendingContact> getPendingContacts() throws DbException; PendingContact getPendingContact(Transaction txn, PendingContactId p)
throws DbException;
/**
* Returns a list of {@link PendingContact PendingContacts} and their
* {@link PendingContactState states}.
*/
Collection<Pair<PendingContact, PendingContactState>> getPendingContacts()
throws DbException;
/** /**
* Removes a {@link PendingContact}. * Removes a {@link PendingContact}.
@@ -91,8 +152,13 @@ public interface ContactManager {
Contact getContact(ContactId c) throws DbException; Contact getContact(ContactId c) throws DbException;
/** /**
* Returns the contact with the given remoteAuthorId * Returns the contact with the given ID.
* that was added by the LocalAuthor with the given localAuthorId */
Contact getContact(Transaction txn, ContactId c) throws DbException;
/**
* Returns the contact with the given {@code remoteAuthorId}
* that belongs to the local pseudonym with the given {@code localAuthorId}.
* *
* @throws NoSuchContactException If the contact is not in the database * @throws NoSuchContactException If the contact is not in the database
*/ */
@@ -100,8 +166,8 @@ public interface ContactManager {
throws DbException; throws DbException;
/** /**
* Returns the contact with the given remoteAuthorId * Returns the contact with the given {@code remoteAuthorId}
* that was added by the LocalAuthor with the given localAuthorId * that belongs to the local pseudonym with the given {@code localAuthorId}.
* *
* @throws NoSuchContactException If the contact is not in the database * @throws NoSuchContactException If the contact is not in the database
*/ */
@@ -109,7 +175,7 @@ public interface ContactManager {
AuthorId localAuthorId) throws DbException; AuthorId localAuthorId) throws DbException;
/** /**
* Returns all active contacts. * Returns all contacts.
*/ */
Collection<Contact> getContacts() throws DbException; Collection<Contact> getContacts() throws DbException;
@@ -124,25 +190,27 @@ public interface ContactManager {
void removeContact(Transaction txn, ContactId c) throws DbException; void removeContact(Transaction txn, ContactId c) throws DbException;
/** /**
* Sets an alias name for the contact or unsets it if alias is null. * Sets an alias for the contact or unsets it if {@code alias} is null.
*/ */
void setContactAlias(Transaction txn, ContactId c, @Nullable String alias) void setContactAlias(Transaction txn, ContactId c, @Nullable String alias)
throws DbException; throws DbException;
/** /**
* Sets an alias name for the contact or unsets it if alias is null. * Sets an alias for the contact or unsets it if {@code alias} is null.
*/ */
void setContactAlias(ContactId c, @Nullable String alias) void setContactAlias(ContactId c, @Nullable String alias)
throws DbException; throws DbException;
/** /**
* Return true if a contact with this name and public key already exists * Returns true if a contact with this {@code remoteAuthorId} belongs to
* the local pseudonym with this {@code localAuthorId}.
*/ */
boolean contactExists(Transaction txn, AuthorId remoteAuthorId, boolean contactExists(Transaction txn, AuthorId remoteAuthorId,
AuthorId localAuthorId) throws DbException; AuthorId localAuthorId) throws DbException;
/** /**
* Return true if a contact with this name and public key already exists * Returns true if a contact with this {@code remoteAuthorId} belongs to
* the local pseudonym with this {@code localAuthorId}.
*/ */
boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId) boolean contactExists(AuthorId remoteAuthorId, AuthorId localAuthorId)
throws DbException; throws DbException;

View File

@@ -0,0 +1,45 @@
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.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.transport.StreamWriter;
import java.io.IOException;
import java.io.InputStream;
@NotNullByDefault
public interface HandshakeManager {
/**
* Handshakes with the given pending contact. Returns an ephemeral master
* key authenticated with both parties' handshake key pairs and a flag
* indicating whether the local peer is Alice or Bob.
*
* @param in An incoming stream for the handshake, which must be secured in
* handshake mode
* @param out An outgoing stream for the handshake, which must be secured
* in handshake mode
*/
HandshakeResult handshake(PendingContactId p, InputStream in,
StreamWriter out) throws DbException, IOException;
class HandshakeResult {
private final SecretKey masterKey;
private final boolean alice;
public HandshakeResult(SecretKey masterKey, boolean alice) {
this.masterKey = masterKey;
this.alice = alice;
}
public SecretKey getMasterKey() {
return masterKey;
}
public boolean isAlice() {
return alice;
}
}
}

View File

@@ -12,15 +12,13 @@ public class PendingContact {
private final PendingContactId id; private final PendingContactId id;
private final PublicKey publicKey; private final PublicKey publicKey;
private final String alias; private final String alias;
private final PendingContactState state;
private final long timestamp; private final long timestamp;
public PendingContact(PendingContactId id, PublicKey publicKey, public PendingContact(PendingContactId id, PublicKey publicKey,
String alias, PendingContactState state, long timestamp) { String alias, long timestamp) {
this.id = id; this.id = id;
this.publicKey = publicKey; this.publicKey = publicKey;
this.alias = alias; this.alias = alias;
this.state = state;
this.timestamp = timestamp; this.timestamp = timestamp;
} }
@@ -36,10 +34,6 @@ public class PendingContact {
return alias; return alias;
} }
public PendingContactState getState() {
return state;
}
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }

View File

@@ -1,30 +1,10 @@
package org.briarproject.bramble.api.contact; package org.briarproject.bramble.api.contact;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public enum PendingContactState { public enum PendingContactState {
WAITING_FOR_CONNECTION(0), WAITING_FOR_CONNECTION,
CONNECTED(1), OFFLINE,
ADDING_CONTACT(2), CONNECTING,
FAILED(3); ADDING_CONTACT,
FAILED
private final int value;
PendingContactState(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static PendingContactState fromValue(int value) {
for (PendingContactState s : values()) if (s.value == value) return s;
throw new IllegalArgumentException();
}
} }

View File

@@ -14,12 +14,18 @@ import javax.annotation.concurrent.Immutable;
public class ContactAddedEvent extends Event { public class ContactAddedEvent extends Event {
private final ContactId contactId; private final ContactId contactId;
private final boolean verified;
public ContactAddedEvent(ContactId contactId) { public ContactAddedEvent(ContactId contactId, boolean verified) {
this.contactId = contactId; this.contactId = contactId;
this.verified = verified;
} }
public ContactId getContactId() { public ContactId getContactId() {
return contactId; return contactId;
} }
public boolean isVerified() {
return verified;
}
} }

View File

@@ -1,22 +0,0 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public class ContactAddedRemotelyEvent extends Event {
private final Contact contact;
public ContactAddedRemotelyEvent(Contact contact) {
this.contact = contact;
}
public Contact getContact() {
return contact;
}
}

View File

@@ -1,32 +0,0 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public class ContactExchangeFailedEvent extends Event {
@Nullable
private final Author duplicateRemoteAuthor;
public ContactExchangeFailedEvent(@Nullable Author duplicateRemoteAuthor) {
this.duplicateRemoteAuthor = duplicateRemoteAuthor;
}
public ContactExchangeFailedEvent() {
this(null);
}
@Nullable
public Author getDuplicateRemoteAuthor() {
return duplicateRemoteAuthor;
}
public boolean wasDuplicateContact() {
return duplicateRemoteAuthor != null;
}
}

View File

@@ -1,20 +0,0 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public class ContactExchangeSucceededEvent extends Event {
private final Author remoteAuthor;
public ContactExchangeSucceededEvent(Author remoteAuthor) {
this.remoteAuthor = remoteAuthor;
}
public Author getRemoteAuthor() {
return remoteAuthor;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.contact.event;
import org.briarproject.bramble.api.contact.PendingContact;
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 pending contact is added.
*/
@Immutable
@NotNullByDefault
public class PendingContactAddedEvent extends Event {
private final PendingContact pendingContact;
public PendingContactAddedEvent(PendingContact pendingContact) {
this.pendingContact = pendingContact;
}
public PendingContact getPendingContact() {
return pendingContact;
}
}

View File

@@ -27,31 +27,55 @@ public interface CryptoComponent {
/** /**
* Derives another secret key from the given secret key. * Derives another secret key from the given secret key.
* *
* @param label a namespaced label indicating the purpose of the derived * @param label A namespaced label indicating the purpose of the derived
* key, to prevent it from being repurposed or colliding with a key derived * key, to prevent it from being repurposed or colliding with a key derived
* for another purpose * for another purpose
* @param inputs Additional inputs that will be included in the derivation
* of the key
*/ */
SecretKey deriveKey(String label, SecretKey k, byte[]... inputs); SecretKey deriveKey(String label, SecretKey k, byte[]... inputs);
/** /**
* Derives a common shared secret from two public keys and one of the * Derives a shared secret from two key pairs.
* corresponding private keys.
* *
* @param label a namespaced label indicating the purpose of this shared * @param label A namespaced label indicating the purpose of this shared
* secret, to prevent it from being repurposed or colliding with a shared * secret, to prevent it from being repurposed or colliding with a shared
* secret derived for another purpose * secret derived for another purpose
* @param theirPublicKey the public key of the remote party * @param theirPublicKey The public key of the remote party
* @param ourKeyPair the key pair of the local party * @param ourKeyPair The key pair of the local party
* @return the shared secret * @param inputs Additional inputs that will be included in the derivation
* of the shared secret
* @return The shared secret
*/ */
SecretKey deriveSharedSecret(String label, PublicKey theirPublicKey, SecretKey deriveSharedSecret(String label, PublicKey theirPublicKey,
KeyPair ourKeyPair, byte[]... inputs) KeyPair ourKeyPair, byte[]... inputs)
throws GeneralSecurityException; throws GeneralSecurityException;
/**
* Derives a shared secret from two static and two ephemeral key pairs.
*
* @param label A namespaced label indicating the purpose of this shared
* secret, to prevent it from being repurposed or colliding with a shared
* secret derived for another purpose
* @param theirStaticPublicKey The static public key of the remote party
* @param theirEphemeralPublicKey The ephemeral public key of the remote
* party
* @param ourStaticKeyPair The static key pair of the local party
* @param ourEphemeralKeyPair The ephemeral key pair of the local party
* @param alice True if the local party is Alice
* @param inputs Additional inputs that will be included in the
* derivation of the shared secret
* @return The shared secret
*/
SecretKey deriveSharedSecret(String label, PublicKey theirStaticPublicKey,
PublicKey theirEphemeralPublicKey, KeyPair ourStaticKeyPair,
KeyPair ourEphemeralKeyPair, boolean alice, byte[]... inputs)
throws GeneralSecurityException;
/** /**
* Signs the given byte[] with the given private key. * Signs the given byte[] with the given private key.
* *
* @param label a namespaced label indicating the purpose of this * @param label A namespaced label indicating the purpose of this
* signature, to prevent it from being repurposed or colliding with a * signature, to prevent it from being repurposed or colliding with a
* signature created for another purpose * signature created for another purpose
*/ */
@@ -62,10 +86,10 @@ public interface CryptoComponent {
* Verifies that the given signature is valid for the signed data * Verifies that the given signature is valid for the signed data
* and the given public key. * and the given public key.
* *
* @param label a namespaced label indicating the purpose of this * @param label A namespaced label indicating the purpose of this
* signature, to prevent it from being repurposed or colliding with a * signature, to prevent it from being repurposed or colliding with a
* signature created for another purpose * signature created for another purpose
* @return true if the signature was valid, false otherwise. * @return True if the signature was valid, false otherwise.
*/ */
boolean verifySignature(byte[] signature, String label, byte[] signed, boolean verifySignature(byte[] signature, String label, byte[] signed,
PublicKey publicKey) throws GeneralSecurityException; PublicKey publicKey) throws GeneralSecurityException;
@@ -74,7 +98,7 @@ public interface CryptoComponent {
* Returns the hash of the given inputs. The inputs are unambiguously * Returns the hash of the given inputs. The inputs are unambiguously
* combined by prefixing each input with its length. * combined by prefixing each input with its length.
* *
* @param label a namespaced label indicating the purpose of this hash, to * @param label A namespaced label indicating the purpose of this hash, to
* prevent it from being repurposed or colliding with a hash created for * prevent it from being repurposed or colliding with a hash created for
* another purpose * another purpose
*/ */
@@ -85,7 +109,7 @@ public interface CryptoComponent {
* given inputs. The inputs are unambiguously combined by prefixing each * given inputs. The inputs are unambiguously combined by prefixing each
* input with its length. * input with its length.
* *
* @param label a namespaced label indicating the purpose of this MAC, to * @param label A namespaced label indicating the purpose of this MAC, to
* prevent it from being repurposed or colliding with a MAC created for * prevent it from being repurposed or colliding with a MAC created for
* another purpose * another purpose
*/ */
@@ -95,10 +119,10 @@ public interface CryptoComponent {
* Verifies that the given message authentication code is valid for the * Verifies that the given message authentication code is valid for the
* given secret key and inputs. * given secret key and inputs.
* *
* @param label a namespaced label indicating the purpose of this MAC, to * @param label A namespaced label indicating the purpose of this MAC, to
* prevent it from being repurposed or colliding with a MAC created for * prevent it from being repurposed or colliding with a MAC created for
* another purpose * another purpose
* @return true if the MAC was valid, false otherwise. * @return True if the MAC was valid, false otherwise.
*/ */
boolean verifyMac(byte[] mac, String label, SecretKey macKey, boolean verifyMac(byte[] mac, String label, SecretKey macKey,
byte[]... inputs); byte[]... inputs);
@@ -108,17 +132,33 @@ public interface CryptoComponent {
* storage. The encryption and authentication keys are derived from the * storage. The encryption and authentication keys are derived from the
* given password. The ciphertext will be decryptable using the same * given password. The ciphertext will be decryptable using the same
* password after the app restarts. * password after the app restarts.
*
* @param keyStrengthener Used to strengthen the password-based key. If
* null, the password-based key will not be strengthened
*/ */
byte[] encryptWithPassword(byte[] plaintext, String password); byte[] encryptWithPassword(byte[] plaintext, String password,
@Nullable KeyStrengthener keyStrengthener);
/** /**
* Decrypts and authenticates the given ciphertext that has been read from * Decrypts and authenticates the given ciphertext that has been read from
* storage. The encryption and authentication keys are derived from the * storage. The encryption and authentication keys are derived from the
* given password. Returns null if the ciphertext cannot be decrypted and * given password.
*
* @param keyStrengthener Used to strengthen the password-based key. If
* null, or if strengthening was not used when encrypting the ciphertext,
* the password-based key will not be strengthened
* @throws DecryptionException If the ciphertext cannot be decrypted and
* authenticated (for example, if the password is wrong). * authenticated (for example, if the password is wrong).
*/ */
@Nullable byte[] decryptWithPassword(byte[] ciphertext, String password,
byte[] decryptWithPassword(byte[] ciphertext, String password); @Nullable KeyStrengthener keyStrengthener)
throws DecryptionException;
/**
* Returns true if the given ciphertext was encrypted using a strengthened
* key. The validity of the ciphertext is not checked.
*/
boolean isEncryptedWithStrengthenedKey(byte[] ciphertext);
/** /**
* Encrypts the given plaintext to the given public key. * Encrypts the given plaintext to the given public key.

View File

@@ -0,0 +1,17 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@NotNullByDefault
public class DecryptionException extends Exception {
private final DecryptionResult result;
public DecryptionException(DecryptionResult result) {
this.result = result;
}
public DecryptionResult getDecryptionResult() {
return result;
}
}

View File

@@ -0,0 +1,29 @@
package org.briarproject.bramble.api.crypto;
/**
* The result of a password-based decryption operation.
*/
public enum DecryptionResult {
/**
* Decryption succeeded.
*/
SUCCESS,
/**
* Decryption failed because the format of the ciphertext was invalid.
*/
INVALID_CIPHERTEXT,
/**
* Decryption failed because the {@link KeyStrengthener} used for
* encryption was not available for decryption.
*/
KEY_STRENGTHENER_ERROR,
/**
* Decryption failed because the password used for decryption did not match
* the password used for encryption.
*/
INVALID_PASSWORD
}

View File

@@ -0,0 +1,23 @@
package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* Interface for strengthening a password-based key, for example by using a
* key stored in a key management service or hardware security module.
*/
@NotNullByDefault
public interface KeyStrengthener {
/**
* Returns true if the strengthener has been initialised.
*/
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
boolean isInitialised();
/**
* Initialises the strengthener if necessary and returns a strong key
* derived from the given key.
*/
SecretKey strengthenKey(SecretKey k);
}

View File

@@ -3,12 +3,37 @@ package org.briarproject.bramble.api.crypto;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import java.security.GeneralSecurityException;
/** /**
* Crypto operations for the transport security protocol - see * Crypto operations for the transport security protocol - see
* https://code.briarproject.org/briar/briar-spec/blob/master/protocols/BTP.md * https://code.briarproject.org/briar/briar-spec/blob/master/protocols/BTP.md
*/ */
public interface TransportCrypto { public interface TransportCrypto {
/**
* Returns true if the local peer is Alice.
*/
boolean isAlice(PublicKey theirHandshakePublicKey,
KeyPair ourHandshakeKeyPair);
/**
* Derives the static master key shared with a contact or pending contact.
*/
SecretKey deriveStaticMasterKey(PublicKey theirHandshakePublicKey,
KeyPair ourHandshakeKeyPair) throws GeneralSecurityException;
/**
* Derives the handshake mode root key from the static master key. To
* prevent tag reuse, separate root keys are derived for contacts and
* pending contacts.
*
* @param pendingContact Whether the static master key is shared with a
* pending contact or a contact
*/
SecretKey deriveHandshakeRootKey(SecretKey staticMasterKey,
boolean pendingContact);
/** /**
* Derives initial rotation mode transport keys for the given transport in * Derives initial rotation mode transport keys for the given transport in
* the given time period from the given root key. * the given time period from the given root key.

View File

@@ -1,8 +1,27 @@
package org.briarproject.bramble.api.db; package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
/** /**
* Thrown when a duplicate contact is added to the database. This exception may * 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. * occur due to concurrent updates and does not indicate a database error.
*/ */
public class ContactExistsException extends DbException { public class ContactExistsException extends DbException {
private final AuthorId local;
private final Author remote;
public ContactExistsException(AuthorId local, Author remote) {
this.local = local;
this.remote = remote;
}
public AuthorId getLocalAuthorId() {
return local;
}
public Author getRemoteAuthor() {
return remote;
}
} }

View File

@@ -29,6 +29,7 @@ import org.briarproject.bramble.api.transport.TransportKeySet;
import org.briarproject.bramble.api.transport.TransportKeys; import org.briarproject.bramble.api.transport.TransportKeys;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -38,7 +39,7 @@ import javax.annotation.Nullable;
* to other components. * to other components.
*/ */
@NotNullByDefault @NotNullByDefault
public interface DatabaseComponent { public interface DatabaseComponent extends TransactionManager {
/** /**
* Opens the database and returns true if the database already existed. * Opens the database and returns true if the database already existed.
@@ -56,56 +57,12 @@ public interface DatabaseComponent {
*/ */
void close() throws DbException; void close() throws DbException;
/**
* Starts a new transaction and returns an object representing it.
* <p/>
* This method acquires locks, so it must not be called while holding a
* lock.
*
* @param readOnly true if the transaction will only be used for reading.
*/
Transaction startTransaction(boolean readOnly) throws DbException;
/**
* Commits a transaction to the database.
*/
void commitTransaction(Transaction txn) throws DbException;
/**
* Ends a transaction. If the transaction has not been committed,
* it will be aborted. If the transaction has been committed,
* any events attached to the transaction are broadcast.
* The database lock will be released in either case.
*/
void endTransaction(Transaction txn);
/**
* Runs the given task within a transaction.
*/
<E extends Exception> void transaction(boolean readOnly,
DbRunnable<E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task.
*/
<R, E extends Exception> R transactionWithResult(boolean readOnly,
DbCallable<R, E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task, which may be null.
*/
@Nullable
<R, E extends Exception> R transactionWithNullableResult(boolean readOnly,
NullableDbCallable<R, E> task) throws DbException, E;
/** /**
* Stores a contact associated with the given local and remote pseudonyms, * Stores a contact associated with the given local and remote pseudonyms,
* and returns an ID for the contact. * and returns an ID for the contact.
*/ */
ContactId addContact(Transaction txn, Author remote, AuthorId local, ContactId addContact(Transaction txn, Author remote, AuthorId local,
boolean verified) throws DbException; @Nullable PublicKey handshake, boolean verified) throws DbException;
/** /**
* Stores a group. * Stores a group.
@@ -121,12 +78,12 @@ public interface DatabaseComponent {
* Stores a local message. * Stores a local message.
*/ */
void addLocalMessage(Transaction txn, Message m, Metadata meta, void addLocalMessage(Transaction txn, Message m, Metadata meta,
boolean shared) throws DbException; boolean shared, boolean temporary) throws DbException;
/** /**
* Stores a pending contact. * Stores a pending contact.
*/ */
void addPendingContact(Transaction txn, PendingContact p) void addPendingContact(Transaction txn, PendingContact p, AuthorId local)
throws DbException; throws DbException;
/** /**
@@ -448,6 +405,14 @@ public interface DatabaseComponent {
*/ */
long getNextSendTime(Transaction txn, ContactId c) throws DbException; long getNextSendTime(Transaction txn, ContactId c) throws DbException;
/**
* Returns the pending contact with the given ID.
* <p/>
* Read-only.
*/
PendingContact getPendingContact(Transaction txn, PendingContactId p)
throws DbException;
/** /**
* Returns all pending contacts. * Returns all pending contacts.
* <p/> * <p/>
@@ -463,6 +428,13 @@ public interface DatabaseComponent {
*/ */
Settings getSettings(Transaction txn, String namespace) throws DbException; Settings getSettings(Transaction txn, String namespace) throws DbException;
/**
* Returns the versions of the sync protocol supported by the given contact.
* <p/>
* Read-only.
*/
List<Byte> getSyncVersions(Transaction txn, ContactId c) throws DbException;
/** /**
* Returns all transport keys for the given transport. * Returns all transport keys for the given transport.
* <p/> * <p/>
@@ -546,6 +518,12 @@ public interface DatabaseComponent {
void removePendingContact(Transaction txn, PendingContactId p) void removePendingContact(Transaction txn, PendingContactId p)
throws DbException; throws DbException;
/**
* Removes all temporary messages (and all associated state) from the
* database.
*/
void removeTemporaryMessages(Transaction txn) throws DbException;
/** /**
* Removes a transport (and all associated state) from the database. * Removes a transport (and all associated state) from the database.
*/ */
@@ -574,6 +552,11 @@ public interface DatabaseComponent {
void setGroupVisibility(Transaction txn, ContactId c, GroupId g, void setGroupVisibility(Transaction txn, ContactId c, GroupId g,
Visibility v) throws DbException; Visibility v) throws DbException;
/**
* Marks the given message as permanent, i.e. not temporary.
*/
void setMessagePermanent(Transaction txn, MessageId m) throws DbException;
/** /**
* Marks the given message as shared. * Marks the given message as shared.
*/ */
@@ -604,6 +587,12 @@ public interface DatabaseComponent {
void setReorderingWindow(Transaction txn, KeySetId k, TransportId t, void setReorderingWindow(Transaction txn, KeySetId k, TransportId t,
long timePeriod, long base, byte[] bitmap) throws DbException; long timePeriod, long base, byte[] bitmap) throws DbException;
/**
* Sets the versions of the sync protocol supported by the given contact.
*/
void setSyncVersions(Transaction txn, ContactId c, List<Byte> supported)
throws DbException;
/** /**
* Marks the given transport keys as usable for outgoing streams. * Marks the given transport keys as usable for outgoing streams.
*/ */

View File

@@ -1,13 +1,29 @@
package org.briarproject.bramble.api.db; package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.crypto.KeyStrengthener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.File; import java.io.File;
import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface DatabaseConfig { public interface DatabaseConfig {
/**
* Returns the directory where the database stores its data.
*/
File getDatabaseDirectory(); File getDatabaseDirectory();
/**
* Returns the directory where the encrypted database key is stored.
*/
File getDatabaseKeyDirectory(); File getDatabaseKeyDirectory();
/**
* Returns a {@link KeyStrengthener} for strengthening the encryption of
* the database key, or null if no strengthener should be used.
*/
@Nullable
KeyStrengthener getKeyStrengthener();
} }

View File

@@ -1,9 +1,21 @@
package org.briarproject.bramble.api.db; package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.contact.PendingContact;
/** /**
* Thrown when a duplicate pending contact is added to the database. This * Thrown when a duplicate pending contact is added to the database. This
* exception may occur due to concurrent updates and does not indicate a * exception may occur due to concurrent updates and does not indicate a
* database error. * database error.
*/ */
public class PendingContactExistsException extends DbException { public class PendingContactExistsException extends DbException {
private final PendingContact pendingContact;
public PendingContactExistsException(PendingContact pendingContact) {
this.pendingContact = pendingContact;
}
public PendingContact getPendingContact() {
return pendingContact;
}
} }

View File

@@ -0,0 +1,54 @@
package org.briarproject.bramble.api.db;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface TransactionManager {
/**
* Starts a new transaction and returns an object representing it.
* <p/>
* This method acquires locks, so it must not be called while holding a
* lock.
*
* @param readOnly true if the transaction will only be used for reading.
*/
Transaction startTransaction(boolean readOnly) throws DbException;
/**
* Commits a transaction to the database.
*/
void commitTransaction(Transaction txn) throws DbException;
/**
* Ends a transaction. If the transaction has not been committed,
* it will be aborted. If the transaction has been committed,
* any events attached to the transaction are broadcast.
* The database lock will be released in either case.
*/
void endTransaction(Transaction txn);
/**
* Runs the given task within a transaction.
*/
<E extends Exception> void transaction(boolean readOnly,
DbRunnable<E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task.
*/
<R, E extends Exception> R transactionWithResult(boolean readOnly,
DbCallable<R, E> task) throws DbException, E;
/**
* Runs the given task within a transaction and returns the result of the
* task, which may be null.
*/
@Nullable
<R, E extends Exception> R transactionWithNullableResult(boolean readOnly,
NullableDbCallable<R, E> task) throws DbException, E;
}

View File

@@ -18,6 +18,8 @@ public interface EventBus {
/** /**
* Asynchronously notifies all listeners of an event. Listeners are * Asynchronously notifies all listeners of an event. Listeners are
* notified on the {@link EventExecutor}. * notified on the {@link EventExecutor}.
* <p>
* This method can safely be called while holding a lock.
*/ */
void broadcast(Event e); void broadcast(Event e);
} }

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.io;
import java.io.InputStream;
public interface TimeoutMonitor {
/**
* Returns an {@link InputStream} that wraps the given stream and allows
* read timeouts to be detected.
*
* @param timeoutMs The read timeout in milliseconds. Timeouts will be
* detected eventually but are not guaranteed to be detected immediately.
*/
InputStream createTimeoutInputStream(InputStream in, long timeoutMs);
}

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.data.BdfList;
import java.io.IOException; import java.io.IOException;
/** /**
* An class for managing a particular key agreement listener. * Accepts key agreement connections over a given transport.
*/ */
public abstract class KeyAgreementListener { public abstract class KeyAgreementListener {

View File

@@ -22,4 +22,11 @@ public class NullSafety {
@Nullable Object b) { @Nullable Object b) {
if ((a == null) == (b == null)) throw new AssertionError(); if ((a == null) == (b == null)) throw new AssertionError();
} }
/**
* Checks that the argument is null.
*/
public static void requireNull(@Nullable Object o) {
if (o != null) throw new AssertionError();
}
} }

View File

@@ -8,6 +8,4 @@ public interface BluetoothConstants {
String PROP_ADDRESS = "address"; String PROP_ADDRESS = "address";
String PROP_UUID = "uuid"; String PROP_UUID = "uuid";
String PREF_BT_ENABLE = "enable";
} }

View File

@@ -0,0 +1,28 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.duplex.DuplexPlugin;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
/**
* An interface for handling connections created by transport plugins.
*/
@NotNullByDefault
public interface ConnectionHandler {
/**
* Handles a connection created by a {@link DuplexPlugin}.
*/
void handleConnection(DuplexTransportConnection c);
/**
* Handles a reader created by a {@link SimplexPlugin}.
*/
void handleReader(TransportConnectionReader r);
/**
* Handles a writer created by a {@link SimplexPlugin}.
*/
void handleWriter(TransportConnectionWriter w);
}

View File

@@ -1,17 +0,0 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.plugin.duplex.DuplexTransportConnection;
public interface ConnectionManager {
void manageIncomingConnection(TransportId t, TransportConnectionReader r);
void manageIncomingConnection(TransportId t, DuplexTransportConnection d);
void manageOutgoingConnection(ContactId c, TransportId t,
TransportConnectionWriter w);
void manageOutgoingConnection(ContactId c, TransportId t,
DuplexTransportConnection d);
}

View File

@@ -1,23 +0,0 @@
package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection;
/**
* Keeps track of which contacts are currently connected by which transports.
*/
@NotNullByDefault
public interface ConnectionRegistry {
void registerConnection(ContactId c, TransportId t, boolean incoming);
void unregisterConnection(ContactId c, TransportId t, boolean incoming);
Collection<ContactId> getConnectedContacts(TransportId t);
boolean isConnected(ContactId c, TransportId t);
boolean isConnected(ContactId c);
}

View File

@@ -4,10 +4,12 @@ public interface LanTcpConstants {
TransportId ID = new TransportId("org.briarproject.bramble.lan"); TransportId ID = new TransportId("org.briarproject.bramble.lan");
// a transport property (shared with contacts) // Transport properties (shared with contacts)
String PROP_IP_PORTS = "ipPorts"; String PROP_IP_PORTS = "ipPorts";
String PROP_PORT = "port";
String PROP_IPV6 = "ipv6";
// a local setting // Local settings (not shared with contacts)
String PREF_LAN_IP_PORTS = "ipPorts"; String PREF_LAN_IP_PORTS = "ipPorts";
String PREF_IPV6 = "ipv6";
} }

View File

@@ -1,14 +1,57 @@
package org.briarproject.bramble.api.plugin; package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.Pair;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.SettingsManager;
import java.util.Map; import java.util.Collection;
@NotNullByDefault @NotNullByDefault
public interface Plugin { public interface Plugin {
enum State {
/**
* The plugin has not finished starting or has been stopped.
*/
STARTING_STOPPING,
/**
* The plugin is disabled by settings. Use {@link #getReasonsDisabled()}
* to find out which settings are responsible.
*/
DISABLED,
/**
* The plugin is being enabled and can't yet make or receive
* connections.
*/
ENABLING,
/**
* The plugin is enabled and can make or receive connections.
*/
ACTIVE,
/**
* The plugin is enabled but can't make or receive connections
*/
INACTIVE
}
/**
* The string for the boolean preference
* to use with the {@link SettingsManager} to enable or disable the plugin.
*/
String PREF_PLUGIN_ENABLE = "enable";
/**
* Reason flag returned by {@link #getReasonsDisabled()} to indicate that
* the plugin has been disabled by the user.
*/
int REASON_USER = 1;
/** /**
* Returns the plugin's transport identifier. * Returns the plugin's transport identifier.
*/ */
@@ -35,9 +78,18 @@ public interface Plugin {
void stop() throws PluginException; void stop() throws PluginException;
/** /**
* Returns true if the plugin is running. * Returns the current state of the plugin.
*/ */
boolean isRunning(); State getState();
/**
* Returns a set of flags indicating why the plugin is
* {@link State#DISABLED disabled}, or 0 if the plugin is not disabled.
* <p>
* The flags used are plugin-specific, except the generic flag
* {@link #REASON_USER}, which may be used by any plugin.
*/
int getReasonsDisabled();
/** /**
* Returns true if the plugin should be polled periodically to attempt to * Returns true if the plugin should be polled periodically to attempt to
@@ -51,8 +103,9 @@ public interface Plugin {
int getPollingInterval(); int getPollingInterval();
/** /**
* Attempts to establish connections to the given contacts, passing any * Attempts to create connections using the given transport properties,
* created connections to the callback. * passing any created connections to the corresponding handlers.
*/ */
void poll(Map<ContactId, TransportProperties> contacts); void poll(Collection<Pair<TransportProperties, ConnectionHandler>>
properties);
} }

View File

@@ -1,6 +1,10 @@
package org.briarproject.bramble.api.plugin; package org.briarproject.bramble.api.plugin;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.event.TransportActiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportInactiveEvent;
import org.briarproject.bramble.api.plugin.event.TransportStateEvent;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.settings.Settings; import org.briarproject.bramble.api.settings.Settings;
@@ -9,7 +13,7 @@ import org.briarproject.bramble.api.settings.Settings;
* the application. * the application.
*/ */
@NotNullByDefault @NotNullByDefault
public interface PluginCallback { public interface PluginCallback extends ConnectionHandler {
/** /**
* Returns the plugin's settings * Returns the plugin's settings
@@ -32,12 +36,17 @@ public interface PluginCallback {
void mergeLocalProperties(TransportProperties p); void mergeLocalProperties(TransportProperties p);
/** /**
* Signals that the transport is enabled. * Informs the callback of the plugin's current state.
* <p>
* If the current state is different from the previous state, the callback
* will broadcast a {@link TransportStateEvent}. If the current state is
* {@link State#ACTIVE} and the previous state was not
* {@link State#ACTIVE}, the callback will broadcast a
* {@link TransportActiveEvent}. If the current state is not
* {@link State#ACTIVE} and the previous state was {@link State#ACTIVE},
* the callback will broadcast a {@link TransportInactiveEvent}.
* <p>
* This method can safely be called while holding a lock.
*/ */
void transportEnabled(); void pluginStateChanged(State state);
/**
* Signals that the transport is disabled.
*/
void transportDisabled();
} }

View File

@@ -5,6 +5,8 @@ import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map;
@NotNullByDefault @NotNullByDefault
public interface PluginConfig { public interface PluginConfig {
@@ -14,4 +16,11 @@ public interface PluginConfig {
Collection<SimplexPluginFactory> getSimplexFactories(); Collection<SimplexPluginFactory> getSimplexFactories();
boolean shouldPoll(); boolean shouldPoll();
/**
* Returns a map representing transport preferences. For each entry in the
* map, connections via the transports identified by the value are
* preferred to connections via the transport identified by the key.
*/
Map<TransportId, List<TransportId>> getTransportPreferences();
} }

View File

@@ -36,4 +36,22 @@ public interface PluginManager {
* Returns any duplex plugins that support key agreement. * Returns any duplex plugins that support key agreement.
*/ */
Collection<DuplexPlugin> getKeyAgreementPlugins(); Collection<DuplexPlugin> getKeyAgreementPlugins();
/**
* Returns any duplex plugins that support rendezvous.
*/
Collection<DuplexPlugin> getRendezvousPlugins();
/**
* Enables or disables the plugin
* identified by the given {@link TransportId}.
* <p>
* Note that this applies the change asynchronously
* and there are no order guarantees.
* <p>
* If no plugin with the given {@link TransportId} is registered,
* this is a no-op.
*/
void setPluginEnabled(TransportId t, boolean enabled);
} }

View File

@@ -21,6 +21,21 @@ public interface TorConstants {
int PREF_TOR_NETWORK_AUTOMATIC = 0; int PREF_TOR_NETWORK_AUTOMATIC = 0;
int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1; int PREF_TOR_NETWORK_WITHOUT_BRIDGES = 1;
int PREF_TOR_NETWORK_WITH_BRIDGES = 2; int PREF_TOR_NETWORK_WITH_BRIDGES = 2;
// TODO: Remove when settings migration code is removed
int PREF_TOR_NETWORK_NEVER = 3; int PREF_TOR_NETWORK_NEVER = 3;
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
*/
int REASON_BATTERY = 2;
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
*/
int REASON_MOBILE_DATA = 4;
/**
* Reason flag returned by {@link Plugin#getReasonsDisabled()}.
*/
int REASON_COUNTRY_BLOCKED = 8;
} }

View File

@@ -4,6 +4,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.plugin.TransportConnectionReader; import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter; import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -14,6 +15,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
public abstract class AbstractDuplexTransportConnection public abstract class AbstractDuplexTransportConnection
implements DuplexTransportConnection { implements DuplexTransportConnection {
protected final TransportProperties remote = new TransportProperties();
private final Plugin plugin; private final Plugin plugin;
private final Reader reader; private final Reader reader;
private final Writer writer; private final Writer writer;
@@ -44,6 +47,11 @@ public abstract class AbstractDuplexTransportConnection
return writer; return writer;
} }
@Override
public TransportProperties getRemoteProperties() {
return remote;
}
private class Reader implements TransportConnectionReader { private class Reader implements TransportConnectionReader {
@Override @Override

View File

@@ -3,8 +3,11 @@ package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.data.BdfList; import org.briarproject.bramble.api.data.BdfList;
import org.briarproject.bramble.api.keyagreement.KeyAgreementListener; import org.briarproject.bramble.api.keyagreement.KeyAgreementListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.ConnectionHandler;
import org.briarproject.bramble.api.plugin.Plugin; import org.briarproject.bramble.api.plugin.Plugin;
import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.properties.TransportProperties;
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
import org.briarproject.bramble.api.rendezvous.RendezvousEndpoint;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -40,4 +43,19 @@ public interface DuplexPlugin extends Plugin {
@Nullable @Nullable
DuplexTransportConnection createKeyAgreementConnection( DuplexTransportConnection createKeyAgreementConnection(
byte[] remoteCommitment, BdfList descriptor); byte[] remoteCommitment, BdfList descriptor);
/**
* Returns true if the plugin supports rendezvous connections.
*/
boolean supportsRendezvous();
/**
* Creates and returns an endpoint that uses the given key material to
* rendezvous with a pending contact, and the given connection handler to
* handle incoming connections. Returns null if an endpoint cannot be
* created.
*/
@Nullable
RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
boolean alice, ConnectionHandler incoming);
} }

View File

@@ -1,17 +0,0 @@
package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
/**
* An interface through which a duplex plugin interacts with the rest of the
* application.
*/
@NotNullByDefault
public interface DuplexPluginCallback extends PluginCallback {
void incomingConnectionCreated(DuplexTransportConnection d);
void outgoingConnectionCreated(ContactId c, DuplexTransportConnection d);
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.plugin.duplex; package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -25,5 +26,5 @@ public interface DuplexPluginFactory {
* Creates and returns a plugin, or null if no plugin can be created. * Creates and returns a plugin, or null if no plugin can be created.
*/ */
@Nullable @Nullable
DuplexPlugin createPlugin(DuplexPluginCallback callback); DuplexPlugin createPlugin(PluginCallback callback);
} }

View File

@@ -3,6 +3,7 @@ package org.briarproject.bramble.api.plugin.duplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportConnectionReader; import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter; import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
import org.briarproject.bramble.api.properties.TransportProperties;
/** /**
* An interface for reading and writing data over a duplex transport. The * An interface for reading and writing data over a duplex transport. The
@@ -23,4 +24,10 @@ public interface DuplexTransportConnection {
* for writing to the connection. * for writing to the connection.
*/ */
TransportConnectionWriter getWriter(); TransportConnectionWriter getWriter();
/**
* Returns a possibly empty set of {@link TransportProperties} describing
* the remote peer.
*/
TransportProperties getRemoteProperties();
} }

View File

@@ -13,13 +13,14 @@ public class ConnectionClosedEvent extends Event {
private final ContactId contactId; private final ContactId contactId;
private final TransportId transportId; private final TransportId transportId;
private final boolean incoming; private final boolean incoming, exception;
public ConnectionClosedEvent(ContactId contactId, TransportId transportId, public ConnectionClosedEvent(ContactId contactId, TransportId transportId,
boolean incoming) { boolean incoming, boolean exception) {
this.contactId = contactId; this.contactId = contactId;
this.transportId = transportId; this.transportId = transportId;
this.incoming = incoming; this.incoming = incoming;
this.exception = exception;
} }
public ContactId getContactId() { public ContactId getContactId() {
@@ -33,4 +34,8 @@ public class ConnectionClosedEvent extends Event {
public boolean isIncoming() { public boolean isIncoming() {
return incoming; return incoming;
} }
public boolean isException() {
return exception;
}
} }

View File

@@ -2,20 +2,22 @@ package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
/** /**
* An event that is broadcast when a transport is disabled. * An event that is broadcast when a plugin enters the {@link State#ACTIVE}
* state.
*/ */
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class TransportDisabledEvent extends Event { public class TransportActiveEvent extends Event {
private final TransportId transportId; private final TransportId transportId;
public TransportDisabledEvent(TransportId transportId) { public TransportActiveEvent(TransportId transportId) {
this.transportId = transportId; this.transportId = transportId;
} }

View File

@@ -2,20 +2,22 @@ package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event; import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.Immutable;
/** /**
* An event that is broadcast when a transport is enabled. * An event that is broadcast when a plugin leaves the {@link State#ACTIVE}
* state.
*/ */
@Immutable @Immutable
@NotNullByDefault @NotNullByDefault
public class TransportEnabledEvent extends Event { public class TransportInactiveEvent extends Event {
private final TransportId transportId; private final TransportId transportId;
public TransportEnabledEvent(TransportId transportId) { public TransportInactiveEvent(TransportId transportId) {
this.transportId = transportId; this.transportId = transportId;
} }

View File

@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.plugin.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.Plugin.State;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when the {@link State state} of a plugin changes.
*/
@Immutable
@NotNullByDefault
public class TransportStateEvent extends Event {
private final TransportId transportId;
private final State state;
public TransportStateEvent(TransportId transportId, State state) {
this.transportId = transportId;
this.state = state;
}
public TransportId getTransportId() {
return transportId;
}
public State getState() {
return state;
}
}

View File

@@ -1,19 +0,0 @@
package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportConnectionReader;
import org.briarproject.bramble.api.plugin.TransportConnectionWriter;
/**
* An interface through which a simplex plugin interacts with the rest of the
* application.
*/
@NotNullByDefault
public interface SimplexPluginCallback extends PluginCallback {
void readerCreated(TransportConnectionReader r);
void writerCreated(ContactId c, TransportConnectionWriter w);
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.bramble.api.plugin.simplex; package org.briarproject.bramble.api.plugin.simplex;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.PluginCallback;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -25,5 +26,5 @@ public interface SimplexPluginFactory {
* Creates and returns a plugin, or null if no plugin can be created. * Creates and returns a plugin, or null if no plugin can be created.
*/ */
@Nullable @Nullable
SimplexPlugin createPlugin(SimplexPluginCallback callback); SimplexPlugin createPlugin(PluginCallback callback);
} }

View File

@@ -11,4 +11,28 @@ public interface TransportPropertyConstants {
* The maximum length of a property's key or value in UTF-8 bytes. * The maximum length of a property's key or value in UTF-8 bytes.
*/ */
int MAX_PROPERTY_LENGTH = 100; int MAX_PROPERTY_LENGTH = 100;
/**
* Message metadata key for the transport ID of a local or remote update,
* as a BDF string.
*/
String MSG_KEY_TRANSPORT_ID = "transportId";
/**
* Message metadata key for the version number of a local or remote update,
* as a BDF long.
*/
String MSG_KEY_VERSION = "version";
/**
* Message metadata key for whether an update is local or remote, as a BDF
* boolean.
*/
String MSG_KEY_LOCAL = "local";
/**
* Group metadata key for any discovered transport properties of the
* contact, as a BDF dictionary.
*/
String GROUP_KEY_DISCOVERED = "discovered";
} }

View File

@@ -34,6 +34,14 @@ public interface TransportPropertyManager {
void addRemoteProperties(Transaction txn, ContactId c, void addRemoteProperties(Transaction txn, ContactId c,
Map<TransportId, TransportProperties> props) throws DbException; Map<TransportId, TransportProperties> props) throws DbException;
/**
* Stores the given properties discovered from an incoming transport
* connection. They will be overridden by any properties received while
* adding the contact or synced from the contact.
*/
void addRemotePropertiesFromConnection(ContactId c, TransportId t,
TransportProperties props) throws DbException;
/** /**
* Returns the local transport properties for all transports. * Returns the local transport properties for all transports.
*/ */

View File

@@ -1,10 +1,14 @@
package org.briarproject.bramble.api.record; package org.briarproject.bramble.api.record;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.Predicate;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface RecordReader { public interface RecordReader {
@@ -16,5 +20,20 @@ public interface RecordReader {
*/ */
Record readRecord() throws IOException; Record readRecord() throws IOException;
/**
* Reads and returns the next record matching the 'accept' predicate,
* skipping any records that match the 'ignore' predicate. Returns null if
* no record matching the 'accept' predicate is found before the end of the
* stream.
*
* @throws EOFException If the end of the stream is reached without
* reading a complete record
* @throws FormatException If a record is read that does not match the
* 'accept' or 'ignore' predicates
*/
@Nullable
Record readRecord(Predicate<Record> accept, Predicate<Record> ignore)
throws IOException;
void close() throws IOException; void close() throws IOException;
} }

View File

@@ -0,0 +1,15 @@
package org.briarproject.bramble.api.rendezvous;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* A source of key material for use in making rendezvous connections.
*/
@NotNullByDefault
public interface KeyMaterialSource {
/**
* Returns the requested amount of key material.
*/
byte[] getKeyMaterial(int length);
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api.rendezvous;
import org.briarproject.bramble.api.properties.TransportProperties;
import java.io.Closeable;
import java.io.IOException;
/**
* An interface for making and accepting rendezvous connections with a pending
* contact over a given transport.
*/
public interface RendezvousEndpoint extends Closeable {
/**
* Returns a set of transport properties for connecting to the pending
* contact.
*/
TransportProperties getRemoteTransportProperties();
/**
* Closes the handler and releases any resources held by it, such as
* network sockets.
*/
@Override
void close() throws IOException;
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.rendezvous;
import org.briarproject.bramble.api.contact.PendingContactId;
/**
* Interface for the poller that makes rendezvous connections to pending
* contacts.
*/
public interface RendezvousPoller {
long getLastPollTime(PendingContactId p);
}

View File

@@ -0,0 +1,32 @@
package org.briarproject.bramble.api.rendezvous.event;
import org.briarproject.bramble.api.contact.PendingContactId;
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 rendezvous connection is closed.
*/
@Immutable
@NotNullByDefault
public class RendezvousConnectionClosedEvent extends Event {
private final PendingContactId pendingContactId;
private final boolean success;
public RendezvousConnectionClosedEvent(PendingContactId pendingContactId,
boolean success) {
this.pendingContactId = pendingContactId;
this.success = success;
}
public PendingContactId getPendingContactId() {
return pendingContactId;
}
public boolean isSuccess() {
return success;
}
}

View File

@@ -0,0 +1,25 @@
package org.briarproject.bramble.api.rendezvous.event;
import org.briarproject.bramble.api.contact.PendingContactId;
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 rendezvous connection is opened.
*/
@Immutable
@NotNullByDefault
public class RendezvousConnectionOpenedEvent extends Event {
private final PendingContactId pendingContactId;
public RendezvousConnectionOpenedEvent(PendingContactId pendingContactId) {
this.pendingContactId = pendingContactId;
}
public PendingContactId getPendingContactId() {
return pendingContactId;
}
}

View File

@@ -0,0 +1,36 @@
package org.briarproject.bramble.api.rendezvous.event;
import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import java.util.Collection;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a transport plugin is polled for connections
* to one or more pending contacts.
*/
@Immutable
@NotNullByDefault
public class RendezvousPollEvent extends Event {
private final TransportId transportId;
private final Collection<PendingContactId> pendingContacts;
public RendezvousPollEvent(TransportId transportId,
Collection<PendingContactId> pendingContacts) {
this.transportId = transportId;
this.pendingContacts = pendingContacts;
}
public TransportId getTransportId() {
return transportId;
}
public Collection<PendingContactId> getPendingContacts() {
return pendingContacts;
}
}

View File

@@ -1,10 +1,16 @@
package org.briarproject.bramble.api.sync; package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection; import java.util.Collection;
import javax.annotation.concurrent.Immutable;
/** /**
* A record acknowledging receipt of one or more {@link Message Messages}. * A record acknowledging receipt of one or more {@link Message Messages}.
*/ */
@Immutable
@NotNullByDefault
public class Ack { public class Ack {
private final Collection<MessageId> acked; private final Collection<MessageId> acked;

View File

@@ -1,8 +1,14 @@
package org.briarproject.bramble.api.sync; package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH; import static org.briarproject.bramble.api.sync.SyncConstants.MESSAGE_HEADER_LENGTH;
@Immutable
@NotNullByDefault
public class Message { public class Message {
/** /**

View File

@@ -1,10 +1,16 @@
package org.briarproject.bramble.api.sync; package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection; import java.util.Collection;
import javax.annotation.concurrent.Immutable;
/** /**
* A record offering the recipient one or more {@link Message Messages}. * A record offering the recipient one or more {@link Message Messages}.
*/ */
@Immutable
@NotNullByDefault
public class Offer { public class Offer {
private final Collection<MessageId> offered; private final Collection<MessageId> offered;

View File

@@ -0,0 +1,23 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* A record containing a nonce for choosing between redundant sessions.
*/
@Immutable
@NotNullByDefault
public class Priority {
private final byte[] nonce;
public Priority(byte[] nonce) {
this.nonce = nonce;
}
public byte[] getNonce() {
return nonce;
}
}

View File

@@ -0,0 +1,13 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
/**
* An interface for handling a {@link Priority} record received by an
* incoming {@link SyncSession}.
*/
@NotNullByDefault
public interface PriorityHandler {
void handle(Priority p);
}

View File

@@ -9,5 +9,6 @@ public interface RecordTypes {
byte MESSAGE = 1; byte MESSAGE = 1;
byte OFFER = 2; byte OFFER = 2;
byte REQUEST = 3; byte REQUEST = 3;
byte VERSIONS = 4;
byte PRIORITY = 5;
} }

View File

@@ -1,10 +1,16 @@
package org.briarproject.bramble.api.sync; package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection; import java.util.Collection;
import javax.annotation.concurrent.Immutable;
/** /**
* A record requesting one or more {@link Message Messages} from the recipient. * A record requesting one or more {@link Message Messages} from the recipient.
*/ */
@Immutable
@NotNullByDefault
public class Request { public class Request {
private final Collection<MessageId> requested; private final Collection<MessageId> requested;

View File

@@ -2,6 +2,9 @@ package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.UniqueId; import org.briarproject.bramble.api.UniqueId;
import java.util.List;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES; import static org.briarproject.bramble.api.record.Record.MAX_RECORD_PAYLOAD_BYTES;
public interface SyncConstants { public interface SyncConstants {
@@ -11,6 +14,11 @@ public interface SyncConstants {
*/ */
byte PROTOCOL_VERSION = 0; byte PROTOCOL_VERSION = 0;
/**
* The versions of the sync protocol this peer supports.
*/
List<Byte> SUPPORTED_VERSIONS = singletonList(PROTOCOL_VERSION);
/** /**
* The maximum length of a group descriptor in bytes. * The maximum length of a group descriptor in bytes.
*/ */
@@ -35,4 +43,16 @@ public interface SyncConstants {
* The maximum number of message IDs in an ack, offer or request record. * The maximum number of message IDs in an ack, offer or request record.
*/ */
int MAX_MESSAGE_IDS = MAX_RECORD_PAYLOAD_BYTES / UniqueId.LENGTH; int MAX_MESSAGE_IDS = MAX_RECORD_PAYLOAD_BYTES / UniqueId.LENGTH;
/**
* The maximum number of versions of the sync protocol a peer may support
* simultaneously.
*/
int MAX_SUPPORTED_VERSIONS = 10;
/**
* The length of the priority nonce used for choosing between redundant
* connections.
*/
int PRIORITY_NONCE_BYTES = 16;
} }

View File

@@ -25,4 +25,11 @@ public interface SyncRecordReader {
Request readRequest() throws IOException; Request readRequest() throws IOException;
boolean hasVersions() throws IOException;
Versions readVersions() throws IOException;
boolean hasPriority() throws IOException;
Priority readPriority() throws IOException;
} }

View File

@@ -15,5 +15,9 @@ public interface SyncRecordWriter {
void writeRequest(Request r) throws IOException; void writeRequest(Request r) throws IOException;
void writeVersions(Versions v) throws IOException;
void writePriority(Priority p) throws IOException;
void flush() throws IOException; void flush() throws IOException;
} }

View File

@@ -2,18 +2,23 @@ package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.StreamWriter; import org.briarproject.bramble.api.transport.StreamWriter;
import java.io.InputStream; import java.io.InputStream;
import javax.annotation.Nullable;
@NotNullByDefault @NotNullByDefault
public interface SyncSessionFactory { public interface SyncSessionFactory {
SyncSession createIncomingSession(ContactId c, InputStream in); SyncSession createIncomingSession(ContactId c, InputStream in,
PriorityHandler handler);
SyncSession createSimplexOutgoingSession(ContactId c, int maxLatency, SyncSession createSimplexOutgoingSession(ContactId c, TransportId t,
StreamWriter streamWriter); int maxLatency, StreamWriter streamWriter);
SyncSession createDuplexOutgoingSession(ContactId c, int maxLatency, SyncSession createDuplexOutgoingSession(ContactId c, TransportId t,
int maxIdleTime, StreamWriter streamWriter); int maxLatency, int maxIdleTime, StreamWriter streamWriter,
@Nullable Priority priority);
} }

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api.sync;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import javax.annotation.concurrent.Immutable;
/**
* A record telling the recipient which versions of the sync protocol the
* sender supports.
*/
@Immutable
@NotNullByDefault
public class Versions {
private final List<Byte> supported;
public Versions(List<Byte> supported) {
this.supported = supported;
}
public List<Byte> getSupportedVersions() {
return supported;
}
}

View File

@@ -0,0 +1,26 @@
package org.briarproject.bramble.api.sync.event;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.plugin.TransportId;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when all sync connections using a given
* transport should be closed.
*/
@Immutable
@NotNullByDefault
public class CloseSyncConnectionsEvent extends Event {
private final TransportId transportId;
public CloseSyncConnectionsEvent(TransportId transportId) {
this.transportId = transportId;
}
public TransportId getTransportId() {
return transportId;
}
}

View File

@@ -0,0 +1,34 @@
package org.briarproject.bramble.api.sync.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.List;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when the versions of the sync protocol supported
* by a contact are updated.
*/
@Immutable
@NotNullByDefault
public class SyncVersionsUpdatedEvent extends Event {
private final ContactId contactId;
private final List<Byte> supported;
public SyncVersionsUpdatedEvent(ContactId contactId, List<Byte> supported) {
this.contactId = contactId;
this.supported = supported;
}
public ContactId getContactId() {
return contactId;
}
public List<Byte> getSupportedVersions() {
return supported;
}
}

View File

@@ -2,11 +2,14 @@ package org.briarproject.bramble.api.transport;
import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.PendingContactId; import org.briarproject.bramble.api.contact.PendingContactId;
import org.briarproject.bramble.api.crypto.KeyPair;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction; import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.plugin.TransportId; import org.briarproject.bramble.api.plugin.TransportId;
import java.security.GeneralSecurityException;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -18,9 +21,9 @@ import javax.annotation.Nullable;
public interface KeyManager { public interface KeyManager {
/** /**
* Informs the key manager that a new contact has been added. Derives and * Derives and stores a set of rotation mode transport keys for
* stores a set of rotation mode transport keys for communicating with the * communicating with the given contact over each transport and returns the
* contact over each transport and returns the key set IDs. * key set IDs.
* <p/> * <p/>
* {@link StreamContext StreamContexts} for the contact can be created * {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned. * after this method has returned.
@@ -28,7 +31,7 @@ public interface KeyManager {
* @param alice True if the local party is Alice * @param alice True if the local party is Alice
* @param active Whether the derived keys can be used for outgoing streams * @param active Whether the derived keys can be used for outgoing streams
*/ */
Map<TransportId, KeySetId> addContactWithRotationKeys(Transaction txn, Map<TransportId, KeySetId> addRotationKeys(Transaction txn,
ContactId c, SecretKey rootKey, long timestamp, boolean alice, ContactId c, SecretKey rootKey, long timestamp, boolean alice,
boolean active) throws DbException; boolean active) throws DbException;
@@ -39,11 +42,10 @@ public interface KeyManager {
* <p/> * <p/>
* {@link StreamContext StreamContexts} for the contact can be created * {@link StreamContext StreamContexts} for the contact can be created
* after this method has returned. * after this method has returned.
*
* @param alice True if the local party is Alice
*/ */
Map<TransportId, KeySetId> addContactWithHandshakeKeys(Transaction txn, Map<TransportId, KeySetId> addContact(Transaction txn, ContactId c,
ContactId c, SecretKey rootKey, boolean alice) throws DbException; PublicKey theirPublicKey, KeyPair ourKeyPair)
throws DbException, GeneralSecurityException;
/** /**
* Informs the key manager that a new pending contact has been added. * Informs the key manager that a new pending contact has been added.
@@ -53,12 +55,10 @@ public interface KeyManager {
* <p/> * <p/>
* {@link StreamContext StreamContexts} for the pending contact can be * {@link StreamContext StreamContexts} for the pending contact can be
* created after this method has returned. * created after this method has returned.
*
* @param alice True if the local party is Alice
*/ */
Map<TransportId, KeySetId> addPendingContact(Transaction txn, Map<TransportId, KeySetId> addPendingContact(Transaction txn,
PendingContactId p, SecretKey rootKey, boolean alice) PendingContactId p, PublicKey theirPublicKey, KeyPair ourKeyPair)
throws DbException; throws DbException, GeneralSecurityException;
/** /**
* Marks the given transport keys as usable for outgoing streams. * Marks the given transport keys as usable for outgoing streams.

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