You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2018/12/18 07:17:17 UTC
[incubator-plc4x] 01/01: Refactored the IsoOnTcp Protocol to have
serialization/deserialization inside the protocol model classes.
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/io-model
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git
commit 3d26147d94794161cf810df272f5070703827ff7
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Tue Dec 18 08:17:12 2018 +0100
Refactored the IsoOnTcp Protocol to have serialization/deserialization inside the protocol model classes.
---
.../java/org/apache/plc4x/java/spi/ModelIO.java} | 13 ++--
.../org/apache/plc4x/java/spi/ToByteProtocol.java} | 12 ++--
.../java/isoontcp/protocol/IsoOnTcpProtocol.java | 69 ++++++----------------
.../isoontcp/protocol/model/IsoOnTcpMessage.java | 63 ++++++++++++++++++++
.../isoontcp/protocol/IsoOnTcpProtocolTest.java | 10 ++--
5 files changed, 98 insertions(+), 69 deletions(-)
diff --git a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/spi/ModelIO.java
similarity index 76%
copy from plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
copy to plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/spi/ModelIO.java
index 1500d80..0d33b61 100644
--- a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/spi/ModelIO.java
@@ -16,15 +16,16 @@
specific language governing permissions and limitations
under the License.
*/
-package org.apache.plc4x.java.isoontcp.protocol.model;
+
+package org.apache.plc4x.java.spi;
import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.base.messages.PlcRawMessage;
+import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
+
+public interface ModelIO<T> {
-public class IsoOnTcpMessage extends PlcRawMessage {
+ void encode(T model, ByteBuf buf) throws PlcProtocolException;
- public IsoOnTcpMessage(ByteBuf userData) {
- super(userData);
- }
+ T decode(ByteBuf buf) throws PlcProtocolException;
}
diff --git a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/spi/ToByteProtocol.java
similarity index 73%
copy from plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
copy to plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/spi/ToByteProtocol.java
index 1500d80..6f4ed0f 100644
--- a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
+++ b/plc4j/protocols/driver-bases/base/src/main/java/org/apache/plc4x/java/spi/ToByteProtocol.java
@@ -16,15 +16,13 @@
specific language governing permissions and limitations
under the License.
*/
-package org.apache.plc4x.java.isoontcp.protocol.model;
-import io.netty.buffer.ByteBuf;
-import org.apache.plc4x.java.base.messages.PlcRawMessage;
+package org.apache.plc4x.java.spi;
+
+import org.apache.plc4x.java.base.PlcByteToMessageCodec;
+
+public abstract class ToByteProtocol<T> extends PlcByteToMessageCodec<T> {
-public class IsoOnTcpMessage extends PlcRawMessage {
- public IsoOnTcpMessage(ByteBuf userData) {
- super(userData);
- }
}
diff --git a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocol.java b/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocol.java
index afd6146..f2f1607 100644
--- a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocol.java
+++ b/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocol.java
@@ -31,10 +31,14 @@ import java.util.List;
public class IsoOnTcpProtocol extends PlcByteToMessageCodec<IsoOnTcpMessage> {
- static final byte ISO_ON_TCP_MAGIC_NUMBER = 0x03;
-
private static final Logger logger = LoggerFactory.getLogger(IsoOnTcpProtocol.class);
+ private final IsoOnTcpMessage.ModelIO rootModelIO;
+
+ public IsoOnTcpProtocol() {
+ rootModelIO = new IsoOnTcpMessage.ModelIO();
+ }
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Encoding
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -42,25 +46,11 @@ public class IsoOnTcpProtocol extends PlcByteToMessageCodec<IsoOnTcpMessage> {
@Override
protected void encode(ChannelHandlerContext ctx, IsoOnTcpMessage in, ByteBuf out) throws Exception {
logger.debug("ISO on TCP Message sent");
- // At this point of processing all higher levels have already serialized their payload.
- // This data is passed to the lower levels in form of an IoBuffer.
- final ByteBuf userData = in.getUserData();
-
- int packetSize = userData.readableBytes() + 4;
-
- // Version (is always constant 0x03)
- out.writeByte(ISO_ON_TCP_MAGIC_NUMBER);
- // Reserved (is always constant 0x00)
- out.writeByte((byte) 0x00);
- // Packet length (including ISOonTCP header)
- // ("remaining" returns the number of bytes left to read in this buffer.
- // It is usually set to a read position of 0 and a limit at the end.
- // So in general remaining is equivalent to a non-existing
- // "userData.size()" method.)
- out.writeShort((short) packetSize);
-
- // Output the payload.
- out.writeBytes(userData);
+ try {
+ rootModelIO.encode(in, out);
+ } catch (PlcProtocolException e) {
+ exceptionCaught(ctx, e);
+ }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -72,37 +62,14 @@ public class IsoOnTcpProtocol extends PlcByteToMessageCodec<IsoOnTcpMessage> {
if(logger.isTraceEnabled()) {
logger.trace("Got Data: {}", ByteBufUtil.hexDump(in));
}
- // If at least 4 bytes are readable, peek into them (without changing the read position)
- // and get the packet length. Only if the available amount of readable bytes is larger or
- // equal to this, continue processing the rest.
- /*if(chunkedResponse != null) {
- chunkedResponse.writeBytes(in);
- } else*/ if(in.readableBytes() >= 4) {
- logger.debug("ISO on TCP Message received");
- // The ISO on TCP protocol is really simple and in this case the buffer length
- // will take care of the higher levels not reading more than is in the packet.
- // So we just gobble up the header and continue reading in higher levels.
- if (in.getByte(0) != ISO_ON_TCP_MAGIC_NUMBER) {
- logger.warn("Expecting ISO on TCP magic number: {}", ISO_ON_TCP_MAGIC_NUMBER);
- if (logger.isDebugEnabled()) {
- logger.debug("Got Data: {}", ByteBufUtil.hexDump(in));
- }
- exceptionCaught(ctx, new PlcProtocolException(
- String.format("Expecting ISO on TCP magic number: %02X", ISO_ON_TCP_MAGIC_NUMBER)));
- return;
- }
- // Byte 1 is a reserved byte set to 0x00
- short packetLength = in.getShort(2);
- if(in.readableBytes() >= packetLength) {
- // Skip the 4 bytes we peeked into manually.
- in.skipBytes(4);
- // Simply place the current buffer to the output ... the next handler will continue.
- ByteBuf payload = in.readBytes(packetLength - 4);
- out.add(new IsoOnTcpMessage(payload));
- /*} else {
- chunkedResponse = Unpooled.buffer(packetLength);
- chunkedResponse.writeBytes(in, packetLength);*/
+ logger.debug("ISO on TCP Message received");
+ try {
+ IsoOnTcpMessage decodedMessage = rootModelIO.decode(in);
+ if(decodedMessage != null) {
+ out.add(decodedMessage);
}
+ } catch (PlcProtocolException e) {
+ exceptionCaught(ctx, e);
}
}
diff --git a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java b/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
index 1500d80..e855244 100644
--- a/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
+++ b/plc4j/protocols/iso-on-tcp/src/main/java/org/apache/plc4x/java/isoontcp/protocol/model/IsoOnTcpMessage.java
@@ -19,12 +19,75 @@
package org.apache.plc4x.java.isoontcp.protocol.model;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import org.apache.plc4x.java.api.exceptions.PlcProtocolException;
import org.apache.plc4x.java.base.messages.PlcRawMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class IsoOnTcpMessage extends PlcRawMessage {
+ private static final Logger logger = LoggerFactory.getLogger(IsoOnTcpMessage.class);
+
+ public static final byte ISO_ON_TCP_MAGIC_NUMBER = 0x03;
+
public IsoOnTcpMessage(ByteBuf userData) {
super(userData);
}
+ public static class ModelIO implements org.apache.plc4x.java.spi.ModelIO<IsoOnTcpMessage> {
+
+ @Override
+ public void encode(IsoOnTcpMessage model, ByteBuf out) throws PlcProtocolException {
+ final ByteBuf userData = model.getUserData();
+
+ int packetSize = userData.readableBytes() + 4;
+
+ // Version (is always constant 0x03)
+ out.writeByte(ISO_ON_TCP_MAGIC_NUMBER);
+ // Reserved (is always constant 0x00)
+ out.writeByte((byte) 0x00);
+ // Packet length (including ISOonTCP header)
+ // ("remaining" returns the number of bytes left to read in this buffer.
+ // It is usually set to a read position of 0 and a limit at the end.
+ // So in general remaining is equivalent to a non-existing
+ // "userData.size()" method.)
+ out.writeShort((short) packetSize);
+
+ // Output the payload.
+ out.writeBytes(userData);
+ }
+
+ @Override
+ public IsoOnTcpMessage decode(ByteBuf in) throws PlcProtocolException {
+ // If at least 4 bytes are readable, peek into them (without changing the read position)
+ // and get the packet length. Only if the available amount of readable bytes is larger or
+ // equal to this, continue processing the rest.
+ if(in.readableBytes() >= 4) {
+ // The ISO on TCP protocol is really simple and in this case the buffer length
+ // will take care of the higher levels not reading more than is in the packet.
+ // So we just gobble up the header and continue reading in higher levels.
+ if (in.getByte(0) != ISO_ON_TCP_MAGIC_NUMBER) {
+ logger.warn("Expecting ISO on TCP magic number: {}", ISO_ON_TCP_MAGIC_NUMBER);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Got Data: {}", ByteBufUtil.hexDump(in));
+ }
+ throw new PlcProtocolException(
+ String.format("Expecting ISO on TCP magic number: %02X", ISO_ON_TCP_MAGIC_NUMBER));
+ }
+ // Byte 1 is a reserved byte set to 0x00
+ short packetLength = in.getShort(2);
+ if(in.readableBytes() >= packetLength) {
+ // Skip the 4 bytes we peeked into manually.
+ in.skipBytes(4);
+ // Simply place the current buffer to the output ... the next handler will continue.
+ ByteBuf payload = in.readBytes(packetLength - 4);
+ return new IsoOnTcpMessage(payload);
+ }
+ }
+ return null;
+ }
+
+ }
+
}
diff --git a/plc4j/protocols/iso-on-tcp/src/test/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocolTest.java b/plc4j/protocols/iso-on-tcp/src/test/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocolTest.java
index 8b158e4..089843b 100644
--- a/plc4j/protocols/iso-on-tcp/src/test/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocolTest.java
+++ b/plc4j/protocols/iso-on-tcp/src/test/java/org/apache/plc4x/java/isoontcp/protocol/IsoOnTcpProtocolTest.java
@@ -55,7 +55,7 @@ public class IsoOnTcpProtocolTest {
assertThat(obj, instanceOf(ByteBuf.class));
ByteBuf byteBuf = (ByteBuf) obj;
assertThat("The TCP on ISO Header should add 4 bytes to the data sent", byteBuf.readableBytes(), equalTo(4 + 3));
- assertThat(byteBuf.getByte(0), equalTo(IsoOnTcpProtocol.ISO_ON_TCP_MAGIC_NUMBER) );
+ assertThat(byteBuf.getByte(0), equalTo(IsoOnTcpMessage.ISO_ON_TCP_MAGIC_NUMBER) );
assertThat("The length value in the packet should reflect the size of the entire data being sent", byteBuf.getShort(2), equalTo((short) (4 + 3)) );
}
@@ -66,7 +66,7 @@ public class IsoOnTcpProtocolTest {
@Category(FastTests.class)
public void decode() {
EmbeddedChannel channel = new EmbeddedChannel(new IsoOnTcpProtocol());
- channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpProtocol.ISO_ON_TCP_MAGIC_NUMBER,
+ channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpMessage.ISO_ON_TCP_MAGIC_NUMBER,
(byte) 0x00, (byte) 0x00, (byte) 0x0D,
(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09}));
channel.checkException();
@@ -106,7 +106,7 @@ public class IsoOnTcpProtocolTest {
@Category(FastTests.class)
public void decodeWayTooShort() {
EmbeddedChannel channel = new EmbeddedChannel(new IsoOnTcpProtocol());
- channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpProtocol.ISO_ON_TCP_MAGIC_NUMBER,
+ channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpMessage.ISO_ON_TCP_MAGIC_NUMBER,
(byte) 0x00, (byte) 0x00, (byte) 0x0D}));
channel.checkException();
Object obj = channel.readInbound();
@@ -121,7 +121,7 @@ public class IsoOnTcpProtocolTest {
@Category(FastTests.class)
public void decodeTooShort() {
EmbeddedChannel channel = new EmbeddedChannel(new IsoOnTcpProtocol());
- channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpProtocol.ISO_ON_TCP_MAGIC_NUMBER,
+ channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpMessage.ISO_ON_TCP_MAGIC_NUMBER,
(byte) 0x00, (byte) 0x00, (byte) 0x0D,
(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08}));
channel.checkException();
@@ -149,7 +149,7 @@ public class IsoOnTcpProtocolTest {
// Do some deserialization
EmbeddedChannel channel = new EmbeddedChannel(new IsoOnTcpProtocol());
- channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpProtocol.ISO_ON_TCP_MAGIC_NUMBER,
+ channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{IsoOnTcpMessage.ISO_ON_TCP_MAGIC_NUMBER,
(byte) 0x00, (byte) 0x00, (byte) 0x0D,
(byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09}));
channel.checkException();