diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-11-22 12:18:30 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-11-22 12:18:30 -0300 |
| commit | ef3f533878771a470e5600e8dde13011365bb5d3 (patch) | |
| tree | e5665e1dc2e337f9dedc857eb084db159f1e5a31 | |
| parent | 37261f0d5c214b926053329bf24d8e7bd1efbfcb (diff) | |
| parent | 6677eede732ab9ba6687229caf498d0df8874f11 (diff) | |
| download | mullvadvpn-ef3f533878771a470e5600e8dde13011365bb5d3.tar.xz mullvadvpn-ef3f533878771a470e5600e8dde13011365bb5d3.zip | |
Merge branch 'use-jnix'
48 files changed, 475 insertions, 1053 deletions
diff --git a/Cargo.lock b/Cargo.lock index 5e57baa371..5c6db6f0b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -820,7 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "jni" -version = "0.13.1" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cesu8 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -837,6 +837,27 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "jnix" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "jni 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jnix-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "jnix-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "jsonrpc-client-core" version = "0.5.0" source = "git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b#68aac55b6ddff5e1242594b54f7f9149fe215ff7" @@ -1294,7 +1315,7 @@ dependencies = [ "err-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "jni 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "jnix 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1390,6 +1411,7 @@ dependencies = [ "chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)", "err-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jnix 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mullvad-paths 0.1.0", @@ -2408,6 +2430,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jnix 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.2 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)", "jsonrpc-macros 8.0.1 (git+https://github.com/mullvad/jsonrpc?branch=mullvad-fork)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2494,6 +2517,7 @@ dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "err-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "jnix 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "x25519-dalek 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3211,8 +3235,10 @@ dependencies = [ "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum ipnetwork 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bf7762e2b430ad80cbef992a1d4f15a15d9d4068bdd8e57acb0a3d21d0cf7f40" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" -"checksum jni 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e00f1fd30a82a801f8bf38bcb0895088a0013cde111acb713c0824edc372aa4" +"checksum jni 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1981310da491a4f0f815238097d0d43d8072732b5ae5f8bd0d8eadf5bf245402" "checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +"checksum jnix 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "14b5a1a12dc744e2a28311fec971a88ed9ff44cc882fe8ed0824609e32b0d36a" +"checksum jnix-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6381b00e7628f4d3971b9851ffff686dffdde91d15c5ab16621fcee7a52a946" "checksum jsonrpc-client-core 0.5.0 (git+https://github.com/mullvad/jsonrpc-client-rs?rev=68aac55b)" = "<none>" "checksum jsonrpc-client-core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f29cb249837420fb0cee7fb0fbf1d22679e121b160e71bb5e0d90b9df241c23e" "checksum jsonrpc-client-http 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e642eb74423b9dfcb4512fda167148746b76f788a823cd712fadf409f31d302" diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt index ae731b4161..4789d27a2c 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt @@ -19,9 +19,9 @@ class ConnectActionButton(val parentView: View) { is TunnelState.Disconnected -> disconnected() is TunnelState.Disconnecting -> { when (value.actionAfterDisconnect) { - is ActionAfterDisconnect.Nothing -> disconnected() - is ActionAfterDisconnect.Block -> connected() - is ActionAfterDisconnect.Reconnect -> connecting() + ActionAfterDisconnect.Nothing -> disconnected() + ActionAfterDisconnect.Block -> connected() + ActionAfterDisconnect.Reconnect -> connecting() } } is TunnelState.Connecting -> connecting() diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt index 17f44a64da..664156dd04 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt @@ -18,9 +18,9 @@ class ConnectionStatus(val parentView: View, val resources: Resources) { when (state) { is TunnelState.Disconnecting -> { when (state.actionAfterDisconnect) { - is ActionAfterDisconnect.Nothing -> disconnected() - is ActionAfterDisconnect.Block -> connected() - is ActionAfterDisconnect.Reconnect -> connecting() + ActionAfterDisconnect.Nothing -> disconnected() + ActionAfterDisconnect.Block -> connected() + ActionAfterDisconnect.Reconnect -> connecting() } } is TunnelState.Disconnected -> disconnected() diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ForegroundNotificationManager.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ForegroundNotificationManager.kt index c99d8d7a0d..80890e56ca 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ForegroundNotificationManager.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ForegroundNotificationManager.kt @@ -40,7 +40,7 @@ class ForegroundNotificationManager(val service: Service, val connectionProxy: C reconnecting = (value is TunnelState.Disconnecting && - value.actionAfterDisconnect is ActionAfterDisconnect.Reconnect) || + value.actionAfterDisconnect == ActionAfterDisconnect.Reconnect) || (value is TunnelState.Connecting && reconnecting) updateNotification() @@ -62,7 +62,7 @@ class ForegroundNotificationManager(val service: Service, val connectionProxy: C is TunnelState.Connected -> R.string.secured is TunnelState.Disconnecting -> { when (state.actionAfterDisconnect) { - is ActionAfterDisconnect.Reconnect -> R.string.reconnecting + ActionAfterDisconnect.Reconnect -> R.string.reconnecting else -> R.string.disconnecting } } @@ -80,7 +80,7 @@ class ForegroundNotificationManager(val service: Service, val connectionProxy: C is TunnelState.Connected -> R.string.disconnect is TunnelState.Disconnecting -> { when (state.actionAfterDisconnect) { - is ActionAfterDisconnect.Reconnect -> R.string.cancel + ActionAfterDisconnect.Reconnect -> R.string.cancel else -> R.string.connect } } @@ -98,7 +98,7 @@ class ForegroundNotificationManager(val service: Service, val connectionProxy: C is TunnelState.Connected -> KEY_DISCONNECT_ACTION is TunnelState.Disconnecting -> { when (state.actionAfterDisconnect) { - is ActionAfterDisconnect.Reconnect -> KEY_DISCONNECT_ACTION + ActionAfterDisconnect.Reconnect -> KEY_DISCONNECT_ACTION else -> KEY_CONNECT_ACTION } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/LocationInfo.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/LocationInfo.kt index 9278bb315f..9210712365 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/LocationInfo.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/LocationInfo.kt @@ -99,8 +99,8 @@ class LocationInfo(val parentView: View, val context: Context) { private fun showInAddress(endpoint: Endpoint?) { if (endpoint != null) { val transportProtocol = when (endpoint.protocol) { - is TransportProtocol.Tcp -> context.getString(R.string.tcp) - is TransportProtocol.Udp -> context.getString(R.string.udp) + TransportProtocol.Tcp -> context.getString(R.string.tcp) + TransportProtocol.Udp -> context.getString(R.string.udp) } inAddress.text = context.getString( diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt index 352fe4dd71..f6fd4c9e1e 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt @@ -124,9 +124,9 @@ class NotificationBanner( when (state) { is TunnelState.Disconnecting -> { when (state.actionAfterDisconnect) { - is ActionAfterDisconnect.Nothing -> return false - is ActionAfterDisconnect.Block -> showBlocking(null) - is ActionAfterDisconnect.Reconnect -> showBlocking(null) + ActionAfterDisconnect.Nothing -> return false + ActionAfterDisconnect.Block -> showBlocking(null) + ActionAfterDisconnect.Reconnect -> showBlocking(null) } } is TunnelState.Disconnected -> return false @@ -179,12 +179,12 @@ class NotificationBanner( is BlockReason.TapAdapterProblem -> R.string.tap_adapter_problem is BlockReason.ParameterGeneration -> { when (reason.error) { - is ParameterGenerationError.NoMatchingRelay -> R.string.no_matching_relay - is ParameterGenerationError.NoMatchingBridgeRelay -> { + ParameterGenerationError.NoMatchingRelay -> R.string.no_matching_relay + ParameterGenerationError.NoMatchingBridgeRelay -> { R.string.no_matching_bridge_relay } - is ParameterGenerationError.NoWireguardKey -> R.string.no_wireguard_key - is ParameterGenerationError.CustomTunnelHostResultionError -> { + ParameterGenerationError.NoWireguardKey -> R.string.no_wireguard_key + ParameterGenerationError.CustomTunnelHostResultionError -> { R.string.custom_tunnel_host_resolution_error } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/SwitchLocationButton.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/SwitchLocationButton.kt index f6561e4da1..930c1ff626 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/SwitchLocationButton.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/SwitchLocationButton.kt @@ -57,9 +57,9 @@ class SwitchLocationButton(val parentView: View, val resources: Resources) { is TunnelState.Disconnected -> showLocation() is TunnelState.Disconnecting -> { when (state.actionAfterDisconnect) { - is ActionAfterDisconnect.Nothing -> showLocation() - is ActionAfterDisconnect.Block -> showLocation() - is ActionAfterDisconnect.Reconnect -> showLabel() + ActionAfterDisconnect.Nothing -> showLocation() + ActionAfterDisconnect.Block -> showLocation() + ActionAfterDisconnect.Reconnect -> showLabel() } } is TunnelState.Connecting -> showLabel() diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/WireguardKeyFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/WireguardKeyFragment.kt index e51e43630f..141e373ccf 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/WireguardKeyFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/WireguardKeyFragment.kt @@ -152,16 +152,15 @@ class WireguardKeyFragment : Fragment() { publicKeyAge.setText(formatKeyDateCreated(key.dateCreated)) - if (keyState.verified != null) { - if (keyState.verified) { + keyState.verified?.let { verified -> + if (verified) { setStatusMessage(R.string.wireguard_key_valid, R.color.green) } else { setStatusMessage(R.string.wireguard_key_invalid, R.color.red) } } - if (keyState.replacementFailure != null) { - showKeygenFailure(keyState.replacementFailure) - } + + keyState.replacementFailure?.let { error -> showKeygenFailure(error) } } is KeygenEvent.Failure -> { showKeygenFailure(keyState.failure) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/ConnectionProxy.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/ConnectionProxy.kt index 06c594ed1c..ee429ca18d 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/ConnectionProxy.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/ConnectionProxy.kt @@ -105,7 +105,7 @@ class ConnectionProxy(val context: Context, val daemon: Deferred<MullvadDaemon>) return false } else { scheduleToResetAnticipatedState() - uiState = TunnelState.Disconnecting(ActionAfterDisconnect.Nothing()) + uiState = TunnelState.Disconnecting(ActionAfterDisconnect.Nothing) return true } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt index 94444c5d46..0057f034d8 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt @@ -49,9 +49,9 @@ class LocationInfoCache( } is TunnelState.Disconnecting -> { when (value.actionAfterDisconnect) { - is ActionAfterDisconnect.Nothing -> location = lastKnownRealLocation - is ActionAfterDisconnect.Block -> location = null - is ActionAfterDisconnect.Reconnect -> location = locationFromSelectedRelay() + ActionAfterDisconnect.Nothing -> location = lastKnownRealLocation + ActionAfterDisconnect.Block -> location = null + ActionAfterDisconnect.Reconnect -> location = locationFromSelectedRelay() } } is TunnelState.Blocked -> location = null diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt index 32b3c10ba7..7d016821a4 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/RelayListListener.kt @@ -7,6 +7,7 @@ import kotlinx.coroutines.launch import net.mullvad.mullvadvpn.MainActivity import net.mullvad.mullvadvpn.MullvadDaemon import net.mullvad.mullvadvpn.model.Constraint +import net.mullvad.mullvadvpn.model.RelayConstraints import net.mullvad.mullvadvpn.model.RelaySettings import net.mullvad.mullvadvpn.relaylist.RelayItem import net.mullvad.mullvadvpn.relaylist.RelayList @@ -78,7 +79,8 @@ class RelayListListener(val parentActivity: MainActivity) { synchronized(this) { val relayList = this.relayList - relaySettings = newRelaySettings ?: RelaySettings.RelayConstraints(Constraint.Any()) + relaySettings = newRelaySettings + ?: RelaySettings.Normal(RelayConstraints(Constraint.Any())) if (relayList != null) { relayListChanged(relayList) @@ -100,8 +102,8 @@ class RelayListListener(val parentActivity: MainActivity) { when (relaySettings) { is RelaySettings.CustomTunnelEndpoint -> return null - is RelaySettings.RelayConstraints -> { - val location = relaySettings.location + is RelaySettings.Normal -> { + val location = relaySettings.relayConstraints.location return relayList?.findItemForLocation(location, true) } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/CustomTunnelEndpoint.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/CustomTunnelEndpoint.kt new file mode 100644 index 0000000000..05dd38a80b --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/CustomTunnelEndpoint.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.model + +class CustomTunnelEndpoint() diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/KeygenEvent.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/KeygenEvent.kt index f2f85453f9..0e1e801895 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/KeygenEvent.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/KeygenEvent.kt @@ -1,11 +1,21 @@ package net.mullvad.mullvadvpn.model sealed class KeygenEvent { - class NewKey( - val publicKey: PublicKey, - val verified: Boolean?, - val replacementFailure: KeygenFailure? - ) : KeygenEvent() + class NewKey(val publicKey: PublicKey) : KeygenEvent() { + var verified: Boolean? = false + private set + var replacementFailure: KeygenFailure? = null + private set + + constructor( + publicKey: PublicKey, + verified: Boolean?, + replacementFailure: KeygenFailure? + ) : this(publicKey) { + this.verified = verified + this.replacementFailure = replacementFailure + } + } class Failure(val failure: KeygenFailure) : KeygenEvent() } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Relay.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Relay.kt index 01c2eb9481..f260baf6e2 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Relay.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/Relay.kt @@ -1,3 +1,6 @@ package net.mullvad.mullvadvpn.model -data class Relay(val hostname: String, val hasWireguardTunnels: Boolean, val active: Boolean) +data class Relay(val hostname: String, val active: Boolean, val tunnels: RelayTunnels) { + val hasWireguardTunnels + get() = tunnels.wireguard.isEmpty() +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt new file mode 100644 index 0000000000..e4e6d6634e --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraints.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.model + +data class RelayConstraints(val location: Constraint<LocationConstraint>) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayList.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayList.kt index 57a4a0e6c5..bc9ec3327a 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayList.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayList.kt @@ -1,3 +1,5 @@ package net.mullvad.mullvadvpn.model -data class RelayList(val countries: List<RelayListCountry>) +import java.util.ArrayList + +data class RelayList(val countries: ArrayList<RelayListCountry>) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCity.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCity.kt index 406d2b5ca5..329120350d 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCity.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCity.kt @@ -1,3 +1,5 @@ package net.mullvad.mullvadvpn.model -data class RelayListCity(val name: String, val code: String, val relays: List<Relay>) +import java.util.ArrayList + +data class RelayListCity(val name: String, val code: String, val relays: ArrayList<Relay>) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCountry.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCountry.kt index de6817b03c..035cb52d19 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCountry.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayListCountry.kt @@ -1,3 +1,9 @@ package net.mullvad.mullvadvpn.model -data class RelayListCountry(val name: String, val code: String, val cities: List<RelayListCity>) +import java.util.ArrayList + +data class RelayListCountry( + val name: String, + val code: String, + val cities: ArrayList<RelayListCity> +) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt index 6fded8f9c5..cb53911883 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt @@ -2,5 +2,5 @@ package net.mullvad.mullvadvpn.model sealed class RelaySettings { class CustomTunnelEndpoint() : RelaySettings() - class RelayConstraints(var location: Constraint<LocationConstraint>) : RelaySettings() + class Normal(var relayConstraints: RelayConstraints) : RelaySettings() } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayTunnels.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayTunnels.kt new file mode 100644 index 0000000000..5946620566 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayTunnels.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.model + +import java.util.ArrayList + +data class RelayTunnels(val wireguard: ArrayList<WireguardEndpointData>) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardEndpointData.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardEndpointData.kt new file mode 100644 index 0000000000..1d39f1170d --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/WireguardEndpointData.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.model + +class WireguardEndpointData() diff --git a/android/src/main/kotlin/net/mullvad/talpid/net/TransportProtocol.kt b/android/src/main/kotlin/net/mullvad/talpid/net/TransportProtocol.kt index d4372f54ed..013399dc52 100644 --- a/android/src/main/kotlin/net/mullvad/talpid/net/TransportProtocol.kt +++ b/android/src/main/kotlin/net/mullvad/talpid/net/TransportProtocol.kt @@ -1,6 +1,5 @@ package net.mullvad.talpid.net -sealed class TransportProtocol { - class Tcp : TransportProtocol() - class Udp : TransportProtocol() +enum class TransportProtocol { + Tcp, Udp } diff --git a/android/src/main/kotlin/net/mullvad/talpid/tun_provider/TunConfig.kt b/android/src/main/kotlin/net/mullvad/talpid/tun_provider/TunConfig.kt index fe8d0f55c7..761462013e 100644 --- a/android/src/main/kotlin/net/mullvad/talpid/tun_provider/TunConfig.kt +++ b/android/src/main/kotlin/net/mullvad/talpid/tun_provider/TunConfig.kt @@ -1,10 +1,11 @@ package net.mullvad.talpid.tun_provider import java.net.InetAddress +import java.util.ArrayList data class TunConfig( - val addresses: List<InetAddress>, - val dnsServers: List<InetAddress>, - val routes: List<InetNetwork>, + val addresses: ArrayList<InetAddress>, + val dnsServers: ArrayList<InetAddress>, + val routes: ArrayList<InetNetwork>, val mtu: Int ) diff --git a/android/src/main/kotlin/net/mullvad/talpid/tunnel/ActionAfterDisconnect.kt b/android/src/main/kotlin/net/mullvad/talpid/tunnel/ActionAfterDisconnect.kt index c352ab06ad..c20d5b33e4 100644 --- a/android/src/main/kotlin/net/mullvad/talpid/tunnel/ActionAfterDisconnect.kt +++ b/android/src/main/kotlin/net/mullvad/talpid/tunnel/ActionAfterDisconnect.kt @@ -1,7 +1,5 @@ package net.mullvad.talpid.tunnel -sealed class ActionAfterDisconnect { - class Nothing : ActionAfterDisconnect() - class Block : ActionAfterDisconnect() - class Reconnect : ActionAfterDisconnect() +enum class ActionAfterDisconnect { + Nothing, Block, Reconnect } diff --git a/android/src/main/kotlin/net/mullvad/talpid/tunnel/ParameterGenerationError.kt b/android/src/main/kotlin/net/mullvad/talpid/tunnel/ParameterGenerationError.kt index 92547a02b4..51fa8ac461 100644 --- a/android/src/main/kotlin/net/mullvad/talpid/tunnel/ParameterGenerationError.kt +++ b/android/src/main/kotlin/net/mullvad/talpid/tunnel/ParameterGenerationError.kt @@ -1,8 +1,5 @@ package net.mullvad.talpid.tunnel -sealed class ParameterGenerationError { - class NoMatchingRelay : ParameterGenerationError() - class NoMatchingBridgeRelay : ParameterGenerationError() - class NoWireguardKey : ParameterGenerationError() - class CustomTunnelHostResultionError : ParameterGenerationError() +enum class ParameterGenerationError { + NoMatchingRelay, NoMatchingBridgeRelay, NoWireguardKey, CustomTunnelHostResultionError } diff --git a/mullvad-jni/Cargo.toml b/mullvad-jni/Cargo.toml index b8b1711e10..138a1be50e 100644 --- a/mullvad-jni/Cargo.toml +++ b/mullvad-jni/Cargo.toml @@ -13,7 +13,7 @@ crate_type = ["cdylib"] err-derive = "0.2.1" futures = "0.1" ipnetwork = "0.15" -jni = "0.13" +jnix = { version = "0.1", features = ["derive"] } jsonrpc-client-core = "0.5" jsonrpc-core = "8" lazy_static = "1" diff --git a/mullvad-jni/src/classes.rs b/mullvad-jni/src/classes.rs new file mode 100644 index 0000000000..39b7713932 --- /dev/null +++ b/mullvad-jni/src/classes.rs @@ -0,0 +1,58 @@ +pub const CLASSES: &[&str] = &[ + "java/lang/Boolean", + "java/net/InetAddress", + "java/net/InetSocketAddress", + "java/util/ArrayList", + "net/mullvad/mullvadvpn/model/AccountData", + "net/mullvad/mullvadvpn/model/AppVersionInfo", + "net/mullvad/mullvadvpn/model/Constraint$Any", + "net/mullvad/mullvadvpn/model/Constraint$Only", + "net/mullvad/mullvadvpn/model/GeoIpLocation", + "net/mullvad/mullvadvpn/model/GetAccountDataResult$Ok", + "net/mullvad/mullvadvpn/model/GetAccountDataResult$InvalidAccount", + "net/mullvad/mullvadvpn/model/GetAccountDataResult$RpcError", + "net/mullvad/mullvadvpn/model/GetAccountDataResult$OtherError", + "net/mullvad/mullvadvpn/model/KeygenEvent$NewKey", + "net/mullvad/mullvadvpn/model/KeygenEvent$Failure", + "net/mullvad/mullvadvpn/model/KeygenFailure$TooManyKeys", + "net/mullvad/mullvadvpn/model/KeygenFailure$GenerationFailure", + "net/mullvad/mullvadvpn/model/LocationConstraint$City", + "net/mullvad/mullvadvpn/model/LocationConstraint$Country", + "net/mullvad/mullvadvpn/model/LocationConstraint$Hostname", + "net/mullvad/mullvadvpn/model/PublicKey", + "net/mullvad/mullvadvpn/model/Relay", + "net/mullvad/mullvadvpn/model/RelayConstraints", + "net/mullvad/mullvadvpn/model/RelayList", + "net/mullvad/mullvadvpn/model/RelayListCity", + "net/mullvad/mullvadvpn/model/RelayListCountry", + "net/mullvad/mullvadvpn/model/RelaySettings$CustomTunnelEndpoint", + "net/mullvad/mullvadvpn/model/RelaySettings$Normal", + "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$CustomTunnelEndpoint", + "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$RelayConstraintsUpdate", + "net/mullvad/mullvadvpn/model/RelayTunnels", + "net/mullvad/mullvadvpn/model/Settings", + "net/mullvad/mullvadvpn/model/TunnelState$Blocked", + "net/mullvad/mullvadvpn/model/TunnelState$Connected", + "net/mullvad/mullvadvpn/model/TunnelState$Connecting", + "net/mullvad/mullvadvpn/model/TunnelState$Disconnected", + "net/mullvad/mullvadvpn/model/TunnelState$Disconnecting", + "net/mullvad/mullvadvpn/model/WireguardEndpointData", + "net/mullvad/mullvadvpn/MullvadDaemon", + "net/mullvad/mullvadvpn/MullvadVpnService", + "net/mullvad/talpid/net/Endpoint", + "net/mullvad/talpid/net/TransportProtocol", + "net/mullvad/talpid/net/TunnelEndpoint", + "net/mullvad/talpid/tun_provider/InetNetwork", + "net/mullvad/talpid/tun_provider/TunConfig", + "net/mullvad/talpid/tunnel/ActionAfterDisconnect", + "net/mullvad/talpid/tunnel/BlockReason$AuthFailed", + "net/mullvad/talpid/tunnel/BlockReason$Ipv6Unavailable", + "net/mullvad/talpid/tunnel/BlockReason$SetFirewallPolicyError", + "net/mullvad/talpid/tunnel/BlockReason$SetDnsError", + "net/mullvad/talpid/tunnel/BlockReason$StartTunnelError", + "net/mullvad/talpid/tunnel/BlockReason$ParameterGeneration", + "net/mullvad/talpid/tunnel/BlockReason$IsOffline", + "net/mullvad/talpid/tunnel/BlockReason$TapAdapterProblem", + "net/mullvad/talpid/tunnel/ParameterGenerationError", + "net/mullvad/talpid/TalpidVpnService", +]; diff --git a/mullvad-jni/src/from_java.rs b/mullvad-jni/src/from_java.rs index c016134f23..9cccd738d7 100644 --- a/mullvad-jni/src/from_java.rs +++ b/mullvad-jni/src/from_java.rs @@ -1,7 +1,7 @@ -use crate::{get_class, is_null::IsNull}; -use jni::{ - objects::{JObject, JString}, - JNIEnv, +use crate::is_null::IsNull; +use jnix::{ + jni::objects::{JObject, JString}, + JnixEnv, }; use mullvad_types::relay_constraints::{ Constraint, LocationConstraint, RelayConstraintsUpdate, RelaySettingsUpdate, @@ -11,7 +11,7 @@ use std::fmt::Debug; pub trait FromJava<'env> { type JavaType: 'env; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self; + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self; } impl<'env, T> FromJava<'env> for Option<T> @@ -21,7 +21,7 @@ where { type JavaType = T::JavaType; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self { + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self { if source.is_null() { None } else { @@ -33,7 +33,7 @@ where impl<'env> FromJava<'env> for String { type JavaType = JString<'env>; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self { + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self { String::from( env.get_string(source) .expect("Failed to convert from Java String"), @@ -48,7 +48,7 @@ where { type JavaType = JObject<'env>; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self { + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self { if is_instance_of(env, source, "net/mullvad/mullvadvpn/model/Constraint$Any") { Constraint::Any } else if is_instance_of(env, source, "net/mullvad/mullvadvpn/model/Constraint$Only") { @@ -64,7 +64,7 @@ where impl<'env> FromJava<'env> for LocationConstraint { type JavaType = JObject<'env>; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self { + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self { let country_class = "net/mullvad/mullvadvpn/model/LocationConstraint$Country"; let city_class = "net/mullvad/mullvadvpn/model/LocationConstraint$City"; let hostname_class = "net/mullvad/mullvadvpn/model/LocationConstraint$Hostname"; @@ -100,7 +100,7 @@ impl<'env> FromJava<'env> for LocationConstraint { impl<'env> FromJava<'env> for RelayConstraintsUpdate { type JavaType = JObject<'env>; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self { + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self { let location = get_object_field( env, source, @@ -120,7 +120,7 @@ impl<'env> FromJava<'env> for RelayConstraintsUpdate { impl<'env> FromJava<'env> for RelaySettingsUpdate { type JavaType = JObject<'env>; - fn from_java(env: &JNIEnv<'env>, source: Self::JavaType) -> Self { + fn from_java(env: &JnixEnv<'env>, source: Self::JavaType) -> Self { let custom_tunnel_endpoint_class = "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$CustomTunnelEndpoint"; let relay_constraints_update_class = @@ -137,18 +137,18 @@ impl<'env> FromJava<'env> for RelaySettingsUpdate { } fn is_instance_of<'env>( - env: &JNIEnv<'env>, + env: &JnixEnv<'env>, object: JObject<'env>, class_name: &'static str, ) -> bool { - let class = get_class(class_name); + let class = env.get_class(class_name); env.is_instance_of(object, &class) .expect("Failed to check if an object is an instance of a specified class") } fn get_string_field<'env>( - env: &JNIEnv<'env>, + env: &JnixEnv<'env>, object: JObject<'env>, field_name: &str, ) -> JString<'env> { @@ -161,7 +161,7 @@ fn get_string_field<'env>( } fn get_object_field<'env>( - env: &JNIEnv<'env>, + env: &JnixEnv<'env>, object: JObject<'env>, field_name: &str, field_type: &str, diff --git a/mullvad-jni/src/into_java.rs b/mullvad-jni/src/into_java.rs deleted file mode 100644 index bc97ac4bc0..0000000000 --- a/mullvad-jni/src/into_java.rs +++ /dev/null @@ -1,811 +0,0 @@ -use crate::{daemon_interface, get_class}; -use ipnetwork::IpNetwork; -use jni::{ - objects::{JList, JObject, JString, JValue}, - signature::JavaType, - sys::{jboolean, jint, jshort, jsize}, - JNIEnv, -}; -use mullvad_types::{ - account::AccountData, - location::GeoIpLocation, - relay_constraints::{Constraint, LocationConstraint, RelayConstraints, RelaySettings}, - relay_list::{Relay, RelayList, RelayListCity, RelayListCountry}, - settings::Settings, - states::TunnelState, - version::AppVersionInfo, - wireguard::{KeygenEvent, PublicKey}, - CustomTunnelEndpoint, -}; -use std::{ - fmt::Debug, - net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, -}; -use talpid_core::tunnel::tun_provider::TunConfig; -use talpid_types::{ - net::{Endpoint, TransportProtocol, TunnelEndpoint}, - tunnel::{ActionAfterDisconnect, BlockReason, ParameterGenerationError}, -}; - -pub trait IntoJava<'env> { - type JavaType; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType; -} - -impl<'env, T> IntoJava<'env> for Option<T> -where - T: IntoJava<'env>, - T::JavaType: From<JObject<'env>>, -{ - type JavaType = T::JavaType; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - Some(data) => data.into_java(env), - None => T::JavaType::from(JObject::null()), - } - } -} - -impl<'env> IntoJava<'env> for String { - type JavaType = JString<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - env.new_string(&self).expect("Failed to create Java String") - } -} - -impl<'env, T> IntoJava<'env> for Vec<T> -where - T: IntoJava<'env>, - JObject<'env>: From<T::JavaType>, -{ - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("java/util/ArrayList"); - let initial_capacity = self.len(); - let parameters = [JValue::Int(initial_capacity as jint)]; - - let list_object = env - .new_object(&class, "(I)V", ¶meters) - .expect("Failed to create ArrayList object"); - - let list = - JList::from_env(env, list_object).expect("Failed to create JList from ArrayList"); - - for element in self { - let java_element = env.auto_local(JObject::from(element.into_java(env))); - - list.add(java_element.as_obj()) - .expect("Failed to add element to ArrayList"); - } - - list_object - } -} - -impl<'array, 'env> IntoJava<'env> for &'array [u8] { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let size = self.len(); - let array = env - .new_byte_array(size as jsize) - .expect("Failed to create a Java array of bytes"); - - let data = unsafe { std::slice::from_raw_parts(self.as_ptr() as *const i8, size) }; - - env.set_byte_array_region(array, 0, data) - .expect("Failed to copy bytes to Java array"); - - JObject::from(array) - } -} - -fn ipvx_addr_into_java<'env>(original_octets: &[u8], env: &JNIEnv<'env>) -> JObject<'env> { - let class = get_class("java/net/InetAddress"); - - let constructor = env - .get_static_method_id(&class, "getByAddress", "([B)Ljava/net/InetAddress;") - .expect("Failed to get InetAddress.getByAddress method ID"); - - let octets_array = env - .new_byte_array(original_octets.len() as i32) - .expect("Failed to create byte array to store IP address"); - - let octet_data: Vec<i8> = original_octets - .into_iter() - .map(|octet| *octet as i8) - .collect(); - - env.set_byte_array_region(octets_array, 0, &octet_data) - .expect("Failed to copy IP address octets to byte array"); - - let octets = env.auto_local(JObject::from(octets_array)); - let result = env - .call_static_method_unchecked( - &class, - constructor, - JavaType::Object("java/net/InetAddress".to_owned()), - &[JValue::Object(octets.as_obj())], - ) - .expect("Failed to create InetAddress Java object"); - - match result { - JValue::Object(object) => JObject::from(object.into_inner()), - value => { - panic!( - "InetAddress.getByAddress returned an invalid value: {:?}", - value - ); - } - } -} - -impl<'env> IntoJava<'env> for Ipv4Addr { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - ipvx_addr_into_java(self.octets().as_ref(), env) - } -} - -impl<'env> IntoJava<'env> for Ipv6Addr { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - ipvx_addr_into_java(self.octets().as_ref(), env) - } -} - -impl<'env> IntoJava<'env> for IpAddr { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - IpAddr::V4(address) => address.into_java(env), - IpAddr::V6(address) => address.into_java(env), - } - } -} - -impl<'env> IntoJava<'env> for SocketAddr { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("java/net/InetSocketAddress"); - let ip_address = env.auto_local(self.ip().into_java(env)); - let port = self.port() as jint; - let parameters = [JValue::Object(ip_address.as_obj()), JValue::Int(port)]; - - env.new_object(&class, "(Ljava/net/InetAddress;I)V", ¶meters) - .expect("Failed to create InetSocketAddress Java object") - } -} - -impl<'env> IntoJava<'env> for IpNetwork { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/talpid/tun_provider/InetNetwork"); - let address = env.auto_local(self.ip().into_java(env)); - let prefix_length = self.prefix() as jshort; - let parameters = [ - JValue::Object(address.as_obj()), - JValue::Short(prefix_length), - ]; - - env.new_object(&class, "(Ljava/net/InetAddress;S)V", ¶meters) - .expect("Failed to create InetNetwork Java object") - } -} - -impl<'env> IntoJava<'env> for PublicKey { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/PublicKey"); - let key = env.auto_local(self.key.as_bytes().into_java(env)); - let date_created = env.auto_local(*self.created.to_string().into_java(env)); - let parameters = [ - JValue::Object(key.as_obj()), - JValue::Object(date_created.as_obj()), - ]; - - env.new_object(&class, "([BLjava/lang/String;)V", ¶meters) - .expect("Failed to create PublicKey Java object") - } -} - -impl<'env> IntoJava<'env> for AppVersionInfo { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/AppVersionInfo"); - let current_is_supported = self.current_is_supported as jboolean; - let current_is_outdated = self.current_is_outdated as jboolean; - let latest_stable = env.auto_local(*self.latest_stable.into_java(env)); - let latest = env.auto_local(*self.latest.into_java(env)); - let parameters = [ - JValue::Bool(current_is_supported), - JValue::Bool(current_is_outdated), - JValue::Object(latest_stable.as_obj()), - JValue::Object(latest.as_obj()), - ]; - - env.new_object( - &class, - "(ZZLjava/lang/String;Ljava/lang/String;)V", - ¶meters, - ) - .expect("Failed to create AppVersionInfo Java object") - } -} - -impl<'env> IntoJava<'env> for AccountData { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/AccountData"); - let account_expiry = env.auto_local(JObject::from(self.expiry.to_string().into_java(env))); - let parameters = [JValue::Object(account_expiry.as_obj())]; - - env.new_object(&class, "(Ljava/lang/String;)V", ¶meters) - .expect("Failed to create AccountData Java object") - } -} - -impl<'env> IntoJava<'env> for TunConfig { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/talpid/tun_provider/TunConfig"); - let addresses = env.auto_local(self.addresses.into_java(env)); - let dns_servers = env.auto_local(self.dns_servers.into_java(env)); - let routes = env.auto_local(self.routes.into_java(env)); - let mtu = self.mtu as jint; - let parameters = [ - JValue::Object(addresses.as_obj()), - JValue::Object(dns_servers.as_obj()), - JValue::Object(routes.as_obj()), - JValue::Int(mtu), - ]; - - env.new_object( - &class, - "(Ljava/util/List;Ljava/util/List;Ljava/util/List;I)V", - ¶meters, - ) - .expect("Failed to create TunConfig Java object") - } -} - -impl<'env> IntoJava<'env> for TransportProtocol { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class_name = match self { - TransportProtocol::Tcp => "net/mullvad/talpid/net/TransportProtocol$Tcp", - TransportProtocol::Udp => "net/mullvad/talpid/net/TransportProtocol$Udp", - }; - let class = get_class(class_name); - - env.new_object(&class, "()V", &[]) - .expect("Failed to create TransportProtocol sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for Endpoint { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/talpid/net/Endpoint"); - let address = env.auto_local(self.address.into_java(env)); - let protocol = env.auto_local(self.protocol.into_java(env)); - let parameters = [ - JValue::Object(address.as_obj()), - JValue::Object(protocol.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/net/InetSocketAddress;Lnet/mullvad/talpid/net/TransportProtocol;)V", - ¶meters, - ) - .expect("Failed to create Endpoint sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for TunnelEndpoint { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/talpid/net/TunnelEndpoint"); - let endpoint = env.auto_local(self.endpoint.into_java(env)); - let parameters = [JValue::Object(endpoint.as_obj())]; - - env.new_object(&class, "(Lnet/mullvad/talpid/net/Endpoint;)V", ¶meters) - .expect("Failed to create TunnelEndpoint sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for GeoIpLocation { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/GeoIpLocation"); - let ipv4 = env.auto_local(self.ipv4.into_java(env)); - let ipv6 = env.auto_local(self.ipv6.into_java(env)); - let country = env.auto_local(JObject::from(self.country.into_java(env))); - let city = env.auto_local(JObject::from(self.city.into_java(env))); - let hostname = env.auto_local(JObject::from(self.hostname.into_java(env))); - let parameters = [ - JValue::Object(ipv4.as_obj()), - JValue::Object(ipv6.as_obj()), - JValue::Object(country.as_obj()), - JValue::Object(city.as_obj()), - JValue::Object(hostname.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/net/InetAddress;Ljava/net/InetAddress;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", - ¶meters, - ) - .expect("Failed to create GeoIpLocation Java object") - } -} - -impl<'env> IntoJava<'env> for RelayList { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/RelayList"); - let relay_countries = env.auto_local(self.countries.into_java(env)); - let parameters = [JValue::Object(relay_countries.as_obj())]; - - env.new_object(&class, "(Ljava/util/List;)V", ¶meters) - .expect("Failed to create RelayList Java object") - } -} - -impl<'env> IntoJava<'env> for RelayListCountry { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/RelayListCountry"); - let name = env.auto_local(JObject::from(self.name.into_java(env))); - let code = env.auto_local(JObject::from(self.code.into_java(env))); - let relay_cities = env.auto_local(self.cities.into_java(env)); - let parameters = [ - JValue::Object(name.as_obj()), - JValue::Object(code.as_obj()), - JValue::Object(relay_cities.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V", - ¶meters, - ) - .expect("Failed to create RelayListCountry Java object") - } -} - -impl<'env> IntoJava<'env> for RelayListCity { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/RelayListCity"); - let name = env.auto_local(JObject::from(self.name.into_java(env))); - let code = env.auto_local(JObject::from(self.code.into_java(env))); - let relays = env.auto_local(self.relays.into_java(env)); - let parameters = [ - JValue::Object(name.as_obj()), - JValue::Object(code.as_obj()), - JValue::Object(relays.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)V", - ¶meters, - ) - .expect("Failed to create RelayListCity Java object") - } -} - -impl<'env> IntoJava<'env> for Relay { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/Relay"); - let hostname = env.auto_local(JObject::from(self.hostname.into_java(env))); - let has_wireguard_tunnels = (!self.tunnels.wireguard.is_empty()) as jboolean; - let parameters = [ - JValue::Object(hostname.as_obj()), - JValue::Bool(has_wireguard_tunnels), - JValue::Bool(self.active as jboolean), - ]; - - env.new_object(&class, "(Ljava/lang/String;ZZ)V", ¶meters) - .expect("Failed to create Relay Java object") - } -} - -impl<'env, T> IntoJava<'env> for Constraint<T> -where - T: Clone + Eq + Debug + IntoJava<'env>, - JObject<'env>: From<T::JavaType>, -{ - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - Constraint::Any => { - let class = get_class("net/mullvad/mullvadvpn/model/Constraint$Any"); - - env.new_object(&class, "()V", &[]) - .expect("Failed to create Constraint.Any Java object") - } - Constraint::Only(constraint) => { - let class = get_class("net/mullvad/mullvadvpn/model/Constraint$Only"); - let value = env.auto_local(JObject::from(constraint.into_java(env))); - let parameters = [JValue::Object(value.as_obj())]; - - env.new_object(&class, "(Ljava/lang/Object;)V", ¶meters) - .expect("Failed to create Constraint.Only Java object") - } - } - } -} - -impl<'env> IntoJava<'env> for LocationConstraint { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - LocationConstraint::Country(country_code) => { - let class = get_class("net/mullvad/mullvadvpn/model/LocationConstraint$Country"); - let country = env.auto_local(JObject::from(country_code.into_java(env))); - let parameters = [JValue::Object(country.as_obj())]; - - env.new_object(&class, "(Ljava/lang/String;)V", ¶meters) - .expect("Failed to create LocationConstraint.Country Java object") - } - LocationConstraint::City(country_code, city_code) => { - let class = get_class("net/mullvad/mullvadvpn/model/LocationConstraint$City"); - let country = env.auto_local(JObject::from(country_code.into_java(env))); - let city = env.auto_local(JObject::from(city_code.into_java(env))); - let parameters = [ - JValue::Object(country.as_obj()), - JValue::Object(city.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/lang/String;Ljava/lang/String;)V", - ¶meters, - ) - .expect("Failed to create LocationConstraint.City Java object") - } - LocationConstraint::Hostname(country_code, city_code, hostname) => { - let class = get_class("net/mullvad/mullvadvpn/model/LocationConstraint$Hostname"); - let country = env.auto_local(JObject::from(country_code.into_java(env))); - let city = env.auto_local(JObject::from(city_code.into_java(env))); - let hostname = env.auto_local(JObject::from(hostname.into_java(env))); - let parameters = [ - JValue::Object(country.as_obj()), - JValue::Object(city.as_obj()), - JValue::Object(hostname.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", - ¶meters, - ) - .expect("Failed to create LocationConstraint.Hostname Java object") - } - } - } -} - -impl<'env> IntoJava<'env> for RelaySettings { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - RelaySettings::CustomTunnelEndpoint(endpoint) => endpoint.into_java(env), - RelaySettings::Normal(relay_constraints) => relay_constraints.into_java(env), - } - } -} - -impl<'env> IntoJava<'env> for CustomTunnelEndpoint { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/RelaySettings$CustomTunnelEndpoint"); - - env.new_object(&class, "()V", &[]) - .expect("Failed to create CustomTunnelEndpoint Java object") - } -} - -impl<'env> IntoJava<'env> for KeygenEvent { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - KeygenEvent::NewKey(public_key) => { - let class = get_class("net/mullvad/mullvadvpn/model/KeygenEvent$NewKey"); - let java_public_key = env.auto_local(public_key.into_java(env)); - - let parameters = [ - JValue::Object(java_public_key.as_obj()), - JValue::Object(JObject::null()), - JValue::Object(JObject::null()), - ]; - - env.new_object( - &class, - "(Lnet/mullvad/mullvadvpn/model/PublicKey;Ljava/lang/Boolean;Lnet/mullvad/mullvadvpn/model/KeygenFailure;)V", - ¶meters, - ) - .expect("Failed to create KeygenEvent.NewKey Java object") - } - KeygenEvent::TooManyKeys => { - let failure_class = - get_class("net/mullvad/mullvadvpn/model/KeygenFailure$TooManyKeys"); - - let failure = env - .new_object(&failure_class, "()V", &[]) - .expect("Failed to create KeygenFailure.TooManyKeys Java object"); - - let class = get_class("net/mullvad/mullvadvpn/model/KeygenEvent$Failure"); - env.new_object( - &class, - "(Lnet/mullvad/mullvadvpn/model/KeygenFailure;)V", - &[JValue::Object(failure)], - ) - .expect("Failed to create KeygenEvent.Failure Java object") - } - KeygenEvent::GenerationFailure => { - let failure_class = - get_class("net/mullvad/mullvadvpn/model/KeygenFailure$GenerationFailure"); - let failure = env - .new_object(&failure_class, "()V", &[]) - .expect("Failed to create KeygenFailure.GenerationFailure Java object"); - - let class = get_class("net/mullvad/mullvadvpn/model/KeygenEvent$Failure"); - env.new_object( - &class, - "(Lnet/mullvad/mullvadvpn/model/KeygenFailure;)V", - &[JValue::Object(failure)], - ) - .expect("Failed to create KeygenEvent.GenerationFailure Java object") - } - } - } -} - -impl<'env> IntoJava<'env> for RelayConstraints { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/RelaySettings$RelayConstraints"); - let location = env.auto_local(self.location.into_java(env)); - let parameters = [JValue::Object(location.as_obj())]; - - env.new_object( - &class, - "(Lnet/mullvad/mullvadvpn/model/Constraint;)V", - ¶meters, - ) - .expect("Failed to create RelaySettings.RelayConstraints Java object") - } -} - -impl<'env> IntoJava<'env> for Settings { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class = get_class("net/mullvad/mullvadvpn/model/Settings"); - let account_token = env.auto_local(JObject::from(self.get_account_token().into_java(env))); - let relay_settings = env.auto_local(self.get_relay_settings().into_java(env)); - let parameters = [ - JValue::Object(account_token.as_obj()), - JValue::Object(relay_settings.as_obj()), - ]; - - env.new_object( - &class, - "(Ljava/lang/String;Lnet/mullvad/mullvadvpn/model/RelaySettings;)V", - ¶meters, - ) - .expect("Failed to create Settings Java object") - } -} - -impl<'env> IntoJava<'env> for ActionAfterDisconnect { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let variant = match self { - ActionAfterDisconnect::Nothing => "Nothing", - ActionAfterDisconnect::Block => "Block", - ActionAfterDisconnect::Reconnect => "Reconnect", - }; - let class_name = format!( - "net/mullvad/talpid/tunnel/ActionAfterDisconnect${}", - variant - ); - let class = get_class(&class_name); - - env.new_object(&class, "()V", &[]) - .expect("Failed to create ActionAfterDisconnect sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for BlockReason { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let variant = match self { - BlockReason::AuthFailed(reason) => { - let class = get_class("net/mullvad/talpid/tunnel/BlockReason$AuthFailed"); - let reason = env.auto_local(JObject::from(reason.into_java(env))); - let parameters = [JValue::Object(reason.as_obj())]; - - return env - .new_object(&class, "(Ljava/lang/String;)V", ¶meters) - .expect("Failed to create BlockReason.AuthFailed Java object"); - } - BlockReason::Ipv6Unavailable => "Ipv6Unavailable", - BlockReason::SetFirewallPolicyError => "SetFirewallPolicyError", - BlockReason::SetDnsError => "SetDnsError", - BlockReason::StartTunnelError => "StartTunnelError", - BlockReason::TunnelParameterError(reason) => { - let class = get_class("net/mullvad/talpid/tunnel/BlockReason$ParameterGeneration"); - let reason = env.auto_local(JObject::from(reason.into_java(env))); - let parameters = [JValue::Object(reason.as_obj())]; - return env - .new_object( - &class, - "(Lnet/mullvad/talpid/tunnel/ParameterGenerationError;)V", - ¶meters, - ) - .expect("Failed to create BlockReason.ParameterGeneration Java object"); - } - BlockReason::IsOffline => "IsOffline", - BlockReason::TapAdapterProblem => "TapAdapterProblem", - }; - let class_name = format!("net/mullvad/talpid/tunnel/BlockReason${}", variant); - let class = get_class(&class_name); - - env.new_object(&class, "()V", &[]) - .expect("Failed to create BlockReason sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for ParameterGenerationError { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - let class_variant = match self { - ParameterGenerationError::NoMatchingRelay => "NoMatchingRelay", - ParameterGenerationError::NoMatchingBridgeRelay => "NoMatchingBridgeRelay ", - ParameterGenerationError::NoWireguardKey => "NoWireguardKey", - ParameterGenerationError::CustomTunnelHostResultionError => { - "CustomTunnelHostResultionError" - } - }; - let class_name = format!( - "net/mullvad/talpid/tunnel/ParameterGenerationError${}", - class_variant - ); - let class = get_class(&class_name); - env.new_object(&class, "()V", &[]) - .expect("Failed to create ParameterGenerationError sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for TunnelState { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - TunnelState::Disconnected => { - let class = get_class("net/mullvad/mullvadvpn/model/TunnelState$Disconnected"); - - env.new_object(&class, "()V", &[]) - } - TunnelState::Connecting { endpoint, location } => { - let class = get_class("net/mullvad/mullvadvpn/model/TunnelState$Connecting"); - let endpoint = env.auto_local(endpoint.into_java(env)); - let location = env.auto_local(location.into_java(env)); - let parameters = [ - JValue::Object(endpoint.as_obj()), - JValue::Object(location.as_obj()), - ]; - let signature = - "(Lnet/mullvad/talpid/net/TunnelEndpoint;Lnet/mullvad/mullvadvpn/model/GeoIpLocation;)V"; - - env.new_object(&class, signature, ¶meters) - } - TunnelState::Connected { endpoint, location } => { - let class = get_class("net/mullvad/mullvadvpn/model/TunnelState$Connected"); - let endpoint = env.auto_local(endpoint.into_java(env)); - let location = env.auto_local(location.into_java(env)); - let parameters = [ - JValue::Object(endpoint.as_obj()), - JValue::Object(location.as_obj()), - ]; - let signature = - "(Lnet/mullvad/talpid/net/TunnelEndpoint;Lnet/mullvad/mullvadvpn/model/GeoIpLocation;)V"; - - env.new_object(&class, signature, ¶meters) - } - TunnelState::Disconnecting(action_after_disconnect) => { - let class = get_class("net/mullvad/mullvadvpn/model/TunnelState$Disconnecting"); - let after_disconnect = env.auto_local(action_after_disconnect.into_java(env)); - let parameters = [JValue::Object(after_disconnect.as_obj())]; - let signature = "(Lnet/mullvad/talpid/tunnel/ActionAfterDisconnect;)V"; - - env.new_object(&class, signature, ¶meters) - } - TunnelState::Blocked(block_reason) => { - let class = get_class("net/mullvad/mullvadvpn/model/TunnelState$Blocked"); - let reason = env.auto_local(block_reason.into_java(env)); - let parameters = [JValue::Object(reason.as_obj())]; - let signature = "(Lnet/mullvad/talpid/tunnel/BlockReason;)V"; - - env.new_object(&class, signature, ¶meters) - } - } - .expect("Failed to create TunnelState sub-class variant Java object") - } -} - -impl<'env> IntoJava<'env> for Result<AccountData, daemon_interface::Error> { - type JavaType = JObject<'env>; - - fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType { - match self { - Ok(data) => { - let class = get_class("net/mullvad/mullvadvpn/model/GetAccountDataResult$Ok"); - let java_account_data = env.auto_local(data.into_java(&env)); - let parameters = [JValue::Object(java_account_data.as_obj())]; - - env.new_object( - &class, - "(Lnet/mullvad/mullvadvpn/model/AccountData;)V", - ¶meters, - ) - .expect("Failed to create GetAccountDataResult.Ok Java object") - } - Err(error) => { - let class_name = match error { - daemon_interface::Error::RpcError(jsonrpc_client_core::Error( - jsonrpc_client_core::ErrorKind::JsonRpcError(jsonrpc_core::Error { - code: jsonrpc_core::ErrorCode::ServerError(-200), - .. - }), - _, - )) => "net/mullvad/mullvadvpn/model/GetAccountDataResult$InvalidAccount", - daemon_interface::Error::RpcError(_) => { - "net/mullvad/mullvadvpn/model/GetAccountDataResult$RpcError" - } - _ => "net/mullvad/mullvadvpn/model/GetAccountDataResult$OtherError", - }; - let class = get_class(class_name); - - env.new_object(&class, "()V", &[]) - .expect("Failed to create a GetAccountDataResult error sub-class Java object") - } - } - } -} diff --git a/mullvad-jni/src/is_null.rs b/mullvad-jni/src/is_null.rs index 628fc4c81a..9353d7211c 100644 --- a/mullvad-jni/src/is_null.rs +++ b/mullvad-jni/src/is_null.rs @@ -1,4 +1,4 @@ -use jni::objects::{JObject, JString}; +use jnix::jni::objects::{JObject, JString}; use std::ops::Deref; pub trait IsNull { diff --git a/mullvad-jni/src/jni_event_listener.rs b/mullvad-jni/src/jni_event_listener.rs index 5725171ca1..45020111fa 100644 --- a/mullvad-jni/src/jni_event_listener.rs +++ b/mullvad-jni/src/jni_event_listener.rs @@ -1,8 +1,9 @@ -use crate::{get_class, into_java::IntoJava}; -use jni::{ - objects::{GlobalRef, JMethodID, JObject, JValue}, - signature::{JavaType, Primitive}, - AttachGuard, JNIEnv, +use jnix::{ + jni::{ + objects::{GlobalRef, JMethodID, JObject, JValue}, + signature::{JavaType, Primitive}, + }, + IntoJava, JnixEnv, }; use mullvad_daemon::EventListener; use mullvad_types::{ @@ -16,13 +17,13 @@ use talpid_types::ErrorExt; #[error(no_from)] pub enum Error { #[error(display = "Failed to create global reference to MullvadDaemon Java object")] - CreateGlobalReference(#[error(source)] jni::errors::Error), + CreateGlobalReference(#[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to find {} method", _0)] - FindMethod(&'static str, #[error(source)] jni::errors::Error), + FindMethod(&'static str, #[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to retrieve Java VM instance")] - GetJvmInstance(#[error(source)] jni::errors::Error), + GetJvmInstance(#[error(source)] jnix::jni::errors::Error), } enum Event { @@ -37,7 +38,7 @@ enum Event { pub struct JniEventListener(mpsc::Sender<Event>); impl JniEventListener { - pub fn spawn(env: &JNIEnv, mullvad_daemon: &JObject) -> Result<Self, Error> { + pub fn spawn(env: &JnixEnv, mullvad_daemon: &JObject) -> Result<Self, Error> { JniEventHandler::spawn(env, mullvad_daemon) } } @@ -65,7 +66,7 @@ impl EventListener for JniEventListener { } struct JniEventHandler<'env> { - env: AttachGuard<'env>, + env: JnixEnv<'env>, mullvad_ipc_client: JObject<'env>, notify_app_version_info_event: JMethodID<'env>, notify_keygen_event: JMethodID<'env>, @@ -77,7 +78,7 @@ struct JniEventHandler<'env> { impl JniEventHandler<'_> { pub fn spawn( - old_env: &JNIEnv, + old_env: &JnixEnv, old_mullvad_ipc_client: &JObject, ) -> Result<JniEventListener, Error> { let (tx, rx) = mpsc::channel(); @@ -87,10 +88,14 @@ impl JniEventHandler<'_> { .map_err(Error::CreateGlobalReference)?; thread::spawn(move || match jvm.attach_current_thread() { - Ok(env) => match JniEventHandler::new(env, mullvad_ipc_client.as_obj(), rx) { - Ok(mut listener) => listener.run(), - Err(error) => log::error!("{}", error.display_chain()), - }, + Ok(attach_guard) => { + let env = JnixEnv::from(attach_guard.clone()); + + match JniEventHandler::new(env, mullvad_ipc_client.as_obj(), rx) { + Ok(mut listener) => listener.run(), + Err(error) => log::error!("{}", error.display_chain()), + } + } Err(error) => { log::error!( "{}", @@ -107,11 +112,11 @@ impl JniEventHandler<'_> { impl<'env> JniEventHandler<'env> { fn new( - env: AttachGuard<'env>, + env: JnixEnv<'env>, mullvad_ipc_client: JObject<'env>, events: mpsc::Receiver<Event>, ) -> Result<Self, Error> { - let class = get_class("net/mullvad/mullvadvpn/MullvadDaemon"); + let class = env.get_class("net/mullvad/mullvadvpn/MullvadDaemon"); let notify_app_version_info_event = Self::get_method_id( &env, &class, @@ -156,7 +161,7 @@ impl<'env> JniEventHandler<'env> { } fn get_method_id( - env: &AttachGuard<'env>, + env: &JnixEnv<'env>, class: &GlobalRef, method: &'static str, signature: &str, @@ -180,7 +185,7 @@ impl<'env> JniEventHandler<'env> { } fn handle_keygen_event(&self, event: KeygenEvent) { - let java_keygen_event = self.env.auto_local(event.into_java(&self.env)); + let java_keygen_event = event.into_java(&self.env); let result = self.env.call_method_unchecked( self.mullvad_ipc_client, @@ -198,7 +203,7 @@ impl<'env> JniEventHandler<'env> { } fn handle_relay_list_event(&self, relay_list: RelayList) { - let java_relay_list = self.env.auto_local(relay_list.into_java(&self.env)); + let java_relay_list = relay_list.into_java(&self.env); let result = self.env.call_method_unchecked( self.mullvad_ipc_client, @@ -216,7 +221,7 @@ impl<'env> JniEventHandler<'env> { } fn handle_settings(&self, settings: Settings) { - let java_settings = self.env.auto_local(settings.into_java(&self.env)); + let java_settings = settings.into_java(&self.env); let result = self.env.call_method_unchecked( self.mullvad_ipc_client, @@ -234,7 +239,7 @@ impl<'env> JniEventHandler<'env> { } fn handle_tunnel_event(&self, event: TunnelState) { - let java_tunnel_state = self.env.auto_local(event.into_java(&self.env)); + let java_tunnel_state = event.into_java(&self.env); let result = self.env.call_method_unchecked( self.mullvad_ipc_client, @@ -252,7 +257,7 @@ impl<'env> JniEventHandler<'env> { } fn handle_app_version_info_event(&self, app_version_info: AppVersionInfo) { - let java_app_version_info = self.env.auto_local(app_version_info.into_java(&self.env)); + let java_app_version_info = app_version_info.into_java(&self.env); let result = self.env.call_method_unchecked( self.mullvad_ipc_client, diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index 11c4d8b7e7..0e00decd04 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -1,26 +1,28 @@ #![cfg(target_os = "android")] +mod classes; mod daemon_interface; mod from_java; -mod into_java; mod is_null; mod jni_event_listener; mod vpn_service_tun_provider; use crate::{ - daemon_interface::DaemonInterface, from_java::FromJava, into_java::IntoJava, - jni_event_listener::JniEventListener, vpn_service_tun_provider::VpnServiceTunProvider, + daemon_interface::DaemonInterface, from_java::FromJava, jni_event_listener::JniEventListener, + vpn_service_tun_provider::VpnServiceTunProvider, }; -use jni::{ - objects::{GlobalRef, JObject, JString, JValue}, - sys::{jboolean, JNI_FALSE, JNI_TRUE}, - JNIEnv, +use jnix::{ + jni::{ + objects::{JObject, JString, JValue}, + sys::{jboolean, JNI_FALSE, JNI_TRUE}, + JNIEnv, + }, + IntoJava, JnixEnv, }; use lazy_static::lazy_static; use mullvad_daemon::{logging, version, Daemon, DaemonCommandSender}; -use parking_lot::RwLock; +use mullvad_types::account::AccountData; use std::{ - collections::HashMap, path::{Path, PathBuf}, sync::{mpsc, Once}, thread, @@ -29,74 +31,10 @@ use talpid_types::ErrorExt; const LOG_FILENAME: &str = "daemon.log"; -const CLASSES_TO_LOAD: &[&str] = &[ - "java/lang/Boolean", - "java/net/InetAddress", - "java/net/InetSocketAddress", - "java/util/ArrayList", - "net/mullvad/mullvadvpn/model/AccountData", - "net/mullvad/mullvadvpn/model/AppVersionInfo", - "net/mullvad/mullvadvpn/model/Constraint$Any", - "net/mullvad/mullvadvpn/model/Constraint$Only", - "net/mullvad/mullvadvpn/model/GeoIpLocation", - "net/mullvad/mullvadvpn/model/GetAccountDataResult$Ok", - "net/mullvad/mullvadvpn/model/GetAccountDataResult$InvalidAccount", - "net/mullvad/mullvadvpn/model/GetAccountDataResult$RpcError", - "net/mullvad/mullvadvpn/model/GetAccountDataResult$OtherError", - "net/mullvad/mullvadvpn/model/KeygenEvent$NewKey", - "net/mullvad/mullvadvpn/model/KeygenEvent$Failure", - "net/mullvad/mullvadvpn/model/KeygenFailure$TooManyKeys", - "net/mullvad/mullvadvpn/model/KeygenFailure$GenerationFailure", - "net/mullvad/mullvadvpn/model/LocationConstraint$City", - "net/mullvad/mullvadvpn/model/LocationConstraint$Country", - "net/mullvad/mullvadvpn/model/LocationConstraint$Hostname", - "net/mullvad/mullvadvpn/model/PublicKey", - "net/mullvad/mullvadvpn/model/Relay", - "net/mullvad/mullvadvpn/model/RelayList", - "net/mullvad/mullvadvpn/model/RelayListCity", - "net/mullvad/mullvadvpn/model/RelayListCountry", - "net/mullvad/mullvadvpn/model/RelaySettings$CustomTunnelEndpoint", - "net/mullvad/mullvadvpn/model/RelaySettings$RelayConstraints", - "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$CustomTunnelEndpoint", - "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$RelayConstraintsUpdate", - "net/mullvad/mullvadvpn/model/Settings", - "net/mullvad/mullvadvpn/model/TunnelState$Blocked", - "net/mullvad/mullvadvpn/model/TunnelState$Connected", - "net/mullvad/mullvadvpn/model/TunnelState$Connecting", - "net/mullvad/mullvadvpn/model/TunnelState$Disconnected", - "net/mullvad/mullvadvpn/model/TunnelState$Disconnecting", - "net/mullvad/mullvadvpn/MullvadDaemon", - "net/mullvad/mullvadvpn/MullvadVpnService", - "net/mullvad/talpid/net/Endpoint", - "net/mullvad/talpid/net/TransportProtocol$Tcp", - "net/mullvad/talpid/net/TransportProtocol$Udp", - "net/mullvad/talpid/net/TunnelEndpoint", - "net/mullvad/talpid/tun_provider/InetNetwork", - "net/mullvad/talpid/tun_provider/TunConfig", - "net/mullvad/talpid/tunnel/ActionAfterDisconnect$Block", - "net/mullvad/talpid/tunnel/ActionAfterDisconnect$Nothing", - "net/mullvad/talpid/tunnel/ActionAfterDisconnect$Reconnect", - "net/mullvad/talpid/tunnel/BlockReason$AuthFailed", - "net/mullvad/talpid/tunnel/BlockReason$Ipv6Unavailable", - "net/mullvad/talpid/tunnel/BlockReason$SetFirewallPolicyError", - "net/mullvad/talpid/tunnel/BlockReason$SetDnsError", - "net/mullvad/talpid/tunnel/BlockReason$StartTunnelError", - "net/mullvad/talpid/tunnel/BlockReason$ParameterGeneration", - "net/mullvad/talpid/tunnel/BlockReason$IsOffline", - "net/mullvad/talpid/tunnel/BlockReason$TapAdapterProblem", - "net/mullvad/talpid/tunnel/ParameterGenerationError$NoMatchingRelay", - "net/mullvad/talpid/tunnel/ParameterGenerationError$NoMatchingBridgeRelay", - "net/mullvad/talpid/tunnel/ParameterGenerationError$NoWireguardKey", - "net/mullvad/talpid/tunnel/ParameterGenerationError$CustomTunnelHostResultionError", - "net/mullvad/talpid/TalpidVpnService", -]; - lazy_static! { static ref LOG_INIT_RESULT: Result<PathBuf, String> = start_logging().map_err(|error| error.display_chain()); static ref DAEMON_INTERFACE: DaemonInterface = DaemonInterface::new(); - static ref CLASSES: RwLock<HashMap<&'static str, GlobalRef>> = - RwLock::new(HashMap::with_capacity(CLASSES_TO_LOAD.len())); } static LOAD_CLASSES: Once = Once::new(); @@ -123,6 +61,34 @@ pub enum Error { StartLogging(#[error(source)] logging::Error), } +#[derive(IntoJava)] +#[jnix(package = "net.mullvad.mullvadvpn.model")] +pub enum GetAccountDataResult { + Ok(AccountData), + InvalidAccount, + RpcError, + OtherError, +} + +impl From<Result<AccountData, daemon_interface::Error>> for GetAccountDataResult { + fn from(result: Result<AccountData, daemon_interface::Error>) -> Self { + match result { + Ok(account_data) => GetAccountDataResult::Ok(account_data), + Err(error) => match error { + daemon_interface::Error::RpcError(jsonrpc_client_core::Error( + jsonrpc_client_core::ErrorKind::JsonRpcError(jsonrpc_core::Error { + code: jsonrpc_core::ErrorCode::ServerError(-200), + .. + }), + _, + )) => GetAccountDataResult::InvalidAccount, + daemon_interface::Error::RpcError(_) => GetAccountDataResult::RpcError, + _ => GetAccountDataResult::OtherError, + }, + } + } +} + #[no_mangle] #[allow(non_snake_case)] pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_initialize( @@ -130,9 +96,11 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_initialize( this: JObject, vpnService: JObject, ) { + let env = JnixEnv::from(env); + match *LOG_INIT_RESULT { Ok(ref log_dir) => { - LOAD_CLASSES.call_once(|| load_classes(&env)); + LOAD_CLASSES.call_once(|| env.preload_classes(classes::CLASSES.iter().cloned())); if let Err(error) = initialize(&env, &this, &vpnService, log_dir.clone()) { log::error!("{}", error.display_chain()); @@ -156,26 +124,8 @@ fn start_logging() -> Result<PathBuf, Error> { Ok(log_dir) } -fn load_classes(env: &JNIEnv) { - let mut classes = CLASSES.write(); - - for class in CLASSES_TO_LOAD { - classes.insert(class, load_class_reference(env, class)); - } -} - -fn load_class_reference(env: &JNIEnv, name: &str) -> GlobalRef { - let class = match env.find_class(name) { - Ok(class) => class, - Err(_) => panic!("Failed to find {} Java class", name), - }; - - env.new_global_ref(JObject::from(class)) - .expect("Failed to convert local reference to Java class into a global reference") -} - fn initialize( - env: &JNIEnv, + env: &JnixEnv, this: &JObject, vpn_service: &JObject, log_dir: PathBuf, @@ -190,7 +140,7 @@ fn initialize( } fn spawn_daemon( - env: &JNIEnv, + env: &JnixEnv, this: &JObject, tun_provider: VpnServiceTunProvider, log_dir: PathBuf, @@ -236,13 +186,6 @@ fn create_daemon( Ok(daemon) } -fn get_class(name: &str) -> GlobalRef { - match CLASSES.read().get(name) { - Some(class) => class.clone(), - None => panic!("Class not loaded: {}", name), - } -} - #[no_mangle] #[allow(non_snake_case)] pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_connect(_: JNIEnv, _: JObject) { @@ -271,8 +214,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_generateWiregua env: JNIEnv<'env>, _: JObject, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.generate_wireguard_key() { - Ok(keygen_event) => keygen_event.into_java(&env), + Ok(keygen_event) => keygen_event.into_java(&env).forget(), Err(error) => { log::error!( "{}", @@ -289,10 +234,12 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_verifyWireguard env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.verify_wireguard_key() { Ok(key_is_valid) => env .new_object( - &get_class("java/lang/Boolean"), + &env.get_class("java/lang/Boolean"), "(Z)V", &[JValue::Bool(key_is_valid as jboolean)], ) @@ -314,6 +261,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getAccountData< _: JObject<'this>, accountToken: JString, ) -> JObject<'env> { + let env = JnixEnv::from(env); let account = String::from_java(&env, accountToken); let result = DAEMON_INTERFACE.get_account_data(account); @@ -324,7 +272,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getAccountData< ); } - result.into_java(&env) + GetAccountDataResult::from(result).into_java(&env).forget() } #[no_mangle] @@ -332,15 +280,17 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getAccountData< pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getWwwAuthToken<'env, 'this>( env: JNIEnv<'env>, _: JObject<'this>, -) -> JString<'env> { +) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_www_auth_token() { - Ok(token) => token.into_java(&env), + Ok(token) => token.into_java(&env).forget(), Err(err) => { log::error!( "{}", err.display_chain_with_msg("Failed to get WWW auth token") ); - String::new().into_java(&env) + String::new().into_java(&env).forget() } } } @@ -351,8 +301,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getCurrentLocat env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_current_location() { - Ok(location) => location.into_java(&env), + Ok(location) => location.into_java(&env).forget(), Err(error) => { log::error!( "{}", @@ -368,15 +320,17 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getCurrentLocat pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getCurrentVersion<'env, 'this>( env: JNIEnv<'env>, _: JObject<'this>, -) -> JString<'env> { +) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_current_version() { - Ok(location) => location.into_java(&env), + Ok(location) => location.into_java(&env).forget(), Err(error) => { log::error!( "{}", error.display_chain_with_msg("Failed to get current version") ); - String::new().into_java(&env) + String::new().into_java(&env).forget() } } } @@ -387,8 +341,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getRelayLocatio env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_relay_locations() { - Ok(relay_list) => relay_list.into_java(&env), + Ok(relay_list) => relay_list.into_java(&env).forget(), Err(error) => { log::error!( "{}", @@ -405,8 +361,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getSettings<'en env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_settings() { - Ok(settings) => settings.into_java(&env), + Ok(settings) => settings.into_java(&env).forget(), Err(error) => { log::error!("{}", error.display_chain_with_msg("Failed to get settings")); JObject::null() @@ -420,8 +378,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getState<'env, env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_state() { - Ok(state) => state.into_java(&env), + Ok(state) => state.into_java(&env).forget(), Err(error) => { log::error!("{}", error.display_chain_with_msg("Failed to get state")); JObject::null() @@ -435,8 +395,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getVersionInfo< env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_version_info() { - Ok(version_info) => version_info.into_java(&env), + Ok(version_info) => version_info.into_java(&env).forget(), Err(error) => { log::error!( "{}", @@ -453,8 +415,10 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_getWireguardKey env: JNIEnv<'env>, _: JObject<'this>, ) -> JObject<'env> { + let env = JnixEnv::from(env); + match DAEMON_INTERFACE.get_wireguard_key() { - Ok(key) => key.into_java(&env), + Ok(key) => key.into_java(&env).forget(), Err(error) => { log::error!( "{}", @@ -472,6 +436,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_setAccount( _: JObject, accountToken: JString, ) { + let env = JnixEnv::from(env); let account = <Option<String> as FromJava>::from_java(&env, accountToken); if let Err(error) = DAEMON_INTERFACE.set_account(account) { @@ -497,6 +462,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_updateRelaySett _: JObject, relaySettingsUpdate: JObject, ) { + let env = JnixEnv::from(env); let update = FromJava::from_java(&env, relaySettingsUpdate); if let Err(error) = DAEMON_INTERFACE.update_relay_settings(update) { @@ -514,6 +480,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_dataproxy_MullvadProblemRepor _: JObject, outputPath: JString, ) -> jboolean { + let env = JnixEnv::from(env); let output_path_string = String::from_java(&env, outputPath); let output_path = Path::new(&output_path_string); @@ -538,6 +505,7 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_dataproxy_MullvadProblemRepor userMessage: JString, outputPath: JString, ) -> jboolean { + let env = JnixEnv::from(env); let user_email = String::from_java(&env, userEmail); let user_message = String::from_java(&env, userMessage); let output_path_string = String::from_java(&env, outputPath); diff --git a/mullvad-jni/src/vpn_service_tun_provider.rs b/mullvad-jni/src/vpn_service_tun_provider.rs index 35ca55c300..01f1905814 100644 --- a/mullvad-jni/src/vpn_service_tun_provider.rs +++ b/mullvad-jni/src/vpn_service_tun_provider.rs @@ -1,9 +1,11 @@ -use crate::{get_class, into_java::IntoJava}; use ipnetwork::IpNetwork; -use jni::{ - objects::{GlobalRef, JObject, JValue}, - signature::{JavaType, Primitive}, - JNIEnv, JavaVM, +use jnix::{ + jni::{ + objects::{GlobalRef, JObject, JValue}, + signature::{JavaType, Primitive}, + JavaVM, + }, + IntoJava, JnixEnv, }; use std::{ fs::File, @@ -20,25 +22,25 @@ use talpid_types::BoxedError; #[error(no_from)] pub enum Error { #[error(display = "Failed to attach Java VM to tunnel thread")] - AttachJvmToThread(#[error(source)] jni::errors::Error), + AttachJvmToThread(#[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to allow socket to bypass tunnel")] Bypass, #[error(display = "Failed to call Java method TalpidVpnService.{}", _0)] - CallMethod(&'static str, #[error(source)] jni::errors::Error), + CallMethod(&'static str, #[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to create Java VM handle clone")] - CloneJavaVm(#[error(source)] jni::errors::Error), + CloneJavaVm(#[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to create global reference to TalpidVpnService instance")] - CreateGlobalReference(#[error(source)] jni::errors::Error), + CreateGlobalReference(#[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to find TalpidVpnService.{} method", _0)] - FindMethod(&'static str, #[error(source)] jni::errors::Error), + FindMethod(&'static str, #[error(source)] jnix::jni::errors::Error), #[error(display = "Failed to get Java VM instance")] - GetJvmInstance(#[error(source)] jni::errors::Error), + GetJvmInstance(#[error(source)] jnix::jni::errors::Error), #[error( display = "Received an invalid result from TalpidVpnService.{}: {}", @@ -59,9 +61,9 @@ pub struct VpnServiceTunProvider { impl VpnServiceTunProvider { /// Create a new VpnServiceTunProvider interfacing with Android's VpnService. - pub fn new(env: &JNIEnv, mullvad_vpn_service: &JObject) -> Result<Self, Error> { + pub fn new(env: &JnixEnv, mullvad_vpn_service: &JObject) -> Result<Self, Error> { let jvm = env.get_java_vm().map_err(Error::GetJvmInstance)?; - let class = get_class("net/mullvad/talpid/TalpidVpnService"); + let class = env.get_class("net/mullvad/talpid/TalpidVpnService"); let object = env .new_global_ref(*mullvad_vpn_service) .map_err(Error::CreateGlobalReference)?; @@ -103,10 +105,11 @@ impl VpnServiceTunProvider { } fn open_tun(&mut self, config: TunConfig) -> Result<(), Error> { - let env = self - .jvm - .attach_current_thread_as_daemon() - .map_err(Error::AttachJvmToThread)?; + let env = JnixEnv::from( + self.jvm + .attach_current_thread_as_daemon() + .map_err(Error::AttachJvmToThread)?, + ); let create_tun_method = env .get_method_id( &self.class, @@ -115,7 +118,7 @@ impl VpnServiceTunProvider { ) .map_err(|cause| Error::FindMethod("createTun", cause))?; - let java_config = env.auto_local(config.clone().into_java(&env)); + let java_config = config.clone().into_java(&env); let result = env .call_method_unchecked( self.object.as_obj(), @@ -194,10 +197,11 @@ impl Tun for VpnServiceTun { } fn bypass(&mut self, socket: RawFd) -> Result<(), BoxedError> { - let env = self - .jvm - .attach_current_thread_as_daemon() - .map_err(|cause| BoxedError::new(Error::AttachJvmToThread(cause)))?; + let env = JnixEnv::from( + self.jvm + .attach_current_thread_as_daemon() + .map_err(|cause| BoxedError::new(Error::AttachJvmToThread(cause)))?, + ); let create_tun_method = env .get_method_id(&self.class, "bypass", "(I)Z") .map_err(|cause| BoxedError::new(Error::FindMethod("bypass", cause)))?; diff --git a/mullvad-types/Cargo.toml b/mullvad-types/Cargo.toml index f02cbc0dab..8ec0369d69 100644 --- a/mullvad-types/Cargo.toml +++ b/mullvad-types/Cargo.toml @@ -18,3 +18,6 @@ serde_json = "1.0" talpid-types = { path = "../talpid-types" } mullvad-paths = { path = "../mullvad-paths" } + +[target.'cfg(target_os = "android")'.dependencies] +jnix = { version = "0.1", features = ["derive"] } diff --git a/mullvad-types/src/account.rs b/mullvad-types/src/account.rs index 909b6c0070..a725db13ee 100644 --- a/mullvad-types/src/account.rs +++ b/mullvad-types/src/account.rs @@ -1,10 +1,15 @@ use chrono::{offset::Utc, DateTime}; +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; pub type AccountToken = String; #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct AccountData { + #[cfg_attr(target_os = "android", jnix(map = "|expiry| expiry.to_string()"))] pub expiry: DateTime<Utc>, } diff --git a/mullvad-types/src/custom_tunnel.rs b/mullvad-types/src/custom_tunnel.rs index ea84e28979..12c293c22d 100644 --- a/mullvad-types/src/custom_tunnel.rs +++ b/mullvad-types/src/custom_tunnel.rs @@ -1,4 +1,6 @@ use crate::settings::TunnelOptions; +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::{ fmt, io, @@ -18,6 +20,10 @@ pub enum Error { #[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] +// TODO: Remove this Java conversion once `jnix` supports skipping fields in enum tuple variants. +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] +#[cfg_attr(target_os = "android", jnix(skip_all))] pub struct CustomTunnelEndpoint { host: String, config: ConnectionConfig, diff --git a/mullvad-types/src/location.rs b/mullvad-types/src/location.rs index fbb2c1a7ef..07a0c00795 100644 --- a/mullvad-types/src/location.rs +++ b/mullvad-types/src/location.rs @@ -1,3 +1,5 @@ +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; @@ -64,15 +66,21 @@ pub struct AmIMullvad { /// GeoIP information exposed from the daemon to frontends. #[derive(Debug, Clone, Serialize, Deserialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct GeoIpLocation { pub ipv4: Option<Ipv4Addr>, pub ipv6: Option<Ipv6Addr>, pub country: String, pub city: Option<String>, + #[cfg_attr(target_os = "android", jnix(skip))] pub latitude: f64, + #[cfg_attr(target_os = "android", jnix(skip))] pub longitude: f64, + #[cfg_attr(target_os = "android", jnix(skip))] pub mullvad_exit_ip: bool, pub hostname: Option<String>, + #[cfg_attr(target_os = "android", jnix(skip))] pub bridge_hostname: Option<String>, } diff --git a/mullvad-types/src/relay_constraints.rs b/mullvad-types/src/relay_constraints.rs index 9306b6670b..63d8070a0e 100644 --- a/mullvad-types/src/relay_constraints.rs +++ b/mullvad-types/src/relay_constraints.rs @@ -3,6 +3,8 @@ use crate::{ relay_list::{OpenVpnEndpointData, WireguardEndpointData}, CustomTunnelEndpoint, }; +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::fmt; use talpid_types::net::{openvpn::ProxySettings, TransportProtocol}; @@ -14,6 +16,8 @@ pub trait Match<T> { #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum Constraint<T: fmt::Debug + Clone + Eq + PartialEq> { Any, Only(T), @@ -61,6 +65,8 @@ impl<T: fmt::Debug + Clone + Eq + PartialEq> Match<T> for Constraint<T> { #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum RelaySettings { CustomTunnelEndpoint(CustomTunnelEndpoint), Normal(RelayConstraints), @@ -120,10 +126,15 @@ impl RelaySettings { #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[cfg_attr(not(target_os = "android"), derive(Default))] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct RelayConstraints { pub location: Constraint<LocationConstraint>, + #[cfg_attr(target_os = "android", jnix(skip))] pub tunnel_protocol: Constraint<TunnelProtocol>, + #[cfg_attr(target_os = "android", jnix(skip))] pub wireguard_constraints: WireguardConstraints, + #[cfg_attr(target_os = "android", jnix(skip))] pub openvpn_constraints: OpenVpnConstraints, } @@ -187,6 +198,8 @@ impl fmt::Display for RelayConstraints { #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum LocationConstraint { /// A country is represented by its two letter country code. Country(CountryCode), diff --git a/mullvad-types/src/relay_list.rs b/mullvad-types/src/relay_list.rs index ee87751c43..a086dd108c 100644 --- a/mullvad-types/src/relay_list.rs +++ b/mullvad-types/src/relay_list.rs @@ -2,7 +2,8 @@ use crate::{ endpoint::MullvadEndpoint, location::{CityCode, CountryCode, Location}, }; - +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::{ fmt, @@ -15,6 +16,8 @@ use talpid_types::net::{ #[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct RelayList { pub countries: Vec<RelayListCountry>, } @@ -28,6 +31,8 @@ impl RelayList { } #[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct RelayListCountry { pub name: String, pub code: CountryCode, @@ -35,32 +40,46 @@ pub struct RelayListCountry { } #[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct RelayListCity { pub name: String, pub code: CityCode, + #[cfg_attr(target_os = "android", jnix(skip))] pub latitude: f64, + #[cfg_attr(target_os = "android", jnix(skip))] pub longitude: f64, pub relays: Vec<Relay>, } #[derive(Debug, Clone, Deserialize, Serialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct Relay { pub hostname: String, + #[cfg_attr(target_os = "android", jnix(skip))] pub ipv4_addr_in: Ipv4Addr, + #[cfg_attr(target_os = "android", jnix(skip))] pub include_in_country: bool, pub active: bool, + #[cfg_attr(target_os = "android", jnix(skip))] pub weight: u64, #[serde(skip_serializing_if = "RelayTunnels::is_empty", default)] pub tunnels: RelayTunnels, #[serde(skip_serializing_if = "RelayBridges::is_empty", default)] + #[cfg_attr(target_os = "android", jnix(skip))] pub bridges: RelayBridges, #[serde(skip)] + #[cfg_attr(target_os = "android", jnix(skip))] pub location: Option<Location>, } #[derive(Debug, Default, Clone, Deserialize, Serialize)] #[serde(default)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct RelayTunnels { + #[cfg_attr(target_os = "android", jnix(skip))] pub openvpn: Vec<OpenVpnEndpointData>, pub wireguard: Vec<WireguardEndpointData>, } @@ -95,6 +114,9 @@ impl fmt::Display for OpenVpnEndpointData { } #[derive(Clone, Eq, PartialEq, Hash, Deserialize, Serialize, Debug)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] +#[cfg_attr(target_os = "android", jnix(skip_all))] pub struct WireguardEndpointData { /// Port to connect to pub port_ranges: Vec<(u16, u16)>, diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs index 80ea68c6ce..0c3aa2f6fe 100644 --- a/mullvad-types/src/settings/mod.rs +++ b/mullvad-types/src/settings/mod.rs @@ -2,6 +2,8 @@ use crate::relay_constraints::{ BridgeConstraints, BridgeSettings, BridgeState, Constraint, LocationConstraint, RelayConstraints, RelaySettings, RelaySettingsUpdate, }; +#[cfg(target_os = "android")] +use jnix::IntoJava; use log::{debug, info}; use serde::{Deserialize, Serialize}; use serde_json; @@ -53,22 +55,31 @@ static SETTINGS_FILE: &str = "settings.json"; /// Mullvad daemon settings. #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[serde(default)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct Settings { account_token: Option<String>, relay_settings: RelaySettings, + #[cfg_attr(target_os = "android", jnix(skip))] bridge_settings: BridgeSettings, + #[cfg_attr(target_os = "android", jnix(skip))] bridge_state: BridgeState, /// If the daemon should allow communication with private (LAN) networks. + #[cfg_attr(target_os = "android", jnix(skip))] allow_lan: bool, /// Extra level of kill switch. When this setting is on, the disconnected state will block /// the firewall to not allow any traffic in or out. + #[cfg_attr(target_os = "android", jnix(skip))] block_when_disconnected: bool, /// If the daemon should connect the VPN tunnel directly on start or not. + #[cfg_attr(target_os = "android", jnix(skip))] auto_connect: bool, /// Options that should be applied to tunnels of a specific type regardless of where the relays /// might be located. + #[cfg_attr(target_os = "android", jnix(skip))] tunnel_options: TunnelOptions, /// Specifies settings schema version + #[cfg_attr(target_os = "android", jnix(skip))] settings_version: migrations::SettingsVersion, } diff --git a/mullvad-types/src/states.rs b/mullvad-types/src/states.rs index 9c3ffa42a9..e905f329c5 100644 --- a/mullvad-types/src/states.rs +++ b/mullvad-types/src/states.rs @@ -1,4 +1,6 @@ use crate::location::GeoIpLocation; +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use talpid_types::{ net::TunnelEndpoint, @@ -19,6 +21,8 @@ pub enum TargetState { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] #[serde(tag = "state", content = "details")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum TunnelState { Disconnected, Connecting { diff --git a/mullvad-types/src/version.rs b/mullvad-types/src/version.rs index 6e626104d7..21fffca04b 100644 --- a/mullvad-types/src/version.rs +++ b/mullvad-types/src/version.rs @@ -1,8 +1,12 @@ +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; /// AppVersionInfo represents the current stable and the current latest release versions of the /// Mullvad VPN app. #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct AppVersionInfo { /// False if Mullvad has stopped supporting the currently running version. This could mean /// a number of things. For example: diff --git a/mullvad-types/src/wireguard.rs b/mullvad-types/src/wireguard.rs index 8675a6e845..dce0fb74de 100644 --- a/mullvad-types/src/wireguard.rs +++ b/mullvad-types/src/wireguard.rs @@ -1,4 +1,6 @@ use chrono::{offset::Utc, DateTime}; +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::fmt; use talpid_types::net::wireguard; @@ -24,8 +26,12 @@ impl WireguardData { /// Represents a published public key #[derive(Serialize, Deserialize, Clone, Debug)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct PublicKey { + #[cfg_attr(target_os = "android", jnix(map = "|key| *key.as_bytes()"))] pub key: wireguard::PublicKey, + #[cfg_attr(target_os = "android", jnix(map = "|date_time| date_time.to_string()"))] pub created: DateTime<Utc>, } @@ -37,9 +43,11 @@ pub struct AssociatedAddresses { pub ipv6_address: ipnetwork::Ipv6Network, } +/// Event that is emitted when the daemon has finished generating a key. #[serde(rename_all = "snake_case")] #[derive(Clone, Debug, Deserialize, Serialize)] -/// Event that is emitted when the daemon has finished generating a key. +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum KeygenEvent { NewKey(PublicKey), TooManyKeys, diff --git a/talpid-core/Cargo.toml b/talpid-core/Cargo.toml index 2695ca0f57..a91c71d843 100644 --- a/talpid-core/Cargo.toml +++ b/talpid-core/Cargo.toml @@ -37,6 +37,10 @@ tokio-executor = "0.1" tokio-io = "0.1" +[target.'cfg(target_os = "android")'.dependencies] +jnix = { version = "0.1", features = ["derive"] } + + [target.'cfg(target_os = "linux")'.dependencies] dbus = "0.6" failure = "0.1" diff --git a/talpid-core/src/tunnel/tun_provider/mod.rs b/talpid-core/src/tunnel/tun_provider/mod.rs index 16c9c3f17c..c6701ceac9 100644 --- a/talpid-core/src/tunnel/tun_provider/mod.rs +++ b/talpid-core/src/tunnel/tun_provider/mod.rs @@ -1,5 +1,7 @@ use cfg_if::cfg_if; use ipnetwork::IpNetwork; +#[cfg(target_os = "android")] +use jnix::IntoJava; use std::net::IpAddr; #[cfg(unix)] use std::os::unix::io::AsRawFd; @@ -71,6 +73,11 @@ pub trait TunProvider: Send + 'static { /// Configuration for creating a tunnel device. #[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr( + target_os = "android", + jnix(package = "net.mullvad.talpid.tun_provider") +)] pub struct TunConfig { /// IP addresses for the tunnel interface. pub addresses: Vec<IpAddr>, @@ -79,8 +86,31 @@ pub struct TunConfig { pub dns_servers: Vec<IpAddr>, /// Routes to configure for the tunnel. + #[cfg_attr( + target_os = "android", + jnix(map = "|networks| networks.into_iter().map(InetNetwork::from).collect::<Vec<_>>()") + )] pub routes: Vec<IpNetwork>, /// Maximum Transmission Unit in the tunnel. + #[cfg_attr(target_os = "android", jnix(map = "|mtu| mtu as i32"))] pub mtu: u16, } + +#[cfg(target_os = "android")] +#[derive(IntoJava)] +#[jnix(package = "net.mullvad.talpid.tun_provider")] +struct InetNetwork { + address: IpAddr, + prefix: i16, +} + +#[cfg(target_os = "android")] +impl From<IpNetwork> for InetNetwork { + fn from(ip_network: IpNetwork) -> Self { + InetNetwork { + address: ip_network.ip(), + prefix: ip_network.prefix() as i16, + } + } +} diff --git a/talpid-types/Cargo.toml b/talpid-types/Cargo.toml index 0412c8f501..ff675eed0d 100644 --- a/talpid-types/Cargo.toml +++ b/talpid-types/Cargo.toml @@ -13,3 +13,6 @@ base64 = "0.10" x25519-dalek = { version = "0.5", features = [ "std", "u64_backend" ], default-features = false } rand = "0.7" err-derive = "0.2.1" + +[target.'cfg(target_os = "android")'.dependencies] +jnix = { version = "0.1", features = ["derive"] } diff --git a/talpid-types/src/net/mod.rs b/talpid-types/src/net/mod.rs index 9c57e7b393..b3b38331cb 100644 --- a/talpid-types/src/net/mod.rs +++ b/talpid-types/src/net/mod.rs @@ -1,3 +1,5 @@ +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::{ error::Error, @@ -79,11 +81,15 @@ impl fmt::Display for TunnelType { /// A tunnel endpoint is broadcast during the connecting and connected states of the tunnel state /// machine. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.net"))] pub struct TunnelEndpoint { #[serde(flatten)] pub endpoint: Endpoint, /// Type of the tunnel + #[cfg_attr(target_os = "android", jnix(skip))] pub tunnel_type: TunnelType, + #[cfg_attr(target_os = "android", jnix(skip))] pub proxy: Option<proxy::ProxyEndpoint>, } @@ -104,6 +110,8 @@ impl fmt::Display for TunnelEndpoint { /// Represents a network layer IP address together with the transport layer protocol and port. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.net"))] pub struct Endpoint { /// The socket address for the endpoint pub address: SocketAddr, @@ -130,6 +138,8 @@ impl fmt::Display for Endpoint { /// Representation of a transport protocol, either UDP or TCP. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.net"))] pub enum TransportProtocol { /// Represents the UDP transport protocol. Udp, diff --git a/talpid-types/src/tunnel.rs b/talpid-types/src/tunnel.rs index 24b05ee24b..9ab3ed6d36 100644 --- a/talpid-types/src/tunnel.rs +++ b/talpid-types/src/tunnel.rs @@ -1,4 +1,6 @@ use crate::net::TunnelEndpoint; +#[cfg(target_os = "android")] +use jnix::IntoJava; use serde::{Deserialize, Serialize}; use std::fmt; @@ -22,6 +24,8 @@ pub enum TunnelStateTransition { /// Action that will be taken after disconnection is complete. #[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.tunnel"))] pub enum ActionAfterDisconnect { Nothing, Block, @@ -41,6 +45,8 @@ impl TunnelStateTransition { #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] #[serde(tag = "reason", content = "details")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.tunnel"))] pub enum BlockReason { /// Authentication with remote server failed. AuthFailed(Option<String>), @@ -63,6 +69,8 @@ pub enum BlockReason { /// Errors that can occur when generating tunnel parameters. #[derive(err_derive::Error, Debug, Serialize, Clone, PartialEq, Deserialize)] #[serde(rename_all = "snake_case")] +#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.talpid.tunnel"))] pub enum ParameterGenerationError { /// Failure to select a matching tunnel relay #[error(display = "Failure to select a matching tunnel relay")] |
