• Recent
    • Tags
    • Popular
    • Register
    • Login

    Please Note This forum exists for community support for the Mango product family and the Radix IoT Platform. Although Radix IoT employees participate in this forum from time to time, there is no guarantee of a response to anything posted here, nor can Radix IoT, LLC guarantee the accuracy of any information expressed or conveyed. Specific project questions from customers with active support contracts are asked to send requests to support@radixiot.com.

    Radix IoT Website Mango 3 Documentation Website Mango 4 Documentation Website Mango 5 Documentation Website

    Patch for UDP 7 segments bug

    BACnet4J general discussion
    2
    12
    4.9k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      japearson
      last edited by

      Hi Matthew,

      We found a bug where com.serotonin.bacnet4j.npdu.ip.IpMessageControl.sendResponse(InetSocketAddress, Network, ConfirmedRequest, AcknowledgementService) was limiting the number of UDP packets to 7 segments instead of more than 64. We need to have at least 2000 BACnet Objects on a local device and it was complaining about too many segments.

      I have created a patch for this, how should I give this to you?

      For my own convenience I have converted your CVS repository to GIT, so if you like I could put the repository up on Github, then I could fork your repository and create pull request. Otherwise I can just upload a patch in the [url=http://sourceforge.net/tracker/?group_id=224576&atid=1062318]Patches section of sourceforge

      Let me know what you prefer.

      Cheers,

      -Joel

      1 Reply Last reply Reply Quote 0
      • M
        mlohbihler
        last edited by

        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.

        Best regards,
        Matthew

        1 Reply Last reply Reply Quote 0
        • J
          japearson
          last edited by

          @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;
              }
          
          
          1 Reply Last reply Reply Quote 0
          • M
            mlohbihler
            last edited by

            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.

            Best regards,
            Matthew

            1 Reply Last reply Reply Quote 0
            • J
              japearson
              last edited by

              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?

              1 Reply Last reply Reply Quote 0
              • M
                mlohbihler
                last edited by

                I noticed that too and committed a fix just after.

                Best regards,
                Matthew

                1 Reply Last reply Reply Quote 0
                • M
                  mlohbihler
                  last edited by

                  Re test, sure, send it along.

                  Best regards,
                  Matthew

                  1 Reply Last reply Reply Quote 0
                  • J
                    japearson
                    last edited by

                    Ok done: https://sourceforge.net/tracker/?func=detail&aid=3562579&group_id=224576&atid=1062318

                    1 Reply Last reply Reply Quote 0
                    • M
                      mlohbihler
                      last edited by

                      Patch has been applied. Thanks.

                      Best regards,
                      Matthew

                      1 Reply Last reply Reply Quote 0
                      • J
                        japearson
                        last edited by

                        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

                        1 Reply Last reply Reply Quote 0
                        • M
                          mlohbihler
                          last edited by

                          Indeed. A fix has been checked in.

                          Best regards,
                          Matthew

                          1 Reply Last reply Reply Quote 0
                          • First post
                            Last post