Patch for UDP 7 segments bug
-
Not sure what you mean. This is the code that i have (lines 274 and 275):
if (segmentsRequired > request.getMaxSegmentsAccepted() || segmentsRequired > 128) throw new BACnetException("Response too big to send to device; too many segments required");
BACnet4J will respond with up to 128 segments unless limited further by the max accepted by the client.
-
@mlohbihler said:
Not sure what you mean. This is the code that i have (lines 274 and 275):
if (segmentsRequired > request.getMaxSegmentsAccepted() || segmentsRequired > 128) throw new BACnetException("Response too big to send to device; too many segments required");
BACnet4J will respond with up to 128 segments unless limited further by the max accepted by the client.
That is true, however request.getMaxSegmentsAccepted() is a maximum of number 7 and not 128.
Look at lines 240 - 258 of ConfirmedRequest, maxSegmentsAccepted is set directly from the byte queue, which works for everything except the one use of getMaxSegmentsAccepted. It needs to work exactly like maxApduLengthAccepted, which is the solution I came up with. I created an enum that maps between the integer/byte value and the actual meaning of that value.
ConfirmedRequest(ServicesSupported servicesSupported, ByteQueue queue) throws BACnetException { byte b = queue.pop(); segmentedMessage = (b & 8) != 0; moreFollows = (b & 4) != 0; segmentedResponseAccepted = (b & 2) != 0; b = queue.pop(); maxSegmentsAccepted = (b & 0x70) >> 4; maxApduLengthAccepted = MaxApduLength.valueOf((byte) (b & 0xf)); invokeId = queue.pop(); if (segmentedMessage) { sequenceNumber = queue.popU1B(); proposedWindowSize = queue.popU1B(); } serviceChoice = queue.pop(); serviceData = new ByteQueue(queue.popAll()); ConfirmedRequestService.checkConfirmedRequestService(servicesSupported, serviceChoice); }
Lines 191-193 show that no conversion is taking place, it's still the original byte/integer value.
public int getMaxSegmentsAccepted() { return maxSegmentsAccepted; }
-
Ah, i see what you mean. The code is using the encoded value as the actual max segments. I've checked in a fix for this into the SF repo. I created an enum for the max segments like there is for the max APDU length. Thanks for pointing this out.
-
Thanks that now breaks the AnnexFEncodingTest though, I also wrote a test that tries to use 4000 objects as well, should I submit that as a patch for you?
-
I noticed that too and committed a fix just after.
-
Re test, sure, send it along.
-
-
Patch has been applied. Thanks.
-
Hi Matthew,
You missed the MORE_THAN_64 segments in the valueOf function, which makes bacnet4j pretty unusable
This is the diff of what's missing:
diff --git a/src/com/serotonin/bacnet4j/enums/MaxSegments.java b/src/com/serotonin/bacnet4j/enums/MaxSegments.java index 0845c74..362e210 100644 --- a/src/com/serotonin/bacnet4j/enums/MaxSegments.java +++ b/src/com/serotonin/bacnet4j/enums/MaxSegments.java @@ -67,6 +67,8 @@ public enum MaxSegments { return UP_TO_32; if (id == UP_TO_64.id) return UP_TO_64; + if (id == MORE_THAN_64.id) + return MORE_THAN_64; throw new IllegalArgumentException("Unknown id: " + id); }
Cheers,
-Joel
-
Indeed. A fix has been checked in.