1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-06-24 22:10:55 +02:00

Xiaomi: Fix edge cases in chunked math

This commit is contained in:
José Rebelo 2023-10-22 10:34:38 +01:00
parent fa72820e5a
commit 7fb81b6e0d

View File

@ -39,6 +39,9 @@ import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
public class XiaomiCharacteristic { public class XiaomiCharacteristic {
public static final byte[] PAYLOAD_ACK = new byte[]{0, 0, 3, 0}; public static final byte[] PAYLOAD_ACK = new byte[]{0, 0, 3, 0};
// max chunk size, including headers
public static final int MAX_WRITE_SIZE = 242;
private final Logger LOG; private final Logger LOG;
private final XiaomiSupport mSupport; private final XiaomiSupport mSupport;
@ -182,9 +185,9 @@ public class XiaomiCharacteristic {
case 1: case 1:
LOG.debug("Got chunked ack start"); LOG.debug("Got chunked ack start");
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunks"); final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunks");
for (int i = 0; i * 242 < currentSending.length; i++) { for (int i = 0; i * MAX_WRITE_SIZE < currentSending.length; i++) {
final int startIndex = i * 242; final int startIndex = i * MAX_WRITE_SIZE;
final int endIndex = Math.min((i + 1) * 242, currentSending.length); final int endIndex = Math.min((i + 1) * MAX_WRITE_SIZE, currentSending.length);
LOG.debug("Sending chunk {} from {} to {}", i, startIndex, endIndex); LOG.debug("Sending chunk {} from {} to {}", i, startIndex, endIndex);
final byte[] chunkToSend = new byte[2 + endIndex - startIndex]; final byte[] chunkToSend = new byte[2 + endIndex - startIndex];
BLETypeConversions.writeUint16(chunkToSend, 0, i + 1); BLETypeConversions.writeUint16(chunkToSend, 0, i + 1);
@ -265,7 +268,7 @@ public class XiaomiCharacteristic {
buf.putShort((short) 0); buf.putShort((short) 0);
buf.put((byte) 0); buf.put((byte) 0);
buf.put((byte) (isEncrypted ? 1 : 0)); buf.put((byte) (isEncrypted ? 1 : 0));
buf.putShort((short) Math.max(1, Math.round(currentSending.length / 247.0))); buf.putShort((short) Math.ceil(currentSending.length / (float) MAX_WRITE_SIZE));
final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunked start"); final TransactionBuilder builder = mSupport.createTransactionBuilder("send chunked start");
builder.write(bluetoothGattCharacteristic, buf.array()); builder.write(bluetoothGattCharacteristic, buf.array());
@ -274,13 +277,15 @@ public class XiaomiCharacteristic {
LOG.debug("Sending next - single"); LOG.debug("Sending next - single");
// Encrypt single command // Encrypt single command
final int commandLength = 6 + currentSending.length; final int commandLength = (isEncrypted ? 6 : 4) + currentSending.length;
final ByteBuffer buf = ByteBuffer.allocate(commandLength).order(ByteOrder.LITTLE_ENDIAN); final ByteBuffer buf = ByteBuffer.allocate(commandLength).order(ByteOrder.LITTLE_ENDIAN);
buf.putShort((short) 0); buf.putShort((short) 0);
buf.put((byte) 2); // 2 for command buf.put((byte) 2); // 2 for command
buf.put((byte) 1); // 1 for encrypted buf.put((byte) (isEncrypted ? 1 : 2));
buf.putShort(encryptedIndex++); if (isEncrypted) {
buf.putShort(encryptedIndex++);
}
buf.put(currentSending); // it's already encrypted buf.put(currentSending); // it's already encrypted
waitingAck = true; waitingAck = true;
@ -297,7 +302,8 @@ public class XiaomiCharacteristic {
return true; return true;
} }
return payload.length + 6 > 244; // payload + 6 bytes at the start with the encryption stuff
return payload.length + 6 > MAX_WRITE_SIZE;
} }
private void sendAck() { private void sendAck() {