1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-29 13:26:50 +01:00

Zepp OS: Add support for compressed file transfer

This commit is contained in:
José Rebelo 2023-06-11 16:37:24 +01:00
parent d29e092ce7
commit 55cecceb38

View File

@ -25,6 +25,9 @@ import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
@ -152,10 +155,23 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
final int length = BLETypeConversions.toUint32(payload, pos); final int length = BLETypeConversions.toUint32(payload, pos);
pos += 4; pos += 4;
final int crc32 = BLETypeConversions.toUint32(payload, pos); final int crc32 = BLETypeConversions.toUint32(payload, pos);
pos += 4;
LOG.info("Got transfer request: session={}, url={}, filename={}, length={}", session, url, filename, length); final boolean compressed;
if (pos < payload.length) {
final Boolean compressedBoolean = booleanFromByte(payload[pos]);
if (compressedBoolean == null) {
LOG.warn("Unknown compression type {}", payload[pos]);
return;
}
compressed = compressedBoolean;
} else {
compressed = false;
}
final FileTransferRequest request = new FileTransferRequest(url, filename, new byte[length], getSupport()); LOG.info("Got transfer request: session={}, url={}, filename={}, length={}, compressed={}", session, url, filename, length, compressed);
final FileTransferRequest request = new FileTransferRequest(url, filename, new byte[length], compressed, getSupport());
request.setCrc32(crc32); request.setCrc32(crc32);
final ByteBuffer buf = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN); final ByteBuffer buf = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN);
@ -212,21 +228,43 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
if (lastPacket) { if (lastPacket) {
mSessionRequests.remove(session); mSessionRequests.remove(session);
if (request.getProgress() != request.getSize()) { final byte[] data;
LOG.warn("Request not finished: {}/{}", request.getProgress(), request.getSize()); if (request.isCompressed()) {
data = decompress(request.getBytes());
if (data == null) {
LOG.error("Failed to decompress bytes for session={}", session);
return; return;
} }
} else {
data = request.getBytes();
}
final int checksum = CheckSums.getCRC32(request.getBytes()); final int checksum = CheckSums.getCRC32(data);
if (checksum != request.getCrc32()) { if (checksum != request.getCrc32()) {
LOG.warn("Checksum mismatch: expected {}, got {}", request.getCrc32(), checksum); LOG.warn("Checksum mismatch: expected {}, got {}", request.getCrc32(), checksum);
return; return;
} }
request.getCallback().onFileDownloadFinish(request.getUrl(), request.getFilename(), request.getBytes()); request.getCallback().onFileDownloadFinish(request.getUrl(), request.getFilename(), data);
} }
} }
public static byte[] decompress(final byte[] data) {
final Inflater inflater = new Inflater();
final byte[] output = new byte[data.length];
inflater.setInput(data);
try {
inflater.inflate(output);
} catch (final DataFormatException e) {
LOG.error("Failed to decompress data", e);
return null;
} finally {
inflater.end();
}
return output;
}
public void sendFile(final String url, final String filename, final byte[] bytes, final Callback callback) { public void sendFile(final String url, final String filename, final byte[] bytes, final Callback callback) {
if (mChunkSize < 0) { if (mChunkSize < 0) {
LOG.error("Service not initialized, refusing to send {}", url); LOG.error("Service not initialized, refusing to send {}", url);
@ -236,7 +274,7 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
LOG.info("Sending {} bytes to {}", bytes.length, url); LOG.info("Sending {} bytes to {}", bytes.length, url);
final FileTransferRequest request = new FileTransferRequest(url, filename, bytes, callback); final FileTransferRequest request = new FileTransferRequest(url, filename, bytes, false, callback);
byte session = (byte) mSessionRequests.size(); byte session = (byte) mSessionRequests.size();
while (mSessionRequests.containsKey(session)) { while (mSessionRequests.containsKey(session)) {
@ -331,15 +369,17 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
private final String url; private final String url;
private final String filename; private final String filename;
private final byte[] bytes; private final byte[] bytes;
private final boolean compressed;
private final Callback callback; private final Callback callback;
private int progress = 0; private int progress = 0;
private byte index = 0; private byte index = 0;
private int crc32; private int crc32;
public FileTransferRequest(final String url, final String filename, final byte[] bytes, final Callback callback) { public FileTransferRequest(final String url, final String filename, final byte[] bytes, boolean compressed, final Callback callback) {
this.url = url; this.url = url;
this.filename = filename; this.filename = filename;
this.bytes = bytes; this.bytes = bytes;
this.compressed = compressed;
this.callback = callback; this.callback = callback;
this.crc32 = CheckSums.getCRC32(bytes); this.crc32 = CheckSums.getCRC32(bytes);
} }
@ -360,6 +400,10 @@ public class ZeppOsFileTransferService extends AbstractZeppOsService {
return bytes.length; return bytes.length;
} }
public boolean isCompressed() {
return compressed;
}
public Callback getCallback() { public Callback getCallback() {
return callback; return callback;
} }