Skip to content

Commit 556b32d

Browse files
committed
Limit max data length based on used memory read/write service
1 parent 63a6c64 commit 556b32d

File tree

4 files changed

+40
-25
lines changed

4 files changed

+40
-25
lines changed

src/io/calimero/mgmt/ManagementClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1201,7 +1201,7 @@ private byte[] readMemoryExt(final Destination dst, final int startAddr, final i
12011201
KNXDisconnectException, KNXRemoteException, KNXLinkClosedException, InterruptedException {
12021202
final byte[] send = createAPDU(MemoryExtendedRead,
12031203
(byte) bytes, (byte) (startAddr >>> 16), (byte) (startAddr >>> 8), (byte) startAddr);
1204-
final byte[] apdu = sendWait(dst, priority, send, MemoryExtendedReadResponse, 4, 252);
1204+
final byte[] apdu = sendWait(dst, priority, send, MemoryExtendedReadResponse, 4, 253);
12051205
final ReturnCode ret = ReturnCode.of(apdu[2] & 0xff);
12061206
if (ret != ReturnCode.Success)
12071207
throw new KnxNegativeReturnCodeException(format("read memory from %s 0x%x", dst.getAddress(), startAddr), ret);

src/io/calimero/mgmt/ManagementProceduresImpl.java

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -671,11 +671,12 @@ public void writeMemory(final IndividualAddress device, final long startAddress,
671671
1, 1, ctrl);
672672
}
673673

674-
// write memory in chunks with a maximum length of asduLength
675-
final int asduLength = maxApduLength(d) - (extMemoryServices ? 5 : 3);
676-
for (int i = 0; i < data.length; i += asduLength) {
677-
int remainingBytes = data.length - i;
678-
final byte[] range = Arrays.copyOfRange(data, i, i + Math.min(asduLength, remainingBytes));
674+
final int apduLength = maxApduLength(d);
675+
// write memory in chunks with a maximum length of dataLength
676+
final int dataLength = extMemoryServices ? Math.min(249, apduLength - 5) : Math.min(63, apduLength - 3);
677+
for (int i = 0; i < data.length; i += dataLength) {
678+
int remainingBytes = data.length - i;
679+
final byte[] range = Arrays.copyOfRange(data, i, i + Math.min(dataLength, remainingBytes));
679680

680681
// on server verification, our mgmt client will already compare the response value
681682
mc.writeMemory(d, (int) startAddress + i, range);
@@ -697,18 +698,15 @@ public byte[] readMemory(final IndividualAddress device, final long startAddress
697698
throw new KNXIllegalArgumentException("start address is no 32 Bit address");
698699
if (bytes < 0)
699700
throw new KNXIllegalArgumentException("bytes to read require a positive number");
700-
// sanity check, at least emit a warning
701-
// if (bytes > 4096)
702-
// logger.log(WARNING, "reading over 4K of device memory "
703-
// + "(hope you know what you are doing)");
704701

705702
final Destination d = getOrCreateDestination(device);
706703
final boolean extMemoryServices = ((ManagementClientImpl) mc).supportsFeature(d, SupportedServiceGroup.ExtMemory);
707704

705+
final int apduLength = maxApduLength(d);
706+
final int dataLength = extMemoryServices ? Math.min(249, apduLength - 5) : Math.min(63, apduLength - 3);
708707
final byte[] read = new byte[bytes];
709-
final int asduLength = maxApduLength(d) - (extMemoryServices ? 5 : 3);
710-
for (int i = 0; i < read.length; i += asduLength) {
711-
final int size = i + asduLength <= read.length ? asduLength : read.length - i;
708+
for (int i = 0; i < read.length; i += dataLength) {
709+
final int size = i + dataLength <= read.length ? dataLength : read.length - i;
712710
final byte[] range = mc.readMemory(d, (int) startAddress + i, size);
713711
System.arraycopy(range, 0, read, i, range.length);
714712
}

test/io/calimero/mgmt/ManagementClientImplTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ void readMemory() throws KNXException, InterruptedException
220220
@Test
221221
void readMemoryMaxDataLength() throws KNXException, InterruptedException {
222222
try {
223-
mc.readMemory(dco, 0x1000, 63);
223+
mc.readMemory(dcl, 0x1000, 63);
224224
}
225225
catch (KNXTimeoutException ok) {
226226
// dst max apdu < 66, read is ignored
@@ -233,7 +233,7 @@ void readMemoryMaxDataLength() throws KNXException, InterruptedException {
233233

234234
@Test
235235
void readMemoryDataLengthOutOfRange() {
236-
assertThrows(KNXIllegalArgumentException.class, () -> mc.readMemory(dco, 0x1000, 64));
236+
assertThrows(KNXIllegalArgumentException.class, () -> mc.readMemory(dcl, 0x1000, 64));
237237
}
238238

239239
@Test
@@ -499,7 +499,7 @@ void writeMemory() throws KNXException, InterruptedException
499499

500500
@Test
501501
void writeMemoryTooMuchData() {
502-
assertThrows(KNXIllegalArgumentException.class, () -> mc.writeMemory(dco, 0x105, new byte[64]));
502+
assertThrows(KNXIllegalArgumentException.class, () -> mc.writeMemory(dcl, 0x105, new byte[64]));
503503
}
504504

505505
@Test

test/io/calimero/mgmt/ManagementProceduresImplTest.java

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ class ManagementProceduresImplTest
6767
private ManagementProcedures mp;
6868
private KNXNetworkLink link;
6969
private final IndividualAddress device = Util.getKnxDeviceCO();
70+
private final IndividualAddress deviceNoExtMem = Util.getKnxDevice();
7071
private final IndividualAddress deviceInProgMode = Util.getKnxDevice();
7172
private IndividualAddress nonexist;
7273

@@ -223,34 +224,50 @@ void writeMemoryShort() throws KNXException, InterruptedException
223224
{
224225
final byte[] data = new byte[8];
225226

226-
mp.writeMemory(device, 0x10, data, false, false);
227+
mp.writeMemory(deviceNoExtMem, 0x10, data, false, false);
227228

228-
mp.writeMemory(device, 0x10, data, true, false);
229+
mp.writeMemory(deviceNoExtMem, 0x10, data, true, false);
229230

230-
mp.writeMemory(device, 0x10, data, false, true);
231+
mp.writeMemory(deviceNoExtMem, 0x10, data, false, true);
231232
}
232233

233234
@Test
234235
void writeMemoryLong() throws KNXException, InterruptedException
235236
{
236-
final byte[] data = new byte[32];
237+
final byte[] data = new byte[2 * 63 + 10];
237238

238-
mp.writeMemory(device, 0x10, data, false, false);
239+
mp.writeMemory(deviceNoExtMem, 0x1000, data, false, false);
239240

240-
mp.writeMemory(device, 0x10, data, true, false);
241+
mp.writeMemory(deviceNoExtMem, 0x1000, data, true, false);
241242

242-
mp.writeMemory(device, 0x10, data, false, true);
243+
mp.writeMemory(deviceNoExtMem, 0x1000, data, false, true);
244+
}
245+
246+
@Test
247+
void writeMemoryExt() throws KNXException, InterruptedException {
248+
final byte[] data = new byte[2 * 149 + 10];
249+
final int startAddress = 0x10000;
250+
251+
mp.writeMemory(Util.getRouterAddress(), startAddress, data, false, false);
252+
mp.writeMemory(Util.getRouterAddress(), startAddress, data, true, false);
253+
mp.writeMemory(Util.getRouterAddress(), startAddress, data, false, true);
243254
}
244255

245256
@Test
246257
void readMemoryShort() throws KNXException, InterruptedException
247258
{
248-
/*final byte[] data =*/ mp.readMemory(device, 0x10, 8);
259+
/*final byte[] data =*/ mp.readMemory(deviceNoExtMem, 0x10, 8);
249260
}
250261

251262
@Test
252263
void readMemoryLong() throws KNXException, InterruptedException
253264
{
254-
/*final byte[] data =*/ mp.readMemory(device, 0x20, 17);
265+
/*final byte[] data =*/ mp.readMemory(deviceNoExtMem, 0x20, 2 * 63 + 10);
266+
}
267+
268+
@Test
269+
void readMemoryExt() throws KNXException, InterruptedException {
270+
final int startAddress = 0x10000;
271+
mp.readMemory(Util.getRouterAddress(), startAddress, 2 * 249 + 10);
255272
}
256273
}

0 commit comments

Comments
 (0)