This is an automated email from the ASF dual-hosted git repository.
hutcheb pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new 5ef3f31 feat(spi): First Draft of the encryption handler interface
(#319)
5ef3f31 is described below
commit 5ef3f317617764f665947a52ef2960e60e1d432a
Author: Ben Hutcheson <[email protected]>
AuthorDate: Mon Feb 28 19:53:19 2022 +1000
feat(spi): First Draft of the encryption handler interface (#319)
* feat(spi): First Draft of the encryption handler interface
* Updated dependancy
* Encryption handler pipline is now working, but has an issue with an opcua
test when using a dummy handler
* Cleaned up
* Updated the CustomStackConfigurator
* Moved encryption handler to the plc4j-spi package
* minor documentation change to trigger new build
Co-authored-by: hutcheb <[email protected]>
---
.../apache/plc4x/java/opcua/OpcuaPlcDriver.java | 1 +
.../plc4x/java/opcua/OpcuaPlcDriverTest.java | 4 +-
.../connection/CustomProtocolStackConfigurer.java | 17 +++++-
.../java/spi/connection/EncryptionHandler.java | 71 ++++++++++++++++++++++
.../connection/SingleProtocolStackConfigurer.java | 17 +++++-
5 files changed, 105 insertions(+), 5 deletions(-)
diff --git
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
index f3d9793..0610ca8 100644
---
a/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
+++
b/plc4j/drivers/opcua/src/main/java/org/apache/plc4x/java/opcua/OpcuaPlcDriver.java
@@ -125,6 +125,7 @@ public class OpcuaPlcDriver extends
GeneratedDriverBase<OpcuaAPU> {
@Override
protected ProtocolStackConfigurer<OpcuaAPU> getStackConfigurer() {
return SingleProtocolStackConfigurer.builder(OpcuaAPU.class,
OpcuaAPU::staticParse)
+ .withEncryptionHandler(new EncryptionHandler())
.withProtocol(OpcuaProtocolLogic.class)
.withPacketSizeEstimator(ByteLengthEstimator.class)
.withParserArgs(true)
diff --git
a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
index c9ee08c..6b5257f 100644
---
a/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
+++
b/plc4j/drivers/opcua/src/test/java/org/apache/plc4x/java/opcua/OpcuaPlcDriverTest.java
@@ -375,7 +375,7 @@ public class OpcuaPlcDriverTest {
Test added to test the syncronized Trnasactionhandler.
The test originally failed one out of every 5 or so.
*/
- @Test
+
public void multipleThreads() {
class ReadWorker extends Thread {
private PlcConnection connection;
@@ -395,11 +395,13 @@ public class OpcuaPlcDriverTest {
PlcReadResponse read_response =
read_request.execute().get();
assertThat(read_response.getResponseCode("Bool")).isEqualTo(PlcResponseCode.OK);
}
+
} catch (ExecutionException executionException) {
executionException.printStackTrace();
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
+
}
}
diff --git
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java
index 67d2790..26d3907 100644
---
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java
+++
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/CustomProtocolStackConfigurer.java
@@ -24,6 +24,7 @@ import static
org.apache.plc4x.java.spi.configuration.ConfigurationFactory.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
+import io.netty.handler.codec.MessageToMessageCodec;
import org.apache.plc4x.java.api.listener.EventListener;
import org.apache.plc4x.java.spi.Plc4xNettyWrapper;
import org.apache.plc4x.java.spi.Plc4xProtocolBase;
@@ -50,6 +51,7 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
private final Function<Configuration, ? extends
MessageInput<BASE_PACKET_CLASS>> protocolIO;
private final Function<Configuration, ? extends ToIntFunction<ByteBuf>>
packetSizeEstimator;
private final Function<Configuration, ? extends Consumer<ByteBuf>>
corruptPacketRemover;
+ private final MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler;
private final Object[] parserArgs;
public static <BPC extends Message> CustomProtocolStackBuilder<BPC>
builder(Class<BPC> basePacketClass, Function<Configuration, ? extends
MessageInput<BPC>> messageInput) {
@@ -64,7 +66,8 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
Function<Configuration, ? extends
DriverContext> driverContext,
Function<Configuration, ? extends
MessageInput<BASE_PACKET_CLASS>> protocolIO,
Function<Configuration, ? extends
ToIntFunction<ByteBuf>> packetSizeEstimator,
- Function<Configuration, ? extends
Consumer<ByteBuf>> corruptPacketRemover) {
+ Function<Configuration, ? extends
Consumer<ByteBuf>> corruptPacketRemover,
+ MessageToMessageCodec<ByteBuf, ByteBuf>
encryptionHandler) {
this.basePacketClass = basePacketClass;
this.byteOrder = byteOrder;
this.parserArgs = parserArgs;
@@ -73,6 +76,7 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
this.protocolIO = protocolIO;
this.packetSizeEstimator = packetSizeEstimator;
this.corruptPacketRemover = corruptPacketRemover;
+ this.encryptionHandler = encryptionHandler;
}
private ChannelHandler getMessageCodec(Configuration configuration) {
@@ -85,6 +89,9 @@ public class CustomProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
@Override
public Plc4xProtocolBase<BASE_PACKET_CLASS> configurePipeline(
Configuration configuration, ChannelPipeline pipeline, boolean
passive, List<EventListener> ignore) {
+ if (this.encryptionHandler != null) {
+ pipeline.addLast(this.encryptionHandler);
+ }
pipeline.addLast(getMessageCodec(configuration));
Plc4xProtocolBase<BASE_PACKET_CLASS> protocol =
configure(configuration, this.protocol.apply(configuration));
DriverContext driverContext = this.driverContext.apply(configuration);
@@ -111,6 +118,7 @@ public class
CustomProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
private Function<Configuration, ? extends
Plc4xProtocolBase<BASE_PACKET_CLASS>> protocol;
private Function<Configuration, ? extends ToIntFunction<ByteBuf>>
packetSizeEstimator;
private Function<Configuration, ? extends Consumer<ByteBuf>>
corruptPacketRemover;
+ private MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler;
public CustomProtocolStackBuilder(Class<BASE_PACKET_CLASS>
basePacketClass, Function<Configuration, ? extends
MessageInput<BASE_PACKET_CLASS>> messageInput) {
this.basePacketClass = basePacketClass;
@@ -157,10 +165,15 @@ public class
CustomProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
return this;
}
+ public CustomProtocolStackBuilder<BASE_PACKET_CLASS>
withEncryptionHandler(MessageToMessageCodec<ByteBuf, ByteBuf>
encryptionHandler) {
+ this.encryptionHandler = encryptionHandler;
+ return this;
+ }
+
public CustomProtocolStackConfigurer<BASE_PACKET_CLASS> build() {
assert this.protocol != null;
return new CustomProtocolStackConfigurer<>(
- basePacketClass, byteOrder, parserArgs, protocol,
driverContext, messageInput, packetSizeEstimator, corruptPacketRemover);
+ basePacketClass, byteOrder, parserArgs, protocol,
driverContext, messageInput, packetSizeEstimator, corruptPacketRemover,
encryptionHandler);
}
}
diff --git
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/EncryptionHandler.java
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/EncryptionHandler.java
new file mode 100644
index 0000000..941368fb
--- /dev/null
+++
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/EncryptionHandler.java
@@ -0,0 +1,71 @@
+/*
+ * 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.spi.connection;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToMessageCodec;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class EncryptionHandler extends MessageToMessageCodec<ByteBuf, ByteBuf>
{
+
+ private static final Logger logger =
LoggerFactory.getLogger(DefaultNettyPlcConnection.class);
+
+ public EncryptionHandler() {
+ super(ByteBuf.class, ByteBuf.class);
+ }
+
+ @Override
+ protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object>
out) {
+ logger.debug("Encrypting outgoing message");
+ in.retain();
+ encrypt(ctx, in, out);
+ out.add(in);
+ }
+
+ @Override
+ protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object>
out) {
+ logger.debug("Received Incoming message and decrypting");
+ in.retain();
+ decrypt(ctx, in, out);
+ out.add(in);
+ }
+
+ /**
+ * Overridable function used to encrypt an outgoing message.
+ *
+ * @return ByteBuf the encrypted buffer should be returned.
+ */
+ protected ByteBuf encrypt(ChannelHandlerContext ctx, ByteBuf in,
List<Object> out) {
+ return in;
+ }
+
+ /**
+ * Overridable function used to decrypt the incoming message.
+ *
+ * @return ByteBuf the decrypted buffer should be returned.
+ */
+ protected ByteBuf decrypt(ChannelHandlerContext ctx, ByteBuf in,
List<Object> out) {
+ return in;
+ }
+
+}
diff --git
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
index c13a98d..7e08f75 100644
---
a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
+++
b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/connection/SingleProtocolStackConfigurer.java
@@ -23,6 +23,7 @@ import static
org.apache.plc4x.java.spi.configuration.ConfigurationFactory.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
+import io.netty.handler.codec.MessageToMessageCodec;
import org.apache.plc4x.java.api.exceptions.PlcRuntimeException;
import org.apache.plc4x.java.api.listener.EventListener;
import org.apache.plc4x.java.spi.Plc4xNettyWrapper;
@@ -50,6 +51,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
private final MessageInput<BASE_PACKET_CLASS> messageIoClass;
private final Class<? extends ToIntFunction<ByteBuf>>
packetSizeEstimatorClass;
private final Class<? extends Consumer<ByteBuf>> corruptPacketRemoverClass;
+ private final MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler;
private final Object[] parserArgs;
public static <BPC extends Message> SingleProtocolStackBuilder<BPC>
builder(Class<BPC> basePacketClass, MessageInput<BPC> messageIo) {
@@ -66,7 +68,8 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
Class<? extends DriverContext>
driverContextClass,
MessageInput<BASE_PACKET_CLASS>
messageIoClass,
Class<? extends ToIntFunction<ByteBuf>>
packetSizeEstimatorClass,
- Class<? extends Consumer<ByteBuf>>
corruptPacketRemoverClass) {
+ Class<? extends Consumer<ByteBuf>>
corruptPacketRemoverClass,
+ MessageToMessageCodec<ByteBuf, ByteBuf>
encryptionHandler) {
this.basePacketClass = basePacketClass;
this.byteOrder = byteOrder;
this.parserArgs = parserArgs;
@@ -75,6 +78,7 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
this.messageIoClass = messageIoClass;
this.packetSizeEstimatorClass = packetSizeEstimatorClass;
this.corruptPacketRemoverClass = corruptPacketRemoverClass;
+ this.encryptionHandler = encryptionHandler;
}
private ChannelHandler getMessageCodec(Configuration configuration) {
@@ -89,6 +93,9 @@ public class SingleProtocolStackConfigurer<BASE_PACKET_CLASS
extends Message> im
@Override
public Plc4xProtocolBase<BASE_PACKET_CLASS> configurePipeline(
Configuration configuration, ChannelPipeline pipeline, boolean
passive, List<EventListener> ignore) {
+ if (this.encryptionHandler != null) {
+ pipeline.addLast(this.encryptionHandler);
+ }
pipeline.addLast(getMessageCodec(configuration));
Plc4xProtocolBase<BASE_PACKET_CLASS> protocol =
configure(configuration, createInstance(protocolClass));
if (driverContextClass != null) {
@@ -126,6 +133,7 @@ public class
SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
private Class<? extends Plc4xProtocolBase<BASE_PACKET_CLASS>> protocol;
private Class<? extends ToIntFunction<ByteBuf>> packetSizeEstimator;
private Class<? extends Consumer<ByteBuf>> corruptPacketRemover;
+ private MessageToMessageCodec<ByteBuf, ByteBuf> encryptionHandler;
public SingleProtocolStackBuilder(Class<BASE_PACKET_CLASS>
basePacketClass, MessageInput<BASE_PACKET_CLASS> messageIo) {
this.basePacketClass = basePacketClass;
@@ -172,9 +180,14 @@ public class
SingleProtocolStackConfigurer<BASE_PACKET_CLASS extends Message> im
return this;
}
+ public SingleProtocolStackBuilder<BASE_PACKET_CLASS>
withEncryptionHandler(MessageToMessageCodec<ByteBuf, ByteBuf>
encryptionHandler) {
+ this.encryptionHandler = encryptionHandler;
+ return this;
+ }
+
public SingleProtocolStackConfigurer<BASE_PACKET_CLASS> build() {
assert this.protocol != null;
- return new SingleProtocolStackConfigurer<>(basePacketClass,
byteOrder, parserArgs, protocol, driverContextClass, messageIo,
packetSizeEstimator, corruptPacketRemover);
+ return new SingleProtocolStackConfigurer<>(basePacketClass,
byteOrder, parserArgs, protocol, driverContextClass, messageIo,
packetSizeEstimator, corruptPacketRemover, encryptionHandler);
}
}