This is an automated email from the ASF dual-hosted git repository. sruehl pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
The following commit(s) were added to refs/heads/master by this push: new c825014 use own crc16 impl c825014 is described below commit c825014bd63842f4bb28b1cd27fc248183ad0c5d Author: Sebastian Rühl <sru...@apache.org> AuthorDate: Thu Mar 8 14:12:16 2018 +0100 use own crc16 impl --- .../ads/api/serial/AMSSerialAcknowledgeFrame.java | 38 +++++++++++++ .../plc4x/java/ads/api/serial/AMSSerialFrame.java | 66 +++++++++++++++------- .../java/ads/api/serial/AMSSerialResetFrame.java | 38 +++++++++++++ .../java/ads/protocol/ADS2SerialProtocol.java | 25 +------- .../plc4x/java/ads/protocol/util/DigestUtil.java | 55 ++++++++++++++++++ 5 files changed, 179 insertions(+), 43 deletions(-) diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java index ebdf8bb..e1663c5 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialAcknowledgeFrame.java @@ -111,4 +111,42 @@ public class AMSSerialAcknowledgeFrame implements ByteReadable { public ByteBuf getByteBuf() { return buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AMSSerialAcknowledgeFrame)) return false; + + AMSSerialAcknowledgeFrame that = (AMSSerialAcknowledgeFrame) o; + + if (!magicCookie.equals(that.magicCookie)) return false; + if (!transmitterAddress.equals(that.transmitterAddress)) return false; + if (!receiverAddress.equals(that.receiverAddress)) return false; + if (!fragmentNumber.equals(that.fragmentNumber)) return false; + if (!userDataLength.equals(that.userDataLength)) return false; + return crc.equals(that.crc); + } + + @Override + public int hashCode() { + int result = magicCookie.hashCode(); + result = 31 * result + transmitterAddress.hashCode(); + result = 31 * result + receiverAddress.hashCode(); + result = 31 * result + fragmentNumber.hashCode(); + result = 31 * result + userDataLength.hashCode(); + result = 31 * result + crc.hashCode(); + return result; + } + + @Override + public String toString() { + return "AMSSerialAcknowledgeFrame{" + + "magicCookie=" + magicCookie + + ", transmitterAddress=" + transmitterAddress + + ", receiverAddress=" + receiverAddress + + ", fragmentNumber=" + fragmentNumber + + ", userDataLength=" + userDataLength + + ", crc=" + crc + + '}'; + } } diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java index d807a7e..aa9e3fd 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialFrame.java @@ -22,10 +22,7 @@ import io.netty.buffer.ByteBuf; import org.apache.plc4x.java.ads.api.generic.AMSPacket; import org.apache.plc4x.java.ads.api.serial.types.*; import org.apache.plc4x.java.ads.api.util.ByteReadable; -import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import org.apache.plc4x.java.ads.protocol.util.DigestUtil; /** * An AMS packet can be transferred via RS232 with the help of an AMS serial frame. @@ -102,23 +99,7 @@ public class AMSSerialFrame implements ByteReadable { this.amsPacket = amsPacket; byte[] amsPacketBytes = amsPacket.getBytes(); this.userData = UserData.of(amsPacketBytes); - // TODO: java has no CRC-16 implementation so we better be of implementing it by ourself. - MessageDigest messageDigest; - try { - messageDigest = MessageDigest.getInstance("CRC-16"); - } catch (NoSuchAlgorithmException e) { - throw new PlcRuntimeException(e); - } - messageDigest.update(magicCookie.getBytes()); - messageDigest.update(transmitterAddress.getBytes()); - messageDigest.update(receiverAddress.getBytes()); - messageDigest.update(fragmentNumber.getBytes()); - messageDigest.update(userDataLength.getBytes()); - byte[] digest = messageDigest.digest(amsPacketBytes); - if (digest.length > 2) { - throw new PlcRuntimeException("Digest length too great " + digest.length); - } - this.crc = CRC.of(digest[0], digest[1]); + this.crc = CRC.of(DigestUtil.calculateCrc16(() -> buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData))); } public static AMSSerialFrame of(MagicCookie magicCookie, TransmitterAddress transmitterAddress, ReceiverAddress receiverAddress, FragmentNumber fragmentNumber, UserDataLength userDataLength, UserData userData, CRC crc) { @@ -138,4 +119,47 @@ public class AMSSerialFrame implements ByteReadable { return buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData, crc); } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AMSSerialFrame)) return false; + + AMSSerialFrame that = (AMSSerialFrame) o; + + if (!magicCookie.equals(that.magicCookie)) return false; + if (!transmitterAddress.equals(that.transmitterAddress)) return false; + if (!receiverAddress.equals(that.receiverAddress)) return false; + if (!fragmentNumber.equals(that.fragmentNumber)) return false; + if (!userDataLength.equals(that.userDataLength)) return false; + if (!amsPacket.equals(that.amsPacket)) return false; + if (!userData.equals(that.userData)) return false; + return crc.equals(that.crc); + } + + @Override + public int hashCode() { + int result = magicCookie.hashCode(); + result = 31 * result + transmitterAddress.hashCode(); + result = 31 * result + receiverAddress.hashCode(); + result = 31 * result + fragmentNumber.hashCode(); + result = 31 * result + userDataLength.hashCode(); + result = 31 * result + amsPacket.hashCode(); + result = 31 * result + userData.hashCode(); + result = 31 * result + crc.hashCode(); + return result; + } + + @Override + public String toString() { + return "AMSSerialFrame{" + + "magicCookie=" + magicCookie + + ", transmitterAddress=" + transmitterAddress + + ", receiverAddress=" + receiverAddress + + ", fragmentNumber=" + fragmentNumber + + ", userDataLength=" + userDataLength + + ", amsPacket=" + amsPacket + + ", userData=" + userData + + ", crc=" + crc + + '}'; + } } diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java index 0524643..30da46e 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/api/serial/AMSSerialResetFrame.java @@ -110,4 +110,42 @@ public class AMSSerialResetFrame implements ByteReadable { public ByteBuf getByteBuf() { return buildByteBuff(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, crc); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AMSSerialResetFrame)) return false; + + AMSSerialResetFrame that = (AMSSerialResetFrame) o; + + if (!magicCookie.equals(that.magicCookie)) return false; + if (!transmitterAddress.equals(that.transmitterAddress)) return false; + if (!receiverAddress.equals(that.receiverAddress)) return false; + if (!fragmentNumber.equals(that.fragmentNumber)) return false; + if (!userDataLength.equals(that.userDataLength)) return false; + return crc.equals(that.crc); + } + + @Override + public int hashCode() { + int result = magicCookie.hashCode(); + result = 31 * result + transmitterAddress.hashCode(); + result = 31 * result + receiverAddress.hashCode(); + result = 31 * result + fragmentNumber.hashCode(); + result = 31 * result + userDataLength.hashCode(); + result = 31 * result + crc.hashCode(); + return result; + } + + @Override + public String toString() { + return "AMSSerialResetFrame{" + + "magicCookie=" + magicCookie + + ", transmitterAddress=" + transmitterAddress + + ", receiverAddress=" + receiverAddress + + ", fragmentNumber=" + fragmentNumber + + ", userDataLength=" + userDataLength + + ", crc=" + crc + + '}'; + } } diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/ADS2SerialProtocol.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/ADS2SerialProtocol.java index 51cc11b..f75819d 100644 --- a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/ADS2SerialProtocol.java +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/ADS2SerialProtocol.java @@ -29,14 +29,11 @@ import org.apache.plc4x.java.ads.api.serial.AMSSerialFrame; import org.apache.plc4x.java.ads.api.serial.AMSSerialResetFrame; import org.apache.plc4x.java.ads.api.serial.types.*; import org.apache.plc4x.java.ads.api.tcp.AMSTCPHeader; +import org.apache.plc4x.java.ads.protocol.util.DigestUtil; import org.apache.plc4x.java.api.exceptions.PlcProtocolException; -import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -108,24 +105,8 @@ public class ADS2SerialProtocol extends MessageToMessageCodec<ByteBuf, AMSPacket LOGGER.debug("Ams Serial Reset Frame received {}", amsSerialResetFrame); break; } - - // TODO: java has no CRC-16 implementation so we better be of implementing it by ourself. - MessageDigest messageDigest; - try { - messageDigest = MessageDigest.getInstance("CRC-16"); - } catch (NoSuchAlgorithmException e) { - throw new PlcRuntimeException(e); - } - messageDigest.update(magicCookie.getBytes()); - messageDigest.update(transmitterAddress.getBytes()); - messageDigest.update(receiverAddress.getBytes()); - messageDigest.update(fragmentNumber.getBytes()); - messageDigest.update(userDataLength.getBytes()); - byte[] digest = messageDigest.digest(userData.getBytes()); - if (digest.length > 2) { - throw new PlcRuntimeException("Digest length too great " + digest.length); - } - if (!Arrays.equals(digest, crc.getBytes())) { + int calculatedCrc16 = DigestUtil.calculateCrc16(magicCookie, transmitterAddress, receiverAddress, fragmentNumber, userDataLength, userData); + if (!crc.equals(CRC.of(calculatedCrc16))) { throw new PlcProtocolException("CRC checksum wrong"); } diff --git a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/DigestUtil.java b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/DigestUtil.java new file mode 100644 index 0000000..ad74dc5 --- /dev/null +++ b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/DigestUtil.java @@ -0,0 +1,55 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. + */ +package org.apache.plc4x.java.ads.protocol.util; + +import io.netty.buffer.ByteBuf; +import org.apache.plc4x.java.ads.api.util.ByteReadable; + +/** + * TODO: temporary due to unclear licence + * From https://stackoverflow.com/a/18333436/850036 + * // TODO: replace this with a better implementation. Maybe: + * http://www.source-code.biz/snippets/java/crc16/ + * https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Standards_and_common_use + * or even better a netty supplied crc-16 + * https://github.com/openhab/jamod/blob/64cdbd16fbb7febd39470f873a00be986b052e39/src/main/java/net/wimpi/modbus/util/ModbusUtil.java + */ +public class DigestUtil { + + private DigestUtil() { + // Utility class + } + + public static int calculateCrc16(ByteReadable... byteReadables) { + if (byteReadables.length == 1) { + return calculateCrc16(byteReadables[0].getBytes()); + } + return calculateCrc16(new ByteReadable() { + @Override + public ByteBuf getByteBuf() { + return buildByteBuff(byteReadables); + } + }.getBytes()); + } + + public static int calculateCrc16(byte[] bytes) { + // TODO: implement me + return 0; + } +} -- To stop receiving notification emails like this one, please contact sru...@apache.org.