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();