From 1f1fc33e4388a3386dd08ed79f0ae4ff8139e8ec Mon Sep 17 00:00:00 2001 From: "Martin.JM" Date: Thu, 20 Jun 2024 14:55:07 +0200 Subject: [PATCH] Huawei: Fix BR partial packets Would crash before. See added test for example. --- .../devices/huawei/HuaweiSupportProvider.java | 15 ++++-- .../huawei/TestHuaweiSupportProvider.java | 53 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/TestHuaweiSupportProvider.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java index a978917dc..6d45b488e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/HuaweiSupportProvider.java @@ -890,10 +890,19 @@ public class HuaweiSupportProvider { } public void onSocketRead(byte[] data) { - //Check multiple packet in data + // The data can contain multiple packets, which need to be split. + // But we also need to take into account partial packets (where data does not contain a full packet) + if (data[0] != 0x5a) { + // Part of partial packet, just parse + responseManager.handleData(data); + return; + } + ByteBuffer bData = ByteBuffer.wrap(data); - while (bData.remaining() != 0x00) { - int dataLen = bData.getShort(bData.position() + 1) + 0x05; // magic + len + CRC + while (bData.remaining() != 0) { + int dataLen = bData.getShort(bData.position() + 1) + 0x05; + if (dataLen > bData.remaining()) + dataLen = bData.remaining(); // Part of partial packet, just parse the remainder byte[] newData = new byte[dataLen]; bData.get(newData, 0, dataLen); responseManager.handleData(newData); diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/TestHuaweiSupportProvider.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/TestHuaweiSupportProvider.java new file mode 100644 index 000000000..3bd7a81c1 --- /dev/null +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huawei/TestHuaweiSupportProvider.java @@ -0,0 +1,53 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.huawei; + +import org.junit.Test; +import org.mockito.Mockito; + +public class TestHuaweiSupportProvider { + + @Test + public void testOnSocketReadExactPacket() { + byte[] data1 = {(byte) 0x5A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x99, (byte) 0x6B}; + + HuaweiBRSupport support = new HuaweiBRSupport(); + + HuaweiSupportProvider supportProvider = new HuaweiSupportProvider(support); + supportProvider.responseManager = Mockito.mock(ResponseManager.class); + + supportProvider.onSocketRead(data1); + + Mockito.verify(supportProvider.responseManager, Mockito.times(1)).handleData(data1); + } + + @Test + public void testOnSocketReadMultiplePacket() { + byte[] expected = {(byte) 0x5A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x99, (byte) 0x6B}; + byte[] data1 = {(byte) 0x5A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x99, (byte) 0x6B, (byte) 0x5A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x99, (byte) 0x6B}; + + HuaweiBRSupport support = new HuaweiBRSupport(); + + HuaweiSupportProvider supportProvider = new HuaweiSupportProvider(support); + supportProvider.responseManager = Mockito.mock(ResponseManager.class); + + supportProvider.onSocketRead(data1); + + Mockito.verify(supportProvider.responseManager, Mockito.times(2)).handleData(expected); + } + + @Test + public void testOnSocketReadPartialPacket() { + byte[] data1 = {(byte) 0x5A, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x04, (byte) 0x01}; + byte[] data2 = {(byte) 0x01, (byte) 0x01, (byte) 0x02, (byte) 0x99, (byte) 0x6B}; + + HuaweiBRSupport support = new HuaweiBRSupport(); + + HuaweiSupportProvider supportProvider = new HuaweiSupportProvider(support); + supportProvider.responseManager = Mockito.mock(ResponseManager.class); + + supportProvider.onSocketRead(data1); + supportProvider.onSocketRead(data2); + + Mockito.verify(supportProvider.responseManager, Mockito.times(1)).handleData(data1); + Mockito.verify(supportProvider.responseManager, Mockito.times(1)).handleData(data2); + } +}