From d6a2974e55095aefd91a919b5fc6e3613b151c10 Mon Sep 17 00:00:00 2001 From: "Rajaratnam, Roshan" Date: Wed, 20 Nov 2019 16:31:29 +0100 Subject: [PATCH 1/4] Fixes a bug causing the maximum packet size to be calculated incorrectly this was introduced while migrating to BLE Library 2.1.1 --- .../nrfmeshprovisioner/ble/BleMeshManager.java | 11 +++++------ .../viewmodels/NrfMeshRepository.java | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java index 6481573e6..0b768c826 100644 --- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java +++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java @@ -108,11 +108,11 @@ public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) { @Override protected void initialize() { - requestMtu(MTU_SIZE_MAX).enqueue(); + //requestMtu(MTU_SIZE_MAX).enqueue(); // This callback will be called each time a notification is received. final DataReceivedCallback onDataReceived = (device, data) -> - mCallbacks.onDataReceived(device, getMtu(), data.getValue()); + mCallbacks.onDataReceived(device, getMaximumPacketSize(), data.getValue()); // Set the notification callback and enable notification on Data In characteristic. final BluetoothGattCharacteristic characteristic = isProvisioningComplete ? @@ -178,7 +178,7 @@ public void sendPdu(final byte[] pdu) { // This callback will be called each time the data were sent. final DataSentCallback callback = (device, data) -> - mCallbacks.onDataSent(device, getMtu(), data.getValue()); + mCallbacks.onDataSent(device, getMaximumPacketSize(), data.getValue()); // Write the right characteristic. final BluetoothGattCharacteristic characteristic = isProvisioningComplete ? @@ -189,9 +189,8 @@ public void sendPdu(final byte[] pdu) { .enqueue(); } - @Override - public int getMtu() { - return super.getMtu(); + public int getMaximumPacketSize() { + return super.getMtu() - 3; } public boolean isProvisioningComplete() { diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java index c018b25be..e3e9d984c 100644 --- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java +++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/viewmodels/NrfMeshRepository.java @@ -637,7 +637,7 @@ public void onMeshPduCreated(final byte[] pdu) { @Override public int getMtu() { - return mBleMeshManager.getMtu(); + return mBleMeshManager.getMaximumPacketSize(); } @Override From efb054e423dfa72fb47a64684912fffd21130cc4 Mon Sep 17 00:00:00 2001 From: Roshan Rajaratnam Date: Wed, 20 Nov 2019 16:56:12 +0100 Subject: [PATCH 2/4] Uncomment mtu request --- .../android/nrfmeshprovisioner/ble/BleMeshManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java index 0b768c826..1e73082f9 100644 --- a/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java +++ b/Example/nrf-mesh/app/src/main/java/no/nordicsemi/android/nrfmeshprovisioner/ble/BleMeshManager.java @@ -108,7 +108,7 @@ public boolean isRequiredServiceSupported(@NonNull final BluetoothGatt gatt) { @Override protected void initialize() { - //requestMtu(MTU_SIZE_MAX).enqueue(); + requestMtu(MTU_SIZE_MAX).enqueue(); // This callback will be called each time a notification is received. final DataReceivedCallback onDataReceived = (device, data) -> @@ -208,4 +208,4 @@ private boolean hasWriteNoResponseProperty(@NonNull final BluetoothGattCharacter private boolean hasNotifyProperty(@NonNull final BluetoothGattCharacteristic characteristic) { return (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0; } -} \ No newline at end of file +} From 9f96f5eb31c1f94e8f7069dae7b073af37d337f2 Mon Sep 17 00:00:00 2001 From: "Rajaratnam, Roshan" Date: Thu, 21 Nov 2019 08:44:23 +0100 Subject: [PATCH 3/4] Validate provisionee public key length during provisioning process and return failure state if invalid. --- .../MeshProvisioningHandler.java | 168 ++++++++++-------- .../ProvisioningFailedState.java | 35 +--- .../ProvisioningPublicKeyState.java | 6 +- .../provisionerstates/ProvisioningState.java | 8 +- 4 files changed, 102 insertions(+), 115 deletions(-) diff --git a/android-nrf-mesh-library/meshprovisioner/src/main/java/no/nordicsemi/android/meshprovisioner/MeshProvisioningHandler.java b/android-nrf-mesh-library/meshprovisioner/src/main/java/no/nordicsemi/android/meshprovisioner/MeshProvisioningHandler.java index f62344f79..a40c739d6 100644 --- a/android-nrf-mesh-library/meshprovisioner/src/main/java/no/nordicsemi/android/meshprovisioner/MeshProvisioningHandler.java +++ b/android-nrf-mesh-library/meshprovisioner/src/main/java/no/nordicsemi/android/meshprovisioner/MeshProvisioningHandler.java @@ -23,6 +23,7 @@ package no.nordicsemi.android.meshprovisioner; import android.content.Context; +import android.util.Log; import java.nio.ByteBuffer; import java.util.UUID; @@ -50,7 +51,7 @@ import no.nordicsemi.android.meshprovisioner.utils.StaticOOBType; class MeshProvisioningHandler implements InternalProvisioningCallbacks { - + private static final String TAG = MeshProvisioningHandler.class.getSimpleName(); static final int ATTENTION_TIMER = 5; //seconds private final InternalTransportCallbacks mInternalTransportCallbacks; private final Context mContext; @@ -98,60 +99,65 @@ void setProvisioningCallbacks(MeshProvisioningStatusCallbacks provisioningCallba void parseProvisioningNotifications(final byte[] data) { final UnprovisionedMeshNode unprovisionedMeshNode = mUnprovisionedMeshNode; - switch (provisioningState.getState()) { - case PROVISIONING_INVITE: - break; - case PROVISIONING_CAPABILITIES: - if (validateMessage(data)) { - if (!parseProvisioningCapabilitiesMessage(unprovisionedMeshNode, data)) { + try { + switch (provisioningState.getState()) { + case PROVISIONING_INVITE: + break; + case PROVISIONING_CAPABILITIES: + if (validateMessage(data)) { + if (!parseProvisioningCapabilitiesMessage(unprovisionedMeshNode, data)) { + parseProvisioningState(unprovisionedMeshNode, data); + } + } else { parseProvisioningState(unprovisionedMeshNode, data); } - } else { - parseProvisioningState(unprovisionedMeshNode, data); - } - break; - case PROVISIONING_START: - break; - case PROVISIONING_PUBLIC_KEY: - if (validateMessage(data)) { - parseProvisioneePublicKeyXY(unprovisionedMeshNode, data); - } else { - parseProvisioningState(unprovisionedMeshNode, data); - } - break; - case PROVISIONING_INPUT_COMPLETE: - if (validateMessage(data)) { - if (parseProvisioningInputCompleteState(data)) { - sendProvisioningConfirmation(null); + break; + case PROVISIONING_START: + break; + case PROVISIONING_PUBLIC_KEY: + if (validateMessage(data)) { + parseProvisioneePublicKeyXY(unprovisionedMeshNode, data); + } else { + parseProvisioningState(unprovisionedMeshNode, data); } - } else { - parseProvisioningState(unprovisionedMeshNode, data); - } - break; - case PROVISIONING_CONFIRMATION: - if (validateMessage(data)) { - if (parseProvisioneeConfirmation(data)) { - sendRandomConfirmationPDU(unprovisionedMeshNode); + break; + case PROVISIONING_INPUT_COMPLETE: + if (validateMessage(data)) { + if (parseProvisioningInputCompleteState(data)) { + sendProvisioningConfirmation(null); + } + } else { + parseProvisioningState(unprovisionedMeshNode, data); } - } else { - parseProvisioningState(unprovisionedMeshNode, data); - } - break; - case PROVISIONING_RANDOM: - if (validateMessage(data)) { - if (parseProvisioneeRandom(data)) { - sendProvisioningData(unprovisionedMeshNode); + break; + case PROVISIONING_CONFIRMATION: + if (validateMessage(data)) { + if (parseProvisioneeConfirmation(data)) { + sendRandomConfirmationPDU(unprovisionedMeshNode); + } + } else { + parseProvisioningState(unprovisionedMeshNode, data); + } + break; + case PROVISIONING_RANDOM: + if (validateMessage(data)) { + if (parseProvisioneeRandom(data)) { + sendProvisioningData(unprovisionedMeshNode); + } + } else { + parseProvisioningState(unprovisionedMeshNode, data); } - } else { + break; + case PROVISIONING_DATA: + case PROVISIONING_COMPLETE: + case PROVISIONING_FAILED: parseProvisioningState(unprovisionedMeshNode, data); - } - break; - case PROVISIONING_DATA: - case PROVISIONING_COMPLETE: - case PROVISIONING_FAILED: - parseProvisioningState(unprovisionedMeshNode, data); - break; + break; + } + } catch (Exception ex) { + Log.e(TAG, "Exception in " + provisioningState.getState().name() + " : " + ex.getMessage()); + parseProvisioningState(unprovisionedMeshNode, data); } } @@ -180,18 +186,16 @@ void handleProvisioningWriteCallbacks() { } private void parseProvisioningState(final UnprovisionedMeshNode unprovisionedMeshNode, final byte[] data) { + isProvisioningPublicKeySent = false; + isProvisioneePublicKeyReceived = false; if (data[1] == ProvisioningState.State.PROVISIONING_COMPLETE.getState()) { provisioningState = new ProvisioningCompleteState(unprovisionedMeshNode); - isProvisioningPublicKeySent = false; - isProvisioneePublicKeyReceived = false; //Generate the network id and store it in the mesh node, this is needed to reconnect to the device at a later stage. final ProvisionedMeshNode provisionedMeshNode = new ProvisionedMeshNode(unprovisionedMeshNode); mInternalMeshManagerCallbacks.onNodeProvisioned(provisionedMeshNode); mStatusCallbacks.onProvisioningCompleted(provisionedMeshNode, ProvisioningState.States.PROVISIONING_COMPLETE, data); } else { - isProvisioningPublicKeySent = false; - isProvisioneePublicKeyReceived = false; - final ProvisioningFailedState provisioningFailedState = new ProvisioningFailedState(mContext, unprovisionedMeshNode); + final ProvisioningFailedState provisioningFailedState = new ProvisioningFailedState(); provisioningState = provisioningFailedState; if (provisioningFailedState.parseData(data)) { mStatusCallbacks.onProvisioningFailed(unprovisionedMeshNode, ProvisioningState.States.PROVISIONING_FAILED, data); @@ -202,11 +206,11 @@ private void parseProvisioningState(final UnprovisionedMeshNode unprovisionedMes /** * Initializes a mesh node object to be provisioned * - * @param uuid Device UUID of unprovisioned node - * @param networkKey Network key - * @param flags Flag containing the key refresh or the iv update operations - * @param ivIndex 32-bit value shared across the network - * @param globalTtl Global ttl which is also the number of hops to be used for a message + * @param uuid Device UUID of unprovisioned node + * @param networkKey Network key + * @param flags Flag containing the key refresh or the iv update operations + * @param ivIndex 32-bit value shared across the network + * @param globalTtl Global ttl which is also the number of hops to be used for a message * @return {@link MeshModel} to be provisioned */ private UnprovisionedMeshNode initializeMeshNode(@NonNull final UUID uuid, @@ -235,7 +239,8 @@ private UnprovisionedMeshNode initializeMeshNode(@NonNull final UUID uuid, return unprovisionedMeshNode; } - private boolean validateProvisioningDataInput(final NetworkKey networkKey, final Integer flags, final Integer ivIndex) { + private boolean validateProvisioningDataInput(final NetworkKey networkKey, + final Integer flags, final Integer ivIndex) { String error; if (networkKey == null) { @@ -268,12 +273,12 @@ private boolean validateProvisioningDataInput(final NetworkKey networkKey, final * This method must be invoked before calling {@link #startProvisioningNoOOB(UnprovisionedMeshNode)} *

Date: Thu, 21 Nov 2019 08:45:56 +0100 Subject: [PATCH 4/4] Version bumped for release --- Example/nrf-mesh/app/build.gradle | 4 ++-- android-nrf-mesh-library/meshprovisioner/build.gradle | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Example/nrf-mesh/app/build.gradle b/Example/nrf-mesh/app/build.gradle index a80b206cf..62a5e6cc7 100644 --- a/Example/nrf-mesh/app/build.gradle +++ b/Example/nrf-mesh/app/build.gradle @@ -30,8 +30,8 @@ android { applicationId "no.nordicsemi.android.nrfmeshprovisioner" minSdkVersion 18 targetSdkVersion 29 - versionCode 57 - versionName "2.1.1" + versionCode 58 + versionName "2.1.2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true vectorDrawables.useSupportLibrary = true diff --git a/android-nrf-mesh-library/meshprovisioner/build.gradle b/android-nrf-mesh-library/meshprovisioner/build.gradle index 099549677..b0988127f 100644 --- a/android-nrf-mesh-library/meshprovisioner/build.gradle +++ b/android-nrf-mesh-library/meshprovisioner/build.gradle @@ -29,8 +29,8 @@ android { defaultConfig { minSdkVersion 18 targetSdkVersion 29 - versionCode 57 - versionName "2.1.1" + versionCode 58 + versionName "2.1.2" javaCompileOptions { annotationProcessorOptions {